diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/bugs/__init__.py b/tests/bugs/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/bugs/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/bugs/test_core_0000.py b/tests/bugs/test_core_0000.py new file mode 100644 index 00000000..859b94f0 --- /dev/null +++ b/tests/bugs/test_core_0000.py @@ -0,0 +1,34 @@ +#coding:utf-8 +# +# id: bugs.core_0000 +# title: Dummy test +# decription: +# +# tracker_id: CORE-0000 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table t1(id int); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=4.0') +def test_core_0000_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_0001.py b/tests/bugs/test_core_0001.py new file mode 100644 index 00000000..9bb8182b --- /dev/null +++ b/tests/bugs/test_core_0001.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_0001 +# title: FBserver shutsdown when a user password is attempted to be modified to a empty string +# decription: +# tracker_id: CORE-0001 +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter user tmp$c0001 password '123'; + commit; + alter user tmp$c0001 password ''; + commit; + drop user tmp$c0001; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER USER TMP$C0001 failed + -Password should not be empty string + """ + +@pytest.mark.version('>=3.0') +def test_core_0001_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_0002.py b/tests/bugs/test_core_0002.py new file mode 100644 index 00000000..3e06334e --- /dev/null +++ b/tests/bugs/test_core_0002.py @@ -0,0 +1,60 @@ +#coding:utf-8 +# +# id: bugs.core_0002 +# title: Incorrect value returned with execute statement calculation +# decription: +# tracker_id: CORE-0002 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + create table t1 ( + campo1 numeric(15,2), + campo2 numeric(15,2) + ); + commit; + set term ^; + create procedure teste + returns ( + retorno numeric(15,2)) + as + begin + execute statement 'select first 1 (campo1*campo2) from t1' into :retorno; + suspend; + end + ^ + set term ;^ + commit; + + insert into t1 (campo1, campo2) values (10.5, 5.5); + commit; + + select * from teste; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RETORNO 57.75 + """ + +@pytest.mark.version('>=2.5') +def test_core_0002_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0010.py b/tests/bugs/test_core_0010.py new file mode 100644 index 00000000..de6fe9cf --- /dev/null +++ b/tests/bugs/test_core_0010.py @@ -0,0 +1,51 @@ +#coding:utf-8 +# +# id: bugs.core_0010 +# title: Navigation vs IS NULL vs compound index +# decription: +# tracker_id: CORE-0010 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table t (f1 int, f2 int); + create index t_idx on t (f1, f2); + + insert into t (f1, f2) values (1, 1); + insert into t (f1, f2) values (null, 2); + insert into t (f1, f2) values (3, 3); + + set list on; + + select * + from t + where f1 is null + order by f1, f2; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F1 + F2 2 + """ + +@pytest.mark.version('>=2.5') +def test_core_0010_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0014.py b/tests/bugs/test_core_0014.py new file mode 100644 index 00000000..1dbf82a1 --- /dev/null +++ b/tests/bugs/test_core_0014.py @@ -0,0 +1,187 @@ +#coding:utf-8 +# +# id: bugs.core_0014 +# title: Trigger do it wrong +# decription: Computed by columns inside triggers always=NULL +# tracker_id: CORE-0014 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Works OK on 1.5.6 and up to 4.0.0. + create domain dom_datum_vreme as timestamp not null; + create domain dom_dokid as varchar(20) not null; + create domain dom_jid as integer; + create domain dom_kolicina as integer default 0; + create domain dom_naziv as varchar(100) not null; + create domain dom_novac as double precision default 0; + create domain dom_rabat as float default 0; + create domain dom_status as integer default 0; + commit; + + create table ulaz_master + ( + ulzid dom_jid not null, + datum dom_datum_vreme not null, + broj_racuna dom_dokid not null, + dobid dom_jid not null, + dobavljac dom_naziv not null, + napid dom_jid not null, + nacin_placanja dom_naziv not null, + datumprispeca timestamp, -- dom_datum_vreme null , + vrednost dom_novac default 0, + rvrednost dom_novac default 0, + status dom_status default 0, + constraint pk_ulaz_master primary key (ulzid) + ); + + create table ulaz_detalji + ( + ulzid dom_jid not null, + artid dom_jid not null, + artikal dom_naziv not null, + kolicina dom_kolicina default 0 not null, + cena dom_novac default 0 not null, + rabat dom_rabat default 0 not null, + ukupno computed by (kolicina * cena), + vratio dom_kolicina default 0, + constraint pk_ulaz_detalji primary key (ulzid, artid) + ); + + + set term ^; + create trigger trig_ulaz_detalji_ai for ulaz_detalji + active after insert position 0 + as + begin + + update ulaz_master u set u.vrednost = u.vrednost + new.ukupno + where u.ulzid = new.ulzid; + + update ulaz_master u set u.rvrednost = u.rvrednost + (1 - new.rabat/100) * new.ukupno + where u.ulzid = new.ulzid; + + end + ^ + set term ;^ + commit; + + -- this trigger sets fiedls to null on rc8. + -- on rc6 it works as it should. + + insert into ulaz_master(ulzid, datum, broj_racuna, dobid, dobavljac, napid, nacin_placanja) + values(1000, '19.03.2016 12:01:03', 'qwerty123', 78966, 'foo-bar', 32101, 'asd-fgh-jkl' ); + /* + create domain dom_datum_vreme as timestamp not null; + create domain dom_dokid as varchar(20) not null; + create domain dom_jid as integer; + create domain dom_kolicina as integer default 0; + create domain dom_naziv as varchar(100) not null; + create domain dom_novac as double precision default 0; + create domain dom_rabat as float default 0; + create domain dom_status as integer default 0; + + datum dom_datum_vreme not null, + broj_racuna dom_dokid not null, + dobid dom_jid not null, + dobavljac dom_naziv not null, + napid dom_jid not null, + nacin_placanja dom_naziv not null, + */ + + set list on; + set count on; + + select + ulzid, datum, broj_racuna, dobid, dobavljac, napid, nacin_placanja, datumprispeca + ,cast(vrednost as numeric(10,2)) as vrednost + ,cast(rvrednost as numeric(10,2)) as rvrednost + ,status + from ulaz_master; + + insert into + ulaz_detalji(ulzid, artid, artikal, kolicina, cena, rabat, vratio) + values(1000, 1000, 'liste', 19, 7, 30, 0); + + select + ulzid, artid, artikal, kolicina, + cast(cena as numeric(12,2)) as cena, + rabat, + cast(ukupno as numeric(12,2)) as ukupno, + vratio + from ulaz_detalji; + + select + ulzid, datum, broj_racuna, dobid, dobavljac, napid, nacin_placanja, datumprispeca + ,cast(vrednost as numeric(10,2)) as vrednost + ,cast(rvrednost as numeric(10,2)) as rvrednost + ,status + from ulaz_master; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ULZID 1000 + DATUM 2016-03-19 12:01:03.0000 + BROJ_RACUNA qwerty123 + DOBID 78966 + DOBAVLJAC foo-bar + NAPID 32101 + NACIN_PLACANJA asd-fgh-jkl + DATUMPRISPECA + VREDNOST 0.00 + RVREDNOST 0.00 + STATUS 0 + + + Records affected: 1 + Records affected: 1 + + ULZID 1000 + ARTID 1000 + ARTIKAL liste + KOLICINA 19 + CENA 7.00 + RABAT 30 + UKUPNO 133.00 + VRATIO 0 + + + Records affected: 1 + + ULZID 1000 + DATUM 2016-03-19 12:01:03.0000 + BROJ_RACUNA qwerty123 + DOBID 78966 + DOBAVLJAC foo-bar + NAPID 32101 + NACIN_PLACANJA asd-fgh-jkl + DATUMPRISPECA + VREDNOST 133.00 + RVREDNOST 93.10 + STATUS 0 + + Records affected: 1 + """ + +@pytest.mark.version('>=2.5') +def test_core_0014_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0037.py b/tests/bugs/test_core_0037.py new file mode 100644 index 00000000..84cc4fc3 --- /dev/null +++ b/tests/bugs/test_core_0037.py @@ -0,0 +1,101 @@ +#coding:utf-8 +# +# id: bugs.core_0037 +# title: Navigation vs IS NULL vs compound index +# decription: +# 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/ +# Checked on: +# 2.5.9.27126: OK, 0.656s. +# 3.0.5.33086: OK, 1.422s. +# 4.0.0.1172: OK, 4.109s. +# 4.0.0.1340: OK, 2.297s. +# 4.0.0.1378: OK, 2.204s. +# +# tracker_id: CORE-0037 +# min_versions: ['2.5.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + + -- 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; + + recreate view v1 as select 1 k from rdb$database; + recreate view v2 as select 1 k from rdb$database; + commit; + + recreate table t1 + ( + t1f1 integer not null primary key, + t1f2 varchar(30) + ); + + recreate table t2 + ( + t2f1 integer not null primary key, + t2f2 integer not null, + t2f3 varchar(30) + ); + + create index t2f2_ndx on t2(t2f2); + + recreate view v1 as select * from t1 where UDR40_frac( mod(t1f1,100) / 100.000) > 0.03; + recreate view v2 as select * from t2 where UDR40_frac( mod(t2f1,100) / 100.000) > 0.03; + + insert into t1(t1f1, t1f2) values (1, '1'); + insert into t1(t1f1, t1f2) values (2, '2'); + insert into t1(t1f1, t1f2) values (3, '3'); + insert into t1(t1f1, t1f2) values (104, '104'); + insert into t1(t1f1, t1f2) values (105, '205'); + insert into t1(t1f1, t1f2) values (106, '106'); + + insert into t2(t2f1, t2f2, t2f3) values (1, 1, '1'); + insert into t2(t2f1, t2f2, t2f3) values (2, 2, '2'); + insert into t2(t2f1, t2f2, t2f3) values (3, 3, '3'); + insert into t2(t2f1, t2f2, t2f3) values (104, 104, '104'); + insert into t2(t2f1, t2f2, t2f3) values (105, 105, '105'); + insert into t2(t2f1, t2f2, t2f3) values (106, 106, '106'); + + set count on; + + select x.*, y.*, UDR40_frac( mod(t2f1,100) / 100.000) + from v1 x, v2 y + where x.t1f1 = y.t2f2 + and UDR40_frac( mod(t2f1,100) / 100.000) < 0.03 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ + +@pytest.mark.version('>=4.0') +def test_core_0037_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0039.py b/tests/bugs/test_core_0039.py new file mode 100644 index 00000000..ca4d4d62 --- /dev/null +++ b/tests/bugs/test_core_0039.py @@ -0,0 +1,1092 @@ +#coding:utf-8 +# +# id: bugs.core_0039 +# title: cannot create procedure with long chain of else-if clauses +# decription: +# tracker_id: CORE-0039 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Checked on FB 4.0.0 with length = 20'000. + -- Current length (1000) was choosen after discuss with dimitr. + -- Batch scenario for generating script with arbitrary number of if-else: + -- @echo off + -- setlocal enabledelayedexpansion enableextensions + -- + -- set n=%1 + -- if .%1.==.. set n=1000 + -- + -- set sql=%~n0.sql + -- del %sql% 2>nul + -- + -- ( + -- echo set heading off; + -- echo select 'Creating procedure. . .' from rdb$database; + -- echo set stat on; + -- ) >>%sql% + -- + -- ( + -- echo set term ^^; + -- echo create or alter procedure sp_ifel(N integer^) + -- echo returns (R double precision^) + -- echo as + -- echo begin + -- ) >> %sql% + -- + -- set /a m=%n%-1 + -- for /l %%i in (0,1,%m%) do ( + -- if .%%i.==.0. ( + -- echo if ( :n ^<= 0 ^) then r = %%i; >>%sql% + -- ) else ( + -- echo else if (:n = %%i^) then r = sqrt(%%i^) ; >>%sql% + -- ) + -- ) + -- echo else r = sqrt(%n%^); >>%sql% + -- + -- ( + -- echo suspend; + -- echo end ^^ + -- echo set term ;^^ + -- echo set list on; + -- echo select * from sp_ifel(%n%^); + -- ) >>%sql% + + set term ^; + create or alter procedure sp_ifel(N integer) + returns (R double precision) + as + begin + if ( :n <= 0 ) then r = 0; + else if (:n = 1) then r = sqrt(1) ; + else if (:n = 2) then r = sqrt(2) ; + else if (:n = 3) then r = sqrt(3) ; + else if (:n = 4) then r = sqrt(4) ; + else if (:n = 5) then r = sqrt(5) ; + else if (:n = 6) then r = sqrt(6) ; + else if (:n = 7) then r = sqrt(7) ; + else if (:n = 8) then r = sqrt(8) ; + else if (:n = 9) then r = sqrt(9) ; + else if (:n = 10) then r = sqrt(10) ; + else if (:n = 11) then r = sqrt(11) ; + else if (:n = 12) then r = sqrt(12) ; + else if (:n = 13) then r = sqrt(13) ; + else if (:n = 14) then r = sqrt(14) ; + else if (:n = 15) then r = sqrt(15) ; + else if (:n = 16) then r = sqrt(16) ; + else if (:n = 17) then r = sqrt(17) ; + else if (:n = 18) then r = sqrt(18) ; + else if (:n = 19) then r = sqrt(19) ; + else if (:n = 20) then r = sqrt(20) ; + else if (:n = 21) then r = sqrt(21) ; + else if (:n = 22) then r = sqrt(22) ; + else if (:n = 23) then r = sqrt(23) ; + else if (:n = 24) then r = sqrt(24) ; + else if (:n = 25) then r = sqrt(25) ; + else if (:n = 26) then r = sqrt(26) ; + else if (:n = 27) then r = sqrt(27) ; + else if (:n = 28) then r = sqrt(28) ; + else if (:n = 29) then r = sqrt(29) ; + else if (:n = 30) then r = sqrt(30) ; + else if (:n = 31) then r = sqrt(31) ; + else if (:n = 32) then r = sqrt(32) ; + else if (:n = 33) then r = sqrt(33) ; + else if (:n = 34) then r = sqrt(34) ; + else if (:n = 35) then r = sqrt(35) ; + else if (:n = 36) then r = sqrt(36) ; + else if (:n = 37) then r = sqrt(37) ; + else if (:n = 38) then r = sqrt(38) ; + else if (:n = 39) then r = sqrt(39) ; + else if (:n = 40) then r = sqrt(40) ; + else if (:n = 41) then r = sqrt(41) ; + else if (:n = 42) then r = sqrt(42) ; + else if (:n = 43) then r = sqrt(43) ; + else if (:n = 44) then r = sqrt(44) ; + else if (:n = 45) then r = sqrt(45) ; + else if (:n = 46) then r = sqrt(46) ; + else if (:n = 47) then r = sqrt(47) ; + else if (:n = 48) then r = sqrt(48) ; + else if (:n = 49) then r = sqrt(49) ; + else if (:n = 50) then r = sqrt(50) ; + else if (:n = 51) then r = sqrt(51) ; + else if (:n = 52) then r = sqrt(52) ; + else if (:n = 53) then r = sqrt(53) ; + else if (:n = 54) then r = sqrt(54) ; + else if (:n = 55) then r = sqrt(55) ; + else if (:n = 56) then r = sqrt(56) ; + else if (:n = 57) then r = sqrt(57) ; + else if (:n = 58) then r = sqrt(58) ; + else if (:n = 59) then r = sqrt(59) ; + else if (:n = 60) then r = sqrt(60) ; + else if (:n = 61) then r = sqrt(61) ; + else if (:n = 62) then r = sqrt(62) ; + else if (:n = 63) then r = sqrt(63) ; + else if (:n = 64) then r = sqrt(64) ; + else if (:n = 65) then r = sqrt(65) ; + else if (:n = 66) then r = sqrt(66) ; + else if (:n = 67) then r = sqrt(67) ; + else if (:n = 68) then r = sqrt(68) ; + else if (:n = 69) then r = sqrt(69) ; + else if (:n = 70) then r = sqrt(70) ; + else if (:n = 71) then r = sqrt(71) ; + else if (:n = 72) then r = sqrt(72) ; + else if (:n = 73) then r = sqrt(73) ; + else if (:n = 74) then r = sqrt(74) ; + else if (:n = 75) then r = sqrt(75) ; + else if (:n = 76) then r = sqrt(76) ; + else if (:n = 77) then r = sqrt(77) ; + else if (:n = 78) then r = sqrt(78) ; + else if (:n = 79) then r = sqrt(79) ; + else if (:n = 80) then r = sqrt(80) ; + else if (:n = 81) then r = sqrt(81) ; + else if (:n = 82) then r = sqrt(82) ; + else if (:n = 83) then r = sqrt(83) ; + else if (:n = 84) then r = sqrt(84) ; + else if (:n = 85) then r = sqrt(85) ; + else if (:n = 86) then r = sqrt(86) ; + else if (:n = 87) then r = sqrt(87) ; + else if (:n = 88) then r = sqrt(88) ; + else if (:n = 89) then r = sqrt(89) ; + else if (:n = 90) then r = sqrt(90) ; + else if (:n = 91) then r = sqrt(91) ; + else if (:n = 92) then r = sqrt(92) ; + else if (:n = 93) then r = sqrt(93) ; + else if (:n = 94) then r = sqrt(94) ; + else if (:n = 95) then r = sqrt(95) ; + else if (:n = 96) then r = sqrt(96) ; + else if (:n = 97) then r = sqrt(97) ; + else if (:n = 98) then r = sqrt(98) ; + else if (:n = 99) then r = sqrt(99) ; + else if (:n = 100) then r = sqrt(100) ; + else if (:n = 101) then r = sqrt(101) ; + else if (:n = 102) then r = sqrt(102) ; + else if (:n = 103) then r = sqrt(103) ; + else if (:n = 104) then r = sqrt(104) ; + else if (:n = 105) then r = sqrt(105) ; + else if (:n = 106) then r = sqrt(106) ; + else if (:n = 107) then r = sqrt(107) ; + else if (:n = 108) then r = sqrt(108) ; + else if (:n = 109) then r = sqrt(109) ; + else if (:n = 110) then r = sqrt(110) ; + else if (:n = 111) then r = sqrt(111) ; + else if (:n = 112) then r = sqrt(112) ; + else if (:n = 113) then r = sqrt(113) ; + else if (:n = 114) then r = sqrt(114) ; + else if (:n = 115) then r = sqrt(115) ; + else if (:n = 116) then r = sqrt(116) ; + else if (:n = 117) then r = sqrt(117) ; + else if (:n = 118) then r = sqrt(118) ; + else if (:n = 119) then r = sqrt(119) ; + else if (:n = 120) then r = sqrt(120) ; + else if (:n = 121) then r = sqrt(121) ; + else if (:n = 122) then r = sqrt(122) ; + else if (:n = 123) then r = sqrt(123) ; + else if (:n = 124) then r = sqrt(124) ; + else if (:n = 125) then r = sqrt(125) ; + else if (:n = 126) then r = sqrt(126) ; + else if (:n = 127) then r = sqrt(127) ; + else if (:n = 128) then r = sqrt(128) ; + else if (:n = 129) then r = sqrt(129) ; + else if (:n = 130) then r = sqrt(130) ; + else if (:n = 131) then r = sqrt(131) ; + else if (:n = 132) then r = sqrt(132) ; + else if (:n = 133) then r = sqrt(133) ; + else if (:n = 134) then r = sqrt(134) ; + else if (:n = 135) then r = sqrt(135) ; + else if (:n = 136) then r = sqrt(136) ; + else if (:n = 137) then r = sqrt(137) ; + else if (:n = 138) then r = sqrt(138) ; + else if (:n = 139) then r = sqrt(139) ; + else if (:n = 140) then r = sqrt(140) ; + else if (:n = 141) then r = sqrt(141) ; + else if (:n = 142) then r = sqrt(142) ; + else if (:n = 143) then r = sqrt(143) ; + else if (:n = 144) then r = sqrt(144) ; + else if (:n = 145) then r = sqrt(145) ; + else if (:n = 146) then r = sqrt(146) ; + else if (:n = 147) then r = sqrt(147) ; + else if (:n = 148) then r = sqrt(148) ; + else if (:n = 149) then r = sqrt(149) ; + else if (:n = 150) then r = sqrt(150) ; + else if (:n = 151) then r = sqrt(151) ; + else if (:n = 152) then r = sqrt(152) ; + else if (:n = 153) then r = sqrt(153) ; + else if (:n = 154) then r = sqrt(154) ; + else if (:n = 155) then r = sqrt(155) ; + else if (:n = 156) then r = sqrt(156) ; + else if (:n = 157) then r = sqrt(157) ; + else if (:n = 158) then r = sqrt(158) ; + else if (:n = 159) then r = sqrt(159) ; + else if (:n = 160) then r = sqrt(160) ; + else if (:n = 161) then r = sqrt(161) ; + else if (:n = 162) then r = sqrt(162) ; + else if (:n = 163) then r = sqrt(163) ; + else if (:n = 164) then r = sqrt(164) ; + else if (:n = 165) then r = sqrt(165) ; + else if (:n = 166) then r = sqrt(166) ; + else if (:n = 167) then r = sqrt(167) ; + else if (:n = 168) then r = sqrt(168) ; + else if (:n = 169) then r = sqrt(169) ; + else if (:n = 170) then r = sqrt(170) ; + else if (:n = 171) then r = sqrt(171) ; + else if (:n = 172) then r = sqrt(172) ; + else if (:n = 173) then r = sqrt(173) ; + else if (:n = 174) then r = sqrt(174) ; + else if (:n = 175) then r = sqrt(175) ; + else if (:n = 176) then r = sqrt(176) ; + else if (:n = 177) then r = sqrt(177) ; + else if (:n = 178) then r = sqrt(178) ; + else if (:n = 179) then r = sqrt(179) ; + else if (:n = 180) then r = sqrt(180) ; + else if (:n = 181) then r = sqrt(181) ; + else if (:n = 182) then r = sqrt(182) ; + else if (:n = 183) then r = sqrt(183) ; + else if (:n = 184) then r = sqrt(184) ; + else if (:n = 185) then r = sqrt(185) ; + else if (:n = 186) then r = sqrt(186) ; + else if (:n = 187) then r = sqrt(187) ; + else if (:n = 188) then r = sqrt(188) ; + else if (:n = 189) then r = sqrt(189) ; + else if (:n = 190) then r = sqrt(190) ; + else if (:n = 191) then r = sqrt(191) ; + else if (:n = 192) then r = sqrt(192) ; + else if (:n = 193) then r = sqrt(193) ; + else if (:n = 194) then r = sqrt(194) ; + else if (:n = 195) then r = sqrt(195) ; + else if (:n = 196) then r = sqrt(196) ; + else if (:n = 197) then r = sqrt(197) ; + else if (:n = 198) then r = sqrt(198) ; + else if (:n = 199) then r = sqrt(199) ; + else if (:n = 200) then r = sqrt(200) ; + else if (:n = 201) then r = sqrt(201) ; + else if (:n = 202) then r = sqrt(202) ; + else if (:n = 203) then r = sqrt(203) ; + else if (:n = 204) then r = sqrt(204) ; + else if (:n = 205) then r = sqrt(205) ; + else if (:n = 206) then r = sqrt(206) ; + else if (:n = 207) then r = sqrt(207) ; + else if (:n = 208) then r = sqrt(208) ; + else if (:n = 209) then r = sqrt(209) ; + else if (:n = 210) then r = sqrt(210) ; + else if (:n = 211) then r = sqrt(211) ; + else if (:n = 212) then r = sqrt(212) ; + else if (:n = 213) then r = sqrt(213) ; + else if (:n = 214) then r = sqrt(214) ; + else if (:n = 215) then r = sqrt(215) ; + else if (:n = 216) then r = sqrt(216) ; + else if (:n = 217) then r = sqrt(217) ; + else if (:n = 218) then r = sqrt(218) ; + else if (:n = 219) then r = sqrt(219) ; + else if (:n = 220) then r = sqrt(220) ; + else if (:n = 221) then r = sqrt(221) ; + else if (:n = 222) then r = sqrt(222) ; + else if (:n = 223) then r = sqrt(223) ; + else if (:n = 224) then r = sqrt(224) ; + else if (:n = 225) then r = sqrt(225) ; + else if (:n = 226) then r = sqrt(226) ; + else if (:n = 227) then r = sqrt(227) ; + else if (:n = 228) then r = sqrt(228) ; + else if (:n = 229) then r = sqrt(229) ; + else if (:n = 230) then r = sqrt(230) ; + else if (:n = 231) then r = sqrt(231) ; + else if (:n = 232) then r = sqrt(232) ; + else if (:n = 233) then r = sqrt(233) ; + else if (:n = 234) then r = sqrt(234) ; + else if (:n = 235) then r = sqrt(235) ; + else if (:n = 236) then r = sqrt(236) ; + else if (:n = 237) then r = sqrt(237) ; + else if (:n = 238) then r = sqrt(238) ; + else if (:n = 239) then r = sqrt(239) ; + else if (:n = 240) then r = sqrt(240) ; + else if (:n = 241) then r = sqrt(241) ; + else if (:n = 242) then r = sqrt(242) ; + else if (:n = 243) then r = sqrt(243) ; + else if (:n = 244) then r = sqrt(244) ; + else if (:n = 245) then r = sqrt(245) ; + else if (:n = 246) then r = sqrt(246) ; + else if (:n = 247) then r = sqrt(247) ; + else if (:n = 248) then r = sqrt(248) ; + else if (:n = 249) then r = sqrt(249) ; + else if (:n = 250) then r = sqrt(250) ; + else if (:n = 251) then r = sqrt(251) ; + else if (:n = 252) then r = sqrt(252) ; + else if (:n = 253) then r = sqrt(253) ; + else if (:n = 254) then r = sqrt(254) ; + else if (:n = 255) then r = sqrt(255) ; + else if (:n = 256) then r = sqrt(256) ; + else if (:n = 257) then r = sqrt(257) ; + else if (:n = 258) then r = sqrt(258) ; + else if (:n = 259) then r = sqrt(259) ; + else if (:n = 260) then r = sqrt(260) ; + else if (:n = 261) then r = sqrt(261) ; + else if (:n = 262) then r = sqrt(262) ; + else if (:n = 263) then r = sqrt(263) ; + else if (:n = 264) then r = sqrt(264) ; + else if (:n = 265) then r = sqrt(265) ; + else if (:n = 266) then r = sqrt(266) ; + else if (:n = 267) then r = sqrt(267) ; + else if (:n = 268) then r = sqrt(268) ; + else if (:n = 269) then r = sqrt(269) ; + else if (:n = 270) then r = sqrt(270) ; + else if (:n = 271) then r = sqrt(271) ; + else if (:n = 272) then r = sqrt(272) ; + else if (:n = 273) then r = sqrt(273) ; + else if (:n = 274) then r = sqrt(274) ; + else if (:n = 275) then r = sqrt(275) ; + else if (:n = 276) then r = sqrt(276) ; + else if (:n = 277) then r = sqrt(277) ; + else if (:n = 278) then r = sqrt(278) ; + else if (:n = 279) then r = sqrt(279) ; + else if (:n = 280) then r = sqrt(280) ; + else if (:n = 281) then r = sqrt(281) ; + else if (:n = 282) then r = sqrt(282) ; + else if (:n = 283) then r = sqrt(283) ; + else if (:n = 284) then r = sqrt(284) ; + else if (:n = 285) then r = sqrt(285) ; + else if (:n = 286) then r = sqrt(286) ; + else if (:n = 287) then r = sqrt(287) ; + else if (:n = 288) then r = sqrt(288) ; + else if (:n = 289) then r = sqrt(289) ; + else if (:n = 290) then r = sqrt(290) ; + else if (:n = 291) then r = sqrt(291) ; + else if (:n = 292) then r = sqrt(292) ; + else if (:n = 293) then r = sqrt(293) ; + else if (:n = 294) then r = sqrt(294) ; + else if (:n = 295) then r = sqrt(295) ; + else if (:n = 296) then r = sqrt(296) ; + else if (:n = 297) then r = sqrt(297) ; + else if (:n = 298) then r = sqrt(298) ; + else if (:n = 299) then r = sqrt(299) ; + else if (:n = 300) then r = sqrt(300) ; + else if (:n = 301) then r = sqrt(301) ; + else if (:n = 302) then r = sqrt(302) ; + else if (:n = 303) then r = sqrt(303) ; + else if (:n = 304) then r = sqrt(304) ; + else if (:n = 305) then r = sqrt(305) ; + else if (:n = 306) then r = sqrt(306) ; + else if (:n = 307) then r = sqrt(307) ; + else if (:n = 308) then r = sqrt(308) ; + else if (:n = 309) then r = sqrt(309) ; + else if (:n = 310) then r = sqrt(310) ; + else if (:n = 311) then r = sqrt(311) ; + else if (:n = 312) then r = sqrt(312) ; + else if (:n = 313) then r = sqrt(313) ; + else if (:n = 314) then r = sqrt(314) ; + else if (:n = 315) then r = sqrt(315) ; + else if (:n = 316) then r = sqrt(316) ; + else if (:n = 317) then r = sqrt(317) ; + else if (:n = 318) then r = sqrt(318) ; + else if (:n = 319) then r = sqrt(319) ; + else if (:n = 320) then r = sqrt(320) ; + else if (:n = 321) then r = sqrt(321) ; + else if (:n = 322) then r = sqrt(322) ; + else if (:n = 323) then r = sqrt(323) ; + else if (:n = 324) then r = sqrt(324) ; + else if (:n = 325) then r = sqrt(325) ; + else if (:n = 326) then r = sqrt(326) ; + else if (:n = 327) then r = sqrt(327) ; + else if (:n = 328) then r = sqrt(328) ; + else if (:n = 329) then r = sqrt(329) ; + else if (:n = 330) then r = sqrt(330) ; + else if (:n = 331) then r = sqrt(331) ; + else if (:n = 332) then r = sqrt(332) ; + else if (:n = 333) then r = sqrt(333) ; + else if (:n = 334) then r = sqrt(334) ; + else if (:n = 335) then r = sqrt(335) ; + else if (:n = 336) then r = sqrt(336) ; + else if (:n = 337) then r = sqrt(337) ; + else if (:n = 338) then r = sqrt(338) ; + else if (:n = 339) then r = sqrt(339) ; + else if (:n = 340) then r = sqrt(340) ; + else if (:n = 341) then r = sqrt(341) ; + else if (:n = 342) then r = sqrt(342) ; + else if (:n = 343) then r = sqrt(343) ; + else if (:n = 344) then r = sqrt(344) ; + else if (:n = 345) then r = sqrt(345) ; + else if (:n = 346) then r = sqrt(346) ; + else if (:n = 347) then r = sqrt(347) ; + else if (:n = 348) then r = sqrt(348) ; + else if (:n = 349) then r = sqrt(349) ; + else if (:n = 350) then r = sqrt(350) ; + else if (:n = 351) then r = sqrt(351) ; + else if (:n = 352) then r = sqrt(352) ; + else if (:n = 353) then r = sqrt(353) ; + else if (:n = 354) then r = sqrt(354) ; + else if (:n = 355) then r = sqrt(355) ; + else if (:n = 356) then r = sqrt(356) ; + else if (:n = 357) then r = sqrt(357) ; + else if (:n = 358) then r = sqrt(358) ; + else if (:n = 359) then r = sqrt(359) ; + else if (:n = 360) then r = sqrt(360) ; + else if (:n = 361) then r = sqrt(361) ; + else if (:n = 362) then r = sqrt(362) ; + else if (:n = 363) then r = sqrt(363) ; + else if (:n = 364) then r = sqrt(364) ; + else if (:n = 365) then r = sqrt(365) ; + else if (:n = 366) then r = sqrt(366) ; + else if (:n = 367) then r = sqrt(367) ; + else if (:n = 368) then r = sqrt(368) ; + else if (:n = 369) then r = sqrt(369) ; + else if (:n = 370) then r = sqrt(370) ; + else if (:n = 371) then r = sqrt(371) ; + else if (:n = 372) then r = sqrt(372) ; + else if (:n = 373) then r = sqrt(373) ; + else if (:n = 374) then r = sqrt(374) ; + else if (:n = 375) then r = sqrt(375) ; + else if (:n = 376) then r = sqrt(376) ; + else if (:n = 377) then r = sqrt(377) ; + else if (:n = 378) then r = sqrt(378) ; + else if (:n = 379) then r = sqrt(379) ; + else if (:n = 380) then r = sqrt(380) ; + else if (:n = 381) then r = sqrt(381) ; + else if (:n = 382) then r = sqrt(382) ; + else if (:n = 383) then r = sqrt(383) ; + else if (:n = 384) then r = sqrt(384) ; + else if (:n = 385) then r = sqrt(385) ; + else if (:n = 386) then r = sqrt(386) ; + else if (:n = 387) then r = sqrt(387) ; + else if (:n = 388) then r = sqrt(388) ; + else if (:n = 389) then r = sqrt(389) ; + else if (:n = 390) then r = sqrt(390) ; + else if (:n = 391) then r = sqrt(391) ; + else if (:n = 392) then r = sqrt(392) ; + else if (:n = 393) then r = sqrt(393) ; + else if (:n = 394) then r = sqrt(394) ; + else if (:n = 395) then r = sqrt(395) ; + else if (:n = 396) then r = sqrt(396) ; + else if (:n = 397) then r = sqrt(397) ; + else if (:n = 398) then r = sqrt(398) ; + else if (:n = 399) then r = sqrt(399) ; + else if (:n = 400) then r = sqrt(400) ; + else if (:n = 401) then r = sqrt(401) ; + else if (:n = 402) then r = sqrt(402) ; + else if (:n = 403) then r = sqrt(403) ; + else if (:n = 404) then r = sqrt(404) ; + else if (:n = 405) then r = sqrt(405) ; + else if (:n = 406) then r = sqrt(406) ; + else if (:n = 407) then r = sqrt(407) ; + else if (:n = 408) then r = sqrt(408) ; + else if (:n = 409) then r = sqrt(409) ; + else if (:n = 410) then r = sqrt(410) ; + else if (:n = 411) then r = sqrt(411) ; + else if (:n = 412) then r = sqrt(412) ; + else if (:n = 413) then r = sqrt(413) ; + else if (:n = 414) then r = sqrt(414) ; + else if (:n = 415) then r = sqrt(415) ; + else if (:n = 416) then r = sqrt(416) ; + else if (:n = 417) then r = sqrt(417) ; + else if (:n = 418) then r = sqrt(418) ; + else if (:n = 419) then r = sqrt(419) ; + else if (:n = 420) then r = sqrt(420) ; + else if (:n = 421) then r = sqrt(421) ; + else if (:n = 422) then r = sqrt(422) ; + else if (:n = 423) then r = sqrt(423) ; + else if (:n = 424) then r = sqrt(424) ; + else if (:n = 425) then r = sqrt(425) ; + else if (:n = 426) then r = sqrt(426) ; + else if (:n = 427) then r = sqrt(427) ; + else if (:n = 428) then r = sqrt(428) ; + else if (:n = 429) then r = sqrt(429) ; + else if (:n = 430) then r = sqrt(430) ; + else if (:n = 431) then r = sqrt(431) ; + else if (:n = 432) then r = sqrt(432) ; + else if (:n = 433) then r = sqrt(433) ; + else if (:n = 434) then r = sqrt(434) ; + else if (:n = 435) then r = sqrt(435) ; + else if (:n = 436) then r = sqrt(436) ; + else if (:n = 437) then r = sqrt(437) ; + else if (:n = 438) then r = sqrt(438) ; + else if (:n = 439) then r = sqrt(439) ; + else if (:n = 440) then r = sqrt(440) ; + else if (:n = 441) then r = sqrt(441) ; + else if (:n = 442) then r = sqrt(442) ; + else if (:n = 443) then r = sqrt(443) ; + else if (:n = 444) then r = sqrt(444) ; + else if (:n = 445) then r = sqrt(445) ; + else if (:n = 446) then r = sqrt(446) ; + else if (:n = 447) then r = sqrt(447) ; + else if (:n = 448) then r = sqrt(448) ; + else if (:n = 449) then r = sqrt(449) ; + else if (:n = 450) then r = sqrt(450) ; + else if (:n = 451) then r = sqrt(451) ; + else if (:n = 452) then r = sqrt(452) ; + else if (:n = 453) then r = sqrt(453) ; + else if (:n = 454) then r = sqrt(454) ; + else if (:n = 455) then r = sqrt(455) ; + else if (:n = 456) then r = sqrt(456) ; + else if (:n = 457) then r = sqrt(457) ; + else if (:n = 458) then r = sqrt(458) ; + else if (:n = 459) then r = sqrt(459) ; + else if (:n = 460) then r = sqrt(460) ; + else if (:n = 461) then r = sqrt(461) ; + else if (:n = 462) then r = sqrt(462) ; + else if (:n = 463) then r = sqrt(463) ; + else if (:n = 464) then r = sqrt(464) ; + else if (:n = 465) then r = sqrt(465) ; + else if (:n = 466) then r = sqrt(466) ; + else if (:n = 467) then r = sqrt(467) ; + else if (:n = 468) then r = sqrt(468) ; + else if (:n = 469) then r = sqrt(469) ; + else if (:n = 470) then r = sqrt(470) ; + else if (:n = 471) then r = sqrt(471) ; + else if (:n = 472) then r = sqrt(472) ; + else if (:n = 473) then r = sqrt(473) ; + else if (:n = 474) then r = sqrt(474) ; + else if (:n = 475) then r = sqrt(475) ; + else if (:n = 476) then r = sqrt(476) ; + else if (:n = 477) then r = sqrt(477) ; + else if (:n = 478) then r = sqrt(478) ; + else if (:n = 479) then r = sqrt(479) ; + else if (:n = 480) then r = sqrt(480) ; + else if (:n = 481) then r = sqrt(481) ; + else if (:n = 482) then r = sqrt(482) ; + else if (:n = 483) then r = sqrt(483) ; + else if (:n = 484) then r = sqrt(484) ; + else if (:n = 485) then r = sqrt(485) ; + else if (:n = 486) then r = sqrt(486) ; + else if (:n = 487) then r = sqrt(487) ; + else if (:n = 488) then r = sqrt(488) ; + else if (:n = 489) then r = sqrt(489) ; + else if (:n = 490) then r = sqrt(490) ; + else if (:n = 491) then r = sqrt(491) ; + else if (:n = 492) then r = sqrt(492) ; + else if (:n = 493) then r = sqrt(493) ; + else if (:n = 494) then r = sqrt(494) ; + else if (:n = 495) then r = sqrt(495) ; + else if (:n = 496) then r = sqrt(496) ; + else if (:n = 497) then r = sqrt(497) ; + else if (:n = 498) then r = sqrt(498) ; + else if (:n = 499) then r = sqrt(499) ; + else if (:n = 500) then r = sqrt(500) ; + else if (:n = 501) then r = sqrt(501) ; + else if (:n = 502) then r = sqrt(502) ; + else if (:n = 503) then r = sqrt(503) ; + else if (:n = 504) then r = sqrt(504) ; + else if (:n = 505) then r = sqrt(505) ; + else if (:n = 506) then r = sqrt(506) ; + else if (:n = 507) then r = sqrt(507) ; + else if (:n = 508) then r = sqrt(508) ; + else if (:n = 509) then r = sqrt(509) ; + else if (:n = 510) then r = sqrt(510) ; + else if (:n = 511) then r = sqrt(511) ; + else if (:n = 512) then r = sqrt(512) ; + else if (:n = 513) then r = sqrt(513) ; + else if (:n = 514) then r = sqrt(514) ; + else if (:n = 515) then r = sqrt(515) ; + else if (:n = 516) then r = sqrt(516) ; + else if (:n = 517) then r = sqrt(517) ; + else if (:n = 518) then r = sqrt(518) ; + else if (:n = 519) then r = sqrt(519) ; + else if (:n = 520) then r = sqrt(520) ; + else if (:n = 521) then r = sqrt(521) ; + else if (:n = 522) then r = sqrt(522) ; + else if (:n = 523) then r = sqrt(523) ; + else if (:n = 524) then r = sqrt(524) ; + else if (:n = 525) then r = sqrt(525) ; + else if (:n = 526) then r = sqrt(526) ; + else if (:n = 527) then r = sqrt(527) ; + else if (:n = 528) then r = sqrt(528) ; + else if (:n = 529) then r = sqrt(529) ; + else if (:n = 530) then r = sqrt(530) ; + else if (:n = 531) then r = sqrt(531) ; + else if (:n = 532) then r = sqrt(532) ; + else if (:n = 533) then r = sqrt(533) ; + else if (:n = 534) then r = sqrt(534) ; + else if (:n = 535) then r = sqrt(535) ; + else if (:n = 536) then r = sqrt(536) ; + else if (:n = 537) then r = sqrt(537) ; + else if (:n = 538) then r = sqrt(538) ; + else if (:n = 539) then r = sqrt(539) ; + else if (:n = 540) then r = sqrt(540) ; + else if (:n = 541) then r = sqrt(541) ; + else if (:n = 542) then r = sqrt(542) ; + else if (:n = 543) then r = sqrt(543) ; + else if (:n = 544) then r = sqrt(544) ; + else if (:n = 545) then r = sqrt(545) ; + else if (:n = 546) then r = sqrt(546) ; + else if (:n = 547) then r = sqrt(547) ; + else if (:n = 548) then r = sqrt(548) ; + else if (:n = 549) then r = sqrt(549) ; + else if (:n = 550) then r = sqrt(550) ; + else if (:n = 551) then r = sqrt(551) ; + else if (:n = 552) then r = sqrt(552) ; + else if (:n = 553) then r = sqrt(553) ; + else if (:n = 554) then r = sqrt(554) ; + else if (:n = 555) then r = sqrt(555) ; + else if (:n = 556) then r = sqrt(556) ; + else if (:n = 557) then r = sqrt(557) ; + else if (:n = 558) then r = sqrt(558) ; + else if (:n = 559) then r = sqrt(559) ; + else if (:n = 560) then r = sqrt(560) ; + else if (:n = 561) then r = sqrt(561) ; + else if (:n = 562) then r = sqrt(562) ; + else if (:n = 563) then r = sqrt(563) ; + else if (:n = 564) then r = sqrt(564) ; + else if (:n = 565) then r = sqrt(565) ; + else if (:n = 566) then r = sqrt(566) ; + else if (:n = 567) then r = sqrt(567) ; + else if (:n = 568) then r = sqrt(568) ; + else if (:n = 569) then r = sqrt(569) ; + else if (:n = 570) then r = sqrt(570) ; + else if (:n = 571) then r = sqrt(571) ; + else if (:n = 572) then r = sqrt(572) ; + else if (:n = 573) then r = sqrt(573) ; + else if (:n = 574) then r = sqrt(574) ; + else if (:n = 575) then r = sqrt(575) ; + else if (:n = 576) then r = sqrt(576) ; + else if (:n = 577) then r = sqrt(577) ; + else if (:n = 578) then r = sqrt(578) ; + else if (:n = 579) then r = sqrt(579) ; + else if (:n = 580) then r = sqrt(580) ; + else if (:n = 581) then r = sqrt(581) ; + else if (:n = 582) then r = sqrt(582) ; + else if (:n = 583) then r = sqrt(583) ; + else if (:n = 584) then r = sqrt(584) ; + else if (:n = 585) then r = sqrt(585) ; + else if (:n = 586) then r = sqrt(586) ; + else if (:n = 587) then r = sqrt(587) ; + else if (:n = 588) then r = sqrt(588) ; + else if (:n = 589) then r = sqrt(589) ; + else if (:n = 590) then r = sqrt(590) ; + else if (:n = 591) then r = sqrt(591) ; + else if (:n = 592) then r = sqrt(592) ; + else if (:n = 593) then r = sqrt(593) ; + else if (:n = 594) then r = sqrt(594) ; + else if (:n = 595) then r = sqrt(595) ; + else if (:n = 596) then r = sqrt(596) ; + else if (:n = 597) then r = sqrt(597) ; + else if (:n = 598) then r = sqrt(598) ; + else if (:n = 599) then r = sqrt(599) ; + else if (:n = 600) then r = sqrt(600) ; + else if (:n = 601) then r = sqrt(601) ; + else if (:n = 602) then r = sqrt(602) ; + else if (:n = 603) then r = sqrt(603) ; + else if (:n = 604) then r = sqrt(604) ; + else if (:n = 605) then r = sqrt(605) ; + else if (:n = 606) then r = sqrt(606) ; + else if (:n = 607) then r = sqrt(607) ; + else if (:n = 608) then r = sqrt(608) ; + else if (:n = 609) then r = sqrt(609) ; + else if (:n = 610) then r = sqrt(610) ; + else if (:n = 611) then r = sqrt(611) ; + else if (:n = 612) then r = sqrt(612) ; + else if (:n = 613) then r = sqrt(613) ; + else if (:n = 614) then r = sqrt(614) ; + else if (:n = 615) then r = sqrt(615) ; + else if (:n = 616) then r = sqrt(616) ; + else if (:n = 617) then r = sqrt(617) ; + else if (:n = 618) then r = sqrt(618) ; + else if (:n = 619) then r = sqrt(619) ; + else if (:n = 620) then r = sqrt(620) ; + else if (:n = 621) then r = sqrt(621) ; + else if (:n = 622) then r = sqrt(622) ; + else if (:n = 623) then r = sqrt(623) ; + else if (:n = 624) then r = sqrt(624) ; + else if (:n = 625) then r = sqrt(625) ; + else if (:n = 626) then r = sqrt(626) ; + else if (:n = 627) then r = sqrt(627) ; + else if (:n = 628) then r = sqrt(628) ; + else if (:n = 629) then r = sqrt(629) ; + else if (:n = 630) then r = sqrt(630) ; + else if (:n = 631) then r = sqrt(631) ; + else if (:n = 632) then r = sqrt(632) ; + else if (:n = 633) then r = sqrt(633) ; + else if (:n = 634) then r = sqrt(634) ; + else if (:n = 635) then r = sqrt(635) ; + else if (:n = 636) then r = sqrt(636) ; + else if (:n = 637) then r = sqrt(637) ; + else if (:n = 638) then r = sqrt(638) ; + else if (:n = 639) then r = sqrt(639) ; + else if (:n = 640) then r = sqrt(640) ; + else if (:n = 641) then r = sqrt(641) ; + else if (:n = 642) then r = sqrt(642) ; + else if (:n = 643) then r = sqrt(643) ; + else if (:n = 644) then r = sqrt(644) ; + else if (:n = 645) then r = sqrt(645) ; + else if (:n = 646) then r = sqrt(646) ; + else if (:n = 647) then r = sqrt(647) ; + else if (:n = 648) then r = sqrt(648) ; + else if (:n = 649) then r = sqrt(649) ; + else if (:n = 650) then r = sqrt(650) ; + else if (:n = 651) then r = sqrt(651) ; + else if (:n = 652) then r = sqrt(652) ; + else if (:n = 653) then r = sqrt(653) ; + else if (:n = 654) then r = sqrt(654) ; + else if (:n = 655) then r = sqrt(655) ; + else if (:n = 656) then r = sqrt(656) ; + else if (:n = 657) then r = sqrt(657) ; + else if (:n = 658) then r = sqrt(658) ; + else if (:n = 659) then r = sqrt(659) ; + else if (:n = 660) then r = sqrt(660) ; + else if (:n = 661) then r = sqrt(661) ; + else if (:n = 662) then r = sqrt(662) ; + else if (:n = 663) then r = sqrt(663) ; + else if (:n = 664) then r = sqrt(664) ; + else if (:n = 665) then r = sqrt(665) ; + else if (:n = 666) then r = sqrt(666) ; + else if (:n = 667) then r = sqrt(667) ; + else if (:n = 668) then r = sqrt(668) ; + else if (:n = 669) then r = sqrt(669) ; + else if (:n = 670) then r = sqrt(670) ; + else if (:n = 671) then r = sqrt(671) ; + else if (:n = 672) then r = sqrt(672) ; + else if (:n = 673) then r = sqrt(673) ; + else if (:n = 674) then r = sqrt(674) ; + else if (:n = 675) then r = sqrt(675) ; + else if (:n = 676) then r = sqrt(676) ; + else if (:n = 677) then r = sqrt(677) ; + else if (:n = 678) then r = sqrt(678) ; + else if (:n = 679) then r = sqrt(679) ; + else if (:n = 680) then r = sqrt(680) ; + else if (:n = 681) then r = sqrt(681) ; + else if (:n = 682) then r = sqrt(682) ; + else if (:n = 683) then r = sqrt(683) ; + else if (:n = 684) then r = sqrt(684) ; + else if (:n = 685) then r = sqrt(685) ; + else if (:n = 686) then r = sqrt(686) ; + else if (:n = 687) then r = sqrt(687) ; + else if (:n = 688) then r = sqrt(688) ; + else if (:n = 689) then r = sqrt(689) ; + else if (:n = 690) then r = sqrt(690) ; + else if (:n = 691) then r = sqrt(691) ; + else if (:n = 692) then r = sqrt(692) ; + else if (:n = 693) then r = sqrt(693) ; + else if (:n = 694) then r = sqrt(694) ; + else if (:n = 695) then r = sqrt(695) ; + else if (:n = 696) then r = sqrt(696) ; + else if (:n = 697) then r = sqrt(697) ; + else if (:n = 698) then r = sqrt(698) ; + else if (:n = 699) then r = sqrt(699) ; + else if (:n = 700) then r = sqrt(700) ; + else if (:n = 701) then r = sqrt(701) ; + else if (:n = 702) then r = sqrt(702) ; + else if (:n = 703) then r = sqrt(703) ; + else if (:n = 704) then r = sqrt(704) ; + else if (:n = 705) then r = sqrt(705) ; + else if (:n = 706) then r = sqrt(706) ; + else if (:n = 707) then r = sqrt(707) ; + else if (:n = 708) then r = sqrt(708) ; + else if (:n = 709) then r = sqrt(709) ; + else if (:n = 710) then r = sqrt(710) ; + else if (:n = 711) then r = sqrt(711) ; + else if (:n = 712) then r = sqrt(712) ; + else if (:n = 713) then r = sqrt(713) ; + else if (:n = 714) then r = sqrt(714) ; + else if (:n = 715) then r = sqrt(715) ; + else if (:n = 716) then r = sqrt(716) ; + else if (:n = 717) then r = sqrt(717) ; + else if (:n = 718) then r = sqrt(718) ; + else if (:n = 719) then r = sqrt(719) ; + else if (:n = 720) then r = sqrt(720) ; + else if (:n = 721) then r = sqrt(721) ; + else if (:n = 722) then r = sqrt(722) ; + else if (:n = 723) then r = sqrt(723) ; + else if (:n = 724) then r = sqrt(724) ; + else if (:n = 725) then r = sqrt(725) ; + else if (:n = 726) then r = sqrt(726) ; + else if (:n = 727) then r = sqrt(727) ; + else if (:n = 728) then r = sqrt(728) ; + else if (:n = 729) then r = sqrt(729) ; + else if (:n = 730) then r = sqrt(730) ; + else if (:n = 731) then r = sqrt(731) ; + else if (:n = 732) then r = sqrt(732) ; + else if (:n = 733) then r = sqrt(733) ; + else if (:n = 734) then r = sqrt(734) ; + else if (:n = 735) then r = sqrt(735) ; + else if (:n = 736) then r = sqrt(736) ; + else if (:n = 737) then r = sqrt(737) ; + else if (:n = 738) then r = sqrt(738) ; + else if (:n = 739) then r = sqrt(739) ; + else if (:n = 740) then r = sqrt(740) ; + else if (:n = 741) then r = sqrt(741) ; + else if (:n = 742) then r = sqrt(742) ; + else if (:n = 743) then r = sqrt(743) ; + else if (:n = 744) then r = sqrt(744) ; + else if (:n = 745) then r = sqrt(745) ; + else if (:n = 746) then r = sqrt(746) ; + else if (:n = 747) then r = sqrt(747) ; + else if (:n = 748) then r = sqrt(748) ; + else if (:n = 749) then r = sqrt(749) ; + else if (:n = 750) then r = sqrt(750) ; + else if (:n = 751) then r = sqrt(751) ; + else if (:n = 752) then r = sqrt(752) ; + else if (:n = 753) then r = sqrt(753) ; + else if (:n = 754) then r = sqrt(754) ; + else if (:n = 755) then r = sqrt(755) ; + else if (:n = 756) then r = sqrt(756) ; + else if (:n = 757) then r = sqrt(757) ; + else if (:n = 758) then r = sqrt(758) ; + else if (:n = 759) then r = sqrt(759) ; + else if (:n = 760) then r = sqrt(760) ; + else if (:n = 761) then r = sqrt(761) ; + else if (:n = 762) then r = sqrt(762) ; + else if (:n = 763) then r = sqrt(763) ; + else if (:n = 764) then r = sqrt(764) ; + else if (:n = 765) then r = sqrt(765) ; + else if (:n = 766) then r = sqrt(766) ; + else if (:n = 767) then r = sqrt(767) ; + else if (:n = 768) then r = sqrt(768) ; + else if (:n = 769) then r = sqrt(769) ; + else if (:n = 770) then r = sqrt(770) ; + else if (:n = 771) then r = sqrt(771) ; + else if (:n = 772) then r = sqrt(772) ; + else if (:n = 773) then r = sqrt(773) ; + else if (:n = 774) then r = sqrt(774) ; + else if (:n = 775) then r = sqrt(775) ; + else if (:n = 776) then r = sqrt(776) ; + else if (:n = 777) then r = sqrt(777) ; + else if (:n = 778) then r = sqrt(778) ; + else if (:n = 779) then r = sqrt(779) ; + else if (:n = 780) then r = sqrt(780) ; + else if (:n = 781) then r = sqrt(781) ; + else if (:n = 782) then r = sqrt(782) ; + else if (:n = 783) then r = sqrt(783) ; + else if (:n = 784) then r = sqrt(784) ; + else if (:n = 785) then r = sqrt(785) ; + else if (:n = 786) then r = sqrt(786) ; + else if (:n = 787) then r = sqrt(787) ; + else if (:n = 788) then r = sqrt(788) ; + else if (:n = 789) then r = sqrt(789) ; + else if (:n = 790) then r = sqrt(790) ; + else if (:n = 791) then r = sqrt(791) ; + else if (:n = 792) then r = sqrt(792) ; + else if (:n = 793) then r = sqrt(793) ; + else if (:n = 794) then r = sqrt(794) ; + else if (:n = 795) then r = sqrt(795) ; + else if (:n = 796) then r = sqrt(796) ; + else if (:n = 797) then r = sqrt(797) ; + else if (:n = 798) then r = sqrt(798) ; + else if (:n = 799) then r = sqrt(799) ; + else if (:n = 800) then r = sqrt(800) ; + else if (:n = 801) then r = sqrt(801) ; + else if (:n = 802) then r = sqrt(802) ; + else if (:n = 803) then r = sqrt(803) ; + else if (:n = 804) then r = sqrt(804) ; + else if (:n = 805) then r = sqrt(805) ; + else if (:n = 806) then r = sqrt(806) ; + else if (:n = 807) then r = sqrt(807) ; + else if (:n = 808) then r = sqrt(808) ; + else if (:n = 809) then r = sqrt(809) ; + else if (:n = 810) then r = sqrt(810) ; + else if (:n = 811) then r = sqrt(811) ; + else if (:n = 812) then r = sqrt(812) ; + else if (:n = 813) then r = sqrt(813) ; + else if (:n = 814) then r = sqrt(814) ; + else if (:n = 815) then r = sqrt(815) ; + else if (:n = 816) then r = sqrt(816) ; + else if (:n = 817) then r = sqrt(817) ; + else if (:n = 818) then r = sqrt(818) ; + else if (:n = 819) then r = sqrt(819) ; + else if (:n = 820) then r = sqrt(820) ; + else if (:n = 821) then r = sqrt(821) ; + else if (:n = 822) then r = sqrt(822) ; + else if (:n = 823) then r = sqrt(823) ; + else if (:n = 824) then r = sqrt(824) ; + else if (:n = 825) then r = sqrt(825) ; + else if (:n = 826) then r = sqrt(826) ; + else if (:n = 827) then r = sqrt(827) ; + else if (:n = 828) then r = sqrt(828) ; + else if (:n = 829) then r = sqrt(829) ; + else if (:n = 830) then r = sqrt(830) ; + else if (:n = 831) then r = sqrt(831) ; + else if (:n = 832) then r = sqrt(832) ; + else if (:n = 833) then r = sqrt(833) ; + else if (:n = 834) then r = sqrt(834) ; + else if (:n = 835) then r = sqrt(835) ; + else if (:n = 836) then r = sqrt(836) ; + else if (:n = 837) then r = sqrt(837) ; + else if (:n = 838) then r = sqrt(838) ; + else if (:n = 839) then r = sqrt(839) ; + else if (:n = 840) then r = sqrt(840) ; + else if (:n = 841) then r = sqrt(841) ; + else if (:n = 842) then r = sqrt(842) ; + else if (:n = 843) then r = sqrt(843) ; + else if (:n = 844) then r = sqrt(844) ; + else if (:n = 845) then r = sqrt(845) ; + else if (:n = 846) then r = sqrt(846) ; + else if (:n = 847) then r = sqrt(847) ; + else if (:n = 848) then r = sqrt(848) ; + else if (:n = 849) then r = sqrt(849) ; + else if (:n = 850) then r = sqrt(850) ; + else if (:n = 851) then r = sqrt(851) ; + else if (:n = 852) then r = sqrt(852) ; + else if (:n = 853) then r = sqrt(853) ; + else if (:n = 854) then r = sqrt(854) ; + else if (:n = 855) then r = sqrt(855) ; + else if (:n = 856) then r = sqrt(856) ; + else if (:n = 857) then r = sqrt(857) ; + else if (:n = 858) then r = sqrt(858) ; + else if (:n = 859) then r = sqrt(859) ; + else if (:n = 860) then r = sqrt(860) ; + else if (:n = 861) then r = sqrt(861) ; + else if (:n = 862) then r = sqrt(862) ; + else if (:n = 863) then r = sqrt(863) ; + else if (:n = 864) then r = sqrt(864) ; + else if (:n = 865) then r = sqrt(865) ; + else if (:n = 866) then r = sqrt(866) ; + else if (:n = 867) then r = sqrt(867) ; + else if (:n = 868) then r = sqrt(868) ; + else if (:n = 869) then r = sqrt(869) ; + else if (:n = 870) then r = sqrt(870) ; + else if (:n = 871) then r = sqrt(871) ; + else if (:n = 872) then r = sqrt(872) ; + else if (:n = 873) then r = sqrt(873) ; + else if (:n = 874) then r = sqrt(874) ; + else if (:n = 875) then r = sqrt(875) ; + else if (:n = 876) then r = sqrt(876) ; + else if (:n = 877) then r = sqrt(877) ; + else if (:n = 878) then r = sqrt(878) ; + else if (:n = 879) then r = sqrt(879) ; + else if (:n = 880) then r = sqrt(880) ; + else if (:n = 881) then r = sqrt(881) ; + else if (:n = 882) then r = sqrt(882) ; + else if (:n = 883) then r = sqrt(883) ; + else if (:n = 884) then r = sqrt(884) ; + else if (:n = 885) then r = sqrt(885) ; + else if (:n = 886) then r = sqrt(886) ; + else if (:n = 887) then r = sqrt(887) ; + else if (:n = 888) then r = sqrt(888) ; + else if (:n = 889) then r = sqrt(889) ; + else if (:n = 890) then r = sqrt(890) ; + else if (:n = 891) then r = sqrt(891) ; + else if (:n = 892) then r = sqrt(892) ; + else if (:n = 893) then r = sqrt(893) ; + else if (:n = 894) then r = sqrt(894) ; + else if (:n = 895) then r = sqrt(895) ; + else if (:n = 896) then r = sqrt(896) ; + else if (:n = 897) then r = sqrt(897) ; + else if (:n = 898) then r = sqrt(898) ; + else if (:n = 899) then r = sqrt(899) ; + else if (:n = 900) then r = sqrt(900) ; + else if (:n = 901) then r = sqrt(901) ; + else if (:n = 902) then r = sqrt(902) ; + else if (:n = 903) then r = sqrt(903) ; + else if (:n = 904) then r = sqrt(904) ; + else if (:n = 905) then r = sqrt(905) ; + else if (:n = 906) then r = sqrt(906) ; + else if (:n = 907) then r = sqrt(907) ; + else if (:n = 908) then r = sqrt(908) ; + else if (:n = 909) then r = sqrt(909) ; + else if (:n = 910) then r = sqrt(910) ; + else if (:n = 911) then r = sqrt(911) ; + else if (:n = 912) then r = sqrt(912) ; + else if (:n = 913) then r = sqrt(913) ; + else if (:n = 914) then r = sqrt(914) ; + else if (:n = 915) then r = sqrt(915) ; + else if (:n = 916) then r = sqrt(916) ; + else if (:n = 917) then r = sqrt(917) ; + else if (:n = 918) then r = sqrt(918) ; + else if (:n = 919) then r = sqrt(919) ; + else if (:n = 920) then r = sqrt(920) ; + else if (:n = 921) then r = sqrt(921) ; + else if (:n = 922) then r = sqrt(922) ; + else if (:n = 923) then r = sqrt(923) ; + else if (:n = 924) then r = sqrt(924) ; + else if (:n = 925) then r = sqrt(925) ; + else if (:n = 926) then r = sqrt(926) ; + else if (:n = 927) then r = sqrt(927) ; + else if (:n = 928) then r = sqrt(928) ; + else if (:n = 929) then r = sqrt(929) ; + else if (:n = 930) then r = sqrt(930) ; + else if (:n = 931) then r = sqrt(931) ; + else if (:n = 932) then r = sqrt(932) ; + else if (:n = 933) then r = sqrt(933) ; + else if (:n = 934) then r = sqrt(934) ; + else if (:n = 935) then r = sqrt(935) ; + else if (:n = 936) then r = sqrt(936) ; + else if (:n = 937) then r = sqrt(937) ; + else if (:n = 938) then r = sqrt(938) ; + else if (:n = 939) then r = sqrt(939) ; + else if (:n = 940) then r = sqrt(940) ; + else if (:n = 941) then r = sqrt(941) ; + else if (:n = 942) then r = sqrt(942) ; + else if (:n = 943) then r = sqrt(943) ; + else if (:n = 944) then r = sqrt(944) ; + else if (:n = 945) then r = sqrt(945) ; + else if (:n = 946) then r = sqrt(946) ; + else if (:n = 947) then r = sqrt(947) ; + else if (:n = 948) then r = sqrt(948) ; + else if (:n = 949) then r = sqrt(949) ; + else if (:n = 950) then r = sqrt(950) ; + else if (:n = 951) then r = sqrt(951) ; + else if (:n = 952) then r = sqrt(952) ; + else if (:n = 953) then r = sqrt(953) ; + else if (:n = 954) then r = sqrt(954) ; + else if (:n = 955) then r = sqrt(955) ; + else if (:n = 956) then r = sqrt(956) ; + else if (:n = 957) then r = sqrt(957) ; + else if (:n = 958) then r = sqrt(958) ; + else if (:n = 959) then r = sqrt(959) ; + else if (:n = 960) then r = sqrt(960) ; + else if (:n = 961) then r = sqrt(961) ; + else if (:n = 962) then r = sqrt(962) ; + else if (:n = 963) then r = sqrt(963) ; + else if (:n = 964) then r = sqrt(964) ; + else if (:n = 965) then r = sqrt(965) ; + else if (:n = 966) then r = sqrt(966) ; + else if (:n = 967) then r = sqrt(967) ; + else if (:n = 968) then r = sqrt(968) ; + else if (:n = 969) then r = sqrt(969) ; + else if (:n = 970) then r = sqrt(970) ; + else if (:n = 971) then r = sqrt(971) ; + else if (:n = 972) then r = sqrt(972) ; + else if (:n = 973) then r = sqrt(973) ; + else if (:n = 974) then r = sqrt(974) ; + else if (:n = 975) then r = sqrt(975) ; + else if (:n = 976) then r = sqrt(976) ; + else if (:n = 977) then r = sqrt(977) ; + else if (:n = 978) then r = sqrt(978) ; + else if (:n = 979) then r = sqrt(979) ; + else if (:n = 980) then r = sqrt(980) ; + else if (:n = 981) then r = sqrt(981) ; + else if (:n = 982) then r = sqrt(982) ; + else if (:n = 983) then r = sqrt(983) ; + else if (:n = 984) then r = sqrt(984) ; + else if (:n = 985) then r = sqrt(985) ; + else if (:n = 986) then r = sqrt(986) ; + else if (:n = 987) then r = sqrt(987) ; + else if (:n = 988) then r = sqrt(988) ; + else if (:n = 989) then r = sqrt(989) ; + else if (:n = 990) then r = sqrt(990) ; + else if (:n = 991) then r = sqrt(991) ; + else if (:n = 992) then r = sqrt(992) ; + else if (:n = 993) then r = sqrt(993) ; + else if (:n = 994) then r = sqrt(994) ; + else if (:n = 995) then r = sqrt(995) ; + else if (:n = 996) then r = sqrt(996) ; + else if (:n = 997) then r = sqrt(997) ; + else if (:n = 998) then r = sqrt(998) ; + else if (:n = 999) then r = sqrt(999) ; + else r = sqrt(1000); + suspend; + end ^ + set term ;^ + set list on; + select * from sp_ifel(1000); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + R 31.62277660168379 + """ + +@pytest.mark.version('>=2.5') +def test_core_0039_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0053.py b/tests/bugs/test_core_0053.py new file mode 100644 index 00000000..aaaef1d3 --- /dev/null +++ b/tests/bugs/test_core_0053.py @@ -0,0 +1,150 @@ +#coding:utf-8 +# +# id: bugs.core_0053 +# title: FIRST 1 vs ORDER DESC vs explicit plan (ODS11) +# decription: +# Test uses pre-created database which has several procedures for analyzing performance by with the help of MON$ tables. +# Performance results are gathered in the table STAT_LOG, each odd run will save mon$ counters with "-" sign and next +# (even) run will save them with "+" -- see SP_GATHER_STAT. +# Aggegation of results is done in the view V_AGG_STAT (negative values relate to start, positive to the end of measure, +# difference between them means performance expenses which we want to evaluate). +# NOTE. Before each new measure we have to set generator G_GATHER_STAT to zero in order to make it produce proper values +# starting with 1 (odd --> NEGATIVE sign for counters). This is done in SP_TRUNCATE_STAT. +# +# :::::::::::::::::::::::::::::::::::::::: NB :::::::::::::::::::::::::::::::::::: +# 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 change code of SP_TRUNCATE_STAT: instead of 'alter sequence restart...' we do +# reset like this: c = gen_id(g_gather_stat, -gen_id(g_gather_stat, 0)); +# +# Checked on: +# 4.0.0.2164 SS: 2.511s. +# 4.0.0.2164 CS: 2.533s. +# 3.0.7.33356 SS: 1.495s. +# 3.0.7.33356 CS: 2.865s. +# 2.5.9.27150 SC: 0.730s. +# +# tracker_id: CORE-0053 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='mon-stat-gathering-2_5.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + + create or alter procedure gendata as begin end; + recreate table test (F1 integer, F2 date); + commit; + + set term ^; + create or alter procedure GenData as + declare i integer; + begin + i= 0; + while (i < 100000) do begin + insert into test(F1, F2) values (:i, 'yesterday'); + i= i+1; + end + end + ^ + set term ;^ + commit; + + execute procedure gendata; + commit; + + create desc index test_f1_f2 on test(F1, F2); + commit; + + execute procedure sp_truncate_stat; + commit; + + -- #################### MEASURE-1 ################# + + execute procedure sp_gather_stat; ------- catch statistics BEFORE measured statement(s) + commit; + + set plan on; + select first 1 f1 + from test t + where t.f1=17 and f2 <= 'today' + plan (T order test_f1_f2) + order by F1 desc, F2 desc; + set plan off; + + execute procedure sp_gather_stat; ------- catch statistics BEFORE measured statement(s) + commit; + + -- #################### MEASURE-2 ################# + + + execute procedure sp_gather_stat; ------- catch statistics BEFORE measured statement(s) + commit; + + set plan on; + select first 1 f1 + from test t + where t.f1=17 and f2 <= 'today' + plan (t order test_f1_f2 index (test_f1_f2)) + order by F1 desc, F2 desc; + set plan off; + + execute procedure sp_gather_stat; ------- catch statistics BEFORE measured statement(s) + commit; + + -- #################### ANALYZING RESULTS ################# + + set list on; + select + iif( idx_1 / idx_2 > max_ratio, 'PLAN (T ORDER ) is slow! Ratio > ' || max_ratio, + iif( idx_2 / idx_1 > max_ratio, 'PLAN (T ORDER INDEX()) is slow! Ratio > '|| max_ratio, + 'PERFORMANCE IS THE SAME.' + ) + ) result + from ( + select + cast(min(idx_1) as double precision) as idx_1, + cast( min(idx_2) as double precision) as idx_2, + 3.00 as max_ratio + from ( + select iif(rowset=1, indexed_reads, null) idx_1, iif(rowset=2, indexed_reads, null) idx_2 + from v_agg_stat + ) g + ); + -- Difference of indexed reads that is reported by MON$ tables: + -- on 2.5 = {5, 5}, on 3.0 = {5, 3} ==> ratio 3.00 should be always enough. + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (T ORDER TEST_F1_F2) + F1 17 + PLAN (T ORDER TEST_F1_F2 INDEX (TEST_F1_F2)) + F1 17 + RESULT PERFORMANCE IS THE SAME. + """ + +@pytest.mark.version('>=2.5.1') +def test_core_0053_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0058.py b/tests/bugs/test_core_0058.py new file mode 100644 index 00000000..f3842eef --- /dev/null +++ b/tests/bugs/test_core_0058.py @@ -0,0 +1,69 @@ +#coding:utf-8 +# +# id: bugs.core_0058 +# title: WHERE CURRENT OF doesn't work +# decription: +# tracker_id: CORE-0058 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('line: [0-9]+, col: [0-9]+', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- NB: changed expected value of SQLSTATE to actual. See comment in git: + -- "Prevent stack trace (line/column info) from overriding the real error's SQLSTATE", 30-apr-2016 + -- https://github.com/FirebirdSQL/firebird/commit/d1d8b36a07d4f11d98d2c8ec16fb8ec073da442b // FB 4.0 + -- https://github.com/FirebirdSQL/firebird/commit/849bfac745bc9158e9ef7990f5d52913f8b72f02 // FB 3.0 + -- https://github.com/FirebirdSQL/firebird/commit/b9d4142c4ed1fdf9b7c633edc7b2425f7b93eed0 // FB 2.5 + -- See also letter from dimitr, 03-may-2016 19:24. + + recreate table test (a integer not null, constraint test_pk primary key (a)); + insert into test (a) values (1); + insert into test (a) values (2); + insert into test (a) values (3); + insert into test (a) values (4); + commit; + + set term ^; + create procedure test_upd(d integer) as + declare c cursor for ( + select a from test + ); + begin + open c; + update test set a = a + :d + where current of c; + close c; + end + ^ + set term ;^ + commit; + + execute procedure test_upd (2); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22000 + no current record for fetch operation + -At procedure 'TEST_UPD' + """ + +@pytest.mark.version('>=2.5') +def test_core_0058_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_0059.py b/tests/bugs/test_core_0059.py new file mode 100644 index 00000000..634e5f0d --- /dev/null +++ b/tests/bugs/test_core_0059.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_0059 +# title: Automatic not null in PK columns incomplete +# decription: +# tracker_id: CORE-0059 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test (a int, b float, c varchar(10), primary key (a, b, c)); + commit; + insert into test(a) values(null); + insert into test(a,b) values(1,null); + insert into test(a,b,c) values(1,1,null); + insert into test default values; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."A", value "*** null ***" + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."B", value "*** null ***" + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."C", value "*** null ***" + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."A", value "*** null ***" + """ + +@pytest.mark.version('>=2.5') +def test_core_0059_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_0063.py b/tests/bugs/test_core_0063.py new file mode 100644 index 00000000..f9b17c49 --- /dev/null +++ b/tests/bugs/test_core_0063.py @@ -0,0 +1,59 @@ +#coding:utf-8 +# +# id: bugs.core_0063 +# title: Sequence of commands crash FB server +# decription: +# tracker_id: CORE-0063 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='WIN1252', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + + create domain d_descricao_30000_nn as varchar(30000) not null collate win_ptbr; + create table movimento( complemento d_descricao_30000_nn ); + + insert into movimento values (''); + insert into movimento values ('1234567890'); + insert into movimento values (''); + + create domain d_text_blob as blob sub_type text collate win_ptbr; + + alter table movimento add complemento2 d_text_blob; + + update movimento set complemento2 = complemento; + + alter table movimento drop complemento, add complemento d_text_blob; + + drop domain d_descricao_30000_nn; + + update movimento set complemento = complemento2; + set list on; + select 'OK' as result from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT OK + """ + +@pytest.mark.version('>=2.5') +def test_core_0063_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0070.py b/tests/bugs/test_core_0070.py new file mode 100644 index 00000000..23fd8baa --- /dev/null +++ b/tests/bugs/test_core_0070.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_0070 +# title: Expression index regression since 2.0a3 +# decription: +# tracker_id: CORE-0070 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table t1 (col1 varchar(36)); + commit; + insert into t1 select lower(uuid_to_char(gen_uuid())) from rdb$types rows 100; + commit; + create index idx1 on t1 computed by (upper(col1)); + commit; + + set planonly; + select * from t1 where upper(col1) = '1'; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (T1 INDEX (IDX1)) + """ + +@pytest.mark.version('>=2.5') +def test_core_0070_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0076.py b/tests/bugs/test_core_0076.py new file mode 100644 index 00000000..2e65a9d3 --- /dev/null +++ b/tests/bugs/test_core_0076.py @@ -0,0 +1,76 @@ +#coding:utf-8 +# +# id: bugs.core_0076 +# title: Invalid ROW_COUNT variable value after DELETE +# decription: +# tracker_id: CORE-0076 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter procedure test_del as begin end; + + recreate table test ( + a integer not null, + constraint test_pk primary key (a) + ); + insert into test (a) values (1); + insert into test (a) values (2); + insert into test (a) values (3); + insert into test (a) values (4); + insert into test (a) values (5); + insert into test (a) values (6); + insert into test (a) values (7); + insert into test (a) values (8); + insert into test (a) values (9); + insert into test (a) values (10); + commit; + + set list on; + select count(*) as cnt from test where a between 4 and 7; + + set term ^; + create or alter procedure test_del (l integer, r integer) returns (rc integer) as + begin + delete from test where a between :l and :r; + rc = row_count; + suspend; + end + ^ + set term ;^ + execute procedure test_del (4, 7); + select * from test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CNT 4 + RC 4 + A 1 + A 2 + A 3 + A 8 + A 9 + A 10 + """ + +@pytest.mark.version('>=2.5') +def test_core_0076_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0085.py b/tests/bugs/test_core_0085.py new file mode 100644 index 00000000..ba67c607 --- /dev/null +++ b/tests/bugs/test_core_0085.py @@ -0,0 +1,201 @@ +#coding:utf-8 +# +# id: bugs.core_0085 +# title: Query with not in (select) returns wrong result +# decription: +# tracker_id: CORE-0085 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Results are OK since 2.1.7 up to 4.0.0 + -- Confirmed wrong result on 1.5.6 + + set term ^; + create or alter procedure tst1 + returns (packages integer) + as + begin + packages=1; + suspend; + packages=2; + suspend; + end^ + set term ;^ + + recreate table frrates1 ( + frrates1 integer not null, + packages integer, + primary key(frrates1) + ); + commit; + + create index idx_frrates1_packages on frrates1 (packages); + commit; + + recreate table schedpkgs1 ( + schedpkgs1 integer not null, + schedule integer, + frrates1 integer, + primary key (schedpkgs1) + ); + commit; + + create index idx_schedpkgs1_schedule on schedpkgs1 (schedule); + commit; + + insert into frrates1 (frrates1, packages) values (11, 1); + insert into frrates1 (frrates1, packages) values (12, 2); + /* second record is essential (must exist in tst1) */ + commit; + + insert into schedpkgs1 (schedpkgs1, schedule, frrates1) values(21, 16651,11); + insert into schedpkgs1 (schedpkgs1, schedule, frrates1) values(22, 16651,null); + /* important null value */ + commit; + + + set count on; + set list on; + + -- sub-query to be used later in sub-select, + -- correctly uses frrates1 primary key index fr index (rdb$primary121), + -- correctly returns (1) + + select fr.packages + from schedpkgs1 sp + join frrates1 fr on fr.frrates1=sp.frrates1 + where sp.schedule = 16651; + + -- 1. results from stored procedure (1, 2), + -- filtered out by sub-select query (1), + -- expected results -- (2), + -- ib5.6 correctly uses frrates1 primary key index fr index (rdb$primary121), + -- ib5.6 returns correct results (2), + -- problem -- fb1.5.3/2.0rc2 does not return anything, + -- problem -- fb1.5.3/2.0rc2 uses wrong frrates1 + -- index fr index (idx_frrates1_packages) + + select packages + from tst1 + where packages not in (select fr.packages + from schedpkgs1 sp + join frrates1 fr on + fr.frrates1=sp.frrates1 + where sp.schedule = 16651); + + -- 2a. adding additional filter in sub-select query + -- 'fr.packages>0' fb1.5.3 still uses questionable frrates1 index fr + -- index (idx_frrates1_packages) but results are as expected (2) + + select packages + from tst1 + where packages not in (select fr.packages + from schedpkgs1 sp + join frrates1 fr on + fr.frrates1=sp.frrates1 + where sp.schedule = 16651 + and fr.packages>0); + + -- 2b. replacing "not in" with "<> any" will return + -- expected result and uses expected indices + + select t.packages + from tst1 t + where t.packages <> all (select fr.packages + from schedpkgs1 sp + join frrates1 fr on + fr.frrates1=sp.frrates1 + where sp.schedule = 16651); + + -- 3. using table instead of stored procedure in main + -- query, both ib5.6 and fb1.5.3 uses questionable frrates1 + -- index fr index (idx_frrates1_packages), + -- and results are wrong, i.e. does not return (2) + + select f2.packages + from frrates1 f2 + where f2.packages not in + ( + select fr.packages + from schedpkgs1 sp + join frrates1 fr on + fr.frrates1=sp.frrates1 + where sp.schedule = 16651 + ); + + + -- 4a. adding the same additional filter + -- 'fr.packages>0' in sub-select query, + -- incorrect results in ib5.6 (no results) (fr index + -- (rdb$primary121,idx_frrates1_packages)), + -- correct results in fb1.5.3 (returns 2) + -- fb1.5.3 still uses questionable frrates1 index fr + -- index (idx_frrates1_packages) + + + select f2.packages + from frrates1 f2 + where f2.packages not in + ( + select fr.packages + from schedpkgs1 sp + join frrates1 fr on + fr.frrates1=sp.frrates1 + where sp.schedule = 16651 + and fr.packages > 0 + ); + + -- 4b. and again, the same query with <> any instead + -- not in works correctly + + select f2.packages + from frrates1 f2 + where f2.packages <> all + ( + select fr.packages + from schedpkgs1 sp + join frrates1 fr on + fr.frrates1=sp.frrates1 + where sp.schedule = 16651 + ); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PACKAGES 1 + Records affected: 1 + PACKAGES 2 + Records affected: 1 + PACKAGES 2 + Records affected: 1 + PACKAGES 2 + Records affected: 1 + PACKAGES 2 + Records affected: 1 + PACKAGES 2 + Records affected: 1 + PACKAGES 2 + Records affected: 1 + """ + +@pytest.mark.version('>=2.5') +def test_core_0085_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0086.py b/tests/bugs/test_core_0086.py new file mode 100644 index 00000000..cbf92d71 --- /dev/null +++ b/tests/bugs/test_core_0086.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: bugs.core_86 +# title: Index bug +# decription: Can not fetch the data when Index is use +# tracker_id: CORE-86 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_86 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core86.fbk', init=init_script_1) + +test_script_1 = """Select * from YLK A where PH = '0021' +and HPBH = '492' +and CD = 'MG' +and JLDW = 'JIAN' +and JZDW = 'DUN' +and CK = '8K' +and HW = '1.8' +and SH='1.81';""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ID_YLK PH HPBH CD JLDW JZDW CK HW SH +============ ==================== ============ ==================== ====== ====== ================ ============ ===================== + 110 0021 492 MG JIAN DUN 8K 1.8 1.81000 + +""" + +@pytest.mark.version('>=2.1') +def test_core_86_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0088.py b/tests/bugs/test_core_0088.py new file mode 100644 index 00000000..f4e22a87 --- /dev/null +++ b/tests/bugs/test_core_0088.py @@ -0,0 +1,84 @@ +#coding:utf-8 +# +# id: bugs.core_0088 +# title: Join on diffrent datatypes +# decription: +# tracker_id: CORE-88 +# min_versions: [] +# versions: 2.5 +# qmid: bugs.core_88 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE TEST_A ( + ID INTEGER NOT NULL PRIMARY KEY, + SNUM CHAR(10) UNIQUE +); + +CREATE TABLE TEST_B ( + ID INTEGER NOT NULL PRIMARY KEY, + NUM NUMERIC(15,2) UNIQUE +); + +commit; + +INSERT INTO TEST_A (ID, SNUM) VALUES (1, '01'); +INSERT INTO TEST_A (ID, SNUM) VALUES (2, '02'); +INSERT INTO TEST_A (ID, SNUM) VALUES (3, '03'); +INSERT INTO TEST_A (ID, SNUM) VALUES (5, '05'); + +commit; + +INSERT INTO TEST_B (ID, NUM) VALUES (1, 1); +INSERT INTO TEST_B (ID, NUM) VALUES (2, 2); +INSERT INTO TEST_B (ID, NUM) VALUES (3, 3); +INSERT INTO TEST_B (ID, NUM) VALUES (4, 4); + +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; + +SELECT * FROM test_b WHERE num NOT IN (SELECT snum FROM test_a) ; + +SELECT * FROM test_b WHERE num IN (SELECT snum FROM test_a) ; + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +PLAN (TEST_A NATURAL) +PLAN (TEST_A NATURAL) +PLAN (TEST_B NATURAL) + + ID NUM +============ ===================== + 4 4.00 + + +PLAN (TEST_A NATURAL) +PLAN (TEST_B NATURAL) + + ID NUM +============ ===================== + 1 1.00 + 2 2.00 + 3 3.00 + +""" + +@pytest.mark.version('>=2.5') +def test_core_0088_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0089.py b/tests/bugs/test_core_0089.py new file mode 100644 index 00000000..72da0624 --- /dev/null +++ b/tests/bugs/test_core_0089.py @@ -0,0 +1,328 @@ +#coding:utf-8 +# +# id: bugs.core_0089 +# title: Using where params in SUM return incorrect results +# decription: +# tracker_id: CORE-0089 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- DDL and data are based on text file (report) that is attached to ticket. + -- No difference between FB 1.5.6 and 4.0.0 found. + -- Added PK on table categorygroup and index "schemacategories(typecol)" + -- after analyzing text of queries - it seems to me that such indices + -- does exist on real schema. + + recreate table schemacategories( + schemanr int + ,catnr int + ,typecol int + ,depnr int + ,ownedby int + ,heritage char(4) + ); + commit; + create index sch_cat_typecol on schemacategories(typecol); + + recreate table categorygroup( + id int primary key + ,parent int + ,depnr int + ,heritage char(4) + ,activecol int + ,displaytype int + ); + commit; + + insert into schemacategories values(11, 472, 10, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 463, 10, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 464, 10, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 497, 4, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 501, 4, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 296, 4, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 265, 4, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 496, 4, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 500, 4, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 498, 4, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 499, 4, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 494, 4, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 261, 4, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 495, 4, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 413, 5, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 244, 5, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 488, 5, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 492, 5, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 249, 5, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 493, 5, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 247, 5, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 502, 6, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 251, 6, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 490, 6, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 367, 6, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 489, 6, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 505, 5, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 506, 4, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 507, 5, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 508, 5, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 509, 5, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 491, 6, 1, 10000175, 'TRUE'); + insert into schemacategories values(11, 450, 1, 1, 10000090, 'TRUE'); + insert into schemacategories values(11, 485, 1, 1, 10000090, 'TRUE'); + insert into schemacategories values(11, 486, 1, 1, 10000090, 'TRUE'); + insert into schemacategories values(11, 451, 1, 1, 10000090, 'TRUE'); + insert into schemacategories values(11, 452, 1, 1, 10000090, 'TRUE'); + insert into schemacategories values(11, 453, 1, 1, 10000090, 'TRUE'); + insert into schemacategories values(11, 454, 1, 1, 10000090, 'TRUE'); + insert into schemacategories values(11, 455, 1, 1, 10000090, 'TRUE'); + insert into schemacategories values(11, 456, 1, 1, 10000090, 'TRUE'); + commit; + + + insert into categorygroup values(1,0,1,'TRUE',1,1); + insert into categorygroup values(2,0,1,'TRUE',1,2); + insert into categorygroup values(3,0,1,'TRUE',1,2); + insert into categorygroup values(4,0,1,'TRUE',1,3); + insert into categorygroup values(5,0,1,'TRUE',1,3); + insert into categorygroup values(6,0,1,'TRUE',1,3); + insert into categorygroup values(7,0,1,'TRUE',1,2); + insert into categorygroup values(8,5,1,'TRUE',0,3); + insert into categorygroup values(9,0,1,'TRUE',1,2); + insert into categorygroup values(10,0,1,'TRUE',1,2); + commit; + + set list on; + select sc.schemanr,sc.catnr,sc.typecol,cg.id + from schemacategories sc, categorygroup cg + where sc.schemanr = 11 and sc.typecol = cg.id + order by sc.catnr; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + SCHEMANR 11 + CATNR 244 + TYPECOL 5 + ID 5 + + SCHEMANR 11 + CATNR 247 + TYPECOL 5 + ID 5 + + SCHEMANR 11 + CATNR 249 + TYPECOL 5 + ID 5 + + SCHEMANR 11 + CATNR 251 + TYPECOL 6 + ID 6 + + SCHEMANR 11 + CATNR 261 + TYPECOL 4 + ID 4 + + SCHEMANR 11 + CATNR 265 + TYPECOL 4 + ID 4 + + SCHEMANR 11 + CATNR 296 + TYPECOL 4 + ID 4 + + SCHEMANR 11 + CATNR 367 + TYPECOL 6 + ID 6 + + SCHEMANR 11 + CATNR 413 + TYPECOL 5 + ID 5 + + SCHEMANR 11 + CATNR 450 + TYPECOL 1 + ID 1 + + SCHEMANR 11 + CATNR 451 + TYPECOL 1 + ID 1 + + SCHEMANR 11 + CATNR 452 + TYPECOL 1 + ID 1 + + SCHEMANR 11 + CATNR 453 + TYPECOL 1 + ID 1 + + SCHEMANR 11 + CATNR 454 + TYPECOL 1 + ID 1 + + SCHEMANR 11 + CATNR 455 + TYPECOL 1 + ID 1 + + SCHEMANR 11 + CATNR 456 + TYPECOL 1 + ID 1 + + SCHEMANR 11 + CATNR 463 + TYPECOL 10 + ID 10 + + SCHEMANR 11 + CATNR 464 + TYPECOL 10 + ID 10 + + SCHEMANR 11 + CATNR 472 + TYPECOL 10 + ID 10 + + SCHEMANR 11 + CATNR 485 + TYPECOL 1 + ID 1 + + SCHEMANR 11 + CATNR 486 + TYPECOL 1 + ID 1 + + SCHEMANR 11 + CATNR 488 + TYPECOL 5 + ID 5 + + SCHEMANR 11 + CATNR 489 + TYPECOL 6 + ID 6 + + SCHEMANR 11 + CATNR 490 + TYPECOL 6 + ID 6 + + SCHEMANR 11 + CATNR 491 + TYPECOL 6 + ID 6 + + SCHEMANR 11 + CATNR 492 + TYPECOL 5 + ID 5 + + SCHEMANR 11 + CATNR 493 + TYPECOL 5 + ID 5 + + SCHEMANR 11 + CATNR 494 + TYPECOL 4 + ID 4 + + SCHEMANR 11 + CATNR 495 + TYPECOL 4 + ID 4 + + SCHEMANR 11 + CATNR 496 + TYPECOL 4 + ID 4 + + SCHEMANR 11 + CATNR 497 + TYPECOL 4 + ID 4 + + SCHEMANR 11 + CATNR 498 + TYPECOL 4 + ID 4 + + SCHEMANR 11 + CATNR 499 + TYPECOL 4 + ID 4 + + SCHEMANR 11 + CATNR 500 + TYPECOL 4 + ID 4 + + SCHEMANR 11 + CATNR 501 + TYPECOL 4 + ID 4 + + SCHEMANR 11 + CATNR 502 + TYPECOL 6 + ID 6 + + SCHEMANR 11 + CATNR 505 + TYPECOL 5 + ID 5 + + SCHEMANR 11 + CATNR 506 + TYPECOL 4 + ID 4 + + SCHEMANR 11 + CATNR 507 + TYPECOL 5 + ID 5 + + SCHEMANR 11 + CATNR 508 + TYPECOL 5 + ID 5 + + SCHEMANR 11 + CATNR 509 + TYPECOL 5 + ID 5 + """ + +@pytest.mark.version('>=2.5') +def test_core_0089_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0091.py b/tests/bugs/test_core_0091.py new file mode 100644 index 00000000..52a0e912 --- /dev/null +++ b/tests/bugs/test_core_0091.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_91 +# title: Recreate and self-referencing indexes +# decription: +# tracker_id: CORE-91 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_91 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """recreate table t2 ( + i integer not null primary key, + p integer references t2(i) on delete set null + ); +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select * from t2; +insert into t2 values (1, null); +delete from t2 where i=1; +commit; + +recreate table t2 ( + i integer not null primary key, + p integer references t2(i) on delete set null + ); +commit; +select * from t2; +insert into t2 values (1, null); +delete from t2 where i=1; +commit; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1') +def test_core_91_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_0099.py b/tests/bugs/test_core_0099.py new file mode 100644 index 00000000..97f0b9f9 --- /dev/null +++ b/tests/bugs/test_core_0099.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: bugs.core_99 +# title: Strange/Inconsistent query results +# decription: +# tracker_id: CORE-99 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_99 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table T1 (F1 char(4), F2 char(4)); +create index T1_F1 on T1 (F1); + +insert into T1 (F1, F2) values ('001', '001'); +insert into T1 (F1, F2) values ('002', '002'); +insert into T1 (F1, F2) values ('003', '003'); +insert into T1 (F1, F2) values ('004', '004'); + +commit; +""" + +db_1 = db_factory(sql_dialect=1, init=init_script_1) + +test_script_1 = """select * from t1 where f1 = 3; +select * from t1 where f2 = 3; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """F1 F2 +====== ====== +003 003 + +F1 F2 +====== ====== +003 003 + +""" + +@pytest.mark.version('>=2.1') +def test_core_99_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0101.py b/tests/bugs/test_core_0101.py new file mode 100644 index 00000000..3f6e09d2 --- /dev/null +++ b/tests/bugs/test_core_0101.py @@ -0,0 +1,111 @@ +#coding:utf-8 +# +# id: bugs.core_0101 +# title: JOIN the same table - problem with alias names +# decription: +# tracker_id: CORE-0101 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Confirmed wrong result on WI-V1.5.6.5026, all above wirks fine. + recreate table test(id int); + insert into test values(1); + insert into test values(-1); + insert into test values(-2); + insert into test values(2); + commit; + + --set plan on; + set list on; + + select * + from ( + select test.id a_id, b.id as b_id + from test test + join test b on test.id = b.id + ) order by 1,2 + ; + + create index test_id on test(id); + + select * + from ( + select test.id a_id, b.id as b_id + from test test + join test b on test.id = b.id + ) order by 1,2 + ; + + select * + from ( + select test.id a_id, b.id as b_id + from (select id from test order by id) test + join (select id from test order by id) b on test.id = b.id + ) order by 1,2 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A_ID -2 + B_ID -2 + + A_ID -1 + B_ID -1 + + A_ID 1 + B_ID 1 + + A_ID 2 + B_ID 2 + + + + A_ID -2 + B_ID -2 + + A_ID -1 + B_ID -1 + + A_ID 1 + B_ID 1 + + A_ID 2 + B_ID 2 + + + + A_ID -2 + B_ID -2 + + A_ID -1 + B_ID -1 + + A_ID 1 + B_ID 1 + + A_ID 2 + B_ID 2 + """ + +@pytest.mark.version('>=2.5') +def test_core_0101_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0104.py b/tests/bugs/test_core_0104.py new file mode 100644 index 00000000..9ac407de --- /dev/null +++ b/tests/bugs/test_core_0104.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_0104 +# title: Dropping and recreating a table in the same txn disables PK +# decription: +# tracker_id: CORE-104 +# min_versions: [] +# versions: 2.5.3 +# qmid: bugs.core_104-250 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table test (acolumn int not null primary key); +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET AUTODDL OFF; + +drop table test; +create table test (acolumn int not null primary key); + +commit; + +insert into test values (1); +insert into test values (1); + +commit; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 23000 +violation of PRIMARY or UNIQUE KEY constraint "INTEG_4" on table "TEST" +-Problematic key value is ("ACOLUMN" = 1) +""" + +@pytest.mark.version('>=2.5.3') +def test_core_0104_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_0115.py b/tests/bugs/test_core_0115.py new file mode 100644 index 00000000..52442654 --- /dev/null +++ b/tests/bugs/test_core_0115.py @@ -0,0 +1,67 @@ +#coding:utf-8 +# +# id: bugs.core_0115 +# title: bug with ALL keyword +# decription: +# tracker_id: CORE-0115 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test (i int not null); + + insert into test values (2); + insert into test values (3); + commit; + + set plan on; + + set count on; + select * from test where 1 > all(select i from test); + + commit; + + alter table test add constraint test_pk primary key(i) using index test_pk; + commit; + + select * from test where i > all(select i from test); + select * from test where i > 0 and i > all(select i from test where i > 0); + + set count off; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (TEST NATURAL) + PLAN (TEST NATURAL) + Records affected: 0 + + PLAN (TEST NATURAL) + PLAN (TEST NATURAL) + Records affected: 0 + + PLAN (TEST INDEX (TEST_PK)) + PLAN (TEST INDEX (TEST_PK)) + Records affected: 0 + """ + +@pytest.mark.version('>=2.5') +def test_core_0115_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0116.py b/tests/bugs/test_core_0116.py new file mode 100644 index 00000000..c7f99572 --- /dev/null +++ b/tests/bugs/test_core_0116.py @@ -0,0 +1,51 @@ +#coding:utf-8 +# +# id: bugs.core_0116 +# title: CREATE TABLE - no blob for external +# decription: CREATE TABLE - blob not allow for external tables +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# tracker_id: CORE-116 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_116-250 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Untill build 3.0.0.31721 STDERR was: + -- -Data type BLOB is not supported ... field '' + -- Since WI-T3.0.0.31733 STDERR became normal - contains name of field. + -- See correction in 'expected_stderr' secsion (23.03.2015). + create table ext_log external file '$(DATABASE_LOCATION)z.dat' (F1 INT, F2 BLOB SUB_TYPE TEXT); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = HY004 + unsuccessful metadata update + -CREATE TABLE EXT_LOG failed + -SQL error code = -607 + -Invalid command + -Data type BLOB is not supported for EXTERNAL TABLES. Relation 'EXT_LOG', field 'F2' + """ + +@pytest.mark.version('>=3.0') +def test_core_0116_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_0117.py b/tests/bugs/test_core_0117.py new file mode 100644 index 00000000..ff141f93 --- /dev/null +++ b/tests/bugs/test_core_0117.py @@ -0,0 +1,77 @@ +#coding:utf-8 +# +# id: bugs.core_0117 +# title: Expression evaluation not supported on LEFT JOIN +# decription: +# tracker_id: CORE-0117 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Output is fine in WI-V1.5.6.5026 and all above. + set list on; + + recreate table t1( + id numeric( 18, 0) not null, + id2 numeric( 18,0), + date1 date, + constraint pk_t1 primary key (id) + ); + + recreate table t2( + id numeric( 18, 0) not null, + id2 numeric( 18,0), + date1 date, + constraint pk_t2 primary key (id) + ); + + + insert into t1(id, id2, date1) values (1, 1, '10/13/2003'); + insert into t1(id, id2, date1) values (2, 2, '09/13/2003'); + insert into t2(id, id2, date1) values (1, 1, '09/13/2003'); + commit; + + --executing the following query in isql returns the error + --message "expression evaluation not supported" after + --retrieving the + --first row. + + + select t_1.id2, t_1.date1 as d1, t_2.date1 as d2 + from t1 t_1 + left join t2 t_2 on t_1.id2=t_2.id2 + where + extract(month from t_1.date1) + <> + extract(month from t_2.date1) + ; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID2 1 + D1 2003-10-13 + D2 2003-09-13 + """ + +@pytest.mark.version('>=2.5') +def test_core_0117_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0119.py b/tests/bugs/test_core_0119.py new file mode 100644 index 00000000..19e97cc6 --- /dev/null +++ b/tests/bugs/test_core_0119.py @@ -0,0 +1,75 @@ +#coding:utf-8 +# +# id: bugs.core_0119 +# title: numeric div in dialect 3 mangles data +# decription: +# NOTE. Results for FB 4.0 become differ from old one. Discussed with Alex, 30.10.2019. +# Precise value of 70000 / 1.95583 is: 35790.431683735296 (checked on https://www.wolframalpha.com ) +# Section 'expected-stdout' was adjusted to be match for results that are issued in recent FB. +# Discuss with Alex see in e-mail, letters 30.10.2019. +# Checked on: +# 4.0.0.1635 SS: 0.909s. +# 3.0.5.33182 SS: 0.740s. +# 2.5.9.27146 SC: 0.212s. +# +# 21.06.2020, 4.0.0.2068 (see also: CORE-6337): +# changed subtype from 0 to 1 for cast (-70000 as numeric (18,5)) / cast (1.95583 as numeric (18,5)) +# (after discuss with dimitr, letter 21.06.2020 08:43). +# +# 25.06.2020, 4.0.0.2076: changed types in SQLDA from numeric to int128 // after discuss with Alex about CORE-6342. +# +# tracker_id: CORE-0119 +# min_versions: ['2.5.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('^((?!(sqltype|DIV_RESULT)).)*$', ''), ('[ \t]+', ' '), ('.*alias.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set sqlda_display on; + select cast (-70000 as numeric (18,5)) / cast (1.95583 as numeric (18,5)) as div_result_1 from rdb$database; + + -- doc\\sql.extensions\\README.data_types: + -- - QUANTIZE - has two DECFLOAT arguments. The returned value is first argument scaled using + -- second value as a pattern. For example QUANTIZE(1234, 9.999) returns 1234.000. + + select QUANTIZE(cast(-70000 as decfloat(34)) / cast (1.95583 as decfloat(34)), 9.9999999999) as div_result_2 from rdb$database; + select (-4611686018427387904)/-0.5 div_result_3 from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 01: sqltype: 32752 INT128 scale: -10 subtype: 1 len: 16 + DIV_RESULT_1 -35790.4316837352 + + 01: sqltype: 32762 DECFLOAT(34) scale: 0 subtype: 0 len: 16 + DIV_RESULT_2 -35790.4316837353 + + 01: sqltype: 32752 INT128 scale: -1 subtype: 0 len: 16 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22003 + arithmetic exception, numeric overflow, or string truncation + -numeric value is out of range + """ + +@pytest.mark.version('>=4.0') +def test_core_0119_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0142.py b/tests/bugs/test_core_0142.py new file mode 100644 index 00000000..e2389561 --- /dev/null +++ b/tests/bugs/test_core_0142.py @@ -0,0 +1,102 @@ +#coding:utf-8 +# +# id: bugs.core_0142 +# title: index breaks = ANY result +# decription: +# tracker_id: CORE-0142 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Confirmed wrong output on WI-V1.5.6.5026. + -- Since 2.0.0 works fine. + + recreate view v_test(k) as select 1 k from rdb$database; + commit; + + recreate table customers ( + cnum integer, + cname char(10), + city char(10), + rating integer, + snum integer + ); + + recreate view v_test(cnum, cname, city, rating, snum) as + select * + from customers c + where not c.rating = any + (select r.rating + from customers r + where r.city = 'san jose'); + commit; + + insert into customers values (2001, 'hoffman', 'london', 100, 1001); + insert into customers values (2002, 'giovanni', 'rome', 200, 1003); + insert into customers values (2003, 'lui', 'san jose', 200, 1002); + insert into customers values (2004, 'grass', 'berlin', 300, 1002); + insert into customers values (2006, 'clemens', 'london', null, 1001); + insert into customers values (2008, 'cisneros', 'san jose', 300, 1007); + insert into customers values (2007, 'pereira', 'rome', 100, 1004); + commit; + + set list on; + + select * from v_test order by cnum; + commit; + + create index byrating on customers (rating); + commit; + + select * from v_test order by cnum; + commit; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CNUM 2001 + CNAME hoffman + CITY london + RATING 100 + SNUM 1001 + + CNUM 2007 + CNAME pereira + CITY rome + RATING 100 + SNUM 1004 + + CNUM 2001 + CNAME hoffman + CITY london + RATING 100 + SNUM 1001 + + CNUM 2007 + CNAME pereira + CITY rome + RATING 100 + SNUM 1004 + """ + +@pytest.mark.version('>=2.5') +def test_core_0142_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0143.py b/tests/bugs/test_core_0143.py new file mode 100644 index 00000000..10340cd7 --- /dev/null +++ b/tests/bugs/test_core_0143.py @@ -0,0 +1,85 @@ +#coding:utf-8 +# +# id: bugs.core_0143 +# title: Using where params in SUM return incorrect results +# decription: +# 30.10.2019. NB: new datatype in FB 4.0 was introduces: numeric(38,0). +# It can lead to additional ident of values when we show them in form "SET LIST ON", +# so we have to ignore all internal spaces - see added 'substitution' section below. +# Checked on: +# 4.0.0.1635 SS: 1.061s. +# 3.0.5.33182 SS: 0.754s. +# 2.5.9.27146 SC: 0.190s. +# +# tracker_id: CORE-0143 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table yeardata + ( + id integer not null, + ayear integer, + avalue numeric( 18, 2), + constraint pk_yeardata primary key (id) + ); + commit; + + insert into yeardata(id, ayear, avalue) values (1, 2005, 3.40); + insert into yeardata(id, ayear, avalue) values (2, 2005, 6.60); + insert into yeardata(id, ayear, avalue) values (3, 2004, 5.20); + insert into yeardata(id, ayear, avalue) values (4, 2004, 5.80); + insert into yeardata(id, ayear, avalue) values (5, 2004, 5.00); + commit; + + set list on; + select + sum(case when ayear = 2004 then avalue else null end) as avalue_2004_1 + ,sum(case when ayear = 2005 then avalue else null end) as avalue_2005_1 + from yeardata; + + set term ^; + execute block returns( avalue_2004_2 numeric( 18, 2), avalue_2005_2 numeric( 18, 2)) as + begin + execute statement + ( + 'select + sum(case when ayear = ? then avalue else null end) + ,sum(case when ayear = ? then avalue else null end) + from yeardata' + ) ( 2004, 2005 ) + into avalue_2004_2, avalue_2005_2; + suspend; + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + AVALUE_2004_1 16.00 + AVALUE_2005_1 10.00 + AVALUE_2004_2 16.00 + AVALUE_2005_2 10.00 + """ + +@pytest.mark.version('>=2.5') +def test_core_0143_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0148.py b/tests/bugs/test_core_0148.py new file mode 100644 index 00000000..41ee0693 --- /dev/null +++ b/tests/bugs/test_core_0148.py @@ -0,0 +1,56 @@ +#coding:utf-8 +# +# id: bugs.core_0148 +# title: SELECT '1' UNION SELECT '12' +# decription: +# tracker_id: CORE-0148 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Confirmed: runtime error on WI-V1.5.6.5026: + -- -SQL error code = -104 + -- -Invalid command + -- -Data type unknown + + recreate table test_a(x int); + recreate table test_b(y int); + + insert into test_a values(9999999); + insert into test_b values(888888); + + set list on; + select '1' || a.x as result + from test_a a + union + select '12' || b.y + from test_b b + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT 12888888 + RESULT 19999999 + """ + +@pytest.mark.version('>=2.5') +def test_core_0148_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0149.py b/tests/bugs/test_core_0149.py new file mode 100644 index 00000000..cf251fdb --- /dev/null +++ b/tests/bugs/test_core_0149.py @@ -0,0 +1,236 @@ +#coding:utf-8 +# +# id: bugs.core_0149 +# title: Left joining views with null fails +# decription: +# tracker_id: CORE-0149 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + -- Initial comment by johnsparrowuk, 19/Mar/04 12:00 AM: + recreate view currentpeople(k) as select 1 as k from rdb$database; + recreate view finishedpeople(k) as select 1 as k from rdb$database; + commit; + + recreate table mytable ( + person varchar(20) not null, + status int not null, primary key (person,status) + ); + + recreate view currentpeople(person) as + select distinct person as person + from mytable where status = 1; + + recreate view finishedpeople(person) as + select distinct person as person + from mytable where status = 2; + + insert into mytable values ('john',1); + insert into mytable values ('john',2); + insert into mytable values ('fred',1); + commit; + + -- This works fine: fred-null, john-john + select * + from currentpeople c + left join finishedpeople f on c.person = f.person + order by c.person, f.person + ; + + -- This is as expected too: john-john + select * + from currentpeople c + left join finishedpeople f + on c.person = f.person where f.person = 'john' + order by c.person, f.person + ; + + -- WHATS HAPPENING HERE????? fred-null, JOHN-NULL where does the john-null come from??? + select * + from currentpeople c + left join finishedpeople f on c.person = f.person + where f.person is null + order by c.person, f.person + ; + commit; + + --################################################# + + -- Alice F. Bird added a comment - 14/Jun/06 09:32 AM + recreate table test ( + id int not null, + name varchar(15), + pid integer + ); + + insert into test(id, name, pid) values(1, 'Car', null); + insert into test(id, name, pid) values(2, 'Engine', 1); + insert into test(id, name, pid) values(3, 'Body', 1); + insert into test(id, name, pid) values(4, 'Oil Filter',2); + insert into test(id, name, pid) values(5, 'Air Filter',2); + insert into test(id, name, pid) values(6, 'Door Left', 3); + insert into test(id, name, pid) values(7, 'Door Right',3); + commit; + + -- This query issued WRONG result on 1.5.6 + -- (because first data source - 'TEST' - has not alias) + select * + from test + left outer join test t2 + on test.pid=t2.id + order by test.id, t2.id + ; + + -- This works fine: + select * + from test t1 + left outer join test t2 + on t1.pid=t2.id + order by t1.id, t2.id + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PERSON fred + PERSON + + PERSON john + PERSON john + + + + PERSON john + PERSON john + + + + PERSON fred + PERSON + + + + ID 1 + NAME Car + PID + ID + NAME + PID + + ID 2 + NAME Engine + PID 1 + ID 1 + NAME Car + PID + + ID 3 + NAME Body + PID 1 + ID 1 + NAME Car + PID + + ID 4 + NAME Oil Filter + PID 2 + ID 2 + NAME Engine + PID 1 + + ID 5 + NAME Air Filter + PID 2 + ID 2 + NAME Engine + PID 1 + + ID 6 + NAME Door Left + PID 3 + ID 3 + NAME Body + PID 1 + + ID 7 + NAME Door Right + PID 3 + ID 3 + NAME Body + PID 1 + + + + ID 1 + NAME Car + PID + ID + NAME + PID + + ID 2 + NAME Engine + PID 1 + ID 1 + NAME Car + PID + + ID 3 + NAME Body + PID 1 + ID 1 + NAME Car + PID + + ID 4 + NAME Oil Filter + PID 2 + ID 2 + NAME Engine + PID 1 + + ID 5 + NAME Air Filter + PID 2 + ID 2 + NAME Engine + PID 1 + + ID 6 + NAME Door Left + PID 3 + ID 3 + NAME Body + PID 1 + + ID 7 + NAME Door Right + PID 3 + ID 3 + NAME Body + PID 1 + """ + +@pytest.mark.version('>=2.5') +def test_core_0149_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0165.py b/tests/bugs/test_core_0165.py new file mode 100644 index 00000000..fac51bfc --- /dev/null +++ b/tests/bugs/test_core_0165.py @@ -0,0 +1,84 @@ +#coding:utf-8 +# +# id: bugs.core_0165 +# title: Query using VIEW with UNION causes crash +# decription: +# Original test see im: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_24.script +# +# tracker_id: CORE-0165 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate view v_test1 ( id, x ) as select 1, 2 from rdb$database; + recreate view v_test2 ( id, x ) as select 1, 2 from rdb$database; + commit; + + recreate table test1 ( + id int not null, + x int not null); + + recreate table test2 ( + id int not null, + y int not null); + + recreate view v_test1 ( id, x ) as + select id, x + from test1 + union + select id, x + from test1; + + recreate view v_test2 ( id, y ) as + select id, y + from test2 + union + select id, y + from test2; + commit; + + insert into test1 values(1, 123); + insert into test1 values(2, 456); + insert into test2 values(3, 151); + insert into test2 values(2, 456); + insert into test2 values(1, 123); + commit; + + set list on; + --set plan on; + select i.id as id_1, i.x as x, j.id as id_2, j.y as y + from v_test1 i, v_test2 j + where i.id = j.id + and j.y = (select max(x.y) from v_test2 x) + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID_1 2 + X 456 + ID_2 2 + Y 456 + """ + +@pytest.mark.version('>=2.5') +def test_core_0165_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0166.py b/tests/bugs/test_core_0166.py new file mode 100644 index 00000000..efcc7772 --- /dev/null +++ b/tests/bugs/test_core_0166.py @@ -0,0 +1,136 @@ +#coding:utf-8 +# +# id: bugs.core_0166 +# title: cannot specify PLAN in UPDATE statement +# decription: +# tracker_id: CORE-0166 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table company(id int not null primary key, contact_id int, company_name varchar(60)); + recreate table contact(id int not null primary key using index contact_id, contact_name varchar(60)); + alter table company add constraint company_fk foreign key(contact_id) references contact(id); + commit; + + insert into contact values(1, '+784956253581, Vovan'); + insert into contact values(2, '+375172223217, Shurik'); + insert into contact values(3, '+380442057337, Vitalik'); + + insert into company values(100, 1, 'Pepsico, Inc.'); + insert into company values(101, 1, ''); + insert into company values(102, 2, 'Balaha, Inc.'); + insert into company values(103, 2, ''); + insert into company values(104, 2, null); + insert into company values(105, 3, null); + insert into company values(106, 3, 'Firebird Foundation'); + commit; + + set list on; + + select c.* + from company c order by c.id; + + set plan on; + set count on; + + update company c set c.company_name = + ( select k.contact_name + from contact k + where k.id = c.contact_id + PLAN (K INDEX (CONTACT_ID)) + ) + where c.company_name is null or c.company_name = '' + PLAN (C NATURAL) + ; + + set plan off; + set count off; + + select c.* + from company c order by c.id; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 100 + CONTACT_ID 1 + COMPANY_NAME Pepsico, Inc. + + ID 101 + CONTACT_ID 1 + COMPANY_NAME + + ID 102 + CONTACT_ID 2 + COMPANY_NAME Balaha, Inc. + + ID 103 + CONTACT_ID 2 + COMPANY_NAME + + ID 104 + CONTACT_ID 2 + COMPANY_NAME + + ID 105 + CONTACT_ID 3 + COMPANY_NAME + + ID 106 + CONTACT_ID 3 + COMPANY_NAME Firebird Foundation + + PLAN (K INDEX (CONTACT_ID)) + PLAN (C NATURAL) + Records affected: 4 + + ID 100 + CONTACT_ID 1 + COMPANY_NAME Pepsico, Inc. + + ID 101 + CONTACT_ID 1 + COMPANY_NAME +784956253581, Vovan + + ID 102 + CONTACT_ID 2 + COMPANY_NAME Balaha, Inc. + + ID 103 + CONTACT_ID 2 + COMPANY_NAME +375172223217, Shurik + + ID 104 + CONTACT_ID 2 + COMPANY_NAME +375172223217, Shurik + + ID 105 + CONTACT_ID 3 + COMPANY_NAME +380442057337, Vitalik + + ID 106 + CONTACT_ID 3 + COMPANY_NAME Firebird Foundation + """ + +@pytest.mark.version('>=2.5') +def test_core_0166_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0185.py b/tests/bugs/test_core_0185.py new file mode 100644 index 00000000..f4a86547 --- /dev/null +++ b/tests/bugs/test_core_0185.py @@ -0,0 +1,69 @@ +#coding:utf-8 +# +# id: bugs.core_0185 +# title: DB crashes if trigger BU deletes own row +# decription: +# Ortiginal test: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_28.script +# +# tracker_id: CORE-0185 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table test (id integer not null); + commit; + set term ^ ; + create trigger test_bu for test active before update position 0 as + begin + delete from test where id=old.id; + end + ^ + set term ; ^ + commit; + + insert into test values (1); + insert into test values (2); + insert into test values (3); + insert into test values (4); + insert into test values (5); + insert into test values (6); + commit; + + update test set id=-1 where id=1; + rollback; + set list on; + select count(*) from test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + COUNT 6 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22000 + no current record for fetch operation + """ + +@pytest.mark.version('>=2.5') +def test_core_0185_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0188.py b/tests/bugs/test_core_0188.py new file mode 100644 index 00000000..dfe4ddd1 --- /dev/null +++ b/tests/bugs/test_core_0188.py @@ -0,0 +1,164 @@ +#coding:utf-8 +# +# id: bugs.core_0188 +# title: trigger on view with union receive nulls +# decription: +# Passed on: WI-V3.0.0.32487, WI-T4.0.0.141 -- works fine. +# On WI-V2.5.6.27001 issues wrong result thus min_version (for now) is 3.0. +# +# tracker_id: CORE-0188 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set width ctx_name 30; + set width ctx_val 10; + + recreate view v_ctx_data as + select mon$variable_name as ctx_name, mon$variable_value as ctx_val + from mon$context_variables c + where mon$attachment_id = current_connection or mon$transaction_id = current_transaction; + + recreate view v_test as select 1 k from rdb$database; + commit; + + recreate table test_a (id int); + recreate table test_b (id int); + + commit; + + recreate view v_test(id, row_from_table_b) + as + select id, cast(0 as int) + from test_a a + where not exists (select * from test_b b where b.id = a.id) + + union all + + select id, cast(1 as int) + from test_b; + + commit; + + set term ^; + create or alter procedure sp_zap_context_vars as + declare ctx_ssn int; + declare ctx_name varchar(80); + begin + for + select mon$attachment_id, mon$variable_name as ctx_name + from mon$context_variables c + where mon$attachment_id = current_connection or mon$transaction_id = current_transaction + into ctx_ssn, ctx_name + do + execute statement + 'rdb$set_context(' + || iif(ctx_ssn is not null, '''USER_SESSION''', '''USER_TRANSACTION''') + || ', ''' + || ctx_name + || ''', null )' + ; + end + ^ + + create trigger v_test_bu for v_test active before update position 0 as + declare o int; + begin + rdb$set_context('USER_SESSION','trigger_sees_old_id', old.id); + rdb$set_context('USER_SESSION','trigger_sees_old_of_b1', old.row_from_table_b); + rdb$set_context('USER_SESSION','trigger_sees_new_id', new.id); + rdb$set_context('USER_SESSION','trigger_sees_new_of_b', new.row_from_table_b); + if (new.row_from_table_b = 1) then + begin + rdb$set_context('USER_SESSION','trigger_sees_old_of_b2', old.row_from_table_b); + if (old.row_from_table_b = 0) then + begin + rdb$set_context('USER_SESSION','trigger_sees_old_of_b3', old.row_from_table_b); + execute statement ( 'insert into test_b(id) values(?)') (new.id); + execute statement ( 'delete from test_a where id = ?' ) (new.id); + rdb$set_context('USER_SESSION','trigger_DID_its_job', new.id); + end + end + else + delete from test_b + where id = old.id; + end + ^ + set term ;^ + commit; + + + insert into test_a(id) values(1); + commit; + + set list on; + + select * from v_test; -- will return one record based on data in table test_a + + -- must insert row into test_b and remove row with the same id from test_a: + execute procedure sp_zap_context_vars; + select * from v_ctx_data; + + update v_test set row_from_table_b = 1 where id = 1; + commit; + + set count on; + select * from test_a; + select * from test_b; + select * from v_ctx_data; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + ROW_FROM_TABLE_B 0 + Records affected: 0 + ID 1 + Records affected: 1 + + CTX_NAME trigger_DID_its_job + CTX_VAL 1 + + CTX_NAME trigger_sees_new_id + CTX_VAL 1 + + CTX_NAME trigger_sees_new_of_b + CTX_VAL 1 + + CTX_NAME trigger_sees_old_id + CTX_VAL 1 + + CTX_NAME trigger_sees_old_of_b1 + CTX_VAL 0 + + CTX_NAME trigger_sees_old_of_b2 + CTX_VAL 0 + + CTX_NAME trigger_sees_old_of_b3 + CTX_VAL 0 + + + Records affected: 7 + """ + +@pytest.mark.version('>=3.0') +def test_core_0188_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0190.py b/tests/bugs/test_core_0190.py new file mode 100644 index 00000000..7a39b625 --- /dev/null +++ b/tests/bugs/test_core_0190.py @@ -0,0 +1,55 @@ +#coding:utf-8 +# +# id: bugs.core_0190 +# title: SYSDBA can grant non existent roles +# decription: +# tracker_id: CORE-0190 +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('Statement failed, SQLSTATE = HY000', ''), ('record not found for user:.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter user tmp$c0196 password '123'; + commit; + grant no_such_role to tmp$c0196; + commit; + set count on; + set list on; + select * from rdb$user_privileges where rdb$user = upper('tmp$c0196') rows 1; + commit; + drop user tmp$c0196; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -GRANT failed + -SQL role NO_SUCH_ROLE does not exist + """ + +@pytest.mark.version('>=3.0') +def test_core_0190_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0195.py b/tests/bugs/test_core_0195.py new file mode 100644 index 00000000..eb529261 --- /dev/null +++ b/tests/bugs/test_core_0195.py @@ -0,0 +1,120 @@ +#coding:utf-8 +# +# id: bugs.core_0195 +# title: Bugcheck 291 +# decription: +# tracker_id: +# min_versions: ['2.0.7'] +# versions: 2.0.7 +# qmid: bugs.core_0195 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table tbl_bugcheck291 + ( + ID integer NOT NULL PRIMARY KEY, + DATA integer + ); + + commit; + + insert into tbl_bugcheck291 (id, data) values (1,100); + + commit; + + set term ^; + create trigger bu_tbl_bugcheck291 for tbl_bugcheck291 + before update + as + begin + if(new.data is not null) then + begin + if(new.data<110) then + begin + update tbl_bugcheck291 x set x.data=new.data+1 where x.id=new.id; + end + end + end + ^ + set term ;^ + commit; + + update tbl_bugcheck291 set data=105 where id=1; + + commit; + + update tbl_bugcheck291 set data=105 where id=1; + + /*FB2.5: internal Firebird consistency check (cannot find record back version (291), file: vio.cpp line: 5014).*/ + update tbl_bugcheck291 set data=105 where id=1; + + /*internal Firebird consistency check (can't continue after bugcheck).*/ + update tbl_bugcheck291 set data=105 where id=1; + update tbl_bugcheck291 set data=105 where id=1; + update tbl_bugcheck291 set data=105 where id=1; + update tbl_bugcheck291 set data=105 where id=1; + commit; + + ------------------------------------------------ + + create table "TBL_BUGCHECK291B" + ( + "DATA" integer, + "FLAG" integer + ); + + set term ^; + create trigger "TRG_BUGCHECK291B" for "TBL_BUGCHECK291B" + active before update position 1 + as + begin + if (new.Flag = 16 and new.Data = 1) then begin + update tbl_bugcheck291b set Data = 2 where Flag = 46; + update tbl_bugcheck291b set Data = 3 where Flag = 46; + end + if (new.Flag = 46 and new.Data = 2) then begin + update tbl_bugcheck291b set Data = 4 where Flag = 14; + update tbl_bugcheck291b set Data = 5 where Flag = 15; + end + if (new.Flag = 14 and new.Data = 4) then begin + update tbl_bugcheck291b set Data = 6 where Flag = 46; + end + if (new.Flag = 15 and new.Data = 5) then begin + update tbl_bugcheck291b set Data = 7 where Flag = 46; + end + if (new.Flag = 46 and new.Data = 3) then begin + update tbl_bugcheck291b set Data = 8 where Flag = 46; + end + end + ^ + set term ;^ + commit; + + insert into tbl_bugcheck291b(Flag) values(14); + insert into tbl_bugcheck291b(Flag) values(15); + insert into tbl_bugcheck291b(Flag) values(16); + insert into tbl_bugcheck291b(Flag) values(46); + commit; + + update tbl_bugcheck291b set Data=1 where Flag = 16; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.0.7') +def test_core_0195_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_0198.py b/tests/bugs/test_core_0198.py new file mode 100644 index 00000000..fabcc1c6 --- /dev/null +++ b/tests/bugs/test_core_0198.py @@ -0,0 +1,117 @@ +#coding:utf-8 +# +# id: bugs.core_0198 +# title: wrong order by in table join storedproc +# decription: +# tracker_id: CORE-0198 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table my_table + ( + k varchar(10) not null, + d1 integer, + d2 integer, + v1 varchar(10), + primary key (k) + ); + + set term ^; + create or alter procedure select_me returns( + data varchar(10) + ) as + begin + data = 'one'; + suspend; + data = 'two'; + suspend; + data = 'three'; + suspend; + end + ^ + set term ;^ + commit; + + insert into my_table values ('one', 1, 99, 'zz'); + insert into my_table values ('two', 2, 98, 'yy'); + insert into my_table values ('three', 3, 97, 'xx'); + commit; + + set list on; + + select * + from my_table t join select_me p on (t.k = p.data) + order by t.d1 + ; + commit; + + create index i1 on my_table(d1); + commit; + + select * + from my_table t join select_me p on (t.k = p.data) + order by t.d1 + ; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + K one + D1 1 + D2 99 + V1 zz + DATA one + + K two + D1 2 + D2 98 + V1 yy + DATA two + + K three + D1 3 + D2 97 + V1 xx + DATA three + + K one + D1 1 + D2 99 + V1 zz + DATA one + + K two + D1 2 + D2 98 + V1 yy + DATA two + + K three + D1 3 + D2 97 + V1 xx + DATA three + """ + +@pytest.mark.version('>=2.5') +def test_core_0198_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0200.py b/tests/bugs/test_core_0200.py new file mode 100644 index 00000000..37f15f44 --- /dev/null +++ b/tests/bugs/test_core_0200.py @@ -0,0 +1,51 @@ +#coding:utf-8 +# +# id: bugs.core_0200 +# title: Empty column names with aggregate funcs +# decription: +# tracker_id: CORE-200 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_200 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select (select count(1) from rdb$database) from rdb$database ; +select (select avg(1) from rdb$database) from rdb$database ; +select (select sum(1) from rdb$database) from rdb$database ; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ COUNT +===================== + 1 + + + AVG +===================== + 1 + + + SUM +===================== + 1 + +""" + +@pytest.mark.version('>=3.0') +def test_core_0200_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0203.py b/tests/bugs/test_core_0203.py new file mode 100644 index 00000000..3ffb496c --- /dev/null +++ b/tests/bugs/test_core_0203.py @@ -0,0 +1,160 @@ +#coding:utf-8 +# +# id: bugs.core_0203 +# title: CREATE VIEW ignores PLAN +# decription: +# 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. +# +# ::: NOTE ::: +# 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)". +# +# Checked on: +# 4.0.0.1743 SS: 1.781s. +# 4.0.0.1714 CS: 6.500s. +# 3.0.6.33236 SS: 1.313s. +# 3.0.6.33236 CS: 1.891s. +# 2.5.9.27149 SC: 1.047s. +# +# tracker_id: CORE-0203 +# min_versions: ['2.5'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('[ ]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + 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; + + insert into test(x,y) select rand()*100, rand()*10000 from rdb$types,rdb$types rows 10000; + commit; + + create index test_x_asc on test(x); + create descending index test_x_desc on test(x); + + create index test_y_x on test(y, x); + create index test_x_y on test(x, y); + + create index test_sum_x_y on test computed by (x+y); + create descending index test_sub_x_y on test computed by (x-y); + + commit; + + recreate view v_test1 as select * from test t where x = 0 plan (t natural); + recreate view v_test2 as select * from test t where x = 0; + 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 planonly; + --set echo on; + + 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 + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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)) + + PLAN (V1 T INDEX (TEST_X_Y)) + + 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)) + + """ + +@pytest.mark.version('>=2.5') +def test_core_0203_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0209.py b/tests/bugs/test_core_0209.py new file mode 100644 index 00000000..2f726438 --- /dev/null +++ b/tests/bugs/test_core_0209.py @@ -0,0 +1,137 @@ +#coding:utf-8 +# +# id: bugs.core_0209 +# title: CHECK constraints fire twice +# decription: +# tracker_id: CORE-0209 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [("-At trigger 'V_TEST_BIU' line.*", "-At trigger 'V_TEST_BIU' line")] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create domain dm_restricted_char as char(1) check (value in ('A','B','C', 'D','E')); + + recreate table test ( + id integer, + col dm_restricted_char + ); + + recreate view v_test as select * from test; + + set term ^; + create trigger tab_biu for test before insert or update as + begin + new.col = upper (new.col); + end^ + + create trigger v_test_biu for v_test before insert or update as + begin + -- ::: NB ::: + -- Since 2.0 trigger that belongs to updatable view MUST have DML + -- statement that handles underlying TABLE (this was not so in 1.5). + if ( inserting ) then + insert into test values( new.id, new.col ); + else + update test set col = new.col, id = new.id + where id = old.id; + end^ + + set term ;^ + commit; + + set count on; + set list on; + SET ECHO ON; + + insert into v_test values (11, 'a'); + insert into v_test values (12, 'b'); + insert into v_test values (13, 'c'); + insert into v_test values (14, 'd'); + + select * from test; + commit; + + update v_test set col='e' where id=11; + update v_test set col='e' where id=14; + + update test set col='z' where id=12; + update v_test set col='x' where id=13; + + select * from test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + insert into v_test values (11, 'a'); + Records affected: 1 + insert into v_test values (12, 'b'); + Records affected: 1 + insert into v_test values (13, 'c'); + Records affected: 1 + insert into v_test values (14, 'd'); + Records affected: 1 + + select * from test; + ID 11 + COL A + ID 12 + COL B + ID 13 + COL C + ID 14 + COL D + Records affected: 4 + commit; + + update v_test set col='e' where id=11; + Records affected: 1 + update v_test set col='e' where id=14; + Records affected: 1 + + update test set col='z' where id=12; + Records affected: 0 + update v_test set col='x' where id=13; + Records affected: 0 + + select * from test; + + ID 11 + COL E + ID 12 + COL B + ID 13 + COL C + ID 14 + COL E + Records affected: 4 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."COL", value "Z" + + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."COL", value "X" + -At trigger 'V_TEST_BIU' line: 8, col: 5 + """ + +@pytest.mark.version('>=2.5') +def test_core_0209_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0210.py b/tests/bugs/test_core_0210.py new file mode 100644 index 00000000..780b9d1c --- /dev/null +++ b/tests/bugs/test_core_0210.py @@ -0,0 +1,80 @@ +#coding:utf-8 +# +# id: bugs.core_0210 +# title: CS server crash altering SP in 2 connect +# decription: +# +# tracker_id: CORE-0210 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import fdb +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# stm1='''create or alter procedure sp_test as +# begin +# exit; +# end +# ''' +# stm2='''create or alter procedure sp_test as +# declare x int; +# begin +# exit; +# end +# ''' +# +# con1 = fdb.connect(dsn=dsn) +# con2 = fdb.connect(dsn=dsn) +# +# xtpb = ( [ fdb.isc_tpb_concurrency ] ) +# +# con1.begin( tpb = xtpb ) +# +# cur1=con1.cursor() +# cur2=con2.cursor() +# +# cur1.execute(stm1) +# con1.commit() +# +# con2.begin( tpb = xtpb ) +# cur2.execute(stm2) +# con2.commit() +# +# con1.begin( tpb = xtpb ) +# cur1.execute(stm1) +# con1.commit() +# +# con1.close() +# con2.close() +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_0210_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_0211.py b/tests/bugs/test_core_0211.py new file mode 100644 index 00000000..a93eb36b --- /dev/null +++ b/tests/bugs/test_core_0211.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_0211 +# title: SELECT...HAVING...NOT IN crashes server +# decription: +# Crashed on: WI-V3.0.0.32380, WI-T4.0.0.32399, found 16-mar-2016. +# Passed on: WI-V3.0.0.32487, WI-T4.0.0.141 -- works fine. +# +# tracker_id: CORE-0211 +# min_versions: ['2.0'] +# versions: 2.0.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.0 +# resources: None + +substitutions_1 = [('RDB\\$RELATION_ID[ ]+\\d+', 'RDB$RELATION_ID')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select r.rdb$relation_id, count(*) + from rdb$database r + group by r.rdb$relation_id + having count(*) not in (select r2.rdb$relation_id from rdb$database r2); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$RELATION_ID 134 + COUNT 1 + """ + +@pytest.mark.version('>=2.0.0') +def test_core_0211_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0214.py b/tests/bugs/test_core_0214.py new file mode 100644 index 00000000..32ccdf56 --- /dev/null +++ b/tests/bugs/test_core_0214.py @@ -0,0 +1,200 @@ +#coding:utf-8 +# +# id: bugs.core_0214 +# title: Count ( DISTINCT ... ) is too slow +# decription: +# tracker_id: CORE-0214 +# min_versions: ['2.5.5'] +# versions: 2.5.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + -- 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". + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + 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; + commit; + + set list on; + + set term ^; + + execute block returns ( + ratio_for_1e1 varchar(50) + ,ratio_for_1e2 varchar(50) + ,ratio_for_1e3 varchar(50) + ,ratio_for_1e4 varchar(50) + ,ratio_for_1e5 varchar(50) + ) + 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) = 3.00; + + -- ############################################ + + 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; + 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, <= ' || max_diff_threshold; + ratio_for_1e2 = 'Acceptable, <= ' || max_diff_threshold; + ratio_for_1e3 = 'Acceptable, <= ' || max_diff_threshold; + ratio_for_1e4 = 'Acceptable, <= ' || max_diff_threshold; + ratio_for_1e5 = 'Acceptable, <= ' || max_diff_threshold; + + if (ratio_select_vs_count_1e1 > max_diff_threshold) then + ratio_for_1e1 = 'Regression: ratio = '||ratio_select_vs_count_1e1||' > '||max_diff_threshold; + + if (ratio_select_vs_count_1e2 > max_diff_threshold) then + ratio_for_1e2 = 'Regression: ratio = '||ratio_select_vs_count_1e2||' > '||max_diff_threshold; + + if (ratio_select_vs_count_1e3 > max_diff_threshold) then + ratio_for_1e3 = 'Regression: ratio = '||ratio_select_vs_count_1e3||' > '||max_diff_threshold; + + if (ratio_select_vs_count_1e4 > max_diff_threshold) then + ratio_for_1e4 = 'Regression: ratio = '||ratio_select_vs_count_1e4||' > '||max_diff_threshold; + + if (ratio_select_vs_count_1e5 > max_diff_threshold) then + ratio_for_1e5 = 'Regression: ratio = '||ratio_select_vs_count_1e5||' > '||max_diff_threshold; + + + suspend; + + end + ^ set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RATIO_FOR_1E1 Acceptable, <= 3.0000 + RATIO_FOR_1E2 Acceptable, <= 3.0000 + RATIO_FOR_1E3 Acceptable, <= 3.0000 + RATIO_FOR_1E4 Acceptable, <= 3.0000 + RATIO_FOR_1E5 Acceptable, <= 3.0000 + """ + +@pytest.mark.version('>=2.5.5') +def test_core_0214_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0216.py b/tests/bugs/test_core_0216.py new file mode 100644 index 00000000..553dc719 --- /dev/null +++ b/tests/bugs/test_core_0216.py @@ -0,0 +1,62 @@ +#coding:utf-8 +# +# id: bugs.core_0216 +# title: Too many grants lose privileges +# decription: Issuing more than 2000 grants on any one object causes +# an internal buffer flow in generating the access +# control list that actually enforces the rights. +# tracker_id: CORE-216 +# min_versions: ['2.5'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table T (PK integer); +create table LOG(PK integer); +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# c = db_conn.cursor() +# # Create 4000 triggers on table T +# i = 1 +# cmd = """create trigger LOGT_%d for T after insert as +# begin +# insert into log (PK) values (new.pk); +# end +# """ +# while i <= 4000: +# c.execute(cmd % i) +# i += 1 +# db_conn.commit() +# +# # Grants +# i = 1 +# cmd = """GRANT INSERT ON LOG TO TRIGGER LOGT_%d""" +# while i <= 4000: +# try: +# c.execute(cmd % i) +# except Exception as e: +# print('Error:',e) +# i = 4000 +# i += 1 +# db_conn.commit() +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_0216_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_0223.py b/tests/bugs/test_core_0223.py new file mode 100644 index 00000000..eb35eac7 --- /dev/null +++ b/tests/bugs/test_core_0223.py @@ -0,0 +1,76 @@ +#coding:utf-8 +# +# id: bugs.core_0223 +# title: ALTER TABLE altering to VARCHAR +# decription: +# tracker_id: CORE-0223 +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + recreate table test1(x int); + --create index test1_x on test1(x); + + insert into test1 values(2000000000); + insert into test1 values(100000000); + insert into test1 values(50000000); + commit; + + select * from test1 order by x; + commit; + + alter table test1 alter x type varchar(5); + alter table test1 alter x type varchar(9); + + alter table test1 alter x type varchar(11); + + -- Here values must be sorted as TEXT: + select * from test1 order by x; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + X 50000000 + X 100000000 + X 2000000000 + + X 100000000 + X 2000000000 + X 50000000 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER TABLE TEST1 failed + -New size specified for column X must be at least 11 characters. + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER TABLE TEST1 failed + -New size specified for column X must be at least 11 characters. + """ + +@pytest.mark.version('>=3.0') +def test_core_0223_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0282.py b/tests/bugs/test_core_0282.py new file mode 100644 index 00000000..471ceca6 --- /dev/null +++ b/tests/bugs/test_core_0282.py @@ -0,0 +1,51 @@ +#coding:utf-8 +# +# id: bugs.core_0282 +# title: DOMAINs don't register their dependency on other objects +# decription: +# tracker_id: CORE-282 +# min_versions: [] +# versions: 2.5 +# qmid: bugs.core_282-250 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t(a int); +create domain d int check(value > (select max(a) from t)); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """drop table t; +commit; +create table u(a d); +commit; +show table u; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """A (D) INTEGER Nullable + check(value > (select max(a) from t)) +""" +expected_stderr_1 = """Statement failed, SQLSTATE = 42000 +unsuccessful metadata update +-cannot delete +-COLUMN T.A +-there are 1 dependencies +""" + +@pytest.mark.version('>=2.5') +def test_core_0282_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0284.py b/tests/bugs/test_core_0284.py new file mode 100644 index 00000000..fe0f23ea --- /dev/null +++ b/tests/bugs/test_core_0284.py @@ -0,0 +1,60 @@ +#coding:utf-8 +# +# id: bugs.core_0284 +# title: Blob Comparison with constant +# decription: +# tracker_id: CORE-284 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_284 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE T1 (PK INTEGER NOT NULL, COL1 BLOB SUB_TYPE TEXT); +commit; +insert into T1 (PK,COL1) values (1,'text'); +insert into T1 (PK,COL1) values (2,''); +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select * from T1 where COL1 = ''; +select * from T1 where COL1 = 'text'; +commit; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PK COL1 +============ ================= + 2 80:1 +============================================================================== +COL1: + +============================================================================== + + + PK COL1 +============ ================= + 1 80:0 +============================================================================== +COL1: +text +============================================================================== + +""" + +@pytest.mark.version('>=3.0') +def test_core_0284_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0297.py b/tests/bugs/test_core_0297.py new file mode 100644 index 00000000..21664229 --- /dev/null +++ b/tests/bugs/test_core_0297.py @@ -0,0 +1,142 @@ +#coding:utf-8 +# +# id: bugs.core_0297 +# title: bug #585624 IB server stalled by simple script +# decription: +# ::: NB ::: +# ### Name of original test has no any relation with actual task of this test: ### +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_23.script +# +# Issue in original script: bug #585624 IB server stalled by simple script" +# Found in FB tracker as: http://tracker.firebirdsql.org/browse/CORE-297 +# Fixed in 1.5.0 +# +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(charset='ISO8859_1', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create procedure group_copy ( + source integer, + destination integer) + as + begin + exit; + end^ + + create procedure insert_values ( + cont integer, + d_group integer) + as + begin + exit; + end^ + set term ;^ + + create table groups ( + gr_id integer not null, + gr_name varchar(40) character set iso8859_1 not null + collate de_de + ); + + create table test ( + id integer not null, + t_group integer not null + ); + + alter table groups add constraint pk_groups primary key (gr_id); + alter table test add constraint pk_test primary key (id, t_group); + alter table test add constraint fk_test foreign key (t_group) references groups (gr_id); + + set term ^; + alter procedure group_copy ( + source integer, + destination integer) + as + begin + insert into test( id, t_group ) + select a.id, :destination + from test a + where a.t_group = :source + and not exists ( + select * from test b + where b.id = a.id + and :destination = b.t_group + ); + end + ^ + + alter procedure insert_values ( + cont integer, + d_group integer) + as + declare anz integer; + begin + anz = 0; + + while ( anz < cont ) do + begin + if ( not exists ( + select id + from test where id = :anz + and t_group = :d_group + ) + ) then + insert into test( id, t_group ) values( :anz, :d_group ); + + anz = anz +1; + end + end + ^ + set term ;^ + commit; + + + insert into groups values ( 1 , 'Group1' ); + insert into groups values ( 2 , 'Group2' ); + commit; + execute procedure insert_values( 3000 , 1); + commit; + + delete from test where t_group = 2; + execute procedure group_copy( 1 , 2 ); + commit; + + set list on; + select count(*) from test; + select * from groups; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + COUNT 6000 + GR_ID 1 + GR_NAME Group1 + GR_ID 2 + GR_NAME Group2 + """ + +@pytest.mark.version('>=2.5') +def test_core_0297_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0304.py b/tests/bugs/test_core_0304.py new file mode 100644 index 00000000..14386f68 --- /dev/null +++ b/tests/bugs/test_core_0304.py @@ -0,0 +1,419 @@ +#coding:utf-8 +# +# id: bugs.core_0304 +# title: ANY user can drop procedures, generators, exceptions. +# decription: +# fb30Cs, build 3.0.4.32924: OK, 4.406s. +# FB30SS, build 3.0.4.32939: OK, 1.563s. +# +# 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/ +# Checked on: +# 4.0.0.1172: OK, 8.140s. +# 4.0.0.1340: OK, 4.797s. +# 4.0.0.1378: OK, 4.032s. +# +# tracker_id: CORE-304 +# min_versions: ['3.0'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter user tmp$c0304 password '123'; + commit; + + 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; + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + drop user tmp$c0304; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_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 TABLE 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,<4.0') +def test_core_0304_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + create or alter user tmp$c0304 password '123'; + commit; + + -- 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; + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + drop user tmp$c0304; + commit; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_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 TABLE 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_core_0304_2(act_2: Action): + act_2.expected_stderr = expected_stderr_2 + act_2.execute() + assert act_2.clean_expected_stderr == act_2.clean_stderr + diff --git a/tests/bugs/test_core_0335.py b/tests/bugs/test_core_0335.py new file mode 100644 index 00000000..77c19fa2 --- /dev/null +++ b/tests/bugs/test_core_0335.py @@ -0,0 +1,586 @@ +#coding:utf-8 +# +# id: bugs.core_0335 +# title: Unsuccessful execution caused by system error <...> bad BLR -- invalid stream +# decription: +# Original ticket title: "Lost connexion with Big request" +# Test checks that: +# 1) we *can* run query with unions, where is limit specific for 2.5.x vs 3.x +# 2) we can *not* run query with unions. +# Actual value of is 128 for 2.5.x (NOT 255 as errormessage issues!) and 255 for 3.0. +# +# Checked on WI-V2.5.7.27025, WI-V3.0.1.32598. +# +# tracker_id: CORE-335 +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table test(id int); + commit; + insert into test select 1 from rdb$types rows 10; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + + -- ########################## + -- FIRST QUERY: SHOULD PASS. + -- ########################## + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union -- 10 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union -- 20 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union -- 30 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union -- 40 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union -- 50 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union -- 60 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union -- 70 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union -- 80 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union -- 90 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --100 + + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --110 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --120 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union -- last allowed in 2.5.7; add subsequent leads in 2.5.x to Too many Contexts of Relation/Procedure/Views. Maximum allowed is 255 + select first 5 * from test union + select first 5 * from test union --130 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --140 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --150 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --160 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --170 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --180 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --190 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --200 + + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --210 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --220 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --230 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --240 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --250 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test ------------------- last allowed in 3.0 + ; /* union select first 5 * from test; */ + + + -- ########################## + -- SECOND QUERY: SHOULD FAIL. + -- ########################## + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union -- 10 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union -- 20 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union -- 30 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union -- 40 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union -- 50 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union -- 60 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union -- 70 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union -- 80 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union -- 90 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --100 + + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --110 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --120 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union -- last allowed in 2.5.7; add subsequent leads in 2.5.x to Too many Contexts of Relation/Procedure/Views. Maximum allowed is 255 + select first 5 * from test union + select first 5 * from test union --130 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --140 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --150 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --160 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --170 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --180 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --190 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --200 + + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --210 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --220 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --230 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --240 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union --250 + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test union + select first 5 * from test ------------------- last allowed in 3.0 + union all select first 5 * from test; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + Records affected: 1 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 54001 + Dynamic SQL Error + -Too many Contexts of Relation/Procedure/Views. Maximum allowed is 256 + """ + +@pytest.mark.version('>=3.0') +def test_core_0335_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0337.py b/tests/bugs/test_core_0337.py new file mode 100644 index 00000000..b0939a15 --- /dev/null +++ b/tests/bugs/test_core_0337.py @@ -0,0 +1,147 @@ +#coding:utf-8 +# +# id: bugs.core_0337 +# title: bug #910430 ISQL and database dialect +# decription: +# ::: NB ::: +# ### Name of original test has no any relation with actual task of this test: ### +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_25.script +# +# When ISQL disconnects from database (either by dropping it or by trying to connect to +# non-existent database) is still remembers its sql dialect, which can lead to some +# inappropriate warning messages. +# +# Issue in original script: bug #910430 ISQL and database dialect +# Found in FB tracker as: http://tracker.firebirdsql.org/browse/CORE-337 +# Fixed in 2.0 Beta 1 +# +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('CREATE DATABASE.*', 'CREATE DATABASE')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# +# #-------------------------------------------- +# +# 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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# +# #-------------------------------------------- +# +# test_fdb=os.path.join(context['temp_directory'],'tmp_0337.fdb') +# +# cleanup( test_fdb, ) +# +# db_conn.close() +# sql=''' +# set echo on; +# +# show sql dialect; +# +# set sql dialect 1; +# +# show sql dialect; +# +# set sql dialect 3; +# +# create database 'localhost:%(test_fdb)s' user '%(user_name)s' password '%(user_password)s'; +# +# show sql dialect; +# +# drop database; +# +# show database; +# +# show sql dialect; +# +# set sql dialect 1; +# ''' % dict(globals(), **locals()) +# +# f_sql_chk = open( os.path.join(context['temp_directory'],'tmp_0337_ddl.sql'), 'w', buffering = 0) +# f_sql_chk.write(sql) +# flush_and_close( f_sql_chk ) +# +# f_sql_log = open( ''.join( (os.path.splitext(f_sql_chk.name)[0], '.log' ) ), 'w', buffering = 0) +# subprocess.call( [ context['isql_path'], '-q', '-i', f_sql_chk.name ], stdout = f_sql_log, stderr = subprocess.STDOUT) +# flush_and_close( f_sql_log ) +# +# with open(f_sql_log.name,'r') as f: +# for line in f: +# if line.split(): +# print( line.upper() ) +# +# cleanup( (test_fdb, f_sql_log.name, f_sql_chk.name) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + SHOW SQL DIALECT; + CLIENT SQL DIALECT HAS NOT BEEN SET AND NO DATABASE HAS BEEN CONNECTED YET. + + SET SQL DIALECT 1; + SHOW SQL DIALECT; + CLIENT SQL DIALECT IS SET TO: 1. NO DATABASE HAS BEEN CONNECTED. + + SET SQL DIALECT 3; + CREATE DATABASE 'LOCALHOST:C:\\FBTESTING\\QA\\FBT-REPO\\TMP2\\TMP_0337.FDB' USER 'SYSDBA' PASSWORD 'MASTERKEY'; + + SHOW SQL DIALECT; + CLIENT SQL DIALECT IS SET TO: 3 AND DATABASE SQL DIALECT IS: 3 + + DROP DATABASE; + + SHOW DATABASE; + COMMAND ERROR: SHOW DATABASE + + SHOW SQL DIALECT; + CLIENT SQL DIALECT IS SET TO: 3. NO DATABASE HAS BEEN CONNECTED. + + SET SQL DIALECT 1; + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_0337_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_0366.py b/tests/bugs/test_core_0366.py new file mode 100644 index 00000000..727b2d3a --- /dev/null +++ b/tests/bugs/test_core_0366.py @@ -0,0 +1,465 @@ +#coding:utf-8 +# +# id: bugs.core_0366 +# title: Complex view crashes server +# decription: +# NOTE-1. +# Name of original test has no any relation with actual task of this test: ### +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_26.script +# +# Issue in original script: bug #583690 Complex view crashes server +# Found in FB tracker as: http://tracker.firebirdsql.org/browse/CORE-366 +# Fixed on 2.0 Beta 1 +# +# NOTE-2. +# We expect that compilation of this test script finished OK, without any errors/warnings. +# 2.5 issues "too many contexts / max allowed 255'; because of this, min_version=3.0 +# +# Checked on: 4.0.0.1803; 3.0.6.33265 +# +# tracker_id: CORE-0366 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + CREATE TABLE DRZAVA( + POZIVNIBROJDRZAVE VARCHAR(4) NOT NULL, + NAZIVDRZAVE VARCHAR(20), + GRUPA INTEGER NOT NULL, + PRIMARY KEY(POZIVNIBROJDRZAVE) + ); + + CREATE TABLE LOG ( + BROJ VARCHAR(25) NOT NULL, + POCETAK TIMESTAMP NOT NULL, + TRAJANJE INTEGER NOT NULL, + LOKAL INTEGER, + LINIJA INTEGER, + CENA NUMERIC(8,2) NOT NULL + ); + + CREATE TABLE LOKAL( + BROJLOKALA INTEGER NOT NULL, + NAZIVLOKALA VARCHAR(25) NOT NULL, + PRIMARY KEY(BROJLOKALA) + ); + + CREATE TABLE MESNI( + PTT CHAR(5) NOT NULL, + LOKALNIPREFIX VARCHAR(5) NOT NULL, + PRIMARY KEY (PTT,LOKALNIPREFIX) + ); + + CREATE TABLE MREZA( + BROJMREZE VARCHAR(4) NOT NULL, + POZIVNIBROJ VARCHAR(4) NOT NULL, + ZONA INTEGER NOT NULL, + PRIMARY KEY (BROJMREZE,POZIVNIBROJ) + ); + + CREATE TABLE VrstaRT( + SifraVRT char(7) NOT NULL, + NazivVRT varchar(30) NOT NULL, + JM varchar(6), + PRIMARY KEY (SifraVRT) + ); + + CREATE TABLE Poslovnica( + SifraPoslovnice char(2) NOT NULL, + NazivPoslovnice varchar(18) NOT NULL, + PRIMARY KEY(SifraPoslovnice) + ); + + CREATE TABLE RezijskiTrosak( + RedniBroj integer NOT NULL, + DatumTroska timestamp NOT NULL, + SifraPoslovnice char(2) NOT NULL + REFERENCES Poslovnica (SifraPoslovnice) ON UPDATE CASCADE, + SifraVRT char(7) NOT NULL + REFERENCES VrstaRT(SifraVRT) ON UPDATE CASCADE, + Kolicina decimal(8,2), + Iznos decimal(8,2) NOT NULL, + PRIMARY KEY (RedniBroj) + ); + + CREATE GENERATOR GEN_RT_ID; + SET GENERATOR GEN_RT_ID TO 0; + + CREATE TABLE VrstaMT( + SifraVMT char(7) NOT NULL, + NazivVMT varchar(30) NOT NULL, + DefaultJM varchar(6), + PRIMARY KEY(SifraVMT) + ); + + CREATE TABLE Roba( + SifraRobe char(6) NOT NULL, + VrstaRobe char(7) NOT NULL + REFERENCES VrstaMT (SifraVMT) ON UPDATE CASCADE, + NazivRobe varchar(30) NOT NULL, + JM varchar(6) NOT NULL, + BarCode varchar(50), + Pakovanje integer, + Napomena varchar(100), + PRIMARY KEY(SifraRobe) + ); + + CREATE TABLE Mesto( + PTT char(5) NOT NULL, + NazivMesta varchar(40) NOT NULL, + PozivniBroj char(4), + PRIMARY KEY(PTT) + ); + + CREATE TABLE Komitent( + SifraKomitenta integer NOT NULL, + Naziv varchar(25) NOT NULL , + PTT char(5) NOT NULL + REFERENCES Mesto(PTT) ON UPDATE CASCADE, + Napomena varchar(100), + Owner char(8), + PRIMARY KEY(SifraKomitenta) + ); + + CREATE GENERATOR GEN_Komitent_ID; + SET GENERATOR GEN_Komitent_ID TO 0; + + CREATE TABLE VrstaDetalja( + SifraVD integer NOT NULL, + OpisVD varchar(15), + Telefon char(1), + CHECK (telefon is null or telefon = 'D' or telefon ='Z'), + PRIMARY KEY(SifraVD) + ); + + CREATE GENERATOR GEN_VrstaDetalja_ID; + SET GENERATOR GEN_VrstaDetalja_ID TO 0; + + CREATE TABLE KomitentDetaljno ( + SifraKD integer NOT NULL, + SifraKomitenta integer NOT NULL + REFERENCES Komitent (SifraKomitenta) ON UPDATE CASCADE ON DELETE CASCADE, + SifraVD integer NOT NULL + REFERENCES VrstaDetalja (SifraVD) ON UPDATE CASCADE, + Podatak varchar(40) NOT NULL, + CistBroj varchar(25), + PRIMARY KEY(SifraKD) + ); + + CREATE GENERATOR GEN_KOMITENTDETALJNO_ID; + SET GENERATOR GEN_KOMITENTDETALJNO_ID TO 0; + + CREATE TABLE Prijem( + BRDOK integer NOT NULL, + DatumUlaza timestamp NOT NULL, + SifraKomitenta integer + REFERENCES Komitent(SifraKomitenta) ON UPDATE CASCADE, + PRIMARY KEY(BRDOK) + ); + + CREATE GENERATOR GEN_PRIJ_ID; + SET GENERATOR GEN_PRIJ_ID TO 0; + + CREATE TABLE Prijemst( + BRDOK integer NOT NULL + REFERENCES Prijem(BRDOK) ON UPDATE CASCADE ON DELETE CASCADE, + SifraRobe char(6) NOT NULL + REFERENCES ROBA(SifraRobe) ON UPDATE CASCADE, + Kolicina decimal(8,2) NOT NULL, + Cena decimal(8,2) NOT NULL, + PRIMARY KEY (BRDOK,SifraRobe) + ); + + CREATE TABLE Alokacija( + Brdok integer NOT NULL, + Datum timestamp NOT NULL, + SifraPoslovnice char(2) NOT NULL + REFERENCES Poslovnica (SifraPoslovnice) ON UPDATE CASCADE, + PRIMARY KEY (Brdok) + ); + + CREATE GENERATOR GEN_ALOK_ID; + SET GENERATOR GEN_ALOK_ID TO 1; + + CREATE TABLE Alokacijast( + Brdok integer NOT NULL + REFERENCES Alokacija(BRDOK) ON UPDATE CASCADE ON DELETE CASCADE, + SifraRobe char(6) NOT NULL + REFERENCES ROBA(SifraRobe) ON UPDATE CASCADE, + Kolicina decimal(8,2) NOT NULL, + Cena decimal(8,2) NOT NULL, + PRIMARY KEY (Brdok,SifraRobe) + ); + + CREATE TABLE VrstaGoriva( + SifraVrsteGoriva Integer NOT NULL, + NazivVrsteGoriva varchar(10) NOT NULL, + PRIMARY KEY(SifraVrsteGoriva) + ); + + + CREATE TABLE VrstaVozila( + SifraVrste char(2) NOT NULL, + NazivVrste varchar(18) NOT NULL, + PRIMARY KEY(SifraVrste) + ); + + CREATE TABLE Vozilo( + SifraVozila char(12) NOT NULL, + SifraVrste char(2) NOT NULL + REFERENCES VrstaVozila (SifraVrste) ON UPDATE CASCADE, + RegBroj char(10), + Marka char(10), + Tip char(20), + BrojSasije char(25), + BrojMotora char(25), + PrvaRegistracija timestamp, + SnagaMotora decimal(10,2), + Zapremina integer, + Nosivost integer, + MestaZaSedenje char(4), + Karoserija char(25), + Boja char(20), + BrojOsovina char(1), + RokPPAparata timestamp, + PRIMARY KEY(SifraVozila) + ); + + CREATE TABLE Vozac( + SifraVozaca integer NOT NULL, + Ime char(25) NOT NULL, + Kategorije char(5) NOT NULL, + DatumVazenjaDozvole Timestamp, + PRIMARY KEY(SifraVozaca) + ); + + CREATE TABLE SipanjeGoriva( + SifraSG integer NOT NULL, + Datum Timestamp NOT NULL, + SifraVozila char(12) NOT NULL + REFERENCES Vozilo(SifraVozila) ON UPDATE CASCADE, + SifraVozaca integer NOT NULL + REFERENCES Vozac(SifraVozaca) ON UPDATE CASCADE, + SifraVrsteGoriva integer NOT NULL + REFERENCES VrstaGoriva (SifraVrsteGoriva) ON UPDATE CASCADE, + SifraPoslovnice char(2) NOT NULL + REFERENCES Poslovnica (SifraPoslovnice) ON UPDATE CASCADE, + KMsat decimal(9,1), + Kolicina decimal(10, 2) NOT NULL, + Cena decimal(8,2) NOT NULL, + PunDoCepa char(1), + CHECK (PunDoCepa = 'N' or PunDoCepa = 'D'), + PRIMARY KEY (SifraSG) + ); + + CREATE GENERATOR GEN_GORIVO_ID; + SET GENERATOR GEN_GORIVO_ID TO 1; + + CREATE TABLE Popravka( + Datum Timestamp NOT NULL, + SifraVozila char(12) NOT NULL + REFERENCES Vozilo(SifraVozila) ON UPDATE CASCADE, + SifraVozaca integer NOT NULL + REFERENCES Vozac(SifraVozaca) ON UPDATE CASCADE, + SifraPoslovnice char(2) NOT NULL + REFERENCES Poslovnica (SifraPoslovnice) ON UPDATE CASCADE, + Iznos decimal(12,2) NOT NULL, + Opis varchar(200), + PRIMARY KEY(Datum,SifraVozila) + ); + + CREATE TABLE Registracija( + Datum Timestamp NOT NULL, + SifraVozila char(12) NOT NULL + REFERENCES Vozilo(SifraVozila) ON UPDATE CASCADE, + CenaTehnickog decimal(12,2), + CenaOsiguranja decimal(12,2), + OstaliTroskovi decimal(12,2), + SifraPoslovnice char(2) NOT NULL + REFERENCES Poslovnica (SifraPoslovnice) ON UPDATE CASCADE, + PRIMARY KEY(Datum,SifraVozila) + ); + + CREATE TABLE DUMMY( + foobar integer NOT NULL primary key, + check (foobar = 1) + ); + + INSERT INTO dummy VALUES(1); + + + + CREATE VIEW APROMET(DATUM, SO, VRSTA,IZNOS) AS + select + rt.datumtroska, + SIFRAPOSLOVNICE, + cast(vrt.nazivvrt as varchar(30)), + cast(rt.iznos as numeric(18, 2)) + from rezijskitrosak rt + left join VRSTART vrt on rt.sifravrt = vrt.sifravrt + + union all + + SELECT + AL.DATUM, + SIFRAPOSLOVNICE, + cast('KancMat'as varchar(30)), + cast(sum(alst.kolicina * alst.cena) as numeric(18, 2)) + FROM ALOKACIJAST ALST + LEFT JOIN ALOKACIJA AL ON ALST.brdok=AL.brdok + LEFT JOIN ROBA R ON ALST.sifrarobe = R.sifrarobe + WHERE R.vrstarobe = 'KM' + GROUP BY AL.DATUM, SIFRAPOSLOVNICE + + union all + + SELECT + AL.DATUM, + SIFRAPOSLOVNICE, + cast ('Hemikalije' as varchar(30)), + cast(sum(alst.kolicina * alst.cena) as numeric(18, 2)) + FROM ALOKACIJAST ALST + LEFT JOIN ALOKACIJA AL ON ALST.brdok=AL.brdok + LEFT JOIN ROBA R ON ALST.sifrarobe = R.sifrarobe + WHERE R.vrstarobe = 'HE' + GROUP BY AL.DATUM, SIFRAPOSLOVNICE + + union all + + SELECT + AL.DATUM, + SIFRAPOSLOVNICE, + cast('Prehrana' as varchar(30)), + cast(sum(alst.kolicina * alst.cena) as numeric(18, 2)) + FROM ALOKACIJAST ALST + LEFT JOIN ALOKACIJA AL ON ALST.brdok=AL.brdok + LEFT JOIN ROBA R ON ALST.sifrarobe = R.sifrarobe + WHERE R.vrstarobe = 'HR' + GROUP BY AL.DATUM, SIFRAPOSLOVNICE + + union all + + SELECT + pp.datum, + SIFRAPOSLOVNICE, + cast('Popravke' as varchar(30)), + cast(sum(iznos) as numeric(18,2)) + FROM popravka pp + GROUP BY pp.DATUM, SIFRAPOSLOVNICE + + union all + + SELECT + rg.datum, + SIFRAPOSLOVNICE, + cast('Registracije' as varchar(30)), + cast(sum(cenatehnickog + cenaosiguranja+ostalitroskovi) as numeric(18,2)) + FROM registracija rg + GROUP BY rg.DATUM, SIFRAPOSLOVNICE + + union all + + SELECT + sg.datum, + SIFRAPOSLOVNICE, + cast('Gorivo' as varchar(30)), + cast(sum(kolicina * cena) as numeric(18,2)) + FROM sipanjegoriva sg + GROUP BY + sg.DATUM, SIFRAPOSLOVNICE + ; + + + CREATE VIEW VV(VRSTA) AS + select distinct vrsta from apromet a; + commit; + + + SELECT vv.VRSTA, + (select sum(ap.iznos) + from apromet ap where ap.vrsta = + vv.vrsta + and + extract(month from ap.datum)=1), + (select + sum(ap.iznos) from apromet ap where ap.vrsta = + vv.vrsta + and + extract(month from ap.datum)=2), + (select + sum(ap.iznos) from apromet ap where ap.vrsta = + vv.vrsta + and + extract(month from ap.datum)=3), + (select + sum(ap.iznos) from apromet ap where ap.vrsta = + vv.vrsta + and + extract(month from ap.datum)=4), + (select + sum(ap.iznos) from apromet ap where ap.vrsta = + vv.vrsta + and + extract(month from ap.datum)=5), + (select + sum(ap.iznos) from apromet ap where ap.vrsta = + vv.vrsta + and + extract(month from ap.datum)=6), + (select + sum(ap.iznos) from apromet ap where ap.vrsta = + vv.vrsta + and + extract(month from ap.datum)=7), + (select + sum(ap.iznos) from apromet ap where ap.vrsta = + vv.vrsta + and + extract(month from ap.datum)=8), + (select + sum(ap.iznos) from apromet ap where ap.vrsta = + vv.vrsta + and + extract(month from ap.datum)=9), + (select + sum(ap.iznos) from apromet ap where ap.vrsta = + vv.vrsta + and + extract(month from ap.datum)=10), + (select + sum(ap.iznos) from apromet ap where ap.vrsta = + vv.vrsta + and + extract(month from ap.datum)=11), + (select + sum(ap.iznos) from apromet ap where ap.vrsta = + vv.vrsta + and + extract(month from ap.datum)=12), + (select + sum(ap.iznos) from apromet ap where ap.vrsta + = + vv.vrsta) + FROM vv; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +def test_core_0366_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_0389.py b/tests/bugs/test_core_0389.py new file mode 100644 index 00000000..b32d25e0 --- /dev/null +++ b/tests/bugs/test_core_0389.py @@ -0,0 +1,110 @@ +#coding:utf-8 +# +# id: bugs.core_0389 +# title: NULLS FIRST does not work with unions +# decription: +# tracker_id: CORE-389 +# min_versions: ['2.0.7'] +# versions: 2.0.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.7 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """ + create table t(x int); + insert into t values(2222); + insert into t values(222 ); + insert into t values(22); + insert into t values(2); + insert into t values(null); + insert into t values(null); + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + select distinct x + from t + + union all + + select distinct x + from t + + order by 1 nulls first + ; + -------------------------- + select distinct x + from t + + union all + + select distinct x + from t + + order by 1 desc nulls first + ; + -------------------------- + select x + from t + + union + + select x + from t + + order by 1 nulls first + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + X + ============ + + + 2 + 2 + 22 + 22 + 222 + 222 + 2222 + 2222 + + + X + ============ + + + 2222 + 2222 + 222 + 222 + 22 + 22 + 2 + 2 + + X + ============ + + 2 + 22 + 222 + 2222 + """ + +@pytest.mark.version('>=2.0.7') +def test_core_0389_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0405.py b/tests/bugs/test_core_0405.py new file mode 100644 index 00000000..311969dd --- /dev/null +++ b/tests/bugs/test_core_0405.py @@ -0,0 +1,96 @@ +#coding:utf-8 +# +# id: bugs.core_0405 +# title: Garbage vs indices/constraints +# decription: +# Confirmed bug on 3.0.4.32924, got: +# DatabaseError: +# Error while commiting transaction: +# - SQLCODE: -803 +# - attempt to store duplicate value (visible to active transactions) in unique index "TEST_X" +# -803 +# 335544349 +# ---------------------------------------------------- +# :: NB :: +# No error on Firebird 4.0 (any: SS,SC, CS). +# Works OK on: 4.0.0.838 +# +# tracker_id: CORE-0405 +# min_versions: ['3.0.4'] +# versions: 3.0.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import fdb +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# con=fdb.connect( dsn=dsn, no_gc=1 ) +# #print( con.firebird_version ) +# +# con.execute_immediate('recreate table test(x int)') +# con.commit() +# cur=con.cursor() +# +# stm='insert into test( x ) values( ? )' +# val = [ (2,), (3,), (3,), (2,) ] +# cur.executemany( stm, val ) +# +# cur.execute('select x from test order by x') +# for r in cur: +# print(r[0]) +# +# cur.execute('delete from test') +# +# cur.execute('select count(*) from test') +# for r in cur: +# print(r[0]) +# +# con.execute_immediate('create unique index test_x on test(x)') +# con.commit() +# +# +# cur.execute("select rdb$index_name from rdb$indices where rdb$relation_name='TEST'") +# for r in cur: +# print( r[0].rstrip() ) +# +# con.close() +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 2 + 2 + 3 + 3 + 0 + TEST_X + """ + +@pytest.mark.version('>=3.0.4') +@pytest.mark.xfail +def test_core_0405_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_0461.py b/tests/bugs/test_core_0461.py new file mode 100644 index 00000000..d9b8fb36 --- /dev/null +++ b/tests/bugs/test_core_0461.py @@ -0,0 +1,541 @@ +#coding:utf-8 +# +# id: bugs.core_0461 +# title: JOIN including a complex view kills the server +# decription: +# NB: all versions of 2.1 and 2.5 fail on 2nd query (issue 2002-jul-12) with message about +# "too many contexts, max = 256" so this test checks only FB 3.0 and above. +# +# tracker_id: CORE-0461 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + + create domain d_global_id as varchar(15) not null ; + create domain d_long_desc as varchar(200); + create domain d_group as integer default 0 check ((value is not null)); + + create domain d_global_ref as varchar(15); + create domain d_icon as smallint check (((value is null) or (value between 0 and 8))); + + recreate table knowledgestreams ( + stream_id d_global_id not null, + name d_long_desc, + content_groups d_group, + constraint pk_knowledgestreams primary key (stream_id) + ); + + recreate table mainmenu ( + menu_id d_global_id not null, + parent_id d_global_ref, + description d_long_desc, + content_group d_group not null, + icon d_icon, + constraint pk_mainmenu primary key (menu_id) + ); + + alter table mainmenu add constraint fk_mainmenu foreign key (parent_id) + references mainmenu(menu_id) on delete cascade on update cascade; + + recreate table menu_groups ( + menu_id d_global_id not null, + content_id d_global_id not null + ); + + create index menu_groups_idx1 on menu_groups (menu_id); + create index menu_groups_idx2 on menu_groups (content_id); + + recreate table streammenu ( + stream_id d_global_id not null, + parent d_global_id not null, + constraint pk_streammenu primary key (parent, stream_id) + ); + + alter table streammenu add constraint fk_streammenu_parent foreign key + (parent) references mainmenu(menu_id) on delete cascade; + + alter table streammenu add constraint fk_streammenu_stream_id foreign + key (stream_id) references knowledgestreams(stream_id) on delete + cascade; + + create view fullmenu ( + code, + parent, + description, + link, + content_group + ) as + select menu_id,parent_id,description,cast(null as + varchar(100)),content_group from mainmenu + union all + select m.stream_id, m.parent, s.name + ,cast('/servlets/uk.co.wmeng.intelus.knowledgestream?action=display&id=' + || s.stream_id as varchar(100)),content_groups from streammenu m join + knowledgestreams s on s.stream_id = m.stream_id + ; + + ------------------------------------------------- + + create table drzava + ( + pozivnibrojdrzave varchar(4) not null, + nazivdrzave varchar(20), + grupa integer not null, + primary key (pozivnibrojdrzave) + ); + + create table log + ( + broj varchar(25) not null, + pocetak timestamp not null, + trajanje integer not null, + lokal integer, + linija integer, + cena numeric(8,2) not null + ); + + create table lokal + ( + brojlokala integer not null, + nazivlokala varchar(25) not null, + primary key (brojlokala) + ); + + create table mesni + ( + ptt char(5) not null, + lokalniprefix varchar(5) not null, + primary key (ptt, lokalniprefix) + ); + + create table mreza + ( + brojmreze varchar(4) not null, + pozivnibroj varchar(4) not null, + zona integer not null, + primary key (brojmreze, pozivnibroj) + ); + + create table vrstart + ( + sifravrt char(7) not null, + nazivvrt varchar(30) not null, + jm varchar(6), + primary key (sifravrt) + ); + + create table poslovnica + ( + sifraposlovnice char(2) not null, + nazivposlovnice varchar(18) not null, + primary key (sifraposlovnice) + ); + + create table rezijskitrosak + ( + rednibroj integer not null, + datumtroska timestamp not null, + sifraposlovnice char(2) not null references + poslovnica (sifraposlovnice) on update cascade, + sifravrt char(7) not null references vrstart + (sifravrt) on update cascade, + kolicina decimal(8,2), + iznos decimal(8,2) not null, + primary key (rednibroj) + ); + + create generator gen_rt_id; + set generator gen_rt_id to 0; + + create table vrstamt + ( + sifravmt char(7) not null, + nazivvmt varchar(30) not null, + defaultjm varchar(6), + primary key (sifravmt) + ); + + create table roba + ( + sifrarobe char(6) not null, + vrstarobe char(7) not null references vrstamt + (sifravmt) on update cascade, + nazivrobe varchar(30) not null, + jm varchar(6) not null, + barcode varchar(50), + pakovanje integer, + napomena varchar(100), + primary key (sifrarobe) + ); + + create table mesto + ( + ptt char(5) not null, + nazivmesta varchar(40) not null, + pozivnibroj char(4), + primary key (ptt) + ); + + create table komitent + ( + sifrakomitenta integer not null, + naziv varchar(25) not null , + ptt char(5) not null references mesto + (ptt) on update cascade, + napomena varchar(100), + owner char(8), + primary key (sifrakomitenta) + ); + + create generator gen_komitent_id; + set generator gen_komitent_id to 0; + + create table vrstadetalja + ( + sifravd integer not null, + opisvd varchar(15), + telefon char(1), + check (telefon is null or telefon = 'd' or telefon = 'z'), + primary key(sifravd) + ); + + create generator gen_vrstadetalja_id; + set generator gen_vrstadetalja_id to 0; + + create table komitentdetaljno + ( + sifrakd integer not null, + sifrakomitenta integer not null references komitent + (sifrakomitenta) on update cascade on delete + cascade, + sifravd integer not null references + vrstadetalja (sifravd) on update cascade, + podatak varchar(40) not null, + cistbroj varchar(25), + primary key(sifrakd) + ); + + create generator gen_komitentdetaljno_id; + set generator gen_komitentdetaljno_id to 0; + + create table prijem + ( + brdok integer not null, + datumulaza timestamp not null, + sifrakomitenta integer references komitent + (sifrakomitenta) on update cascade, + primary key (brdok) + ); + + create generator gen_prij_id; + set generator gen_prij_id to 0; + + create table prijemst + ( + brdok integer not null references prijem + (brdok) on update cascade on delete cascade, + sifrarobe char(6) not null references roba + (sifrarobe) on update cascade, + kolicina decimal(8,2) not null, + cena decimal(8,2) not null, + primary key (brdok, sifrarobe) + ); + + create table alokacija + ( + brdok integer not null, + datum timestamp not null, + sifraposlovnice char(2) not null references poslovnica + (sifraposlovnice) on update cascade, + primary key (brdok) + ); + + create generator gen_alok_id; + set generator gen_alok_id to 1; + + create table alokacijast + ( + brdok integer not null references alokacija + (brdok) on update cascade on delete cascade, + sifrarobe char(6) not null references roba + (sifrarobe) on update cascade, + kolicina decimal(8,2) not null, + cena decimal(8,2) not null, + primary key (brdok, sifrarobe) + ); + + create table vrstagoriva + ( + sifravrstegoriva integer not null, + nazivvrstegoriva varchar(10) not null, + primary key (sifravrstegoriva) + ); + + + create table vrstavozila + ( + sifravrste char(2) not null, + nazivvrste varchar(18) not null, + primary key (sifravrste) + ); + + create table vozilo + ( + sifravozila char(12) not null, + sifravrste char(2) not null references + vrstavozila (sifravrste) on update cascade, + regbroj char(10), + marka char(10), + tip char(20), + brojsasije char(25), + brojmotora char(25), + prvaregistracija timestamp, + snagamotora decimal(10,2), + zapremina integer, + nosivost integer, + mestazasedenje char(4), + karoserija char(25), + boja char(20), + brojosovina char(1), + rokppaparata timestamp, + + primary key (sifravozila) + ); + + create table vozac + ( + sifravozaca integer not null, + ime char(25) not null, + kategorije char(5) not null, + datumvazenjadozvole timestamp, + + primary key (sifravozaca) + ); + + + create table sipanjegoriva + ( + sifrasg integer not null, + datum timestamp not null, + sifravozila char(12) not null references vozilo + (sifravozila) on update cascade, + sifravozaca integer not null references vozac + (sifravozaca) on update cascade, + sifravrstegoriva integer not null references + vrstagoriva (sifravrstegoriva) on update cascade, + sifraposlovnice char(2) not null references + poslovnica (sifraposlovnice) on update cascade, + kmsat decimal(9,1), + kolicina decimal(10, 2) not null, + cena decimal(8,2) not null, + pundocepa char(1), + check (pundocepa = 'n' or pundocepa = 'd'), + + primary key (sifrasg) + ); + + create generator gen_gorivo_id; + set generator gen_gorivo_id to 1; + + create table popravka + ( + datum timestamp not null, + sifravozila char(12) not null references vozilo + (sifravozila) on update cascade, + sifravozaca integer not null references vozac + (sifravozaca) on update cascade, + sifraposlovnice char(2) not null references + poslovnica (sifraposlovnice) on update cascade, + iznos decimal(12,2) not null, + opis varchar(200), + + primary key (datum,sifravozila) + ); + + + create table registracija + ( + datum timestamp not null, + sifravozila char(12) not null references vozilo + (sifravozila) on update cascade, + cenatehnickog decimal(12,2), + cenaosiguranja decimal(12,2), + ostalitroskovi decimal(12,2), + sifraposlovnice char(2) not null references + poslovnica (sifraposlovnice) on update cascade, + + primary key (datum,sifravozila) + ); + + create table dummy + ( + foobar integer not null primary key, + check (foobar = 1) + ); + + insert into dummy values (1); + + + /* then, i create few views to make summary report */ + + create view apromet(datum, so, vrsta, iznos) + as + + select rt.datumtroska, sifraposlovnice, cast + (vrt.nazivvrt as varchar + (30)), cast (rt.iznos as numeric(18, 2)) + from rezijskitrosak rt + left join vrstart vrt on rt.sifravrt = vrt.sifravrt + + union all + + select al.datum, sifraposlovnice, cast ('kancmat' + as varchar(30)), + cast(sum(alst.kolicina * alst.cena) as numeric(18, 2)) + from alokacijast alst + left join alokacija al on alst.brdok=al.brdok + left join roba r on alst.sifrarobe = r.sifrarobe + where r.vrstarobe = 'km' + group by al.datum, sifraposlovnice + + union all + + select al.datum, sifraposlovnice, cast ('hemikalije' + as varchar(30)), + cast(sum(alst.kolicina * alst.cena) as numeric(18, 2)) + from alokacijast alst + left join alokacija al on alst.brdok=al.brdok + left join roba r on alst.sifrarobe = r.sifrarobe + where r.vrstarobe = 'he' + group by al.datum, sifraposlovnice + + union all + + select al.datum, sifraposlovnice, cast ('prehrana' + as varchar(30)), + cast(sum(alst.kolicina * alst.cena) as numeric(18, 2)) + from alokacijast alst + left join alokacija al on alst.brdok=al.brdok + left join roba r on alst.sifrarobe = r.sifrarobe + where r.vrstarobe = 'hr' + group by al.datum, sifraposlovnice + union all + + select pp.datum, sifraposlovnice, cast ('popravke' + as varchar(30)), + cast(sum(iznos) as numeric(18,2)) + from popravka pp + group by pp.datum, sifraposlovnice + + union all + + select rg.datum, sifraposlovnice, cast ('registracije' + as varchar + (30)), cast(sum(cenatehnickog + cenaosiguranja + + ostalitroskovi) as + numeric(18,2)) + from registracija rg + group by rg.datum, sifraposlovnice + + union all + + select sg.datum, sifraposlovnice, cast ('gorivo' as + varchar(30)), cast + (sum(kolicina * cena) as numeric(18,2)) + from sipanjegoriva sg + group by sg.datum, sifraposlovnice + ; + + + create view vv(vrsta) + as + select distinct vrsta + from apromet a + ; + + ------------------------------------------------- + + set list on; + + select distinct fm.code, fm.description, fm.link + from fullmenu fm + join menu_groups mg on fm.code = mg.menu_id + ; + + select 'Query from issue 2000-oct-18 passed OK' as msg from rdb$database; + + ------------------------------------------------- + + select + vv.vrsta, + (select sum(ap.iznos) from apromet ap where ap.vrsta = + vv.vrsta and + extract(month from ap.datum)=1), + (select sum(ap.iznos) from apromet ap where ap.vrsta = + vv.vrsta and + extract(month from ap.datum)=2), + (select sum(ap.iznos) from apromet ap where ap.vrsta = + vv.vrsta and + extract(month from ap.datum)=3), + (select sum(ap.iznos) from apromet ap where ap.vrsta = + vv.vrsta and + extract(month from ap.datum)=4), + (select sum(ap.iznos) from apromet ap where ap.vrsta = + vv.vrsta and + extract(month from ap.datum)=5), + (select sum(ap.iznos) from apromet ap where ap.vrsta = + vv.vrsta and + extract(month from ap.datum)=6), + (select sum(ap.iznos) from apromet ap where ap.vrsta = + vv.vrsta and + extract(month from ap.datum)=7), + (select sum(ap.iznos) from apromet ap where ap.vrsta = + vv.vrsta and + extract(month from ap.datum)=8), + (select sum(ap.iznos) from apromet ap where ap.vrsta = + vv.vrsta and + extract(month from ap.datum)=9), + (select sum(ap.iznos) from apromet ap where ap.vrsta = + vv.vrsta and + extract(month from ap.datum)=10), + (select sum(ap.iznos) from apromet ap where ap.vrsta = + vv.vrsta and + extract(month from ap.datum)=11), + (select sum(ap.iznos) from apromet ap where ap.vrsta = + vv.vrsta and + extract(month from ap.datum)=12), + (select sum(ap.iznos) from apromet ap where ap.vrsta = vv.vrsta) + from vv + ; + + select 'Query from issue 2002-jul-12 passed OK' as msg from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG Query from issue 2000-oct-18 passed OK + MSG Query from issue 2002-jul-12 passed OK + """ + +@pytest.mark.version('>=3.0') +def test_core_0461_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0474.py b/tests/bugs/test_core_0474.py new file mode 100644 index 00000000..1aca3bb0 --- /dev/null +++ b/tests/bugs/test_core_0474.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: bugs.core_0474 +# title: Redundant evaluations in COALESCE +# decription: +# Proper result - only since 2.5.0 :-) +# On WI-V2.1.7.18553 Firebird 2.1 result still wrong (curr_gen 4) +# +# tracker_id: CORE-0474 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create generator g1; + commit; + set list on; + select + coalesce( + nullif(gen_id(g1,1),1), + nullif(gen_id(g1,1),2), + gen_id(g1,1), + nullif(gen_id(g1,1),4), + gen_id(g1,1) + ) + as curr_gen + from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CURR_GEN 3 + """ + +@pytest.mark.version('>=2.5') +def test_core_0474_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0475.py b/tests/bugs/test_core_0475.py new file mode 100644 index 00000000..87148c6f --- /dev/null +++ b/tests/bugs/test_core_0475.py @@ -0,0 +1,140 @@ +#coding:utf-8 +# +# id: bugs.core_0475 +# title: ORDER BY has no effect +# decription: +# tracker_id: CORE-0475 +# min_versions: ['2.5.6'] +# versions: 2.5.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter procedure getChilds as begin end; + recreate table test ( + code integer not null primary key using index test_pk, + name varchar(2) not null unique, + parent integer, + foreign key (parent) references test(code) using index test_fk + ); + + set term ^; + create or alter procedure getChilds(par integer) returns (code integer,children integer) as + begin + for + select + m.code, Min(c.code) from + test m + left join test c on m.code = c.parent + where m.parent = :par or (m.parent is null and :par is null) + group by m.code + into :code,:children + do + suspend; + end + ^ + set term ;^ + commit; + + insert into test values (0,'A',null); + insert into test values (1,'AA',0); + insert into test values (3,'AB',0); + insert into test values (4,'AC',0); + insert into test values (2,'AD',0); + insert into test values (5,'B',null); + insert into test values (6,'BA',5); + insert into test values (7,'BB',5); + insert into test values (8,'BC',5); + insert into test values (9,'BD',5); + insert into test values (10,'BE',5); + insert into test values (11,'BF',5); + + set list on; + + select * + from getChilds(0) + inner join test + on getChilds.code = test.code + order by name + ; + + + select * + from getChilds(0) + inner join test + on getChilds.code = test.code + order by name desc + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CODE 1 + CHILDREN + CODE 1 + NAME AA + PARENT 0 + + CODE 3 + CHILDREN + CODE 3 + NAME AB + PARENT 0 + + CODE 4 + CHILDREN + CODE 4 + NAME AC + PARENT 0 + + CODE 2 + CHILDREN + CODE 2 + NAME AD + PARENT 0 + + + + CODE 2 + CHILDREN + CODE 2 + NAME AD + PARENT 0 + + CODE 4 + CHILDREN + CODE 4 + NAME AC + PARENT 0 + + CODE 3 + CHILDREN + CODE 3 + NAME AB + PARENT 0 + + CODE 1 + CHILDREN + CODE 1 + NAME AA + PARENT 0 + """ + +@pytest.mark.version('>=2.5.6') +def test_core_0475_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0479.py b/tests/bugs/test_core_0479.py new file mode 100644 index 00000000..c0c98471 --- /dev/null +++ b/tests/bugs/test_core_0479.py @@ -0,0 +1,294 @@ +#coding:utf-8 +# +# id: bugs.core_0479 +# title: Grants overwrite previous rdb$security_classes entries +# decription: +# Test attempts to create all kinds of objects () that can be 'target' for GRANT ON statement. +# Length of each object is equal to implementation maximum for 2.5.x, 3.0.x and 4.0. +# Pairs of objects differ only in last character. +# After all, we check that no dupicates are created in rdb$security_classes table for field rdb$security_class. +# NOTE-1: for 3.0.x and 4.0 we create objects as quoted, in UTF8, - for additional checking that we have no problem with non-ascii characters. +# NOTE-2: max length in 4.0 is 63 utf8 CHARACTERS (not bytes). +# Checked on WI-V2.5.7.27027, WI-V3.0.2.32630, WI-T4.0.0.454. +# +# tracker_id: CORE-0479 +# min_versions: ['2.5.0'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + create or alter view v_check as + select sc.rdb$security_class, r.obj_type, min(r.obj_name) as obj_1, max(r.obj_name) as obj_2 + from rdb$security_classes sc + left join + ( + + select r.rdb$relation_name as obj_name, r.rdb$security_class as sec_class, 'table/view' as obj_type + from rdb$relations r + + union all + + select p.rdb$procedure_name, p.rdb$security_class, 'stored proc' + from rdb$procedures p + + union all + + select p.rdb$function_name, p.rdb$security_class, 'stored func' + from rdb$functions p + + union all + + select p.rdb$package_name, p.rdb$security_class, 'package' + from rdb$packages p + + union all + + select r.rdb$role_name as obj_name, r.rdb$security_class as sec_class, 'role' as obj_type + from rdb$roles r + + ) r on sc.rdb$security_class = r.sec_class + group by 1,2 + having count(*) > 1 + ; + ----------------------------------------------------------------- + -- tÁÃÀÅĂÂÄĀČĒĻŅŠŪŽĪáéíóúýàèìòùâêŹ + -- tÁÃÀÅĂÂÄĀČĒĻŅŠŪŽĪáéíóúýàèìòùâêŻ + + recreate table + "tÁÃÀÅĂÂÄĀČĒĻŅŠŪŽ" + (x int) + ; + + recreate table + "TÁÃÀÅĂÂÄĀČĒĻŅŠŪŽ" + (x int) + ; + ----------------------------------------------------------------- + create view + "vÁÃÀÅĂÂÄĀČĒĻŅŠŪŽ" + as select * from + "tÁÃÀÅĂÂÄĀČĒĻŅŠŪŽ" + ; + + create view + "VÁÃÀÅĂÂÄĀČĒĻŅŠŪŽ" + as select * from + "TÁÃÀÅĂÂÄĀČĒĻŅŠŪŽ" + ; + ----------------------------------------------------------------- + + create procedure + "pÁÃÀÅĂÂÄĀČĒĻŅŠŪŽ" + as begin + end; + + create procedure + "PÁÃÀÅĂÂÄĀČĒĻŅŠŪŽ" + as begin + end; + ----------------------------------------------------------------- + + set term ^; + create function + "fÁÃÀÅĂÂÄĀČĒĻŅŠŪŽ" + returns int + as begin + return 1; + end + ^ + create function + "FÁÃÀÅĂÂÄĀČĒĻŅŠŪŽ" + returns int + as begin + return 1; + end + ^ + ----------------------------------------------------------------- + + create package + "gÁÃÀÅĂÂÄĀČĒĻŅŠŪŽ" + as begin end + ^ + create package + "GÁÃÀÅĂÂÄĀČĒĻŅŠŪŽ" + as begin end + ^ + set term ;^ + ----------------------------------------------------------------- + + create role + "rÁÃÀÅĂÂÄĀČĒĻŅŠŪŽ" + ; + + create role + "RÁÃÀÅĂÂÄĀČĒĻŅŠŪŽ" + ; + + commit; + + SET LIST ON; + SET COUNT ON; + + select * from v_check; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_core_0479_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set bail on; + create or alter view v_check as + select sc.rdb$security_class, r.obj_type, min(r.obj_name) as obj_1, max(r.obj_name) as obj_2 + from rdb$security_classes sc + left join + ( + + select r.rdb$relation_name as obj_name, r.rdb$security_class as sec_class, 'table/view' as obj_type + from rdb$relations r + + union all + + select p.rdb$procedure_name, p.rdb$security_class, 'stored proc' + from rdb$procedures p + + union all + + select p.rdb$function_name, p.rdb$security_class, 'stored func' + from rdb$functions p + + union all + + select p.rdb$package_name, p.rdb$security_class, 'package' + from rdb$packages p + + union all + + select r.rdb$role_name as obj_name, r.rdb$security_class as sec_class, 'role' as obj_type + from rdb$roles r + + ) r on sc.rdb$security_class = r.sec_class + group by 1,2 + having count(*) > 1 + ; + ----------------------------------------------------------------- + recreate table + "tÁÃÀÅĂÂÄĀČĒĻŅŠŪŽĪáéíóúýàèìòùâêîôûãñõäëïöüÿçšδθλξσψωąęłźżњћџăşţŹ" + (x int) + ; + + recreate table + "tÁÃÀÅĂÂÄĀČĒĻŅŠŪŽĪáéíóúýàèìòùâêîôûãñõäëïöüÿçšδθλξσψωąęłźżњћџăşţŻ" + (x int) + ; + ----------------------------------------------------------------- + recreate view + "vÁÃÀÅĂÂÄĀČĒĻŅŠŪŽĪáéíóúýàèìòùâêîôûãñõäëïöüÿçšδθλξσψωąęłźżњћџăşţŹ" + as select * from + "tÁÃÀÅĂÂÄĀČĒĻŅŠŪŽĪáéíóúýàèìòùâêîôûãñõäëïöüÿçšδθλξσψωąęłźżњћџăşţŹ" + ; + + recreate view + "vÁÃÀÅĂÂÄĀČĒĻŅŠŪŽĪáéíóúýàèìòùâêîôûãñõäëïöüÿçšδθλξσψωąęłźżњћџăşţŻ" + as select * from + "tÁÃÀÅĂÂÄĀČĒĻŅŠŪŽĪáéíóúýàèìòùâêîôûãñõäëïöüÿçšδθλξσψωąęłźżњћџăşţŻ" + ; + ----------------------------------------------------------------- + + create procedure + "pÁÃÀÅĂÂÄĀČĒĻŅŠŪŽĪáéíóúýàèìòùâêîôûãñõäëïöüÿçšδθλξσψωąęłźżњћџăşţŹ" + as begin + end; + + create procedure + "pÁÃÀÅĂÂÄĀČĒĻŅŠŪŽĪáéíóúýàèìòùâêîôûãñõäëïöüÿçšδθλξσψωąęłźżњћџăşţŻ" + as begin + end; + ----------------------------------------------------------------- + + set term ^; + create function + "fÁÃÀÅĂÂÄĀČĒĻŅŠŪŽĪáéíóúýàèìòùâêîôûãñõäëïöüÿçšδθλξσψωąęłźżњћџăşţŹ" + returns int + as begin + return 1; + end + ^ + create function + "fÁÃÀÅĂÂÄĀČĒĻŅŠŪŽĪáéíóúýàèìòùâêîôûãñõäëïöüÿçšδθλξσψωąęłźżњћџăşţŻ" + returns int + as begin + return 1; + end + ^ + ----------------------------------------------------------------- + + create package + "gÁÃÀÅĂÂÄĀČĒĻŅŠŪŽĪáéíóúýàèìòùâêîôûãñõäëïöüÿçšδθλξσψωąęłźżњћџăşţŹ" + as begin end + ^ + create package + "gÁÃÀÅĂÂÄĀČĒĻŅŠŪŽĪáéíóúýàèìòùâêîôûãñõäëïöüÿçšδθλξσψωąęłźżњћџăşţŻ" + as begin end + ^ + set term ;^ + ----------------------------------------------------------------- + + create role + "rÁÃÀÅĂÂÄĀČĒĻŅŠŪŽĪáéíóúýàèìòùâêîôûãñõäëïöüÿçšδθλξσψωąęłźżњћџăşţŹ" + ; + + create role + "rÁÃÀÅĂÂÄĀČĒĻŅŠŪŽĪáéíóúýàèìòùâêîôûãñõäëïöüÿçšδθλξσψωąęłźżњћџăşţŻ" + ; + + commit; + + SET LIST ON; + SET COUNT ON; + + select * from v_check; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + Records affected: 0 + """ + +@pytest.mark.version('>=4.0') +def test_core_0479_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/bugs/test_core_0480.py b/tests/bugs/test_core_0480.py new file mode 100644 index 00000000..3cd883c0 --- /dev/null +++ b/tests/bugs/test_core_0480.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: bugs.core_0480 +# title: Foreign key relation VARCHAR <-> INT +# decription: +# tracker_id: CORE-480 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_480-21 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table T1 (PK1 INTEGER, COL VARCHAR(10)); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """create table T2 (PK2 INTEGER, FK1 VARCHAR(10), COL VARCHAR(10), +foreign key (FK1) references T1 (PK1)); + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """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_core_0480_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_0501.py b/tests/bugs/test_core_0501.py new file mode 100644 index 00000000..d2bf14e2 --- /dev/null +++ b/tests/bugs/test_core_0501.py @@ -0,0 +1,1052 @@ +#coding:utf-8 +# +# id: bugs.core_0501 +# title: Lot of syntax tests for COALESCE() +# decription: +# It tests many problems Adriano found when fixing CORE-501, CORE-1343 and CORE-2041. +# +# 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. +# +# tracker_id: CORE-501 +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + create sequence s1; + + create table t1 ( + n integer primary key, + x integer, + cn computed by (coalesce(n + 0, null)), + cx computed by (coalesce(x + 0, null)) + ); + + -- test update or insert + update or insert into t1 values (next value for s1, 10); + update or insert into t1 values (next value for s1, 20); + update or insert into t1 values (next value for s1, 30); + + --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + -- test update or insert using coalesce + update or insert into t1 + values (coalesce((select first 1 n from t1 order by n), null), coalesce(40 + 60, 0)); + + select 'point-01' as msg, t.* + from t1 t; + + --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + -- test update or insert in PSQL + set term ^ ; + execute block returns (msg varchar(30), n integer, x integer, cn integer, cx integer) as + declare z integer = 200; + begin + update or insert into t1 + values (coalesce((select first 1 skip 1 n from t1 order by n), null), :z); + + msg = 'point-02'; + for + select n, x, cn, cx + from t1 + into n, x, cn, cx + do + suspend; + end + ^ + set term ;^ + + --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + -- test view + create view v1 as + select + n -- integer primary key + ,x -- integer + ,cn --computed by (coalesce(n + 0, null)) + ,cx -- computed by (coalesce(x + 0, null)) + ,coalesce(n + 0, null) as vcn + from t1; + + select 'point-03' as msg, v.* + from v1 v; + + --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + -- test update or insert into a view + update or insert into v1(n,x) values (next value for s1, 40); + + select 'point-04' as msg, v.* + from v1 v; + + --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + -- test update or insert into a view in PSQL + set term ^ ; + execute block returns (msg varchar(30), n integer, x integer, cn integer, cx integer) as + declare z integer = 300; + begin + update or insert into v1(n, x) values ( (select first 1 skip 2 n from t1 order by n), :z ); + + msg = 'point-05'; + for + select n, x, cn, cx + from v1 + into n, x, cn, cx + do + suspend; + end + ^ + + --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + -- test view trigger + create trigger v1_bi before insert on v1 as + declare z integer = 1000; + begin + insert into t1(n, x) values (coalesce(new.n + :z, null), new.x); + end + ^ + set term ;^ + + insert into v1(n, x) values (8, 88); + + select 'point-06' as msg, v.* from v1 v; + + --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + -- several tests of COALESCE: + select 'point-07' as msg, coalesce(n * 1, null) coal_01 from v1; + select 'point-08' as msg, coalesce(n * 1, null) coal_02 from t1 group by coalesce(n * 1, null); + select 'point-09' as msg, v.* from (select coalesce(n * 1, null) coal_03 from v1 group by coalesce(n * 1, null) ) v; + select 'point-10' as msg, v.* from (select coalesce(n * 1, null) coal_04 from v1 group by 1) v; + select 'point-11' as msg, v.* from (select coalesce(n * 1, null) coal_05 from v1 group by 1 having coalesce(n * 1, null) < 100) v; + select 'point-12' as msg, v.* from (select coalesce(n * 10, null) coal_06 from v1 order by 1) v; + select 'point-13' as msg, v.* from (select coalesce(n * 10, null) coal_07a, coalesce(x * 10, null) coal_07b from v1 order by 2 desc, 1 desc) v; + select 'point-14' as msg, v.* from (select coalesce(n * 10, null) coal_08a, coalesce(x * 10, null) coal_08b from v1 order by 1 desc, 2 desc) v; + + --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + -- test 'case when ... then ... else ... end' + select + 'point-15' as msg + ,v.* + from ( + select case n * 1 when 1 then n * 1 else n + 0 end case_group_by_01 + from v1 + group by case n * 1 when 1 then n * 1 else n + 0 end + ) v; + + select + 'point-16' as msg + ,v.* + from ( + select case n * 1 when 1 then n * 1 else n + 0 end case_group_by_02 + from v1 group by 1 + ) v; + + select + 'point-17' as msg + ,v.* + from ( + select case n * 1 when 1 then n * 1 else n + 0 end case_group_by_03 + from v1 + group by 1 + having case n * 1 when 1 then n * 1 else n + 0 end < 100 + ) v; + + select + 'point-18' as msg + ,v.* + from ( + select case n * 1 when 1 then n * 1 else n + 0 end case_group_by_04 + from v1 + order by 1 desc + ) v; + + --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + -- test non-valid statements (they must raise SQLSTATE = 42000 / -Invalid expression in the HAVING clause): + + select + 'point-19' as msg + ,v.* + from ( + select coalesce(n * 1, null) non_valid_01 + from v1 + group by 1 having coalesce(n * 0, null) < 100 + ) v; + + select + 'point-20' as msg + ,v.* + from ( + select case n * 1 when 1 then n * 1 else n + 0 end non_valid_02 + from v1 + group by case n * 1 when 1 then n * 1 else n + 1 end + ) v; + + select + 'point-21' as msg + ,v.* + from ( + select case n * 1 when 1 then n * 1 else n + 0 end non_valid_03 + from v1 + group by 1 + having case n * 1 when 1 then n * 1 else n + 1 end < 100 + ) v; + + --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + set term ^ ; + create procedure p1 returns (n integer) as + begin + -- This expression is VALID, no error should be here: + for + select coalesce(n * 1, null) + from t1 + group by coalesce(n * 1, null) + into n + do + suspend; + end + ^ + set term ; ^ + commit; + + select 'point-22' as msg, p.* from p1 p; + + -- set blob all; + -- select rdb$procedure_blr from rdb$procedures where rdb$procedure_name = 'P1'; + + --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + -- test coalesce in view condition + + create view v2 as + select + t1.n as v2_n + ,coalesce(n + 1, null) as v2_x1 + ,coalesce(n + 2, null) as v2_x2 + from t1 + where coalesce(0 + 0, null) = coalesce(0 + 0, null); + + select 'point-23' as msg, v.* from v2 v; + + --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + -- test coalesce in view using distinct + create view v3 as + select distinct + t1.n v3_n, + coalesce(n + 1, null) + coalesce(n + 11, null) v3_x1, + coalesce(n + 2, null) + coalesce(n + 22, null) v3_x2 + from t1; + + select 'point-24' as msg, v.* from v3 v; + + --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + -- test coalesce with subselect with coalesce in view + create view v4 as + select + t1.n v4_n, + coalesce((select coalesce(0 + 1, null) from rdb$database), null) v4_x1, + coalesce((select coalesce(2 + 1, null) from rdb$database), null) v4_x2 + from t1; + + select 'point-25' as msg, v.* from v4 v; + + --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + -- test coalesce in view using union + create view v5 (n, x1, x2) as + select + t1.n v5_n, + coalesce(n + 1, null) + coalesce(n + 11, null) v5_x1, + coalesce(n + 2, null) + coalesce(n + 22, null) v5_x2 + from t1 + + union all + + select + t1.n, + coalesce(n + 1, null) + coalesce(n + 11, null), + coalesce(n + 2, null) + coalesce(n + 22, null) + from t1; + + select 'point-26' as msg, v.* from v5 v; + + --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + -- test constraints on table COLUMNS: + alter table t1 + add constraint t1_n check (coalesce(n + 0, null) < 10), + add constraint t1_cx check (coalesce(cx + 0, null) < 10); + + insert into t1(n,x) values (5, 5); + insert into t1(n,x) values (50, 5); -- violates TABLE COLUMN constraint 't1_n': value of 'n' must be < 10; SQLSTATE = 23000 + insert into t1(n,x) values (5, 50); -- violates TABLE COLUMN constraint 't1_cx': value of 'cx' must be < 10; SQLSTATE = 23000 + + select 'point-27' as msg, t.* from t1 t; + + --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + -- test DOMAIN constraints: + create domain dc1 as integer check (coalesce(value + 0, null) < 10); + create domain dc2 as integer check (coalesce(value + 0, null) < 10); + + alter table t1 + add dc1 dc1, + add dc2 dc2; + + insert into t1 (n, dc1) values (6, 6); + insert into t1 (n, dc2) values (7, 7); + insert into t1 (n, dc1) values (8, 10); -- violates DOMAIN constrain 'dc1' + insert into t1 (n, dc2) values (8, 10); -- violates DOMAIN constrain 'dc2' + + select 'point-28' as msg, t.* from t1 t; + + --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + -- add bad computed expression with coalesce + alter table t1 + add bc computed by (coalesce(n / (n - 2), null)); + + select 'point-29' as msg, t.bc from t1 as t order by t.n; -- must return only one record; raises on second: SQLSTATE = 22012 / arithmetic exception... / -Integer divide by zero + + --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + -- test missed parameters: + + -- This statement will raise exception related to SQLDA. + -- Old error messages: + -- -SQL error code = -804 + -- -SQLDA missing or incorrect version, or incorrect number/type of variables + -- Messages since http://sourceforge.net/p/firebird/code/63010 (2016-02-23, DS): + -- -SQLDA error + -- -Wrong number of parameters (expected 3, got 0) + -- (replacement with new text was approved by dimitr, letter 24-feb-2016 22:01). + + set sqlda_display on; + -------------------------------------------------------------- + select + 'point-30' as msg + ,coalesce(1 + cast(? as integer) + ,2 + cast(? as integer)) + from rdb$database + where coalesce(3 + cast(? as bigint), null) = 0; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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 + + + + 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 + -No SQLDA for input values provided + """ + +@pytest.mark.version('>=3.0') +def test_core_0501_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0507.py b/tests/bugs/test_core_0507.py new file mode 100644 index 00000000..70d25831 --- /dev/null +++ b/tests/bugs/test_core_0507.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: bugs.core_0507 +# title: ambiguous statements return unpredictable results +# decription: +# +# tracker_id: CORE-507 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set planonly; + select r.rdb$relation_name, rc.rdb$relation_name, rc.rdb$constraint_type + from rdb$relations r left join rdb$relation_constraints rc + on r.rdb$relation_name = rc.rdb$relation_name + order by rdb$relation_name; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42702 + Dynamic SQL Error + -SQL error code = -204 + -Ambiguous field name between a field and a field in the select list with name + -RDB$RELATION_NAME + """ + +@pytest.mark.version('>=2.5') +def test_core_0507_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_0521.py b/tests/bugs/test_core_0521.py new file mode 100644 index 00000000..46cdfeb7 --- /dev/null +++ b/tests/bugs/test_core_0521.py @@ -0,0 +1,78 @@ +#coding:utf-8 +# +# id: bugs.core_0521 +# title: Permissions are checked case-insensitively +# decription: +# +# tracker_id: CORE-521 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('execute', 'EXECUTE'), ('-Effective user is.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create user tmp$c0521 password '123'; + commit; + + set term ^; + create procedure perm + as begin + end^ + + create procedure "PeRm" + as begin + execute procedure perm; + end^ + + create procedure "pErM" + as begin + --execute procedure perm; + execute procedure "PeRm"; + end^ + set term ;^ + commit; + + grant execute on procedure perm to procedure "PeRm"; + grant execute on procedure "pErM" to user tmp$c0521; + commit; + + connect '$(DSN)' user tmp$c0521 password '123'; + set list on; + select current_user as whoami from rdb$database; + execute procedure "pErM"; + + commit; + connect '$(DSN)' user sysdba password 'masterkey'; + drop user tmp$c0521; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHOAMI TMP$C0521 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 28000 + no permission for EXECUTE access to PROCEDURE PeRm + """ + +@pytest.mark.version('>=2.5') +def test_core_0521_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0583.py b/tests/bugs/test_core_0583.py new file mode 100644 index 00000000..0fe0739b --- /dev/null +++ b/tests/bugs/test_core_0583.py @@ -0,0 +1,71 @@ +#coding:utf-8 +# +# id: bugs.core_0583 +# title: before triggers are firing after checks +# decription: +# +# tracker_id: CORE-583 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('-At trigger.*', '-At trigger')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test1 (i int, constraint test1_chk check (i between 1 and 5)); + commit; + + set term ^; + create trigger test1_bi for test1 active before insert position 0 as + begin + new.i=6; + end + ^ + + create trigger test1_bu for test1 active before update position 0 as + begin + new.i=7; + end + ^ + set term ;^ + commit; + + set count on; + insert into test1 values (2); + select * from test1; + update test1 set i=2 where i = 6; + select * from test1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + Records affected: 0 + Records affected: 0 + Records affected: 0 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 23000 + Operation violates CHECK constraint TEST1_CHK on view or table TEST1 + -At trigger 'CHECK_3' + """ + +@pytest.mark.version('>=2.5') +def test_core_0583_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0606.py b/tests/bugs/test_core_0606.py new file mode 100644 index 00000000..38f7bf16 --- /dev/null +++ b/tests/bugs/test_core_0606.py @@ -0,0 +1,144 @@ +#coding:utf-8 +# +# id: bugs.core_0606 +# title: Tricky role defeats basic SQL security +# decription: +# CHecked on: +# 4.0.0.1635 SS: 1.482s. +# 4.0.0.1633 CS: 1.954s. +# 3.0.5.33180 SS: 0.976s. +# 3.0.5.33178 CS: 1.265s. +# 2.5.9.27119 SS: 0.297s. +# 2.5.9.27146 SC: 0.306s. +# +# tracker_id: CORE-0606 +# min_versions: ['2.5'] +# versions: 2.5.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.6 +# resources: None + +substitutions_1 = [('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.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + execute block as + begin + begin + execute statement 'drop role "FOR CVC"'; + when any do begin end + end + begin + execute statement 'drop role "FOR"'; + when any do begin end + end + end + ^set term ;^ + commit; + + drop user cvc; + commit; + + recreate table "t t"(data int); + commit; + insert into "t t" values(123456); + commit; + + create user cvc password 'pw'; + commit; + + create role "FOR CVC"; + create role "FOR"; + + 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; + + drop user cvc; + commit; + drop role "FOR CVC"; + drop role "FOR"; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + /* 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_1 = """ + 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 + """ + +@pytest.mark.version('>=2.5.6') +def test_core_0606_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0610.py b/tests/bugs/test_core_0610.py new file mode 100644 index 00000000..632d43c2 --- /dev/null +++ b/tests/bugs/test_core_0610.py @@ -0,0 +1,60 @@ +#coding:utf-8 +# +# id: bugs.core_0610 +# title: FIRST is applied before aggregation +# decription: +# tracker_id: CORE-0610 +# min_versions: ['2.1.7'] +# versions: 2.1.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table A (id integer not null); + create table B (id integer not null, A integer not null, v integer); + commit; + insert into A (id) values (1); + insert into A (id) values (2); + insert into A (id) values (3); + insert into B (id, A, v) values (1, 1, 1); + insert into B (id, A, v) values (2, 1, 1); + insert into B (id, A, v) values (3, 2, 2); + insert into B (id, A, v) values (4, 2, 2); + insert into B (id, A, v) values (5, 3, 3); + insert into B (id, A, v) values (6, 3, 3); + commit; + set list on; + select first 1 count(*) from a; + select first 2 a.id, sum(b.v) from A,B where a.id = b.a + group by a.id + order by a.id; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + COUNT 3 + ID 1 + SUM 2 + ID 2 + SUM 4 + """ + +@pytest.mark.version('>=2.1.7') +def test_core_0610_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0611.py b/tests/bugs/test_core_0611.py new file mode 100644 index 00000000..56db13b0 --- /dev/null +++ b/tests/bugs/test_core_0611.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: bugs.core_0611 +# title: SKIP is off by one +# decription: +# tracker_id: CORE-0611 +# min_versions: ['2.1.7'] +# versions: 2.1.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table A (id integer not null); + commit; + insert into A (id) values (1); + insert into A (id) values (2); + insert into A (id) values (3); + commit; + set list on; + select skip 0 id from a order by id; + select skip 2 id from a order by id; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + ID 2 + ID 3 + ID 3 + """ + +@pytest.mark.version('>=2.1.7') +def test_core_0611_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0623.py b/tests/bugs/test_core_0623.py new file mode 100644 index 00000000..d3ef3f3e --- /dev/null +++ b/tests/bugs/test_core_0623.py @@ -0,0 +1,126 @@ +#coding:utf-8 +# +# id: bugs.core_0623 +# title: ORDER BY on a VIEW turns values in fields into NULL +# decription: +# 30.10.2019. NB: new datatype in FB 4.0 was introduces: numeric(38,0). +# It can lead to additional ident of values when we show them in form "SET LIST ON", +# so we have to ignore all internal spaces - see added 'substitution' section below. +# Checked on: +# 4.0.0.1635 SS: 1.470s. +# 3.0.5.33182 SS: 0.981s. +# 2.5.9.27146 SC: 0.297s. +# +# tracker_id: CORE-0623 +# min_versions: ['2.1.7'] +# versions: 2.1.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.7 +# resources: None + +substitutions_1 = [('=.*', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table p1 ( + x_p1 numeric(10,0), + f_entrada date + ); + + create view vp1 ( + x_p1, + f_entrada + ) as + select x_p1, f_entrada from p1; + + create table p2 ( + x_p2 numeric(10,0), + p1_x_p1 numeric(10,0), + n_one numeric(10,0), + n_two numeric(10,0) + ); + + create view vp2 ( + p1_x_p1, + n_one, + n_two + ) as + select p1_x_p1, sum(n_one), sum(n_two) + from p2 group by p1_x_p1; + + create view vvp1 ( + p1_x_p1, + f_entrada, + n_one, + n_two + ) as + select p1.x_p1, p1.f_entrada, p2.n_one, p2.n_two + from vp1 p1 left join vp2 p2 on p1.x_p1=p2.p1_x_p1; + commit; + + insert into p1 values (1,'07/10/2001'); + insert into p1 values (2,'07/13/2001'); + insert into p1 values (3,'08/12/2001'); + + insert into p2 values (1,1,0,1); + insert into p2 values (2,2,1,0); + insert into p2 values (3,1,0,1); + commit; + + select * from vvp1; + select * from vvp1 order by f_entrada; + + insert into p1 values (4,'08/10/2001'); + insert into p2 values (4,2,0,1); + insert into p2 values (5,2,1,1); + commit; + select * from vvp1; + select * from vvp1 order by f_entrada; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + P1_X_P1 F_ENTRADA N_ONE N_TWO + ===================== =========== ===================== ===================== + 1 2001-07-10 0 2 + 2 2001-07-13 1 0 + 3 2001-08-12 + + + P1_X_P1 F_ENTRADA N_ONE N_TWO + ===================== =========== ===================== ===================== + 1 2001-07-10 0 2 + 2 2001-07-13 1 0 + 3 2001-08-12 + + + P1_X_P1 F_ENTRADA N_ONE N_TWO + ===================== =========== ===================== ===================== + 1 2001-07-10 0 2 + 2 2001-07-13 2 2 + 3 2001-08-12 + 4 2001-08-10 + + + P1_X_P1 F_ENTRADA N_ONE N_TWO + ===================== =========== ===================== ===================== + 1 2001-07-10 0 2 + 2 2001-07-13 2 2 + 4 2001-08-10 + 3 2001-08-12 + """ + +@pytest.mark.version('>=2.1.7') +def test_core_0623_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0625.py b/tests/bugs/test_core_0625.py new file mode 100644 index 00000000..0cca59dd --- /dev/null +++ b/tests/bugs/test_core_0625.py @@ -0,0 +1,57 @@ +#coding:utf-8 +# +# id: bugs.core_0625 +# title: Token unknown in simple SELECT with GROUP BY and ORDER BY +# decription: getting SQL error code = -104, Token unknown count. +# tracker_id: CORE-0625 +# min_versions: ['2.1.7'] +# versions: 2.1.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.7 +# resources: None + +substitutions_1 = [('\\(+', ''), ('\\)+', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table customers(cust_id int primary key using index customers_pk, country int); + commit; + + insert into customers + select r.rdb$relation_id, rand()*10 + from rdb$relations r; + commit; + + create index customers_country on customers(country); + commit; + + set planonly; + --set explain on; + select country, count(country) + from customers + group by country + order by count(country); + -- NB: PLAN up to 2.5 contains TWO parenthesis: + -- PLAN SORT ((CUSTOMERS ORDER CUSTOMERS_COUNTRY)) + -- ^^ ^^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN SORT CUSTOMERS ORDER CUSTOMERS_COUNTRY + """ + +@pytest.mark.version('>=2.1.7') +def test_core_0625_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0629.py b/tests/bugs/test_core_0629.py new file mode 100644 index 00000000..db2493d3 --- /dev/null +++ b/tests/bugs/test_core_0629.py @@ -0,0 +1,123 @@ +#coding:utf-8 +# +# id: bugs.core_0629 +# title: Grouping on derived fields processing NULL data kills IB +# decription: +# tracker_id: CORE-0629 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + create or alter view v_test as select 1 id from rdb$database; + commit; + + recreate table test( + id integer not null, + dt_beg date, + dt_end date, + constraint pk_test primary key (id) + ); + commit; + + create or alter view v_test as + select id, extract(year from dt_beg) - extract(year from dt_end) dy + from test; + commit; + + insert into test values(1, '01.01.2015', null); + insert into test values(2, '01.01.2015', '01.01.2015'); + insert into test values(3, null, null); + insert into test values(4, null, null); + insert into test values(5, '01.01.2015', '31.12.2014'); + commit; + + select dy from v_test group by dy; + commit; + + ------------------------------------------- + + create or alter view v_test as select 1 id from rdb$database; + commit; + recreate table test + ( + a integer, + b date, + c computed by (extract(day from b)-extract(day from b)) + ); + commit; + insert into test(a, b) values(1, DATE '2015-05-24'); + insert into test(a, b) values(1, null); + commit; + select c from test group by c; + commit; + + create or alter view v_test as select b-b as dd from test; + commit; + select dd from v_test group by dd; + commit; + + create or alter view v_test as select b-0 as dd from test; + select dd from v_test group by dd; + + create or alter view v_test + as select cast(b as timestamp) as dt from test; + select dt from v_test group by dt; + + ------------ + + create or alter view v_test as select 1 id from rdb$database; + commit; + recreate table test(a int, b time, c computed by(cast(b as time))); + commit; + + insert into test(a, b) values(1, '15:00:29.191'); + insert into test(a, b) values(1, null); + commit; + + select c from test group by c; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DY + DY 0 + DY 1 + + C + C 0 + + DD + DD 0 + + DD + DD 2015-05-24 + + DT + DT 2015-05-24 00:00:00.0000 + + C + C 15:00:29.1910 + """ + +@pytest.mark.version('>=2.5') +def test_core_0629_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0655.py b/tests/bugs/test_core_0655.py new file mode 100644 index 00000000..8ada67a6 --- /dev/null +++ b/tests/bugs/test_core_0655.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: bugs.core_655 +# title: Blob Type 1 compatibility with VarChar +# decription: Blob Sub-Type 1 (text) column treated in the same manner as a VarChar column +# for assignments, conversions, cast, lower, upper, trim, concatenate and substring +# tracker_id: CORE-655 +# min_versions: ['2.1.0'] +# versions: 2.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t1 (f1 BLOB SUB_TYPE 1 SEGMENT SIZE 80); +insert into t1 values ('Firebird '); + +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select cast(lower(f1) as varchar(20)) lf1, cast(upper(f1) as varchar(20)) uf1, cast(trim(f1)||'2.1' as varchar(20))tf1, cast(f1||'2.1' as varchar(20)) cf1, cast(substring(f1 from 1 for 5) as varchar(20)) sf1 from t1; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Database: localhost:C: btest mpugs.core_655.fdb, User: SYSDBA +SQL> +LF1 UF1 TF1 CF1 SF1 +==================== ==================== ==================== ==================== ==================== +firebird FIREBIRD Firebird2.1 Firebird 2.1 Fireb + +SQL>""" + +@pytest.mark.version('>=2.1') +def test_core_655_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0696.py b/tests/bugs/test_core_0696.py new file mode 100644 index 00000000..d173bb23 --- /dev/null +++ b/tests/bugs/test_core_0696.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: bugs.core_0696 +# title: User Account maintanance in SQL +# decription: +# tracker_id: CORE-696 +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE USER alex PASSWORD 'test'; +COMMIT; +ALTER USER alex FIRSTNAME 'Alex' LASTNAME 'Peshkov'; +COMMIT; +ALTER USER alex PASSWORD 'IdQfA'; +COMMIT; +DROP USER alex; +COMMIT; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.0') +def test_core_0696_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_0733.py b/tests/bugs/test_core_0733.py new file mode 100644 index 00000000..e413564f --- /dev/null +++ b/tests/bugs/test_core_0733.py @@ -0,0 +1,358 @@ +#coding:utf-8 +# +# id: bugs.core_0733 +# title: Compress Data over the Network +# decription: +# CHANGED 22.12.2019: CODE REDUCTION: REMOVED MEASURES OT TIME. +# Results are completely opposite to those which were obtained on snapshots when this test was implenmented (3.0.5.33084, 4.0.0.1347). +# Requirement to compress data leads to DEGRADATION of performance when data are stored on local machine, and we have no ability +# to change storage when fbt_run is in work (at least for nowadays). +# After discuss with dimitr it was decided to remove any logging and its analysis. +# We only verify matching of RDB$GET_CONTEXT('SYSTEM', 'WIRE_COMPRESSED') and value that was stored in the firebird.conf +# for current check. +# +# ### NOTE ### +# Changed value of parameter WireCompression (in firebird.conf) will be seen by application if it reloads client library. +# Reconnect is NOT enough for this. For this reason we use subprocess and call ISQL utility to do above mentioned actions +# in new execution context. +# +# See also tests for: +# CORE-5536 - checks that field mon$wire_compressed actually exists in MON$ATTACHMENTS table; +# CORE-5913 - checks that built-in rdb$get_context('SYSTEM','WIRE_ENCRYPTED') is avaliable; +# +# Checked on: +# 4.0.0.1693 SS: 3.031s. +# 4.0.0.1346 SC: 2.890s. +# 4.0.0.1691 CS: 3.678s. +# 3.0.5.33215 SS: 1.452s. +# 3.0.5.33084 SC: 1.344s. +# 3.0.5.33212 CS: 3.175s. +# +# +# tracker_id: CORE-0733 +# min_versions: ['3.0.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create domain dm_dump varchar(32700) character set none; + recreate table t_log( required_value varchar(5), actual_value varchar(5), elap_ms int ); + commit; + set term ^; + create or alter procedure sp_uuid(a_compressable boolean, n_limit int default 1) + returns (b dm_dump) as + declare g char(16) character set octets; + begin + if ( a_compressable ) then + while (n_limit > 0) do + begin + g = gen_uuid(); + b = lpad('',32700, 'AAAAAAAAAAAAAAAA' ); + n_limit = n_limit - 1; + suspend; + end + else + while (n_limit > 0) do + begin + b = lpad('',32700, gen_uuid() ); + n_limit = n_limit - 1; + suspend; + end + end + ^ + set term ;^ + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import time as tm +# import datetime +# from time import time +# import re +# import shutil +# import subprocess +# import platform +# +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# DB_NAME = '$(DATABASE_LOCATION)' + 'bugs.core_0733.fdb' +# +# DB_PATH = '$(DATABASE_LOCATION)' +# U_NAME = user_name +# U_PSWD = user_password +# NUL_DEVICE = 'nul' if platform.system() == 'Windows' else '/dev/null' +# +# N_ROWS = 1 +# +# F_SQL_NAME=os.path.join(context['temp_directory'],'tmp_core_0733.sql') +# +# fb_home = services.connect(host='localhost', user= user_name, password= user_password).get_home_directory() +# dts = datetime.datetime.now().strftime("%y%m%d_%H%M%S") +# fbconf_bak = fb_home+'firebird_'+dts+'.tmp_0733.bak' +# shutil.copy2( fb_home+'firebird.conf', fbconf_bak ) +# +# db_conn.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'): +# # otherwise: "OSError: [Errno 9] Bad file descriptor"! +# os.fsync(file_handle.fileno()) +# file_handle.close() +# +# #-------------------------------------------- +# +# def prepare_fb_conf( fb_home, a_required_value ): +# +# f_fbconf=open(fb_home+'firebird.conf','r') +# fbconf_content=f_fbconf.readlines() +# f_fbconf.close() +# for i,s in enumerate( fbconf_content ): +# if s.lower().lstrip().startswith( 'wirecompression'.lower() ): +# fbconf_content[i] = '# ' + s +# +# fbconf_content.append('\\n# Temporarily added by fbtest, CORE-0733. Should be removed auto:') +# fbconf_content.append("\\n#" + '='*30 ) +# fbconf_content.append('\\nWireCompression = %s' % a_required_value ) +# fbconf_content.append("\\n#" + '='*30 ) +# fbconf_content.append("\\n" ) +# +# f_fbconf=open(fb_home+'firebird.conf','w') +# f_fbconf.writelines( fbconf_content ) +# f_fbconf.close() +# #------------------------------------------------------------------------------------ +# +# def prepare_sql_4run( required_compression, db_path, n_rows, sql_file_name ): +# global os +# global U_NAME +# global U_PSWD +# global NUL_DEVICE +# +# sql_dump='tmp_core_0733_compression_%(required_compression)s.dump' % ( locals() ) +# +# if os.path.isfile( '%(db_path)s%(sql_dump)s' % (locals()) ): +# os.remove( '%(db_path)s%(sql_dump)s' % (locals()) ) +# +# if n_rows is None: +# return +# +# #------------------ +# +# sql_text=''' +# set list on; +# +# set term ^; +# execute block returns(dts timestamp) as +# begin +# dts = 'now'; +# rdb$set_context('USER_SESSION','DTS_BEG', dts); +# suspend; +# end +# ^ +# set term ;^ +# +# --out %(db_path)s%(sql_dump)s; +# out nul; +# +# set term ^; +# execute block returns(b dm_dump) as +# begin +# /*********** +# for +# execute statement 'select b from sp_uuid( true, %(n_rows)s )' +# on external 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME') +# as user '%(U_NAME)s' password '%(U_PSWD)s' +# into b +# do +# suspend; +# ***********/ +# end +# ^ +# set term ;^ +# out; +# +# set term ^; +# execute block returns(dts timestamp) as +# begin +# dts = 'now'; +# rdb$set_context('USER_SESSION','DTS_END', dts); +# suspend; +# end +# ^ +# set term ;^ +# +# insert into t_log( required_value, actual_value, elap_ms) +# values( +# upper( '%(required_compression)s' ) +# ,upper( rdb$get_context('SYSTEM','WIRE_COMPRESSED') ) +# ,datediff( millisecond +# from cast(rdb$get_context('USER_SESSION','DTS_BEG') as timestamp) +# to cast(rdb$get_context('USER_SESSION','DTS_END') as timestamp) +# ) +# ) +# returning required_value, actual_value, elap_ms +# ; +# commit; +# ''' % dict(globals(), **locals()) +# # ( locals() ) +# +# f_sql=open( sql_file_name, 'w') +# f_sql.write( sql_text ) +# f_sql.close() +# +# #------------------------- +# +# # Call for removing dump from disk: +# prepare_sql_4run( 'false', DB_PATH, None, None ) +# prepare_sql_4run( 'true', DB_PATH, None, None ) +# +# +# REQUIRED_WIRE_COMPRESSION = 'false' +# # ------------------------------------------------------ ########### +# # Generate SQL script for running when WireCompression = |||FALSE||| +# # ------------------------------------------------------ ########### +# prepare_sql_4run( REQUIRED_WIRE_COMPRESSION, DB_PATH, N_ROWS, F_SQL_NAME ) +# +# # ------------------------------------------------------ ########### +# # Update content of firebird.conf with WireCompression = |||FALSE||| +# # ------------------------------------------------------ ########### +# prepare_fb_conf( fb_home, REQUIRED_WIRE_COMPRESSION) +# +# +# # -------------------------------------------------------------------------------------- +# # Launch ISQL in separate context of execution with job to obtain data and log duration +# # -------------------------------------------------------------------------------------- +# +# fn_log = open(os.devnull, 'w') +# #fn_log = open( os.path.join(context['temp_directory'],'tmp_0733_with_compression.log'), 'w') +# f_isql_obtain_data_err = open( os.path.join(context['temp_directory'],'tmp_0733_obtain_data.err'), 'w') +# +# subprocess.call( [ context['isql_path'], dsn, "-i", F_SQL_NAME ], +# stdout = fn_log, +# stderr = f_isql_obtain_data_err +# ) +# fn_log.close() +# f_isql_obtain_data_err.close() +# +# # Call for removing dump from disk: +# #prepare_sql_4run( False, DB_PATH, None, None ) +# #prepare_sql_4run( True, DB_PATH, None, None ) +# +# +# # Update content of firebird.conf with WireCompression = true +# ############################################################## +# +# REQUIRED_WIRE_COMPRESSION = 'true' +# # ------------------------------------------------------ ########### +# # Generate SQL script for running when WireCompression = ||| TRUE||| +# # ------------------------------------------------------ ########### +# prepare_sql_4run( REQUIRED_WIRE_COMPRESSION, DB_PATH, N_ROWS, F_SQL_NAME ) +# +# # ------------------------------------------------------ ########### +# # Update content of firebird.conf with WireCompression = ||| TRUE||| +# # ------------------------------------------------------ ########### +# prepare_fb_conf( fb_home, REQUIRED_WIRE_COMPRESSION) +# +# fn_log = open(os.devnull, 'w') +# #fn_log = open( os.path.join(context['temp_directory'],'tmp_0733_without_compress.log'), 'w') +# f_isql_obtain_data_err = open( os.path.join(context['temp_directory'],'tmp_0733_obtain_data.err'), 'a') +# +# subprocess.call( [ context['isql_path'], dsn, "-i", F_SQL_NAME ], +# stdout = fn_log, +# stderr = f_isql_obtain_data_err +# ) +# fn_log.close() +# flush_and_close( f_isql_obtain_data_err ) +# +# # Call for removing dump from disk: +# #prepare_sql_4run( REQUIRED_WIRE_COMPRESSION, DB_PATH, None, None ) +# +# # RESTORE original config: +# ########################## +# shutil.copy2( fbconf_bak , fb_home+'firebird.conf') +# +# sql=''' +# -- select * from t_log; +# -- REQUIRED_VALUE ACTUAL_VALUE ELAP_MS +# -- ============== ============ ============ +# -- FALSE FALSE 2187 +# -- TRUE TRUE 1782 +# set list on; +# select +# result_of_req_compare_to_actual +# --,iif( slowest_with_compression < fastest_without_compression, +# -- 'EXPECTED: compression was FASTER.', +# -- 'POOR. slowest_with_compression=' || slowest_with_compression || ', fastest_without_compression=' || fastest_without_compression +# -- ) as result_of_compression_benchmark +# from ( +# select +# min( iif( upper(required_value) is distinct from upper(actual_value) +# ,coalesce(required_value,'') || coalesce(actual_value,'') +# ,'EXPECTED: actual values were equal to required.' +# ) +# ) as result_of_req_compare_to_actual +# ,min( iif( upper(required_value) = upper('false'), elap_ms, null ) ) fastest_without_compression +# ,max( iif( upper(required_value) = upper('true'), elap_ms, null ) ) slowest_with_compression +# from t_log +# ) +# ; +# set list off; +# --select * from t_log; +# +# ''' +# runProgram('isql', [ dsn ], sql) +# +# +# # Additional check: STDERR for ISQL must be EMPTY. +# ################################################## +# +# f_list=(f_isql_obtain_data_err,) +# for i in range(len(f_list)): +# f_name=f_list[i].name +# if os.path.getsize(f_name) > 0: +# with open( f_name,'r') as f: +# for line in f: +# print("Unexpected STDERR, file "+f_name+": "+line) +# +# os.remove(f_isql_obtain_data_err.name) +# os.remove(fbconf_bak) +# os.remove(F_SQL_NAME) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT_OF_REQ_COMPARE_TO_ACTUAL EXPECTED: actual values were equal to required. + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_0733_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_0769.py b/tests/bugs/test_core_0769.py new file mode 100644 index 00000000..fb94ce37 --- /dev/null +++ b/tests/bugs/test_core_0769.py @@ -0,0 +1,304 @@ +#coding:utf-8 +# +# id: bugs.core_0769 +# title: Wildcards/Regular Expressions in WHERE clause - SIMILAR TO predicate +# decription: +# tracker_id: CORE-769 +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT IIF('ab' SIMILAR TO 'ab|cd|efg','true','false'),'true','''ab'' SIMILAR TO ''ab|cd|efg''' FROM RDB$DATABASE; +SELECT IIF('efg' SIMILAR TO 'ab|cd|efg','true','false'),'true','''efg'' SIMILAR TO ''ab|cd|efg''' FROM RDB$DATABASE; +SELECT IIF('a' SIMILAR TO 'ab|cd|efg','true','false'),'false','''a'' SIMILAR TO ''ab|cd|efg''' FROM RDB$DATABASE; +SELECT IIF('' SIMILAR TO 'a*','true','false'),'true',''''' SIMILAR TO ''a*''' FROM RDB$DATABASE; +SELECT IIF('a' SIMILAR TO 'a*','true','false'),'true','''a'' SIMILAR TO ''a*''' FROM RDB$DATABASE; +SELECT IIF('aaa' SIMILAR TO 'a*','true','false'),'true','''aaa'' SIMILAR TO ''a*''' FROM RDB$DATABASE; +SELECT IIF('' SIMILAR TO 'a+','true','false'),'false',''''' SIMILAR TO ''a+''' FROM RDB$DATABASE; +SELECT IIF('a' SIMILAR TO 'a+','true','false'),'true','''a'' SIMILAR TO ''a+''' FROM RDB$DATABASE; +SELECT IIF('aaa' SIMILAR TO 'a+','true','false'),'true','''aaa'' SIMILAR TO ''a+''' FROM RDB$DATABASE; +SELECT IIF('' SIMILAR TO 'a?','true','false'),'true',''''' SIMILAR TO ''a?''' FROM RDB$DATABASE; +SELECT IIF('a' SIMILAR TO 'a?','true','false'),'true','''a'' SIMILAR TO ''a?''' FROM RDB$DATABASE; +SELECT IIF('aaa' SIMILAR TO 'a?','true','false'),'false','''aaa'' SIMILAR TO ''a?''' FROM RDB$DATABASE; +SELECT IIF('' SIMILAR TO 'a{2,}','true','false'),'false',''''' SIMILAR TO ''a{2,}''' FROM RDB$DATABASE; +SELECT IIF('a' SIMILAR TO 'a{2,}','true','false'),'false','''a'' SIMILAR TO ''a{2,}''' FROM RDB$DATABASE; +SELECT IIF('aa' SIMILAR TO 'a{2,}','true','false'),'true','''aa'' SIMILAR TO ''a{2,}''' FROM RDB$DATABASE; +SELECT IIF('aaa' SIMILAR TO 'a{2,}','true','false'),'true','''aaa'' SIMILAR TO ''a{2,}''' FROM RDB$DATABASE; +SELECT IIF('' SIMILAR TO 'a{2,4}','true','false'),'false',''''' SIMILAR TO ''a{2,4}''' FROM RDB$DATABASE; +SELECT IIF('a' SIMILAR TO 'a{2,4}','true','false'),'false','''a'' SIMILAR TO ''a{2,4}''' FROM RDB$DATABASE; +SELECT IIF('aa' SIMILAR TO 'a{2,4}','true','false'),'true','''aa'' SIMILAR TO ''a{2,4}''' FROM RDB$DATABASE; +SELECT IIF('aaa' SIMILAR TO 'a{2,4}','true','false'),'true','''aaa'' SIMILAR TO ''a{2,4}''' FROM RDB$DATABASE; +SELECT IIF('aaaa' SIMILAR TO 'a{2,4}','true','false'),'true','''aaaa'' SIMILAR TO ''a{2,4}''' FROM RDB$DATABASE; +SELECT IIF('aaaaa' SIMILAR TO 'a{2,4}','true','false'),'false','''aaaaa'' SIMILAR TO ''a{2,4}''' FROM RDB$DATABASE; +SELECT IIF('' SIMILAR TO '_','true','false'),'false',''''' SIMILAR TO ''_''' FROM RDB$DATABASE; +SELECT IIF('a' SIMILAR TO '_','true','false'),'true','''a'' SIMILAR TO ''_''' FROM RDB$DATABASE; +SELECT IIF('1' SIMILAR TO '_','true','false'),'true','''1'' SIMILAR TO ''_''' FROM RDB$DATABASE; +SELECT IIF('a1' SIMILAR TO '_','true','false'),'false','''a1'' SIMILAR TO ''_''' FROM RDB$DATABASE; +SELECT IIF('' SIMILAR TO '%','true','false'),'true',''''' SIMILAR TO ''%''' FROM RDB$DATABASE; +SELECT IIF('az' SIMILAR TO 'a%z','true','false'),'true','''az'' SIMILAR TO ''a%z''' FROM RDB$DATABASE; +SELECT IIF('a123z' SIMILAR TO 'a%z','true','false'),'true','''a123z'' SIMILAR TO ''a%z''' FROM RDB$DATABASE; +SELECT IIF('azx' SIMILAR TO 'a%z','true','false'),'false','''azx'' SIMILAR TO ''a%z''' FROM RDB$DATABASE; +SELECT IIF('ab' SIMILAR TO '(ab){2}','true','false'),'false','''ab'' SIMILAR TO ''(ab){2}''' FROM RDB$DATABASE; +SELECT IIF('aabb' SIMILAR TO '(ab){2}','true','false'),'false','''aabb'' SIMILAR TO ''(ab){2}''' FROM RDB$DATABASE; +SELECT IIF('abab' SIMILAR TO '(ab){2}','true','false'),'true','''abab'' SIMILAR TO ''(ab){2}''' FROM RDB$DATABASE; +SELECT IIF('b' SIMILAR TO '[abc]','true','false'),'true','''b'' SIMILAR TO ''[abc]''' FROM RDB$DATABASE; +SELECT IIF('d' SIMILAR TO '[abc]','true','false'),'false','''d'' SIMILAR TO ''[abc]''' FROM RDB$DATABASE; +SELECT IIF('9' SIMILAR TO '[0-9]','true','false'),'true','''9'' SIMILAR TO ''[0-9]''' FROM RDB$DATABASE; +SELECT IIF('9' SIMILAR TO '[0-8]','true','false'),'false','''9'' SIMILAR TO ''[0-8]''' FROM RDB$DATABASE; +SELECT IIF('b' SIMILAR TO '[^abc]','true','false'),'false','''b'' SIMILAR TO ''[^abc]''' FROM RDB$DATABASE; +SELECT IIF('d' SIMILAR TO '[^abc]','true','false'),'true','''d'' SIMILAR TO ''[^abc]''' FROM RDB$DATABASE; +SELECT IIF('3' SIMILAR TO '[[:DIGIT:]^3]','true','false'),'false','''3'' SIMILAR TO ''[[:DIGIT:]^3]''' FROM RDB$DATABASE; +SELECT IIF('4' SIMILAR TO '[[:DIGIT:]^3]','true','false'),'true','''4'' SIMILAR TO ''[[:DIGIT:]^3]''' FROM RDB$DATABASE; +SELECT IIF('4' SIMILAR TO '[[:DIGIT:]]','true','false'),'true','''4'' SIMILAR TO ''[[:DIGIT:]]''' FROM RDB$DATABASE; +SELECT IIF('a' SIMILAR TO '[[:DIGIT:]]','true','false'),'false','''a'' SIMILAR TO ''[[:DIGIT:]]''' FROM RDB$DATABASE; +SELECT IIF('4' SIMILAR TO '[^[:DIGIT:]]','true','false'),'false','''4'' SIMILAR TO ''[^[:DIGIT:]]''' FROM RDB$DATABASE; +SELECT IIF('a' SIMILAR TO '[^[:DIGIT:]]','true','false'),'true','''a'' SIMILAR TO ''[^[:DIGIT:]]''' FROM RDB$DATABASE; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +CASE CONSTANT CONSTANT +====== ======== =========================== +true true 'ab' SIMILAR TO 'ab|cd|efg' + + +CASE CONSTANT CONSTANT +====== ======== ============================ +true true 'efg' SIMILAR TO 'ab|cd|efg' + + +CASE CONSTANT CONSTANT +====== ======== ========================== +false false 'a' SIMILAR TO 'ab|cd|efg' + + +CASE CONSTANT CONSTANT +====== ======== ================== +true true '' SIMILAR TO 'a*' + + +CASE CONSTANT CONSTANT +====== ======== =================== +true true 'a' SIMILAR TO 'a*' + + +CASE CONSTANT CONSTANT +====== ======== ===================== +true true 'aaa' SIMILAR TO 'a*' + + +CASE CONSTANT CONSTANT +====== ======== ================== +false false '' SIMILAR TO 'a+' + + +CASE CONSTANT CONSTANT +====== ======== =================== +true true 'a' SIMILAR TO 'a+' + + +CASE CONSTANT CONSTANT +====== ======== ===================== +true true 'aaa' SIMILAR TO 'a+' + + +CASE CONSTANT CONSTANT +====== ======== ================== +true true '' SIMILAR TO 'a?' + + +CASE CONSTANT CONSTANT +====== ======== =================== +true true 'a' SIMILAR TO 'a?' + + +CASE CONSTANT CONSTANT +====== ======== ===================== +false false 'aaa' SIMILAR TO 'a?' + + +CASE CONSTANT CONSTANT +====== ======== ===================== +false false '' SIMILAR TO 'a{2,}' + + +CASE CONSTANT CONSTANT +====== ======== ====================== +false false 'a' SIMILAR TO 'a{2,}' + + +CASE CONSTANT CONSTANT +====== ======== ======================= +true true 'aa' SIMILAR TO 'a{2,}' + + +CASE CONSTANT CONSTANT +====== ======== ======================== +true true 'aaa' SIMILAR TO 'a{2,}' + + +CASE CONSTANT CONSTANT +====== ======== ====================== +false false '' SIMILAR TO 'a{2,4}' + + +CASE CONSTANT CONSTANT +====== ======== ======================= +false false 'a' SIMILAR TO 'a{2,4}' + + +CASE CONSTANT CONSTANT +====== ======== ======================== +true true 'aa' SIMILAR TO 'a{2,4}' + + +CASE CONSTANT CONSTANT +====== ======== ========================= +true true 'aaa' SIMILAR TO 'a{2,4}' + + +CASE CONSTANT CONSTANT +====== ======== ========================== +true true 'aaaa' SIMILAR TO 'a{2,4}' + + +CASE CONSTANT CONSTANT +====== ======== =========================== +false false 'aaaaa' SIMILAR TO 'a{2,4}' + + +CASE CONSTANT CONSTANT +====== ======== ================= +false false '' SIMILAR TO '_' + + +CASE CONSTANT CONSTANT +====== ======== ================== +true true 'a' SIMILAR TO '_' + + +CASE CONSTANT CONSTANT +====== ======== ================== +true true '1' SIMILAR TO '_' + + +CASE CONSTANT CONSTANT +====== ======== =================== +false false 'a1' SIMILAR TO '_' + + +CASE CONSTANT CONSTANT +====== ======== ================= +true true '' SIMILAR TO '%' + + +CASE CONSTANT CONSTANT +====== ======== ===================== +true true 'az' SIMILAR TO 'a%z' + + +CASE CONSTANT CONSTANT +====== ======== ======================== +true true 'a123z' SIMILAR TO 'a%z' + + +CASE CONSTANT CONSTANT +====== ======== ====================== +false false 'azx' SIMILAR TO 'a%z' + + +CASE CONSTANT CONSTANT +====== ======== ========================= +false false 'ab' SIMILAR TO '(ab){2}' + + +CASE CONSTANT CONSTANT +====== ======== =========================== +false false 'aabb' SIMILAR TO '(ab){2}' + + +CASE CONSTANT CONSTANT +====== ======== =========================== +true true 'abab' SIMILAR TO '(ab){2}' + + +CASE CONSTANT CONSTANT +====== ======== ====================== +true true 'b' SIMILAR TO '[abc]' + + +CASE CONSTANT CONSTANT +====== ======== ====================== +false false 'd' SIMILAR TO '[abc]' + + +CASE CONSTANT CONSTANT +====== ======== ====================== +true true '9' SIMILAR TO '[0-9]' + + +CASE CONSTANT CONSTANT +====== ======== ====================== +false false '9' SIMILAR TO '[0-8]' + + +CASE CONSTANT CONSTANT +====== ======== ======================= +false false 'b' SIMILAR TO '[^abc]' + + +CASE CONSTANT CONSTANT +====== ======== ======================= +true true 'd' SIMILAR TO '[^abc]' + + +CASE CONSTANT CONSTANT +====== ======== ============================== +false false '3' SIMILAR TO '[[:DIGIT:]^3]' + + +CASE CONSTANT CONSTANT +====== ======== ============================== +true true '4' SIMILAR TO '[[:DIGIT:]^3]' + + +CASE CONSTANT CONSTANT +====== ======== ============================ +true true '4' SIMILAR TO '[[:DIGIT:]]' + + +CASE CONSTANT CONSTANT +====== ======== ============================ +false false 'a' SIMILAR TO '[[:DIGIT:]]' + + +CASE CONSTANT CONSTANT +====== ======== ============================= +false false '4' SIMILAR TO '[^[:DIGIT:]]' + + +CASE CONSTANT CONSTANT +====== ======== ============================= +true true 'a' SIMILAR TO '[^[:DIGIT:]]' + +""" + +@pytest.mark.version('>=3.0') +def test_core_0769_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0790.py b/tests/bugs/test_core_0790.py new file mode 100644 index 00000000..4de099b0 --- /dev/null +++ b/tests/bugs/test_core_0790.py @@ -0,0 +1,75 @@ +#coding:utf-8 +# +# id: bugs.core_0790 +# title: Alter view +# decription: +# tracker_id: CORE-790 +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table users ( + id integer, + name varchar(20), + passwd varchar(20) +); + +create view v_users as + select name from users; +commit;""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """alter view v_users (id, name, passwd ) as + select id, name, passwd from users; +commit; +show view v_users; +create view v_users_name as + select name from v_users; +commit; +alter view v_users (id, name ) as + select id, name from users; +commit; +show view v_users; +show view v_users_name; + + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Database: localhost:C: btest2 mpugs.core_0790.fdb, User: SYSDBA +SQL> CON> SQL> SQL> ID INTEGER Nullable +NAME VARCHAR(20) Nullable +PASSWD VARCHAR(20) Nullable +View Source: +==== ====== + + select id, name, passwd from users +SQL> CON> SQL> SQL> CON> SQL> SQL> ID INTEGER Nullable +NAME VARCHAR(20) Nullable +View Source: +==== ====== + + select id, name from users +SQL> NAME VARCHAR(20) Nullable +View Source: +==== ====== + + select name from v_users +SQL> SQL> SQL> SQL>""" + +@pytest.mark.version('>=2.5.0') +def test_core_0790_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0800.py b/tests/bugs/test_core_0800.py new file mode 100644 index 00000000..36e8b63c --- /dev/null +++ b/tests/bugs/test_core_0800.py @@ -0,0 +1,98 @@ +#coding:utf-8 +# +# id: bugs.core_0800 +# title: Easy metadata extract improvements +# decription: +# Domain DDL: move its CHECK clause from 'create' to 'alter' statement. +# +# tracker_id: CORE-0800 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + set term ^; + execute block as + begin + begin + execute statement 'drop domain dm_test'; + when any do begin end + end + begin + execute statement 'drop collation name_coll'; + when any do begin end + end + end^ + set term ;^ + commit; + + create collation name_coll for utf8 from unicode no pad case insensitive accent insensitive; + commit; + + create domain dm_test varchar(20) + character set utf8 + default 'foo' + not null + check (value in ('foo', 'rio', 'bar')) + collate name_coll + ; + commit; + """ + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import subprocess +# +# db_conn.close() +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_file="$(DATABASE_LOCATION)bugs.core_0800.fdb" +# +# f_extract_meta = open( os.path.join(context['temp_directory'],'tmp_meta_0800_init.sql'), 'w') +# subprocess.call( [context['isql_path'], dsn, "-x", "-ch", "utf8"], +# stdout = f_extract_meta, +# stderr = subprocess.STDOUT +# ) +# f_extract_meta.close() +# +# with open( f_extract_meta.name, 'r') as f: +# for line in f: +# if 'ALTER DOMAIN' in line.upper(): +# print( line ) +# +# ############################### +# # Cleanup. +# +# f_list=[] +# f_list.append(f_extract_meta) +# +# for i in range(len(f_list)): +# if os.path.isfile(f_list[i].name): +# os.remove(f_list[i].name) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ALTER DOMAIN DM_TEST ADD CONSTRAINT + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_0800_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_0805.py b/tests/bugs/test_core_0805.py new file mode 100644 index 00000000..75847f86 --- /dev/null +++ b/tests/bugs/test_core_0805.py @@ -0,0 +1,172 @@ +#coding:utf-8 +# +# id: bugs.core_805 +# title: Privileges of dynamic statements in SP +# decription: +# Checked on: +# 4.0.0.1635 SS: 1.650s. +# 4.0.0.1633 CS: 1.714s. +# 3.0.5.33180 SS: 0.960s. +# 3.0.5.33178 CS: 1.203s. +# 2.5.9.27119 SS: 0.324s. +# 2.5.9.27146 SC: 0.342s. +# +# tracker_id: CORE-805 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set wng off; + -- Drop old account if it remains from prevoius run: + set term ^; + execute block as + begin + begin + execute statement 'drop user tmp$c0805_senior' with autonomous transaction; + when any do begin end + end + begin + execute statement 'drop user tmp$c0805_junior' with autonomous transaction; + when any do begin end + end + begin + execute statement 'drop role tmp$r4junior'; + when any do begin end + end + end + ^ + set term ;^ + commit; + + create user tmp$c0805_senior password 'qwe'; + create user tmp$c0805_junior password '123'; + commit; + + create role tmp$r4junior; + commit; + + create or alter procedure sp_test as begin end; + + recreate table test(id int, x int); + commit; + + insert into test values(1, 100); + commit; + + set term ^; + create or alter procedure sp_test returns(id int, x int) as + begin + for select id, x from test into id, x do suspend; + end + ^ + + create or alter procedure sp_main(a_usr varchar(31), a_pwd varchar(31), a_role varchar(31) = 'NONE') + returns(who_am_i varchar(31), what_is_my_role varchar(31), id int, x int) as + begin + for + execute statement + 'select current_user, current_role, id, x from sp_test' + WITH CALLER PRIVILEGES + as user a_usr password a_pwd role a_role + into who_am_i, what_is_my_role, id, x + do + suspend; + end + ^ + set term ;^ + commit; + + revoke all on all from tmp$c0805_senior; + revoke all on all from tmp$c0805_junior; + revoke all on all from tmp$r4junior; --restored as uncommented statement, 05.03.2018 + commit; + + grant select on test to procedure sp_test; + grant execute on procedure sp_main to tmp$c0805_senior; + grant execute on procedure sp_main to tmp$r4junior; + grant execute on procedure sp_test to procedure sp_main; + grant tmp$r4junior to tmp$c0805_junior; + commit; + + -- result: + -- 1) table TEST can be queried only by procedure sp_test; + -- 2) procedure sp_test is called only from another procedure - sp_main - and only via ES + -- 3) procedure sp_main can be called: + -- 2.1) directly by user tmp$c0805_senior (no role required to him); + -- 2.2) indirectly by ROLE 'tmp$r4junior' which is granted to user 'tmp$c0805_junior'. + + -- Both these users should be able to see data of table 'TEST': + + set list on; + + set term ^; + execute block returns(who_am_i varchar(31), what_is_my_role varchar(31), id int, x int) as + begin + for execute statement ('select * from sp_main( :u, :p)') ( u := 'tmp$c0805_senior', p := 'qwe' ) + into who_am_i, what_is_my_role, id, x + do suspend; + end + ^ + execute block returns(who_am_i varchar(31), what_is_my_role varchar(31), id int, x int) as + begin + for execute statement ('select * from sp_main( :u, :p, :r)') ( u := 'tmp$c0805_junior', p := '123', r := 'tmp$r4junior' ) + into who_am_i, what_is_my_role, id, x + 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; + + drop user tmp$c0805_senior; + drop user tmp$c0805_junior; + drop role tmp$r4junior; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHO_AM_I TMP$C0805_SENIOR + WHAT_IS_MY_ROLE NONE + ID 1 + X 100 + + WHO_AM_I TMP$C0805_JUNIOR + WHAT_IS_MY_ROLE TMP$R4JUNIOR + ID 1 + X 100 + """ + +@pytest.mark.version('>=2.5') +def test_core_805_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0824.py b/tests/bugs/test_core_0824.py new file mode 100644 index 00000000..24959a0e --- /dev/null +++ b/tests/bugs/test_core_0824.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_0824 +# title: accent ignoring collation for unicode +# decription: +# tracker_id: CORE-824 +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT IIF('eeaauoeeeaauo' = 'ÉÈÀÂÛÔÊéèàâûô' COLLATE UNICODE_CI_AI ,'true','false'),'true','''eeaauoeeeaauo'' = ''ÉÈÀÂÛÔÊéèàâûô'' COLLATE UNICODE_CI_AI' FROM RDB$DATABASE; +SELECT IIF('EEAAUOEEEAAUO' = 'ÉÈÀÂÛÔÊéèàâûô' COLLATE UNICODE_CI_AI ,'true','false'),'true','''EEAAUOEEEAAUO'' = ''ÉÈÀÂÛÔÊéèàâûô'' COLLATE UNICODE_CI_AI' FROM RDB$DATABASE; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +CASE CONSTANT CONSTANT +====== ======== ======================================================= +true true 'eeaauoeeeaauo' = 'ÉÈÀÂÛÔÊéèàâûô' COLLATE UNICODE_CI_AI + + +CASE CONSTANT CONSTANT +====== ======== ======================================================= +true true 'EEAAUOEEEAAUO' = 'ÉÈÀÂÛÔÊéèàâûô' COLLATE UNICODE_CI_AI + +""" + +@pytest.mark.version('>=3.0') +def test_core_0824_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0842.py b/tests/bugs/test_core_0842.py new file mode 100644 index 00000000..d42474a5 --- /dev/null +++ b/tests/bugs/test_core_0842.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: bugs.core_842 +# title: Specific query crashing server +# decription: Run the query below twice and the server will crash: +# +# select +# cast('' as varchar(32765)), +# cast('' as varchar(32748)) +# from +# rdb$database; +# tracker_id: CORE-842 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_842 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select cast('' as varchar(32765)), cast('' as varchar(32748)) from rdb$database; + select cast('' as varchar(32765)), cast('' as varchar(32748)) from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CAST + CAST + CAST + CAST + """ + +@pytest.mark.version('>=2.1') +def test_core_842_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0847.py b/tests/bugs/test_core_0847.py new file mode 100644 index 00000000..d01e6709 --- /dev/null +++ b/tests/bugs/test_core_0847.py @@ -0,0 +1,85 @@ +#coding:utf-8 +# +# id: bugs.core_0847 +# title: computed field can't be changed to non-computed using 'alter table alter column type xy' +# decription: +# tracker_id: CORE-847 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_847 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table t ( + f1 varchar(10), + f2 varchar(10), + cf computed by (f1 || ' - ' || f2) + ); + + insert into t (f1,f2) values ('0123456789','abcdefghij'); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set blob off; + set list on; + + select f1,f2,cf 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'); + + alter table t alter cf type varchar(30); + commit; + + select f1,f2,cf 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'); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F1 0123456789 + F2 abcdefghij + CF_BEFORE_ALTERING 0123456789 - abcdefghij + + FIELD_NAME CF + COMPUTED_SOURCE_BEFORE_ALTERING (f1 || ' - ' || f2) + + F1 0123456789 + F2 abcdefghij + CF_AFTER_ALTERING 0123456789 - abcdefghij + + FIELD_NAME CF + COMPUTED_SOURCE_AFTER_ALTERING (f1 || ' - ' || f2) + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER TABLE T failed + -Cannot add or remove COMPUTED from column CF + """ + +@pytest.mark.version('>=3.0') +def test_core_0847_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0850.py b/tests/bugs/test_core_0850.py new file mode 100644 index 00000000..354a259c --- /dev/null +++ b/tests/bugs/test_core_0850.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: bugs.core_0850 +# title: DYN allows to set defaults for computed fields when altering a field +# decription: +# tracker_id: CORE-850 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_850 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t2(a int, b int computed by (00)); +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """alter table t2 alter b set default 5; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """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_core_0850_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_0851.py b/tests/bugs/test_core_0851.py new file mode 100644 index 00000000..face4437 --- /dev/null +++ b/tests/bugs/test_core_0851.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: bugs.core_0851 +# title: Field can be used multiple times in multi-segment index definition +# decription: +# tracker_id: CORE-851 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_851-250 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t (i integer); +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """create index ti on t(i,i); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42000 +unsuccessful metadata update +-CREATE INDEX TI failed +-Field I cannot be used twice in index TI +""" + +@pytest.mark.version('>=3.0') +def test_core_0851_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_0852.py b/tests/bugs/test_core_0852.py new file mode 100644 index 00000000..7cf56327 --- /dev/null +++ b/tests/bugs/test_core_0852.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: bugs.core_852 +# title: substring(current_user from 4) fails +# decription: select substring( current_user from 4) from rdb$database; +# fails on string truncation +# tracker_id: CORE-852 +# min_versions: [] +# versions: 2.0 +# qmid: bugs.core_852 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select substring(current_user from 4) from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + SUBSTRING DBA + """ + +@pytest.mark.version('>=2.0') +def test_core_852_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0855.py b/tests/bugs/test_core_0855.py new file mode 100644 index 00000000..f8017ccf --- /dev/null +++ b/tests/bugs/test_core_0855.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: bugs.core_0855 +# title: Aggregates in the WHERE clause vs derived tables +# decription: Aggregates in the WHERE clause vs derived tables +# tracker_id: CORE-855 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_855-250 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select * from ( + select rdb$relation_id + from rdb$database +) +where sum(rdb$relation_id) = 0; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42000 +Dynamic SQL Error +-SQL error code = -104 +-Cannot use an aggregate or window function in a WHERE clause, use HAVING (for aggregate only) instead +""" + +@pytest.mark.version('>=3.0') +def test_core_0855_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_0856.py b/tests/bugs/test_core_0856.py new file mode 100644 index 00000000..405c1450 --- /dev/null +++ b/tests/bugs/test_core_0856.py @@ -0,0 +1,79 @@ +#coding:utf-8 +# +# id: bugs.core_0856 +# title: Unable to set FName, MName, LName fields in security to blank +# decription: +# tracker_id: CORE-856 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_856 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter user tmp$c0856 password '123' + firstname '....:....1....:....2....:....3..' + middlename '....:....1....:....2....:....3..' + lastname '....:....1....:....2....:....3..' + ; + commit; + 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'); + + alter user tmp$c0856 + firstname '' + middlename _ascii x'09' + lastname _ascii x'0A' + ; + + commit; + select + sec$user_name, + octet_length(sec$first_name), + octet_length(sec$middle_name), + octet_length(sec$last_name), + ascii_val(left(sec$first_name,1)), + ascii_val(left(sec$middle_name,1)), + ascii_val(left(sec$last_name,1)) + from sec$users where upper(sec$user_name)=upper('tmp$c0856'); + commit; + + drop user tmp$c0856; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + SEC$USER_NAME TMP$C0856 + SEC$FIRST_NAME ....:....1....:....2....:....3.. + SEC$MIDDLE_NAME ....:....1....:....2....:....3.. + SEC$LAST_NAME ....:....1....:....2....:....3.. + + SEC$USER_NAME TMP$C0856 + OCTET_LENGTH + OCTET_LENGTH 1 + OCTET_LENGTH 1 + ASCII_VAL + ASCII_VAL 9 + ASCII_VAL 10 + """ + +@pytest.mark.version('>=3.0') +def test_core_0856_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0857.py b/tests/bugs/test_core_0857.py new file mode 100644 index 00000000..0bbe10a7 --- /dev/null +++ b/tests/bugs/test_core_0857.py @@ -0,0 +1,94 @@ +#coding:utf-8 +# +# id: bugs.core_857 +# title: Containing not working correctly +# decription: +# Could not find build 2.0 RC3. +# Checked on: +# 4.0.0.1713 SS: 1.625s. +# 4.0.0.1346 SC: 1.675s. +# 3.0.5.33218 SS: 1.000s. +# 3.0.5.33084 SC: 0.890s. +# 2.5.9.27149 SC: 0.266s. +# +# 02-mar-2021. Re-implemented in ordeer to have ability to run this test on Linux. +# We run 'init_script' using charset = utf8 but then run separate ISQL-process +# with request to establish connection using charset = win1252. +# +# Checked on: +# * Windows: 4.0.0.2377, 3.0.8.33420, 2.5.9.27152 +# * Linux: 4.0.0.2377, 3.0.8.33415 +# +# tracker_id: CORE-857 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + 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_1 = db_factory(charset='WIN1252', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# sql_cmd=''' +# set names win1252; +# connect '%(dsn)s' user '%(user_name)s' password '%(user_password)s'; +# 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; +# ''' % dict(globals(), **locals()) +# runProgram( 'isql', [ '-q' ], sql_cmd) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CONNECTION_CSET WIN1252 + test_1 result: + test_2 result: 1 + ci_ai result: 1 + between result: 1 + octet_length diff: 1 + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_857_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_0858.py b/tests/bugs/test_core_0858.py new file mode 100644 index 00000000..b40288ef --- /dev/null +++ b/tests/bugs/test_core_0858.py @@ -0,0 +1,107 @@ +#coding:utf-8 +# +# id: bugs.core_858 +# title: Server crash when using UDF +# decription: +# Checked on: +# 2.5.9.27126: OK, 0.594s. +# 3.0.5.33086: OK, 1.343s. +# 4.0.0.1378: OK, 6.969s. +# +# 24.01.2019. +# Disabled this test to be run on FB 4.0: added record to '%FBT_REPO% ests\\qa4x-exclude-list.txt'. +# +# 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/ +# +# UDF function 'sright' has direct built-in analog 'right', there is no UDR function for it. +# +# tracker_id: CORE-858 +# min_versions: [] +# versions: 3.0, 4.0 +# qmid: bugs.core_858 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + declare external function sright + varchar(100) by descriptor, smallint, + varchar(100) by descriptor returns parameter 3 + entry_point 'right' module_name 'fbudf'; + + commit; + + set list on; + select + rdb$function_name + ,rdb$function_type + ,rdb$module_name + ,rdb$entrypoint + ,rdb$return_argument + ,rdb$system_flag + ,rdb$legacy_flag + from rdb$functions where upper(rdb$function_name) = upper('sright'); + + select sright('qwerty', 2) as sright_result from rdb$database; + commit; + + drop external function sright; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$FUNCTION_NAME SRIGHT + RDB$FUNCTION_TYPE + RDB$MODULE_NAME fbudf + RDB$ENTRYPOINT right + RDB$RETURN_ARGUMENT 3 + RDB$SYSTEM_FLAG 0 + RDB$LEGACY_FLAG 1 + + SRIGHT_RESULT ty + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_core_858_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + -- This section was intentionally left empty. + -- No message should be in expected_* sections. + -- It is STRONGLY RECOMMENDED to add this ticket + -- in the 'excluded-list file: + -- %FBT_REPO% ests\\qa4x-exclude-list.txt + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + + +@pytest.mark.version('>=4.0') +def test_core_858_2(act_2: Action): + act_2.execute() + diff --git a/tests/bugs/test_core_0859.py b/tests/bugs/test_core_0859.py new file mode 100644 index 00000000..aaad131f --- /dev/null +++ b/tests/bugs/test_core_0859.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: bugs.core_0859 +# title: Sorting is allowed for blobs and arrays +# decription: This one is supposed to fail for now, as we restored the legacy behavior until we're able to implement DISTINCT for blobs properly +# tracker_id: CORE-859 +# min_versions: [] +# versions: 9.1 +# qmid: bugs.core_859 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 9.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t (i integer, b blob sub_type text, a integer [5]); +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# c = db_conn.cursor() +# try: +# c.prep('select * from t order by b') +# except: +# pass +# else: +# print ('Test Failed in case 1') +# +# try: +# c.prep('select * from t order by a') +# except: +# pass +# else: +# print ('Test Failed in case 2') +# +# try: +# c.prep('select b, count(*) from t group by b') +# except: +# pass +# else: +# print ('Test Failed in case 3') +# +# try: +# c.prep('select a, count(*) from t group by a') +# except: +# pass +# else: +# print ('Test Failed in case 4') +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=9.1') +@pytest.mark.xfail +def test_core_0859_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_0866.py b/tests/bugs/test_core_0866.py new file mode 100644 index 00000000..f680a8e4 --- /dev/null +++ b/tests/bugs/test_core_0866.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: bugs.core_866 +# title: Removing a NOT NULL constraint is not visible until reconnect +# decription: +# tracker_id: CORE-866 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_866 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table test ( + id integer not null, + col varchar(20) not null + ); + insert into test (id, col) values (1, 'data'); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + update rdb$relation_fields + set rdb$null_flag = null + where (rdb$field_name = upper('col')) and (rdb$relation_name = upper('test')); + commit; + + update test set col = null where id = 1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + UPDATE operation is not allowed for system table RDB$RELATION_FIELDS + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."COL", value "*** null ***" + """ + +@pytest.mark.version('>=3.0') +def test_core_866_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_0870.py b/tests/bugs/test_core_0870.py new file mode 100644 index 00000000..076e6973 --- /dev/null +++ b/tests/bugs/test_core_0870.py @@ -0,0 +1,38 @@ +#coding:utf-8 +# +# id: bugs.core_0870 +# title: Engine crashes while trying to backup a logically corrupt db +# decription: This test works only for fb 2.1-2.5 and was converted to dummy one for 3.0 as it needs specificaly corrupted database. We don't have such database with ODS 12 required by fb 3.0+ +# tracker_id: CORE-870 +# min_versions: ['2.1'] +# versions: 3.0 +# qmid: bugs.core_870 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; select 'Extracted .fdb file has not supported ODS for using on Firebird 3.0' as msg from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG Extracted .fdb file has not supported ODS for using on Firebird 3.0 + """ + +@pytest.mark.version('>=3.0') +def test_core_0870_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0871.py b/tests/bugs/test_core_0871.py new file mode 100644 index 00000000..6a0e59ee --- /dev/null +++ b/tests/bugs/test_core_0871.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_871 +# title: Incorrect handling of null within view - returns 0 +# decription: +# tracker_id: CORE-871 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_871 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE DOMAIN D INTEGER NOT NULL; +CREATE TABLE T (A D); +CREATE TABLE U (B D); +CREATE VIEW V (A, B) AS +SELECT T.A, U.B FROM T LEFT JOIN U ON (T.A = U.B); + +COMMIT; + +INSERT INTO T VALUES(1); +COMMIT; + +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT * FROM V; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """A B +============ ============ + 1 + +""" + +@pytest.mark.version('>=2.1') +def test_core_871_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0878.py b/tests/bugs/test_core_0878.py new file mode 100644 index 00000000..6cad1474 --- /dev/null +++ b/tests/bugs/test_core_0878.py @@ -0,0 +1,74 @@ +#coding:utf-8 +# +# id: bugs.core_878 +# title: problem when dropping column that is a primary key +# decription: +# tracker_id: CORE-878 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_878 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """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 pk3 (i1 integer not null primary key, i2 integer); +commit; +show table pk3; +alter table pk3 drop i1; +commit; + +show table pk1; + +show table pk2; + +show table pk3; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """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('>=2.1') +def test_core_878_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0879.py b/tests/bugs/test_core_0879.py new file mode 100644 index 00000000..06a8d16e --- /dev/null +++ b/tests/bugs/test_core_0879.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_879 +# title: Dependencies are not cleared when creation of expression index fails +# decription: +# tracker_id: CORE-879 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table tab ( a varchar(10000) ); + commit; + create index ix on tab computed by (upper(a)); + drop table tab; + commit; + show table tab; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -key size exceeds implementation restriction for index "IX" + There is no table TAB in this database + """ + +@pytest.mark.version('>=2.5') +def test_core_879_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_0881.py b/tests/bugs/test_core_0881.py new file mode 100644 index 00000000..a2a3a6e3 --- /dev/null +++ b/tests/bugs/test_core_0881.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: bugs.core_881 +# title: Singleton isn't respected in COMPUTED BY expressions +# decription: +# tracker_id: CORE-881 +# min_versions: [] +# versions: 2.5.0 +# qmid: bugs.core_881-250 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t1 (n integer); +create table t2 (n integer, c computed by ((select n from t1))); + +insert into t1 values (1); +insert into t1 values (2); +insert into t2 values (1); +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select * from t2; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """N C +============ ============ +""" +expected_stderr_1 = """Statement failed, SQLSTATE = 21000 +multiple rows in singleton select +""" + +@pytest.mark.version('>=2.5.0') +def test_core_881_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0883.py b/tests/bugs/test_core_0883.py new file mode 100644 index 00000000..57bdc55a --- /dev/null +++ b/tests/bugs/test_core_0883.py @@ -0,0 +1,141 @@ +#coding:utf-8 +# +# id: bugs.core_883 +# title: The built-in BLR printer doesn't support all FB2 features +# decription: +# tracker_id: CORE-883 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_883 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('RDB\\$PROCEDURE_BLR.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core0883-ods12.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + set blob all; + select rdb$procedure_blr + from rdb$procedures + where rdb$procedure_name = upper('sp1'); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +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, + + 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 + """ + +@pytest.mark.version('>=3.0') +def test_core_883_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0885.py b/tests/bugs/test_core_0885.py new file mode 100644 index 00000000..c9e63eda --- /dev/null +++ b/tests/bugs/test_core_0885.py @@ -0,0 +1,182 @@ +#coding:utf-8 +# +# id: bugs.core_0885 +# title: It is impossible to take away rights on update of a column +# decription: +# tracker_id: CORE-885 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('-Effective user is.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set wng off; + set list on; + + create or alter user john_senior password 'sen' revoke admin role; + create or alter user mick_junior password 'jun' revoke admin role; + commit; + + 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 user john_senior; + drop user mick_junior; + drop role modifier; + drop table test; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 28000 + no permission for UPDATE access to TABLE TEST + """ + +@pytest.mark.version('>=3.0') +def test_core_0885_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0886.py b/tests/bugs/test_core_0886.py new file mode 100644 index 00000000..03f9d004 --- /dev/null +++ b/tests/bugs/test_core_0886.py @@ -0,0 +1,60 @@ +#coding:utf-8 +# +# id: bugs.core_0886 +# title: SPs in views +# decription: +# tracker_id: CORE-886 +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """set term !!; +create procedure MY_PROCEDURE (input1 INTEGER) +returns (output1 INTEGER) +as begin + output1 = input1+1; + suspend; +end !! +set term ;!! +commit; + +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """create view a_view as +select * from MY_PROCEDURE(1); +commit; +show view a_view; +select *from a_view; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Database: localhost:C: btest2 mpugs.core_0886.fdb, User: SYSDBA +SQL> CON> SQL> SQL> OUTPUT1 INTEGER Nullable +View Source: +==== ====== + +select * from MY_PROCEDURE(1) +SQL> + OUTPUT1 +============ + 2 + +SQL> SQL>""" + +@pytest.mark.version('>=2.5.0') +def test_core_0886_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0888.py b/tests/bugs/test_core_0888.py new file mode 100644 index 00000000..eb71a619 --- /dev/null +++ b/tests/bugs/test_core_0888.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: bugs.core_888 +# title: DDL - object in use +# decription: +# tracker_id: CORE-888 +# min_versions: [] +# versions: 2.0.1 +# qmid: bugs.core_888 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET TERM ^ ; +CREATE PROCEDURE TestProc +AS +BEGIN + EXIT; +END ^ +SET TERM ; ^ + +EXECUTE PROCEDURE TestProc; + +DROP PROCEDURE TestProc; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.0.1') +def test_core_888_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_0896.py b/tests/bugs/test_core_0896.py new file mode 100644 index 00000000..956f3b2c --- /dev/null +++ b/tests/bugs/test_core_0896.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: bugs.core_896 +# title: SUBSTRING with NULL offset or length don't return NULL +# decription: +# tracker_id: CORE-896 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_896 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select substring('abc' from null) from rdb$database; +select substring('abc' from 2 for null) from rdb$database; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """SUBSTRING +========= + + +SUBSTRING +========= + + +""" + +@pytest.mark.version('>=2.1') +def test_core_896_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0899.py b/tests/bugs/test_core_0899.py new file mode 100644 index 00000000..86601b7c --- /dev/null +++ b/tests/bugs/test_core_0899.py @@ -0,0 +1,142 @@ +#coding:utf-8 +# +# id: bugs.core_899 +# title: Problems with explicit cursors in unwanted states +# decription: +# tracker_id: CORE-899 +# min_versions: [] +# versions: 2.5.0 +# qmid: bugs.core_899-250 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [('line:\\s[0-9]+,', 'line: x'), ('col:\\s[0-9]+', 'col: y')] + +init_script_1 = """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_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select * from SP_OK; +select * from SP_CLOSED; +select * from SP_NOTOPEN; +select * from SP_FETCHED; + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID TXT +============ ============================== + 1 Text description + + + ID TXT +============ ============================== + 1 OK + + ID TXT +============ ============================== + + ID TXT +============ ============================== + 1 OK +""" +expected_stderr_1 = """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 +""" + +@pytest.mark.version('>=2.5.0') +def test_core_899_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0903.py b/tests/bugs/test_core_0903.py new file mode 100644 index 00000000..8d506b3f --- /dev/null +++ b/tests/bugs/test_core_0903.py @@ -0,0 +1,68 @@ +#coding:utf-8 +# +# id: bugs.core_0903 +# title: New value of column is accessable before update +# decription: +# tracker_id: CORE-903 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE TEST ( + T1 INTEGER, + T2 INTEGER, + T3 INTEGER, + T4 INTEGER +); + +Insert into test (T1, T2, T3, T4) values ( 0, 0 , 0, 0); + +SET TERM ^ ; + +CREATE OR ALTER PROCEDURE CH_TEST ( + num integer) +as +begin + +update TEST + set + T1= T1 + T2 + T3 + T4 + :NUM + ,T2= T1 + T2 + T3 + T4 + :NUM + ,T3= T1 + T2 + T3 + T4 + :NUM + ,T4= T1 + T2 + T3 + T4 + :NUM + ; + +end^ + +SET TERM ; ^ +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """execute procedure ch_test( 1 ); +select * from test; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + T1 T2 T3 T4 +============ ============ ============ ============ + 1 1 1 1 + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_0903_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0907.py b/tests/bugs/test_core_0907.py new file mode 100644 index 00000000..b53ee509 --- /dev/null +++ b/tests/bugs/test_core_0907.py @@ -0,0 +1,87 @@ +#coding:utf-8 +# +# id: bugs.core_907 +# title: Server crash on violation of NOT NULL constraint +# decription: +# tracker_id: CORE-907 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_907-250 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table crash (a1 integer,a2 integer,a3 integer, a4 integer) ; + commit; + insert into crash (a1, a2, a3, a4) values ( 1, 2, 3, 4); + insert into crash (a1, a2, a3 ) values ( 2, 3, 4 ); + insert into crash (a1, a2, a4) values ( 2, 3, 4); + commit; + alter table crash add a5 computed by (a2*a3*a4); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Since 3.0 one may do like this (and NOT by updating RDB tables): + -- ALTER TABLE ALTER [NOT] NULL + -- ALTER DOMAIN [NOT] NULL + -- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + -- 02.04.2015: since rev. 61204 (build 3.0.0.31767)syntax of altering nullability for + -- domains and tables has been changed: mandatory SET | DROP clause now needed, i.e.: + -- ALTER TABLE
ALTER {DROP | SET} NOT NULL + -- ALTER DOMAIN {DROP | SET} NOT NULL + -- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + + -- This attempt will FAIL with message: + -- -Cannot make field A5 of table CRASH NOT NULL because there are NULLs present + alter table crash alter a5 SET not null; + commit; + + update crash set a3=1 where a3 is null; + update crash set a4=1 where a4 is null; + commit; + + alter table crash alter a1 SET not null; + alter table crash alter a2 SET not null; + alter table crash alter a3 SET not null; + alter table crash alter a4 SET not null; + alter table crash alter a5 SET not null; + commit; + update crash set a1=null, a2=null, a3=null,a4=null rows 1; + commit; + show table crash; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A1 INTEGER Not Null + A2 INTEGER Not Null + A3 INTEGER Not Null + A4 INTEGER Not Null + A5 Computed by: (a2*a3*a4) + """ +expected_stderr_1 = """ + 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 ***" + """ + +@pytest.mark.version('>=3.0') +def test_core_907_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0908.py b/tests/bugs/test_core_0908.py new file mode 100644 index 00000000..af0563c3 --- /dev/null +++ b/tests/bugs/test_core_0908.py @@ -0,0 +1,153 @@ +#coding:utf-8 +# +# id: bugs.core_0908 +# title: Garbage in plan output of complex statement +# decription: 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. +# tracker_id: CORE-908 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_908 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """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_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """set plan on; +select * from big_plan ; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (BIG_PLAN NATURAL) +X +============ +1 +""" + +@pytest.mark.version('>=3.0') +def test_core_0908_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0924.py b/tests/bugs/test_core_0924.py new file mode 100644 index 00000000..9a73a1a4 --- /dev/null +++ b/tests/bugs/test_core_0924.py @@ -0,0 +1,57 @@ +#coding:utf-8 +# +# id: bugs.core_0924 +# title: An attempt to select DB_KEY from a procedure crashes the server +# decription: +# tracker_id: CORE-924 +# min_versions: [] +# versions: 2.5 +# qmid: bugs.core_924-250 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('line\\s[0-9]+,', 'line x'), ('column\\s[0-9]+', 'column y')] + +init_script_1 = """CREATE TABLE T1 (ID1 INTEGER NOT NULL); +SET TERM ^; +CREATE PROCEDURE AP +returns (output1 INTEGER) +AS +BEGIN + FOR SELECT ID1 FROM T1 INTO :output1 + DO + BEGIN + SUSPEND; + END +END ^ +SET TERM ;^ +COMMIT; +INSERT INTO T1 VALUES (1); +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT RDB$DB_KEY from AP; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42S22 +Dynamic SQL Error +-SQL error code = -206 +-Column unknown +-DB_KEY +-At line 1, column 8 +""" + +@pytest.mark.version('>=2.5') +def test_core_0924_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_0925.py b/tests/bugs/test_core_0925.py new file mode 100644 index 00000000..f8f0acbc --- /dev/null +++ b/tests/bugs/test_core_0925.py @@ -0,0 +1,68 @@ +#coding:utf-8 +# +# id: bugs.core_925 +# title: ALL predicate works incorrectly for some subqueries +# decription: +# tracker_id: CORE-925 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_925 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE STAFF (EMPNUM CHAR(3) NOT NULL UNIQUE, + EMPNAME CHAR(20), + GRADE DECIMAL(4), + CITY CHAR(15)); + CREATE TABLE WORKS ( EMPNUM CHAR(3) NOT NULL, + PNUM CHAR(3) NOT NULL, + HOURS DECIMAL(5), + UNIQUE(EMPNUM,PNUM)); + COMMIT; + + INSERT INTO STAFF VALUES ('E1','Alice',12,'Deale'); + INSERT INTO STAFF VALUES ('E2','Betty',10,'Vienna'); + INSERT INTO STAFF VALUES ('E3','Carmen',13,'Vienna'); + INSERT INTO STAFF VALUES ('E4','Don',12,'Deale'); + INSERT INTO STAFF VALUES ('E5','Ed',13,'Akron'); + + INSERT INTO WORKS VALUES ('E1','P1',40); + INSERT INTO WORKS VALUES ('E1','P2',20); + INSERT INTO WORKS VALUES ('E1','P3',80); + INSERT INTO WORKS VALUES ('E1','P4',20); + INSERT INTO WORKS VALUES ('E1','P5',12); + INSERT INTO WORKS VALUES ('E1','P6',12); + INSERT INTO WORKS VALUES ('E2','P1',40); + INSERT INTO WORKS VALUES ('E2','P2',80); + INSERT INTO WORKS VALUES ('E3','P2',20); + INSERT INTO WORKS VALUES ('E4','P2',20); + INSERT INTO WORKS VALUES ('E4','P4',40); + INSERT INTO WORKS VALUES ('E4','P5',80); + COMMIT; +""" + +db_1 = db_factory(charset='ISO8859_1', sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT EMPNUM +FROM WORKS +GROUP BY EMPNUM +HAVING EMPNUM = ALL + ( SELECT WORKS.EMPNUM + FROM WORKS JOIN STAFF ON WORKS.EMPNUM = STAFF.EMPNUM ); + + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1') +def test_core_925_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_0927.py b/tests/bugs/test_core_0927.py new file mode 100644 index 00000000..6d57eaf8 --- /dev/null +++ b/tests/bugs/test_core_0927.py @@ -0,0 +1,90 @@ +#coding:utf-8 +# +# id: bugs.core_0927 +# title: Grants don't work for procedures used inside views +# decription: +# Checked on: 4.0.0.1635: OK, 2.209s; 3.0.5.33180: OK, 1.838s; 2.5.9.27119: OK, 0.292s. +# +# tracker_id: CORE-927 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set wng off; + set list on; + + -- Drop old account if it remains from prevoius run: + set term ^; + execute block as + begin + begin + execute statement 'drop user tmp$c0927' with autonomous transaction; + when any do begin end + end + end^ + set term ;^ + commit; + + create user tmp$c0927 password '123'; + commit; + revoke all on all from tmp$c0927; + commit; + + create or alter view v_test as select 1 id from rdb$database; + commit; + + set term ^; + create or alter procedure sp_test returns (result integer) as + begin + result = 1; + suspend; + end + ^ + set term ;^ + commit; + + create or alter view v_test as + select (select result from sp_test) as result from rdb$database; + + grant execute on procedure sp_test to view v_test; + grant select on v_test to tmp$c0927; + commit; + + ------------------------------------------------- + connect '$(DSN)' user 'tmp$c0927' password '123'; + ------------------------------------------------- + select current_user as who_am_i, v.* from v_test v; + commit; + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + + drop user tmp$c0927; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHO_AM_I TMP$C0927 + RESULT 1 + """ + +@pytest.mark.version('>=2.5.2') +def test_core_0927_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0929.py b/tests/bugs/test_core_0929.py new file mode 100644 index 00000000..ad8bf31e --- /dev/null +++ b/tests/bugs/test_core_0929.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_0929 +# title: Bug in DSQL parameter +# decription: +# tracker_id: CORE-929 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_929 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE TEST (MYDATE DATE NOT NULL PRIMARY KEY); +COMMIT; + +INSERT INTO TEST VALUES (CURRENT_DATE); +INSERT INTO TEST VALUES (CURRENT_DATE + 1); +INSERT INTO TEST VALUES (CURRENT_DATE + 2); +INSERT INTO TEST VALUES (CURRENT_DATE + 3); +COMMIT; + +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# c = db_conn.cursor() +# try: +# c.prep('SELECT * FROM TEST WHERE MYDATE + CAST(? AS INTEGER) >= ?') +# except Exception,e: +# print ('Test FAILED') +# print (e) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1') +@pytest.mark.xfail +def test_core_0929_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_0932.py b/tests/bugs/test_core_0932.py new file mode 100644 index 00000000..fda973e5 --- /dev/null +++ b/tests/bugs/test_core_0932.py @@ -0,0 +1,48 @@ +#coding:utf-8 +# +# id: bugs.core_0932 +# title: Comment in create database +# decription: Accept comment in Create database +# tracker_id: CORE-932 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: bugs.core_932p + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + commit; + create database /* foo */ '$(DATABASE_LOCATION)tmp_c0932_1.fdb'; + select iif( m.mon$database_name containing 'tmp_c0932_1', 'OK', 'FAIL' ) as result_1 from mon$database m; + commit; + drop database; + create database /*/**//**/'$(DATABASE_LOCATION)tmp_c0932_2.fdb'/*/**//**//**//*/**/; + select iif( m.mon$database_name containing 'tmp_c0932_2', 'OK', 'FAIL' ) as result_2 from mon$database m; + commit; + drop database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT_1 OK + RESULT_2 OK + """ + +@pytest.mark.version('>=2.5') +def test_core_0932_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0945.py b/tests/bugs/test_core_0945.py new file mode 100644 index 00000000..a417c313 --- /dev/null +++ b/tests/bugs/test_core_0945.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: bugs.core_0945 +# title: Bad error message when tring to create FK to non-existent table +# decription: +# tracker_id: CORE-945 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_945-250 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE TABLE TAB_TestA ( + UID INTEGER NOT NULL PRIMARY KEY +); + +CREATE TABLE TAB_TestB ( + UID INTEGER NOT NULL PRIMARY KEY, + TestA INTEGER CONSTRAINT FK_TestA REFERENCES TABTestA(UID) ON UPDATE CASCADE +); + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42000 +unsuccessful metadata update +-CREATE TABLE TAB_TESTB failed +-Table TABTESTA not found +""" + +@pytest.mark.version('>=3.0') +def test_core_0945_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_0952.py b/tests/bugs/test_core_0952.py new file mode 100644 index 00000000..c000b8a7 --- /dev/null +++ b/tests/bugs/test_core_0952.py @@ -0,0 +1,55 @@ +#coding:utf-8 +# +# id: bugs.core_952 +# title: AV when blob is used in expression index +# decription: +# tracker_id: CORE-952 +# min_versions: [] +# versions: 2.0.1 +# qmid: bugs.core_952 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table T ( + ID integer not null, + N1 blob sub_type 1 segment size 80, + N2 varchar(10) +); +commit; + +insert into T (ID, N1, N2) values (1, 'www', 'qwer'); +commit; + +alter table T add constraint PK_T primary key (ID); +create index T_IDX on T computed by (cast(substring(N1 from 1 for 100) as varchar(100))); +commit; + +update T set T.N2 = 'asdf' where T.ID = 1; +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT ID,N2 FROM T; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ID N2 +============ ========== + 1 asdf + +""" + +@pytest.mark.version('>=2.0.1') +def test_core_952_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0959.py b/tests/bugs/test_core_0959.py new file mode 100644 index 00000000..37778944 --- /dev/null +++ b/tests/bugs/test_core_0959.py @@ -0,0 +1,164 @@ +#coding:utf-8 +# +# id: bugs.core_0959 +# title: GSTAT does not work using the localhost connection string +# decription: +# Refactored 17.11.2017. Covers ticket CORE-5629. +# +# For 3.0+ we check in log of GSTAT presense of following lines: +# * with timestamp of GSTAT start +# * with DB name +# * with DB attributes +# * with table 'TEST' pointer page and index root page numbers +# * with count of data pages and average fill for table 'TEST' +# * with number of index root page, depath of index and number of buckets and nodes for index 'TEST_S' +# * with timestamp of GSTAT finish. +# If line from log matches to any of pattenrs then we do output if this line for checking in 'expected_stdout' section. +# Otherwise line is ignored. +# +# Check is done using regexp searches -- see definition of patterns hdr_dbname_ptn, hdr_dbattr_ptn, table_ppip_ptn etc. +# +# For 2.5.x check was changed only by added line with with timestamp of GSTAT start in 'expected_stdout' section. +# +# Checked on: +# FB25SC, build 2.5.8.27078: OK, 0.297s. +# FB30SS, build 3.0.3.32837: OK, 2.344s. +# FB40SS, build 4.0.0.800: OK, 2.437s. +# +# tracker_id: CORE-959 +# min_versions: ['2.5'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('Database ".*', 'Database'), ('Gstat execution time .*', 'Gstat execution time'), ('Attributes .*', 'Attributes'), ('Primary pointer page: \\d+, Index root page: \\d+\\s*', 'Primary pointer page, Index root page'), ('Data pages: \\d+, average fill: \\d+[percent_sign]', 'Data pages, average fill'), ('Root page: \\d+, depth: \\d+, leaf buckets: \\d+, nodes: \\d+\\s*', 'Root page, depth, leaf buckets, nodes'), ('Gstat completion time .*', 'Gstat completion time')] + +init_script_1 = """ + create sequence g; + create table test(id int primary key using index test_id_pk); + commit; + insert into test(id) select gen_id(g,1) from rdb$types,rdb$types rows 1000; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# import time +# import re +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# hdr_dbname_ptn=re.compile('Database\\s+"', re.IGNORECASE) +# hdr_dbattr_ptn=re.compile('Attributes\\s+\\.*', re.IGNORECASE) +# table_ppip_ptn=re.compile('Primary\\s+pointer\\s+page:\\s+\\d+,\\s+Index root page:\\s+\\d+\\s*', re.IGNORECASE) +# table_dpaf_ptn=re.compile('Data\\s+pages:\\s+\\d+,\\s+average\\s+fill:\\s+\\d+%\\s*', re.IGNORECASE) +# index_root_ptn=re.compile('Root\\s+page:\\s+\\d+,\\s+depth:\\s+\\d+,\\s+leaf\\s+buckets:\\s+\\d+,\\s+nodes:\\s+\\d+\\s*', re.IGNORECASE) +# +# gstat_init_ptn=re.compile('Gstat\\s+execution\\s+time\\s+', re.IGNORECASE) +# gstat_fini_ptn=re.compile('Gstat\\s+completion\\s+time\\s+', re.IGNORECASE) +# +# watched_ptn_list=( +# hdr_dbname_ptn +# ,hdr_dbattr_ptn +# ,table_ppip_ptn +# ,table_dpaf_ptn +# ,index_root_ptn +# ,gstat_init_ptn +# ,gstat_fini_ptn +# ) +# db_name=db_conn.database_name +# db_conn.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'): +# # otherwise: "OSError: [Errno 9] Bad file descriptor"! +# os.fsync(file_handle.fileno()) +# file_handle.close() +# +# #-------------------------------------------- +# +# f_dbstat_log = open( os.path.join(context['temp_directory'],'tmp_local_host_0959.log'), 'w') +# f_dbstat_err = open( os.path.join(context['temp_directory'],'tmp_local_host_0959.err'), 'w') +# context['isql_path'] +# subprocess.check_call([context['fbsvcmgr_path'] +# ,"localhost:service_mgr" +# ,"action_db_stats" +# ,"dbname", db_name +# ,"sts_record_versions" +# ,"sts_data_pages" +# ,"sts_idx_pages" +# ], +# stdout=f_dbstat_log, +# stderr=f_dbstat_err +# ) +# +# flush_and_close( f_dbstat_log ) +# flush_and_close( f_dbstat_err ) +# +# with open( f_dbstat_log.name,'r') as f: +# for line in f: +# if line.split(): +# for p in watched_ptn_list: +# if p.search( line ): +# print( ' '.join(line.replace('%','[percent_sign]').split()) ) +# +# with open( f_dbstat_err.name,'r') as f: +# for line in f: +# if line.split(): +# print('UNEXPECTED STDERR in '+f_dbstat_err.name+': '+line) +# +# +# ##################### +# # Cleanup. +# time.sleep(1) +# +# f_list=( +# f_dbstat_log +# ,f_dbstat_err +# ) +# +# for i in range(len(f_list)): +# if os.path.isfile(f_list[i].name): +# os.remove(f_list[i].name) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Database "C:\\MIX\\FIREBIRD\\QA\\FBT-REPO\\TMP\\BUGS.CORE_0959.FDB" + Gstat execution time Fri Nov 17 12:37:29 2017 + Attributes force write + Primary pointer page: 193, Index root page: 194 + Data pages: 7, average fill: 45[percent_sign] + Root page: 197, depth: 1, leaf buckets: 1, nodes: 1000 + Gstat completion time Fri Nov 17 12:37:29 2017 + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_0959_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_0965.py b/tests/bugs/test_core_0965.py new file mode 100644 index 00000000..9a88b191 --- /dev/null +++ b/tests/bugs/test_core_0965.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: bugs.core_965 +# title: Many aggregate functions within a single select list may cause a server crash +# decription: This test may crash the server. +# tracker_id: CORE-965 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_965-250 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table tagg (col varchar(30000)) ; + +insert into tagg (col) values ('0123456789') ; +commit ; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select 1 from ( + select col as f1, min(col) as f2, max(col) as f3 + from tagg + group by 1 +) ; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CONSTANT +============ + 1 +""" + +@pytest.mark.version('>=3.0') +def test_core_965_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0967.py b/tests/bugs/test_core_0967.py new file mode 100644 index 00000000..b7840015 --- /dev/null +++ b/tests/bugs/test_core_0967.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: bugs.core_0967 +# title: SQL with incorrect characters (outside the ASCII range) may be processed wrongly +# decription: +# tracker_id: CORE-967 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_967 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t (i integer); +insert into t values (0); +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# c = db_conn.cursor() +# try: +# c.execute('update t set i=1'+chr(238)+' where 1=0') +# except Exception,e: +# msg = repr(e[0]) +# msg = msg.replace(chr(92),"/") +# print (msg) +# else: +# c.execute('select * from t') +# printData(c) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """'Error while preparing SQL statement:/n- SQLCODE: -104/n- Dynamic SQL Error/n- SQL error code = -104/n- Token unknown - line 1, column 17/n- /xee' +""" + +@pytest.mark.version('>=2.1') +@pytest.mark.xfail +def test_core_0967_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_0972.py b/tests/bugs/test_core_0972.py new file mode 100644 index 00000000..1ed45691 --- /dev/null +++ b/tests/bugs/test_core_0972.py @@ -0,0 +1,66 @@ +#coding:utf-8 +# +# id: bugs.core_972 +# title: Case insensitive collation for UTF-8 +# decription: Basic test for case-insensitive comparison of char and blob fields with text literals. Use non-ascii text here. +# tracker_id: CORE-972 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: bugs.core_972 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('BLOB_ID .*', '')] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- 2.5.8.27062: OK, 1.297s. + -- 2.5.8.27065: OK, 0.719s. + -- 3.0.3.32727: OK, 2.609s. + -- 3.0.3.32738: OK, 1.375s. + -- 4.0.0.651: OK, 2.547s. + -- 4.0.0.680: OK, 1.141s. + + create table test(fc varchar(50) collate unicode_ci, fb blob sub_type 1collate unicode_ci); + commit; + insert into test(fc,fb) values ('bibliothèque Éditeur', 'mêlés à des OBJETS DE L''EXTRÊME-Orient'); + insert into test(fc,fb) values ('bibliothÈque éditeur', 'MÊlés à des objETS DE l''extrême-orient'); + commit; + set list on; + set blob all; + set count on; + select fc as blob_id from test + where fc='BiblioTHÈQUE ÉDiteuR' + + UNION ALL + + select fb as blob_id from test + where fb + between 'MÊLÉS À DES OBJETS DE L''EXTRÊME-ORIENT' + and 'mÊLÉS À des objETS DE L''EXTRÊME-ORIENT' + order by 1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + bibliothèque Éditeur + bibliothÈque éditeur + mêlés à des OBJETS DE L'EXTRÊME-Orient + MÊlés à des objETS DE l'extrême-orient + Records affected: 4 + """ + +@pytest.mark.version('>=2.5') +def test_core_972_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0979.py b/tests/bugs/test_core_0979.py new file mode 100644 index 00000000..737622d7 --- /dev/null +++ b/tests/bugs/test_core_0979.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_979 +# title: Make RDB$DB_KEY in outer joins return NULL when appropriate +# decription: ---------------------------------------------------------------------------------------------- +# -- test de la fonctionalité +# -- +# -- +# --Make RDB$DB_KEY in outer joins return NULL when appropriate +# --A. dos Santos Fernandes +# --Feature request CORE-979 +# tracker_id: CORE-979 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_979 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE employee( id_employee INTEGER , prenom VARCHAR(20) ,id_department INTEGER, PRIMARY KEY(id_employee)); +CREATE TABLE department(id_department INTEGER, name VARCHAR(20)); +COMMIT; +INSERT INTO employee(id_employee, prenom,id_department) VALUES (1,'benoit',1 ); +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select department.rdb$db_key from employee +left OUTER JOIN department + on department.id_department = employee.id_department; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """DB_KEY +================ +""" + +@pytest.mark.version('>=2.1') +def test_core_979_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0986.py b/tests/bugs/test_core_0986.py new file mode 100644 index 00000000..9440c832 --- /dev/null +++ b/tests/bugs/test_core_0986.py @@ -0,0 +1,388 @@ +#coding:utf-8 +# +# id: bugs.core_0986 +# title: Non-ASCII quoted identifiers are not converted to metadata (UNICODE_FSS) charset +# decription: +# Test prepares file that will serve as input SQL script and will have CYRYLLIC names for all +# database objects: collations, domains, exceptions, tables, views etc. +# File has name = 'tmp_non_ascii_ddl_0986.sql' and is encoded to windows-1251 codepage. +# Then we: +# 1. Attempt to apply this file in ISQL __WITHOUT__ specifying charset and with 'set bail on'. +# This action should IMMEDIATELY be denied (i.e. no objects should be created in database at all). +# Also, two logs should be created for this attempt: +# 1.1) STDOUT with first (and single) statement that ISQL was to be executed; +# 1.2) STDERR with single exception, it depends on major FB version: +# * for FB 3.x: SQLSTATE = 22000 / malformed string; +# * for FB 4.x: SQLSTATE = 22018 / Cannot transliterate ... +# +# 2. Attempt to apply the same script but now _WITH_ specification of connect charset: -ch win1251. +# This attempt should finish SUCCESSFULLY, and we will verify it by checking its: +# 2.1) STDOUT - it should contain phrase "Metadata created OK." +# 2.2) STDERR - it should be EMPTY. +# +# Confirmed on 2.0.7: one might to run ISQL without specifying '-ch XXXX' switch and give it +# script which +# 1) was encoded in NON unicode character set (e.g. win1251 - as is used in this test) and +# 2) did create DB objects with non-ascii names. +# +# Checked on: +# 4.0.0.1635 SS: 3.217s. +# 4.0.0.1633 CS: 3.619s. +# 3.0.5.33180 SS: 2.548s. +# 3.0.5.33178 CS: 3.153s. +# +# 17-mar-2021. Re-implemented in order to have ability to run this test on Linux. +# Ttest 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 = WIN1251 and perform needed DML. +# Result will be redirected to .log which will be opened via codecs.open(...encoding='cp1251'). +# Its content will be converted to UTF8 for further parsing. +# +# Checked on: +# * Windows: 4.0.0.2387, 3.0.8.33426 +# * Linux: 4.0.0.2387, 3.0.8.33426 +# +# +# tracker_id: CORE-0986 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# +# # 28.10.2019. This is needed in Python 2.7 for converting string in UTF8 to cp1251 +# import codecs +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# #-------------------------------------------- +# +# 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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# # Obtain engine version: +# cur1 = db_conn.cursor() +# cur1.execute("select rdb$get_context('SYSTEM','ENGINE_VERSION') as engine_version from rdb$database") +# for row in cur1: +# engine = row[0] +# +# db_conn.close() +# +# non_ascii_ddl=''' +# set bail on; +# +# -- set names win1251; +# connect '%(dsn)s' user '%(user_name)s' password '%(user_password)s'; +# +# set echo on; +# +# create collation "Циферки" for utf8 from unicode case insensitive 'NUMERIC-SORT=1'; +# create collation "Испания" for iso8859_1 from es_es_ci_ai 'SPECIALS-FIRST=1';; +# commit; +# +# create domain "ИД'шники" int; +# create domain "Группы" varchar(30) check( value in ('Электрика', 'Ходовая', 'Арматурка', 'Кузовщина') ); +# create domain "Артикулы" varchar(12) character set utf8 check( value = upper(value) ) +# collate "Циферки" -- enabled since core-5220 was fixed (30.04.2016) +# ; +# create domain "Комрады" varchar(40) character set iso8859_1 +# collate "Испания" -- enabled since core-5220 was fixed (30.04.2016) +# ; +# create domain "Кол-во" numeric(12,3) not null; +# +# create sequence generilka; +# create sequence "Генерилка"; +# +# 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) +# recreate exception "Невзлет" 'Запись обломалась, ваши не пляшут. Но не стесняйтесь и обязательно заходите еще, мы всегда рады видеть вас. До скорой встречи, товарищ!'; +# commit; +# +# ------------------------------------------------- +# recreate table "склад" ( +# "ИД'шник" "ИД'шники" +# ,"Откудова" "Группы" +# ,"Номенклатура" "Артикулы" +# ,"ИД'родителя" "ИД'шники" +# ,"сколько там" "Кол-во" +# ,constraint "ПК-ИД'шник" primary key ("ИД'шник") using index "склад_ПК" +# ,constraint "ФК-на-родока" foreign key("ИД'родителя") references "склад" ("ИД'шник") using index "склад_ФК" +# ,constraint "остаток >=0" check ("сколько там" >= 0) +# ); +# +# recreate view "Электрика"("ид изделия", "Название", "Запас") as +# select +# "ИД'шник" +# ,"Номенклатура" +# ,"сколько там" +# from "склад" +# where "Откудова" = 'Электрика' +# ; +# +# set term ^; +# create or alter trigger "склад би" for "склад" active before insert as +# begin +# --new."ИД'шник" = coalesce( new."ИД'шник", gen_id(generilka, 1) ); +# -- not avail up to 2.5.6: +# new."ИД'шник" = coalesce( new."ИД'шник", gen_id("Генерилка", 1) ); +# end +# ^ +# +# create or alter procedure "Доб на склад"( +# "Откудова" varchar(30) +# ,"Номенклатура" varchar(30) +# ,"ИД'родителя" int +# ,"сколько там" numeric(12,3) +# ) returns ( +# "код возврата" int +# ) as +# begin +# insert into "склад"( +# "Откудова" +# ,"Номенклатура" +# ,"ИД'родителя" +# ,"сколько там" +# ) values ( +# :"Откудова" +# ,:"Номенклатура" +# ,:"ИД'родителя" +# ,:"сколько там" +# ); +# +# end +# ^ +# create or alter procedure "Удалить" as +# begin +# /* +# Антон Павлович Чехов. Каштанка +# +# 1. Дурное поведение +# +# Молодая рыжая собака - помесь такса с дворняжкой - очень похожая мордой +# на лисицу, бегала взад и вперед по тротуару и беспокойно оглядывалась по +# сторонам. Изредка она останавливалась и, плача, приподнимая то одну озябшую +# лапу, то другую, старалась дать себе отчет: как это могло случиться, что она +# заблудилась? +# */ +# end +# ^ +# set term ;^ +# +# grant select on "склад" to "манагер"; +# grant select, insert, update, delete on "склад" to "начсклд"; +# -- no avail in 2.0: grant execute procedure "Доб на склад" to "начсклд"; +# +# +# comment on sequence "Генерилка" is 'Генератор простых идей'; +# comment on table "склад" is 'Это всё, что мы сейчас имеем в наличии'; +# comment on view "Электрика" is 'Не суй пальцы в розетку, будет бо-бо!'; +# comment on procedure "Доб на склад" is 'Процедурка добавления изделия на склад'; +# comment on parameter "Доб на склад"."Откудова" is 'Группа изделия, которое собираемся добавить'; +# +# comment on parameter "Доб на склад"."ИД'родителя" is ' +# Федор Михайлович Достоевский +# +# Преступление и наказание +# +# Роман в шести частях с эпилогом +# +# +# Часть первая +# +# I +# В начале июля, в чрезвычайно жаркое время, под вечер, один молодой человек вышел из своей каморки, которую нанимал от жильцов в С -- м переулке, на улицу и медленно, как бы в нерешимости, отправился к К -- ну мосту. +# Он благополучно избегнул встречи с своею хозяйкой на лестнице. Каморка его приходилась под самою кровлей высокого пятиэтажного дома и походила более на шкаф, чем на квартиру. Квартирная же хозяйка его, у которой он нанимал эту каморку с обедом и прислугой, помещалась одною лестницей ниже, в отдельной квартире, и каждый раз, при выходе на улицу, ему непременно надо было проходить мимо хозяйкиной кухни, почти всегда настежь отворенной на лестницу. И каждый раз молодой человек, проходя мимо, чувствовал какое-то болезненное и трусливое ощущение, которого стыдился и от которого морщился. Он был должен кругом хозяйке и боялся с нею встретиться. +# Не то чтоб он был так труслив и забит, совсем даже напротив; но с некоторого времени он был в раздражительном и напряженном состоянии, похожем на ипохондрию. Он до того углубился в себя и уединился от всех, что боялся даже всякой встречи, не только встречи с хозяйкой. Он был задавлен бедностью; но даже стесненное положение перестало в последнее время тяготить его. Насущными делами своими он совсем перестал и не хотел заниматься. Никакой хозяйки, в сущности, он не боялся, что бы та ни замышляла против него. Но останавливаться на лестнице, слушать всякий вздор про всю эту обыденную дребедень, до которой ему нет никакого дела, все эти приставания о платеже, угрозы, жалобы, и при этом самому изворачиваться, извиняться, лгать, -- нет уж, лучше проскользнуть как-нибудь кошкой по лестнице и улизнуть, чтобы никто не видал. +# Впрочем, на этот раз страх встречи с своею кредиторшей даже его самого поразил по выходе на улицу. +# "На какое дело хочу покуситься и в то же время каких пустяков боюсь! -- подумал он с странною улыбкой. -- Гм... да... всё в руках человека, и всё-то он мимо носу проносит, единственно от одной трусости... это уж аксиома... Любопытно, чего люди больше всего боятся? Нового шага, нового собственного слова они всего больше боятся... А впрочем, я слишком много болтаю. Оттого и ничего не делаю, что болтаю. Пожалуй, впрочем, и так: оттого болтаю, что ничего не делаю. Это я в этот последний месяц выучился болтать, лежа по целым суткам в углу и думая... о царе Горохе. Ну зачем я теперь иду? Разве я способен на это? Разве это серьезно? Совсем не серьезно. Так, ради фантазии сам себя тешу; игрушки! Да, пожалуй что и игрушки!" +# На улице жара стояла страшная, к тому же духота, толкотня, всюду известка, леса, кирпич, пыль и та особенная летняя вонь, столь известная каждому петербуржцу, не имеющему возможности нанять дачу, -- всё это разом неприятно потрясло и без того уже расстроенные нервы юноши. Нестерпимая же вонь из распивочных, которых в этой части города особенное множество, и пьяные, поминутно попадавшиеся, несмотря на буднее время, довершили отвратительный и грустный колорит картины. Чувство глубочайшего омерзения мелькнуло на миг в тонких чертах молодого человека. Кстати, он был замечательно хорош собою, с прекрасными темными глазами, темно-рус, ростом выше среднего, тонок и строен. Но скоро он впал как бы в глубокую задумчивость, даже, вернее сказать, как бы в какое-то забытье, и пошел, уже не замечая окружающего, да и не желая его замечать. Изредка только бормотал он что-то про себя, от своей привычки к монологам, в которой он сейчас сам себе признался. В эту же минуту он и сам сознавал, что мысли его порою мешаются и что он очень слаб: второй день как уж он почти совсем ничего не ел. +# Он был до того худо одет, что иной, даже и привычный человек, посовестился бы днем выходить в таких лохмотьях на улицу. Впрочем, квартал был таков, что костюмом здесь было трудно кого-нибудь удивить. Близость Сенной, обилие известных заведений и, по преимуществу, цеховое и ремесленное население, скученное в этих серединных петербургских улицах и переулках, пестрили иногда общую панораму такими субъектами, что странно было бы и удивляться при встрече с иною фигурой. Но столько злобного презрения уже накопилось в душе молодого человека, что, несмотря на всю свою, иногда очень молодую, щекотливость, он менее всего совестился своих лохмотьев на улице. Другое дело при встрече с иными знакомыми или с прежними товарищами, с которыми вообще он не любил встречаться... А между тем, когда один пьяный, которого неизвестно почему и куда провозили в это время по улице в огромной телеге, запряженной огромною ломовою лошадью, крикнул ему вдруг, проезжая: "Эй ты, немецкий шляпник!" -- и заорал во всё горло, указывая на него рукой, -- молодой человек вдруг остановился и судорожно схватился за свою шляпу. Шляпа эта была высокая, круглая, циммермановская, но вся уже изношенная, совсем рыжая, вся в дырах и пятнах, без полей и самым безобразнейшим углом заломившаяся на сторону. Но не стыд, а совсем другое чувство, похожее даже на испуг, охватило его. +# "Я так и знал! -- бормотал он в смущении, -- я так и думал! Это уж всего сквернее! Вот эдакая какая-нибудь глупость, какая-нибудь пошлейшая мелочь, весь замысел может испортить! Да, слишком приметная шляпа... Смешная, потому и приметная... К моим лохмотьям непременно нужна фуражка, хотя бы старый блин какой-нибудь, а не этот урод. Никто таких не носит, за версту заметят, запомнят... главное, потом запомнят, ан и улика. Тут нужно быть как можно неприметнее... Мелочи, мелочи главное!.. Вот эти-то мелочи и губят всегда и всё..." +# +# '; +# -------------------------------------------------- +# commit; +# --/* +# --TEMPLY COMMENTED UNTIL CORE-5221 IS OPEN: +# set echo on; +# show collation; +# show domain; +# show exception; -- <<<<<<<<<<<<< +# show sequence; +# show table; +# show trigger; +# show view; +# show procedure; +# show role; +# --*/ +# set list on; +# set echo off; +# select 'Metadata created OK.' as msg from rdb$database; +# +# ''' % dict(globals(), **locals()) +# +# +# f_checksql = open( os.path.join(context['temp_directory'], 'tmp_0986_w1251.sql'), 'w' ) +# f_checksql.write( non_ascii_ddl.decode('utf8').encode('cp1251') ) +# flush_and_close( f_checksql ) +# +# # Result: file 'tmp_0986_w1251' is encoded in cp1251 and contains SQL statements to be executed. +# +# ########################################################################################################### +# ### check-1: attempt to apply DDL with non-ascii characters __WITHOUT__ charset specifying (for ISQL) ### +# ########################################################################################################### +# +# f_apply_cset_none_log = open( os.path.join(context['temp_directory'],'tmp_0986_apply_cset_none.log'), 'w') +# f_apply_cset_none_err = open( os.path.join(context['temp_directory'],'tmp_0986_apply_cset_none.err'), 'w') +# +# subprocess.call( [ context['isql_path'], "-q", "-i", f_checksql.name ], +# stdout = f_apply_cset_none_log, +# stderr = f_apply_cset_none_err +# ) +# +# # This file should contain only FIRST statement from DDL hich contains non-ascii characters: +# # (because of 'set BAIL on' ISQL should immediately terminate its job): +# # create collation "Циферки" for utf8 from unicode case insensitive 'NUMERIC-SORT=1';: +# # +# flush_and_close( f_apply_cset_none_log ) +# +# # This file should contain error on 1st DDL statement which contains non-ascii characters: +# # FB 3.x: +# # Statement failed, SQLSTATE = 22000 +# # unsuccessful metadata update +# # -CREATE COLLATION Циферки failed +# # -Malformed string +# # FB 4.x: +# # Statement failed, SQLSTATE = 22018 +# # arithmetic exception, numeric overflow, or string truncation +# # -Cannot transliterate character between character sets +# # +# flush_and_close( f_apply_cset_none_err ) +# +# ############################################################################################################# +# ### check-2: attempt to apply DDL with non-ascii characters ___WITH___ specifying: ISQL ... -ch WIN1251 ### +# ############################################################################################################# +# +# f_apply_cset_1251_log = open( os.path.join(context['temp_directory'],'tmp_0986_apply_cset_1251.log'), 'w') +# f_apply_cset_1251_err = open( os.path.join(context['temp_directory'],'tmp_0986_apply_cset_1251.err'), 'w') +# +# subprocess.call( [ context['isql_path'], "-q", "-i", f_checksql.name, "-ch", "win1251" ], +# stdout = f_apply_cset_1251_log, +# stderr = f_apply_cset_1251_err +# ) +# +# # This file should contain ALL applied statements, plus final message: +# # MSG Metadata created OK. +# flush_and_close( f_apply_cset_1251_log ) +# +# # This file should NOT contain any errors: +# flush_and_close( f_apply_cset_1251_err ) +# +# # CHECK RESULTS: +# ################ +# +# # This stdout log should contain only ONE statement (create collation ...), +# # this DDL failed and caused ISQL to immediately terminate: +# # +# with open( f_apply_cset_none_log.name, 'r') as f: +# for line in f: +# out_txt='STDLOG WHEN CSET=NONE: '; +# if line.strip(): +# if line.strip().decode("cp1251").encode('utf8').startswith('create collation'): +# print( out_txt + "FOUND EXPECTED 'CREATE COLLATION STATEMENT'" ) +# else: +# print( out_txt+'SOME OTHER STATEMENT FOUND' ) +# +# with open( f_apply_cset_none_err.name, 'r') as f: +# for line in f: +# out_txt='STDERR WHEN CSET=NONE: '; +# if 'SQLSTATE =' in line: +# if 'SQLSTATE = 22000' in line and engine.startswith('3.') or 'SQLSTATE = 22018' in line and not engine.startswith('3.'): +# print( out_txt+'FOUND EXPECTED SQLSTATE IN ERROR MESSAGE' ) +# else: +# print( out_txt+'SOME OTHER ERROR FOUND: '+line ) +# +# # This log should contain 'magic text' which tells that all finished OK: +# # MSG Metadata created OK. +# +# if 'Metadata created OK.' in open(f_apply_cset_1251_log.name).read(): +# print('STDLOG WHEN CSET=1251: ALL FINISHED OK.') +# +# # This log should be EMPTY: when we used '-ch win1251' then metadata +# # with non-ascii names in DB objects should be created successfully: +# # +# with open( f_apply_cset_1251_err.name, 'r') as f: +# for line in f: +# if line: +# print('Unexpected STDERR when use -ch win1251: ' + line) +# +# # CLEANUP +# ######### +# time.sleep(1) +# cleanup( ( f_apply_cset_none_log, f_apply_cset_none_err, f_apply_cset_1251_log, f_apply_cset_1251_err,f_checksql, ) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + STDLOG WHEN CSET=NONE: FOUND EXPECTED 'CREATE COLLATION STATEMENT' + STDERR WHEN CSET=NONE: FOUND EXPECTED SQLSTATE IN ERROR MESSAGE + STDLOG WHEN CSET=1251: ALL FINISHED OK. + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_0986_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_0995.py b/tests/bugs/test_core_0995.py new file mode 100644 index 00000000..2da67c81 --- /dev/null +++ b/tests/bugs/test_core_0995.py @@ -0,0 +1,88 @@ +#coding:utf-8 +# +# id: bugs.core_995 +# title: select with FIRST and LEFT JOIN needs excess SORT in plan +# decription: +# tracker_id: CORE-995 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_995 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table orgaccount (id numeric(15,0)); + commit; + recreate table org( + id numeric(15,0) primary key using index pk_org, + name varchar(1000) + ); + + recreate table orgaccount ( + id numeric(15,0) primary key using index pk_orgaccount, + name varchar(1000), + org_id numeric (15,0) not null references org using index fk_orgaccount + ); + + insert into org values (1, 'org1'); + insert into org values (2, 'org2'); + insert into org values (3, 'org3'); + insert into org values (4, 'org4'); + insert into org values (5, 'org5'); + insert into org values (6, 'org6'); + + insert into orgaccount values (1, 'account1', 1); + insert into orgaccount values (2, 'account2', 1); + insert into orgaccount values (3, 'account3', 1); + insert into orgaccount values (4, 'account4', 1); + insert into orgaccount values (5, 'account5', 1); + insert into orgaccount values (6, 'account6', 2); + insert into orgaccount values (7, 'account7', 2); + insert into orgaccount values (8, 'account8', 3); + + commit; + set statistics index pk_org; + set statistics index pk_orgaccount; + set statistics index fk_orgaccount; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set planonly; + + -- testing plan for OUTER join: + select first 10 * + from orgaccount + LEFT join org on org.id=orgaccount.org_id + where orgaccount.id>4 + order by orgaccount.id; + + -- testing plan for INNER join: + select first 10 * + from orgaccount + INNER join org on org.id=orgaccount.org_id + where orgaccount.id>4 + order by orgaccount.id; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN JOIN (ORGACCOUNT ORDER PK_ORGACCOUNT, ORG INDEX (PK_ORG)) + PLAN JOIN (ORGACCOUNT ORDER PK_ORGACCOUNT, ORG INDEX (PK_ORG)) + """ + +@pytest.mark.version('>=3.0') +def test_core_995_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_0996.py b/tests/bugs/test_core_0996.py new file mode 100644 index 00000000..e246bf8c --- /dev/null +++ b/tests/bugs/test_core_0996.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: bugs.core_996 +# title: Keyword AS not recognized in clause FROM +# decription: The sentence SELECT * FROM
AS is not recognized correct. +# tracker_id: CORE-996 +# min_versions: [] +# versions: 2.0 +# qmid: bugs.core_996 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE T1 (ID1 INTEGER NOT NULL); +INSERT INTO T1 VALUES (1); +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT ID1 from T1 AS BLA; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ ID1 +============ + 1 +""" + +@pytest.mark.version('>=2.0') +def test_core_996_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1000.py b/tests/bugs/test_core_1000.py new file mode 100644 index 00000000..6a5adea5 --- /dev/null +++ b/tests/bugs/test_core_1000.py @@ -0,0 +1,61 @@ +#coding:utf-8 +# +# id: bugs.core_1000 +# title: Incorrect results when left join on subquery with constant column +# decription: +# tracker_id: CORE-1000 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE A ( + ID INTEGER +); + +CREATE TABLE B ( + ID INTEGER +); + +insert into A (id) values (1); +insert into A (id) values (2); +insert into A (id) values (3); + +insert into B (id) values (1); +insert into B (id) values (2); + +commit; +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select a.id, b.id, bexists +from a + left join (select id, 1 bexists from b) b on (a.id=b.id); + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID ID BEXISTS +============ ============ ============ + 1 1 1 + 2 2 1 + 3 + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_1000_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1002.py b/tests/bugs/test_core_1002.py new file mode 100644 index 00000000..a56bac02 --- /dev/null +++ b/tests/bugs/test_core_1002.py @@ -0,0 +1,32 @@ +#coding:utf-8 +# +# id: bugs.core_1002 +# title: bad handling of /*/ comments in ISQL +# decription: +# tracker_id: CORE-1002 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1002 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """/*/ select * from rdb$database; /*/ +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1') +def test_core_1002_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_1004.py b/tests/bugs/test_core_1004.py new file mode 100644 index 00000000..458ae527 --- /dev/null +++ b/tests/bugs/test_core_1004.py @@ -0,0 +1,73 @@ +#coding:utf-8 +# +# id: bugs.core_1004 +# title: context already in use (BLR error) +# decription: +# tracker_id: CORE-1004 +# min_versions: [] +# versions: 2.0.1 +# qmid: bugs.core_1004 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """SET TERM ^; + +CREATE OR ALTER PROCEDURE GET_REL_NAME (REL_ID INT) RETURNS (REL_NAME VARCHAR(32)) +AS +BEGIN + FOR SELECT R.RDB$RELATION_NAME + FROM RDB$RELATIONS R + WHERE R.RDB$RELATION_ID = :REL_ID + INTO :REL_NAME + DO + SUSPEND; +END^ + +SET TERM ;^ + +COMMIT; + +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET TERM ^; + +CREATE OR ALTER PROCEDURE BUG +AS +DECLARE C CURSOR FOR ( + SELECT (SELECT REL_NAME FROM GET_REL_NAME(R.RDB$RELATION_ID)) + FROM RDB$RELATIONS R + ); +DECLARE REL_NAME VARCHAR(32); +BEGIN + OPEN C; + WHILE (1 = 1) DO + BEGIN + FETCH C INTO :REL_NAME; + + IF (ROW_COUNT = 0) + THEN LEAVE; + END + + CLOSE C; +END^ + +SET TERM ;^ + +COMMIT; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.0.1') +def test_core_1004_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_1005.py b/tests/bugs/test_core_1005.py new file mode 100644 index 00000000..49db131c --- /dev/null +++ b/tests/bugs/test_core_1005.py @@ -0,0 +1,72 @@ +#coding:utf-8 +# +# id: bugs.core_1005 +# title: DISTINCT vs NULLS LAST clause: wrong order of NULLs +# decription: +# tracker_id: CORE-1005 +# min_versions: [] +# versions: 2.0.1 +# qmid: bugs.core_1005 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table T (A int, B int) ; +commit ; + +insert into T values (1,1); +insert into T values (1,1); +insert into T values (2,2); +insert into T values (3,3); +insert into T values (null,null); +insert into T values (null,null); +insert into T values (4,4); +commit ; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select distinct A, B from T order by A nulls last, B nulls last ; +select distinct A, B from T order by A nulls last ; +select distinct A, B from T order by B nulls last ; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """A B +============ ============ + 1 1 + 2 2 + 3 3 + 4 4 + + +A B +============ ============ + 1 1 + 2 2 + 3 3 + 4 4 + + +A B +============ ============ + 1 1 + 2 2 + 3 3 + 4 4 + + +""" + +@pytest.mark.version('>=2.0.1') +def test_core_1005_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1006.py b/tests/bugs/test_core_1006.py new file mode 100644 index 00000000..ba18ac99 --- /dev/null +++ b/tests/bugs/test_core_1006.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: bugs.core_1006 +# title: AV at rollback and \\ or garbage collection if updated table have expression index with SELECT in it +# decription: This test takes the server down. +# tracker_id: CORE-1006 +# min_versions: [] +# versions: 2.0.1 +# qmid: bugs.core_1006 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core1006.fbk', init=init_script_1) + +test_script_1 = """ + set term ^; + execute block + as + declare f1 int; + declare f2 int; + begin + for + select + t1.id + as id1 -- <<< ::: NB ::: add alias, otherwise can`t compile in 3.0 + ,t2.id + as id2 -- <<< ::: NB ::: add alias, otherwise can`t compile in 3.0 + from table1 t1, table2 t2 + where t1.id = t2.id + into :f1, :f2 + as cursor cur + do + update table1 set name = :f1 + :f2 where current of cur; + end + ^ set term ;^ + rollback; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.0.1') +def test_core_1006_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_1009.py b/tests/bugs/test_core_1009.py new file mode 100644 index 00000000..1020393b --- /dev/null +++ b/tests/bugs/test_core_1009.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: bugs.core_1009 +# title: Restoring RDB$BASE_FIELD for expression +# decription: RDB$BASE_FIELD for expression have to be NULL +# tracker_id: CORE-1009 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1009 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core1009.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + select rdb$field_name, rdb$base_field from rdb$relation_fields where rdb$relation_name = 'TEST_VIEW'; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$FIELD_NAME ID + RDB$BASE_FIELD ID + RDB$FIELD_NAME EXPR + RDB$BASE_FIELD + """ + +@pytest.mark.version('>=2.1') +def test_core_1009_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1010.py b/tests/bugs/test_core_1010.py new file mode 100644 index 00000000..b1178491 --- /dev/null +++ b/tests/bugs/test_core_1010.py @@ -0,0 +1,61 @@ +#coding:utf-8 +# +# id: bugs.core_1010 +# title: Local buffer overrun in DYN_error() that takes down the server +# decription: 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. +# tracker_id: CORE-1010 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_1010-21 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('line:.*', ''), ('col:.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Removed old code: all attempts to create triggers on SYSTEM tables now are prohibited, even for SYSDBA. + create exception ex_test '!!!'; + commit; + + set term ^ ; + create or alter trigger rdb$procedures_biu for rdb$procedures + active after update or delete position 0 + as + begin + exception ex_test; + end + ^ + commit^ + + create or alter procedure proctest returns (result integer) as + begin + result = 0; + suspend; + end^ + set term ; ^ + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -CREATE OR ALTER TRIGGER RDB$PROCEDURES_BIU failed + -no permission for ALTER access to TABLE RDB$PROCEDURES + """ + +@pytest.mark.version('>=3.0') +def test_core_1010_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_1018.py b/tests/bugs/test_core_1018.py new file mode 100644 index 00000000..430e097b --- /dev/null +++ b/tests/bugs/test_core_1018.py @@ -0,0 +1,79 @@ +#coding:utf-8 +# +# id: bugs.core_1018 +# title: Provide mechanism to get engine version without needing to call API function +# decription: +# tracker_id: CORE-1018 +# min_versions: [] +# versions: 3.0, 4.0 +# qmid: bugs.core_1018-211 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + -- Engine version could contain more than one digit in any section or more sections. + -- Changed pattern for matching such cases of engine version as: + -- '3.2.23' or '3.3.2.1.0.1.2.3.4.5.7' etc + select iif( t.ev similar to '[0-9]+.[0-9]+.[0-9]+((.?[0-9]+)*)', substring(ev from 1 for 3), null) as version + from ( + select rdb$get_context('SYSTEM', 'ENGINE_VERSION') ev + from rdb$database + )t; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + VERSION 3.0 + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_core_1018_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set list on; + -- Engine version could contain more than one digit in any section or more sections. + -- Changed pattern for matching such cases of engine version as: + -- '3.2.23' or '3.3.2.1.0.1.2.3.4.5.7' etc + select iif( t.ev similar to '[0-9]+.[0-9]+.[0-9]+((.?[0-9]+)*)', substring(ev from 1 for 3), null) as version + from ( + select rdb$get_context('SYSTEM', 'ENGINE_VERSION') ev + from rdb$database + )t; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + VERSION 4.0 + """ + +@pytest.mark.version('>=4.0') +def test_core_1018_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/bugs/test_core_1019.py b/tests/bugs/test_core_1019.py new file mode 100644 index 00000000..df5b1c4e --- /dev/null +++ b/tests/bugs/test_core_1019.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_1019 +# title: Make information available regading ODS Version and Dialect via SQL +# decription: +# tracker_id: CORE-1019 +# min_versions: [] +# versions: 2.5.0 +# qmid: bugs.core_1019-250 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + -- Refactored 05-may-2018, to be universal for all possible ODS numbers: + select + iif( mon$ods_major similar to '[[:digit:]]{1,2}', 'YES', 'NO!') as "ods_major_looks_ok ?" + , iif( mon$ods_minor similar to '[[:digit:]]{1,2}', 'YES', 'NO!') as "ods_minor_looks_ok ?" + , iif( mon$sql_dialect similar to '[[:digit:]]{1}', 'YES', 'NO!') as "sql_dialect_looks_ok ?" + from mon$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ods_major_looks_ok ? YES + ods_minor_looks_ok ? YES + sql_dialect_looks_ok ? YES + """ + +@pytest.mark.version('>=2.5.0') +def test_core_1019_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1025.py b/tests/bugs/test_core_1025.py new file mode 100644 index 00000000..faea65db --- /dev/null +++ b/tests/bugs/test_core_1025.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_1025 +# title: Server crashes at runtime when an explicit MERGE plan is specified over a few JOIN ones +# decription: +# tracker_id: CORE-1025 +# min_versions: [] +# versions: 2.0.1 +# qmid: bugs.core_1025 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """recreate table t (id int not null); +alter table t add constraint pk primary key (id); + +insert into t values (1); +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select * +from t t1, t t2, t t3, t t4 +where t1.id = t2.id + and t2.id = t3.id + and t3.id = t4.id +PLAN MERGE (JOIN (T1 NATURAL, T2 INDEX (PK)), JOIN(T3 NATURAL, T4 INDEX (PK))); + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ID ID ID ID +============ ============ ============ ============ + 1 1 1 1 + +""" + +@pytest.mark.version('>=2.0.1') +def test_core_1025_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1026_utf8.py b/tests/bugs/test_core_1026_utf8.py new file mode 100644 index 00000000..5def0024 --- /dev/null +++ b/tests/bugs/test_core_1026_utf8.py @@ -0,0 +1,280 @@ +#coding:utf-8 +# +# id: bugs.core_1026_utf8 +# title: Estonian collation in UTF8 charset +# decription: +# Original ticker subj: Estonian collations for WIN1252 charset +# +# http://www.eki.ee/itstandard/2000/FDCC.shtml.en +# Estonian sort order changes the default positions for one base character (), š and ž ('s' and 'z' with caron) +# and four accented vowels in the Estonian alphabet: +# * and all it's modifications are ordered after ; +# * 'š' and 'ž' are separate letters and follow the unaccented and respectively. +# * all four Estonian vowels with diacritics - 'ä', 'ö', 'õ' and 'ü' - are also sorted as separate +# letters after 'w'; +# * 'w' is generally sorted as a separate letter except of Estonian personnal names. +# Thus the Estonian alphabet ends with: +# #################################### +# ... r s š z ž t u v w õ ä ö ü x y +# #################################### +# +# NOTE-1: +# collation = WIN1252_UNICODE (defined for charset WIN1252 in %FB_HOME%\\intl +# bintl.conf) sorts +# estonian letters NOT as expected: a,A,ä,Ä,b...,o,O,ö,Ö,õ,Õ,...,s,S,š,Š,t,T,u,U,ü,Ü,...,z,Z,ž,Ž +# +# NOTE-2: +# collation WIN1257_EE (defined for charset WIN1257) sorts estonian letters properly but this collation +# is not what author asked about ("CP 1257 (Baltic) is suggested as second when 1252 is not available.") +# Because of this, UTF8 collation for LOCALE=et_EE is tested here. +# +# NOTE-3: +# lowercase letters are sorted BEFORE uppercase ones ('a' < 'A') when we use most of collations, +# including utf8 'LOCALE=et_EE'. This is defined by current ICU implementation. +# Current syntax of CREATE COLLATION statement do not allow to change priority of uppercase/lowercase +# letters which denote the same character when they are sorted. +# +# Result of sorting such letters will be opposite to "ascii-style" where uppercase letters ('A') +# are always considered as less then lowercase ones ('a'). +# +# Quote from https://unicode.org/reports/tr10/#Case_Comparisons +# ===== +# "In some languages, it is common to sort lowercase before uppercase; in other languages this is reversed. +# Often this is more dependent on the individual concerned, and is not standard across a single language. +# It is strongly recommended that implementations provide parameterization that allows uppercase to be +# sorted before lowercase, and provides information as to the standard (if any) for particular countries". +# ====== +# See also: +# http://userguide.icu-project.org/collation/concepts +# +# Checked on 4.0.0.2214 +# +# tracker_id: CORE-1026 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + + -- NB: 'et' in 'LOCALE=...' must be specified in lowercase! + create collation estonian_coll_cs_as for utf8 from unicode 'LOCALE=et_EE'; + create collation estonian_coll_ci_ai for utf8 from unicode case insensitive accent insensitive 'LOCALE=et_EE'; + + create table test( + id smallint generated by default as identity + ,s varchar(1) character set utf8 collate estonian_coll_cs_as + ); + commit; + + + -- Fill records according to SORT order that is declared by Estonian Standardization Board + -- http://www.eki.ee/itstandard/2000/FDCC.shtml.en + + insert into test(s) values( 'a' ); + insert into test(s) values( 'A' ); + insert into test(s) values( 'b' ); + insert into test(s) values( 'B' ); + insert into test(s) values( 'c' ); + insert into test(s) values( 'C' ); + insert into test(s) values( 'd' ); + insert into test(s) values( 'D' ); + insert into test(s) values( 'e' ); + insert into test(s) values( 'E' ); + insert into test(s) values( 'f' ); + insert into test(s) values( 'F' ); + insert into test(s) values( 'g' ); + insert into test(s) values( 'G' ); + insert into test(s) values( 'h' ); + insert into test(s) values( 'H' ); + insert into test(s) values( 'i' ); + insert into test(s) values( 'I' ); + insert into test(s) values( 'j' ); + insert into test(s) values( 'J' ); + insert into test(s) values( 'k' ); + insert into test(s) values( 'K' ); + insert into test(s) values( 'l' ); + insert into test(s) values( 'L' ); + insert into test(s) values( 'm' ); + insert into test(s) values( 'M' ); + insert into test(s) values( 'n' ); + insert into test(s) values( 'N' ); + insert into test(s) values( 'o' ); + insert into test(s) values( 'O' ); + insert into test(s) values( 'p' ); + insert into test(s) values( 'P' ); + insert into test(s) values( 'r' ); + insert into test(s) values( 'R' ); + insert into test(s) values( 's' ); + insert into test(s) values( 'S' ); + + insert into test(s) values( 'š' ); + insert into test(s) values( 'Š' ); + insert into test(s) values( 'z' ); + insert into test(s) values( 'Z' ); + insert into test(s) values( 'ž' ); + insert into test(s) values( 'Ž' ); + insert into test(s) values( 't' ); + insert into test(s) values( 'T' ); + insert into test(s) values( 'u' ); + insert into test(s) values( 'U' ); + insert into test(s) values( 'v' ); + insert into test(s) values( 'V' ); + insert into test(s) values( 'õ' ); + insert into test(s) values( 'Õ' ); + insert into test(s) values( 'ä' ); + insert into test(s) values( 'Ä' ); + insert into test(s) values( 'ö' ); + insert into test(s) values( 'Ö' ); + insert into test(s) values( 'ü' ); + insert into test(s) values( 'Ü' ); + insert into test(s) values( 'x' ); + insert into test(s) values( 'X' ); + insert into test(s) values( 'y' ); + insert into test(s) values( 'Y' ); + + commit; + + set heading off; + + -- test-1: + -- check whether letters are sorted properly when case- and accent-sensitive collation is in use: + -- values of row_number()over(order by a.s) must be equal to ID values. + select a.id,a.s,row_number()over(order by a.s) rn from test a; + + + -- test-2: + -- check that every character matches to some another (and single) with respect + -- to requirement: "case insensitive, accent insensitive". + -- This means that for 'a' we must find 'A' (but NOT 'ä' or 'Ä') etc. + -- NOTE. + -- 'š', 'ž', 'õ', 'ä', 'ö' and 'ü' - must be considered and sorted as *separate* letters. + -- upper() / lower() for each of them must find match to only *one* character with another ID in the 'test' table + + set count on; + select a.id, a.s, b.id, b.s + from test a + join test b on + a.s collate estonian_coll_ci_ai = b.s collate estonian_coll_ci_ai + and a.id < b.id + order by a.id, b.id + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 1 a 1 + 2 A 2 + 3 b 3 + 4 B 4 + 5 c 5 + 6 C 6 + 7 d 7 + 8 D 8 + 9 e 9 + 10 E 10 + 11 f 11 + 12 F 12 + 13 g 13 + 14 G 14 + 15 h 15 + 16 H 16 + 17 i 17 + 18 I 18 + 19 j 19 + 20 J 20 + 21 k 21 + 22 K 22 + 23 l 23 + 24 L 24 + 25 m 25 + 26 M 26 + 27 n 27 + 28 N 28 + 29 o 29 + 30 O 30 + 31 p 31 + 32 P 32 + 33 r 33 + 34 R 34 + 35 s 35 + 36 S 36 + 37 š 37 + 38 Š 38 + 39 z 39 + 40 Z 40 + 41 ž 41 + 42 Ž 42 + 43 t 43 + 44 T 44 + 45 u 45 + 46 U 46 + 47 v 47 + 48 V 48 + 49 õ 49 + 50 Õ 50 + 51 ä 51 + 52 Ä 52 + 53 ö 53 + 54 Ö 54 + 55 ü 55 + 56 Ü 56 + 57 x 57 + 58 X 58 + 59 y 59 + 60 Y 60 + + + 1 a 2 A + 3 b 4 B + 5 c 6 C + 7 d 8 D + 9 e 10 E + 11 f 12 F + 13 g 14 G + 15 h 16 H + 17 i 18 I + 19 j 20 J + 21 k 22 K + 23 l 24 L + 25 m 26 M + 27 n 28 N + 29 o 30 O + 31 p 32 P + 33 r 34 R + 35 s 36 S + 37 š 38 Š + 39 z 40 Z + 41 ž 42 Ž + 43 t 44 T + 45 u 46 U + 47 v 48 V + 49 õ 50 Õ + 51 ä 52 Ä + 53 ö 54 Ö + 55 ü 56 Ü + 57 x 58 X + 59 y 60 Y + + Records affected: 30 + """ + +@pytest.mark.version('>=4.0') +def test_core_1026_utf8_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1029.py b/tests/bugs/test_core_1029.py new file mode 100644 index 00000000..83d6675f --- /dev/null +++ b/tests/bugs/test_core_1029.py @@ -0,0 +1,66 @@ +#coding:utf-8 +# +# id: bugs.core_1029 +# title: Bad plan in outer joins with IS NULL clauses (dependent on order of predicates) +# decription: +# tracker_id: CORE-1029 +# min_versions: [] +# versions: 2.0.1 +# qmid: bugs.core_1029 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """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_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """set plan on; + +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; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN JOIN (A INDEX (TBI2), B INDEX (TBI1)) + + ID COL ID COL +============ ============ ============ ============ + 1 1 1 + 1 1 + +PLAN JOIN (A INDEX (TBI2), B INDEX (TBI1)) + + ID COL ID COL +============ ============ ============ ============ + 1 1 1 + 1 1 + +""" + +@pytest.mark.version('>=2.0.1') +def test_core_1029_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1033.py b/tests/bugs/test_core_1033.py new file mode 100644 index 00000000..4cd6ecff --- /dev/null +++ b/tests/bugs/test_core_1033.py @@ -0,0 +1,76 @@ +#coding:utf-8 +# +# id: bugs.core_1033 +# title: like doesn't work for computed values (at least in a view) +# decription: +# tracker_id: CORE-1033 +# min_versions: [] +# versions: 2.5 +# qmid: bugs.core_1033 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table TABLE_X ( + id numeric(10,0) not null, + descr varchar(50) not null +); + +commit; + +create view X_VW (id, description) +as select id, x.descr || ' ('||x.id||')' from TABLE_X as x; + +commit; + +insert into TABLE_X values (1,'xyz'); +insert into TABLE_X values (2,'xyzxyz'); +insert into TABLE_X values (3,'xyz012'); + +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select * from X_VW ; + +select * from X_VW where description like 'xyz (1)' ; + +select * from X_VW where description like 'xyz (%)' ; + +select * from X_VW where description like 'xyz%' ; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ ID DESCRIPTION +===================== ========================================================================= + 1 xyz (1) + 2 xyzxyz (2) + 3 xyz012 (3) + + ID DESCRIPTION +===================== ========================================================================= + 1 xyz (1) + + ID DESCRIPTION +===================== ========================================================================= + 1 xyz (1) + + ID DESCRIPTION +===================== ========================================================================= + 1 xyz (1) + 2 xyzxyz (2) + 3 xyz012 (3) +""" + +@pytest.mark.version('>=2.5') +def test_core_1033_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1036.py b/tests/bugs/test_core_1036.py new file mode 100644 index 00000000..b146c17e --- /dev/null +++ b/tests/bugs/test_core_1036.py @@ -0,0 +1,81 @@ +#coding:utf-8 +# +# id: bugs.core_1036 +# title: extend retutnning support added in ver 2 in update record of table and in updateble view +# decription: +# Only basic support is checked here (i.e. only table and one-to-one projection view, WITHOUT trigger(s)). +# +# tracker_id: CORE-1036 +# min_versions: ['3.0.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate view v_test as select 1 x from rdb$database; + commit; + + recreate table test(id int primary key, x int default 11, y int default 12, z computed by(x+y) ); + commit; + + recreate view v_test as select id, x, y, z from test; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + insert into test(id, x, y) values(1,100,200); + commit; + + insert into test(id) values(2) returning x as t_inserted_x, y as t_inserted_y, z as t_inserted_z; + update test set id=-id, x=-2*y, y=-3*x where id=1 returning x as t_updated_x, y as t_updated_y, z as t_updated_z; + delete from test where id < 0 returning x as t_deleted_x, y as t_deleted_y, z as t_deleted_z; + + delete from test; + insert into test(id, x, y) values(1,100,200); + commit; + + insert into v_test(id) values(3) returning x as v_inserted_x, y as v_inserted_y, z as v_inserted_z; + update v_test set id=-id, x=-2*y, y=-3*x where id=1 returning x as v_updated_x, y as v_updated_y, z as v_updated_z; + delete from v_test where id < 0 returning x as v_deleted_x, y as v_deleted_y, z as v_deleted_z; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + T_INSERTED_X 11 + T_INSERTED_Y 12 + T_INSERTED_Z 23 + T_UPDATED_X -400 + T_UPDATED_Y -300 + T_UPDATED_Z -700 + T_DELETED_X -400 + T_DELETED_Y -300 + T_DELETED_Z -700 + + V_INSERTED_X 11 + V_INSERTED_Y 12 + V_INSERTED_Z 23 + V_UPDATED_X -400 + V_UPDATED_Y -300 + V_UPDATED_Z -700 + V_DELETED_X -400 + V_DELETED_Y -300 + V_DELETED_Z -700 + """ + +@pytest.mark.version('>=3.0') +def test_core_1036_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1040.py b/tests/bugs/test_core_1040.py new file mode 100644 index 00000000..b1b5d706 --- /dev/null +++ b/tests/bugs/test_core_1040.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: bugs.core_1040 +# title: Wrong single-segment ascending index on character field with NULL and empty string values +# decription: Wrong single-segment ascending index on character field with NULL and empty string values +# tracker_id: CORE-1040 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_1040 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """recreate table t (str varchar(10)); +commit; + +insert into t values (''); +insert into t values (null); +commit; + +create index t_i on t (str); +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select count(*) from t where str is null;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ COUNT +===================== + 1 + +""" + +@pytest.mark.version('>=3.0') +def test_core_1040_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1055.py b/tests/bugs/test_core_1055.py new file mode 100644 index 00000000..547985ca --- /dev/null +++ b/tests/bugs/test_core_1055.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: bugs.core_1055 +# title: Wrong parameter matching for self-referenced procedures +# decription: +# tracker_id: CORE-1055 +# min_versions: [] +# versions: 2.0.1 +# qmid: bugs.core_1055 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """SET TERM ^; + +create procedure PN (p1 int) +as +begin + execute procedure PN (:p1); +end ^ + +SET TERM ;^ + +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET TERM ^; + +alter procedure PN (p1 int, p2 int) +as +begin + execute procedure PN (:p1, :p2); +end^ + +SET TERM ;^ + +commit; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.0.1') +def test_core_1055_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_1056.py b/tests/bugs/test_core_1056.py new file mode 100644 index 00000000..852ba60e --- /dev/null +++ b/tests/bugs/test_core_1056.py @@ -0,0 +1,60 @@ +#coding:utf-8 +# +# id: bugs.core_1056 +# title: A query could produce different results, depending on the presence of an index +# decription: +# tracker_id: CORE-1056 +# min_versions: [] +# versions: 2.0 +# qmid: bugs.core_1056 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t (c varchar(10) character set win1250 collate pxw_csy); +insert into t values ('ch'); +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """set plan on; + +select * from t where c starting with 'c'; +commit; + +create index t_c on t (c); +commit; + +select * from t where c starting with 'c'; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +PLAN (T NATURAL) + +C +========== +ch + + +PLAN (T INDEX (T_C)) + +C +========== +ch + +""" + +@pytest.mark.version('>=2.0') +def test_core_1056_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1058.py b/tests/bugs/test_core_1058.py new file mode 100644 index 00000000..2715b89b --- /dev/null +++ b/tests/bugs/test_core_1058.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: bugs.core_1058 +# title: ALTER DOMAIN and ALTER TABLE don't allow to change character set and/or collation +# decription: +# tracker_id: CORE-1058 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1058 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE DOMAIN D_TEST AS VARCHAR(100) CHARACTER SET WIN1251; +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ALTER DOMAIN D_TEST TYPE VARCHAR(100) CHARACTER SET UTF8; +COMMIT; +SHOW DOMAIN D_TEST; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """D_TEST VARCHAR(100) CHARACTER SET UTF8 Nullable +""" + +@pytest.mark.version('>=2.1') +def test_core_1058_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1063.py b/tests/bugs/test_core_1063.py new file mode 100644 index 00000000..a74d1b1a --- /dev/null +++ b/tests/bugs/test_core_1063.py @@ -0,0 +1,122 @@ +#coding:utf-8 +# +# id: bugs.core_1063 +# title: Server hangs eating CPU and performs huge I/O copying different codepage fields +# decription: +# tracker_id: CORE-1063 +# min_versions: [] +# versions: 2.0.1 +# qmid: bugs.core_1063 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core1063.fbk', init=init_script_1) + +test_script_1 = """alter table cms_wiki +add u_name varchar(100) character set UTF8, +add u_title varchar(100) character set UTF8, +add u_description blob sub_type 1 character set UTF8, +add u_text blob sub_type 1 character set UTF8; + +commit; + +update cms_wiki set +u_name = name, u_title = title, u_text = text, u_description = description; + +commit; + +drop index uq_cms_wiki; + +alter table cms_wiki drop name, drop description, drop text, drop title; + +commit; + +alter table cms_wiki +alter u_name to name, +alter u_title to title, +alter u_description to description, +alter u_text to text; + +commit; + +CREATE UNIQUE INDEX UQ_CMS_WIKI ON CMS_WIKI (NAME, SITE_ID); + +commit; +set heading off; +select name from CMS_WIKI; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + .menu + awards.htm + affiliate_program.htm + user_guide.htm + forms/feedback.htm + faq.htm + products.htm + zonetick_v2.7_plan.htm + fxstreet.htm + confirmed.htm + index.htm + mail/confirm + launch.htm + .menu + forms/why_uninstall.htm + modification_guidelines.htm + forms/feature_request.htm + addition_minneapolis.htm + cities.htm + index.htm + + index.meta + index.htm + database_format_discussion.htm + .menu + profiles.htm + modification_guidelines.htm + update.htm + oem.htm + content_providers.htm + addition_hamburg.htm + forms/confirm.htm + packs.htm + zonetick_v2.7_released.htm + quotes.htm + skins.htm + feedback.htm + addition_phoenix.htm + zonetick_v3.0_plan.htm + wrtimetracker_v0.4_released.htm + zonetick_v2.7_beta.htm + + + jobs.htm + contact.htm + wrtimetracker/faq.htm + wrtimetracker/user_manual.htm + addition_salt_lake_city.htm + wrtimetracker/index.htm + wrtimetracker/license.htm + addition_singapore.htm + addition_lipetsk.htm + addition_miami.htm + addition_miami.htm + .menu_zonetick + """ + +@pytest.mark.version('>=2.0.1') +def test_core_1063_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1073.py b/tests/bugs/test_core_1073.py new file mode 100644 index 00000000..0cd25697 --- /dev/null +++ b/tests/bugs/test_core_1073.py @@ -0,0 +1,111 @@ +#coding:utf-8 +# +# id: bugs.core_1073 +# title: SINGULAR buggy when nulls present +# decription: +# tracker_id: CORE-1073 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1073 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t (a integer); +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# def check(step,cur,statement,exp): +# cur.execute(statement) +# r = cur.fetchone() +# if (exp and (r is None)) or (not exp and (r is not None)): +# print ('Test FAILED in step ',step,', expectation ',exp) +# print ('Statement:',statement) +# +# c = db_conn.cursor() +# p_singular = 'select 1 from rdb$database where singular(select * from t where a = 1)' +# n_singular = 'select 1 from rdb$database where not(singular(select * from t where a = 1))' +# p_nsingular = 'select 1 from rdb$database where not singular( select * from t where a = 1)' +# n_nsingular = 'select 1 from rdb$database where not(not singular(select * from t where a = 1))' +# +# ins = 'insert into t values (%s)' +# +# # Step 1 +# +# c.execute(ins % '2') +# c.execute(ins % 'null') +# db_conn.commit() +# +# check(1,c,p_singular,False) +# check(1,c,n_singular,True) +# check(1,c,p_nsingular,True) +# check(1,c,n_nsingular,False) +# +# c.execute('delete from t') +# db_conn.commit() +# +# # Step 2 +# +# c.execute(ins % '1') +# c.execute(ins % 'null') +# db_conn.commit() +# +# check(2,c,p_singular,True) +# check(2,c,n_singular,False) +# check(2,c,p_nsingular,False) +# check(2,c,n_nsingular,True) +# +# c.execute('delete from t') +# db_conn.commit() +# +# # Step 3 +# +# c.execute(ins % '1') +# c.execute(ins % 'null') +# c.execute(ins % '1') +# db_conn.commit() +# +# check(3,c,p_singular,False) +# check(3,c,n_singular,True) +# check(3,c,p_nsingular,True) +# check(3,c,n_nsingular,False) +# +# c.execute('delete from t') +# db_conn.commit() +# +# # Step 4 +# +# c.execute(ins % '1') +# c.execute(ins % '1') +# c.execute(ins % 'null') +# db_conn.commit() +# +# check(4,c,p_singular,False) +# check(4,c,n_singular,True) +# check(4,c,p_nsingular,True) +# check(4,c,n_nsingular,False) +# +# c.execute('delete from t') +# db_conn.commit() +# +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1') +@pytest.mark.xfail +def test_core_1073_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_1076.py b/tests/bugs/test_core_1076.py new file mode 100644 index 00000000..26e35026 --- /dev/null +++ b/tests/bugs/test_core_1076.py @@ -0,0 +1,188 @@ +#coding:utf-8 +# +# id: bugs.core_1076 +# title: gsec truncate First.Middle.Last Name fields to 17 chars instead of 32 chars available in field definition +# decription: +# FB2.0 correctly saves First, Middle & Last Name fields in the security database to the available length of 32 characters. +# FB1.5.3 and still now FB1.5.4RC1 truncates these field lengths to 17 chars. +# --- +# 11.01.2016: refactored for 3.0: use FBSVCMGR instead of GSEC. This was agreed with Alex, see his reply 11.01.2015 17:57. +# +# +# tracker_id: CORE-1076 +# min_versions: [] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# from subprocess import Popen +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# +# #-------------------------------------------- +# +# 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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# +# #-------------------------------------------- +# +# db_name=db_conn.database_name +# db_conn.close() +# +# svc = services.connect(host='localhost') +# security_db_name = svc.get_security_database_path() # path+name of security DB +# svc.close() +# +# check_login="Nebuchadnezzar2_King_of_Babylon" +# +# f_svc_log=open( os.path.join(context['temp_directory'],'tmp_1076_fbsvc.log'), 'w') +# f_svc_err=open( os.path.join(context['temp_directory'],'tmp_1076_fbsvc.err'), 'w') +# +# f_svc_log.write("Try to add user.") +# f_svc_log.write("\\n") +# f_svc_log.seek(0,2) +# +# subprocess.call( [ context['fbsvcmgr_path'] +# ,"localhost:service_mgr" +# ,"action_add_user" +# ,"dbname", security_db_name +# ,"sec_username", check_login +# ,"sec_password", "Nebu_King_of_Babylon" +# ] +# ,stdout=f_svc_log, stderr=f_svc_err +# ) +# +# f_svc_log.seek(0,2) +# f_svc_log.write("\\n") +# f_svc_log.write("Try to modify user: change password and some attributes.") +# f_svc_log.write("\\n") +# f_svc_log.seek(0,2) +# +# subprocess.call( [ context['fbsvcmgr_path'] +# ,"localhost:service_mgr" +# ,"action_modify_user" +# ,"dbname", security_db_name +# ,"sec_username", check_login +# ,"sec_firstname", "Nebuchadnezzar3_King_of_Babylon" +# ,"sec_middlename", "Nebuchadnezzar4_King_of_Babylon" +# ,"sec_lastname", "Nebuchadnezzar5_King_of_Babylon" +# ] +# ,stdout=f_svc_log, stderr=f_svc_err +# ) +# +# f_svc_log.seek(0,2) +# f_svc_log.write("\\n") +# f_svc_log.write("All done.") +# f_svc_log.write("\\n") +# +# flush_and_close( f_svc_log ) +# flush_and_close( f_svc_err ) +# +# isql_txt=''' 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('%s'); +# commit; +# drop user %s; +# ''' % (check_login, check_login) +# +# f_sql_txt=open( os.path.join(context['temp_directory'],'tmp_1076_isql.sql'), 'w') +# f_sql_txt.write(isql_txt) +# flush_and_close( f_sql_txt ) +# +# f_sql_log=open( os.path.join(context['temp_directory'],'tmp_1076_isql.log'), 'w') +# f_sql_err=open( os.path.join(context['temp_directory'],'tmp_1076_isql.err'), 'w') +# +# subprocess.call( [ context['isql_path'], dsn, "-i", f_sql_txt.name ] +# ,stdout=f_sql_log +# ,stderr=f_sql_err +# ) +# +# flush_and_close( f_sql_log ) +# flush_and_close( f_sql_err ) +# +# with open( f_svc_log.name,'r') as f: +# l = [l for l in f.readlines() if l.strip()] +# +# for line in l: +# print("SVC STDOUT: "+line ) +# +# with open( f_svc_err.name,'r') as f: +# l = [l for l in f.readlines() if l.strip()] +# +# for line in l: +# print("SVC STDERR: "+line ) +# +# with open( f_sql_log.name,'r') as f: +# l = [l for l in f.readlines() if l.strip()] +# +# for line in l: +# print("SQL STDOUT: "+line ) +# +# with open( f_sql_err.name,'r') as f: +# l = [l for l in f.readlines() if l.strip()] +# +# for line in l: +# print("SQL STDERR: "+line ) +# +# ############################################# +# +# # Cleanup. +# time.sleep(1) +# cleanup( [i.name for i in (f_svc_log, f_svc_err, f_sql_log, f_sql_err, f_sql_txt)] ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + SVC STDOUT: Try to add user. + SVC STDOUT: Try to modify user: change password and some attributes. + SVC STDOUT: All done. + SQL STDOUT: SEC$USER_NAME NEBUCHADNEZZAR2_KING_OF_BABYLON + SQL STDOUT: SEC$FIRST_NAME Nebuchadnezzar3_King_of_Babylon + SQL STDOUT: SEC$MIDDLE_NAME Nebuchadnezzar4_King_of_Babylon + SQL STDOUT: SEC$LAST_NAME Nebuchadnezzar5_King_of_Babylon + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_1076_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_1078.py b/tests/bugs/test_core_1078.py new file mode 100644 index 00000000..35f0b04b --- /dev/null +++ b/tests/bugs/test_core_1078.py @@ -0,0 +1,34 @@ +#coding:utf-8 +# +# id: bugs.core_1078 +# title: View with equally named source fields not faisible +# decription: +# tracker_id: CORE-1078 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1078 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t1(id integer, field1 integer); +create table t2(id integer, field1 integer); +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """create view view1 as select t1.field1 as t1f1, t2.field1 as t2f1 from t1 JOIN t2 on t2.id = t1.id; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1') +def test_core_1078_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_1083.py b/tests/bugs/test_core_1083.py new file mode 100644 index 00000000..8e6ca762 --- /dev/null +++ b/tests/bugs/test_core_1083.py @@ -0,0 +1,80 @@ +#coding:utf-8 +# +# id: bugs.core_1083 +# title: User (not SYSDBA) what have privileges with grant option, can't revoke privileges, granted by other user or SYSDBA +# decription: +# tracker_id: CORE-1083 +# min_versions: ['2.1.0'] +# versions: 3.0 +# qmid: bugs.core_1083 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('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.')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- 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. + + 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; + + connect 'localhost:$(DATABASE_LOCATION)bugs.core_1083.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; + + connect 'localhost:$(DATABASE_LOCATION)bugs.core_1083.fdb' user 'SYSDBA' password 'masterkey'; + set echo on; + drop user tmp$c1083; + set echo off; + commit; + -- ('-TMP\\$C1083 is not grantor.*', '') + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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; + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -REVOKE failed + -TMP$C1083 is not grantor of UPDATE on TAB2 to ROLE1. + """ + +@pytest.mark.version('>=3.0') +def test_core_1083_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1089.py b/tests/bugs/test_core_1089.py new file mode 100644 index 00000000..888c974d --- /dev/null +++ b/tests/bugs/test_core_1089.py @@ -0,0 +1,141 @@ +#coding:utf-8 +# +# id: bugs.core_1089 +# title: Wrong ordering with views, distinct, left join and order by +# decription: +# tracker_id: CORE-1089 +# min_versions: ['2.0.6'] +# versions: 2.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table fat( + idxxfat varchar(26) not null, + progfat int, + idxxccb varchar(20), + ndonfat int, + constraint pk$_fat primary key (idxxfat) + ); + create table sca( + idxxsca varchar(16) not null, + progsca int, + idxxfat varchar(26), + constraint pk$_sca primary key (idxxsca) + ); + commit; + + create view vw$_sca as + select distinct + sca.idxxsca, + sca.progsca, + sca.idxxfat, + fat.idxxccb, + fat.ndonfat + from sca + left join fat on sca.idxxfat=fat.idxxfat; + + + insert into fat (idxxfat,progfat,idxxccb,ndonfat) values('2007.1',1,'y',1002); + insert into fat (idxxfat,progfat,idxxccb,ndonfat) values('2007.2',2,'x',1001); + commit; + + insert into sca (idxxsca,progsca,idxxfat) values ('2007.4',4,'2007.1'); + insert into sca (idxxsca,progsca,idxxfat) values ('2007.3',3,'2007.1'); + insert into sca (idxxsca,progsca,idxxfat) values ('2007.2',2,'2007.2'); + insert into sca (idxxsca,progsca,idxxfat) values ('2007.1',1,'2007.2'); + commit; + + -- test-1: + set list on; + select 'test-1' as msg, v.* + from vw$_sca v + order by 2 desc; + commit; + + ------------------------------------ + -- Sample from core-2863 (wrong output confirmed on 2.1.0.17798): + + recreate view test_view as select 1 i from rdb$database; + commit; + + recreate table test_table(myfield integer); + + recreate view test_view(myfield1, myfield2) as + select distinct m.myfield, s.myfield + from test_table m + left join test_table s on m.myfield = s.myfield; + commit; + + insert into test_table values (1); + insert into test_table values (2); + + commit; + + set list on; + + select 'test-2' as msg, v.* + from test_view v + order by myfield1 desc; + commit; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG test-1 + IDXXSCA 2007.4 + PROGSCA 4 + IDXXFAT 2007.1 + IDXXCCB y + NDONFAT 1002 + + MSG test-1 + IDXXSCA 2007.3 + PROGSCA 3 + IDXXFAT 2007.1 + IDXXCCB y + NDONFAT 1002 + + MSG test-1 + IDXXSCA 2007.2 + PROGSCA 2 + IDXXFAT 2007.2 + IDXXCCB x + NDONFAT 1001 + + MSG test-1 + IDXXSCA 2007.1 + PROGSCA 1 + IDXXFAT 2007.2 + IDXXCCB x + NDONFAT 1001 + + + MSG test-2 + MYFIELD1 2 + MYFIELD2 2 + + MSG test-2 + MYFIELD1 1 + MYFIELD2 1 + """ + +@pytest.mark.version('>=2.0.6') +def test_core_1089_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1090.py b/tests/bugs/test_core_1090.py new file mode 100644 index 00000000..01db7937 --- /dev/null +++ b/tests/bugs/test_core_1090.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_1090 +# title: Error msg "Could not find UNIQUE INDEX" when in fact one is present +# decription: +# tracker_id: CORE-1090 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_1090-250 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t (i integer not null); +create unique index ti on t(i); +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """show table t; +show index ti; + +create table t2 (i integer references t(i)); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """I INTEGER Not Null +TI UNIQUE INDEX ON T(I) +""" +expected_stderr_1 = """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 +""" + +@pytest.mark.version('>=3.0') +def test_core_1090_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1095.py b/tests/bugs/test_core_1095.py new file mode 100644 index 00000000..22cbf6f9 --- /dev/null +++ b/tests/bugs/test_core_1095.py @@ -0,0 +1,112 @@ +#coding:utf-8 +# +# id: bugs.core_1095 +# title: Support BETWEEN predicate for select expressions +# decription: +# Checked on WI-V3.0.2.32670, WI-T4.0.0.503 - all fine. +# NOTE. Plan with table name (instead of alias 'R_CHK') in 2nd line was: +# === +# PLAN (R_CHK NATURAL) +# PLAN (RDB$DATABASE NATURAL) <<<< ?? +# PLAN (R_OUT NATURAL) +# === +# Fixed 28.01.2017 11:51 ("Preserve the alias after the relation/procedure node copying"). +# https://github.com/FirebirdSQL/firebird/commit/36b86a02e5df20d82855fe1af00bac27022bbf8e +# https://github.com/FirebirdSQL/firebird/commit/cbe9ac071f187e7766c2a67fdf47683604361059 +# Checked on WI-V3.0.2.32677, WI-T4.0.0.519 +# Checked again 22.11.2017: +# 3.0.3.32837: OK, 2.781s. +# 3.0.3.32838: OK, 1.438s. +# 4.0.0.800: OK, 2.547s. +# 4.0.0.801: OK, 1.640s. +# +# tracker_id: CORE-1095 +# min_versions: ['3.0.2'] +# versions: 3.0.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set sqlda_display on; + set planonly; + -- Before 3.0.2 following statement failed with: + -- Statement failed, SQLSTATE = HY004 + -- Unsupported field type specified in BETWEEN predicate. + select 3 from rdb$database r_out where ((select count(*) from rdb$database r_chk) between ? and ?); + + ---------------------------------------------------------- + + -- Following sample is from CORE-5596 (added 22.11.2017). + -- On 2.5.x it issues: + -- Statement failed, SQLSTATE = XX000 + -- internal Firebird consistency check ((CMP) copy: cannot remap (221), file: cmp.cpp line: 3091) + select 1 + from rdb$database + where + iif( + exists( select 1 from rdb$database ) + , 0e0 + , 0e0 + ) + between ? and ? + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + INPUT message field count: 2 + 01: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: alias: + : table: owner: + 02: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: alias: + : table: owner: + + PLAN (R_CHK NATURAL) + PLAN (R_CHK NATURAL) + PLAN (R_OUT NATURAL) + + OUTPUT message field count: 1 + 01: sqltype: 496 LONG scale: 0 subtype: 0 len: 4 + : name: CONSTANT alias: CONSTANT + : table: owner: + + + + INPUT message field count: 2 + 01: sqltype: 480 DOUBLE scale: 0 subtype: 0 len: 8 + : name: alias: + : table: owner: + 02: sqltype: 480 DOUBLE scale: 0 subtype: 0 len: 8 + : name: alias: + : table: owner: + + PLAN (RDB$DATABASE NATURAL) + PLAN (RDB$DATABASE NATURAL) + PLAN (RDB$DATABASE NATURAL) + + OUTPUT message field count: 1 + 01: sqltype: 496 LONG scale: 0 subtype: 0 len: 4 + : name: CONSTANT alias: CONSTANT + : table: owner: + + """ + +@pytest.mark.version('>=3.0.2') +def test_core_1095_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1108.py b/tests/bugs/test_core_1108.py new file mode 100644 index 00000000..4aac6ffb --- /dev/null +++ b/tests/bugs/test_core_1108.py @@ -0,0 +1,96 @@ +#coding:utf-8 +# +# id: bugs.core_1108 +# title: Wrong results with GROUP BY on constants +# decription: This test may hang (or take very long time to finish) the server version 1.5.x +# tracker_id: CORE-1108 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_1108-21 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE EMPLOYEE ( + EMP_NO SMALLINT, + JOB_COUNTRY VARCHAR(15)); + +COMMIT; + +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (2, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (4, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (5, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (8, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (9, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (11, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (12, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (14, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (15, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (20, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (24, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (28, 'England'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (29, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (34, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (36, 'England'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (37, 'England'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (44, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (45, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (46, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (52, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (61, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (65, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (71, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (72, 'Canada'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (83, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (85, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (94, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (105, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (107, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (109, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (110, 'Japan'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (113, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (114, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (118, 'Japan'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (121, 'Italy'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (127, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (134, 'France'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (136, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (138, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (141, 'Switzerland'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (144, 'USA'); +INSERT INTO EMPLOYEE (EMP_NO, JOB_COUNTRY) VALUES (145, 'USA'); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """Select 'Country:', Job_Country, Count(*) + From Employee + Group By 1,2;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """CONSTANT JOB_COUNTRY COUNT +======== =============== ===================== +Country: Canada 1 +Country: England 3 +Country: France 1 +Country: Italy 1 +Country: Japan 2 +Country: Switzerland 1 +Country: USA 33 + +""" + +@pytest.mark.version('>=3.0') +def test_core_1108_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1112.py b/tests/bugs/test_core_1112.py new file mode 100644 index 00000000..b42b2358 --- /dev/null +++ b/tests/bugs/test_core_1112.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: bugs.core_1112 +# title: Crash when dealing with a string literal longer than 32K +# decription: This test may crash the server +# tracker_id: CORE-1112 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1112 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# c = db_conn.cursor() +# longstr = 'abc' * 10930 +# try: +# c.execute("select * from rdb$database where '%s' = 'a'" % longstr) +# except: +# pass +# +# try: +# c.execute("select * from rdb$database where '%s' containing 'a'" % longstr) +# except: +# pass +# c.execute("select 'a' from rdb$database") +# print (c.fetchall()) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """[('a',)] +""" + +@pytest.mark.version('>=2.1') +@pytest.mark.xfail +def test_core_1112_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_1117.py b/tests/bugs/test_core_1117.py new file mode 100644 index 00000000..930b55b5 --- /dev/null +++ b/tests/bugs/test_core_1117.py @@ -0,0 +1,2094 @@ +#coding:utf-8 +# +# id: bugs.core_1117 +# title: Remove or extend limit of command text length (64K) +# decription: +# 30.10.2019. NB: new datatype in FB 4.0 was introduces: numeric(38,0). +# It can lead to additional ident of values when we show them in form "SET LIST ON", +# so we have to ignore all internal spaces - see added 'substitution' section below. +# Checked on: +# 4.0.0.1635 SS: 0.917s. +# 3.0.5.33182 SS: 0.765s. +# +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: bugs.core_1117 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- This test verifies that we can issue STATIC `SELECT` statement with length more than 64K. + -- Following `SELECT` has length = ~72900 bytes, but FB 3.0 can successfully hangle + -- much longer (checked up to 5000 columns). + -- FB 2.5 fails with such commands with message: "Single isql command exceeded maximum buffer size" + -- See also: CORE-1609 ("PSQL output parameter size limited"). + -- -------------------------------------------------------------------------------- + -- -- Batch for generating such script with variable number of columns: + -- @echo off + -- setlocal enabledelayedexpansion enableextensions + -- set pq=%1 + -- if .%1.==.. exit + -- set sql=c1117.sql + -- del %sql% 2>nul + -- + -- echo recreate sequence g; >>%sql% + -- echo commit;>>%sql% + -- echo set list on; >>%sql% + -- echo set stat on; >>%sql% + -- echo select >>%sql% + -- echo sum(>>%sql% + -- for /l %%i in (1, 1, %pq%) do ( + -- if .%%i.==.1. ( + -- echo gen_value_on_col_%%i >>%sql% + -- ) else ( + -- echo + gen_value_on_col_%%i >>%sql% + -- ) + -- ) + -- echo ) as sum_all>>%sql% + -- echo from (>>%sql% + -- echo select>>%sql% + -- for /l %%i in (1, 1, %pq%) do ( + -- if .%%i.==.1. ( + -- echo gen_id(g, 1^) as gen_value_on_col_%%i >>%sql% + -- ) else ( + -- echo ,gen_id(g, 1^) as gen_value_on_col_%%i >>%sql% + -- ) + -- ) + -- echo from rdb$database>>%sql% + -- echo );>>%sql% + + recreate sequence g; + commit; + set list on; + select + sum( + gen_value_on_col_1 + + gen_value_on_col_2 + + gen_value_on_col_3 + + gen_value_on_col_4 + + gen_value_on_col_5 + + gen_value_on_col_6 + + gen_value_on_col_7 + + gen_value_on_col_8 + + gen_value_on_col_9 + + gen_value_on_col_10 + + gen_value_on_col_11 + + gen_value_on_col_12 + + gen_value_on_col_13 + + gen_value_on_col_14 + + gen_value_on_col_15 + + gen_value_on_col_16 + + gen_value_on_col_17 + + gen_value_on_col_18 + + gen_value_on_col_19 + + gen_value_on_col_20 + + gen_value_on_col_21 + + gen_value_on_col_22 + + gen_value_on_col_23 + + gen_value_on_col_24 + + gen_value_on_col_25 + + gen_value_on_col_26 + + gen_value_on_col_27 + + gen_value_on_col_28 + + gen_value_on_col_29 + + gen_value_on_col_30 + + gen_value_on_col_31 + + gen_value_on_col_32 + + gen_value_on_col_33 + + gen_value_on_col_34 + + gen_value_on_col_35 + + gen_value_on_col_36 + + gen_value_on_col_37 + + gen_value_on_col_38 + + gen_value_on_col_39 + + gen_value_on_col_40 + + gen_value_on_col_41 + + gen_value_on_col_42 + + gen_value_on_col_43 + + gen_value_on_col_44 + + gen_value_on_col_45 + + gen_value_on_col_46 + + gen_value_on_col_47 + + gen_value_on_col_48 + + gen_value_on_col_49 + + gen_value_on_col_50 + + gen_value_on_col_51 + + gen_value_on_col_52 + + gen_value_on_col_53 + + gen_value_on_col_54 + + gen_value_on_col_55 + + gen_value_on_col_56 + + gen_value_on_col_57 + + gen_value_on_col_58 + + gen_value_on_col_59 + + gen_value_on_col_60 + + gen_value_on_col_61 + + gen_value_on_col_62 + + gen_value_on_col_63 + + gen_value_on_col_64 + + gen_value_on_col_65 + + gen_value_on_col_66 + + gen_value_on_col_67 + + gen_value_on_col_68 + + gen_value_on_col_69 + + gen_value_on_col_70 + + gen_value_on_col_71 + + gen_value_on_col_72 + + gen_value_on_col_73 + + gen_value_on_col_74 + + gen_value_on_col_75 + + gen_value_on_col_76 + + gen_value_on_col_77 + + gen_value_on_col_78 + + gen_value_on_col_79 + + gen_value_on_col_80 + + gen_value_on_col_81 + + gen_value_on_col_82 + + gen_value_on_col_83 + + gen_value_on_col_84 + + gen_value_on_col_85 + + gen_value_on_col_86 + + gen_value_on_col_87 + + gen_value_on_col_88 + + gen_value_on_col_89 + + gen_value_on_col_90 + + gen_value_on_col_91 + + gen_value_on_col_92 + + gen_value_on_col_93 + + gen_value_on_col_94 + + gen_value_on_col_95 + + gen_value_on_col_96 + + gen_value_on_col_97 + + gen_value_on_col_98 + + gen_value_on_col_99 + + gen_value_on_col_100 + + gen_value_on_col_101 + + gen_value_on_col_102 + + gen_value_on_col_103 + + gen_value_on_col_104 + + gen_value_on_col_105 + + gen_value_on_col_106 + + gen_value_on_col_107 + + gen_value_on_col_108 + + gen_value_on_col_109 + + gen_value_on_col_110 + + gen_value_on_col_111 + + gen_value_on_col_112 + + gen_value_on_col_113 + + gen_value_on_col_114 + + gen_value_on_col_115 + + gen_value_on_col_116 + + gen_value_on_col_117 + + gen_value_on_col_118 + + gen_value_on_col_119 + + gen_value_on_col_120 + + gen_value_on_col_121 + + gen_value_on_col_122 + + gen_value_on_col_123 + + gen_value_on_col_124 + + gen_value_on_col_125 + + gen_value_on_col_126 + + gen_value_on_col_127 + + gen_value_on_col_128 + + gen_value_on_col_129 + + gen_value_on_col_130 + + gen_value_on_col_131 + + gen_value_on_col_132 + + gen_value_on_col_133 + + gen_value_on_col_134 + + gen_value_on_col_135 + + gen_value_on_col_136 + + gen_value_on_col_137 + + gen_value_on_col_138 + + gen_value_on_col_139 + + gen_value_on_col_140 + + gen_value_on_col_141 + + gen_value_on_col_142 + + gen_value_on_col_143 + + gen_value_on_col_144 + + gen_value_on_col_145 + + gen_value_on_col_146 + + gen_value_on_col_147 + + gen_value_on_col_148 + + gen_value_on_col_149 + + gen_value_on_col_150 + + gen_value_on_col_151 + + gen_value_on_col_152 + + gen_value_on_col_153 + + gen_value_on_col_154 + + gen_value_on_col_155 + + gen_value_on_col_156 + + gen_value_on_col_157 + + gen_value_on_col_158 + + gen_value_on_col_159 + + gen_value_on_col_160 + + gen_value_on_col_161 + + gen_value_on_col_162 + + gen_value_on_col_163 + + gen_value_on_col_164 + + gen_value_on_col_165 + + gen_value_on_col_166 + + gen_value_on_col_167 + + gen_value_on_col_168 + + gen_value_on_col_169 + + gen_value_on_col_170 + + gen_value_on_col_171 + + gen_value_on_col_172 + + gen_value_on_col_173 + + gen_value_on_col_174 + + gen_value_on_col_175 + + gen_value_on_col_176 + + gen_value_on_col_177 + + gen_value_on_col_178 + + gen_value_on_col_179 + + gen_value_on_col_180 + + gen_value_on_col_181 + + gen_value_on_col_182 + + gen_value_on_col_183 + + gen_value_on_col_184 + + gen_value_on_col_185 + + gen_value_on_col_186 + + gen_value_on_col_187 + + gen_value_on_col_188 + + gen_value_on_col_189 + + gen_value_on_col_190 + + gen_value_on_col_191 + + gen_value_on_col_192 + + gen_value_on_col_193 + + gen_value_on_col_194 + + gen_value_on_col_195 + + gen_value_on_col_196 + + gen_value_on_col_197 + + gen_value_on_col_198 + + gen_value_on_col_199 + + gen_value_on_col_200 + + gen_value_on_col_201 + + gen_value_on_col_202 + + gen_value_on_col_203 + + gen_value_on_col_204 + + gen_value_on_col_205 + + gen_value_on_col_206 + + gen_value_on_col_207 + + gen_value_on_col_208 + + gen_value_on_col_209 + + gen_value_on_col_210 + + gen_value_on_col_211 + + gen_value_on_col_212 + + gen_value_on_col_213 + + gen_value_on_col_214 + + gen_value_on_col_215 + + gen_value_on_col_216 + + gen_value_on_col_217 + + gen_value_on_col_218 + + gen_value_on_col_219 + + gen_value_on_col_220 + + gen_value_on_col_221 + + gen_value_on_col_222 + + gen_value_on_col_223 + + gen_value_on_col_224 + + gen_value_on_col_225 + + gen_value_on_col_226 + + gen_value_on_col_227 + + gen_value_on_col_228 + + gen_value_on_col_229 + + gen_value_on_col_230 + + gen_value_on_col_231 + + gen_value_on_col_232 + + gen_value_on_col_233 + + gen_value_on_col_234 + + gen_value_on_col_235 + + gen_value_on_col_236 + + gen_value_on_col_237 + + gen_value_on_col_238 + + gen_value_on_col_239 + + gen_value_on_col_240 + + gen_value_on_col_241 + + gen_value_on_col_242 + + gen_value_on_col_243 + + gen_value_on_col_244 + + gen_value_on_col_245 + + gen_value_on_col_246 + + gen_value_on_col_247 + + gen_value_on_col_248 + + gen_value_on_col_249 + + gen_value_on_col_250 + + gen_value_on_col_251 + + gen_value_on_col_252 + + gen_value_on_col_253 + + gen_value_on_col_254 + + gen_value_on_col_255 + + gen_value_on_col_256 + + gen_value_on_col_257 + + gen_value_on_col_258 + + gen_value_on_col_259 + + gen_value_on_col_260 + + gen_value_on_col_261 + + gen_value_on_col_262 + + gen_value_on_col_263 + + gen_value_on_col_264 + + gen_value_on_col_265 + + gen_value_on_col_266 + + gen_value_on_col_267 + + gen_value_on_col_268 + + gen_value_on_col_269 + + gen_value_on_col_270 + + gen_value_on_col_271 + + gen_value_on_col_272 + + gen_value_on_col_273 + + gen_value_on_col_274 + + gen_value_on_col_275 + + gen_value_on_col_276 + + gen_value_on_col_277 + + gen_value_on_col_278 + + gen_value_on_col_279 + + gen_value_on_col_280 + + gen_value_on_col_281 + + gen_value_on_col_282 + + gen_value_on_col_283 + + gen_value_on_col_284 + + gen_value_on_col_285 + + gen_value_on_col_286 + + gen_value_on_col_287 + + gen_value_on_col_288 + + gen_value_on_col_289 + + gen_value_on_col_290 + + gen_value_on_col_291 + + gen_value_on_col_292 + + gen_value_on_col_293 + + gen_value_on_col_294 + + gen_value_on_col_295 + + gen_value_on_col_296 + + gen_value_on_col_297 + + gen_value_on_col_298 + + gen_value_on_col_299 + + gen_value_on_col_300 + + gen_value_on_col_301 + + gen_value_on_col_302 + + gen_value_on_col_303 + + gen_value_on_col_304 + + gen_value_on_col_305 + + gen_value_on_col_306 + + gen_value_on_col_307 + + gen_value_on_col_308 + + gen_value_on_col_309 + + gen_value_on_col_310 + + gen_value_on_col_311 + + gen_value_on_col_312 + + gen_value_on_col_313 + + gen_value_on_col_314 + + gen_value_on_col_315 + + gen_value_on_col_316 + + gen_value_on_col_317 + + gen_value_on_col_318 + + gen_value_on_col_319 + + gen_value_on_col_320 + + gen_value_on_col_321 + + gen_value_on_col_322 + + gen_value_on_col_323 + + gen_value_on_col_324 + + gen_value_on_col_325 + + gen_value_on_col_326 + + gen_value_on_col_327 + + gen_value_on_col_328 + + gen_value_on_col_329 + + gen_value_on_col_330 + + gen_value_on_col_331 + + gen_value_on_col_332 + + gen_value_on_col_333 + + gen_value_on_col_334 + + gen_value_on_col_335 + + gen_value_on_col_336 + + gen_value_on_col_337 + + gen_value_on_col_338 + + gen_value_on_col_339 + + gen_value_on_col_340 + + gen_value_on_col_341 + + gen_value_on_col_342 + + gen_value_on_col_343 + + gen_value_on_col_344 + + gen_value_on_col_345 + + gen_value_on_col_346 + + gen_value_on_col_347 + + gen_value_on_col_348 + + gen_value_on_col_349 + + gen_value_on_col_350 + + gen_value_on_col_351 + + gen_value_on_col_352 + + gen_value_on_col_353 + + gen_value_on_col_354 + + gen_value_on_col_355 + + gen_value_on_col_356 + + gen_value_on_col_357 + + gen_value_on_col_358 + + gen_value_on_col_359 + + gen_value_on_col_360 + + gen_value_on_col_361 + + gen_value_on_col_362 + + gen_value_on_col_363 + + gen_value_on_col_364 + + gen_value_on_col_365 + + gen_value_on_col_366 + + gen_value_on_col_367 + + gen_value_on_col_368 + + gen_value_on_col_369 + + gen_value_on_col_370 + + gen_value_on_col_371 + + gen_value_on_col_372 + + gen_value_on_col_373 + + gen_value_on_col_374 + + gen_value_on_col_375 + + gen_value_on_col_376 + + gen_value_on_col_377 + + gen_value_on_col_378 + + gen_value_on_col_379 + + gen_value_on_col_380 + + gen_value_on_col_381 + + gen_value_on_col_382 + + gen_value_on_col_383 + + gen_value_on_col_384 + + gen_value_on_col_385 + + gen_value_on_col_386 + + gen_value_on_col_387 + + gen_value_on_col_388 + + gen_value_on_col_389 + + gen_value_on_col_390 + + gen_value_on_col_391 + + gen_value_on_col_392 + + gen_value_on_col_393 + + gen_value_on_col_394 + + gen_value_on_col_395 + + gen_value_on_col_396 + + gen_value_on_col_397 + + gen_value_on_col_398 + + gen_value_on_col_399 + + gen_value_on_col_400 + + gen_value_on_col_401 + + gen_value_on_col_402 + + gen_value_on_col_403 + + gen_value_on_col_404 + + gen_value_on_col_405 + + gen_value_on_col_406 + + gen_value_on_col_407 + + gen_value_on_col_408 + + gen_value_on_col_409 + + gen_value_on_col_410 + + gen_value_on_col_411 + + gen_value_on_col_412 + + gen_value_on_col_413 + + gen_value_on_col_414 + + gen_value_on_col_415 + + gen_value_on_col_416 + + gen_value_on_col_417 + + gen_value_on_col_418 + + gen_value_on_col_419 + + gen_value_on_col_420 + + gen_value_on_col_421 + + gen_value_on_col_422 + + gen_value_on_col_423 + + gen_value_on_col_424 + + gen_value_on_col_425 + + gen_value_on_col_426 + + gen_value_on_col_427 + + gen_value_on_col_428 + + gen_value_on_col_429 + + gen_value_on_col_430 + + gen_value_on_col_431 + + gen_value_on_col_432 + + gen_value_on_col_433 + + gen_value_on_col_434 + + gen_value_on_col_435 + + gen_value_on_col_436 + + gen_value_on_col_437 + + gen_value_on_col_438 + + gen_value_on_col_439 + + gen_value_on_col_440 + + gen_value_on_col_441 + + gen_value_on_col_442 + + gen_value_on_col_443 + + gen_value_on_col_444 + + gen_value_on_col_445 + + gen_value_on_col_446 + + gen_value_on_col_447 + + gen_value_on_col_448 + + gen_value_on_col_449 + + gen_value_on_col_450 + + gen_value_on_col_451 + + gen_value_on_col_452 + + gen_value_on_col_453 + + gen_value_on_col_454 + + gen_value_on_col_455 + + gen_value_on_col_456 + + gen_value_on_col_457 + + gen_value_on_col_458 + + gen_value_on_col_459 + + gen_value_on_col_460 + + gen_value_on_col_461 + + gen_value_on_col_462 + + gen_value_on_col_463 + + gen_value_on_col_464 + + gen_value_on_col_465 + + gen_value_on_col_466 + + gen_value_on_col_467 + + gen_value_on_col_468 + + gen_value_on_col_469 + + gen_value_on_col_470 + + gen_value_on_col_471 + + gen_value_on_col_472 + + gen_value_on_col_473 + + gen_value_on_col_474 + + gen_value_on_col_475 + + gen_value_on_col_476 + + gen_value_on_col_477 + + gen_value_on_col_478 + + gen_value_on_col_479 + + gen_value_on_col_480 + + gen_value_on_col_481 + + gen_value_on_col_482 + + gen_value_on_col_483 + + gen_value_on_col_484 + + gen_value_on_col_485 + + gen_value_on_col_486 + + gen_value_on_col_487 + + gen_value_on_col_488 + + gen_value_on_col_489 + + gen_value_on_col_490 + + gen_value_on_col_491 + + gen_value_on_col_492 + + gen_value_on_col_493 + + gen_value_on_col_494 + + gen_value_on_col_495 + + gen_value_on_col_496 + + gen_value_on_col_497 + + gen_value_on_col_498 + + gen_value_on_col_499 + + gen_value_on_col_500 + + gen_value_on_col_501 + + gen_value_on_col_502 + + gen_value_on_col_503 + + gen_value_on_col_504 + + gen_value_on_col_505 + + gen_value_on_col_506 + + gen_value_on_col_507 + + gen_value_on_col_508 + + gen_value_on_col_509 + + gen_value_on_col_510 + + gen_value_on_col_511 + + gen_value_on_col_512 + + gen_value_on_col_513 + + gen_value_on_col_514 + + gen_value_on_col_515 + + gen_value_on_col_516 + + gen_value_on_col_517 + + gen_value_on_col_518 + + gen_value_on_col_519 + + gen_value_on_col_520 + + gen_value_on_col_521 + + gen_value_on_col_522 + + gen_value_on_col_523 + + gen_value_on_col_524 + + gen_value_on_col_525 + + gen_value_on_col_526 + + gen_value_on_col_527 + + gen_value_on_col_528 + + gen_value_on_col_529 + + gen_value_on_col_530 + + gen_value_on_col_531 + + gen_value_on_col_532 + + gen_value_on_col_533 + + gen_value_on_col_534 + + gen_value_on_col_535 + + gen_value_on_col_536 + + gen_value_on_col_537 + + gen_value_on_col_538 + + gen_value_on_col_539 + + gen_value_on_col_540 + + gen_value_on_col_541 + + gen_value_on_col_542 + + gen_value_on_col_543 + + gen_value_on_col_544 + + gen_value_on_col_545 + + gen_value_on_col_546 + + gen_value_on_col_547 + + gen_value_on_col_548 + + gen_value_on_col_549 + + gen_value_on_col_550 + + gen_value_on_col_551 + + gen_value_on_col_552 + + gen_value_on_col_553 + + gen_value_on_col_554 + + gen_value_on_col_555 + + gen_value_on_col_556 + + gen_value_on_col_557 + + gen_value_on_col_558 + + gen_value_on_col_559 + + gen_value_on_col_560 + + gen_value_on_col_561 + + gen_value_on_col_562 + + gen_value_on_col_563 + + gen_value_on_col_564 + + gen_value_on_col_565 + + gen_value_on_col_566 + + gen_value_on_col_567 + + gen_value_on_col_568 + + gen_value_on_col_569 + + gen_value_on_col_570 + + gen_value_on_col_571 + + gen_value_on_col_572 + + gen_value_on_col_573 + + gen_value_on_col_574 + + gen_value_on_col_575 + + gen_value_on_col_576 + + gen_value_on_col_577 + + gen_value_on_col_578 + + gen_value_on_col_579 + + gen_value_on_col_580 + + gen_value_on_col_581 + + gen_value_on_col_582 + + gen_value_on_col_583 + + gen_value_on_col_584 + + gen_value_on_col_585 + + gen_value_on_col_586 + + gen_value_on_col_587 + + gen_value_on_col_588 + + gen_value_on_col_589 + + gen_value_on_col_590 + + gen_value_on_col_591 + + gen_value_on_col_592 + + gen_value_on_col_593 + + gen_value_on_col_594 + + gen_value_on_col_595 + + gen_value_on_col_596 + + gen_value_on_col_597 + + gen_value_on_col_598 + + gen_value_on_col_599 + + gen_value_on_col_600 + + gen_value_on_col_601 + + gen_value_on_col_602 + + gen_value_on_col_603 + + gen_value_on_col_604 + + gen_value_on_col_605 + + gen_value_on_col_606 + + gen_value_on_col_607 + + gen_value_on_col_608 + + gen_value_on_col_609 + + gen_value_on_col_610 + + gen_value_on_col_611 + + gen_value_on_col_612 + + gen_value_on_col_613 + + gen_value_on_col_614 + + gen_value_on_col_615 + + gen_value_on_col_616 + + gen_value_on_col_617 + + gen_value_on_col_618 + + gen_value_on_col_619 + + gen_value_on_col_620 + + gen_value_on_col_621 + + gen_value_on_col_622 + + gen_value_on_col_623 + + gen_value_on_col_624 + + gen_value_on_col_625 + + gen_value_on_col_626 + + gen_value_on_col_627 + + gen_value_on_col_628 + + gen_value_on_col_629 + + gen_value_on_col_630 + + gen_value_on_col_631 + + gen_value_on_col_632 + + gen_value_on_col_633 + + gen_value_on_col_634 + + gen_value_on_col_635 + + gen_value_on_col_636 + + gen_value_on_col_637 + + gen_value_on_col_638 + + gen_value_on_col_639 + + gen_value_on_col_640 + + gen_value_on_col_641 + + gen_value_on_col_642 + + gen_value_on_col_643 + + gen_value_on_col_644 + + gen_value_on_col_645 + + gen_value_on_col_646 + + gen_value_on_col_647 + + gen_value_on_col_648 + + gen_value_on_col_649 + + gen_value_on_col_650 + + gen_value_on_col_651 + + gen_value_on_col_652 + + gen_value_on_col_653 + + gen_value_on_col_654 + + gen_value_on_col_655 + + gen_value_on_col_656 + + gen_value_on_col_657 + + gen_value_on_col_658 + + gen_value_on_col_659 + + gen_value_on_col_660 + + gen_value_on_col_661 + + gen_value_on_col_662 + + gen_value_on_col_663 + + gen_value_on_col_664 + + gen_value_on_col_665 + + gen_value_on_col_666 + + gen_value_on_col_667 + + gen_value_on_col_668 + + gen_value_on_col_669 + + gen_value_on_col_670 + + gen_value_on_col_671 + + gen_value_on_col_672 + + gen_value_on_col_673 + + gen_value_on_col_674 + + gen_value_on_col_675 + + gen_value_on_col_676 + + gen_value_on_col_677 + + gen_value_on_col_678 + + gen_value_on_col_679 + + gen_value_on_col_680 + + gen_value_on_col_681 + + gen_value_on_col_682 + + gen_value_on_col_683 + + gen_value_on_col_684 + + gen_value_on_col_685 + + gen_value_on_col_686 + + gen_value_on_col_687 + + gen_value_on_col_688 + + gen_value_on_col_689 + + gen_value_on_col_690 + + gen_value_on_col_691 + + gen_value_on_col_692 + + gen_value_on_col_693 + + gen_value_on_col_694 + + gen_value_on_col_695 + + gen_value_on_col_696 + + gen_value_on_col_697 + + gen_value_on_col_698 + + gen_value_on_col_699 + + gen_value_on_col_700 + + gen_value_on_col_701 + + gen_value_on_col_702 + + gen_value_on_col_703 + + gen_value_on_col_704 + + gen_value_on_col_705 + + gen_value_on_col_706 + + gen_value_on_col_707 + + gen_value_on_col_708 + + gen_value_on_col_709 + + gen_value_on_col_710 + + gen_value_on_col_711 + + gen_value_on_col_712 + + gen_value_on_col_713 + + gen_value_on_col_714 + + gen_value_on_col_715 + + gen_value_on_col_716 + + gen_value_on_col_717 + + gen_value_on_col_718 + + gen_value_on_col_719 + + gen_value_on_col_720 + + gen_value_on_col_721 + + gen_value_on_col_722 + + gen_value_on_col_723 + + gen_value_on_col_724 + + gen_value_on_col_725 + + gen_value_on_col_726 + + gen_value_on_col_727 + + gen_value_on_col_728 + + gen_value_on_col_729 + + gen_value_on_col_730 + + gen_value_on_col_731 + + gen_value_on_col_732 + + gen_value_on_col_733 + + gen_value_on_col_734 + + gen_value_on_col_735 + + gen_value_on_col_736 + + gen_value_on_col_737 + + gen_value_on_col_738 + + gen_value_on_col_739 + + gen_value_on_col_740 + + gen_value_on_col_741 + + gen_value_on_col_742 + + gen_value_on_col_743 + + gen_value_on_col_744 + + gen_value_on_col_745 + + gen_value_on_col_746 + + gen_value_on_col_747 + + gen_value_on_col_748 + + gen_value_on_col_749 + + gen_value_on_col_750 + + gen_value_on_col_751 + + gen_value_on_col_752 + + gen_value_on_col_753 + + gen_value_on_col_754 + + gen_value_on_col_755 + + gen_value_on_col_756 + + gen_value_on_col_757 + + gen_value_on_col_758 + + gen_value_on_col_759 + + gen_value_on_col_760 + + gen_value_on_col_761 + + gen_value_on_col_762 + + gen_value_on_col_763 + + gen_value_on_col_764 + + gen_value_on_col_765 + + gen_value_on_col_766 + + gen_value_on_col_767 + + gen_value_on_col_768 + + gen_value_on_col_769 + + gen_value_on_col_770 + + gen_value_on_col_771 + + gen_value_on_col_772 + + gen_value_on_col_773 + + gen_value_on_col_774 + + gen_value_on_col_775 + + gen_value_on_col_776 + + gen_value_on_col_777 + + gen_value_on_col_778 + + gen_value_on_col_779 + + gen_value_on_col_780 + + gen_value_on_col_781 + + gen_value_on_col_782 + + gen_value_on_col_783 + + gen_value_on_col_784 + + gen_value_on_col_785 + + gen_value_on_col_786 + + gen_value_on_col_787 + + gen_value_on_col_788 + + gen_value_on_col_789 + + gen_value_on_col_790 + + gen_value_on_col_791 + + gen_value_on_col_792 + + gen_value_on_col_793 + + gen_value_on_col_794 + + gen_value_on_col_795 + + gen_value_on_col_796 + + gen_value_on_col_797 + + gen_value_on_col_798 + + gen_value_on_col_799 + + gen_value_on_col_800 + + gen_value_on_col_801 + + gen_value_on_col_802 + + gen_value_on_col_803 + + gen_value_on_col_804 + + gen_value_on_col_805 + + gen_value_on_col_806 + + gen_value_on_col_807 + + gen_value_on_col_808 + + gen_value_on_col_809 + + gen_value_on_col_810 + + gen_value_on_col_811 + + gen_value_on_col_812 + + gen_value_on_col_813 + + gen_value_on_col_814 + + gen_value_on_col_815 + + gen_value_on_col_816 + + gen_value_on_col_817 + + gen_value_on_col_818 + + gen_value_on_col_819 + + gen_value_on_col_820 + + gen_value_on_col_821 + + gen_value_on_col_822 + + gen_value_on_col_823 + + gen_value_on_col_824 + + gen_value_on_col_825 + + gen_value_on_col_826 + + gen_value_on_col_827 + + gen_value_on_col_828 + + gen_value_on_col_829 + + gen_value_on_col_830 + + gen_value_on_col_831 + + gen_value_on_col_832 + + gen_value_on_col_833 + + gen_value_on_col_834 + + gen_value_on_col_835 + + gen_value_on_col_836 + + gen_value_on_col_837 + + gen_value_on_col_838 + + gen_value_on_col_839 + + gen_value_on_col_840 + + gen_value_on_col_841 + + gen_value_on_col_842 + + gen_value_on_col_843 + + gen_value_on_col_844 + + gen_value_on_col_845 + + gen_value_on_col_846 + + gen_value_on_col_847 + + gen_value_on_col_848 + + gen_value_on_col_849 + + gen_value_on_col_850 + + gen_value_on_col_851 + + gen_value_on_col_852 + + gen_value_on_col_853 + + gen_value_on_col_854 + + gen_value_on_col_855 + + gen_value_on_col_856 + + gen_value_on_col_857 + + gen_value_on_col_858 + + gen_value_on_col_859 + + gen_value_on_col_860 + + gen_value_on_col_861 + + gen_value_on_col_862 + + gen_value_on_col_863 + + gen_value_on_col_864 + + gen_value_on_col_865 + + gen_value_on_col_866 + + gen_value_on_col_867 + + gen_value_on_col_868 + + gen_value_on_col_869 + + gen_value_on_col_870 + + gen_value_on_col_871 + + gen_value_on_col_872 + + gen_value_on_col_873 + + gen_value_on_col_874 + + gen_value_on_col_875 + + gen_value_on_col_876 + + gen_value_on_col_877 + + gen_value_on_col_878 + + gen_value_on_col_879 + + gen_value_on_col_880 + + gen_value_on_col_881 + + gen_value_on_col_882 + + gen_value_on_col_883 + + gen_value_on_col_884 + + gen_value_on_col_885 + + gen_value_on_col_886 + + gen_value_on_col_887 + + gen_value_on_col_888 + + gen_value_on_col_889 + + gen_value_on_col_890 + + gen_value_on_col_891 + + gen_value_on_col_892 + + gen_value_on_col_893 + + gen_value_on_col_894 + + gen_value_on_col_895 + + gen_value_on_col_896 + + gen_value_on_col_897 + + gen_value_on_col_898 + + gen_value_on_col_899 + + gen_value_on_col_900 + + gen_value_on_col_901 + + gen_value_on_col_902 + + gen_value_on_col_903 + + gen_value_on_col_904 + + gen_value_on_col_905 + + gen_value_on_col_906 + + gen_value_on_col_907 + + gen_value_on_col_908 + + gen_value_on_col_909 + + gen_value_on_col_910 + + gen_value_on_col_911 + + gen_value_on_col_912 + + gen_value_on_col_913 + + gen_value_on_col_914 + + gen_value_on_col_915 + + gen_value_on_col_916 + + gen_value_on_col_917 + + gen_value_on_col_918 + + gen_value_on_col_919 + + gen_value_on_col_920 + + gen_value_on_col_921 + + gen_value_on_col_922 + + gen_value_on_col_923 + + gen_value_on_col_924 + + gen_value_on_col_925 + + gen_value_on_col_926 + + gen_value_on_col_927 + + gen_value_on_col_928 + + gen_value_on_col_929 + + gen_value_on_col_930 + + gen_value_on_col_931 + + gen_value_on_col_932 + + gen_value_on_col_933 + + gen_value_on_col_934 + + gen_value_on_col_935 + + gen_value_on_col_936 + + gen_value_on_col_937 + + gen_value_on_col_938 + + gen_value_on_col_939 + + gen_value_on_col_940 + + gen_value_on_col_941 + + gen_value_on_col_942 + + gen_value_on_col_943 + + gen_value_on_col_944 + + gen_value_on_col_945 + + gen_value_on_col_946 + + gen_value_on_col_947 + + gen_value_on_col_948 + + gen_value_on_col_949 + + gen_value_on_col_950 + + gen_value_on_col_951 + + gen_value_on_col_952 + + gen_value_on_col_953 + + gen_value_on_col_954 + + gen_value_on_col_955 + + gen_value_on_col_956 + + gen_value_on_col_957 + + gen_value_on_col_958 + + gen_value_on_col_959 + + gen_value_on_col_960 + + gen_value_on_col_961 + + gen_value_on_col_962 + + gen_value_on_col_963 + + gen_value_on_col_964 + + gen_value_on_col_965 + + gen_value_on_col_966 + + gen_value_on_col_967 + + gen_value_on_col_968 + + gen_value_on_col_969 + + gen_value_on_col_970 + + gen_value_on_col_971 + + gen_value_on_col_972 + + gen_value_on_col_973 + + gen_value_on_col_974 + + gen_value_on_col_975 + + gen_value_on_col_976 + + gen_value_on_col_977 + + gen_value_on_col_978 + + gen_value_on_col_979 + + gen_value_on_col_980 + + gen_value_on_col_981 + + gen_value_on_col_982 + + gen_value_on_col_983 + + gen_value_on_col_984 + + gen_value_on_col_985 + + gen_value_on_col_986 + + gen_value_on_col_987 + + gen_value_on_col_988 + + gen_value_on_col_989 + + gen_value_on_col_990 + + gen_value_on_col_991 + + gen_value_on_col_992 + + gen_value_on_col_993 + + gen_value_on_col_994 + + gen_value_on_col_995 + + gen_value_on_col_996 + + gen_value_on_col_997 + + gen_value_on_col_998 + + gen_value_on_col_999 + + gen_value_on_col_1000 + ) as sum_all + from ( + select + gen_id(g, 1) as gen_value_on_col_1 + ,gen_id(g, 1) as gen_value_on_col_2 + ,gen_id(g, 1) as gen_value_on_col_3 + ,gen_id(g, 1) as gen_value_on_col_4 + ,gen_id(g, 1) as gen_value_on_col_5 + ,gen_id(g, 1) as gen_value_on_col_6 + ,gen_id(g, 1) as gen_value_on_col_7 + ,gen_id(g, 1) as gen_value_on_col_8 + ,gen_id(g, 1) as gen_value_on_col_9 + ,gen_id(g, 1) as gen_value_on_col_10 + ,gen_id(g, 1) as gen_value_on_col_11 + ,gen_id(g, 1) as gen_value_on_col_12 + ,gen_id(g, 1) as gen_value_on_col_13 + ,gen_id(g, 1) as gen_value_on_col_14 + ,gen_id(g, 1) as gen_value_on_col_15 + ,gen_id(g, 1) as gen_value_on_col_16 + ,gen_id(g, 1) as gen_value_on_col_17 + ,gen_id(g, 1) as gen_value_on_col_18 + ,gen_id(g, 1) as gen_value_on_col_19 + ,gen_id(g, 1) as gen_value_on_col_20 + ,gen_id(g, 1) as gen_value_on_col_21 + ,gen_id(g, 1) as gen_value_on_col_22 + ,gen_id(g, 1) as gen_value_on_col_23 + ,gen_id(g, 1) as gen_value_on_col_24 + ,gen_id(g, 1) as gen_value_on_col_25 + ,gen_id(g, 1) as gen_value_on_col_26 + ,gen_id(g, 1) as gen_value_on_col_27 + ,gen_id(g, 1) as gen_value_on_col_28 + ,gen_id(g, 1) as gen_value_on_col_29 + ,gen_id(g, 1) as gen_value_on_col_30 + ,gen_id(g, 1) as gen_value_on_col_31 + ,gen_id(g, 1) as gen_value_on_col_32 + ,gen_id(g, 1) as gen_value_on_col_33 + ,gen_id(g, 1) as gen_value_on_col_34 + ,gen_id(g, 1) as gen_value_on_col_35 + ,gen_id(g, 1) as gen_value_on_col_36 + ,gen_id(g, 1) as gen_value_on_col_37 + ,gen_id(g, 1) as gen_value_on_col_38 + ,gen_id(g, 1) as gen_value_on_col_39 + ,gen_id(g, 1) as gen_value_on_col_40 + ,gen_id(g, 1) as gen_value_on_col_41 + ,gen_id(g, 1) as gen_value_on_col_42 + ,gen_id(g, 1) as gen_value_on_col_43 + ,gen_id(g, 1) as gen_value_on_col_44 + ,gen_id(g, 1) as gen_value_on_col_45 + ,gen_id(g, 1) as gen_value_on_col_46 + ,gen_id(g, 1) as gen_value_on_col_47 + ,gen_id(g, 1) as gen_value_on_col_48 + ,gen_id(g, 1) as gen_value_on_col_49 + ,gen_id(g, 1) as gen_value_on_col_50 + ,gen_id(g, 1) as gen_value_on_col_51 + ,gen_id(g, 1) as gen_value_on_col_52 + ,gen_id(g, 1) as gen_value_on_col_53 + ,gen_id(g, 1) as gen_value_on_col_54 + ,gen_id(g, 1) as gen_value_on_col_55 + ,gen_id(g, 1) as gen_value_on_col_56 + ,gen_id(g, 1) as gen_value_on_col_57 + ,gen_id(g, 1) as gen_value_on_col_58 + ,gen_id(g, 1) as gen_value_on_col_59 + ,gen_id(g, 1) as gen_value_on_col_60 + ,gen_id(g, 1) as gen_value_on_col_61 + ,gen_id(g, 1) as gen_value_on_col_62 + ,gen_id(g, 1) as gen_value_on_col_63 + ,gen_id(g, 1) as gen_value_on_col_64 + ,gen_id(g, 1) as gen_value_on_col_65 + ,gen_id(g, 1) as gen_value_on_col_66 + ,gen_id(g, 1) as gen_value_on_col_67 + ,gen_id(g, 1) as gen_value_on_col_68 + ,gen_id(g, 1) as gen_value_on_col_69 + ,gen_id(g, 1) as gen_value_on_col_70 + ,gen_id(g, 1) as gen_value_on_col_71 + ,gen_id(g, 1) as gen_value_on_col_72 + ,gen_id(g, 1) as gen_value_on_col_73 + ,gen_id(g, 1) as gen_value_on_col_74 + ,gen_id(g, 1) as gen_value_on_col_75 + ,gen_id(g, 1) as gen_value_on_col_76 + ,gen_id(g, 1) as gen_value_on_col_77 + ,gen_id(g, 1) as gen_value_on_col_78 + ,gen_id(g, 1) as gen_value_on_col_79 + ,gen_id(g, 1) as gen_value_on_col_80 + ,gen_id(g, 1) as gen_value_on_col_81 + ,gen_id(g, 1) as gen_value_on_col_82 + ,gen_id(g, 1) as gen_value_on_col_83 + ,gen_id(g, 1) as gen_value_on_col_84 + ,gen_id(g, 1) as gen_value_on_col_85 + ,gen_id(g, 1) as gen_value_on_col_86 + ,gen_id(g, 1) as gen_value_on_col_87 + ,gen_id(g, 1) as gen_value_on_col_88 + ,gen_id(g, 1) as gen_value_on_col_89 + ,gen_id(g, 1) as gen_value_on_col_90 + ,gen_id(g, 1) as gen_value_on_col_91 + ,gen_id(g, 1) as gen_value_on_col_92 + ,gen_id(g, 1) as gen_value_on_col_93 + ,gen_id(g, 1) as gen_value_on_col_94 + ,gen_id(g, 1) as gen_value_on_col_95 + ,gen_id(g, 1) as gen_value_on_col_96 + ,gen_id(g, 1) as gen_value_on_col_97 + ,gen_id(g, 1) as gen_value_on_col_98 + ,gen_id(g, 1) as gen_value_on_col_99 + ,gen_id(g, 1) as gen_value_on_col_100 + ,gen_id(g, 1) as gen_value_on_col_101 + ,gen_id(g, 1) as gen_value_on_col_102 + ,gen_id(g, 1) as gen_value_on_col_103 + ,gen_id(g, 1) as gen_value_on_col_104 + ,gen_id(g, 1) as gen_value_on_col_105 + ,gen_id(g, 1) as gen_value_on_col_106 + ,gen_id(g, 1) as gen_value_on_col_107 + ,gen_id(g, 1) as gen_value_on_col_108 + ,gen_id(g, 1) as gen_value_on_col_109 + ,gen_id(g, 1) as gen_value_on_col_110 + ,gen_id(g, 1) as gen_value_on_col_111 + ,gen_id(g, 1) as gen_value_on_col_112 + ,gen_id(g, 1) as gen_value_on_col_113 + ,gen_id(g, 1) as gen_value_on_col_114 + ,gen_id(g, 1) as gen_value_on_col_115 + ,gen_id(g, 1) as gen_value_on_col_116 + ,gen_id(g, 1) as gen_value_on_col_117 + ,gen_id(g, 1) as gen_value_on_col_118 + ,gen_id(g, 1) as gen_value_on_col_119 + ,gen_id(g, 1) as gen_value_on_col_120 + ,gen_id(g, 1) as gen_value_on_col_121 + ,gen_id(g, 1) as gen_value_on_col_122 + ,gen_id(g, 1) as gen_value_on_col_123 + ,gen_id(g, 1) as gen_value_on_col_124 + ,gen_id(g, 1) as gen_value_on_col_125 + ,gen_id(g, 1) as gen_value_on_col_126 + ,gen_id(g, 1) as gen_value_on_col_127 + ,gen_id(g, 1) as gen_value_on_col_128 + ,gen_id(g, 1) as gen_value_on_col_129 + ,gen_id(g, 1) as gen_value_on_col_130 + ,gen_id(g, 1) as gen_value_on_col_131 + ,gen_id(g, 1) as gen_value_on_col_132 + ,gen_id(g, 1) as gen_value_on_col_133 + ,gen_id(g, 1) as gen_value_on_col_134 + ,gen_id(g, 1) as gen_value_on_col_135 + ,gen_id(g, 1) as gen_value_on_col_136 + ,gen_id(g, 1) as gen_value_on_col_137 + ,gen_id(g, 1) as gen_value_on_col_138 + ,gen_id(g, 1) as gen_value_on_col_139 + ,gen_id(g, 1) as gen_value_on_col_140 + ,gen_id(g, 1) as gen_value_on_col_141 + ,gen_id(g, 1) as gen_value_on_col_142 + ,gen_id(g, 1) as gen_value_on_col_143 + ,gen_id(g, 1) as gen_value_on_col_144 + ,gen_id(g, 1) as gen_value_on_col_145 + ,gen_id(g, 1) as gen_value_on_col_146 + ,gen_id(g, 1) as gen_value_on_col_147 + ,gen_id(g, 1) as gen_value_on_col_148 + ,gen_id(g, 1) as gen_value_on_col_149 + ,gen_id(g, 1) as gen_value_on_col_150 + ,gen_id(g, 1) as gen_value_on_col_151 + ,gen_id(g, 1) as gen_value_on_col_152 + ,gen_id(g, 1) as gen_value_on_col_153 + ,gen_id(g, 1) as gen_value_on_col_154 + ,gen_id(g, 1) as gen_value_on_col_155 + ,gen_id(g, 1) as gen_value_on_col_156 + ,gen_id(g, 1) as gen_value_on_col_157 + ,gen_id(g, 1) as gen_value_on_col_158 + ,gen_id(g, 1) as gen_value_on_col_159 + ,gen_id(g, 1) as gen_value_on_col_160 + ,gen_id(g, 1) as gen_value_on_col_161 + ,gen_id(g, 1) as gen_value_on_col_162 + ,gen_id(g, 1) as gen_value_on_col_163 + ,gen_id(g, 1) as gen_value_on_col_164 + ,gen_id(g, 1) as gen_value_on_col_165 + ,gen_id(g, 1) as gen_value_on_col_166 + ,gen_id(g, 1) as gen_value_on_col_167 + ,gen_id(g, 1) as gen_value_on_col_168 + ,gen_id(g, 1) as gen_value_on_col_169 + ,gen_id(g, 1) as gen_value_on_col_170 + ,gen_id(g, 1) as gen_value_on_col_171 + ,gen_id(g, 1) as gen_value_on_col_172 + ,gen_id(g, 1) as gen_value_on_col_173 + ,gen_id(g, 1) as gen_value_on_col_174 + ,gen_id(g, 1) as gen_value_on_col_175 + ,gen_id(g, 1) as gen_value_on_col_176 + ,gen_id(g, 1) as gen_value_on_col_177 + ,gen_id(g, 1) as gen_value_on_col_178 + ,gen_id(g, 1) as gen_value_on_col_179 + ,gen_id(g, 1) as gen_value_on_col_180 + ,gen_id(g, 1) as gen_value_on_col_181 + ,gen_id(g, 1) as gen_value_on_col_182 + ,gen_id(g, 1) as gen_value_on_col_183 + ,gen_id(g, 1) as gen_value_on_col_184 + ,gen_id(g, 1) as gen_value_on_col_185 + ,gen_id(g, 1) as gen_value_on_col_186 + ,gen_id(g, 1) as gen_value_on_col_187 + ,gen_id(g, 1) as gen_value_on_col_188 + ,gen_id(g, 1) as gen_value_on_col_189 + ,gen_id(g, 1) as gen_value_on_col_190 + ,gen_id(g, 1) as gen_value_on_col_191 + ,gen_id(g, 1) as gen_value_on_col_192 + ,gen_id(g, 1) as gen_value_on_col_193 + ,gen_id(g, 1) as gen_value_on_col_194 + ,gen_id(g, 1) as gen_value_on_col_195 + ,gen_id(g, 1) as gen_value_on_col_196 + ,gen_id(g, 1) as gen_value_on_col_197 + ,gen_id(g, 1) as gen_value_on_col_198 + ,gen_id(g, 1) as gen_value_on_col_199 + ,gen_id(g, 1) as gen_value_on_col_200 + ,gen_id(g, 1) as gen_value_on_col_201 + ,gen_id(g, 1) as gen_value_on_col_202 + ,gen_id(g, 1) as gen_value_on_col_203 + ,gen_id(g, 1) as gen_value_on_col_204 + ,gen_id(g, 1) as gen_value_on_col_205 + ,gen_id(g, 1) as gen_value_on_col_206 + ,gen_id(g, 1) as gen_value_on_col_207 + ,gen_id(g, 1) as gen_value_on_col_208 + ,gen_id(g, 1) as gen_value_on_col_209 + ,gen_id(g, 1) as gen_value_on_col_210 + ,gen_id(g, 1) as gen_value_on_col_211 + ,gen_id(g, 1) as gen_value_on_col_212 + ,gen_id(g, 1) as gen_value_on_col_213 + ,gen_id(g, 1) as gen_value_on_col_214 + ,gen_id(g, 1) as gen_value_on_col_215 + ,gen_id(g, 1) as gen_value_on_col_216 + ,gen_id(g, 1) as gen_value_on_col_217 + ,gen_id(g, 1) as gen_value_on_col_218 + ,gen_id(g, 1) as gen_value_on_col_219 + ,gen_id(g, 1) as gen_value_on_col_220 + ,gen_id(g, 1) as gen_value_on_col_221 + ,gen_id(g, 1) as gen_value_on_col_222 + ,gen_id(g, 1) as gen_value_on_col_223 + ,gen_id(g, 1) as gen_value_on_col_224 + ,gen_id(g, 1) as gen_value_on_col_225 + ,gen_id(g, 1) as gen_value_on_col_226 + ,gen_id(g, 1) as gen_value_on_col_227 + ,gen_id(g, 1) as gen_value_on_col_228 + ,gen_id(g, 1) as gen_value_on_col_229 + ,gen_id(g, 1) as gen_value_on_col_230 + ,gen_id(g, 1) as gen_value_on_col_231 + ,gen_id(g, 1) as gen_value_on_col_232 + ,gen_id(g, 1) as gen_value_on_col_233 + ,gen_id(g, 1) as gen_value_on_col_234 + ,gen_id(g, 1) as gen_value_on_col_235 + ,gen_id(g, 1) as gen_value_on_col_236 + ,gen_id(g, 1) as gen_value_on_col_237 + ,gen_id(g, 1) as gen_value_on_col_238 + ,gen_id(g, 1) as gen_value_on_col_239 + ,gen_id(g, 1) as gen_value_on_col_240 + ,gen_id(g, 1) as gen_value_on_col_241 + ,gen_id(g, 1) as gen_value_on_col_242 + ,gen_id(g, 1) as gen_value_on_col_243 + ,gen_id(g, 1) as gen_value_on_col_244 + ,gen_id(g, 1) as gen_value_on_col_245 + ,gen_id(g, 1) as gen_value_on_col_246 + ,gen_id(g, 1) as gen_value_on_col_247 + ,gen_id(g, 1) as gen_value_on_col_248 + ,gen_id(g, 1) as gen_value_on_col_249 + ,gen_id(g, 1) as gen_value_on_col_250 + ,gen_id(g, 1) as gen_value_on_col_251 + ,gen_id(g, 1) as gen_value_on_col_252 + ,gen_id(g, 1) as gen_value_on_col_253 + ,gen_id(g, 1) as gen_value_on_col_254 + ,gen_id(g, 1) as gen_value_on_col_255 + ,gen_id(g, 1) as gen_value_on_col_256 + ,gen_id(g, 1) as gen_value_on_col_257 + ,gen_id(g, 1) as gen_value_on_col_258 + ,gen_id(g, 1) as gen_value_on_col_259 + ,gen_id(g, 1) as gen_value_on_col_260 + ,gen_id(g, 1) as gen_value_on_col_261 + ,gen_id(g, 1) as gen_value_on_col_262 + ,gen_id(g, 1) as gen_value_on_col_263 + ,gen_id(g, 1) as gen_value_on_col_264 + ,gen_id(g, 1) as gen_value_on_col_265 + ,gen_id(g, 1) as gen_value_on_col_266 + ,gen_id(g, 1) as gen_value_on_col_267 + ,gen_id(g, 1) as gen_value_on_col_268 + ,gen_id(g, 1) as gen_value_on_col_269 + ,gen_id(g, 1) as gen_value_on_col_270 + ,gen_id(g, 1) as gen_value_on_col_271 + ,gen_id(g, 1) as gen_value_on_col_272 + ,gen_id(g, 1) as gen_value_on_col_273 + ,gen_id(g, 1) as gen_value_on_col_274 + ,gen_id(g, 1) as gen_value_on_col_275 + ,gen_id(g, 1) as gen_value_on_col_276 + ,gen_id(g, 1) as gen_value_on_col_277 + ,gen_id(g, 1) as gen_value_on_col_278 + ,gen_id(g, 1) as gen_value_on_col_279 + ,gen_id(g, 1) as gen_value_on_col_280 + ,gen_id(g, 1) as gen_value_on_col_281 + ,gen_id(g, 1) as gen_value_on_col_282 + ,gen_id(g, 1) as gen_value_on_col_283 + ,gen_id(g, 1) as gen_value_on_col_284 + ,gen_id(g, 1) as gen_value_on_col_285 + ,gen_id(g, 1) as gen_value_on_col_286 + ,gen_id(g, 1) as gen_value_on_col_287 + ,gen_id(g, 1) as gen_value_on_col_288 + ,gen_id(g, 1) as gen_value_on_col_289 + ,gen_id(g, 1) as gen_value_on_col_290 + ,gen_id(g, 1) as gen_value_on_col_291 + ,gen_id(g, 1) as gen_value_on_col_292 + ,gen_id(g, 1) as gen_value_on_col_293 + ,gen_id(g, 1) as gen_value_on_col_294 + ,gen_id(g, 1) as gen_value_on_col_295 + ,gen_id(g, 1) as gen_value_on_col_296 + ,gen_id(g, 1) as gen_value_on_col_297 + ,gen_id(g, 1) as gen_value_on_col_298 + ,gen_id(g, 1) as gen_value_on_col_299 + ,gen_id(g, 1) as gen_value_on_col_300 + ,gen_id(g, 1) as gen_value_on_col_301 + ,gen_id(g, 1) as gen_value_on_col_302 + ,gen_id(g, 1) as gen_value_on_col_303 + ,gen_id(g, 1) as gen_value_on_col_304 + ,gen_id(g, 1) as gen_value_on_col_305 + ,gen_id(g, 1) as gen_value_on_col_306 + ,gen_id(g, 1) as gen_value_on_col_307 + ,gen_id(g, 1) as gen_value_on_col_308 + ,gen_id(g, 1) as gen_value_on_col_309 + ,gen_id(g, 1) as gen_value_on_col_310 + ,gen_id(g, 1) as gen_value_on_col_311 + ,gen_id(g, 1) as gen_value_on_col_312 + ,gen_id(g, 1) as gen_value_on_col_313 + ,gen_id(g, 1) as gen_value_on_col_314 + ,gen_id(g, 1) as gen_value_on_col_315 + ,gen_id(g, 1) as gen_value_on_col_316 + ,gen_id(g, 1) as gen_value_on_col_317 + ,gen_id(g, 1) as gen_value_on_col_318 + ,gen_id(g, 1) as gen_value_on_col_319 + ,gen_id(g, 1) as gen_value_on_col_320 + ,gen_id(g, 1) as gen_value_on_col_321 + ,gen_id(g, 1) as gen_value_on_col_322 + ,gen_id(g, 1) as gen_value_on_col_323 + ,gen_id(g, 1) as gen_value_on_col_324 + ,gen_id(g, 1) as gen_value_on_col_325 + ,gen_id(g, 1) as gen_value_on_col_326 + ,gen_id(g, 1) as gen_value_on_col_327 + ,gen_id(g, 1) as gen_value_on_col_328 + ,gen_id(g, 1) as gen_value_on_col_329 + ,gen_id(g, 1) as gen_value_on_col_330 + ,gen_id(g, 1) as gen_value_on_col_331 + ,gen_id(g, 1) as gen_value_on_col_332 + ,gen_id(g, 1) as gen_value_on_col_333 + ,gen_id(g, 1) as gen_value_on_col_334 + ,gen_id(g, 1) as gen_value_on_col_335 + ,gen_id(g, 1) as gen_value_on_col_336 + ,gen_id(g, 1) as gen_value_on_col_337 + ,gen_id(g, 1) as gen_value_on_col_338 + ,gen_id(g, 1) as gen_value_on_col_339 + ,gen_id(g, 1) as gen_value_on_col_340 + ,gen_id(g, 1) as gen_value_on_col_341 + ,gen_id(g, 1) as gen_value_on_col_342 + ,gen_id(g, 1) as gen_value_on_col_343 + ,gen_id(g, 1) as gen_value_on_col_344 + ,gen_id(g, 1) as gen_value_on_col_345 + ,gen_id(g, 1) as gen_value_on_col_346 + ,gen_id(g, 1) as gen_value_on_col_347 + ,gen_id(g, 1) as gen_value_on_col_348 + ,gen_id(g, 1) as gen_value_on_col_349 + ,gen_id(g, 1) as gen_value_on_col_350 + ,gen_id(g, 1) as gen_value_on_col_351 + ,gen_id(g, 1) as gen_value_on_col_352 + ,gen_id(g, 1) as gen_value_on_col_353 + ,gen_id(g, 1) as gen_value_on_col_354 + ,gen_id(g, 1) as gen_value_on_col_355 + ,gen_id(g, 1) as gen_value_on_col_356 + ,gen_id(g, 1) as gen_value_on_col_357 + ,gen_id(g, 1) as gen_value_on_col_358 + ,gen_id(g, 1) as gen_value_on_col_359 + ,gen_id(g, 1) as gen_value_on_col_360 + ,gen_id(g, 1) as gen_value_on_col_361 + ,gen_id(g, 1) as gen_value_on_col_362 + ,gen_id(g, 1) as gen_value_on_col_363 + ,gen_id(g, 1) as gen_value_on_col_364 + ,gen_id(g, 1) as gen_value_on_col_365 + ,gen_id(g, 1) as gen_value_on_col_366 + ,gen_id(g, 1) as gen_value_on_col_367 + ,gen_id(g, 1) as gen_value_on_col_368 + ,gen_id(g, 1) as gen_value_on_col_369 + ,gen_id(g, 1) as gen_value_on_col_370 + ,gen_id(g, 1) as gen_value_on_col_371 + ,gen_id(g, 1) as gen_value_on_col_372 + ,gen_id(g, 1) as gen_value_on_col_373 + ,gen_id(g, 1) as gen_value_on_col_374 + ,gen_id(g, 1) as gen_value_on_col_375 + ,gen_id(g, 1) as gen_value_on_col_376 + ,gen_id(g, 1) as gen_value_on_col_377 + ,gen_id(g, 1) as gen_value_on_col_378 + ,gen_id(g, 1) as gen_value_on_col_379 + ,gen_id(g, 1) as gen_value_on_col_380 + ,gen_id(g, 1) as gen_value_on_col_381 + ,gen_id(g, 1) as gen_value_on_col_382 + ,gen_id(g, 1) as gen_value_on_col_383 + ,gen_id(g, 1) as gen_value_on_col_384 + ,gen_id(g, 1) as gen_value_on_col_385 + ,gen_id(g, 1) as gen_value_on_col_386 + ,gen_id(g, 1) as gen_value_on_col_387 + ,gen_id(g, 1) as gen_value_on_col_388 + ,gen_id(g, 1) as gen_value_on_col_389 + ,gen_id(g, 1) as gen_value_on_col_390 + ,gen_id(g, 1) as gen_value_on_col_391 + ,gen_id(g, 1) as gen_value_on_col_392 + ,gen_id(g, 1) as gen_value_on_col_393 + ,gen_id(g, 1) as gen_value_on_col_394 + ,gen_id(g, 1) as gen_value_on_col_395 + ,gen_id(g, 1) as gen_value_on_col_396 + ,gen_id(g, 1) as gen_value_on_col_397 + ,gen_id(g, 1) as gen_value_on_col_398 + ,gen_id(g, 1) as gen_value_on_col_399 + ,gen_id(g, 1) as gen_value_on_col_400 + ,gen_id(g, 1) as gen_value_on_col_401 + ,gen_id(g, 1) as gen_value_on_col_402 + ,gen_id(g, 1) as gen_value_on_col_403 + ,gen_id(g, 1) as gen_value_on_col_404 + ,gen_id(g, 1) as gen_value_on_col_405 + ,gen_id(g, 1) as gen_value_on_col_406 + ,gen_id(g, 1) as gen_value_on_col_407 + ,gen_id(g, 1) as gen_value_on_col_408 + ,gen_id(g, 1) as gen_value_on_col_409 + ,gen_id(g, 1) as gen_value_on_col_410 + ,gen_id(g, 1) as gen_value_on_col_411 + ,gen_id(g, 1) as gen_value_on_col_412 + ,gen_id(g, 1) as gen_value_on_col_413 + ,gen_id(g, 1) as gen_value_on_col_414 + ,gen_id(g, 1) as gen_value_on_col_415 + ,gen_id(g, 1) as gen_value_on_col_416 + ,gen_id(g, 1) as gen_value_on_col_417 + ,gen_id(g, 1) as gen_value_on_col_418 + ,gen_id(g, 1) as gen_value_on_col_419 + ,gen_id(g, 1) as gen_value_on_col_420 + ,gen_id(g, 1) as gen_value_on_col_421 + ,gen_id(g, 1) as gen_value_on_col_422 + ,gen_id(g, 1) as gen_value_on_col_423 + ,gen_id(g, 1) as gen_value_on_col_424 + ,gen_id(g, 1) as gen_value_on_col_425 + ,gen_id(g, 1) as gen_value_on_col_426 + ,gen_id(g, 1) as gen_value_on_col_427 + ,gen_id(g, 1) as gen_value_on_col_428 + ,gen_id(g, 1) as gen_value_on_col_429 + ,gen_id(g, 1) as gen_value_on_col_430 + ,gen_id(g, 1) as gen_value_on_col_431 + ,gen_id(g, 1) as gen_value_on_col_432 + ,gen_id(g, 1) as gen_value_on_col_433 + ,gen_id(g, 1) as gen_value_on_col_434 + ,gen_id(g, 1) as gen_value_on_col_435 + ,gen_id(g, 1) as gen_value_on_col_436 + ,gen_id(g, 1) as gen_value_on_col_437 + ,gen_id(g, 1) as gen_value_on_col_438 + ,gen_id(g, 1) as gen_value_on_col_439 + ,gen_id(g, 1) as gen_value_on_col_440 + ,gen_id(g, 1) as gen_value_on_col_441 + ,gen_id(g, 1) as gen_value_on_col_442 + ,gen_id(g, 1) as gen_value_on_col_443 + ,gen_id(g, 1) as gen_value_on_col_444 + ,gen_id(g, 1) as gen_value_on_col_445 + ,gen_id(g, 1) as gen_value_on_col_446 + ,gen_id(g, 1) as gen_value_on_col_447 + ,gen_id(g, 1) as gen_value_on_col_448 + ,gen_id(g, 1) as gen_value_on_col_449 + ,gen_id(g, 1) as gen_value_on_col_450 + ,gen_id(g, 1) as gen_value_on_col_451 + ,gen_id(g, 1) as gen_value_on_col_452 + ,gen_id(g, 1) as gen_value_on_col_453 + ,gen_id(g, 1) as gen_value_on_col_454 + ,gen_id(g, 1) as gen_value_on_col_455 + ,gen_id(g, 1) as gen_value_on_col_456 + ,gen_id(g, 1) as gen_value_on_col_457 + ,gen_id(g, 1) as gen_value_on_col_458 + ,gen_id(g, 1) as gen_value_on_col_459 + ,gen_id(g, 1) as gen_value_on_col_460 + ,gen_id(g, 1) as gen_value_on_col_461 + ,gen_id(g, 1) as gen_value_on_col_462 + ,gen_id(g, 1) as gen_value_on_col_463 + ,gen_id(g, 1) as gen_value_on_col_464 + ,gen_id(g, 1) as gen_value_on_col_465 + ,gen_id(g, 1) as gen_value_on_col_466 + ,gen_id(g, 1) as gen_value_on_col_467 + ,gen_id(g, 1) as gen_value_on_col_468 + ,gen_id(g, 1) as gen_value_on_col_469 + ,gen_id(g, 1) as gen_value_on_col_470 + ,gen_id(g, 1) as gen_value_on_col_471 + ,gen_id(g, 1) as gen_value_on_col_472 + ,gen_id(g, 1) as gen_value_on_col_473 + ,gen_id(g, 1) as gen_value_on_col_474 + ,gen_id(g, 1) as gen_value_on_col_475 + ,gen_id(g, 1) as gen_value_on_col_476 + ,gen_id(g, 1) as gen_value_on_col_477 + ,gen_id(g, 1) as gen_value_on_col_478 + ,gen_id(g, 1) as gen_value_on_col_479 + ,gen_id(g, 1) as gen_value_on_col_480 + ,gen_id(g, 1) as gen_value_on_col_481 + ,gen_id(g, 1) as gen_value_on_col_482 + ,gen_id(g, 1) as gen_value_on_col_483 + ,gen_id(g, 1) as gen_value_on_col_484 + ,gen_id(g, 1) as gen_value_on_col_485 + ,gen_id(g, 1) as gen_value_on_col_486 + ,gen_id(g, 1) as gen_value_on_col_487 + ,gen_id(g, 1) as gen_value_on_col_488 + ,gen_id(g, 1) as gen_value_on_col_489 + ,gen_id(g, 1) as gen_value_on_col_490 + ,gen_id(g, 1) as gen_value_on_col_491 + ,gen_id(g, 1) as gen_value_on_col_492 + ,gen_id(g, 1) as gen_value_on_col_493 + ,gen_id(g, 1) as gen_value_on_col_494 + ,gen_id(g, 1) as gen_value_on_col_495 + ,gen_id(g, 1) as gen_value_on_col_496 + ,gen_id(g, 1) as gen_value_on_col_497 + ,gen_id(g, 1) as gen_value_on_col_498 + ,gen_id(g, 1) as gen_value_on_col_499 + ,gen_id(g, 1) as gen_value_on_col_500 + ,gen_id(g, 1) as gen_value_on_col_501 + ,gen_id(g, 1) as gen_value_on_col_502 + ,gen_id(g, 1) as gen_value_on_col_503 + ,gen_id(g, 1) as gen_value_on_col_504 + ,gen_id(g, 1) as gen_value_on_col_505 + ,gen_id(g, 1) as gen_value_on_col_506 + ,gen_id(g, 1) as gen_value_on_col_507 + ,gen_id(g, 1) as gen_value_on_col_508 + ,gen_id(g, 1) as gen_value_on_col_509 + ,gen_id(g, 1) as gen_value_on_col_510 + ,gen_id(g, 1) as gen_value_on_col_511 + ,gen_id(g, 1) as gen_value_on_col_512 + ,gen_id(g, 1) as gen_value_on_col_513 + ,gen_id(g, 1) as gen_value_on_col_514 + ,gen_id(g, 1) as gen_value_on_col_515 + ,gen_id(g, 1) as gen_value_on_col_516 + ,gen_id(g, 1) as gen_value_on_col_517 + ,gen_id(g, 1) as gen_value_on_col_518 + ,gen_id(g, 1) as gen_value_on_col_519 + ,gen_id(g, 1) as gen_value_on_col_520 + ,gen_id(g, 1) as gen_value_on_col_521 + ,gen_id(g, 1) as gen_value_on_col_522 + ,gen_id(g, 1) as gen_value_on_col_523 + ,gen_id(g, 1) as gen_value_on_col_524 + ,gen_id(g, 1) as gen_value_on_col_525 + ,gen_id(g, 1) as gen_value_on_col_526 + ,gen_id(g, 1) as gen_value_on_col_527 + ,gen_id(g, 1) as gen_value_on_col_528 + ,gen_id(g, 1) as gen_value_on_col_529 + ,gen_id(g, 1) as gen_value_on_col_530 + ,gen_id(g, 1) as gen_value_on_col_531 + ,gen_id(g, 1) as gen_value_on_col_532 + ,gen_id(g, 1) as gen_value_on_col_533 + ,gen_id(g, 1) as gen_value_on_col_534 + ,gen_id(g, 1) as gen_value_on_col_535 + ,gen_id(g, 1) as gen_value_on_col_536 + ,gen_id(g, 1) as gen_value_on_col_537 + ,gen_id(g, 1) as gen_value_on_col_538 + ,gen_id(g, 1) as gen_value_on_col_539 + ,gen_id(g, 1) as gen_value_on_col_540 + ,gen_id(g, 1) as gen_value_on_col_541 + ,gen_id(g, 1) as gen_value_on_col_542 + ,gen_id(g, 1) as gen_value_on_col_543 + ,gen_id(g, 1) as gen_value_on_col_544 + ,gen_id(g, 1) as gen_value_on_col_545 + ,gen_id(g, 1) as gen_value_on_col_546 + ,gen_id(g, 1) as gen_value_on_col_547 + ,gen_id(g, 1) as gen_value_on_col_548 + ,gen_id(g, 1) as gen_value_on_col_549 + ,gen_id(g, 1) as gen_value_on_col_550 + ,gen_id(g, 1) as gen_value_on_col_551 + ,gen_id(g, 1) as gen_value_on_col_552 + ,gen_id(g, 1) as gen_value_on_col_553 + ,gen_id(g, 1) as gen_value_on_col_554 + ,gen_id(g, 1) as gen_value_on_col_555 + ,gen_id(g, 1) as gen_value_on_col_556 + ,gen_id(g, 1) as gen_value_on_col_557 + ,gen_id(g, 1) as gen_value_on_col_558 + ,gen_id(g, 1) as gen_value_on_col_559 + ,gen_id(g, 1) as gen_value_on_col_560 + ,gen_id(g, 1) as gen_value_on_col_561 + ,gen_id(g, 1) as gen_value_on_col_562 + ,gen_id(g, 1) as gen_value_on_col_563 + ,gen_id(g, 1) as gen_value_on_col_564 + ,gen_id(g, 1) as gen_value_on_col_565 + ,gen_id(g, 1) as gen_value_on_col_566 + ,gen_id(g, 1) as gen_value_on_col_567 + ,gen_id(g, 1) as gen_value_on_col_568 + ,gen_id(g, 1) as gen_value_on_col_569 + ,gen_id(g, 1) as gen_value_on_col_570 + ,gen_id(g, 1) as gen_value_on_col_571 + ,gen_id(g, 1) as gen_value_on_col_572 + ,gen_id(g, 1) as gen_value_on_col_573 + ,gen_id(g, 1) as gen_value_on_col_574 + ,gen_id(g, 1) as gen_value_on_col_575 + ,gen_id(g, 1) as gen_value_on_col_576 + ,gen_id(g, 1) as gen_value_on_col_577 + ,gen_id(g, 1) as gen_value_on_col_578 + ,gen_id(g, 1) as gen_value_on_col_579 + ,gen_id(g, 1) as gen_value_on_col_580 + ,gen_id(g, 1) as gen_value_on_col_581 + ,gen_id(g, 1) as gen_value_on_col_582 + ,gen_id(g, 1) as gen_value_on_col_583 + ,gen_id(g, 1) as gen_value_on_col_584 + ,gen_id(g, 1) as gen_value_on_col_585 + ,gen_id(g, 1) as gen_value_on_col_586 + ,gen_id(g, 1) as gen_value_on_col_587 + ,gen_id(g, 1) as gen_value_on_col_588 + ,gen_id(g, 1) as gen_value_on_col_589 + ,gen_id(g, 1) as gen_value_on_col_590 + ,gen_id(g, 1) as gen_value_on_col_591 + ,gen_id(g, 1) as gen_value_on_col_592 + ,gen_id(g, 1) as gen_value_on_col_593 + ,gen_id(g, 1) as gen_value_on_col_594 + ,gen_id(g, 1) as gen_value_on_col_595 + ,gen_id(g, 1) as gen_value_on_col_596 + ,gen_id(g, 1) as gen_value_on_col_597 + ,gen_id(g, 1) as gen_value_on_col_598 + ,gen_id(g, 1) as gen_value_on_col_599 + ,gen_id(g, 1) as gen_value_on_col_600 + ,gen_id(g, 1) as gen_value_on_col_601 + ,gen_id(g, 1) as gen_value_on_col_602 + ,gen_id(g, 1) as gen_value_on_col_603 + ,gen_id(g, 1) as gen_value_on_col_604 + ,gen_id(g, 1) as gen_value_on_col_605 + ,gen_id(g, 1) as gen_value_on_col_606 + ,gen_id(g, 1) as gen_value_on_col_607 + ,gen_id(g, 1) as gen_value_on_col_608 + ,gen_id(g, 1) as gen_value_on_col_609 + ,gen_id(g, 1) as gen_value_on_col_610 + ,gen_id(g, 1) as gen_value_on_col_611 + ,gen_id(g, 1) as gen_value_on_col_612 + ,gen_id(g, 1) as gen_value_on_col_613 + ,gen_id(g, 1) as gen_value_on_col_614 + ,gen_id(g, 1) as gen_value_on_col_615 + ,gen_id(g, 1) as gen_value_on_col_616 + ,gen_id(g, 1) as gen_value_on_col_617 + ,gen_id(g, 1) as gen_value_on_col_618 + ,gen_id(g, 1) as gen_value_on_col_619 + ,gen_id(g, 1) as gen_value_on_col_620 + ,gen_id(g, 1) as gen_value_on_col_621 + ,gen_id(g, 1) as gen_value_on_col_622 + ,gen_id(g, 1) as gen_value_on_col_623 + ,gen_id(g, 1) as gen_value_on_col_624 + ,gen_id(g, 1) as gen_value_on_col_625 + ,gen_id(g, 1) as gen_value_on_col_626 + ,gen_id(g, 1) as gen_value_on_col_627 + ,gen_id(g, 1) as gen_value_on_col_628 + ,gen_id(g, 1) as gen_value_on_col_629 + ,gen_id(g, 1) as gen_value_on_col_630 + ,gen_id(g, 1) as gen_value_on_col_631 + ,gen_id(g, 1) as gen_value_on_col_632 + ,gen_id(g, 1) as gen_value_on_col_633 + ,gen_id(g, 1) as gen_value_on_col_634 + ,gen_id(g, 1) as gen_value_on_col_635 + ,gen_id(g, 1) as gen_value_on_col_636 + ,gen_id(g, 1) as gen_value_on_col_637 + ,gen_id(g, 1) as gen_value_on_col_638 + ,gen_id(g, 1) as gen_value_on_col_639 + ,gen_id(g, 1) as gen_value_on_col_640 + ,gen_id(g, 1) as gen_value_on_col_641 + ,gen_id(g, 1) as gen_value_on_col_642 + ,gen_id(g, 1) as gen_value_on_col_643 + ,gen_id(g, 1) as gen_value_on_col_644 + ,gen_id(g, 1) as gen_value_on_col_645 + ,gen_id(g, 1) as gen_value_on_col_646 + ,gen_id(g, 1) as gen_value_on_col_647 + ,gen_id(g, 1) as gen_value_on_col_648 + ,gen_id(g, 1) as gen_value_on_col_649 + ,gen_id(g, 1) as gen_value_on_col_650 + ,gen_id(g, 1) as gen_value_on_col_651 + ,gen_id(g, 1) as gen_value_on_col_652 + ,gen_id(g, 1) as gen_value_on_col_653 + ,gen_id(g, 1) as gen_value_on_col_654 + ,gen_id(g, 1) as gen_value_on_col_655 + ,gen_id(g, 1) as gen_value_on_col_656 + ,gen_id(g, 1) as gen_value_on_col_657 + ,gen_id(g, 1) as gen_value_on_col_658 + ,gen_id(g, 1) as gen_value_on_col_659 + ,gen_id(g, 1) as gen_value_on_col_660 + ,gen_id(g, 1) as gen_value_on_col_661 + ,gen_id(g, 1) as gen_value_on_col_662 + ,gen_id(g, 1) as gen_value_on_col_663 + ,gen_id(g, 1) as gen_value_on_col_664 + ,gen_id(g, 1) as gen_value_on_col_665 + ,gen_id(g, 1) as gen_value_on_col_666 + ,gen_id(g, 1) as gen_value_on_col_667 + ,gen_id(g, 1) as gen_value_on_col_668 + ,gen_id(g, 1) as gen_value_on_col_669 + ,gen_id(g, 1) as gen_value_on_col_670 + ,gen_id(g, 1) as gen_value_on_col_671 + ,gen_id(g, 1) as gen_value_on_col_672 + ,gen_id(g, 1) as gen_value_on_col_673 + ,gen_id(g, 1) as gen_value_on_col_674 + ,gen_id(g, 1) as gen_value_on_col_675 + ,gen_id(g, 1) as gen_value_on_col_676 + ,gen_id(g, 1) as gen_value_on_col_677 + ,gen_id(g, 1) as gen_value_on_col_678 + ,gen_id(g, 1) as gen_value_on_col_679 + ,gen_id(g, 1) as gen_value_on_col_680 + ,gen_id(g, 1) as gen_value_on_col_681 + ,gen_id(g, 1) as gen_value_on_col_682 + ,gen_id(g, 1) as gen_value_on_col_683 + ,gen_id(g, 1) as gen_value_on_col_684 + ,gen_id(g, 1) as gen_value_on_col_685 + ,gen_id(g, 1) as gen_value_on_col_686 + ,gen_id(g, 1) as gen_value_on_col_687 + ,gen_id(g, 1) as gen_value_on_col_688 + ,gen_id(g, 1) as gen_value_on_col_689 + ,gen_id(g, 1) as gen_value_on_col_690 + ,gen_id(g, 1) as gen_value_on_col_691 + ,gen_id(g, 1) as gen_value_on_col_692 + ,gen_id(g, 1) as gen_value_on_col_693 + ,gen_id(g, 1) as gen_value_on_col_694 + ,gen_id(g, 1) as gen_value_on_col_695 + ,gen_id(g, 1) as gen_value_on_col_696 + ,gen_id(g, 1) as gen_value_on_col_697 + ,gen_id(g, 1) as gen_value_on_col_698 + ,gen_id(g, 1) as gen_value_on_col_699 + ,gen_id(g, 1) as gen_value_on_col_700 + ,gen_id(g, 1) as gen_value_on_col_701 + ,gen_id(g, 1) as gen_value_on_col_702 + ,gen_id(g, 1) as gen_value_on_col_703 + ,gen_id(g, 1) as gen_value_on_col_704 + ,gen_id(g, 1) as gen_value_on_col_705 + ,gen_id(g, 1) as gen_value_on_col_706 + ,gen_id(g, 1) as gen_value_on_col_707 + ,gen_id(g, 1) as gen_value_on_col_708 + ,gen_id(g, 1) as gen_value_on_col_709 + ,gen_id(g, 1) as gen_value_on_col_710 + ,gen_id(g, 1) as gen_value_on_col_711 + ,gen_id(g, 1) as gen_value_on_col_712 + ,gen_id(g, 1) as gen_value_on_col_713 + ,gen_id(g, 1) as gen_value_on_col_714 + ,gen_id(g, 1) as gen_value_on_col_715 + ,gen_id(g, 1) as gen_value_on_col_716 + ,gen_id(g, 1) as gen_value_on_col_717 + ,gen_id(g, 1) as gen_value_on_col_718 + ,gen_id(g, 1) as gen_value_on_col_719 + ,gen_id(g, 1) as gen_value_on_col_720 + ,gen_id(g, 1) as gen_value_on_col_721 + ,gen_id(g, 1) as gen_value_on_col_722 + ,gen_id(g, 1) as gen_value_on_col_723 + ,gen_id(g, 1) as gen_value_on_col_724 + ,gen_id(g, 1) as gen_value_on_col_725 + ,gen_id(g, 1) as gen_value_on_col_726 + ,gen_id(g, 1) as gen_value_on_col_727 + ,gen_id(g, 1) as gen_value_on_col_728 + ,gen_id(g, 1) as gen_value_on_col_729 + ,gen_id(g, 1) as gen_value_on_col_730 + ,gen_id(g, 1) as gen_value_on_col_731 + ,gen_id(g, 1) as gen_value_on_col_732 + ,gen_id(g, 1) as gen_value_on_col_733 + ,gen_id(g, 1) as gen_value_on_col_734 + ,gen_id(g, 1) as gen_value_on_col_735 + ,gen_id(g, 1) as gen_value_on_col_736 + ,gen_id(g, 1) as gen_value_on_col_737 + ,gen_id(g, 1) as gen_value_on_col_738 + ,gen_id(g, 1) as gen_value_on_col_739 + ,gen_id(g, 1) as gen_value_on_col_740 + ,gen_id(g, 1) as gen_value_on_col_741 + ,gen_id(g, 1) as gen_value_on_col_742 + ,gen_id(g, 1) as gen_value_on_col_743 + ,gen_id(g, 1) as gen_value_on_col_744 + ,gen_id(g, 1) as gen_value_on_col_745 + ,gen_id(g, 1) as gen_value_on_col_746 + ,gen_id(g, 1) as gen_value_on_col_747 + ,gen_id(g, 1) as gen_value_on_col_748 + ,gen_id(g, 1) as gen_value_on_col_749 + ,gen_id(g, 1) as gen_value_on_col_750 + ,gen_id(g, 1) as gen_value_on_col_751 + ,gen_id(g, 1) as gen_value_on_col_752 + ,gen_id(g, 1) as gen_value_on_col_753 + ,gen_id(g, 1) as gen_value_on_col_754 + ,gen_id(g, 1) as gen_value_on_col_755 + ,gen_id(g, 1) as gen_value_on_col_756 + ,gen_id(g, 1) as gen_value_on_col_757 + ,gen_id(g, 1) as gen_value_on_col_758 + ,gen_id(g, 1) as gen_value_on_col_759 + ,gen_id(g, 1) as gen_value_on_col_760 + ,gen_id(g, 1) as gen_value_on_col_761 + ,gen_id(g, 1) as gen_value_on_col_762 + ,gen_id(g, 1) as gen_value_on_col_763 + ,gen_id(g, 1) as gen_value_on_col_764 + ,gen_id(g, 1) as gen_value_on_col_765 + ,gen_id(g, 1) as gen_value_on_col_766 + ,gen_id(g, 1) as gen_value_on_col_767 + ,gen_id(g, 1) as gen_value_on_col_768 + ,gen_id(g, 1) as gen_value_on_col_769 + ,gen_id(g, 1) as gen_value_on_col_770 + ,gen_id(g, 1) as gen_value_on_col_771 + ,gen_id(g, 1) as gen_value_on_col_772 + ,gen_id(g, 1) as gen_value_on_col_773 + ,gen_id(g, 1) as gen_value_on_col_774 + ,gen_id(g, 1) as gen_value_on_col_775 + ,gen_id(g, 1) as gen_value_on_col_776 + ,gen_id(g, 1) as gen_value_on_col_777 + ,gen_id(g, 1) as gen_value_on_col_778 + ,gen_id(g, 1) as gen_value_on_col_779 + ,gen_id(g, 1) as gen_value_on_col_780 + ,gen_id(g, 1) as gen_value_on_col_781 + ,gen_id(g, 1) as gen_value_on_col_782 + ,gen_id(g, 1) as gen_value_on_col_783 + ,gen_id(g, 1) as gen_value_on_col_784 + ,gen_id(g, 1) as gen_value_on_col_785 + ,gen_id(g, 1) as gen_value_on_col_786 + ,gen_id(g, 1) as gen_value_on_col_787 + ,gen_id(g, 1) as gen_value_on_col_788 + ,gen_id(g, 1) as gen_value_on_col_789 + ,gen_id(g, 1) as gen_value_on_col_790 + ,gen_id(g, 1) as gen_value_on_col_791 + ,gen_id(g, 1) as gen_value_on_col_792 + ,gen_id(g, 1) as gen_value_on_col_793 + ,gen_id(g, 1) as gen_value_on_col_794 + ,gen_id(g, 1) as gen_value_on_col_795 + ,gen_id(g, 1) as gen_value_on_col_796 + ,gen_id(g, 1) as gen_value_on_col_797 + ,gen_id(g, 1) as gen_value_on_col_798 + ,gen_id(g, 1) as gen_value_on_col_799 + ,gen_id(g, 1) as gen_value_on_col_800 + ,gen_id(g, 1) as gen_value_on_col_801 + ,gen_id(g, 1) as gen_value_on_col_802 + ,gen_id(g, 1) as gen_value_on_col_803 + ,gen_id(g, 1) as gen_value_on_col_804 + ,gen_id(g, 1) as gen_value_on_col_805 + ,gen_id(g, 1) as gen_value_on_col_806 + ,gen_id(g, 1) as gen_value_on_col_807 + ,gen_id(g, 1) as gen_value_on_col_808 + ,gen_id(g, 1) as gen_value_on_col_809 + ,gen_id(g, 1) as gen_value_on_col_810 + ,gen_id(g, 1) as gen_value_on_col_811 + ,gen_id(g, 1) as gen_value_on_col_812 + ,gen_id(g, 1) as gen_value_on_col_813 + ,gen_id(g, 1) as gen_value_on_col_814 + ,gen_id(g, 1) as gen_value_on_col_815 + ,gen_id(g, 1) as gen_value_on_col_816 + ,gen_id(g, 1) as gen_value_on_col_817 + ,gen_id(g, 1) as gen_value_on_col_818 + ,gen_id(g, 1) as gen_value_on_col_819 + ,gen_id(g, 1) as gen_value_on_col_820 + ,gen_id(g, 1) as gen_value_on_col_821 + ,gen_id(g, 1) as gen_value_on_col_822 + ,gen_id(g, 1) as gen_value_on_col_823 + ,gen_id(g, 1) as gen_value_on_col_824 + ,gen_id(g, 1) as gen_value_on_col_825 + ,gen_id(g, 1) as gen_value_on_col_826 + ,gen_id(g, 1) as gen_value_on_col_827 + ,gen_id(g, 1) as gen_value_on_col_828 + ,gen_id(g, 1) as gen_value_on_col_829 + ,gen_id(g, 1) as gen_value_on_col_830 + ,gen_id(g, 1) as gen_value_on_col_831 + ,gen_id(g, 1) as gen_value_on_col_832 + ,gen_id(g, 1) as gen_value_on_col_833 + ,gen_id(g, 1) as gen_value_on_col_834 + ,gen_id(g, 1) as gen_value_on_col_835 + ,gen_id(g, 1) as gen_value_on_col_836 + ,gen_id(g, 1) as gen_value_on_col_837 + ,gen_id(g, 1) as gen_value_on_col_838 + ,gen_id(g, 1) as gen_value_on_col_839 + ,gen_id(g, 1) as gen_value_on_col_840 + ,gen_id(g, 1) as gen_value_on_col_841 + ,gen_id(g, 1) as gen_value_on_col_842 + ,gen_id(g, 1) as gen_value_on_col_843 + ,gen_id(g, 1) as gen_value_on_col_844 + ,gen_id(g, 1) as gen_value_on_col_845 + ,gen_id(g, 1) as gen_value_on_col_846 + ,gen_id(g, 1) as gen_value_on_col_847 + ,gen_id(g, 1) as gen_value_on_col_848 + ,gen_id(g, 1) as gen_value_on_col_849 + ,gen_id(g, 1) as gen_value_on_col_850 + ,gen_id(g, 1) as gen_value_on_col_851 + ,gen_id(g, 1) as gen_value_on_col_852 + ,gen_id(g, 1) as gen_value_on_col_853 + ,gen_id(g, 1) as gen_value_on_col_854 + ,gen_id(g, 1) as gen_value_on_col_855 + ,gen_id(g, 1) as gen_value_on_col_856 + ,gen_id(g, 1) as gen_value_on_col_857 + ,gen_id(g, 1) as gen_value_on_col_858 + ,gen_id(g, 1) as gen_value_on_col_859 + ,gen_id(g, 1) as gen_value_on_col_860 + ,gen_id(g, 1) as gen_value_on_col_861 + ,gen_id(g, 1) as gen_value_on_col_862 + ,gen_id(g, 1) as gen_value_on_col_863 + ,gen_id(g, 1) as gen_value_on_col_864 + ,gen_id(g, 1) as gen_value_on_col_865 + ,gen_id(g, 1) as gen_value_on_col_866 + ,gen_id(g, 1) as gen_value_on_col_867 + ,gen_id(g, 1) as gen_value_on_col_868 + ,gen_id(g, 1) as gen_value_on_col_869 + ,gen_id(g, 1) as gen_value_on_col_870 + ,gen_id(g, 1) as gen_value_on_col_871 + ,gen_id(g, 1) as gen_value_on_col_872 + ,gen_id(g, 1) as gen_value_on_col_873 + ,gen_id(g, 1) as gen_value_on_col_874 + ,gen_id(g, 1) as gen_value_on_col_875 + ,gen_id(g, 1) as gen_value_on_col_876 + ,gen_id(g, 1) as gen_value_on_col_877 + ,gen_id(g, 1) as gen_value_on_col_878 + ,gen_id(g, 1) as gen_value_on_col_879 + ,gen_id(g, 1) as gen_value_on_col_880 + ,gen_id(g, 1) as gen_value_on_col_881 + ,gen_id(g, 1) as gen_value_on_col_882 + ,gen_id(g, 1) as gen_value_on_col_883 + ,gen_id(g, 1) as gen_value_on_col_884 + ,gen_id(g, 1) as gen_value_on_col_885 + ,gen_id(g, 1) as gen_value_on_col_886 + ,gen_id(g, 1) as gen_value_on_col_887 + ,gen_id(g, 1) as gen_value_on_col_888 + ,gen_id(g, 1) as gen_value_on_col_889 + ,gen_id(g, 1) as gen_value_on_col_890 + ,gen_id(g, 1) as gen_value_on_col_891 + ,gen_id(g, 1) as gen_value_on_col_892 + ,gen_id(g, 1) as gen_value_on_col_893 + ,gen_id(g, 1) as gen_value_on_col_894 + ,gen_id(g, 1) as gen_value_on_col_895 + ,gen_id(g, 1) as gen_value_on_col_896 + ,gen_id(g, 1) as gen_value_on_col_897 + ,gen_id(g, 1) as gen_value_on_col_898 + ,gen_id(g, 1) as gen_value_on_col_899 + ,gen_id(g, 1) as gen_value_on_col_900 + ,gen_id(g, 1) as gen_value_on_col_901 + ,gen_id(g, 1) as gen_value_on_col_902 + ,gen_id(g, 1) as gen_value_on_col_903 + ,gen_id(g, 1) as gen_value_on_col_904 + ,gen_id(g, 1) as gen_value_on_col_905 + ,gen_id(g, 1) as gen_value_on_col_906 + ,gen_id(g, 1) as gen_value_on_col_907 + ,gen_id(g, 1) as gen_value_on_col_908 + ,gen_id(g, 1) as gen_value_on_col_909 + ,gen_id(g, 1) as gen_value_on_col_910 + ,gen_id(g, 1) as gen_value_on_col_911 + ,gen_id(g, 1) as gen_value_on_col_912 + ,gen_id(g, 1) as gen_value_on_col_913 + ,gen_id(g, 1) as gen_value_on_col_914 + ,gen_id(g, 1) as gen_value_on_col_915 + ,gen_id(g, 1) as gen_value_on_col_916 + ,gen_id(g, 1) as gen_value_on_col_917 + ,gen_id(g, 1) as gen_value_on_col_918 + ,gen_id(g, 1) as gen_value_on_col_919 + ,gen_id(g, 1) as gen_value_on_col_920 + ,gen_id(g, 1) as gen_value_on_col_921 + ,gen_id(g, 1) as gen_value_on_col_922 + ,gen_id(g, 1) as gen_value_on_col_923 + ,gen_id(g, 1) as gen_value_on_col_924 + ,gen_id(g, 1) as gen_value_on_col_925 + ,gen_id(g, 1) as gen_value_on_col_926 + ,gen_id(g, 1) as gen_value_on_col_927 + ,gen_id(g, 1) as gen_value_on_col_928 + ,gen_id(g, 1) as gen_value_on_col_929 + ,gen_id(g, 1) as gen_value_on_col_930 + ,gen_id(g, 1) as gen_value_on_col_931 + ,gen_id(g, 1) as gen_value_on_col_932 + ,gen_id(g, 1) as gen_value_on_col_933 + ,gen_id(g, 1) as gen_value_on_col_934 + ,gen_id(g, 1) as gen_value_on_col_935 + ,gen_id(g, 1) as gen_value_on_col_936 + ,gen_id(g, 1) as gen_value_on_col_937 + ,gen_id(g, 1) as gen_value_on_col_938 + ,gen_id(g, 1) as gen_value_on_col_939 + ,gen_id(g, 1) as gen_value_on_col_940 + ,gen_id(g, 1) as gen_value_on_col_941 + ,gen_id(g, 1) as gen_value_on_col_942 + ,gen_id(g, 1) as gen_value_on_col_943 + ,gen_id(g, 1) as gen_value_on_col_944 + ,gen_id(g, 1) as gen_value_on_col_945 + ,gen_id(g, 1) as gen_value_on_col_946 + ,gen_id(g, 1) as gen_value_on_col_947 + ,gen_id(g, 1) as gen_value_on_col_948 + ,gen_id(g, 1) as gen_value_on_col_949 + ,gen_id(g, 1) as gen_value_on_col_950 + ,gen_id(g, 1) as gen_value_on_col_951 + ,gen_id(g, 1) as gen_value_on_col_952 + ,gen_id(g, 1) as gen_value_on_col_953 + ,gen_id(g, 1) as gen_value_on_col_954 + ,gen_id(g, 1) as gen_value_on_col_955 + ,gen_id(g, 1) as gen_value_on_col_956 + ,gen_id(g, 1) as gen_value_on_col_957 + ,gen_id(g, 1) as gen_value_on_col_958 + ,gen_id(g, 1) as gen_value_on_col_959 + ,gen_id(g, 1) as gen_value_on_col_960 + ,gen_id(g, 1) as gen_value_on_col_961 + ,gen_id(g, 1) as gen_value_on_col_962 + ,gen_id(g, 1) as gen_value_on_col_963 + ,gen_id(g, 1) as gen_value_on_col_964 + ,gen_id(g, 1) as gen_value_on_col_965 + ,gen_id(g, 1) as gen_value_on_col_966 + ,gen_id(g, 1) as gen_value_on_col_967 + ,gen_id(g, 1) as gen_value_on_col_968 + ,gen_id(g, 1) as gen_value_on_col_969 + ,gen_id(g, 1) as gen_value_on_col_970 + ,gen_id(g, 1) as gen_value_on_col_971 + ,gen_id(g, 1) as gen_value_on_col_972 + ,gen_id(g, 1) as gen_value_on_col_973 + ,gen_id(g, 1) as gen_value_on_col_974 + ,gen_id(g, 1) as gen_value_on_col_975 + ,gen_id(g, 1) as gen_value_on_col_976 + ,gen_id(g, 1) as gen_value_on_col_977 + ,gen_id(g, 1) as gen_value_on_col_978 + ,gen_id(g, 1) as gen_value_on_col_979 + ,gen_id(g, 1) as gen_value_on_col_980 + ,gen_id(g, 1) as gen_value_on_col_981 + ,gen_id(g, 1) as gen_value_on_col_982 + ,gen_id(g, 1) as gen_value_on_col_983 + ,gen_id(g, 1) as gen_value_on_col_984 + ,gen_id(g, 1) as gen_value_on_col_985 + ,gen_id(g, 1) as gen_value_on_col_986 + ,gen_id(g, 1) as gen_value_on_col_987 + ,gen_id(g, 1) as gen_value_on_col_988 + ,gen_id(g, 1) as gen_value_on_col_989 + ,gen_id(g, 1) as gen_value_on_col_990 + ,gen_id(g, 1) as gen_value_on_col_991 + ,gen_id(g, 1) as gen_value_on_col_992 + ,gen_id(g, 1) as gen_value_on_col_993 + ,gen_id(g, 1) as gen_value_on_col_994 + ,gen_id(g, 1) as gen_value_on_col_995 + ,gen_id(g, 1) as gen_value_on_col_996 + ,gen_id(g, 1) as gen_value_on_col_997 + ,gen_id(g, 1) as gen_value_on_col_998 + ,gen_id(g, 1) as gen_value_on_col_999 + ,gen_id(g, 1) as gen_value_on_col_1000 + from rdb$database + ); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + SUM_ALL 500500 + """ + +@pytest.mark.version('>=3.0') +def test_core_1117_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1120.py b/tests/bugs/test_core_1120.py new file mode 100644 index 00000000..21084ead --- /dev/null +++ b/tests/bugs/test_core_1120.py @@ -0,0 +1,57 @@ +#coding:utf-8 +# +# id: bugs.core_1120 +# title: Conversion from string to number is not standard compliant +# decription: +# tracker_id: CORE-1120 +# min_versions: [] +# versions: 2.5.0 +# qmid: bugs.core_1120-250 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select cast(5.6 as integer) from rdb$database; +select cast('5.6' as integer) from rdb$database; +select cast('5,6' as integer) from rdb$database; +select cast('5,6,7 8 9' as integer) from rdb$database; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """CAST +============ + 6 + +CAST +============ + 6 + +CAST +============ +CAST +============ +""" +expected_stderr_1 = """Statement failed, SQLSTATE = 22018 +conversion error from string "5,6" +Statement failed, SQLSTATE = 22018 +conversion error from string "5,6,7 8 9" +""" + +@pytest.mark.version('>=2.5.0') +def test_core_1120_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1122.py b/tests/bugs/test_core_1122.py new file mode 100644 index 00000000..552b3c72 --- /dev/null +++ b/tests/bugs/test_core_1122.py @@ -0,0 +1,116 @@ +#coding:utf-8 +# +# id: bugs.core_1122 +# title: Recursive Query bug in FB2.1 +# decription: +# tracker_id: CORE-1122 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1122 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table tb_menus( + record_id integer, + parent_id integer, + order_item integer not null, + menu_name varchar(120), + app_name varchar(80), + menu_icon blob sub_type 0 segment size 80 + ); + commit; + + insert into tb_menus values (0, null, 1, 'm1', null, null); + insert into tb_menus values (1, 0, 1, 'm1 - sub1', 'app1.exe', null); + insert into tb_menus values (2, 0, 1, 'm1 - sub2', 'app2.exe', null); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + -------------------- 1st query ------------------ + with recursive + menus_list as ( + select + parent_id, + record_id, + order_item, + menu_name, + app_name, + menu_icon, + cast('' as varchar(255)) ident + from tb_menus + where parent_id is null + + UNION ALL + + select + m.parent_id, + m.record_id, + m.order_item, + m.menu_name, + m.app_name, + m.menu_icon, -- ::: NB ::: this field was not qualified ==> parsing error in 3.0 (but not in 2.5.4 or 2.1.7) + h.ident || ' ' as ident + from tb_menus m + join menus_list h on m.parent_id = h.record_id + ) + select + parent_id, + record_id, + order_item, + (ident || menu_name) "menu name", + app_name, + menu_icon + from menus_list; + -------------------- 2nd query ------------------ + select menu_icon from tb_menus + UNION ALL + select menu_icon from tb_menus; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PARENT_ID + RECORD_ID 0 + ORDER_ITEM 1 + menu name m1 + APP_NAME + MENU_ICON + PARENT_ID 0 + RECORD_ID 1 + ORDER_ITEM 1 + menu name m1 - sub1 + APP_NAME app1.exe + MENU_ICON + PARENT_ID 0 + RECORD_ID 2 + ORDER_ITEM 1 + menu name m1 - sub2 + APP_NAME app2.exe + MENU_ICON + + MENU_ICON + MENU_ICON + MENU_ICON + MENU_ICON + MENU_ICON + MENU_ICON + """ + +@pytest.mark.version('>=2.1') +def test_core_1122_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1126.py b/tests/bugs/test_core_1126.py new file mode 100644 index 00000000..f24f6b4d --- /dev/null +++ b/tests/bugs/test_core_1126.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: bugs.core_1126 +# title: UNION vs UTF8 literals : arithmetic exception is thrown +# decription: +# tracker_id: CORE-1126 +# min_versions: [] +# versions: 2.5 +# qmid: bugs.core_1126 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT _UTF8 'Z' FROM RDB$DATABASE +UNION ALL +SELECT _UTF8 'A' FROM RDB$DATABASE; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """CONSTANT +======== +Z +A + +""" + +@pytest.mark.version('>=2.5') +def test_core_1126_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1130.py b/tests/bugs/test_core_1130.py new file mode 100644 index 00000000..61c0155c --- /dev/null +++ b/tests/bugs/test_core_1130.py @@ -0,0 +1,57 @@ +#coding:utf-8 +# +# id: bugs.core_1130 +# title: Bad optimization -- left join (or ) +# decription: +# tracker_id: +# min_versions: [] +# versions: 2.0.1 +# qmid: bugs.core_1130 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """SET TERM ^; +create procedure p + returns (r int) +as +begin + r = 1; + suspend; +end +^ +SET TERM ;^ +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +select * +from p + left join ( select rdb$relation_id from rdb$relations ) r + on p.r = r.rdb$relation_id; + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN JOIN (P NATURAL, R RDB$RELATIONS INDEX (RDB$INDEX_1)) + + R RDB$RELATION_ID +============ =============== + 1 1 + +""" + +@pytest.mark.version('>=2.0.1') +def test_core_1130_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1142.py b/tests/bugs/test_core_1142.py new file mode 100644 index 00000000..734f270e --- /dev/null +++ b/tests/bugs/test_core_1142.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_1142 +# title: Cannot alter generator's comment to the same value +# decription: +# tracker_id: CORE-1142 +# min_versions: [] +# versions: 2.0.2 +# qmid: bugs.core_1142 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create generator T;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """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; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """COMMENT ON GENERATOR T IS comment; +COMMENT ON GENERATOR T IS comment; +COMMENT ON GENERATOR T IS different comment; +""" + +@pytest.mark.version('>=2.0.2') +def test_core_1142_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1145.py b/tests/bugs/test_core_1145.py new file mode 100644 index 00000000..47fdcd84 --- /dev/null +++ b/tests/bugs/test_core_1145.py @@ -0,0 +1,87 @@ +#coding:utf-8 +# +# id: bugs.core_1145 +# title: Server locks up while attempting to commit a deletion of an expression index +# decription: This test may lock up the server. +# tracker_id: CORE-1145 +# min_versions: [] +# versions: 2.0.2 +# qmid: bugs.core_1145 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table expt1 (col1 int); +create table expt2 (col2 int); +commit; + +insert into expt1 values (1); +insert into expt1 values (2); + +insert into expt2 values (1); +insert into expt2 values (2); +commit; + +create index iexpt1 on expt1 computed (col1 + 1); +create index iexpt2 on expt2 computed (col2 + 1); +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """set plan on; +select * from expt1 where col1 + 1 = 2; +select * from expt2 where col2 + 1 = 2; +commit; + +drop index iexpt2; +commit; -- lockup + +select * from expt1 where col1 + 1 = 2; +select * from expt2 where col2 + 1 = 2; +commit; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +PLAN (EXPT1 INDEX (IEXPT1)) + + COL1 +============ + 1 + + +PLAN (EXPT2 INDEX (IEXPT2)) + + COL2 +============ + 1 + + +PLAN (EXPT1 INDEX (IEXPT1)) + + COL1 +============ + 1 + + +PLAN (EXPT2 NATURAL) + + COL2 +============ + 1 + +""" + +@pytest.mark.version('>=2.0.2') +def test_core_1145_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1146.py b/tests/bugs/test_core_1146.py new file mode 100644 index 00000000..a1742528 --- /dev/null +++ b/tests/bugs/test_core_1146.py @@ -0,0 +1,62 @@ +#coding:utf-8 +# +# id: bugs.core_1146 +# title: AV in rse\\invalidate_child_rpbs for recursive queies +# decription: This may crash the server with AV +# tracker_id: CORE-1146 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1146 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table c ( + id integer, + name varchar(100) + ); + recreate table t ( + id integer, + ownercode integer, + code integer + ); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Updated code to recent FB version: add prefixes to every field from the query + with recursive x as + ( + select --1 as step, + t.id, t.ownercode, t.code, c2.name as ownclass, c1.name as class + from t inner join c c1 on c1.id = t.code + left join c c2 on c2.id = t.ownercode + where ownercode = 0 + + union all + + select --x.step+1 + t.id, t.ownercode, x.code, c2.name as ownclass, c1.name as class + from t inner join c c1 on c1.id = t.code + left join c c2 on c2.id = t.ownercode + inner join x on t.ownercode = x.code + ) + select * from x + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1') +def test_core_1146_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_1148.py b/tests/bugs/test_core_1148.py new file mode 100644 index 00000000..5858a3b7 --- /dev/null +++ b/tests/bugs/test_core_1148.py @@ -0,0 +1,103 @@ +#coding:utf-8 +# +# id: bugs.core_1148 +# title: Every user can view server log using services API +# decription: +# Instead of usage 'resource:test_user' (as it was before) we create every time this test run user TMP$C1148 +# and make test connect to database as this user in order to check ability to connect and get engine version. +# Then we parse engine version (is it 2.5 or 3.0 ?) and construct command to obtain Firebird log using FBSVCMGR +# (switches differ for 2.5 and 3.0! For 2.5 it must be: "action_get_ib_log", for 3.0: "action_get_fb_log"). +# After that we try to extract firebird log using fbsvcmgr and this command is EXPECTED return error, so we log +# this message to separate file (and STDOUT is redirected to /dev/null). +# Finally, we check content of 1st and 2nd files and remove temply created user. +# +# tracker_id: CORE-1148 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: bugs.core_1148 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('ENGINE_VERSION .*', 'ENGINE_VERSION'), ('STDERR: UNABLE TO PERFORM OPERATION.*', 'STDERR: UNABLE TO PERFORM OPERATION'), ('STDERR: -YOU MUST HAVE SYSDBA RIGHTS AT THIS SERVER*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# +# # Refactored 05-JAN-2016: removed dependency on recource 'test_user' because this lead to: +# # UNTESTED: bugs.core_2729 +# # Add new user +# # Unexpected stderr stream received from GSEC. +# # (i.e. test remained in state "Untested" because of internal error in gsec while creating user 'test' from resource). +# # Checked on WI-V2.5.5.26952 (SC), WI-V3.0.0.32266 (SS/SC/CS). +# +# import os +# import subprocess +# import time +# +# # Obtain engine version: +# engine = str(db_conn.engine_version) +# +# db_conn.execute_immediate("create user tmp$c1148 password 'QweRtyUi'") +# db_conn.commit() +# +# if engine.startswith('2.5'): +# get_firebird_log_key='action_get_ib_log' +# else: +# get_firebird_log_key='action_get_fb_log' +# +# fn_nul = open(os.devnull, 'w') +# fn_err=open( os.path.join(context['temp_directory'],'tmp_1148_get_fb_log.err'), 'w') +# subprocess.call([ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# "user","TMP$C1148","password","QweRtyUi", +# get_firebird_log_key +# ], +# stdout=fn_nul, +# stderr=fn_err +# ) +# fn_nul.close() +# fn_err.close() +# +# # CLEANUP: drop user that was temp-ly created for this test: +# ########## +# db_conn.execute_immediate('drop user tmp$c1148') +# db_conn.commit() +# +# # Ouput error log: it should contain text about unable to perform operation. +# # NB: text in FB 4.0 was splitted, phrase "You must have SYSDBA rights..." is +# # printed on separate line. Checking for matching to this phrase can be skipped +# # (see 'substitutions' section below): +# with open( fn_err.name,'r') as f: +# for line in f: +# print("STDERR: "+line.upper()) +# +# # Do not remove this pause: on Windows closing of handles can take some (small) time. +# # Otherwise Windows(32) access error can raise here. +# time.sleep(1) +# +# if os.path.isfile(fn_err.name): +# os.remove(fn_err.name) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + STDERR: UNABLE TO PERFORM OPERATION + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_1148_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_1150.py b/tests/bugs/test_core_1150.py new file mode 100644 index 00000000..b8357d81 --- /dev/null +++ b/tests/bugs/test_core_1150.py @@ -0,0 +1,58 @@ +#coding:utf-8 +# +# id: bugs.core_1150 +# title: Error conversion error from string " " using outer join on int64 and int fields +# decription: +# tracker_id: CORE-1150 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1150 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE J ( + ID INTEGER NOT NULL, + CODETABLE INTEGER, + CODEVSPTABLE INTEGER +); + + +CREATE TABLE TT ( + ID BIGINT NOT NULL +); + +ALTER TABLE TT ADD CONSTRAINT PK_TT PRIMARY KEY (ID); + +COMMIT; + +INSERT INTO TT(ID) VALUES(1); +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT 1 + FROM TT T1 LEFT JOIN J ON J.CODETABLE = T1.ID + LEFT JOIN TT T2 ON J.CODEVSPTABLE = T2.ID ; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """CONSTANT +============ + 1 + +""" + +@pytest.mark.version('>=2.1') +def test_core_1150_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1152.py b/tests/bugs/test_core_1152.py new file mode 100644 index 00000000..bd09cecb --- /dev/null +++ b/tests/bugs/test_core_1152.py @@ -0,0 +1,37 @@ +#coding:utf-8 +# +# id: bugs.core_1152 +# title: cannot erase a table with check constraints referencing more than a single columns +# decription: +# tracker_id: CORE-1152 +# min_versions: [] +# versions: 2.0 +# qmid: bugs.core_1152 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE test( +int1 INTEGER, +int2 INTEGER, +CHECK(int1 IS NULL OR int2 IS NULL) +); +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """DROP TABLE test; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.0') +def test_core_1152_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_1153.py b/tests/bugs/test_core_1153.py new file mode 100644 index 00000000..f1fa5a45 --- /dev/null +++ b/tests/bugs/test_core_1153.py @@ -0,0 +1,108 @@ +#coding:utf-8 +# +# id: bugs.core_1153 +# title: Activating index change "STARTING" working as "LIKE" in join condition +# decription: +# tracker_id: CORE-1153 +# min_versions: [] +# versions: 2.0.2 +# qmid: bugs.core_1153 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """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_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """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 + +""" + +@pytest.mark.version('>=2.0.2') +def test_core_1153_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1156.py b/tests/bugs/test_core_1156.py new file mode 100644 index 00000000..e7acf9db --- /dev/null +++ b/tests/bugs/test_core_1156.py @@ -0,0 +1,60 @@ +#coding:utf-8 +# +# id: bugs.core_1156 +# title: Prepare fails when having a parameter in a DSQL statement before a sub query +# decription: +# tracker_id: CORE-1156 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1156 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# c = db_conn.cursor() +# try: +# c.prep('select count(*) from rdb$database where ? < (select count(*) from rdb$database)') +# except: +# print ('Test FAILED in case 1') +# +# try: +# c.prep('select count(*) from rdb$database where (select count(*) from rdb$database) > ?') +# except: +# print ('Test FAILED in case 2') +# +# try: +# c.prep('select count(*) from rdb$database where ? < cast ((select count(*) from rdb$database) as integer)') +# except: +# print ('Test FAILED in case 3') +# +# try: +# c.prep('select count(*) from rdb$database where 0 < (select count(*) from rdb$database)') +# except: +# print ('Test FAILED in case 4') +# +# try: +# c.prep('select count(*) from rdb$database where cast (? as integer) < (select count(*) from rdb$database)') +# except: +# print ('Test FAILED in case 5') +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1') +@pytest.mark.xfail +def test_core_1156_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_1162.py b/tests/bugs/test_core_1162.py new file mode 100644 index 00000000..3f4452a2 --- /dev/null +++ b/tests/bugs/test_core_1162.py @@ -0,0 +1,67 @@ +#coding:utf-8 +# +# id: bugs.core_1162 +# title: Problem altering numeric field type +# decription: 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. +# tracker_id: CORE-1162 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_1162-250 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """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; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """A +======= + 99.99 + +""" +expected_stderr_1 = """Statement failed, SQLSTATE = 42000 +unsuccessful metadata update +-ALTER TABLE TAB failed +-New scale specified for column A must be at most 2. +""" + +@pytest.mark.version('>=3.0') +def test_core_1162_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1165.py b/tests/bugs/test_core_1165.py new file mode 100644 index 00000000..aa9a95eb --- /dev/null +++ b/tests/bugs/test_core_1165.py @@ -0,0 +1,68 @@ +#coding:utf-8 +# +# id: bugs.core_1165 +# title: WHEN tracks only the dependency on the first exception in PSQL +# decription: +# tracker_id: CORE-1165 +# min_versions: [] +# versions: 2.5.0 +# qmid: bugs.core_1165-250 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """recreate exception e1 'e1' ; +recreate exception e2 'e2' ; + +set term ^; + +create procedure p as +begin + begin end + when exception e1, exception e2 do + begin + end +end^ + +set term ;^ +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """show depend p; + +recreate exception e1 'e1'; +recreate exception e2 'e2'; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """[P:Procedure] +E2:Exception, E1:Exception ++++ +""" +expected_stderr_1 = """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 +""" + +@pytest.mark.version('>=2.5.0') +def test_core_1165_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1167.py b/tests/bugs/test_core_1167.py new file mode 100644 index 00000000..552e0213 --- /dev/null +++ b/tests/bugs/test_core_1167.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: bugs.core_1167 +# title: CHARACTER SET GBK is not installed +# decription: Default character set is GBK +# Create Table T1(ID integer, FName Varchar(20); -- OK +# Commit; ---Error Message: CHARACTER SET GBK is not installed +# tracker_id: CORE-1167 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1167 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='GBK', sql_dialect=3, init=init_script_1) + +test_script_1 = """Create Table T1(ID integer, FName Varchar(20) CHARACTER SET GBK); +COMMIT; +SHOW TABLE T1; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ID INTEGER Nullable +FNAME VARCHAR(20) Nullable +""" + +@pytest.mark.version('>=2.1') +def test_core_1167_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1171.py b/tests/bugs/test_core_1171.py new file mode 100644 index 00000000..d9005194 --- /dev/null +++ b/tests/bugs/test_core_1171.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: bugs.core_1171 +# title: isql exponential format of numbers has zero pad on windows +# decription: +# tracker_id: CORE-1171 +# min_versions: ['2.1.3'] +# versions: 2.1.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """select cast ('-2.488355210669293e+39' as double precision) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CAST +======================= + -2.488355210669293e+39 + +""" + +@pytest.mark.version('>=2.1.3') +def test_core_1171_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1172.py b/tests/bugs/test_core_1172.py new file mode 100644 index 00000000..b58ca351 --- /dev/null +++ b/tests/bugs/test_core_1172.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: bugs.core_1172 +# title: Symbols ignored for ES_ES_CI_AI collation +# decription: +# tracker_id: CORE-1172 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1172 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE TABLE_A ( + FIELD_A VARCHAR(10) CHARACTER SET iso8859_1 COLLATE ES_ES_CI_AI +); + +ALTER TABLE TABLE_A ADD CONSTRAINT UNQ1_TABLE_A UNIQUE (FIELD_A); + +INSERT INTO TABLE_A (FIELD_A) VALUES ('A'); + +commit; + +create collation es_es_ci_ai2 for iso8859_1 from es_es_ci_ai 'SPECIALS-FIRST=1'; + +CREATE TABLE TABLE_B ( + FIELD_A VARCHAR(10) CHARACTER SET iso8859_1 COLLATE ES_ES_CI_AI2 +); + +ALTER TABLE TABLE_B ADD CONSTRAINT UNQ1_TABLE_B UNIQUE (FIELD_A); + +INSERT INTO TABLE_B (FIELD_A) VALUES ('A'); + +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """INSERT INTO TABLE_A (FIELD_A) VALUES ('A.'); +INSERT INTO TABLE_A (FIELD_A) VALUES ('A-'); +INSERT INTO TABLE_A (FIELD_A) VALUES ('-A'); +INSERT INTO TABLE_A (FIELD_A) VALUES ('(A)'); +INSERT INTO TABLE_A (FIELD_A) VALUES ('(A)a'); +INSERT INTO TABLE_A (FIELD_A) VALUES ('Aa'); + +INSERT INTO TABLE_B (FIELD_A) VALUES ('A.'); +INSERT INTO TABLE_B (FIELD_A) VALUES ('A-'); +INSERT INTO TABLE_B (FIELD_A) VALUES ('-A'); +INSERT INTO TABLE_B (FIELD_A) VALUES ('(A)'); +INSERT INTO TABLE_B (FIELD_A) VALUES ('(A)a'); +INSERT INTO TABLE_B (FIELD_A) VALUES ('Aa'); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1') +def test_core_1172_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_1173.py b/tests/bugs/test_core_1173.py new file mode 100644 index 00000000..7ea91a4a --- /dev/null +++ b/tests/bugs/test_core_1173.py @@ -0,0 +1,105 @@ +#coding:utf-8 +# +# id: bugs.core_1173 +# title: Expression index based on computed fields +# decription: +# Index based on COMPUTED-BY column must be taken in account by optimizer. +# 13.08.2020: replaced expected_stdout with only PLAN output (concrete data values no matter in this test). +# Checked on: +# 4.0.0.2151 SS: 1.475s. +# 3.0.7.33348 SS: 1.172s. +# 2.5.9.27150 SC: 0.311s. +# +# tracker_id: +# min_versions: ['2.5.4'] +# versions: 2.5.4 +# qmid: bugs.core_1173 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create sequence g; + recreate table test ( + fcode integer not null, + fdate date not null, + ftime time not null, + fcomp computed by (fdate+ftime), + constraint test_pk primary key (fcode) + ); + + insert into test(fcode, fdate, ftime) + select gen_id(g,1), dateadd( gen_id(g,1) day to cast('01.01.2010' as date) ), dateadd( gen_id(g,1) second to cast('00:00:00' as time) ) from rdb$types rows 200; + commit; + + -- ######################################################################### + + -- Index on COMPUTED BY field, ascending: + create index test_on_computed_field_asc on test computed by (fcomp); + commit; + + set plan on; + + select * from test where fcomp>'now' rows 0; + commit; + + drop index test_on_computed_field_asc; + commit; + + -- COMPUTED-BY index with expression equal to computed-by column, ascending: + create index test_fdate_ftime_asc on test computed by (fdate+ftime); + select * from test where fcomp>'now' rows 0; + commit; + + drop index test_fdate_ftime_asc; + commit; + + -- ######################################################################### + + -- Index on COMPUTED BY field, descending: + create descending index test_on_computed_field_dec on test computed by (fcomp); + commit; + + set plan on; + + select * from test where fcomp>'now' rows 0; + commit; + + drop index test_on_computed_field_dec; + commit; + + -- COMPUTED-BY index with expression equal to computed-by column, decending: + create descending index test_fdate_ftime_dec on test computed by (fdate+ftime); + select * from test where fcomp>'now' rows 0; + commit; + + drop index test_fdate_ftime_dec; + commit; + + set plan off; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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)) + """ + +@pytest.mark.version('>=2.5.4') +def test_core_1173_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1175.py b/tests/bugs/test_core_1175.py new file mode 100644 index 00000000..6836a40a --- /dev/null +++ b/tests/bugs/test_core_1175.py @@ -0,0 +1,78 @@ +#coding:utf-8 +# +# id: bugs.core_1175 +# title: Error "Data type unknown" when any UDF argument is a built-in function containing a DSQL parameter reference +# decription: +# For FB 2.5 and 3.x - this test uses UDF from ib_udf. +# +# 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/ +# +# Checked on: +# 4.0.0.1340: OK, 2.594s. +# 4.0.0.1378: OK, 5.579s. +# +# NOTE. Build 4.0.0.1172 (date: 25.08.2018) raises here: +# SQLCODE: -902... expression evaluation not supported... +# Invalid data type for division in dialect 3 +# gdscode = 335544569. +# +# tracker_id: CORE-1175 +# min_versions: [] +# versions: 4.0 +# qmid: bugs.core_1175 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + -- 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 function UDR40_div ( + n1 integer, + n2 integer + ) returns double precision + external name 'udf_compat!UC_div' + engine udr; + + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# \\ +# c = db_conn.cursor() +# try: +# c.prep( 'select 1 from rdb$database where UDR40_frac( ? ) != UDR40_div( ?, ?) / ? ' ) +# print ( 'Test PASSED!' ) +# except Exception,e: +# print( 'Test FAILED!' ) +# print( e ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Test PASSED! + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_1175_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_1179.py b/tests/bugs/test_core_1179.py new file mode 100644 index 00000000..f4b88c4f --- /dev/null +++ b/tests/bugs/test_core_1179.py @@ -0,0 +1,97 @@ +#coding:utf-8 +# +# id: bugs.core_1179 +# title: "CH" and "LL" are not separate spanish alphabet letters since 1994 +# decription: +# tracker_id: CORE-1179 +# min_versions: ['2.1.7'] +# versions: 2.1.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.7 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test_utf8(id int, esp varchar(10)); + commit; + + insert into test_utf8 values(-2,'CH'); + insert into test_utf8 values(-1,'LL'); + insert into test_utf8 values( 1,'C'); + insert into test_utf8 values( 2,'CA'); + insert into test_utf8 values( 3,'CZ'); + insert into test_utf8 values( 5,'D'); + + insert into test_utf8 values( 6,'L'); + insert into test_utf8 values( 7,'LA'); + insert into test_utf8 values( 8,'LZ'); + insert into test_utf8 values(10,'M'); + commit; + + recreate table test_iso( id int, esp varchar(10) character set ISO8859_1 ); + commit; + + + insert into test_iso values(-2,'CH'); + insert into test_iso values(-1,'LL'); + insert into test_iso values( 1,'C'); + insert into test_iso values( 2,'CA'); + insert into test_iso values( 3,'CZ'); + insert into test_iso values( 5,'D'); + + insert into test_iso values( 6,'L'); + insert into test_iso values( 7,'LA'); + insert into test_iso values( 8,'LZ'); + insert into test_iso values(10,'M'); + commit; + + select id, esp from test_utf8 order by esp collate utf8; + select id, esp from test_iso order by esp collate es_es; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID ESP + ============ ========== + 1 C + 2 CA + -2 CH + 3 CZ + 5 D + 6 L + 7 LA + -1 LL + 8 LZ + 10 M + + + ID ESP + ============ ========== + 1 C + 2 CA + -2 CH + 3 CZ + 5 D + 6 L + 7 LA + -1 LL + 8 LZ + 10 M + """ + +@pytest.mark.version('>=2.1.7') +def test_core_1179_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1181.py b/tests/bugs/test_core_1181.py new file mode 100644 index 00000000..89111104 --- /dev/null +++ b/tests/bugs/test_core_1181.py @@ -0,0 +1,76 @@ +#coding:utf-8 +# +# id: bugs.core_1181 +# title: Union returns inconsistent field names +# decription: +# tracker_id: CORE-1181 +# min_versions: ['2.0.7'] +# versions: 2.0.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test1(id numeric(15, 2)); + commit; + + recreate table test2(id double precision); + commit; + + + insert into test1 values(0); + commit; + + insert into test2 values(1e0); ---- do NOT use 0e0! something weird occurs on linux: aux '0' in fractional part! + commit; + + + set list on; + + select id as test1_id + from test1 + group by id + + union + + select cast(0 as numeric(15,2)) + from rdb$database; + + ----------------------------------- + + select id as test2_id + from test2 + group by id + + union + + select cast(1 as double precision) + from rdb$database; + + + -- Results were checked both on dialect 1 & 3, they are identical. + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TEST1_ID 0.00 + TEST2_ID 1.000000000000000 + """ + +@pytest.mark.version('>=2.0.7') +def test_core_1181_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1183.py b/tests/bugs/test_core_1183.py new file mode 100644 index 00000000..d1cf2446 --- /dev/null +++ b/tests/bugs/test_core_1183.py @@ -0,0 +1,63 @@ +#coding:utf-8 +# +# id: bugs.core_1183 +# title: View cannot be created if its WHERE clause contains IN with a procedure reference +# decription: +# tracker_id: CORE-1183 +# min_versions: [] +# versions: 2.0.2 +# qmid: bugs.core_1183 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + set term ^; + create or alter procedure p + returns (col int) + as + begin + col = 1; + suspend; + end^ + set term ;^ + commit; + + create or alter view v + as + select + rdb$description v_descr, + rdb$relation_id v_rel_id, + rdb$character_set_name v_cset_name + from rdb$database + where 1 in ( select col from p ); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select v_descr, sign(v_rel_id) as v_rel_id, v_cset_name + from v; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + V_DESCR + V_REL_ID 1 + V_CSET_NAME NONE + """ + +@pytest.mark.version('>=2.0.2') +def test_core_1183_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1188.py b/tests/bugs/test_core_1188.py new file mode 100644 index 00000000..b9526220 --- /dev/null +++ b/tests/bugs/test_core_1188.py @@ -0,0 +1,132 @@ +#coding:utf-8 +# +# id: bugs.core_1188 +# title: Select Starting with :Param (Empty string) doesn't work if using index with many fields +# decription: +# tracker_id: CORE-1188 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- NB! As of 17.04.2015 this ticket resolves trouble only for FB-3.0. + -- Build WI-V2.5.4.26857 returns NO rows! + -- 23.10.2016: WI-V2.5.7.27026 - result the same (bad). + + set list on; + + -- from core-1188: + recreate table test_1( + f01 varchar(10), + f02 varchar(10) + ); + commit; + insert into test_1 values('a','b'); + commit; + create index test_1_idx on test_1(f01,f02); + commit; + + + set term ^; + execute block returns( + msg varchar(10), + f01 type of column test_1.f01, + f02 type of column test_1.f02 + ) as + declare v_stt1 varchar(255); + begin + msg='test_1'; + v_stt1 = 'select f01, f02 from test_1 where f01=''a'' and f02 starting with ?'; + for + execute statement(v_stt1) ('') + into f01, f02 + do + suspend; + end + ^ + set term ;^ + + + -- from core-3971: + recreate table test_2 ( + field_id integer not null, + field_desc varchar(10) not null, + field_sel smallint not null + ); + + create index test_2_idx1 on test_2 (field_id, field_desc); + create index test_2_idx2 on test_2 (field_sel, field_desc); + commit; + + insert into test_2 (field_id, field_desc, field_sel) + values (1, '', 1); + insert into test_2 (field_id, field_desc, field_sel) + values (2, '', 1); + insert into test_2 (field_id, field_desc, field_sel) + values (3, 'b', 1); + + set term ^; + execute block returns( + msg varchar(10), + f01 type of column test_2.field_id, + f02 type of column test_2.field_desc, + f03 type of column test_2.field_sel + ) as + declare v_stt varchar(255); + begin + msg = 'test_2'; + v_stt = 'select field_id, ''>''||field_desc||''<'', field_sel' + ||' from test_2' + || ' where field_sel = 1 and field_desc starting with ? '; + + for + execute statement(v_stt) ('') + into f01, f02, f03 + do + suspend; + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG test_1 + F01 a + F02 b + + MSG test_2 + F01 1 + F02 >< + F03 1 + + MSG test_2 + F01 2 + F02 >< + F03 1 + + MSG test_2 + F01 3 + F02 >b< + F03 1 + """ + +@pytest.mark.version('>=3.0') +def test_core_1188_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1196.py b/tests/bugs/test_core_1196.py new file mode 100644 index 00000000..083795e9 --- /dev/null +++ b/tests/bugs/test_core_1196.py @@ -0,0 +1,1039 @@ +#coding:utf-8 +# +# id: bugs.core_1196 +# title: Long SQL statements break TCP/IP connection +# decription: +# tracker_id: CORE-1196 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1196 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT + 1, /* Looooooooong comment */ + 2, /* Looooooooong comment */ + 3, /* Looooooooong comment */ + 4, /* Looooooooong comment */ + 5, /* Looooooooong comment */ + 6, /* Looooooooong comment */ + 7, /* Looooooooong comment */ + 8, /* Looooooooong comment */ + 9, /* Looooooooong comment */ + 10, /* Looooooooong comment */ + 11, /* Looooooooong comment */ + 12, /* Looooooooong comment */ + 13, /* Looooooooong comment */ + 14, /* Looooooooong comment */ + 15, /* Looooooooong comment */ + 16, /* Looooooooong comment */ + 17, /* Looooooooong comment */ + 18, /* Looooooooong comment */ + 19, /* Looooooooong comment */ + 20, /* Looooooooong comment */ + 21, /* Looooooooong comment */ + 22, /* Looooooooong comment */ + 23, /* Looooooooong comment */ + 24, /* Looooooooong comment */ + 25, /* Looooooooong comment */ + 26, /* Looooooooong comment */ + 27, /* Looooooooong comment */ + 28, /* Looooooooong comment */ + 29, /* Looooooooong comment */ + 30, /* Looooooooong comment */ + 31, /* Looooooooong comment */ + 32, /* Looooooooong comment */ + 33, /* Looooooooong comment */ + 34, /* Looooooooong comment */ + 35, /* Looooooooong comment */ + 36, /* Looooooooong comment */ + 37, /* Looooooooong comment */ + 38, /* Looooooooong comment */ + 39, /* Looooooooong comment */ + 40, /* Looooooooong comment */ + 41, /* Looooooooong comment */ + 42, /* Looooooooong comment */ + 43, /* Looooooooong comment */ + 44, /* Looooooooong comment */ + 45, /* Looooooooong comment */ + 46, /* Looooooooong comment */ + 47, /* Looooooooong comment */ + 48, /* Looooooooong comment */ + 49, /* Looooooooong comment */ + 50, /* Looooooooong comment */ + 51, /* Looooooooong comment */ + 52, /* Looooooooong comment */ + 53, /* Looooooooong comment */ + 54, /* Looooooooong comment */ + 55, /* Looooooooong comment */ + 56, /* Looooooooong comment */ + 57, /* Looooooooong comment */ + 58, /* Looooooooong comment */ + 59, /* Looooooooong comment */ + 60, /* Looooooooong comment */ + 61, /* Looooooooong comment */ + 62, /* Looooooooong comment */ + 63, /* Looooooooong comment */ + 64, /* Looooooooong comment */ + 65, /* Looooooooong comment */ + 66, /* Looooooooong comment */ + 67, /* Looooooooong comment */ + 68, /* Looooooooong comment */ + 69, /* Looooooooong comment */ + 70, /* Looooooooong comment */ + 71, /* Looooooooong comment */ + 72, /* Looooooooong comment */ + 73, /* Looooooooong comment */ + 74, /* Looooooooong comment */ + 75, /* Looooooooong comment */ + 76, /* Looooooooong comment */ + 77, /* Looooooooong comment */ + 78, /* Looooooooong comment */ + 79, /* Looooooooong comment */ + 80, /* Looooooooong comment */ + 81, /* Looooooooong comment */ + 82, /* Looooooooong comment */ + 83, /* Looooooooong comment */ + 84, /* Looooooooong comment */ + 85, /* Looooooooong comment */ + 86, /* Looooooooong comment */ + 86, /* Looooooooong comment */ + 88, /* Looooooooong comment */ + 89, /* Looooooooong comment */ + 90, /* Looooooooong comment */ + 91, /* Looooooooong comment */ + 92, /* Looooooooong comment */ + 93, /* Looooooooong comment */ + 94, /* Looooooooong comment */ + 95, /* Looooooooong comment */ + 96, /* Looooooooong comment */ + 97, /* Looooooooong comment */ + 98, /* Looooooooong comment */ + 99, /* Looooooooong comment */ +100, /* Looooooooong comment */ +101, /* Looooooooong comment */ +102, /* Looooooooong comment */ +103, /* Looooooooong comment */ +104, /* Looooooooong comment */ +105, /* Looooooooong comment */ +106, /* Looooooooong comment */ +107, /* Looooooooong comment */ +108, /* Looooooooong comment */ +109, /* Looooooooong comment */ +110, /* Looooooooong comment */ +111, /* Looooooooong comment */ +112, /* Looooooooong comment */ +113, /* Looooooooong comment */ +114, /* Looooooooong comment */ +115, /* Looooooooong comment */ +116, /* Looooooooong comment */ +117, /* Looooooooong comment */ +118, /* Looooooooong comment */ +119, /* Looooooooong comment */ +120, /* Looooooooong comment */ +121, /* Looooooooong comment */ +122, /* Looooooooong comment */ +123, /* Looooooooong comment */ +124, /* Looooooooong comment */ +125, /* Looooooooong comment */ +126, /* Looooooooong comment */ +127, /* Looooooooong comment */ +128, /* Looooooooong comment */ +129, /* Looooooooong comment */ +130, /* Looooooooong comment */ +131, /* Looooooooong comment */ +132, /* Looooooooong comment */ +133, /* Looooooooong comment */ +134, /* Looooooooong comment */ +135, /* Looooooooong comment */ +136, /* Looooooooong comment */ +137, /* Looooooooong comment */ +138, /* Looooooooong comment */ +139, /* Looooooooong comment */ +140, /* Looooooooong comment */ +141, /* Looooooooong comment */ +142, /* Looooooooong comment */ +143, /* Looooooooong comment */ +144, /* Looooooooong comment */ +145, /* Looooooooong comment */ +146, /* Looooooooong comment */ +147, /* Looooooooong comment */ +148, /* Looooooooong comment */ +149, /* Looooooooong comment */ +150, /* Looooooooong comment */ +151, /* Looooooooong comment */ +152, /* Looooooooong comment */ +153, /* Looooooooong comment */ +154, /* Looooooooong comment */ +155, /* Looooooooong comment */ +156, /* Looooooooong comment */ +157, /* Looooooooong comment */ +158, /* Looooooooong comment */ +159, /* Looooooooong comment */ +160, /* Looooooooong comment */ +161, /* Looooooooong comment */ +162, /* Looooooooong comment */ +163, /* Looooooooong comment */ +164, /* Looooooooong comment */ +165, /* Looooooooong comment */ +166, /* Looooooooong comment */ +167, /* Looooooooong comment */ +168, /* Looooooooong comment */ +169, /* Looooooooong comment */ +170, /* Looooooooong comment */ +171, /* Looooooooong comment */ +172, /* Looooooooong comment */ +173, /* Looooooooong comment */ +174, /* Looooooooong comment */ +175, /* Looooooooong comment */ +176, /* Looooooooong comment */ +177, /* Looooooooong comment */ +178, /* Looooooooong comment */ +179, /* Looooooooong comment */ +180, /* Looooooooong comment */ +181, /* Looooooooong comment */ +182, /* Looooooooong comment */ +183, /* Looooooooong comment */ +184, /* Looooooooong comment */ +185, /* Looooooooong comment */ +186, /* Looooooooong comment */ +186, /* Looooooooong comment */ +188, /* Looooooooong comment */ +189, /* Looooooooong comment */ +190, /* Looooooooong comment */ +191, /* Looooooooong comment */ +192, /* Looooooooong comment */ +193, /* Looooooooong comment */ +194, /* Looooooooong comment */ +195, /* Looooooooong comment */ +196, /* Looooooooong comment */ +197, /* Looooooooong comment */ +198, /* Looooooooong comment */ +199, /* Looooooooong comment */ +200, /* Looooooooong comment */ +201, /* Looooooooong comment */ +202, /* Looooooooong comment */ +203, /* Looooooooong comment */ +204, /* Looooooooong comment */ +205, /* Looooooooong comment */ +206, /* Looooooooong comment */ +207, /* Looooooooong comment */ +208, /* Looooooooong comment */ +209, /* Looooooooong comment */ +210, /* Looooooooong comment */ +211, /* Looooooooong comment */ +212, /* Looooooooong comment */ +213, /* Looooooooong comment */ +214, /* Looooooooong comment */ +215, /* Looooooooong comment */ +216, /* Looooooooong comment */ +217, /* Looooooooong comment */ +218, /* Looooooooong comment */ +219, /* Looooooooong comment */ +220, /* Looooooooong comment */ +221, /* Looooooooong comment */ +222, /* Looooooooong comment */ +223, /* Looooooooong comment */ +224, /* Looooooooong comment */ +225, /* Looooooooong comment */ +226, /* Looooooooong comment */ +227, /* Looooooooong comment */ +228, /* Looooooooong comment */ +229, /* Looooooooong comment */ +230, /* Looooooooong comment */ +231, /* Looooooooong comment */ +232, /* Looooooooong comment */ +233, /* Looooooooong comment */ +234, /* Looooooooong comment */ +235, /* Looooooooong comment */ +236, /* Looooooooong comment */ +237, /* Looooooooong comment */ +238, /* Looooooooong comment */ +239, /* Looooooooong comment */ +240, /* Looooooooong comment */ +241, /* Looooooooong comment */ +242, /* Looooooooong comment */ +243, /* Looooooooong comment */ +244, /* Looooooooong comment */ +245, /* Looooooooong comment */ +246, /* Looooooooong comment */ +247, /* Looooooooong comment */ +248, /* Looooooooong comment */ +249, /* Looooooooong comment */ +250, /* Looooooooong comment */ +251, /* Looooooooong comment */ +252, /* Looooooooong comment */ +253, /* Looooooooong comment */ +254, /* Looooooooong comment */ +255, /* Looooooooong comment */ +256, /* Looooooooong comment */ +257, /* Looooooooong comment */ +258, /* Looooooooong comment */ +259, /* Looooooooong comment */ +260, /* Looooooooong comment */ +261, /* Looooooooong comment */ +262, /* Looooooooong comment */ +263, /* Looooooooong comment */ +264, /* Looooooooong comment */ +265, /* Looooooooong comment */ +266, /* Looooooooong comment */ +267, /* Looooooooong comment */ +268, /* Looooooooong comment */ +269, /* Looooooooong comment */ +270, /* Looooooooong comment */ +271, /* Looooooooong comment */ +272, /* Looooooooong comment */ +273, /* Looooooooong comment */ +274, /* Looooooooong comment */ +275, /* Looooooooong comment */ +276, /* Looooooooong comment */ +277, /* Looooooooong comment */ +278, /* Looooooooong comment */ +279, /* Looooooooong comment */ +280, /* Looooooooong comment */ +281, /* Looooooooong comment */ +282, /* Looooooooong comment */ +283, /* Looooooooong comment */ +284, /* Looooooooong comment */ +285, /* Looooooooong comment */ +286, /* Looooooooong comment */ +286, /* Looooooooong comment */ +288, /* Looooooooong comment */ +289, /* Looooooooong comment */ +290, /* Looooooooong comment */ +291, /* Looooooooong comment */ +292, /* Looooooooong comment */ +293, /* Looooooooong comment */ +294, /* Looooooooong comment */ +295, /* Looooooooong comment */ +296, /* Looooooooong comment */ +297, /* Looooooooong comment */ +298, /* Looooooooong comment */ +299, /* Looooooooong comment */ +300, /* Looooooooong comment */ +301, /* Looooooooong comment */ +302, /* Looooooooong comment */ +303, /* Looooooooong comment */ +304, /* Looooooooong comment */ +305, /* Looooooooong comment */ +306, /* Looooooooong comment */ +307, /* Looooooooong comment */ +308, /* Looooooooong comment */ +309, /* Looooooooong comment */ +310, /* Looooooooong comment */ +311, /* Looooooooong comment */ +312, /* Looooooooong comment */ +313, /* Looooooooong comment */ +314, /* Looooooooong comment */ +315, /* Looooooooong comment */ +316, /* Looooooooong comment */ +317, /* Looooooooong comment */ +318, /* Looooooooong comment */ +319, /* Looooooooong comment */ +320, /* Looooooooong comment */ +321, /* Looooooooong comment */ +322, /* Looooooooong comment */ +323, /* Looooooooong comment */ +324, /* Looooooooong comment */ +325, /* Looooooooong comment */ +326, /* Looooooooong comment */ +327, /* Looooooooong comment */ +328, /* Looooooooong comment */ +329, /* Looooooooong comment */ +330, /* Looooooooong comment */ +331, /* Looooooooong comment */ +332, /* Looooooooong comment */ +333, /* Looooooooong comment */ +334, /* Looooooooong comment */ +335, /* Looooooooong comment */ +336, /* Looooooooong comment */ +337, /* Looooooooong comment */ +338, /* Looooooooong comment */ +339, /* Looooooooong comment */ +340, /* Looooooooong comment */ +341, /* Looooooooong comment */ +342, /* Looooooooong comment */ +343, /* Looooooooong comment */ +344, /* Looooooooong comment */ +345, /* Looooooooong comment */ +346, /* Looooooooong comment */ +347, /* Looooooooong comment */ +348, /* Looooooooong comment */ +349, /* Looooooooong comment */ +350, /* Looooooooong comment */ +351, /* Looooooooong comment */ +352, /* Looooooooong comment */ +353, /* Looooooooong comment */ +354, /* Looooooooong comment */ +355, /* Looooooooong comment */ +356, /* Looooooooong comment */ +357, /* Looooooooong comment */ +358, /* Looooooooong comment */ +359, /* Looooooooong comment */ +360, /* Looooooooong comment */ +361, /* Looooooooong comment */ +362, /* Looooooooong comment */ +363, /* Looooooooong comment */ +364, /* Looooooooong comment */ +365, /* Looooooooong comment */ +366, /* Looooooooong comment */ +367, /* Looooooooong comment */ +368, /* Looooooooong comment */ +369, /* Looooooooong comment */ +370, /* Looooooooong comment */ +371, /* Looooooooong comment */ +372, /* Looooooooong comment */ +373, /* Looooooooong comment */ +374, /* Looooooooong comment */ +375, /* Looooooooong comment */ +376, /* Looooooooong comment */ +377, /* Looooooooong comment */ +378, /* Looooooooong comment */ +379, /* Looooooooong comment */ +380, /* Looooooooong comment */ +381, /* Looooooooong comment */ +382, /* Looooooooong comment */ +383, /* Looooooooong comment */ +384, /* Looooooooong comment */ +385, /* Looooooooong comment */ +386, /* Looooooooong comment */ +386, /* Looooooooong comment */ +388, /* Looooooooong comment */ +389, /* Looooooooong comment */ +390, /* Looooooooong comment */ +391, /* Looooooooong comment */ +392, /* Looooooooong comment */ +393, /* Looooooooong comment */ +394, /* Looooooooong comment */ +395, /* Looooooooong comment */ +396, /* Looooooooong comment */ +397, /* Looooooooong comment */ +398, /* Looooooooong comment */ +399, /* Looooooooong comment */ +400, /* Looooooooong comment */ +401, /* Looooooooong comment */ +402, /* Looooooooong comment */ +403, /* Looooooooong comment */ +404, /* Looooooooong comment */ +405, /* Looooooooong comment */ +406, /* Looooooooong comment */ +407, /* Looooooooong comment */ +408, /* Looooooooong comment */ +409, /* Looooooooong comment */ +410, /* Looooooooong comment */ +411, /* Looooooooong comment */ +412, /* Looooooooong comment */ +413, /* Looooooooong comment */ +414, /* Looooooooong comment */ +415, /* Looooooooong comment */ +416, /* Looooooooong comment */ +417, /* Looooooooong comment */ +418, /* Looooooooong comment */ +419, /* Looooooooong comment */ +420, /* Looooooooong comment */ +421, /* Looooooooong comment */ +422, /* Looooooooong comment */ +423, /* Looooooooong comment */ +424, /* Looooooooong comment */ +425, /* Looooooooong comment */ +426, /* Looooooooong comment */ +427, /* Looooooooong comment */ +428, /* Looooooooong comment */ +429, /* Looooooooong comment */ +430, /* Looooooooong comment */ +431, /* Looooooooong comment */ +432, /* Looooooooong comment */ +433, /* Looooooooong comment */ +434, /* Looooooooong comment */ +435, /* Looooooooong comment */ +436, /* Looooooooong comment */ +437, /* Looooooooong comment */ +438, /* Looooooooong comment */ +439, /* Looooooooong comment */ +440, /* Looooooooong comment */ +441, /* Looooooooong comment */ +442, /* Looooooooong comment */ +443, /* Looooooooong comment */ +444, /* Looooooooong comment */ +445, /* Looooooooong comment */ +446, /* Looooooooong comment */ +447, /* Looooooooong comment */ +448, /* Looooooooong comment */ +449, /* Looooooooong comment */ +450, /* Looooooooong comment */ +451, /* Looooooooong comment */ +452, /* Looooooooong comment */ +453, /* Looooooooong comment */ +454, /* Looooooooong comment */ +455, /* Looooooooong comment */ +456, /* Looooooooong comment */ +457, /* Looooooooong comment */ +458, /* Looooooooong comment */ +459, /* Looooooooong comment */ +460, /* Looooooooong comment */ +461, /* Looooooooong comment */ +462, /* Looooooooong comment */ +463, /* Looooooooong comment */ +464, /* Looooooooong comment */ +465, /* Looooooooong comment */ +466, /* Looooooooong comment */ +467, /* Looooooooong comment */ +468, /* Looooooooong comment */ +469, /* Looooooooong comment */ +470, /* Looooooooong comment */ +471, /* Looooooooong comment */ +472, /* Looooooooong comment */ +473, /* Looooooooong comment */ +474, /* Looooooooong comment */ +475, /* Looooooooong comment */ +476, /* Looooooooong comment */ +477, /* Looooooooong comment */ +478, /* Looooooooong comment */ +479, /* Looooooooong comment */ +480, /* Looooooooong comment */ +481, /* Looooooooong comment */ +482, /* Looooooooong comment */ +483, /* Looooooooong comment */ +484, /* Looooooooong comment */ +485, /* Looooooooong comment */ +486, /* Looooooooong comment */ +486, /* Looooooooong comment */ +488, /* Looooooooong comment */ +489, /* Looooooooong comment */ +490, /* Looooooooong comment */ +491, /* Looooooooong comment */ +492, /* Looooooooong comment */ +493, /* Looooooooong comment */ +494, /* Looooooooong comment */ +495, /* Looooooooong comment */ +496, /* Looooooooong comment */ +497, /* Looooooooong comment */ +498, /* Looooooooong comment */ +499, /* Looooooooong comment */ +500, /* Looooooooong comment */ +501, /* Looooooooong comment */ +502, /* Looooooooong comment */ +503, /* Looooooooong comment */ +504, /* Looooooooong comment */ +505, /* Looooooooong comment */ +506, /* Looooooooong comment */ +507, /* Looooooooong comment */ +508, /* Looooooooong comment */ +509, /* Looooooooong comment */ +510, /* Looooooooong comment */ +511, /* Looooooooong comment */ +512, /* Looooooooong comment */ +513, /* Looooooooong comment */ +514, /* Looooooooong comment */ +515, /* Looooooooong comment */ +516, /* Looooooooong comment */ +517, /* Looooooooong comment */ +518, /* Looooooooong comment */ +519, /* Looooooooong comment */ +520, /* Looooooooong comment */ +521, /* Looooooooong comment */ +522, /* Looooooooong comment */ +523, /* Looooooooong comment */ +524, /* Looooooooong comment */ +525, /* Looooooooong comment */ +526, /* Looooooooong comment */ +527, /* Looooooooong comment */ +528, /* Looooooooong comment */ +529, /* Looooooooong comment */ +530, /* Looooooooong comment */ +531, /* Looooooooong comment */ +532, /* Looooooooong comment */ +533, /* Looooooooong comment */ +534, /* Looooooooong comment */ +535, /* Looooooooong comment */ +536, /* Looooooooong comment */ +537, /* Looooooooong comment */ +538, /* Looooooooong comment */ +539, /* Looooooooong comment */ +540, /* Looooooooong comment */ +541, /* Looooooooong comment */ +542, /* Looooooooong comment */ +543, /* Looooooooong comment */ +544, /* Looooooooong comment */ +545, /* Looooooooong comment */ +546, /* Looooooooong comment */ +547, /* Looooooooong comment */ +548, /* Looooooooong comment */ +549, /* Looooooooong comment */ +550, /* Looooooooong comment */ +551, /* Looooooooong comment */ +552, /* Looooooooong comment */ +553, /* Looooooooong comment */ +554, /* Looooooooong comment */ +555, /* Looooooooong comment */ +556, /* Looooooooong comment */ +557, /* Looooooooong comment */ +558, /* Looooooooong comment */ +559, /* Looooooooong comment */ +560, /* Looooooooong comment */ +561, /* Looooooooong comment */ +562, /* Looooooooong comment */ +563, /* Looooooooong comment */ +564, /* Looooooooong comment */ +565, /* Looooooooong comment */ +566, /* Looooooooong comment */ +567, /* Looooooooong comment */ +568, /* Looooooooong comment */ +569, /* Looooooooong comment */ +570, /* Looooooooong comment */ +571, /* Looooooooong comment */ +572, /* Looooooooong comment */ +573, /* Looooooooong comment */ +574, /* Looooooooong comment */ +575, /* Looooooooong comment */ +576, /* Looooooooong comment */ +577, /* Looooooooong comment */ +578, /* Looooooooong comment */ +579, /* Looooooooong comment */ +580, /* Looooooooong comment */ +581, /* Looooooooong comment */ +582, /* Looooooooong comment */ +583, /* Looooooooong comment */ +584, /* Looooooooong comment */ +585, /* Looooooooong comment */ +586, /* Looooooooong comment */ +586, /* Looooooooong comment */ +588, /* Looooooooong comment */ +589, /* Looooooooong comment */ +590, /* Looooooooong comment */ +591, /* Looooooooong comment */ +592, /* Looooooooong comment */ +593, /* Looooooooong comment */ +594, /* Looooooooong comment */ +595, /* Looooooooong comment */ +596, /* Looooooooong comment */ +597, /* Looooooooong comment */ +598, /* Looooooooong comment */ +599, /* Looooooooong comment */ +600, /* Looooooooong comment */ +601, /* Looooooooong comment */ +602, /* Looooooooong comment */ +603, /* Looooooooong comment */ +604, /* Looooooooong comment */ +605, /* Looooooooong comment */ +606, /* Looooooooong comment */ +607, /* Looooooooong comment */ +608, /* Looooooooong comment */ +609, /* Looooooooong comment */ +610, /* Looooooooong comment */ +611, /* Looooooooong comment */ +612, /* Looooooooong comment */ +613, /* Looooooooong comment */ +614, /* Looooooooong comment */ +615, /* Looooooooong comment */ +616, /* Looooooooong comment */ +617, /* Looooooooong comment */ +618, /* Looooooooong comment */ +619, /* Looooooooong comment */ +620, /* Looooooooong comment */ +621, /* Looooooooong comment */ +622, /* Looooooooong comment */ +623, /* Looooooooong comment */ +624, /* Looooooooong comment */ +625, /* Looooooooong comment */ +626, /* Looooooooong comment */ +627, /* Looooooooong comment */ +628, /* Looooooooong comment */ +629, /* Looooooooong comment */ +630, /* Looooooooong comment */ +631, /* Looooooooong comment */ +632, /* Looooooooong comment */ +633, /* Looooooooong comment */ +634, /* Looooooooong comment */ +635, /* Looooooooong comment */ +636, /* Looooooooong comment */ +637, /* Looooooooong comment */ +638, /* Looooooooong comment */ +639, /* Looooooooong comment */ +640, /* Looooooooong comment */ +641, /* Looooooooong comment */ +642, /* Looooooooong comment */ +643, /* Looooooooong comment */ +644, /* Looooooooong comment */ +645, /* Looooooooong comment */ +646, /* Looooooooong comment */ +647, /* Looooooooong comment */ +648, /* Looooooooong comment */ +649, /* Looooooooong comment */ +650, /* Looooooooong comment */ +651, /* Looooooooong comment */ +652, /* Looooooooong comment */ +653, /* Looooooooong comment */ +654, /* Looooooooong comment */ +655, /* Looooooooong comment */ +656, /* Looooooooong comment */ +657, /* Looooooooong comment */ +658, /* Looooooooong comment */ +659, /* Looooooooong comment */ +660, /* Looooooooong comment */ +661, /* Looooooooong comment */ +662, /* Looooooooong comment */ +663, /* Looooooooong comment */ +664, /* Looooooooong comment */ +665, /* Looooooooong comment */ +666, /* Looooooooong comment */ +667, /* Looooooooong comment */ +668, /* Looooooooong comment */ +669, /* Looooooooong comment */ +670, /* Looooooooong comment */ +671, /* Looooooooong comment */ +672, /* Looooooooong comment */ +673, /* Looooooooong comment */ +674, /* Looooooooong comment */ +675, /* Looooooooong comment */ +676, /* Looooooooong comment */ +677, /* Looooooooong comment */ +678, /* Looooooooong comment */ +679, /* Looooooooong comment */ +680, /* Looooooooong comment */ +681, /* Looooooooong comment */ +682, /* Looooooooong comment */ +683, /* Looooooooong comment */ +684, /* Looooooooong comment */ +685, /* Looooooooong comment */ +686, /* Looooooooong comment */ +686, /* Looooooooong comment */ +688, /* Looooooooong comment */ +689, /* Looooooooong comment */ +690, /* Looooooooong comment */ +691, /* Looooooooong comment */ +692, /* Looooooooong comment */ +693, /* Looooooooong comment */ +694, /* Looooooooong comment */ +695, /* Looooooooong comment */ +696, /* Looooooooong comment */ +697, /* Looooooooong comment */ +698, /* Looooooooong comment */ +700, /* Looooooooong comment */ +701, /* Looooooooong comment */ +702, /* Looooooooong comment */ +703, /* Looooooooong comment */ +704, /* Looooooooong comment */ +705, /* Looooooooong comment */ +706, /* Looooooooong comment */ +707, /* Looooooooong comment */ +708, /* Looooooooong comment */ +709, /* Looooooooong comment */ +710, /* Looooooooong comment */ +711, /* Looooooooong comment */ +712, /* Looooooooong comment */ +713, /* Looooooooong comment */ +714, /* Looooooooong comment */ +715, /* Looooooooong comment */ +716, /* Looooooooong comment */ +717, /* Looooooooong comment */ +718, /* Looooooooong comment */ +719, /* Looooooooong comment */ +720, /* Looooooooong comment */ +721, /* Looooooooong comment */ +722, /* Looooooooong comment */ +723, /* Looooooooong comment */ +724, /* Looooooooong comment */ +725, /* Looooooooong comment */ +726, /* Looooooooong comment */ +727, /* Looooooooong comment */ +728, /* Looooooooong comment */ +729, /* Looooooooong comment */ +730, /* Looooooooong comment */ +731, /* Looooooooong comment */ +732, /* Looooooooong comment */ +733, /* Looooooooong comment */ +734, /* Looooooooong comment */ +735, /* Looooooooong comment */ +736, /* Looooooooong comment */ +737, /* Looooooooong comment */ +738, /* Looooooooong comment */ +739, /* Looooooooong comment */ +740, /* Looooooooong comment */ +741, /* Looooooooong comment */ +742, /* Looooooooong comment */ +743, /* Looooooooong comment */ +744, /* Looooooooong comment */ +745, /* Looooooooong comment */ +746, /* Looooooooong comment */ +747, /* Looooooooong comment */ +748, /* Looooooooong comment */ +749, /* Looooooooong comment */ +750, /* Looooooooong comment */ +751, /* Looooooooong comment */ +752, /* Looooooooong comment */ +753, /* Looooooooong comment */ +754, /* Looooooooong comment */ +755, /* Looooooooong comment */ +756, /* Looooooooong comment */ +757, /* Looooooooong comment */ +758, /* Looooooooong comment */ +759, /* Looooooooong comment */ +760, /* Looooooooong comment */ +761, /* Looooooooong comment */ +762, /* Looooooooong comment */ +763, /* Looooooooong comment */ +764, /* Looooooooong comment */ +765, /* Looooooooong comment */ +766, /* Looooooooong comment */ +767, /* Looooooooong comment */ +768, /* Looooooooong comment */ +769, /* Looooooooong comment */ +770, /* Looooooooong comment */ +771, /* Looooooooong comment */ +772, /* Looooooooong comment */ +773, /* Looooooooong comment */ +774, /* Looooooooong comment */ +775, /* Looooooooong comment */ +776, /* Looooooooong comment */ +777, /* Looooooooong comment */ +778, /* Looooooooong comment */ +779, /* Looooooooong comment */ +780, /* Looooooooong comment */ +781, /* Looooooooong comment */ +782, /* Looooooooong comment */ +783, /* Looooooooong comment */ +784, /* Looooooooong comment */ +785, /* Looooooooong comment */ +786, /* Looooooooong comment */ +786, /* Looooooooong comment */ +788, /* Looooooooong comment */ +789, /* Looooooooong comment */ +790, /* Looooooooong comment */ +791, /* Looooooooong comment */ +792, /* Looooooooong comment */ +793, /* Looooooooong comment */ +794, /* Looooooooong comment */ +795, /* Looooooooong comment */ +796, /* Looooooooong comment */ +797, /* Looooooooong comment */ +798, /* Looooooooong comment */ +799, /* Looooooooong comment */ +800, /* Looooooooong comment */ +801, /* Looooooooong comment */ +802, /* Looooooooong comment */ +803, /* Looooooooong comment */ +804, /* Looooooooong comment */ +805, /* Looooooooong comment */ +806, /* Looooooooong comment */ +807, /* Looooooooong comment */ +808, /* Looooooooong comment */ +809, /* Looooooooong comment */ +810, /* Looooooooong comment */ +811, /* Looooooooong comment */ +812, /* Looooooooong comment */ +813, /* Looooooooong comment */ +814, /* Looooooooong comment */ +815, /* Looooooooong comment */ +816, /* Looooooooong comment */ +817, /* Looooooooong comment */ +818, /* Looooooooong comment */ +819, /* Looooooooong comment */ +820, /* Looooooooong comment */ +821, /* Looooooooong comment */ +822, /* Looooooooong comment */ +823, /* Looooooooong comment */ +824, /* Looooooooong comment */ +825, /* Looooooooong comment */ +826, /* Looooooooong comment */ +827, /* Looooooooong comment */ +828, /* Looooooooong comment */ +829, /* Looooooooong comment */ +830, /* Looooooooong comment */ +831, /* Looooooooong comment */ +832, /* Looooooooong comment */ +833, /* Looooooooong comment */ +834, /* Looooooooong comment */ +835, /* Looooooooong comment */ +836, /* Looooooooong comment */ +837, /* Looooooooong comment */ +838, /* Looooooooong comment */ +839, /* Looooooooong comment */ +840, /* Looooooooong comment */ +841, /* Looooooooong comment */ +842, /* Looooooooong comment */ +843, /* Looooooooong comment */ +844, /* Looooooooong comment */ +845, /* Looooooooong comment */ +846, /* Looooooooong comment */ +847, /* Looooooooong comment */ +848, /* Looooooooong comment */ +849, /* Looooooooong comment */ +850, /* Looooooooong comment */ +851, /* Looooooooong comment */ +852, /* Looooooooong comment */ +853, /* Looooooooong comment */ +854, /* Looooooooong comment */ +855, /* Looooooooong comment */ +856, /* Looooooooong comment */ +857, /* Looooooooong comment */ +858, /* Looooooooong comment */ +859, /* Looooooooong comment */ +860, /* Looooooooong comment */ +861, /* Looooooooong comment */ +862, /* Looooooooong comment */ +863, /* Looooooooong comment */ +864, /* Looooooooong comment */ +865, /* Looooooooong comment */ +866, /* Looooooooong comment */ +867, /* Looooooooong comment */ +868, /* Looooooooong comment */ +869, /* Looooooooong comment */ +870, /* Looooooooong comment */ +871, /* Looooooooong comment */ +872, /* Looooooooong comment */ +873, /* Looooooooong comment */ +874, /* Looooooooong comment */ +875, /* Looooooooong comment */ +876, /* Looooooooong comment */ +877, /* Looooooooong comment */ +878, /* Looooooooong comment */ +879, /* Looooooooong comment */ +880, /* Looooooooong comment */ +881, /* Looooooooong comment */ +882, /* Looooooooong comment */ +883, /* Looooooooong comment */ +884, /* Looooooooong comment */ +885, /* Looooooooong comment */ +886, /* Looooooooong comment */ +886, /* Looooooooong comment */ +888, /* Looooooooong comment */ +889, /* Looooooooong comment */ +890, /* Looooooooong comment */ +891, /* Looooooooong comment */ +892, /* Looooooooong comment */ +893, /* Looooooooong comment */ +894, /* Looooooooong comment */ +895, /* Looooooooong comment */ +896, /* Looooooooong comment */ +897, /* Looooooooong comment */ +898, /* Looooooooong comment */ +899, /* Looooooooong comment */ +900, /* Looooooooong comment */ +901, /* Looooooooong comment */ +902, /* Looooooooong comment */ +903, /* Looooooooong comment */ +904, /* Looooooooong comment */ +905, /* Looooooooong comment */ +906, /* Looooooooong comment */ +907, /* Looooooooong comment */ +908, /* Looooooooong comment */ +909, /* Looooooooong comment */ +910, /* Looooooooong comment */ +911, /* Looooooooong comment */ +912, /* Looooooooong comment */ +913, /* Looooooooong comment */ +914, /* Looooooooong comment */ +915, /* Looooooooong comment */ +916, /* Looooooooong comment */ +917, /* Looooooooong comment */ +918, /* Looooooooong comment */ +919, /* Looooooooong comment */ +920, /* Looooooooong comment */ +921, /* Looooooooong comment */ +922, /* Looooooooong comment */ +923, /* Looooooooong comment */ +924, /* Looooooooong comment */ +925, /* Looooooooong comment */ +926, /* Looooooooong comment */ +927, /* Looooooooong comment */ +928, /* Looooooooong comment */ +929, /* Looooooooong comment */ +930, /* Looooooooong comment */ +931, /* Looooooooong comment */ +932, /* Looooooooong comment */ +933, /* Looooooooong comment */ +934, /* Looooooooong comment */ +935, /* Looooooooong comment */ +936, /* Looooooooong comment */ +937, /* Looooooooong comment */ +938, /* Looooooooong comment */ +939, /* Looooooooong comment */ +940, /* Looooooooong comment */ +941, /* Looooooooong comment */ +942, /* Looooooooong comment */ +943, /* Looooooooong comment */ +944, /* Looooooooong comment */ +945, /* Looooooooong comment */ +946, /* Looooooooong comment */ +947, /* Looooooooong comment */ +948, /* Looooooooong comment */ +949, /* Looooooooong comment */ +950, /* Looooooooong comment */ +951, /* Looooooooong comment */ +952, /* Looooooooong comment */ +953, /* Looooooooong comment */ +954, /* Looooooooong comment */ +955, /* Looooooooong comment */ +956, /* Looooooooong comment */ +957, /* Looooooooong comment */ +958, /* Looooooooong comment */ +959, /* Looooooooong comment */ +960, /* Looooooooong comment */ +961, /* Looooooooong comment */ +962, /* Looooooooong comment */ +963, /* Looooooooong comment */ +964, /* Looooooooong comment */ +965, /* Looooooooong comment */ +966, /* Looooooooong comment */ +967, /* Looooooooong comment */ +968, /* Looooooooong comment */ +969, /* Looooooooong comment */ +970, /* Looooooooong comment */ +971, /* Looooooooong comment */ +972, /* Looooooooong comment */ +973, /* Looooooooong comment */ +974, /* Looooooooong comment */ +975, /* Looooooooong comment */ +976, /* Looooooooong comment */ +977, /* Looooooooong comment */ +978, /* Looooooooong comment */ +979, /* Looooooooong comment */ +980, /* Looooooooong comment */ +981, /* Looooooooong comment */ +982, /* Looooooooong comment */ +983, /* Looooooooong comment */ +984, /* Looooooooong comment */ +985, /* Looooooooong comment */ +986, /* Looooooooong comment */ +986, /* Looooooooong comment */ +988, /* Looooooooong comment */ +989, /* Looooooooong comment */ +990, /* Looooooooong comment */ +991, /* Looooooooong comment */ +992, /* Looooooooong comment */ +993, /* Looooooooong comment */ +994, /* Looooooooong comment */ +995, /* Looooooooong comment */ +996, /* Looooooooong comment */ +997, /* Looooooooong comment */ +998, /* Looooooooong comment */ +999, /* Looooooooong comment */ +1000 +FROM RDB$DATABASE;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT +============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ ============ + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 86 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 186 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 286 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 386 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 486 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 586 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 686 688 689 690 691 692 693 694 695 696 697 698 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 786 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 886 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 986 988 989 990 991 992 993 994 995 996 997 998 999 1000 + +""" + +@pytest.mark.version('>=2.1') +def test_core_1196_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1213.py b/tests/bugs/test_core_1213.py new file mode 100644 index 00000000..aeb47a29 --- /dev/null +++ b/tests/bugs/test_core_1213.py @@ -0,0 +1,68 @@ +#coding:utf-8 +# +# id: bugs.core_1213 +# title: CURRENT OF support views +# decription: +# tracker_id: CORE-1213 +# min_versions: [] +# versions: 2.1.0 +# qmid: bugs.core_1213 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE TAB1 (COL1 INTEGER); +CREATE VIEW V1 (COL1) AS SELECT COL1 FROM TAB1; +COMMIT; +INSERT INTO TAB1 (COL1) VALUES (1); +INSERT INTO TAB1 (COL1) VALUES (2); +INSERT INTO TAB1 (COL1) VALUES (3); +COMMIT; +SET TERM ^ ; +CREATE PROCEDURE P1 AS +DECLARE vCOL1 INTEGER; +BEGIN +FOR SELECT COL1 FROM V1 WHERE COL1 IN (2,3) INTO :vCOL1 AS CURSOR VIEW_CURSOR DO + BEGIN + DELETE FROM V1 WHERE CURRENT OF VIEW_CURSOR; + END +END ^ +COMMIT ^ + + +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT COL1 FROM V1; +EXECUTE PROCEDURE P1; +SELECT COL1 FROM V1; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + COL1 +============ + 1 + 2 + 3 + + + COL1 +============ + 1 + +""" + +@pytest.mark.version('>=2.1.0') +def test_core_1213_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1215.py b/tests/bugs/test_core_1215.py new file mode 100644 index 00000000..0d9615d5 --- /dev/null +++ b/tests/bugs/test_core_1215.py @@ -0,0 +1,83 @@ +#coding:utf-8 +# +# id: bugs.core_1215 +# title: Wrong SELECT query results using index to evaluate >= condition +# decription: +# tracker_id: CORE-1215 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_1215 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE T (ID INT); +COMMIT; + +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^ + +set term ;^ +commit; + +CREATE INDEX IDX_T ON T (ID); +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """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 + +""" + +@pytest.mark.version('>=3.0') +def test_core_1215_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1227.py b/tests/bugs/test_core_1227.py new file mode 100644 index 00000000..35005e2c --- /dev/null +++ b/tests/bugs/test_core_1227.py @@ -0,0 +1,56 @@ +#coding:utf-8 +# +# id: bugs.core_1227 +# title: LIST() function seems not work if used twice or more in a query +# decription: f I try to use the LIST() function twice or more in a query the following error occurs: +# +# Undefined name. +# Dynamic SQL Error. +# SQL error code = -204. +# Implementation limit exceeded. +# Block size exceeds implementation restriction. +# tracker_id: CORE-1227 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_1227 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE TESTTABLE (ID integer, FIELD1 char(5), FIELD2 char(20)); +INSERT INTO TESTTABLE VALUES (1,'aaaaa','bbbbbbbbb'); +INSERT INTO TESTTABLE VALUES (1,'ccccc','ddddddddd'); +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT LIST(FIELD1), LIST(FIELD2) FROM TESTTABLE GROUP BY ID; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ LIST LIST +================= ================= + 0:1 0:2 +============================================================================== +LIST: +aaaaa,ccccc +============================================================================== +============================================================================== +LIST: +bbbbbbbbb ,ddddddddd +============================================================================== + +""" + +@pytest.mark.version('>=3.0') +def test_core_1227_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1244.py b/tests/bugs/test_core_1244.py new file mode 100644 index 00000000..8692aaaa --- /dev/null +++ b/tests/bugs/test_core_1244.py @@ -0,0 +1,57 @@ +#coding:utf-8 +# +# id: bugs.core_1244 +# title: Server crash on select * from +# decription: Simple select from recursive CTE crashes the server when query uses asterisk. +# tracker_id: CORE-1244 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1244 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE ARTICLES (ARTICLEID integer, PARENTID integer); +COMMIT; +INSERT INTO ARTICLES VALUES (1,NULL); +INSERT INTO ARTICLES VALUES (2,1); +COMMIT;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """with recursive + Art_Tree as ( + select A.ArticleID + from Articles A + where A.ParentID is NULL + +union all + +select A.ArticleID + from Articles A + join Art_Tree T on (A.ParentID=T.ArticleID) + ) +select * + from Art_Tree; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ARTICLEID +============ + 1 + 2 + +""" + +@pytest.mark.version('>=2.1') +def test_core_1244_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1245.py b/tests/bugs/test_core_1245.py new file mode 100644 index 00000000..488237ef --- /dev/null +++ b/tests/bugs/test_core_1245.py @@ -0,0 +1,58 @@ +#coding:utf-8 +# +# id: bugs.core_1245 +# title: Incorrect column values with outer joins and views +# decription: +# tracker_id: CORE-1245 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE T1 (N INTEGER); +CREATE TABLE T2 (N INTEGER); +CREATE VIEW V (N1, N2, N3) AS + select t1.n, t2.n, 3 + from t1 + full join t2 + on (t1.n = t2.n) +; + +insert into t1 values (1); +insert into t1 values (2); +insert into t2 values (2); +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select rdb$relation_id, v.rdb$db_key, v.* + from rdb$database + full outer join v + on (1 = 0) + ; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +RDB$RELATION_ID DB_KEY N1 N2 N3 +=============== ================================ ============ ============ ============ + 81000000010000008000000002000000 2 2 3 + 00000000000000008000000001000000 1 3 + 131 + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_1245_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1246.py b/tests/bugs/test_core_1246.py new file mode 100644 index 00000000..5dad7fa0 --- /dev/null +++ b/tests/bugs/test_core_1246.py @@ -0,0 +1,52 @@ +#coding:utf-8 +# +# id: bugs.core_1246 +# title: Incorrect column values with outer joins and derived tables +# decription: +# tracker_id: CORE-1246 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE T1 (N INTEGER); +CREATE TABLE T2 (N INTEGER); + +insert into t1 values (1); +insert into t1 values (2); +insert into t2 values (2); +commit;""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select * + from (select 1 n from rdb$database) t1 + full join (select 2 n from rdb$database) t2 + on (t2.n = t1.n) +; + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + N N +============ ============ + 2 + 1 + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_1246_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1248.py b/tests/bugs/test_core_1248.py new file mode 100644 index 00000000..019c1865 --- /dev/null +++ b/tests/bugs/test_core_1248.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: bugs.core_1248 +# title: Incorrect timestamp arithmetic when one of operands is negative number +# decription: +# tracker_id: CORE-1248 +# min_versions: ['3.0.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + select cast('04.05.2007' as timestamp) - (-7) from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 2007-05-11 00:00:00.0000 + """ + +@pytest.mark.version('>=3.0') +def test_core_1248_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1249.py b/tests/bugs/test_core_1249.py new file mode 100644 index 00000000..ce033bc7 --- /dev/null +++ b/tests/bugs/test_core_1249.py @@ -0,0 +1,66 @@ +#coding:utf-8 +# +# id: bugs.core_1249 +# title: Full shutdown mode doesn't work on Classic if there are other connections to the database +# decription: This bug affects only Windows CS, but we'll test all platforms and architectures anyway. +# tracker_id: CORE-1249 +# min_versions: [] +# versions: 2.0.2 +# qmid: bugs.core_1249 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# cur1 = db_conn.cursor() +# #cur1.execute('select 1 from rdb$database') +# runProgram('gfix',[dsn,'-user',user_name,'-pas',user_password,'-shut','full','-force','0']) +# +# try: +# cur1.execute('select 1 from rdb$database') +# print ('BUG! Operation allowed after shutdown!') +# except Exception, e: +# print("OK: operation not allowed.") +# print( ' '.join( ( 'Exception', ('DOES' if 'shutdown' in e[0] else 'does NOT'), 'contain text about shutdown.') ) ) +# if 'shutdown' not in e[0]: +# print(e[0]) +# +# # Error while starting transaction: +# # - SQLCODE: -902 +# # - connection shutdown +# # - Database is shutdown. <<<<<<<<<<<<<<<<<<<< NEW message in 4.0 +# # +# # Following messages can appear now after 'connection shutdown' (letter from dimitr, 08-may-2017 20:41): +# # isc_att_shut_killed: Killed by database administrator +# # isc_att_shut_idle: Idle timeout expired +# # isc_att_shut_db_down: Database is shutdown +# # isc_att_shut_engine: Engine is shutdown +# +# runProgram('gfix',[dsn,'-user',user_name,'-pas',user_password,'-online']) +# +# # 'substitutions': [('^.*shutdown','shutdown')] +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + OK: operation not allowed. + Exception DOES contain text about shutdown. + """ + +@pytest.mark.version('>=2.0.2') +@pytest.mark.xfail +def test_core_1249_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_1253.py b/tests/bugs/test_core_1253.py new file mode 100644 index 00000000..3d8ad272 --- /dev/null +++ b/tests/bugs/test_core_1253.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: bugs.core_1253 +# title: LIST(DISTINCT) concatenate VARCHAR values as CHAR +# decription: +# tracker_id: CORE-1253 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1253 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE T1 (C1 varchar(5)); +COMMIT; +INSERT INTO T1 VALUES ('1'); +INSERT INTO T1 VALUES ('2'); +COMMIT;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select list(distinct c1) from t1; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """LIST +================= + 0:1 +============================================================================== +LIST: +1,2 +============================================================================== + +""" + +@pytest.mark.version('>=2.1') +def test_core_1253_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1254.py b/tests/bugs/test_core_1254.py new file mode 100644 index 00000000..8e92acbc --- /dev/null +++ b/tests/bugs/test_core_1254.py @@ -0,0 +1,62 @@ +#coding:utf-8 +# +# id: bugs.core_1254 +# title: Problem with DISTINCT and insensitive collations +# decription: +# tracker_id: CORE-1254 +# min_versions: ['2.5'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """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; + +""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT GROUP_ID, QUESTION, SUM(SCORE) FROM TEST GROUP BY 1,2; +SELECT DISTINCT GROUP_ID, QUESTION FROM TEST;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +GROUP_ID QUESTION SUM +======== ============ ===================== +a 1 2 +a 2 2 +a 3 2 + + +GROUP_ID QUESTION +======== ============ +a 1 +a 2 +a 3 + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_1254_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1255.py b/tests/bugs/test_core_1255.py new file mode 100644 index 00000000..e925783a --- /dev/null +++ b/tests/bugs/test_core_1255.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: bugs.core_1255 +# title: String truncation error when concatenating _UTF8 string onto extract(year result +# decription: The query +# +# SELECT ((EXTRACT(YEAR FROM CAST('2007-01-01' AS DATE)) || _UTF8'')) col FROM rdb$database GROUP BY 1; +# +# Produces the error +# Statement failed, SQLCODE = -802 +# arithmetic exception, numeric overflow, or string truncation +# tracker_id: CORE-1255 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_1255 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT ((EXTRACT(YEAR FROM CAST('2007-01-01' AS DATE)) || _UTF8'')) col FROM rdb$database GROUP BY 1; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """COL +====== +2007 + +""" + +@pytest.mark.version('>=3.0') +def test_core_1255_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1256.py b/tests/bugs/test_core_1256.py new file mode 100644 index 00000000..d8e5c052 --- /dev/null +++ b/tests/bugs/test_core_1256.py @@ -0,0 +1,66 @@ +#coding:utf-8 +# +# id: bugs.core_1256 +# title: Table columns hide destination variables of RETURNING INTO +# decription: +# tracker_id: CORE-1256 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1256 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t (n integer) ; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """set term ^; + +-- ok + +execute block returns (n integer) +as +begin + insert into t values (1) returning n into :n; + suspend; +end^ + +-- not ok + +execute block returns (n integer) +as +begin + insert into t values (1) returning n into n; + suspend; +end^ + +set term ;^ +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + N +============ + 1 + + + N +============ + 1 + +""" + +@pytest.mark.version('>=2.1') +def test_core_1256_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1263.py b/tests/bugs/test_core_1263.py new file mode 100644 index 00000000..df9bcd11 --- /dev/null +++ b/tests/bugs/test_core_1263.py @@ -0,0 +1,51 @@ +#coding:utf-8 +# +# id: bugs.core_1263 +# title: GSec incorrectly processes some switches +# decription: +# tracker_id: CORE-1263 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_1263 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!invalid switch specified).)*$', ''), ('invalid switch specified.*', 'invalid switch specified'), ('.*gsec is deprecated.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# commands = """add BADPARAM -pa PWD +# add BADPARAM -pas PWD +# add BADPARAM -password PWD +# add BADPARAM -user USR +# add BADPARAM -database DB +# add BADPARAM -trusted +# quit +# """ +# runProgram('gsec',['-user',user_name,'-pas',user_password],commands) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + GSEC> invalid switch specified in interactive mode + GSEC> invalid switch specified in interactive mode + GSEC> invalid switch specified in interactive mode + GSEC> invalid switch specified in interactive mode + GSEC> invalid switch specified in interactive mode + GSEC> invalid switch specified + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_1263_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_1267.py b/tests/bugs/test_core_1267.py new file mode 100644 index 00000000..d0fb49fa --- /dev/null +++ b/tests/bugs/test_core_1267.py @@ -0,0 +1,52 @@ +#coding:utf-8 +# +# id: bugs.core_1267 +# title: Small bug with default value for domains in PSQL +# decription: +# tracker_id: CORE-1267 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1267 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE DOMAIN BIT AS SMALLINT CHECK (VALUE IN (0,1) OR VALUE IS NULL); +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """set term ^; + +EXECUTE BLOCK +RETURNS ( + ID BIT) +AS +BEGIN + SUSPEND; +END ^ + +set term ;^ +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID +======= + + +""" + +@pytest.mark.version('>=2.1') +def test_core_1267_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1271.py b/tests/bugs/test_core_1271.py new file mode 100644 index 00000000..b64c2ac7 --- /dev/null +++ b/tests/bugs/test_core_1271.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: bugs.core_1271 +# title: Ceation of invalid procedures/triggers allowed +# decription: invalid procedures/triggers (with invalid plans, for example) was allowed to be created +# tracker_id: CORE-1271 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_1271-250 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create procedure p returns (out int) as + begin + for + select rdb$relation_id + from rdb$relations + plan (rdb$relations order rdb$index_1) + order by rdb$description + into :out + do + suspend; + end + ^ + commit^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 2F000 + Error while parsing procedure P's BLR + -index RDB$INDEX_1 cannot be used in the specified plan + """ + +@pytest.mark.version('>=3.0') +def test_core_1271_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_1274.py b/tests/bugs/test_core_1274.py new file mode 100644 index 00000000..598fcf1c --- /dev/null +++ b/tests/bugs/test_core_1274.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_1274 +# title: Wrong results when PLAN MERGE is chosen and datatypes of the equality predicate arguments are different +# decription: +# tracker_id: CORE-1274 +# min_versions: ['2.1.4'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t1 (col1 int); +create table t2 (col2 varchar(10)); +commit; + +insert into t1 values (100); +insert into t1 values (20); +insert into t1 values (3); +commit; + +insert into t2 values ('100'); +insert into t2 values ('20'); +insert into t2 values ('3'); +commit;""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """select * from t1 join t2 on col1 = col2 ORDER by 1 DESC; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + COL1 COL2 +============ ========== + 100 100 + 20 20 + 3 3 + +""" + +@pytest.mark.version('>=3.0') +def test_core_1274_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1286.py b/tests/bugs/test_core_1286.py new file mode 100644 index 00000000..3ed77926 --- /dev/null +++ b/tests/bugs/test_core_1286.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: bugs.core_1286 +# title: isql: zero divide + coredump when use "-pag 0" command switch & set heading on inside .sql script +# decription: +# tracker_id: CORE-1286 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: bugs.core_1286 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table test(id int); +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# script = """ +# set heading on; +# select 1 as r from rdb$fields rows 1; +# -- Crash of ISQL (not server) is reproduced when make connect by ISQL of WI-V2.5.1.26351. +# -- After ISQL crash firebird.log contains: INET/inet_error: read errno = 10054 +# """ +# runProgram('isql',[dsn,'-pag','0','-user',user_name,'-pas',user_password],script) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + R +============ + 1 +""" + +@pytest.mark.version('>=2.5.2') +@pytest.mark.xfail +def test_core_1286_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_1291.py b/tests/bugs/test_core_1291.py new file mode 100644 index 00000000..18ff7df4 --- /dev/null +++ b/tests/bugs/test_core_1291.py @@ -0,0 +1,263 @@ +#coding:utf-8 +# +# id: bugs.core_1291 +# title: Can't transliterate character set when look at procedure text in database just created from script (and thus in ODS 11.1) +# decription: +# tracker_id: CORE-1291 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1291 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [('Use CONNECT or CREATE DATABASE to specify a database', ''), ('SQL> ', ''), ('CON> ', '')] + +init_script_1 = """""" + +db_1 = db_factory(init=init_script_1) + +# test_script_1 +#--- +# import os +# +# script = """SET SQL DIALECT 3; +# +# SET NAMES WIN1251; +# +# CREATE DATABASE '%s' +# DEFAULT CHARACTER SET WIN1251; +# """ % dsn +# +# scriptfile = open(os.path.join(context['files_location'],'core_1291.sql'),'r') +# script = script + ''.join(scriptfile) +# scriptfile.close() +# +# runProgram('isql',['-user',user_name,'-pas',user_password],script) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Procedure text: +============================================================================= +DECLARE VARIABLE NDSDiv DOUBLE PRECISION; +DECLARE VARIABLE ID_ExportFieldDoc Integer; +begin + SELECT Val FROM TBL_Const_Float + WHERE Name='NDSDiv' + INTO :NDSDiv; + FOR SELECT id_exportfielddoc, accountcredit, accountdebit FROM tbl_exportentry + WHERE id_exportgroupentry=:id_group + INTO :id_exportfielddoc, :accountcredit, :accountdebit + DO BEGIN + IF ((AccountCredit<>0) or (AccountDebit<>0)) THEN BEGIN + IF (id_exportfielddoc=110) THEN BEGIN + SELECT SUM(A.PriceRub*B.Volume/A.PointMul), SUM(A.PriceDoc*B.Volume/A.PointMul) FROM TBL_INDOC_TEMP A, + TBL_OUTDOC_TEMP B, + TBL_ITEMSALE C, + TBL_INDOC D + WHERE b.id_outdoc=:id_outdoc and b.id_itemsale=c.id_itemsale and c.id_firstindoc_temp=a.id_indoc_temp and + d.id_indoc=a.id_indoc and d.doctype = 6 + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=111) THEN BEGIN + SELECT SUM(A.PriceCalcRub*B.Volume/A.PointMul), SUM(A.PriceCalcDoc*B.Volume/A.PointMul) FROM TBL_INDOC_TEMP A, + TBL_OUTDOC_TEMP B, + TBL_ITEMSALE C, + TBL_INDOC D + WHERE b.id_outdoc=:id_outdoc and b.id_itemsale=c.id_itemsale and c.id_firstindoc_temp=a.id_indoc_temp and + d.id_indoc=a.id_indoc and d.doctype = 6 + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=112) THEN BEGIN + SELECT SUM(A.SummDoc), SUM(A.SummDoc) FROM TBL_OUTDOC_TEMP A, + TBL_ITEMSALE B, + TBL_INDOC_TEMP C, + TBL_INDOC D + WHERE A.ID_OUTDOC=:id_outdoc and b.id_itemsale=a.id_itemsale and c.id_indoc_temp=b.id_firstindoc_temp and + d.id_indoc=c.id_indoc and d.doctype = 6 + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=113) THEN BEGIN + SELECT SUM(A.NDS*A.PriceRub*B.Volume/(A.PointMul*100)), SUM(A.NDS*A.PriceDoc*B.Volume/(A.PointMul*100)) FROM TBL_INDOC_TEMP A, + TBL_OUTDOC_TEMP B, + TBL_ITEMSALE C, + TBL_INDOC D + WHERE b.id_outdoc=:id_outdoc and b.id_itemsale=c.id_itemsale and c.id_firstindoc_temp=a.id_indoc_temp and + d.id_indoc=a.id_indoc and d.doctype = 6 + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=114) THEN BEGIN + SELECT SUM(A.NDS*A.PriceCalcRub*B.Volume/(A.PointMul*100)), SUM(A.NDS*A.PriceCalcDoc*B.Volume/(A.PointMul*100)) FROM TBL_INDOC_TEMP A, + TBL_OUTDOC_TEMP B, + TBL_ITEMSALE C, + TBL_INDOC D + WHERE b.id_outdoc=:id_outdoc and b.id_itemsale=c.id_itemsale and c.id_firstindoc_temp=a.id_indoc_temp and + d.id_indoc=a.id_indoc and d.doctype = 6 + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=115) THEN BEGIN + SELECT SUM(A.SummNDSDoc), SUM(A.SummNDSDoc) FROM TBL_OUTDOC_TEMP A, + TBL_ITEMSALE B, + TBL_INDOC_TEMP C, + TBL_INDOC D + WHERE A.ID_OUTDOC=:id_outdoc and b.id_itemsale=a.id_itemsale and c.id_indoc_temp=b.id_firstindoc_temp and + d.id_indoc=c.id_indoc and d.doctype = 6 + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=116) THEN BEGIN + SELECT SUM((A.PriceRub*B.Volume/A.PointMul)*(1+A.NDS/100)), SUM((A.PriceDoc*B.Volume/A.PointMul)*(1+A.NDS/100)) FROM TBL_INDOC_TEMP A, + TBL_OUTDOC_TEMP B, + TBL_ITEMSALE C, + TBL_INDOC D + WHERE b.id_outdoc=:id_outdoc and b.id_itemsale=c.id_itemsale and c.id_firstindoc_temp=a.id_indoc_temp and + d.id_indoc=a.id_indoc and d.doctype = 6 + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=117) THEN BEGIN + SELECT SUM((A.PriceCalcRub*B.Volume/A.PointMul)*(1+A.NDS/100)), SUM((A.PriceCalcDoc*B.Volume/A.PointMul)*(1+A.NDS/100)) FROM TBL_INDOC_TEMP A, + TBL_OUTDOC_TEMP B, + TBL_ITEMSALE C, + TBL_INDOC D + WHERE b.id_outdoc=:id_outdoc and b.id_itemsale=c.id_itemsale and c.id_firstindoc_temp=a.id_indoc_temp and + d.id_indoc=a.id_indoc and d.doctype = 6 + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=118) THEN BEGIN + SELECT SUM(A.SummWithNDSDoc), SUM(A.SummWithNDSDoc) FROM TBL_OUTDOC_TEMP A, + TBL_ITEMSALE B, + TBL_INDOC_TEMP C, + TBL_INDOC D + WHERE A.ID_OUTDOC=:id_outdoc and b.id_itemsale=a.id_itemsale and c.id_indoc_temp=b.id_firstindoc_temp and + d.id_indoc=c.id_indoc and d.doctype = 6 + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=119) THEN BEGIN + SELECT SUM((A.PriceCalcRub-A.PriceRub)*B.Volume/A.PointMul), SUM((A.PriceCalcDoc-A.PriceDoc)*B.Volume/A.PointMul) FROM TBL_INDOC_TEMP A, + TBL_OUTDOC_TEMP B, + TBL_ITEMSALE C, + TBL_INDOC D + WHERE b.id_outdoc=:id_outdoc and b.id_itemsale=c.id_itemsale and c.id_firstindoc_temp=a.id_indoc_temp and + d.id_indoc=a.id_indoc and d.doctype = 6 + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=120) THEN BEGIN + SELECT SUM(B.SummDoc-(A.PriceRub*B.Volume/A.PointMul)), SUM(B.SummDoc-(A.PriceDoc*B.Volume/A.PointMul)) FROM TBL_INDOC_TEMP A, + TBL_OUTDOC_TEMP B, + TBL_ITEMSALE C, + TBL_INDOC D + WHERE b.id_outdoc=:id_outdoc and b.id_itemsale=c.id_itemsale and c.id_firstindoc_temp=a.id_indoc_temp and + d.id_indoc=a.id_indoc and d.doctype = 6 + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=121) THEN BEGIN + SELECT SUM(A.NDS*(A.PriceCalcRub-A.PriceRub)*B.Volume/(A.PointMul*100)), SUM(A.NDS*(A.PriceCalcDoc-A.PriceDoc)*B.Volume/(A.PointMul*100)) FROM TBL_INDOC_TEMP A, + TBL_OUTDOC_TEMP B, + TBL_ITEMSALE C, + TBL_INDOC D + WHERE b.id_outdoc=:id_outdoc and b.id_itemsale=c.id_itemsale and c.id_firstindoc_temp=a.id_indoc_temp and + d.id_indoc=a.id_indoc and d.doctype = 6 + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=122) THEN BEGIN + SELECT SUM(B.SummNDSDoc-A.NDS*A.PriceRub*B.Volume/(A.PointMul*100)), SUM(B.SummNDSDoc-A.NDS*A.PriceDoc*B.Volume/(A.PointMul*100)) FROM TBL_INDOC_TEMP A, + TBL_OUTDOC_TEMP B, + TBL_ITEMSALE C, + TBL_INDOC D + WHERE b.id_outdoc=:id_outdoc and b.id_itemsale=c.id_itemsale and c.id_firstindoc_temp=a.id_indoc_temp and + d.id_indoc=a.id_indoc and d.doctype = 6 + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=123) THEN BEGIN + SELECT SUM(((A.PriceCalcRub-A.PriceRub)*B.Volume/A.PointMul)*(1+A.NDS/100)), SUM(((A.PriceCalcDoc-A.PriceDoc)*B.Volume/A.PointMul)*(1+A.NDS/100)) FROM TBL_INDOC_TEMP A, + TBL_OUTDOC_TEMP B, + TBL_ITEMSALE C, + TBL_INDOC D + WHERE b.id_outdoc=:id_outdoc and b.id_itemsale=c.id_itemsale and c.id_firstindoc_temp=a.id_indoc_temp and + d.id_indoc=a.id_indoc and d.doctype = 6 + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=124) THEN BEGIN + SELECT SUM(B.SummWithNDSDoc-(A.PriceRub*B.Volume/A.PointMul)*(1+A.NDS/100)), SUM(B.SummWithNDSDoc-(A.PriceDoc*B.Volume/A.PointMul)*(1+A.NDS/100)) FROM TBL_INDOC_TEMP A, + TBL_OUTDOC_TEMP B, + TBL_ITEMSALE C, + TBL_INDOC D + WHERE b.id_outdoc=:id_outdoc and b.id_itemsale=c.id_itemsale and c.id_firstindoc_temp=a.id_indoc_temp and + d.id_indoc=a.id_indoc and d.doctype = 6 + INTO :summrus, :summdoc; + END + + IF (id_exportfielddoc=125) THEN BEGIN + SELECT SUM(A.PriceRub*B.Volume/A.PointMul), SUM(A.PriceDoc*B.Volume/A.PointMul) FROM TBL_INDOC_TEMP A, + TBL_OUTDOC_TEMP B, + TBL_ITEMSALE C, + TBL_INDOC D + WHERE b.id_outdoc=:id_outdoc and b.id_itemsale=c.id_itemsale and c.id_firstindoc_temp=a.id_indoc_temp and + d.id_indoc=a.id_indoc and d.doctype = 6 and b.nds=0 + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=126) THEN BEGIN + SELECT SUM(A.PriceCalcRub*B.Volume/A.PointMul), SUM(A.PriceCalcDoc*B.Volume/A.PointMul) FROM TBL_INDOC_TEMP A, + TBL_OUTDOC_TEMP B, + TBL_ITEMSALE C, + TBL_INDOC D + WHERE b.id_outdoc=:id_outdoc and b.id_itemsale=c.id_itemsale and c.id_firstindoc_temp=a.id_indoc_temp and + d.id_indoc=a.id_indoc and d.doctype = 6 and b.nds=0 + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=127) THEN BEGIN + SELECT SUM(A.SummDoc), SUM(A.SummDoc) FROM TBL_OUTDOC_TEMP A, + TBL_ITEMSALE B, + TBL_INDOC_TEMP C, + TBL_INDOC D + WHERE A.ID_OUTDOC=:id_outdoc and b.id_itemsale=a.id_itemsale and c.id_indoc_temp=b.id_firstindoc_temp and + d.id_indoc=c.id_indoc and d.doctype = 6 and a.nds=0 + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=128) THEN BEGIN + SELECT SUM((A.PriceCalcRub-A.PriceRub)*B.Volume/A.PointMul), SUM((A.PriceCalcDoc-A.PriceDoc)*B.Volume/A.PointMul) FROM TBL_INDOC_TEMP A, + TBL_OUTDOC_TEMP B, + TBL_ITEMSALE C, + TBL_INDOC D + WHERE b.id_outdoc=:id_outdoc and b.id_itemsale=c.id_itemsale and c.id_firstindoc_temp=a.id_indoc_temp and + d.id_indoc=a.id_indoc and d.doctype = 6 and b.nds=0 + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=129) THEN BEGIN + SELECT SUM(B.SummDoc-(A.PriceRub*B.Volume/A.PointMul)), SUM(B.SummDoc-(A.PriceDoc*B.Volume/A.PointMul)) FROM TBL_INDOC_TEMP A, + TBL_OUTDOC_TEMP B, + TBL_ITEMSALE C, + TBL_INDOC D + WHERE b.id_outdoc=:id_outdoc and b.id_itemsale=c.id_itemsale and c.id_firstindoc_temp=a.id_indoc_temp and + d.id_indoc=a.id_indoc and d.doctype = 6 and b.nds=0 + INTO :summrus, :summdoc; + END + IF ((id_exportfielddoc>129)and(id_exportfielddoc<145)) THEN BEGIN + execute procedure prc_expsumm_8_10 ( id_exportfielddoc, id_outdoc, NDSDiv ) returning_values( summrus, summdoc ); + END + IF ((id_exportfielddoc>144)and(id_exportfielddoc<160)) THEN BEGIN + execute procedure prc_expsumm_8_20 ( id_exportfielddoc, id_outdoc, NDSDiv ) returning_values( summrus, summdoc ); + END + IF ((SummRus>0) or (SummDoc>0)) THEN SUSPEND; + END + END +END +============================================================================= +Parameters: +ID_INDOC INPUT INTEGER +ID_OUTDOC INPUT INTEGER +ID_GROUP INPUT INTEGER +ACCOUNTCREDIT OUTPUT INTEGER +ACCOUNTDEBIT OUTPUT INTEGER +SUMMRUS OUTPUT DOUBLE PRECISION +SUMMDOC OUTPUT DOUBLE PRECISION +""" + +@pytest.mark.version('>=2.1') +@pytest.mark.xfail +def test_core_1291_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_1292.py b/tests/bugs/test_core_1292.py new file mode 100644 index 00000000..c9041df4 --- /dev/null +++ b/tests/bugs/test_core_1292.py @@ -0,0 +1,104 @@ +#coding:utf-8 +# +# id: bugs.core_1292 +# title: Can't create table using long username and UTF8 as attachment charset +# decription: +# Checked on: 4.0.0.1635 SS/CS; 3.0.5.33180 SS/CS; 2.5.9.27119 SC/SS +# +# tracker_id: CORE-1292 +# min_versions: [] +# versions: 2.5 +# qmid: bugs.core_1292 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('PRIV_LIST.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + 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 ( + select + p.rdb$user usr_name + ,p.rdb$grantor grantor + ,p.rdb$grant_option can_grant + ,p.rdb$relation_name tab_name + ,p.rdb$user_type usr_type + ,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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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('>=2.5') +def test_core_1292_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1295.py b/tests/bugs/test_core_1295.py new file mode 100644 index 00000000..7f5f9b2d --- /dev/null +++ b/tests/bugs/test_core_1295.py @@ -0,0 +1,38 @@ +#coding:utf-8 +# +# id: bugs.core_1295 +# title: Bad optimization of queries with DB_KEY +# decription: +# tracker_id: CORE-1295 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (RDB$RELATIONS INDEX ()) +PLAN (RDB$RELATIONS INDEX ()) +""" + +@pytest.mark.version('>=2.5.3') +def test_core_1295_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1306.py b/tests/bugs/test_core_1306.py new file mode 100644 index 00000000..cba0818f --- /dev/null +++ b/tests/bugs/test_core_1306.py @@ -0,0 +1,59 @@ +#coding:utf-8 +# +# id: bugs.core_1306 +# title: Indices not used for views +# decription: +# tracker_id: CORE-1306 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_1306 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """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_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """set plan on; + +SELECT * FROM "TABLE" WHERE ID = 1 +UNION ALL +SELECT * FROM "VIEW" WHERE ID = 1 ; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +PLAN (TABLE INDEX (RDB$PRIMARY1), VIEW TABLE INDEX (RDB$PRIMARY1)) + + ID +============ + 1 + 1 + +""" + +@pytest.mark.version('>=3.0') +def test_core_1306_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1312.py b/tests/bugs/test_core_1312.py new file mode 100644 index 00000000..f285cfbc --- /dev/null +++ b/tests/bugs/test_core_1312.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: bugs.core_1312 +# title: A remote attacker can check, if a file is present in the system, running firebird server +# decription: Check if password validation is done as soon as possible +# tracker_id: CORE-1312 +# min_versions: [] +# versions: 2.5.0 +# qmid: bugs.core_1312-250 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + commit; + connect 'localhost:bla' user 'qqq' password 'zzz'; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 28000 +Your user name and password are not defined. Ask your database administrator to set up a Firebird login. +""" + +@pytest.mark.version('>=2.5.0') +def test_core_1312_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_1313.py b/tests/bugs/test_core_1313.py new file mode 100644 index 00000000..33be3a60 --- /dev/null +++ b/tests/bugs/test_core_1313.py @@ -0,0 +1,64 @@ +#coding:utf-8 +# +# id: bugs.core_1313 +# title: RDB$DB_KEY not supported in derived tables and merge command +# decription: +# tracker_id: CORE-1313 +# min_versions: [] +# versions: 2.5 +# qmid: bugs.core_1313 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table t (c1 integer); + commit; + + insert into t values (1); + insert into t values (2); + insert into t values (3); + + commit; + + select 'point-1' msg, t1.* + from t t1 + right join (select t.rdb$db_key as dbkey from t) t2 on t2.dbkey = t1.rdb$db_key; + + merge into t t1 + using (select t.rdb$db_key as dbkey from t) t2 + on t2.dbkey = t1.rdb$db_key + when not matched then insert values (null); + + select 'point-2' msg, t.* from t; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG C1 + point-1 1 + point-1 2 + point-1 3 + + MSG C1 + point-2 1 + point-2 2 + point-2 3 + """ + +@pytest.mark.version('>=2.5') +def test_core_1313_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1315.py b/tests/bugs/test_core_1315.py new file mode 100644 index 00000000..d9e16a3e --- /dev/null +++ b/tests/bugs/test_core_1315.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: bugs.core_1315 +# title: Data type unknown +# decription: +# tracker_id: CORE-1315 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1315 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# cur = db_conn.cursor() +# try: +# statement = cur.prep('select coalesce(?,1) from RDB$DATABASE') +# except Exception,e: +# print ('Failed!',e) +# else: +# cur.execute(statement,[2]) +# printData(cur) +# print() +# cur.execute(statement,[None]) +# printData(cur) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """COALESCE +----------- +2 + +COALESCE +----------- +1 +""" + +@pytest.mark.version('>=2.1') +@pytest.mark.xfail +def test_core_1315_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_1316.py b/tests/bugs/test_core_1316.py new file mode 100644 index 00000000..15174de6 --- /dev/null +++ b/tests/bugs/test_core_1316.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_1316 +# title: NOT NULL constraint for procedure parameters and variables +# decription: +# tracker_id: CORE-1316 +# min_versions: [] +# versions: 2.5 +# qmid: bugs.core_1316 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('line: \\d+, col: \\d+', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """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); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """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 +""" + +@pytest.mark.version('>=2.5') +def test_core_1316_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_1318.py b/tests/bugs/test_core_1318.py new file mode 100644 index 00000000..7548d176 --- /dev/null +++ b/tests/bugs/test_core_1318.py @@ -0,0 +1,84 @@ +#coding:utf-8 +# +# id: bugs.core_1318 +# title: Error "Identifier ... is too long using multiple (nested) derived tables +# decription: +# tracker_id: CORE-1318 +# min_versions: ['2.0.7'] +# versions: 2.0.7 +# qmid: bugs.core_1318 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select 0*count(*) cnt + from ( + select A1.ID + from( + select A2.ID from( + select A3.ID from( + select A4.ID from( + select A5.ID from( + select A6.ID from( + select A7.ID from( + select A8.ID from( + select A9.ID from( + select A10.ID from( + select rdb$relations.rdb$relation_id as id from rdb$relations where rdb$relations.rdb$relation_id = 1 + ) as A10 + union + select rdb$relations.rdb$relation_id as id from rdb$relations where rdb$relations.rdb$relation_id = 2 + ) as A9 + union + select rdb$relations.rdb$relation_id as id from rdb$relations where rdb$relations.rdb$relation_id = 3 + ) as A8 + union + select rdb$relations.rdb$relation_id as id from rdb$relations where rdb$relations.rdb$relation_id = 4 + ) as A7 + union + select rdb$relations.rdb$relation_id as id from rdb$relations where rdb$relations.rdb$relation_id = 5 + ) as A6 + union + select rdb$relations.rdb$relation_id as id from rdb$relations where rdb$relations.rdb$relation_id = 6 + ) as A5 + union + select rdb$relations.rdb$relation_id as id from rdb$relations where rdb$relations.rdb$relation_id = 7 + ) as A4 + union + select rdb$relations.rdb$relation_id as id from rdb$relations where rdb$relations.rdb$relation_id = 8 + ) as A3 + union + select rdb$relations.rdb$relation_id as id from rdb$relations where rdb$relations.rdb$relation_id = 9 + ) as A2 + union + select rdb$relations.rdb$relation_id as id from rdb$relations where rdb$relations.rdb$relation_id = 10 + ) as A1 + union + select rdb$relations.rdb$relation_id as id from rdb$relations where rdb$relations.rdb$relation_id = 11 + ) + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CNT 0 + """ + +@pytest.mark.version('>=2.0.7') +def test_core_1318_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1329.py b/tests/bugs/test_core_1329.py new file mode 100644 index 00000000..f885159c --- /dev/null +++ b/tests/bugs/test_core_1329.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: bugs.core_1329 +# title: size of alias name in a table +# decription: Bug with size of alias name in a table (but still minor that 31 characters) +# tracker_id: CORE-1329 +# min_versions: [] +# versions: 2.0.1 +# qmid: bugs.core_1329 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE TABLE BIG_TABLE_1234567890123 (COD INTEGER NOT NULL PRIMARY KEY); +COMMIT; +SELECT +BIG_TABLE_1234567890123.COD +FROM +BIG_TABLE_1234567890123 +JOIN (SELECT + BIG_TABLE_1234567890123.COD + FROM + BIG_TABLE_1234567890123) BIG_TABLE_1234567890123_ ON +BIG_TABLE_1234567890123.COD = BIG_TABLE_1234567890123_.COD; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.0.1') +def test_core_1329_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_1331.py b/tests/bugs/test_core_1331.py new file mode 100644 index 00000000..7353621a --- /dev/null +++ b/tests/bugs/test_core_1331.py @@ -0,0 +1,62 @@ +#coding:utf-8 +# +# id: bugs.core_1331 +# title: Charset transliterations don't work with EXECUTE STATEMENT +# decription: +# tracker_id: CORE-1331 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_1331 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core1331-25.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + select opis as direct_select from T1; + set term ^ ; + execute block returns ( execute_block_select varchar(100) ) as + BEGIN + for select opis from t1 + into :execute_block_select + do + SUSPEND; + END^ + + execute block returns ( execute_sttm_select varchar(100) ) as + BEGIN + for execute statement 'select opis from t1' + into :execute_sttm_select + do + SUSPEND; + END ^ + + set term ;^ +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DIRECT_SELECT ASCII + DIRECT_SELECT милан + EXECUTE_BLOCK_SELECT ASCII + EXECUTE_BLOCK_SELECT милан + EXECUTE_STTM_SELECT ASCII + EXECUTE_STTM_SELECT милан + """ + +@pytest.mark.version('>=3.0') +def test_core_1331_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1334.py b/tests/bugs/test_core_1334.py new file mode 100644 index 00000000..40b31121 --- /dev/null +++ b/tests/bugs/test_core_1334.py @@ -0,0 +1,52 @@ +#coding:utf-8 +# +# id: bugs.core_1334 +# title: Joins with NULL RDB$DB_KEY crash the server +# decription: +# tracker_id: CORE-1334 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1334 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t1 (id integer primary key); +create table t2 (id integer references t1); +COMMIT; +insert into t1 values (1); +insert into t1 values (2); +insert into t2 values (2); +COMMIT;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select * + from t1 + left join t2 + on (t2.id = t1.id) + left join t2 t3 + on (t3.rdb$db_key = t2.rdb$db_key); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID ID ID +============ ============ ============ + 1 + 2 2 2 + +""" + +@pytest.mark.version('>=2.1') +def test_core_1334_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1338.py b/tests/bugs/test_core_1338.py new file mode 100644 index 00000000..eead8053 --- /dev/null +++ b/tests/bugs/test_core_1338.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_1338 +# title: Problem with view , computed field and functions +# decription: +# tracker_id: CORE-1338 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1338 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """create table a (a numeric(15,15)); + +insert into a values(2); + +create view b(a) as select round(a,2) from a; + +select * from b; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A +===================== + 2.000000000000000 + +""" + +@pytest.mark.version('>=2.1') +def test_core_1338_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1343.py b/tests/bugs/test_core_1343.py new file mode 100644 index 00000000..aeb1d473 --- /dev/null +++ b/tests/bugs/test_core_1343.py @@ -0,0 +1,91 @@ +#coding:utf-8 +# +# id: bugs.core_1343 +# title: Bug with a simple case and a subquery +# decription: +# tracker_id: CORE-1343 +# min_versions: [] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """--works fine (searched case with a subquery) + +SELECT + CASE + WHEN (SELECT 'A' FROM RDB$DATABASE) = 'A' THEN + 'Y' + WHEN (SELECT 'A' FROM RDB$DATABASE) = 'B' THEN + 'B' + ELSE + 'N' + END +FROM RDB$DATABASE; + +--works fine (simple case without a subquery) +SELECT + CASE 'A' + WHEN 'A' THEN + 'Y' + WHEN 'B' THEN + 'N' + ELSE + 'U' + END +FROM RDB$DATABASE; + +--don't work (simple case with a subquery) +SELECT + CASE (SELECT 'A' FROM RDB$DATABASE) + WHEN 'A' THEN + 'Y' + WHEN 'B' THEN + 'N' + ELSE + 'U' + END +FROM RDB$DATABASE; + +/* +Invalid token. +invalid request BLR at offset 110. +context already in use (BLR error). +*/ +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +CASE +====== +Y + + +CASE +====== +Y + + +CASE +====== +Y + +""" + +@pytest.mark.version('>=2.5') +def test_core_1343_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1346.py b/tests/bugs/test_core_1346.py new file mode 100644 index 00000000..43554ff0 --- /dev/null +++ b/tests/bugs/test_core_1346.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: bugs.core_1346 +# title: lpad and rpad with two columns not working +# decription: +# tracker_id: CORE-1346 +# min_versions: [] +# versions: 2.1.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select lpad('xxx', 8, '0') one, lpad('yyy', 8, '0') two from rdb$database; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +ONE TWO +======== ======== +00000xxx 00000yyy + +""" + +@pytest.mark.version('>=2.1.4') +def test_core_1346_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1347.py b/tests/bugs/test_core_1347.py new file mode 100644 index 00000000..9208f1ce --- /dev/null +++ b/tests/bugs/test_core_1347.py @@ -0,0 +1,149 @@ +#coding:utf-8 +# +# id: bugs.core_1347 +# title: Unexpected "cannot transliterate" error +# decription: +# 05-mar-2021. Re-implemented in order to have ability to run this test on Linux. +# Test encodes to UTF8 all needed statements (SET NAMES; CONNECT; DDL and DML) and stores this text in .sql file. +# NOTE: 'SET NAMES' contain character set that must be used for reproducing problem (WIN1251 in this test). +# Then ISQL is launched in separate (child) process which performs all necessary actions (using required charset). +# Result will be redirected to log(s) which will be opened further via codecs.open(...encoding='cp1251'). +# Finally, its content will be converted to UTF8 for showing in expected_stdout. +# Checked on: +# * Windows: 4.0.0.2377, 3.0.8.33423; old version: 3.0.4.32972, 3.0.2.32703, 3.0.1.32609, 3.0.0.32483, 2.5.9.27152 +# * Linux: 4.0.0.2379, 3.0.8.33415 +# +# tracker_id: CORE-1347 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='WIN1251', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import codecs +# import subprocess +# import time +# engine = db_conn.engine_version +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql_txt=''' set bail on; +# set names win1251; +# connect '%(dsn)s' user '%(user_name)s' password '%(user_password)s'; +# +# set term ^ ; +# create procedure sp_test ( +# p_tablename varchar(30) , +# p_idname varchar(30) , +# p_seqname varchar(30) , +# p_isusefunc smallint +# ) +# returns ( +# column_value bigint +# ) +# as +# declare variable l_maxid bigint; +# begin +# /* +# -- Находим разрыв в значениях ПК таблицы +# -- если разрыв отсутствует то дергаем секвенс +# -- p_IsUseFunc=1 - дергать секвенс ч/з ф-цию GetSeqValue +# */ +# end ^ +# set term ;^ +# commit; +# +# set list on; +# set count on; +# +# select pr.rdb$procedure_name +# from rdb$procedures pr +# where pr.rdb$procedure_source containing '1' +# and pr.rdb$procedure_name = upper('sp_test'); +# +# ''' % dict(globals(), **locals()) +# +# f_run_sql = open( os.path.join(context['temp_directory'], 'tmp_5325_win1251.sql'), 'w' ) +# f_run_sql.write( sql_txt.decode('utf8').encode('cp1251') ) +# flush_and_close( f_run_sql ) +# +# # result: file tmp_5325_win1251.sql is encoded in win1251 +# +# f_run_log = open( os.path.splitext(f_run_sql.name)[0]+'.log', 'w') +# subprocess.call( [ context['isql_path'], '-q', '-i', f_run_sql.name ], +# stdout = f_run_log, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_run_log ) # result: output will be encoded in win1251 +# +# with codecs.open(f_run_log.name, 'r', encoding='cp1251' ) as f: +# result_in_win1251 = f.readlines() +# +# for i in result_in_win1251: +# print( i.encode('utf8') ) +# +# # cleanup: +# ########### +# cleanup( (f_run_sql, f_run_log) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$PROCEDURE_NAME SP_TEST + Records affected: 1 + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_1347_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_1356.py b/tests/bugs/test_core_1356.py new file mode 100644 index 00000000..150f79ef --- /dev/null +++ b/tests/bugs/test_core_1356.py @@ -0,0 +1,52 @@ +#coding:utf-8 +# +# id: bugs.core_1356 +# title: TYPE OF COLUMN in PSQL +# decription: +# tracker_id: CORE-1356 +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter procedure sp_ins_person as begin end; + commit; + recreate table person ( + id integer, + name varchar(40) + ); + commit; + + set term ^; + create or alter procedure sp_ins_person ( + id type of column person.id, + name type of column person.name + ) as + declare variable new_id type of column person.id; + begin + insert into person (id, name) values (:id, :name) returning id into :new_id; + end^ + set term ;^ + commit; + --show procedure sp_ins_person; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.0') +def test_core_1356_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_1361.py b/tests/bugs/test_core_1361.py new file mode 100644 index 00000000..63bcc1f8 --- /dev/null +++ b/tests/bugs/test_core_1361.py @@ -0,0 +1,164 @@ +#coding:utf-8 +# +# id: bugs.core_1361 +# title: Index operations for global temporary tables are not visible for the active connection +# decription: +# Checked on: +# 4.0.0.1635 SS: 1.863s. +# 4.0.0.1633 CS: 2.386s. +# 3.0.5.33180 SS: 1.302s. +# 3.0.5.33178 CS: 1.778s. +# +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: bugs.core_1361 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + set term ^; + create or alter procedure sp_check_plan returns(sql_plan blob) as + begin + end + ^ + execute block as + begin + begin execute statement 'drop role poor_dba'; when any do begin end end + begin execute statement 'drop role cool_dba'; when any do begin end end + begin execute statement 'drop role super_dba'; when any do begin end end + end + ^ + set term ;^ + commit; + + recreate global temporary table gtt_session(x int, y int) on commit preserve rows; + commit; + create role poor_dba; + create role cool_dba; + create role super_dba; + commit; + + grant poor_dba to sysdba; -- for connect #1 + grant cool_dba to sysdba; -- for connect #2 + grant super_dba to sysdba; -- for connect #3 (index also WILL be seen for it) + commit; + + set term ^; + create or alter procedure sp_check_plan returns(sql_plan blob) as + declare n int; + begin + insert into gtt_session + select rand()*100, rand()*100 + from rdb$types,rdb$triggers + union all + select -2, -3 + from rdb$database; + + execute statement + 'select ' + || ' (select count(*) from gtt_session g where g.x + g.y = -5) ' + || ' ,mon$explained_plan ' + || 'from mon$statements s ' + || 'where s.mon$transaction_id = current_transaction and mon$explained_plan containing ''GTT_SESSION'' ' + || 'rows 1' + into n, sql_plan; + suspend; + end + ^ + set term ;^ + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set blob all; + set term ^; + execute block returns(using_index smallint) as + declare v_dbname type of column mon$database.mon$database_name; + declare v_usr varchar(31) = 'SYSDBA'; + declare v_pwd varchar(20) = 'masterkey'; + declare role_1 varchar(31) = 'POOR_DBA'; + declare role_2 varchar(31) = 'COOL_DBA'; + declare role_3 varchar(31) = 'SUPER_DBA'; + declare sql_plan blob; + begin + + v_dbname = 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME'); + + execute statement 'select sql_plan from sp_check_plan' + on external v_dbname + as user v_usr password v_pwd role upper( role_1 ) + into sql_plan; + using_index = iif(sql_plan containing 'GTT_SESSION_X_Y', 1, 0); + suspend; + + -------------------------------------------------------- + + execute statement 'create index gtt_session_x_y on gtt_session computed by ( x+y )' + with autonomous transaction + on external v_dbname + as user v_usr password v_pwd role upper( role_2 ); + -- nb: changing this to 'role_1' will produce in firebird.log: + -- internal Firebird consistency check (invalid SEND request (167), + -- file: JrdStatement.cpp line: 325) + + execute statement 'select sql_plan from sp_check_plan' + on external v_dbname + as user v_usr password v_pwd role upper( role_2 ) + into sql_plan; + using_index = iif(sql_plan containing 'GTT_SESSION_X_Y', 1, 0); + suspend; + + -------------------------------------------------------- + + execute statement 'select sql_plan from sp_check_plan' + on external v_dbname + as user v_usr password v_pwd role upper( role_3 ) + into sql_plan; + using_index = iif(sql_plan containing 'GTT_SESSION_X_Y', 1, 0); + 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + USING_INDEX 0 + USING_INDEX 1 + USING_INDEX 1 + """ + +@pytest.mark.version('>=3.0') +def test_core_1361_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1362.py b/tests/bugs/test_core_1362.py new file mode 100644 index 00000000..ae41d05d --- /dev/null +++ b/tests/bugs/test_core_1362.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: bugs.core_1362 +# title: Too large numbers cause positive infinity to be inserted into database +# decription: +# tracker_id: CORE-1362 +# min_versions: [] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test (col1 double precision); + commit; + -- this should PASS: + insert into test values( 1.79769313486231570E+308 ); + -- this is too big, should raise exception: + insert into test values( 1.79769313486232e+308 ); + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22003 + Floating-point overflow. The exponent of a floating-point operation is greater than the magnitude allowed. + """ + +@pytest.mark.version('>=4.0') +def test_core_1362_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_1363.py b/tests/bugs/test_core_1363.py new file mode 100644 index 00000000..f31f1a5b --- /dev/null +++ b/tests/bugs/test_core_1363.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: bugs.core_1363 +# title: ISQL crash when converted-from-double string longer than 23 bytes +# decription: +# tracker_id: CORE-1363 +# min_versions: ['2.5'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select -2.488355210669293e-22 from rdb$database; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CONSTANT +======================= + -2.488355210669293e-22 + +""" + +@pytest.mark.version('>=2.5') +def test_core_1363_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1366.py b/tests/bugs/test_core_1366.py new file mode 100644 index 00000000..63701ac3 --- /dev/null +++ b/tests/bugs/test_core_1366.py @@ -0,0 +1,159 @@ +#coding:utf-8 +# +# id: bugs.core_1366 +# title: French insensitive collation FR_FR_CI_AI +# decription: +# ::: NOTE ::: +# In order to check correctness of following statements under ISQL itself (NOT under fbt_run), do following: +# 1) open some text editor that supports charset = ISO8859_1 and set encoding for new document = ISO 8859-1 +# (e.g. in Notepad++ pull-down menu: "Encoding / Character sets / Western european / ISO 8859_1") +# 2) type commands statements that contains diacritical marks (accents) and save to .sql +# 3) open this .sql in FAR editor and ensure that letters with diacritical marks are displayed as SINGLE characters +# 4) run isql -i +# In order to run this script under fbt_run: +# 1) open Notepad++ new .fbt document and set Encoding = "UTF8 without BOM" +# 2) copy-paste text from , ensure that letters with diacritical marks are readable +# (it should be pasted here in UTF8 encoding) +# 3) add in `expected_stdout` section required output by copy-paste from result of isql -i +# (it should be pasted here in UTF8 encoding) +# 4) save .fbt and ensure that it was saved in UTF8 encoding, otherwise exeption like +# "UnicodeDecodeError: 'utf8' codec can't decode byte 0xc3 in position 621: invalid continuation byte" will raise. +# +# 14.08.2020: +# removed usage of generator because gen_id() result differs in FB 4.x vs previous versions since fixed core-6084. +# Use hard-coded values for IDs. +# Checked on: +# 4.0.0.2151 SS: 1.672s. +# 3.0.7.33348 SS: 0.984s. +# 2.5.9.27150 SC: 0.277s. +# +# 28.02.2021 +# Changed connection charset to UTF8 otherwise on Linux this test leads to 'ERROR' with issuing: +# ==== +# Statement failed, SQLSTATE = 42000 +# Dynamic SQL Error +# -SQL error code = -104 +# -Token unknown - line 4, column 1 +# -e +# Statement failed, SQLSTATE = 42000 +# Dynamic SQL Error +# -SQL error code = -104 +# -Token unknown - line 3, column 1 +# -o +# . . . +# ==== +# Checked again on: +# 1) Windows: 4.0.0.2372; 3.0.8.33416 +# 2) Linux: 4.0.0.2377 +# +# tracker_id: CORE-1366 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=.*', ''), ('[ \t]+', ' ')] + +init_script_1 = """ + 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_1 = db_factory(charset='ISO8859_1', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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.version('>=2.5') +def test_core_1366_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1371.py b/tests/bugs/test_core_1371.py new file mode 100644 index 00000000..bea56fc0 --- /dev/null +++ b/tests/bugs/test_core_1371.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: bugs.core_1371 +# title: Execute block fails within execute statement +# decription: +# tracker_id: CORE-1371 +# min_versions: [] +# versions: 2.0.2 +# qmid: bugs.core_1371 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """set term ^; +create procedure P +as +begin + execute statement 'execute block as begin end'; +end ^ + +set term ;^ +commit; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.0.2') +def test_core_1371_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_1373.py b/tests/bugs/test_core_1373.py new file mode 100644 index 00000000..66ad94b4 --- /dev/null +++ b/tests/bugs/test_core_1373.py @@ -0,0 +1,73 @@ +#coding:utf-8 +# +# id: bugs.core_1373 +# title: Incorrect result of recursive CTE query when recursive member's SELECT list contains expression using self-referenced fields +# decription: +# tracker_id: CORE-1373 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1373 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """RECREATE TABLE Phases +(Id INT NOT NULL PRIMARY KEY, ParentPhaseId INT); + +CREATE GENERATOR GenPhases; +COMMIT; + +INSERT INTO Phases VALUES(491, NULL); +INSERT INTO Phases VALUES(494, 491); +INSERT INTO Phases VALUES(495, 491); +INSERT INTO Phases VALUES(497, 494); +INSERT INTO Phases VALUES(498, NULL); + +-- below i want to renumber Phases table and keep parent-child relation +SET GENERATOR GenPhases to 0; +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """WITH RECURSIVE + Tree (OldPhaseId, OldParentPhaseId, NewPhaseId, NewParentPhaseId) AS + ( + SELECT P.Id, P.ParentPhaseId, GEN_ID(GenPhases, 1), CAST(NULL AS INTEGER) + FROM Phases P + WHERE P.ParentPhaseId IS NULL + + UNION ALL + + SELECT P.Id, P.ParentPhaseId, GEN_ID(GenPhases, 1), T.NewPhaseId + FROM Phases P, Tree T + WHERE P.ParentPhaseId = T.OldPhaseId + ) +SELECT * FROM Tree; + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + OLDPHASEID OLDPARENTPHASEID NEWPHASEID NEWPARENTPHASEID +============ ================ ===================== ================ + 491 1 + 494 491 2 1 + 497 494 3 2 + 495 491 4 1 + 498 5 + +""" + +@pytest.mark.version('>=2.1') +def test_core_1373_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1377.py b/tests/bugs/test_core_1377.py new file mode 100644 index 00000000..f5fa905c --- /dev/null +++ b/tests/bugs/test_core_1377.py @@ -0,0 +1,52 @@ +#coding:utf-8 +# +# id: bugs.core_1377 +# title: Add an ability to change role without reconnecting to database. +# decription: +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: bugs.core_1377 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create role r1377a; + create role r1377b; + commit; + grant r1377a to sysdba; + grant r1377b to sysdba; + commit; + set list on; + set role r1377a; + select current_user, current_role from rdb$database; + set role r1377b; + select current_user, current_role from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + USER SYSDBA + ROLE R1377A + + USER SYSDBA + ROLE R1377B + """ + +@pytest.mark.version('>=3.0') +def test_core_1377_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1378.py b/tests/bugs/test_core_1378.py new file mode 100644 index 00000000..1d4d64c4 --- /dev/null +++ b/tests/bugs/test_core_1378.py @@ -0,0 +1,181 @@ +#coding:utf-8 +# +# id: bugs.core_1378 +# title: Domain names and charset issues +# decription: +# 05-mar-2021. Re-implemented in order to have ability to run this test on Linux. +# Test encodes to UTF8 all needed statements (SET NAMES; CONNECT; DDL and DML) and stores this text in .sql file. +# NOTE: 'SET NAMES' contain character set that must be used for reproducing problem (WIN1251 in this test). +# Then ISQL is launched in separate (child) process which performs all necessary actions (using required charset). +# Result will be redirected to log(s) which will be opened further via codecs.open(...encoding='cp1251'). +# Finally, its content will be converted to UTF8 for showing in expected_stdout. +# Checked on: +# * Windows: 4.0.0.2377, 3.0.8.33423; 2.5.9.27152 +# * Linux: 4.0.0.2379, 3.0.8.33415 +# +# tracker_id: +# min_versions: ['2.5.9'] +# versions: 2.5.9 +# qmid: bugs.core_1378 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.9 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='WIN1251', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import codecs +# import subprocess +# import time +# engine = db_conn.engine_version +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql_txt=''' set bail on; +# set names win1251; +# connect '%(dsn)s' user '%(user_name)s' password '%(user_password)s'; +# +# create collation "вид прописи" for win1251 from pxw_cyrl pad space case insensitive accent insensitive; +# commit; +# create domain "значение числа" as int; +# create domain "число прописью" as varchar(8191) character set win1251 collate "вид прописи"; +# commit; +# create table test( id "значение числа", txt "число прописью"); +# commit; +# set term ^; +# create procedure sp_test ( i_number "значение числа") returns( o_text "число прописью") as +# begin +# suspend; +# end +# ^ +# set term ;^ +# commit; +# +# --set blob all; +# --select rdb$procedure_source as rdb_source_blob_id from rdb$procedures where rdb$procedure_name = upper('sp_test'); +# set list on; +# +# select rdb$procedure_name from rdb$procedures where rdb$procedure_name = upper('sp_test'); +# +# select +# p.rdb$parameter_name +# ,p.rdb$field_source +# ,f.rdb$field_type +# ,f.rdb$field_sub_type +# ,f.rdb$field_length +# ,f.rdb$character_length +# ,f.rdb$character_set_id +# ,f.rdb$collation_id +# ,c.rdb$character_set_name +# ,s.rdb$collation_name +# from rdb$procedure_parameters p +# left join rdb$fields f on p.rdb$field_source = f.rdb$field_name +# left join rdb$character_sets c on f.rdb$character_set_id = c.rdb$character_set_id +# left join rdb$collations s on +# f.rdb$collation_id = s.rdb$collation_id +# and c.rdb$character_set_id = s.rdb$character_set_id +# where rdb$procedure_name = upper('sp_test') +# ; +# +# +# ''' % dict(globals(), **locals()) +# +# f_run_sql = open( os.path.join(context['temp_directory'], 'tmp_1378_win1251.sql'), 'w' ) +# f_run_sql.write( sql_txt.decode('utf8').encode('cp1251') ) +# flush_and_close( f_run_sql ) +# +# # result: file tmp_1378_win1251.sql is encoded in win1251 +# +# f_run_log = open( os.path.splitext(f_run_sql.name)[0]+'.log', 'w') +# subprocess.call( [ context['isql_path'], '-q', '-i', f_run_sql.name ], +# stdout = f_run_log, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_run_log ) # result: output will be encoded in win1251 +# +# with codecs.open(f_run_log.name, 'r', encoding='cp1251' ) as f: +# result_in_win1251 = f.readlines() +# +# for i in result_in_win1251: +# print( i.encode('utf8') ) +# +# # cleanup: +# ########### +# cleanup( (f_run_sql, f_run_log) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$PROCEDURE_NAME SP_TEST + RDB$PARAMETER_NAME I_NUMBER + RDB$FIELD_SOURCE значение числа + RDB$FIELD_TYPE 8 + RDB$FIELD_SUB_TYPE 0 + RDB$FIELD_LENGTH 4 + RDB$CHARACTER_LENGTH + RDB$CHARACTER_SET_ID + RDB$COLLATION_ID + RDB$CHARACTER_SET_NAME + RDB$COLLATION_NAME + RDB$PARAMETER_NAME O_TEXT + RDB$FIELD_SOURCE число прописью + RDB$FIELD_TYPE 37 + RDB$FIELD_SUB_TYPE 0 + RDB$FIELD_LENGTH 8191 + RDB$CHARACTER_LENGTH 8191 + RDB$CHARACTER_SET_ID 52 + RDB$COLLATION_ID 126 + RDB$CHARACTER_SET_NAME WIN1251 + RDB$COLLATION_NAME вид прописи + """ + +@pytest.mark.version('>=2.5.9') +@pytest.mark.xfail +def test_core_1378_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_1379.py b/tests/bugs/test_core_1379.py new file mode 100644 index 00000000..d43fc3f1 --- /dev/null +++ b/tests/bugs/test_core_1379.py @@ -0,0 +1,79 @@ +#coding:utf-8 +# +# id: bugs.core_1379 +# title: Invalid parameter type when using it in CHAR_LENGTH function +# decription: +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: bugs.core_1379 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('-At block line: [\\d]+, col: [\\d]+', '-At block line')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set term ^; + execute block returns(r int) as + begin + execute statement ('select 1 from rdb$database where char_length(?) = 0') (1) into r; + suspend; + end + ^ + execute block returns(r int) as + begin + execute statement ('select 1 from rdb$database where char_length(?) = 0') ('') into r; + suspend; + end + ^ + execute block returns(r int) as + declare c varchar(1) = ''; + begin + execute statement ('select 1 from rdb$database where char_length(?) = 0') (c) into r; + suspend; + end + ^ + set term ;^ + -- 05.05.2015: + -- 1) changed min version to 2.5 (according to ticket header info; output in 2.5 and 3.0 now fully matches) + -- 2) removed STDOUT (for the first ES); + -- 3) changed expected STDERR: all three ES must now raise exception 'Data type unknown'. + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = HY004 + Dynamic SQL Error + -SQL error code = -804 + -Data type unknown + -At block line: 3, col: 9 + + Statement failed, SQLSTATE = HY004 + Dynamic SQL Error + -SQL error code = -804 + -Data type unknown + -At block line: 3, col: 9 + + Statement failed, SQLSTATE = HY004 + Dynamic SQL Error + -SQL error code = -804 + -Data type unknown + -At block line: 3, col: 9 + """ + +@pytest.mark.version('>=2.5') +def test_core_1379_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_1384.py b/tests/bugs/test_core_1384.py new file mode 100644 index 00000000..1d1e5d54 --- /dev/null +++ b/tests/bugs/test_core_1384.py @@ -0,0 +1,83 @@ +#coding:utf-8 +# +# id: bugs.core_1384 +# title: LIKE doesn't work correctly with collations using SPECIALS-FIRST=1 +# decription: +# 02-mar-2021. Re-implemented in ordeer to have ability to run this test on Linux. +# We run 'init_script' using charset = utf8 but then run separate ISQL-process +# with request to establish connection using charset = ISO8859_1. +# +# *** NOTE *** +# Script that must be executed by ISQL does NOT contain any nnon-ascii characters. +# Query with diacritical symbols was moved into view V_TEST which is created in init_script +# using charset ***UTF-8*** (otherwise is seems to be unable to run this test on Linux). +# +# Checked on: +# * Windows: 4.0.0.2377, 3.0.8.33420, 2.5.9.27152 +# * Linux: 4.0.0.2377, 3.0.8.33415 +# +# tracker_id: CORE-1384 +# min_versions: ['2.1.7'] +# versions: 2.1.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create collation coll_es for iso8859_1 from external ('ES_ES_CI_AI') 'SPECIALS-FIRST=1'; + create collation coll_fr for iso8859_1 from external ('FR_FR') CASE INSENSITIVE accent insensitive 'SPECIALS-FIRST=1'; + commit; + + create or alter view v_test as + select + iif( _iso8859_1 'Ja ' collate coll_es like _iso8859_1 '% a%' collate coll_es, 1, 0) result_for_es_ci_ai + ,iif( _iso8859_1 'ka ' collate coll_fr like _iso8859_1 '% a%' collate coll_fr, 1, 0) result_for_fr_ci_ai + from rdb$database + UNION ALL -- added comparison to pattern with diactiric mark: + select + iif( _iso8859_1 'Jà ' collate coll_es like _iso8859_1 '% à %' collate coll_es, 1, 0) result_for_es_ci_ai + ,iif( _iso8859_1 'kà ' collate coll_fr like _iso8859_1 '% à %' collate coll_fr, 1, 0) result_for_fr_ci_ai + from rdb$database + ; + """ + +db_1 = db_factory(charset='ISO8859_1', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# sql_cmd=''' +# set names ISO8859_1; +# connect '%(dsn)s' user '%(user_name)s' password '%(user_password)s'; +# set list on; +# show collation; +# select * from v_test; +# ''' % dict(globals(), **locals()) +# +# runProgram( 'isql', [ '-q' ], sql_cmd) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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 + RESULT_FOR_FR_CI_AI 0 + """ + +@pytest.mark.version('>=2.1.7') +@pytest.mark.xfail +def test_core_1384_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_1386.py b/tests/bugs/test_core_1386.py new file mode 100644 index 00000000..8c9bb457 --- /dev/null +++ b/tests/bugs/test_core_1386.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: bugs.core_1386 +# title: Generated columns +# decription: +# tracker_id: CORE-1386 +# min_versions: [] +# versions: 2.1.0 +# qmid: bugs.core_1386 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """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; + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """COL1 INTEGER Nullable +COL2 Computed by: (COL1 +1) +COL3 Computed by: (COL1 +1) + + COL1 COL2 COL3 +============ ===================== ============ + 1 2 2 + +""" + +@pytest.mark.version('>=2.1.0') +def test_core_1386_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1389.py b/tests/bugs/test_core_1389.py new file mode 100644 index 00000000..b208e55c --- /dev/null +++ b/tests/bugs/test_core_1389.py @@ -0,0 +1,102 @@ +#coding:utf-8 +# +# id: bugs.core_1389 +# title: Indexed MIN/MAX aggregates produce three index reads instead of the expected one indexed read +# decription: +# We use API call db_info(fdb.isc_info_read_idx_count) for obtaining number of indexed reads and +# extract their values which are reported per table and are cumulative since start of attachment. +# Four statements are used for analyzing (table have all needed indexes): +# * select max(x) from ...; +# * select x from ... order by x asc rows 1; +# * select min(y) from ...; +# * select y from ... order by y desc rows 1; +# +# All of them must take only one indexed read. +# +# Info about 'isc_info_read_idx_count': +# Number of indexed database reads <...> +# Reported per table. +# Calculated since the current database attachment started // CUMULATIVE! +# +# See also: +# http://pythonhosted.org/fdb/reference.html#fdb.Connection.database_info +# +# Confirmed bug on WI-V2.0.0.12724: db_info() received 3 (three) indexed reads instead of 1 for queries: +# 'select min(...) from ...' and 'select max(...) from ...' +# +# tracker_id: CORE-1389 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table test(x int, y int); + commit; + insert into test(x, y) + select -1, 1 from (select 1 i from rdb$types rows 200) a, (select 1 i from rdb$types rows 200) b; + commit; + + create index test_x on test(x); + create descending index test_y on test(y); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import fdb +# sql_get_rel_id="select rdb$relation_id from rdb$relations where trim(rdb$relation_name)=upper('test')" +# +# cur=db_conn.cursor() +# cur.execute(sql_get_rel_id) +# +# test_rel=-1 +# for r in cur: +# test_rel=r[0] +# +# sql_set=[ +# 'select min(x) from test', +# 'select x from test order by x rows 1', +# 'select max(y) from test', +# 'select y from test order by y desc rows 1' +# ] +# +# v_previous_idx_counter=0 +# for i in range(0,len(sql_set)): +# cur.execute(sql_set[i]) +# for r in cur: +# y=r[0] +# +# info = db_conn.db_info(fdb.isc_info_read_idx_count) +# # WI-V2.0.0.12724 +# for k,v_cumulative_idx_counter in info.items(): +# if k == test_rel: +# print( 'Number of indexed reads: ' + str(v_cumulative_idx_counter - v_previous_idx_counter) ) +# v_previous_idx_counter = v_cumulative_idx_counter +# cur.close() +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Number of indexed reads: 1 + Number of indexed reads: 1 + Number of indexed reads: 1 + Number of indexed reads: 1 + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_1389_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_1395.py b/tests/bugs/test_core_1395.py new file mode 100644 index 00000000..1d01c345 --- /dev/null +++ b/tests/bugs/test_core_1395.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: bugs.core_1395 +# title: Few problems with domains's check constraints +# decription: +# tracker_id: CORE-1395 +# min_versions: [] +# versions: 2.5 +# qmid: bugs.core_1395-250 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE TEST ( ID INTEGER ); +CREATE DOMAIN TEST_DOMAIN AS INTEGER CHECK (EXISTS(SELECT * FROM TEST WHERE ID=VALUE)); +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """DROP TABLE TEST; +COMMIT; + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42000 +unsuccessful metadata update +-cannot delete +-COLUMN TEST.ID +-there are 1 dependencies +""" + +@pytest.mark.version('>=2.5') +def test_core_1395_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_1401.py b/tests/bugs/test_core_1401.py new file mode 100644 index 00000000..c1a735eb --- /dev/null +++ b/tests/bugs/test_core_1401.py @@ -0,0 +1,66 @@ +#coding:utf-8 +# +# id: bugs.core_1401 +# title: Global temporary table instance may pick up not all indices +# decription: +# tracker_id: CORE-1401 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1401 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """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; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +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 + +""" + +@pytest.mark.version('>=2.1') +def test_core_1401_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1402.py b/tests/bugs/test_core_1402.py new file mode 100644 index 00000000..602795a0 --- /dev/null +++ b/tests/bugs/test_core_1402.py @@ -0,0 +1,105 @@ +#coding:utf-8 +# +# id: bugs.core_1402 +# title: CREATE VIEW without column list when UNION is used +# decription: +# tracker_id: CORE-1402 +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [('V_SOURCE.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate view V1 as + select d.rdb$relation_id from rdb$database d + union all + select d.rdb$relation_id from rdb$database d; + + recreate view V2 as + select d.rdb$relation_id as q from rdb$database d + union all + select d.rdb$relation_id as w from rdb$database d; + + recreate view V3 as + select a from (select 1 a from rdb$database) + union all + select b from (select 1 b from rdb$database); + + recreate view V4 as + select a as a1 from (select 1 a from rdb$database) + union all + select b as b1 from (select 1 b from rdb$database); + commit; + + set blob all; + set list on; + + -- Removed 'show view' commands because of core-4782 (failed on windows builds when connection charset = UTF8). + -- Added checking query to RDB$ tables instead that views indeed DO have fields of proper type (7=smallint, 8=int): + select + r.rdb$relation_name v_name, + r.rdb$view_source v_source, + f.rdb$field_name f_name, + ff.rdb$field_type f_type + from rdb$relations r + join rdb$relation_fields f using (rdb$relation_name) + join rdb$fields ff on f.rdb$field_source = ff.rdb$field_name + where + r.rdb$relation_type = 1 + and r.rdb$relation_name in ('V1','V2','V3','V4') + order by v_name, f_name; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + V_NAME V1 + V_SOURCE 6:1e8 + select d.rdb$relation_id from rdb$database d + union all + select d.rdb$relation_id from rdb$database d + F_NAME RDB$RELATION_ID + F_TYPE 7 + + V_NAME V2 + V_SOURCE 6:1eb + select d.rdb$relation_id as q from rdb$database d + union all + select d.rdb$relation_id as w from rdb$database d + F_NAME Q + F_TYPE 7 + + V_NAME V3 + V_SOURCE 6:2ce + select a from (select 1 a from rdb$database) + union all + select b from (select 1 b from rdb$database) + F_NAME A + F_TYPE 8 + + V_NAME V4 + V_SOURCE 6:2d1 + select a as a1 from (select 1 a from rdb$database) + union all + select b as b1 from (select 1 b from rdb$database) + F_NAME A1 + F_TYPE 8 + """ + +@pytest.mark.version('>=2.5.0') +def test_core_1402_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1409.py b/tests/bugs/test_core_1409.py new file mode 100644 index 00000000..cc0ea511 --- /dev/null +++ b/tests/bugs/test_core_1409.py @@ -0,0 +1,62 @@ +#coding:utf-8 +# +# id: bugs.core_1409 +# title: Support for autonomous transactions +# decription: +# tracker_id: CORE-1409 +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table log ( + msg varchar(60) +); +commit; +set term !; + +create trigger t_conn on connect +as +begin + if (current_user = 'SYSDBA') then + begin + in autonomous transaction + do + begin + insert into log (msg) values ('SYSDBA connected'); + end + end +end! + +set term ;! +commit; +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select msg from log; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Database: localhost:C: btest2 mpugs.core_1409.fdb, User: SYSDBA +SQL> +MSG +============================================================ +SYSDBA connected + +SQL>""" + +@pytest.mark.version('>=2.5.0') +def test_core_1409_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1419.py b/tests/bugs/test_core_1419.py new file mode 100644 index 00000000..7bee5f48 --- /dev/null +++ b/tests/bugs/test_core_1419.py @@ -0,0 +1,74 @@ +#coding:utf-8 +# +# id: bugs.core_1419 +# title: Wrong current timestamp evaluation for selectable procedures +# decription: In our implementation, CURRENT_DATE/TIME[STAMP] values are evaluated at the request (aka SQL statement) start time and are permanent for the duration of that request. This rule includes the nested calls (procedures and triggers) as well, i.e. they inherit the parent's timestamp, thus providing the stable date-time value for the entire call stack. However, this rule is broken for selectable procedures that evaluate current date-time values at every invocation. +# tracker_id: CORE-1419 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_1419 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """set term ^; + +create procedure ts1 returns ( ts timestamp ) +as +begin + ts = current_timestamp; + suspend; +end^ + +create procedure ts2 returns ( ts_self timestamp, ts_execute timestamp, ts_select timestamp ) +as + declare cnt int = 1000000; +begin + ts_self = current_timestamp; + execute procedure ts1 returning_values :ts_execute; + select ts from ts1 into :ts_select; + suspend; + + while (cnt > 0) do + cnt = cnt - 1; + + ts_self = current_timestamp; + execute procedure ts1 returning_values :ts_execute; + select ts from ts1 into :ts_select; + suspend; +end^ + +set term ;^ + +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT COUNT(*) +FROM ts2 +WHERE cast(ts_self as varchar(50))=cast(ts_execute as varchar(50)) +AND cast(ts_self as varchar(50))=cast(ts_select as varchar(50)) +; + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + COUNT +===================== + 2 + +""" + +@pytest.mark.version('>=3.0') +def test_core_1419_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1428.py b/tests/bugs/test_core_1428.py new file mode 100644 index 00000000..e2d4f6ed --- /dev/null +++ b/tests/bugs/test_core_1428.py @@ -0,0 +1,48 @@ +#coding:utf-8 +# +# id: bugs.core_1428 +# title: Incorrect timestamp substraction in 3 dialect when result is negative number +# decription: +# tracker_id: CORE-1428 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1428 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT (CAST('2007-08-22 00:00:00.0019' AS TIMESTAMP) - CAST('2007-08-22 00:00:00.0000' AS TIMESTAMP)) *86400*10000 AS A + FROM RDB$DATABASE; +SELECT (CAST('2007-08-22 00:00:00.0000' AS TIMESTAMP) - CAST('2007-08-22 00:00:00.0019' AS TIMESTAMP)) *86400*10000 AS A + FROM RDB$DATABASE; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A +===================== + 19.008000000 + + + A +===================== + -19.008000000 + +""" + +@pytest.mark.version('>=2.1') +def test_core_1428_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1431.py b/tests/bugs/test_core_1431.py new file mode 100644 index 00000000..d2db01eb --- /dev/null +++ b/tests/bugs/test_core_1431.py @@ -0,0 +1,241 @@ +#coding:utf-8 +# +# id: bugs.core_1431 +# title: Greek characters in cp1251 vs uppercasing +# decription: +# 02-mar-2021. Re-implemented in ordeer to have ability to run this test on Linux. +# We run 'init_script' using charset = utf8 but then run separate ISQL-process +# with request to establish connection using charset = WIN1251. +# +# NOTE-1. +# Script that must be executed by ISQL does NOT contain any non-ascii characters. +# We run query that produces ASCII-ONLY output with *description* of characters +# which have no 'partners' when appying upper() function (e.g., ellipsis, euro sign etc). +# +# NOTE-2. +# Character 'SOFT HYPHEN' WAS EXCLUDED from check list: it can not be properly interpreted +# on Linux when trying to insert this character: +# "UnicodeDecodeError: 'utf8' codec can't decode byte 0xc2 in position ... invalid continuation byte" +# +# Checked on: +# * Windows: 4.0.0.2377, 3.0.8.33420, 2.5.9.27152 +# * Linux: 4.0.0.2377, 3.0.8.33415 +# +# tracker_id: CORE-1431 +# min_versions: ['2.1.7'] +# versions: 2.1.7 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table c1251(c char(1) character set win1251, id int, descr varchar(80) ); + commit; + + -- http://www.columbia.edu/kermit/cp1251.html + --char dec col/row oct hex description + insert into c1251( c, id, descr ) values('Ђ', 128, 'CYRILLIC CAPITAL LETTER DJE'); + insert into c1251( c, id, descr ) values('Ѓ', 129, 'CYRILLIC CAPITAL LETTER GJE'); + insert into c1251( c, id, descr ) values('‚', 130, 'LOW 9 SINGLE QUOTE'); + insert into c1251( c, id, descr ) values('ѓ', 131, 'CYRILLIC SMALL LETTER GJE'); + insert into c1251( c, id, descr ) values('„', 132, 'LOW 9 DOUBLE QUOTE'); + insert into c1251( c, id, descr ) values('…', 133, 'ELLIPSIS'); + insert into c1251( c, id, descr ) values('†', 134, 'DAGGER'); + insert into c1251( c, id, descr ) values('‡', 135, 'DOUBLE DAGGER'); + insert into c1251( c, id, descr ) values('€', 136, 'EURO SIGN'); + insert into c1251( c, id, descr ) values('‰', 137, 'PER MIL SIGN'); + insert into c1251( c, id, descr ) values('Љ', 138, 'CYRILLIC CAPITAL LETTER LJE'); + insert into c1251( c, id, descr ) values('‹', 139, 'LEFT SINGLE QUOTE BRACKET'); + insert into c1251( c, id, descr ) values('Њ', 140, 'CYRILLIC CAPITAL LETTER NJE'); + insert into c1251( c, id, descr ) values('Ќ', 141, 'CYRILLIC CAPITAL LETTER KJE'); + insert into c1251( c, id, descr ) values('Ћ', 142, 'CYRILLIC CAPITAL LETTER TSHE'); + insert into c1251( c, id, descr ) values('Џ', 143, 'CYRILLIC CAPITAL LETTER DZHE'); + insert into c1251( c, id, descr ) values('ђ', 144, 'CYRILLIC SMALL LETTER DJE'); + insert into c1251( c, id, descr ) values('‘', 145, 'HIGH 6 SINGLE QUOTE'); + insert into c1251( c, id, descr ) values('’', 146, 'HIGH 9 SINGLE QUOTE'); + insert into c1251( c, id, descr ) values('“', 147, 'HIGH 6 DOUBLE QUOTE'); + insert into c1251( c, id, descr ) values('”', 148, 'HIGH 9 DOUBLE QUOTE'); + insert into c1251( c, id, descr ) values('•', 149, 'LARGE CENTERED DOT'); + insert into c1251( c, id, descr ) values('–', 150, 'EN DASH'); + insert into c1251( c, id, descr ) values('—', 151, 'EM DASH'); + insert into c1251( c, id, descr ) values('™', 153, 'TRADEMARK SIGN'); + insert into c1251( c, id, descr ) values('љ', 154, 'CYRILLIC SMALL LETTER LJE'); + insert into c1251( c, id, descr ) values('›', 155, 'RIGHT SINGLE QUOTE BRACKET'); + insert into c1251( c, id, descr ) values('њ', 156, 'CYRILLIC SMALL LETTER NJE'); + insert into c1251( c, id, descr ) values('ќ', 157, 'CYRILLIC SMALL LETTER KJE'); + insert into c1251( c, id, descr ) values('ћ', 158, 'CYRILLIC CAPITAL LETTER TSHE'); + insert into c1251( c, id, descr ) values('џ', 159, 'CYRILLIC CAPITAL LETTER DZHE'); + --insert into c1251( c, id, descr ) values(', ', 160, 'NO-BREAK SPACE'); + insert into c1251( c, id, descr ) values('Ў', 161, 'CYRILLIC CAPITAL LETTER SHORT U'); + insert into c1251( c, id, descr ) values('ў', 162, 'CYRILLIC SMALL LETTER SHORT U'); + insert into c1251( c, id, descr ) values('Ј', 163, 'CYRILLIC CAPITAL LETTER JE'); + insert into c1251( c, id, descr ) values('¤', 164, 'CURRENCY SIGN'); + insert into c1251( c, id, descr ) values('Ґ', 165, 'CYRILLIC CAPITAL LETTER GHE WITH UPTURN'); + insert into c1251( c, id, descr ) values('¦', 166, 'BROKEN BAR'); + insert into c1251( c, id, descr ) values('§', 167, 'PARAGRAPH SIGN'); + insert into c1251( c, id, descr ) values('Ё', 168, 'CYRILLIC CAPITAL LETTER IO'); + insert into c1251( c, id, descr ) values('©', 169, 'COPYRIGHT SIGN'); + insert into c1251( c, id, descr ) values('Є', 170, 'CYRILLIC CAPITAL LETTER UKRAINIAN IE'); + insert into c1251( c, id, descr ) values('«', 171, 'LEFT ANGLE QUOTATION MARK'); + insert into c1251( c, id, descr ) values('¬', 172, 'NOT SIGN'); + + -- insert into c1251( c, id, descr ) values('[SKIPPED! CAN NOT BE INTERPRETED ON LINUX!]', 173, 'SOFT HYPHEN'); + + insert into c1251( c, id, descr ) values('®', 174, 'REGISTERED TRADE MARK SIGN'); + insert into c1251( c, id, descr ) values('Ї', 175, 'CYRILLIC CAPITAL LETTER YI'); + insert into c1251( c, id, descr ) values('°', 176, 'DEGREE SIGN, RING ABOVE'); + insert into c1251( c, id, descr ) values('±', 177, 'PLUS-MINUS SIGN'); + insert into c1251( c, id, descr ) values('І', 178, 'CYRILLIC CAPITAL LETTER BYELORUSSION-UKRAINIAN I'); + insert into c1251( c, id, descr ) values('і', 179, 'CYRILLIC SMALL LETTER BYELORUSSION-UKRAINIAN I'); + insert into c1251( c, id, descr ) values('ґ', 180, 'CYRILLIC SMALL LETTER GHE WITH UPTURN'); + insert into c1251( c, id, descr ) values('µ', 181, 'MICRO SIGN'); + insert into c1251( c, id, descr ) values('¶', 182, 'PILCROW SIGN'); + insert into c1251( c, id, descr ) values('·', 183, 'MIDDLE DOT'); + insert into c1251( c, id, descr ) values('ё', 184, 'CYRILLIC SMALL LETTER IO'); + insert into c1251( c, id, descr ) values('№', 185, 'NUMERO SIGN'); + insert into c1251( c, id, descr ) values('є', 186, 'CYRILLIC SMALL LETTER UKRAINIAN IE'); + insert into c1251( c, id, descr ) values('»', 187, 'RIGHT ANGLE QUOTATION MARK'); + insert into c1251( c, id, descr ) values('ј', 188, 'CYRILLIC SMALL LETTER JE'); + insert into c1251( c, id, descr ) values('Ѕ', 189, 'CYRILLIC CAPITAL LETTER DZE'); + insert into c1251( c, id, descr ) values('ѕ', 190, 'CYRILLIC SMALL LETTER DZE'); + insert into c1251( c, id, descr ) values('ї', 191, 'CYRILLIC SMALL LETTER YI'); + insert into c1251( c, id, descr ) values('А', 192, 'CYRILLIC CAPITAL LETTER A'); + insert into c1251( c, id, descr ) values('Б', 193, 'CYRILLIC CAPITAL LETTER BE'); + insert into c1251( c, id, descr ) values('В', 194, 'CYRILLIC CAPITAL LETTER VE'); + insert into c1251( c, id, descr ) values('Г', 195, 'CYRILLIC CAPITAL LETTER GHE'); + insert into c1251( c, id, descr ) values('Д', 196, 'CYRILLIC CAPITAL LETTER DE'); + insert into c1251( c, id, descr ) values('Е', 197, 'CYRILLIC CAPITAL LETTER IE'); + insert into c1251( c, id, descr ) values('Ж', 198, 'CYRILLIC CAPITAL LETTER ZHE'); + insert into c1251( c, id, descr ) values('З', 199, 'CYRILLIC CAPITAL LETTER ZE'); + insert into c1251( c, id, descr ) values('И', 200, 'CYRILLIC CAPITAL LETTER I'); + insert into c1251( c, id, descr ) values('Й', 201, 'CYRILLIC CAPITAL LETTER SHORT I'); + insert into c1251( c, id, descr ) values('К', 202, 'CYRILLIC CAPITAL LETTER KA'); + insert into c1251( c, id, descr ) values('Л', 203, 'CYRILLIC CAPITAL LETTER EL'); + insert into c1251( c, id, descr ) values('М', 204, 'CYRILLIC CAPITAL LETTER EM'); + insert into c1251( c, id, descr ) values('Н', 205, 'CYRILLIC CAPITAL LETTER EN'); + insert into c1251( c, id, descr ) values('О', 206, 'CYRILLIC CAPITAL LETTER O'); + insert into c1251( c, id, descr ) values('П', 207, 'CYRILLIC CAPITAL LETTER PE'); + insert into c1251( c, id, descr ) values('Р', 208, 'CYRILLIC CAPITAL LETTER ER'); + insert into c1251( c, id, descr ) values('С', 209, 'CYRILLIC CAPITAL LETTER ES'); + insert into c1251( c, id, descr ) values('Т', 210, 'CYRILLIC CAPITAL LETTER TE'); + insert into c1251( c, id, descr ) values('У', 211, 'CYRILLIC CAPITAL LETTER U'); + insert into c1251( c, id, descr ) values('Ф', 212, 'CYRILLIC CAPITAL LETTER EF'); + insert into c1251( c, id, descr ) values('Х', 213, 'CYRILLIC CAPITAL LETTER HA'); + insert into c1251( c, id, descr ) values('Ц', 214, 'CYRILLIC CAPITAL LETTER TSE'); + insert into c1251( c, id, descr ) values('Ч', 215, 'CYRILLIC CAPITAL LETTER CHE'); + insert into c1251( c, id, descr ) values('Ш', 216, 'CYRILLIC CAPITAL LETTER SHA'); + insert into c1251( c, id, descr ) values('Щ', 217, 'CYRILLIC CAPITAL LETTER SHCHA'); + insert into c1251( c, id, descr ) values('Ъ', 218, 'CYRILLIC CAPITAL LETTER HARD SIGN'); + insert into c1251( c, id, descr ) values('Ы', 219, 'CYRILLIC CAPITAL LETTER YERU'); + insert into c1251( c, id, descr ) values('Ь', 220, 'CYRILLIC CAPITAL LETTER SOFT SIGN'); + insert into c1251( c, id, descr ) values('Э', 221, 'CYRILLIC CAPITAL LETTER E'); + insert into c1251( c, id, descr ) values('Ю', 222, 'CYRILLIC CAPITAL LETTER YU'); + insert into c1251( c, id, descr ) values('Я', 223, 'CYRILLIC CAPITAL LETTER YA'); + insert into c1251( c, id, descr ) values('а', 224, 'CYRILLIC SMALL LETTER A'); + insert into c1251( c, id, descr ) values('б', 225, 'CYRILLIC SMALL LETTER BE'); + insert into c1251( c, id, descr ) values('в', 226, 'CYRILLIC SMALL LETTER VE'); + insert into c1251( c, id, descr ) values('г', 227, 'CYRILLIC SMALL LETTER GHE'); + insert into c1251( c, id, descr ) values('д', 228, 'CYRILLIC SMALL LETTER DE'); + insert into c1251( c, id, descr ) values('е', 229, 'CYRILLIC SMALL LETTER IE'); + insert into c1251( c, id, descr ) values('ж', 230, 'CYRILLIC SMALL LETTER ZHE'); + insert into c1251( c, id, descr ) values('з', 231, 'CYRILLIC SMALL LETTER ZE'); + insert into c1251( c, id, descr ) values('и', 232, 'CYRILLIC SMALL LETTER I'); + insert into c1251( c, id, descr ) values('й', 233, 'CYRILLIC SMALL LETTER SHORT I'); + insert into c1251( c, id, descr ) values('к', 234, 'CYRILLIC SMALL LETTER KA'); + insert into c1251( c, id, descr ) values('л', 235, 'CYRILLIC SMALL LETTER EL'); + insert into c1251( c, id, descr ) values('м', 236, 'CYRILLIC SMALL LETTER EM'); + insert into c1251( c, id, descr ) values('н', 237, 'CYRILLIC SMALL LETTER EN'); + insert into c1251( c, id, descr ) values('о', 238, 'CYRILLIC SMALL LETTER O'); + insert into c1251( c, id, descr ) values('п', 239, 'CYRILLIC SMALL LETTER PE'); + insert into c1251( c, id, descr ) values('р', 240, 'CYRILLIC SMALL LETTER ER'); + insert into c1251( c, id, descr ) values('с', 241, 'CYRILLIC SMALL LETTER ES'); + insert into c1251( c, id, descr ) values('т', 242, 'CYRILLIC SMALL LETTER TE'); + insert into c1251( c, id, descr ) values('у', 243, 'CYRILLIC SMALL LETTER U'); + insert into c1251( c, id, descr ) values('ф', 244, 'CYRILLIC SMALL LETTER EF'); + insert into c1251( c, id, descr ) values('х', 245, 'CYRILLIC SMALL LETTER HA'); + insert into c1251( c, id, descr ) values('ц', 246, 'CYRILLIC SMALL LETTER TSE'); + insert into c1251( c, id, descr ) values('ч', 247, 'CYRILLIC SMALL LETTER CHE'); + insert into c1251( c, id, descr ) values('ш', 248, 'CYRILLIC SMALL LETTER CHA'); + insert into c1251( c, id, descr ) values('щ', 249, 'CYRILLIC SMALL LETTER SHCHA'); + insert into c1251( c, id, descr ) values('ъ', 250, 'CYRILLIC SMALL LETTER HARD SIGN'); + insert into c1251( c, id, descr ) values('ы', 251, 'CYRILLIC SMALL LETTER YERU'); + insert into c1251( c, id, descr ) values('ь', 252, 'CYRILLIC SMALL LETTER SOFT SIGN'); + insert into c1251( c, id, descr ) values('э', 253, 'CYRILLIC SMALL LETTER E'); + insert into c1251( c, id, descr ) values('ю', 254, 'CYRILLIC SMALL LETTER YU'); + insert into c1251( c, id, descr ) values('я', 255, 'CYRILLIC SMALL LETTER YA'); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# +# db_conn.close() +# +# sql_cmd=''' +# set names WIN1251; +# connect '%(dsn)s' user '%(user_name)s' password '%(user_password)s'; +# set list on; +# -- Test: following statement should pass OK, w/o exceptions: +# select min(t.descr) as has_no_upper_case_equiv +# -- PREVIOUSLY we use here: "upper(c) has_no_upper_case_equiv" // can be run on Windows only +# from c1251 t +# group by upper(t.c) +# having count(*) <> 2 +# ; +# ''' % dict(globals(), **locals()) +# +# runProgram( 'isql', [ '-q' ], sql_cmd) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + HAS_NO_UPPER_CASE_EQUIV LOW 9 SINGLE QUOTE + HAS_NO_UPPER_CASE_EQUIV LOW 9 DOUBLE QUOTE + HAS_NO_UPPER_CASE_EQUIV ELLIPSIS + HAS_NO_UPPER_CASE_EQUIV DAGGER + HAS_NO_UPPER_CASE_EQUIV DOUBLE DAGGER + HAS_NO_UPPER_CASE_EQUIV EURO SIGN + HAS_NO_UPPER_CASE_EQUIV PER MIL SIGN + HAS_NO_UPPER_CASE_EQUIV LEFT SINGLE QUOTE BRACKET + HAS_NO_UPPER_CASE_EQUIV HIGH 6 SINGLE QUOTE + HAS_NO_UPPER_CASE_EQUIV HIGH 9 SINGLE QUOTE + HAS_NO_UPPER_CASE_EQUIV HIGH 6 DOUBLE QUOTE + HAS_NO_UPPER_CASE_EQUIV HIGH 9 DOUBLE QUOTE + HAS_NO_UPPER_CASE_EQUIV LARGE CENTERED DOT + HAS_NO_UPPER_CASE_EQUIV EN DASH + HAS_NO_UPPER_CASE_EQUIV EM DASH + HAS_NO_UPPER_CASE_EQUIV TRADEMARK SIGN + HAS_NO_UPPER_CASE_EQUIV RIGHT SINGLE QUOTE BRACKET + HAS_NO_UPPER_CASE_EQUIV CURRENCY SIGN + HAS_NO_UPPER_CASE_EQUIV BROKEN BAR + HAS_NO_UPPER_CASE_EQUIV PARAGRAPH SIGN + HAS_NO_UPPER_CASE_EQUIV COPYRIGHT SIGN + HAS_NO_UPPER_CASE_EQUIV LEFT ANGLE QUOTATION MARK + HAS_NO_UPPER_CASE_EQUIV NOT SIGN + HAS_NO_UPPER_CASE_EQUIV REGISTERED TRADE MARK SIGN + HAS_NO_UPPER_CASE_EQUIV DEGREE SIGN, RING ABOVE + HAS_NO_UPPER_CASE_EQUIV PLUS-MINUS SIGN + HAS_NO_UPPER_CASE_EQUIV MICRO SIGN + HAS_NO_UPPER_CASE_EQUIV PILCROW SIGN + HAS_NO_UPPER_CASE_EQUIV MIDDLE DOT + HAS_NO_UPPER_CASE_EQUIV NUMERO SIGN + HAS_NO_UPPER_CASE_EQUIV RIGHT ANGLE QUOTATION MARK + """ + +@pytest.mark.version('>=2.1.7') +@pytest.mark.xfail +def test_core_1431_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_1432.py b/tests/bugs/test_core_1432.py new file mode 100644 index 00000000..340cd1fd --- /dev/null +++ b/tests/bugs/test_core_1432.py @@ -0,0 +1,55 @@ +#coding:utf-8 +# +# id: bugs.core_1432 +# title: Collation not propagated between record formats +# decription: +# tracker_id: CORE-1432 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE DOMAIN D_1250 VARCHAR(10) CHARACTER SET WIN1250 COLLATE WIN1250; +CREATE DOMAIN D_CZ VARCHAR(10) CHARACTER SET WIN1250 COLLATE WIN_CZ; + +CREATE TABLE T (I INTEGER, A D_1250); +INSERT INTO T VALUES(10, 'a'); +COMMIT; +""" + +db_1 = db_factory(page_size=4096, charset='WIN1250', sql_dialect=3, init=init_script_1) + +test_script_1 = """SET COUNT ON; + +SELECT * FROM T WHERE A='A'; + +ALTER TABLE T ALTER A TYPE D_CZ; +commit; + +SELECT * FROM T WHERE A='A'; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Records affected: 0 + + I A +============ ========== + 10 a + +Records affected: 1 +""" + +@pytest.mark.version('>=2.5.0') +def test_core_1432_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1434.py b/tests/bugs/test_core_1434.py new file mode 100644 index 00000000..bcba01a7 --- /dev/null +++ b/tests/bugs/test_core_1434.py @@ -0,0 +1,81 @@ +#coding:utf-8 +# +# id: bugs.core_1434 +# title: Incorrect result with EXECUTE STATEMENT and VARCHAR columns +# decription: Last two bytes of VARCHAR columns are lost. +# tracker_id: CORE-1434 +# min_versions: [] +# versions: 2.0.2 +# qmid: bugs.core_1434 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set term ^; + execute block returns (res varchar(31)) + as + begin + for execute statement + 'select cast(rdb$relation_name as varchar(24)) ' + || ' from rdb$relations r where r.rdb$system_flag = 1 and r.rdb$relation_name NOT starting with ''MON$''' + || ' order by rdb$relation_id rows 30' + into :res + do + suspend; + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RES RDB$PAGES + RES RDB$DATABASE + RES RDB$FIELDS + RES RDB$INDEX_SEGMENTS + RES RDB$INDICES + RES RDB$RELATION_FIELDS + RES RDB$RELATIONS + RES RDB$VIEW_RELATIONS + RES RDB$FORMATS + RES RDB$SECURITY_CLASSES + RES RDB$FILES + RES RDB$TYPES + RES RDB$TRIGGERS + RES RDB$DEPENDENCIES + RES RDB$FUNCTIONS + RES RDB$FUNCTION_ARGUMENTS + RES RDB$FILTERS + RES RDB$TRIGGER_MESSAGES + RES RDB$USER_PRIVILEGES + RES RDB$TRANSACTIONS + RES RDB$GENERATORS + RES RDB$FIELD_DIMENSIONS + RES RDB$RELATION_CONSTRAINTS + RES RDB$REF_CONSTRAINTS + RES RDB$CHECK_CONSTRAINTS + RES RDB$LOG_FILES + RES RDB$PROCEDURES + RES RDB$PROCEDURE_PARAMETERS + RES RDB$CHARACTER_SETS + RES RDB$COLLATIONS + """ + +@pytest.mark.version('>=2.0.2') +def test_core_1434_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1436.py b/tests/bugs/test_core_1436.py new file mode 100644 index 00000000..d96d4182 --- /dev/null +++ b/tests/bugs/test_core_1436.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: bugs.core_1436 +# title: Outer joins don't work properly with the MON$ tables +# decription: +# tracker_id: CORE-1436 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1436 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select db.MON$FORCED_WRITES fw + from mon$attachments att + left join mon$database db on db.mon$creation_date = att.mon$timestamp + rows 1; + -- select db.mon$database_name + -- from mon$attachments att + -- left join mon$database db on db.mon$creation_date = att.mon$timestamp; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + FW + """ + +@pytest.mark.version('>=2.1') +def test_core_1436_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1444.py b/tests/bugs/test_core_1444.py new file mode 100644 index 00000000..fd671c30 --- /dev/null +++ b/tests/bugs/test_core_1444.py @@ -0,0 +1,91 @@ +#coding:utf-8 +# +# id: bugs.core_1444 +# title: Execute statement 'select ....' into new.... +# decription: +# tracker_id: CORE-1444 +# min_versions: [] +# versions: 2.0.2 +# qmid: bugs.core_1444 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE EXCEPTION DEXC '???'; + +CREATE TABLE TEST +( + C1 char(31), + C2 char(31) +); + +commit; + +SET TERM ^ ; + +CREATE TRIGGER TEST_BI FOR TEST +ACTIVE BEFORE INSERT POSITION 20 +AS +declare variable sql varchar(30000); +declare variable wrk_c1 char(31); +declare variable wrk_c2 char(31); +BEGIN + /* when new.c1,new.... isn't NULL -> execute statement work ok. + when new.c1,new.c2, is null -> execute statement has some problem */ + + sql=' select first 1 RDB$CHARACTER_SET_NAME,RDB$DEFAULT_COLLATE_NAME + from RDB$CHARACTER_SETS + where RDB$CHARACTER_SET_NAME is not null'; + + execute statement sql + into new.c1,new.c2; + + select first 1 RDB$CHARACTER_SET_NAME,RDB$DEFAULT_COLLATE_NAME + from RDB$CHARACTER_SETS + where RDB$CHARACTER_SET_NAME is not null + into :wrk_c1,:wrk_c2; + + if (wrk_c1 is not null and + new.c1 is null) then + exception dexc 'Is it a bug ? I think yes, it is.'; +END +^ +set term ; ^ + +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """/* Bug */ +insert into test(C1,C2) values (NULL,NULL); + +/* OK */ +insert into test(C1,C2) values ('A','A'); + +commit; + +select * from test; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +C1 C2 +=============================== =============================== +NONE NONE +NONE NONE + +""" + +@pytest.mark.version('>=2.0.2') +def test_core_1444_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1451.py b/tests/bugs/test_core_1451.py new file mode 100644 index 00000000..260e886c --- /dev/null +++ b/tests/bugs/test_core_1451.py @@ -0,0 +1,52 @@ +#coding:utf-8 +# +# id: bugs.core_1451 +# title: Using RDB$DB_KEY in where section while selecting from a procedure crashes the server +# decription: +# tracker_id: CORE-1451 +# min_versions: [] +# versions: 2.5.0 +# qmid: bugs.core_1451-250 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [('line\\s[0-9]+,', 'line x'), ('column\\s[0-9]+', 'column y')] + +init_script_1 = """SET TERM ^; +create procedure test_proc +returns (A INTEGER) +as +begin + A = 1; + SUSPEND; +end^ +SET TERM ;^ +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select * from test_proc +where rdb$db_key is not null; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42S22 +Dynamic SQL Error +-SQL error code = -206 +-Column unknown +-DB_KEY +-At line 2, column 7 +""" + +@pytest.mark.version('>=2.5.0') +def test_core_1451_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_1453.py b/tests/bugs/test_core_1453.py new file mode 100644 index 00000000..e638f8e2 --- /dev/null +++ b/tests/bugs/test_core_1453.py @@ -0,0 +1,61 @@ +#coding:utf-8 +# +# id: bugs.core_1453 +# title: Allow usage of functions in LIST delimiter parameter +# decription: +# tracker_id: CORE-1443 +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """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_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select ID, LIST( trim(NAME), ASCII_CHAR(35) ) +from T1 +group by 1; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Database: localhost:C:\\Users\\win7\\Firebird_tests\\fbt-repository\\tmp\\bugs.core_1453.fdb, User: SYSDBA +SQL> CON> CON> + ID LIST +============ ================= + 1 0:1 +============================================================================== +LIST: +ORANGE#LEMON#APPLE +============================================================================== + 2 0:2 +============================================================================== +LIST: +PEAR#ORANGE#APPLE +============================================================================== + +SQL>""" + +@pytest.mark.version('>=2.5.0') +def test_core_1453_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1454.py b/tests/bugs/test_core_1454.py new file mode 100644 index 00000000..61018486 --- /dev/null +++ b/tests/bugs/test_core_1454.py @@ -0,0 +1,81 @@ +#coding:utf-8 +# +# id: bugs.core_1454 +# title: ALTER mechanism for computed fields +# decription: Computed field had a lot of inconsistencies and problems +# It's possible to use a explicit type, but only together with a (new) computed expression. +# cf core-0847 +# tracker_id: CORE-1454 +# min_versions: ['2.5'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table t ( + f1 varchar(10), + f2 varchar(10), + cf computed by (f1 || ' - ' || f2) + ); + + insert into t (f1,f2) values ('0123456789','abcdefghij'); + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set width fld_name 31; + set width fld_expr 80; + + select f1,f2,cf from t; + + select b.rdb$field_name fld_name, cast(a.rdb$computed_source as varchar(80)) fld_expr, a.rdb$field_length fld_length + 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'); + + alter table t alter cf type varchar(30) computed by (f1 || ' - ' || f2 || ' - more'); + commit; + + select f1,f2,cf from t; + + select b.rdb$field_name fld_name, cast(a.rdb$computed_source as varchar(80)) fld_expr, a.rdb$field_length fld_length + 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'); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F1 0123456789 + F2 abcdefghij + CF 0123456789 - abcdefghij + FLD_NAME CF + FLD_EXPR (f1 || ' - ' || f2) + FLD_LENGTH 23 + F1 0123456789 + F2 abcdefghij + CF 0123456789 - abcdefghij - more + FLD_NAME CF + FLD_EXPR (f1 || ' - ' || f2 || ' - more') + FLD_LENGTH 30 + """ + +@pytest.mark.version('>=2.5.0') +def test_core_1454_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1462.py b/tests/bugs/test_core_1462.py new file mode 100644 index 00000000..35e95be7 --- /dev/null +++ b/tests/bugs/test_core_1462.py @@ -0,0 +1,298 @@ +#coding:utf-8 +# +# id: bugs.core_1462 +# title: Server crash caused by a buffer overrun in the optimizer when more than 255 relation references exist in the query +# decription: +# tracker_id: CORE-1462 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_1462-21 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table test (i integer); +create index test_i on test(i); +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select test.i from test + inner join test as t1 on t1.i = test.i + inner join test as t2 on t2.i = test.i + inner join test as t3 on t3.i = test.i + inner join test as t4 on t4.i = test.i + inner join test as t5 on t5.i = test.i + inner join test as t6 on t6.i = test.i + inner join test as t7 on t7.i = test.i + inner join test as t8 on t8.i = test.i + inner join test as t9 on t9.i = test.i + inner join test as t10 on t10.i = test.i + inner join test as t11 on t11.i = test.i + inner join test as t12 on t12.i = test.i + inner join test as t13 on t13.i = test.i + inner join test as t14 on t14.i = test.i + inner join test as t15 on t15.i = test.i + inner join test as t16 on t16.i = test.i + inner join test as t17 on t17.i = test.i + inner join test as t18 on t18.i = test.i + inner join test as t19 on t19.i = test.i + inner join test as t20 on t20.i = test.i + inner join test as t21 on t21.i = test.i + inner join test as t22 on t22.i = test.i + inner join test as t23 on t23.i = test.i + inner join test as t24 on t24.i = test.i + inner join test as t25 on t25.i = test.i + inner join test as t26 on t26.i = test.i + inner join test as t27 on t27.i = test.i + inner join test as t28 on t28.i = test.i + inner join test as t29 on t29.i = test.i + inner join test as t30 on t30.i = test.i + inner join test as t31 on t31.i = test.i + inner join test as t32 on t32.i = test.i + inner join test as t33 on t33.i = test.i + inner join test as t34 on t34.i = test.i + inner join test as t35 on t35.i = test.i + inner join test as t36 on t36.i = test.i + inner join test as t37 on t37.i = test.i + inner join test as t38 on t38.i = test.i + inner join test as t39 on t39.i = test.i + inner join test as t40 on t40.i = test.i + inner join test as t41 on t41.i = test.i + inner join test as t42 on t42.i = test.i + inner join test as t43 on t43.i = test.i + inner join test as t44 on t44.i = test.i + inner join test as t45 on t45.i = test.i + inner join test as t46 on t46.i = test.i + inner join test as t47 on t47.i = test.i + inner join test as t48 on t48.i = test.i + inner join test as t49 on t49.i = test.i + inner join test as t50 on t50.i = test.i + inner join test as t51 on t51.i = test.i + inner join test as t52 on t52.i = test.i + inner join test as t53 on t53.i = test.i + inner join test as t54 on t54.i = test.i + inner join test as t55 on t55.i = test.i + inner join test as t56 on t56.i = test.i + inner join test as t57 on t57.i = test.i + inner join test as t58 on t58.i = test.i + inner join test as t59 on t59.i = test.i + inner join test as t60 on t60.i = test.i + inner join test as t61 on t61.i = test.i + inner join test as t62 on t62.i = test.i + inner join test as t63 on t63.i = test.i + inner join test as t64 on t64.i = test.i + inner join test as t65 on t65.i = test.i + inner join test as t66 on t66.i = test.i + inner join test as t67 on t67.i = test.i + inner join test as t68 on t68.i = test.i + inner join test as t69 on t69.i = test.i + inner join test as t70 on t70.i = test.i + inner join test as t71 on t71.i = test.i + inner join test as t72 on t72.i = test.i + inner join test as t73 on t73.i = test.i + inner join test as t74 on t74.i = test.i + inner join test as t75 on t75.i = test.i + inner join test as t76 on t76.i = test.i + inner join test as t77 on t77.i = test.i + inner join test as t78 on t78.i = test.i + inner join test as t79 on t79.i = test.i + inner join test as t80 on t80.i = test.i + inner join test as t81 on t81.i = test.i + inner join test as t82 on t82.i = test.i + inner join test as t83 on t83.i = test.i + inner join test as t84 on t84.i = test.i + inner join test as t85 on t85.i = test.i + inner join test as t86 on t86.i = test.i + inner join test as t87 on t87.i = test.i + inner join test as t88 on t88.i = test.i + inner join test as t89 on t89.i = test.i + inner join test as t90 on t90.i = test.i + inner join test as t91 on t91.i = test.i + inner join test as t92 on t92.i = test.i + inner join test as t93 on t93.i = test.i + inner join test as t94 on t94.i = test.i + inner join test as t95 on t95.i = test.i + inner join test as t96 on t96.i = test.i + inner join test as t97 on t97.i = test.i + inner join test as t98 on t98.i = test.i + inner join test as t99 on t99.i = test.i + inner join test as t100 on t100.i = test.i + inner join test as t101 on t101.i = test.i + inner join test as t102 on t102.i = test.i + inner join test as t103 on t103.i = test.i + inner join test as t104 on t104.i = test.i + inner join test as t105 on t105.i = test.i + inner join test as t106 on t106.i = test.i + inner join test as t107 on t107.i = test.i + inner join test as t108 on t108.i = test.i + inner join test as t109 on t109.i = test.i + inner join test as t110 on t110.i = test.i + inner join test as t111 on t111.i = test.i + inner join test as t112 on t112.i = test.i + inner join test as t113 on t113.i = test.i + inner join test as t114 on t114.i = test.i + inner join test as t115 on t115.i = test.i + inner join test as t116 on t116.i = test.i + inner join test as t117 on t117.i = test.i + inner join test as t118 on t118.i = test.i + inner join test as t119 on t119.i = test.i + inner join test as t120 on t120.i = test.i + inner join test as t121 on t121.i = test.i + inner join test as t122 on t122.i = test.i + inner join test as t123 on t123.i = test.i + inner join test as t124 on t124.i = test.i + inner join test as t125 on t125.i = test.i + inner join test as t126 on t126.i = test.i + inner join test as t127 on t127.i = test.i + inner join test as t128 on t128.i = test.i + inner join test as t129 on t129.i = test.i + inner join test as t130 on t130.i = test.i + inner join test as t131 on t131.i = test.i + inner join test as t132 on t132.i = test.i + inner join test as t133 on t133.i = test.i + inner join test as t134 on t134.i = test.i + inner join test as t135 on t135.i = test.i + inner join test as t136 on t136.i = test.i + inner join test as t137 on t137.i = test.i + inner join test as t138 on t138.i = test.i + inner join test as t139 on t139.i = test.i + inner join test as t140 on t140.i = test.i + inner join test as t141 on t141.i = test.i + inner join test as t142 on t142.i = test.i + inner join test as t143 on t143.i = test.i + inner join test as t144 on t144.i = test.i + inner join test as t145 on t145.i = test.i + inner join test as t146 on t146.i = test.i + inner join test as t147 on t147.i = test.i + inner join test as t148 on t148.i = test.i + inner join test as t149 on t149.i = test.i + inner join test as t150 on t150.i = test.i + inner join test as t151 on t151.i = test.i + inner join test as t152 on t152.i = test.i + inner join test as t153 on t153.i = test.i + inner join test as t154 on t154.i = test.i + inner join test as t155 on t155.i = test.i + inner join test as t156 on t156.i = test.i + inner join test as t157 on t157.i = test.i + inner join test as t158 on t158.i = test.i + inner join test as t159 on t159.i = test.i + inner join test as t160 on t160.i = test.i + inner join test as t161 on t161.i = test.i + inner join test as t162 on t162.i = test.i + inner join test as t163 on t163.i = test.i + inner join test as t164 on t164.i = test.i + inner join test as t165 on t165.i = test.i + inner join test as t166 on t166.i = test.i + inner join test as t167 on t167.i = test.i + inner join test as t168 on t168.i = test.i + inner join test as t169 on t169.i = test.i + inner join test as t170 on t170.i = test.i + inner join test as t171 on t171.i = test.i + inner join test as t172 on t172.i = test.i + inner join test as t173 on t173.i = test.i + inner join test as t174 on t174.i = test.i + inner join test as t175 on t175.i = test.i + inner join test as t176 on t176.i = test.i + inner join test as t177 on t177.i = test.i + inner join test as t178 on t178.i = test.i + inner join test as t179 on t179.i = test.i + inner join test as t180 on t180.i = test.i + inner join test as t181 on t181.i = test.i + inner join test as t182 on t182.i = test.i + inner join test as t183 on t183.i = test.i + inner join test as t184 on t184.i = test.i + inner join test as t185 on t185.i = test.i + inner join test as t186 on t186.i = test.i + inner join test as t187 on t187.i = test.i + inner join test as t188 on t188.i = test.i + inner join test as t189 on t189.i = test.i + inner join test as t190 on t190.i = test.i + inner join test as t191 on t191.i = test.i + inner join test as t192 on t192.i = test.i + inner join test as t193 on t193.i = test.i + inner join test as t194 on t194.i = test.i + inner join test as t195 on t195.i = test.i + inner join test as t196 on t196.i = test.i + inner join test as t197 on t197.i = test.i + inner join test as t198 on t198.i = test.i + inner join test as t199 on t199.i = test.i + inner join test as t200 on t200.i = test.i + inner join test as t201 on t201.i = test.i + inner join test as t202 on t202.i = test.i + inner join test as t203 on t203.i = test.i + inner join test as t204 on t204.i = test.i + inner join test as t205 on t205.i = test.i + inner join test as t206 on t206.i = test.i + inner join test as t207 on t207.i = test.i + inner join test as t208 on t208.i = test.i + inner join test as t209 on t209.i = test.i + inner join test as t210 on t210.i = test.i + inner join test as t211 on t211.i = test.i + inner join test as t212 on t212.i = test.i + inner join test as t213 on t213.i = test.i + inner join test as t214 on t214.i = test.i + inner join test as t215 on t215.i = test.i + inner join test as t216 on t216.i = test.i + inner join test as t217 on t217.i = test.i + inner join test as t218 on t218.i = test.i + inner join test as t219 on t219.i = test.i + inner join test as t220 on t220.i = test.i + inner join test as t221 on t221.i = test.i + inner join test as t222 on t222.i = test.i + inner join test as t223 on t223.i = test.i + inner join test as t224 on t224.i = test.i + inner join test as t225 on t225.i = test.i + inner join test as t226 on t226.i = test.i + inner join test as t227 on t227.i = test.i + inner join test as t228 on t228.i = test.i + inner join test as t229 on t229.i = test.i + inner join test as t230 on t230.i = test.i + inner join test as t231 on t231.i = test.i + inner join test as t232 on t232.i = test.i + inner join test as t233 on t233.i = test.i + inner join test as t234 on t234.i = test.i + inner join test as t235 on t235.i = test.i + inner join test as t236 on t236.i = test.i + inner join test as t237 on t237.i = test.i + inner join test as t238 on t238.i = test.i + inner join test as t239 on t239.i = test.i + inner join test as t240 on t240.i = test.i + inner join test as t241 on t241.i = test.i + inner join test as t242 on t242.i = test.i + inner join test as t243 on t243.i = test.i + inner join test as t244 on t244.i = test.i + inner join test as t245 on t245.i = test.i + inner join test as t246 on t246.i = test.i + inner join test as t247 on t247.i = test.i + inner join test as t248 on t248.i = test.i + inner join test as t249 on t249.i = test.i + inner join test as t250 on t250.i = test.i + inner join test as t251 on t251.i = test.i + inner join test as t252 on t252.i = test.i + inner join test as t253 on t253.i = test.i + inner join test as t254 on t254.i = test.i + inner join test as t255 on t255.i = test.i + inner join test as t256 on t256.i = test.i + ; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 54001 +Dynamic SQL Error +-Too many Contexts of Relation/Procedure/Views. Maximum allowed is 256 +""" + +@pytest.mark.version('>=3.0') +def test_core_1462_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_1482.py b/tests/bugs/test_core_1482.py new file mode 100644 index 00000000..1b90ee98 --- /dev/null +++ b/tests/bugs/test_core_1482.py @@ -0,0 +1,82 @@ +#coding:utf-8 +# +# id: bugs.core_1482 +# title: Make optimizer to consider ORDER BY optimization when making decision about join order +# decription: +# tracker_id: CORE-1482 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table tcolor(id int , name varchar(20) ); + recreate table thorses(id int, color_id int, name varchar(20)); + commit; + + set term ^; + execute block as + declare i int; + declare n_main int = 50; + declare ratio int = 1000; + begin + i = 0; + while (i < n_main) do + begin + i = i + 1; + insert into tcolor(id, name) + values (:i, 'color #' || :i); + end + i = 0; + while (i < n_main * ratio) do + begin + i = i + 1; + insert into thorses(id, color_id, name) + values (:i, mod(:i, :n_main)+1, 'horse #' || :i); + end + end + ^ + set term ;^ + commit; + + create index tcolor_id on tcolor(id); + create index thorses_color_id on thorses(color_id); + -- this index was forgotten in previous revisions: + create index thorses_id on thorses(id); + commit; + + set list on; + select (select count(*) from tcolor) colors_cnt, (select count(*) from thorses) horses_cnt + from rdb$database; + set planonly; + -- in 2.1 and 2.5: PLAN SORT (JOIN (M NATURAL, D INDEX (THORSES_COLOR_ID))) -- doesn`t see 'rows 1' + -- in 3.0 plan should CHANGE and take in account 'rows N' limit: + select * from tcolor m join thorses d on m.id = d.color_id order by d.id rows 1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + COLORS_CNT 50 + HORSES_CNT 50000 + + PLAN JOIN (D ORDER THORSES_ID, M INDEX (TCOLOR_ID)) + """ + +@pytest.mark.version('>=3.0') +def test_core_1482_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1489.py b/tests/bugs/test_core_1489.py new file mode 100644 index 00000000..f56ab77d --- /dev/null +++ b/tests/bugs/test_core_1489.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: bugs.core_1489 +# title: DATEADD wrong work with NULL arguments +# decription: +# tracker_id: CORE-1489 +# min_versions: [] +# versions: 2.1.0 +# qmid: bugs.core_1489 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT 1, DATEADD(SECOND, Null, CAST('01.01.2007' AS DATE)) FROM RDB$DATABASE; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CONSTANT DATEADD +============ =========== + 1 + +""" + +@pytest.mark.version('>=2.1.0') +def test_core_1489_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1492.py b/tests/bugs/test_core_1492.py new file mode 100644 index 00000000..ab58598e --- /dev/null +++ b/tests/bugs/test_core_1492.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_1492 +# title: BLOB isn't compatible with [VAR]CHAR in COALESCE +# decription: +# tracker_id: CORE-1492 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1492 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [('B_BLOB.*', 'B_BLOB')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table t (id int primary key, b blob sub_type text ); + commit; + + insert into t(id, b) values (1, NULL); + insert into t(id, b) values (2, 'QWER'); + commit; + + set list on; + select coalesce(b, '') as b_blob + from t + order by id; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + B_BLOB 0:1 + B_BLOB 82:1e0 + QWER + """ + +@pytest.mark.version('>=2.1') +def test_core_1492_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1497.py b/tests/bugs/test_core_1497.py new file mode 100644 index 00000000..044e6d92 --- /dev/null +++ b/tests/bugs/test_core_1497.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: bugs.core_1497 +# title: New builtin function DATEADD() implements wrong choice of keywords for expanded syntax +# decription: +# tracker_id: CORE-1497 +# min_versions: ['2.1.0'] +# versions: 2.1.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT DATEADD(1 DAY TO date '29-Feb-2012') +,DATEADD(1 MONTH TO date '29-Feb-2012') +,DATEADD(1 YEAR TO date '29-Feb-2012') +FROM RDB$DATABASE;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Database: localhost:C: btest2 mpugs.core_1497.fdb, User: SYSDBA +SQL> CON> CON> CON> + DATEADD DATEADD DATEADD +=========== =========== =========== +2012-03-01 2012-03-29 2013-02-28 + +SQL>""" + +@pytest.mark.version('>=2.1.0') +def test_core_1497_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1506.py b/tests/bugs/test_core_1506.py new file mode 100644 index 00000000..cf5252bd --- /dev/null +++ b/tests/bugs/test_core_1506.py @@ -0,0 +1,66 @@ +#coding:utf-8 +# +# id: bugs.core_1506 +# title: Server crash with isc_dsql_execute_immediate and zero length string +# decription: +# Confirmed on 2.1.0.17798, got: +# Error while executing SQL statement: +# +# - SQLCODE: -902 +# +# - Unable to complete network request to host "localhost". +# +# - Error reading data from the connection. +# -902, 335544721) +# firebird.log contains only this: +# CSPROG Sat Mar 10 19:13:29 2018 +# INET/inet_error: read errno = 10054 +# +# Checked on: +# 2.5.9.27107: OK, 0.297s. +# 3.0.4.32924: OK, 1.562s. +# 4.0.0.918: OK, 1.735s. +# +# NB: FB 3.+ contain TWO messages with almost the same text about SQLSTATE = -104. +# Second line is filtered out - see 'substitutions' section. +# +# tracker_id: CORE-1506 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('- SQL error code.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# try: +# db_conn.execute_immediate('') +# except Exception, e: +# print( e[0] ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Error while executing SQL statement: + - SQLCODE: -104 + - Unexpected end of command + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_1506_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_1509.py b/tests/bugs/test_core_1509.py new file mode 100644 index 00000000..7347c457 --- /dev/null +++ b/tests/bugs/test_core_1509.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_1509 +# title: Conversion from double to varchar insert trailing spaces +# decription: +# Confirmed bug on WI-V2.0.0.12724: output of cast(cast(0e0 as double precision) as varchar(32))||'z' +# is: |0.0000000000000000 z| (four spaces inside) +# +# tracker_id: CORE-1509 +# min_versions: [] +# versions: 2.5.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select + iif( position(' z' in t1)>0, 'BAD: >' || t1 || '<', 'OK.') as chk1 + ,iif( position(' z' in t2)>0, 'BAD: >' || t2 || '<', 'OK.') as chk2 + ,iif( position(' z' in t3)>0, 'BAD: >' || t3 || '<', 'OK.') as chk3 + from ( + select + cast(exp(-744.0346068132731393)-exp(-745.1332191019410399) as varchar(32))||'z' t1 + ,cast(sin(0) as varchar(32))||'z' t2 + ,cast(cast(0e0 as double precision) as varchar(32))||'z' t3 + from rdb$database + ); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CHK1 OK. + CHK2 OK. + CHK3 OK. + """ + +@pytest.mark.version('>=2.5.0') +def test_core_1509_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1510.py b/tests/bugs/test_core_1510.py new file mode 100644 index 00000000..a64268ed --- /dev/null +++ b/tests/bugs/test_core_1510.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: bugs.core_1510 +# title: Bad XSQLVAR [NULL flags] for (2*COALESCE(NULL,NULL)) +# decription: +# tracker_id: CORE-1510 +# min_versions: ['2.1.7'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!sqltype).)*$', ''), ('[ ]+', ' '), ('[\t]*', ' '), ('charset:.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set sqlda_display; + select 2*COALESCE(NULL,NULL) from RDB$DATABASE; + select 2*IIF(NULL is NULL, NULL, NULL) from RDB$DATABASE; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 01: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + 01: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + """ + +@pytest.mark.version('>=3.0') +def test_core_1510_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1511.py b/tests/bugs/test_core_1511.py new file mode 100644 index 00000000..4b2fab51 --- /dev/null +++ b/tests/bugs/test_core_1511.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: bugs.core_1511 +# title: POSITION(string_exp1, string_exp2 [, start]) +# decription: +# tracker_id: CORE-1511 +# min_versions: ['2.1.0'] +# versions: 2.1.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT position ('be', 'To be or not to be') +,position ('be', 'To be or not to be', 4) +,position ('be', 'To be or not to be', 8) +,position ('be', 'To be or not to be', 18) +FROM RDB$DATABASE;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Database: localhost:C: btest2 mpugs.core_1511.fdb, User: SYSDBA +SQL> CON> CON> CON> CON> + POSITION POSITION POSITION POSITION +============ ============ ============ ============ + 4 4 17 0 + +SQL>""" + +@pytest.mark.version('>=2.1.0') +def test_core_1511_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1512.py b/tests/bugs/test_core_1512.py new file mode 100644 index 00000000..2d91f8bc --- /dev/null +++ b/tests/bugs/test_core_1512.py @@ -0,0 +1,126 @@ +#coding:utf-8 +# +# id: bugs.core_1512 +# title: Connection lost running script +# decription: +# tracker_id: CORE-1512 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='ISO8859_1', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Confirmed crash on WI-V2.1.7.18553 for: CREATE TABLE FHO_OS(...) + + CREATE DOMAIN DM_COD AS + NUMERIC(4,0); + + CREATE DOMAIN DM_COD2 AS + NUMERIC(8,0); + + CREATE DOMAIN DM_DES AS + VARCHAR(80) + COLLATE PT_PT; + + CREATE DOMAIN DM_FONE AS + VARCHAR(20) + COLLATE PT_PT; + + CREATE DOMAIN DM_ID AS + NUMERIC(4,0); + + CREATE DOMAIN DM_ID2 AS + NUMERIC(8,0); + + CREATE DOMAIN DM_IMG AS + BLOB SUB_TYPE 0 SEGMENT SIZE 4096; + + CREATE DOMAIN DM_IND AS + CHAR(1) + COLLATE PT_PT; + + CREATE DOMAIN DM_IND2 AS + CHAR(2) + COLLATE PT_PT; + + CREATE DOMAIN DM_NM AS + VARCHAR(80) + COLLATE PT_PT; + + CREATE DOMAIN DM_PWS AS + VARCHAR(10) + COLLATE PT_PT; + + CREATE DOMAIN DM_TP AS + CHAR(1) + COLLATE PT_PT; + + CREATE DOMAIN DM_TXT AS + BLOB SUB_TYPE 1 SEGMENT SIZE 4096; + + CREATE TABLE FHO_ATIV_TEC ( + COD_USUARIO DM_COD NOT NULL, + DT_INICIO TIMESTAMP NOT NULL, + DT_TERMINO TIMESTAMP, + COD_ATIVIDADE DM_COD2 NOT NULL, + ID_OS DM_ID2 + ); + + CREATE TABLE FHO_OS ( + ID_OS DM_ID2 NOT NULL, + DT_INICIO TIMESTAMP NOT NULL, + DT_TERMINO TIMESTAMP, + COD_FICHA DM_COD2, + COD_USUARIO DM_COD NOT NULL, + COD_ATIVIDADE DM_COD2 NOT NULL, + COD_PROJETO DM_COD2, + TXT_DESCRICAO DM_TXT, + IND_PENDENTE DM_IND NOT NULL, + IND_CANCELADO DM_IND NOT NULL, + ID_OS_ORIGEM DM_ID2, + COD_USUARIO_ENVIOU DM_COD, + NRO_PRIORIDADE INTEGER, + PERC_FATURAR NUMERIC(5,2), + TXT_DESCRICAO_TECNICA DM_TXT, + DT_PREVISAO_TERMINO DATE, + NM_CONTATO DM_NM, + IND_EXIBE_RELEASE DM_IND, + HRS_ORCAMENTO NUMERIC(5,2), + IND_STATUS COMPUTED BY (CASE WHEN (FHO_OS.IND_CANCELADO <> 'N') THEN + 'CANCELADA' + WHEN (SELECT FIRST 1 (CASE WHEN T.DT_TERMINO IS NULL THEN 1 END) FROM FHO_ATIV_TEC T + WHERE (T.COD_USUARIO = FHO_OS.COD_USUARIO) AND (T.ID_OS = FHO_OS.ID_OS) ORDER BY T.DT_INICIO DESC) IS NOT NULL THEN + 'EM USO' + WHEN (FHO_OS.DT_TERMINO IS NULL) THEN + 'ABERTA' + WHEN (FHO_OS.IND_PENDENTE = 'S') THEN + 'PENDENTE' + ELSE + 'FECHADA' + END), + COD_TP_OS DM_COD, + HRS_CONTRATO NUMERIC(5,2), + HRS_PREVISAO_TERMINO NUMERIC(5,2), + PERC_HORA_MAQUINA NUMERIC(5,2) + ); + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5') +def test_core_1512_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_1514.py b/tests/bugs/test_core_1514.py new file mode 100644 index 00000000..57441054 --- /dev/null +++ b/tests/bugs/test_core_1514.py @@ -0,0 +1,183 @@ +#coding:utf-8 +# +# id: bugs.core_1514 +# title: Many new 2.1 built in functions have incorrect NULL semantics +# decription: +# tracker_id: CORE-1514 +# min_versions: [] +# versions: 2.5 +# qmid: bugs.core_1514 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT ABS(null) from rdb$database; +SELECT ACOS(null) from rdb$database; +SELECT ASCII_VAL(null) from rdb$database; +SELECT ASIN(null) from rdb$database; +SELECT ATAN(null) from rdb$database; +SELECT ATAN2(null,null) from rdb$database; +SELECT BIN_AND(null,null) from rdb$database; +SELECT BIN_OR(null,null) from rdb$database; +SELECT BIN_XOR(null,null) from rdb$database; +SELECT COS(null) from rdb$database; +SELECT COSH(null) from rdb$database; +SELECT COT(null) from rdb$database; +SELECT dateadd(year, null, current_date) from rdb$database; +SELECT FLOOR(null) from rdb$database; +SELECT LN(null) from rdb$database; +SELECT LOG(null,null) from rdb$database; +SELECT LOG10(null) from rdb$database; +SELECT MOD(null,null) from rdb$database; +SELECT SIGN(null) from rdb$database; +SELECT SIN(null) from rdb$database; +SELECT SINH(null) from rdb$database; +SELECT SQRT(null) from rdb$database; +SELECT TAN(null) from rdb$database; +SELECT TANH(null) from rdb$database; +select trunc(1, cast(null as integer)) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ABS +============ + + + + ACOS +======================= + + + +ASCII_VAL +========= + + + + ASIN +======================= + + + + ATAN +======================= + + + + ATAN2 +======================= + + + + BIN_AND +============ + + + + BIN_OR +============ + + + + BIN_XOR +============ + + + + COS +======================= + + + + COSH +======================= + + + + COT +======================= + + + + DATEADD +=========== + + + + FLOOR +============ + + + + LN +======================= + + + + LOG +======================= + + + + LOG10 +======================= + + + + MOD +============ + + + + SIGN +======= + + + + SIN +======================= + + + + SINH +======================= + + + + SQRT +======================= + + + + TAN +======================= + + + + TANH +======================= + + + + TRUNC +============ + + +""" + +@pytest.mark.version('>=2.5') +def test_core_1514_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1518.py b/tests/bugs/test_core_1518.py new file mode 100644 index 00000000..99e5ccf6 --- /dev/null +++ b/tests/bugs/test_core_1518.py @@ -0,0 +1,75 @@ +#coding:utf-8 +# +# id: bugs.core_1518 +# title: Adding a non-null restricted column to a populated table renders the table inconsistent +# decription: +# tracker_id: CORE-1518 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + -- 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_nn int not null; + create table test(c1 int); + commit; + insert into test(c1) values (null); + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Source sample in the ticket: + -- create table dyd(c1 integer), insert one record with value = 1. + -- alter table dyd add c2 integer not null ==> did not raise exception but should. + + + -- All these statements should produce exception in 3.0: + alter table test alter c1 set not null; + alter table test alter c1 type dm_nn; + alter table test add c2 int not null; -- this also check for core-2696 ("alter table" command can add a field which has "not null" definition) + alter table test add c3 dm_nn; + + -- still passed on 3.0 (does not verifies old data on new check condition): + -- alter table test add constraint test_nn check(c1 is not null); -- :((( + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22006 + unsuccessful metadata update + -Cannot make field C1 of table TEST NOT NULL because there are NULLs present + + Statement failed, SQLSTATE = 22006 + unsuccessful metadata update + -Cannot make field C1 of table TEST NOT NULL because there are NULLs present + + Statement failed, SQLSTATE = 22006 + unsuccessful metadata update + -Cannot make field C2 of table TEST NOT NULL because there are NULLs present + + Statement failed, SQLSTATE = 22006 + unsuccessful metadata update + -Cannot make field C3 of table TEST NOT NULL because there are NULLs present + """ + +@pytest.mark.version('>=3.0') +def test_core_1518_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_152.py b/tests/bugs/test_core_152.py new file mode 100644 index 00000000..7788c28a --- /dev/null +++ b/tests/bugs/test_core_152.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: bugs.core_152 +# title: Sqlsubtype incorrect on timestamp math, constant arithmetic +# decription: +# tracker_id: CORE-152 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_152 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!sqltype|DTS_DIFF).)*$', ''), ('[ ]+', ' '), ('[\t]*', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set sqlda_display; + set list on; + select current_timestamp - current_timestamp dts_diff from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 01: sqltype: 580 INT64 scale: -9 subtype: 1 len: 8 + : name: SUBTRACT alias: DTS_DIFF + DTS_DIFF 0.000000000 + """ + +@pytest.mark.version('>=3.0') +def test_core_152_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1522.py b/tests/bugs/test_core_1522.py new file mode 100644 index 00000000..c2e1082a --- /dev/null +++ b/tests/bugs/test_core_1522.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_1522 +# title: Inconsistent DATEDIFF behaviour +# decription: +# tracker_id: CORE-1522 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1522 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT DATEDIFF(HOUR, CAST('01:59:59' AS TIME), CAST('02:59:58' AS TIME)) FROM RDB$DATABASE; +SELECT DATEDIFF(HOUR, CAST('01:59:59' AS TIME), CAST('02:59:59' AS TIME)) FROM RDB$DATABASE; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DATEDIFF +===================== + 1 + + + DATEDIFF +===================== + 1 + +""" + +@pytest.mark.version('>=2.1') +def test_core_1522_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1525.py b/tests/bugs/test_core_1525.py new file mode 100644 index 00000000..e2f2cbd4 --- /dev/null +++ b/tests/bugs/test_core_1525.py @@ -0,0 +1,75 @@ +#coding:utf-8 +# +# id: bugs.core_1525 +# title: Computed field + index not working in WHERE +# decription: +# tracker_id: +# min_versions: ['2.0.7'] +# versions: 2.0.7 +# qmid: bugs.core_1525 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table test_1 ( + id integer not null, + last_day date, + comp_last_day computed by (coalesce(last_day, cast('2999-12-31' as date))) + ); + + + insert into test_1 values (1, '2007-10-10'); + insert into test_1 values (2, null); + commit; + + set list on; + + select * + from test_1 + where cast ('2007-09-09' as date) < comp_last_day; + + create index idx_1 on test_1 computed by ( coalesce(last_day, cast('2999-12-31' as date)) ); + commit; + set plan on; + + select * + from test_1 + where cast ('2007-09-09' as date) < comp_last_day; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + LAST_DAY 2007-10-10 + COMP_LAST_DAY 2007-10-10 + ID 2 + LAST_DAY + COMP_LAST_DAY 2999-12-31 + + PLAN (TEST_1 INDEX (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 + """ + +@pytest.mark.version('>=2.0.7') +def test_core_1525_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1528.py b/tests/bugs/test_core_1528.py new file mode 100644 index 00000000..53885273 --- /dev/null +++ b/tests/bugs/test_core_1528.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: bugs.core_1528 +# title: Functions DATEDIFF does not work in dialect 1 +# decription: +# tracker_id: CORE-1528 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1528 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=1, init=init_script_1) + +test_script_1 = """SELECT DATEDIFF(DAY, CAST('18.10.2007' AS TIMESTAMP), CAST('23.10.2007' AS TIMESTAMP)) FROM RDB$DATABASE;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DATEDIFF +======================= + 5.000000000000000 + +""" + +@pytest.mark.version('>=2.1') +def test_core_1528_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1533.py b/tests/bugs/test_core_1533.py new file mode 100644 index 00000000..9bcf91ac --- /dev/null +++ b/tests/bugs/test_core_1533.py @@ -0,0 +1,55 @@ +#coding:utf-8 +# +# id: bugs.core_1533 +# title: JOIN on first record of ordered derived table returns wrong record +# decription: +# tracker_id: CORE-1533 +# min_versions: [] +# versions: 2.0.4 +# qmid: bugs.core_1533 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table X ( + ID integer, + DAT DATE +); +commit; +insert into X (ID, DAT) values (1, '2006-05-16'); +insert into X (ID, DAT) values (2, '2004-11-16'); +insert into X (ID, DAT) values (3, '2007-01-01'); +insert into X (ID, DAT) values (4, '2005-07-11'); +commit; +create index IDX_X on X (DAT); +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select X2.ID, x1.ID,x2.dat from X as X2 left join (select first 1 X.ID from X order by X.DAT) X1 on X1.ID=X2.ID; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID ID DAT +============ ============ =========== + 1 2006-05-16 + 2 2 2004-11-16 + 3 2007-01-01 + 4 2005-07-11 + +""" + +@pytest.mark.version('>=2.0.4') +def test_core_1533_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1539.py b/tests/bugs/test_core_1539.py new file mode 100644 index 00000000..445bc943 --- /dev/null +++ b/tests/bugs/test_core_1539.py @@ -0,0 +1,159 @@ +#coding:utf-8 +# +# id: bugs.core_1539 +# title: select * from rdb$triggers where rdb$trigger_source like 'CHECK%' +# decription: +# ::: NOTE ::: +# In order to check correctness of following statements under ISQL itself (NOT under fbt_run), do following: +# 1) open some text editor that supports charset = win1251 and set encoding for new document = WIN1251 +# (e.g. in Notepad++ pull-down menu: "Encoding / Character sets / Cyrillic / Windows 1251") +# 2) type text save to .sql +# 3) open this .sql in FAR editor and ensure that letters are displayed as SINGLE-BYTE characters +# 4) run isql -i +# In order to run this script under fbt_run: +# 1) open Notepad++ new .fbt document and set Encoding = "UTF8 without BOM" +# 2) copy-paste text from , ensure that letters remains readable +# (it should be pasted here in UTF8 encoding) +# 3) add in `expected_stdout` section required output by copy-paste from result of isql -i +# (it should be pasted here in UTF8 encoding) +# 4) save .fbt and ensure that it was saved in UTF8 encoding, otherwise exeption like +# "UnicodeDecodeError: 'utf8' codec can't decode byte 0xc3 in position 621: invalid continuation byte" +# will raise. +# +# +# 02-mar-2021. Re-implemented in ordeer to have ability to run this test on Linux. +# We run 'init_script' using charset = utf8 but then run separate ISQL-process +# with request to establish connection using charset = WIN1251. +# Its output is redirected to separate files. File with results of errors (STDERR) must remain empty. +# If it contain anything, we use codecs.open(..., 'r', 'cp1251') + encode('utf8') to display its content. +# +# Checked on: +# * Windows: 4.0.0.2377, 3.0.8.33420, 2.5.9.27152 +# * Linux: 4.0.0.2377, 3.0.8.33415 +# +# +# tracker_id: CORE-1539 +# min_versions: ['2.1'] +# versions: 2.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + -- ### 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. + recreate table test ( + bugtype varchar(20), + bugfrequency varchar(20), + decision varchar(20), + fixerkey int, + decisiondate date + ); + + alter table test + add constraint test_bugtype check (bugtype in ('зрабіць', 'трэба зрабіць', 'недахоп', 'памылка', 'катастрофа')) + ,add constraint test_bugfrequency check (bugfrequency in ('ніколі', 'зрэдку', 'часам', 'часта', 'заўсёды', 'не прыкладаецца')) + ,add constraint test_decision check (decision in ('адкрыта', 'зроблена', 'састарэла', 'адхілена', 'часткова', 'выдалена')) + ,add constraint test_fixerkey check ((decision = 'адкрыта' and fixerkey is null and decisiondate is null) or (decision <> 'адкрыта' and not fixerkey is null and not decisiondate is null)) + ; + commit; + """ + +db_1 = db_factory(charset='WIN1251', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import time +# import codecs +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# sql_cmd=''' +# set names WIN1251; +# connect '%(dsn)s' user '%(user_name)s' password '%(user_password)s'; +# 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); +# ; +# ''' % dict(globals(), **locals()) +# +# f_sql_chk = open( os.path.join(context['temp_directory'],'tmp_1539_run.sql'), 'w') +# f_sql_chk.write(sql_cmd) +# flush_and_close( f_sql_chk ) +# +# f_sql_log = open( ''.join( (os.path.splitext(f_sql_chk.name)[0], '.log' ) ), 'w') +# f_sql_err = open( ''.join( (os.path.splitext(f_sql_chk.name)[0], '.err' ) ), 'w') +# subprocess.call( [ context['isql_path'], '-q', '-i', f_sql_chk.name ], stdout = f_sql_log, stderr = f_sql_err) +# flush_and_close( f_sql_log ) +# flush_and_close( f_sql_err ) +# +# # If any error occurs --> open .err file and convert messages from there (encoded in win1251) to utf-8: +# # +# with codecs.open(f_sql_err.name,'r', encoding='cp1251') as f: +# for line in f: +# if line: +# print( 'Unexpected STDERR, line: %s' % line.encode('utf-8') ) +# +# cleanup( (f_sql_chk, f_sql_log, f_sql_err) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1') +@pytest.mark.xfail +def test_core_1539_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_1544.py b/tests/bugs/test_core_1544.py new file mode 100644 index 00000000..a78d3c3a --- /dev/null +++ b/tests/bugs/test_core_1544.py @@ -0,0 +1,62 @@ +#coding:utf-8 +# +# id: bugs.core_1544 +# title: RDB$procedures generator overflow +# decription: +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- ::: WARNING ::: This code executes about ~3-4 minutes on Pentium 3.0 GHz with SATA HDD + set term ^; + execute block as + declare i int = 0; + declare n int = 32839; + begin + while (i=3.0') +@pytest.mark.slow +def test_core_1544_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1549.py b/tests/bugs/test_core_1549.py new file mode 100644 index 00000000..d018fde0 --- /dev/null +++ b/tests/bugs/test_core_1549.py @@ -0,0 +1,124 @@ +#coding:utf-8 +# +# id: bugs.core_1549 +# title: Subquery-based predicates are not evaluated early in the join order +# decription: +# tracker_id: CORE-1549 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_1549 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + 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; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + EXISTS with ref. to 1st stream: + + Select Expression + -> 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) + 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: + + Select Expression + -> 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) + 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_core_1549_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1550.py b/tests/bugs/test_core_1550.py new file mode 100644 index 00000000..c107a497 --- /dev/null +++ b/tests/bugs/test_core_1550.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: bugs.core_1550 +# title: Unnecessary index scan happens when the same index is mapped to both WHERE and ORDER BY clauses +# decription: +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: bugs.core_1550 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test(id int); + commit; + insert into test(id) select r.rdb$relation_id from rdb$relations r; + commit; + create index test_id on test(id); + commit; + + set planonly; + select * + from test + where id < 10 + order by id; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (TEST ORDER TEST_ID) + """ + +@pytest.mark.version('>=3.0') +def test_core_1550_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1550_postfix.py b/tests/bugs/test_core_1550_postfix.py new file mode 100644 index 00000000..cf694ded --- /dev/null +++ b/tests/bugs/test_core_1550_postfix.py @@ -0,0 +1,104 @@ +#coding:utf-8 +# +# id: bugs.core_1550_postfix +# title: Unnecessary index scan happens when the same index is mapped to both WHERE and ORDER BY clauses +# decription: +# http://sourceforge.net/p/firebird/code/60368 +# Date: 2014-12-16 11:40:42 +0000 (Tue, 16 Dec 2014) +# +# First letter to dimitr: 30.09.2014 20:01. +# Reproduced on 3.0.0.31472 Beta 2 (10.dec.2014). +# Checked on: +# 3.0.3.32837: OK, 1.516s. +# 3.0.3.32838: OK, 0.953s. +# 4.0.0.800: OK, 1.625s. +# 4.0.0.801: OK, 1.125s. +# +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- sent to dimitr 30.09.14 at 22:09 + set term ^; + execute block as + begin + execute statement 'drop sequence g'; + when any do begin end + end^ + set term ;^ + commit; + + create sequence g; commit; + recreate table td(id int primary key using index td_pk, f01 int, f02 int); commit; + recreate table tm(id int); commit; + + insert into tm select gen_id(g,1) from rdb$types rows 100; + commit; + + insert into td(id, f01, f02) select id, (select min(id) from tm), gen_id(g,1) from tm; commit; + + create index td_f01_non_unq on td(f01); + create unique index td_f01_f02_unq on td(f01, f02); -- ### NB: compound UNIQUE index presens here beside of PK ### + commit; + + set planonly; + + -- 1. Check for usage when only PK fields are involved: + select * + from tm m + where exists( + select * from td d where m.id = d.id + order by d.id --------------------------- ### this "useless" order by should prevent from bitmap creation in 3.0+ + ); + -- Ineffective plan was here: + -- PLAN (D ORDER TD_PK INDEX (TD_PK)) + -- ... ^ + -- | + -- +-----> BITMAP created! + + -- 2. Check for usage when fields from UNIQUE index are involved: + select * + from tm m + where exists( + select * from td d + where m.id = d.f01 and d.f02 = 10 + order by d.f01, d.f02 ------------------- ### this "useless" order by should prevent from bitmap creation in 3.0+ + ); + + -- Ineffective plan was here: + -- PLAN (D ORDER TD_F01_F02_UNQ INDEX (TD_F01_F02_UNQ)) + -- ... ^ + -- | + -- +-----> BITMAP created! + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (D ORDER TD_PK) + PLAN (M NATURAL) + + PLAN (D ORDER TD_F01_F02_UNQ) + PLAN (M NATURAL) + """ + +@pytest.mark.version('>=3.0') +def test_core_1550_postfix_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1551.py b/tests/bugs/test_core_1551.py new file mode 100644 index 00000000..f49caac9 --- /dev/null +++ b/tests/bugs/test_core_1551.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: bugs.core_1551 +# title: AV when all statements are cancelled +# decription: +# tracker_id: CORE-1551 +# min_versions: [] +# versions: 2.5.0 +# qmid: bugs.core_1551-250 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """delete from MON$STATEMENTS; +delete from MON$ATTACHMENTS; +COMMIT; +SELECT 1 FROM RDB$DATABASE; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CONSTANT +============ + 1 + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_1551_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1554.py b/tests/bugs/test_core_1554.py new file mode 100644 index 00000000..ca25f59e --- /dev/null +++ b/tests/bugs/test_core_1554.py @@ -0,0 +1,57 @@ +#coding:utf-8 +# +# id: bugs.core_1554 +# title: select ... where ... <> ALL (select ... join ...) bug +# decription: +# tracker_id: +# min_versions: ['2.1.7'] +# versions: 2.1.7 +# qmid: bugs.core_1554 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select + ( + select count(*) from rdb$triggers t1 + ) + - + ( + select count(*) + from rdb$triggers t1 + where + t1.RDB$SYSTEM_FLAG=1 and + t1.rdb$trigger_name <> + all ( + select t2.rdb$trigger_name + from rdb$triggers t2 + join rdb$triggers t3 on t3.rdb$trigger_name=t2.rdb$trigger_name + where t2.rdb$trigger_name='xxx' + ) + ) as cnt + from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CNT 0 + """ + +@pytest.mark.version('>=2.1.7') +def test_core_1554_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1555.py b/tests/bugs/test_core_1555.py new file mode 100644 index 00000000..904ca391 --- /dev/null +++ b/tests/bugs/test_core_1555.py @@ -0,0 +1,122 @@ +#coding:utf-8 +# +# id: bugs.core_1555 +# title: 'select ...from...where...not in (select...from...)' no results +# decription: +# tracker_id: +# min_versions: ['2.1.7'] +# versions: 2.1.7 +# qmid: bugs.core_1555 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^ ; + create or alter procedure tst1 returns (boxes integer) as + begin + boxes=1; + suspend; + boxes=2; + suspend; + end + ^ + set term ;^ + commit; + + recreate table frrates1 ( + frrates1 integer not null, + boxes integer, + primary key(frrates1) + ); + commit; + + create index idx_frrates1_boxes on frrates1 (boxes); + commit; + + recreate table schedpkgs1 ( + schedpkgs1 integer not null, + schedule integer, + frrates1 integer, + primary key (schedpkgs1) + ); + commit; + + create index idx_schedpkgs1_schedule on schedpkgs1 (schedule); + commit; + + + insert into frrates1 (frrates1, boxes) values (11, 1); + insert into frrates1 (frrates1, boxes) values (12, 2); + commit; + + insert into schedpkgs1 (schedpkgs1, schedule, frrates1) values(21, 16651, 11); + insert into schedpkgs1 (schedpkgs1, schedule, frrates1) values(22, 16651, null); + commit; + + --------------------------- + + set list on; + + select fr.boxes + from schedpkgs1 sp + join frrates1 fr on fr.frrates1=sp.frrates1 + where sp.schedule = 16651; + + + select boxes + from tst1 + where boxes not in (select fr.boxes + from schedpkgs1 sp + join frrates1 fr on fr.frrates1=sp.frrates1 + where sp.schedule = 16651); + + + select boxes + from tst1 + where boxes not in (select fr.boxes + from schedpkgs1 sp + join frrates1 fr on fr.frrates1=sp.frrates1 + where sp.schedule = 16651 and fr.boxes>0); + + + select f2.boxes + from frrates1 f2 + where f2.boxes not in (select fr.boxes + from schedpkgs1 sp + join frrates1 fr on fr.frrates1=sp.frrates1 + where sp.schedule = 16651); + + select f2.boxes + from frrates1 f2 + where f2.boxes not in (select fr.boxes + from schedpkgs1 sp + join frrates1 fr on fr.frrates1=sp.frrates1 + where sp.schedule = 16651 and fr.boxes>0); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + BOXES 1 + BOXES 2 + BOXES 2 + BOXES 2 + BOXES 2 + """ + +@pytest.mark.version('>=2.1.7') +def test_core_1555_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1559.py b/tests/bugs/test_core_1559.py new file mode 100644 index 00000000..56c8a06c --- /dev/null +++ b/tests/bugs/test_core_1559.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_1559 +# title: Dropping NOT NULL contranint doesn'have the desired effect +# decription: +# tracker_id: CORE-1559 +# min_versions: [] +# versions: 2.5.3 +# qmid: bugs.core_1559-250 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """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; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Database: localhost:C:\\Users\\win7\\Firebird_tests\\fbt-repository\\tmp\\bugs.core_1559.fdb, User: SYSDBA +SQL> SQL> SQL> SQL> SQL> SQL> SQL> SQL> SQL> + N +============ + + +SQL>""" +expected_stderr_1 = """Statement failed, SQLSTATE = 23000 +validation error for column "T"."N", value "*** null ***" +""" + +@pytest.mark.version('>=2.5.3') +def test_core_1559_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1560.py b/tests/bugs/test_core_1560.py new file mode 100644 index 00000000..76060a8f --- /dev/null +++ b/tests/bugs/test_core_1560.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: bugs.core_1560 +# title: NULLIF crashes when first parameter is constant empty string +# decription: +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1560 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select nullif('','') from rdb$database; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +CASE +====== + + +""" + +@pytest.mark.version('>=2.1') +def test_core_1560_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1572.py b/tests/bugs/test_core_1572.py new file mode 100644 index 00000000..eefe8d9b --- /dev/null +++ b/tests/bugs/test_core_1572.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: bugs.core_1572 +# title: Multiple Rows in Singleton Select not reported in a View +# decription: +# tracker_id: CORE-1572 +# min_versions: [] +# versions: 2.5.0 +# qmid: bugs.core_1572-250 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE TABLE1 ( ID1 INTEGER NOT NULL, FIELD1 VARCHAR(20)); +CREATE TABLE TABLE2 ( ID2 INTEGER NOT NULL, FIELD2 VARCHAR(20)); + +INSERT INTO TABLE1 (ID1, FIELD1) VALUES (1, 'ONE'); +INSERT INTO TABLE2 (ID2, FIELD2) VALUES (2, 'TWO'); +INSERT INTO TABLE2 (ID2, FIELD2) VALUES (3, 'THREE'); + +CREATE VIEW VIEW_TABLE( ID1, FIELD1, FIELD2) AS +SELECT TABLE1.ID1, TABLE1.FIELD1, ( SELECT TABLE2.FIELD2 FROM TABLE2 ) FROM TABLE1; +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT * FROM VIEW_TABLE; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID1 FIELD1 FIELD2 +============ ==================== ==================== +""" +expected_stderr_1 = """Statement failed, SQLSTATE = 21000 +multiple rows in singleton select +""" + +@pytest.mark.version('>=2.5.0') +def test_core_1572_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1582.py b/tests/bugs/test_core_1582.py new file mode 100644 index 00000000..3ae4440d --- /dev/null +++ b/tests/bugs/test_core_1582.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: bugs.core_1582 +# title: ABS() rounds NUMERIC values +# decription: +# tracker_id: CORE-1582 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1582 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT + ABS(CAST(-1.98 AS NUMERIC(10,2))), + ABS(CAST(-1.23 AS DECIMAL(10,2))), + ABS(CAST(-1.98 AS NUMERIC(9,2))), + ABS(CAST(-1.23 AS DECIMAL(9,2))) + FROM RDB$DATABASE; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ABS ABS ABS ABS +===================== ===================== ===================== ===================== + 1.98 1.23 1.98 1.23 + +""" + +@pytest.mark.version('>=2.1') +def test_core_1582_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1584.py b/tests/bugs/test_core_1584.py new file mode 100644 index 00000000..7cbcf149 --- /dev/null +++ b/tests/bugs/test_core_1584.py @@ -0,0 +1,62 @@ +#coding:utf-8 +# +# id: bugs.core_1584 +# title: Server crashed or bugcheck when inserting in monitoring tables. +# decription: +# tracker_id: CORE-1584 +# min_versions: [] +# versions: 2.5 +# qmid: bugs.core_1584-250 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + insert into mon$statements( + mon$statement_id + ,mon$attachment_id + ,mon$transaction_id + ,mon$state + ,mon$timestamp + ,mon$sql_text + ,mon$stat_id + ) values( + 1 + ,current_connection + ,current_transaction + ,1 + ,'now' + ,null + ,1 + ); + set list on; + select 1 as x from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + X 1 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + operation not supported + """ + +@pytest.mark.version('>=2.5') +def test_core_1584_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1592.py b/tests/bugs/test_core_1592.py new file mode 100644 index 00000000..db924985 --- /dev/null +++ b/tests/bugs/test_core_1592.py @@ -0,0 +1,67 @@ +#coding:utf-8 +# +# id: bugs.core_1592 +# title: Altering procedure parameters can lead to unrestorable database +# decription: +# Checked on 4.0.0.1193 - works OK (DOES raise error during compilation). +# +# tracker_id: CORE-1592 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set list on; + set term ^; + create or alter procedure p2 as begin end + ^ + commit + ^ + create or alter procedure p1 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; + end + ^ + + -- This should FAIL and terminate script execution: + alter procedure p1 returns ( x2 integer ) as begin + x2 = 10; suspend; + end + ^ + set term ;^ + commit; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -PARAMETER P1.X1 + -there are 1 dependencies + """ + +@pytest.mark.version('>=4.0') +def test_core_1592_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_1605.py b/tests/bugs/test_core_1605.py new file mode 100644 index 00000000..21cfc255 --- /dev/null +++ b/tests/bugs/test_core_1605.py @@ -0,0 +1,63 @@ +#coding:utf-8 +# +# id: bugs.core_1605 +# title: Bugcheck 232 (invalid operation) for an aggregated query +# decription: +# tracker_id: CORE-1605 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test (id int); + + set term ^; + create or alter procedure sp_test (id int) returns (result int) as + begin + result = id * id; + suspend; + end + ^ + + set term ;^ + commit; + + insert into test values(1); + insert into test values(2); + insert into test values(3); + commit; + + select + sum( id ), + sum( (select result from sp_test(id)) ) + from test + group by 2; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Cannot use an aggregate or window function in a GROUP BY clause + """ + +@pytest.mark.version('>=3.0') +def test_core_1605_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_1606.py b/tests/bugs/test_core_1606.py new file mode 100644 index 00000000..7b26e920 --- /dev/null +++ b/tests/bugs/test_core_1606.py @@ -0,0 +1,142 @@ +#coding:utf-8 +# +# id: bugs.core_1606 +# title: Ability to insert child record if parent record is locked but foreign key target unchanged +# decription: +# Master table has two record, both are updated but without changing PK field. +# Than we check that we CAN add rows in detail table with references to existed PK from main, +# and even can change FK-values in these added rows, but can do it only with maintenance that +# MAIN table's PK exists for new values in FK +# Checked on: +# 4.0.0.1635 SS: 1.598s. +# 4.0.0.1633 CS: 1.883s. +# 3.0.5.33180 SS: 1.077s. +# 3.0.5.33178 CS: 1.391s. +# 2.5.9.27119 SS: 0.347s. +# 2.5.9.27146 SC: 0.352s. +# +# tracker_id: CORE-1606 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + execute block as + begin + execute statement 'drop sequence g'; + when any do begin end + end + ^ + set term ;^ + commit; + create sequence g; + commit; + recreate table tdetl(id int constraint tdetl_pk primary key, pid int); + commit; + recreate table tmain(id int constraint tmain_pk primary key, x int); + commit; + alter table tdetl add constraint tdetl_fk foreign key(pid) references tmain(id); + commit; + insert into tmain(id, x) values(1, 100); + insert into tmain(id, x) values(2, 200); + commit; + + set list on; + set transaction no wait; + + --set count on; + update tmain set id = id, x = -x*10 where id=1; + update tmain set id = id, x = -x*20 where id=2; + + set term ^; + execute block returns(id int, pid int) as + declare s varchar(1024); + begin + + s = 'insert into tdetl(id, pid) select gen_id(g,1), cast( ? as int) from rdb$types rows 3'; + /* + -- todo later, after fix CORE-4796 + 'merge into tdetl t ' + || 'using ( select 5 as id, 1 as pid from rdb$types rows 2 ) s ' + || 'on t.id=s.id ' + || 'when matched then update set t.pid = s.pid ' + || 'when not matched then insert values( s.id, s.pid)'; + */ + execute statement ( s ) ( 1 ) -------------------------------------- [1]: add rows with pid=1 + on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') + as user 'sysdba' password 'masterkey' role 'RCHILD'; + + execute statement ( s ) ( 2 ) -------------------------------------- [2]: add rows with pid=2 + on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') + as user 'sysdba' password 'masterkey' role 'RCHILD'; + + execute statement ('update tdetl set pid = 3 - pid') -- rows with pid=1 that were inserted on [1] will have pid=2 and vice versa + on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') + as user 'sysdba' password 'masterkey' role 'RCHILD'; + + for + execute statement 'select id,pid from tdetl order by id' + on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') + as user 'sysdba' password 'masterkey' role 'RCHILD' + into id,pid + 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + PID 2 + ID 2 + PID 2 + ID 3 + PID 2 + ID 4 + PID 1 + ID 5 + PID 1 + ID 6 + PID 1 + """ + +@pytest.mark.version('>=2.5') +def test_core_1606_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1607.py b/tests/bugs/test_core_1607.py new file mode 100644 index 00000000..2e218a25 --- /dev/null +++ b/tests/bugs/test_core_1607.py @@ -0,0 +1,63 @@ +#coding:utf-8 +# +# id: bugs.core_1607 +# title: Correlated subquery is optimized badly if it depends on the union stream +# decription: +# tracker_id: CORE-1607 +# min_versions: ['2.1'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLANONLY ON; +select 1 +from ( select rdb$relation_name, ( select 1 from rdb$database ) as c from rdb$relations ) r +where exists ( select * from rdb$relation_fields f where f.rdb$relation_name = r.rdb$relation_name ); +select 1 +from ( + select * from rdb$relations + union all + select * from rdb$relations +) r +where exists ( select * from rdb$relation_fields f where f.rdb$relation_name = r.rdb$relation_name ); +select ( select first 1 r.rdb$relation_name + from rdb$relations r + where r.rdb$relation_id = d.rdb$relation_id - 1 ) +from ( + select * from rdb$database + union all + select * from rdb$database +) d; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +PLAN (R RDB$DATABASE NATURAL) +PLAN (F INDEX (RDB$INDEX_4)) +PLAN (R RDB$RELATIONS NATURAL) + +PLAN (F INDEX (RDB$INDEX_4)) +PLAN (R RDB$RELATIONS NATURAL, R RDB$RELATIONS NATURAL) + +PLAN (R INDEX (RDB$INDEX_1)) +PLAN (D RDB$DATABASE NATURAL, D RDB$DATABASE NATURAL) +""" + +@pytest.mark.version('>=3.0') +def test_core_1607_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1609.py b/tests/bugs/test_core_1609.py new file mode 100644 index 00000000..8c8172af --- /dev/null +++ b/tests/bugs/test_core_1609.py @@ -0,0 +1,141 @@ +#coding:utf-8 +# +# id: bugs.core_1609 +# title: PSQL output parameter size limited +# decription: +# tracker_id: CORE-1609 +# min_versions: ['3.0.1'] +# versions: 3.0.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set term ^; + + create or alter procedure spro$parse_tag1 as begin end + ^ + create or alter procedure spro$parse_tag2 as begin end + ^ + create or alter procedure spro$parse_tag3 as begin end + ^ + commit + ^ + + execute block as + begin + execute statement 'drop domain spro$long_string'; + when any do begin end + end + ^ + commit + ^ + + create domain spro$long_string as varchar(32765) character set none collate none + ^ + commit + ^ + + create or alter procedure spro$parse_tag1( + str_in type of spro$long_string, + delimeter varchar(10)) + returns ( + str_out1 type of spro$long_string, + str_out2 type of spro$long_string) + as begin + suspend; + end + ^ + + create or alter procedure spro$parse_tag2( + str_in type of spro$long_string, + delimeter varchar(10)) + returns ( + str_out1 type of spro$long_string, + str_out2 varchar(32759)) + as begin + suspend; + end + ^ + + create or alter procedure spro$parse_tag3( + str_in type of spro$long_string, + delimeter varchar(10)) + returns ( + str_out01 varchar(32765) + ,str_out02 varchar(32765) + ,str_out03 varchar(32765) + ,str_out04 varchar(32765) + ,str_out05 varchar(32765) + ,str_out06 varchar(32765) + ,str_out07 varchar(32765) + ,str_out08 varchar(32765) + ,str_out09 varchar(32765) + ,str_out10 varchar(32765) + ,str_out11 varchar(32765) + ,str_out12 varchar(32765) + ,str_out13 varchar(32765) + ,str_out14 varchar(32765) + ,str_out15 varchar(32765) + ,str_out16 varchar(32765) + ,str_out17 varchar(32765) + ,str_out18 varchar(32765) + ,str_out19 varchar(32765) + ,str_out20 varchar(32765) + ,str_out21 varchar(32765) + ,str_out22 varchar(32765) + ,str_out23 varchar(32765) + ,str_out24 varchar(32765) + ,str_out25 varchar(32765) + ,str_out26 varchar(32765) + ,str_out27 varchar(32765) + ,str_out28 varchar(32765) + ,str_out29 varchar(32765) + ,str_out30 varchar(32765) + ,str_out31 varchar(32765) + ,str_out32 varchar(32765) + ,str_out33 varchar(32765) + ,str_out34 varchar(32765) + ,str_out35 varchar(32765) + ,str_out36 varchar(32765) + ,str_out37 varchar(32765) + ,str_out38 varchar(32765) + ,str_out39 varchar(32765) + ,str_out40 varchar(32765) + ,str_out41 varchar(32765) + ,str_out42 varchar(32765) + ,str_out43 varchar(32765) + ,str_out44 varchar(32765) + ,str_out45 varchar(32765) + ,str_out46 varchar(32765) + ,str_out47 varchar(32765) + ,str_out48 varchar(32765) + ,str_out49 varchar(32765) + ,str_out50 varchar(32765) + ) as + begin + suspend; + end + ^ + set term ;^ + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0.1') +def test_core_1609_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_1619.py b/tests/bugs/test_core_1619.py new file mode 100644 index 00000000..98df9a91 --- /dev/null +++ b/tests/bugs/test_core_1619.py @@ -0,0 +1,57 @@ +#coding:utf-8 +# +# id: bugs.core_1619 +# title: Some aggregate functions does NOT support NULL-constant in 3-d dialect +# decription: +# tracker_id: CORE-1619 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select + avg(null) as avg_for_null + ,sum(null) as sum_for_null + ,var_samp(null) as var_samp_for_null + ,var_pop(null) as var_pop_for_null + ,stddev_samp(null) as stddev_samp_for_null + ,stddev_pop(null) as stddev_pop_for_null + ,covar_samp(null, null) as covar_samp_for_nulls + ,covar_pop(null, null) as covar_pop_for_nulls + ,corr(null, null) as corr_for_nulls + from rdb$relations; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + AVG_FOR_NULL + SUM_FOR_NULL + VAR_SAMP_FOR_NULL + VAR_POP_FOR_NULL + STDDEV_SAMP_FOR_NULL + STDDEV_POP_FOR_NULL + COVAR_SAMP_FOR_NULLS + COVAR_POP_FOR_NULLS + CORR_FOR_NULLS + """ + +@pytest.mark.version('>=3.0') +def test_core_1619_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1620.py b/tests/bugs/test_core_1620.py new file mode 100644 index 00000000..c45842d3 --- /dev/null +++ b/tests/bugs/test_core_1620.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_1620 +# title: Incorrect error message (column number) if the empty SQL string is prepared +# decription: +# tracker_id: CORE-1620 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [("-At procedure 'TEST_ES1' line:.*", '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create procedure test_es1 as + begin + execute statement ''; + end + ^ + set term ;^ + commit; + execute procedure test_es1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Unexpected end of command - line 1, column 1 + -At procedure 'TEST_ES1' line: 3, col: 9 + """ + +@pytest.mark.version('>=3.0') +def test_core_1620_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_1624.py b/tests/bugs/test_core_1624.py new file mode 100644 index 00000000..6f33c5ee --- /dev/null +++ b/tests/bugs/test_core_1624.py @@ -0,0 +1,67 @@ +#coding:utf-8 +# +# id: bugs.core_1624 +# title: MERGE not correctly worked with parameters in MATCHING clause +# decription: +# tracker_id: CORE-1624 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table src(id int, x int); + recreate table tgt(id int, x int); + commit; + insert into src values(1, 100); + insert into src values(2, 200); + insert into src values(3, 300); + insert into src values(4, 400); + commit; + insert into tgt values(2, 10); + insert into tgt values(3, 20); + commit; + set term ^; + execute block as + declare v_stt varchar(255); + begin + v_stt = + 'merge into tgt t using src s on s.id = t.id ' + || 'when matched then update set t.x = s.x + ?' + || 'when NOT matched then insert values(s.id, s.id + ?)'; + + execute statement (v_stt) ( 1000, 20000 ); + end + ^ + set term ;^ + select * from tgt; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID X + ============ ============ + 2 1200 + 3 1300 + 1 20001 + 4 20004 + """ + +@pytest.mark.version('>=2.5') +def test_core_1624_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1640.py b/tests/bugs/test_core_1640.py new file mode 100644 index 00000000..4ce41dee --- /dev/null +++ b/tests/bugs/test_core_1640.py @@ -0,0 +1,82 @@ +#coding:utf-8 +# +# id: bugs.core_1640 +# title: Create or Alter view +# decription: +# tracker_id: CORE-1640 +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table users ( + id integer, + name varchar(20), + passwd varchar(20) +); + +commit;""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """create or alter view v_users as + select name from users; +commit; +show view v_users; +create or alter view v_users (id, name, passwd ) as + select id, name, passwd from users; +commit; +show view v_users; +create or alter view v_users_name as + select name from v_users; +commit; +create or alter view v_users (id, name ) as + select id, name from users; +commit; +show view v_users; +show view v_users_name; + + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Database: localhost:C: btest2 mpugs.core_1640.fdb, User: SYSDBA +SQL> CON> SQL> SQL> NAME VARCHAR(20) Nullable +View Source: +==== ====== + + select name from users +SQL> CON> SQL> SQL> ID INTEGER Nullable +NAME VARCHAR(20) Nullable +PASSWD VARCHAR(20) Nullable +View Source: +==== ====== + + select id, name, passwd from users +SQL> CON> SQL> SQL> CON> SQL> SQL> ID INTEGER Nullable +NAME VARCHAR(20) Nullable +View Source: +==== ====== + + select id, name from users +SQL> NAME VARCHAR(20) Nullable +View Source: +==== ====== + + select name from v_users +SQL> SQL> SQL>""" + +@pytest.mark.version('>=2.5.0') +def test_core_1640_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1642.py b/tests/bugs/test_core_1642.py new file mode 100644 index 00000000..11a527a6 --- /dev/null +++ b/tests/bugs/test_core_1642.py @@ -0,0 +1,107 @@ +#coding:utf-8 +# +# id: bugs.core_1642 +# title: Non-privileged monitoring reports wrong attachment data +# decription: +# When non-SYSDBA user selects from MON$ATTACHMENTS and other attachments are active at this point, +# the resulting rowset refers to a wrong attachment (the one with minimal ID) instead of the current attachment. +# Checked on: 4.0.0.1635; 3.0.5.33180; 2.5.9.27119. +# +# tracker_id: CORE-1642 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + -- Drop old account if it remains from prevoius run: + set term ^; + execute block as + begin + begin + execute statement 'drop user tmp$c1642_alan' with autonomous transaction; + when any do begin end + end + begin + execute statement 'drop user tmp$c1642_john' with autonomous transaction; + when any do begin end + end + begin + execute statement 'drop user tmp$c1642_mick' with autonomous transaction; + when any do begin end + end + end + ^ + set term ;^ + commit; + + create user tmp$c1642_alan password '123'; + create user tmp$c1642_john password '456'; + create user tmp$c1642_mick password '789'; + commit; + + create or alter view v_my_attach as + select current_user as who_am_i, iif(current_connection - mon$attachment_id = 0, 'OK.', 'BAD') as my_attach_id + from mon$attachments; + commit; + + grant select on v_my_attach to public; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# con1=fdb.connect( dsn = dsn, user = 'tmp$c1642_alan', password = '123') +# con2=fdb.connect( dsn = dsn, user = 'tmp$c1642_john', password = '456') +# con3=fdb.connect( dsn = dsn, user = 'tmp$c1642_mick', password = '789') +# +# cur1=con1.cursor() +# cur2=con2.cursor() +# cur3=con3.cursor() +# +# chk_sql='select who_am_i, my_attach_id from v_my_attach' +# cur1.execute(chk_sql) +# cur2.execute(chk_sql) +# cur3.execute(chk_sql) +# +# for c in (cur1,cur2,cur3): +# for r in c: +# print(r[0],r[1]) +# +# cur1.close() +# cur2.close() +# cur3.close() +# con1.close() +# con2.close() +# con3.close() +# +# db_conn.execute_immediate('drop user tmp$c1642_alan') +# db_conn.execute_immediate('drop user tmp$c1642_john') +# db_conn.execute_immediate('drop user tmp$c1642_mick') +# db_conn.commit() +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TMP$C1642_ALAN OK. + TMP$C1642_JOHN OK. + TMP$C1642_MICK OK. + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_1642_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_1649.py b/tests/bugs/test_core_1649.py new file mode 100644 index 00000000..70bf93d8 --- /dev/null +++ b/tests/bugs/test_core_1649.py @@ -0,0 +1,119 @@ +#coding:utf-8 +# +# id: bugs.core_1649 +# title: AV when recursive query used MERGE JOIN in execution plan +# decription: +# tracker_id: CORE-1649 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1649 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE XXX ( + ID INTEGER, + L INTEGER, + R INTEGER, + TYP INTEGER, + XID INTEGER); + +CREATE TABLE con ( + typ integer, + xid integer +); +COMMIT; +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (20, 7, 8, 0, 3); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (36, 18, 19, 1, 200017); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (18, 3, 4, 1, 200011); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (35, 16, 17, 1, 200014); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (34, 15, 20, 0, 5); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (32, 10, 11, 1, 200016); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (41, 25, 26, 1, 200020); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (37, 22, 39, 0, 6); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (39, 23, 24, 1, 200018); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (43, 27, 28, 1, 200021); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (46, 29, 30, 1, 200023); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (52, 35, 36, 1, 200026); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (51, 33, 34, 1, 200025); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (50, 31, 32, 1, 200024); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (54, 37, 38, 1, 200027); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (109, 63, 64, 1, 200048); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (93, 40, 41, 1, 200049); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (107, 59, 60, 1, 200052); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (95, 42, 43, 1, 200051); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (108, 61, 62, 1, 200028); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (97, 44, 45, 1, 200053); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (1, 1, 68, -1, NULL); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (106, 57, 58, 1, 200050); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (105, 55, 56, 1, 200033); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (100, 46, 47, 1, 200031); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (104, 53, 54, 1, 100003); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (101, 48, 65, 0, 7); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (103, 51, 52, 1, 100004); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (102, 49, 50, 1, 100002); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (110, 66, 67, 1, 200093); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (113, 12, 13, 1, 200094); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (3, 6, 21, 0, 1); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (22, 9, 14, 0, 4); +INSERT INTO XXX (ID, L, R, TYP, XID) VALUES (10, 2, 5, 0, 2); + +INSERT INTO CON (TYP, XID) VALUES (0, 6); +INSERT INTO CON (TYP, XID) VALUES (1, 2); +INSERT INTO CON (TYP, XID) VALUES (1, 3); +INSERT INTO CON (TYP, XID) VALUES (1, 18); +INSERT INTO CON (TYP, XID) VALUES (1, 19); +INSERT INTO CON (TYP, XID) VALUES (1, 62); +INSERT INTO CON (TYP, XID) VALUES (1, 151); +INSERT INTO CON (TYP, XID) VALUES (1, 224); +INSERT INTO CON (TYP, XID) VALUES (1, 254); +INSERT INTO CON (TYP, XID) VALUES (1, 255); +INSERT INTO CON (TYP, XID) VALUES (1, 281); +INSERT INTO CON (TYP, XID) VALUES (1, 200053); + +COMMIT;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """with recursive +downtree (lvl, id, l, r) +as +(-- base + select -1, id, l, r + from xxx + where typ = -1 + + -- children + union all + select parent.lvl + 1, child.id, child.l, child.r + from xxx child + natural join con + + join downtree parent on child.l between parent.l and parent.r and + child.id <> parent.id +) +select * from downtree; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + LVL ID L R +============ ============ ============ ============ + -1 1 1 68 + 0 37 22 39 + 0 97 44 45 + +""" + +@pytest.mark.version('>=2.1') +def test_core_1649_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1650.py b/tests/bugs/test_core_1650.py new file mode 100644 index 00000000..ccb33aad --- /dev/null +++ b/tests/bugs/test_core_1650.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: bugs.core_1650 +# title: Infinite row generation in "select gen_id(..) from rdb$database" with "group by" +# decription: +# tracker_id: CORE-1650 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create generator g; +commit; +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select first 10 1, gen_id(g, 1 ) +from rdb$database +group by 1,2; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CONSTANT GEN_ID +============ ===================== + 1 3 + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_1650_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1656.py b/tests/bugs/test_core_1656.py new file mode 100644 index 00000000..c7b56be5 --- /dev/null +++ b/tests/bugs/test_core_1656.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: bugs.core_1656 +# title: Ability to format UUID from char(16) OCTETS to human readable form and vice versa +# decription: +# tracker_id: CORE-1656 +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select uuid_to_char(char_to_uuid('93519227-8D50-4E47-81AA-8F6678C096A1')) from rdb$database; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +UUID_TO_CHAR +==================================== +93519227-8D50-4E47-81AA-8F6678C096A1 + +""" + +@pytest.mark.version('>=3.0') +def test_core_1656_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1677.py b/tests/bugs/test_core_1677.py new file mode 100644 index 00000000..366669ef --- /dev/null +++ b/tests/bugs/test_core_1677.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: bugs.core_1677 +# title: Floor & ceiling functions give wrong results with exact numeric arguments +# decription: Floor & ceiling functions give wrong results with exact numeric arguments +# select floor(cast(1500 as numeric(18,5))) from rdb$database -> -4827 (wrong) +# select floor(cast(1500 as numeric(18,4))) from rdb$database -> 1500 (correct) +# select ceiling(cast(1500 as numeric(18,5))) from rdb$database -> -4826 (wrong) +# +# Actually, any precision higher than 6 gives a wrong result. +# tracker_id: CORE-1677 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_1677 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select floor(cast(1500 as numeric(18,5))) F1,floor(cast(1500 as numeric(18,4))) F2, ceiling(cast(1500 as numeric(18,5))) F3 from rdb$database; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F1 F2 F3 +===================== ===================== ===================== + 1500 1500 1500 + +""" + +@pytest.mark.version('>=2.1') +def test_core_1677_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1689.py b/tests/bugs/test_core_1689.py new file mode 100644 index 00000000..670f5cfa --- /dev/null +++ b/tests/bugs/test_core_1689.py @@ -0,0 +1,149 @@ +#coding:utf-8 +# +# id: bugs.core_1689 +# title: 'There are dependencies' error message shows the wrong count of dependent objects. +# decription: +# For FB 2.5 and 3.x - this test uses UDF from ib_udf. +# +# 24.01.2019. +# Added separate code for running on FB 3.0.x because its current STDERR now differ from old one. +# +# Added separate code for running on FB 4.0.x. +# 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/ +# +# Checked on: +# 2.5.9.27126: OK, 0.719s. +# 3.0.5.33086: OK, 1.734s. +# 4.0.0.1340: OK, 3.078s. +# 4.0.0.1378: OK, 3.234s. +# +# NOTE. Build 4.0.0.1172 (date: 25.08.2018) raises here exception with 'UDF' instead 'Function' in STDERR. +# +# tracker_id: CORE-1689 +# min_versions: ['2.5.0'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + set term ^; + declare external function UDF30_getExactTimestamp + timestamp + returns parameter 1 + entry_point 'getExactTimestamp' module_name 'fbudf'^ + + create table t(a int)^ + create trigger tad for t after delete as declare dummy timestamp; begin dummy = UDF30_getExactTimestamp(); end^ + create view vudf(t) as select UDF30_getExactTimestamp() from rdb$database^ + create table tudf(a int, c computed by(UDF30_getExactTimestamp()))^ + create domain dud int check(value between extract(week from UDF30_getExactTimestamp()) and 25)^ + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + drop external function UDF30_getExactTimestamp; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 38000 + unsuccessful metadata update + -cannot delete + -Function UDF30_GETEXACTTIMESTAMP + -there are 4 dependencies + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_core_1689_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + -- See declaration sample in plugins\\udr\\UdfBackwardCompatibility.sql: + set bail on; + create function UDR40_getExactTimestampUTC + returns timestamp + external name 'udf_compat!UC_getExactTimestampUTC' + engine udr; + + create table test_dts( + id int, + dts timestamp check ( datediff(minute from dts to UDR40_getExactTimestampUTC()) < 5 ) + ); + commit; + + set term ^; + create trigger trg_test_dts_ad for test_dts after delete as + declare dummy timestamp; + begin + dummy = UDR40_getExactTimestampUTC(); + end + ^ + set term ;^ + commit; + + + + create view v_test as + select UDR40_getExactTimestampUTC() as UTC_stamp -- rdb$N, dep_type=3 + from rdb$database + ; + + + create table test_udr(a int, c computed by( UDR40_getExactTimestampUTC() )) -- rdb$N, dep_type=3 + ; + + create domain dm_test int check(value between extract(week from UDR40_getExactTimestampUTC() ) and 25) ; + + commit; + + drop function UDR40_getExactTimestampUTC; + + /* + set count on; + set list on; + select rd.rdb$dependent_name, rd.rdb$dependent_type + from rdb$dependencies rd + where rd.rdb$depended_on_name = upper('UDR40_GETEXACTTIMESTAMPUTC') + order by rd.rdb$dependent_name + ; + */ + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_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_core_1689_2(act_2: Action): + act_2.expected_stderr = expected_stderr_2 + act_2.execute() + assert act_2.clean_expected_stderr == act_2.clean_stderr + diff --git a/tests/bugs/test_core_1690.py b/tests/bugs/test_core_1690.py new file mode 100644 index 00000000..345844fd --- /dev/null +++ b/tests/bugs/test_core_1690.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: bugs.core_1690 +# title: arithmetic exception, numeric overflow, or string truncation in utf8 tables +# decription: +# tracker_id: CORE-1690 +# min_versions: [] +# versions: 2.1.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table A (C1 INTEGER PRIMARY KEY); +""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """show table A; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """C1 INTEGER Not Null +CONSTRAINT INTEG_2: + Primary key (C1) +""" + +@pytest.mark.version('>=2.1.3') +def test_core_1690_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1693.py b/tests/bugs/test_core_1693.py new file mode 100644 index 00000000..d7ce91c8 --- /dev/null +++ b/tests/bugs/test_core_1693.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_1693 +# title: Error in EXECUTE STATEMENT inside CONNECT / TRANSACTION START triggers +# decription: +# tracker_id: CORE-1693 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """set term ^ ; + +create trigger t_connect on connect +as + declare v integer; +begin + execute statement 'select 1 from rdb$database' into v; +end ^ + +set term ; ^ +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select 1 from rdb$database; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CONSTANT +============ + 1 + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_1693_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1694.py b/tests/bugs/test_core_1694.py new file mode 100644 index 00000000..3e8d97dc --- /dev/null +++ b/tests/bugs/test_core_1694.py @@ -0,0 +1,158 @@ +#coding:utf-8 +# +# id: bugs.core_1694 +# title: Bug in create/alter Database trigger (with Russian comment) +# decription: +# tracker_id: CORE-1694 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('[+++].*', ''), ('[===].*', ''), ('Trigger text.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ +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 + /* + — 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 года известная Анна Павловна Шерер, фрейлина и приближенная + императрицы Марии Феодоровны, встречая важного и чиновного князя Василия, первого + приехавшего на ее вечер. Анна Павловна кашляла несколько дней, у нее был грипп, как она + говорила (грипп был тогда новое слово, употреблявшееся только редкими). + */ + 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 — отвечал, нисколько не смутясь такою встречей, вошедший + князь, в придворном, шитом мундире, в чулках, башмаках и звездах, с светлым выражением + плоского лица. Он говорил на том изысканном французском языке, на котором не только говорили, + но и думали наши деды, и с теми, тихими, покровительственными интонациями, которые свойственны + состаревшемуся в свете и при дворе значительному человеку. Он подошел к Анне Павловне, + поцеловал ее руку, подставив ей свою надушенную и сияющую лысину, и покойно уселся на диване. + */ + 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. + Князь Василий говорил всегда лениво, как актер говорит роль старой пиесы. Анна Павловна Шерер, + напротив, несмотря на свои сорок лет, была преисполнена оживления и порывов. + */ + declare w int = 3; +begin + u = + /* + Ах, не говорите мне про Австрию! Я ничего не понимаю, может быть, но Австрия никогда не хотела + и не хочет войны. Она предает нас. Россия одна должна быть спасительницей Европы. Наш благодетель + знает свое высокое призвание и будет верен ему. Вот одно, во что я верю. Нашему доброму и чудному + */ + v + + /*государю предстоит величайшая роль в мире, и он так добродетелен и хорош, что Бог не оставит его, + и он исполнит свое призвание задавить гидру революции, которая теперь еще ужаснее в лице этого + убийцы и злодея. Мы одни должны искупить кровь праведника. На кого нам надеяться, я вас спрашиваю?.. + */ + w; + /* + Англия с своим коммерческим духом не поймет и не может понять всю высоту души императора Александра + */ +end' +; +end +^ +set term ;^ +commit; + +show trigger trg_conn; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +TRG_CONN, Sequence: 0, Type: ON CONNECT, Active +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 года известная Анна Павловна Шерер, фрейлина и приближенная + императрицы Марии Феодоровны, встречая важного и чиновного князя Василия, первого + приехавшего на ее вечер. Анна Павловна кашляла несколько дней, у нее был грипп, как она + говорила (грипп был тогда новое слово, употреблявшееся только редкими). + */ + 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 — отвечал, нисколько не смутясь такою встречей, вошедший + князь, в придворном, шитом мундире, в чулках, башмаках и звездах, с светлым выражением + плоского лица. Он говорил на том изысканном французском языке, на котором не только говорили, + но и думали наши деды, и с теми, тихими, покровительственными интонациями, которые свойственны + состаревшемуся в свете и при дворе значительному человеку. Он подошел к Анне Павловне, + поцеловал ее руку, подставив ей свою надушенную и сияющую лысину, и покойно уселся на диване. + */ + 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. + Князь Василий говорил всегда лениво, как актер говорит роль старой пиесы. Анна Павловна Шерер, + напротив, несмотря на свои сорок лет, была преисполнена оживления и порывов. + */ + declare w int = 3; +begin + u = + /* + Ах, не говорите мне про Австрию! Я ничего не понимаю, может быть, но Австрия никогда не хотела + и не хочет войны. Она предает нас. Россия одна должна быть спасительницей Европы. Наш благодетель + знает свое высокое призвание и будет верен ему. Вот одно, во что я верю. Нашему доброму и чудному + */ + v + + /*государю предстоит величайшая роль в мире, и он так добродетелен и хорош, что Бог не оставит его, + и он исполнит свое призвание задавить гидру революции, которая теперь еще ужаснее в лице этого + убийцы и злодея. Мы одни должны искупить кровь праведника. На кого нам надеяться, я вас спрашиваю?.. + */ + w; + /* + Англия с своим коммерческим духом не поймет и не может понять всю высоту души императора Александра + */ +end ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + """ + +@pytest.mark.version('>=2.5') +def test_core_1694_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1712.py b/tests/bugs/test_core_1712.py new file mode 100644 index 00000000..707da828 --- /dev/null +++ b/tests/bugs/test_core_1712.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: bugs.core_1712 +# title: Buffer overflow in conversion +# decription: +# Confirmed bug on WI-V2.0.0.12724: +# * "buffer overrun" when use dialect 1; +# * "string right truncation" when use dialect 3. +# Checked on: +# Windows: 3.0.8.33445, 4.0.0.2416 +# Linux: 3.0.8.33426, 4.0.0.2416 +# +# tracker_id: CORE-1712 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=1, init=init_script_1) + +test_script_1 = """ + recreate table testtable(f1 numeric(15, 2)); + commit; + + insert into testtable(f1) values(1e19); + commit; + + set list on; + select replace(cast(f1 as varchar(30)),'0','') f1_as_varchar30 from testtable; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F1_AS_VARCHAR30 1.e+19 + """ + +@pytest.mark.version('>=2.5') +def test_core_1712_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1715.py b/tests/bugs/test_core_1715.py new file mode 100644 index 00000000..bdccffe0 --- /dev/null +++ b/tests/bugs/test_core_1715.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_1715 +# title: Incorrect "key size exceeds implementation restriction for index" error +# decription: +# tracker_id: CORE-1715 +# min_versions: [] +# versions: 2.1.0 +# qmid: bugs.core_1715 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """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_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """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; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """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) +""" + +@pytest.mark.version('>=2.1.0') +def test_core_1715_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1716.py b/tests/bugs/test_core_1716.py new file mode 100644 index 00000000..1d95f67b --- /dev/null +++ b/tests/bugs/test_core_1716.py @@ -0,0 +1,109 @@ +#coding:utf-8 +# +# id: bugs.core_1716 +# title: Wrong variable initialization in recursive procedures +# decription: +# tracker_id: CORE-1716 +# min_versions: ['2.1.7'] +# versions: 2.1.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.7 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create domain dm_int as integer default 0 not null; + commit; + + -- sample with returned variable + set term ^; + create procedure sp_test1(a_cnt int) + returns (o_cnt int, o_ret dm_int) + as + begin + while (a_cnt>0) do + begin + o_cnt = a_cnt; + a_cnt = a_cnt-1; + for + select o_ret + from sp_test1( :a_cnt ) + into o_ret + do + suspend; + end + suspend; + end + ^ + + create procedure sp_test2(a_cnt int) + returns (o_cnt int, o_ret dm_int) + as + declare x dm_int; + begin + while (a_cnt>0) do + begin + o_cnt = a_cnt; + a_cnt = a_cnt-1; + for + select o_ret + from sp_test2( :a_cnt ) + into o_ret + do begin + o_ret = x; + suspend; + end + end + o_ret=x; + suspend; + end + ^ + set term ;^ + commit; + + select * from sp_test1(3); + select * from sp_test2(3); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + O_CNT O_RET + ============ ============ + 3 0 + 3 0 + 3 0 + 3 0 + 2 0 + 2 0 + 1 0 + 1 0 + + + O_CNT O_RET + ============ ============ + 3 0 + 3 0 + 3 0 + 3 0 + 2 0 + 2 0 + 1 0 + 1 0 + """ + +@pytest.mark.version('>=2.1.7') +def test_core_1716_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1724.py b/tests/bugs/test_core_1724.py new file mode 100644 index 00000000..85361b44 --- /dev/null +++ b/tests/bugs/test_core_1724.py @@ -0,0 +1,76 @@ +#coding:utf-8 +# +# id: bugs.core_1724 +# title: Common table expressions cannot be used in computed columns and quantified predicates (IN / ANY / ALL) +# decription: +# tracker_id: CORE-1724 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select + sign( count(*) ) + + ( + with recursive + n as( + select 0 i from rdb$database + union all + select n.i+1 from n + where n.i < 10 + ) + select avg(i) + from n + ) s + from rdb$pages p + where p.rdb$relation_id + > all ( + with recursive + n as( + select 0 i from rdb$database + union all + select n.i+1 from n + where n.i < 10 + ) + select i + from n + ) + and p.rdb$page_number + not in ( + with recursive + n as( + select 0 i from rdb$database + union all + select n.i+1 from n + where n.i < 10 + ) + select i + from n + ); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + S 6 + """ + +@pytest.mark.version('>=2.5') +def test_core_1724_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1725.py b/tests/bugs/test_core_1725.py new file mode 100644 index 00000000..7dca442e --- /dev/null +++ b/tests/bugs/test_core_1725.py @@ -0,0 +1,404 @@ +#coding:utf-8 +# +# id: bugs.core_1725 +# title: Unable to restore a database with inactive indices if any SP/trigger contains an explicit plan +# decription: +# We create database and add a table with two indices there. +# Then we create several program objects that use these indices explicitly by specifying 'PLAN' clause: +# view, standalone procedure, standalone function, packaged procedure and function and DB-level trigger. +# We also create several units that do not use these index explicitly. +# Then we extract metadata from this DB ans saved in "initial" .sql, see 'f_meta_init' var. +# +# After this, we do backup and restore (using PIPE mechanism in order to avoid creation of unneeded .fbk). +# Restored database is further renamed to initial name and we do on this DB: +# * full validation and +# * metadata extraction, see 'f_meta_rest' var. +# +# Result of validation must be "0 errors and 0 warnings". +# Result of extracted metadata comparison must be empty (no difference). ALL program objects must be preserved. +# +# Checked on: +# 4.0.0.1881 SS: 6.238s. +# 4.0.0.1391 SC: 12.503s. +# 3.0.6.33283 SS: 3.859s. +# 3.0.6.33276 SS: 4.002s. +# +# ::: NB ::: This bug was fixed between 17-dec-2018 and 23-jan-2019. +# Builds 4.0.0.1346 and 3.0.5.33084 (both of 17.12.2018) still have bug: no program units will be in restored DB. +# Builds 4.0.0.1391 (23.01.2019) and 3.0.5.33097 (01.02.2019) work fine. +# +# tracker_id: CORE-1725 +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import time +# import shutil +# import difflib +# import subprocess +# from subprocess import Popen +# from subprocess import PIPE +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# DB_PATH = os.sep.join( db_conn.database_name.split(os.sep)[:-1] ) +# db_conn.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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# +# #-------------------------------------------- +# +# def svc_get_fb_log( f_fb_log ): +# +# global subprocess +# subprocess.call( [ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# "action_get_fb_log" +# ], +# stdout=f_fb_log, stderr=subprocess.STDOUT +# ) +# return +# +# #-------------------------------------------- +# +# tmp_initdb = os.path.join(context['temp_directory'],'tmp_1725_init.fdb') +# tmp_restdb = os.path.join(context['temp_directory'],'tmp_1725_rest.fdb') +# +# cleanup( (tmp_initdb, tmp_restdb,) ) +# +# sql_init=''' +# set bail on; +# +# create database 'localhost:%(tmp_initdb)s' user %(user_name)s password '%(user_password)s'; +# +# 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 +# ; +# 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 +# from test group by x +# plan (TEST ORDER TEST_X) +# union all +# select cnt from v_worker +# ) +# 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) +# from ( +# select count(*) as cnt +# from test group by x +# plan (TEST ORDER TEST_X) +# 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 +# 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 +# +# 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 +# +# 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 +# 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 +# ^ +# set term ;^ +# commit; +# ''' % dict(globals(), **locals()) +# +# f_init_sql=open( os.path.join(context['temp_directory'],'tmp_1725_init.sql'), 'w') +# f_init_sql.write(sql_init) +# f_init_sql.close() +# +# f_init_log=open( os.path.join(context['temp_directory'],'tmp_1725_init.log'), 'w', buffering = 0) +# f_init_err=open( os.path.join(context['temp_directory'],'tmp_1725_init.err'), 'w', buffering = 0) +# subprocess.call( [ context['isql_path'], '-q', '-i', f_init_sql.name], stdout=f_init_log, stderr=f_init_err ) +# flush_and_close( f_init_log ) +# flush_and_close( f_init_err ) +# +# #---------------------------------------------------------------------- +# +# # Extract metadata from initial DB: +# ################## +# f_meta_init=open( os.path.join(context['temp_directory'],'tmp_1725_meta.init.sql'), 'w', buffering = 0) +# subprocess.call( [ context['isql_path'], '-nod', '-x', 'localhost:'+tmp_initdb ], stdout=f_meta_init, stderr=subprocess.STDOUT ) +# flush_and_close( f_meta_init ) +# +# #---------------------------------------------------------------------- +# +# # backup + restore _WITHOUT_ building indices: +# ################### +# # https://docs.python.org/2/library/subprocess.html#replacing-shell-pipeline +# p_sender = subprocess.Popen( [ context['gbak_path'], '-b', 'localhost:'+tmp_initdb, 'stdout' ], stdout=PIPE) +# p_getter = subprocess.Popen( [ context['gbak_path'], '-c', '-i', 'stdin', tmp_restdb ], stdin = p_sender.stdout, stdout = PIPE ) +# p_sender.stdout.close() +# p_getter_stdout, p_getter_stderr = p_getter.communicate() +# +# #---------------------------------------------------------------------- +# +# # Get FB log before validation, run validation and get FB log after it: +# ############ +# f_fblog_before=open( os.path.join(context['temp_directory'],'tmp_1725_fblog_before_validation.txt'), 'w') +# svc_get_fb_log( f_fblog_before ) +# flush_and_close( f_fblog_before ) +# +# f_validate_log=open( os.path.join(context['temp_directory'],'tmp_1725_validate.log'), 'w', buffering = 0) +# f_validate_err=open( os.path.join(context['temp_directory'],'tmp_1725_validate.err'), 'w', buffering = 0) +# subprocess.call( [ context['gfix_path'], '-v', '-full', 'localhost:'+tmp_restdb ], stdout=f_validate_log, stderr=f_validate_err ) +# flush_and_close( f_validate_log ) +# flush_and_close( f_validate_err ) +# +# f_fblog_after=open( os.path.join(context['temp_directory'],'tmp_1725_fblog__after_validation.txt'), 'w') +# svc_get_fb_log( f_fblog_after ) +# flush_and_close( f_fblog_after ) +# +# #---------------------------------------------------------------------- +# shutil.move(tmp_restdb, tmp_initdb) +# #---------------------------------------------------------------------- +# +# # Extract metadata from restored DB: +# ################## +# f_meta_rest=open( os.path.join(context['temp_directory'],'tmp_1725_meta.rest.sql'), 'w', buffering = 0) +# subprocess.call( [ context['isql_path'], '-nod', '-x', 'localhost:'+tmp_initdb ], stdout=f_meta_rest, stderr=subprocess.STDOUT ) +# flush_and_close( f_meta_rest ) +# +# #---------------------------------------------------------------------- +# +# oldmeta=open(f_meta_init.name, 'r') +# newmeta=open(f_meta_rest.name, 'r') +# +# diffmeta = ''.join(difflib.unified_diff( +# oldmeta.readlines(), +# newmeta.readlines() +# )) +# oldmeta.close() +# newmeta.close() +# +# f_meta_diff=open( os.path.join(context['temp_directory'],'tmp_1725_meta_diff.txt'), 'w', buffering = 0) +# f_meta_diff.write(diffmeta) +# flush_and_close( f_meta_diff ) +# +# #---------------------------------------------------------------------- +# +# # Compare firebird.log versions BEFORE and AFTER this test: +# ###################### +# +# oldfb=open(f_fblog_before.name, 'r') +# newfb=open(f_fblog_after.name, 'r') +# +# difftext = ''.join(difflib.unified_diff( +# oldfb.readlines(), +# newfb.readlines() +# )) +# oldfb.close() +# newfb.close() +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_5719_valid_diff.txt'), 'w', buffering = 0) +# f_diff_txt.write(difftext) +# flush_and_close( f_diff_txt ) +# +# #----------------------------------------------------------------------- +# +# # CHECKS: +# ######### +# +# # Logs of initial .sql must be empty. +# # Result of diff in extracted metadata .sql must be empty. +# # Output of 'gfix -v -full' must be empty. +# for g in (f_init_log, f_init_err, f_meta_diff, f_validate_log, f_validate_err): +# with open(g.name, 'r') as f: +# for line in f: +# if line.split(): +# print('UNEXPECTED OUTPUT in ' + os.path.split(g.name)[-1] + ': ' + line ) +# +# # Result of diff in firebird.log before and after validation must contain text with ZERO warninngs and ZERO errors: +# # + Validation finished: 0 errors, 0 warnings, 0 fixed +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# if line.startswith('+') and 'Validation' in line: +# print( line ) +# +# # Cleanup: +# ########## +# +# # do NOT remove this pause otherwise some of logs will not be enable for deletion and test will finish with +# # Exception raised while executing Python test script. exception: WindowsError: 32 +# time.sleep(1) +# +# cleanup( [ i.name for i in ( f_init_sql, f_init_log, f_init_err, f_meta_init, f_meta_rest, f_meta_diff, f_fblog_before, f_fblog_after, f_validate_log, f_validate_err, f_diff_txt ) ] + [ tmp_initdb, ] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + + Validation started + + Validation finished: 0 errors, 0 warnings, 0 fixed + """ + +@pytest.mark.version('>=3.0.6') +@pytest.mark.xfail +def test_core_1725_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_1735.py b/tests/bugs/test_core_1735.py new file mode 100644 index 00000000..cc67bd0f --- /dev/null +++ b/tests/bugs/test_core_1735.py @@ -0,0 +1,37 @@ +#coding:utf-8 +# +# id: bugs.core_1735 +# title: Bug in SET DEFAULT statement +# decription: +# tracker_id: CORE-1735 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE TEST ( + A INTEGER +); +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ALTER TABLE TEST ADD CHECK (A > 0); + +ALTER TABLE TEST ALTER A SET DEFAULT '1000'; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.0') +def test_core_1735_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_1746.py b/tests/bugs/test_core_1746.py new file mode 100644 index 00000000..8bf9b702 --- /dev/null +++ b/tests/bugs/test_core_1746.py @@ -0,0 +1,325 @@ +#coding:utf-8 +# +# id: bugs.core_1746 +# title: Expression index can be created while doing inserts into table +# decription: +# We check three cases of Tx setting: WAIT, NO WAIT and LOCK TIMEOUT n. +# +# First ISQL session always inserts some number of rows and falls in delay (it is created +# artificially by attempting to insert duplicate key in index in Tx with lock timeout = 7). +# +# Second ISQL is launched in SYNC mode after small delay (3 seconds) and starts transaction +# with corresponding WAIT/NO WAIT/LOCK TIMEOUT clause. +# +# If Tx starts with NO wait or lock timeout then this (2nd) ISQL always MUST FAIL. +# +# After 2nd ISQL will finish, we have to wait yet 5 seconds for 1st ISQL will gone. +# Total time of these two delays (3+5=8) must be greater than lock timeout in the script which +# is running by 1st ISQL (7 seconds). +# +# Initial version of this test did use force interruption of both ISQL processes but this was unneeded, +# though it helped to discover some other bug in engine which produced bugcheck - see CORE-5275. +# +# Checked on: +# 4.0.0.2164 SS: 37.707s. +# 4.0.0.2119 SS: 37.982s. +# 4.0.0.2164 CS: 39.116s. +# 3.0.7.33356 SS: 36.675s. +# 3.0.7.33356 CS: 37.839s. +# 2.5.9.27150 SC: 35.755s. +# +# tracker_id: CORE-1746 +# min_versions: ['2.5.6'] +# versions: 2.5.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.6 +# resources: None + +substitutions_1 = [('0: CREATE INDEX LOG: RDB_EXPR_BLOB.*', '0: CREATE INDEX LOG: RDB_EXPR_BLOB'), ('BULK_INSERT_START.*', 'BULK_INSERT_START'), ('BULK_INSERT_FINISH.*', 'BULK_INSERT_FINISH'), ('CREATE_INDX_START.*', 'CREATE_INDX_START'), ('AFTER LINE.*', 'AFTER LINE')] + +init_script_1 = """ + create or alter procedure sp_ins(n int) as begin end; + + recreate table test(x int unique using index test_x, s varchar(10) default 'qwerty' ); + + set term ^; + execute block as + begin + execute statement 'drop sequence g'; + when any do begin end + end + ^ + set term ;^ + commit; + create sequence g; + commit; + + set term ^; + create or alter procedure sp_ins(n int) as + begin + while (n>0) do + begin + insert into test( x ) values( gen_id(g,1) ); + n = n - 1; + end + end + ^ + set term ;^ + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# +# +# ######################################################### +# +# # NB-1: value of 'rows_to_add' must have value that will require at least +# # 4...5 seconds for inserting such number of rows +# # NB-2: FB 2.5 makes DML *faster* than 3.0 in single-connection mode! +# +# rows_to_add=1000 +# +# sql_bulk_insert=''' set bail on; +# set list on; +# +# -- do NOT use it !! >>> alter sequence g restart with 0; -- gen_id(g,1) will return 0 rather than 1 since 06-aug-2020 on FB 4.x !! +# +# delete from test; +# set term ^; +# execute block as +# declare c bigint; +# begin +# c = gen_id(g, -gen_id(g, 0)); -- restart sequence +# end +# ^ +# set term ;^ +# commit; +# +# set transaction lock timeout 7; -- THIS LOCK TIMEOUT SERVES ONLY FOR DELAY, see below auton Tx start. +# +# select current_timestamp as bulk_insert_start from rdb$database; +# set term ^; +# execute block as +# declare i int; +# begin +# execute procedure sp_ins( %(rows_to_add)s ); +# begin +# -- ######################################################### +# -- ####################### D E L A Y ##################### +# -- ######################################################### +# in autonomous transaction do +# insert into test( x ) values( %(rows_to_add)s ); -- this will cause delay because of duplicate in index +# when any do +# begin +# i = gen_id(g,1); +# end +# end +# end +# ^ +# set term ;^ +# commit; +# select current_timestamp as bulk_insert_finish from rdb$database; +# ''' +# +# sql_create_indx=''' set bail on; +# set list on; +# set blob all; +# select +# iif( gen_id(g,0) > 0 and gen_id(g,0) < 1 + %(rows_to_add)s, +# 'OK, IS RUNNING', +# iif( gen_id(g,0) <=0, +# 'WRONG: not yet started, current gen_id='||gen_id(g,0), +# 'WRONG: already finished, rows_to_add='||%(rows_to_add)s ||', current gen_id='||gen_id(g,0) +# ) +# ) as inserts_state, +# current_timestamp as create_indx_start +# from rdb$database; +# set autoddl off; +# commit; +# +# set echo on; +# set transaction %(tx_decl)s; +# +# create index test_%(idx_name)s on test computed by( %(idx_expr)s ); +# commit; +# set echo off; +# +# select +# iif( gen_id(g,0) >= 1 + %(rows_to_add)s, +# 'OK, FINISHED', +# 'SOMETHING WRONG: current gen_id=' || gen_id(g,0)||', rows_to_add='||%(rows_to_add)s +# ) as inserts_state +# from rdb$database; +# +# set count on; +# select +# rdb$index_name +# ,coalesce(rdb$unique_flag,0) as rdb$unique_flag +# ,coalesce(rdb$index_inactive,0) as rdb$index_inactive +# ,rdb$expression_source as rdb_expr_blob +# from rdb$indices ri +# where ri.rdb$index_name = upper( 'test_%(idx_name)s' ) +# ; +# set count off; +# set echo on; +# set plan on; +# select 1 from test where %(idx_expr)s > '' rows 0; +# set plan off; +# set echo off; +# commit; +# drop index test_%(idx_name)s; +# commit; +# ''' +# +# tx_param=['WAIT','NO WAIT','LOCK TIMEOUT 1'] +# +# for i in range(len(tx_param)): +# +# #if i >= 2: +# # continue # temply! +# +# f_bulk_insert_sql = open( os.path.join(context['temp_directory'],'tmp_1746_ins.sql'), 'w') +# f_bulk_insert_sql.write(sql_bulk_insert % locals() ) +# f_bulk_insert_sql.close() +# +# tx_decl=tx_param[i] +# idx_name=tx_decl.replace(' ','_') +# idx_expr="'"+idx_name+"'|| s" +# +# f_create_indx_sql = open( os.path.join(context['temp_directory'],'tmp_1746_idx_%s.sql' % str(i) ), 'w') +# f_create_indx_sql.write( sql_create_indx % locals() ) +# f_create_indx_sql.close() +# +# f_bulk_insert_log = open( os.path.join(context['temp_directory'],'tmp_1746_ins_%s.log' % str(i) ), 'w') +# +# # This will insert rows and then stay in pause 10 seconds: +# p_bulk_insert=subprocess.Popen( [ context['isql_path'], dsn, "-q", "-i", f_bulk_insert_sql.name ], +# stdout = f_bulk_insert_log, +# stderr = subprocess.STDOUT +# ) +# +# # 3.0 Classic: seems that it requires at least 2 seconds for ISQL be loaded into memory. +# time.sleep(3) +# +# f_create_indx_log = open( os.path.join(context['temp_directory'],'tmp_1746_idx_%s.log' % str(i) ), 'w') +# +# # This will wait until first ISQL finished: +# subprocess.call( [ context['isql_path'], dsn, "-n", "-q", "-i", f_create_indx_sql.name ], +# stdout = f_create_indx_log, +# stderr = subprocess.STDOUT +# ) +# +# time.sleep(7) # NB: this delay plus previous (3+5=8) must be GREATER than lock timeout in +# +# p_bulk_insert.terminate() +# flush_and_close( f_bulk_insert_log ) +# flush_and_close( f_create_indx_log ) +# +# +# with open( f_bulk_insert_log.name,'r') as f: +# for line in f: +# if line.split(): +# print( str(i)+': BULK INSERTS LOG: '+line.strip().upper() ) +# +# with open( f_create_indx_log.name,'r') as f: +# for line in f: +# if line.split(): +# print( str(i)+': CREATE INDEX LOG: '+line.strip().upper() ) +# +# cleanup( [i.name for i in (f_bulk_insert_sql, f_create_indx_sql, f_bulk_insert_log, f_create_indx_log)] ) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 0: BULK INSERTS LOG: BULK_INSERT_START + 0: BULK INSERTS LOG: BULK_INSERT_FINISH + 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: COMMIT; + 0: CREATE INDEX LOG: SET ECHO OFF; + 0: CREATE INDEX LOG: INSERTS_STATE OK, FINISHED + 0: CREATE INDEX LOG: RDB$INDEX_NAME TEST_WAIT + 0: CREATE INDEX LOG: RDB$UNIQUE_FLAG 0 + 0: CREATE INDEX LOG: RDB$INDEX_INACTIVE 0 + 0: CREATE INDEX LOG: RDB_EXPR_BLOB + 0: CREATE INDEX LOG: ( 'WAIT'|| S ) + 0: CREATE INDEX LOG: RECORDS AFFECTED: 1 + 0: CREATE INDEX LOG: SET PLAN ON; + 0: CREATE INDEX LOG: SELECT 1 FROM TEST WHERE 'WAIT'|| S > '' ROWS 0; + 0: CREATE INDEX LOG: PLAN (TEST INDEX (TEST_WAIT)) + 0: CREATE INDEX LOG: SET PLAN OFF; + 0: CREATE INDEX LOG: SET ECHO OFF; + + 1: BULK INSERTS LOG: BULK_INSERT_START + 1: BULK INSERTS LOG: BULK_INSERT_FINISH + 1: CREATE INDEX LOG: INSERTS_STATE OK, IS RUNNING + 1: CREATE INDEX LOG: CREATE_INDX_START + 1: CREATE INDEX LOG: SET TRANSACTION NO WAIT; + 1: CREATE INDEX LOG: CREATE INDEX TEST_NO_WAIT ON TEST COMPUTED BY( 'NO_WAIT'|| S ); + 1: CREATE INDEX LOG: COMMIT; + 1: CREATE INDEX LOG: STATEMENT FAILED, SQLSTATE = 40001 + 1: CREATE INDEX LOG: LOCK CONFLICT ON NO WAIT TRANSACTION + 1: CREATE INDEX LOG: -UNSUCCESSFUL METADATA UPDATE + 1: CREATE INDEX LOG: -OBJECT TABLE "TEST" IS IN USE + 1: CREATE INDEX LOG: AFTER LINE + + 2: BULK INSERTS LOG: BULK_INSERT_START + 2: BULK INSERTS LOG: BULK_INSERT_FINISH + 2: CREATE INDEX LOG: INSERTS_STATE OK, IS RUNNING + 2: CREATE INDEX LOG: CREATE_INDX_START + 2: CREATE INDEX LOG: SET TRANSACTION LOCK TIMEOUT 1; + 2: CREATE INDEX LOG: CREATE INDEX TEST_LOCK_TIMEOUT_1 ON TEST COMPUTED BY( 'LOCK_TIMEOUT_1'|| S ); + 2: CREATE INDEX LOG: COMMIT; + 2: CREATE INDEX LOG: STATEMENT FAILED, SQLSTATE = 40001 + 2: CREATE INDEX LOG: LOCK TIME-OUT ON WAIT TRANSACTION + 2: CREATE INDEX LOG: -UNSUCCESSFUL METADATA UPDATE + 2: CREATE INDEX LOG: -OBJECT TABLE "TEST" IS IN USE + 2: CREATE INDEX LOG: AFTER LINE + """ + +@pytest.mark.version('>=2.5.6') +@pytest.mark.xfail +def test_core_1746_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_1749.py b/tests/bugs/test_core_1749.py new file mode 100644 index 00000000..257fb916 --- /dev/null +++ b/tests/bugs/test_core_1749.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_1749 +# title: DDL statement with AUTODDL ON won't show statistics +# decription: +# tracker_id: CORE-1749 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [('^Current memory.*', ''), ('^Delta memory.*', ''), ('^Max memory.*', ''), ('^Elapsed time.*', ''), ('^Buffers.*', ''), ('^Reads.*', ''), ('^Writes.*', ''), ('^Elapsed time.*', ''), ('^Cpu.*', ''), ('^Fetches.*', 'STATS')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """set stat on; + +create generator A; + +set autoddl off; + +create generator B; +commit; + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """STATS +STATS +STATS +""" + +@pytest.mark.version('>=2.5.0') +def test_core_1749_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1750.py b/tests/bugs/test_core_1750.py new file mode 100644 index 00000000..ba484156 --- /dev/null +++ b/tests/bugs/test_core_1750.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: bugs.core_1750 +# title: Include information about context variables into the monitoring tables +# decription: +# tracker_id: CORE-1750 +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + select mon$variable_name, mon$variable_value from mon$context_variables; + commit; + set term ^; + execute block as + declare c int; + begin + c = rdb$set_context('USER_SESSION', 'SESSION_LEVEL_VARIABLE', 1); + end + ^ + commit + ^ + execute block as + declare c int; + begin + c = rdb$set_context('USER_TRANSACTION', 'TRANSACTION_LEVEL_VARIABLE', 1); + end + ^ + select mon$variable_name, mon$variable_value from mon$context_variables + ^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + + MON$VARIABLE_NAME SESSION_LEVEL_VARIABLE + MON$VARIABLE_VALUE 1 + MON$VARIABLE_NAME TRANSACTION_LEVEL_VARIABLE + MON$VARIABLE_VALUE 1 + + Records affected: 2 + """ + +@pytest.mark.version('>=2.5.0') +def test_core_1750_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1752.py b/tests/bugs/test_core_1752.py new file mode 100644 index 00000000..1ca89c4d --- /dev/null +++ b/tests/bugs/test_core_1752.py @@ -0,0 +1,71 @@ +#coding:utf-8 +# +# id: bugs.core_1752 +# title: Results of a join with different collations depend on the execution plan +# decription: +# tracker_id: CORE-1752 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core1752.fbk', init=init_script_1) + +test_script_1 = """ + select a.zeitstempel, b.artikelnr + from t1 a + join t2 b on b.artikelnr = a.artikelnr --collate de_de + order by 1,2 + ; + + select a.zeitstempel, b.artikelnr + from t1 a + join t2 b on b.artikelnr = a.artikelnr collate de_de + order by 1,2 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +ZEITSTEMPEL ARTIKELNR +================================ =============== +11997831915bde60630658f7ed147baa 10045 +1199797956ebe80ac53a54ebd164c707 9930 +1199798232de53f704854945c17be47e 10005 +1199799582060cc10385b2eafcdfd567 10045 +1199799582060cc10385b2eafcdfd567 10056 +119981802446bba36e437bf0181bb41c 9761 +119981811832e8ec4bb875a5d54ca202 9510 +1199823157b3f2d13b93184ab1e3b29d 9703 +1199827557240a59c5148b42a9374fc9 9920 + + +ZEITSTEMPEL ARTIKELNR +================================ =============== +11997831915bde60630658f7ed147baa 10045 +1199797956ebe80ac53a54ebd164c707 9930 +1199798232de53f704854945c17be47e 10005 +1199799582060cc10385b2eafcdfd567 10045 +1199799582060cc10385b2eafcdfd567 10056 +119981802446bba36e437bf0181bb41c 9761 +119981811832e8ec4bb875a5d54ca202 9510 +1199823157b3f2d13b93184ab1e3b29d 9703 +1199827557240a59c5148b42a9374fc9 9920 + """ + +@pytest.mark.version('>=2.5.1') +def test_core_1752_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1760.py b/tests/bugs/test_core_1760.py new file mode 100644 index 00000000..07ca15d4 --- /dev/null +++ b/tests/bugs/test_core_1760.py @@ -0,0 +1,195 @@ +#coding:utf-8 +# +# id: bugs.core_1760 +# title: Support hex numeric and string literals +# decription: +# See doc\\sql.extensions\\README.hex_literals.txt +# +# REFACTORED 27.02.2020: +# 1) all SQL code was moved into separate file: $files_location/core_1760.sql because it is common for all major FB versions; +# 2) added examples from https://firebirdsql.org/refdocs/langrefupd25-bigint.html (see core_1760.sql); +# 3) added check for output datatypes (sqlda_display). +# +# Checked on: +# 4.0.0.1789 SS: 1.458s. +# 3.0.6.33259 SS: 0.805s. +# 2.5.9.27149 SC: 0.397s. +# +# tracker_id: CORE-1760 +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('.*At line.*', ''), ('-Token unknown.*', '-Token unknown')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# #-------------------------------------------- +# +# 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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# #-------------------------------------------- +# +# db_conn.close() +# +# sql_chk = os.path.join(context['files_location'],'core_1760.sql') +# +# f_sql_log = open( os.path.join(context['temp_directory'],'tmp_core_1760.log'), 'w', buffering = 0) +# f_sql_err = open( os.path.join(context['temp_directory'],'tmp_core_1760.err'), 'w', buffering = 0) +# +# subprocess.call( [ context['isql_path'], dsn, '-q', '-i', sql_chk ], stdout = f_sql_log, stderr = f_sql_err) +# +# flush_and_close( f_sql_log ) +# flush_and_close( f_sql_err ) +# +# for f in (f_sql_log, f_sql_err): +# with open( f.name,'r') as g: +# for line in g: +# if line.strip(): +# print( ('STDOUT: ' if f == f_sql_log else 'STDERR: ') + line ) +# +# cleanup( (f_sql_log.name, f_sql_err.name) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + STDOUT: CONSTANT 11 + STDOUT: CONSTANT 0123456789 + STDOUT: CONSTANT 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 + STDOUT: UUID_TO_CHAR BA1749B5-83BF-9146-B360-F54E25FE583E + STDOUT: -1(a) -1 + STDOUT: +15 15 + STDOUT: 32767 32767 + STDOUT: 32768 32768 + STDOUT: 65535 65535 + STDOUT: 65536(a) 65536 + STDOUT: 65536(b) 65536 + STDOUT: -2147483648 -2147483648 + STDOUT: +2147483648(a) 2147483648 + STDOUT: +2147483648(b) 2147483648 + STDOUT: -1(b) -1 + STDOUT: +4294967295 4294967295 + STDOUT: +4294967296(a) 4294967296 + STDOUT: +4294967296(b) 4294967296 + STDOUT: 9223372036854775807 9223372036854775807 + STDOUT: -9223372036854775808 -9223372036854775808 + STDOUT: -9223372036854775807 -9223372036854775807 + STDOUT: -9223372036854775806 -9223372036854775806 + STDOUT: -1(c) -1 + STDOUT: INPUT message field count: 0 + STDOUT: OUTPUT message field count: 19 + STDOUT: 01: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + STDOUT: : name: -1(a) alias: -1(a) + STDOUT: : table: V_TEST owner: SYSDBA + STDOUT: 02: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + STDOUT: : name: +15 alias: +15 + STDOUT: : table: V_TEST owner: SYSDBA + STDOUT: 03: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + STDOUT: : name: 32767 alias: 32767 + STDOUT: : table: V_TEST owner: SYSDBA + STDOUT: 04: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + STDOUT: : name: 32768 alias: 32768 + STDOUT: : table: V_TEST owner: SYSDBA + STDOUT: 05: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + STDOUT: : name: 65535 alias: 65535 + STDOUT: : table: V_TEST owner: SYSDBA + STDOUT: 06: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + STDOUT: : name: 65536(a) alias: 65536(a) + STDOUT: : table: V_TEST owner: SYSDBA + STDOUT: 07: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + STDOUT: : name: 65536(b) alias: 65536(b) + STDOUT: : table: V_TEST owner: SYSDBA + STDOUT: 08: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + STDOUT: : name: -2147483648 alias: -2147483648 + STDOUT: : table: V_TEST owner: SYSDBA + STDOUT: 09: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + STDOUT: : name: +2147483648(a) alias: +2147483648(a) + STDOUT: : table: V_TEST owner: SYSDBA + STDOUT: 10: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + STDOUT: : name: +2147483648(b) alias: +2147483648(b) + STDOUT: : table: V_TEST owner: SYSDBA + STDOUT: 11: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + STDOUT: : name: -1(b) alias: -1(b) + STDOUT: : table: V_TEST owner: SYSDBA + STDOUT: 12: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + STDOUT: : name: +4294967295 alias: +4294967295 + STDOUT: : table: V_TEST owner: SYSDBA + STDOUT: 13: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + STDOUT: : name: +4294967296(a) alias: +4294967296(a) + STDOUT: : table: V_TEST owner: SYSDBA + STDOUT: 14: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + STDOUT: : name: +4294967296(b) alias: +4294967296(b) + STDOUT: : table: V_TEST owner: SYSDBA + STDOUT: 15: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + STDOUT: : name: 9223372036854775807 alias: 9223372036854775807 + STDOUT: : table: V_TEST owner: SYSDBA + STDOUT: 16: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + STDOUT: : name: -9223372036854775808 alias: -9223372036854775808 + STDOUT: : table: V_TEST owner: SYSDBA + STDOUT: 17: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + STDOUT: : name: -9223372036854775807 alias: -9223372036854775807 + STDOUT: : table: V_TEST owner: SYSDBA + STDOUT: 18: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + STDOUT: : name: -9223372036854775806 alias: -9223372036854775806 + STDOUT: : table: V_TEST owner: SYSDBA + STDOUT: 19: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + STDOUT: : name: -1(c) alias: -1(c) + STDOUT: : table: V_TEST owner: SYSDBA + + STDERR: Statement failed, SQLSTATE = 42000 + STDERR: Dynamic SQL Error + STDERR: -SQL error code = -104 + STDERR: -Token unknown - line 1, column 9 + STDERR: -'1' + + STDERR: Statement failed, SQLSTATE = 42000 + STDERR: Dynamic SQL Error + STDERR: -SQL error code = -104 + STDERR: -Token unknown - line 1, column 9 + STDERR: -'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678x' + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_1760_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_1774.py b/tests/bugs/test_core_1774.py new file mode 100644 index 00000000..ac4170b2 --- /dev/null +++ b/tests/bugs/test_core_1774.py @@ -0,0 +1,48 @@ +#coding:utf-8 +# +# id: bugs.core_1774 +# title: Problem with COLLATE ES_ES_CI_AI +# decription: +# tracker_id: CORE-1774 +# min_versions: ['2.0.7'] +# versions: 2.0.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='ISO8859_1', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table table_a ( + field_a varchar(100) character set iso8859_1 collate es_es_ci_ai + ); + commit; + insert into table_a (field_a) values ('Hace buena noche'); + insert into table_a (field_a) values ('Voy a hacer de comer'); + insert into table_a (field_a) values ('The web is hacked'); + commit; + + set list on; + select * from table_a where field_a like '%HACK%'; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + FIELD_A The web is hacked + """ + +@pytest.mark.version('>=2.0.7') +def test_core_1774_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1782.py b/tests/bugs/test_core_1782.py new file mode 100644 index 00000000..9a20d495 --- /dev/null +++ b/tests/bugs/test_core_1782.py @@ -0,0 +1,75 @@ +#coding:utf-8 +# +# id: bugs.core_1782 +# title: ISQL crashes when fetching data for a column having alias longer than 30 characters +# decription: +# tracker_id: CORE-1782 +# min_versions: ['2.1.7'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select 1 as test567890test567890test567890test567890 from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_core_1782_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + +# version: 4.0 +# resources: None + +substitutions_2 = [('-At line[:]{0,1}[\\s]+[\\d]+,[\\s]+column[:]{0,1}[\\s]+[\\d]+', '')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + -- NB: 4.0 has limit on length of column size = 255 _bytes_ (not characters). + -- More complex test see in core_2350.fbt + set list on; +select 'Check column title, ASCII, width = 256' as +i2345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890i2345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890i23456789012345678901234567890123456 +from rdb$database; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stderr_2 = """ + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -token size exceeds limit + """ + +@pytest.mark.version('>=4.0') +def test_core_1782_2(act_2: Action): + act_2.expected_stderr = expected_stderr_2 + act_2.execute() + assert act_2.clean_expected_stderr == act_2.clean_stderr + diff --git a/tests/bugs/test_core_1784.py b/tests/bugs/test_core_1784.py new file mode 100644 index 00000000..3f24ce28 --- /dev/null +++ b/tests/bugs/test_core_1784.py @@ -0,0 +1,60 @@ +#coding:utf-8 +# +# id: bugs.core_1784 +# title: Error with EXECUTE PROCEDURE inside EXECUTE STATEMENT +# decription: +# tracker_id: CORE-1784 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """set term ^ ; +create procedure p1 returns (n1 integer, n2 integer) +as +begin + n1 = 111; + n2 = 222; +end ^ + +set term ; ^ + +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """set term ^ ; + +execute block returns (n1 integer, n2 integer) +as +begin + execute statement + 'execute procedure p1' into n1, n2; + suspend; +end^ + +set term ; ^ +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + N1 N2 +============ ============ + 111 222 + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_1784_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1787.py b/tests/bugs/test_core_1787.py new file mode 100644 index 00000000..29b4526e --- /dev/null +++ b/tests/bugs/test_core_1787.py @@ -0,0 +1,61 @@ +#coding:utf-8 +# +# id: bugs.core_1787 +# title: Consistency check when subquery is ordered by aggregate function from other context +# decription: +# tracker_id: CORE-1787 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE TEST_TABLE1 +(ID BIGINT, + FK_ID INTEGER, + REG_DATE TIMESTAMP NOT NULL); + +COMMIT; + +insert into test_table1 values (1,5,'01.01.2000'); +insert into test_table1 values (2,5,'01.01.2001'); +insert into test_table1 values (3,7,'01.01.2002'); +insert into test_table1 values (4,8,'01.01.2003'); +insert into test_table1 values (5,8,'01.01.2004'); +insert into test_table1 values (6,8,'01.01.2005'); +insert into test_table1 values (7,8,'01.01.2007'); + +COMMIT; +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select t.fk_id,(select first 1 t1.reg_date from test_table1 t1 where t1.fk_id = t.fk_id + order by min(t.fk_id)) +from test_table1 t +group by t.fk_id; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + FK_ID REG_DATE +============ ========================= + 5 2000-01-01 00:00:00.0000 + 7 2002-01-01 00:00:00.0000 + 8 2003-01-01 00:00:00.0000 + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_1787_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1793.py b/tests/bugs/test_core_1793.py new file mode 100644 index 00000000..70ffc07e --- /dev/null +++ b/tests/bugs/test_core_1793.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_1793 +# title: AV at prepare of query with unused parametrized CTE +# decription: +# tracker_id: CORE-1793 +# min_versions: [] +# versions: 2.5 +# qmid: bugs.core_1793 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Updated 06.01.2018: + -- 25SC, build 2.5.8.27089: OK, 0.297s. + -- 30SS, build 3.0.3.32861: OK, 1.578s. + -- 40SS, build 4.0.0.840: OK, 1.390s. + recreate table test(x int); + commit; + set planonly; + with + x as (select x.x from test x), + y as (select y.x from test y) + select * from y; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (Y Y NATURAL) + """ +expected_stderr_1 = """ + SQL warning code = -104 + -CTE "X" is not used in query + """ + +@pytest.mark.version('>=2.5') +def test_core_1793_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1795.py b/tests/bugs/test_core_1795.py new file mode 100644 index 00000000..c151988d --- /dev/null +++ b/tests/bugs/test_core_1795.py @@ -0,0 +1,98 @@ +#coding:utf-8 +# +# id: bugs.core_1795 +# title: Server crashes on SQL script +# decription: +# tracker_id: CORE-1795 +# min_versions: ['2.1.7'] +# versions: 2.1.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table colors ( + colorid integer not null, + colorname varchar(20) + ); + + create table flowers ( + flowerid integer not null, + flowername varchar(30), + colorid integer + ); + + commit; + + insert into colors (colorid, colorname) values (0, 'not defined'); + insert into colors (colorid, colorname) values (1, 'red'); + insert into colors (colorid, colorname) values (2, 'white'); + insert into colors (colorid, colorname) values (3, 'blue'); + insert into colors (colorid, colorname) values (4, 'yellow'); + insert into colors (colorid, colorname) values (5, 'black'); + insert into colors (colorid, colorname) values (6, 'purple'); + + insert into flowers (flowerid, flowername, colorid) values (1, 'red rose', 1); + insert into flowers (flowerid, flowername, colorid) values (2, 'white rose', 2); + insert into flowers (flowerid, flowername, colorid) values (3, 'blue rose', 3); + insert into flowers (flowerid, flowername, colorid) values (4, 'yellow rose', 4); + insert into flowers (flowerid, flowername, colorid) values (5, 'black rose', 5); + insert into flowers (flowerid, flowername, colorid) values (6, 'red tulip', 1); + insert into flowers (flowerid, flowername, colorid) values (7, 'white tulip', 2); + insert into flowers (flowerid, flowername, colorid) values (8, 'yellow tulip', 4); + insert into flowers (flowerid, flowername, colorid) values (9, 'blue gerbera', 3); + insert into flowers (flowerid, flowername, colorid) values (10, 'purple gerbera', 6); + + commit; + + -- normally these indexes are created by the primary/foreign keys, + -- but we don't want to rely on them for this test + create unique asc index pk_colors on colors (colorid); + create unique asc index pk_flowers on flowers (flowerid); + create asc index fk_flowers_colors on flowers (colorid); + create asc index i_colors_colorname on colors (colorname); + commit; + + set list on; + -- disable output of PLAN, it differ in 3.0 vs rest: set plan on; + select + f.colorid, + c.colorname, + count(*) + from + colors c + left join flowers f on (f.colorid = c.colorid) + group by + f.colorid, c.colorname + having + c.colorname starting with 'b'; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + COLORID 3 + COLORNAME blue + COUNT 2 + + COLORID 5 + COLORNAME black + COUNT 1 + """ + +@pytest.mark.version('>=2.1.7') +def test_core_1795_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1797.py b/tests/bugs/test_core_1797.py new file mode 100644 index 00000000..dd15f210 --- /dev/null +++ b/tests/bugs/test_core_1797.py @@ -0,0 +1,84 @@ +#coding:utf-8 +# +# id: bugs.core_1797 +# title: OLD/NEW.RDB$DB_KEY returns incorrect result in triggers +# decription: +# tracker_id: CORE-1797 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t (n integer) ; +create table x (c char(8) character set octets); +set term ^ ; +create trigger t_ai for t after insert +as +begin + insert into x values (new.rdb$db_key); +end ^ +set term ; ^ +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """insert into t values (1) returning rdb$db_key; + +select rdb$db_key from t; +select * from x; + +insert into t values (2) returning rdb$db_key; + +select rdb$db_key from t; +select * from x; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +DB_KEY +================ +8000000001000000 + + +DB_KEY +================ +8000000001000000 + + +C +================ +8000000001000000 + + +DB_KEY +================ +8000000002000000 + + +DB_KEY +================ +8000000001000000 +8000000002000000 + + +C +================ +8000000001000000 +8000000002000000 + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_1797_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1798.py b/tests/bugs/test_core_1798.py new file mode 100644 index 00000000..9d548a63 --- /dev/null +++ b/tests/bugs/test_core_1798.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: bugs.core_1798 +# title: RDB$DB_KEY evaluates to NULL in INSERT ... RETURNING +# decription: +# tracker_id: +# min_versions: [] +# versions: 2.1.1 +# qmid: bugs.core_1798 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t (n integer); +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """insert into t values (1) returning rdb$db_key; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +DB_KEY +================ +8000000001000000 + +""" + +@pytest.mark.version('>=2.1.1') +def test_core_1798_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1802.py b/tests/bugs/test_core_1802.py new file mode 100644 index 00000000..f76e4f43 --- /dev/null +++ b/tests/bugs/test_core_1802.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: bugs.core_1802 +# title: Maximum key size using PXW_CSY collation +# decription: +# tracker_id: CORE-1802 +# min_versions: [] +# versions: 2.5.3 +# qmid: bugs.core_1802 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE TABLE TAB21( + ID INTEGER, + A VARCHAR(490) CHARACTER SET WIN1250 COLLATE PXW_CSY, + CONSTRAINT CU UNIQUE(A) ); +COMMIT; +SHOW INDEX CU; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """CU UNIQUE INDEX ON TAB21(A) +""" + +@pytest.mark.version('>=2.5.3') +def test_core_1802_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1810.py b/tests/bugs/test_core_1810.py new file mode 100644 index 00000000..278687a7 --- /dev/null +++ b/tests/bugs/test_core_1810.py @@ -0,0 +1,80 @@ +#coding:utf-8 +# +# id: bugs.core_1810 +# title: Usernames with '.' character +# decription: +# tracker_id: CORE-1810 +# min_versions: ['2.1.7'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('Statement failed, SQLSTATE.*', ''), ('record not found for user:.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set wng off; + recreate table test(id int, x int, y int, z int); + commit; + insert into test values(1, 100, 200, 300); + commit; + drop user "$.$"; + commit; + create role "#.#"; + commit; + create user "$.$" password '123'; + commit; + + revoke all on all from "$.$"; + grant "#.#" to "$.$"; + grant select on test to "#.#"; + commit; + + connect '$(DSN)' user "$.$" password '123' role "#.#"; + commit; + + select + current_user, + current_role, + iif( upper(a.mon$remote_protocol) starting with upper('TCP'), 'YES', 'NO!') is_remote_connection + from rdb$database m + join mon$attachments a on a.mon$attachment_id = current_connection + ; + + select * from test; + commit; + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + commit; + drop user "$.$"; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + USER $.$ + ROLE #.# + IS_REMOTE_CONNECTION YES + + ID 1 + X 100 + Y 200 + Z 300 + """ + +@pytest.mark.version('>=2.5') +def test_core_1810_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1811.py b/tests/bugs/test_core_1811.py new file mode 100644 index 00000000..958bc51e --- /dev/null +++ b/tests/bugs/test_core_1811.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_1811 +# title: Incorrect parser's reaction to the unquoted usage of the keyword "VALUE" +# decription: +# tracker_id: CORE-1811 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """recreate table T ( "VALUE" int ) ; +commit; +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """delete from T where "VALUE" = 1; +-- OK + +delete from T where value = 1 ; +-- ERROR: Illegal use of keyword VALUE +-- This is correct. + +delete from T where value = ? ; +-- ERROR: Data type unknown (release build) or assertion failure (debug build) +-- There should be the same error as previously (Illegal use of keyword VALUE) +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42000 +Dynamic SQL Error +-SQL error code = -901 +-Illegal use of keyword VALUE +Statement failed, SQLSTATE = 42000 +Dynamic SQL Error +-SQL error code = -901 +-Illegal use of keyword VALUE +""" + +@pytest.mark.version('>=2.5.0') +def test_core_1811_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_1812.py b/tests/bugs/test_core_1812.py new file mode 100644 index 00000000..630b2655 --- /dev/null +++ b/tests/bugs/test_core_1812.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_1812 +# title: Index is not used for some date/time expressions in dialect 1 +# decription: +# 02.02.2019. Added separate code for FB 4.0: statements like SELECT TIMESTAMP 'now' FROM RDB$DATABASE; +# -- can not be used anymore (Statement failed, SQLSTATE = 22018 / conversion error from string "now"). +# Details about timezone datatype see in: doc\\sql.extensions\\README.time_zone.md +# +# tracker_id: CORE-1812 +# min_versions: [] +# versions: 4.0 +# qmid: bugs.core_1812 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=1, init=init_script_1) + +test_script_1 = """ + create table test (dts timestamp) ; + commit; + insert into test + select dateadd( rand() * 10 second to localtimestamp ) + from rdb$types, rdb$types; + commit; + create index test_dts on test(dts); + commit; + + set planonly; + select * from test where dts = localtimestamp; + select * from test where dts = current_timestamp; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (TEST INDEX (TEST_DTS)) + PLAN (TEST NATURAL) + """ + +@pytest.mark.version('>=4.0') +def test_core_1812_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1815.py b/tests/bugs/test_core_1815.py new file mode 100644 index 00000000..512108e0 --- /dev/null +++ b/tests/bugs/test_core_1815.py @@ -0,0 +1,439 @@ +#coding:utf-8 +# +# id: bugs.core_1815 +# title: Ability to grant role to another role +# decription: +# ### 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. +# +# Checked on WI-T4.0.0.322 -- all fine. +# +# tracker_id: CORE-1815 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + 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 user tmp$c1815_boss password 'boss' revoke admin role; -- boss + create or alter user tmp$c1815_acnt password 'acnt' revoke admin role; -- accountant + create or alter user tmp$c1815_pdsk password 'pdsk' revoke admin role; -- paydesk + commit; + + revoke all on all from tmp$c1815_boss; + revoke all on all from tmp$c1815_acnt; + revoke all on all from tmp$c1815_pdsk; + commit; + + 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; + + set term ^; + execute block as + begin + begin execute statement 'drop role rboss'; when any do begin end end + begin execute statement 'drop role racnt'; when any do begin end end + begin execute statement 'drop role rpdsk'; when any do begin end end + end + ^ + set term ^; + 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; + + -- 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 + + -- 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; + + -- ############################################################################################### + + connect '$(DSN)' user sysdba password 'masterkey'; + + -- 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): + + grant racnt to rboss; -- RESTORE access for role 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 PASS + commit; + + -- cleanup + connect '$(DSN)' user sysdba password 'masterkey'; + drop user tmp$c1815_boss; + drop user tmp$c1815_acnt; + drop user tmp$c1815_pdsk; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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 + + WHOAMI TMP$C1815_ACNT + MY_ROLE RACNT + R_NAME RPDSK + R_OWNER SYSDBA + R_IN_USE + + + WHOAMI TMP$C1815_ACNT + ID 1 + S acnt + + + WHOAMI TMP$C1815_PDSK + MY_ROLE RPDSK + R_NAME RBOSS + R_OWNER SYSDBA + R_IN_USE + + WHOAMI TMP$C1815_PDSK + MY_ROLE RPDSK + R_NAME RACNT + R_OWNER SYSDBA + R_IN_USE + + WHOAMI TMP$C1815_PDSK + MY_ROLE RPDSK + R_NAME RPDSK + R_OWNER SYSDBA + R_IN_USE + + + WHOAMI TMP$C1815_PDSK + 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 + 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 + + WHOAMI TMP$C1815_BOSS + MY_ROLE RBOSS + R_NAME RPDSK + R_OWNER SYSDBA + R_IN_USE + + + 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 + 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 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE TPDSK + -Effective user is TMP$C1815_BOSS + + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE TACNT + -Effective user is TMP$C1815_BOSS + """ + +@pytest.mark.version('>=4.0') +def test_core_1815_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1828.py b/tests/bugs/test_core_1828.py new file mode 100644 index 00000000..b0181954 --- /dev/null +++ b/tests/bugs/test_core_1828.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: bugs.core_1828 +# title: Error with ABS in dialect 1 +# decription: +# tracker_id: CORE-1828 +# min_versions: ['2.5'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE TEST (MYNUM INTEGER); +COMMIT; +INSERT INTO TEST (MYNUM) VALUES (1); +INSERT INTO TEST (MYNUM) VALUES (-1); +INSERT INTO TEST (MYNUM) VALUES (2147483647); +INSERT INTO TEST (MYNUM) VALUES (-2147483648); +COMMIT; +""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=1, init=init_script_1) + +test_script_1 = """SELECT ABS(MYNUM) FROM TEST;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ABS +======================= + 1.000000000000000 + 1.000000000000000 + 2147483647.000000 + 2147483648.000000 + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_1828_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1830.py b/tests/bugs/test_core_1830.py new file mode 100644 index 00000000..eded2fe5 --- /dev/null +++ b/tests/bugs/test_core_1830.py @@ -0,0 +1,79 @@ +#coding:utf-8 +# +# id: bugs.core_1830 +# title: Possible index corruption with multiply updates of the same record in the same transaction and using of savepoints +# decription: +# tracker_id: CORE-1830 +# min_versions: [] +# versions: 2.5 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('column.*', 'column x'), ('[ \t]+', ' '), ('-At block line: [\\d]+, col: [\\d]+', '')] + +init_script_1 = """ + create table a(id char(1), name varchar(255)); + + create index idx_a on a (id); + create exception ex_perm 'Something wrong occurs...'; + commit ; + + insert into a (id) values ('1'); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select * from a where id = '1'; + set term ^; + execute block as + begin + update a set name = 'xxx'; + update a set id = '2'; + exception ex_perm; + end ^ + set term ; ^ + select * from a ; + select * from a where id = '1' ; + + commit; + select * from a ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + NAME + + ID 1 + NAME + + ID 1 + NAME + + ID 1 + NAME + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = HY000 + exception 1 + -EX_PERM + -Something wrong occurs... + """ + +@pytest.mark.version('>=2.5') +def test_core_1830_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1837.py b/tests/bugs/test_core_1837.py new file mode 100644 index 00000000..6469e4b0 --- /dev/null +++ b/tests/bugs/test_core_1837.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: bugs.core_1837 +# title: Procedure text is stored truncated in system tables if any variable have default value +# decription: +# tracker_id: CORE-1837 +# min_versions: ['2.1.7'] +# versions: 2.1.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.7 +# resources: None + +substitutions_1 = [('RDB\\$PROCEDURE_SOURCE.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create procedure sp_test + as + declare x int = 0; + begin + exit; + end ^ + commit ^ + + set list on ^ + set blob all ^ + select p.rdb$procedure_source from rdb$procedures p where p.rdb$procedure_name = upper('sp_test') ^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$PROCEDURE_SOURCE 1a:0 + declare x int = 0; + begin + exit; + end + """ + +@pytest.mark.version('>=2.1.7') +def test_core_1837_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1839.py b/tests/bugs/test_core_1839.py new file mode 100644 index 00000000..22061518 --- /dev/null +++ b/tests/bugs/test_core_1839.py @@ -0,0 +1,112 @@ +#coding:utf-8 +# +# id: bugs.core_1839 +# title: AV when sorting by field, calculated using recursive CTE +# decription: Bug happened only when table, used in CTE, contained records with different formats +# tracker_id: CORE-1839 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('ALL_CAPTIONS.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test(id int, pid int, name varchar(20)); + commit; + insert into test values(1, null, 'earth'); + insert into test values(2, 1, 'europe'); + insert into test values(3, 2, 'Sverige'); + insert into test values(4, 2, 'Norge'); + insert into test values(5, 2, 'Dänemarks'); + insert into test values(6, 1, 'africa'); + insert into test values(7, 6, 'kenya'); + insert into test values(8, 6, 'egypt'); + commit; + + alter table test add geo char(48); ------ change records format + commit; + + insert into test values(9, 1, 'asia', null); + insert into test values(10, 9, 'iran', null); + insert into test values(11, 9, 'turkey', null); + insert into test values(12, 10, 'tehran', '35°41''46"N 51°25''23"E'); + insert into test values(13, 11, 'istanbul', '41°00''49"N 28°57''18"E'); + + -- pid = 7 - kenya, 8= egypt + insert into test values(14, 7, 'nairobi', '1°17''S 36°49"E'); + insert into test values(15, 8, 'al-qāhirah', '30°3''0"N 31°14''0"E'); + + commit; + + alter table test add full_caption computed by ( + ( + with recursive + r as( + select a.id, a.pid, cast(a.name as varchar(8000)) caption, a.geo, 0 as rlevel + from test a + where a.pid is null + union all + select b.id, b.pid, r.caption ||':' || b.name, b.geo, r.rlevel+1 + --select b.id, b.pid, b.name, b.geo, r.rlevel+1 + from test b + join r on b.pid=r.id + ) + ,c as( + select id,caption||':'||geo full_name from r where geo is not null order by id desc + ) + select full_name + from c + where id = test.id + ) + ); + commit; + + alter table test ------ change records format + add year_found smallint, + alter geo type varchar(50), + alter full_caption position 1, + alter pid type bigint, + alter id type bigint + ; + commit; + -- pid=3 = sweden, 4 = norway, 5 = denmark + insert into test values(16, 3, 'stockholm', '59°19''46"N 18°4''7"E', 1252); + insert into test values(17, 4, 'oslo', '59°57"N 10°45"E', 1000); + insert into test values(18, 5, 'København', '55°40''34"N 12°34''6"E', 1167); + + commit; + + set list on; + select list(x.full_caption, ';') all_captions + from ( + select trim(x.full_caption) full_caption + from test x + where x.full_caption is not null + order by cast( x.full_caption as varchar(8000) ) + ) x; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ALL_CAPTIONS 0:1 + earth:africa:egypt:al-qāhirah:30°3'0"N 31°14'0"E;earth:africa:kenya:nairobi:1°17'S 36°49"E;earth:asia:iran:tehran:35°41'46"N 51°25'23"E;earth:asia:turkey:istanbul:41°00'49"N 28°57'18"E;earth:europe:Dänemarks:København:55°40'34"N 12°34'6"E;earth:europe:Norge:oslo:59°57"N 10°45"E;earth:europe:Sverige:stockholm:59°19'46"N 18°4'7"E + """ + +@pytest.mark.version('>=2.5') +def test_core_1839_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1841.py b/tests/bugs/test_core_1841.py new file mode 100644 index 00000000..35fe2a1e --- /dev/null +++ b/tests/bugs/test_core_1841.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: bugs.core_1841 +# title: If some VIEW used derived tables and long table namesliases, It is possible to overflow RDB$VIEW_RELATIONS.RDB$CONTEXT_NAME +# decription: +# tracker_id: CORE-1841 +# min_versions: [] +# versions: 2.5.0 +# qmid: bugs.core_1841-250 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """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; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ID SMALLINT Expression +View Source: +==== ====== + +select RDB$RELATION_ID + from (select * from RDB$DATABASE long_alias_long_alias_1) long_alias_long_alias_2 +""" + +@pytest.mark.version('>=2.5.0') +def test_core_1841_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1842.py b/tests/bugs/test_core_1842.py new file mode 100644 index 00000000..ad90e4b2 --- /dev/null +++ b/tests/bugs/test_core_1842.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_1842 +# title: DEFAULT values are unnecessary evaluated +# decription: +# tracker_id: CORE-1842 +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table tb_date ( + tb_date_id integer not null primary key, + f_date date default 0); +commit;""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """INSERT INTO TB_DATE ( + TB_DATE_ID, F_DATE) + VALUES ( + 1, '09-MAY-1945'); +insert into tb_date ( + tb_date_id, f_date) + values ( + 2, null); +commit; +SELECT TB_DATE_ID, F_DATE FROM TB_DATE; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Database: localhost:C: btest2 mpugs.core_1842.fdb, User: SYSDBA +SQL> CON> CON> CON> SQL> CON> CON> CON> SQL> SQL> + TB_DATE_ID F_DATE +============ =========== + 1 1945-05-09 + 2 + +SQL>""" + +@pytest.mark.version('>=2.5.0') +def test_core_1842_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1845.py b/tests/bugs/test_core_1845.py new file mode 100644 index 00000000..aa2a1688 --- /dev/null +++ b/tests/bugs/test_core_1845.py @@ -0,0 +1,163 @@ +#coding:utf-8 +# +# id: bugs.core_1845 +# title: Some standard calls show server installation directory to regular users +# decription: +# Instead of usage 'resource:test_user' (as it was before) we create every time this test run user TMP$C1845 +# and make test connect to database with login = this user in order to check ability to make attach. +# Then we do subsequent run of FBSVCMGR utility with passing ONE of following options from 'Information requests' +# group: +# info_server_version +# info_implementation +# info_user_dbpath +# info_get_env +# info_get_env_lock +# info_get_env_msg +# info_svr_db_info +# info_version +# NOTE: option 'info_capabilities' was introduces only in 3.0. Its output differs on Classic vs SS and SC. +# Currently this option is NOT passed to fbsvcmgr. +# +# tracker_id: CORE-1845 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: bugs.core_1845 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('SERVER VERSION:.*', 'SERVER VERSION:'), ('SERVER IMPLEMENTATION:.*', 'SERVER IMPLEMENTATION:'), ('SERVICE MANAGER VERSION:.*', 'SERVICE MANAGER VERSION:'), ('Statement failed, SQLSTATE = HY000', ''), ('record not found for user.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# +# # Refactored 05-JAN-2016: removed dependency on recource 'test_user' because this lead to: +# # UNTESTED: bugs.core_1845 +# # Add new user +# # Unexpected stderr stream received from GSEC. +# # (i.e. test remained in state "Untested" because of internal error in gsec while creating user 'test' from resource). +# # Checked on WI-V2.5.5.26952 (SC), WI-V3.0.0.32266 (SS/SC/CS). +# +# import os +# import subprocess +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# #-------------------------------------------- +# +# 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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# +# #-------------------------------------------- +# +# sql_create_user=''' drop user tmp$c1845; +# commit; +# create user tmp$c1845 password 'QweRtyUi'; +# commit; +# connect '%s' user 'TMP$C1845' password 'QweRtyUi'; +# set list on; +# select current_user who_am_i from rdb$database; +# quit; +# ''' % dsn +# +# sqllog=open( os.path.join(context['temp_directory'],'tmp_user_1845.log'), 'w') +# sqllog.close() +# runProgram('isql',[dsn,'-user',user_name,'-pas',user_password,'-q','-m', '-o', sqllog.name], sql_create_user) +# +# +# fn_log=open( os.path.join(context['temp_directory'],'tmp_fbsvc_1845.log'), 'w') +# +# svc_list=["info_server_version","info_implementation","info_user_dbpath","info_get_env","info_get_env_lock","info_get_env_msg","info_svr_db_info","info_version"] +# +# for i in range(len(svc_list)): +# fn_log.write("Check service '"+svc_list[i]+"':") +# fn_log.write("\\n") +# fn_log.seek(0,2) +# subprocess.call([ context['fbsvcmgr_path'],"localhost:service_mgr","user","TMP$C1845","password","QweRtyUi", svc_list[i]] +# ,stdout=fn_log +# ,stderr=fn_log +# ) +# fn_log.write("\\n") +# +# flush_and_close( fn_log ) +# +# # CLEANUP: drop user that was temp-ly created for this test: +# ########## +# runProgram('isql', [dsn, '-q','-m', '-o', sqllog.name], 'drop user tmp$c1845; commit;') +# +# # Check content of files: 1st shuld contain name of temply created user, 2nd should be with error during get FB log: +# +# with open( sqllog.name,'r') as f: +# print(f.read()) +# +# # Print output of fbsvcmgr but: 1) remove exceessive whitespaces from lines; 2) transform text to uppercase +# # (in order to reduce possibility of mismatches in case of minor changes that can occur in future versions of fbsvcmgr) +# +# with open( fn_log.name,'r') as f: +# for line in f: +# print( ' '.join(line.split()).upper() ) +# +# # Do not remove this pause: on Windows closing of handles can take some (small) time. +# # Otherwise Windows(32) access error can raise here. +# time.sleep(1) +# +# cleanup( (sqllog.name, fn_log.name) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHO_AM_I TMP$C1845 + CHECK SERVICE 'INFO_SERVER_VERSION': + SERVER VERSION: WI-V3.0.0.32266 FIREBIRD 3.0 RELEASE CANDIDATE 2 + CHECK SERVICE 'INFO_IMPLEMENTATION': + SERVER IMPLEMENTATION: FIREBIRD/WINDOWS/INTEL/I386 + CHECK SERVICE 'INFO_USER_DBPATH': + SERVICE ISC_INFO_SVC_USER_DBPATH REQUIRES SYSDBA PERMISSIONS. REATTACH TO THE SERVICE MANAGER USING THE SYSDBA ACCOUNT. + CHECK SERVICE 'INFO_GET_ENV': + SERVICE ISC_INFO_SVC_GET_ENV REQUIRES SYSDBA PERMISSIONS. REATTACH TO THE SERVICE MANAGER USING THE SYSDBA ACCOUNT. + CHECK SERVICE 'INFO_GET_ENV_LOCK': + SERVICE ISC_INFO_SVC_GET_ENV REQUIRES SYSDBA PERMISSIONS. REATTACH TO THE SERVICE MANAGER USING THE SYSDBA ACCOUNT. + CHECK SERVICE 'INFO_GET_ENV_MSG': + SERVICE ISC_INFO_SVC_GET_ENV REQUIRES SYSDBA PERMISSIONS. REATTACH TO THE SERVICE MANAGER USING THE SYSDBA ACCOUNT. + CHECK SERVICE 'INFO_SVR_DB_INFO': + SERVICE ISC_INFO_SVC_SVR_DB_INFO REQUIRES SYSDBA PERMISSIONS. REATTACH TO THE SERVICE MANAGER USING THE SYSDBA ACCOUNT. + CHECK SERVICE 'INFO_VERSION': + SERVICE MANAGER VERSION: 2 + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_1845_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_1846.py b/tests/bugs/test_core_1846.py new file mode 100644 index 00000000..26e47da2 --- /dev/null +++ b/tests/bugs/test_core_1846.py @@ -0,0 +1,55 @@ +#coding:utf-8 +# +# id: bugs.core_1846 +# title: Allow index walk (ORDER plan) when there is a composite index {A, B} and the query looks like WHERE A = ? ORDER BY B +# decription: +# tracker_id: CORE-1846 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test( + n1 int + ,n2 int + ); + commit; + + insert into test select rand()*100, rand()*100 from rdb$types; + commit; + + create index test_n1_n2_asc on test(n1, n2); + commit; + create descending index test_n2_n1_desc on test(n2, n1); + commit; + + set planonly; + select * from test where n1 = ? order by n2 asc; + select * from test where n2 = ? order by n1 desc; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (TEST ORDER TEST_N1_N2_ASC) + PLAN (TEST ORDER TEST_N2_N1_DESC) + """ + +@pytest.mark.version('>=3.0') +def test_core_1846_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1859.py b/tests/bugs/test_core_1859.py new file mode 100644 index 00000000..345c66cd --- /dev/null +++ b/tests/bugs/test_core_1859.py @@ -0,0 +1,68 @@ +#coding:utf-8 +# +# id: bugs.core_1859 +# title: Arithmetic overflow or division by zero has occurred. in MAX function +# decription: +# It was found that error raises in 2.1.0.17798 when we create table with two fields +# of UNICODE_FSS type and add there six rows. Content of fields were taken from table +# rdb$procedure_parameters of empty database. +# Data that are inserted have been found after several simplifications of source DB. +# Exception that raised: +# === +# Statement failed, SQLCODE = -802 +# arithmetic exception, numeric overflow, or string truncation +# === +# Checked on: +# 2.1.1.17910 -- no error. +# 2.5.9.27126: OK, 0.672s. +# 3.0.5.33086: OK, 1.343s. +# 4.0.0.1378: OK, 5.797s. +# +# tracker_id: CORE-1859 +# min_versions: ['2.1.7'] +# versions: 2.1.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test( param_name rdb$parameter_name, proc_name rdb$procedure_name ); + commit; + insert into test values('A1', 'ABCDEFGHIJK'); + insert into test values('A', 'ASDFGHJKL'); + commit; + + set list on; + set count on; + select sign(count(*)) + from ( + select t.param_name, max( t.proc_name ) pnmax + from + ( select t.param_name, t.proc_name from test t rows 6 ) t + group by 1 + ); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + SIGN 1 + Records affected: 1 + """ + +@pytest.mark.version('>=2.1.7') +def test_core_1859_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1865.py b/tests/bugs/test_core_1865.py new file mode 100644 index 00000000..8bf12b02 --- /dev/null +++ b/tests/bugs/test_core_1865.py @@ -0,0 +1,87 @@ +#coding:utf-8 +# +# id: bugs.core_1865 +# title: BLR error on restore database with computed by Field +# decription: +# Confirmed bug on WI-V2.0.0.12724: it was unable to restore DB with "-o" command switch ("-one_at_a_time"): +# got errors that are specified in the ticket. +# No errors on WI-V2.1.0.17798, and also on: +# 2.5.9.27107: OK, 1.953s. +# 3.0.4.32924: OK, 5.281s. +# 4.0.0.918: OK, 4.078s. +# NB-1: old versions of FB did restore with redirection all messages to STDERR, w/o STDOUT. For this reason we store +# all output to file and then check whether this file contains at least one line with phrase "ERROR:". +# NB-2: could _NOT_ reproduce without use "-o" command switch! +# +# tracker_id: CORE-1865 +# min_versions: ['2.0.0'] +# versions: 2.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import time +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# sql_ddl=''' +# create table tmain(id int); +# create table tdetl( id int, pid int, cost numeric(12,2) ); +# alter table tmain +# add dsum2 computed by ( (select sum(cost) from tdetl d where d.pid = tmain.id) ) +# ; +# commit; +# ''' +# runProgram('isql', [ dsn, '-q' ], sql_ddl) +# +# tmpfbk='$(DATABASE_LOCATION)'+'core_1865.fbk' +# tmpfdb='$(DATABASE_LOCATION)'+'tmp_check_1865.fdb' +# +# runProgram( 'gbak', [ '-b', dsn, tmpfbk ] ) +# +# f_restore_log=open( os.path.join(context['temp_directory'],'tmp_check_1865.log'), 'w') +# subprocess.call( [ context['gbak_path'], '-rep', '-o', '-v', tmpfbk, 'localhost:' + tmpfdb], stdout = f_restore_log, stderr=subprocess.STDOUT) +# f_restore_log.close() +# time.sleep(1) +# +# # should be empty: +# ################## +# with open( f_restore_log.name,'r') as f: +# for line in f: +# if line.split(): +# if 'ERROR:'.lower() in line.lower(): +# print('UNEXPECTED ERROR ON RESTORE: '+line) +# +# os.remove(f_restore_log.name) +# os.remove(tmpfdb) +# os.remove(tmpfbk) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.0') +@pytest.mark.xfail +def test_core_1865_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_1869.py b/tests/bugs/test_core_1869.py new file mode 100644 index 00000000..604a8369 --- /dev/null +++ b/tests/bugs/test_core_1869.py @@ -0,0 +1,139 @@ +#coding:utf-8 +# +# id: bugs.core_1869 +# title: Roles granting/revoking logic +# decription: +# Test for "grant ... to ... GRANTED BY ..." clause +# Checked on: +# 2.5.9.27107: OK, 0.656s. +# 3.0.4.32924: OK, 4.313s. +# 4.0.0.916: OK, 2.406s. +# +# tracker_id: CORE-1869 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create user tmp$c1869_u01 password '123'; + create user tmp$c1869_u02 password '123'; + set term ^; + execute block as + begin + execute statement 'drop role boss'; + when any do begin end + end + ^ + set term ;^ + commit; + create role boss; + commit; + + recreate view v_grants as + select + p.rdb$user as who_was_granted + ,p.rdb$privilege as privilege_type + ,p.rdb$relation_name as role_name + ,r.rdb$owner_name as role_owner + ,p.rdb$grantor as granted_by + ,p.rdb$grant_option as grant_option + from rdb$user_privileges p + left join rdb$roles r on p.rdb$relation_name = r.rdb$role_name + where + p.rdb$object_type=13 + and upper(p.rdb$user) != upper('SYSDBA') -- we have to add this because role RDB$ADMIN is shown as granted to SYSDBA in 4.0.x + ; + commit; + grant select on v_grants to public; + commit; + + set list on; + + grant boss to tmp$c1869_u01; + grant boss to tmp$c1869_u02 granted by tmp$c1869_u01; + commit; + + -- TWO record should be printed: + select 'init' as msg, v.* from v_grants v; + commit; + + connect '$(DSN)' user 'tmp$c1869_u02' password '123' role 'BOSS'; + + select current_user, current_role from rdb$database; + commit; + + connect '$(DSN)' user 'tmp$c1869_u01' password '123'; + + -- this should PASS without error: user "_u01" was specified as GRANTOR in the statement: + -- "grant boss to ..._u02 granted by ..._u01" (see above): + revoke boss from tmp$c1869_u02; + commit; + + connect '$(DSN)' user 'tmp$c1869_u02' password '123' role 'BOSS'; + + -- Now user ..._u02 should be connected WITHOUT any actual role: + select current_user, current_role from rdb$database; + + -- now only ONE record should be printed: + select 'fini' as msg, v.* from v_grants v; + commit; + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + drop user tmp$c1869_u01; + drop user tmp$c1869_u02; + commit; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG init + WHO_WAS_GRANTED TMP$C1869_U01 + PRIVILEGE_TYPE M + ROLE_NAME BOSS + ROLE_OWNER SYSDBA + GRANTED_BY SYSDBA + GRANT_OPTION 0 + + MSG init + WHO_WAS_GRANTED TMP$C1869_U02 + PRIVILEGE_TYPE M + ROLE_NAME BOSS + ROLE_OWNER SYSDBA + GRANTED_BY TMP$C1869_U01 + GRANT_OPTION 0 + + USER TMP$C1869_U02 + ROLE BOSS + + USER TMP$C1869_U02 + ROLE NONE + + MSG fini + WHO_WAS_GRANTED TMP$C1869_U01 + PRIVILEGE_TYPE M + ROLE_NAME BOSS + ROLE_OWNER SYSDBA + GRANTED_BY SYSDBA + GRANT_OPTION 0 + """ + +@pytest.mark.version('>=2.5') +def test_core_1869_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1875.py b/tests/bugs/test_core_1875.py new file mode 100644 index 00000000..781e3066 --- /dev/null +++ b/tests/bugs/test_core_1875.py @@ -0,0 +1,78 @@ +#coding:utf-8 +# +# id: bugs.core_1875 +# title: Error on script with current_date +# decription: +# Confirmed bug on: 2.1.0.17798, result was: +# === +# Statement failed, SQLCODE = -902 +# Unable to complete network request to host "localhost". +# -Error reading data from the connection. +# Connection rejected by remote interface +# === +# Works fine on: 2.1.1.17910. +# Also checked on: +# build 2.5.9.27107: OK, 0.391s. +# build 3.0.4.32924: OK, 2.610s. +# build 4.0.0.916: OK, 1.515s. +# PS. +# It seems that bug was somehow related to "if" statement. For example, following statements: +# select 1 from new_table nt where nt.data_reg = cast(current_date as date) into c; +# or: +# select 1 from rdb$database +# where not exists( +# select 1 from new_table nt where nt.data_reg = cast(current_date as date) +# ) +# into c; +# -- finished without errors. +# +# tracker_id: CORE-1875 +# min_versions: ['2.1.0'] +# versions: 2.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table new_table ( + data_reg timestamp -- can be used in this test instead of type 'date' (result the same: 2.1.0 crashes) + ); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set term ^; + execute block returns(msg varchar(10)) as + declare c int; + begin + if ( exists( select 1 from new_table nt where nt.data_reg = cast(current_date as date) ) ) then + begin + end + msg = 'Done'; + suspend; + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG Done + """ + +@pytest.mark.version('>=2.1') +def test_core_1875_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1885.py b/tests/bugs/test_core_1885.py new file mode 100644 index 00000000..3ccd6bfc --- /dev/null +++ b/tests/bugs/test_core_1885.py @@ -0,0 +1,100 @@ +#coding:utf-8 +# +# id: bugs.core_1885 +# title: CREATE COLLATION connection lost under Posix +# decription: CREATE COLLATION connection lost under Posix when using LOCALE option +# tracker_id: CORE-1885 +# min_versions: [] +# versions: 3.0, 4.0 +# qmid: bugs.core_1885-250 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Attribute 'LOCALE=en_US' is defined for charset = ISO8859_1 rather that for UTF8, see intl/fbintl.conf + CREATE COLLATION UNICODE_ENUS_CI_3X FOR UTF8 FROM UNICODE CASE INSENSITIVE 'LOCALE=en_US'; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = HY000 + unsuccessful metadata update + -CREATE COLLATION UNICODE_ENUS_CI_3X failed + -Invalid collation attributes + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_core_1885_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + +# version: 4.0 +# resources: None + +substitutions_2 = [('SPECIFIC_ATTR_BLOB_ID.*', ''), ('COLL-VERSION=\\d+\\.\\d+\\.\\d+\\.\\d+', 'COLL-VERSION=xx'), ('COLL-VERSION=\\d+\\.\\d+', 'COLL-VERSION=xx')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + -- ::: NB ::: 31.01.2019 + -- Since builds 4.0.0.1410, 26.01.2019, FULL ICU library icudt63l.dat is included in snapshot, + -- so this collation *CAN AND MUST* be created w/o errors. + + set list on; + set count on; + create collation unicode_enus_ci_4x for utf8 from unicode case insensitive 'LOCALE=en_US'; + commit; + + select + rc.rdb$collation_name + ,rc.rdb$collation_attributes + ,rc.rdb$base_collation_name + ,rc.rdb$specific_attributes as specific_attr_blob_id + ,rs.rdb$character_set_name + --,rs.rdb$number_of_characters + ,rs.rdb$bytes_per_character + from rdb$collations rc + join rdb$character_sets rs + on rc.rdb$character_set_id = rs.rdb$character_set_id + where + rc.rdb$system_flag is distinct from 1 + and rc.rdb$collation_name = upper('unicode_enus_ci_4x'); + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + RDB$COLLATION_NAME UNICODE_ENUS_CI_4X + + RDB$COLLATION_ATTRIBUTES 3 + RDB$BASE_COLLATION_NAME UNICODE + + SPECIFIC_ATTR_BLOB_ID 1d:1e7 + COLL-VERSION=xx;LOCALE=en_US + RDB$CHARACTER_SET_NAME UTF8 + + RDB$BYTES_PER_CHARACTER 4 + + Records affected: 1 + """ + +@pytest.mark.version('>=4.0') +def test_core_1885_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/bugs/test_core_1891.py b/tests/bugs/test_core_1891.py new file mode 100644 index 00000000..0ccc6a8e --- /dev/null +++ b/tests/bugs/test_core_1891.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: bugs.core_1891 +# title: SHOW VIEW shows non-sense information for view fields with expressions +# decription: +# tracker_id: CORE-1891 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table test (n integer); +create view view_test (x, y) as select n, n * 2 from test; +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """show view view_test; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """X INTEGER Nullable +Y BIGINT Expression +View Source: +==== ====== + select n, n * 2 from test +""" + +@pytest.mark.version('>=2.5.0') +def test_core_1891_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1894.py b/tests/bugs/test_core_1894.py new file mode 100644 index 00000000..d37992fe --- /dev/null +++ b/tests/bugs/test_core_1894.py @@ -0,0 +1,81 @@ +#coding:utf-8 +# +# id: bugs.core_1894 +# title: Circular dependencies between computed fields crashs the engine +# decription: +# Checked on LI-T4.0.0.419 after commit 19.10.2016 18:26 +# https://github.com/FirebirdSQL/firebird/commit/6a00b3aee6ba17b2f80a5b00def728023e347707 +# -- all OK. +# +# tracker_id: CORE-1894 +# min_versions: ['3.0.2'] +# versions: 3.0.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table t ( + n integer, + n1 computed by (n), + n2 computed by (n1) + ); + + recreate table t2 ( + n integer, + c1 computed by (1), + c2 computed by (c1) + ); + + alter table t alter n1 computed by (n2); + commit; + + set autoddl off; + alter table t2 drop c1; + alter table t2 add c1 computed by (c2); + commit; + + select * from t; + select * from t2; -- THIS LEAD SERVER CRASH (checked on WI-T4.0.0.399) + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -Cannot have circular dependencies with computed fields + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -COLUMN 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 T2.C1 + -there are 1 dependencies + """ + +@pytest.mark.version('>=3.0.2') +def test_core_1894_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_1907.py b/tests/bugs/test_core_1907.py new file mode 100644 index 00000000..5dfda3fe --- /dev/null +++ b/tests/bugs/test_core_1907.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: bugs.core_1907 +# title: Dropping and adding a domain constraint in the same transaction leaves incorrect dependencies +# decription: +# tracker_id: CORE-1907 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t1 (n integer); +create table t2 (n integer); + +create domain d1 integer check (value = (select n from t1)); +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """set autoddl off; + +alter domain d1 drop constraint; +alter domain d1 add constraint check (value = (select n from t2));; +commit; + +drop table t1; -- cannot drop - there are dependencies +commit; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.0') +def test_core_1907_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_1910.py b/tests/bugs/test_core_1910.py new file mode 100644 index 00000000..b7fdaffe --- /dev/null +++ b/tests/bugs/test_core_1910.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: bugs.core_1910 +# title: Not valid fields in MERGE's insert clause are allowed +# decription: +# tracker_id: CORE-1910 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [('column.*', '')] + +init_script_1 = """create table t1 (n integer, x integer); +create table t2 (a integer, b integer); +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """merge into t1 t1 + using (select * from t2) t2 + on t1.n = t2.a + when matched then + update set x = t2.b + when not matched then + insert (a, x) values (1, 2); -- "a" is not a field of t1 +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42S22 +Dynamic SQL Error +-SQL error code = -206 +-Column unknown +-A +-At line 7, column 15 +""" + +@pytest.mark.version('>=2.5.0') +def test_core_1910_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_1926.py b/tests/bugs/test_core_1926.py new file mode 100644 index 00000000..bc13d297 --- /dev/null +++ b/tests/bugs/test_core_1926.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_1926 +# title: MON$DATABASE returns outdated transaction counters +# decription: Fields MON$NEXT_TRANSACTION etc contain incorrect (outdated) numbers on Classic if there are other active attachments. +# tracker_id: CORE-1926 +# min_versions: [] +# versions: 2.1.2 +# qmid: bugs.core_1926 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# c = db_conn.cursor() +# c.execute('SELECT 1 FROM RDB$DATABASE') +# con_detail = kdb.connect(dsn=dsn.encode(),user=user_name.encode(),password=user_password.encode()) +# con_detail.begin() +# c = con_detail.cursor() +# c.execute("select MON$NEXT_TRANSACTION from MON$DATABASE") +# for row in c: +# i = row[0] +# con_detail.commit() +# c.execute("select MON$NEXT_TRANSACTION from MON$DATABASE") +# for row in c: +# j = row[0] +# print (j-i) +# con_detail.commit() +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """1 +""" + +@pytest.mark.version('>=2.1.2') +@pytest.mark.xfail +def test_core_1926_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_1930.py b/tests/bugs/test_core_1930.py new file mode 100644 index 00000000..daab150e --- /dev/null +++ b/tests/bugs/test_core_1930.py @@ -0,0 +1,238 @@ +#coding:utf-8 +# +# id: bugs.core_1930 +# title: Possible AV in engine if procedure was altered to have no outputs and dependent procedures was not recompiled +# decription: +# 26.01.2019: added separate code for 4.0 because more detailed exception text appeared there: +# ====== +# unsuccessful metadata update +# -cannot delete +# -PARAMETER SP1.X +# -there are 1 dependencies +# ===== +# Checked on: +# 3.0.5.33084: OK, 1.156s. +# 3.0.5.33097: OK, 1.016s. +# 4.0.0.1340: OK, 12.890s. +# 4.0.0.1410: OK, 16.156s. +# +# tracker_id: CORE-1930 +# min_versions: ['2.5.0'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('Data source : Firebird::localhost:.*', 'Data source : Firebird::localhost:'), ('-At block line: [\\d]+, col: [\\d]+', '-At block line')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +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_1', test_script_1, substitutions=substitutions_1) + +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_core_1930_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + +# version: 4.0 +# resources: None + +substitutions_2 = [('Data source : Firebird::localhost:.*', 'Data source : Firebird::localhost:'), ('-At block line: [\\d]+, col: [\\d]+', '-At block line')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + 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 + begin + 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 + ^ + 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_2', test_script_2, substitutions=substitutions_2) + +expected_stderr_2 = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -PARAMETER 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 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: + -At block line + """ + +@pytest.mark.version('>=4.0') +def test_core_1930_2(act_2: Action): + act_2.expected_stderr = expected_stderr_2 + act_2.execute() + assert act_2.clean_expected_stderr == act_2.clean_stderr + diff --git a/tests/bugs/test_core_1935.py b/tests/bugs/test_core_1935.py new file mode 100644 index 00000000..e9f569be --- /dev/null +++ b/tests/bugs/test_core_1935.py @@ -0,0 +1,75 @@ +#coding:utf-8 +# +# id: bugs.core_1935 +# title: SIMILAR TO character classes are incorrectly recognized +# decription: +# Checked on: +# 2.5.9.27107: OK, 0.406s. +# 3.0.4.32924: OK, 2.250s. +# 4.0.0.916: OK, 1.562s. +# +# tracker_id: CORE-1935 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + -- two subsequent classes in double braces, concatenated together: + select 11 as r from rdb$database where '1a' similar to '[[:DIGIT:]][[:ALPHA:]]'; -- output: 11 + + -- comparison with SINGLE class of ONE character length: either digit or whitespace or alpha: + select 12 as r from rdb$database where '1a' similar to '[[:DIGIT:][:WHITESPACE:][:ALPHA:]]'; -- no output, no error + + -- comparison with character '2' followed by either digit or whitespace or alpha (should produce non-empty result): + select 21 as r from rdb$database where '2a' similar to '2[[:DIGIT:][:WHITESPACE:][:ALPHA:]]'; -- output: 21 + + -- comparison with SINGLE class of ONE character length: digit either alnum either alpha + select 22 as r from rdb$database where '2a' similar to '[[:DIGIT:][:ALNUM:][:ALPHA:]]'; -- no output, no error + + -- comparison with TWO classes: 1st is result of concatenation alnum and whitespace, 2ns is alnum: + select 31 as r from rdb$database where '3a' similar to '[[:ALNUM:][:WHITESPACE:]][[:ALNUM:]]'; -- 31 + + -- comparison with TWO classes: 1st alnum, 2nd is result of concatenation whitespace and digit: + select 32 as r from rdb$database where '32' similar to '[[:ALNUM:]][[:WHITESPACE:][:DIGIT:]]'; -- 32 + + select 41 as r from rdb$database where '4a' SIMILAR TO '[%[:DIGIT:][:ALNUM:]]%'; + + select 42 as r from rdb$database where '4b' SIMILAR TO '[[:DIGIT:][:ALNUM:]]'; -- no output, no error + + select 51 as r from rdb$database where '5a' SIMILAR TO '%[[:DIGIT:][:ALNUM:]%]'; -- 51 + + select 52 as r from rdb$database where '5a' similar to '[%[:DIGIT:][:ALPHA:]][[:ALNUM:]%]'; -- 52 + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + R 11 + R 21 + R 31 + R 32 + R 41 + R 51 + R 52 + """ + +@pytest.mark.version('>=2.5') +def test_core_1935_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1936.py b/tests/bugs/test_core_1936.py new file mode 100644 index 00000000..3df6ac08 --- /dev/null +++ b/tests/bugs/test_core_1936.py @@ -0,0 +1,107 @@ +#coding:utf-8 +# +# id: bugs.core_1936 +# title: The log(base, number) built-in function doesn't check parameters and delivers NAN values instead. +# decription: +# tracker_id: CORE-1936 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select log(2, 00) from rdb$database; +select log(2, -2) from rdb$database; +select log(0, 1) from rdb$database; +select log(0, 2) from rdb$database; +select log(-1, 2) from rdb$database; +select log(-1, 0) from rdb$database; +select log(-1, -1) from rdb$database; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + LOG +======================= + + LOG +======================= + + LOG +======================= + + LOG +======================= + + LOG +======================= + + LOG +======================= + + LOG +======================= +""" +expected_stderr_1 = """Statement failed, SQLSTATE = 42000 + +expression evaluation not supported + +-Argument for LOG must be positive + +Statement failed, SQLSTATE = 42000 + +expression evaluation not supported + +-Argument for LOG must be positive + +Statement failed, SQLSTATE = 42000 + +expression evaluation not supported + +-Base for LOG must be positive + +Statement failed, SQLSTATE = 42000 + +expression evaluation not supported + +-Base for LOG must be positive + +Statement failed, SQLSTATE = 42000 + +expression evaluation not supported + +-Base for LOG must be positive + +Statement failed, SQLSTATE = 42000 + +expression evaluation not supported + +-Base for LOG must be positive + +Statement failed, SQLSTATE = 42000 + +expression evaluation not supported + +-Base for LOG must be positive + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_1936_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1943.py b/tests/bugs/test_core_1943.py new file mode 100644 index 00000000..ef8d0b81 --- /dev/null +++ b/tests/bugs/test_core_1943.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: bugs.core_1943 +# title: GROUP BY RAND() returns infinite rows +# decription: +# tracker_id: CORE-1943 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select first 10 1 from rdb$database a group by rand(); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CONSTANT +============ + 1 + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_1943_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1945.py b/tests/bugs/test_core_1945.py new file mode 100644 index 00000000..9bf29d85 --- /dev/null +++ b/tests/bugs/test_core_1945.py @@ -0,0 +1,189 @@ +#coding:utf-8 +# +# id: bugs.core_1945 +# title: Custom attribute for collation to sort numbers in numeric order +# decription: +# tracker_id: CORE-1945 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Result were checked on LI-T3.0.0.31827 (64x) and WI-T3.0.0.31836 (32x). + -- ::: NOTE ::: FB 2.5 (at least build 2.5.5.26870 what has been checked) + -- produces WRONG output for such rows when using collation CI_AI: + -- d111 + -- ð1 + -- Ð11 + -- Ð1111 + -- o7 + -- Õ7777 + -- Ø77 + -- ø777 + -- (it seems that trouble somehow related to letters with diagonal strokes as diacritical addition: Ð and Ø) + + -- Proper order: + -- ð1 + -- Ð11 + -- d111 + -- Ð1111 + -- o7 + -- Ø77 + -- ø777 + -- Õ7777 + + recreate table test(s varchar(50)); + commit; + set term ^; + execute block as + begin + begin execute statement 'drop collation ns_coll'; when any do begin end end + begin execute statement 'drop collation ns_coll_ci'; when any do begin end end + begin execute statement 'drop collation ns_coll_ci_ai'; when any do begin end end + end + ^ + set term ;^ + commit; + + create collation ns_coll for utf8 from unicode 'NUMERIC-SORT=1'; + create collation ns_coll_ci for utf8 from unicode case insensitive 'NUMERIC-SORT=1'; + create collation ns_coll_ci_ai for utf8 from unicode case insensitive accent insensitive 'NUMERIC-SORT=1'; + commit; + + recreate table test( + s_norm varchar(50) character set utf8 collate ns_coll + ,s_ci varchar(50) character set utf8 collate ns_coll_ci + ,s_ciai varchar(50) character set utf8 collate ns_coll_ci_ai + ); + commit; + + insert into test(s_norm, s_ci, s_ciai) values('n8888', 'ñ8888', 'Ñ8888'); + insert into test(s_norm, s_ci, s_ciai) values('n8', 'ñ8', 'ñ8'); + insert into test(s_norm, s_ci, s_ciai) values('N88', 'Ñ88', 'Ň88'); + + insert into test(s_norm, s_ci, s_ciai) values( 'O77', 'õ77', 'Ø77'); + insert into test(s_norm, s_ci, s_ciai) values( 'o7777', 'Õ7777', 'Õ7777'); + insert into test(s_norm, s_ci, s_ciai) values( 'O7', 'Õ7', 'o7'); + insert into test(s_norm, s_ci, s_ciai) values( 'o777', 'õ777', 'ø777'); + + insert into test(s_norm, s_ci, s_ciai) values('d1', 'd1', 'ð1'); + insert into test(s_norm, s_ci, s_ciai) values('D11', 'd11', 'Ð11'); + insert into test(s_norm, s_ci, s_ciai) values('D1111', 'D1111', 'Ð1111'); + insert into test(s_norm, s_ci, s_ciai) values('d111', 'd111', 'd111'); + + insert into test(s_norm, s_ci, s_ciai ) values('a9999', 'ä9999', 'Ą9999' ); + insert into test(s_norm, s_ci, s_ciai ) values('a9', 'Ä9', 'Á9' ); + insert into test(s_norm, s_ci, s_ciai ) values('A99', 'ä99', 'à99' ); + insert into test(s_norm, s_ci, s_ciai ) values('a999', 'ä999', 'â999' ); + + insert into test(s_norm, s_ci, s_ciai ) values('L444', 'Ł444', 'L444'); + insert into test(s_norm, s_ci, s_ciai ) values('l44444', 'ł44444', 'ł44444'); + + insert into test(s_norm, s_ci, s_ciai ) values('c2', 'Ç2', 'ç2'); + insert into test(s_norm, s_ci, s_ciai ) values('C222', 'ç222', 'Ç222'); + insert into test(s_norm, s_ci, s_ciai ) values('c22', 'Ç22', 'C22'); + + insert into test(s_norm, s_ci, s_ciai ) values('S55', 'Š55', 'Š55' ); + insert into test(s_norm, s_ci, s_ciai ) values('s555', 'š555', 'ş555'); + insert into test(s_norm, s_ci, s_ciai ) values('s5', 'Š5', 'š5'); + + set list on; + select s_norm from test order by s_norm; + select s_ci from test order by s_ci; + select s_ciai from test order by s_ciai; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + S_NORM a9 + S_NORM A99 + S_NORM a999 + S_NORM a9999 + S_NORM c2 + S_NORM c22 + S_NORM C222 + S_NORM d1 + S_NORM D11 + S_NORM d111 + S_NORM D1111 + S_NORM L444 + S_NORM l44444 + S_NORM n8 + S_NORM N88 + S_NORM n8888 + S_NORM O7 + S_NORM O77 + S_NORM o777 + S_NORM o7777 + S_NORM s5 + S_NORM S55 + S_NORM s555 + + S_CI Ä9 + S_CI ä99 + S_CI ä999 + S_CI ä9999 + S_CI Ç2 + S_CI Ç22 + S_CI ç222 + S_CI d1 + S_CI d11 + S_CI d111 + S_CI D1111 + S_CI Ł444 + S_CI ł44444 + S_CI ñ8 + S_CI Ñ88 + S_CI ñ8888 + S_CI Õ7 + S_CI õ77 + S_CI õ777 + S_CI Õ7777 + S_CI Š5 + S_CI Š55 + S_CI š555 + + S_CIAI Á9 + S_CIAI à99 + S_CIAI â999 + S_CIAI Ą9999 + S_CIAI ç2 + S_CIAI C22 + S_CIAI Ç222 + S_CIAI ð1 + S_CIAI Ð11 + S_CIAI d111 + S_CIAI Ð1111 + S_CIAI L444 + S_CIAI ł44444 + S_CIAI ñ8 + S_CIAI Ň88 + S_CIAI Ñ8888 + S_CIAI o7 + S_CIAI Ø77 + S_CIAI ø777 + S_CIAI Õ7777 + S_CIAI š5 + S_CIAI Š55 + S_CIAI ş555 + """ + +@pytest.mark.version('>=3.0') +def test_core_1945_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_195.py b/tests/bugs/test_core_195.py new file mode 100644 index 00000000..af412e25 --- /dev/null +++ b/tests/bugs/test_core_195.py @@ -0,0 +1,148 @@ +#coding:utf-8 +# +# id: bugs.core_195 +# title: Bugcheck 291 +# decription: +# tracker_id: CORE-195 +# min_versions: ['1.5.0'] +# versions: 1.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table tbl_bugcheck291 +( + ID integer NOT NULL PRIMARY KEY, + DATA integer +); + +commit; + +insert into tbl_bugcheck291 (id, data) values (1,100); + +commit; + +SET TERM ^ ; + +create trigger bu_tbl_bugcheck291 for tbl_bugcheck291 + before update +as +begin + if (new.data is not null) then + begin + if(new.data<110)then + begin + update tbl_bugcheck291 x set x.data=new.data+1 where x.id=new.id; + end + end +end +^ +COMMIT WORK ^ +SET TERM ;^ + +CREATE TABLE T1 + +( + + DATA INTEGER, + + FLAG INTEGER + +); + + + +SET TERM ^ ; + + + +CREATE TRIGGER TRIG1 FOR T1 + +ACTIVE BEFORE UPDATE POSITION 1 + +as + +begin + +if (new.Flag = 16 and new.Data = 1) then begin + + update t1 set Data = 2 where Flag = 46; + + update t1 set Data = 3 where Flag = 46; + +end + +if (new.Flag = 46 and new.Data = 2) then begin + + update t1 set Data = 4 where Flag = 14; + + update t1 set Data = 5 where Flag = 15; + +end + +if (new.Flag = 14 and new.Data = 4) then begin + + update t1 set Data = 6 where Flag = 46; + +end + +if (new.Flag = 15 and new.Data = 5) then begin + + update t1 set Data = 7 where Flag = 46; + +end + +if (new.Flag = 46 and new.Data = 3) then begin + + update t1 set Data = 8 where Flag = 46; + +end + +end + + ^ + + + +COMMIT ^ + +SET TERM ;^ + + + +insert into t1(Flag) values(14); + +insert into t1(Flag) values(15); + +insert into t1(Flag) values(16); + +insert into t1(Flag) values(46); + +commit; + +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """update tbl_bugcheck291 set data=105 where id=1; +commit; +update tbl_bugcheck291 set data=105 where id=1; +commit; +update t1 set Data=1 where Flag = 16; +commit; + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=1.5.0') +def test_core_195_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_1962.py b/tests/bugs/test_core_1962.py new file mode 100644 index 00000000..a931b876 --- /dev/null +++ b/tests/bugs/test_core_1962.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_1962 +# title: Incorrect extraction of MILLISECONDs +# decription: +# tracker_id: CORE-1962 +# min_versions: ['2.1.2'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select extract(millisecond from time '01:00:10.5555') EXTRACTED_MS from rdb$database + union all + select extract(millisecond from time '00:00:00.0004') from rdb$database + union all + select extract(millisecond from time '23:59:59.9995') from rdb$database + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + EXTRACTED_MS 555.5 + EXTRACTED_MS 0.4 + EXTRACTED_MS 999.5 + """ + +@pytest.mark.version('>=3.0') +def test_core_1962_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1971.py b/tests/bugs/test_core_1971.py new file mode 100644 index 00000000..058d467c --- /dev/null +++ b/tests/bugs/test_core_1971.py @@ -0,0 +1,75 @@ +#coding:utf-8 +# +# id: bugs.core_1971 +# title: Set the fixed and documented check order for WHERE clause and other conditional sentences +# decription: +# tracker_id: CORE-1971 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """ + create table t_links ( + link_type integer, + right_id integer, + prop_value varchar(1024) + ); + + insert into t_links (link_type,right_id,prop_value) values(2,161,'2001'); + insert into t_links (link_type,right_id,prop_value) values(2,161,'2002'); + insert into t_links (link_type,right_id,prop_value) values(2,161,'2003'); + insert into t_links (link_type,right_id,prop_value) values(10,161,'any string'); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select * from t_links + where (right_id=161 and link_type=2) and cast(prop_value as integer)<>2001; + + select * from t_links + where cast(prop_value as integer)<>2001 and (right_id=161 and link_type=2); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + LINK_TYPE 2 + RIGHT_ID 161 + PROP_VALUE 2002 + + LINK_TYPE 2 + RIGHT_ID 161 + PROP_VALUE 2003 + + LINK_TYPE 2 + RIGHT_ID 161 + PROP_VALUE 2002 + + LINK_TYPE 2 + RIGHT_ID 161 + PROP_VALUE 2003 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22018 + conversion error from string "any string" + """ + +@pytest.mark.version('>=2.5.0') +def test_core_1971_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1972.py b/tests/bugs/test_core_1972.py new file mode 100644 index 00000000..ae00f553 --- /dev/null +++ b/tests/bugs/test_core_1972.py @@ -0,0 +1,139 @@ +#coding:utf-8 +# +# id: bugs.core_1972 +# title: Non-SYSDBA user can change FW mode of database. +# decription: +# We create common user using Services API and try to establish TWO subsequent connections under his login: +# 1) with flag 'forced_write' = 1 and then +# 2) with flad 'no_reserve' = 1. +# Note: both values of these flags have to be equal 1 because of some specifics of DPB building inside fdb driver: +# value 0 means 'nothing to add', so no error will be raised in this case (and we DO expect error in this ticket). +# In WI-V2.1.1.17910 one may to specify *ANY* values of these flags and NO error will be raised. +# Fortunately, actual DB state also was not changed. +# +# Starting from WI-V2.1.2.18118 attempt to specify non-zero flag leads to runtime exception with SQLCODE=-901 +# ("unable to perform: you must be either SYSDBA or owner...") +# See also: https://firebirdsql.org/rlsnotesh/rnfb210-apiods.html +# +# Additional filtering of output is required because of different error message in 4.0: it checks whether current user +# has grant of role with system privilege 'CHANGE_HEADER_SETTINGS'. +# If no then message will be "System privilege CHANGE_HEADER_SETTINGS is missing" (differ from older FB versions). +# If yes then DB header is allowed to be change and NO ERROR at all will be raised on attempt to establish such connections. +# For that reason it was decided to completely suppress output of error detalization ("you must be either SYSDBA" or +# "System privilege CHANGE_HEADER_SETTINGS is missing") and to display only line with SQLCODE. +# +# Checked on 2.1.2.18118, and also on: +# 2.5.9.27107: OK, 0.328s. +# 3.0.4.32924: OK, 2.078s. +# 4.0.0.916: OK, 1.079s. +# +# tracker_id: CORE-1972 +# min_versions: ['2.1.1'] +# versions: 2.1.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.1 +# resources: None + +substitutions_1 = [('^((?!Successfully|Trying_to_establish|SQLCODE:).)*$', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import fdb +# from fdb import services +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # Obtain engine version: +# engine = str(db_conn.engine_version) # convert to text because 'float' object has no attribute 'startswith' +# db_conn.close() +# +# FB_PORT= '' # '/3212' +# A_USER = 'TMP$C1972' +# A_PSWD = '123' +# +# con=None +# try: +# con = services.connect(host='localhost'+FB_PORT, user='SYSDBA', password='masterkey') +# usr = services.User(A_USER) +# usr.password = A_PSWD +# con.add_user(usr) +# print('Successfully added non-privileged user') +# finally: +# if con: +# con.close() +# #------------------------------------------------------------------------------------------- +# +# # 1. Try to specifying 'force_write' flag: no errors and NO changes in 2.1.1; error in 2.1.2 and above: +# try: +# print( 'Trying_to_establish connection with specifying force_write' ) +# con = fdb.connect(dsn = dsn, user = A_USER, password = A_PSWD, force_write = 1 ) +# print ( 'done', con.firebird_version ) +# cur=con.cursor() +# cur.execute('select current_user,mon$forced_writes from mon$database') +# for r in cur: +# print('whoami:', r[0], '; mon$forced_writes:', r[1]) +# except Exception, e: +# print(e[0]) +# finally: +# if con: +# con.close() +# +# # 2. Try to specifying 'no_reserve' flag: no errors and NO changes in 2.1.1; error in 2.1.2 and above: +# try: +# print( 'Trying_to_establish connection with specifying no_reserve' ) +# con = fdb.connect(dsn = dsn, user = A_USER, password = A_PSWD, no_reserve = 1 ) +# print ( 'done', con.firebird_version ) +# cur=con.cursor() +# cur.execute('select current_user,mon$reserve_space from mon$database') +# for r in cur: +# print('whoami:', r[0], '; mon$reserve_space:', r[1]) +# except Exception, e: +# print(e[0]) +# finally: +# if con: +# con.close() +# +# #------------------------------------------------------------------------------------------- +# try: +# con = services.connect(host='localhost' + FB_PORT, user='SYSDBA', password='masterkey') +# con.remove_user(A_USER) +# print('Successfully removed non-privileged user') +# finally: +# if con: +# con.close() +# +# print('Successfully finished script') +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Successfully added non-privileged user + + Trying_to_establish connection with specifying force_write + - SQLCODE: -901 + + Trying_to_establish connection with specifying no_reserve + - SQLCODE: -901 + + Successfully removed non-privileged user + Successfully finished script + """ + +@pytest.mark.version('>=2.1.1') +@pytest.mark.xfail +def test_core_1972_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_1986.py b/tests/bugs/test_core_1986.py new file mode 100644 index 00000000..66b5ff82 --- /dev/null +++ b/tests/bugs/test_core_1986.py @@ -0,0 +1,52 @@ +#coding:utf-8 +# +# id: bugs.core_1986 +# title: Altering domains name drops dependencies using the domain +# decription: +# tracker_id: CORE-1986 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE DOMAIN D_SOME AS INTEGER; + +CREATE OR ALTER PROCEDURE SP_SOME( + SOME_PARAM D_SOME) +AS +BEGIN +END; +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ALTER DOMAIN D_SOME TO D_OTHER; + +execute procedure SP_SOME (1); +commit; +execute procedure SP_SOME (1); +commit; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42000 +unsuccessful metadata update +-cannot delete +-DOMAIN D_SOME +-there are 1 dependencies +""" + +@pytest.mark.version('>=2.5.0') +def test_core_1986_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_1989.py b/tests/bugs/test_core_1989.py new file mode 100644 index 00000000..a8403f4c --- /dev/null +++ b/tests/bugs/test_core_1989.py @@ -0,0 +1,116 @@ +#coding:utf-8 +# +# id: bugs.core_1989 +# title: UTF8 UNICODE_CI collate can´t be used in foreing key constraint +# decription: +# tracker_id: CORE-1989 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """-- Domains + +CREATE DOMAIN INT64 AS +BIGINT; + +CREATE DOMAIN VARCHAR100 AS +VARCHAR(100) +COLLATE UNICODE_CI; + +CREATE DOMAIN VARCHAR100_CS AS +VARCHAR(100) +COLLATE UNICODE; + +CREATE DOMAIN VARCHAR30 AS +VARCHAR(30) +COLLATE UNICODE_CI; + +CREATE DOMAIN VARCHAR30_CS AS +VARCHAR(30) +COLLATE UNICODE; + +-- Tables + +CREATE TABLE ROLES ( + ROLE_NAME VARCHAR30 NOT NULL, + APPLICATION_NAME VARCHAR100 NOT NULL +); + + +CREATE TABLE ROLES_CS ( + ROLE_NAME VARCHAR30_CS NOT NULL, + APPLICATION_NAME VARCHAR100_CS NOT NULL +); + + +CREATE TABLE USERS ( + USER_NAME VARCHAR100 NOT NULL, + APPLICATION_NAME VARCHAR100 NOT NULL +); + + +CREATE TABLE USERS_CS ( + USER_NAME VARCHAR100_CS NOT NULL, + APPLICATION_NAME VARCHAR100_CS NOT NULL +); + + +CREATE TABLE USERS_IN_ROLES ( + USER_NAME VARCHAR100 NOT NULL, + ROLE_NAME VARCHAR30 NOT NULL, + APPLICATION_NAME VARCHAR100 NOT NULL +); + + +CREATE TABLE USERS_IN_ROLES_CS ( + USER_NAME VARCHAR100_CS NOT NULL, + ROLE_NAME VARCHAR30_CS NOT NULL, + APPLICATION_NAME VARCHAR100_CS NOT NULL +); + +-- Primary Keys + +ALTER TABLE ROLES ADD CONSTRAINT PK_ROLES PRIMARY KEY (ROLE_NAME, APPLICATION_NAME); +ALTER TABLE ROLES_CS ADD CONSTRAINT PK_ROLES_CS PRIMARY KEY (ROLE_NAME, APPLICATION_NAME); +ALTER TABLE USERS ADD CONSTRAINT PK_USERS PRIMARY KEY (USER_NAME, APPLICATION_NAME); +ALTER TABLE USERS_CS ADD CONSTRAINT PK_USERS_CS PRIMARY KEY (USER_NAME, APPLICATION_NAME); + +-- Foreign Keys + +ALTER TABLE USERS_IN_ROLES ADD CONSTRAINT FK_USERS_IN_ROLES_ROLES FOREIGN KEY (ROLE_NAME, APPLICATION_NAME) REFERENCES ROLES (ROLE_NAME, APPLICATION_NAME) ON DELETE CASCADE ON UPDATE CASCADE; +ALTER TABLE USERS_IN_ROLES ADD CONSTRAINT FK_USERS_IN_ROLES_USERS FOREIGN KEY (USER_NAME, APPLICATION_NAME) REFERENCES USERS (USER_NAME, APPLICATION_NAME) ON DELETE CASCADE ON UPDATE CASCADE; +ALTER TABLE USERS_IN_ROLES_CS ADD CONSTRAINT FK_USERS_IN_ROLES_ROLES_CS FOREIGN KEY (ROLE_NAME, APPLICATION_NAME) REFERENCES ROLES_CS (ROLE_NAME, APPLICATION_NAME) ON DELETE CASCADE ON UPDATE CASCADE; +ALTER TABLE USERS_IN_ROLES_CS ADD CONSTRAINT FK_USERS_IN_ROLES_USERS_CS FOREIGN KEY (USER_NAME, APPLICATION_NAME) REFERENCES USERS_CS (USER_NAME, APPLICATION_NAME) ON DELETE CASCADE ON UPDATE CASCADE; + + +""" + +db_1 = db_factory(page_size=16384, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """insert into USERS(USER_NAME, APPLICATION_NAME) values('User', 'App'); +insert into USERS_CS(USER_NAME, APPLICATION_NAME) values('User', 'App'); +insert into ROLES(ROLE_NAME, APPLICATION_NAME) values('Role', 'App'); +insert into ROLES_CS(ROLE_NAME, APPLICATION_NAME) values('Role', 'App'); +commit; +insert into USERS_IN_ROLES_CS(USER_NAME, ROLE_NAME, APPLICATION_NAME) values('User', 'Role', 'App'); +commit; +-- Raises error +insert into USERS_IN_ROLES(USER_NAME, ROLE_NAME, APPLICATION_NAME) values('User', 'Role', 'App'); +commit; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.0') +def test_core_1989_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_1992.py b/tests/bugs/test_core_1992.py new file mode 100644 index 00000000..73dc6278 --- /dev/null +++ b/tests/bugs/test_core_1992.py @@ -0,0 +1,420 @@ +#coding:utf-8 +# +# id: bugs.core_1992 +# title: bad BLR -- invalid stream for union select +# decription: +# 06.02.2019. Test was refactored. +# CONFIRMED bug on WI-V2.5.1.26351, got: +# Statement failed, SQLSTATE = HY000 +# bad BLR -- invalid stream +# No error since WI-V2.5.2.26540. +# +# Old version of test for this ticket used dialects 1 and 3, separately, in order to check all datatypes. +# This was excessive because bug was not related to dialect, thus I decided to remove old .fbt files and +# use new version. Beside, query for this test was adjusted for readability - added CTE instead of nested +# sub-queries. +# +# ::: NB ::: +# We have no care about correctness of query results here. +# For this reason all rows are count'ed and we only verify that sign(count(*)) = 1, and no more checks. +# +# Checked on: +# 2.5.9.27127: OK, 0.546s. +# 3.0.5.33097: OK, 4.172s. +# 4.0.0.1421: OK, 3.328s. +# +# tracker_id: CORE-1992 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + set term ^; + create or alter procedure sp01( + a_01 smallint, + a_02 int, + a_03 bigint, + a_04 numeric(9,0), + a_05 numeric(10,0), + a_06 float, + a_07 double precision, + --a_08 date, + --a_09 time, + a_10 timestamp, + a_11 varchar(1), + a_12 char(2), + a_13 blob + ) returns ( + o_01 smallint, + o_02 int, + o_03 bigint, + o_04 numeric(9,0), + o_05 numeric(10,0), + o_06 float, + o_07 double precision, + --o_08 date, + --o_09 time, + o_10 timestamp, + o_11 varchar(1), + o_12 char(2), + o_13 blob + ) as + begin + suspend; + end + ^ + set term ;^ + commit; + + ------------------------------------ + + with + extent1 as + ( + select + trim(f.rdb$function_name) as Id + , null as CatalogName + , null as SchemaName + , trim(f.rdb$function_name) as Name + , trim( + case fa.rdb$field_type + when 7 then + case fa.rdb$field_sub_type + when 0 then 'smallint' + when 1 then 'numeric' + when 2 then 'decimal' + end + when 8 then + case fa.rdb$field_sub_type + when 0 then 'int' + when 1 then 'numeric' + when 2 then 'decimal' + end + when 16 then + case fa.rdb$field_sub_type + when 0 then 'bigint' + when 1 then 'numeric' + when 2 then 'decimal' + end + when 10 then 'float' + when 27 then 'double' + when 12 then 'date' + when 13 then 'time' + when 35 then 'timestamp' + when 261 then 'blob' + when 37 then 'varchar' + when 14 then 'char' + when 40 then 'cstring' + end + ) as ReturnTypeName + , fa.rdb$character_length as ReturnMaxLength + , fa.rdb$field_precision as ReturnPrecision + , 0 as ReturnDateTimePrecision + , fa.rdb$field_scale * (-1) as ReturnScale + , null as ReturnCollationCatalog + , null as ReturnCollationSchema + , null as ReturnCollationName + , null as ReturnCharacterSetCatalog + , null as ReturnCharacterSetSchema + , null as ReturnCharacterSetName + , CAST(0 as smallint) as ReturnIsMultiSet + , CAST(0 as smallint) as IsAggregate + , CAST(0 as smallint) as IsBuiltIn + , CAST((select CASE COUNT(*) WHEN 1 THEN 1 ELSE 0 END FROM rdb$function_arguments fa WHERE fa.rdb$function_name = f.rdb$function_name ) as smallint) as IsNiladic + from rdb$functions f + inner join rdb$function_arguments fa on (f.rdb$function_name = fa.rdb$function_name and f.rdb$return_argument = fa.rdb$argument_position) + where f.rdb$system_flag = 0 -- ::: nb ::: need add alias f. in 3.0! + ) + ,extent2 as ( + select + null as id + , null as parentid + , null as name + , null as ordinal + , null as typename + , null as maxlength + , null as dblprecision + , null as datetimeprecision + , null as scale + , null as collationcatalog + , null as collationschema + , null as collationname + , null as charactersetcatalog + , null as charactersetschema + , null as charactersetname + , null as ismultiset + , null as mode + , null as defaulttype + from rdb$database + where 0=1 + ), + extent3 as ( + select + trim(pp.rdb$procedure_name) || 'x' || trim(pp.rdb$parameter_name) as id + , trim(pp.rdb$procedure_name) as parentid + , trim(pp.rdb$parameter_name) as name + , pp.rdb$parameter_number+1 as ordinal + , trim( + case f.rdb$field_type + when 7 then + case f.rdb$field_sub_type + when 0 then 'smallint' + when 1 then 'numeric' + when 2 then 'decimal' + end + when 8 then + case f.rdb$field_sub_type + when 0 then 'int' + when 1 then 'numeric' + when 2 then 'decimal' + end + when 16 then + case f.rdb$field_sub_type + when 0 then 'bigint' + when 1 then 'numeric' + when 2 then 'decimal' + end + when 10 then 'float' + when 27 then 'double' + when 12 then 'date' + when 13 then 'time' + when 35 then 'timestamp' + when 261 then 'blob' + when 37 then 'varchar' + when 14 then 'char' + when 40 then 'cstring' + end + ) as typename + , f.rdb$character_length as MaxLength + , f.rdb$field_precision as DblPrecision + , 0 as DateTimePrecision + , f.rdb$field_scale * (-1) as Scale + , null as CollationCatalog + , null as CollationSchema + , null CollationName + , null as CharacterSetCatalog + , null as CharacterSetSchema + , null as CharacterSetName + , cast(0 as smallint) as IsMultiSet + , trim(iif(pp.rdb$parameter_type = 1, 'OUT', 'IN')) as Mode + , null as DefaultType + from rdb$procedure_parameters pp + join rdb$fields f on (pp.rdb$field_source = f.rdb$field_name) + ) + ,extent4 as ( + select + trim(rdb$procedure_name) as id + , null as catalogname + , '' as schemaname -- bug or not??? need to be not null + , trim(rdb$procedure_name) as name + from + rdb$procedures + ) + ,extent5 as ( + select + null as Id + , null as ParentId + , null as Name + , null as Ordinal + , null as TypeName + , null as MaxLength + , null as DblPrecision + , null as DateTimePrecision + , null as Scale + , null as CollationCatalog + , null as CollationSchema + , null as CollationName + , null as CharacterSetCatalog + , null as CharacterSetSchema + , null as CharacterSetName + , null as IsMultiSet + , null as Mode + , null as DefaultType + from rdb$database where 0=1 + ) + ,extent6 as ( + select + trim(pp.rdb$procedure_name) || 'x' || trim(pp.rdb$parameter_name) as id + , trim(pp.rdb$procedure_name) as parentid + , trim(pp.rdb$parameter_name) as name + , pp.rdb$parameter_number+1 as ordinal + , trim( + case f.rdb$field_type + when 7 then + case f.rdb$field_sub_type + when 0 then 'smallint' + when 1 then 'numeric' + when 2 then 'decimal' + end + when 8 then + case f.rdb$field_sub_type + when 0 then 'int' + when 1 then 'numeric' + when 2 then 'decimal' + end + when 16 then + case f.rdb$field_sub_type + when 0 then 'bigint' + when 1 then 'numeric' + when 2 then 'decimal' + end + when 10 then 'float' + when 27 then 'double' + when 12 then 'date' + when 13 then 'time' + when 35 then 'timestamp' + when 261 then 'blob' + when 37 then 'varchar' + when 14 then 'char' + when 40 then 'cstring' + end + ) as TypeName + , f.rdb$character_length as MaxLength + , f.rdb$field_precision as DblPrecision + , 0 as DateTimePrecision + , f.rdb$field_scale * (-1) as Scale + , null as CollationCatalog + , null as CollationSchema + , null CollationName + , null as CharacterSetCatalog + , null as CharacterSetSchema + , null as CharacterSetName + , cast(0 as smallint) as IsMultiSet + , trim(iif(pp.rdb$parameter_type = 1, 'OUT', 'IN')) as Mode + , null as DefaultType + from rdb$procedure_parameters pp + join rdb$fields f on (pp.rdb$field_source = f.rdb$field_name) + ) + + ,UnionAll1 as ( -- e2 union all e3 + select + e2.name as name, + e2.ordinal as ordinal, + e2.typename as typename, + e2.mode as mode, + 0 as c1, + e2.parentid as parentid + from extent2 as e2 + + UNION ALL + + select + e3.name as name, + e3.ordinal as ordinal, + e3.typename as typename, + e3.mode as mode, + 6 as c1, + e3.parentid as parentId + from extent3 as e3 + ) + + ,unionAll2 as ( -- e5 union all e6 + + select + e5.name as name, + e5.ordinal as ordinal, + e5.typename as typename, + e5.mode as mode, + 0 as c1, + e5.parentid as parentid + from extent5 as e5 + + UNION ALL + + select + e6.name as name, + e6.ordinal as ordinal, + e6.typename as typename, + e6.mode as mode, + 6 as c1, + e6.parentid as parentid + from extent6 as e6 + ) + ,unionall3 as ( -- e1 left join u1 UNION ALL e4 left join u2 + select + e1.schemaname as schemaname, + e1.name as name, + e1.returntypename as returntypename, + e1.isaggregate as isaggregate, + cast(1 as smallint) as c1, + e1.isbuiltin as isbuiltin, + e1.isniladic as isniladic, + u1.name as c2, + u1.typename as c3, + u1.mode as c4, + u1.ordinal as c5 + from extent1 e1 + left join unionAll1 u1 on (0 = u1.C1) AND (e1.Id = u1.ParentId) + + UNION ALL + + select + e4.schemaname as schemaname, + e4.name as name, + cast(null as varchar(1000)) as c1, + cast(0 as smallint) as c2, + cast(0 as smallint) as c3, + cast(0 as smallint) as c4, + cast(0 as smallint) as c5, + u2.name as c6, + u2.typename as c7, + u2.mode as c8, + u2.ordinal as c9 + from extent4 as e4 + left outer join unionall2 as u2 on (6 = u2.c1) and (e4.id = u2.parentid) + ) -- end of unionAll3 + + ,project7 as ( + select + u3.schemaname as c1, + u3.name as c2, + u3.returntypename as c3, + u3.isaggregate as c4, + u3.c1 as c5, + u3.isbuiltin as c6, + u3.isniladic as c7, + u3.c2 as c8, + u3.c3 as c9, + u3.c4 as c10, + u3.c5 as c11, + 1 as c12 + from unionAll3 as u3 + ) + ,c_final as ( + select + p7.c8 as par_name, + p7.c9 as par_type, + p7.c10 as par_dir + from project7 as p7 + order by par_dir,par_name + ) + select sign(count(*)) as result from c_final + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT 1 + """ + +@pytest.mark.version('>=2.5.2') +def test_core_1992_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_1997.py b/tests/bugs/test_core_1997.py new file mode 100644 index 00000000..8a82c31d --- /dev/null +++ b/tests/bugs/test_core_1997.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_1997 +# title: Broken foreign key handling for multi-segmented index using multi-level collations +# decription: +# tracker_id: CORE-1997 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """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_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """delete from pk; -- should not be allowed +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """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') +""" + +@pytest.mark.version('>=2.5.2') +def test_core_1997_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_1999.py b/tests/bugs/test_core_1999.py new file mode 100644 index 00000000..24e12774 --- /dev/null +++ b/tests/bugs/test_core_1999.py @@ -0,0 +1,223 @@ +#coding:utf-8 +# +# id: bugs.core_1999 +# title: TimeStamp in the every line output gbak.exe utility +# decription: +# Database for this test was created beforehand and filled-up with all possible kind of objects: +# domain, table, view, standalone procedure & function, package, trigger, sequence, exception and role. +# Then backup was created for this DB and it was packed into .zip archive - see files/core_1999_nn.zip. +# This test extract .fbk from .zip and does its restore and then - again backup, but with option 'res_stat tdrw'. +# Both processes are logged. Finally, we parse these logs by counting lines which contain NO statistics. +# Presence of statistics is determined by analyzing corresponding tokens of each line. Token which contains only +# digits (with exception of "dot" and "comma" characters) is considered as VALUE related to some statistics. +# Backup log should contain only single (1st) line w/o statistics, restore - 1st and last lines. +# NB. +# Utility fbsvcmgr in 2.5.5 was not able to produce output with statistics (i.e. "res_stat tdrw") until commit #62537 +# (see: http://sourceforge.net/p/firebird/code/62537 ). +# +# 28.10.2019. Checked on: +# 4.0.0.1635 SS: 3.495s. +# 4.0.0.1633 CS: 3.982s. +# 3.0.5.33180 SS: 2.469s. +# 3.0.5.33178 CS: 4.538s. +# 2.5.9.27119 SS: 1.972s. +# 2.5.9.27146 SC: 1.540s. +# +# 13.04.2021: removed code for 2.5.x, changed platform to 'All', replaced path to FB utilities with 'context[...]'. +# Checked on: +# Windows: 3.0.8.33445, 4.0.0.2416 +# Linux: 3.0.8.33426, 4.0.0.2416 +# +# +# tracker_id: CORE-1999 +# min_versions: ['3.0.5'] +# versions: 3.0.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import zipfile +# import time +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.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 ) +# +# #-------------------------------------------- +# +# zf = zipfile.ZipFile( os.path.join(context['files_location'],'core_1999_30.zip') ) +# zf.extractall( context['temp_directory'] ) +# zf.close() +# +# # Result: core_1999_30.fbk is extracted into context['temp_directory'] +# +# tmpres='$(DATABASE_LOCATION)tmp_core_1999_30.fdb' +# tmpbkp='$(DATABASE_LOCATION)tmp_core_1999_30.fbk' +# +# f_restore=open( os.path.join(context['temp_directory'],'tmp_restore_1999_30.log'), 'w') +# subprocess.check_call( [ context['fbsvcmgr_path'] +# ,"localhost:service_mgr" +# ,"action_restore" +# ,"bkp_file",tmpbkp +# ,"dbname",tmpres +# ,"res_replace" +# ,"verbose" +# ,"res_stat","tdrw" +# ], +# stdout=f_restore, stderr=subprocess.STDOUT +# ) +# flush_and_close( f_restore ) +# +# # Result: database file 'tmp_core_1999_30.fdb' should be created after this restoring, log in 'tmp_restore_1999_30.log' +# +# f_backup=open( os.path.join(context['temp_directory'],'tmp_backup_1999_30.log'), 'w') +# subprocess.check_call( [ context['fbsvcmgr_path'] +# ,"localhost:service_mgr" +# ,"action_backup" +# ,"dbname",tmpres +# ,"bkp_file",tmpbkp +# ,"verbose" +# ,"bkp_stat","tdrw" +# ], +# stdout=f_backup, stderr=subprocess.STDOUT +# ) +# flush_and_close( f_backup ) +# +# # Result: backup file 'tmp_core_1999_30.fbk' should be replaced after this backup, log in 'tmp_backup_1999_30.log' +# +# +# # Sample of backup log with statistics: +# # ------------------------------------- +# # gbak: time delta reads writes +# # gbak: 0.019 0.019 43 0 readied database . . .fdb for backup +# # gbak: 0.019 0.000 0 0 creating file . . ..fbk +# # gbak: 0.020 0.000 0 0 starting transaction +# # gbak: 0.023 0.002 22 1 database . . . has a page size of 4096 bytes. +# # gbak: 0.023 0.000 1 0 writing domains +# # gbak: 0.024 0.000 6 0 writing domain RDB$11 +# # . . . +# # gbak: 0.847 0.109 2 0 closing file, committing, and finishing. 1105920 bytes written +# # gbak: 0.847 0.000 802 2 total statistics +# +# rows_without_stat=0 +# with open(f_backup.name, 'r') as f: +# for line in f: +# tokens=line.split() +# if not ( tokens[1].replace('.','',1).replace(',','',1).isdigit() and tokens[2].replace('.','',1).replace(',','',1).isdigit() and tokens[3].replace('.','',1).replace(',','',1).isdigit() and tokens[4].replace('.','',1).replace(',','',1).isdigit() ): +# rows_without_stat = rows_without_stat + 1 +# +# print("bkp: rows_without_stat="+str(rows_without_stat)) +# +# # Sample of restore log with statistics: +# # ------------------------------------- +# # gbak: time delta reads writes +# # gbak: 0.000 0.000 0 0 opened file ....fbk +# # gbak: 0.004 0.003 0 0 transportable backup -- data in XDR format +# # gbak: 0.004 0.000 0 0 backup file is compressed +# # gbak: 0.004 0.000 0 0 backup version is 10 +# # gbak: 0.275 0.270 0 711 created database ....fdb, page_size 4096 bytes +# # gbak: 0.277 0.002 0 2 started transaction +# # gbak: 0.278 0.001 0 0 restoring domain RDB$11 +# # . . . +# # gbak: 1.987 0.000 0 31 fixing system generators +# # gbak: 2.016 0.029 0 10 finishing, closing, and going home +# # gbak: 2.017 0.000 0 1712 total statistics +# # gbak:adjusting the ONLINE and FORCED WRITES flags +# +# +# rows_without_stat=0 +# with open(f_restore.name, 'r') as f: +# for line in f: +# tokens=line.split() +# if not ( +# tokens[1].replace('.','',1).replace(',','',1).isdigit() +# and +# tokens[2].replace('.','',1).replace(',','',1).isdigit() +# and +# tokens[3].replace('.','',1).replace(',','',1).isdigit() +# and +# tokens[4].replace('.','',1).replace(',','',1).isdigit() +# ): +# rows_without_stat = rows_without_stat + 1 +# +# print("res: rows_without_stat="+str(rows_without_stat)) +# +# # Backup log should contain SINGLE row without statistics, in its header (1st line): +# # gbak: time delta reads writes +# +# # Restore log should contain TWO rows without statistics, first and last: +# # gbak: time delta reads writes +# # gbak:adjusting the ONLINE and FORCED WRITES flags +# +# ##################################################################### +# # Cleanup: +# +# # do NOT remove this pause otherwise some of logs will not be enable for deletion and test will finish with +# # Exception raised while executing Python test script. exception: WindowsError: 32 +# time.sleep(1) +# +# # CLEANUP +# ######### +# cleanup( (f_backup, f_restore, tmpbkp, tmpres ) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + bkp: rows_without_stat=1 + res: rows_without_stat=2 + """ + +@pytest.mark.version('>=3.0.5') +@pytest.mark.xfail +def test_core_1999_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2001.py b/tests/bugs/test_core_2001.py new file mode 100644 index 00000000..384986a6 --- /dev/null +++ b/tests/bugs/test_core_2001.py @@ -0,0 +1,52 @@ +#coding:utf-8 +# +# id: bugs.core_2001 +# title: When trying to show "conversion error", "arithmetic exception/string truncation" may appear instead, misleading the user +# decription: +# tracker_id: CORE-2001 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select cast('1995' as date) from rdb$database; +select cast('1995-12-2444444444444444444444444444444' as date) from rdb$database; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CAST +=========== + + CAST +===========""" +expected_stderr_1 = """Statement failed, SQLSTATE = 22018 + +conversion error from string "1995" + +Statement failed, SQLSTATE = 22018 + +conversion error from string "1995-12-2444444444444444444444444444444" + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_2001_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2004.py b/tests/bugs/test_core_2004.py new file mode 100644 index 00000000..bfc14016 --- /dev/null +++ b/tests/bugs/test_core_2004.py @@ -0,0 +1,218 @@ +#coding:utf-8 +# +# id: bugs.core_2004 +# title: ALTER USER XXX INACTIVE +# decription: +# We create two users ('foo' and 'bar') and make them immediatelly INACTIVE. +# One of them has been granted with RDB$ADMIN role, so he will be able to manage of other user access. +# Then we chek then connect for one of these users (e.g., 'foo') is unable because of his inactive status. +# After this we change state of FOO to active and verify that he can make connect. +# When this user successfully establish connect, he will try to : +# * create and immediatelly drop new user ('rio'); +# * change state of other existing user ('bar') to active. +# Finally, we check that user 'bar' really can connect now (after he was allowed to do this by 'foo'). +# +# ::: NB ::: +# FB config parameters AuthClient and UserManager must contain 'Srp' plugin in their values. +# +# Checked on Super and Classic: +# 3.0.4.32924: OK, 3.234s. +# 4.0.0.918: OK, 5.063s. +# +# tracker_id: CORE-2004 +# min_versions: ['3.0.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('Use CONNECT or CREATE DATABASE.*', ''), ('.*After line.*', '')] + +init_script_1 = """ + create or alter view v_check as + select s.sec$user_name, s.sec$active, s.sec$plugin + from rdb$database r + left join sec$users s on lower(s.sec$user_name) in (lower('tmp$c2004_foo'), lower('tmp$c2004_bar'), lower('tmp$c2004_rio')) + ; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import time +# import subprocess +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# #-------------------------------------------- +# +# 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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# +# #-------------------------------------------- +# +# db_conn.close() +# db_name=dsn +# sql_txt=''' +# set list on; +# commit; +# connect '%(db_name)s' user SYSDBA password 'masterkey'; +# create or alter user tmp$c2004_foo password '123' inactive using plugin Srp grant admin role; +# +# -- NB: currently it seems strange that one need to grant rdb$admin to 'foo' +# -- For what reason this role need to be added if 'foo' does his actions only in security_db ? +# -- Sent letter to dimitr and alex, 10-mar-18 16:00 +# grant rdb$admin to tmp$c2004_foo; +# +# create or alter user tmp$c2004_bar password '456' inactive using plugin Srp; +# commit; +# +# set count on; +# select 'init_state' as msg, v.* from v_check v; +# set count off; +# +# select 'try to connect as INACTIVE users' as msg from rdb$database; +# commit; +# +# connect '%(db_name)s' user tmp$c2004_foo password '123'; -- should fail +# select current_user as who_am_i from rdb$database; +# rollback; +# +# connect '%(db_name)s' user tmp$c2004_bar password '456'; -- should fail +# select current_user as who_am_i from rdb$database; +# rollback; +# +# connect '%(db_name)s' user SYSDBA password 'masterkey'; +# +# +# -- NB: following "alter user" statement must contain "using plugin Srp" clause +# -- otherwise get: +# -- Statement failed, SQLSTATE = HY000 +# -- record not found for user: TMP$C2004_BAR +# +# alter user tmp$c2004_foo active using plugin Srp; +# select 'try to connect as user FOO which was just set as active by SYSDBA.' as msg from rdb$database; +# commit; +# +# connect '%(db_name)s' user tmp$c2004_foo password '123' role 'RDB$ADMIN'; -- should pass +# select current_user as who_am_i, current_role as whats_my_role from rdb$database; +# +# +# -- should pass because foo has admin role: +# create or alter user tmp$c2004_rio password '123' using plugin Srp; +# drop user tmp$c2004_rio using plugin Srp; +# +# -- should pass because foo has admin role: +# alter user tmp$c2004_bar active using plugin Srp; +# select 'try to connect as user BAR which was just set as active by FOO.' as msg from rdb$database; +# commit; +# +# connect '%(db_name)s' user tmp$c2004_bar password '456'; -- should pass +# select current_user as who_am_i from rdb$database; +# commit; +# +# +# connect '%(db_name)s' user SYSDBA password 'masterkey'; +# select 'try to drop both non-privileged users by SYSDBA.' as msg from rdb$database; +# drop user tmp$c2004_foo using plugin Srp; +# drop user tmp$c2004_bar using plugin Srp; +# commit; +# set count on; +# +# select 'final_state' as msg, v.* from v_check v; +# set count off; +# ''' % locals() +# +# +# f_isql_run=open( os.path.join(context['temp_directory'],'tmp_check_2004.sql'), 'w') +# f_isql_run.write( sql_txt ) +# f_isql_run.close() +# +# f_isql_log=open( os.path.join(context['temp_directory'],'tmp_check_2004.log'), 'w') +# f_isql_err=open( os.path.join(context['temp_directory'],'tmp_check_2004.err'), 'w') +# +# subprocess.call( [ context['isql_path'], '-q', '-i', f_isql_run.name], stdout = f_isql_log, stderr=f_isql_err) +# +# flush_and_close( f_isql_log ) +# flush_and_close( f_isql_err ) +# +# with open(f_isql_log.name,'r') as f: +# for line in f: +# if line.rstrip().split(): +# print( 'STDLOG: ', line ) +# +# with open(f_isql_err.name,'r') as f: +# for line in f: +# if line.rstrip().split(): +# print( 'STDERR: ', line ) +# +# # Cleanup: +# ########## +# time.sleep(1) +# cleanup( [i.name for i in (f_isql_run, f_isql_log, f_isql_err)] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + STDLOG: MSG init_state + STDLOG: SEC$USER_NAME TMP$C2004_FOO + STDLOG: SEC$ACTIVE + STDLOG: SEC$PLUGIN Srp + STDLOG: MSG init_state + STDLOG: SEC$USER_NAME TMP$C2004_BAR + STDLOG: SEC$ACTIVE + STDLOG: SEC$PLUGIN Srp + STDLOG: Records affected: 2 + STDLOG: MSG try to connect as INACTIVE users + STDLOG: MSG try to connect as user FOO which was just set as active by SYSDBA. + STDLOG: WHO_AM_I TMP$C2004_FOO + STDLOG: WHATS_MY_ROLE RDB$ADMIN + STDLOG: MSG try to connect as user BAR which was just set as active by FOO. + STDLOG: WHO_AM_I TMP$C2004_BAR + STDLOG: MSG try to drop both non-privileged users by SYSDBA. + STDLOG: MSG final_state + STDLOG: SEC$USER_NAME + STDLOG: SEC$ACTIVE + STDLOG: SEC$PLUGIN + STDLOG: Records affected: 1 + STDERR: Statement failed, SQLSTATE = 28000 + STDERR: Your user name and password are not defined. Ask your database administrator to set up a Firebird login. + STDERR: Statement failed, SQLSTATE = 28000 + STDERR: Your user name and password are not defined. Ask your database administrator to set up a Firebird login. + STDERR: After line 19 in file C:\\MIX irebird\\QA bt-repo mp mp_check_2004.sql + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_2004_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2005.py b/tests/bugs/test_core_2005.py new file mode 100644 index 00000000..e9f986af --- /dev/null +++ b/tests/bugs/test_core_2005.py @@ -0,0 +1,109 @@ +#coding:utf-8 +# +# id: bugs.core_2005 +# title: Support SQL 2008 syntax for MERGE statement with DELETE extension +# decription: +# tracker_id: CORE-2005 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table src(id int primary key, x int, y int, z computed by(x+y)); + recreate table tgt(id int primary key, x int, y int, z computed by(x+y)); + commit; + + insert into src values(1, 5, 2); + insert into src values(3, 4, 3); + insert into src values(5, 3, 4); + insert into src values(6, 2, 5); + insert into src values(7, 1, 1); + insert into src values(8, 0, 0); + insert into src values(9, 1, 2); + commit; + + + insert into tgt values(2, 2, 5); + insert into tgt values(3, 3, 5); + insert into tgt values(4, 1, 7); + insert into tgt values(5, 6, 3); + commit; + + set transaction snapshot no wait; + + set term ^; + execute block as + begin + in autonomous transaction do + merge into tgt t + using src s + on s.id = t.id + when not matched and s.z >= 7 then + insert values(id, x, y) + when matched and t.z > s.z then + delete + when matched then + update set x = s.x, y = s.y + ; + + merge into src t + using tgt s + on s.id = t.id + when matched and t.z <= s.z then + update set x = s.x, y = s.y + when not matched and s.z >= 7 then + insert values(id, x, y) + when matched then + delete + ; + end + ^ + set term ;^ + commit; + + select * from src; + select * from tgt; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID X Y Z +============ ============ ============ ===================== + 1 5 2 7 + 3 3 5 8 + 5 6 3 9 + 6 2 5 7 + 7 1 1 2 + 8 0 0 0 + 9 1 2 3 + 2 2 5 7 + 4 1 7 8 + + + ID X Y Z +============ ============ ============ ===================== + 2 2 5 7 + 4 1 7 8 + 1 5 2 7 + 6 2 5 7 + """ + +@pytest.mark.version('>=3.0') +def test_core_2005_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2006.py b/tests/bugs/test_core_2006.py new file mode 100644 index 00000000..86672285 --- /dev/null +++ b/tests/bugs/test_core_2006.py @@ -0,0 +1,495 @@ +#coding:utf-8 +# +# id: bugs.core_2006 +# title: SUBSTRING with regular expression (SIMILAR TO) capability +# decription: +# tracker_id: CORE-2006 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + ------------------------------------------------------------------------------ + + -- Test for matching with percent characters before and after pattern: + select + trim(str) str + ,trim(ptn) ptn + ,iif( trim(str) similar to '%'||trim(ptn)||'%', 1, 0 ) "str similar to %ptn%" + ,substring( trim(str) similar '%\\"' || trim(ptn) || '\\"%' escape '\\' ) "subs(str similar to %ptn%)" + from( + select + 'WDWDWDWD' str + ,'((DW)|(WD)){4}' ptn + from rdb$database + + union all + + select + 'AAXYAAXYAAAAXYAAAXYAA' str + ,'(AAXY|AAAX){2,}' ptn + from rdb$database + + union all + + select + 'YZZXYZZ0Z0YZZYZZYYZZZYZZ0Z0YZZ' + ,'(0Z0(Y|Z)*){2}' + from rdb$database + + union all + + select + 'AARARARAARARAR' + ,'RA(AR){3}' + from rdb$database + + union all + + + select + 'eiavieieav' str + ,'(ie){2,}' ptn + from rdb$database + + union all + + select + 'avieieavav' str + ,'(av|ie){2,}' ptn + from rdb$database + + union all + + select + 'avieieieav' str + ,'((av)|(ie)){2,}' ptn + from rdb$database + + ); + + ---------------------- + + -- Test for exact matching to pattern: + select + trim(str) str + ,trim(ptn) ptn + ,iif( trim(str) similar to trim(ptn), 1, 0 ) "str similar to ptn" + ,substring( trim(str) similar '\\"' || trim(ptn) || '\\"' escape '\\' ) "subs(str similar to ptn)" + from( + select ----------- core-2389 + 'x/t' str + ,'%[/]t' ptn + from rdb$database + + + union all + + select ------------------- core-2756 + '2015-04-13' str + ,'[[:DIGIT:]]{4}[-][[:DIGIT:]]{2}[-][[:DIGIT:]]{2}' ptn + from rdb$database + + union all + + select ------------------- core-2780 + 'WI-T3.0.0.31780 Firebird 3.0 Beta 2' + ,'%[0-9]+.[0-9]+.[0-9]+((.?[0-9]+)*)[[:WHITESPACE:]]%' + from rdb$database + + union all + + select ----------- core-3523 + 'm' + ,'[p-k]' + from rdb$database + + union all + + ------------------- core-3754 + + select '1', '(1|2){0,}' from rdb$database union all select + '1', '(1|2){0,1}' from rdb$database union all select + '1', '(1|2){1}' from rdb$database union all select + '123', '(1|12[3]?){1}' from rdb$database union all select + '123', '(1|12[3]?)+' from rdb$database union all select + + ------------- core-0769 + 'ab', 'ab|cd|efg' from rdb$database union all select + 'efg', 'ab|cd|efg' from rdb$database union all select + 'a', 'ab|cd|efg' from rdb$database union all select -- 0 + '', 'a*' from rdb$database union all select + 'a', 'a*' from rdb$database union all select + 'aaa', 'a*' from rdb$database union all select + '', 'a+' from rdb$database union all select -- 0 + 'a', 'a+' from rdb$database union all select + 'aaa', 'a+' from rdb$database union all select + '', 'a?' from rdb$database union all select + 'a', 'a?' from rdb$database union all select + 'aaa', 'a?' from rdb$database union all select -- 0 + '', 'a{2,}' from rdb$database union all select -- 0 + 'a', 'a{2,}' from rdb$database union all select -- 0 + 'aa', 'a{2,}' from rdb$database union all select + 'aaa', 'a{2,}' from rdb$database union all select + '', 'a{2,4}' from rdb$database union all select -- 0 + 'a', 'a{2,4}' from rdb$database union all select -- 0 + 'aa', 'a{2,4}' from rdb$database union all select + 'aaa', 'a{2,4}' from rdb$database union all select + 'aaaa', 'a{2,4}' from rdb$database union all select + 'aaaaa', 'a{2,4}' from rdb$database union all select -- 0 + '', '_' from rdb$database union all select -- 0 + 'a', '_' from rdb$database union all select + '1', '_' from rdb$database union all select + 'a1', '_' from rdb$database union all select -- 0 + '', '%' from rdb$database union all select + 'az', 'a%z' from rdb$database union all select + 'a123z', 'a%z' from rdb$database union all select + 'azx', 'a%z' from rdb$database union all select -- 0 + 'ab', '(ab){2}' from rdb$database union all select -- 0 + 'aabb', '(ab){2}' from rdb$database union all select -- 0 + 'abab', '(ab){2}' from rdb$database union all select + 'b', '[abc]' from rdb$database union all select + 'd', '[abc]' from rdb$database union all select -- 0 + '9', '[0-9]' from rdb$database union all select + '9', '[0-8]' from rdb$database union all select -- 0 + 'b', '[^abc]' from rdb$database union all select -- 0 + 'd', '[^abc]' from rdb$database union all select + '3', '[[:DIGIT:]^3]' from rdb$database union all select -- 0 + '4', '[[:DIGIT:]^3]' from rdb$database union all select + '4', '[[:DIGIT:]]' from rdb$database union all select + 'a', '[[:DIGIT:]]' from rdb$database union all select -- 0 + '4', '[^[:DIGIT:]]' from rdb$database union all select -- 0 + 'a', '[^[:DIGIT:]]' from rdb$database + ); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + STR WDWDWDWD + PTN ((DW)|(WD)){4} + str similar to %ptn% 1 + subs(str similar to %ptn%) WDWDWDWD + + STR AAXYAAXYAAAAXYAAAXYAA + PTN (AAXY|AAAX){2,} + str similar to %ptn% 1 + subs(str similar to %ptn%) AAXYAAXY + + STR YZZXYZZ0Z0YZZYZZYYZZZYZZ0Z0YZZ + PTN (0Z0(Y|Z)*){2} + str similar to %ptn% 1 + subs(str similar to %ptn%) 0Z0YZZYZZYYZZZYZZ0Z0YZZ + + STR AARARARAARARAR + PTN RA(AR){3} + str similar to %ptn% 1 + subs(str similar to %ptn%) RAARARAR + + STR eiavieieav + PTN (ie){2,} + str similar to %ptn% 1 + subs(str similar to %ptn%) ieie + + STR avieieavav + PTN (av|ie){2,} + str similar to %ptn% 1 + subs(str similar to %ptn%) avieieavav + + STR avieieieav + PTN ((av)|(ie)){2,} + str similar to %ptn% 1 + subs(str similar to %ptn%) avieieieav + + + + STR x/t + PTN %[/]t + str similar to ptn 1 + subs(str similar to ptn) x/t + + STR 2015-04-13 + PTN [[:DIGIT:]]{4}[-][[:DIGIT:]]{2}[-][[:DIGIT:]]{2} + str similar to ptn 1 + subs(str similar to ptn) 2015-04-13 + + STR WI-T3.0.0.31780 Firebird 3.0 Beta 2 + PTN %[0-9]+.[0-9]+.[0-9]+((.?[0-9]+)*)[[:WHITESPACE:]]% + str similar to ptn 1 + subs(str similar to ptn) WI-T3.0.0.31780 Firebird 3.0 Beta 2 + + STR m + PTN [p-k] + str similar to ptn 0 + subs(str similar to ptn) + + STR 1 + PTN (1|2){0,} + str similar to ptn 1 + subs(str similar to ptn) 1 + + STR 1 + PTN (1|2){0,1} + str similar to ptn 1 + subs(str similar to ptn) 1 + + STR 1 + PTN (1|2){1} + str similar to ptn 1 + subs(str similar to ptn) 1 + + STR 123 + PTN (1|12[3]?){1} + str similar to ptn 1 + subs(str similar to ptn) 123 + + STR 123 + PTN (1|12[3]?)+ + str similar to ptn 1 + subs(str similar to ptn) 123 + + STR ab + PTN ab|cd|efg + str similar to ptn 1 + subs(str similar to ptn) ab + + STR efg + PTN ab|cd|efg + str similar to ptn 1 + subs(str similar to ptn) efg + + STR a + PTN ab|cd|efg + str similar to ptn 0 + subs(str similar to ptn) + + STR + PTN a* + str similar to ptn 1 + subs(str similar to ptn) + + STR a + PTN a* + str similar to ptn 1 + subs(str similar to ptn) a + + STR aaa + PTN a* + str similar to ptn 1 + subs(str similar to ptn) aaa + + STR + PTN a+ + str similar to ptn 0 + subs(str similar to ptn) + + STR a + PTN a+ + str similar to ptn 1 + subs(str similar to ptn) a + + STR aaa + PTN a+ + str similar to ptn 1 + subs(str similar to ptn) aaa + + STR + PTN a? + str similar to ptn 1 + subs(str similar to ptn) + + STR a + PTN a? + str similar to ptn 1 + subs(str similar to ptn) a + + STR aaa + PTN a? + str similar to ptn 0 + subs(str similar to ptn) + + STR + PTN a{2,} + str similar to ptn 0 + subs(str similar to ptn) + + STR a + PTN a{2,} + str similar to ptn 0 + subs(str similar to ptn) + + STR aa + PTN a{2,} + str similar to ptn 1 + subs(str similar to ptn) aa + + STR aaa + PTN a{2,} + str similar to ptn 1 + subs(str similar to ptn) aaa + + STR + PTN a{2,4} + str similar to ptn 0 + subs(str similar to ptn) + + STR a + PTN a{2,4} + str similar to ptn 0 + subs(str similar to ptn) + + STR aa + PTN a{2,4} + str similar to ptn 1 + subs(str similar to ptn) aa + + STR aaa + PTN a{2,4} + str similar to ptn 1 + subs(str similar to ptn) aaa + + STR aaaa + PTN a{2,4} + str similar to ptn 1 + subs(str similar to ptn) aaaa + + STR aaaaa + PTN a{2,4} + str similar to ptn 0 + subs(str similar to ptn) + + STR + PTN _ + str similar to ptn 0 + subs(str similar to ptn) + + STR a + PTN _ + str similar to ptn 1 + subs(str similar to ptn) a + + STR 1 + PTN _ + str similar to ptn 1 + subs(str similar to ptn) 1 + + STR a1 + PTN _ + str similar to ptn 0 + subs(str similar to ptn) + + STR + PTN % + str similar to ptn 1 + subs(str similar to ptn) + + STR az + PTN a%z + str similar to ptn 1 + subs(str similar to ptn) az + + STR a123z + PTN a%z + str similar to ptn 1 + subs(str similar to ptn) a123z + + STR azx + PTN a%z + str similar to ptn 0 + subs(str similar to ptn) + + STR ab + PTN (ab){2} + str similar to ptn 0 + subs(str similar to ptn) + + STR aabb + PTN (ab){2} + str similar to ptn 0 + subs(str similar to ptn) + + STR abab + PTN (ab){2} + str similar to ptn 1 + subs(str similar to ptn) abab + + STR b + PTN [abc] + str similar to ptn 1 + subs(str similar to ptn) b + + STR d + PTN [abc] + str similar to ptn 0 + subs(str similar to ptn) + + STR 9 + PTN [0-9] + str similar to ptn 1 + subs(str similar to ptn) 9 + + STR 9 + PTN [0-8] + str similar to ptn 0 + subs(str similar to ptn) + + STR b + PTN [^abc] + str similar to ptn 0 + subs(str similar to ptn) + + STR d + PTN [^abc] + str similar to ptn 1 + subs(str similar to ptn) d + + STR 3 + PTN [[:DIGIT:]^3] + str similar to ptn 0 + subs(str similar to ptn) + + STR 4 + PTN [[:DIGIT:]^3] + str similar to ptn 1 + subs(str similar to ptn) 4 + + STR 4 + PTN [[:DIGIT:]] + str similar to ptn 1 + subs(str similar to ptn) 4 + + STR a + PTN [[:DIGIT:]] + str similar to ptn 0 + subs(str similar to ptn) + + STR 4 + PTN [^[:DIGIT:]] + str similar to ptn 0 + subs(str similar to ptn) + + STR a + PTN [^[:DIGIT:]] + str similar to ptn 1 + subs(str similar to ptn) a + """ + +@pytest.mark.version('>=3.0') +def test_core_2006_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2008.py b/tests/bugs/test_core_2008.py new file mode 100644 index 00000000..eda1370b --- /dev/null +++ b/tests/bugs/test_core_2008.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: bugs.core_2008 +# title: NOT NULL procedure parameters +# decription: +# tracker_id: CORE-2008 +# min_versions: [] +# versions: 2.1.2 +# qmid: bugs.core_2008 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create or alter procedure test_procedure(id int not null) as begin end; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select rdb$parameter_name p_name, rdb$null_flag n_flag + from rdb$procedure_parameters + where rdb$procedure_name=upper('test_procedure'); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + P_NAME ID + N_FLAG 1 + """ + +@pytest.mark.version('>=2.1.2') +def test_core_2008_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2017.py b/tests/bugs/test_core_2017.py new file mode 100644 index 00000000..1873b71f --- /dev/null +++ b/tests/bugs/test_core_2017.py @@ -0,0 +1,131 @@ +#coding:utf-8 +# +# id: bugs.core_2017 +# title: I/O statistics for stored procedures are not accounted in monitoring tables +# decription: +# We open TWO cursors within the same attachments and: +# 1) make query to procedure inside cursor-1 (trivial count from table there); +# 2) ask MON$ tables inside cur-2 with aquiring IO statistics (fetches) for cur-1 statement. +# Number of fetches should be not less then 202400 - see results for 2.1.x, 2.5.x and 3.0 below. +# +# 17.12.2016 NOTE. Value of fetches in 3.0.2 and 4.0.0 was significantly reduced (~ twice) since ~25-nov-2016 +# See results for: 4.0.0.459 and 3.0.2.32641 +# Possible reason: +# https://github.com/FirebirdSQL/firebird/commit/8d5b1ff46ed9f22be4a394b941961c522e063ed1 +# https://github.com/FirebirdSQL/firebird/commit/dac882c97e2642e260abef475de75c490c5e4bc7 +# "Introduced small per-relation cache of physical numbers of data pages. +# It allows to reduce number of pointer page fetches and improves performance." +# +# +# tracker_id: CORE-2017 +# min_versions: ['2.5.7'] +# versions: 2.5.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create table T (C integer); + commit; + + set term ^ ; + + execute block + as + declare i int = 0; + begin + while (i < 100000) do + begin + insert into T values (:i); + i = i + 1; + end + end ^ + commit ^ + + create procedure sp_test + returns (i bigint) + as + begin + select count(*) + from T + into :i; + suspend; + end ^ + + commit ^ + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# +# # Obtain engine version: +# engine = str(db_conn.engine_version) # convert to text because 'float' object has no attribute 'startswith' +# +# stt1 = db_conn.cursor() +# stt2 = db_conn.cursor() +# +# sp_query = "select * from sp_test" +# stt2.execute(sp_query) +# for row in stt2: +# pass +# +# # do NOT!! >>> con1.commit() +# +# # Threshold: minimal value of fetches that should be reflected in mon$tables. +# +# MIN_FETCHES = 202400 if engine.startswith('2.5') else 104500 +# +# sql_io=''' +# select +# -- i.mon$page_fetches +# --,m.mon$sql_text +# --,rdb$get_context('SYSTEM','ENGINE_VERSION') +# iif( i.mon$page_fetches > %(MIN_FETCHES)s, 'IO statistics for procedure is OK', +# 'Strange low value for fetches: ' || i.mon$page_fetches +# ) as fetches_result +# from rdb$database r +# left join mon$statements m on +# m.mon$sql_text containing '%(sp_query)s' +# and m.mon$sql_text NOT containing 'mon$statements' +# left join mon$io_stats i on +# m.mon$stat_id = i.mon$stat_id and i.mon$stat_group = 3 +# ; +# ''' % locals() +# stt1.execute(sql_io) +# +# for row in stt1: +# print(row[0]) +# +# # (0, 'select * from sp_test', '2.1.0') +# # (0, 'select * from sp_test', '2.1.1') +# # (202472, 'select * from sp_test', '2.1.2') +# # (202472, 'select * from sp_test', '2.1.3') +# # (202472, 'select * from sp_test', '2.1.7') +# # (202472, 'select * from sp_test', '2.5.0') +# # (202472, 'select * from sp_test', '2.5.1') +# # (202472, 'select * from sp_test', '2.5.2') +# # (202472, 'select * from sp_test', '2.5.3') +# # BEFORE 3.0.2.32641: (202472, 'select * from sp_test', '3.0.0') // after: 104942 +# # BEFORE 4.0.0.459: (202472, 'select * from sp_test', '4.0.0') // after: 104942 +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + IO statistics for procedure is OK + """ + +@pytest.mark.version('>=2.5.7') +@pytest.mark.xfail +def test_core_2017_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2018.py b/tests/bugs/test_core_2018.py new file mode 100644 index 00000000..7043adc5 --- /dev/null +++ b/tests/bugs/test_core_2018.py @@ -0,0 +1,140 @@ +#coding:utf-8 +# +# id: bugs.core_2018 +# title: Only one client can access a readonly database +# decription: +# Restored database contains GTT. According to CORE-3399 we can write in it even in read-only database. +# This GTT serves as temp buffer for output row (we can not use windowed function in 2.5) +# Checked on: +# 4.0.0.1635 SS: 2.094s. +# 4.0.0.1633 CS: 3.591s. +# 3.0.5.33180 SS: 2.061s. +# 3.0.5.33178 CS: 2.383s. +# 2.5.9.27119 SS: 0.872s. +# 2.5.9.27146 SC: 0.435s. +# +# tracker_id: CORE-2018 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core2018-read_only.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + select MON$READ_ONLY from mon$database; + commit; + + -- ::: NB ::: + -- For CLASSIC mode each ES/EDS will increase value of current_connection by 2, for SS/SC - by 1. + -- In order to avoid dependency of architecture it was decided to accumulate _SEQUENTIAL_ numbers + -- of connection IDs (i.e. without holes) in GTT and ouput all of them after loop finish. + -- This sequential order can be easy achieved in 3.0 using dense_rank() but in 2.5 we need to + -- write SQL with additional subquery, see below. + set term ^; + execute block returns(sequential_attach_no int, attaches_i_can_see int) as + declare v_dbname type of column mon$database.mon$database_name; + declare v_stt varchar(192) = 'select current_connection, count(distinct a.mon$attachment_id) from mon$attachments a where a.mon$user=current_user and a.mon$remote_protocol is not null'; + declare v_usr varchar(31) = 'SYSDBA'; + declare v_pwd varchar(20) = 'masterkey'; + declare n int = 10; + declare v_attach_id int; + begin + v_dbname = 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME'); + + while (n > 0 ) do + begin + execute statement v_stt + on external v_dbname + as user v_usr password v_pwd role upper('BOSS#'||n) + into v_attach_id, attaches_i_can_see; + + -- This CAN be done since CORE-3399 was fixed (2.5.1): + insert into gtt_attaches(attach_id, sequential_id, attaches_i_can_see) + select + :v_attach_id + ,( select count(*) from gtt_attaches x where x.attach_id < :v_attach_id ) + 1 -- can`t use windowed funcs in 2.5 + ,:attaches_i_can_see + from rdb$database; + n = n-1; + end + for + select sequential_id, attaches_i_can_see + from gtt_attaches + into sequential_attach_no, attaches_i_can_see + do suspend; + end + ^ + set term ;^ + --select * from gtt_attaches; + 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MON$READ_ONLY 1 + + SEQUENTIAL_ATTACH_NO 1 + ATTACHES_I_CAN_SEE 2 + + SEQUENTIAL_ATTACH_NO 2 + ATTACHES_I_CAN_SEE 3 + + SEQUENTIAL_ATTACH_NO 3 + ATTACHES_I_CAN_SEE 4 + + SEQUENTIAL_ATTACH_NO 4 + ATTACHES_I_CAN_SEE 5 + + SEQUENTIAL_ATTACH_NO 5 + ATTACHES_I_CAN_SEE 6 + + SEQUENTIAL_ATTACH_NO 6 + ATTACHES_I_CAN_SEE 7 + + SEQUENTIAL_ATTACH_NO 7 + ATTACHES_I_CAN_SEE 8 + + SEQUENTIAL_ATTACH_NO 8 + ATTACHES_I_CAN_SEE 9 + + SEQUENTIAL_ATTACH_NO 9 + ATTACHES_I_CAN_SEE 10 + + SEQUENTIAL_ATTACH_NO 10 + ATTACHES_I_CAN_SEE 11 + """ + +@pytest.mark.version('>=2.5.1') +def test_core_2018_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2019.py b/tests/bugs/test_core_2019.py new file mode 100644 index 00000000..c6ac00c7 --- /dev/null +++ b/tests/bugs/test_core_2019.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: bugs.core_2019 +# title: UTF-8 conversion error (string truncation) +# decription: +# tracker_id: CORE-2019 +# min_versions: [] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """recreate table test ( + column1 varchar(10) character set none collate none ); + +insert into test values ('1234567890'); +commit; +""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """select coalesce(column1, '') from test; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +COALESCE +========== +1234567890 + +""" + +@pytest.mark.version('>=3.0') +def test_core_2019_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_202.py b/tests/bugs/test_core_202.py new file mode 100644 index 00000000..ce9c6a62 --- /dev/null +++ b/tests/bugs/test_core_202.py @@ -0,0 +1,87 @@ +#coding:utf-8 +# +# id: bugs.core_202 +# title: ORDER BY works wrong with collate PT_PT +# decription: +# tracker_id: CORE-202 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_202 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE STOCKS ( + MNEN INTEGER NOT NULL, + ACTIVO VARCHAR(50) CHARACTER SET ISO8859_1 COLLATE PT_PT +); + +COMMIT WORK; + +INSERT INTO STOCKS (MNEN, ACTIVO) VALUES (1, 'B&A'); +INSERT INTO STOCKS (MNEN, ACTIVO) VALUES (2, 'BES'); +INSERT INTO STOCKS (MNEN, ACTIVO) VALUES (3, 'BCP'); +INSERT INTO STOCKS (MNEN, ACTIVO) VALUES (4, 'B&A Pref.'); +INSERT INTO STOCKS (MNEN, ACTIVO) VALUES (5, 'Banif'); + +COMMIT WORK; + +CREATE COLLATION PT_PT2 FOR ISO8859_1 FROM PT_PT 'SPECIALS-FIRST=1'; + +COMMIT WORK; + +CREATE TABLE STOCKS2 ( + MNEN INTEGER NOT NULL, + ACTIVO VARCHAR(50) CHARACTER SET ISO8859_1 COLLATE PT_PT2 +); + +COMMIT WORK; + +INSERT INTO STOCKS2 (MNEN, ACTIVO) VALUES (1, 'B&A'); +INSERT INTO STOCKS2 (MNEN, ACTIVO) VALUES (2, 'BES'); +INSERT INTO STOCKS2 (MNEN, ACTIVO) VALUES (3, 'BCP'); +INSERT INTO STOCKS2 (MNEN, ACTIVO) VALUES (4, 'B&A Pref.'); +INSERT INTO STOCKS2 (MNEN, ACTIVO) VALUES (5, 'Banif'); + +COMMIT WORK; + +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT ACTIVO FROM STOCKS ORDER BY ACTIVO; + +SELECT ACTIVO FROM STOCKS2 ORDER BY ACTIVO; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ACTIVO +================================================== +B&A +Banif +B&A Pref. +BCP +BES + +ACTIVO +================================================== +B&A +B&A Pref. +Banif +BCP +BES + +""" + +@pytest.mark.version('>=2.1') +def test_core_202_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2022.py b/tests/bugs/test_core_2022.py new file mode 100644 index 00000000..2733cbe5 --- /dev/null +++ b/tests/bugs/test_core_2022.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: bugs.core_2022 +# title: "EXECUTE BLOCK" statement does not support "CREATE USER" +# decription: +# tracker_id: CORE-2022 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """set term ^ ; +execute block +as +begin +EXECUTE statement 'create user test1 password ''test1'''; +EXECUTE statement 'create user test2 password ''test2'''; +end ^ + +commit ^ + +execute block +as +begin +EXECUTE statement 'drop user test1'; +EXECUTE statement 'drop user test2'; +end ^ + +commit ^ +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.0') +def test_core_2022_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_2026.py b/tests/bugs/test_core_2026.py new file mode 100644 index 00000000..0f4188ac --- /dev/null +++ b/tests/bugs/test_core_2026.py @@ -0,0 +1,74 @@ +#coding:utf-8 +# +# id: bugs.core_2026 +# title: Problem with a read-only marked database +# decription: +# Since FB 2.1 engine performs transliteraion of blobs between character sets. +# In this case system blob, stored in UNICODE_FSS, transliterated into connection charset. +# To do this, temporary blob is created. Engine didn't support temporary blobs creation in +# read-only databases since read-only databases was introduced +# +# tracker_id: CORE-2026 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('RDB\\$DEFAULT_SOURCE.*', '')] + +init_script_1 = """ + recreate table test(x integer default 0); + commit; + """ + +db_1 = db_factory(charset='ISO8859_1', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# script=''' +# set list on; +# set blob all; +# select mon$read_only from mon$database; +# set count on; +# select RDB$FIELD_NAME, rdb$default_source +# from rdb$relation_fields +# where rdb$default_source is not null; +# ''' +# runProgram('isql',[dsn],script) +# runProgram('gfix',['-mode','read_only',dsn]) +# runProgram('isql',['-ch','iso8859_1',dsn],script) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MON$READ_ONLY 0 + RDB$FIELD_NAME X + default 0 + Records affected: 1 + MON$READ_ONLY 1 + RDB$FIELD_NAME X + default 0 + Records affected: 1 + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_2026_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2027.py b/tests/bugs/test_core_2027.py new file mode 100644 index 00000000..0c7362c8 --- /dev/null +++ b/tests/bugs/test_core_2027.py @@ -0,0 +1,88 @@ +#coding:utf-8 +# +# id: bugs.core_2027 +# title: Incorrect buffer size for ORDER BY expression with system fields +# decription: +# tracker_id: CORE-2027 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table t(rel_name char(31) character set unicode_fss); + commit; + insert into t + select r.rdb$relation_name from rdb$relations r + order by r.rdb$relation_id + rows 40; -- minimal numer of rows in rdb$relations that is common for 2.5 and 3.0 + commit; + + set list on; + select t.rel_name + from t + order by '0' || t.rel_name; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + REL_NAME MON$ATTACHMENTS + REL_NAME MON$CALL_STACK + REL_NAME MON$DATABASE + REL_NAME MON$IO_STATS + REL_NAME MON$RECORD_STATS + REL_NAME MON$STATEMENTS + REL_NAME MON$TRANSACTIONS + REL_NAME RDB$BACKUP_HISTORY + REL_NAME RDB$CHARACTER_SETS + REL_NAME RDB$CHECK_CONSTRAINTS + REL_NAME RDB$COLLATIONS + REL_NAME RDB$DATABASE + REL_NAME RDB$DEPENDENCIES + REL_NAME RDB$EXCEPTIONS + REL_NAME RDB$FIELDS + REL_NAME RDB$FIELD_DIMENSIONS + REL_NAME RDB$FILES + REL_NAME RDB$FILTERS + REL_NAME RDB$FORMATS + REL_NAME RDB$FUNCTIONS + REL_NAME RDB$FUNCTION_ARGUMENTS + REL_NAME RDB$GENERATORS + REL_NAME RDB$INDEX_SEGMENTS + REL_NAME RDB$INDICES + REL_NAME RDB$LOG_FILES + REL_NAME RDB$PAGES + REL_NAME RDB$PROCEDURES + REL_NAME RDB$PROCEDURE_PARAMETERS + REL_NAME RDB$REF_CONSTRAINTS + REL_NAME RDB$RELATIONS + REL_NAME RDB$RELATION_CONSTRAINTS + REL_NAME RDB$RELATION_FIELDS + REL_NAME RDB$ROLES + REL_NAME RDB$SECURITY_CLASSES + REL_NAME RDB$TRANSACTIONS + REL_NAME RDB$TRIGGERS + REL_NAME RDB$TRIGGER_MESSAGES + REL_NAME RDB$TYPES + REL_NAME RDB$USER_PRIVILEGES + REL_NAME RDB$VIEW_RELATIONS + """ + +@pytest.mark.version('>=2.5.0') +def test_core_2027_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2031.py b/tests/bugs/test_core_2031.py new file mode 100644 index 00000000..2fb04c8c --- /dev/null +++ b/tests/bugs/test_core_2031.py @@ -0,0 +1,58 @@ +#coding:utf-8 +# +# id: bugs.core_2031 +# title: Null in the first record in a condition on rdb$db_key +# decription: +# tracker_id: CORE-2031 +# min_versions: [] +# versions: 2.1.2 +# qmid: bugs.core_2031 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE A1 ( + FA1 INTEGER, + FA2 INTEGER +); +commit; +insert into a1 (fa1, fa2) values (1, 1); +insert into a1 (fa1, fa2) values (1, 2); +insert into a1 (fa1, fa2) values (1, 3); +insert into a1 (fa1, fa2) values (1, 4); +insert into a1 (fa1, fa2) values (1, 5); +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """update a1 a set a.fa1 = +(select 2 from a1 aa +where a.rdb$db_key = aa.rdb$db_key); +commit; +select * from A1;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + FA1 FA2 +============ ============ + 2 1 + 2 2 + 2 3 + 2 4 + 2 5 + +""" + +@pytest.mark.version('>=2.1.2') +def test_core_2031_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2032.py b/tests/bugs/test_core_2032.py new file mode 100644 index 00000000..5451673b --- /dev/null +++ b/tests/bugs/test_core_2032.py @@ -0,0 +1,111 @@ +#coding:utf-8 +# +# id: bugs.core_2032 +# title: Stored procedure recursively called by calculated field fails after reconnect +# decription: +# Confirmed bug on 4.0.0.2353; 3.0.8.33401. +# Checked on 4.0.0.2365, 3.0.8.33415 -- all fine. +# +# tracker_id: CORE-2032 +# min_versions: ['3.0.8'] +# versions: 3.0.8 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.8 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create or alter procedure strange_procedure ( + result_to_return float, + reference_id integer) + returns (result float) as + begin + suspend; + end + ^ + set term ;^ + commit; + + create table test ( + id integer not null, + result_to_return float, + reference_id integer, + calc_fld computed by ( + ( + select result + from + strange_procedure( + test.result_to_return, + test.reference_id + ) + ) + ) + ); + commit; + + insert into test (id, result_to_return, reference_id) values (1, 20, 0); + insert into test (id, result_to_return, reference_id) values (0, 10, null); + commit; + + + set term ^; + create or alter procedure strange_procedure ( + result_to_return float, + reference_id integer) + returns ( + result float) + as + declare variable sum_of_referenced_items float; + begin + -- initialize variables + result = result_to_return; + sum_of_referenced_items = 0; + + -- if reference is null then it + -- must be record id = 0 + if (reference_id is null) then + begin + select sum(t.calc_fld) + from test t where t.reference_id = 0 + into :sum_of_referenced_items; + + if (sum_of_referenced_items > :result) + then + result = sum_of_referenced_items; + end + + suspend; + end + ^ + set term ;^ + commit; + set list on; + select calc_fld as value_before_reconnect from test where ID = 0; + commit; + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + select calc_fld as value_after_reconnect from test where ID = 0; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + VALUE_BEFORE_RECONNECT 20 + VALUE_AFTER_RECONNECT 20 + """ + +@pytest.mark.version('>=3.0.8') +def test_core_2032_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2036.py b/tests/bugs/test_core_2036.py new file mode 100644 index 00000000..a7a1d43f --- /dev/null +++ b/tests/bugs/test_core_2036.py @@ -0,0 +1,61 @@ +#coding:utf-8 +# +# id: bugs.core_2036 +# title: Parameters order of EXECUTE BLOCK statement is reversed if called from EXECUTE STATEMENT +# decription: +# 2.5.9.27107: OK, 0.328s. +# 3.0.4.32924: OK, 0.906s. +# 4.0.0.918: OK, 1.110s. +# +# tracker_id: CORE-2036 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set term ^; + execute block returns(p1 int, p2 int, p3 int) as + declare s varchar(255); + begin + s = 'execute block ( i1 int = ?, i2 int = ?, i3 int = ? ) returns(o1 int, o2 int, o3 int) as ' + || 'begin ' + || ' o1 = i1 * 2; ' + || ' o2 = i2 * 4; ' + || ' o3 = i3 * 8; ' + || ' suspend; ' + || 'end ' + ; + execute statement (s) (654, 543, 432) into p1, p2, p3; + suspend; + end + ^ + set term ^; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + P1 1308 + P2 2172 + P3 3456 + """ + +@pytest.mark.version('>=2.5.0') +def test_core_2036_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2038.py b/tests/bugs/test_core_2038.py new file mode 100644 index 00000000..c13a337b --- /dev/null +++ b/tests/bugs/test_core_2038.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_2038 +# title: New EXECUTE STATEMENT implementation asserts or throws an error if used both before and after commin/rollback retaining +# decription: +# tracker_id: CORE-2038 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """-- set transaction read write snapshot; +set term ^ ; +execute block returns (i integer) +as +begin + execute statement 'select 1 from rdb$database' into :i; +end ^ +commit retain^ +execute block returns (i integer) +as +begin + execute statement 'select 1 from rdb$database' into :i; +end ^ +commit retain^ +commit ^ +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.0') +def test_core_2038_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_2039.py b/tests/bugs/test_core_2039.py new file mode 100644 index 00000000..28c41f2e --- /dev/null +++ b/tests/bugs/test_core_2039.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: bugs.core_2039 +# title: Domain-level CHECK constraints wrongly process NULL values +# decription: +# tracker_id: CORE-2039 +# min_versions: [] +# versions: 2.1.2 +# qmid: bugs.core_2039 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE DOMAIN D_DATE AS DATE +CHECK (VALUE BETWEEN DATE '01.01.1900' AND DATE '01.01.2050'); + +CREATE PROCEDURE TMP (PDATE D_DATE) +AS BEGIN END; + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """EXECUTE PROCEDURE TMP (NULL); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1.2') +def test_core_2039_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_2041.py b/tests/bugs/test_core_2041.py new file mode 100644 index 00000000..d9cd1da0 --- /dev/null +++ b/tests/bugs/test_core_2041.py @@ -0,0 +1,86 @@ +#coding:utf-8 +# +# id: bugs.core_2041 +# title: update or insert with gen_id() with wrong generator value +# decription: +# tracker_id: CORE-2041 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE GENERATOR LOGID; + +set generator LOGID to 0; + +CREATE TABLE LOGBOOK + ( ID integer not null, + ENTRY varchar(64), + PRIMARY KEY (ID)); + +set term ^ ; + +create procedure logrow(txt varchar(64)) +as + declare variable lid integer; +begin + lid = gen_id(LOGID, 1); + update or insert into logbook (id, entry) + values (:lid, :txt); +end^ + +set term ; ^ +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """update or insert into logbook (id, entry) values (gen_id(LOGID, 1), 'Testing 1'); +update or insert into logbook (id, entry) values (gen_id(LOGID, 1), 'Testing 2'); +update or insert into logbook (id, entry) values (gen_id(LOGID, 1), 'Testing 3'); +update or insert into logbook (id, entry) values (gen_id(LOGID, 1), 'Testing 4'); +select * from logbook; + +execute procedure logrow('Test 1'); +execute procedure logrow('Test 2'); +execute procedure logrow('Test 3'); +execute procedure logrow('Test 4'); +select * from logbook; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID ENTRY +============ ================================================================ + 1 Testing 1 + 2 Testing 2 + 3 Testing 3 + 4 Testing 4 + + + ID ENTRY +============ ================================================================ + 1 Testing 1 + 2 Testing 2 + 3 Testing 3 + 4 Testing 4 + 5 Test 1 + 6 Test 2 + 7 Test 3 + 8 Test 4 + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_2041_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2042.py b/tests/bugs/test_core_2042.py new file mode 100644 index 00000000..f4dd70aa --- /dev/null +++ b/tests/bugs/test_core_2042.py @@ -0,0 +1,102 @@ +#coding:utf-8 +# +# id: bugs.core_2042 +# title: connection lost to database when used AUTONOMOUS TRANSACTION +# decription: +# tracker_id: CORE-2042 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + set term ^; + create or alter procedure test_caller_name + returns ( + object_name char(31), + object_type smallint) + as + begin + end + ^ + create or alter procedure get_caller_name + returns ( + object_name char(31), + object_type smallint) + as + declare variable tran_id integer; + begin + tran_id = current_transaction; + + in autonomous transaction do + begin + select cs.mon$object_name, cs.mon$object_type + from mon$call_stack cs, mon$statements st + where cs.mon$statement_id = st.mon$statement_id + and st.mon$transaction_id = :tran_id + and cs.mon$caller_id is null -- :: nb :: Added this condition because output differs in 3.0 vs 2.5! + order by cs.mon$call_id + rows 1 + into :object_name, :object_type; + end + + suspend; + end + ^ + + create or alter procedure test_caller_name + returns ( + object_name char(31), + object_type smallint) + as + begin + select object_name, object_type from get_caller_name + into :object_name, :object_type; + + suspend; + end + ^ + set term ;^ + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select * from test_caller_name; + select * from test_caller_name; + select * from test_caller_name; + select * from test_caller_name; + select * from test_caller_name; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + OBJECT_NAME TEST_CALLER_NAME + OBJECT_TYPE 5 + OBJECT_NAME TEST_CALLER_NAME + OBJECT_TYPE 5 + OBJECT_NAME TEST_CALLER_NAME + OBJECT_TYPE 5 + OBJECT_NAME TEST_CALLER_NAME + OBJECT_TYPE 5 + OBJECT_NAME TEST_CALLER_NAME + OBJECT_TYPE 5 + """ + +@pytest.mark.version('>=2.5.0') +def test_core_2042_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2044.py b/tests/bugs/test_core_2044.py new file mode 100644 index 00000000..6fe3d92a --- /dev/null +++ b/tests/bugs/test_core_2044.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: bugs.core_2044 +# title: Incorrect result with UPDATE OR INSERT ... RETURNING OLD and non-nullable columns +# decription: +# tracker_id: CORE-2044 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t ( + n integer primary key, + x1 integer not null, + x2 integer +); +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """update or insert into t + values (1, 1, 1) + returning old.n, old.x1, old.x2, new.n, new.x1, new.x2; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CONSTANT CONSTANT CONSTANT N X1 X2 +============ ============ ============ ============ ============ ============ + 1 1 1 + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_2044_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2051.py b/tests/bugs/test_core_2051.py new file mode 100644 index 00000000..a7cbb54a --- /dev/null +++ b/tests/bugs/test_core_2051.py @@ -0,0 +1,57 @@ +#coding:utf-8 +# +# id: bugs.core_2051 +# title: don't work subquery in COALESCE +# decription: +# tracker_id: CORE-2051 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: bugs.core_2051 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test1(id int primary key using index test1_pk); + commit; + insert into test1 values(1); + insert into test1 values(2); + insert into test1 values(3); + commit; + + recreate table test2(id int primary key using index test2_pk); + commit; + insert into test2 values(1); + 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (T2 INDEX (TEST2_PK)) + PLAN (T1 ORDER TEST1_PK) + ID2 1 + ID2 2 + ID2 0 + """ + +@pytest.mark.version('>=2.5') +def test_core_2051_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2053.py b/tests/bugs/test_core_2053.py new file mode 100644 index 00000000..99aca68e --- /dev/null +++ b/tests/bugs/test_core_2053.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_2053 +# title: Computed expressions may be optimized badly if used inside the RETURNING clause of the INSERT statement +# decription: +# tracker_id: CORE-2053 +# min_versions: [] +# versions: 2.1.2 +# qmid: bugs.core_2053 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """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_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """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;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +PLAN (T1 INDEX (I1)) + + CASE +============ + 1 + +""" + +@pytest.mark.version('>=2.1.2') +def test_core_2053_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2061.py b/tests/bugs/test_core_2061.py new file mode 100644 index 00000000..5893782f --- /dev/null +++ b/tests/bugs/test_core_2061.py @@ -0,0 +1,33 @@ +#coding:utf-8 +# +# id: bugs.core_2061 +# title: ALTER VIEW WITH CHECK OPTION crashes the engin +# decription: +# tracker_id: CORE-2061 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """create or alter view v as select * from rdb$database where 1 = 0 with check option; +alter view v as select * from rdb$database where 1 = 1 with check option; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.0') +def test_core_2061_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_2067.py b/tests/bugs/test_core_2067.py new file mode 100644 index 00000000..c19584c1 --- /dev/null +++ b/tests/bugs/test_core_2067.py @@ -0,0 +1,68 @@ +#coding:utf-8 +# +# id: bugs.core_2067 +# title: GROUP by and RDB$DB_KEY problems +# decription: +# tracker_id: CORE-2067 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t1 (n integer); +insert into t1 values (1); +insert into t1 values (2); +insert into t1 values (3); +commit; +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """-- First problem: it should be invalid to group by n and select rdb$db_key +select n, rdb$db_key from t1 group by n; + +-- Second problem: error: column unknown DB_KEY is wrong raised +select n, rdb$db_key from t1 group by 1, 2; + +-- Third problem: wrong values for rdb$db_key are returned +select n, t1.rdb$db_key from t1 group by 1, 2; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + N DB_KEY +============ ================ + 1 8000000001000000 + 2 8000000002000000 + 3 8000000003000000 + + + N DB_KEY +============ ================ + 1 8000000001000000 + 2 8000000002000000 + 3 8000000003000000 + +""" +expected_stderr_1 = """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) +""" + +@pytest.mark.version('>=2.5.0') +def test_core_2067_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2068.py b/tests/bugs/test_core_2068.py new file mode 100644 index 00000000..86e9090f --- /dev/null +++ b/tests/bugs/test_core_2068.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: bugs.core_2068 +# title: Comparision with IN and subquery with RDB$DB_KEY returns wrong result +# decription: +# tracker_id: CORE-2068 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t1 (n integer); + +insert into t1 values (1); +insert into t1 values (2); +insert into t1 values (3); +commit; +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select a.* + from t1 a + where a.rdb$db_key = ( + select b.rdb$db_key + from t1 b + where n = 1 +); + +select a.* + from t1 a + where a.rdb$db_key in ( + select b.rdb$db_key + from t1 b + where n = 1 +); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + N +============ + 1 + + + N +============ + 1 + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_2068_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2069.py b/tests/bugs/test_core_2069.py new file mode 100644 index 00000000..5987e1d7 --- /dev/null +++ b/tests/bugs/test_core_2069.py @@ -0,0 +1,80 @@ +#coding:utf-8 +# +# id: bugs.core_2069 +# title: Incorrect VIEW expansion when RDB$DB_KEY is used in view body +# decription: +# tracker_id: CORE-2069 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t1 (n integer); + +insert into t1 values (1); +insert into t1 values (2); +insert into t1 values (3); +commit; +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """-- ok +select a.* + from t1 a + where a.rdb$db_key = ( + select b.rdb$db_key + from t1 b + where n = 1 +); + +-- ok +create view v1 as + select a.* + from t1 a + where a.rdb$db_key = ( + select b.rdb$db_key + from t1 b + where n = 1 +); + +-- ok +select * from v1; + +-- wrong: returns nothing +select * from v1 union all select * from v1; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + N +============ + 1 + + + N +============ + 1 + + + N +============ + 1 + 1 + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_2069_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2073.py b/tests/bugs/test_core_2073.py new file mode 100644 index 00000000..edd3338e --- /dev/null +++ b/tests/bugs/test_core_2073.py @@ -0,0 +1,74 @@ +#coding:utf-8 +# +# id: bugs.core_2073 +# title: Expression indexes bug: incorrect result for the inverted boolean +# decription: +# tracker_id: CORE-2073 +# min_versions: [] +# versions: 3.0 +# qmid: bugs.core_2073 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """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_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """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; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +PLAN (T INDEX (TMP_DATE1_IDX1)) + + COUNT +===================== + 61 + + +PLAN (T INDEX (TMP_DATE1_IDX2)) + + COUNT +===================== + 61 + +""" + +@pytest.mark.version('>=3.0') +def test_core_2073_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2075.py b/tests/bugs/test_core_2075.py new file mode 100644 index 00000000..ca9fcc95 --- /dev/null +++ b/tests/bugs/test_core_2075.py @@ -0,0 +1,68 @@ +#coding:utf-8 +# +# id: bugs.core_2075 +# title: Parts of RDB$DB_KEY of views may be inverted when using outer joins +# decription: +# tracker_id: CORE-2075 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t1 (n integer); +create table t2 (n integer); + +insert into t1 values (1); +insert into t1 values (2); +insert into t1 values (3); +insert into t1 values (4); +insert into t1 values (5); +insert into t1 values (6); + +insert into t2 values (2); +insert into t2 values (4); +insert into t2 values (5); +insert into t2 values (8); +commit; + +create view v (t1, t2) as + select t1.rdb$db_key, t2.rdb$db_key + from t1 + full join t2 + on t2.n = t1.n; +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select v.rdb$db_key, v.* + from v; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +DB_KEY T1 T2 +================================ ================ ================ +81000000010000008000000002000000 8000000002000000 8100000001000000 +81000000020000008000000004000000 8000000004000000 8100000002000000 +81000000030000008000000005000000 8000000005000000 8100000003000000 +81000000040000000000000000000000 8100000004000000 +00000000000000008000000001000000 8000000001000000 +00000000000000008000000003000000 8000000003000000 +00000000000000008000000006000000 8000000006000000 + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_2075_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2078.py b/tests/bugs/test_core_2078.py new file mode 100644 index 00000000..597c169c --- /dev/null +++ b/tests/bugs/test_core_2078.py @@ -0,0 +1,367 @@ +#coding:utf-8 +# +# id: bugs.core_2078 +# title: Suboptimal join plan if there are selective non-indexed predicates involved +# decription: +# This test operates with three tables: "small", "medium" and "big" - which are INNER-join'ed. +# It was found that there is some threshold ratio between number of rows in "small" vs "medium" +# tables which affects on generated PLAN after reaching this ratio. +# In particular, when tables have following values of rows: 26, 300 and 3000 - than optimizer +# still DOES take in account "WHERE" condition with non-indexed field in SMALL table ("where s.sf = 0"), +# and this lead to GOOD (fast) performance because SMALL table will be FIRST in the join order. +# However, if number of rows in SMALL table will change from 26 to 27 (yes, just one row) than +# optimizer do NOT consider additional condition (WHERE-filter) on that table and begin choose +# SLOW (ineffective) plan where MEDIUM table is first in join order. +# After discussion with dimitr, it was decided to: +# 1) put here TWO cases of query: with "fast" and "slow" plan; +# 2) replace too narrow threshold-pair (26 vs 27) with more wider (now: 15 and 45) because otherwise +# even minor changes in optimizer can breake this test expected output. +# Test make TWO PAIRS (i.e. total FOUR) runs: +# 1. When number of rows in SMALL table is less than threshold: +# 1.1. Without 'where'-filter on small table - to ensure that plan will contain MEDIUM table as first in join; +# 1.2. WITH 'where'-filter on small table - to ensure that plan will be CHANGED and SMALL table will be first; +# 2. When number of rows in SMALL table is beyond the threshold: +# 2.1. Without 'where'-filter on small table - plan will contain MEDIUM table as first in join; +# 2.2. WITH 'where'-filter on small table - plan will NOT changed, MEDIUM table will remain first in join. +# Beside output of PLAN itself, test also: +# 1) displays index statistics +# 2) compares fetches with some 'upper-limit' constants in order to alert us in case when fetches become too high. +# These constants have been obtained after sereval experiments with page_size = 4k, and their values are base on +# following typical results (which are the same on 2.5 and 3.0): +# FETCHES_1_1 19636 +# FETCHES_1_2 9094 +# FETCHES_2_1 19548 +# FETCHES_2_2 19548 +# +# 18.08.2020. +# Test uses pre-created database which has several procedures for analyzing performance by with the help of MON$ tables. +# Performance results are gathered in the table STAT_LOG, each odd run will save mon$ counters with "-" sign and next +# (even) run will save them with "+" -- see SP_GATHER_STAT. +# Aggegation of results is done in the view V_AGG_STAT (negative values relate to start, positive to the end of measure, +# difference between them means performance expenses which we want to evaluate). +# NOTE. Before each new measure we have to set generator G_GATHER_STAT to zero in order to make it produce proper values +# starting with 1 (odd --> NEGATIVE sign for counters). This is done in SP_TRUNCATE_STAT. +# +# :::::::::::::::::::::::::::::::::::::::: NB :::::::::::::::::::::::::::::::::::: +# 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 change code of SP_TRUNCATE_STAT: instead of 'alter sequence restart...' we do +# reset like this: c = gen_id(g_gather_stat, -gen_id(g_gather_stat, 0)); +# +# Checked on: +# 4.0.0.2164 SS: 2.183s. +# 4.0.0.2119 SS: 2.280s. +# 4.0.0.2164 CS: 2.705s. +# 3.0.7.33356 SS: 1.500s. +# 3.0.7.33356 CS: 2.445s. +# 2.5.9.27150 SC: 0.653s. +# +# tracker_id: CORE-2078 +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='mon-stat-gathering-3_0.fbk', init=init_script_1) + +test_script_1 = """ + create or alter procedure sp_fill_data(a_sml_rows int, a_med_rows int, a_big_rows int) as begin end; + recreate table tbig(id int, sid int, mid int); + commit; + recreate table tsml(id int not null, sf int); + commit; + recreate table tmed(id int not null); + commit; + + set term ^; + create or alter procedure sp_fill_data(a_sml_rows int, a_med_rows int, a_big_rows int) + as + declare i int; + declare i_mod2 smallint; + begin + + -- gather old record versions if they are from previous run: + select count(*) from tsml into i; + select count(*) from tmed into i; + select count(*) from tbig into i; + + i=0; + while (i < a_sml_rows) do + begin + insert into tsml(id, sf) values( :i, :i - (:i/2)*2 ); + i = i+1; + end + + i=0; + while (i < a_med_rows) do + begin + insert into tmed(id) values( :i ); + i = i+1; + end + + i=0; + while (i < a_big_rows) do + begin + insert into tbig(id, sid, mid) values( :i, :i - (:i/2)*2, :i - (:i/:a_med_rows)*:a_med_rows ); + i = i+1; + end + + end + ^ + + create or alter procedure srv_recalc_idx_stat + returns ( + tab_name varchar(31), + idx_name varchar(31), + idx_stat_afte numeric(12, 10) -- double precision + ) + as + begin + -- Refresh index statistics all user (non-system) tables. + -- Needs to be run in regular basis (`cron` on linux, `at` on windows) + -- otherwise ineffective plans can be generated when doing inner joins! + -- Example to run: select * from srv_recalc_idx_stat; + for + select ri.rdb$relation_name, ri.rdb$index_name + from rdb$indices ri + join rdb$relations rr on ri.rdb$relation_name = rr.rdb$relation_name + where + coalesce(ri.rdb$system_flag,0)=0 + and rr.rdb$relation_type = 0 -- exclude GTTs! + order by ri.rdb$relation_name, ri.rdb$index_name + into + tab_name, idx_name + do begin + execute statement( 'set statistics index '||idx_name ) + with autonomous transaction + ; + + select ri.rdb$statistics + from rdb$indices ri + where ri.rdb$relation_name = :tab_name and ri.rdb$index_name = :idx_name + into idx_stat_afte; + + suspend; + end + end + ^ + + set term ;^ + commit; + + alter table tsml add constraint tsml_pk primary key(id) using index tsml_pk; + alter table tmed add constraint tmed_pk primary key(id) using index tmed_pk; + + alter table tbig add constraint tbig_fk_sml foreign key(sid) references tsml using index tbig_idx1_fk_sml; + alter table tbig add constraint tbig_fk_med foreign key(mid) references tmed using index tbig_idx2_fk_med; + commit; + + set width tab_name 31; + set width idx_name 31; + set list on; + + -------------------- prepare-1 ------------------ + --execute procedure sp_fill_data(26, 300, 3000); + execute procedure sp_fill_data(15, 300, 3000); + commit; + + set transaction read committed; + select + tab_name as run1_tab_name + ,idx_name as run1_idx_name + ,idx_stat_afte run1_idx_stat + from srv_recalc_idx_stat where tab_name in ( upper('tsml'), upper('tmed'), upper('tbig') ); + commit; + + --------------------- run-1.1 ------------------- + -----alter sequence g_gather_stat restart with 0; + execute procedure sp_truncate_stat; + commit; + + execute procedure sp_gather_stat; ------- catch statistics BEFORE measured statement(s) + commit; + + set plan on; + select count(*) cnt_1_1 + from tsml s + join tbig b on b.sid = s.id + join tmed m on b.mid = m.id + ; + set plan off; + + execute procedure sp_gather_stat; ------- catch statistics AFTER measured statement(s) + commit; + + --------------------- run-1.2 ------------------- + execute procedure sp_gather_stat; ------- catch statistics BEFORE measured statement(s) + commit; + + set plan on; + select count(*) cnt_1_2 + from tsml s + join tbig b on b.sid = s.id + join tmed m on b.mid = m.id + where s.sf = 0 -- selective non-indexed boolean + ; + set plan off; + + execute procedure sp_gather_stat; ------- catch statistics AFTER measured statement(s) + commit; + + -------------------- prepare-2 ------------------ + delete from tbig; + delete from tmed; + delete from tsml; + commit; + + --execute procedure sp_fill_data(27, 300, 3000); + execute procedure sp_fill_data(45, 300, 3000); + commit; + + set transaction read committed; + select + tab_name as run2_tab_name + ,idx_name as run2_idx_name + ,idx_stat_afte run2_idx_stat + from srv_recalc_idx_stat where tab_name in ( upper('tsml'), upper('tmed'), upper('tbig') ); + commit; + + --------------------- run-2.1 ------------------- + execute procedure sp_gather_stat; ------- catch statistics BEFORE measured statement(s) + commit; + + set plan on; + select count(*) cnt_2_1 + from tsml s + join tbig b on b.sid = s.id + join tmed m on b.mid = m.id + ; + set plan off; + + execute procedure sp_gather_stat; ------- catch statistics AFTER measured statement(s) + commit; + --------------------- run-2.2 ------------------- + + execute procedure sp_gather_stat; ------- catch statistics BEFORE measured statement(s) + commit; + set plan on; + select count(*) cnt_2_2 + from tsml s + join tbig b on b.sid = s.id + join tmed m on b.mid = m.id + where s.sf = 0 -- selective non-indexed boolean + ; + set plan off; + execute procedure sp_gather_stat; ------- catch statistics AFTER measured statement(s) + commit; + + + -- Here we define constants that serve as *upper* limit for fetches: + set term ^; + execute block as + begin + rdb$set_context('USER_SESSION','MAX_FETCHES_FOR_SLOW', 22000); + rdb$set_context('USER_SESSION','MAX_FETCHES_FOR_FAST', 11000); + end + ^ + set term ;^ + + -- Typical values for page_size 4K on 2.5 and 3.0: + -- FETCHES_1_1 19636 + -- FETCHES_1_2 9094 + -- FETCHES_2_1 19548 + -- FETCHES_2_2 19548 + + -- Show results: + -- ============= + select + iif( fetches_1_1 <= max_fetches_for_slow, 'acceptable', 'regression: '|| fetches_1_1 || ' > ' || max_fetches_for_slow) as fetches_1_1 + ,iif( fetches_1_2 <= max_fetches_for_fast, 'acceptable', 'regression: '|| fetches_1_2 || ' > ' || max_fetches_for_fast ) as fetches_1_2 + ,iif( fetches_2_1 <= max_fetches_for_slow, 'acceptable', 'regression: '|| fetches_2_1 || ' > ' || max_fetches_for_slow ) as fetches_2_1 + ,iif( fetches_2_2 <= max_fetches_for_slow, 'acceptable', 'regression: '|| fetches_2_2 || ' > ' || max_fetches_for_slow ) as fetches_2_2 + from ( + select + max( iif(rowset = 1, page_fetches, null) ) fetches_1_1 + ,max( iif(rowset = 2, page_fetches, null) ) fetches_1_2 + ,max( iif(rowset = 3, page_fetches, null) ) fetches_2_1 + ,max( iif(rowset = 4, page_fetches, null) ) fetches_2_2 + ,cast(rdb$get_context('USER_SESSION','MAX_FETCHES_FOR_SLOW') as int) as max_fetches_for_slow + ,cast(rdb$get_context('USER_SESSION','MAX_FETCHES_FOR_FAST') as int) as max_fetches_for_fast + from v_agg_stat + ) + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RUN1_TAB_NAME TBIG + RUN1_IDX_NAME TBIG_IDX1_FK_SML + RUN1_IDX_STAT 0.5000000000 + + RUN1_TAB_NAME TBIG + RUN1_IDX_NAME TBIG_IDX2_FK_MED + RUN1_IDX_STAT 0.0033333334 + + RUN1_TAB_NAME TMED + RUN1_IDX_NAME TMED_PK + RUN1_IDX_STAT 0.0033333334 + + RUN1_TAB_NAME TSML + RUN1_IDX_NAME TSML_PK + RUN1_IDX_STAT 0.0666666701 + + PLAN JOIN (M NATURAL, B INDEX (TBIG_IDX2_FK_MED), S INDEX (TSML_PK)) + CNT_1_1 3000 + + PLAN JOIN (S NATURAL, B INDEX (TBIG_IDX1_FK_SML), M INDEX (TMED_PK)) + CNT_1_2 1500 + + RUN2_TAB_NAME TBIG + RUN2_IDX_NAME TBIG_IDX1_FK_SML + RUN2_IDX_STAT 0.5000000000 + + RUN2_TAB_NAME TBIG + RUN2_IDX_NAME TBIG_IDX2_FK_MED + RUN2_IDX_STAT 0.0033333334 + + RUN2_TAB_NAME TMED + RUN2_IDX_NAME TMED_PK + RUN2_IDX_STAT 0.0033333334 + + RUN2_TAB_NAME TSML + RUN2_IDX_NAME TSML_PK + RUN2_IDX_STAT 0.0222222228 + + PLAN JOIN (M NATURAL, B INDEX (TBIG_IDX2_FK_MED), S INDEX (TSML_PK)) + CNT_2_1 3000 + + PLAN JOIN (M NATURAL, B INDEX (TBIG_IDX2_FK_MED), S INDEX (TSML_PK)) + CNT_2_2 1500 + + FETCHES_1_1 acceptable + FETCHES_1_2 acceptable + FETCHES_2_1 acceptable + FETCHES_2_2 acceptable + """ + +@pytest.mark.version('>=3.0') +def test_core_2078_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2081.py b/tests/bugs/test_core_2081.py new file mode 100644 index 00000000..6c1ff08a --- /dev/null +++ b/tests/bugs/test_core_2081.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: bugs.core_2081 +# title: RDB$DB_KEY in subselect expression incorrectly returns NULL +# decription: +# tracker_id: CORE-2081 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select a.rdb$db_key, (select b.rdb$db_key from rdb$database b) + from rdb$database a; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +DB_KEY DB_KEY +================ ================ +0100000001000000 0100000001000000 + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_2081_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2098.py b/tests/bugs/test_core_2098.py new file mode 100644 index 00000000..51aa2221 --- /dev/null +++ b/tests/bugs/test_core_2098.py @@ -0,0 +1,48 @@ +#coding:utf-8 +# +# id: bugs.core_2098 +# title: View over global temporary table +# decription: +# tracker_id: CORE-2098 +# min_versions: [] +# versions: 2.1.2 +# qmid: bugs.core_2098 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create global temporary table temptable ( + id integer); +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """recreate view tempview1 +as +select + a.id as id +from + temptable a; +commit; +recreate view tempview2 +as +select + a.id + 1 as id +from + temptable a; +commit; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1.2') +def test_core_2098_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_2101.py b/tests/bugs/test_core_2101.py new file mode 100644 index 00000000..bc51e469 --- /dev/null +++ b/tests/bugs/test_core_2101.py @@ -0,0 +1,62 @@ +#coding:utf-8 +# +# id: bugs.core_2101 +# title: Bugcheck 249 when attempting to fetch outside the end-of-stream mark for the open PSQL cursor +# decription: +# Confirmed on WI-V2.1.7.18553 Firebird 2.1: +# Statement failed, SQLSTATE = XX000 +# internal Firebird consistency check (pointer page vanished from DPM_next (249), file: dpm.cpp line: 1698) +# +# tracker_id: CORE-2101 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('SQLSTATE.*', 'SQLSTATE'), ('line: \\d+,', 'line: x'), ('col: \\d+', 'col: y')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table t1 ( f1 smallint ); + set term ^ ; + create procedure p1 + as + declare v1 smallint; + declare c1 cursor for ( select f1 from t1 ); + begin + open c1; + while (1=1) do + begin + fetch c1 into :v1; + if(row_count = 1) then leave; + end + close c1; + end ^ + set term ; ^ + commit; + + execute procedure p1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = HY109 + attempt to fetch past the last record in a record stream + -At procedure 'P1' line: 19, col: 18 + """ + +@pytest.mark.version('>=2.5') +def test_core_2101_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_2115.py b/tests/bugs/test_core_2115.py new file mode 100644 index 00000000..e7c3a10b --- /dev/null +++ b/tests/bugs/test_core_2115.py @@ -0,0 +1,192 @@ +#coding:utf-8 +# +# id: bugs.core_2115 +# title: Query plan is missing for the long query +# decription: +# tracker_id: CORE-2115 +# min_versions: [] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# import zipfile +# import filecmp +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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() +# os.fsync(file_handle.fileno()) +# +# file_handle.close() +# +# #-------------------------------------------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #------------------------------------------- +# +# zf = zipfile.ZipFile( os.path.join(context['files_location'],'core_2115.zip'), 'r' ) +# for name in zf.namelist(): +# zo=zf.open(name, 'rU') +# fn=open( os.path.join(context['temp_directory'],name), 'w') +# fn.write( zo.read().replace('\\r','') ) +# fn.close() +# +# ### do NOT: preserves Carriage Return character from Windows: zf.extractall( context['temp_directory'] ) +# zf.close() +# +# # Result: files +# # 1. tmp_core_2115_queries_with_long_plans.sql and +# # 2. tmp_core_2115_check_txt_of_long_plans.log +# # -- have been extracted into context['temp_directory'] +# # +# # These queries were created in AUTOMATED way using following batch scenario: +# # +# # @echo off +# # setlocal enabledelayedexpansion enableextensions +# # +# # set in_list_min_count=50 +# # set in_list_max_count=1500 +# # +# # @rem -Implementation limit exceeded +# # @rem -Too many values (more than 1500) in member list to match against +# # +# # set log=%~n0.log +# # set sql=%~n0.sql +# # del %sql% 2>nul +# # ( +# # echo -- GENERATED AUTO, DO NOT EDIT. +# # echo. +# # echo recreate table t234567890123456789012345678901( +# # echo f234567890123456789012345678901 smallint +# # echo unique using index x234567890123456789012345678901 +# # echo ^); +# # echo commit; +# # echo. +# # @rem echo set list on; select current_timestamp from rdb$database; +# # echo set planonly; +# # ) >> %sql% +# # +# # +# # for /l %%i in (%in_list_min_count%, 25, %in_list_max_count%) do ( +# # @echo Generating query with IN-list of %%i elements. +# # call :make_query %sql% %%i +# # ) +# # +# # @echo Done. +# # +# # goto end +# # +# # :make_query +# # +# # setlocal +# # set sql=%1 +# # set in_elems=%2 +# # set /a k=10000+%in_elems% +# # set suff=!k:~1,4! +# # +# # ( +# # echo. +# # echo -- Query with "IN"-list of %in_elems% elements: +# # echo select %in_elems% as c +# # echo from t234567890123456789012345678901 as +# # echo t__________________________!suff! +# # echo where f234567890123456789012345678901 in ( +# # ) >>%sql% +# # +# # set /a k=1 +# # set s= +# # for /l %%i in (1,1,%in_elems%) do ( +# # if .!s!.==.. ( +# # set s=0 +# # ) else ( +# # set s=!s!,0 +# # ) +# # set /a m=!k! %% 50 +# # +# # if !m! equ 0 ( +# # if .%%i.==.%in_elems%. ( echo !s!>>%sql% ) else ( echo !s!,>>%sql% ) +# # set s= +# # ) +# # set /a k=!k!+1 +# # ) +# # +# # +# # ( +# # if not .!s!.==.. echo !s! +# # echo ^); +# # ) >>%sql% +# # +# # endlocal & goto:eof +# # +# # :end +# +# sql_long_plans_qry=os.path.join(context['temp_directory'],'tmp_core_2115_queries_with_long_plans.sql') +# sql_long_plans_chk=os.path.join(context['temp_directory'],'tmp_core_2115_check_txt_of_long_plans.log') +# +# sql_long_plans_res=open( os.path.join(context['temp_directory'],'tmp_core_2115_current_txt_of_long_plans.log'), 'w') +# +# subprocess.call( [context["isql_path"], dsn, "-i", sql_long_plans_qry], stdout=sql_long_plans_res, stderr=subprocess.STDOUT ) +# flush_and_close( sql_long_plans_res ) +# +# if filecmp.cmp( sql_long_plans_chk, sql_long_plans_res.name): +# print("Current plans match to original ones.") +# else: +# print("Found at least one MISMATCH with original plans.") +# +# +# # cleanup +# ########## +# +# f_list = [ sql_long_plans_qry, sql_long_plans_chk, sql_long_plans_res.name ] +# cleanup( f_list ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Current plans match to original ones. + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_2115_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2117.py b/tests/bugs/test_core_2117.py new file mode 100644 index 00000000..9476662f --- /dev/null +++ b/tests/bugs/test_core_2117.py @@ -0,0 +1,89 @@ +#coding:utf-8 +# +# id: bugs.core_2117 +# title: Incorrect ROW_COUNT value with indexed retrieval and subquery +# decription: +# tracker_id: CORE-2117 +# min_versions: [] +# versions: 2.1.2 +# qmid: bugs.core_2117 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t (n integer); + +insert into t values (1); +insert into t values (2); +insert into t values (3); + +commit; + +create index t_n on t (n); +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """set term !!; + +execute block returns (n integer) +as + declare x integer; +begin + update t set n = n where n = -1; + n = row_count; + suspend; + + update t set n = n where n = (select -1 from rdb$database); + n = row_count; + suspend; + + update t set n = n where n = -1; + n = row_count; + suspend; + + for select 1 from t where n = -1 into x do + begin + end + n = row_count; + suspend; + + for select 1 from t where n = (select -1 from rdb$database) into x do + begin + end + n = row_count; + suspend; + + delete from t where n = (select -1 from rdb$database); + n = row_count; + suspend; +end!! + +set term ;!!""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + N +============ + 0 + 0 + 0 + 0 + 0 + 0 + +""" + +@pytest.mark.version('>=2.1.2') +def test_core_2117_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2118.py b/tests/bugs/test_core_2118.py new file mode 100644 index 00000000..0a49b77a --- /dev/null +++ b/tests/bugs/test_core_2118.py @@ -0,0 +1,72 @@ +#coding:utf-8 +# +# id: bugs.core_2118 +# title: UPDATE OR INSERT with subquery used in the MATCHING part doesn't insert record +# decription: +# 14.08.2020: +# removed usage of generator because gen_id() result differs in FB 4.x vs previous versions since fixed core-6084. +# Use hard-coded value for ID that is written into table MACRO.. +# Checked on: +# 4.0.0.2151 SS: 1.749s. +# 3.0.7.33348 SS: 0.897s. +# 2.5.9.27150 SC: 0.378s. +# +# tracker_id: CORE-2118 +# min_versions: [] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', ''), ('[ \t]+', ' ')] + +init_script_1 = """ + create table macro ( + id integer not null, + t1 integer, + code varchar(50) + ); + + create table param ( + id integer not null, + p1 integer + ); + + commit; + alter table macro add constraint pk_macro primary key (id); + alter table param add constraint pk_param primary key (id); + commit; + alter table macro add constraint fk_macro_1 foreign key (t1) references param (id); + commit; + + insert into param (id, p1) values (2, 11); + commit; + """ + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + update or insert into macro (id, t1, code) values ( 1, (select id from param where p1 = 11), 'fsdfdsf') matching (t1); + commit; + set list on; + select id, t1, code from macro; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + T1 2 + CODE fsdfdsf + """ + +@pytest.mark.version('>=3.0') +def test_core_2118_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2132.py b/tests/bugs/test_core_2132.py new file mode 100644 index 00000000..bd6446ec --- /dev/null +++ b/tests/bugs/test_core_2132.py @@ -0,0 +1,173 @@ +#coding:utf-8 +# +# id: bugs.core_2132 +# title: Indexed retrieval cannot be chosen if a stored procedure is used inside the comparison predicate +# decription: +# tracker_id: CORE-2132 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """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_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """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) ); + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +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 + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_2132_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2140.py b/tests/bugs/test_core_2140.py new file mode 100644 index 00000000..889419b0 --- /dev/null +++ b/tests/bugs/test_core_2140.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_2140 +# title: Error messages after parameters substitution contains ' +# ' characters instead of line break +# decription: +# tracker_id: CORE-2140 +# min_versions: ['2.5.6'] +# versions: 2.5.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.6 +# resources: None + +substitutions_1 = [('column.*', 'column x'), ('-At block line: [\\d]+, col: [\\d]+', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + 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 ^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + 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 + """ + +@pytest.mark.version('>=2.5.6') +def test_core_2140_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_2153.py b/tests/bugs/test_core_2153.py new file mode 100644 index 00000000..807f3439 --- /dev/null +++ b/tests/bugs/test_core_2153.py @@ -0,0 +1,48 @@ +#coding:utf-8 +# +# id: bugs.core_2153 +# title: SIMILAR TO predicate hangs with "|" option +# decription: +# tracker_id: CORE-2153 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select iif( 'avieieavav' similar to '%(av|ie){2,}%', 1, 0) r from rdb$database; + select iif( 'avieieieav' similar to '%((av)|(ie)){2,}%', 1, 0) r from rdb$database; + select iif( 'eiavieieav' similar to '%(av)|{2,}%', 1, 0) r from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + R 1 + R 1 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + Invalid SIMILAR TO pattern + """ + +@pytest.mark.version('>=2.5.0') +def test_core_2153_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2155.py b/tests/bugs/test_core_2155.py new file mode 100644 index 00000000..d31538cd --- /dev/null +++ b/tests/bugs/test_core_2155.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: bugs.core_2155 +# title: Join of SP with view or table may fail with "No current record for fetch operation" +# decription: +# tracker_id: CORE-2155 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + set term ^; + create or alter procedure sp_test(a_id int) returns (a_dup int) as + begin + a_dup = 2*a_id; + suspend; + end + ^ + set term ;^ + + create or alter view v_relations_a as + select rdb$relation_id, rdb$field_id + from rdb$relations; + + create or alter view v_relations_b as + select dummy_alias.rdb$relation_id, dummy_alias.rdb$field_id + from rdb$relations as dummy_alias; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set planonly; + + select v.rdb$relation_id, p.* + from v_relations_a v + INNER join sp_test(v.rdb$field_id) p on 1=1; + + select v.rdb$relation_id, p.* + from v_relations_b v + INNER join sp_test(v.rdb$field_id) p on 1=1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN JOIN (V RDB$RELATIONS NATURAL, P NATURAL) + PLAN JOIN (V DUMMY_ALIAS NATURAL, P NATURAL) + """ + +@pytest.mark.version('>=3.0') +def test_core_2155_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2164.py b/tests/bugs/test_core_2164.py new file mode 100644 index 00000000..916de095 --- /dev/null +++ b/tests/bugs/test_core_2164.py @@ -0,0 +1,162 @@ +#coding:utf-8 +# +# id: bugs.core_2164 +# title: error in operator "and" in as clausule where +# decription: +# tracker_id: CORE-2164 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create domain dcodempresa as integer; + create domain dcadena30 as varchar(30) default ''; + create domain dcod_anuncio as integer; + create domain dcodmedio as integer; + create domain dfecha as timestamp; + create domain dentero as integer; + create domain dimporte as numeric(10,2); + commit; + + create table empresas ( + cod_empresa dcodempresa not null, + nombre dcadena30, + provincia dcadena30, + constraint pk_empresas primary key (cod_empresa) + ); + + create table anuncios ( + cod_anuncio dcod_anuncio not null, + descripcion dcadena30, + cod_empresa dcodempresa not null, + constraint pk_anuncios primary key (cod_anuncio) + ); + + create table medios ( + cod_medio dcodmedio not null, + nombre dcadena30, + provincia dcadena30, + constraint pk_medios primary key (cod_medio) + ); + + create table emisiones ( + cod_anuncio dcod_anuncio not null, + fecha dfecha, + veces dentero, + importe dimporte, + cod_medio dcodmedio not null, + constraint pk_emisiones primary key (cod_anuncio,cod_medio) + ); + + + alter table anuncios add foreign key (cod_empresa) references empresas (cod_empresa) on update cascade on delete no action ; + alter table emisiones add foreign key (cod_anuncio) references anuncios (cod_anuncio) on update cascade on delete no action ; + alter table emisiones add foreign key (cod_medio) references medios (cod_medio) on update cascade on delete no action ; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + --------------------- data script -------------------------------------- + delete from emisiones; + delete from anuncios; + delete from empresas; + delete from medios; + commit; + + + insert into empresas (cod_empresa,nombre,provincia) + values (1,'puleva','granada'); + insert into empresas (cod_empresa,nombre,provincia) + values (2,'covap','cordoba'); + insert into empresas (cod_empresa,nombre,provincia) + values (3,'la vega','malaga'); + + insert into medios (cod_medio,nombre,provincia) + values (1,'diario sur','malaga'); + insert into medios (cod_medio,nombre,provincia) + values (2,'40 granada','granada'); + insert into medios (cod_medio,nombre,provincia) + values (3,'el pais','madrid'); + + + insert into anuncios (cod_anuncio,descripcion,cod_empresa) + values (1,'la mejor leche',1); + insert into anuncios (cod_anuncio,descripcion,cod_empresa) + values (2,'la dieta mediterranea ',1); + insert into anuncios (cod_anuncio,descripcion,cod_empresa) + values (3,'el valle de los pedroches',2); + + + insert into emisiones (cod_anuncio,fecha,veces,importe,cod_medio) + values (1,'10/01/2007',3,25,1); + insert into emisiones (cod_anuncio,fecha,veces,importe,cod_medio) + values (1,'10/11/2007',3,25,3); + insert into emisiones (cod_anuncio,fecha,veces,importe,cod_medio) + values (1,'10/01/2007',4,30,2); + insert into emisiones (cod_anuncio,fecha,veces,importe,cod_medio) + values (3,'11/01/2007',1,45,3); + commit; + + ----------------------------------------------------------------- + + set list on; + set count on; + select e.nombre,a.cod_anuncio + from empresas e + inner join anuncios a on (a.cod_empresa=e.cod_empresa) + where a.cod_anuncio not in + (select em.cod_anuncio + from emisiones em + inner join medios m on (m.cod_medio=em.cod_medio) + where m.provincia<>e.provincia + ); + + --This statement don't return any rows + -- + --If append other subselect, it returns one row ?why? + --The second statement is + + select e.nombre,a.cod_anuncio + from empresas e + inner join anuncios a on (a.cod_empresa=e.cod_empresa) + where a.cod_anuncio not in + (select em.cod_anuncio + from emisiones em + inner join medios m on (m.cod_medio=em.cod_medio) + where m.provincia<>e.provincia + ) + and ------ fails + a.cod_anuncio in + (select em1.cod_anuncio + from emisiones em1 + inner join medios m1 on (m1.cod_medio=em1.cod_medio) + where m1.provincia=e.provincia + ); + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + NOMBRE puleva + COD_ANUNCIO 2 + Records affected: 1 + Records affected: 0 + """ + +@pytest.mark.version('>=2.5') +def test_core_2164_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2176.py b/tests/bugs/test_core_2176.py new file mode 100644 index 00000000..366984fd --- /dev/null +++ b/tests/bugs/test_core_2176.py @@ -0,0 +1,327 @@ +#coding:utf-8 +# +# id: bugs.core_2176 +# title: Unexpected (wrong) results with COALESCE and GROUP BY +# decription: +# tracker_id: CORE-2176 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter view v_rel (rid, rnm, rty) as + select r.rdb$relation_id, r.rdb$relation_name, r.rdb$relation_type + from rdb$relations r + where r.rdb$relation_id <= 30 -- ::: NB ::: added this cond because number of rows in 2.5 and 3.0 differ! + ; + commit; + + set count on ; + set list on; + + select rid as c from v_rel + group by 1 ; + -- correct result + + select * from ( + select rid as c from v_rel + ) group by 1 ; + -- also correct + + select coalesce(rid, 0) as c from v_rel + group by 1 ; + -- ERROR: no zero ID is reported, the last ID is reported twice + + select * from ( + select coalesce(rid, 0) as c from v_rel + ) group by 1 ; + -- ERROR: single NULL is returned + + select * from ( + select coalesce(rid, 0) as a, coalesce(rty, 0) as b from v_rel + ) group by 1, 2 ; + -- ERROR: infinite result set with all zero values + + select * from ( + select coalesce(rid, 0) as a, coalesce(rnm, '') as b from v_rel + ) group by 1, 2 ; + -- ERROR: conversion error + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + C 0 + C 1 + C 2 + C 3 + C 4 + C 5 + C 6 + C 7 + C 8 + C 9 + C 10 + C 11 + C 12 + C 13 + C 14 + C 15 + C 16 + C 17 + C 18 + C 19 + C 20 + C 21 + C 22 + C 23 + C 24 + C 25 + C 26 + C 27 + C 28 + C 29 + C 30 + Records affected: 31 + C 0 + C 1 + C 2 + C 3 + C 4 + C 5 + C 6 + C 7 + C 8 + C 9 + C 10 + C 11 + C 12 + C 13 + C 14 + C 15 + C 16 + C 17 + C 18 + C 19 + C 20 + C 21 + C 22 + C 23 + C 24 + C 25 + C 26 + C 27 + C 28 + C 29 + C 30 + Records affected: 31 + C 0 + C 1 + C 2 + C 3 + C 4 + C 5 + C 6 + C 7 + C 8 + C 9 + C 10 + C 11 + C 12 + C 13 + C 14 + C 15 + C 16 + C 17 + C 18 + C 19 + C 20 + C 21 + C 22 + C 23 + C 24 + C 25 + C 26 + C 27 + C 28 + C 29 + C 30 + Records affected: 31 + C 0 + C 1 + C 2 + C 3 + C 4 + C 5 + C 6 + C 7 + C 8 + C 9 + C 10 + C 11 + C 12 + C 13 + C 14 + C 15 + C 16 + C 17 + C 18 + C 19 + C 20 + C 21 + C 22 + C 23 + C 24 + C 25 + C 26 + C 27 + C 28 + C 29 + C 30 + Records affected: 31 + A 0 + B 0 + A 1 + B 0 + A 2 + B 0 + A 3 + B 0 + A 4 + B 0 + A 5 + B 0 + A 6 + B 0 + A 7 + B 0 + A 8 + B 0 + A 9 + B 0 + A 10 + B 0 + A 11 + B 0 + A 12 + B 0 + A 13 + B 0 + A 14 + B 0 + A 15 + B 0 + A 16 + B 0 + A 17 + B 0 + A 18 + B 0 + A 19 + B 0 + A 20 + B 0 + A 21 + B 0 + A 22 + B 0 + A 23 + B 0 + A 24 + B 0 + A 25 + B 0 + A 26 + B 0 + A 27 + B 0 + A 28 + B 0 + A 29 + B 0 + A 30 + B 0 + Records affected: 31 + A 0 + B RDB$PAGES + A 1 + B RDB$DATABASE + A 2 + B RDB$FIELDS + A 3 + B RDB$INDEX_SEGMENTS + A 4 + B RDB$INDICES + A 5 + B RDB$RELATION_FIELDS + A 6 + B RDB$RELATIONS + A 7 + B RDB$VIEW_RELATIONS + A 8 + B RDB$FORMATS + A 9 + B RDB$SECURITY_CLASSES + A 10 + B RDB$FILES + A 11 + B RDB$TYPES + A 12 + B RDB$TRIGGERS + A 13 + B RDB$DEPENDENCIES + A 14 + B RDB$FUNCTIONS + A 15 + B RDB$FUNCTION_ARGUMENTS + A 16 + B RDB$FILTERS + A 17 + B RDB$TRIGGER_MESSAGES + A 18 + B RDB$USER_PRIVILEGES + A 19 + B RDB$TRANSACTIONS + A 20 + B RDB$GENERATORS + A 21 + B RDB$FIELD_DIMENSIONS + A 22 + B RDB$RELATION_CONSTRAINTS + A 23 + B RDB$REF_CONSTRAINTS + A 24 + B RDB$CHECK_CONSTRAINTS + A 25 + B RDB$LOG_FILES + A 26 + B RDB$PROCEDURES + A 27 + B RDB$PROCEDURE_PARAMETERS + A 28 + B RDB$CHARACTER_SETS + A 29 + B RDB$COLLATIONS + A 30 + B RDB$EXCEPTIONS + Records affected: 31 + """ + +@pytest.mark.version('>=2.5.0') +def test_core_2176_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2192.py b/tests/bugs/test_core_2192.py new file mode 100644 index 00000000..6e448d94 --- /dev/null +++ b/tests/bugs/test_core_2192.py @@ -0,0 +1,395 @@ +#coding:utf-8 +# +# id: bugs.core_2192 +# title: Extend maximum database page size to 32KB +# decription: +# We create DB with page_size = 32784, then add two table int it, both with UTF8 fields. +# First table (test_non_coll) has field which is based on trivial text domain. +# Second table (test_collated) has two 'domained' fields and both underlying domains are +# based on two collations: case_insensitive and case_insensitive + accent_insensitive. +# NOTE: we use MAXIMAL POSSIBLE length of every text field. +# Then we add to both tables some text data in order to check then correctness of queries +# which use several kinds of search (namely: starting with, like and between). +# Then we make validation, backup, restore and run again DML query and validation. +# Also, we do extraction of metadata before backup and after restore. +# Finally, we: +# 1) check that all error logs are empty; +# 2) compare logs of DML, metadata extraction - they should be identical. +# +# Checked on 4.0.0.172, intermediate build based on sources of 10-may-2015 10:44 - works fine. +# +# tracker_id: CORE-2192 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# import difflib +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# #-------------------------------------------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #------------------------------------------- +# +# db_conn.close() +# +# tmpfdb1=os.path.join(context['temp_directory'],'tmp_2192_32k.fdb') +# if os.path.isfile(tmpfdb1): +# os.remove(tmpfdb1) +# +# tmpfbk1=os.path.join(context['temp_directory'],'tmp_2192_32k.fbk') +# if os.path.isfile(tmpfbk1): +# os.remove(tmpfbk1) +# +# +# test_size = 32768 # -- Ran 1 tests in 4.504s +# # test_size = 16384 # -- Ran 1 tests in 2.735s +# +# max_indx1 = test_size / 4 - 9 +# max_indx6 = max_indx1 / 6 +# max_indx8 = max_indx1 / 8 +# +# +# sql_ddl=''' set list on; +# set bail on; +# set echo on; +# create database 'localhost:%(tmpfdb1)s' page_size %(test_size)s; +# select mon$page_size as page_size from mon$database; +# commit; +# create sequence g; +# commit; +# create collation utf8_ci for utf8 from unicode case insensitive; +# create collation utf8_ai_ci for utf8 from unicode accent insensitive case insensitive ; +# commit; +# create domain dm_non_coll as varchar( %(max_indx1)s ); +# create domain dm_collated_ci as varchar( %(max_indx6)s ) character set utf8 collate utf8_ci; +# create domain dm_collated_ai_ci as varchar( %(max_indx6)s ) character set utf8 collate utf8_ai_ci; +# commit; +# recreate table test_non_coll( +# txt_non_coll dm_non_coll +# ); +# recreate table test_collated( +# txt_ci dm_collated_ci +# ,txt_ai_ci dm_collated_ai_ci +# ); +# commit; +# create index test_non_coll on test_non_coll(txt_non_coll); +# create index test_coll_ci on test_collated(txt_ci); +# create index test_coll_ai_ci on test_collated(txt_ai_ci); +# commit; +# ''' % locals() +# +# dml_test = ''' --show version; +# delete from test_non_coll; +# delete from test_collated; +# commit; +# set count on; +# insert into test_non_coll(txt_non_coll) +# select +# rpad('', %(max_indx1)s, 'QWERTY' || gen_id(g,1) ) +# from +# -- rdb$types rows 10000 +# (select 1 i from rdb$types rows 200), (select 1 i from rdb$types rows 5) +# rows 361 +# ; +# commit; +# +# insert into test_collated(txt_ci, txt_ai_ci) +# select +# rpad('', %(max_indx6)s, 'Ещё Съешь Этих Мягких Французских Булочек Да Выпей Же Чаю') +# ,rpad('', %(max_indx6)s, 'Ещё Французских Булочек Этих Мягких Съешь Да Чаю Выпей Же') +# from +# (select 1 i from rdb$types rows 250), (select 1 i from rdb$types rows 2) +# ; +# +# commit; +# +# set count off; +# set list on; +# set plan on; +# +# select count(*) +# from test_non_coll +# where txt_non_coll starting with 'QWERTY' +# +# union all +# +# select count(*) +# from test_collated +# where txt_ci starting with 'еЩё' +# +# union all +# +# select count(*) +# from test_collated +# where txt_ai_ci starting with 'ёЩЕ' +# +# union all +# +# select count(*) +# from test_collated +# where txt_ci = lower(rpad('', %(max_indx6)s, 'Ещё Съешь Этих Мягких Французских Булочек Да Выпей Же Чаю')) +# +# union all +# +# select count(*) +# from test_collated +# where txt_ai_ci = rpad('', %(max_indx6)s, 'Ещё Французских Булочек Этих Мягких Съешь Да Чаю Выпей Же') +# ; +# +# select count(*) +# from test_non_coll +# where txt_non_coll like 'QWERTY%%' +# +# union all +# +# select count(*) +# from test_collated +# where txt_ci like 'еЩё%%' +# +# union all +# +# select count(*) +# from test_collated +# where txt_ai_ci like 'ёЩЕ%%' +# +# union all +# +# select count(*) +# from test_collated +# where txt_ci between +# rpad('', %(max_indx6)s, 'ещё Съешь ЭТИХ Мягких Французских Булочек Да Выпей Же Чаю') +# and +# rpad('', %(max_indx6)s, 'ЕЩЁ Съешь Этих МЯГКИХ фРанцузских Булочек Да Выпей Же Чаю') +# +# union all +# +# select count(*) +# from test_collated +# where txt_ai_ci between +# rpad('', %(max_indx6)s, 'ёще фРанцузских Булочек Этих Мягких Съешь Да Чаю Выпёй Же') +# and +# rpad('', %(max_indx6)s, 'ёщё Французских Булочёк Этих Мягких Съёшь Да Чаю Выпёй Жё') +# ; +# +# set plan off; +# ''' % locals() +# +# f_create_db_32k_sql = open( os.path.join(context['temp_directory'],'tmp_2192_ddl.sql'), 'w') +# f_create_db_32k_sql.write(sql_ddl) +# f_create_db_32k_sql.close() +# +# # 0. CREATE DATABASE +# #################### +# +# f_create_db_32k_log = open( os.path.join(context['temp_directory'],'tmp_2192_ddl.log'), 'w') +# f_create_db_32k_err = open( os.path.join(context['temp_directory'],'tmp_2192_ddl.err'), 'w') +# subprocess.call( [ context['isql_path'], "-q", "-i", f_create_db_32k_sql.name, "-ch", "utf8" ] +# ,stdout = f_create_db_32k_log +# ,stderr = f_create_db_32k_err +# ) +# f_create_db_32k_log.close() +# f_create_db_32k_err.close() +# +# # CHANGE FW to OFF +# ################## +# f_change_fw = open(os.devnull, 'w') +# subprocess.call( [ context['fbsvcmgr_path'], "localhost:service_mgr", "action_properties", "dbname", tmpfdb1, "prp_write_mode", "prp_wm_async" ], stdout = f_change_fw,stderr = subprocess.STDOUT ) +# f_change_fw.close() +# +# # 1. FIRST RUN DML_TEST +# ####################### +# +# f_run_dml_sql = open( os.path.join(context['temp_directory'],'tmp_2192_dml.sql'), 'w') +# f_run_dml_sql.write(dml_test) +# f_run_dml_sql.close() +# +# f_run_dml_log_1 = open( os.path.join(context['temp_directory'],'tmp_2192_dml_1.log'), 'w') +# subprocess.call( [ context['isql_path'], 'localhost:'+tmpfdb1, "-i", f_run_dml_sql.name, "-ch", "utf8" ] +# ,stdout = f_run_dml_log_1 +# ,stderr = subprocess.STDOUT +# ) +# f_run_dml_log_1.close() +# +# # 2. EXTRACT METADATA-1 +# ####################### +# +# f_extract_meta1_sql = open( os.path.join(context['temp_directory'],'tmp_2192_meta1.log'), 'w') +# subprocess.call( [ context['isql_path'], 'localhost:'+tmpfdb1, "-x" ] +# ,stdout = f_extract_meta1_sql +# ,stderr = subprocess.STDOUT +# ) +# f_extract_meta1_sql.close() +# +# # 3. VALIDATE DATABASE-1 +# ######################## +# f_validate_log_1=open( os.path.join(context['temp_directory'],'tmp_2192_validate1.log'), "w") +# f_validate_err_1=open( os.path.join(context['temp_directory'],'tmp_2192_validate1.err'), "w") +# +# subprocess.call( [ context['fbsvcmgr_path'],"localhost:service_mgr","action_validate","dbname", tmpfdb1 ],stdout=f_validate_log_1,stderr=f_validate_err_1 ) +# +# f_validate_log_1.close() +# f_validate_err_1.close() +# +# +# # 4. TRY TO BACKUP AND RESTORE +# ############################## +# +# f_backup_log=open( os.path.join(context['temp_directory'],'tmp_2192_backup.log'), "w") +# f_backup_err=open( os.path.join(context['temp_directory'],'tmp_2192_backup.err'), "w") +# +# subprocess.call( [ context['fbsvcmgr_path'],"localhost:service_mgr","action_backup", "verbose","dbname", tmpfdb1, "bkp_file", tmpfbk1],stdout=f_backup_log,stderr=f_backup_err) +# +# f_backup_log.close() +# f_backup_err.close() +# +# f_restore_log=open( os.path.join(context['temp_directory'],'tmp_2192_restore.log'), "w") +# f_restore_err=open( os.path.join(context['temp_directory'],'tmp_2192_restore.err'), "w") +# subprocess.call( [ context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_restore", "res_replace", "verbose", +# "bkp_file", tmpfbk1, +# "dbname", tmpfdb1 +# ] +# ,stdout=f_restore_log +# ,stderr=f_restore_err +# ) +# f_restore_log.close() +# f_restore_err.close() +# +# # 5. EXTRACT METADATA-2 +# ####################### +# +# f_extract_meta2_sql = open( os.path.join(context['temp_directory'],'tmp_2192_meta2.log'), 'w') +# subprocess.call( [ context['isql_path'], 'localhost:'+tmpfdb1, "-x"],stdout = f_extract_meta2_sql,stderr = subprocess.STDOUT) +# f_extract_meta2_sql.close() +# +# # 6. AGAIN RUN DML_TEST +# ####################### +# +# f_run_dml_log_2 = open( os.path.join(context['temp_directory'],'tmp_2192_dml_2.log'), 'w') +# subprocess.call( [ context['isql_path'], 'localhost:'+tmpfdb1, "-i", f_run_dml_sql.name, "-ch", "utf8" ],stdout = f_run_dml_log_2,stderr = subprocess.STDOUT ) +# f_run_dml_log_2.close() +# +# # 7. VALIDATE DATABASE-2 +# ######################## +# f_validate_log_2=open( os.path.join(context['temp_directory'],'tmp_2192_validate2.log'), "w") +# f_validate_err_2=open( os.path.join(context['temp_directory'],'tmp_2192_validate2.err'), "w") +# +# subprocess.call( [ context['fbsvcmgr_path'],"localhost:service_mgr","action_validate","dbname", tmpfdb1],stdout=f_validate_log_2,stderr=f_validate_err_2) +# +# f_validate_log_2.close() +# f_validate_err_2.close() +# +# +# # 7. CHECKS +# ########### +# # 1) STDERR for: create DB, backup, restore, validation-1 and validation-2 - they all must be EMPTY. +# f_list=[] +# f_list.append(f_create_db_32k_err) +# f_list.append(f_validate_err_1) +# f_list.append(f_backup_err) +# f_list.append(f_restore_err) +# f_list.append(f_validate_err_2) +# +# for i in range(len(f_list)): +# f_name=f_list[i].name +# if os.path.getsize(f_name) > 0: +# with open( f_name,'r') as f: +# for line in f: +# print("Unexpected STDERR, file "+f_name+": "+line) +# +# # 2) diff between dml_1.log and dml_2.log should be EMPTY. +# # 3) diff between meta1.log and meta2.log should be EMPTY. +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_2192_diff.txt'), 'w') +# f_old=[] +# f_new=[] +# +# f_old.append(f_extract_meta1_sql) # DDL: what we have BEFORE database backup +# f_old.append(f_run_dml_log_1) # DML: result of querying tables before DB backup +# f_new.append(f_extract_meta2_sql) # DDL: what we have AFTER database restore +# f_new.append(f_run_dml_log_2) # DML: result of querying tables AFTER database restore +# +# for i in range(len(f_old)): +# old_file=open(f_old[i].name,'r') +# new_file=open(f_new[i].name,'r') +# +# f_diff_txt.write( ''.join( difflib.unified_diff( old_file.readlines(), new_file.readlines() ) ) ) +# +# old_file.close() +# new_file.close() +# +# f_diff_txt.close() +# +# # Should be EMPTY: +# ################## +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# print( 'Unexpected diff: '.join(line.split()).upper() ) +# +# ##################################################################### +# # Cleanup: +# ########## +# time.sleep(1) +# +# f_list= ( +# f_create_db_32k_sql +# ,f_create_db_32k_log +# ,f_create_db_32k_err +# ,f_validate_log_1 +# ,f_validate_err_1 +# ,f_validate_log_2 +# ,f_validate_err_2 +# ,f_backup_log +# ,f_backup_err +# ,f_restore_log +# ,f_restore_err +# ,f_extract_meta1_sql +# ,f_extract_meta2_sql +# ,f_run_dml_sql +# ,f_run_dml_log_1 +# ,f_run_dml_log_2 +# ,f_diff_txt +# ) +# cleanup( [i.name for i in f_list] ) +# +# os.remove(tmpfdb1) +# os.remove(tmpfbk1) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_2192_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2197.py b/tests/bugs/test_core_2197.py new file mode 100644 index 00000000..80042ab7 --- /dev/null +++ b/tests/bugs/test_core_2197.py @@ -0,0 +1,139 @@ +#coding:utf-8 +# +# id: bugs.core_2197 +# title: Add support for -nodbtriggers switch in gbak into services API +# decription: +# We add two database triggers (on connect and on disconnect) and make them do real work only when +# new attachment will be established (see trick with rdb$get_context('USER_SESSION', 'INIT_STATE') ). +# After finish backup we restore database and check that there is no records in 'log' table. +# (if option 'bkp_no_triggers' will be omitted then two records will be in that table). +# Checked on: +# 2.5.9.27103: OK, 0.938s. +# 3.0.4.32920: OK, 2.875s. +# 4.0.0.912: OK, 3.328s. +# +# tracker_id: CORE-2197 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table log( att bigint default current_connection, event_name varchar(20) ); + create sequence g; + set term ^; + create or alter trigger trg_attach inactive on connect as + begin + if ( rdb$get_context('USER_SESSION', 'INIT_STATE') is null ) then + insert into log(event_name) values ('attach'); + end + ^ + create or alter trigger trg_detach inactive on disconnect as + begin + if ( rdb$get_context('USER_SESSION', 'INIT_STATE') is null ) then + insert into log(event_name) values ('detach'); + end + ^ + set term ^; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# from subprocess import Popen +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# thisdb='$(DATABASE_LOCATION)bugs.core_2197.fdb' +# tmpbkp='$(DATABASE_LOCATION)bugs.core_2197_fbk.tmp' +# tmpres='$(DATABASE_LOCATION)bugs.core_2197_new.tmp' +# +# +# #--------------------------------------------------------------- +# +# isql_txt=''' delete from log; +# commit; +# set term ^; +# execute block as begin +# rdb$set_context('USER_SESSION', 'INIT_STATE','1'); +# end +# ^ +# set term ;^ +# alter trigger trg_attach active; +# alter trigger trg_detach active; +# commit; +# --set count on; +# --select * from log; +# ''' +# +# runProgram('isql',[dsn], isql_txt) +# +# f_svc_log=open( os.path.join(context['temp_directory'],'tmp_svc_2197.log'), 'w') +# f_svc_err=open( os.path.join(context['temp_directory'],'tmp_svc_2197.err'), 'w') +# +# subprocess.call( [ context['fbsvcmgr_path'], 'localhost:service_mgr','action_backup', +# 'dbname', thisdb, 'bkp_file', tmpbkp, +# 'bkp_no_triggers' +# ], +# stdout=f_svc_log,stderr=f_svc_err +# ) +# +# runProgram('isql',[dsn, '-nod'], 'set list on; set count on; select 1, g.* from log g;') +# +# subprocess.call( [ context['fbsvcmgr_path'], 'localhost:service_mgr','action_restore', +# 'bkp_file', tmpbkp, 'dbname', tmpres, +# 'res_replace' +# ], +# stdout=f_svc_log,stderr=f_svc_err +# ) +# +# f_svc_log.close() +# f_svc_err.close() +# +# runProgram('isql',[dsn, '-nod'], 'set list on; set count on; select 1, g.* from log g;') +# +# +# ############################################# +# # Cleanup. +# f_list=( +# f_svc_log +# ,f_svc_err +# ) +# +# for i in range(len(f_list)): +# if os.path.isfile(f_list[i].name): +# os.remove(f_list[i].name) +# +# os.remove(tmpbkp) +# os.remove(tmpres) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + Records affected: 0 + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_2197_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2200.py b/tests/bugs/test_core_2200.py new file mode 100644 index 00000000..53f3a11b --- /dev/null +++ b/tests/bugs/test_core_2200.py @@ -0,0 +1,80 @@ +#coding:utf-8 +# +# id: bugs.core_2200 +# title: Extremely slow executing a cross join of 3 tables in Firebird 2.X +# decription: +# tracker_id: CORE-2200 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- 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); + recreate table t1(id int); + recreate table t2(id int); + recreate table t3(id int); + 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 ----------- + 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; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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 + + select count(*) from t3, t2, t1; + PLAN JOIN (T3 NATURAL, T2 NATURAL, T1 NATURAL) + COUNT 0 + """ + +@pytest.mark.version('>=2.5') +def test_core_2200_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2202.py b/tests/bugs/test_core_2202.py new file mode 100644 index 00000000..acec95ec --- /dev/null +++ b/tests/bugs/test_core_2202.py @@ -0,0 +1,67 @@ +#coding:utf-8 +# +# id: bugs.core_2202 +# title: RDB$VIEW_RELATIONS is not cleaned when altering a view +# decription: +# tracker_id: CORE-2202 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table table_1 (id integer); + recreate table table_2 (id integer); + recreate table table_3 (id integer); + + create or alter view vw_table(id) as + select id from table_1; + commit; + + create or alter view vw_table(id) as + select id from table_2; + commit; + + create or alter view vw_table(id) as + select id + from table_3; + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set width vew_name 31; + set width rel_name 31; + set width ctx_name 31; + select + rdb$view_name as vew_name + ,rdb$relation_name as rel_name + ,rdb$view_context + ,rdb$context_name as ctx_name + from rdb$view_relations rv; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + VEW_NAME VW_TABLE + REL_NAME TABLE_3 + RDB$VIEW_CONTEXT 1 + CTX_NAME TABLE_3 + """ + +@pytest.mark.version('>=2.5.0') +def test_core_2202_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2204.py b/tests/bugs/test_core_2204.py new file mode 100644 index 00000000..c464cba1 --- /dev/null +++ b/tests/bugs/test_core_2204.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: bugs.core_2204 +# title: constraints on sp output parameters are checked even when the sp returns zero rows +# decription: +# tracker_id: CORE-2204 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create domain dm_boo as integer not null check (value = 0 or value = 1); + set term ^; + create procedure test returns (b dm_boo) as + begin + if (1 = 0) then + suspend; + end + ^ + set term ;^ + commit; + set count on; + select * from test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ + +@pytest.mark.version('>=3.0') +def test_core_2204_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2208.py b/tests/bugs/test_core_2208.py new file mode 100644 index 00000000..e4a22b74 --- /dev/null +++ b/tests/bugs/test_core_2208.py @@ -0,0 +1,272 @@ +#coding:utf-8 +# +# id: bugs.core_2208 +# title: New gbak option to ignore specific tables data during the backup +# decription: +# We create four tables with ascii and one with non-ascii (cyrillic) names. +# Each table has one row. +# Then we check that one may to: +# 1) skip BACKUP data of some tables +# 2) skip RESTORE data for same tables. +# All cases are checked by call 'fbsvcmgr ... bkp_skip_data ', +# where string matches several tables (i.e. we use SIMILAR_TO ability). +# +# WARNING! +# It was found that there is NO ability (in fbtest only! not in command interpreter) +# to skip data from backup for table with non-ascii name, neither if we specify its name +# as literal nor via pattern. For that reason one of checks currently is commented +# (see below block titled as: `Run-3: try to skip BACKUP of data for table "опечатка"`). +# +# Checked on WI-V3.0.2.32644, WI-T4.0.0.469. +# +# tracker_id: CORE-2208 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table test_01(id char(1)); + recreate table test_02(id char(1)); + recreate table test_0a(id char(1)); + recreate table test_0b(id char(1)); + + recreate table "опечатка"(id char(1)); + commit; + + insert into test_01(id) values('1'); + insert into test_02(id) values('2'); + insert into test_0a(id) values('3'); + insert into test_0b(id) values('4'); + insert into "опечатка"(id) values('ы'); + commit; + -- similar to '(о|а)(п|ч)(е|и)(п|ч)(а|я)(т|д)(к|г)(а|о)'; + recreate view v_check as + select 'test_01' as msg, t.id + from rdb$database left join test_01 t on 1=1 + union all + select 'test_02' as msg, t.id + from rdb$database left join test_02 t on 1=1 + union all + select 'test_0a' as msg, t.id + from rdb$database left join test_0a t on 1=1 + union all + select 'test_0b' as msg, t.id + from rdb$database left join test_0b t on 1=1 + union all + select 'опечатка' as msg, t.id + from rdb$database left join "опечатка" t on 1=1 + ; + """ + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import time +# from subprocess import Popen +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # Obtain engine version: +# engine = str(db_conn.engine_version) # convert to text because 'float' object has no attribute 'startswith' +# +# db_conn.close() +# +# thisdb='$(DATABASE_LOCATION)bugs.core_2208.fdb' +# tmpbkp='$(DATABASE_LOCATION)bugs.core_2208_fbk.tmp' +# tmpres='$(DATABASE_LOCATION)bugs.core_2208_new.tmp' +# +# f_run_sql=open( os.path.join(context['temp_directory'],'tmp_check_2208.sql'), 'w') +# f_run_sql.write('set list on; set count on; select * from v_check;') +# f_run_sql.close() +# +# f_svc_log=open( os.path.join(context['temp_directory'],'tmp_svc_2208.log'), 'w') +# f_svc_err=open( os.path.join(context['temp_directory'],'tmp_svc_2208.err'), 'w') +# +# # Run-1: try to skip BACKUP of data for tables 'test_0a' and 'test_0b'. +# ########################### +# subprocess.call( [ context['fbsvcmgr_path'], 'localhost:service_mgr','action_backup', +# 'dbname', thisdb, 'bkp_file', tmpbkp, +# 'bkp_skip_data', 'test_0[[:alpha:]]' +# ], +# stdout=f_svc_log,stderr=f_svc_err +# ) +# subprocess.call( [ context['fbsvcmgr_path'], 'localhost:service_mgr','action_restore', +# 'bkp_file', tmpbkp, 'dbname', tmpres, +# 'res_replace' +# ], +# stdout=f_svc_log,stderr=f_svc_err +# ) +# +# +# f_run1_log=open( os.path.join(context['temp_directory'],'tmp_run1_2208.log'), 'w') +# subprocess.call( [ context['isql_path'], 'localhost:'+tmpres,'-q','-ch','utf8', '-i', f_run_sql.name],stdout=f_run1_log,stderr=subprocess.STDOUT ) +# f_run1_log.close() +# +# +# # Run-2: try to skip RESTORE of data for tables 'test_01' and 'test_02'. +# ########################### +# subprocess.call( [ context['fbsvcmgr_path'], 'localhost:service_mgr','action_backup', +# 'dbname', thisdb, 'bkp_file', tmpbkp, +# 'bkp_skip_data', 'test_0[[:digit:]]' +# ], +# stdout=f_svc_log,stderr=f_svc_err +# ) +# subprocess.call( [ context['fbsvcmgr_path'], 'localhost:service_mgr','action_restore', +# 'bkp_file', tmpbkp, 'dbname', tmpres, +# 'res_replace' +# ], +# stdout=f_svc_log,stderr=f_svc_err +# ) +# +# f_run2_log=open( os.path.join(context['temp_directory'],'tmp_run2_2208.log'), 'w') +# subprocess.call( [ context['isql_path'], 'localhost:'+tmpres,'-q','-ch','utf8', '-i', f_run_sql.name],stdout=f_run2_log,stderr=subprocess.STDOUT ) +# f_run2_log.close() +# +# ######################################## +# +# ''' +# DEFERRED! IT SEEMS THAT WRONG PATTERN IS PASSED FROM FBTEST TO FBSVCMGR WHEN USE NON-ASCII TABLE NAME! +# +# CAN NOT BE REPRODUCED IN CMD.EXE (chcp 65001): +# ============================================== +# +# Script for isql (do not forget to make chcp 65001 before run it): +# === +# set names utf8; +# shell del C:\\MIX +# irebird\\QA +# bt-repo mp\\c2208w.fdb 2>nul; +# create database 'localhost:C:\\MIX +# irebird\\QA +# bt-repo mp\\c2208w.fdb' default character set utf8; +# recreate table "опечатка"(id char(1)); +# insert into "опечатка"(id) values('ы'); +# commit; +# === +# +# fbsvcmgr localhost:service_mgr action_backup +# dbname C:\\MIX +# irebird\\QA +# bt-repo mp\\C2208W.FDB +# bkp_file C:\\MIX +# irebird\\QA +# bt-repo mp\\C2208W.fbk +# -bkp_skip_data "(о|а)(п|ч)(е|и)(п|ч)(а|я)(т|д)(к|г)(о|а)" +# +# gbak -rep C:\\MIX +# irebird\\QA +# bt-repo mp\\C2208W.fbk localhost:C:\\MIX +# irebird\\QA +# bt-repo mp\\C2208W2.FDB +# +# echo show table; set list on; set count on; select * from "опечатка";|isql /:C:\\MIX +# irebird\\QA +# bt-repo mp\\C2208W2.FDB -ch utf8 +# +# опечатка +# Records affected: 0 +# +# # Run-3: try to skip BACKUP of data for table "опечатка". +# ########################### +# # 'bkp_skip_data', '"(о|а)(п|ч)(е|и)(п|ч)(а|я)(т|д)(к|г)(а|о)"' +# subprocess.call( [ context['fbsvcmgr_path'], 'localhost:service_mgr','action_backup', +# 'dbname', thisdb, 'bkp_file', tmpbkp, +# 'bkp_skip_data', '%о%' +# ], +# stdout=f_svc_log,stderr=f_svc_err +# ) +# subprocess.call( [ context['fbsvcmgr_path'], 'localhost:service_mgr','action_restore', +# 'bkp_file', tmpbkp, 'dbname', tmpres, +# 'res_replace' +# ], +# stdout=f_svc_log,stderr=f_svc_err +# ) +# +# f_run3_log=open( os.path.join(context['temp_directory'],'tmp_run3_2208.log'), 'w') +# subprocess.call( [ context['isql_path'], 'localhost:'+tmpres,'-q','-ch','utf8', '-i', f_run_sql.name],stdout=f_run3_log,stderr=subprocess.STDOUT ) +# f_run3_log.close() +# ''' +# +# f_svc_log.close() +# f_svc_err.close() +# +# # Should be EMPTY: +# with open( f_svc_err.name,'r') as f: +# for line in f: +# if line.split(): +# print('fbsvcmgr(2) unexpected STDERR: '+line.upper() ) +# f.close() +# +# +# with open( f_run1_log.name,'r') as f: +# for line in f: +# if line.split(): +# print('run-1: ' + line) +# f.close() +# +# with open( f_run2_log.name,'r') as f: +# for line in f: +# if line.split(): +# print('run-2: ' + line) +# f.close() +# +# # CLEANUP +# ######### +# f_list=(f_svc_log, f_svc_err,f_run_sql,f_run1_log,f_run2_log) +# for i in range(len(f_list)): +# if os.path.isfile(f_list[i].name): +# os.remove(f_list[i].name) +# +# if os.path.isfile(tmpbkp): +# os.remove(tmpbkp) +# if os.path.isfile(tmpres): +# os.remove(tmpres) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + run-1: MSG test_01 + run-1: ID 1 + run-1: MSG test_02 + run-1: ID 2 + run-1: MSG test_0a + run-1: ID + run-1: MSG test_0b + run-1: ID + run-1: MSG опечатка + run-1: ID ы + run-1: Records affected: 5 + + run-2: MSG test_01 + run-2: ID + run-2: MSG test_02 + run-2: ID + run-2: MSG test_0a + run-2: ID 3 + run-2: MSG test_0b + run-2: ID 4 + run-2: MSG опечатка + run-2: ID ы + run-2: Records affected: 5 + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_2208_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2211.py b/tests/bugs/test_core_2211.py new file mode 100644 index 00000000..b5cc2e65 --- /dev/null +++ b/tests/bugs/test_core_2211.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: bugs.core_2211 +# title: Offset value for SUBSTRING from BLOB more than 32767 makes exception +# decription: +# tracker_id: CORE-2211 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('SUBSTRING.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test(b blob); + commit; + insert into test values(''); + commit; + + set list on; + set blob all; + + set term ^; + execute block as + declare bsize int = 1000000; + declare vclen int = 32760; + begin + while (bsize > 0) do + begin + update test set b = b || rpad('', :vclen, uuid_to_char(gen_uuid())); + bsize = bsize - vclen; + end + --update test set b = b || b; + update test set b = b || rpad('', :vclen, '#'); + end + ^ + set term ;^ + select char_length(b) from test; + select substring(b from char_length(b)-1 for 1) from test; + rollback; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CHAR_LENGTH 1048320 + SUBSTRING 0:43 + # + """ + +@pytest.mark.version('>=2.5') +def test_core_2211_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2215.py b/tests/bugs/test_core_2215.py new file mode 100644 index 00000000..17315469 --- /dev/null +++ b/tests/bugs/test_core_2215.py @@ -0,0 +1,86 @@ +#coding:utf-8 +# +# id: bugs.core_2215 +# title: GROUP BY concatenation with empty string +# decription: +# tracker_id: CORE-2215 +# min_versions: [] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE ATTRIBUTES_DICTIONARY ( + ID INTEGER NOT NULL, + NAME VARCHAR(25) +); + +insert into ATTRIBUTES_DICTIONARY (ID, NAME) + values (1,'ATTR1'); +insert into ATTRIBUTES_DICTIONARY (ID, NAME) + values (2,'ATTR1'); +insert into ATTRIBUTES_DICTIONARY (ID, NAME) + values (3,'ATTR2'); + +commit; +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select ATR.name, count(*) + from ATTRIBUTES_DICTIONARY ATR + group by 1 order by 2 desc ; + +select ATR.name||'TEXT', count(*) + from ATTRIBUTES_DICTIONARY ATR + group by 1 order by 2 desc ; + +select ATR.name||'', count(*) + from ATTRIBUTES_DICTIONARY ATR + group by 1 order by 2 desc ; + +select ATR.name||'', count(*) + from ATTRIBUTES_DICTIONARY ATR + group by ATR.name||'' order by count(*) desc ; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +NAME COUNT +========================= ===================== +ATTR1 2 +ATTR2 1 + + +CONCATENATION COUNT +============================= ===================== +ATTR1TEXT 2 +ATTR2TEXT 1 + + +CONCATENATION COUNT +========================= ===================== +ATTR1 2 +ATTR2 1 + + +CONCATENATION COUNT +========================= ===================== +ATTR1 2 +ATTR2 1 + +""" + +@pytest.mark.version('>=3.0') +def test_core_2215_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2216.py b/tests/bugs/test_core_2216.py new file mode 100644 index 00000000..d4fe2f16 --- /dev/null +++ b/tests/bugs/test_core_2216.py @@ -0,0 +1,187 @@ +#coding:utf-8 +# +# id: bugs.core_2216 +# title: Nbackup as online dump +# decription: +# We create table and leave it empty, than we run "nbackup -b 0 ". +# After this add one row in the table in source DB. +# Then we obtain database GUID of sourec DB and use it in following commands: +# 1. nbackup -b +# 2. nbackup -i -r +# Finally, we: +# 1. Check that inserted record actually does exist in ; +# 2. Run online validation of - it sould NOT produce any errors. +# +# 40CS, build 4.0.0.651: OK, 5.031s. +# 40SC, build 4.0.0.651: OK, 4.765s. +# 40SS, build 4.0.0.680: OK, 4.031s. +# +# tracker_id: CORE-2216 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('BLOB_ID.*', ''), ('[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9]', ''), ('Relation [0-9]{3,4}', 'Relation')] + +init_script_1 = """ + create table test(id int, s varchar(10) unique using index test_s, t timestamp, b blob); + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.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() +# os.fsync(file_handle.fileno()) +# +# file_handle.close() +# +# #-------------------------------------------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #------------------------------------------- +# +# dbfile='$(DATABASE_LOCATION)bugs.core_2216.fdb' +# tmpnbk='$(DATABASE_LOCATION)bugs.core_2216_nb0.fdb' +# tmpadd='$(DATABASE_LOCATION)bugs.core_2216_add.tmp' +# +# if os.path.isfile(tmpnbk): +# os.remove(tmpnbk) +# if os.path.isfile(tmpadd): +# os.remove(tmpadd) +# +# f_nbk1_log=open( os.path.join(context['temp_directory'],'tmp_nbk1_2216.log'), 'w') +# f_nbk1_err=open( os.path.join(context['temp_directory'],'tmp_nbk1_2216.err'), 'w') +# subprocess.call( [ context['nbackup_path'], '-b', '0', dbfile, tmpnbk], stdout=f_nbk1_log,stderr=f_nbk1_err ) +# flush_and_close( f_nbk1_log ) +# flush_and_close( f_nbk1_err ) +# +# +# f_run_sql=open( os.path.join(context['temp_directory'],'tmp_run_2216.sql'), 'w') +# f_run_sql.write('set list on; select rb.rdb$guid as db_guid from rdb$backup_history rb;') +# f_run_sql.close() +# +# f_run_log=open( os.path.join(context['temp_directory'],'tmp_run_2216.log'), 'w') +# subprocess.call( [ context['isql_path'], dsn, '-i', f_run_sql.name], stdout=f_run_log,stderr=subprocess.STDOUT ) +# flush_and_close( f_run_log ) +# +# with open( f_run_log.name,'r') as f: +# for line in f: +# if line.split(): +# db_guid=line.split()[1] +# +# runProgram('isql',[dsn], "insert into test(id,s,t,b) values(1, 'qwerty','11.12.2013 14:15:16.178', 'foo-rio-bar');") +# +# # nbackup -b {28287188-0E3A-4662-29AB-61F7E117E1C0} C:\\MIX +# irebird\\QA +# bt-repo mp\\E40.FDB C:\\MIX +# irebird\\QA +# bt-repo mp\\e40.bku +# # nbackup -i -r C:\\MIX +# irebird\\QA +# bt-repo mp\\e40.nb0 C:\\MIX +# irebird\\QA +# bt-repo mp\\e40.bku +# +# f_nbk2_log=open( os.path.join(context['temp_directory'],'tmp_nbk2_2216.log'), 'w') +# f_nbk2_err=open( os.path.join(context['temp_directory'],'tmp_nbk2_2216.err'), 'w') +# subprocess.call( [ context['nbackup_path'], '-b', db_guid, dbfile, tmpadd], stdout=f_nbk2_log, stderr=f_nbk2_err ) +# flush_and_close( f_nbk2_log ) +# flush_and_close( f_nbk2_err ) +# +# +# +# f_nbk3_log=open( os.path.join(context['temp_directory'],'tmp_nbk3_2216.log'), 'w') +# f_nbk3_err=open( os.path.join(context['temp_directory'],'tmp_nbk3_2216.err'), 'w') +# subprocess.call( [ context['nbackup_path'], '-i', '-r', tmpnbk, tmpadd], stdout=f_nbk3_log, stderr=f_nbk3_err ) +# flush_and_close( f_nbk3_log ) +# flush_and_close( f_nbk3_err ) +# +# # Checking query: +# ################# +# runProgram('isql',['localhost:'+tmpnbk],"set list on;set count on;set blob all;select id,s,t,b as blob_id from test;" ) +# +# f_val_log=open( os.path.join(context['temp_directory'],'tmp_val_2216.log'), "w") +# f_val_err=open( os.path.join(context['temp_directory'],'tmp_val_2216.err'), "w") +# +# subprocess.call([ context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_validate", +# "dbname", tmpnbk +# ], +# stdout=f_val_log, +# stderr=f_val_err) +# flush_and_close( f_val_log ) +# flush_and_close( f_val_err ) +# +# with open( f_val_log.name,'r') as f: +# print(f.read()) +# +# # All of these files must be empty: +# ################################### +# f_list=(f_nbk1_err, f_nbk2_err, f_nbk3_err, f_val_err) +# for i in range(len(f_list)): +# with open( f_list[i].name,'r') as f: +# for line in f: +# if line.split(): +# print( 'UNEXPECTED STDERR in file '+f_list[i].name+': '+line.upper() ) +# +# # Cleanup. +# ############################### +# cleanup( [i.name for i in ( f_run_sql,f_run_log, f_nbk1_log,f_nbk1_err, f_nbk2_log,f_nbk2_err, f_nbk3_log,f_nbk3_err, f_val_log,f_val_err) ] ) +# +# os.remove(tmpnbk) +# os.remove(tmpadd) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + S qwerty + T 2013-12-11 14:15:16.1780 + foo-rio-bar + Records affected: 1 + 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') +@pytest.mark.xfail +def test_core_2216_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2227.py b/tests/bugs/test_core_2227.py new file mode 100644 index 00000000..7d756b4a --- /dev/null +++ b/tests/bugs/test_core_2227.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: bugs.core_2227 +# title: Problem with column names with Accents and triggers +# decription: +# 28.02.2021 +# Changed connection charset to UTF8 otherwise on Linux this test leads to 'ERROR' with issuing: +# ==== +# ISQL_STDERR +# Expected end of statement, encountered EOF +# ==== +# Checked again on: +# 1) Windows: 4.0.0.2372; 3.0.8.33416 +# 2) Linux: 4.0.0.2377 +# +# tracker_id: CORE-2227 +# min_versions: [] +# versions: 2.1.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + RECREATE TABLE TESTING ( + "CÓDIGO" INTEGER + ); + """ + +db_1 = db_factory(charset='ISO8859_1', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + SET TERM ^; + CREATE TRIGGER TESTING_I FOR TESTING + ACTIVE BEFORE INSERT POSITION 0 + AS + BEGIN + NEW."CÓDIGO" = 1; + END ^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1.2') +def test_core_2227_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_2230.py b/tests/bugs/test_core_2230.py new file mode 100644 index 00000000..c0dbd998 --- /dev/null +++ b/tests/bugs/test_core_2230.py @@ -0,0 +1,57 @@ +#coding:utf-8 +# +# id: bugs.core_2230 +# title: Implement domain check of input parameters of execute block +# decription: +# tracker_id: CORE-2230 +# min_versions: [] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE DOMAIN DOM1 AS INTEGER NOT NULL CHECK (value in (0, 1)); +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# c = db_conn.cursor() +# cmd = c.prep('execute block (x DOM1 = ?) returns (y integer) as begin y = x; suspend; end') +# +# c.execute(cmd,[1]) +# printData(c) +# +# try: +# c.execute(cmd,[10]) +# printData(c) +# except kdb.DatabaseError,e: +# print (e[0]) +# else: +# print ('Test Failed') +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Y +----------- +1 +Y +----------- +Cursor.fetchone: +- SQLCODE: -625 +- validation error for variable X, value "10" +""" + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_2230_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2233.py b/tests/bugs/test_core_2233.py new file mode 100644 index 00000000..d4c83543 --- /dev/null +++ b/tests/bugs/test_core_2233.py @@ -0,0 +1,145 @@ +#coding:utf-8 +# +# id: bugs.core_2233 +# title: Allow non-SYSDBA users to monitor not only their current attachment but other their attachments as well +# decription: +# Checked on: +# 4.0.0.1635 SS: OK, 1.605s. 4.0.0.1633 CS: OK, 2.133s. +# 3.0.5.33180 SS: OK, 1.925s. 3.0.5.33178 CS: OK, 1.581s. +# 2.5.9.27119 SC: OK, 0.338s. 2.5.9.27146 SS: OK, 0.317s. +# +# tracker_id: CORE-2233 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('=', '')] + +init_script_1 = """ + set wng off; + -- Drop old account if it remains from prevoius run: + set term ^; + execute block as + begin + begin + execute statement 'drop user tmp$c2233_adam' with autonomous transaction; + when any do begin end + end + begin + execute statement 'drop user tmp$c2233_mike' with autonomous transaction; + when any do begin end + end + begin + execute statement 'drop role tmp$r2233_boss'; + when any do begin end + end + end + ^ + set term ;^ + commit; + + create user tmp$c2233_adam password '123'; + create user tmp$c2233_mike password '456'; + commit; + create role tmp$r2233_boss; + create role tmp$r2233_acnt; + grant tmp$r2233_boss to tmp$c2233_adam; + grant tmp$r2233_acnt to tmp$c2233_adam; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# con0=fdb.connect( dsn = dsn, user='tmp$c2233_mike', password='456' ) +# con1=fdb.connect( dsn = dsn, user='tmp$c2233_adam', password='123' ) +# con2=fdb.connect( dsn = dsn, user='tmp$c2233_adam', password='123' ) +# con3=fdb.connect( dsn = dsn, user='tmp$c2233_adam', password='123', role='tmp$r2233_boss' ) +# con4=fdb.connect( dsn = dsn, user='tmp$c2233_adam', password='123', role='tmp$r2233_acnt' ) +# +# chk_sql=''' +# select current_user as who_am_i, mon$user mon_att_user, mon$role as mon_att_role, count( mon$user ) as mon_att_cnt +# from rdb$database r +# left join mon$attachments a on a.mon$attachment_id != current_connection +# group by 1,2,3 +# ''' +# +# cur_mngr=con0.cursor() +# cur_mngr.execute(chk_sql) +# cur_cols=cur_mngr.description +# for r in cur_mngr: +# for i in range(0,len(cur_cols)): +# print( cur_cols[i][0],':', r[i] ) +# cur_mngr.close() +# #------------------------------------------- +# +# cur_boss=con1.cursor() +# cur_boss.execute(chk_sql) +# cur_cols=cur_boss.description +# for r in cur_boss: +# for i in range(0,len(cur_cols)): +# print( cur_cols[i][0],':', r[i] ) +# cur_boss.close() +# #------------------------------------------- +# +# for c in (con0,con1,con2,con3,con4): +# c.close() +# +# db_conn.execute_immediate('drop user tmp$c2233_adam') +# db_conn.execute_immediate('drop user tmp$c2233_mike') +# db_conn.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 +# ## ############################################################################################# +# db_conn.execute_immediate('delete from mon$attachments where mon$attachment_id != current_connection') +# db_conn.commit() +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHO_AM_I : TMP$C2233_MIKE + MON_ATT_USER : None + MON_ATT_ROLE : None + MON_ATT_CNT : 0 + + WHO_AM_I : TMP$C2233_ADAM + MON_ATT_USER : TMP$C2233_ADAM + MON_ATT_ROLE : NONE + MON_ATT_CNT : 1 + + WHO_AM_I : TMP$C2233_ADAM + MON_ATT_USER : TMP$C2233_ADAM + MON_ATT_ROLE : TMP$R2233_ACNT + MON_ATT_CNT : 1 + + WHO_AM_I : TMP$C2233_ADAM + MON_ATT_USER : TMP$C2233_ADAM + MON_ATT_ROLE : TMP$R2233_BOSS + MON_ATT_CNT : 1 + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_2233_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2238.py b/tests/bugs/test_core_2238.py new file mode 100644 index 00000000..42a5df09 --- /dev/null +++ b/tests/bugs/test_core_2238.py @@ -0,0 +1,67 @@ +#coding:utf-8 +# +# id: bugs.core_2238 +# title: UTF8 and large varchar fields, is disinct from > Implementation limit exceeded. +# decription: +# Test operates with literals of utf8 charset with length = exactly 8191 symbols. +# We insert such literal and then try to update table with another string which differs only in last character. +# Confirmed exception on 2.5: +# statement failed, sqlstate = 54000 +# dynamic sql error +# -sql error code = -204 +# -implementation limit exceeded +# -block size exceeds implementation restriction +# +# tracker_id: CORE-2238 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + create domain dm_long_utf8 as varchar(8191) character set utf8; + create table test (long_text dm_long_utf8); + commit; + set count on; + -- Length of this literal is exact 8191 characters: + insert into test(long_text) + values( + 'Kaikki neuvon-antajat ja etevimmät päälliköt ja mollat ja imamit ja kadit ja kaupungin päähenkilöt olivat suuresti hämmästyksissään. Hänen tunnettu hurskautensa vaati kaikkia äänettömyyteen, sillä välin kuin hän itse lausui pitkän rukouksen, pyytäen Allah''ta ja Profeettaa hämmentämään kaikkia häväiseviä Juutalaisia ja uskottomia ja vuodattamaan totuuden sanoja jumalisten ihmisten suuhun. Ja nyt kunnian-arvoisa sheiki kutsui esiin kaikki todistajat David Alroy''ta vastaan. Heti Kisloch, Kurdilainen, joka oli koroitettu Bagdadin kadiksi, astui esiin, veti sametti-kukkarostansa paperikääryn ja luki semmoisen todistuksen, jossa arvoisa Kisloch vakuutti, että hän ensin tutustui vangin, David Alroy''n kanssa joissakin erämaan raunioissa -- muutamain rosvojen pesässä, joita Alroy johdatti; että hän, Kisloch, oli rehellinen kauppias ja että nämät konnat olivat ryöstäneet hänen karavaninsa ja hän itse joutunut vankeuteen; että hänen vankeutensa toisena yönä Alroy oli ilmestynyt hänen eteensä leijonan muodossa ja kolmantena tuimasilmäisenä härkänä; että hänen oli tapa alinomaa muuttaa itsensä; että hän usein nosti henkiä; että viimein eräänä kauheana yönä Eblis itse tuli suurella juhlasaatolla ja antoi Alroy''lle Salomonin, Davidin pojan valtikan; ja että tämä seuraavana päivänä kohotti lippunsa ja kohta sen jälkeen kukisti Hassan Subah''n ja tämän Seldshukit useitten hirmuisten paholaisten silminnähtävällä avulla. Kalidaan, Indialaisen, Guebriläisen ja Neekerin ja muutamien muitten saman hengen lapsien todistukset vetivät täysin määrin vertoja Kisloch Kurdilaisen uhkealle kertomukselle. Hebrealaisen valloittajan vastustamaton menestys oli kieltämättömällä tavalla selitetty, Mahomettilaisten aseitten kunnia ja Moslemin uskon puhtaus olivat asetetut jälleen entiseen loistoonsa ja saastuttamattomaan maineesensa. Todeksi saatiin, että David Alroy oli Ebliin lapsi, noitamies, taikakalujen ja myrkkyjen käyttäjä. Kansa kuunteli kauhulla ja harmilla. He olisivat tunkeneet vartiaväen läpitse ja repineet hänet kappaleiksi, jolleivät olisi pelänneet Karamanialaisten sotatapparoita. Niin he lohduttivat mieltänsä sillä, että he ennen pitkää saisivat nähdä hänen kidutuksensa. Bagdadin kadi kumarsi Karamanian kuningasta ja kuiskasi soveliaan matkan päästä jotakin kuninkaalliseen korvaan. Torvet kaikkuivat, kuuluttajat vaativat äänettömyyttä ja kuninkaan huulet liikkuivat taas. "Kuule, oi kansa, ja ole viisas. Pääkadi aikoo nyt lukea kuninkaallisen prinsessan Schirenen, noiturin etevimmän uhrin todistuksen." Ja todistus luettiin, joka vakuutti, että David Alroy omisti ja kantoi lähinnä sydäntänsä erästä talismania, jonka Eblis oli antanut hänelle ja jonka voima oli niin suuri, että, jos sitä kerta painettiin naisen rintaa vastaan, tämä ei enää voinut hallita tahtoansa. Tämmöinen kova onni oli kohdannut oikeauskoisten hallitsian tytärtä. "Onko siinä niin kirjoitettu?" vanki kysyi. "On", kadi vastasi, "ja sen alla on vielä prinsessan kuninkaallinen allekirjoitus." "Se on väärennetty." Karamanian kuningas kavahti valta-istuimeltansa ja oli vihoissansa astumallaan sen portaita alas. Hänen kasvonsa olivat veripunaiset, hänen partansa kuin tulen liekki. Joku lempiministeri rohkeni vienosti pidättää häntä hänen kuninkaallisesta vaipastansa. "Tapa paikalla pois se koira", Karamanian kuningas mutisi. "Prinsessa on itse täällä", lausui kadi, "todistamassa niitä noitakeinoja, joitten alaisena hän oli, vaan joitten vaikutuksesta hän nyt Allah''n ja Profeetan voiman kautta on pääsnyt." Alroy''ta vävähti! "Astu esiin, kuninkaallinen prinsessa", kadi sanoi, "ja jos se todistus, jonka kuulit, on perustettu, nosta ylös se kuninkaallinen käsi, joka koristi sen allekirjoituksellaan." Lähellä valta-istuinta oleva eunukkien joukko teki tilaa; naishaamu, joka oli verhottu hunnulla jalkoihin saakka, astui esiin. Hän nosti ylös kätensä; koko kerääntynyt kansa tuskin hengitti mielenliikutuksesta; eunukkien rivit ummistuivat jälleen; huuto kuului ja hunnustettu haamu katosi. "Minä odotan kidutuskoneitasi, kuningas", Alroy lausui raskaan surun äänellä. Hänen lujuutensa näytti luopuneen hänestä. Hänen silmänsä olivat luodut maahan. Hän oli nähtävästi vaipunut syvään miettimiseen taikka heittäynyt epätoivoon. "Valmistakaat seipäät", käski Alp Arslan. Koko kansan joukkoa värisytti vasten mieltäkin. Yksi orja lähestyi ja tarjosi paperikääryä Alroy''lle. Hän tunsi Nubialaisen, joka oli Honainin palveluksessa. Hänen entinen ministerinsä ilmoitti hänelle, että hän oli saapuvilla; että ne ehdot, joita hän vankihuoneessa tarjosi, vielä myönnettäisiin; että jos Alroy, jota asiaa hän ei epäillyt ja jota hän rukoili, suostuisi niitä vastaan-ottamaan, hänen tuli pistää paperikäärö poveensa, mutta, jos hän yhä oli taipumaton, jos hänen yhä oli mieletön päätös kuolla hirveä ja häväisevä kuolema, hänen tuli repiä se rikki ja heittää se tanterelle. Silmänräpäyksellä Alroy otti paperikääryn ja repi sen kiivaasti tuhansiin palasiin. Tuulen puuska levitti kappaleet laajalle yliympäri. Alhaiso riiteli näistä David Alroy''n viimeisistä muistoista; ja tämä vähäinen tapaus tuotti paljon hämminkiä. Tällä välin Neekerit varustivat kidutuksen ja kuoleman koneita. "Tuon juutalaisen koiran itsepintaisuus tekee minun hulluksi", lausui Karamanian kuningas hovimiehillensä. "Minua haluttaa puhutella häntä vähän, ennenkuin hän kuolee." Lempiministeri pyysi hallitsiaansa olemaan levollisena; mutta kuninkaallinen parta kävi niin punaiseksi, ja kuninkaalliset silmät iskivät niin kauheata tulta, että lempiministerikin lopulta myöntyi. Torvi kaikkui, kuuluttajat vaativat vaiti-oloa, ja Alp Arslanin ääni eroitettiin jälleen. "Senkin koira, näetkö sinä, mikä on tarjonasi? Tiedätkö sinä, mikä vartoo sinua sinun herrasi Ebliin asunnoissa? Voiko väärä ylpeys viehättää Juutalaistakin? Eikö elämä ole suloista? Eikö olisi parempi olla minun varvaskenkieni kantaja kuin tulla seivästetyksi?" "Jalomielinen Alp Arslan", vastasi Alroy ilmeisen ylenkatseen äänellä; "luuletko, että mikään kidutus rasittaa niin, kuin se muisto, että sinä olet voittanut minun?" "Partani kautta, hän ivaa minua!" Karamanialaisten hallitsia huudahti; "hän tekee kiusaa minulle! Älkäät koskeko vaippaani. Minä tahdon puhua hänen kanssaan. Te ette näe kauemmaksi kuin hunnustettu haukka, te sokean äidin lapset. Se on noita; hänellä on vielä jälellä joku päätaika; hän pelastaa vielä henkensä. Hän lentää ilmaan taikka vaipuu maan sisään. Hän nauraa meidän kidutuksiamme." Karamanian kuningas astui tuota pikaa valta-istuimensa portaita alaspäin; häntä seurasivat hänen lempiministerinsä ja hänen neuvon-antajansa ja hänen etevimmät päällikkönsä ja kadit ja mollat ja imamit ja kaupungin päähenkilöt. "Sinä noita!" Alp Arslan huudahti, "hävytön noita! halvan äidin halpa poika! koirien koira! niskotteletko sinä meitä vastaan? Kuiskaako herrasi Eblis toivoa sinun korviisi? Nauratko meidän rangaistuksiamme? Aiotko lentää ylös ilmaan? vai painua alas maahan? Niinkö, niinkö?" Hengästyneenä ja vihastansa uupuneena hallitsia vaikeni. Hän repi partaansa ja polki maata rajussa vimmassaan. "Sinä olet viisaampi kuin neuvon-antajasi, kuningas Arslan; minä en nöyrry sinun edessäsi. Minun Herrani, vaikka hän ei ole Eblis, ei ole hylännyt minua. Minä nauran sinun rangaistuksiasi. Sinun kidutuksiasi minä ylenkatson. Minä sekä vaivun maan sisään että kohoan ilmaan. Tyydytkö nyt vastaukseeni?" "Partani kautta", huudahti tulistunut Arslan, "minä tyydyn vastaukseesi. Pelastakoon Eblis sinut, jos hän voi;" ja Karamanian kuningas, Aasian mainioin miekan piteliä veti säilänsä, ikäänkuin salaman, tupesta ja silpaisi yhdellä säväyksellä Alroy''lta pään. Se kaatui, vaan, kun se kaatui, riemuitsevan pilkan hymy näytti vivahtelevan sankarin kylmenevillä kasvoilla ja kysyvän hänen vihollisiltansa: "missä kaikki teidän kidutuksenne nyt ovat?" Do Dzieci Gołąbki i Dziewczynka Dziecię i Koza Wróbel i Jaskółka Osieł i Chłopczyk Nieposłuszny Zajączek Kotek Brytan i Pudelek Egzamin Małego "Misia" Wilk i Owce Lis i Gąski Chłopczyk i Źrebię Gęsia Kapela Lew i Piesek Niedźwiedź i Pszczółka Śniadanie Artysta Z Zimowych Rozrywek Leniwy Chłopczyk Przygoda z Indykiem O hämmästyksissään. Leniwy ЙЦУКЕН' + ); + insert into test(long_text) + values( + 'Kaikki neuvon-antajat ja etevimmät päälliköt ja mollat ja imamit ja kadit ja kaupungin päähenkilöt olivat suuresti hämmästyksissään. Hänen tunnettu hurskautensa vaati kaikkia äänettömyyteen, sillä välin kuin hän itse lausui pitkän rukouksen, pyytäen Allah''ta ja Profeettaa hämmentämään kaikkia häväiseviä Juutalaisia ja uskottomia ja vuodattamaan totuuden sanoja jumalisten ihmisten suuhun. Ja nyt kunnian-arvoisa sheiki kutsui esiin kaikki todistajat David Alroy''ta vastaan. Heti Kisloch, Kurdilainen, joka oli koroitettu Bagdadin kadiksi, astui esiin, veti sametti-kukkarostansa paperikääryn ja luki semmoisen todistuksen, jossa arvoisa Kisloch vakuutti, että hän ensin tutustui vangin, David Alroy''n kanssa joissakin erämaan raunioissa -- muutamain rosvojen pesässä, joita Alroy johdatti; että hän, Kisloch, oli rehellinen kauppias ja että nämät konnat olivat ryöstäneet hänen karavaninsa ja hän itse joutunut vankeuteen; että hänen vankeutensa toisena yönä Alroy oli ilmestynyt hänen eteensä leijonan muodossa ja kolmantena tuimasilmäisenä härkänä; että hänen oli tapa alinomaa muuttaa itsensä; että hän usein nosti henkiä; että viimein eräänä kauheana yönä Eblis itse tuli suurella juhlasaatolla ja antoi Alroy''lle Salomonin, Davidin pojan valtikan; ja että tämä seuraavana päivänä kohotti lippunsa ja kohta sen jälkeen kukisti Hassan Subah''n ja tämän Seldshukit useitten hirmuisten paholaisten silminnähtävällä avulla. Kalidaan, Indialaisen, Guebriläisen ja Neekerin ja muutamien muitten saman hengen lapsien todistukset vetivät täysin määrin vertoja Kisloch Kurdilaisen uhkealle kertomukselle. Hebrealaisen valloittajan vastustamaton menestys oli kieltämättömällä tavalla selitetty, Mahomettilaisten aseitten kunnia ja Moslemin uskon puhtaus olivat asetetut jälleen entiseen loistoonsa ja saastuttamattomaan maineesensa. Todeksi saatiin, että David Alroy oli Ebliin lapsi, noitamies, taikakalujen ja myrkkyjen käyttäjä. Kansa kuunteli kauhulla ja harmilla. He olisivat tunkeneet vartiaväen läpitse ja repineet hänet kappaleiksi, jolleivät olisi pelänneet Karamanialaisten sotatapparoita. Niin he lohduttivat mieltänsä sillä, että he ennen pitkää saisivat nähdä hänen kidutuksensa. Bagdadin kadi kumarsi Karamanian kuningasta ja kuiskasi soveliaan matkan päästä jotakin kuninkaalliseen korvaan. Torvet kaikkuivat, kuuluttajat vaativat äänettömyyttä ja kuninkaan huulet liikkuivat taas. "Kuule, oi kansa, ja ole viisas. Pääkadi aikoo nyt lukea kuninkaallisen prinsessan Schirenen, noiturin etevimmän uhrin todistuksen." Ja todistus luettiin, joka vakuutti, että David Alroy omisti ja kantoi lähinnä sydäntänsä erästä talismania, jonka Eblis oli antanut hänelle ja jonka voima oli niin suuri, että, jos sitä kerta painettiin naisen rintaa vastaan, tämä ei enää voinut hallita tahtoansa. Tämmöinen kova onni oli kohdannut oikeauskoisten hallitsian tytärtä. "Onko siinä niin kirjoitettu?" vanki kysyi. "On", kadi vastasi, "ja sen alla on vielä prinsessan kuninkaallinen allekirjoitus." "Se on väärennetty." Karamanian kuningas kavahti valta-istuimeltansa ja oli vihoissansa astumallaan sen portaita alas. Hänen kasvonsa olivat veripunaiset, hänen partansa kuin tulen liekki. Joku lempiministeri rohkeni vienosti pidättää häntä hänen kuninkaallisesta vaipastansa. "Tapa paikalla pois se koira", Karamanian kuningas mutisi. "Prinsessa on itse täällä", lausui kadi, "todistamassa niitä noitakeinoja, joitten alaisena hän oli, vaan joitten vaikutuksesta hän nyt Allah''n ja Profeetan voiman kautta on pääsnyt." Alroy''ta vävähti! "Astu esiin, kuninkaallinen prinsessa", kadi sanoi, "ja jos se todistus, jonka kuulit, on perustettu, nosta ylös se kuninkaallinen käsi, joka koristi sen allekirjoituksellaan." Lähellä valta-istuinta oleva eunukkien joukko teki tilaa; naishaamu, joka oli verhottu hunnulla jalkoihin saakka, astui esiin. Hän nosti ylös kätensä; koko kerääntynyt kansa tuskin hengitti mielenliikutuksesta; eunukkien rivit ummistuivat jälleen; huuto kuului ja hunnustettu haamu katosi. "Minä odotan kidutuskoneitasi, kuningas", Alroy lausui raskaan surun äänellä. Hänen lujuutensa näytti luopuneen hänestä. Hänen silmänsä olivat luodut maahan. Hän oli nähtävästi vaipunut syvään miettimiseen taikka heittäynyt epätoivoon. "Valmistakaat seipäät", käski Alp Arslan. Koko kansan joukkoa värisytti vasten mieltäkin. Yksi orja lähestyi ja tarjosi paperikääryä Alroy''lle. Hän tunsi Nubialaisen, joka oli Honainin palveluksessa. Hänen entinen ministerinsä ilmoitti hänelle, että hän oli saapuvilla; että ne ehdot, joita hän vankihuoneessa tarjosi, vielä myönnettäisiin; että jos Alroy, jota asiaa hän ei epäillyt ja jota hän rukoili, suostuisi niitä vastaan-ottamaan, hänen tuli pistää paperikäärö poveensa, mutta, jos hän yhä oli taipumaton, jos hänen yhä oli mieletön päätös kuolla hirveä ja häväisevä kuolema, hänen tuli repiä se rikki ja heittää se tanterelle. Silmänräpäyksellä Alroy otti paperikääryn ja repi sen kiivaasti tuhansiin palasiin. Tuulen puuska levitti kappaleet laajalle yliympäri. Alhaiso riiteli näistä David Alroy''n viimeisistä muistoista; ja tämä vähäinen tapaus tuotti paljon hämminkiä. Tällä välin Neekerit varustivat kidutuksen ja kuoleman koneita. "Tuon juutalaisen koiran itsepintaisuus tekee minun hulluksi", lausui Karamanian kuningas hovimiehillensä. "Minua haluttaa puhutella häntä vähän, ennenkuin hän kuolee." Lempiministeri pyysi hallitsiaansa olemaan levollisena; mutta kuninkaallinen parta kävi niin punaiseksi, ja kuninkaalliset silmät iskivät niin kauheata tulta, että lempiministerikin lopulta myöntyi. Torvi kaikkui, kuuluttajat vaativat vaiti-oloa, ja Alp Arslanin ääni eroitettiin jälleen. "Senkin koira, näetkö sinä, mikä on tarjonasi? Tiedätkö sinä, mikä vartoo sinua sinun herrasi Ebliin asunnoissa? Voiko väärä ylpeys viehättää Juutalaistakin? Eikö elämä ole suloista? Eikö olisi parempi olla minun varvaskenkieni kantaja kuin tulla seivästetyksi?" "Jalomielinen Alp Arslan", vastasi Alroy ilmeisen ylenkatseen äänellä; "luuletko, että mikään kidutus rasittaa niin, kuin se muisto, että sinä olet voittanut minun?" "Partani kautta, hän ivaa minua!" Karamanialaisten hallitsia huudahti; "hän tekee kiusaa minulle! Älkäät koskeko vaippaani. Minä tahdon puhua hänen kanssaan. Te ette näe kauemmaksi kuin hunnustettu haukka, te sokean äidin lapset. Se on noita; hänellä on vielä jälellä joku päätaika; hän pelastaa vielä henkensä. Hän lentää ilmaan taikka vaipuu maan sisään. Hän nauraa meidän kidutuksiamme." Karamanian kuningas astui tuota pikaa valta-istuimensa portaita alaspäin; häntä seurasivat hänen lempiministerinsä ja hänen neuvon-antajansa ja hänen etevimmät päällikkönsä ja kadit ja mollat ja imamit ja kaupungin päähenkilöt. "Sinä noita!" Alp Arslan huudahti, "hävytön noita! halvan äidin halpa poika! koirien koira! niskotteletko sinä meitä vastaan? Kuiskaako herrasi Eblis toivoa sinun korviisi? Nauratko meidän rangaistuksiamme? Aiotko lentää ylös ilmaan? vai painua alas maahan? Niinkö, niinkö?" Hengästyneenä ja vihastansa uupuneena hallitsia vaikeni. Hän repi partaansa ja polki maata rajussa vimmassaan. "Sinä olet viisaampi kuin neuvon-antajasi, kuningas Arslan; minä en nöyrry sinun edessäsi. Minun Herrani, vaikka hän ei ole Eblis, ei ole hylännyt minua. Minä nauran sinun rangaistuksiasi. Sinun kidutuksiasi minä ylenkatson. Minä sekä vaivun maan sisään että kohoan ilmaan. Tyydytkö nyt vastaukseeni?" "Partani kautta", huudahti tulistunut Arslan, "minä tyydyn vastaukseesi. Pelastakoon Eblis sinut, jos hän voi;" ja Karamanian kuningas, Aasian mainioin miekan piteliä veti säilänsä, ikäänkuin salaman, tupesta ja silpaisi yhdellä säväyksellä Alroy''lta pään. Se kaatui, vaan, kun se kaatui, riemuitsevan pilkan hymy näytti vivahtelevan sankarin kylmenevillä kasvoilla ja kysyvän hänen vihollisiltansa: "missä kaikki teidän kidutuksenne nyt ovat?" Do Dzieci Gołąbki i Dziewczynka Dziecię i Koza Wróbel i Jaskółka Osieł i Chłopczyk Nieposłuszny Zajączek Kotek Brytan i Pudelek Egzamin Małego "Misia" Wilk i Owce Lis i Gąski Chłopczyk i Źrebię Gęsia Kapela Lew i Piesek Niedźwiedź i Pszczółka Śniadanie Artysta Z Zimowych Rozrywek Leniwy Chłopczyk Przygoda z Indykiem O hämmästyksissään. Leniwy НЕКУЦЙ' + ); + + update test set long_text = null + where long_text is distinct from + 'Kaikki neuvon-antajat ja etevimmät päälliköt ja mollat ja imamit ja kadit ja kaupungin päähenkilöt olivat suuresti hämmästyksissään. Hänen tunnettu hurskautensa vaati kaikkia äänettömyyteen, sillä välin kuin hän itse lausui pitkän rukouksen, pyytäen Allah''ta ja Profeettaa hämmentämään kaikkia häväiseviä Juutalaisia ja uskottomia ja vuodattamaan totuuden sanoja jumalisten ihmisten suuhun. Ja nyt kunnian-arvoisa sheiki kutsui esiin kaikki todistajat David Alroy''ta vastaan. Heti Kisloch, Kurdilainen, joka oli koroitettu Bagdadin kadiksi, astui esiin, veti sametti-kukkarostansa paperikääryn ja luki semmoisen todistuksen, jossa arvoisa Kisloch vakuutti, että hän ensin tutustui vangin, David Alroy''n kanssa joissakin erämaan raunioissa -- muutamain rosvojen pesässä, joita Alroy johdatti; että hän, Kisloch, oli rehellinen kauppias ja että nämät konnat olivat ryöstäneet hänen karavaninsa ja hän itse joutunut vankeuteen; että hänen vankeutensa toisena yönä Alroy oli ilmestynyt hänen eteensä leijonan muodossa ja kolmantena tuimasilmäisenä härkänä; että hänen oli tapa alinomaa muuttaa itsensä; että hän usein nosti henkiä; että viimein eräänä kauheana yönä Eblis itse tuli suurella juhlasaatolla ja antoi Alroy''lle Salomonin, Davidin pojan valtikan; ja että tämä seuraavana päivänä kohotti lippunsa ja kohta sen jälkeen kukisti Hassan Subah''n ja tämän Seldshukit useitten hirmuisten paholaisten silminnähtävällä avulla. Kalidaan, Indialaisen, Guebriläisen ja Neekerin ja muutamien muitten saman hengen lapsien todistukset vetivät täysin määrin vertoja Kisloch Kurdilaisen uhkealle kertomukselle. Hebrealaisen valloittajan vastustamaton menestys oli kieltämättömällä tavalla selitetty, Mahomettilaisten aseitten kunnia ja Moslemin uskon puhtaus olivat asetetut jälleen entiseen loistoonsa ja saastuttamattomaan maineesensa. Todeksi saatiin, että David Alroy oli Ebliin lapsi, noitamies, taikakalujen ja myrkkyjen käyttäjä. Kansa kuunteli kauhulla ja harmilla. He olisivat tunkeneet vartiaväen läpitse ja repineet hänet kappaleiksi, jolleivät olisi pelänneet Karamanialaisten sotatapparoita. Niin he lohduttivat mieltänsä sillä, että he ennen pitkää saisivat nähdä hänen kidutuksensa. Bagdadin kadi kumarsi Karamanian kuningasta ja kuiskasi soveliaan matkan päästä jotakin kuninkaalliseen korvaan. Torvet kaikkuivat, kuuluttajat vaativat äänettömyyttä ja kuninkaan huulet liikkuivat taas. "Kuule, oi kansa, ja ole viisas. Pääkadi aikoo nyt lukea kuninkaallisen prinsessan Schirenen, noiturin etevimmän uhrin todistuksen." Ja todistus luettiin, joka vakuutti, että David Alroy omisti ja kantoi lähinnä sydäntänsä erästä talismania, jonka Eblis oli antanut hänelle ja jonka voima oli niin suuri, että, jos sitä kerta painettiin naisen rintaa vastaan, tämä ei enää voinut hallita tahtoansa. Tämmöinen kova onni oli kohdannut oikeauskoisten hallitsian tytärtä. "Onko siinä niin kirjoitettu?" vanki kysyi. "On", kadi vastasi, "ja sen alla on vielä prinsessan kuninkaallinen allekirjoitus." "Se on väärennetty." Karamanian kuningas kavahti valta-istuimeltansa ja oli vihoissansa astumallaan sen portaita alas. Hänen kasvonsa olivat veripunaiset, hänen partansa kuin tulen liekki. Joku lempiministeri rohkeni vienosti pidättää häntä hänen kuninkaallisesta vaipastansa. "Tapa paikalla pois se koira", Karamanian kuningas mutisi. "Prinsessa on itse täällä", lausui kadi, "todistamassa niitä noitakeinoja, joitten alaisena hän oli, vaan joitten vaikutuksesta hän nyt Allah''n ja Profeetan voiman kautta on pääsnyt." Alroy''ta vävähti! "Astu esiin, kuninkaallinen prinsessa", kadi sanoi, "ja jos se todistus, jonka kuulit, on perustettu, nosta ylös se kuninkaallinen käsi, joka koristi sen allekirjoituksellaan." Lähellä valta-istuinta oleva eunukkien joukko teki tilaa; naishaamu, joka oli verhottu hunnulla jalkoihin saakka, astui esiin. Hän nosti ylös kätensä; koko kerääntynyt kansa tuskin hengitti mielenliikutuksesta; eunukkien rivit ummistuivat jälleen; huuto kuului ja hunnustettu haamu katosi. "Minä odotan kidutuskoneitasi, kuningas", Alroy lausui raskaan surun äänellä. Hänen lujuutensa näytti luopuneen hänestä. Hänen silmänsä olivat luodut maahan. Hän oli nähtävästi vaipunut syvään miettimiseen taikka heittäynyt epätoivoon. "Valmistakaat seipäät", käski Alp Arslan. Koko kansan joukkoa värisytti vasten mieltäkin. Yksi orja lähestyi ja tarjosi paperikääryä Alroy''lle. Hän tunsi Nubialaisen, joka oli Honainin palveluksessa. Hänen entinen ministerinsä ilmoitti hänelle, että hän oli saapuvilla; että ne ehdot, joita hän vankihuoneessa tarjosi, vielä myönnettäisiin; että jos Alroy, jota asiaa hän ei epäillyt ja jota hän rukoili, suostuisi niitä vastaan-ottamaan, hänen tuli pistää paperikäärö poveensa, mutta, jos hän yhä oli taipumaton, jos hänen yhä oli mieletön päätös kuolla hirveä ja häväisevä kuolema, hänen tuli repiä se rikki ja heittää se tanterelle. Silmänräpäyksellä Alroy otti paperikääryn ja repi sen kiivaasti tuhansiin palasiin. Tuulen puuska levitti kappaleet laajalle yliympäri. Alhaiso riiteli näistä David Alroy''n viimeisistä muistoista; ja tämä vähäinen tapaus tuotti paljon hämminkiä. Tällä välin Neekerit varustivat kidutuksen ja kuoleman koneita. "Tuon juutalaisen koiran itsepintaisuus tekee minun hulluksi", lausui Karamanian kuningas hovimiehillensä. "Minua haluttaa puhutella häntä vähän, ennenkuin hän kuolee." Lempiministeri pyysi hallitsiaansa olemaan levollisena; mutta kuninkaallinen parta kävi niin punaiseksi, ja kuninkaalliset silmät iskivät niin kauheata tulta, että lempiministerikin lopulta myöntyi. Torvi kaikkui, kuuluttajat vaativat vaiti-oloa, ja Alp Arslanin ääni eroitettiin jälleen. "Senkin koira, näetkö sinä, mikä on tarjonasi? Tiedätkö sinä, mikä vartoo sinua sinun herrasi Ebliin asunnoissa? Voiko väärä ylpeys viehättää Juutalaistakin? Eikö elämä ole suloista? Eikö olisi parempi olla minun varvaskenkieni kantaja kuin tulla seivästetyksi?" "Jalomielinen Alp Arslan", vastasi Alroy ilmeisen ylenkatseen äänellä; "luuletko, että mikään kidutus rasittaa niin, kuin se muisto, että sinä olet voittanut minun?" "Partani kautta, hän ivaa minua!" Karamanialaisten hallitsia huudahti; "hän tekee kiusaa minulle! Älkäät koskeko vaippaani. Minä tahdon puhua hänen kanssaan. Te ette näe kauemmaksi kuin hunnustettu haukka, te sokean äidin lapset. Se on noita; hänellä on vielä jälellä joku päätaika; hän pelastaa vielä henkensä. Hän lentää ilmaan taikka vaipuu maan sisään. Hän nauraa meidän kidutuksiamme." Karamanian kuningas astui tuota pikaa valta-istuimensa portaita alaspäin; häntä seurasivat hänen lempiministerinsä ja hänen neuvon-antajansa ja hänen etevimmät päällikkönsä ja kadit ja mollat ja imamit ja kaupungin päähenkilöt. "Sinä noita!" Alp Arslan huudahti, "hävytön noita! halvan äidin halpa poika! koirien koira! niskotteletko sinä meitä vastaan? Kuiskaako herrasi Eblis toivoa sinun korviisi? Nauratko meidän rangaistuksiamme? Aiotko lentää ylös ilmaan? vai painua alas maahan? Niinkö, niinkö?" Hengästyneenä ja vihastansa uupuneena hallitsia vaikeni. Hän repi partaansa ja polki maata rajussa vimmassaan. "Sinä olet viisaampi kuin neuvon-antajasi, kuningas Arslan; minä en nöyrry sinun edessäsi. Minun Herrani, vaikka hän ei ole Eblis, ei ole hylännyt minua. Minä nauran sinun rangaistuksiasi. Sinun kidutuksiasi minä ylenkatson. Minä sekä vaivun maan sisään että kohoan ilmaan. Tyydytkö nyt vastaukseeni?" "Partani kautta", huudahti tulistunut Arslan, "minä tyydyn vastaukseesi. Pelastakoon Eblis sinut, jos hän voi;" ja Karamanian kuningas, Aasian mainioin miekan piteliä veti säilänsä, ikäänkuin salaman, tupesta ja silpaisi yhdellä säväyksellä Alroy''lta pään. Se kaatui, vaan, kun se kaatui, riemuitsevan pilkan hymy näytti vivahtelevan sankarin kylmenevillä kasvoilla ja kysyvän hänen vihollisiltansa: "missä kaikki teidän kidutuksenne nyt ovat?" Do Dzieci Gołąbki i Dziewczynka Dziecię i Koza Wróbel i Jaskółka Osieł i Chłopczyk Nieposłuszny Zajączek Kotek Brytan i Pudelek Egzamin Małego "Misia" Wilk i Owce Lis i Gąski Chłopczyk i Źrebię Gęsia Kapela Lew i Piesek Niedźwiedź i Pszczółka Śniadanie Artysta Z Zimowych Rozrywek Leniwy Chłopczyk Przygoda z Indykiem O hämmästyksissään. Leniwy ЙЦУКЕН' + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 1 + Records affected: 1 + Records affected: 1 + """ + +@pytest.mark.version('>=3.0') +def test_core_2238_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2251.py b/tests/bugs/test_core_2251.py new file mode 100644 index 00000000..ec37fea8 --- /dev/null +++ b/tests/bugs/test_core_2251.py @@ -0,0 +1,178 @@ +#coding:utf-8 +# +# id: bugs.core_2251 +# title: gbak doesn't return error code +# decription: +# Inaccessible folder is defined here as $tmp + GUID (i.e. it 100% not yet exists). +# We have to check allof kind for inaccessible file: +# * .fbk when trying to make backup of existing database; +# * .fdb when trying to restore from existing .fbk; +# * .log - for any of these operation +# We are NOT interested when all of these files are in accessible folder(s). +# +# Query to obtain set of interested combinations (all of them should have retcode = 1): +# with +# a as ( +# select 'backup' as action from rdb$database union all +# select 'restore' from rdb$database +# ) +# ,s as ( +# select 'inaccessible' as path_to_source_file from rdb$database union all +# select 'accessible' from rdb$database +# ) +# ,t as ( +# select 'inaccessible' as path_to_target_file from rdb$database union all +# select 'accessible' from rdb$database +# ) +# ,g as ( +# select 'inaccessible' as path_to_action_log from rdb$database union all +# select 'accessible' from rdb$database +# ) +# select * from a,s,t,g +# where NOT (s.path_to_source_file = 'accessible' and t.path_to_target_file = 'accessible' and g.path_to_action_log = 'accessible') +# order by 1,2,3,4; +# +# Confirmed wrong results on: 4.0.0.1714 SC; 4.0.0.1715 CS; 3.0.5.33221 SC; 3.0.5.33225 CS +# Checked on: +# 4.0.0.1726 SS: 3.759s. +# 3.0.5.33232 SS: 1.671s. +# +# tracker_id: CORE-2251 +# min_versions: ['3.0.5'] +# versions: 3.0.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [('\t+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import uuid +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# correct_fdb=db_conn.database_name +# db_conn.close() +# +# #-------------------------------------------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# +# #-------------------------------------------- +# +# inaccessible_dir = os.path.join(context['temp_directory'], str(uuid.uuid4()) ) +# +# invalid_fdb=os.path.join(inaccessible_dir,'tmp_2251.fdb') +# +# invalid_fbk=os.path.join(inaccessible_dir,'tmp_2251.fbk') +# correct_fbk=os.path.join(context['temp_directory'],'tmp_2251.fbk') +# +# invalid_res=os.path.join(inaccessible_dir,'tmp_2251.tmp') +# correct_res=os.path.join(context['temp_directory'],'tmp_2251.tmp') +# +# invalid_log=os.path.join(inaccessible_dir,'tmp_2251.log') +# correct_log=os.path.join(context['temp_directory'],'tmp_2251.log') +# +# ########################################################################################## +# +# f_null_log = open(os.devnull,"w") +# gbak_retcode = subprocess.call( [context['gbak_path'], '-b', '-se', 'localhost:service_mgr', correct_fdb, correct_fbk, '-y', invalid_log ], stdout=f_null_log, stderr=subprocess.STDOUT) +# print( 'backup source_fdb=accessible target_fbk=accessible log_file=inaccessible:'.ljust(100), gbak_retcode ) +# +# cleanup( (correct_log,) ) +# gbak_retcode = subprocess.call( [context['gbak_path'], '-b', '-se', 'localhost:service_mgr', correct_fdb, invalid_fbk, '-y', correct_log ], stdout=f_null_log, stderr=subprocess.STDOUT) +# print('backup source_fdb=accessible target_fbk=inaccessible log_file=accessible:'.ljust(100), gbak_retcode) +# +# gbak_retcode = subprocess.call( [context['gbak_path'], '-b', '-se', 'localhost:service_mgr', correct_fdb, invalid_fbk, '-y', invalid_log ], stdout=f_null_log, stderr=subprocess.STDOUT) +# print('backup source_fdb=accessible target_fbk=inaccessible log_file=inaccessible:'.ljust(100), gbak_retcode) +# +# cleanup( (correct_log,) ) +# gbak_retcode = subprocess.call( [context['gbak_path'], '-b', '-se', 'localhost:service_mgr', invalid_fdb, correct_fbk, '-y', correct_log ], stdout=f_null_log, stderr=subprocess.STDOUT) +# print('backup source_fdb=inaccessible target_fbk=accessible log_file=accessible:'.ljust(100), gbak_retcode) +# +# gbak_retcode = subprocess.call( [context['gbak_path'], '-b', '-se', 'localhost:service_mgr', invalid_fdb, correct_fbk, '-y', invalid_log ], stdout=f_null_log, stderr=subprocess.STDOUT) +# print('backup source_fdb=inaccessible target_fbk=accessible log_file=inaccessible:'.ljust(100), gbak_retcode) +# +# cleanup( (correct_log,) ) +# gbak_retcode = subprocess.call( [context['gbak_path'], '-b', '-se', 'localhost:service_mgr', invalid_fdb, invalid_fbk, '-y', correct_log ], stdout=f_null_log, stderr=subprocess.STDOUT) +# print('backup source_fdb=inaccessible target_fbk=inaccessible log_file=accessible:'.ljust(100), gbak_retcode) +# +# gbak_retcode = subprocess.call( [context['gbak_path'], '-b', '-se', 'localhost:service_mgr', invalid_fdb, invalid_fbk, '-y', invalid_log ], stdout=f_null_log, stderr=subprocess.STDOUT) +# print('backup source_fdb=inaccessible target_fbk=inaccessible log_file=inaccessible:'.ljust(100), gbak_retcode) +# +# ###################################################################################### +# runProgram('gbak', [ '-b', '-se', 'localhost:service_mgr', correct_fdb, correct_fbk] ) +# ###################################################################################### +# +# gbak_retcode = subprocess.call( [context['gbak_path'], '-rep', '-se', 'localhost:service_mgr', correct_fbk, correct_fdb, '-y', invalid_log ], stdout=f_null_log, stderr=subprocess.STDOUT) +# print( 'restore source_fbk=accessible target_fdb=accessible log_file=inaccessible:'.ljust(100), gbak_retcode ) +# +# cleanup( (correct_log,) ) +# gbak_retcode = subprocess.call( [context['gbak_path'], '-rep', '-se', 'localhost:service_mgr', correct_fbk, invalid_fdb, '-y', correct_log ], stdout=f_null_log, stderr=subprocess.STDOUT) +# print( 'restore source_fbk=accessible target_fdb=inaccessible log_file=accessible:'.ljust(100), gbak_retcode ) +# +# gbak_retcode = subprocess.call( [context['gbak_path'], '-rep', '-se', 'localhost:service_mgr', correct_fbk, invalid_fdb, '-y', invalid_log ], stdout=f_null_log, stderr=subprocess.STDOUT) +# print( 'restore source_fbk=accessible target_fdb=inaccessible log_file=inaccessible:'.ljust(100), gbak_retcode ) +# +# cleanup( (correct_log,) ) +# gbak_retcode = subprocess.call( [context['gbak_path'], '-rep', '-se', 'localhost:service_mgr', invalid_fbk, correct_fdb, '-y', correct_log ], stdout=f_null_log, stderr=subprocess.STDOUT) +# print( 'restore source_fbk=inaccessible target_fdb=accessible log_file=accessible:'.ljust(100), gbak_retcode ) +# +# gbak_retcode = subprocess.call( [context['gbak_path'], '-rep', '-se', 'localhost:service_mgr', invalid_fbk, correct_fdb, '-y', invalid_log ], stdout=f_null_log, stderr=subprocess.STDOUT) +# print( 'restore source_fbk=inaccessible target_fdb=accessible log_file=inaccessible:'.ljust(100), gbak_retcode ) +# +# cleanup( (correct_log,) ) +# gbak_retcode = subprocess.call( [context['gbak_path'], '-rep', '-se', 'localhost:service_mgr', invalid_fbk, invalid_fdb, '-y', correct_log ], stdout=f_null_log, stderr=subprocess.STDOUT) +# print( 'restore source_fbk=inaccessible target_fdb=inaccessible log_file=accessible:'.ljust(100), gbak_retcode ) +# +# gbak_retcode = subprocess.call( [context['gbak_path'], '-rep', '-se', 'localhost:service_mgr', invalid_fbk, invalid_fdb, '-y', invalid_log ], stdout=f_null_log, stderr=subprocess.STDOUT) +# print( 'restore source_fbk=inaccessible target_fdb=inaccessible log_file=inaccessible:'.ljust(100), gbak_retcode ) +# +# f_null_log.close() +# +# cleanup( (correct_log,correct_fbk,) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + backup source_fdb=accessible target_fbk=accessible log_file=inaccessible: 1 + backup source_fdb=accessible target_fbk=inaccessible log_file=accessible: 1 + backup source_fdb=accessible target_fbk=inaccessible log_file=inaccessible: 1 + backup source_fdb=inaccessible target_fbk=accessible log_file=accessible: 1 + backup source_fdb=inaccessible target_fbk=accessible log_file=inaccessible: 1 + backup source_fdb=inaccessible target_fbk=inaccessible log_file=accessible: 1 + backup source_fdb=inaccessible target_fbk=inaccessible log_file=inaccessible: 1 + restore source_fbk=accessible target_fdb=accessible log_file=inaccessible: 1 + restore source_fbk=accessible target_fdb=inaccessible log_file=accessible: 1 + restore source_fbk=accessible target_fdb=inaccessible log_file=inaccessible: 1 + restore source_fbk=inaccessible target_fdb=accessible log_file=accessible: 1 + restore source_fbk=inaccessible target_fdb=accessible log_file=inaccessible: 1 + restore source_fbk=inaccessible target_fdb=inaccessible log_file=accessible: 1 + restore source_fbk=inaccessible target_fdb=inaccessible log_file=inaccessible: 1 + """ + +@pytest.mark.version('>=3.0.5') +@pytest.mark.xfail +def test_core_2251_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2252.py b/tests/bugs/test_core_2252.py new file mode 100644 index 00000000..72fdfc6d --- /dev/null +++ b/tests/bugs/test_core_2252.py @@ -0,0 +1,89 @@ +#coding:utf-8 +# +# id: bugs.core_2252 +# title: EXECUTE STATEMENT on EXTERNAL SOURCE does not check the status of the transaction +# decription: +# tracker_id: CORE-2252 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [('Data source : Firebird.*', 'Data source : Firebird'), ('[-]{0,1}At block line: [\\d]+, col: [\\d]+', 'At block line')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set term ^; + execute block returns (tran_id integer) as + begin + + execute statement 'select sign(current_transaction) from rdb$database' + on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') + as user 'sysdba' password 'masterkey' + into :tran_id; + + suspend; + + execute statement 'commit' + on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') + as user 'sysdba' password 'masterkey'; + + execute statement 'select sign(current_transaction) from rdb$database' + on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') + as user 'sysdba' password 'masterkey' + into :tran_id; + + suspend; + end + ^ + 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TRAN_ID 1 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + Execute statement error at isc_dsql_prepare : + 335544986 : Explicit transaction control is not allowed + Statement : commit + Data source : Firebird::localhost:C:\\FBTESTING\\QA\\FBT-REPO\\TMP\\BUGS.CORE_2252.FDB + -At block line: 11, col: 9 + """ + +@pytest.mark.version('>=2.5.0') +def test_core_2252_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2255.py b/tests/bugs/test_core_2255.py new file mode 100644 index 00000000..06143d60 --- /dev/null +++ b/tests/bugs/test_core_2255.py @@ -0,0 +1,63 @@ +#coding:utf-8 +# +# id: bugs.core_2255 +# title: '...exception...string right truncation' when alter view with join +# decription: +# tracker_id: CORE-2255 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE TEST_VARCHAR ( + ID INTEGER, + CAPTION VARCHAR(1024) +); + +INSERT INTO TEST_VARCHAR (ID, CAPTION) VALUES (1, 'CAP_1'); + +CREATE VIEW P_TEST_VARCHAR( + ID, + CAPTION) +AS +SELECT + T1.ID, + T1.CAPTION +FROM TEST_VARCHAR T1; +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ALTER VIEW P_TEST_VARCHAR( + ID) +AS +SELECT + T1.ID +FROM TEST_VARCHAR T1, TEST_VARCHAR T2 + WHERE T1.ID = T2.ID; + +SELECT * FROM P_TEST_VARCHAR; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID +============ + 1 + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_2255_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2257.py b/tests/bugs/test_core_2257.py new file mode 100644 index 00000000..9df5392b --- /dev/null +++ b/tests/bugs/test_core_2257.py @@ -0,0 +1,59 @@ +#coding:utf-8 +# +# id: bugs.core_2257 +# title: internal Firebird consistency check when alter dependent procedures +# decription: +# tracker_id: CORE-2257 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """set term ^ ; +CREATE OR ALTER PROCEDURE B +AS +begin + +end ^ + +CREATE OR ALTER PROCEDURE A +AS +begin + execute procedure B; +end ^ + +COMMIT WORK ^ + +execute procedure A ^ + +COMMIT WORK ^ + +CREATE OR ALTER PROCEDURE B +AS +begin + +end ^ + +COMMIT WORK ^ + +execute procedure A ^ +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.0') +def test_core_2257_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_2258.py b/tests/bugs/test_core_2258.py new file mode 100644 index 00000000..231f4599 --- /dev/null +++ b/tests/bugs/test_core_2258.py @@ -0,0 +1,77 @@ +#coding:utf-8 +# +# id: bugs.core_2258 +# title: internal error when select upper() from union +# decription: +# tracker_id: CORE-2258 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """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) +; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + BLOB_FIELD +================= + 0:1 +============================================================================== +BLOB_FIELD: +123 +============================================================================== + 0:2 +============================================================================== +BLOB_FIELD: +123 +============================================================================== + + + UPPER +================= + 0:7 +============================================================================== +UPPER: +123 +============================================================================== + 0:a +============================================================================== +UPPER: +123 +============================================================================== + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_2258_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2264.py b/tests/bugs/test_core_2264.py new file mode 100644 index 00000000..891eb3b0 --- /dev/null +++ b/tests/bugs/test_core_2264.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: bugs.core_2264 +# title: ALTER DOMAIN with dependencies may leave a transaction handle in inconsistent state causing segmentation faults +# decription: +# tracker_id: CORE-2264 +# min_versions: [] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create domain d int; + set term ^; + create or alter procedure p1 as + declare v d; + begin + v = v + v; + end + ^ + set term ;^ + commit; + alter domain d type varchar(11); + alter domain d type varchar(11); -- segmentation fault here + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +def test_core_2264_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_2265.py b/tests/bugs/test_core_2265.py new file mode 100644 index 00000000..59269416 --- /dev/null +++ b/tests/bugs/test_core_2265.py @@ -0,0 +1,56 @@ +#coding:utf-8 +# +# id: bugs.core_2265 +# title: Grouping by function doesn't work properly +# decription: +# tracker_id: CORE-2265 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t (col1 date, col2 int); +commit; + +insert into t values ('2011-01-01', 1); +commit; +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select extract(year from col1), sum(col2) +from t +group by extract(year from col1); + +select extract(year from col1), sum(col2) +from t +group by 1; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +EXTRACT SUM +======= ===================== + 2011 1 + + +EXTRACT SUM +======= ===================== + 2011 1 + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_2265_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2268.py b/tests/bugs/test_core_2268.py new file mode 100644 index 00000000..155d0161 --- /dev/null +++ b/tests/bugs/test_core_2268.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: bugs.core_2268 +# title: GFIX causes BUGCHECK errors with non valid transaction numbers +# decription: +# tracker_id: CORE-2268 +# min_versions: [] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('^failed to reconnect to a transaction in database.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# runProgram('gfix',['-user',user_name,'-pas',user_password,'-commit','1000000',dsn]) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """transaction is not in limbo +-transaction 1000000 is in an ill-defined state + +""" + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_2268_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2274.py b/tests/bugs/test_core_2274.py new file mode 100644 index 00000000..0e62a80b --- /dev/null +++ b/tests/bugs/test_core_2274.py @@ -0,0 +1,96 @@ +#coding:utf-8 +# +# id: bugs.core_2274 +# title: MERGE non-standard behaviour, accepts multiple matches +# decription: +# Confirmed bug on 4.0.0.2011 +# Checked on 4.0.0.2022 - works fine. +# +# tracker_id: CORE-2274 +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table t_payment_details(operation_id int primary key, person_id int, payment_sum int); + recreate table t_payment_totals(person_id int primary key, payment_sum int); + commit; + insert into t_payment_details(operation_id, person_id, payment_sum) values(0, 10, 0); + insert into t_payment_details(operation_id, person_id, payment_sum) values(1, 11, 11); + insert into t_payment_details(operation_id, person_id, payment_sum) values(2, 22, 222); + insert into t_payment_details(operation_id, person_id, payment_sum) values(3, 11, 3333); + insert into t_payment_details(operation_id, person_id, payment_sum) values(7, 17, 77777); + + insert into t_payment_totals(person_id, payment_sum) values(10, 100); + insert into t_payment_totals(person_id, payment_sum) values(11, 111); + insert into t_payment_totals(person_id, payment_sum) values(22, 222); + + set list on; + select 'before merge' as msg, e.* from t_payment_totals e order by person_id; + + merge into t_payment_totals t + using t_payment_details s on s.person_id = t.person_id + when NOT matched then + insert(person_id, payment_sum) values( s.person_id, s.payment_sum ) + when MATCHED then + update set t.payment_sum = t.payment_sum + s.payment_sum + ; + + select 'after merge' as msg, e.* from t_payment_totals e order by person_id; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG before merge + PERSON_ID 10 + PAYMENT_SUM 100 + + MSG before merge + PERSON_ID 11 + PAYMENT_SUM 111 + + MSG before merge + PERSON_ID 22 + PAYMENT_SUM 222 + + + + MSG after merge + PERSON_ID 10 + PAYMENT_SUM 100 + + MSG after merge + PERSON_ID 11 + PAYMENT_SUM 111 + + MSG after merge + PERSON_ID 22 + PAYMENT_SUM 222 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 21000 + Multiple source records cannot match the same target during MERGE + """ + +@pytest.mark.version('>=4.0') +def test_core_2274_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2284.py b/tests/bugs/test_core_2284.py new file mode 100644 index 00000000..fdaa6ef9 --- /dev/null +++ b/tests/bugs/test_core_2284.py @@ -0,0 +1,72 @@ +#coding:utf-8 +# +# id: bugs.core_2284 +# title: Records left in RDB$PAGES after rollback of CREATE TABLE statement +# decription: +# This test also covers issues of CORE-5677. +# Bug confirmed on: 3.0.3.32837, 4.0.0.800 +# Checked on: +# 3.0.3.32854: OK, 1.968s. +# 4.0.0.832: OK, 1.282s. +# +# tracker_id: CORE-2284 +# min_versions: ['3.0.3'] +# versions: 3.0.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set autoddl off; + recreate table test_cs__master ( + str_pk varchar(32) character set UTF8 not null, + primary key (str_pk) using index test_s_master_pk + ); + + recreate table test_cs__detail ( + str_pk varchar(32) character set WIN1251 not null, + foreign key (str_pk) references test_cs__master (str_pk) + ); + + commit; -- this will raise: "SQLSTATE = 42000 / -partner index segment no 1 has incompatible data type" + + rollback; + + set list on; + + select count(*) + from rdb$pages + where rdb$relation_id >= (select rdb$relation_id from rdb$database); + + rollback; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + COUNT 0 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -partner index segment no 1 has incompatible data type + """ + +@pytest.mark.version('>=3.0.3') +def test_core_2284_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2289.py b/tests/bugs/test_core_2289.py new file mode 100644 index 00000000..62190e5d --- /dev/null +++ b/tests/bugs/test_core_2289.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: bugs.core_2289 +# title: Wrong (primary) constraint name is reported for the foreign key violation during FK creation +# decription: +# tracker_id: CORE-2289 +# min_versions: ['2.1.7'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table packet_detail(id int, packet_id int); + recreate table packet(id int, constraint packet_pk primary key(id) using index packet_idx); + commit; + insert into packet_detail(id, packet_id) values(1, 753); + commit; + + alter table packet_detail + add constraint packet_detail_fk + foreign key (packet_id) + references packet(id) + using index packet_detail_idx + ; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + 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) + """ + +@pytest.mark.version('>=2.5') +def test_core_2289_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_2291.py b/tests/bugs/test_core_2291.py new file mode 100644 index 00000000..25738bcb --- /dev/null +++ b/tests/bugs/test_core_2291.py @@ -0,0 +1,60 @@ +#coding:utf-8 +# +# id: bugs.core_2291 +# title: BUGCHECK 284 (cannot restore singleton select data (284), file: rse.cpp ...) +# decription: +# tracker_id: CORE-2291 +# min_versions: ['2.0.6'] +# versions: 2.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """recreate table t (id int, f2 char(16)); +commit; + +insert into t values (1, '0123456798012345'); +insert into t values (2, '0123456798012345'); +commit; + +alter table t drop f2; +commit; + +update t set id = 3 where id = 2; +commit; +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """SET TERM !!; +execute block returns (id int) +as +begin + select t1.id from t t1 left join t t2 on t1.id = t2.id - 2 + where t2.id = 3 + into :id; + suspend; +end !! +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID +============ + 1 + +""" + +@pytest.mark.version('>=2.0.6') +def test_core_2291_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2293.py b/tests/bugs/test_core_2293.py new file mode 100644 index 00000000..5138cf50 --- /dev/null +++ b/tests/bugs/test_core_2293.py @@ -0,0 +1,63 @@ +#coding:utf-8 +# +# id: bugs.core_2293 +# title: Wrong dependent object type (RELATION) in RDB$DEPEDENCIES for VIEW's +# decription: +# tracker_id: CORE-2293 +# min_versions: [] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter procedure p_v as begin end; + create or alter view v (id) as select 1 id from rdb$database; + commit; + + set term ^ ; + create or alter procedure p_v as + declare x int; + begin + select id from v into :x; + select 1 from rdb$database into :x; + end ^ + set term ; ^ + commit; + + set list on; + select d.rdb$depended_on_type, t.rdb$type_name -- according to the ticket text we have to check only these two columns + from rdb$dependencies d + join rdb$types t on + d.rdb$depended_on_type = t.rdb$type + and t.rdb$field_name = upper('RDB$OBJECT_TYPE') + where d.rdb$dependent_name = upper('P_V'); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$DEPENDED_ON_TYPE 0 + RDB$TYPE_NAME RELATION + RDB$DEPENDED_ON_TYPE 1 + RDB$TYPE_NAME VIEW + RDB$DEPENDED_ON_TYPE 1 + RDB$TYPE_NAME VIEW + """ + +@pytest.mark.version('>=2.5') +def test_core_2293_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2300.py b/tests/bugs/test_core_2300.py new file mode 100644 index 00000000..98422510 --- /dev/null +++ b/tests/bugs/test_core_2300.py @@ -0,0 +1,58 @@ +#coding:utf-8 +# +# id: bugs.core_2300 +# title: Unexpected error "arithmetic exception, numeric overflow, or string truncation" while evaluating SUBSTRING the second time +# decription: +# tracker_id: CORE-2300 +# min_versions: [] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """set term ^ ; +create procedure p + returns ( res varchar(10) ) +as begin + res = null; + suspend; + res = '0123456789'; + suspend; +end ^ +set term ; ^ +commit;""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select substring(res from 1 for 5) from p order by 1; -- success +select substring(res from 1 for 5) from p order by 1; -- error +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +SUBSTRING +========= + +01234 + + +SUBSTRING +========= + +01234 + +""" + +@pytest.mark.version('>=3.0') +def test_core_2300_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2303.py b/tests/bugs/test_core_2303.py new file mode 100644 index 00000000..9905d81a --- /dev/null +++ b/tests/bugs/test_core_2303.py @@ -0,0 +1,64 @@ +#coding:utf-8 +# +# id: bugs.core_2303 +# title: Include PLAN in mon$statements +# decription: +# 21-05-2017: +# fb30Cs, build 3.0.3.32725: OK, 1.406ss. +# fb30SC, build 3.0.3.32725: OK, 0.828ss. +# FB30SS, build 3.0.3.32725: OK, 0.829ss. +# FB40CS, build 4.0.0.645: OK, 1.718ss. +# FB40SC, build 4.0.0.645: OK, 0.968ss. +# FB40SS, build 4.0.0.645: OK, 0.969ss. +# +# tracker_id: CORE-2303 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('MON_EXPLAINED_BLOB_ID .*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set blob all; + set list on; + commit; + select + (select sign(count(*)) from rdb$relations r) + ,s.mon$explained_plan as mon_explained_blob_id + from mon$statements s + where + s.mon$transaction_id = current_transaction + and s.mon$sql_text containing 'from mon$statements' -- prevent from RDB$AUTH record, 4.0 Classic + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + SIGN 1 + + Select Expression + -> Singularity Check + -> Aggregate + -> Table "RDB$RELATIONS" as "R" Full Scan + Select Expression + -> Filter + -> Table "MON$STATEMENTS" as "S" Full Scan + """ + +@pytest.mark.version('>=3.0') +def test_core_2303_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2305.py b/tests/bugs/test_core_2305.py new file mode 100644 index 00000000..ef1b87da --- /dev/null +++ b/tests/bugs/test_core_2305.py @@ -0,0 +1,124 @@ +#coding:utf-8 +# +# id: bugs.core_2305 +# title: Make mon$statement_id value constant among monitoring snapshots +# decription: +# tracker_id: CORE-2305 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test(monitoring_att_id int, running_stt_id int); + commit; + + set term ^; + execute block as + declare monitoring_att_id int; + declare running_stt_id int; + declare v_dbname varchar(255); + declare v_stt varchar(1024); + declare v_usr rdb$user = 'sysdba'; + declare v_pwd varchar(20) = 'masterkey'; + declare v_trn int; + begin + + v_dbname = 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME'); + v_stt = + 'select current_connection, s.mon$statement_id ' + || 'from mon$statements s ' + || 'where s.mon$transaction_id = :x ' + || 'order by s.mon$statement_id rows 1'; + v_trn = current_transaction; + + execute statement (v_stt) ( x := v_trn ) + into monitoring_att_id, running_stt_id; + + insert into test( monitoring_att_id, running_stt_id) + values(:monitoring_att_id, :running_stt_id); + + execute statement (v_stt) ( x := v_trn ) + on external (v_dbname) + as user :v_usr password :v_pwd role 'R_001' + into monitoring_att_id, running_stt_id; + + insert into test( monitoring_att_id, running_stt_id) + values(:monitoring_att_id, :running_stt_id); + + + execute statement (v_stt) ( x := v_trn ) + on external (v_dbname) + as user :v_usr password :v_pwd role 'R_002' + into monitoring_att_id, running_stt_id; + + insert into test( monitoring_att_id, running_stt_id) + values(:monitoring_att_id, :running_stt_id); + + end + ^ + set term ;^ + + -- select * from test; + -- Output of select * from test in 2.5.0: + -- MONITORING_ATT_ID RUNNING_STT_ID + -- ================= ============== + -- 6 5 + -- 7 11 + -- 8 11 + + -- Output of select * from test since 2.5.1: + -- MONITORING_ATT_ID RUNNING_STT_ID + -- ================= ============== + -- 9 122 + -- 10 122 + -- 11 122 + + set list on; + select + count(distinct monitoring_att_id) as num_of_mon$statement_observers + ,count(distinct running_stt_id) as distinct_statement_id_they_saw + from test; + + 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + NUM_OF_MON$STATEMENT_OBSERVERS 3 + DISTINCT_STATEMENT_ID_THEY_SAW 1 + """ + +@pytest.mark.version('>=2.5.1') +def test_core_2305_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2307.py b/tests/bugs/test_core_2307.py new file mode 100644 index 00000000..fdf1ec3b --- /dev/null +++ b/tests/bugs/test_core_2307.py @@ -0,0 +1,179 @@ +#coding:utf-8 +# +# id: bugs.core_2307 +# title: Incomplete API information values +# decription: +# Test creates lot of tables with names starting with 'TEST'. +# Then we retrieve from rdb$relations min and max values of this tables ID ('r_min', 'r_max'). +# After each table is scanned via execute statement, statistics that we retrieve by call db_into() +# is filled with pair: {relation_id, number_of_seq_reads}. +# We have to ckeck that number of entries in this set with r_min <= relation_id <= rmax NOT LESS than +# number of created tables. +# Also, scan for every table should take at least 1 sequential read - and this is checked too. +# +# NOTE: we can SKIP checking concrete values of 'number_of_seq_reads', it does not matter in this test! +# +# See also: +# http://pythonhosted.org/fdb/reference.html#fdb.Connection.database_info +# +# Info about 'isc_info_read_seq_count': +# Number of sequential database reads, that is, the number of sequential table scans (row reads) +# Reported per table. +# Calculated since the current database attachment started. +# +# Confirmed bug on WI-V2.1.2.18118: db_into() received imcompleted data (i.e. not for all tables). +# +# tracker_id: CORE-2307 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import subprocess +# import fdb +# +# db_file=db_conn.database_name +# db_conn.close() +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# +# # Change FW to OFF in order to speed up initial data filling: +# ################## +# +# fn_nul = open(os.devnull, 'w') +# subprocess.call([ context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "prp_write_mode", "prp_wm_async", +# "dbname", db_file ], +# stdout = fn_nul, +# stderr = subprocess.STDOUT +# ) +# fn_nul.close() +# +# # prepare DB for testing: create lot of tables: +# ############################################### +# f_work_sql=open( os.path.join(context['temp_directory'],'tmp_work_2307.sql'), 'w') +# +# num_of_tables = 1000 +# +# sql_ddl=''' +# set term ^; +# Execute block as +# declare variable i integer = 0; +# begin +# while ( i < %(num_of_tables)s ) +# do +# begin +# execute statement 'create table test' || cast(:i as varchar(5)) || ' (c integer)'; +# i = i + 1 ; +# end +# end ^ +# commit ^ +# +# execute block as +# declare variable i integer = 0; +# begin +# while (i < %(num_of_tables)s ) +# do +# begin +# execute statement 'insert into test' || cast(:i as varchar(5)) || ' (c) values (1)'; +# i = i + 1 ; +# end +# end +# ^ +# set term ;^ +# commit; +# ''' % locals() +# +# f_work_sql.write(sql_ddl) +# f_work_sql.close() +# +# f_work_log=open( os.path.join(context['temp_directory'],'tmp_work_2307.log'), 'w') +# f_work_err=open( os.path.join(context['temp_directory'],'tmp_work_2307.err'), 'w') +# subprocess.call( [ context['isql_path'], dsn, "-i", f_work_sql.name], +# stdout = f_work_log, +# stderr = f_work_err +# ) +# +# f_work_log.close() +# f_work_err.close() +# +# sql_dml = ''' +# execute block returns(r_min int, r_max int) as +# declare n varchar(31); +# declare i integer; +# begin +# for +# select min(rdb$relation_id),max(rdb$relation_id) +# from rdb$relations +# where rdb$relation_name starting with upper('test') +# into r_min, r_max +# do +# suspend; +# +# for +# select rdb$relation_name +# from rdb$relations +# -- 4 debug only! >> rows 100 +# into :n +# do +# execute statement 'select 1 as k from ' || :n || ' rows 1' into :i; +# end +# ''' +# +# con = fdb.connect(dsn=dsn) +# cur = con.cursor() +# cur.execute(sql_dml) +# r_min=99999999 +# r_max=-9999999 +# for r in cur: +# r_min=r[0] # minimal ID in rdb$relations for user tables ('TEST1') +# r_max=r[1] # maximal ID in rdb$relations for user tables ('TESTnnnnn') +# +# info = con.db_info(fdb.isc_info_read_seq_count) +# cnt=0 +# for k,v in info.items(): +# cnt = cnt+1 if k >= r_min and k <= r_max and v >= 1 else cnt +# +# print( 'OK' if cnt >= num_of_tables else 'FAILED: db_info(fdb.isc_info_read_seq_count) contains only '+str(cnt)+' entries for scanned '+str(num_of_tables)+ ' user tables.' ) +# +# #for k, v in sorted(info.items()): +# # print('page: '+str(k).zfill(8) + ', num of seq_reads: '+str(v).zfill(8) ) +# +# # Cleanup. +# ############################### +# +# f_list=[f_work_sql,f_work_log,f_work_err] +# for i in range(len(f_list)): +# if os.path.isfile(f_list[i].name): +# os.remove(f_list[i].name) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + OK + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_2307_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2308.py b/tests/bugs/test_core_2308.py new file mode 100644 index 00000000..cdb0d87b --- /dev/null +++ b/tests/bugs/test_core_2308.py @@ -0,0 +1,55 @@ +#coding:utf-8 +# +# id: bugs.core_2308 +# title: SIMILAR TO produces random results with [x-y] expressions +# decription: +# tracker_id: CORE-2308 +# min_versions: [] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """set term ^ ; +CREATE OR ALTER PROCEDURE PROC +RETURNS ( V INTEGER) +AS + BEGIN + IF ('b' SIMILAR TO ('[a-z]')) + THEN v = 1; + ELSE v = 2; + SUSPEND; +END ^ +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """set term ^ ; +EXECUTE BLOCK AS +DECLARE I INT = 1000; +DECLARE V INT; +BEGIN + WHILE (I > 0) DO + BEGIN + I = I - 1; + SELECT V FROM PROC INTO :V; + + IF (V <> 1) + THEN V = 1/0; + END +END ^ +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5') +def test_core_2308_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_2315.py b/tests/bugs/test_core_2315.py new file mode 100644 index 00000000..1370f54c --- /dev/null +++ b/tests/bugs/test_core_2315.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: bugs.core_2315 +# title: Firebird float support does not conform to Interbase spec +# decription: +# tracker_id: CORE-2315 +# min_versions: [] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table float_test (i integer, f float); +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """insert into float_test values (1, 3.0); +insert into float_test values (1, 3.402823466e+38); +select * from float_test; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + I F +============ ============== + 1 3.0000000 + 1 3.4028235e+38 + +""" + +@pytest.mark.version('>=2.5') +def test_core_2315_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2317.py b/tests/bugs/test_core_2317.py new file mode 100644 index 00000000..42a9e0ff --- /dev/null +++ b/tests/bugs/test_core_2317.py @@ -0,0 +1,64 @@ +#coding:utf-8 +# +# id: bugs.core_2317 +# title: select * from (select cast(.... returns null +# decription: +# tracker_id: CORE-2317 +# min_versions: [] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """ + CREATE TABLE PROC( + PROC Char(10) NOT NULL, + TPRO Char(10) NOT NULL, + ACTO Varchar(200) NOT NULL, + CONSTRAINT PROC_PK PRIMARY KEY (PROC) + ); + + CREATE TABLE TPRO( + TPRO Char(10) NOT NULL, + CONSTRAINT TPRO_PK PRIMARY KEY (TPRO) + ); + + CREATE VIEW PROC1 (PROC, ACTO) + AS SELECT "PROC"."PROC","PROC"."ACTO" FROM "PROC" left outer join "TPRO" on "PROC"."TPRO"="TPRO"."TPRO"; + + insert into proc values ('1R1oK3qxdM', '1', '2'); + insert into tpro values ('1'); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + -- returns NULL + select * from (select cast("ACTO" as character(100)) as "D_COL1" from "PROC1" where "PROC"='1R1oK3qxdM') AA; + -- returns the correct value + select * from (select cast("ACTO" as character(100)) as "D_COL1" from "PROC" where "PROC"='1R1oK3qxdM') AA; + select * from (select "ACTO" as "D_COL1" from "PROC1" where "PROC"='1R1oK3qxdM') AA; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + D_COL1 2 + D_COL1 2 + D_COL1 2 + """ + +@pytest.mark.version('>=2.5') +def test_core_2317_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2331.py b/tests/bugs/test_core_2331.py new file mode 100644 index 00000000..e328b9cc --- /dev/null +++ b/tests/bugs/test_core_2331.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: bugs.core_2331 +# title: ALTER DOMAIN invalid RDB$FIELD_SUB_TYPE +# decription: +# tracker_id: CORE-2331 +# min_versions: [] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN TESTDOM VARCHAR(50); +COMMIT; +ALTER DOMAIN TESTDOM TYPE VARCHAR(80); +COMMIT; + +SELECT RDB$FIELD_SUB_TYPE FROM RDB$FIELDS WHERE RDB$FIELD_NAME = 'TESTDOM'; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +RDB$FIELD_SUB_TYPE +================== + 0 + +""" + +@pytest.mark.version('>=2.5') +def test_core_2331_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2339.py b/tests/bugs/test_core_2339.py new file mode 100644 index 00000000..79b8708c --- /dev/null +++ b/tests/bugs/test_core_2339.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: bugs.core_2339 +# title: Incorrect result for the derived expression based on aggregate and computation +# decription: +# tracker_id: CORE-2339 +# min_versions: [] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select * from (select sum(1)*1 as x from rdb$database); +-- result is NULL instead of 1""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + X +===================== + 1 + +""" + +@pytest.mark.version('>=2.5') +def test_core_2339_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2341.py b/tests/bugs/test_core_2341.py new file mode 100644 index 00000000..31fed2fa --- /dev/null +++ b/tests/bugs/test_core_2341.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: bugs.core_2341 +# title: Hidden variables conflict with output parameters, causing assertions, unexpected errors or possibly incorrect results +# decription: +# tracker_id: CORE-2341 +# min_versions: [] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# c = db_conn.cursor() +# +# cmd = c.prep("""execute block (i varchar(10) = ?) returns (o varchar(10)) +# as +# begin +# o = coalesce(cast(o as date), current_date); +# o = i; +# suspend; +# end""") +# c.execute(cmd,['asd']) +# printData(c) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """O +---------- +asd +""" + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_2341_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2350.py b/tests/bugs/test_core_2350.py new file mode 100644 index 00000000..96596140 --- /dev/null +++ b/tests/bugs/test_core_2350.py @@ -0,0 +1,304 @@ +#coding:utf-8 +# +# id: bugs.core_2350 +# title: Too long column name for select alias should be rejected +# decription: +# 26.01.2019, code for FB 4.0: added filtering 'where rdb$system_flag is distinct from 1' for query to rdb$procedures. +# Currently there is one system-defined package (RDB$TIME_ZONE_UTIL) and one stand-alone procedure (RDB$TRANSITIONS) +# Checked on: +# 3.0.4.33034: OK, 2.906s. +# 3.0.5.33097: OK, 1.453s. +# 4.0.0.1340: OK, 2.328s. +# 4.0.0.1410: OK, 2.453s. +# +# tracker_id: CORE-2350 +# min_versions: ['3.0'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table t1 (i integer); + commit; + + insert into t1 values(1); + commit; + + set list on; + --set echo on; + + select i as i23456789012345678901234567890123456 from t1; + select i23456789012345678901234567890123456 + from ( + select i as i23456789012345678901234567890123456 + from t1 + ); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_core_2350_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + +# version: 4.0 +# resources: None + +substitutions_2 = [('-At line[:]{0,1}[\\s]+[\\d]+,[\\s]+column[:]{0,1}[\\s]+[\\d]+', '')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set list on; + select '- column title, ASCII, width = 63' as + i23456789012345678901234567890123456789012345678901234567890123 + from rdb$database; + + select '- column title, ASCII, width = 64' as + i234567890123456789012345678901234567890123456789012345678901234 + from rdb$database; + + select '- column title, UTF8, width = 63' as + "ЛевНиколаевичТолстойАннаКаренинаМнеотмщениеиазвоздамЧАСТЬПЕРВАЯ" + from rdb$database; + + select '- column title, UTF8, width = 64' as + "ЛевНиколаевичТолстойАннаКаренинаМнеотмщениеиазвоздамЧАСТЬПЕРВАЯВ" + from rdb$database; + + set term ^; + + create or alter procedure sp_63a returns(o1 double precision) as + declare + v23456789012345678901234567890123456789012345678901234567890123 + int; + begin + select rand()*1000 as + a23456789012345678901234567890123456789012345678901234567890123 + from rdb$database as + t23456789012345678901234567890123456789012345678901234567890123 + into + v23456789012345678901234567890123456789012345678901234567890123; + o1 = sqrt( + v23456789012345678901234567890123456789012345678901234567890123 + ); + suspend; + end + ^ + + create or alter procedure sp_63u returns(o1 double precision) as + declare + "ЛевНиколаевичТолстойАннаКаренинаМнеотмщениеиазвоздамЧАСТЬПЕРВАЯ" + int; + begin + select rand()*1000 as + "ЛевНиколаевичТолстойАннаКаренинаМнеотмщениеиазвоздамЧАСТЬПЕРВАЯ" + from rdb$database as + "ЛевНиколаевичТолстойАннаКаренинаМнеотмщениеиазвоздамЧАСТЬПЕРВАЯ" + into + "ЛевНиколаевичТолстойАннаКаренинаМнеотмщениеиазвоздамЧАСТЬПЕРВАЯ"; + o1 = sqrt( + "ЛевНиколаевичТолстойАннаКаренинаМнеотмщениеиазвоздамЧАСТЬПЕРВАЯ" + ); + suspend; + end + ^ + + create or alter procedure sp_64u1 returns(o1 double precision) as + declare + "ЛевНиколаевичТолстойАннаКаренинаМнеотмщениеиазвоздамЧАСТЬПЕРВАЯ1" -- 64 characters, UTF8 + int; + begin + select rand()*1000 as + "ЛевНиколаевичТолстойАннаКаренинаМнеотмщениеиазвоздамЧАСТЬПЕРВАЯ" + from rdb$database as + "ЛевНиколаевичТолстойАннаКаренинаМнеотмщениеиазвоздамЧАСТЬПЕРВАЯ" + into + "ЛевНиколаевичТолстойАннаКаренинаМнеотмщениеиазвоздамЧАСТЬПЕРВАЯ1"; + o1 = sqrt( + "ЛевНиколаевичТолстойАннаКаренинаМнеотмщениеиазвоздамЧАСТЬПЕРВАЯ1" + ); + suspend; + end + ^ + + create or alter procedure sp_64u2 returns(o1 double precision) as + declare + "ЛевНиколаевичТолстойАннаКаренинаМнеотмщениеиазвоздамЧАСТЬПЕРВАЯ" + int; + begin + select rand()*1000 as + "ЛевНиколаевичТолстойАннаКаренинаМнеотмщениеиазвоздамЧАСТЬПЕРВАЯ1" -- 64 characters, UTF8 + from rdb$database as + "ЛевНиколаевичТолстойАннаКаренинаМнеотмщениеиазвоздамЧАСТЬПЕРВАЯ" + into + "ЛевНиколаевичТолстойАннаКаренинаМнеотмщениеиазвоздамЧАСТЬПЕРВАЯ"; + o1 = sqrt( + "ЛевНиколаевичТолстойАннаКаренинаМнеотмщениеиазвоздамЧАСТЬПЕРВАЯ" + ); + suspend; + end + ^ + create or alter procedure sp_64u3 returns(o1 double precision) as + declare + "ЛевНиколаевичТолстойАннаКаренинаМнеотмщениеиазвоздамЧАСТЬПЕРВАЯ" + int; + begin + select rand()*1000 as + "ЛевНиколаевичТолстойАннаКаренинаМнеотмщениеиазвоздамЧАСТЬПЕРВАЯ" + from rdb$database as + "ЛевНиколаевичТолстойАннаКаренинаМнеотмщениеиазвоздамЧАСТЬПЕРВАЯ1" -- 64 characters, UTF8 + into + "ЛевНиколаевичТолстойАннаКаренинаМнеотмщениеиазвоздамЧАСТЬПЕРВАЯ"; + o1 = sqrt( + "ЛевНиколаевичТолстойАннаКаренинаМнеотмщениеиазвоздамЧАСТЬПЕРВАЯ" + ); + suspend; + end + ^ + + create or alter procedure sp_64a1 returns(o1 double precision) as + declare + v234567890123456789012345678901234567890123456789012345678901234 -- 64 characters, ascii + int; + begin + select rand()*1000 as + a23456789012345678901234567890123456789012345678901234567890123 + from rdb$database as + t23456789012345678901234567890123456789012345678901234567890123 + into + v234567890123456789012345678901234567890123456789012345678901234; + o1 = sqrt( + v23456789012345678901234567890123456789012345678901234567890123 + ); + suspend; + end + ^ + create or alter procedure sp_64a2 returns(o1 double precision) as + declare + v23456789012345678901234567890123456789012345678901234567890123 + int; + begin + select rand()*1000 as + a234567890123456789012345678901234567890123456789012345678901234 -- 64 characters, ascii + from rdb$database as + t23456789012345678901234567890123456789012345678901234567890123 + into + v23456789012345678901234567890123456789012345678901234567890123; + o1 = sqrt( + v23456789012345678901234567890123456789012345678901234567890123 + ); + suspend; + end + ^ + create or alter procedure sp_64a3 returns(o1 double precision) as + declare + v23456789012345678901234567890123456789012345678901234567890123 + int; + begin + select rand()*1000 as + a23456789012345678901234567890123456789012345678901234567890123 + from rdb$database as + t234567890123456789012345678901234567890123456789012345678901234 -- 64 characters, ascii + into + v23456789012345678901234567890123456789012345678901234567890123; + o1 = sqrt( + v23456789012345678901234567890123456789012345678901234567890123 + ); + suspend; + end + ^ + set term ;^ + commit; + set list on; + set count on; + select rdb$procedure_name from rdb$procedures where rdb$system_flag is distinct from 1; + + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + I23456789012345678901234567890123456789012345678901234567890123 - column title, ASCII, width = 63 + ЛевНиколаевичТолстойАннаКаренинаМнеотмщениеиазвоздамЧАСТЬПЕРВАЯ - column title, UTF8, width = 63 + RDB$PROCEDURE_NAME SP_63A + RDB$PROCEDURE_NAME SP_63U + Records affected: 2 + """ +expected_stderr_2 = """ + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + """ + +@pytest.mark.version('>=4.0') +def test_core_2350_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_expected_stderr == act_2.clean_stderr + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/bugs/test_core_2355.py b/tests/bugs/test_core_2355.py new file mode 100644 index 00000000..4fd0fcce --- /dev/null +++ b/tests/bugs/test_core_2355.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_2355 +# title: Incorrect handling of LOWER/UPPER when result string shrinks in terms of byte length +# decription: +# tracker_id: CORE-2355 +# min_versions: [] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT LOWER('İA') FROM RDB$DATABASE; +SELECT LOWER('AӴЁΪΣƓİ') FROM RDB$DATABASE; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +LOWER +====== +ia + + +LOWER +======= +aӵёϊσɠi + +""" + +@pytest.mark.version('>=3.0') +def test_core_2355_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2359.py b/tests/bugs/test_core_2359.py new file mode 100644 index 00000000..28c4124c --- /dev/null +++ b/tests/bugs/test_core_2359.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_2359 +# title: Logical multibyte maximum string length is not respected when assigning numbers +# decription: +# tracker_id: CORE-2359 +# min_versions: [] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t (c varchar(2) character set utf8); + +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """insert into t values ('aaaaaaaa'); -- error: ok +insert into t values (12345678); -- pass: not ok +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 22001 +arithmetic exception, numeric overflow, or string truncation +-string right truncation +-expected length 2, actual 8 +Statement failed, SQLSTATE = 22001 +arithmetic exception, numeric overflow, or string truncation +-string right truncation +-expected length 2, actual 8 +""" + +@pytest.mark.version('>=3.0') +def test_core_2359_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_2361.py b/tests/bugs/test_core_2361.py new file mode 100644 index 00000000..416f87e3 --- /dev/null +++ b/tests/bugs/test_core_2361.py @@ -0,0 +1,69 @@ +#coding:utf-8 +# +# id: bugs.core_2361 +# title: String truncation reading 8859-1 Spanish column using isc_dsql_fetch with UTF-8 connection.. +# decription: +# tracker_id: CORE-2361 +# min_versions: [] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table "'Master by Reseller$'" ( + "Tier" VARCHAR(20) CHARACTER SET ISO8859_1 COLLATE ES_ES_CI_AI +); + +commit; + +insert into "'Master by Reseller$'" ( "Tier" ) VALUES ('(blank)'); +insert into "'Master by Reseller$'" ( "Tier" ) VALUES ('Approved'); +insert into "'Master by Reseller$'" ( "Tier" ) VALUES ('Bronze'); +insert into "'Master by Reseller$'" ( "Tier" ) VALUES ('DMR'); +insert into "'Master by Reseller$'" ( "Tier" ) VALUES ('Domestic Distributor'); +insert into "'Master by Reseller$'" ( "Tier" ) VALUES ('End-User'); +insert into "'Master by Reseller$'" ( "Tier" ) VALUES ('Evaluation'); +insert into "'Master by Reseller$'" ( "Tier" ) VALUES ('Gold'); +insert into "'Master by Reseller$'" ( "Tier" ) VALUES ('New'); +insert into "'Master by Reseller$'" ( "Tier" ) VALUES ('Silver'); +insert into "'Master by Reseller$'" ( "Tier" ) VALUES ('VAM'); + +commit; +""" + +db_1 = db_factory(page_size=4096, charset='ISO8859_1', sql_dialect=3, init=init_script_1) + +test_script_1 = """select case when 1 = 0 then '(blank)' else "'Master by Reseller$'"."Tier" end from "'Master by Reseller$'"; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +CASE +==================== +(blank) +Approved +Bronze +DMR +Domestic Distributor +End-User +Evaluation +Gold +New +Silver +VAM + +""" + +@pytest.mark.version('>=3.0') +def test_core_2361_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2374.py b/tests/bugs/test_core_2374.py new file mode 100644 index 00000000..9659eb86 --- /dev/null +++ b/tests/bugs/test_core_2374.py @@ -0,0 +1,58 @@ +#coding:utf-8 +# +# id: bugs.core_2374 +# title: ALTER TRIGGER / PROCEDURE wrong error message +# decription: +# tracker_id: CORE-2374 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + alter procedure test1 as + begin + if (a = b) then + b = 1; + end + ^ + alter trigger trg1 as + begin + if (a = b) then + b = 1; + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + 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_core_2374_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_2386.py b/tests/bugs/test_core_2386.py new file mode 100644 index 00000000..ea98660a --- /dev/null +++ b/tests/bugs/test_core_2386.py @@ -0,0 +1,58 @@ +#coding:utf-8 +# +# id: bugs.core_2386 +# title: ALTER VIEW could remove column used in stored procedure or trigger +# decription: +# tracker_id: CORE-2386 +# min_versions: [] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """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 +^ +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ALTER VIEW V_TEST (F1) AS + SELECT 1 FROM RDB$DATABASE ;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42000 +unsuccessful metadata update +-cannot delete +-COLUMN V_TEST.F2 +-there are 1 dependencies +""" + +@pytest.mark.version('>=2.5') +def test_core_2386_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_2389.py b/tests/bugs/test_core_2389.py new file mode 100644 index 00000000..db62a34e --- /dev/null +++ b/tests/bugs/test_core_2389.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: bugs.core_2389 +# title: Wrong matching of SIMILAR TO expression with brackets +# decription: +# tracker_id: CORE-2389 +# min_versions: [] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select 1 from rdb$database where 'x/t' SIMILAR TO '%[/]t'; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CONSTANT +============ + 1 + +""" + +@pytest.mark.version('>=2.5') +def test_core_2389_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2397.py b/tests/bugs/test_core_2397.py new file mode 100644 index 00000000..c0f042fe --- /dev/null +++ b/tests/bugs/test_core_2397.py @@ -0,0 +1,51 @@ +#coding:utf-8 +# +# id: bugs.core_2397 +# title: If you drop two different indexes within the same transaction, you get database corruption +# decription: +# tracker_id: CORE-2397 +# min_versions: [] +# versions: 2.1.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table test(id int, title varchar(50)); +commit; +create index test1 on test computed by (id +1); +create index test2 on test computed by (id +2); +commit; +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """SET AUTODDL OFF; +drop index test1; +drop index test2; +commit; +insert into test values(1,'test'); +commit; +SELECT id from test; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID +============ + 1 + +""" + +@pytest.mark.version('>=2.1.3') +def test_core_2397_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2408.py b/tests/bugs/test_core_2408.py new file mode 100644 index 00000000..e79b48cc --- /dev/null +++ b/tests/bugs/test_core_2408.py @@ -0,0 +1,268 @@ +#coding:utf-8 +# +# id: bugs.core_2408 +# title: isql -ex puts default values of sp parameters before the NOT NULL and COLLATE flags +# decription: +# Quote from ticket: "make a procedure with NOT NULL and/or COLLATE flags *and* a default value on any parameter". +# Test enchances this by checking not only procedure but also function and package. +# Also, check is performed for table (I've encountered the same for TABLES definition in some old databases). +# +# Algorithm is similar to test for core-5089: we create several DB objects which do have properties from ticket. +# Then we extract metadata and save it into file as 'initial' text. +# After this we drop all objects and make attempt to APPLY just extracted metadata script. It should perform without errors. +# Finally, we extract metadata again and do COMPARISON of their current content and those which are stored 'initial' file. +# +# Checked on: WI-V3.0.0.32328 (SS/CS/SC). +# +# tracker_id: CORE-2408 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + set bail on; + set autoddl off; + commit; + + create collation nums_coll for utf8 from unicode case insensitive 'NUMERIC-SORT=1'; + create collation name_coll for utf8 from unicode no pad case insensitive accent insensitive; + + create domain dm_test varchar(20) character set utf8 default 'foo' not null collate nums_coll; + + create table test( + s1 varchar(20) character set utf8 default 'foo' not null collate nums_coll + ,s2 dm_test + ,s3 dm_test default 'bar' + ,s4 dm_test default 'rio' collate name_coll + ); + + set term ^; + create or alter procedure sp_test( + p1 varchar(20) character set utf8 not null collate nums_coll default 'foo' + ,p2 dm_test default 'qwe' + ,p3 dm_test default 'bar' + ,p4 dm_test collate name_coll default 'rio' + ) returns ( + o1 varchar(80) + ,o2 dm_test collate name_coll + ) + as + begin + o1 = lower(p1 || p2 || p3); + o2 = upper(p4); + suspend; + end + ^ + + create or alter function fn_test( + p1 varchar(20) character set utf8 not null collate nums_coll default 'foo' + ,p2 dm_test default 'qwe' + ,p3 dm_test default 'bar' + ,p4 dm_test collate name_coll default 'rio' + ) returns dm_test collate name_coll + as + begin + return lower(left(p1,5) || left(p2,5) || left(p3,5) || left(p4,5)); + end + ^ + + recreate package pg_test as + begin + procedure pg_proc( + p1 varchar(20) character set utf8 not null collate nums_coll default 'foo' + ,p2 dm_test default 'qwe' + ,p3 dm_test default 'bar' + ,p4 dm_test collate name_coll default 'rio' + ) returns ( + o1 varchar(80) + ,o2 dm_test collate name_coll + ); + function pg_func( + p1 varchar(20) character set utf8 not null collate nums_coll default 'foo' + ,p2 dm_test default 'qwe' + ,p3 dm_test default 'bar' + ,p4 dm_test collate name_coll default 'rio' + ) returns dm_test collate name_coll; + end + ^ + + create package body pg_test as + begin + procedure pg_proc( + p1 varchar(20) character set utf8 not null collate nums_coll + ,p2 dm_test + ,p3 dm_test + ,p4 dm_test collate name_coll + ) returns ( + o1 varchar(80) + ,o2 dm_test collate name_coll + ) as + begin + o1 = lower(p1 || p2 || p3); + o2 = upper(p4); + suspend; + end + + function pg_func( + p1 varchar(20) character set utf8 not null collate nums_coll + ,p2 dm_test + ,p3 dm_test + ,p4 dm_test collate name_coll + ) returns dm_test collate name_coll as + begin + return lower(left(p1,5) || left(p2,5) || left(p3,5) || left(p4,5)); + end + end + ^ + set term ;^ + commit; + """ + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import subprocess +# import time +# import difflib +# +# #----------------------------------- +# +# 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() +# os.fsync(file_handle.fileno()) +# +# file_handle.close() +# +# #-------------------------------------------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #------------------------------------------- +# +# db_file=db_conn.database_name +# db_conn.close() +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# f_extract_initial_meta_sql = open( os.path.join(context['temp_directory'],'tmp_meta_2408_init.sql'), 'w') +# subprocess.call( [ context['isql_path'], dsn, "-x", "-ch", "utf8" ], +# stdout = f_extract_initial_meta_sql, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_extract_initial_meta_sql ) +# +# ddl_clear_all=''' +# drop package pg_test; +# drop function fn_test; +# drop procedure sp_test; +# drop table test; +# drop domain dm_test; +# drop collation name_coll; +# drop collation nums_coll; +# commit; +# ''' +# +# f_meta_drop_all_sql = open( os.path.join(context['temp_directory'],'tmp_meta_2408_drop_all.sql'), 'w') +# f_meta_drop_all_sql.write(ddl_clear_all) +# flush_and_close( f_meta_drop_all_sql ) +# +# f_meta_drop_all_log = open( os.path.join(context['temp_directory'],'tmp_meta_2408_drop_all.log'), 'w') +# subprocess.call( [ context['isql_path'], dsn, "-i", f_meta_drop_all_sql.name, "-ch", "utf8" ], +# stdout = f_meta_drop_all_log, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_meta_drop_all_log ) +# +# +# f_apply_extracted_meta_log = open( os.path.join(context['temp_directory'],'tmp_meta_2408_apply.log'), 'w') +# subprocess.call( [ context['isql_path'], dsn, "-i", f_extract_initial_meta_sql.name, "-ch", "utf8" ], +# stdout = f_apply_extracted_meta_log, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_apply_extracted_meta_log ) +# +# f_extract_current_meta_sql = open( os.path.join(context['temp_directory'],'tmp_meta_2408_last.sql'), 'w') +# subprocess.call( [ context['isql_path'], dsn, "-x", "-ch", "utf8"], +# stdout = f_extract_current_meta_sql, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_extract_current_meta_sql ) +# +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_2408_meta_diff.txt'), 'w') +# +# f_old=[] +# f_new=[] +# +# f_old.append(f_extract_initial_meta_sql) # tmp_meta_2408_init.sql -- extracted metadata just after 'init_script' was done +# f_new.append(f_extract_current_meta_sql) # tmp_meta_2408_last.sql -- extracted metadata after drop all object and applying 'tmp_meta_2408_init.sql' +# +# for i in range(len(f_old)): +# old_file=open(f_old[i].name,'r') +# new_file=open(f_new[i].name,'r') +# +# f_diff_txt.write( ''.join( difflib.unified_diff( old_file.readlines(), new_file.readlines() ) ) ) +# +# old_file.close() +# new_file.close() +# +# flush_and_close( f_diff_txt ) +# +# +# # Should be EMPTY: +# ################## +# with open( f_meta_drop_all_log.name, 'r') as f: +# for line in f: +# print( 'Error log of dropping existing objects: ' + f.line() ) +# +# # Should be EMPTY: +# ################## +# with open( f_apply_extracted_meta_log.name, 'r') as f: +# for line in f: +# print( 'Error log of applying extracted metadata: ' + f.line() ) +# +# # Should be EMPTY: +# ################## +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# print( ' '.join(line.split()).upper() ) +# +# ############################### +# # Cleanup. +# time.sleep(1) +# cleanup( [ i.name for i in (f_extract_initial_meta_sql,f_extract_current_meta_sql,f_meta_drop_all_sql,f_meta_drop_all_log,f_apply_extracted_meta_log,f_diff_txt) ] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_2408_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2416.py b/tests/bugs/test_core_2416.py new file mode 100644 index 00000000..ab1a5d11 --- /dev/null +++ b/tests/bugs/test_core_2416.py @@ -0,0 +1,62 @@ +#coding:utf-8 +# +# id: bugs.core_2416 +# title: AV preparing a query with aggregate over derived table +# decription: +# tracker_id: CORE-2416 +# min_versions: [] +# versions: 2.1.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """WITH + t0 AS ( + SELECT 1 AS f0, date '01.03.09' AS f1, 'Event1' AS f2 + FROM rdb$database + ), + + t1 (f1) AS ( + SELECT MIN(t2.f1) AS f1 FROM t0 AS t2 WHERE t2.f0 > t3.f0 AND t2.f1 >= t3.f1 AND t2.f2 = t3.f2 + ) + +SELECT t4.f2, t4.f1_p + FROM (SELECT t3.f0, t3.f1, t3.f2, CAST((SELECT t1.f1 FROM t1) - t3.f1 AS INTEGER) AS f1_p + FROM t0 AS t3 + ) AS t4 + WHERE t4.f1_p IS NOT NULL +GROUP BY t4.f2, t4.f1_p; + +SELECT t4.f2, t4.f1_p + FROM (SELECT t3.f0, t3.f1, t3.f2, + CAST((SELECT t1.f1 FROM ( + SELECT MIN(t2.f1) AS f1 FROM ( + SELECT 1 AS f0, date '01.03.09' AS f1, 'Event1' AS f2 + FROM rdb$database) AS t2 + WHERE t2.f0 > t3.f0 AND t2.f1 >= t3.f1 AND t2.f2 = t3.f2) as t1) + - t3.f1 AS INTEGER) AS f1_p + FROM ( + SELECT 1 AS f0, date '01.03.09' AS f1, 'Event1' AS f2 + FROM rdb$database) AS t3 + ) AS t4 + WHERE t4.f1_p IS NOT NULL +GROUP BY t4.f2, t4.f1_p ; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1.3') +def test_core_2416_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_2420.py b/tests/bugs/test_core_2420.py new file mode 100644 index 00000000..4fdd8946 --- /dev/null +++ b/tests/bugs/test_core_2420.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: bugs.core_2420 +# title: Parsing error in EXECUTE STATEMENT with named parameters +# decription: +# tracker_id: CORE-2420 +# min_versions: [] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """recreate table sch (cod int, num int, name int, prevcod int, udl char(1), root int); +set term ^; +create or alter procedure getschdet(cod int, datedoc date, datedoc2 date, + p1 int, p2 int, p3 int, p4 int, p5 int, p6 int, + p7 int, p8 int, p9 int, p10 int, p11 int, p12 int, p13 int) + returns (summa int) +as +begin + suspend; +end ^ +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# c = db_conn.cursor() +# c.execute("""execute block as +# declare datedoc date; +# declare cod int; +# declare num int; +# declare name int; +# declare summa int; +# begin +# for execute statement ( +# ' select s.cod,s.num, s.name,sum(g.summa) from sch s +# left join getschdet(s.cod,:datedoc ,:datedoc,0,0,0,0,0,0,0,0,0,0,0,1,3) g on 1=1 +# where s.num in (''50'',''51'') and s.udl<>''У'' and s.root=1 +# and not exists (select s2.cod from sch s2 where s2.prevcod=s.cod) +# group by 1,2,3') (datedoc := :datedoc) +# into :cod, :num, :name, :summa +# do exit; +# end""") +# print ('Execution OK') +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Execution OK +""" + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_2420_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2424.py b/tests/bugs/test_core_2424.py new file mode 100644 index 00000000..754fe980 --- /dev/null +++ b/tests/bugs/test_core_2424.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: bugs.core_2424 +# title: Make CREATE VIEW infer column names for views involving a GROUP BY clause or derived table +# decription: +# tracker_id: CORE-2424 +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """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; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Database: localhost:C: btest2 mpugs.core_2424.fdb, User: SYSDBA +SQL> SQL> RDB$RELATION_ID SMALLINT Expression +View Source: +==== ====== + select d.rdb$relation_id from rdb$database d group by d.rdb$relation_id +SQL> SQL> A INTEGER Expression +View Source: +==== ====== + select a from (select 1 a from rdb$database) +SQL>""" + +@pytest.mark.version('>=2.5.0') +def test_core_2424_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2426.py b/tests/bugs/test_core_2426.py new file mode 100644 index 00000000..0b68a9a1 --- /dev/null +++ b/tests/bugs/test_core_2426.py @@ -0,0 +1,48 @@ +#coding:utf-8 +# +# id: bugs.core_2426 +# title: Alter table not respecting collation +# decription: +# tracker_id: CORE-2426 +# min_versions: [] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """-- create domain A_DOMAIN VARCHAR(14) CHARacter SET WIN1252 COLLATE WINPT_BR; +create domain A_DOMAIN VARCHAR(14) CHARacter SET WIN1252; +create domain B_DOMAIN VARCHAR(14) CHARacter SET ISO8859_1 COLLATE PT_BR; + +create table t (FIELD_A VARCHAR(14) CHARacter SET WIN1252 not null COLLATE WIN1252); +alter table t alter field_a type b_domain; +alter table t add primary key (FIELD_A); + +create table t2 (FK B_DOMAIN REFERENCES t(FIELD_A)); +show table t; -- colattion changes to de_de +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """FIELD_A (B_DOMAIN) VARCHAR(14) CHARACTER SET ISO8859_1 Not Null + COLLATE PT_BR +CONSTRAINT INTEG_2: + Primary key (FIELD_A) +""" + +@pytest.mark.version('>=2.5') +def test_core_2426_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2427.py b/tests/bugs/test_core_2427.py new file mode 100644 index 00000000..e81f48d6 --- /dev/null +++ b/tests/bugs/test_core_2427.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: bugs.core_2427 +# title: ALTER VIEW doesn't clear dependencies on old views +# decription: +# tracker_id: CORE-2427 +# min_versions: [] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """create view v1 (n) as select 'ABC' from rdb$database; +create view v3 (n) as select substring(lower(n) from 1) from v1; +create view newv (n) as select 'XYZ' from rdb$database; +alter view v3 (n) as select substring(lower(n) from 1) from newv; +drop view v1; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5') +def test_core_2427_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_2430.py b/tests/bugs/test_core_2430.py new file mode 100644 index 00000000..029547f1 --- /dev/null +++ b/tests/bugs/test_core_2430.py @@ -0,0 +1,48 @@ +#coding:utf-8 +# +# id: bugs.core_2430 +# title: Server adds "NOT" at the end of default value for the TIMESTAMP field +# decription: +# tracker_id: CORE-2430 +# min_versions: [] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """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); + +show table t1; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """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('>=2.5') +def test_core_2430_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2431.py b/tests/bugs/test_core_2431.py new file mode 100644 index 00000000..b198efbd --- /dev/null +++ b/tests/bugs/test_core_2431.py @@ -0,0 +1,60 @@ +#coding:utf-8 +# +# id: bugs.core_2431 +# title: String values in error messages are not converted to connection charset +# decription: +# tracker_id: CORE-2431 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('-At block line: [\\d]+, col: [\\d]+', '-At block line')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core2431.fbk', init=init_script_1) + +test_script_1 = """ + 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; + + set term ^; + execute block as + begin + exception ex_bad_remainder using (-8); + end + ^ + set term ;^ + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CONNECTION_CSET WIN1251 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = HY000 + exception 1 + -EX_BAD_REMAINDER + -Новый остаток изделия будет отрицательным: -8 + -At block line: 3, col: 7 + """ + +@pytest.mark.version('>=3.0') +def test_core_2431_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2434.py b/tests/bugs/test_core_2434.py new file mode 100644 index 00000000..ee77145c --- /dev/null +++ b/tests/bugs/test_core_2434.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: bugs.core_2434 +# title: CREATE USER command: Invalid error message +# decription: Attempt to create user with empty password should raise error with message related to this problem +# tracker_id: CORE-2434 +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create user tmp$c2434 password ''; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE USER TMP$C2434 failed + -Password should not be empty string + """ + +@pytest.mark.version('>=3.0') +def test_core_2434_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_2441.py b/tests/bugs/test_core_2441.py new file mode 100644 index 00000000..03cba22a --- /dev/null +++ b/tests/bugs/test_core_2441.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: bugs.core_2441 +# title: Server crashes on UPDATE OR INSERT statement +# decription: +# tracker_id: CORE-2441 +# min_versions: [] +# versions: 2.1.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE TABLE_TXT ( + FIELD1 VARCHAR(255) +); +commit; +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import datetime +# c = db_conn.cursor() +# c.execute("""UPDATE OR INSERT INTO TABLE_TXT (FIELD1) +# VALUES (CAST(? AS TIMESTAMP)) +# MATCHING(FIELD1)""",[datetime.datetime(2011,5,1)]) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1.3') +@pytest.mark.xfail +def test_core_2441_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2451.py b/tests/bugs/test_core_2451.py new file mode 100644 index 00000000..e0fe18c0 --- /dev/null +++ b/tests/bugs/test_core_2451.py @@ -0,0 +1,37 @@ +#coding:utf-8 +# +# id: bugs.core_2451 +# title: Query SELECT ... WHERE ... IN (SELECT DISTINCT ... ) returns a wrong result set. +# decription: +# tracker_id: CORE-2451 +# min_versions: [] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE TBL_TEST (FLD_VALUE INTEGER); +INSERT INTO TBL_TEST VALUES (1); +INSERT INTO TBL_TEST VALUES (2); +INSERT INTO TBL_TEST VALUES (3); +COMMIT; +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT * FROM TBL_TEST WHERE FLD_VALUE IN (SELECT DISTINCT FLD_VALUE FROM TBL_TEST WHERE FLD_VALUE NOT IN (SELECT DISTINCT FLD_VALUE FROM TBL_TEST)); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5') +def test_core_2451_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_2455.py b/tests/bugs/test_core_2455.py new file mode 100644 index 00000000..f6b5c987 --- /dev/null +++ b/tests/bugs/test_core_2455.py @@ -0,0 +1,113 @@ +#coding:utf-8 +# +# id: bugs.core_2455 +# title: Server fails when doing DROP DATABASE right after error in statistical fnction +# decription: +# tracker_id: CORE-2455 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='ISO8859_1', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + commit; + create database 'localhost:$(DATABASE_LOCATION)trucks'; + + set term ^; + create procedure factorial ( + max_rows integer, + mode integer ) + returns ( + row_num integer, + result integer + ) as + declare variable temp integer; + declare variable counter integer; + begin + counter=0; + temp=1; + while (counter <= max_rows) do + begin + row_num = counter; + + if ( row_num = 0 ) then + temp = 1; + else + temp = temp * row_num; + + result = temp; + counter = counter + 1; + + if (mode=1) then + suspend; + end + + if (mode = 2) then + suspend; + end + ^ + set term ; ^ + commit; + + set list on; + + select 0 as run_no, sp.* from factorial(5,2) sp; + + create table onerow (i integer); + insert into onerow values (5); + + -- note the derived table query + select + 1 as run_no + ,(select ROW_NUM from factorial(i,2)) as RN + from onerow ; + + select + 2 as run_no + ,(select RESULT from factorial(i,2)) as RS + from onerow ; + + -- note the derived table query + select 3 as run_no, (select ROW_NUM from factorial(i,1)) as RN from onerow ; + select 4 as run_no, (select RESULT from factorial(i,1)) as RS from onerow ; + + drop database ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RUN_NO 0 + ROW_NUM 5 + RESULT 120 + RUN_NO 1 + RN 5 + RUN_NO 2 + RS 120 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 21000 + multiple rows in singleton select + Statement failed, SQLSTATE = 21000 + multiple rows in singleton select + """ + +@pytest.mark.version('>=2.5') +def test_core_2455_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2457.py b/tests/bugs/test_core_2457.py new file mode 100644 index 00000000..ad3855b6 --- /dev/null +++ b/tests/bugs/test_core_2457.py @@ -0,0 +1,37 @@ +#coding:utf-8 +# +# id: bugs.core_2457 +# title: UNICODE_CI internal gds software consistency check +# decription: +# tracker_id: CORE-2457 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE ATABLE ( + AFIELD VARCHAR(50) CHARACTER SET UTF8 COLLATE UNICODE_CI); +CREATE DESCENDING INDEX ATABLE_BWD ON ATABLE (AFIELD); +COMMIT;""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT FIRST 1 T.AFIELD FROM ATABLE T + WHERE T.AFIELD < 'X' + ORDER BY T.AFIELD DESC; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.2') +def test_core_2457_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_2475.py b/tests/bugs/test_core_2475.py new file mode 100644 index 00000000..7dc8e2df --- /dev/null +++ b/tests/bugs/test_core_2475.py @@ -0,0 +1,66 @@ +#coding:utf-8 +# +# id: bugs.core_2475 +# title: External table data not visible to other sessions in Classic +# decription: In 2.1.2 SuperServer, any data written to external tables are visible to other sessions. +# However in Classic, this data is not visible. It seems to be cached and written to file eventually, when this happens it becomes visible. +# +# THIS TEST WILL END WITH ERROR IF EXTERNAL TABLE ACCESS IS NOT ALLOWED, WHICH IS BY DEFAULT. It's necessary to adjust firebird.conf. +# tracker_id: CORE-2475 +# min_versions: ['2.1.3'] +# versions: 2.1.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table EXT1 external file '$(DATABASE_LOCATION)EXT1.TBL' +(PK INTEGER); +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# # init +# import os +# ext_filename = '%sEXT1.TBL' % context[db_path_property] +# +# # session A +# c1 = db_conn.cursor() +# c1.execute("insert into EXT1 (PK) values (1)") +# +# db_conn.commit() +# +# # session B +# con2 = kdb.connect(dsn=dsn,user=user_name,password=user_password) +# c2 = con2.cursor() +# c2.execute('select * from EXT1') +# printData(c2) +# +# # cleanup +# con2.close() +# try: +# os.remove(ext_filename) +# except: +# print("Error while removing external table file") +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PK +----------- +1 +""" + +@pytest.mark.version('>=2.1.3') +@pytest.mark.xfail +def test_core_2475_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2477.py b/tests/bugs/test_core_2477.py new file mode 100644 index 00000000..bf6dca10 --- /dev/null +++ b/tests/bugs/test_core_2477.py @@ -0,0 +1,389 @@ +#coding:utf-8 +# +# id: bugs.core_2477 +# title: mon$memory_usage: Sorting memory should be reported as owned by the statement +# decription: +# We create view that gathers monitoring info related to all needed levels of statistics (DB, attachment, transaction, call). +# Then this view is "customized" in order to leave only interested info about activity that will be started by separate isql process. +# Then we start ascynchronously ISQL and make it stay in some (small) pause. At this moment we make first "photo" of mon$ info and store +# it in dict object 'map_beg'. +# NB: we should NOT wait too long because when SORT starts it can very fast to fill whole space of TempCacheLimit and mon$memory* counters +# will not change since this poitn at all (===> one mey to get zero difference between mon$ countyers in this case). +# +# After small pause (in ISQL connect) will gone, ISQL starts to do "huge sort" by invoking query with 'SELECT DISTINCT FROM '. +# We wait about 1..2 second after this sort start and then make 2nd "photo" of monitoring counters and also store their values in another +# dict object ('map_end'). +# +# Finally, we force ISQL to finish (by moving DB in full shutdown state) and compare differences between corresp. values of map_end and map_beg. +# Values for DATABASE level (mon$stat_group = 0) change only in SuperServer but never change in CS/SC and remain zero. We do not compare them. +# Values for TRANSACTION level never increase; moreover, mon$memory_allocated counter at the "end-point" (when sorting is running) even is reduced +# (and the reason still remain unknown for me; see letter to dimitr 04-may-2018 20:07). +# So, we compare only difference of mon$memory* counters for ATTACHMENT and STATEMENT level (mon$stat_group = 1 and 3). +# +# This difference must be not less than some threshold that depends on FB arch, for __BOTH__ levels (and this is main idea of this test) +# ################### +# +# Runs this test on firebird.conf with default TempCacheLimit show following values of differences: +# 1) for SuperServer: ~68.1 Mb; +# 2) for Classic: ~9.4 Mb +# For this reason minimal threshold for consider difference Ok is about 1 Mb (see MIN_DIFF_THRESHOLD). +# +# Checked on (Windows 32 bit): +# 25SC, build 2.5.9.27107: OK, 10.328s. +# 25sS, build 2.5.8.27056: OK, 14.656s. +# 30Cs, build 3.0.4.32947: OK, 14.234s. +# 30SS, build 3.0.4.32963: OK, 17.234s. +# 40CS, build 4.0.0.955: OK, 11.219s. +# 40SS, build 4.0.0.967: OK, 12.718s. +# +# tracker_id: CORE-2477 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create or alter view v_mon as + select * + from ( + select + m.mon$stat_group as stat_gr + ,rpad( decode(m.mon$stat_group, 0,'0:database', 1,'1:attachment', 2,'2:transaction', 3,'3:statement', 4,'4:call'), 15,' ') as stat_type + ,m.mon$memory_used as memo_used + ,m.mon$memory_allocated as memo_allo + ,m.mon$max_memory_used as max_memo_used + ,m.mon$max_memory_allocated as max_memo_allo + ,m.mon$stat_id as stat_id + ,coalesce( s.mon$attachment_id, t.mon$attachment_id, a.mon$attachment_id, -999 ) as att_id + ,coalesce( s.mon$transaction_id, t.mon$transaction_id, -999 ) as trn_id + ,coalesce( s.mon$statement_id, -999) as sttm_id + ,coalesce( decode( s.mon$state, 0,'finished', 1,'running', 2,'suspended' ), 'n/a') as stm_state + ,lower(right( coalesce(trim(coalesce(a.mon$remote_process, a.mon$user)), ''), 20 )) as att_process -- isql.exe or Garbace Collector or Cache Writer + ,lower(left( coalesce(cast(s.mon$sql_text as varchar(2000)),''), 50 )) as sql_text + from mon$memory_usage m + left join mon$statements s on m.mon$stat_group = 3 and m.mon$stat_id = s.mon$stat_id + left join mon$transactions t on + m.mon$stat_group = 2 and m.mon$stat_id = t.mon$stat_id + or m.mon$stat_group = 3 and m.mon$stat_id = s.mon$stat_id and t.mon$transaction_id = s.mon$transaction_id + left join mon$attachments a on + m.mon$stat_group = 1 and m.mon$stat_id = a.mon$stat_id + or m.mon$stat_group=2 and m.mon$stat_id = t.mon$stat_id and a.mon$attachment_id = t.mon$attachment_id + or m.mon$stat_group=3 and m.mon$stat_id = s.mon$stat_id and a.mon$attachment_id = s.mon$attachment_id + where + s.mon$sql_text is null + or + -- NB: There is additional statement like "SELECT RDB$MAP_USING, RDB$MAP_PLUGIN ..." in 4.0! + -- We have to filter it out and leave here only "our" statement that does SORT job: + s.mon$sql_text containing 'distinct' + ) t + where + t.stat_gr = 0 + or + t.att_process similar to '%[\\/]isql(.exe){0,1}' + order by stat_type, stat_id; + + -- Aux. table for make ISQL some small delay just after it will be loaded and establish connection: + recreate table test(id int primary key); + + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# from subprocess import Popen +# import time +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_file=db_conn.database_name +# +# db_conn.close() +# +# ISQL_USER=user_name +# ISQL_PSWD=user_password +# +# MIN_DIFF_THRESHOLD=1000000 +# +# # change on True if one need to look at intermediate results of gathering mon$ info +# # (before ISQL async launch; after launch but before starting sort; while sorting) +# RUN_DBG=False +# +# DELAY_IN_ISQL_BEFORE_IT_STARTS_SORT = 3 +# DELAY_FOR_ISQL_ESTABLISH_ITS_CONNECT = 1 +# DELAY_BEFORE_MON_WHILE_SORT_IS_RUNNING = DELAY_IN_ISQL_BEFORE_IT_STARTS_SORT + DELAY_FOR_ISQL_ESTABLISH_ITS_CONNECT + 1 +# +# SQL_GATHER_SORT_INFO=''' +# select +# v.att_process, +# replace(replace(replace(replace(v.sql_text, ascii_char(10),' '), ascii_char(13),' '),' ',' '),' ',' ') as sql_text, +# v.stat_type, +# v.stm_state, +# v.att_id, +# v.trn_id, +# v.sttm_id, +# v.memo_used, +# v.memo_allo, +# v.max_memo_used, +# v.max_memo_allo +# from v_mon v +# where v.att_id is distinct from current_connection +# ''' +# +# #-------------------------------------------------------------- +# +# def result_msg(a_diff_value, a_min_threshold): +# return ( ('OK, expected: increased significantly.') if a_diff_value > a_min_threshold else ('BAD! Did not increased as expected. Difference: ' + "{:d}".format(a_diff_value)+'.') ) +# +# def debug_store_mon_view(dsn, SQL_GATHER_SORT_INFO, file_name_suffix): +# global os +# global subprocess +# f_sql_dbg=open( os.path.join( context['temp_directory'], 'tmp_c2477_dbg' + file_name_suffix + '.sql' ), 'w') +# f_sql_dbg.write( 'set width att_process 20; set width sql_text 50; ' + SQL_GATHER_SORT_INFO+';') +# f_sql_dbg.close() +# f_log_dbg=open( os.path.join( context['temp_directory'], 'tmp_c2477_dbg' + file_name_suffix + '.log' ), 'w') +# subprocess.call( [ context['isql_path'], dsn, '-q', '-n', '-i', f_sql_dbg.name ], stdout=f_log_dbg, stderr = subprocess.STDOUT) +# f_log_dbg.close() +# os.remove(f_sql_dbg.name) +# +# def forcely_clean_attachments_by_shutdown_online( db_file ): +# +# global RUN_DBG +# global os +# +# f_shutdown_log = open( os.path.join(context['temp_directory'],'tmp_shutdown_and_online_2477.log'), 'w') +# +# subprocess.call( [context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "prp_shutdown_mode", "prp_sm_full", "prp_shutdown_db", "0", +# "dbname", db_file, +# ], +# stdout = f_shutdown_log, +# stderr = subprocess.STDOUT +# ) +# +# subprocess.call( [context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_db_stats", +# "dbname", db_file, "sts_hdr_pages" +# ], +# stdout = f_shutdown_log, +# stderr=subprocess.STDOUT +# ) +# +# subprocess.call( [context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "prp_db_online", +# "dbname", db_file, +# ], +# stdout = f_shutdown_log, +# stderr = subprocess.STDOUT +# ) +# subprocess.call( [context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_db_stats", +# "dbname", db_file, "sts_hdr_pages" +# ], +# stdout = f_shutdown_log, +# stderr=subprocess.STDOUT +# ) +# +# f_shutdown_log.close() +# +# if not RUN_DBG: +# os.remove(f_shutdown_log.name) +# +# +# #-------------------------------------------------------- +# +# +# sql_text=''' +# commit; +# set transaction lock timeout %(DELAY_IN_ISQL_BEFORE_IT_STARTS_SORT)s; +# insert into test(id) values(1); +# set term ^; +# execute block returns(c int) as +# begin +# begin +# -- make ISQL stay in small pause just after connection will be established: +# execute statement ( 'insert into test(id) values(?)' ) (1) +# on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') +# as user '%(ISQL_USER)s' password '%(ISQL_PSWD)s' +# ; +# when any do +# begin +# end +# end +# +# select count(*) +# from ( +# -- this force to use "PLAN SORT": +# select distinct lpad('', 500, uuid_to_char(gen_uuid())) s from rdb$types a,rdb$types b, rdb$types c +# ) +# into c; +# suspend; +# end +# ^ +# set term ;^ +# ''' %locals() +# +# +# f_isql_cmd=open( os.path.join(context['temp_directory'],'tmp_2477_sort.sql'), 'w') +# f_isql_cmd.write(sql_text) +# f_isql_cmd.close() +# +# if RUN_DBG: +# debug_store_mon_view(dsn, SQL_GATHER_SORT_INFO, '0') +# +# +# # Launch async-ly ISQL which must establish connect and: +# # 1) stay in small delay +# # 2) start "big sorting" job (for at least 20-30 seconds): +# +# f_log_sort=open( os.path.join(context['temp_directory'], 'tmp_2477_sort.log'), 'w') +# p_sql = subprocess.Popen( [ context['isql_path'], dsn, '-q', '-n', '-i', f_isql_cmd.name ], stdout=f_log_sort, stderr = subprocess.STDOUT) +# +# # do NOT remove this delay: we have to wait while ISQL for sure will establish connection. +# ########################## +# time.sleep( DELAY_FOR_ISQL_ESTABLISH_ITS_CONNECT ) +# +# +# if RUN_DBG: +# # NOTE: assign RUN_DBG to True and look in debug snapshot file tmp_c2477_dbg1.log +# # with results of 1st gathering of mon$ info. If it will contain only one record (of DB level) +# # than it means that we have to increase DELAY_FOR_ISQL_ESTABLISH_ITS_CONNECT value): +# debug_store_mon_view(dsn, SQL_GATHER_SORT_INFO, '1') +# +# +# # Start separate connect for gather monio +# con_mon=fdb.connect(dsn=dsn) +# cur_mon=con_mon.cursor() +# +# # Gather info from mon$memory_usage before SORT start (ISQL stays in pause now): +# ################################### +# cur_mon.execute(SQL_GATHER_SORT_INFO) +# +# map_beg={} +# +# # Take at once all the records that cursor can return (actually it can return only 5 records in 3.0+ SS): +# for x in cur_mon.fetchmanymap(99): +# # we need only several for storing as KEY-VALUE pairs from the whole set of columns of view v_mon: +# (stat_type, att_id, trn_id, sttm_id) = ( v for k,v in x.items() if k in ( 'STAT_TYPE', 'ATT_ID', 'TRN_ID', 'STTM_ID') ) +# val = [ v for k,v in x.items() if k in ('MEMO_USED', 'MEMO_ALLO') ] +# +# map_beg[ stat_type, att_id, trn_id, sttm_id ] = val +# +# #for k,v in sorted(map_beg.items()): +# # print('::: beg ::: k=',k,'; v=',v) +# +# +# cur_mon.close() +# +# # This is mandatory before any subsequent gathering mon$ info: +# con_mon.commit() +# +# # This *seems* not necessary but one need to test this again in SC/CS: +# con_mon.close() +# con_mon=fdb.connect(dsn=dsn) +# +# # this delay is mandatory and must be greater than delay in ISQL +# # (see 'set tran lock timeout N' in its sql script). +# # We have to give ISQL to actually start SORT job: +# time.sleep( DELAY_BEFORE_MON_WHILE_SORT_IS_RUNNING ) +# +# cur_mon=con_mon.cursor() +# +# # Gather info from mon$memory_usage when SORT is running: +# ################################### +# cur_mon.execute(SQL_GATHER_SORT_INFO) +# map_end={} +# for x in cur_mon.fetchmanymap(99): +# (stat_type, att_id, trn_id, sttm_id) = ( v for k,v in x.items() if k in ( 'STAT_TYPE', 'ATT_ID', 'TRN_ID', 'STTM_ID') ) +# val = [ v for k,v in x.items() if k in ('MEMO_USED', 'MEMO_ALLO') ] +# +# map_end[ stat_type, att_id, trn_id, sttm_id ] = val +# +# cur_mon.close() +# +# if RUN_DBG: +# # NOTE: assign RUN_DBG to True and look in debug snapshot file tmp_c2477_dbg1.log +# # with results of 1st gathering of mon$ info. +# debug_store_mon_view(dsn, SQL_GATHER_SORT_INFO, '2') +# +# con_mon.close() +# +# # We have to be sure that NO ANY activity remains in the database before finish this test. +# # Unfortunately, it seems that just killing process of ISQL (that was launched async-ly) not enough, +# # so we turn database offline and bring back online: +# forcely_clean_attachments_by_shutdown_online( db_file ) +# +# # ::: !! ::: +# ######################################## +# # TERMINATE ISQL THAT DOES HUGE SORT JOB +# ######################################## +# p_sql.terminate() +# f_log_sort.close() +# +# #time.sleep(1) +# +# for k,v in sorted(map_beg.items()): +# +# if 'database' in k[0]: +# # mon$memory_* counters always ZERO in CS/SC for database level +# pass +# +# if 'transaction' in k[0]: +# # mon$memory_* counters never change for transaction level (reason currently is unknown). +# pass +# +# if 'attachment' in k[0] or 'statement' in k[0]: +# +# (beg_memo_used, beg_memo_allo) = v +# +# (end_memo_used, end_memo_allo) = map_end.get(k) +# (dif_memo_used, dif_memo_allo) = (end_memo_used - beg_memo_used, end_memo_allo - beg_memo_allo) +# +# #print( k[0].rstrip()+':' ) +# # 4debug: output value of mon$memory* counters difference: +# #print( ' '.join( (' * DELTA of mon$memory_used:', "{:9d}".format(dif_memo_used), result_msg(dif_memo_used, MIN_DIFF_THRESHOLD) ) ) ) +# #print( ' '.join( (' * DELTA of mon$memory_allo:', "{:9d}".format(dif_memo_allo), result_msg(dif_memo_allo, MIN_DIFF_THRESHOLD) ) ) ) +# +# print( ' '.join( k[0].split(':') ).rstrip() ) +# print( ' * DELTA of mon$memory_used: ' + result_msg(dif_memo_used, MIN_DIFF_THRESHOLD) ) +# print( ' * DELTA of mon$memory_allo: ' + result_msg(dif_memo_allo, MIN_DIFF_THRESHOLD) ) +# +# # cleanup: +# ########## +# time.sleep(1) +# f_list = (f_isql_cmd, f_log_sort) +# for f in f_list: +# os.remove(f.name) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 1 attachment + * DELTA of mon$memory_used: OK, expected: increased significantly. + * DELTA of mon$memory_allo: OK, expected: increased significantly. + + 3 statement + * DELTA of mon$memory_used: OK, expected: increased significantly. + * DELTA of mon$memory_allo: OK, expected: increased significantly. + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_2477_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2484.py b/tests/bugs/test_core_2484.py new file mode 100644 index 00000000..e1cc24e9 --- /dev/null +++ b/tests/bugs/test_core_2484.py @@ -0,0 +1,178 @@ +#coding:utf-8 +# +# id: bugs.core_2484 +# title: Success message when connecting to tiny trash database file +# decription: +# We make invalid FDB file by creating binary file and write small data piece to it. +# Then we try to connect to such "database" using ISQL with passing trivial command +# like 'select current_timestamp' for execution. +# ISQL must raise error and quit (obviously without any result to STDOUT). +# +# ::: NB ::: +# If Windows with non-ascii language is used then message about overlapped IO +# ("-Overlapped I/O operation is in progress") will be translated by OS to localized +# text and it will be displayed in STDERR. This message must be suppressed or ignored. +# +# Because of this, it was decided to redirect output of ISQL to logs and open +# them using codecs.open() with errors='ignore' option. +# We check presense of error message in STDERR file created by ISQL. +# It is ennough to verify that STDERR log contains pattern 'SQLSTATE = '. +# Checked on 4.0.0.2164; 3.0.7.33356 +# +# 02-mar-2021. Re-implemented in order to have ability to run this test on Linux. +# +# NOTE: message that clearly points to the reason of failed connection is shown +# only on Linux FB 3.x: +# ===== +# Statement failed, SQLSTATE = 08004 +# file <...>/tmp_2484_fake.fdb is not a valid database +# ===== +# +# All other cases produce SQLSTATE = 08001 and somewhat strange after it (from my POV): +# ===== +# Windows: +# I/O error during "ReadFile" operation for file "<...>\\TMP_2484_FAKE.FDB" +# -Error while trying to read from file +# +# Linux: +# I/O error during "read_retry" operation for file "<...>/tmp_2484_fake.fdb" +# -Error while trying to read from file +# -Success <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< :-) +# ===== +# +# Checked on: +# * Windows: 4.0.0.2377, 3.0.8.33420 -- both on SS/CS +# * Linux: 4.0.0.2377, 3.0.8.33415 +# +# +# tracker_id: CORE-2484 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('SQLSTATE = 08004', 'SQLSTATE = 08001')] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import codecs +# import re +# import time +# +# db_conn.close() +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# #-------------------------------------------- +# +# 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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# f_fake_fdb = open( os.path.join(context['temp_directory'],'tmp_2484_fake.fdb'), 'wb') +# f_fake_fdb.write('ŒåŁä') +# flush_and_close( f_fake_fdb ) +# +# f_fake_sql = open( os.path.splitext(f_fake_fdb.name)[0]+'.sql', 'w') +# f_fake_sql.write('set heading off; select current_timestamp from rdb$database; quit;') +# flush_and_close( f_fake_sql ) +# +# f_fake_log = open( os.path.splitext(f_fake_fdb.name)[0]+'.log', 'w') +# f_fake_err = open( os.path.splitext(f_fake_fdb.name)[0]+'.err', 'w') +# subprocess.call( [ context['isql_path'], 'localhost:' + f_fake_fdb.name, "-i", f_fake_sql.name ], +# stdout = f_fake_log, +# stderr = f_fake_err +# ) +# flush_and_close( f_fake_log ) +# flush_and_close( f_fake_err ) +# +# ########################################################################### +# # Linux, FB 3.x: +# # Statement failed, SQLSTATE = 08004 +# # file <...>/tmp_2484_fake.fdb is not a valid database +# # Windows, FB 3.x: +# # Statement failed, SQLSTATE = 08001 +# # I/O error during "ReadFile" operation for file "<...>\\TMP_2484_FAKE.FDB" +# # -Error while trying to read from file +# +# # Linux, FB 4.x: +# # Statement failed, SQLSTATE = 08001 +# # I/O error during "read_retry" operation for file "<...>/tmp_2484_fake.fdb" +# # -Error while trying to read from file +# # -Success +# # Windows, FB 4.x: +# # Statement failed, SQLSTATE = 08001 +# # I/O error during "ReadFile" operation for file "C:\\FBTESTING\\QA\\FBT-REPO\\TMP\\TMP_2484_FAKE.FDB" +# # -Error while trying to read from file +# # Overlapped I/O operation is in progress << WILL BE IN LOCALIZED FORM! +# ########################################################################### +# +# p = re.compile('SQLSTATE\\s+=\\s+',re.IGNORECASE) +# with codecs.open( filename = f_fake_err.name, mode = 'r', errors = 'ignore') as f: +# for line in f: +# if p.search(line): +# print(line) +# +# with codecs.open( filename = f_fake_log.name, mode = 'r', errors = 'ignore') as f: +# for line in f: +# if p.search(line): +# print('UNEXPECTED STDOUT: ' + line) +# +# # cleanup: +# ########## +# time.sleep(1) +# cleanup( ( f_fake_fdb, f_fake_sql, f_fake_log, f_fake_err ) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Statement failed, SQLSTATE = 08001 + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_2484_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2493.py b/tests/bugs/test_core_2493.py new file mode 100644 index 00000000..fc45d09a --- /dev/null +++ b/tests/bugs/test_core_2493.py @@ -0,0 +1,312 @@ +#coding:utf-8 +# +# id: bugs.core_2493 +# title: Append the IP address of the remote host to error messages in firebird.log for TCP connections +# decription: +# Following actions are performed by this test: +# +# 1. Obtain current firebird.log and saves it to the file with name = 'tmp_2493_fblog_before.txt'; +# +# 2. Asynchronously launch ISQL in child process with request to return client IP address (via asking context variable) +# and after this - do some 'heavy query' that for sure will take a lot of time and resources. +# Output is redirected to file with name = 'tmp_2493_isql.log' and will be parsed further (we'll search for client IP there). +# +# 3. Kill launched ISQL process after several seconds. At this point new message must appear in firebird.log and it MUST +# be in format described in the ticket. Because this abend will be detected by SERVER, format of message will be like this: +# (for TCPv4): INET/inet_error: read errno = 10054, client host = prog1, address = 127.0.0.1/4076, user = john +# (for TCPv6): INET/inet_error: read errno = 10054, client host = prog2, address = fe80::c40e:21ec:b5c7:8963/56831, user = mick +# +# 4. Wait several seconds and after it - obtain again firebird.log (new content) and save it in 'tmp_2493_fblog_after.txt'. +# +# 5. Make file comparison by calling method from standard Python tool - difflib. Result of this comparison will be stored +# in file with name 'tmp_2493_diff.txt'. This file will have several lines from which we are interested only for one which +# STARTS with "+" (PLUS sign) and does contain phrase 'INET/INET_ERROR'. Diff-file must contain only ONE such line. +# +# 6. Next we parse this line: remove "/" and "="characters from it and split then text into array of words: +# + INET inet_error read errno 10054 client host prog1 address 127.0.0.1 4417 user john ------- for IPv4 +# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 +# + INET inet_error read errno 10054 client host prog2 address x::y:z:u:v 56831 user mick ------- for IPv6 +# 7. Then we scan this array backward and check tokens for matching simple rules (N = array len): +# * token N-1 must be OS user name; this name can be followed by some kind of "suffix": "JOHN.-1.-1" - and we have to take only 1st word from it. +# NB: we current OS user using call of getpass.getuser(). It must be compared in case insensitive manner; +# * token N-2 is just word "user" (as is); +# * token N-3 is port number, it has to be positive value; +# * token N-4 is IP. It must be equal to rdb$get_context('SYSTEM','CLIENT_ADDRESS'). +# +# This is how differences look in firebird.log: +# # 2.5.9: +# # INET/inet_error: read errno = 10054, client address = 127.0.0.1 3268, user ZOTOV.-1.-1 +# # ^ ^ ^ ^ +# # N-4 N-3 N-2 N-1 +# # 3.0.4: +# # INET/inet_error: read errno = 10054, client host = csprog, address = 127.0.0.1 3298, user zotov +# # ^ ^ ^ ^ +# # N-4 N-3 N-2 N-1 +# # 3.0.8 and 4.0.0 RC1: +# # INET/inet_error: read errno = 10054, client host = csprog, address = fe80::fcf1:e33c:e924:969d%16/56887, user = zotov +# # INET/inet_error: read errno = 10054, client host = csprog, address = fe80::fcf1:e33c:e924:969d%16/56883, user = zotov +# +# +# Checked on WI-V3.0.0.32272 x86 and amd64, OS = Windows XP and 8.1, TCPv4 and TCPv6; fdb version = 1.5, Python 2.7 and 3.4. +# Checked 17.02.2018 after adding 2.5.9 to the list of avaliable versions: +# 2.5.9.27103: OK, 5.547s. +# 3.0.3.32837: OK, 7.079s. +# 3.0.4.32912: OK, 6.094s. +# 4.0.0.800: OK, 7.109s. +# 4.0.0.890: OK, 6.360s. +# ### NB ### +# First version of this test was implemented on Windows XP and Python 2.7.8, build 02-jul-2014 win32. +# Unfortunatelly, on Python 3.4 + Win 8.1 it is unable to use socket.inet_pton() call -exception raises with text: +# "AttributeError: 'module' object has no attribute 'inet_pton'". +# For that reason it was decided do NOT use calls of socket.inet_pton() and operate only with remote_address that can be easy +# received using built-in FB context variable. User-defined functions 'is_valid_ipv4' and 'is_valid_ipv6' are left here for +# possible further usage in some other tests. +# +# 20.02.2021: changed 'platform' attribute to Windows only. Content of firebird.log has no changes on Linux during this test run. +# Perhaps, this is temporary and another solution will be found/implemented. Sent letter to dimitr et al, 21.02.2021 08:20. +# +# tracker_id: CORE-2493 +# min_versions: ['2.5.9'] +# versions: 2.5.9 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.9 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table log(ip varchar(255)); + create sequence g; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# from subprocess import Popen +# import signal +# import difflib +# import re +# import socket +# import getpass +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# engine = str(db_conn.engine_version) +# db_conn.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() +# os.fsync(file_handle.fileno()) +# +# file_handle.close() +# +# #-------------------------------------------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #------------------------------------------- +# +# +# def svc_get_fb_log( engine, f_fb_log ): +# +# import subprocess +# +# if engine.startswith('2.5'): +# get_firebird_log_key='action_get_ib_log' +# else: +# get_firebird_log_key='action_get_fb_log' +# +# subprocess.call([ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# get_firebird_log_key +# ], +# stdout=f_fb_log, +# stderr=subprocess.STDOUT +# ) +# +# return +# +# #-------------------------------------------- +# +# # http://stackoverflow.com/questions/319279/how-to-validate-ip-address-in-python +# def is_valid_ipv4(address): +# import socket +# try: +# socket.inet_pton(socket.AF_INET, address) +# except AttributeError: # no inet_pton here, sorry +# try: +# socket.inet_aton(address) +# except socket.error: +# return False +# return address.count('.') == 3 +# except socket.error: # not a valid address +# return False +# +# return True +# +# #-------------------------------------------- +# +# def is_valid_ipv6(address): +# import socket +# try: +# socket.inet_pton(socket.AF_INET6, address) +# except socket.error: # not a valid address +# return False +# return True +# +# #-------------------------------------------- +# +# f_fblog_before=open(os.path.join(context['temp_directory'],'tmp_2493_fblog_before.txt'), 'w') +# +# svc_get_fb_log( engine, f_fblog_before ) +# +# f_fblog_before.close() +# +# isql_txt=''' insert into log(ip) values( rdb$get_context('SYSTEM','CLIENT_ADDRESS') ); +# commit; +# select count(i) from (select gen_id(g,1) i from rdb$types a,rdb$types b,rdb$types c,rdb$types d); +# ''' +# +# f_sql_txt=open( os.path.join(context['temp_directory'],'tmp_2493_isql.sql'), 'w') +# f_sql_txt.write(isql_txt) +# flush_and_close( f_sql_txt ) +# +# f_sql_log=open(os.path.join(context['temp_directory'],'tmp_2493_isql.log'), 'w' ) +# f_sql_err=open(os.path.join(context['temp_directory'],'tmp_2493_isql.err'), 'w' ) +# +# p_isql=Popen( [ context['isql_path'], dsn, "-i", f_sql_txt.name ], stdout=f_sql_log, stderr=f_sql_err +# ) +# time.sleep(3) +# +# p_isql.terminate() +# +# flush_and_close( f_sql_log ) +# flush_and_close( f_sql_err ) +# +# f_sql_txt=open(os.path.join(context['temp_directory'],'tmp_2493_isql.sql'), 'w') +# f_sql_txt.write("set heading off; select iif(gen_id(g,0) = 0, 'Trouble with subprocess: job was not started.', ip) as msg from log; quit;") +# flush_and_close( f_sql_txt ) +# +# mon_ip=subprocess.check_output( [ context['isql_path'], dsn, '-i', f_sql_txt.name ]).split()[0] +# +# f_fblog_after=open(os.path.join(context['temp_directory'],'tmp_2493_fblog_after.txt'), 'w') +# +# svc_get_fb_log( engine, f_fblog_after ) +# +# flush_and_close( f_fblog_after ) +# +# oldfb=open(f_fblog_before.name, 'r') +# newfb=open(f_fblog_after.name, 'r') +# +# difftext = ''.join(difflib.unified_diff( +# oldfb.readlines(), +# newfb.readlines() +# )) +# oldfb.close() +# newfb.close() +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_2493_diff.txt'), 'w') +# f_diff_txt.write(difftext) +# flush_and_close( f_diff_txt ) +# +# inet_msg_words = [] +# logged_err=0 +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# if line.startswith('+') and 'INET/INET_ERROR' in line.upper(): +# # DO NOT include ':' to the list of delimiters! It is involved in IPv6 address: +# inet_msg_words = line.replace(',',' ').replace('/',' ').replace('=',' ').split() +# break +# +# # Tokens, numerated from zero (NB: leftmost is "PLUS" sign and has index = 0) +# # --------------------------------------------------------------------------- +# # + INET inet_error read errno 10054 client host prog1 address 127.0.0.1 4417 user john ------- for IPv4 +# # 0 1 2 3 4 5 6 7 8 9 10 11 12 13 +# # + INET inet_error read errno 10054 client host prog2 address x::y:z:u:v 56831 user mick ------- for IPv6 +# +# # + INET/inet_error: read errno = 10054, client host = csprog, address = fe80::fcf1:e33c:e924:969d%16/56883, user = zotov +# # 0 1 2 3 4 5 6 7 8 9 10 11 12 --> len() = 13 +# +# n = len(inet_msg_words) +# +# parsing_problem_msg = 'Problem with parsing content of firebird.log' +# if len(inet_msg_words) == 0: +# print('%s: message with "inet_error" not found.' % parsing_problem_msg) +# elif len(inet_msg_words) < 4: +# print('%s: message with "inet_error" contains less than 4 tokens.' % parsing_problem_msg) +# else: +# +# #print('Fixed data: '+inet_msg_words[4]+' '+inet_msg_words[5]+' '+inet_msg_words[6]+' '+inet_msg_words[7]) +# +# # http://stackoverflow.com/questions/4271740/how-can-i-use-python-to-get-the-system-hostname +# +# # commented 17.02.2017 due to 2.5.9 (no info about remote host there): +# #if inet_msg_words[8].upper()==socket.gethostname().upper(): +# # print('Remote host: valid, passed socket.gethostname()') +# #else: +# # print('Invalid host=|'+inet_msg_words[8]+'|') +# +# # does not work on Python 3.4! >>> if is_valid_ipv4(inet_msg_words[10]) or is_valid_ipv6(inet_msg_words[10]): +# if inet_msg_words[n-4] + '/' + inet_msg_words[n-3] == mon_ip: +# print("String IP/port: valid, equal to 'CLIENT_ADDRESS'") +# else: +# print('Invalid IP/port=|'+inet_msg_words[n-4]+'/'+inet_msg_words[n-3]+'| - differ from mon_ip=|'+mon_ip+'|') +# +# if inet_msg_words[n-3].isdigit(): +# print('Port value: valid, positive integer.') +# else: +# print('Invalid port=|'+inet_msg_words[n-3]+'|') +# +# if inet_msg_words[n-1].upper().split('.')[0] == getpass.getuser().upper(): +# # 2.5.9: got 'ZOTOV.-1.-1' ==> must be kust of one word: 'ZOTOV' +# print('OS user: valid, passed getpass.getuser()') +# else: +# print('Invalid OS user=|'+inet_msg_words[n-1]+'|') +# +# +# # Cleanup. +# ########## +# time.sleep(1) +# cleanup( [i.name for i in (f_sql_txt,f_sql_log,f_sql_err,f_fblog_before,f_fblog_after,f_diff_txt) ] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + String IP/port: valid, equal to 'CLIENT_ADDRESS' + Port value: valid, positive integer. + OS user: valid, passed getpass.getuser() + """ + +@pytest.mark.version('>=2.5.9') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_2493_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2499.py b/tests/bugs/test_core_2499.py new file mode 100644 index 00000000..763cd7c1 --- /dev/null +++ b/tests/bugs/test_core_2499.py @@ -0,0 +1,72 @@ +#coding:utf-8 +# +# id: bugs.core_2499 +# title: Implementation limit of DISTINCT items are not enforced, causing generation of incorrect BLR +# decription: +# tracker_id: CORE-2499 +# min_versions: ['2.5'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table t ( + n1 int, n2 int, n3 int, n4 int, n5 int, n6 int, n7 int, n8 int, n9 int, n10 int, n11 int, + n12 int, n13 int, n14 int, n15 int, n16 int, n17 int, n18 int, n19 int, n20 int, n21 int, + n22 int, n23 int, n24 int, n25 int, n26 int, n27 int, n28 int, n29 int, n30 int, n31 int, + n32 int, n33 int, n34 int, n35 int, n36 int, n37 int, n38 int, n39 int, n40 int, n41 int, + n42 int, n43 int, n44 int, n45 int, n46 int, n47 int, n48 int, n49 int, n50 int, n51 int, + n52 int, n53 int, n54 int, n55 int, n56 int, n57 int, n58 int, n59 int, n60 int, n61 int, + n62 int, n63 int, n64 int, n65 int, n66 int, n67 int, n68 int, n69 int, n70 int, n71 int, + n72 int, n73 int, n74 int, n75 int, n76 int, n77 int, n78 int, n79 int, n80 int, n81 int, + n82 int, n83 int, n84 int, n85 int, n86 int, n87 int, n88 int, n89 int, n90 int, n91 int, + n92 int, n93 int, n94 int, n95 int, n96 int, n97 int, n98 int, n99 int, n100 int, n101 int, + n102 int, n103 int, n104 int, n105 int, n106 int, n107 int, n108 int, n109 int, n110 int, + n111 int, n112 int, n113 int, n114 int, n115 int, n116 int, n117 int, n118 int, n119 int, + n120 int, n121 int, n122 int, n123 int, n124 int, n125 int, n126 int, n127 int, n128 int, + n129 int, n130 int, n131 int, n132 int, n133 int, n134 int, n135 int, n136 int, n137 int, + n138 int, n139 int, n140 int, n141 int, n142 int, n143 int, n144 int, n145 int, n146 int, + n147 int, n148 int, n149 int, n150 int, n151 int, n152 int, n153 int, n154 int, n155 int, + n156 int, n157 int, n158 int, n159 int, n160 int, n161 int, n162 int, n163 int, n164 int, + n165 int, n166 int, n167 int, n168 int, n169 int, n170 int, n171 int, n172 int, n173 int, + n174 int, n175 int, n176 int, n177 int, n178 int, n179 int, n180 int, n181 int, n182 int, + n183 int, n184 int, n185 int, n186 int, n187 int, n188 int, n189 int, n190 int, n191 int, + n192 int, n193 int, n194 int, n195 int, n196 int, n197 int, n198 int, n199 int, n200 int, + n201 int, n202 int, n203 int, n204 int, n205 int, n206 int, n207 int, n208 int, n209 int, + n210 int, n211 int, n212 int, n213 int, n214 int, n215 int, n216 int, n217 int, n218 int, + n219 int, n220 int, n221 int, n222 int, n223 int, n224 int, n225 int, n226 int, n227 int, + n228 int, n229 int, n230 int, n231 int, n232 int, n233 int, n234 int, n235 int, n236 int, + n237 int, n238 int, n239 int, n240 int, n241 int, n242 int, n243 int, n244 int, n245 int, + n246 int, n247 int, n248 int, n249 int, n250 int, n251 int, n252 int, n253 int, n254 int, + n255 int, n256 int); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + select distinct * from t; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 54011 + Dynamic SQL Error + -SQL error code = -104 + -Invalid command + -Cannot have more than 255 items in DISTINCT / UNION DISTINCT list + """ + +@pytest.mark.version('>=4.0') +def test_core_2499_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_2501.py b/tests/bugs/test_core_2501.py new file mode 100644 index 00000000..14970cad --- /dev/null +++ b/tests/bugs/test_core_2501.py @@ -0,0 +1,57 @@ +#coding:utf-8 +# +# id: bugs.core_2501 +# title: Binary shift functions give wrong results with negative shift values +# decription: +# tracker_id: CORE-2501 +# min_versions: ['2.5'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """select bin_shl(100, -1) from rdb$database; +select bin_shr(100, -1) from rdb$database; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + BIN_SHL +===================== + + BIN_SHR +===================== +""" +expected_stderr_1 = """Statement failed, SQLSTATE = 42000 + +expression evaluation not supported + +-Argument for BIN_SHL must be zero or positive + +Statement failed, SQLSTATE = 42000 + +expression evaluation not supported + +-Argument for BIN_SHR must be zero or positive + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_2501_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2505.py b/tests/bugs/test_core_2505.py new file mode 100644 index 00000000..d5d8b38e --- /dev/null +++ b/tests/bugs/test_core_2505.py @@ -0,0 +1,66 @@ +#coding:utf-8 +# +# id: bugs.core_2505 +# title: Built-in trigonometric functions can produce NaN and Infinity +# decription: +# tracker_id: CORE-2505 +# min_versions: ['2.5'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """select asin(2), cot(0) from rdb$database; +select acos(2) - acos(2) from rdb$database; +select LOG10(-1) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ASIN COT +======================= ======================= + + SUBTRACT +======================= + + LOG10 +======================= +""" +expected_stderr_1 = """Statement failed, SQLSTATE = 42000 + +expression evaluation not supported + +-Argument for COT must be different than zero + +Statement failed, SQLSTATE = 42000 + +expression evaluation not supported + +-Argument for ACOS must be in the range [-1, 1] + +Statement failed, SQLSTATE = 42000 + +expression evaluation not supported + +-Argument for LOG10 must be positive + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_2505_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2508.py b/tests/bugs/test_core_2508.py new file mode 100644 index 00000000..97c6d162 --- /dev/null +++ b/tests/bugs/test_core_2508.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: bugs.core_2508 +# title: Tricky index names can defeat the parsing logic when generating a human readable plan +# decription: +# +# tracker_id: CORE-2508 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table t(a int not null); + create index "abc(" on t(a); + set planonly; + select * from t where a in (0, 1, 2); + -- This will produce in 2.5.x: + -- PLAN (T INDEX (abc(abc(abc()) + -- ^^^ ^^^ + -- | | + -- +---+--- NO commas here! + -- Compare with 3.0: + -- PLAN (T INDEX (abc(, abc(, abc()) + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (T INDEX (abc(, abc(, abc()) + """ + +@pytest.mark.version('>=3.0') +def test_core_2508_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2516.py b/tests/bugs/test_core_2516.py new file mode 100644 index 00000000..c01fb3d1 --- /dev/null +++ b/tests/bugs/test_core_2516.py @@ -0,0 +1,51 @@ +#coding:utf-8 +# +# id: bugs.core_2516 +# title: Wrong processing a SP parameters with arrays +# decription: +# tracker_id: CORE-2516 +# min_versions: [] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create domain t_smallint_array as smallint [0:2]; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create procedure sp_smallint_array(x t_smallint_array) + returns (y t_smallint_array) + as + begin + y=x; + suspend; + end + ^ set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 0A000 + CREATE PROCEDURE 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.0') +def test_core_2516_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_2531.py b/tests/bugs/test_core_2531.py new file mode 100644 index 00000000..368b0eb9 --- /dev/null +++ b/tests/bugs/test_core_2531.py @@ -0,0 +1,225 @@ +#coding:utf-8 +# +# id: bugs.core_2531 +# title: The famous "cannot transliterate" error may be thrown when selecting data from the monitoring tables +# decription: +# In order to check issues of ticket we have to create Python script which is encoded in non-ascii codepage and also +# its codepage should be NON utf8 (choosed: Windows 1252). This is because all .fbt files have to be encoded only in UTF8, +# so we can not put inside .fbt a statement which contains non-ascii SINGLE-BYTE characters. +# +# Character |å|, "LATIN SMALL LETTER A WITH RING ABOVE", was selected in order to verify ticket issue, see: +# http://www.fileformat.info/info/unicode/char/00e5/index.htm +# +# Temporary Python file ("tmp_2531_run.py") will contain encoding statement ('# coding: latin-1') followed by commands for: +# 1) make first attachment to database, by Python itself, with charset = Win1252, with preparing: "select 'gång' from rdb$database"; +# also, this attachments SAVES string of this query into table (NOTE: it works with charset = win1252); +# 2) make second attachment by ISQL, with charset = utf8, which will query mon$statements.mon$sql_text - this should return query +# which has been prepared by first attachment. This query is compared to that which was stored into table by attachment-1, +# and these rows should be equal: |select 'gång' from rdb$database| +# +# Confirmed wrong (incompleted) output of mon$sql_text on 2.1.0.17798 (but there is no "cannot transliterate" error): +# === +# select 'gång: ' || current_timestamp from rdb$database +# select 'g +# ^^^ +# | +# +--- three white-spaces here (after 'g') +# === +# No such effect on builds >= 2.1.3.18185. +# +# Refactored 08-may-2017: replaced buggy "folder.replace()" with bulk of backslashes ("") with locals() usage. +# Checked again on Classic for: WI-V3.0.2.32708, WI-T4.0.0.633 +# (added expression to WHERE-block to filter out record from mon$statements with RDB$AUTH_MAPPING data). +# +# 02-MAR-2021: +# Changed code in order to remove dependency on PATH-list (CLI utilities must be invoked using context['..._path']) +# Full path+name of FB client library file is passed to generated Python code. +# Removed unneeded variables. +# +# Checked on Windows: 4.0.0.2377 (SS/CS), 3.0.8.33420 (SS/CS), 2.5.9.27152 (SC) +# Checked on Linux: 4.0.0.2377, 3.0.8.33415. +# +# tracker_id: CORE-2531 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('SQL_TEXT_BLOB_ID .*', ''), ('[\t ]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import sys +# import subprocess +# import time +# import codecs +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# engine = db_conn.engine_version +# db_conn.close() +# +# svc = services.connect() +# FB_HOME = os.path.normpath( svc.get_home_directory() ) # 'c: +# irebird' --> 'c: +# irebird' (i.e. remove trailing backslash if needed) +# svc.close() +# +# FB_CLNT = '' +# if os.name == 'nt': +# # For Windows we assume that client library is always in FB_HOME dir: +# if engine < 3: +# FB_CLNT=os.path.join(FB_HOME, 'bin', 'fbclient.dll') +# else: +# FB_CLNT=os.path.join(FB_HOME, 'fbclient.dll') +# else: +# # For Linux client library will be searched in 'lib' subdirectory of FB_HOME: +# # con=fdb.connect( dsn='localhost:employee', fb_library_name='/var/tmp/fb40tmp/lib/libfbclient.so', ...) +# FB_CLNT=os.path.join(FB_HOME, 'lib', 'libfbclient.so' ) +# +# #-------------------------------------------- +# +# 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'): +# # 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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# #non_ascii_query="select 'gång' from rdb$database" +# non_ascii_query=u"select 'gång' as non_ascii_literal from rdb$database" +# +# f_sql_txt=''' +# set count on; +# set blob all; +# set list on; +# select stored_sql_expr from non_ascii; +# select +# c.rdb$character_set_name as connection_charset +# ,s.mon$sql_text as sql_text_blob_id +# from mon$attachments a +# left join rdb$character_sets c on a.mon$character_set_id = c.rdb$character_set_id +# left join mon$statements s on a.mon$attachment_id = s.mon$attachment_id +# where +# s.mon$attachment_id <> current_connection +# and s.mon$sql_text containing 'non_ascii_literal' +# ; +# ''' +# +# f_mon_sql = open( os.path.join(context['temp_directory'], 'tmp_2531_w1252.sql'), 'w' ) +# f_mon_sql.write(f_sql_txt) +# flush_and_close( f_mon_sql ) +# +# isql_path = context['isql_path'] +# isql_file = f_mon_sql.name +# +# ###################################################################### +# ### t e m p o r a r y P y t h o n s c r i p t s t ar t ### +# ###################################################################### +# f_python_txt='''# coding: latin-1 +# import os +# import fdb +# import subprocess +# os.environ["ISC_USER"] = '%(user_name)s' +# os.environ["ISC_PASSWORD"] = '%(user_password)s' +# +# att1 = fdb.connect(dsn = r'%(dsn)s', fb_library_name = r'%(FB_CLNT)s', charset = 'win1252') +# att1.execute_immediate("recreate table non_ascii(stored_sql_expr varchar(255) character set win1252)") +# att1.commit() +# +# txt = "%(non_ascii_query)s" +# +# cur1=att1.cursor() +# cur1.execute( "insert into non_ascii(stored_sql_expr) values('%%s')" %% txt.replace("'","''") ) +# att1.commit() +# +# # The will cause SQL expression with non-ascii character +# # appear in mon$statements.mon$sql_text column. +# # NOTE: charset of current connection is >>> win1252 <<< +# cur1.prep(txt) +# +# subprocess.call([ r'%(isql_path)s', r'%(dsn)s', '-ch', 'utf8', '-i', r'%(isql_file)s' ]) +# +# cur1.close() +# att1.commit() +# att1.close() +# ''' % dict(globals(), **locals()) +# ############## temporary Python script finish ################### +# +# +# ##################################################################### +# ### Create temporary Python script with code page = Windows-1252, ### +# ### so |select 'gång' from rdb$database| will be written there in ### +# ### single-byte encoding rather than in utf8. ### +# #################################################################### +# f_python_run=codecs.open( os.path.join(context['temp_directory'],'tmp_2531_w1252.py'), encoding='cp1252', mode='w') +# f_python_run.write(f_python_txt) +# +# flush_and_close( f_python_run ) +# time.sleep(1) +# +# runProgram( sys.executable, [f_python_run.name] ) +# +# # 02.03.2021 DO NOT! subprocess.call( [sys.executable, f_python_run.name] ) -- for unknown reason this will NOT issu anything to STDOUT! +# +# time.sleep(1) +# +# # 02.03.2021: do NOT pass to cleanup() files! +# # It will fail with 'uknown type' for executed script ('f_python_run') +# # because it will consider its type as 'instance' rather than common 'file'! +# # We have to pass only NAMES list of used files here: +# cleanup( [i.name for i in (f_python_run,f_mon_sql)] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + STORED_SQL_EXPR select 'gång' as non_ascii_literal from rdb$database + Records affected: 1 + CONNECTION_CHARSET WIN1252 + select 'gång' as non_ascii_literal from rdb$database + Records affected: 1 + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_2531_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2538.py b/tests/bugs/test_core_2538.py new file mode 100644 index 00000000..c6e7f75d --- /dev/null +++ b/tests/bugs/test_core_2538.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_2538 +# title: PSQL doesnt allow to use singleton query result as input parameter of stored procedure when procedure accessed using 'execute procedure' +# decription: +# tracker_id: CORE-2538 +# min_versions: [] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """set term ^ ; + +create procedure P (I integer) +returns (O integer) +AS +BEGIN + SUSPEND; +END ^ +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """set term ^ ; + +execute block +as +declare variable i integer; +begin + select 1 from P((select 1 from rdb$database)) into :i; +end ^ + +execute block +as +declare variable i integer; +begin + execute procedure P((select 1 from rdb$database)) returning_values :i; +end ^ +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5') +def test_core_2538_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_2555.py b/tests/bugs/test_core_2555.py new file mode 100644 index 00000000..14a0e2a0 --- /dev/null +++ b/tests/bugs/test_core_2555.py @@ -0,0 +1,132 @@ +#coding:utf-8 +# +# id: bugs.core_2555 +# title: CI column does not group correctly with a second column +# decription: +# tracker_id: CORE-2555 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test( + rk char(1) character set none + ,ca varchar(10) character set utf8 collate unicode_ci_ai + ,cb varchar(10) character set utf8 collate unicode_ci + ,id int generated by default as identity constraint pk_test primary key using index pk_test + ); + commit; + + -- Letters from latin-1 with diacritic marks: http://en.wikipedia.org/wiki/ISO/IEC_8859-1 + insert into test(rk, ca, cb) values('d', 'ð', 'd'); + insert into test(rk, ca, cb) values('d', 'Ð', 'd'); + insert into test(rk, ca, cb) values('d', 'Ð', 'D'); + insert into test(rk, ca, cb) values('d', 'd', 'd'); + + insert into test(rk, ca, cb) values('l', 'l', 'Ł'); + insert into test(rk, ca, cb) values('l', 'ł', 'ł'); + + insert into test(rk, ca, cb) values('o', 'Ø', 'õ'); + insert into test(rk, ca, cb) values('o', 'o', 'Õ'); + insert into test(rk, ca, cb) values('o', 'Ó', 'Õ'); + insert into test(rk, ca, cb) values('o', 'õ', 'Õ'); + insert into test(rk, ca, cb) values('o', 'Ö', 'õ'); + + insert into test(rk, ca, cb) values('a', 'Ą', 'ä'); + insert into test(rk, ca, cb) values('a', 'Á', 'Ä'); + insert into test(rk, ca, cb) values('a', 'à', 'ä'); + insert into test(rk, ca, cb) values('a', 'â', 'ä'); + + insert into test(rk, ca, cb) values('c', 'ç', 'Ç'); + insert into test(rk, ca, cb) values('c', 'Ç', 'ç'); + insert into test(rk, ca, cb) values('c', 'C', 'Ç'); + + insert into test(rk, ca, cb) values('u', 'Ú', 'û'); + insert into test(rk, ca, cb) values('u', 'Ù', 'Û'); + insert into test(rk, ca, cb) values('u', 'ü', 'û'); + + insert into test(rk, ca, cb) values('s', 'Š', 'Š'); + insert into test(rk, ca, cb) values('s', 'ş', 'š'); + insert into test(rk, ca, cb) values('s', 'š', 'Š'); + + insert into test(rk, ca, cb) values('n', 'Ñ', 'ñ'); + insert into test(rk, ca, cb) values('n', 'ñ', 'ñ'); + insert into test(rk, ca, cb) values('n', 'Ň', 'Ñ'); + commit; + + set list on; + set plan on; + + -- First, we check result of NATURAL scans: + select rk from test group by ca,cb,rk; + commit; + + -- Then, check results of GROUP BY when it can use index. + -- ::: NOTE ::: + -- As of current state (WI-T3.0.0.31832 beta-2), FB cah do GROUP BY + -- WITH using of index on multi-byte or insensitive collation only + -- when this index is: 1) UNIQUE and 2) ASCENDING. + -- Index still not used in DISTINCT statement, so it's not checked. + -- See comments in CORE-4787. + create unique index test_unq1 on test(ca, cb, rk, id); + 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; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + + PLAN SORT (TEST NATURAL) + RK a + RK c + RK d + RK l + RK n + RK o + RK s + RK u + + PLAN (TEST ORDER TEST_UNQ1) + RK a + RK c + RK d + RK l + RK n + RK o + RK s + RK u + + PLAN (TEST ORDER TEST_UNQ2) + RK a + RK c + RK d + RK l + RK n + RK o + RK s + RK u + """ + +@pytest.mark.version('>=3.0') +def test_core_2555_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2560.py b/tests/bugs/test_core_2560.py new file mode 100644 index 00000000..9fc29aaf --- /dev/null +++ b/tests/bugs/test_core_2560.py @@ -0,0 +1,547 @@ +#coding:utf-8 +# +# id: bugs.core_2560 +# title: Maximum and minimum identifier length should be enforced by DSQL +# decription: +# Changed expected_stderr for 4.0 after discuss with dimitr (see letter 01-aug-2016 15:15). +# Checked on WI-T4.0.0.356, 03-sep-2016. +# +# tracker_id: CORE-2560 +# min_versions: ['3.0'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + --set echo on; + select 1 as cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc + from rdb$database order by cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc; + + select 1 from rdb$database dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd + where dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd.rdb$relation_id > 10; + + savepoint zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz; + + create role rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr; + create sequence gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg; + + create collation uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu for iso8859_1; + + create user zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz password 'q'; + + savepoint ""; + rollback to ""; + + create role ""; + grant select on t1 to role ""; + grant "" to public; + drop role ""; + + create user "" password 'q'; + create user tmp$c2560 password ''; + + create sequence ""; + create domain "" int; + create exception "" as '@1'; + create view "" as select 1 from rdb$database; + create table ""(x int); + create table tx("" int); + create procedure "" as begin end; + create procedure p("" int) as begin end; + set term ^; + create function "" returns int as begin return 1; end + ^ + recreate package "" as + begin + function pg_func(a int) returns bigint; + end + ^ + create package body "" as + begin + function pg_func(a int) returns bigint as + begin + return a * a; + end + end + recreate package pg_test as + begin + function ""(a int) returns bigint; + end + ^ + create package body pg_test as + begin + function ""(a int) returns bigint as + begin + return a * a; + end + end + ^ + execute block returns("" int) as + begin + "" = 1; + suspend; + end + ^ + set term ^; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE USER TMP$C2560 failed + -Password should not be empty string + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_core_2560_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + +# version: 4.0 +# resources: None + +substitutions_2 = [('After line.*', ''), ('-At line[:]{0,1}[\\s]+[\\d]+,[\\s]+column[:]{0,1}[\\s]+[\\d]+', '')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + --set echo on; + --set list on; + + create role +r2345678901234567890123456789012345678901234567890123456789012345; + + create sequence +g2345678901234567890123456789012345678901234567890123456789012345; + + create exception +e2345678901234567890123456789012345678901234567890123456789012345 'foo!..'; + + create collation +c2345678901234567890123456789012345678901234567890123456789012345 for utf8 from unicode; + + create domain +d2345678901234567890123456789012345678901234567890123456789012345 int; + + create table +t2345678901234567890123456789012345678901234567890123456789012345 (x int); + + create table +x( +t2345678901234567890123456789012345678901234567890123456789012345 int); + + create or alter procedure +p2345678901234567890123456789012345678901234567890123456789012345 as begin end; + + set term ^; + create or alter procedure p1 returns( +o2345678901234567890123456789012345678901234567890123456789012345 int +) as +begin + suspend; +end^ + +create or alter procedure p2 returns(o2 double precision) as + declare +v2345678901234567890123456789012345678901234567890123456789012345 + int; +begin + select rand()*1000 as +a2345678901234567890123456789012345678901234567890123456789012345 + from rdb$database + into +v2345678901234567890123456789012345678901234567890123456789012345 + o2 = sqrt( +v2345678901234567890123456789012345678901234567890123456789012345 +); + suspend; +end^ + + + create or alter function +f2345678901234567890123456789012345678901234567890123456789012345 returns int as +begin + return 1; +end^ + + create or alter function +f( +a2345678901234567890123456789012345678901234567890123456789012345 int ) returns int as +begin + return 1; +end^ + + recreate package +p2345678901234567890123456789012345678901234567890123456789012345 + as begin + function f(a int) returns bigint; + end + ^ + + recreate package p1 as + begin + function +f2345678901234567890123456789012345678901234567890123456789012345( a int) returns bigint; + end + ^ + + recreate package p2 as + begin + function g( +a2345678901234567890123456789012345678901234567890123456789012345 int) returns bigint; + end + ^ + + set term ;^ +commit; + + -- deferred, see CORE-5277: + create or alter user +u2345678901234567890123456789012345678901234567890123456789012345 password 'q'; + commit; + + -- ############ check that empty names are forbidden ############### + + create role ""; + + create sequence ""; + + create domain "" int; + + create exception "" as '@1'; + + create view "" as select 1 from rdb$database; + + create table ""(x int); + + create table tx("" int); + + create procedure "" as begin end; + + create procedure p("" int) as begin end; + + set term ^; + create function "" returns int as begin return 1; end + ^ + recreate package "" as + begin + function pg_func(a int) returns bigint; + end + ^ + create package body "" as + begin + function pg_func(a int) returns bigint as + begin + return a * a; + end + end + + recreate package pg_test as + begin + function ""(a int) returns bigint; + end + ^ + create package body pg_test as + begin + function ""(a int) returns bigint as + begin + return a * a; + end + end + ^ + execute block returns("" int) as + begin + "" = 1; + suspend; + end + ^ + set term ^; + + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stderr_2 = """ + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + After line 0 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + After line 5 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + After line 8 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + After line 11 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + After line 14 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + After line 17 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + After line 20 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + After line 24 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + After line 29 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + After line 35 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + After line 51 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + After line 58 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + After line 65 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + After line 72 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + After line 79 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + After line 89 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + After line 94 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + After line 98 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + After line 100 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + After line 102 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + After line 104 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + After line 106 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + After line 108 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + After line 110 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + After line 112 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + After line 116 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + After line 118 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + After line 123 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + After line 136 in file c2560-x.sql + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + After line 144 in file c2560-x.sql + """ + +@pytest.mark.version('>=4.0') +def test_core_2560_2(act_2: Action): + act_2.expected_stderr = expected_stderr_2 + act_2.execute() + assert act_2.clean_expected_stderr == act_2.clean_stderr + diff --git a/tests/bugs/test_core_2566.py b/tests/bugs/test_core_2566.py new file mode 100644 index 00000000..7b18e7a8 --- /dev/null +++ b/tests/bugs/test_core_2566.py @@ -0,0 +1,57 @@ +#coding:utf-8 +# +# id: bugs.core_2566 +# title: internal error [335544384] +# decription: +# tracker_id: CORE-2566 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + create table tab_partner ( + id_partner integer not null, + stav char(1) not null, + id_bankucet integer + ); + + create table typ_stav (hodnota char(1) not null); + + create view x_partner (id_partner, stav) as + select p.id_partner, p.stav + from tab_partner p + left join typ_stav tss on p.stav=tss.hodnota + ; + + insert into tab_partner(id_partner, stav, id_bankucet) values(0, 'A', null); + + select * + from x_partner; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID_PARTNER 0 + STAV A + """ + +@pytest.mark.version('>=2.5') +def test_core_2566_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2573.py b/tests/bugs/test_core_2573.py new file mode 100644 index 00000000..bad8a207 --- /dev/null +++ b/tests/bugs/test_core_2573.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: bugs.core_2573 +# title: The server crashes when selecting from the MON$ tables in the ON DISCONNECT trigger +# decription: +# tracker_id: CORE-2573 +# min_versions: [] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# sql = """CREATE OR ALTER TRIGGER DIST +# ON DISCONNECT POSITION 0 +# AS +# declare variable i integer; +# begin +# select mon$stat_id from mon$attachments rows 1 into :i; +# end +# """ +# +# c = db_conn.cursor() +# c.execute(sql) +# db_conn.commit() +# db_conn.close() +# +# db_conn = kdb.connect(dsn=dsn,user=user_name,password=user_password) +# c = db_conn.cursor() +# c.execute("DROP TRIGGER DIST") +# db_conn.commit() +# db_conn.close() +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_2573_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2578.py b/tests/bugs/test_core_2578.py new file mode 100644 index 00000000..055af49b --- /dev/null +++ b/tests/bugs/test_core_2578.py @@ -0,0 +1,66 @@ +#coding:utf-8 +# +# id: bugs.core_2578 +# title: select rdb$db_key from a view with a more than 1 table joined, results in conversion error +# decription: +# tracker_id: CORE-2578 +# min_versions: [] +# versions: 2.1.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE TABLE_A ( + F_A INTEGER, + F_B INTEGER +); + +CREATE TABLE TABLE_B( + F_A INTEGER, + F_C INTEGER +); + +CREATE VIEW VIEW_A( + K1, + K2, + F_A, + F_B, + F_C) +AS +select A.rdb$db_key, B.rdb$db_key, A.F_A, A.F_B, B.F_C from table_A A +left join table_B B on A.F_A = B.F_A; + +commit; + +insert into TABLE_A (F_A,F_B) values (1,1) ; +insert into TABLE_B (F_A,F_C) values (1,1) ; +commit; + +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select rdb$db_key from VIEW_A order by 1 ; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +DB_KEY +================================ +81000000010000008000000001000000 + +""" + +@pytest.mark.version('>=2.1.4') +def test_core_2578_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2579.py b/tests/bugs/test_core_2579.py new file mode 100644 index 00000000..05ce1a53 --- /dev/null +++ b/tests/bugs/test_core_2579.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: bugs.core_2579 +# title: Parameters and variables cannot be used as expressions in EXECUTE PROCEDURE parameters without a colon prefix +# decription: +# tracker_id: CORE-2579 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """set term ^ ; + +create procedure P123 (param int) +as +begin + execute procedure p123 (param); +end ^ + +set term ; ^ +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.0') +def test_core_2579_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_2581.py b/tests/bugs/test_core_2581.py new file mode 100644 index 00000000..8aa0b7f1 --- /dev/null +++ b/tests/bugs/test_core_2581.py @@ -0,0 +1,71 @@ +#coding:utf-8 +# +# id: bugs.core_2581 +# title: Infinity should not escape from the engine +# decription: +# tracker_id: CORE-2581 +# min_versions: [] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """set sql dialect 1; +select 1e161/1e-161from rdb$database; + +set sql dialect 3; +select 1e308 + 1e308 from rdb$database; +select 1e308 - -1e308 from rdb$database; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """WARNING: Client SQL dialect has been set to 1 when connecting to Database SQL dialect 3 database. + + DIVIDE +======================= + + ADD +======================= + + SUBTRACT +======================= +""" +expected_stderr_1 = """Statement failed, SQLSTATE = 22003 + +arithmetic exception, numeric overflow, or string truncation + +-Floating-point overflow. The exponent of a floating-point operation is greater than the magnitude allowed. + +Statement failed, SQLSTATE = 22003 + +arithmetic exception, numeric overflow, or string truncation + +-Floating-point overflow. The exponent of a floating-point operation is greater than the magnitude allowed. + +Statement failed, SQLSTATE = 22003 + +arithmetic exception, numeric overflow, or string truncation + +-Floating-point overflow. The exponent of a floating-point operation is greater than the magnitude allowed. + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_2581_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2582.py b/tests/bugs/test_core_2582.py new file mode 100644 index 00000000..464bc94a --- /dev/null +++ b/tests/bugs/test_core_2582.py @@ -0,0 +1,98 @@ +#coding:utf-8 +# +# id: bugs.core_2582 +# title: Infinity from UDF should be trapped by the engine +# decription: +# 24.01.2019. +# Disabled this test to be run on FB 4.0: added record to '%FBT_REPO% ests\\qa4x-exclude-list.txt'. +# UDF usage is deprecated in FB 4+, see: ".../doc/README.incompatibilities.3to4.txt". +# Added EMPTY section for FB version 4.0 in this .fbt as one more way to protect from running. +# +# tracker_id: CORE-2582 +# min_versions: ['2.5.0'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + DECLARE EXTERNAL FUNCTION DPOWER + DOUBLE PRECISION BY DESCRIPTOR, DOUBLE PRECISION BY DESCRIPTOR, DOUBLE PRECISION BY DESCRIPTOR + RETURNS PARAMETER 3 + ENTRY_POINT 'power' MODULE_NAME 'fbudf'; + + DECLARE EXTERNAL FUNCTION XASIN + DOUBLE PRECISION + RETURNS DOUBLE PRECISION BY VALUE + ENTRY_POINT 'IB_UDF_asin' MODULE_NAME 'ib_udf'; + + DECLARE EXTERNAL FUNCTION XDIV + INTEGER, INTEGER + RETURNS DOUBLE PRECISION BY VALUE + ENTRY_POINT 'IB_UDF_div' MODULE_NAME 'ib_udf'; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select dpower(1e120, 3) from rdb$database; + select xasin(2) from rdb$database; + select xdiv(10, 0) from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 39000 + expression evaluation not supported + -Floating point overflow in result from UDF DPOWER + -UDF: DPOWER + + Statement failed, SQLSTATE = 39000 + expression evaluation not supported + -Invalid floating point value returned by UDF XASIN + -UDF: XASIN + + Statement failed, SQLSTATE = 39000 + expression evaluation not supported + -Floating point overflow in result from UDF XDIV + -UDF: XDIV + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_core_2582_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + -- This section was intentionally left empty. + -- No message should be in expected_* sections. + -- It is STRONGLY RECOMMENDED to add this ticket + -- in the 'excluded-list file: + -- %FBT_REPO% ests\\qa4x-exclude-list.txt + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + + +@pytest.mark.version('>=4.0') +def test_core_2582_2(act_2: Action): + act_2.execute() + diff --git a/tests/bugs/test_core_2584.py b/tests/bugs/test_core_2584.py new file mode 100644 index 00000000..f8a708ad --- /dev/null +++ b/tests/bugs/test_core_2584.py @@ -0,0 +1,79 @@ +#coding:utf-8 +# +# id: bugs.core_2584 +# title: Wrong results for CASE used together with GROUP BY +# decription: +# tracker_id: CORE-2584 +# min_versions: ['2.5'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- 08.03.2015: removed code based on data in RDB$ tables - they differs in 2.5 vs 3.0. + recreate table rf(rp int); + commit; + + set term ^; + execute block as + declare n int = 250; + begin + delete from rf; + while (n>0) do insert into rf(rp) values( mod(:n, 1+mod(:n,7) ) )returning :n-1 into n; + end + ^ set term ;^ + commit; + + set list on; + select + rp as a, + case rp + when 0 then '0' + when 1 then '1' + when 2 then '2' + when 3 then '3' + when 4 then '4' + end as b, + count(*) as cnt + from rf + where rp < 5 + group by 1, 2; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A 0 + B 0 + CNT 87 + A 1 + B 1 + CNT 52 + A 2 + B 2 + CNT 34 + A 3 + B 3 + CNT 22 + A 4 + B 4 + CNT 14 + """ + +@pytest.mark.version('>=2.5.0') +def test_core_2584_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2602.py b/tests/bugs/test_core_2602.py new file mode 100644 index 00000000..5195435e --- /dev/null +++ b/tests/bugs/test_core_2602.py @@ -0,0 +1,144 @@ +#coding:utf-8 +# +# id: bugs.core_2602 +# title: Attachments using NONE charset may cause reads from MON$ tables to fail +# decription: +# Fully refactored 05-feb-2018. Apply HASH() functions to unicode mon$sql_text in order to returnonly numeric value +# rather than non-translatable unicode representation which can differ on machines with different codepage / OS. +# For example, instead of (on Win XP with codepage 1251): +# r2none (u'othr', u "select '123\\ u0413\\ u040e\\ u0413\\ xa9456' from mon$database", 4, u'UTF8') +# - result was different on Win 2008 R2 with codepage 437 +# r2none (u'othr', u "select '123\\ xc3\\ xa1\\ xc3\\ xa9456' from mon$database", 4, u'UTF8') +# --------------------------------------------------------------------------------------- +# Confirmed bug on 2.1.3.18185, got exception: +# fdb.fbcore.DatabaseError: ('Cursor.fetchone: +# - SQLCODE: -901 +# - lock conflict on no wait transaction', -901, 335544345) +# - just after issued 1st cursor result. +# No error since 2.5.0.26074. +# +# 25.12.2019: added filtering expr to WHERE clause in order to prevent from passing through records related to RDB$AUTH table (4.x). +# Last tested 25.12.2019 on: +# 4.0.0.1707 SS: 1.448s. +# 4.0.0.1346 SC: 1.295s. +# 4.0.0.1691 CS: 2.009s. +# 3.0.5.33218 SS: 0.733s. +# 3.0.5.33084 SC: 0.673s. +# 3.0.5.33212 CS: 1.755s. +# 2.5.9.27149 SC: 0.218s. +# 2.5.9.27119 SS: 2.411s. +# +# tracker_id: CORE-2602 +# min_versions: ['2.5'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import fdb +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# c1none=fdb.connect(dsn=dsn,charset='none') +# c1utf8=fdb.connect(dsn=dsn,charset='utf8') +# +# c2none=fdb.connect(dsn=dsn,charset='none') +# c2utf8=fdb.connect(dsn=dsn,charset='utf8') +# +# r1none = c1none.cursor() +# r1utf8 = c1utf8.cursor() +# +# r2none = c2none.cursor() +# r2utf8 = c2utf8.cursor() +# +# # In attachment with charset = NONE we start query to mon$database which includes two non-ascii characters: +# # 1) Unicode Character 'LATIN SMALL LETTER A WITH ACUTE' (U+00E1) +# # 2) Unicode Character 'LATIN SMALL LETTER E WITH ACUTE' (U+00E9) +# r1none.execute("select '123áé456' from mon$database") +# +# sql=''' +# select +# iif(s.mon$attachment_id = current_connection, 'this', 'othr') as attach +# -- do NOT return SQL text of query with non-ascii characters: it can be displayed differently +# -- depending on machine codepage (or OS?): +# -- >>> disabled 05-feb-2018 >>> , iif(s.mon$sql_text like '%123%456%', s.mon$sql_text, '') as sql_text +# -- Use HASH(sql_text) instead. Bug (in 2.1.3) still can be reproduces with hash() also: +# ,hash(s.mon$sql_text) as sql_text_hash +# ,trim(c.rdb$character_set_name) as charset_name +# from mon$statements s +# join mon$attachments a on s.mon$attachment_id = a.mon$attachment_id +# join rdb$character_sets c on a.mon$character_set_id = c.rdb$character_set_id +# where +# s.mon$attachment_id != current_connection +# and s.mon$sql_text NOT containing 'mon$statements' +# and s.mon$sql_text NOT containing 'rdb$auth' +# and a.mon$remote_protocol is not null +# ''' +# +# r2none.execute(sql) +# for r in r2none: +# #print( ' '.join( 'THIS connect with charset NONE. OTHER connect tiwh charset UTF8.', 'WE see other sqltest hash as: ', r[0], '; sql_text_hash: ', str( r[1] ), '; charset_name', r[2] ) ) +# #print('r2none',r) +# print( ' '.join( ( 'Attach: r2none.', r[0], '; sql_text_hash: ', str( r[1] ), '; charset_name', r[2] ) ) ) +# +# r2utf8.execute(sql) +# for r in r2utf8: +# print( ' '.join( ( 'Attach: r2utf8.', r[0], '; sql_text_hash: ', str( r[1] ), '; charset_name', r[2] ) ) ) +# #print('r2utf8',r) +# +# c1none.close() +# #---------------------------- +# +# r1utf8.execute("select '123áé456' from mon$database") +# +# c2none.commit() +# c2utf8.commit() +# +# r2none.execute(sql) +# for r in r2none: +# #print('r2none', r) +# print( ' '.join( ( 'Attach: r2none.', r[0], '; sql_text_hash: ', str( r[1] ), '; charset_name', r[2] ) ) ) +# +# r2utf8.execute(sql) +# for r in r2utf8: +# #print('r2utf8', r) +# print( ' '.join( ( 'Attach: r2utf8.', r[0], '; sql_text_hash: ', str( r[1] ), '; charset_name', r[2] ) ) ) +# +# c1utf8.close() +# #--------------------------- +# +# c2none.close() +# c2utf8.close() +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Attach: r2none. othr ; sql_text_hash: 98490476833044645 ; charset_name NONE + Attach: r2utf8. othr ; sql_text_hash: 98490476833044645 ; charset_name NONE + Attach: r2none. othr ; sql_text_hash: 97434734411675813 ; charset_name UTF8 + Attach: r2utf8. othr ; sql_text_hash: 97434734411675813 ; charset_name UTF8 + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_2602_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2606.py b/tests/bugs/test_core_2606.py new file mode 100644 index 00000000..ab1ba4ac --- /dev/null +++ b/tests/bugs/test_core_2606.py @@ -0,0 +1,78 @@ +#coding:utf-8 +# +# id: bugs.core_2606 +# title: Multibyte CHAR value requested as VARCHAR is returned with padded spaces +# decription: +# tracker_id: CORE-2606 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# +# db_conn.close() +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# sql_cmd=''' +# set list on; +# +# select s.rdb$character_set_name as client_charset +# from mon$attachments a +# join rdb$character_sets s on a.mon$character_set_id = s.rdb$character_set_id +# where a.mon$attachment_id=current_connection; +# +# --set sqlda_display on; +# --set planonly; +# --set echo on; +# +# select cast('A' as char character set utf8) || '.' as char1_utf8 from rdb$database; +# select cast('A' as varchar(1) character set utf8) || '.' as varc1_utf8 from rdb$database; +# select cast('A' as char character set ascii) || '.' char1_ascii from rdb$database; +# select cast('A' as varchar(1) character set ascii) || '.' varc1_ascii from rdb$database; +# ''' +# +# # Wrong result was encountered only in FB 1.5.6, for cast('A' as Char charset utf8 / ascii), on any client charset. +# # Varchar always returns expected output. +# +# runProgram('isql',['-q', '-ch', 'UTF8', dsn], sql_cmd) +# runProgram('isql',['-q', '-ch', 'SJIS_0208', dsn], sql_cmd) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CLIENT_CHARSET UTF8 + CHAR1_UTF8 A. + VARC1_UTF8 A. + CHAR1_ASCII A. + VARC1_ASCII A. + CLIENT_CHARSET SJIS_0208 + CHAR1_UTF8 A. + VARC1_UTF8 A. + CHAR1_ASCII A. + VARC1_ASCII A. + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_2606_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2607.py b/tests/bugs/test_core_2607.py new file mode 100644 index 00000000..9b50f1a6 --- /dev/null +++ b/tests/bugs/test_core_2607.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_2607 +# title: Introducer (_charset) problems with monitoring and persistent modules +# decription: Usage of introducer (_charset ) is problematic due to usage of different character sets in a single command. The problems are different from version to version, and may be transliteration error, malformed string or just unexpected things. +# tracker_id: CORE-2607 +# min_versions: [] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# c = db_conn.cursor() +# con2 = kdb.connect(dsn=dsn,user=user_name,password=user_password) +# c2 = con2.cursor() +# +# c.execute("select _dos850 '123áé456' from rdb$database") +# c2.execute("select mon$sql_text from mon$statements s where s.mon$sql_text containing '_dos850'") +# #printData(c2) +# for r in c2: +# print(r[0]) +# +# con2.close() +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + select mon$sql_text from mon$statements s where s.mon$sql_text containing '_dos850' + select _dos850 X'313233C3A1C3A9343536' from rdb$database + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_2607_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2612.py b/tests/bugs/test_core_2612.py new file mode 100644 index 00000000..f3b252a6 --- /dev/null +++ b/tests/bugs/test_core_2612.py @@ -0,0 +1,51 @@ +#coding:utf-8 +# +# id: bugs.core_2612 +# title: Connection lost immediatelly after compiling procedure with RPAD system function +# decription: +# tracker_id: CORE-2612 +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create procedure TEST2 (name varchar(50),spaces integer) + returns (rname varchar(200)) + as + begin + rname = name || rpad(' ',:spaces,' '); + suspend; + end^ + set term ;^ + commit; + set list on; + set count on; + select rname || 'end' as rname_padded from TEST2 ('test',5); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RNAME_PADDED test end + Records affected: 1 + """ + +@pytest.mark.version('>=2.5.0') +def test_core_2612_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2615.py b/tests/bugs/test_core_2615.py new file mode 100644 index 00000000..4854d959 --- /dev/null +++ b/tests/bugs/test_core_2615.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: bugs.core_2615 +# title: Silent truncation when using utf8 parameters and utf8 client character set encoding +# decription: +# tracker_id: CORE-2615 +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE test (c CHAR(10) CHARACTER SET UTF8); +COMMIT;""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """INSERT INTO test VALUES ('012345679012345'); +COMMIT;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 22001 +arithmetic exception, numeric overflow, or string truncation +-string right truncation +-expected length 10, actual 15 +""" + +@pytest.mark.version('>=3.0') +def test_core_2615_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_2632.py b/tests/bugs/test_core_2632.py new file mode 100644 index 00000000..3ed2206b --- /dev/null +++ b/tests/bugs/test_core_2632.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_2632 +# title: Invalid BLOB ID when working with monitoring tables +# decription: +# tracker_id: CORE-2632 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('SQL_TEXT_BLOB.*', 'SQL_TEXT_BLOB')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set blob all; + select 1 as k from mon$database; + set count on; + + select s.mon$sql_text as sql_text_blob + from mon$statements s + where s.mon$sql_text NOT containing 'rdb$auth_mapping' -- added 30.03.2017 (4.0.0.x) + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + K 1 + SQL_TEXT_BLOB + select 1 as k from mon$database + + Records affected: 1 + """ + +@pytest.mark.version('>=2.5') +def test_core_2632_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2633.py b/tests/bugs/test_core_2633.py new file mode 100644 index 00000000..759912e1 --- /dev/null +++ b/tests/bugs/test_core_2633.py @@ -0,0 +1,75 @@ +#coding:utf-8 +# +# id: bugs.core_2633 +# title: SELECT WITH LOCK with no fields are accessed clears the data +# decription: +# tracker_id: CORE-2633 +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE T (A VARCHAR(20), B INTEGER); +INSERT INTO T(A,B) VALUES('aaaa',1); +INSERT INTO T(A,B) VALUES('bbbb',2); +INSERT INTO T(A,B) VALUES('cccc',3); +COMMIT; +""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT * FROM T; + +SET TERM ^; +EXECUTE BLOCK AS +DECLARE I INTEGER; +BEGIN + FOR SELECT 1 FROM T WITH LOCK INTO :I DO I=I; +END^ +SET TERM ;^ + +SELECT * FROM T; + +ROLLBACK; + +SELECT * FROM T; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +A B +==================== ============ +aaaa 1 +bbbb 2 +cccc 3 + + +A B +==================== ============ +aaaa 1 +bbbb 2 +cccc 3 + + +A B +==================== ============ +aaaa 1 +bbbb 2 +cccc 3 + +""" + +@pytest.mark.version('>=3.0') +def test_core_2633_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2635.py b/tests/bugs/test_core_2635.py new file mode 100644 index 00000000..b2dfc6cb --- /dev/null +++ b/tests/bugs/test_core_2635.py @@ -0,0 +1,72 @@ +#coding:utf-8 +# +# id: bugs.core_2635 +# title: Unique index with a lot of NULL keys can be corrupted at level 1 +# decription: +# tracker_id: CORE-2635 +# min_versions: ['2.1.4', '2.0.6', '2.5'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """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 + + 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 ^ +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# db_conn.close() +# runProgram('gfix',['-validate','-full','-no_update','-user',user_name,'-password',user_password,dsn]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_2635_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2650.py b/tests/bugs/test_core_2650.py new file mode 100644 index 00000000..0c0d336b --- /dev/null +++ b/tests/bugs/test_core_2650.py @@ -0,0 +1,468 @@ +#coding:utf-8 +# +# id: bugs.core_2650 +# title: Improve sorting performance when long VARCHARs are involved +# decription: +# 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. +# +# 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). +# +# Checked on 4.0.0.2303 SS/CS. +# +# tracker_id: CORE-2650 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + recreate view v_unioned as select 1 id from rdb$database; + commit; + + recreate table test( + id int + ,f01 int + ,f02 int + ,txt_short varchar(998) + ,txt_broad varchar(999) + ,computed_id_dup computed by( id*2 ) + ,computed_ts_dup computed by ( txt_short || txt_short ) + ,computed_tb_dup computed by ( txt_broad || txt_broad ) + ,computed_guid computed by ( lpad('', 2000, uuid_to_char(gen_uuid()) ) ) + ,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 + ,txt_short varchar(983) + ); + + recreate table test_ns_02( + id decfloat + ,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) + ); + + recreate table test_ns_04( + id time with time zone + ,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) + ); + + recreate table test_ns_06( + id varchar(1) character set utf8 collate unicode_ci_ai + ,txt_short varchar(992) + ); + + select * from test_ns_05 order by id; -- must use refetch + + select * from test_ns_06 order by id; -- must NOT use refetch + + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Select Expression + -> Sort (record length: 1036, key length: 8) + -> Table "TEST" as "A01" Full Scan + + Select Expression + -> Refetch + -> Sort (record length: 28, key length: 8) + -> Table "TEST" as "A02" Full Scan + + Select Expression + -> First N Records + -> Refetch + -> Sort (record length: 28, key length: 8) + -> Table "TEST" as "A03" Full Scan + + Select Expression + -> Sort (record length: 1036, key length: 8) + -> Table "TEST" Full Scan + + Select Expression + -> Refetch + -> Sort (record length: 28, key length: 8) + -> Table "TEST" Full Scan + + Select Expression + -> Filter + -> Sort (record length: 1036, key length: 8) + -> Filter + -> Table "TEST" as "X04" Full Scan + Select Expression + -> Filter + -> Table "TEST" as "A04" Full Scan + + Select Expression + -> 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 + + 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 + -> Table "TEST" as "A06" Full Scan + + 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 + -> Table "TEST" as "A07" 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 + + 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 + + Select Expression + -> Filter + -> Sort (record length: 1036, key length: 8) + -> Filter + -> Table "TEST" as "X10" Full Scan + Select Expression + -> Filter + -> Table "TEST" as "A10" Full Scan + + Select Expression + -> 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + Select Expression + -> Refetch + -> Sort (record length: 44, key length: 24) + -> Table "TEST_NS_01" as "A23" Full Scan + + 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 + + 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_core_2650_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2651.py b/tests/bugs/test_core_2651.py new file mode 100644 index 00000000..9ed32509 --- /dev/null +++ b/tests/bugs/test_core_2651.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_2651 +# title: Incorrect "string right truncation" error with NONE column and multibyte connection charset +# decription: +# tracker_id: CORE-2651 +# min_versions: [] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table TEST_NONE +(VARCHAR_1 VARCHAR(1) CHARACTER SET NONE); + +insert into test_none values (ascii_char(1)); +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# con = kdb.connect(dsn=dsn,user=user_name,password=user_password,charset='CP943C') +# c = con.cursor() +# try: +# c.execute("select * from TEST_NONE") +# except: +# print("Test FAILED") +# finally: +# con.close() +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_2651_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2660.py b/tests/bugs/test_core_2660.py new file mode 100644 index 00000000..3e934d92 --- /dev/null +++ b/tests/bugs/test_core_2660.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: bugs.core_2660 +# title: COUNT(*) incorrectly returns 0 when a condition of an outer join doesn't match +# decription: +# tracker_id: CORE-2660 +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """select b.* + from rdb$database a + left join ( + select count(*) c + from rdb$database + ) b on 1 = 0;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + C +===================== + + +""" + +@pytest.mark.version('>=3.0') +def test_core_2660_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2668.py b/tests/bugs/test_core_2668.py new file mode 100644 index 00000000..5bc57e38 --- /dev/null +++ b/tests/bugs/test_core_2668.py @@ -0,0 +1,267 @@ +#coding:utf-8 +# +# id: bugs.core_2668 +# title: Write note into log when automatic sweep is started +# decription: +# In order to make database be 'ready' for sweep auto-start we: +# 1. Launch ISQL in async. process (using Python subprocess.Popen() unit) which does: +# 1.1. Change DB sweep interval to small value (100 selected). +# 1.2. Create table and add one row in it (marked as 'LOCKED_FOR_PAUSE') + COMMIT. +# 1.3. Start EXECUTE BLOCK with adding 150 of rows in autonomous transactions +# (this lead eventually to difference Next - OIT =~ 150). +# 1.4. Run execute block with ES/EDS which will establish new attachment (we specify +# there connection ROLE as some non-existent string, see ":v_role" usage below). +# This EB will try to UPDATE record which is LOCKED now by 1st ("main") attachment. +# ISQL will infinitelly hang since this moment. +# +# 2. Run (in main Python thread) FBSVCMGR with: +# 2.1. Moving database to SHUTDOWN state; +# 2.2. Returning database back to ONLINE. +# 2.3. Obtaining content of firebird.log and storing it in separate file ('f_fblog_before'). +# 2.4. Creating connect to DB and start transaction in order SWEEP will auto start. +# 2.5. Take small delay (~2..3 seconds) in order to allow OS to finish writing new messages +# about SWEEP auto-start in firebird.log. +# 2.6. Obtaining content of firebird.log and storing it in separate file ('f_fblog_after'). +# +# 3. Compare two files: f_fblog_before and f_fblog_after (using Python package "diff"). +# Checked on: +# 4.0.0.2173 SS/SC/CS +# 3.0.7.33357 SS/SC/CS +# 2.5.9.27152 SS/SC/CS +# +# tracker_id: CORE-2668 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import sys +# import time +# import subprocess +# from subprocess import Popen +# import difflib +# import shutil +# import re +# +# def svc_get_fb_log( engine, f_fb_log ): +# +# import subprocess +# +# if engine.startswith('2.5'): +# get_firebird_log_key='action_get_ib_log' +# else: +# get_firebird_log_key='action_get_fb_log' +# +# subprocess.call([ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# get_firebird_log_key +# ], +# stdout=f_fb_log, stderr=subprocess.STDOUT +# ) +# return +# +# engine = str(db_conn.engine_version) +# db_file=db_conn.database_name +# +# db_conn.close() +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# #--------------------------------------------- +# +# 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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# f_init_log = open( os.path.join(context['temp_directory'],'tmp_init_2668.log'), 'w') +# +# subprocess.call( [context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "prp_sweep_interval", "100", +# "dbname", db_file, +# ], +# stdout = f_init_log, +# stderr = subprocess.STDOUT +# ) +# +# subprocess.call([ context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "prp_write_mode", "prp_wm_async", +# "dbname", db_file ], +# stdout = f_init_log, +# stderr = subprocess.STDOUT +# ) +# +# f_work_sql=open( os.path.join(context['temp_directory'],'tmp_work_2668.sql'), 'w') +# +# sql_dml=''' +# 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 = 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; +# +# v_role = left(replace( uuid_to_char(gen_uuid()), '-', ''), 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 +# end +# end +# +# end +# ^ +# set term ;^ +# set heading off; +# select '-- shutdown me now --' from rdb$database; +# ''' +# f_work_sql.write(sql_dml) +# flush_and_close( f_work_sql ) +# +# f_work_log=open( os.path.join(context['temp_directory'],'tmp_work_2668.log'), 'w') +# +# p_work_sql=Popen( [context['isql_path'], dsn, "-i", f_work_sql.name], stdout = f_work_log, stderr = subprocess.STDOUT ) +# time.sleep(3) +# +# subprocess.call( [context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "prp_shutdown_mode", "prp_sm_full", "prp_shutdown_db", "0", +# "dbname", db_file, +# ], +# stdout = f_init_log, +# stderr = subprocess.STDOUT +# ) +# +# +# p_work_sql.terminate() +# flush_and_close( f_work_log ) +# +# subprocess.call( [context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "prp_db_online", +# "dbname", db_file, +# ], +# stdout = f_init_log, +# stderr = subprocess.STDOUT +# ) +# +# flush_and_close( f_init_log ) +# +# # 4 debug only -- shutil.copy2(db_file, os.path.splitext(db_file)[0]+'.copy.fdb') +# +# f_fblog_before=open( os.path.join(context['temp_directory'],'tmp_2668_fblog_before.txt'), 'w') +# svc_get_fb_log( engine, f_fblog_before ) +# flush_and_close( f_fblog_before ) +# +# ########################################### +# # Make connection to database. +# # SWEEP should be auto started at this point: +# ########################################### +# +# con_for_sweep_start=fdb.connect(dsn = dsn) +# +# # NOTE: it is mandatory to start transaction for auto-sweep: +# con_for_sweep_start.begin() +# +# # _!_!_!_!_!_!_!_!_!_! do NOT reduce this delay: firebird.log get new messages NOT instantly !_!_!_!_!_!_!_!_ +# # Currently firebird.log can stay with OLD content if heavy concurrent workload exists on the same host! +# time.sleep(2) +# +# con_for_sweep_start.close() +# +# f_fblog_after=open( os.path.join(context['temp_directory'],'tmp_2668_fblog_after.txt'), 'w') +# svc_get_fb_log( engine, f_fblog_after ) +# flush_and_close( f_fblog_after ) +# +# oldfb=open(f_fblog_before.name, 'r') +# newfb=open(f_fblog_after.name, 'r') +# +# difftext = ''.join(difflib.unified_diff( +# oldfb.readlines(), +# newfb.readlines() +# )) +# oldfb.close() +# newfb.close() +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_2668_diff.txt'), 'w') +# f_diff_txt.write(difftext) +# flush_and_close( f_diff_txt ) +# +# pattern = re.compile('Sweep\\s+.*SWEEPER', re.IGNORECASE) +# +# # NB: difflib.unified_diff() can show line(s) that present in both files, without marking that line(s) with "+". +# # Usually these are 1-2 lines that placed just BEFORE difference starts. +# # So we have to check output before display diff content: lines that are really differ must start with "+". +# +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# if line.startswith('+') and pattern.search(line): +# print('Expected line FOUND.') +# +# ############################### +# # Cleanup. +# time.sleep(1) +# cleanup( [x.name for x in (f_init_log,f_work_sql,f_work_log,f_fblog_before,f_fblog_after,f_diff_txt) ] ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Expected line FOUND. + """ + +@pytest.mark.version('>=2.5.2') +@pytest.mark.xfail +def test_core_2668_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2678.py b/tests/bugs/test_core_2678.py new file mode 100644 index 00000000..b697c2db --- /dev/null +++ b/tests/bugs/test_core_2678.py @@ -0,0 +1,72 @@ +#coding:utf-8 +# +# id: bugs.core_2678 +# title: Full outer join cannot use available indices (very slow execution) +# decription: +# tracker_id: CORE-2678 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table td_data1 ( + c1 varchar(20) character set win1251 not null collate win1251, + c2 integer not null, + c3 date not null, + d1 float not null + ); + create index idx_td_data1 on td_data1(c1,c2,c3); + commit; + + create table td_data2 ( + c1 varchar(20) character set win1251 not null collate win1251, + c2 integer not null, + c3 date not null, + d2 float not null + ); + create index idx_td_data2 on td_data2(c1,c2,c3); + commit; + + set planonly; + select + d1.c1, d2.c1, + d1.c2, d2.c2, + d1.c3, d2.c3, + coalesce(sum(d1.d1), 0) t1, + coalesce(sum(d2.d2), 0) t2 + from td_data1 d1 + full join td_data2 d2 + on + d2.c1 = d1.c1 + and d2.c2 = d1.c2 + and d2.c3 = d1.c3 + group by + d1.c1, d2.c1, + d1.c2, d2.c2, + d1.c3, d2.c3; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN SORT (JOIN (JOIN (D2 NATURAL, D1 INDEX (IDX_TD_DATA1)), JOIN (D1 NATURAL, D2 INDEX (IDX_TD_DATA2)))) + """ + +@pytest.mark.version('>=3.0') +def test_core_2678_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2685.py b/tests/bugs/test_core_2685.py new file mode 100644 index 00000000..a85aaa14 --- /dev/null +++ b/tests/bugs/test_core_2685.py @@ -0,0 +1,112 @@ +#coding:utf-8 +# +# id: bugs.core_2685 +# title: System triggers on view with check option are not removed +# decription: +# tracker_id: CORE-2685 +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Updated code: made STDOUT independent of Firebird version + -- Note about SIMILAR TO: one need here to specify backslash TWICE inside escape clause, + -- e.g: ... escape '\\' (fbt_run feature ?) + set list on; + set width dep_name1 10; + set width dep_name2 10; + set width dep_name3 10; + set width dep_name4 10; + + create or alter view v1 as select 1 id from rdb$database; + commit; + recreate table test_table (id integer, caption varchar(10)); + + ------ block 1 ----- + + create or alter view v1 as + select id, caption from test_table where id > 0; + commit; + + select upper(left(rdb$dependent_name,5)) dep_name1 + from rdb$database b + left join rdb$dependencies d on + d.rdb$depended_on_name = upper( 'v1' ) + and trim(d.rdb$dependent_name) similar to upper('check\\_[[:digit:]]+') escape '\\' + ; + + ------ block 2 ----- + + create or alter view v1 as select id ,caption from test_table where id > 0 + with check option; + commit; + + select upper(left(rdb$dependent_name,5)) dep_name2 + from rdb$database + left join rdb$dependencies d on + d.rdb$depended_on_name = upper( 'v1' ) + and trim(d.rdb$dependent_name) similar to upper('check\\_[[:digit:]]+') escape '\\' + ; + ------ block 3 ----- + + create or alter view v1 as select id, caption from test_table where id > 0 + with check option; + + create or alter view v1 as select id, caption from test_table where id > 0 + with check option; + + create or alter view v1 as select id,caption from test_table where id > 0 + with check option; + commit; + select upper(left(rdb$dependent_name,5)) dep_name3 + from rdb$database + left join rdb$dependencies d on + d.rdb$depended_on_name = upper( 'v1' ) + and trim(d.rdb$dependent_name) similar to upper('check\\_[[:digit:]]+') escape '\\' + ; + + ------ block 4 ----- + + create or alter view v1 as select id,caption from test_table where id > 0; + create or alter view v1 as select id from test_table where id > 0; + commit; + + select upper(left(rdb$dependent_name,5)) dep_name4 + from rdb$database + left join rdb$dependencies d on + d.rdb$depended_on_name = upper( 'v1' ) + and trim(d.rdb$dependent_name) similar to upper('check\\_[[:digit:]]+') escape '\\' + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DEP_NAME1 + DEP_NAME2 CHECK + DEP_NAME2 CHECK + DEP_NAME2 CHECK + DEP_NAME3 CHECK + DEP_NAME3 CHECK + DEP_NAME3 CHECK + DEP_NAME4 + """ + +@pytest.mark.version('>=2.5.0') +def test_core_2685_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2697.py b/tests/bugs/test_core_2697.py new file mode 100644 index 00000000..1d8dc61b --- /dev/null +++ b/tests/bugs/test_core_2697.py @@ -0,0 +1,75 @@ +#coding:utf-8 +# +# id: bugs.core_2697 +# title: Support the "? in (SELECT some_col FROM some_table)" subqueries +# decription: +# tracker_id: CORE-2697 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table t1(id int, x int); + commit; + recreate table t2(id int, t1_id int, y int); + commit; + insert into t1 values(1, 100); + insert into t1 values(2, 200); + insert into t1 values(3, 300); + + insert into t2 values(11, 1, 111); + insert into t2 values(12, 1, 112); + insert into t2 values(13, 1, 113); + insert into t2 values(33, 3, 333); + insert into t2 values(34, 3, 334); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set term ^; + execute block returns(x_in_t2 int) as + declare v_stt varchar(255); + begin + v_stt = + 'select t1.x ' + || 'from t1 ' + || 'where t1.x > 0 ' + || 'and ( ? in ( select mod(t2.id, 2) from t2 where t1.id = t2.t1_id ) )'; + for + execute statement ( v_stt ) ( 0 ) into x_in_t2 + do + suspend; + end + ^ + set term ;^ + -- Output in 2.5: + -- Statement failed, SQLSTATE = HY004 + -- Dynamic SQL Error + -- -SQL error code = -804 + -- -Data type unknown + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + X_IN_T2 100 + X_IN_T2 300 + """ + +@pytest.mark.version('>=3.0') +def test_core_2697_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2699.py b/tests/bugs/test_core_2699.py new file mode 100644 index 00000000..598ebe87 --- /dev/null +++ b/tests/bugs/test_core_2699.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_2699 +# title: Common table expression context could be used with parameters +# decription: +# tracker_id: CORE-2699 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('-At line.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + with x as ( + select 1 n from rdb$database + ) + select * from x(10); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -204 + -Procedure unknown + -X + -At line 4, column 15 + """ + +@pytest.mark.version('>=3.0') +def test_core_2699_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_2712.py b/tests/bugs/test_core_2712.py new file mode 100644 index 00000000..9b3a55ed --- /dev/null +++ b/tests/bugs/test_core_2712.py @@ -0,0 +1,71 @@ +#coding:utf-8 +# +# id: bugs.core_2712 +# title: Do not print "invalid request BLR" for par.cpp errors with valid BLR +# decription: +# +# tracker_id: CORE-2712 +# min_versions: ['3.0.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('table id [0-9]+ is not defined', 'table is not defined')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# msg='' +# +# att1 = kdb.connect(dsn=dsn) +# cur1 = att1.cursor() +# cur1.execute("recreate table test(x int)") +# att1.commit() +# cur1.execute("insert into test values(1)") +# att1.commit() +# +# att2 = kdb.connect(dsn=dsn) +# cur2 = att2.cursor() +# cur2.execute("select 1 from rdb$database") +# +# cur1.execute("drop table test") +# try: +# cur2.prep("update test set x=-x") +# att2.commit() +# except Exception as e: +# msg = e[0] +# print(msg) +# +# att1.close() +# att2.close() +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Error while preparing SQL statement: + - SQLCODE: -219 + - table id 128 is not defined + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_2712_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2720.py b/tests/bugs/test_core_2720.py new file mode 100644 index 00000000..651ef22d --- /dev/null +++ b/tests/bugs/test_core_2720.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: bugs.core_2720 +# title: Wrong evaluation result with divide and unary plus\\minus operations +# decription: +# tracker_id: CORE-2720 +# min_versions: ['2.0.6'] +# versions: 2.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT 36/4/3, 36/-4/3, 36/+4/3, 36/+-4/3, 36/-+4/3, 36/- -4/3, 36/++4/3 FROM RDB$DATABASE;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Database: localhost:C: btest2 mpugs.core_2720.fdb, User: SYSDBA +SQL> + DIVIDE DIVIDE DIVIDE DIVIDE DIVIDE DIVIDE DIVIDE +===================== ===================== ===================== ===================== ===================== ===================== ===================== + 3 -3 3 -3 -3 3 3 + +SQL>""" + +@pytest.mark.version('>=2.0.6') +def test_core_2720_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2721.py b/tests/bugs/test_core_2721.py new file mode 100644 index 00000000..b11a2b5d --- /dev/null +++ b/tests/bugs/test_core_2721.py @@ -0,0 +1,79 @@ +#coding:utf-8 +# +# id: bugs.core_2721 +# title: Issue with SIMILAR TO and UTF8 on 2.5 Beta 2 (and 1) +# decription: +# tracker_id: CORE-2721 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core2721.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + select * from test where utf8field similar to 'DELL %'; + select * from test where utf8field similar to 'DE %'; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ANSIFIELD DELL COMPUTERS + UTF8FIELD DELL COMPUTERS + UNICODECIFIELD DELL COMPUTERS + + ANSIFIELD DELL BV + UTF8FIELD DELL BV + UNICODECIFIELD DELL BV + + ANSIFIELD DELL BV-GLOBAL COMMUNITY + UTF8FIELD DELL BV-GLOBAL COMMUNITY + UNICODECIFIELD DELL BV-GLOBAL COMMUNITY + + Records affected: 3 + + ANSIFIELD DE HEER P.W. BALFOORT + UTF8FIELD DE HEER P.W. BALFOORT + UNICODECIFIELD DE HEER P.W. BALFOORT + + ANSIFIELD DE DRIESTAR + UTF8FIELD DE DRIESTAR + UNICODECIFIELD DE DRIESTAR + + ANSIFIELD DE SINGEL + UTF8FIELD DE SINGEL + UNICODECIFIELD DE SINGEL + + ANSIFIELD DE BOER PLASTIK B.V. + UTF8FIELD DE BOER PLASTIK B.V. + UNICODECIFIELD DE BOER PLASTIK B.V. + + ANSIFIELD DE LOOT PC REPAIR + UTF8FIELD DE LOOT PC REPAIR + UNICODECIFIELD DE LOOT PC REPAIR + + ANSIFIELD DE HEER P.W. BALFOORT + UTF8FIELD DE HEER P.W. BALFOORT + UNICODECIFIELD DE HEER P.W. BALFOORT + + Records affected: 6 + """ + +@pytest.mark.version('>=2.5') +def test_core_2721_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2722.py b/tests/bugs/test_core_2722.py new file mode 100644 index 00000000..4a75bcec --- /dev/null +++ b/tests/bugs/test_core_2722.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: bugs.core_2722 +# title: Storage of malformed blob is allowed when copying from a blob with NONE/OCTETS charset +# decription: +# tracker_id: CORE-2722 +# min_versions: [] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t (b1 blob sub_type text, b2 blob sub_type text character set utf8); + +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """-- This is correct and raise "Malformed string" error +insert into t (b2) values (x'F0'); + +insert into t (b1) values (x'F0'); + +-- This should raise second "Malformed string" error +update t set b2 = b1; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 22000 +Malformed string +Statement failed, SQLSTATE = 22000 +Malformed string +""" + +@pytest.mark.version('>=2.5') +def test_core_2722_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_2724.py b/tests/bugs/test_core_2724.py new file mode 100644 index 00000000..9a2d3ce2 --- /dev/null +++ b/tests/bugs/test_core_2724.py @@ -0,0 +1,268 @@ +#coding:utf-8 +# +# id: bugs.core_2724 +# title: Validate or transform string of DML queries so that engine internals doesn't receive malformed strings +# decription: +# Code from doc/sql.extensions/README.ddl_triggers.txt was taken as basis for this test +# (see ticket issue: "This situation happened with DDL triggers ..."). +# Several DB objects are created here and their DDL contain unicode (Greek) text. +# Attachment these issues these DDL intentionally is run with charset = NONE. +# This charset (NONE) should result in question marks after we finish DDL and want to query log table +# that was filled by DDL trigger and contains issued DDL statements. +# +# tracker_id: CORE-2724 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('SQL_TEXT .*', 'SQL_TEXT'), ('RESULT_INFO .*', 'RESULT_INFO')] + +init_script_1 = """ + create sequence ddl_seq; + + create table ddl_log ( + id bigint not null primary key, + moment timestamp not null, + current_connection_cset varchar(31) not null, + event_type varchar(25) not null, + object_type varchar(25) not null, + ddl_event varchar(25) not null, + object_name varchar(31) not null, + old_object_name varchar(31), + new_object_name varchar(31), + sql_text blob sub_type text not null, + ok char(1) not null, + result_info blob sub_type text + ); + commit; + + set term ^; + create trigger trig_ddl_log_before before any ddl statement + as + declare id type of column ddl_log.id; + declare v_current_connection_cset varchar(31); + begin + -- We do the changes in an AUTONOMOUS TRANSACTION, so if an exception happens and the command + -- didn't run, the log will survive. + in autonomous transaction do + begin + + select coalesce(c.rdb$character_set_name, '??? NULL ???') + from mon$attachments a + left join rdb$character_sets c on a.mon$character_set_id = c.rdb$character_set_id + where a.mon$attachment_id = current_connection + into v_current_connection_cset; + + insert into ddl_log (id, moment, current_connection_cset, + event_type, object_type, ddl_event, object_name, + old_object_name, new_object_name, sql_text, ok, result_info) + values (next value for ddl_seq, + 'now', + :v_current_connection_cset, + rdb$get_context('DDL_TRIGGER', 'EVENT_TYPE'), + rdb$get_context('DDL_TRIGGER', 'OBJECT_TYPE'), + rdb$get_context('DDL_TRIGGER', 'DDL_EVENT'), + rdb$get_context('DDL_TRIGGER', 'OBJECT_NAME'), + rdb$get_context('DDL_TRIGGER', 'OLD_OBJECT_NAME'), + rdb$get_context('DDL_TRIGGER', 'NEW_OBJECT_NAME'), + rdb$get_context('DDL_TRIGGER', 'SQL_TEXT'), + 'N', + 'Κάτι συνέβη. Θα πρέπει να ελέγξετε') -- Something was wrong. One need to check this. + returning id into id; + rdb$set_context('USER_SESSION', 'trig_ddl_log_id', id); + end + end + ^ + + -- Note: the above trigger will fire for this DDL command. It's good idea to use -nodbtriggers + -- when working with them! + create trigger trig_ddl_log_after after any ddl statement + as + begin + -- Here we need an AUTONOMOUS TRANSACTION because the original transaction will not see the + -- record inserted on the BEFORE trigger autonomous transaction if user transaction is not + -- READ COMMITTED. + in autonomous transaction do + update ddl_log set ok = 'Y', + result_info = 'Τα πάντα ήταν επιτυχής' -- Everything has completed successfully + where id = rdb$get_context('USER_SESSION', 'trig_ddl_log_id'); + end + ^ + set term ;^ + commit; + + -- So lets delete the record about trig_ddl_log_after creation. + delete from ddl_log; + commit; + """ + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import time +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# +# sql_check=''' delete from ddl_log; +# commit; +# +# create domain dm_name varchar(50) check (value in ('αμορτισέρ', 'κόμβο', 'σωλήνα', 'φέροντα', 'βραχίονα')); +# recreate table t1 ( +# saller_id integer -- αναγνωριστικό εμπόρου // ID of saler +# ,customer_id integer -- αναγνωριστικό πελάτη // ID of customer +# ,product_name dm_name +# ); +# commit; +# set list on; +# +# select id, current_connection_cset, sql_text, result_info, ddl_event, object_name +# from ddl_log order by id; +# +# commit; +# drop table t1; +# drop domain dm_name; +# exit; +# ''' +# +# f_check_sql = open( os.path.join(context['temp_directory'],'tmp_check_2724.sql'), 'w') +# f_check_sql.write(sql_check) +# flush_and_close( f_check_sql ) +# +# ########################################################################################## +# +# f_ch_none_log = open( os.path.join(context['temp_directory'],'tmp_ch_none_2724.log'), 'w') +# f_ch_none_err = open( os.path.join(context['temp_directory'],'tmp_ch_none_2724.err'), 'w') +# +# subprocess.call( [context['isql_path'], dsn, "-i", f_check_sql.name, +# "-ch", "none"], +# stdout = f_ch_none_log, +# stderr = f_ch_none_err +# ) +# +# flush_and_close( f_ch_none_log ) +# flush_and_close( f_ch_none_err ) +# +# ########################################################################################## +# +# f_ch_utf8_log = open( os.path.join(context['temp_directory'],'tmp_ch_utf8_2724.log'), 'w') +# f_ch_utf8_err = open( os.path.join(context['temp_directory'],'tmp_ch_utf8_2724.err'), 'w') +# +# subprocess.call( [context['isql_path'], dsn, "-user", user_name, "-password", user_password, "-i", f_check_sql.name, +# "-ch", "utf8"], +# stdout = f_ch_utf8_log, +# stderr = f_ch_utf8_err +# ) +# flush_and_close( f_ch_utf8_log ) +# flush_and_close( f_ch_utf8_err ) +# +# +# f_list = [f_ch_none_log, f_ch_none_err, f_ch_utf8_log, f_ch_utf8_err] +# for f in f_list: +# with open( f.name,'r') as f: +# print(f.read()) +# +# +# # Cleanup +# ######### +# time.sleep(1) +# +# f_list.append(f_check_sql) +# cleanup( [i.name for i in f_list] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 2 + CURRENT_CONNECTION_CSET NONE + SQL_TEXT + create domain dm_name varchar(50) check (value in ('??????????????????', '??????????', '????????????', '??????????????', '????????????????')) + RESULT_INFO + Τα πάντα ήταν επιτυχής + DDL_EVENT CREATE DOMAIN + OBJECT_NAME DM_NAME + + ID 3 + CURRENT_CONNECTION_CSET NONE + SQL_TEXT + recreate table t1 ( + saller_id integer -- ?????????????????????????? ?????????????? // ID of saler + ,customer_id integer -- ?????????????????????????? ???????????? // ID of customer + ,product_name dm_name + ) + RESULT_INFO + Τα πάντα ήταν επιτυχής + DDL_EVENT CREATE TABLE + OBJECT_NAME T1 + + ID 6 + CURRENT_CONNECTION_CSET UTF8 + SQL_TEXT 80:0 + create domain dm_name varchar(50) check (value in ('αμορτισέρ', 'κόμβο', 'σωλήνα', 'φέροντα', 'βραχίονα')) + RESULT_INFO 80:2 + Τα πάντα ήταν επιτυχής + DDL_EVENT CREATE DOMAIN + OBJECT_NAME DM_NAME + + ID 7 + CURRENT_CONNECTION_CSET UTF8 + SQL_TEXT + recreate table t1 ( + saller_id integer -- αναγνωριστικό εμπόρου // ID of saler + ,customer_id integer -- αναγνωριστικό πελάτη // ID of customer + ,product_name dm_name + ) + RESULT_INFO + Τα πάντα ήταν επιτυχής + DDL_EVENT CREATE TABLE + OBJECT_NAME T1 + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_2724_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2729.py b/tests/bugs/test_core_2729.py new file mode 100644 index 00000000..5821d518 --- /dev/null +++ b/tests/bugs/test_core_2729.py @@ -0,0 +1,136 @@ +#coding:utf-8 +# +# id: bugs.core_2729 +# title: Current connection may be used by EXECUTE STATEMENT instead of creation of new attachment +# decription: +# Checked on: +# 4.0.0.1635 SS: 1.326s. +# 4.0.0.1633 CS: 1.725s. +# 3.0.5.33180 SS: 0.953s. +# 3.0.5.33178 CS: 1.565s. +# 2.5.9.27119 SS: 0.431s. +# 2.5.9.27146 SC: 0.328s. +# +# tracker_id: CORE-2729 +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Refactored 05-JAN-2016: removed dependency on recource 'test_user' because this lead to: + -- UNTESTED: bugs.core_2729 + -- Add new user + -- Unexpected stderr stream received from GSEC. + -- (i.e. test remained in state "Untested" because of internal error in gsec while creating user 'test' from resource). + -- Checked on WI-V2.5.5.26952 (SC), WI-V3.0.0.32266 (SS/SC/CS). + + set wng off; + -- Drop old account if it remains from prevoius run: + set term ^; + execute block as + begin + begin + execute statement 'drop user tmp$c2729a' with autonomous transaction; + when any do begin end + end + begin + execute statement 'drop user tmp$c2729b' with autonomous transaction; + when any do begin end + end + end + ^ + set term ;^ + commit; + + create user tmp$c2729a password 'QweRtyUi'; + create user tmp$c2729b password 'AsdFghJk'; + commit; + + connect '$(DSN)' user 'TMP$C2729A' password 'QweRtyUi'; + + -- Updated code: made STDOUT insensible to the IDs of attaches + set list on; + set term ^; + execute block returns ( + user_on_start varchar(32), + user_on_extds varchar(32), + same_attach char(1) + ) as + declare v_att_ini int; + declare v_att_eds int; + begin + + user_on_start = current_user; + v_att_ini = current_connection; + + execute statement 'select current_user, current_connection from rdb$database' + into :user_on_extds, :v_att_eds; + + + same_attach = iif( v_att_ini = v_att_eds, 'Y', 'N'); + suspend; + + execute statement 'select current_user, current_connection from rdb$database' + as user 'TMP$C2729B' password 'AsdFghJk' + into :user_on_extds, :v_att_eds; + + same_attach = iif( v_att_ini = v_att_eds, 'Y', 'N'); + suspend; + + end + ^ + set term ;^ + commit; + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + + -- |||||||||||||||||||||||||||| + -- ###################################||| 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; + + drop user tmp$c2729a; + drop user tmp$c2729b; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + USER_ON_START TMP$C2729A + USER_ON_EXTDS TMP$C2729A + SAME_ATTACH Y + + USER_ON_START TMP$C2729A + USER_ON_EXTDS TMP$C2729B + SAME_ATTACH N + """ + +@pytest.mark.version('>=2.5.0') +def test_core_2729_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2731.py b/tests/bugs/test_core_2731.py new file mode 100644 index 00000000..10036e18 --- /dev/null +++ b/tests/bugs/test_core_2731.py @@ -0,0 +1,105 @@ +#coding:utf-8 +# +# id: bugs.core_2731 +# title: Recursive EXECUTE STATEMENT works wrong +# decription: +# Checked on: +# 4.0.0.1635 SS: 2.030s. +# 4.0.0.1633 CS: 5.765s. +# 3.0.5.33180 SS: 3.016s. +# 3.0.5.33178 CS: 4.001s. +# 2.5.9.27119 SS: 0.519s. +# 2.5.9.27146 SC: 0.965s. +# +# tracker_id: CORE-2731 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('[-]{0,1}At block line: [\\d]+, col: [\\d]+', '')] + +init_script_1 = """ + recreate table SQL_SOURCE( + SQL_SOURCE varchar(32000) + ); + commit; + + insert into SQL_SOURCE values( + 'execute block as + declare variable SQL type of column SQL_SOURCE.SQL_SOURCE; + begin + select first(1) SQL_SOURCE from SQL_SOURCE into :SQL; + execute statement :SQL + -- YOUR DB + on external ''$(DSN)'' + as user ''SYSDBA'' password ''masterkey''; + end' + ); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^ ; + execute block as + declare v_sql type of column SQL_SOURCE.SQL_SOURCE; + begin + select first(1) SQL_SOURCE from SQL_SOURCE into :v_sql; + execute statement :v_sql; + end ^ + 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + Execute statement error at isc_dsql_execute2 : + 335544926 : Execute statement error at isc_dsql_execute2 : + 335544926 : Execute statement error at isc_dsql_execute2 : + 335544926 : Execute statement error at isc_dsql_execute2 : + 335544926 : Execute statement error at isc_dsql_execute2 : + 335544926 : Execute statement error at isc_dsql_execute2 : + 335544926 : Execute statement error at isc_dsql_execute2 : + 335544926 : Execute statement error at isc_dsql_execute2 : + 335544926 : Execute statement error at isc_dsql_execute2 : + 335544926 : Execute statement error at isc_dsql_execute2 : + 335544926 : Execute statement error at isc_dsql_execute2 : + 335544926 : Execute statement error at isc_dsql_execute2 : + 335544926 : Execute statement error at isc_dsql_execute2 : + 335544926 : Execute statement error at isc_dsql_execute2 : + 335544926 : Execute statement error at isc_dsql_execute2 : + 335544926 : Execute statement error at isc_dsql_execute2 : + 335544926 : Execute statement error at isc_dsql_execute2 : + 335544926 : Execute statement... + -At block line: 5, col: 5 + """ + +@pytest.mark.version('>=2.5') +def test_core_2731_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_2735.py b/tests/bugs/test_core_2735.py new file mode 100644 index 00000000..60ebebc2 --- /dev/null +++ b/tests/bugs/test_core_2735.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: bugs.core_2735 +# title: isql hangs when trying to show a view based on a procedure +# decription: +# tracker_id: CORE-2735 +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """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;""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """show view vp1; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """A INTEGER Nullable +View Source: +==== ====== + select a from p +""" + +@pytest.mark.version('>=2.5.0') +def test_core_2735_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2741.py b/tests/bugs/test_core_2741.py new file mode 100644 index 00000000..0c35cbd4 --- /dev/null +++ b/tests/bugs/test_core_2741.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: bugs.core_2741 +# title: Naive metadata extraction code in isql is defeated by "check" keyword typed in mixed case +# decription: +# tracker_id: CORE-2741 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create domain dm_int int cHeCk(vAlUE<>0); + create domain dm_dts timestamp cHeCk(valUe<>cUrrent_timEstamp); + commit; + show domain dm_int; + show domain dm_dts; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DM_INT INTEGER Nullable + cHeCk(vAlUE<>0) + DM_DTS TIMESTAMP Nullable + cHeCk(valUe<>cUrrent_timEstamp) + """ + +@pytest.mark.version('>=2.5') +def test_core_2741_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2755.py b/tests/bugs/test_core_2755.py new file mode 100644 index 00000000..6f6e93cf --- /dev/null +++ b/tests/bugs/test_core_2755.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: bugs.core_2755 +# title: SIMILAR TO works wrongly +# decription: +# tracker_id: CORE-2755 +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """select + case when 'ab' SIMILAR TO 'ab|cd|efg' then 'ok' else 'bad' end as ab, + case when 'efg' SIMILAR TO 'ab|cd|efg' then 'ok' else 'bad' end as efg, + case when 'a' SIMILAR TO 'ab|cd|efg' then 'bad' else 'ok' end as a + from rdb$database; + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +AB EFG A +====== ====== ====== +ok ok ok + +""" + +@pytest.mark.version('>=3.0') +def test_core_2755_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2756.py b/tests/bugs/test_core_2756.py new file mode 100644 index 00000000..5ad3950d --- /dev/null +++ b/tests/bugs/test_core_2756.py @@ -0,0 +1,96 @@ +#coding:utf-8 +# +# id: bugs.core_2756 +# title: substring from timestamp - unexpected result +# decription: +# 26.01.2019. Note for 4.0. +# Made more careful parsing for each token of timestamp because of time-with-timezone introduction. +# Checed on: +# 4.0.0.1340: OK, 2.313s. +# 4.0.0.1410: OK, 2.360s. +# +# 02.02.2019. Note for 4.0. +# One need to EXPLICITLY add statement SET TIME ZONE <+HH:MM> at the beginning of test, otherwise +# we will get eception because current_timestamp string will have length more than expected. +# This is because DEFAULT time zone in FB 4.0 includes REGION NAME ('Moscow/Europe") instead of HH:MM shift. +# Checked on: +# 4.0.0.1421: OK, 1.493s. +# +# +# tracker_id: CORE-2756 +# min_versions: ['2.5.1'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set time zone '+00:00'; + + select + -- dts, + iif( left(dts,4) = extract(year from current_timestamp), 'Looks as expected', 'Unexpected for dts = ' || dts ) as year_as_numeric + ,iif( substring(dts from 5 for 1) = '-', 'Looks as expected', 'Unexpected for dts = ' || dts) as year_month_separator + ,iif( substring(dts from 6 for 2) = lpad(extract(month from current_timestamp),2,'0'), 'Looks as expected', 'Unexpected for dts = ' || dts ) month_as_numeric + ,iif( substring(dts from 8 for 1) = '-', 'Looks as expected', 'Unexpected for dts = ' || dts) as month_day_separator + ,iif( substring(dts from 9 for 2) = lpad(extract(day from current_timestamp),2,'0'), 'Looks as expected', 'Unexpected for dts = ' || dts ) day_as_numeric + ,iif( substring(dts from 11 for 1) = ' ', 'Looks as expected', 'Unexpected for dts = ' || dts) as date_time_space_separator + ,iif( substring(dts from 12 for 2) = lpad(extract(hour from current_timestamp),2,'0'), 'Looks as expected', 'Unexpected for dts = ' || dts ) hour_as_numeric + ,iif( substring(dts from 14 for 1) = ':', 'Looks as expected', 'Unexpected for dts = ' || dts) as time_hours_minutes_separator + ,iif( substring(dts from 15 for 2) = lpad(extract(minute from current_timestamp),2,'0'), 'Looks as expected', 'Unexpected for dts = ' || dts ) minute_as_numeric + ,iif( substring(dts from 17 for 1) = ':', 'Looks as expected', 'Unexpected for dts = ' || dts) as time_minutes_seconds_separator + ,iif( substring(dts from 18 for 2) = lpad( floor(extract(second from current_timestamp)), 2,'0'), 'Looks as expected', 'Unexpected for dts = ' || dts ) second_as_numeric + ,iif( substring(dts from 20 for 1) = '.', 'Looks as expected', 'Unexpected for dts = ' || dts) as time_seconds_millis_separator + ,iif( substring(dts from 21 for 4) = lpad( 10 * floor(extract( millisecond from current_timestamp)),4,'0'), 'Looks as expected', 'Unexpected for dts = ' || dts ) millisec_as_numeric + ,iif( substring(dts from 25 for 1) = ' ', 'Looks as expected', 'Unexpected for dts = ' || dts) as time_timezone_space_separator + ,iif( substring(dts from 26 for 1) in ('+','-'), 'Looks as expected', 'Unexpected for dts = ' || dts) GMT_shift_direction + ,iif( substring(dts from 27 for 2) similar to '[[:DIGIT:]]{2}', 'Looks as expected', 'Unexpected for dts = ' || dts) GMT_shift_hours + ,iif( substring(dts from 29 for 1) = ':', 'Looks as expected', 'Unexpected for dts = ' || dts) as GMT_shift_time_separator + ,iif( substring(dts from 30 for 2) similar to '[[:DIGIT:]]{2}', 'Looks as expected', 'Unexpected for dts = ' || dts) GMT_shift_minutes + from ( + select + substring(current_timestamp from 1 for 31) dts + from rdb$database + ) x; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + YEAR_AS_NUMERIC Looks as expected + YEAR_MONTH_SEPARATOR Looks as expected + MONTH_AS_NUMERIC Looks as expected + MONTH_DAY_SEPARATOR Looks as expected + DAY_AS_NUMERIC Looks as expected + DATE_TIME_SPACE_SEPARATOR Looks as expected + HOUR_AS_NUMERIC Looks as expected + TIME_HOURS_MINUTES_SEPARATOR Looks as expected + MINUTE_AS_NUMERIC Looks as expected + TIME_MINUTES_SECONDS_SEPARATOR Looks as expected + SECOND_AS_NUMERIC Looks as expected + TIME_SECONDS_MILLIS_SEPARATOR Looks as expected + MILLISEC_AS_NUMERIC Looks as expected + TIME_TIMEZONE_SPACE_SEPARATOR Looks as expected + GMT_SHIFT_DIRECTION Looks as expected + GMT_SHIFT_HOURS Looks as expected + GMT_SHIFT_TIME_SEPARATOR Looks as expected + GMT_SHIFT_MINUTES Looks as expected + """ + +@pytest.mark.version('>=4.0') +def test_core_2756_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2765.py b/tests/bugs/test_core_2765.py new file mode 100644 index 00000000..7b5c2166 --- /dev/null +++ b/tests/bugs/test_core_2765.py @@ -0,0 +1,233 @@ +#coding:utf-8 +# +# id: bugs.core_2765 +# title: Use of RDB$ADMIN role does not provide SYSDBA rights in GRANT/REVOKE +# decription: +# 06.08.2018: removed old code for 3.0 and 4.0, replaced it with simplified one that does *exactly* what ticket says. +# Checked on 3.0.4.33021, 4.0.0.1143. +# +# tracker_id: CORE-2765 +# min_versions: ['2.5.0'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('no (S|SELECT) privilege with grant option on table/view TEST', 'no SELECT privilege with grant option on table/view TEST')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + --set bail on; + set list on; + set wng off; + create or alter user tmp$c2765_admin password '123'; + create or alter user tmp$c2765_worker1 password '456'; + create or alter user tmp$c2765_worker2 password '789'; + + grant rdb$admin to tmp$c2765_admin; + commit; + + recreate table test(id int, x int); + commit; + insert into test(id, x) values(1, 1000); + commit; + + connect '$(DSN)' user tmp$c2765_admin password '123' role 'RDB$ADMIN'; + select current_user as who_am_i, current_role as what_is_my_role from rdb$database; + --select * from test; + commit; + + grant all on test to tmp$c2765_worker1; + commit; + + connect '$(DSN)' user tmp$c2765_worker1 password '456'; + select current_user as who_am_i, current_role as what_is_my_role from rdb$database; + + -- all these statements should pass: + set count on; + select * from test; + update test set id=-id; + delete from test; + insert into test(id,x) values(2, 2000); + set count off; + rollback; + + + connect '$(DSN)' user tmp$c2765_admin password '123'; + select current_user as who_am_i, current_role as what_is_my_role from rdb$database; + commit; + + grant all on test to tmp$c2765_worker2; -- should fail! + commit; + + connect '$(DSN)' user tmp$c2765_worker2 password '789'; + select current_user as who_am_i, current_role as what_is_my_role from rdb$database; + select * from test; -- should FAIL! + commit; + + -- cleanup: + -- ######## + connect '$(DSN)' user sysdba password 'masterkey'; + drop user tmp$c2765_admin; + drop user tmp$c2765_worker1; + drop user tmp$c2765_worker2; + commit; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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_1 = """ + 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 + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_core_2765_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [('no (S|SELECT) privilege with grant option on table/view TEST', 'no SELECT privilege with grant option on table/view TEST')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + --set bail on; + set list on; + set wng off; + create or alter user tmp$c2765_admin password '123'; + create or alter user tmp$c2765_worker1 password '456'; + create or alter user tmp$c2765_worker2 password '789'; + + grant rdb$admin to tmp$c2765_admin; + commit; + + recreate table test(id int, x int); + commit; + insert into test(id, x) values(1, 1000); + commit; + + connect '$(DSN)' user tmp$c2765_admin password '123' role 'RDB$ADMIN'; + select current_user as who_am_i, current_role as what_is_my_role from rdb$database; + --select * from test; + commit; + + grant all on test to tmp$c2765_worker1; + commit; + + connect '$(DSN)' user tmp$c2765_worker1 password '456'; + select current_user as who_am_i, current_role as what_is_my_role from rdb$database; + + -- all these statements should pass: + set count on; + select * from test; + update test set id=-id; + delete from test; + insert into test(id,x) values(2, 2000); + set count off; + rollback; + + + connect '$(DSN)' user tmp$c2765_admin password '123'; + select current_user as who_am_i, current_role as what_is_my_role from rdb$database; + commit; + + grant all on test to tmp$c2765_worker2; -- should fail! + commit; + + connect '$(DSN)' user tmp$c2765_worker2 password '789'; + select current_user as who_am_i, current_role as what_is_my_role from rdb$database; + select * from test; -- should FAIL! + commit; + + -- cleanup: + -- ######## + connect '$(DSN)' user sysdba password 'masterkey'; + drop user tmp$c2765_admin; + drop user tmp$c2765_worker1; + drop user tmp$c2765_worker2; + commit; + + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +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_core_2765_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_expected_stderr == act_2.clean_stderr + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/bugs/test_core_2766.py b/tests/bugs/test_core_2766.py new file mode 100644 index 00000000..5808d9e8 --- /dev/null +++ b/tests/bugs/test_core_2766.py @@ -0,0 +1,59 @@ +#coding:utf-8 +# +# id: bugs.core_2766 +# title: Error "page 0 is of wrong type (expected 6, found 1)" is thrown while accessing a non-corrupted table +# decription: +# tracker_id: CORE-2766 +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t_master (id int not null, name varchar(64)); +alter table t_master add constraint PK_master primary key (id); + +create table t_detail (id_master int not null, name varchar(64)); +alter table t_detail add constraint FK_detail foreign key (id_master) references t_master (id); + +commit; + +insert into t_master values (1, '1'); +insert into t_detail values (1, 'a'); +commit; +""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """insert into t_master values (3, '2'); +delete from t_master where id = 3; +commit; + +drop table t_detail; +commit; + +delete from t_master; +select count(*) from t_master; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + COUNT +===================== + 0 + +""" + +@pytest.mark.version('>=3.0') +def test_core_2766_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2768.py b/tests/bugs/test_core_2768.py new file mode 100644 index 00000000..ee1fa70c --- /dev/null +++ b/tests/bugs/test_core_2768.py @@ -0,0 +1,111 @@ +#coding:utf-8 +# +# id: bugs.core_2768 +# title: ALTERING OR DROPPING PROCEDURE which has type of domain parameter leads to attempt to delete that domain +# decription: +# Checked on: +# 4.0.0.1763 SS: 1.484s. +# 3.0.6.33240 SS: 0.674s. +# 2.5.9.27149 SC: 0.328s. +# 2.5.0.26074 CS: 0.706s. +# +# tracker_id: CORE-2768 +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate view v_fields as + select rf.rdb$field_name f_name, rf.rdb$field_length f_length, rf.rdb$field_type f_type + from rdb$database r + left join rdb$fields rf on rf.rdb$field_name = upper('dm_test') + ; + + recreate view v_dependencies as + select rd.rdb$dependent_name as dep_obj_name, rd.rdb$depended_on_name as dep_on_what + from rdb$database r + left join rdb$dependencies rd on rd.rdb$dependent_name = upper('sp_test') + ; + + create or alter procedure sp_test as begin end + ; + set term ^; + execute block as + begin + begin + execute statement 'drop domain dm_test'; + when any do begin end + end + end + ^ + set term ;^ + commit; + + create domain dm_test int; + commit; + create or alter procedure sp_test( a_01 type of dm_test ) as begin end; + commit; + + set count on; + set list on; + + select * from v_fields ; + select * from v_dependencies ; + commit; + + alter procedure sp_test as begin end; + commit; -- here was error in 2.5 Beta 2, 2.5 RC1 + + select * from v_fields ; + select * from v_dependencies ; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F_NAME DM_TEST + F_LENGTH 4 + F_TYPE 8 + + + Records affected: 1 + + DEP_OBJ_NAME SP_TEST + DEP_ON_WHAT DM_TEST + + + Records affected: 1 + + F_NAME DM_TEST + F_LENGTH 4 + F_TYPE 8 + + + Records affected: 1 + + DEP_OBJ_NAME + DEP_ON_WHAT + + + Records affected: 1 + """ + +@pytest.mark.version('>=2.5.0') +def test_core_2768_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2780.py b/tests/bugs/test_core_2780.py new file mode 100644 index 00000000..bac78a30 --- /dev/null +++ b/tests/bugs/test_core_2780.py @@ -0,0 +1,56 @@ +#coding:utf-8 +# +# id: bugs.core_2780 +# title: Include client library version and protocol version in mon$attachments +# decription: +# tracker_id: CORE-2780 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + -- See letter from dimitr, 10-apr-2015 09:19 + select + -- All platform protovol name: starts with 'TCP' + iif( cast(mon$remote_protocol as varchar(10) character set utf8) collate unicode_ci starting with 'tcp', 1, 0) is_protocol_valid + -- Prefixes for client version: + -- Windows: WI + -- Linux: LI + -- MacOS: UI (intel) or UP (powerpc) + -- Solaris: SI (intel) or SO (spark) + -- HP-UX: HP + -- '-T' = Testing; '-V' = RC or release + -- 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 + from mon$attachments + where mon$attachment_id = current_connection; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + IS_PROTOCOL_VALID 1 + IS_CLIENT_VERSION_VALID 1 + """ + +@pytest.mark.version('>=3.0') +def test_core_2780_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2783.py b/tests/bugs/test_core_2783.py new file mode 100644 index 00000000..d8fabf58 --- /dev/null +++ b/tests/bugs/test_core_2783.py @@ -0,0 +1,75 @@ +#coding:utf-8 +# +# id: bugs.core_2783 +# title: AV using recursive query as subquery in SELECT list and ORDER'ing by them +# decription: +# tracker_id: CORE-2783 +# min_versions: [] +# versions: 2.1.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT RDB$RELATION_ID, + (WITH RECURSIVE + NUM (ID) AS + ( + SELECT 1 FROM RDB$DATABASE + + UNION ALL + + SELECT ID + 1 + FROM NUM + WHERE ID < 10 + ) + SELECT MAX(ID) FROM NUM + ) AS NNN + FROM RDB$DATABASE +ORDER BY NNN; +WITH RECURSIVE + NUM (ID) AS + ( + SELECT 1 FROM RDB$DATABASE + + UNION ALL + + SELECT ID + 1 + FROM NUM + WHERE ID < 10 + ) +SELECT RDB$RELATION_ID, (SELECT MAX(ID) FROM NUM) AS NNN + FROM RDB$DATABASE +ORDER BY NNN; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Database: localhost:C: btest2 mpugs.core_2783.fdb, User: SYSDBA +SQL> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> +RDB$RELATION_ID NNN +=============== ============ + 128 10 + +SQL> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> +RDB$RELATION_ID NNN +=============== ============ + 128 10 + +SQL>""" + +@pytest.mark.version('>=2.1.4') +def test_core_2783_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2787.py b/tests/bugs/test_core_2787.py new file mode 100644 index 00000000..26718a6f --- /dev/null +++ b/tests/bugs/test_core_2787.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_2787 +# title: Make rdb$system_flag not null +# decription: +# tracker_id: CORE-2787 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set count on; + set list on; + + select rf.rdb$relation_name as rel_name, rf.rdb$null_flag as nullable + from rdb$relation_fields rf + where + upper(rf.rdb$field_name) = upper('rdb$system_flag') + and rdb$null_flag = 1; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ + +@pytest.mark.version('>=3.0') +def test_core_2787_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2788.py b/tests/bugs/test_core_2788.py new file mode 100644 index 00000000..991ed149 --- /dev/null +++ b/tests/bugs/test_core_2788.py @@ -0,0 +1,165 @@ +#coding:utf-8 +# +# id: bugs.core_2788 +# title: isql extracts the array dimensions after the character set name +# decription: +# +# tracker_id: CORE-2788 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('- line .*', ''), ('At line .*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# from subprocess import Popen +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# sql_ddl=''' create domain dm_test as char(1) character set iso8859_1[1:2]; +# create domain dm_test as char(1)[1:2] character set iso8859_1; +# commit; +# show domain dm_test; +# ''' +# +# +# f_init_sql = open( os.path.join(context['temp_directory'],'tmp_init_2788.sql'), 'w') +# f_init_sql.write(sql_ddl) +# flush_and_close( f_init_sql ) +# +# f_init_log = open( os.path.join(context['temp_directory'],'tmp_init_2788.log'), 'w') +# f_init_err = open( os.path.join(context['temp_directory'],'tmp_init_2788.err'), 'w') +# subprocess.call( [context['isql_path'], dsn, "-i", f_init_sql.name], +# stdout = f_init_log, +# stderr = f_init_err +# ) +# # This file should be empty: +# flush_and_close( f_init_log ) +# +# # This file should contain error messages about 1st 'CREATE DOMAIN' statement that has syntax trouble: +# flush_and_close( f_init_err ) +# +# # This file should contain error messages about 1st 'CREATE DOMAIN' statement that has syntax trouble: +# with open( f_init_err.name,'r') as f: +# print(f.read()) +# +# +# f_xmeta_log = open( os.path.join(context['temp_directory'],'tmp_xmeta_2788.log'), 'w') +# f_xmeta_err = open( os.path.join(context['temp_directory'],'tmp_xmeta_2788.err'), 'w') +# subprocess.call( [context['isql_path'], dsn, "-x"], stdout = f_xmeta_log, stderr = f_xmeta_err) +# +# # This file should contain metadata - domain definition: +# flush_and_close( f_xmeta_log ) +# +# # This file should be empty: +# flush_and_close( f_xmeta_err ) +# +# att1 = fdb.connect(dsn=dsn.encode()) +# cur1=att1.cursor() +# cur1.execute("drop domain dm_test") +# att1.commit() +# +# att1.close() +# +# # This shoudl issue "There is no domain DM_TEST in this database": +# runProgram('isql',[dsn, '-q'],'show domain dm_test;') +# +# f_apply_log = open( os.path.join(context['temp_directory'],'tmp_apply_2788.log'), 'w') +# f_apply_err = open( os.path.join(context['temp_directory'],'tmp_apply_2788.err'), 'w') +# subprocess.call( [context['isql_path'], dsn, "-i", f_xmeta_log.name], +# stdout = f_apply_log, +# stderr = f_apply_err +# ) +# # Both of these files should be empty: +# flush_and_close( f_apply_log ) +# flush_and_close( f_apply_err ) +# +# # This shoudl issue DDL of just created domain: +# runProgram('isql',[dsn, '-q'],'show domain dm_test;') +# +# # No output should be here: +# with open( f_xmeta_err.name,'r') as f: +# print(f.read()) +# +# # No output should be here: +# with open( f_apply_log.name,'r') as f: +# print(f.read()) +# +# +# # No output should be here: +# with open( f_apply_err.name,'r') as f: +# print(f.read()) +# +# +# ################################################ +# # Cleanup +# time.sleep(1) +# cleanup( [i.name for i in (f_init_sql,f_init_log,f_init_err,f_xmeta_log,f_xmeta_err,f_apply_log,f_apply_err) ] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Token unknown - line 1, column 57 + -[ + DM_TEST ARRAY OF [2] + CHAR(1) CHARACTER SET ISO8859_1 Nullable + """ +expected_stderr_1 = """ + There is no domain DM_TEST in this database + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_2788_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2796.py b/tests/bugs/test_core_2796.py new file mode 100644 index 00000000..a4df280b --- /dev/null +++ b/tests/bugs/test_core_2796.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: bugs.core_2796 +# title: DB_KEY is always zero for external tables +# decription: +# +# tracker_id: CORE-2796 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table ext_test external file '$(DATABASE_LOCATION)c2796.dat' (col char(24), lf char(1)); + set list on; + set term ^; + execute block returns (ms_diff bigint) + as + declare dbkey char(8) character set octets; + declare v_dts1 timestamp; + begin + v_dts1=cast('now' as timestamp); + insert into ext_test values( :v_dts1-rand()*100, ascii_char(10)); + insert into ext_test values( :v_dts1-rand()*100, ascii_char(10)); + insert into ext_test values( :v_dts1-rand()*100, ascii_char(10)); + insert into ext_test values( :v_dts1, ascii_char(10)); + insert into ext_test values( :v_dts1-rand()*100, ascii_char(10)); + + select rdb$db_key from ext_test order by col desc rows 1 into :dbkey; + + for + select datediff(millisecond from cast(col as timestamp) to :v_dts1) + from ext_test + where rdb$db_key = :dbkey + into ms_diff + do + suspend; + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MS_DIFF 0 + """ + +@pytest.mark.version('>=3.0') +def test_core_2796_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2797.py b/tests/bugs/test_core_2797.py new file mode 100644 index 00000000..d9b1ad2d --- /dev/null +++ b/tests/bugs/test_core_2797.py @@ -0,0 +1,112 @@ +#coding:utf-8 +# +# id: bugs.core_2797 +# title: Problem with default value of SP parameter +# decription: +# tracker_id: CORE-2797 +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('==.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter procedure sp_test as begin end; + commit; + + set term ^; + execute block as + begin + begin execute statement 'drop domain dm_dts_now'; when any do begin end end + begin execute statement 'drop domain dm_dts_cts'; when any do begin end end + begin execute statement 'drop domain dm_int_con'; when any do begin end end + begin execute statement 'drop domain dm_vc_user'; when any do begin end end + end + ^ + set term ;^ + commit; + + create domain dm_dts_now timestamp default 'now' not null ; + create domain dm_dts_cts timestamp default current_timestamp not null ; + create domain dm_int_con int default current_connection; + create domain dm_vc_user int default current_user; + commit; + + set term ^; + create or alter procedure sp_test ( + in01 timestamp not null = 'now' + ,in02 dm_dts_cts = current_timestamp + ,in03 type of dm_dts_now = current_date + ,in04 timestamp not null = 'now' + ,in05 dm_dts_cts = current_timestamp + ,in06 type of dm_dts_now = current_date + ,in07 int not null = current_connection + ,in08 dm_int_con = current_connection + ,in09 dm_int_con = current_connection + ,in10 varchar(31) = current_user + ,in11 dm_vc_user = current_user + ,in12 dm_vc_user = current_user + ) as + declare x integer; + begin + x = 0; + end + ^ + set term ;^ + commit; + + + --set list on; + + set width ppar_name 15; + set width ppar_fld_src 35; + set width ppar_def_src 35; + set width rdbf_fld_name 15; + set width rdbf_def_src 35; + + select + pp.rdb$parameter_name ppar_name + ,replace(replace(cast( pp.rdb$field_source as varchar(35)), ascii_char(13), ''), ascii_char(10), '') ppar_fld_src + ,replace(replace(cast( pp.rdb$default_source as varchar(35)), ascii_char(13), ''), ascii_char(10), '') ppar_def_src + ,f.rdb$field_name rdbf_fld_name + ,replace(replace(cast(f.rdb$default_source as varchar(35)), ascii_char(13), ''), ascii_char(10), '') rdbf_def_src + from rdb$procedure_parameters pp + left join rdb$fields f on pp.rdb$field_source = f.rdb$field_name + where upper(trim(pp.rdb$procedure_name)) = upper('sp_test'); + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PPAR_NAME PPAR_FLD_SRC PPAR_DEF_SRC RDBF_FLD_NAME RDBF_DEF_SRC + IN01 RDB$1 = 'now' RDB$1 + IN02 DM_DTS_CTS = current_timestamp DM_DTS_CTS default current_timestamp + IN03 DM_DTS_NOW = current_date DM_DTS_NOW default 'now' + IN04 RDB$2 = 'now' RDB$2 + IN05 DM_DTS_CTS = current_timestamp DM_DTS_CTS default current_timestamp + IN06 DM_DTS_NOW = current_date DM_DTS_NOW default 'now' + IN07 RDB$3 = current_connection RDB$3 + IN08 DM_INT_CON = current_connection DM_INT_CON default current_connection + IN09 DM_INT_CON = current_connection DM_INT_CON default current_connection + IN10 RDB$4 = current_user RDB$4 + IN11 DM_VC_USER = current_user DM_VC_USER default current_user + IN12 DM_VC_USER = current_user DM_VC_USER default current_user + """ + +@pytest.mark.version('>=3.0') +def test_core_2797_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2798.py b/tests/bugs/test_core_2798.py new file mode 100644 index 00000000..e257826f --- /dev/null +++ b/tests/bugs/test_core_2798.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: bugs.core_2798 +# title: Incomplete plan output (lack of view names) when selecting from views containing procedures inside +# decription: +# tracker_id: CORE-2798 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table t1 (col int); + commit; + + set term ^; + create procedure p1 returns (res int) as begin suspend; end^ + set term ;^ + commit; + + create view v as select 1 as num from t1, t1 as t2, p1, p1 as p2; + commit; + set plan on; + select * from v; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN JOIN (V P1 NATURAL, V P2 NATURAL, V T1 NATURAL, V T2 NATURAL) + """ + +@pytest.mark.version('>=2.5') +def test_core_2798_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2799.py b/tests/bugs/test_core_2799.py new file mode 100644 index 00000000..e7b039cd --- /dev/null +++ b/tests/bugs/test_core_2799.py @@ -0,0 +1,95 @@ +#coding:utf-8 +# +# id: bugs.core_2799 +# title: Changing sort directon in delete statement cause deletion of all records in table +# decription: +# Checked on: +# WI-T3.0.0.31374 Firebird 3.0 Beta 1 +# WI-V3.0.0.32300 Firebird 3.0 Release Candidate 2 +# +# tracker_id: CORE-2799 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test + ( + id integer not null primary key, + kod varchar(5) + ); + commit; + + insert into test(id, kod) values(1, 'abc'); + insert into test(id, kod) values(2, 'abc'); + commit; + + -- now we have 2 rows in table + -- and delete in ___ascending___ oreder + + set count on; + --set echo on; + + delete from test t + where exists(select * from test t2 where t2.id<>t.id and t2.kod=t.kod) + order by t.id asc; + -- 2.5: one row affected + -- 3.0: TWO rows must be affected. + commit; + + + select * from test; + -- 2.5: one row selected id=2 kod='abc' + -- 3.0: NO rows should be selected here. + + set count off; + delete from test; + commit; + insert into test(id, kod) values(1, 'abc'); + insert into test(id, kod) values(2, 'abc'); + commit; + set count on; + + -- now we have 2 rows in table + -- and delete in ___descending___ oreder + + delete from test t + where exists(select * from test t2 where t2.id<>t.id and t2.kod=t.kod) + order by t.id desc; + -- 2.5: two rows affected. + -- 3.0: TWO rows must be affected. + commit; + + select * from test; + -- 2.5: empty result set. + -- 3.0: NO rows should be selected here. + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 2 + Records affected: 0 + Records affected: 2 + Records affected: 0 + """ + +@pytest.mark.version('>=3.0') +def test_core_2799_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2804.py b/tests/bugs/test_core_2804.py new file mode 100644 index 00000000..dfa94453 --- /dev/null +++ b/tests/bugs/test_core_2804.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_2804 +# title: Problems with COMMENT ON and strings using introducer (charset) +# decription: +# tracker_id: CORE-2804 +# min_versions: ['2.5.4'] +# versions: 2.5.4 +# qmid: bugs.core_2804 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.4 +# resources: None + +substitutions_1 = [('DESCR_BLOB_ID.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core2804-ods11.fbk', init=init_script_1) + +test_script_1 = """ + -- Database was prepared with following statements: + -- recreate table test1(id int); + -- recreate table test2(id int); + -- commit; + -- comment on table test1 is _win1251 'win1251: '; + -- comment on table test2 is _unicode_fss 'unicode_fss: '; + -- commit; + + set blob all; + set list on; + select r.rdb$description as descr_blob_id + from rdb$relations r where r.rdb$relation_name in ( upper('test1'), upper('test2') ) + order by r.rdb$relation_name; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DESCR_BLOB_ID 0:3 + win1251: Протокол собрания об уплотнении квартир дома + + DESCR_BLOB_ID 0:6 + unicode_fss: Протокол собрания о помощи детям Германии + """ + +@pytest.mark.version('>=2.5.4') +def test_core_2804_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2806.py b/tests/bugs/test_core_2806.py new file mode 100644 index 00000000..3d9cf1ce --- /dev/null +++ b/tests/bugs/test_core_2806.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: bugs.core_2806 +# title: Views based on procedures can't be created if the proc's output fields participate in an expression +# decription: +# tracker_id: CORE-2806 +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """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^ +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """DOSRC BIGINT Expression +View Source: +==== ====== + select rc * 2 from p +""" + +@pytest.mark.version('>=2.5.0') +def test_core_2806_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2811.py b/tests/bugs/test_core_2811.py new file mode 100644 index 00000000..f845a755 --- /dev/null +++ b/tests/bugs/test_core_2811.py @@ -0,0 +1,78 @@ +#coding:utf-8 +# +# id: bugs.core_2811 +# title: Unsuccessful execution' error when updating a record +# decription: CREATE OR ALTER TRIGGER NEW_TRIGGER FOR NEW_TABLE +# ACTIVE AFTER UPDATE POSITION 20 +# AS +# -- Typically this variable would be used in the trigger. To make it simple, I've +# -- removed all code possible to still get the error. +# declare variable NewHours numeric(9,2) = 0; +# BEGIN +# -- Remove the coalesce and the update will work. +# -- Remove the multiplication and the update will work. +# -- Remove this unneeded variable and the update will work. +# NewHours = coalesce(new.new_field * (0), 0); +# +# -- Remove this exit command and the update will work. I know it's not needed, +# -- however in the scenario I ran into this there was much more code after the +# -- exit, and the exit was inside an IF clause. This is just the simplest way of reproducing it. +# exit; +# end +# ^ +# +# -- Now update the record to see the error: +# update new_table set new_field = 6; +# tracker_id: CORE-2811 +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE NEW_TABLE ( + NEW_FIELD NUMERIC(9,2) +); + +INSERT INTO NEW_TABLE (NEW_FIELD) VALUES (4); + +SET TERM ^ ; + +CREATE OR ALTER TRIGGER NEW_TRIGGER FOR NEW_TABLE +ACTIVE AFTER UPDATE POSITION 20 +AS +declare variable NewHours numeric(9,2) = 0; +BEGIN +NewHours = coalesce(new.new_field * (0), 0); +exit; +end +^ +""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """update new_table set new_field = 6; +select new_field from new_table; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + NEW_FIELD +============ + 6.00 + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_2811_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2812.py b/tests/bugs/test_core_2812.py new file mode 100644 index 00000000..e6e9eaa0 --- /dev/null +++ b/tests/bugs/test_core_2812.py @@ -0,0 +1,176 @@ +#coding:utf-8 +# +# id: bugs.core_2812 +# title: Prohibit any improper mixture of explicit and implicit joins +# decription: +# tracker_id: CORE-2812 +# min_versions: ['2.5.3'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', ''), ('-At line.*', '')] + +init_script_1 = """ + recreate table t_left(id int); + insert into t_left values(111); + insert into t_left values(999); + commit; + + recreate table t_right(id int, val int); + insert into t_right values(111,0); + insert into t_right values(999,123456789); + commit; + + recreate table t_middle(id int); + insert into t_middle values(1); + commit; + + -- one more sample (after discussion with Dmitry by e-mail, 02-apr-2015 19:34) + recreate table t1(id int); + commit; + insert into t1 values( 1 ); + commit; + + recreate table test(x int); + insert into test values(1); + commit; + + + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + select + 'case-1' as msg + ,L.id proc_a_id + ,m.id mid_id + ,R.id b_id, R.val + from t_left L + + , -- ::: nb ::: this is >>> COMMA <<< instead of `cross join` + + t_middle m + left join t_right R on L.id=R.id + ; + + select + 'case-2' as msg + ,l.id a_id, m.id mid_id, r.id b_id, r.val + from t_left l + cross join t_middle m + left join t_right r on l.id=r.id; + + -- Added 02-apr-2015: + select 'case-3' msg, a.id + from t1 a + , t1 b + join t1 c on a.id=c.id + where a.id=b.id; -- this FAILS on 3.0 + + select 'case-4' msg, a.id + from t1 b + , t1 a + join t1 c on a.id=c.id + where a.id=b.id; -- this WORKS on 3.0 + + --------------------------------------------------------- + + -- Added 29-jun-2017, after reading CORE-5573: + + -- This should PASS: + select 1 as z1 + from + test a + join + test s + inner join + ( + test d + join test e on e.x = d.x + join ( test f join test g on f.x = g.x ) on e.x = g.x + --- and f.x=s.x + + ) + on 1=1 + on g.x=d.x + ; + + -- This should FAIL on 3.0+ (but is passes on 2.5): + select 2 as z2 + from + test a + join + test s + inner join + ( + test d + join test e on e.x = d.x + join ( test f join test g on f.x = g.x ) on e.x = g.x + and f.x=s.x -- <<< !! <<< + + ) + on 1=1 + on g.x=d.x + ; + + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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 + + MSG case-4 + ID 1 + + Z1 1 + + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42S22 + Dynamic SQL Error + -SQL error code = -206 + -Column unknown + -L.ID + + Statement failed, SQLSTATE = 42S22 + Dynamic SQL Error + -SQL error code = -206 + -Column unknown + -A.ID + + Statement failed, SQLSTATE = 42S22 + Dynamic SQL Error + -SQL error code + -Column unknown + -S.X + """ + +@pytest.mark.version('>=3.0') +def test_core_2812_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2817.py b/tests/bugs/test_core_2817.py new file mode 100644 index 00000000..6c1cee2f --- /dev/null +++ b/tests/bugs/test_core_2817.py @@ -0,0 +1,96 @@ +#coding:utf-8 +# +# id: bugs.core_2817 +# title: If stored procedure or trigger contains query with PLAN ORDER it could fail after disconnect of attachment where procedure rigger executed first time +# decription: +# +# tracker_id: CORE-2817 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create sequence g; + create or alter procedure sp_test returns(cnt int) as begin end; + recreate table test( + x int, + s varchar(1000) + ); + commit; + + insert into test(x, s) + select gen_id(g,1), rpad('', 1000, uuid_to_char(gen_uuid())) + from rdb$types, rdb$types + rows 1000; + commit; + + create index test_x on test(x); + create index test_s on test(s); + commit; + + set term ^; + create or alter procedure sp_test(a_odd smallint) as + declare c_ord cursor for ( + select s + from test + where mod(x, 2) = :a_odd + order by x + ); + declare v_s type of column test.s; + begin + open c_ord; + while (1=1) do + begin + fetch c_ord into v_s; + if (row_count = 0) then leave; + update test set s = uuid_to_char(gen_uuid()) where current of c_ord; + end + close c_ord; + end + ^ -- sp_test + set term ;^ + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import fdb +# +# db_conn.close() +# att1 = kdb.connect(dsn=dsn.encode(),user='SYSDBA',password='masterkey') +# att2 = kdb.connect(dsn=dsn.encode(),user='SYSDBA',password='masterkey') +# +# cur1 = att1.cursor() +# cur2 = att2.cursor() +# +# sp_run='execute procedure sp_test' +# +# cur1.execute('execute procedure sp_test(0)') +# cur2.execute('execute procedure sp_test(1)') +# +# att1.commit() +# att1.close() +# +# cur2.execute('execute procedure sp_test(1)') +# att2.close() +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_2817_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2822.py b/tests/bugs/test_core_2822.py new file mode 100644 index 00000000..aa4ec386 --- /dev/null +++ b/tests/bugs/test_core_2822.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: bugs.core_2822 +# title: Error "no current row for fetch operation" when subquery includes a non-trivial derived table +# decription: +# tracker_id: CORE-2822 +# min_versions: [] +# versions: 2.1.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select * +from rdb$relations r natural join rdb$relation_fields rf +where 1 = ( + select 1 + from ( + select 1 from rdb$database + union + select 1 + from rdb$fields f + where f.rdb$field_name = rf.rdb$field_source + ) as f (id) ) ; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1.4') +def test_core_2822_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_2826.py b/tests/bugs/test_core_2826.py new file mode 100644 index 00000000..086c9317 --- /dev/null +++ b/tests/bugs/test_core_2826.py @@ -0,0 +1,79 @@ +#coding:utf-8 +# +# id: bugs.core_2826 +# title: Join condition fails for UTF-8 databases. +# decription: +# tracker_id: CORE-2826 +# min_versions: ['2.1.4'] +# versions: 2.1.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set autoddl off; + commit; + + create collation unicode_nopad for utf8 from unicode no pad; + -- !!! >>> COMMENTED THIS ACCORDING TO NOTES IN THE TICKET: >>> commit; <<< + -- Table is created in the same transaction as collation: + create table tst1_nopad ( + k1 varchar(3) character set utf8 collate unicode_nopad, + k2 int, + k3 char(1) character set utf8 collate unicode_nopad, + primary key (k1, k2, k3) using index txt1_nopad_pk + ); + commit; + + insert into tst1_nopad values ('ap', 123, ' '); + insert into tst1_nopad values ('hel', 666, 'v'); + commit; + + set list on; + set plan on; + select t1.* + from tst1_nopad t1 + where t1.k1 = 'ap' + and t1.k2 = 123 + and t1.k3 = ' ' + plan (t1 natural); + + select t1.* + from tst1_nopad t1 + where t1.k1 = 'ap' + and t1.k2 = 123 + and t1.k3 = ' '; + + -- 'show table' was removed, see CORE-4782 ("Command `SHOW TABLE` fails..." - reproduced on Windows builds 2.5 and 3.0 only) + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (T1 NATURAL) + K1 ap + K2 123 + K3 + + PLAN (T1 INDEX (TXT1_NOPAD_PK)) + K1 ap + K2 123 + K3 + """ + +@pytest.mark.version('>=2.1.4') +def test_core_2826_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2831.py b/tests/bugs/test_core_2831.py new file mode 100644 index 00000000..e03fbe8c --- /dev/null +++ b/tests/bugs/test_core_2831.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: bugs.core_2831 +# title: isql shouldn't display db and user name when extracting a script +# decription: +# tracker_id: CORE-2831 +# min_versions: ['2.0.6', '2.1.4', '2.5'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!Database:|User:).)*$', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# # +# runProgram('isql',['-x',dsn,'-user',user_name,'-pass',user_password]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_2831_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2833.py b/tests/bugs/test_core_2833.py new file mode 100644 index 00000000..8925b967 --- /dev/null +++ b/tests/bugs/test_core_2833.py @@ -0,0 +1,151 @@ +#coding:utf-8 +# +# id: bugs.core_2833 +# title: Changing data that affects an expression index that contains references to null date fields fails +# decription: +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: bugs.core_2833 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table policen_order ( + id integer not null, + vstatus integer, + ablauf date, + vstorno integer, + storno date + ); + alter table policen_order add constraint pk_new_table primary key (id); + + set term ^; + execute block as + begin + execute statement 'drop sequence gen_policen_order_id'; + when any do begin end + end + ^ + set term ;^ + commit; + create generator gen_policen_order_id; + commit; + + set term ^; + create or alter trigger policen_order_bi for policen_order + active before insert position 0 as + begin + if (new.id is null) then + new.id = gen_id(gen_policen_order_id,1); + end + ^ + set term ;^ + commit; + + -- insert some data with null dates + insert into policen_order (id, vstatus, ablauf, vstorno, storno) + values (2, 1, null, null, null); + insert into policen_order (id, vstatus, ablauf, vstorno, storno) + values (3, 2, null, null, null); + insert into policen_order (id, vstatus, ablauf, vstorno, storno) + values (4, 3, null, null, null); + commit; + + -- now let's create an obscure index + + create index idx_policen_order_bit_vstatus on policen_order + computed by + ( + case + when policen_order.vstatus=1 then 64 -- anbahnung + when policen_order.vstatus=7 then 32 -- da + when policen_order.vstatus=8 then 16 -- angebot + when policen_order.vstatus=0 then 8 -- vertrag + when policen_order.vstatus=3 then 8 -- vertrag + when policen_order.vstatus=4 then 8 -- vertrag + when policen_order.vstatus=5 then 8 -- vertrag + when policen_order.vstatus=6 then 8 -- vertrag + when policen_order.vstatus=2 then 4 -- fremdvertrag + else 0 + end + + + case + when + coalesce(policen_order.ablauf, current_date+1)<=current_date + or + policen_order.vstorno=1 + and coalesce(policen_order.storno, current_date+1) <= current_date + then 2 + else 0 + end + ); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + update policen_order set vstatus = 8 where id = 2; + commit; + select * from policen_order; + update policen_order set vstatus = 2 where id = 2; + commit; + select * from policen_order; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 2 + VSTATUS 8 + ABLAUF + VSTORNO + STORNO + + ID 3 + VSTATUS 2 + ABLAUF + VSTORNO + STORNO + + ID 4 + VSTATUS 3 + ABLAUF + VSTORNO + STORNO + + + + ID 2 + VSTATUS 2 + ABLAUF + VSTORNO + STORNO + + ID 3 + VSTATUS 2 + ABLAUF + VSTORNO + STORNO + + ID 4 + VSTATUS 3 + ABLAUF + VSTORNO + STORNO + """ + +@pytest.mark.version('>=2.5') +def test_core_2833_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2835.py b/tests/bugs/test_core_2835.py new file mode 100644 index 00000000..e996629f --- /dev/null +++ b/tests/bugs/test_core_2835.py @@ -0,0 +1,95 @@ +#coding:utf-8 +# +# id: bugs.core_2835 +# title: Natural is used to select instead of primary key index +# decription: +# tracker_id: CORE-2835 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table net_net_device( + id integer not null, + constraint pk_net_net_device primary key (id) + ); + + create table net_dev_interconnection( + prim_devid integer not null, + secondary_devid integer not null, + interconnect_level integer, + constraint pk_net_dev_interconnection primary key (prim_devid, secondary_devid) + ); + + alter table net_dev_interconnection add constraint fk_net_dev_interconnection_001 + foreign key (prim_devid) references net_net_device(id); + + alter table net_dev_interconnection add constraint fk_net_dev_interconnection_002 + foreign key (secondary_devid) references net_net_device(id); + + commit; + + set term ^; + execute block + as + declare cnt1 int = 8636; + declare cnt2 int = 4029; + begin + delete from NET_DEV_INTERCONNECTION; + delete from NET_NET_DEVICE; + + while (cnt1 > 0) do + begin + insert into NET_NET_DEVICE values (:cnt1); + cnt1 = cnt1 - 1; + end + + while (cnt2 > 0) do + begin + insert into NET_DEV_INTERCONNECTION values (1, :cnt2, null); + cnt2 = cnt2 - 1; + end + + execute statement 'set statistics index PK_NET_NET_DEVICE'; + execute statement 'set statistics index PK_NET_DEV_INTERCONNECTION'; + execute statement 'set statistics index FK_NET_DEV_INTERCONNECTION_001'; + execute statement 'set statistics index FK_NET_DEV_INTERCONNECTION_002'; + end + ^ + set term ;^ + commit; + + set planonly; + select distinct t0_dep.id + from net_net_device t1_nd, + net_net_device t0_dep, + net_dev_interconnection t3_nd_dependantdevices_relation + where ((t1_nd.id = ? )) + and t1_nd.id=t3_nd_dependantdevices_relation.prim_devid + and t0_dep.id=t3_nd_dependantdevices_relation.secondary_devid; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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))) + """ + +@pytest.mark.version('>=2.5') +def test_core_2835_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2861.py b/tests/bugs/test_core_2861.py new file mode 100644 index 00000000..da8b6881 --- /dev/null +++ b/tests/bugs/test_core_2861.py @@ -0,0 +1,339 @@ +#coding:utf-8 +# +# id: bugs.core_2861 +# title: Cannot remove user with dot in login +# decription: +# Since 10.01.2016 this test (for 3.0) is based on totally new algorithm with checking ability of +# normal work with randomly generated logins. These logins consists only of punctuation chars and +# for sure will have at least one dot. +# The reason of this replacement was failed results on Classic 3.0 when 'gsec' utility is invoked. +# Code for 2.5 was not changed and is preserved (though it was missed for 2.5 before, but it works OK). +# +# See http://web.firebirdsql.org/download/prerelease/results/archive/ for builds: 3.0.0.32266 3.0.0.32268 +# +# Correctness of current code was verified by batch scenario, totally about ~1500 iterations was done. +# Several samples of logins that were be checked: +# ,(/;.>_:%$^`.&<|#?=[~\\*}-{@) +# >=[{+%\\.&|~$`(;#._,])}?*@:^! +# }^\\*@.)#>|/;&!=~`]<[,?.-:(%. +# +# NOTE: currently we EXCLUDE single and double quotes from random login because of CORE-5072. +# +# This login is handled then by both FBSVCMGR and ISQL utilities: +# 1) run FBSVCMGR and: +# 1.1) add user +# 1.2) modifying some of its attributes (password, firstname etc). +# NOTE! We do *not* run 'fbsvcmgr action_delete_user' because it does not work (at least on build 32268) +# ###################################################################################################### +# COMMAND: fbsvcmgr localhost/3333:service_mgr user sysdba password masterkey action_delete_user dbname C:\\MIX +# irebird +# b30\\security3.fdb sec_username john +# STDERR: unexpected item in service parameter block, expected isc_spb_sec_username +# (sent letter to Alex, 09-jan-2016 22:34; after getting reply about this issue test can be further changed). +# 2) run ISQL and: +# 2.1) drop this user that could not be dropped in FBSVCMGR - see previous section. +# 2.2) create this login again; +# 2.3) modifying some of this login attributes; +# 2.4) drop it finally. +# +# See also: +# CORE-1810 ("Usernames with '.' character"; login 'JOHN.SMITH' is used there). +# CORE-3000 (use of unquoted reserved word ADMIN as user name in SQL command). +# +# tracker_id: CORE-2861 +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('[ ]+', ' '), ('[\t]*', ' '), ('.* Name: .*', ' Name: ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# from subprocess import Popen +# import string +# from random import sample, choice +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_name=db_conn.database_name +# db_conn.close() +# +# svc = services.connect(host='localhost') +# security_db_name = svc.get_security_database_path() # path+name of security DB +# svc.close() +# +# # Useful links related to this .fbt: +# # https://docs.python.org/2/library/string.html +# # http://stackoverflow.com/questions/3854692/generate-password-in-python +# # http://stackoverflow.com/questions/2257441/random-string-generation-with-upper-case-letters-and-digits-in-python +# # http://stackoverflow.com/questions/1024049/is-it-pythonic-to-import-inside-functions +# # http://stackoverflow.com/questions/3095071/in-python-what-happens-when-you-import-inside-of-a-function +# +# #-------------------------------------------- +# +# 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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# +# +# #-------------------------------------------- +# +# def svc_show_user( f_svc_log, f_svc_err, title_msg, security_db_name, sec_user ): +# +# global subprocess +# +# f_svc_log.seek(0,2) +# f_svc_log.write("\\n") +# f_svc_log.write(title_msg) +# f_svc_log.write("\\n") +# f_svc_log.seek(0,2) +# +# subprocess.call( [ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# "action_display_user_adm", +# "dbname", security_db_name, +# "sec_username", sec_user, +# ], +# stdout=f_svc_log, stderr=f_svc_err +# ) +# return +# +# #-------------------------------------------- +# +# f_svc_log=open( os.path.join(context['temp_directory'],'tmp_2861_fbsvc.log'), 'w') +# f_svc_err=open( os.path.join(context['temp_directory'],'tmp_2861_fbsvc.err'), 'w') +# +# chars = string.punctuation +# +# # + string.digits +# #string.letters + string.digits +# # do NOT: chars = string.printable -- it includes whitespaces, i.e. LF etc! +# +# # NB: maximal part of user name that is displayed in fbsvcmgr action_display_user is only 28 chars. +# # We build user name as two parts delimited by dot, so max. length of these parts is bound to 13, +# # otherwise total length of user name will be 14+1+14 = 29 and we'll get mismatch on expected stdout. +# +# +# ''' +# length = 13 +# dotted_user=''.join(sample(chars,length)).replace('"','.').replace("'",'.') +# dotted_user=dotted_user+'.'+''.join(sample(chars,length)) +# dotted_user=dotted_user.replace('"','""').replace("'","''") +# ''' +# +# length = 28 +# dotted_user=''.join(sample(chars,length)).replace('"','.').replace("'",'.') +# quoted_user='"'+dotted_user+'"' +# +# f_svc_log.write("Try to add user with name: "+quoted_user) +# f_svc_log.write("\\n") +# f_svc_log.seek(0,2) +# +# subprocess.call( [ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# "action_add_user", +# "dbname", security_db_name, +# "sec_username", quoted_user, +# "sec_password", "foobarkey", +# "sec_admin", "1" +# ], +# stdout=f_svc_log, stderr=f_svc_err +# ) +# +# svc_show_user( f_svc_log, f_svc_err, "Try to display user after adding.", security_db_name, quoted_user ) +# +# f_svc_log.seek(0,2) +# f_svc_log.write("\\n") +# f_svc_log.write("Try to modify user: change password and some attributes.") +# f_svc_log.write("\\n") +# f_svc_log.seek(0,2) +# +# subprocess.call( [ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# "action_modify_user", +# "dbname", security_db_name, +# "sec_username", quoted_user, +# "sec_password", "BSabbath", +# "sec_firstname", "Ozzy", +# "sec_middlename", "The Terrible", +# "sec_lastname", "Osbourne", +# "sec_admin", "0" +# ], +# stdout=f_svc_log, stderr=f_svc_err +# ) +# +# svc_show_user( f_svc_log, f_svc_err, "Try to display user after modifying.", security_db_name, quoted_user ) +# +# f_svc_log.seek(0,2) +# f_svc_log.write("\\n") +# f_svc_log.write("All done.") +# f_svc_log.write("\\n") +# +# flush_and_close( f_svc_log ) +# flush_and_close( f_svc_err ) +# +# ##################################### +# +# # Now we drop user (using ISQL - fbsvcmgr currently does not work) +# # and then create + modify + drop him again by ISQL. +# +# +# isql_txt='''---- %s +# set list on; +# --set echo on; +# create or alter view v_sec as select sec$user_name, sec$first_name, sec$middle_name, sec$last_name, sec$admin +# from sec$users +# where upper(sec$user_name)=upper('%s'); +# commit; +# +# -- select * from v_sec; commit; -- ==> FOO.RIO.BAR, in UPPER case (left after fbsvcmgr add_user) +# +# drop user %s; +# commit; +# +# select 'Try to add user with name: ' || '%s' as isql_msg from rdb$database; +# +# create or alter user %s password '123' grant admin role; +# commit; +# +# select 'Try to display user after adding.' as isql_msg from rdb$database; +# +# select * from v_sec; +# commit; +# +# select 'Try to modify user: change password and some attributes.' as isql_msg from rdb$database; +# +# alter user %s +# password 'Zeppelin' +# firstname 'John' +# middlename 'Bonzo The Beast' +# lastname 'Bonham' +# revoke admin role +# ; +# commit; +# +# select 'Try to display user after modifying.' as isql_msg from rdb$database; +# select * from v_sec; +# commit; +# +# select 'Try to drop user.' as isql_msg from rdb$database; +# drop user %s; +# commit; +# select 'All done.' as isql_msg from rdb$database; +# ''' % (dotted_user, dotted_user, quoted_user.upper(), dotted_user, quoted_user, quoted_user, quoted_user ) +# +# f_sql_txt=open( os.path.join(context['temp_directory'],'tmp_2861_isql.sql'), 'w') +# f_sql_txt.write(isql_txt) +# flush_and_close( f_sql_txt ) +# +# f_sql_log=open( os.path.join(context['temp_directory'],'tmp_2861_isql.log'), 'w') +# f_sql_err=open( os.path.join(context['temp_directory'],'tmp_2861_isql.err'), 'w') +# +# subprocess.call( [ context['isql_path'], dsn, "-i", f_sql_txt.name ], +# stdout=f_sql_log, stderr=f_sql_err +# ) +# +# flush_and_close( f_sql_log ) +# flush_and_close( f_sql_err ) +# +# with open( f_svc_log.name,'r') as f: +# l = [l for l in f.readlines() if l.strip()] +# +# for line in l: +# print("SVC STDOUT: "+line.replace(dotted_user.upper(),"") ) +# +# with open( f_svc_err.name,'r') as f: +# l = [l for l in f.readlines() if l.strip()] +# +# for line in l: +# print("SVC STDERR: "+line+", user: "+dotted_user) +# +# with open( f_sql_log.name,'r') as f: +# l = [l for l in f.readlines() if l.strip()] +# +# for line in l: +# print("SQL STDOUT: "+line.replace(dotted_user,"")) +# +# with open( f_sql_err.name,'r') as f: +# l = [l for l in f.readlines() if l.strip()] +# +# for line in l: +# print("SQL STDERR: "+line+", user: "+dotted_user) +# +# +# # Cleanup. +# ########## +# +# time.sleep(1) +# cleanup( [i.name for i in (f_svc_log,f_svc_err,f_sql_log,f_sql_err,f_sql_txt)] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + SVC STDOUT: Try to add user with name: "" + SVC STDOUT: Try to display user after adding. + SVC STDOUT: Login Full name uid gid adm + SVC STDOUT: 0 0 yes + SVC STDOUT: Try to modify user: change password and some attributes. + SVC STDOUT: Try to display user after modifying. + SVC STDOUT: Login Full name uid gid adm + SVC STDOUT: Ozzy The Terrible Osbourne 0 0 no + SVC STDOUT: All done. + SQL STDOUT: ISQL_MSG Try to add user with name: + SQL STDOUT: ISQL_MSG Try to display user after adding. + SQL STDOUT: SEC$USER_NAME + SQL STDOUT: SEC$FIRST_NAME + SQL STDOUT: SEC$MIDDLE_NAME + SQL STDOUT: SEC$LAST_NAME + SQL STDOUT: SEC$ADMIN + SQL STDOUT: ISQL_MSG Try to modify user: change password and some attributes. + SQL STDOUT: ISQL_MSG Try to display user after modifying. + SQL STDOUT: SEC$USER_NAME + SQL STDOUT: SEC$FIRST_NAME John + SQL STDOUT: SEC$MIDDLE_NAME Bonzo The Beast + SQL STDOUT: SEC$LAST_NAME Bonham + SQL STDOUT: SEC$ADMIN + SQL STDOUT: ISQL_MSG Try to drop user. + SQL STDOUT: ISQL_MSG All done. + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_2861_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2870.py b/tests/bugs/test_core_2870.py new file mode 100644 index 00000000..16ebc619 --- /dev/null +++ b/tests/bugs/test_core_2870.py @@ -0,0 +1,1036 @@ +#coding:utf-8 +# +# id: bugs.core_2870 +# title: View created from JOIN and LEFT JOIN doesnt order +# decription: +# +# tracker_id: CORE-2870 +# min_versions: ['2.5.7'] +# versions: 2.5.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table employee(i int); + recreate table department (i int); + commit; + + recreate table country ( + country varchar(15) not null + ,currency varchar(10) not null + ); + + recreate table department ( + dept_no char(3) not null + ,department varchar(25) not null + ,head_dept char(3) + ,mngr_no smallint + ,budget decimal(12,2) + ,location varchar(15) + ,phone_no varchar(20) default '555-1234' + ); + + recreate table employee ( + emp_no smallint not null + ,first_name varchar(15) not null + ,last_name varchar(20) not null + ,phone_ext varchar(4) + ,hire_date timestamp default 'now' not null + ,dept_no char(3) not null + ,job_code varchar(5) not null + ,job_grade smallint not null + ,job_country varchar(15) not null + ,salary numeric(10,2) not null + ,full_name computed by (last_name || ', ' || first_name) + ); + + create index namex on employee (last_name, first_name); + create descending index budgetx on department (budget); + commit; + + + insert into country (country, currency) values ('usa', 'dollar'); + insert into country (country, currency) values ('england', 'pound'); + insert into country (country, currency) values ('canada', 'cdndlr'); + insert into country (country, currency) values ('switzerland', 'sfranc'); + insert into country (country, currency) values ('japan', 'yen'); + insert into country (country, currency) values ('italy', 'euro'); + insert into country (country, currency) values ('france', 'euro'); + insert into country (country, currency) values ('germany', 'euro'); + insert into country (country, currency) values ('australia', 'adollar'); + insert into country (country, currency) values ('hong kong', 'hkdollar'); + insert into country (country, currency) values ('netherlands', 'euro'); + insert into country (country, currency) values ('belgium', 'euro'); + insert into country (country, currency) values ('austria', 'euro'); + insert into country (country, currency) values ('fiji', 'fdollar'); + insert into country (country, currency) values ('russia', 'ruble'); + insert into country (country, currency) values ('romania', 'rleu'); + + + insert into department (dept_no, department, head_dept, mngr_no, budget, location, phone_no) values ('000', 'corporate headquarters', null, 105, 1000000, 'monterey', '(408) 555-1234'); + insert into department (dept_no, department, head_dept, mngr_no, budget, location, phone_no) values ('100', 'sales and marketing', '000', 85, 2000000, 'san francisco', '(415) 555-1234'); + insert into department (dept_no, department, head_dept, mngr_no, budget, location, phone_no) values ('600', 'engineering', '000', 2, 1100000, 'monterey', '(408) 555-1234'); + insert into department (dept_no, department, head_dept, mngr_no, budget, location, phone_no) values ('900', 'finance', '000', 46, 400000, 'monterey', '(408) 555-1234'); + insert into department (dept_no, department, head_dept, mngr_no, budget, location, phone_no) values ('180', 'marketing', '100', null, 1500000, 'san francisco', '(415) 555-1234'); + insert into department (dept_no, department, head_dept, mngr_no, budget, location, phone_no) values ('620', 'software products div.', '600', null, 1200000, 'monterey', '(408) 555-1234'); + insert into department (dept_no, department, head_dept, mngr_no, budget, location, phone_no) values ('621', 'software development', '620', null, 400000, 'monterey', '(408) 555-1234'); + insert into department (dept_no, department, head_dept, mngr_no, budget, location, phone_no) values ('622', 'quality assurance', '620', 9, 300000, 'monterey', '(408) 555-1234'); + insert into department (dept_no, department, head_dept, mngr_no, budget, location, phone_no) values ('623', 'customer support', '620', 15, 650000, 'monterey', '(408) 555-1234'); + insert into department (dept_no, department, head_dept, mngr_no, budget, location, phone_no) values ('670', 'consumer electronics div.', '600', 107, 1150000, 'burlington, vt', '(802) 555-1234'); + insert into department (dept_no, department, head_dept, mngr_no, budget, location, phone_no) values ('671', 'research and development', '670', 20, 460000, 'burlington, vt', '(802) 555-1234'); + insert into department (dept_no, department, head_dept, mngr_no, budget, location, phone_no) values ('672', 'customer services', '670', 94, 850000, 'burlington, vt', '(802) 555-1234'); + insert into department (dept_no, department, head_dept, mngr_no, budget, location, phone_no) values ('130', 'field office: east coast', '100', 11, 500000, 'boston', '(617) 555-1234'); + insert into department (dept_no, department, head_dept, mngr_no, budget, location, phone_no) values ('140', 'field office: canada', '100', 72, 500000, 'toronto', '(416) 677-1000'); + insert into department (dept_no, department, head_dept, mngr_no, budget, location, phone_no) values ('110', 'pacific rim headquarters', '100', 34, 600000, 'kuaui', '(808) 555-1234'); + insert into department (dept_no, department, head_dept, mngr_no, budget, location, phone_no) values ('115', 'field office: japan', '110', 118, 500000, 'tokyo', '3 5350 0901'); + insert into department (dept_no, department, head_dept, mngr_no, budget, location, phone_no) values ('116', 'field office: singapore', '110', null, 300000, 'singapore', '3 55 1234'); + insert into department (dept_no, department, head_dept, mngr_no, budget, location, phone_no) values ('120', 'european headquarters', '100', 36, 700000, 'london', '71 235-4400'); + insert into department (dept_no, department, head_dept, mngr_no, budget, location, phone_no) values ('121', 'field office: switzerland', '120', 141, 500000, 'zurich', '1 211 7767'); + insert into department (dept_no, department, head_dept, mngr_no, budget, location, phone_no) values ('123', 'field office: france', '120', 134, 400000, 'cannes', '58 68 11 12'); + insert into department (dept_no, department, head_dept, mngr_no, budget, location, phone_no) values ('125', 'field office: italy', '120', 121, 400000, 'milan', '2 430 39 39'); + + + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (2, 'robert', 'nelson', '250', '28-dec-1988 00:00:00', '600', 'vp', 2, 'usa', 105900); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (4, 'bruce', 'young', '233', '28-dec-1988 00:00:00', '621', 'eng', 2, 'usa', 97500); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (5, 'kim', 'lambert', '22', '6-feb-1989 00:00:00', '130', 'eng', 2, 'usa', 102750); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (8, 'leslie', 'johnson', '410', '5-apr-1989 00:00:00', '180', 'mktg', 3, 'usa', 64635); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (9, 'phil', 'forest', '229', '17-apr-1989 00:00:00', '622', 'mngr', 3, 'usa', 75060); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (11, 'k. j.', 'weston', '34', '17-jan-1990 00:00:00', '130', 'srep', 4, 'usa', 86292.94); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (12, 'terri', 'lee', '256', '1-may-1990 00:00:00', '000', 'admin', 4, 'usa', 53793); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (14, 'stewart', 'hall', '227', '4-jun-1990 00:00:00', '900', 'finan', 3, 'usa', 69482.63); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (15, 'katherine', 'young', '231', '14-jun-1990 00:00:00', '623', 'mngr', 3, 'usa', 67241.25); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (20, 'chris', 'papadopoulos', '887', '1-jan-1990 00:00:00', '671', 'mngr', 3, 'usa', 89655); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (24, 'pete', 'fisher', '888', '12-sep-1990 00:00:00', '671', 'eng', 3, 'usa', 81810.19); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (28, 'ann', 'bennet', '5', '1-feb-1991 00:00:00', '120', 'admin', 5, 'england', 22935); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (29, 'roger', 'de souza', '288', '18-feb-1991 00:00:00', '623', 'eng', 3, 'usa', 69482.63); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (34, 'janet', 'baldwin', '2', '21-mar-1991 00:00:00', '110', 'sales', 3, 'usa', 61637.81); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (36, 'roger', 'reeves', '6', '25-apr-1991 00:00:00', '120', 'sales', 3, 'england', 33620.63); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (37, 'willie', 'stansbury', '7', '25-apr-1991 00:00:00', '120', 'eng', 4, 'england', 39224.06); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (44, 'leslie', 'phong', '216', '3-jun-1991 00:00:00', '623', 'eng', 4, 'usa', 56034.38); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (45, 'ashok', 'ramanathan', '209', '1-aug-1991 00:00:00', '621', 'eng', 3, 'usa', 80689.5); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (46, 'walter', 'steadman', '210', '9-aug-1991 00:00:00', '900', 'cfo', 1, 'usa', 116100); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (52, 'carol', 'nordstrom', '420', '2-oct-1991 00:00:00', '180', 'prel', 4, 'usa', 42742.5); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (61, 'luke', 'leung', '3', '18-feb-1992 00:00:00', '110', 'srep', 4, 'usa', 68805); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (65, 'sue anne', 'o''brien', '877', '23-mar-1992 00:00:00', '670', 'admin', 5, 'usa', 31275); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (71, 'jennifer m.', 'burbank', '289', '15-apr-1992 00:00:00', '622', 'eng', 3, 'usa', 53167.5); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (72, 'claudia', 'sutherland', null, '20-apr-1992 00:00:00', '140', 'srep', 4, 'canada', 100914); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (83, 'dana', 'bishop', '290', '1-jun-1992 00:00:00', '621', 'eng', 3, 'usa', 62550); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (85, 'mary s.', 'macdonald', '477', '1-jun-1992 00:00:00', '100', 'vp', 2, 'usa', 111262.5); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (94, 'randy', 'williams', '892', '8-aug-1992 00:00:00', '672', 'mngr', 4, 'usa', 56295); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (105, 'oliver h.', 'bender', '255', '8-oct-1992 00:00:00', '000', 'ceo', 1, 'usa', 212850); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (107, 'kevin', 'cook', '894', '1-feb-1993 00:00:00', '670', 'dir', 2, 'usa', 111262.5); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (109, 'kelly', 'brown', '202', '4-feb-1993 00:00:00', '600', 'admin', 5, 'usa', 27000); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (110, 'yuki', 'ichida', '22', '4-feb-1993 00:00:00', '115', 'eng', 3, 'japan', 6000000); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (113, 'mary', 'page', '845', '12-apr-1993 00:00:00', '671', 'eng', 4, 'usa', 48000); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (114, 'bill', 'parker', '247', '1-jun-1993 00:00:00', '623', 'eng', 5, 'usa', 35000); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (118, 'takashi', 'yamamoto', '23', '1-jul-1993 00:00:00', '115', 'srep', 4, 'japan', 7480000); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (121, 'roberto', 'ferrari', '1', '12-jul-1993 00:00:00', '125', 'srep', 4, 'italy', 33000); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (127, 'michael', 'yanowski', '492', '9-aug-1993 00:00:00', '100', 'srep', 4, 'usa', 44000); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (134, 'jacques', 'glon', null, '23-aug-1993 00:00:00', '123', 'srep', 4, 'france', 38500); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (136, 'scott', 'johnson', '265', '13-sep-1993 00:00:00', '623', 'doc', 3, 'usa', 60000); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (138, 't.j.', 'green', '218', '1-nov-1993 00:00:00', '621', 'eng', 4, 'usa', 36000); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (141, 'pierre', 'osborne', null, '3-jan-1994 00:00:00', '121', 'srep', 4, 'switzerland', 110000); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (144, 'john', 'montgomery', '820', '30-mar-1994 00:00:00', '672', 'eng', 5, 'usa', 35000); + insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, job_country, salary) values (145, 'mark', 'guckenheimer', '221', '2-may-1994 00:00:00', '622', 'eng', 5, 'usa', 32000); + commit; + + alter table country add primary key (country); + alter table department add unique (department); + alter table department add primary key (dept_no); + alter table employee add primary key (emp_no); + + + alter table employee add foreign key (dept_no) references department (dept_no); + alter table department add foreign key (head_dept) references department (dept_no); + alter table department add foreign key (mngr_no) references employee (emp_no); + commit; + + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select distinct + e.emp_no, + e.first_name, + e.last_name, + e.phone_ext, + e.hire_date, + e.dept_no, + e.job_code, + e.job_grade, + e.job_country, + e.salary, + e.full_name, + d.department, + d.head_dept, + d.mngr_no, + d.budget, + d.location, + d.phone_no, + c.country, + c.currency + from employee e + join department d on e.dept_no = d.dept_no + left join country c on e.job_country = c.country + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + EMP_NO 2 + FIRST_NAME robert + LAST_NAME nelson + PHONE_EXT 250 + HIRE_DATE 1988-12-28 00:00:00.0000 + DEPT_NO 600 + JOB_CODE vp + JOB_GRADE 2 + JOB_COUNTRY usa + SALARY 105900.00 + FULL_NAME nelson, robert + DEPARTMENT engineering + HEAD_DEPT 000 + MNGR_NO 2 + BUDGET 1100000.00 + LOCATION monterey + PHONE_NO (408) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 4 + FIRST_NAME bruce + LAST_NAME young + PHONE_EXT 233 + HIRE_DATE 1988-12-28 00:00:00.0000 + DEPT_NO 621 + JOB_CODE eng + JOB_GRADE 2 + JOB_COUNTRY usa + SALARY 97500.00 + FULL_NAME young, bruce + DEPARTMENT software development + HEAD_DEPT 620 + MNGR_NO + BUDGET 400000.00 + LOCATION monterey + PHONE_NO (408) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 5 + FIRST_NAME kim + LAST_NAME lambert + PHONE_EXT 22 + HIRE_DATE 1989-02-06 00:00:00.0000 + DEPT_NO 130 + JOB_CODE eng + JOB_GRADE 2 + JOB_COUNTRY usa + SALARY 102750.00 + FULL_NAME lambert, kim + DEPARTMENT field office: east coast + HEAD_DEPT 100 + MNGR_NO 11 + BUDGET 500000.00 + LOCATION boston + PHONE_NO (617) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 8 + FIRST_NAME leslie + LAST_NAME johnson + PHONE_EXT 410 + HIRE_DATE 1989-04-05 00:00:00.0000 + DEPT_NO 180 + JOB_CODE mktg + JOB_GRADE 3 + JOB_COUNTRY usa + SALARY 64635.00 + FULL_NAME johnson, leslie + DEPARTMENT marketing + HEAD_DEPT 100 + MNGR_NO + BUDGET 1500000.00 + LOCATION san francisco + PHONE_NO (415) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 9 + FIRST_NAME phil + LAST_NAME forest + PHONE_EXT 229 + HIRE_DATE 1989-04-17 00:00:00.0000 + DEPT_NO 622 + JOB_CODE mngr + JOB_GRADE 3 + JOB_COUNTRY usa + SALARY 75060.00 + FULL_NAME forest, phil + DEPARTMENT quality assurance + HEAD_DEPT 620 + MNGR_NO 9 + BUDGET 300000.00 + LOCATION monterey + PHONE_NO (408) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 11 + FIRST_NAME k. j. + LAST_NAME weston + PHONE_EXT 34 + HIRE_DATE 1990-01-17 00:00:00.0000 + DEPT_NO 130 + JOB_CODE srep + JOB_GRADE 4 + JOB_COUNTRY usa + SALARY 86292.94 + FULL_NAME weston, k. j. + DEPARTMENT field office: east coast + HEAD_DEPT 100 + MNGR_NO 11 + BUDGET 500000.00 + LOCATION boston + PHONE_NO (617) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 12 + FIRST_NAME terri + LAST_NAME lee + PHONE_EXT 256 + HIRE_DATE 1990-05-01 00:00:00.0000 + DEPT_NO 000 + JOB_CODE admin + JOB_GRADE 4 + JOB_COUNTRY usa + SALARY 53793.00 + FULL_NAME lee, terri + DEPARTMENT corporate headquarters + HEAD_DEPT + MNGR_NO 105 + BUDGET 1000000.00 + LOCATION monterey + PHONE_NO (408) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 14 + FIRST_NAME stewart + LAST_NAME hall + PHONE_EXT 227 + HIRE_DATE 1990-06-04 00:00:00.0000 + DEPT_NO 900 + JOB_CODE finan + JOB_GRADE 3 + JOB_COUNTRY usa + SALARY 69482.63 + FULL_NAME hall, stewart + DEPARTMENT finance + HEAD_DEPT 000 + MNGR_NO 46 + BUDGET 400000.00 + LOCATION monterey + PHONE_NO (408) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 15 + FIRST_NAME katherine + LAST_NAME young + PHONE_EXT 231 + HIRE_DATE 1990-06-14 00:00:00.0000 + DEPT_NO 623 + JOB_CODE mngr + JOB_GRADE 3 + JOB_COUNTRY usa + SALARY 67241.25 + FULL_NAME young, katherine + DEPARTMENT customer support + HEAD_DEPT 620 + MNGR_NO 15 + BUDGET 650000.00 + LOCATION monterey + PHONE_NO (408) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 20 + FIRST_NAME chris + LAST_NAME papadopoulos + PHONE_EXT 887 + HIRE_DATE 1990-01-01 00:00:00.0000 + DEPT_NO 671 + JOB_CODE mngr + JOB_GRADE 3 + JOB_COUNTRY usa + SALARY 89655.00 + FULL_NAME papadopoulos, chris + DEPARTMENT research and development + HEAD_DEPT 670 + MNGR_NO 20 + BUDGET 460000.00 + LOCATION burlington, vt + PHONE_NO (802) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 24 + FIRST_NAME pete + LAST_NAME fisher + PHONE_EXT 888 + HIRE_DATE 1990-09-12 00:00:00.0000 + DEPT_NO 671 + JOB_CODE eng + JOB_GRADE 3 + JOB_COUNTRY usa + SALARY 81810.19 + FULL_NAME fisher, pete + DEPARTMENT research and development + HEAD_DEPT 670 + MNGR_NO 20 + BUDGET 460000.00 + LOCATION burlington, vt + PHONE_NO (802) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 28 + FIRST_NAME ann + LAST_NAME bennet + PHONE_EXT 5 + HIRE_DATE 1991-02-01 00:00:00.0000 + DEPT_NO 120 + JOB_CODE admin + JOB_GRADE 5 + JOB_COUNTRY england + SALARY 22935.00 + FULL_NAME bennet, ann + DEPARTMENT european headquarters + HEAD_DEPT 100 + MNGR_NO 36 + BUDGET 700000.00 + LOCATION london + PHONE_NO 71 235-4400 + COUNTRY england + CURRENCY pound + + EMP_NO 29 + FIRST_NAME roger + LAST_NAME de souza + PHONE_EXT 288 + HIRE_DATE 1991-02-18 00:00:00.0000 + DEPT_NO 623 + JOB_CODE eng + JOB_GRADE 3 + JOB_COUNTRY usa + SALARY 69482.63 + FULL_NAME de souza, roger + DEPARTMENT customer support + HEAD_DEPT 620 + MNGR_NO 15 + BUDGET 650000.00 + LOCATION monterey + PHONE_NO (408) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 34 + FIRST_NAME janet + LAST_NAME baldwin + PHONE_EXT 2 + HIRE_DATE 1991-03-21 00:00:00.0000 + DEPT_NO 110 + JOB_CODE sales + JOB_GRADE 3 + JOB_COUNTRY usa + SALARY 61637.81 + FULL_NAME baldwin, janet + DEPARTMENT pacific rim headquarters + HEAD_DEPT 100 + MNGR_NO 34 + BUDGET 600000.00 + LOCATION kuaui + PHONE_NO (808) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 36 + FIRST_NAME roger + LAST_NAME reeves + PHONE_EXT 6 + HIRE_DATE 1991-04-25 00:00:00.0000 + DEPT_NO 120 + JOB_CODE sales + JOB_GRADE 3 + JOB_COUNTRY england + SALARY 33620.63 + FULL_NAME reeves, roger + DEPARTMENT european headquarters + HEAD_DEPT 100 + MNGR_NO 36 + BUDGET 700000.00 + LOCATION london + PHONE_NO 71 235-4400 + COUNTRY england + CURRENCY pound + + EMP_NO 37 + FIRST_NAME willie + LAST_NAME stansbury + PHONE_EXT 7 + HIRE_DATE 1991-04-25 00:00:00.0000 + DEPT_NO 120 + JOB_CODE eng + JOB_GRADE 4 + JOB_COUNTRY england + SALARY 39224.06 + FULL_NAME stansbury, willie + DEPARTMENT european headquarters + HEAD_DEPT 100 + MNGR_NO 36 + BUDGET 700000.00 + LOCATION london + PHONE_NO 71 235-4400 + COUNTRY england + CURRENCY pound + + EMP_NO 44 + FIRST_NAME leslie + LAST_NAME phong + PHONE_EXT 216 + HIRE_DATE 1991-06-03 00:00:00.0000 + DEPT_NO 623 + JOB_CODE eng + JOB_GRADE 4 + JOB_COUNTRY usa + SALARY 56034.38 + FULL_NAME phong, leslie + DEPARTMENT customer support + HEAD_DEPT 620 + MNGR_NO 15 + BUDGET 650000.00 + LOCATION monterey + PHONE_NO (408) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 45 + FIRST_NAME ashok + LAST_NAME ramanathan + PHONE_EXT 209 + HIRE_DATE 1991-08-01 00:00:00.0000 + DEPT_NO 621 + JOB_CODE eng + JOB_GRADE 3 + JOB_COUNTRY usa + SALARY 80689.50 + FULL_NAME ramanathan, ashok + DEPARTMENT software development + HEAD_DEPT 620 + MNGR_NO + BUDGET 400000.00 + LOCATION monterey + PHONE_NO (408) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 46 + FIRST_NAME walter + LAST_NAME steadman + PHONE_EXT 210 + HIRE_DATE 1991-08-09 00:00:00.0000 + DEPT_NO 900 + JOB_CODE cfo + JOB_GRADE 1 + JOB_COUNTRY usa + SALARY 116100.00 + FULL_NAME steadman, walter + DEPARTMENT finance + HEAD_DEPT 000 + MNGR_NO 46 + BUDGET 400000.00 + LOCATION monterey + PHONE_NO (408) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 52 + FIRST_NAME carol + LAST_NAME nordstrom + PHONE_EXT 420 + HIRE_DATE 1991-10-02 00:00:00.0000 + DEPT_NO 180 + JOB_CODE prel + JOB_GRADE 4 + JOB_COUNTRY usa + SALARY 42742.50 + FULL_NAME nordstrom, carol + DEPARTMENT marketing + HEAD_DEPT 100 + MNGR_NO + BUDGET 1500000.00 + LOCATION san francisco + PHONE_NO (415) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 61 + FIRST_NAME luke + LAST_NAME leung + PHONE_EXT 3 + HIRE_DATE 1992-02-18 00:00:00.0000 + DEPT_NO 110 + JOB_CODE srep + JOB_GRADE 4 + JOB_COUNTRY usa + SALARY 68805.00 + FULL_NAME leung, luke + DEPARTMENT pacific rim headquarters + HEAD_DEPT 100 + MNGR_NO 34 + BUDGET 600000.00 + LOCATION kuaui + PHONE_NO (808) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 65 + FIRST_NAME sue anne + LAST_NAME o'brien + PHONE_EXT 877 + HIRE_DATE 1992-03-23 00:00:00.0000 + DEPT_NO 670 + JOB_CODE admin + JOB_GRADE 5 + JOB_COUNTRY usa + SALARY 31275.00 + FULL_NAME o'brien, sue anne + DEPARTMENT consumer electronics div. + HEAD_DEPT 600 + MNGR_NO 107 + BUDGET 1150000.00 + LOCATION burlington, vt + PHONE_NO (802) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 71 + FIRST_NAME jennifer m. + LAST_NAME burbank + PHONE_EXT 289 + HIRE_DATE 1992-04-15 00:00:00.0000 + DEPT_NO 622 + JOB_CODE eng + JOB_GRADE 3 + JOB_COUNTRY usa + SALARY 53167.50 + FULL_NAME burbank, jennifer m. + DEPARTMENT quality assurance + HEAD_DEPT 620 + MNGR_NO 9 + BUDGET 300000.00 + LOCATION monterey + PHONE_NO (408) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 72 + FIRST_NAME claudia + LAST_NAME sutherland + PHONE_EXT + HIRE_DATE 1992-04-20 00:00:00.0000 + DEPT_NO 140 + JOB_CODE srep + JOB_GRADE 4 + JOB_COUNTRY canada + SALARY 100914.00 + FULL_NAME sutherland, claudia + DEPARTMENT field office: canada + HEAD_DEPT 100 + MNGR_NO 72 + BUDGET 500000.00 + LOCATION toronto + PHONE_NO (416) 677-1000 + COUNTRY canada + CURRENCY cdndlr + + EMP_NO 83 + FIRST_NAME dana + LAST_NAME bishop + PHONE_EXT 290 + HIRE_DATE 1992-06-01 00:00:00.0000 + DEPT_NO 621 + JOB_CODE eng + JOB_GRADE 3 + JOB_COUNTRY usa + SALARY 62550.00 + FULL_NAME bishop, dana + DEPARTMENT software development + HEAD_DEPT 620 + MNGR_NO + BUDGET 400000.00 + LOCATION monterey + PHONE_NO (408) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 85 + FIRST_NAME mary s. + LAST_NAME macdonald + PHONE_EXT 477 + HIRE_DATE 1992-06-01 00:00:00.0000 + DEPT_NO 100 + JOB_CODE vp + JOB_GRADE 2 + JOB_COUNTRY usa + SALARY 111262.50 + FULL_NAME macdonald, mary s. + DEPARTMENT sales and marketing + HEAD_DEPT 000 + MNGR_NO 85 + BUDGET 2000000.00 + LOCATION san francisco + PHONE_NO (415) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 94 + FIRST_NAME randy + LAST_NAME williams + PHONE_EXT 892 + HIRE_DATE 1992-08-08 00:00:00.0000 + DEPT_NO 672 + JOB_CODE mngr + JOB_GRADE 4 + JOB_COUNTRY usa + SALARY 56295.00 + FULL_NAME williams, randy + DEPARTMENT customer services + HEAD_DEPT 670 + MNGR_NO 94 + BUDGET 850000.00 + LOCATION burlington, vt + PHONE_NO (802) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 105 + FIRST_NAME oliver h. + LAST_NAME bender + PHONE_EXT 255 + HIRE_DATE 1992-10-08 00:00:00.0000 + DEPT_NO 000 + JOB_CODE ceo + JOB_GRADE 1 + JOB_COUNTRY usa + SALARY 212850.00 + FULL_NAME bender, oliver h. + DEPARTMENT corporate headquarters + HEAD_DEPT + MNGR_NO 105 + BUDGET 1000000.00 + LOCATION monterey + PHONE_NO (408) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 107 + FIRST_NAME kevin + LAST_NAME cook + PHONE_EXT 894 + HIRE_DATE 1993-02-01 00:00:00.0000 + DEPT_NO 670 + JOB_CODE dir + JOB_GRADE 2 + JOB_COUNTRY usa + SALARY 111262.50 + FULL_NAME cook, kevin + DEPARTMENT consumer electronics div. + HEAD_DEPT 600 + MNGR_NO 107 + BUDGET 1150000.00 + LOCATION burlington, vt + PHONE_NO (802) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 109 + FIRST_NAME kelly + LAST_NAME brown + PHONE_EXT 202 + HIRE_DATE 1993-02-04 00:00:00.0000 + DEPT_NO 600 + JOB_CODE admin + JOB_GRADE 5 + JOB_COUNTRY usa + SALARY 27000.00 + FULL_NAME brown, kelly + DEPARTMENT engineering + HEAD_DEPT 000 + MNGR_NO 2 + BUDGET 1100000.00 + LOCATION monterey + PHONE_NO (408) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 110 + FIRST_NAME yuki + LAST_NAME ichida + PHONE_EXT 22 + HIRE_DATE 1993-02-04 00:00:00.0000 + DEPT_NO 115 + JOB_CODE eng + JOB_GRADE 3 + JOB_COUNTRY japan + SALARY 6000000.00 + FULL_NAME ichida, yuki + DEPARTMENT field office: japan + HEAD_DEPT 110 + MNGR_NO 118 + BUDGET 500000.00 + LOCATION tokyo + PHONE_NO 3 5350 0901 + COUNTRY japan + CURRENCY yen + + EMP_NO 113 + FIRST_NAME mary + LAST_NAME page + PHONE_EXT 845 + HIRE_DATE 1993-04-12 00:00:00.0000 + DEPT_NO 671 + JOB_CODE eng + JOB_GRADE 4 + JOB_COUNTRY usa + SALARY 48000.00 + FULL_NAME page, mary + DEPARTMENT research and development + HEAD_DEPT 670 + MNGR_NO 20 + BUDGET 460000.00 + LOCATION burlington, vt + PHONE_NO (802) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 114 + FIRST_NAME bill + LAST_NAME parker + PHONE_EXT 247 + HIRE_DATE 1993-06-01 00:00:00.0000 + DEPT_NO 623 + JOB_CODE eng + JOB_GRADE 5 + JOB_COUNTRY usa + SALARY 35000.00 + FULL_NAME parker, bill + DEPARTMENT customer support + HEAD_DEPT 620 + MNGR_NO 15 + BUDGET 650000.00 + LOCATION monterey + PHONE_NO (408) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 118 + FIRST_NAME takashi + LAST_NAME yamamoto + PHONE_EXT 23 + HIRE_DATE 1993-07-01 00:00:00.0000 + DEPT_NO 115 + JOB_CODE srep + JOB_GRADE 4 + JOB_COUNTRY japan + SALARY 7480000.00 + FULL_NAME yamamoto, takashi + DEPARTMENT field office: japan + HEAD_DEPT 110 + MNGR_NO 118 + BUDGET 500000.00 + LOCATION tokyo + PHONE_NO 3 5350 0901 + COUNTRY japan + CURRENCY yen + + EMP_NO 121 + FIRST_NAME roberto + LAST_NAME ferrari + PHONE_EXT 1 + HIRE_DATE 1993-07-12 00:00:00.0000 + DEPT_NO 125 + JOB_CODE srep + JOB_GRADE 4 + JOB_COUNTRY italy + SALARY 33000.00 + FULL_NAME ferrari, roberto + DEPARTMENT field office: italy + HEAD_DEPT 120 + MNGR_NO 121 + BUDGET 400000.00 + LOCATION milan + PHONE_NO 2 430 39 39 + COUNTRY italy + CURRENCY euro + + EMP_NO 127 + FIRST_NAME michael + LAST_NAME yanowski + PHONE_EXT 492 + HIRE_DATE 1993-08-09 00:00:00.0000 + DEPT_NO 100 + JOB_CODE srep + JOB_GRADE 4 + JOB_COUNTRY usa + SALARY 44000.00 + FULL_NAME yanowski, michael + DEPARTMENT sales and marketing + HEAD_DEPT 000 + MNGR_NO 85 + BUDGET 2000000.00 + LOCATION san francisco + PHONE_NO (415) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 134 + FIRST_NAME jacques + LAST_NAME glon + PHONE_EXT + HIRE_DATE 1993-08-23 00:00:00.0000 + DEPT_NO 123 + JOB_CODE srep + JOB_GRADE 4 + JOB_COUNTRY france + SALARY 38500.00 + FULL_NAME glon, jacques + DEPARTMENT field office: france + HEAD_DEPT 120 + MNGR_NO 134 + BUDGET 400000.00 + LOCATION cannes + PHONE_NO 58 68 11 12 + COUNTRY france + CURRENCY euro + + EMP_NO 136 + FIRST_NAME scott + LAST_NAME johnson + PHONE_EXT 265 + HIRE_DATE 1993-09-13 00:00:00.0000 + DEPT_NO 623 + JOB_CODE doc + JOB_GRADE 3 + JOB_COUNTRY usa + SALARY 60000.00 + FULL_NAME johnson, scott + DEPARTMENT customer support + HEAD_DEPT 620 + MNGR_NO 15 + BUDGET 650000.00 + LOCATION monterey + PHONE_NO (408) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 138 + FIRST_NAME t.j. + LAST_NAME green + PHONE_EXT 218 + HIRE_DATE 1993-11-01 00:00:00.0000 + DEPT_NO 621 + JOB_CODE eng + JOB_GRADE 4 + JOB_COUNTRY usa + SALARY 36000.00 + FULL_NAME green, t.j. + DEPARTMENT software development + HEAD_DEPT 620 + MNGR_NO + BUDGET 400000.00 + LOCATION monterey + PHONE_NO (408) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 141 + FIRST_NAME pierre + LAST_NAME osborne + PHONE_EXT + HIRE_DATE 1994-01-03 00:00:00.0000 + DEPT_NO 121 + JOB_CODE srep + JOB_GRADE 4 + JOB_COUNTRY switzerland + SALARY 110000.00 + FULL_NAME osborne, pierre + DEPARTMENT field office: switzerland + HEAD_DEPT 120 + MNGR_NO 141 + BUDGET 500000.00 + LOCATION zurich + PHONE_NO 1 211 7767 + COUNTRY switzerland + CURRENCY sfranc + + EMP_NO 144 + FIRST_NAME john + LAST_NAME montgomery + PHONE_EXT 820 + HIRE_DATE 1994-03-30 00:00:00.0000 + DEPT_NO 672 + JOB_CODE eng + JOB_GRADE 5 + JOB_COUNTRY usa + SALARY 35000.00 + FULL_NAME montgomery, john + DEPARTMENT customer services + HEAD_DEPT 670 + MNGR_NO 94 + BUDGET 850000.00 + LOCATION burlington, vt + PHONE_NO (802) 555-1234 + COUNTRY usa + CURRENCY dollar + + EMP_NO 145 + FIRST_NAME mark + LAST_NAME guckenheimer + PHONE_EXT 221 + HIRE_DATE 1994-05-02 00:00:00.0000 + DEPT_NO 622 + JOB_CODE eng + JOB_GRADE 5 + JOB_COUNTRY usa + SALARY 32000.00 + FULL_NAME guckenheimer, mark + DEPARTMENT quality assurance + HEAD_DEPT 620 + MNGR_NO 9 + BUDGET 300000.00 + LOCATION monterey + PHONE_NO (408) 555-1234 + COUNTRY usa + CURRENCY dollar + """ + +@pytest.mark.version('>=2.5.7') +def test_core_2870_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2871.py b/tests/bugs/test_core_2871.py new file mode 100644 index 00000000..a2c2cbd5 --- /dev/null +++ b/tests/bugs/test_core_2871.py @@ -0,0 +1,240 @@ +#coding:utf-8 +# +# id: bugs.core_2871 +# title: Outer ORDER BY clause has no effect +# decription: If a derived table (or a view) contains both a left/right join and an ORDER BY clause and the outer query also contains an ORDER BY clause, the latter one gets ignored. +# tracker_id: CORE-2871 +# min_versions: ['2.0.6', '2.1.4', '2.5'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """/******************************************************************************/ +/* Domains */ +/******************************************************************************/ + +CREATE DOMAIN COUNTRYNAME AS +VARCHAR(15); + +CREATE DOMAIN DEPTNO AS +CHAR(3) +CHECK (VALUE = '000' OR (VALUE > '0' AND VALUE <= '999') OR VALUE IS NULL); + +CREATE DOMAIN EMPNO AS +SMALLINT; + +CREATE DOMAIN FIRSTNAME AS +VARCHAR(15); + +CREATE DOMAIN JOBCODE AS +VARCHAR(5) +CHECK (VALUE > '99999'); + +CREATE DOMAIN JOBGRADE AS +SMALLINT +CHECK (VALUE BETWEEN 0 AND 6); + +CREATE DOMAIN LASTNAME AS +VARCHAR(20); + +CREATE DOMAIN PHONENUMBER AS +VARCHAR(20); + +CREATE DOMAIN SALARY AS +NUMERIC(10,2) +DEFAULT 0 +CHECK (VALUE > 0); + + + +/******************************************************************************/ +/* Tables */ +/******************************************************************************/ + + + +CREATE TABLE COUNTRY ( + COUNTRY COUNTRYNAME NOT NULL, + CURRENCY VARCHAR(10) NOT NULL +); + + +CREATE TABLE EMPLOYEE ( + EMP_NO EMPNO NOT NULL, + FIRST_NAME FIRSTNAME NOT NULL, + LAST_NAME LASTNAME NOT NULL, + PHONE_EXT VARCHAR(4), + HIRE_DATE TIMESTAMP DEFAULT 'NOW' NOT NULL, + DEPT_NO DEPTNO NOT NULL, + JOB_CODE JOBCODE NOT NULL, + JOB_GRADE JOBGRADE NOT NULL, + JOB_COUNTRY COUNTRYNAME NOT NULL, + SALARY SALARY NOT NULL, + FULL_NAME COMPUTED BY (last_name || ', ' || first_name) +); + + +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (2, 'Robert', 'Nelson', '250', '1988-12-28 00:00:00', '600', 'VP', 2, 'USA', 105900); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (4, 'Bruce', 'Young', '233', '1988-12-28 00:00:00', '621', 'Eng', 2, 'USA', 97500); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (5, 'Kim', 'Lambert', '22', '1989-02-06 00:00:00', '130', 'Eng', 2, 'USA', 102750); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (8, 'Leslie', 'Johnson', '410', '1989-04-05 00:00:00', '180', 'Mktg', 3, 'USA', 64635); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (9, 'Phil', 'Forest', '229', '1989-04-17 00:00:00', '622', 'Mngr', 3, 'USA', 75060); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (11, 'K. J.', 'Weston', '34', '1990-01-17 00:00:00', '130', 'SRep', 4, 'USA', 86292.94); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (12, 'Terri', 'Lee', '256', '1990-05-01 00:00:00', '000', 'Admin', 4, 'USA', 53793); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (14, 'Stewart', 'Hall', '227', '1990-06-04 00:00:00', '900', 'Finan', 3, 'USA', 69482.63); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (15, 'Katherine', 'Young', '231', '1990-06-14 00:00:00', '623', 'Mngr', 3, 'USA', 67241.25); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (20, 'Chris', 'Papadopoulos', '887', '1990-01-01 00:00:00', '671', 'Mngr', 3, 'USA', 89655); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (24, 'Pete', 'Fisher', '888', '1990-09-12 00:00:00', '671', 'Eng', 3, 'USA', 81810.19); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (28, 'Ann', 'Bennet', '5', '1991-02-01 00:00:00', '120', 'Admin', 5, 'England', 22935); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (29, 'Roger', 'De Souza', '288', '1991-02-18 00:00:00', '623', 'Eng', 3, 'USA', 69482.63); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (34, 'Janet', 'Baldwin', '2', '1991-03-21 00:00:00', '110', 'Sales', 3, 'USA', 61637.81); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (36, 'Roger', 'Reeves', '6', '1991-04-25 00:00:00', '120', 'Sales', 3, 'England', 33620.63); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (37, 'Willie', 'Stansbury', '7', '1991-04-25 00:00:00', '120', 'Eng', 4, 'England', 39224.06); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (44, 'Leslie', 'Phong', '216', '1991-06-03 00:00:00', '623', 'Eng', 4, 'USA', 56034.38); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (45, 'Ashok', 'Ramanathan', '209', '1991-08-01 00:00:00', '621', 'Eng', 3, 'USA', 80689.5); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (46, 'Walter', 'Steadman', '210', '1991-08-09 00:00:00', '900', 'CFO', 1, 'USA', 116100); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (52, 'Carol', 'Nordstrom', '420', '1991-10-02 00:00:00', '180', 'PRel', 4, 'USA', 42742.5); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (61, 'Luke', 'Leung', '3', '1992-02-18 00:00:00', '110', 'SRep', 4, 'USA', 68805); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (65, 'Sue Anne', 'O''Brien', '877', '1992-03-23 00:00:00', '670', 'Admin', 5, 'USA', 31275); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (71, 'Jennifer M.', 'Burbank', '289', '1992-04-15 00:00:00', '622', 'Eng', 3, 'USA', 53167.5); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (72, 'Claudia', 'Sutherland', NULL, '1992-04-20 00:00:00', '140', 'SRep', 4, 'Canada', 100914); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (83, 'Dana', 'Bishop', '290', '1992-06-01 00:00:00', '621', 'Eng', 3, 'USA', 62550); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (85, 'Mary S.', 'MacDonald', '477', '1992-06-01 00:00:00', '100', 'VP', 2, 'USA', 111262.5); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (94, 'Randy', 'Williams', '892', '1992-08-08 00:00:00', '672', 'Mngr', 4, 'USA', 56295); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (105, 'Oliver H.', 'Bender', '255', '1992-10-08 00:00:00', '000', 'CEO', 1, 'USA', 212850); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (107, 'Kevin', 'Cook', '894', '1993-02-01 00:00:00', '670', 'Dir', 2, 'USA', 111262.5); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (109, 'Kelly', 'Brown', '202', '1993-02-04 00:00:00', '600', 'Admin', 5, 'USA', 27000); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (110, 'Yuki', 'Ichida', '22', '1993-02-04 00:00:00', '115', 'Eng', 3, 'Japan', 6000000); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (113, 'Mary', 'Page', '845', '1993-04-12 00:00:00', '671', 'Eng', 4, 'USA', 48000); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (114, 'Bill', 'Parker', '247', '1993-06-01 00:00:00', '623', 'Eng', 5, 'USA', 35000); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (118, 'Takashi', 'Yamamoto', '23', '1993-07-01 00:00:00', '115', 'SRep', 4, 'Japan', 7480000); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (121, 'Roberto', 'Ferrari', '1', '1993-07-12 00:00:00', '125', 'SRep', 4, 'Italy', 99000000); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (127, 'Michael', 'Yanowski', '492', '1993-08-09 00:00:00', '100', 'SRep', 4, 'USA', 44000); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (134, 'Jacques', 'Glon', NULL, '1993-08-23 00:00:00', '123', 'SRep', 4, 'France', 390500); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (136, 'Scott', 'Johnson', '265', '1993-09-13 00:00:00', '623', 'Doc', 3, 'USA', 60000); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (138, 'T.J.', 'Green', '218', '1993-11-01 00:00:00', '621', 'Eng', 4, 'USA', 36000); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (141, 'Pierre', 'Osborne', NULL, '1994-01-03 00:00:00', '121', 'SRep', 4, 'Switzerland', 110000); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (144, 'John', 'Montgomery', '820', '1994-03-30 00:00:00', '672', 'Eng', 5, 'USA', 35000); +INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, PHONE_EXT, HIRE_DATE, DEPT_NO, JOB_CODE, JOB_GRADE, JOB_COUNTRY, SALARY) VALUES (145, 'Mark', 'Guckenheimer', '221', '1994-05-02 00:00:00', '622', 'Eng', 5, 'USA', 32000); + +COMMIT WORK; + +INSERT INTO COUNTRY (COUNTRY, CURRENCY) VALUES ('USA', 'Dollar'); +INSERT INTO COUNTRY (COUNTRY, CURRENCY) VALUES ('England', 'Pound'); +INSERT INTO COUNTRY (COUNTRY, CURRENCY) VALUES ('Canada', 'CdnDlr'); +INSERT INTO COUNTRY (COUNTRY, CURRENCY) VALUES ('Switzerland', 'SFranc'); +INSERT INTO COUNTRY (COUNTRY, CURRENCY) VALUES ('Japan', 'Yen'); +INSERT INTO COUNTRY (COUNTRY, CURRENCY) VALUES ('Italy', 'Lira'); +INSERT INTO COUNTRY (COUNTRY, CURRENCY) VALUES ('France', 'FFranc'); +INSERT INTO COUNTRY (COUNTRY, CURRENCY) VALUES ('Germany', 'D-Mark'); +INSERT INTO COUNTRY (COUNTRY, CURRENCY) VALUES ('Australia', 'ADollar'); +INSERT INTO COUNTRY (COUNTRY, CURRENCY) VALUES ('Hong Kong', 'HKDollar'); +INSERT INTO COUNTRY (COUNTRY, CURRENCY) VALUES ('Netherlands', 'Guilder'); +INSERT INTO COUNTRY (COUNTRY, CURRENCY) VALUES ('Belgium', 'BFranc'); +INSERT INTO COUNTRY (COUNTRY, CURRENCY) VALUES ('Austria', 'Schilling'); +INSERT INTO COUNTRY (COUNTRY, CURRENCY) VALUES ('Fiji', 'FDollar'); + +COMMIT WORK; + + + + + +/******************************************************************************/ +/* Primary Keys */ +/******************************************************************************/ + +ALTER TABLE COUNTRY ADD PRIMARY KEY (COUNTRY); +ALTER TABLE EMPLOYEE ADD PRIMARY KEY (EMP_NO); + + +/******************************************************************************/ +/* Indices */ +/******************************************************************************/ + +CREATE INDEX NAMEX ON EMPLOYEE (LAST_NAME, FIRST_NAME); + +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ +select * +from ( + select + emp_no, first_name, last_name, country, currency + from employee + left join country on employee.job_country = country.country + order by last_name +) +order by emp_no desc; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ EMP_NO FIRST_NAME LAST_NAME COUNTRY CURRENCY +======= =============== ==================== =============== ========== + 145 Mark Guckenheimer USA Dollar + 144 John Montgomery USA Dollar + 141 Pierre Osborne Switzerland SFranc + 138 T.J. Green USA Dollar + 136 Scott Johnson USA Dollar + 134 Jacques Glon France FFranc + 127 Michael Yanowski USA Dollar + 121 Roberto Ferrari Italy Lira + 118 Takashi Yamamoto Japan Yen + 114 Bill Parker USA Dollar + 113 Mary Page USA Dollar + 110 Yuki Ichida Japan Yen + 109 Kelly Brown USA Dollar + 107 Kevin Cook USA Dollar + 105 Oliver H. Bender USA Dollar + 94 Randy Williams USA Dollar + 85 Mary S. MacDonald USA Dollar + 83 Dana Bishop USA Dollar + 72 Claudia Sutherland Canada CdnDlr + 71 Jennifer M. Burbank USA Dollar + + EMP_NO FIRST_NAME LAST_NAME COUNTRY CURRENCY +======= =============== ==================== =============== ========== + 65 Sue Anne O'Brien USA Dollar + 61 Luke Leung USA Dollar + 52 Carol Nordstrom USA Dollar + 46 Walter Steadman USA Dollar + 45 Ashok Ramanathan USA Dollar + 44 Leslie Phong USA Dollar + 37 Willie Stansbury England Pound + 36 Roger Reeves England Pound + 34 Janet Baldwin USA Dollar + 29 Roger De Souza USA Dollar + 28 Ann Bennet England Pound + 24 Pete Fisher USA Dollar + 20 Chris Papadopoulos USA Dollar + 15 Katherine Young USA Dollar + 14 Stewart Hall USA Dollar + 12 Terri Lee USA Dollar + 11 K. J. Weston USA Dollar + 9 Phil Forest USA Dollar + 8 Leslie Johnson USA Dollar + 5 Kim Lambert USA Dollar + + EMP_NO FIRST_NAME LAST_NAME COUNTRY CURRENCY +======= =============== ==================== =============== ========== + 4 Bruce Young USA Dollar + 2 Robert Nelson USA Dollar + +""" + +@pytest.mark.version('>=2.5') +def test_core_2871_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2872.py b/tests/bugs/test_core_2872.py new file mode 100644 index 00000000..a25c26be --- /dev/null +++ b/tests/bugs/test_core_2872.py @@ -0,0 +1,64 @@ +#coding:utf-8 +# +# id: bugs.core_2872 +# title: EVL_expr: invalid operation (232) +# decription: +# Confirmed on WI-V2.5.0.26074 and 2.5.7.27027, got: +# === +# Statement failed, SQLSTATE = XX000 +# internal Firebird consistency check (EVL_expr: invalid operation (232), file: evl.cpp line: 1207) +# After line 2 in file c2872.sql +# Statement failed, SQLSTATE = XX000 +# internal Firebird consistency check (can't continue after bugcheck) +# === +# +# tracker_id: CORE-2872 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + select 1 as i + from rdb$database + where count(*) >= all (select count(*) from rdb$database) + ; + select 1 as k + from rdb$database + where count(*) = (select count(*) from rdb$database) + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Cannot use an aggregate or window function in a WHERE clause, use HAVING (for aggregate only) instead + """ + +@pytest.mark.version('>=3.0') +def test_core_2872_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2875.py b/tests/bugs/test_core_2875.py new file mode 100644 index 00000000..895c2c47 --- /dev/null +++ b/tests/bugs/test_core_2875.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: bugs.core_2875 +# title: String right truncation error when char column longer than 4096 bytes compared with string constant +# decription: +# tracker_id: CORE-2875 +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """ + create table tab1 (id int, txt varchar(5000) character set none); + commit; + insert into tab1 values (1, rpad('', 5000, '1')); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + update tab1 set id = 2 where txt = _win1251 'x'; + commit; + set list on; + select id, txt from tab1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + TXT 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 + """ + +@pytest.mark.version('>=2.5.0') +def test_core_2875_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2879.py b/tests/bugs/test_core_2879.py new file mode 100644 index 00000000..9ad54526 --- /dev/null +++ b/tests/bugs/test_core_2879.py @@ -0,0 +1,219 @@ +#coding:utf-8 +# +# id: bugs.core_2879 +# title: Sweep could raise error : page 0 is of wrong type (expected 6, found 1) +# decription: +# Test receives content of firebird.log _before_ and _after_ running query that is show in the ticket. +# Then we compare these two files. +# Difference between them should relate ONLY to sweep start and finish details, and NOT about page wrong type. +# +# Checked on: WI-V2.5.7.27024, WI-V3.0.1.32570, WI-T4.0.0.316 -- all works OK. +# Refactored 01.02.2020, checked on: +# 4.0.0.1759 SS: 4.754s. +# 3.0.6.33240 SS: 3.704s. +# 2.5.9.27119 SS: 6.607s. +# +# tracker_id: CORE-2879 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [('\t+', ' '), ('^((?!start|finish|expected|page|wrong).)*$', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# from subprocess import Popen +# import difflib +# import time +# import datetime +# from datetime import datetime +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# engine = str(db_conn.engine_version) +# db_file = db_conn.database_name # "$(DATABASE_LOCATION)bugs.core_2879.fdb" +# +# db_conn.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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# +# #-------------------------------------------- +# +# def svc_get_fb_log( engine, f_fb_log ): +# +# global subprocess +# +# if engine.startswith('2.5'): +# get_firebird_log_key='action_get_ib_log' +# else: +# get_firebird_log_key='action_get_fb_log' +# +# subprocess.call([ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# get_firebird_log_key +# ], +# stdout=f_fb_log, +# stderr=subprocess.STDOUT +# ) +# +# return +# +# #----------------------------------------------------- +# +# sql_ddl=''' set list on; +# set term ^; +# execute block returns (dts timestamp, sql varchar(80)) as +# declare i int; +# declare s varchar(256); +# begin +# i = 1; +# while (i < 32767) do +# begin +# s = 'tmp' || :i; +# dts = 'now'; +# sql = 'create global temporary table ' || :s || ' (id int);'; +# execute statement sql with autonomous transaction; +# suspend; +# +# dts = 'now'; +# sql = 'drop table ' || :s || ';'; +# execute statement sql with autonomous transaction; +# suspend; +# +# i = i + 1; +# end +# end ^ +# set term ;^ +# ''' +# +# f_isql_cmd=open( os.path.join(context['temp_directory'],'tmp_make_lot_GTT_2879.sql'), 'w', buffering = 0) +# f_isql_cmd.write(sql_ddl) +# f_isql_cmd.close() +# +# # Get content of firebird.log BEFORE test: +# ########################################## +# +# f_fblog_before=open( os.path.join(context['temp_directory'],'tmp_2879_fblog_before.txt'), 'w', buffering = 0) +# svc_get_fb_log( engine, f_fblog_before ) +# flush_and_close( f_fblog_before ) +# +# # LAUNCH ISQL ASYNCHRONOUSLY +# ############################ +# +# f_isql_log=open( os.path.join(context['temp_directory'],'tmp_make_lot_GTT_2879.log'), 'w', buffering = 0) +# p_isql=subprocess.Popen( [context['isql_path'], dsn, "-i", f_isql_cmd.name], +# stdout=f_isql_log, +# stderr=subprocess.STDOUT +# ) +# #------------ +# time.sleep(2) +# #------------ +# +# # LAUNCH SWEEP while ISQL is working: +# # ############ +# fbsvc_log=open( os.path.join(context['temp_directory'],'tmp_svc_2879.log'), 'w', buffering = 0) +# subprocess.call( [ context['fbsvcmgr_path'],"localhost:service_mgr", "action_repair", "dbname", db_file, "rpr_sweep_db"], stdout=fbsvc_log, stderr=subprocess.STDOUT ) +# flush_and_close( fbsvc_log ) +# +# p_isql.terminate() +# f_isql_log.close() +# +# +# # Get content of firebird.log AFTER test: +# ######################################### +# +# f_fblog_after=open( os.path.join(context['temp_directory'],'tmp_2879_fblog_after.txt'), 'w', buffering = 0) +# svc_get_fb_log( engine, f_fblog_after ) +# flush_and_close( f_fblog_after ) +# +# # 07.08.2016 +# # DIFFERENCE in the content of firebird.log should be EMPTY: +# #################### +# +# oldfb=open(f_fblog_before.name, 'r') +# newfb=open(f_fblog_after.name, 'r') +# +# difftext = ''.join(difflib.unified_diff( +# oldfb.readlines(), +# newfb.readlines() +# )) +# oldfb.close() +# newfb.close() +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_2879_diff.txt'), 'w', buffering = 0) +# f_diff_txt.write(difftext) +# flush_and_close( f_diff_txt ) +# +# # NB: difflib.unified_diff() can show line(s) that present in both files, without marking that line(s) with "+". +# # Usually these are 1-2 lines that placed just BEFORE difference starts. +# # So we have to check output before display diff content: lines that are really differ must start with "+". +# +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# if line.startswith('+') and line.split('+'): +# print(line.replace('+',' ')) +# +# # 01.02.2020. 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']) +# +# +# +# # Cleanup: +# ########## +# time.sleep(1) +# cleanup( [i.name for i in (f_isql_cmd, f_isql_log, fbsvc_log, f_fblog_before,f_fblog_after, f_diff_txt)] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Sweep is started by SYSDBA + Sweep is finished + """ + +@pytest.mark.version('>=2.5.1') +@pytest.mark.xfail +def test_core_2879_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2881.py b/tests/bugs/test_core_2881.py new file mode 100644 index 00000000..a3caee06 --- /dev/null +++ b/tests/bugs/test_core_2881.py @@ -0,0 +1,123 @@ +#coding:utf-8 +# +# id: bugs.core_2881 +# title: isql should show packaged procedures and functions categorized per package +# decription: +# tracker_id: CORE-2881 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + 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 + begin + return 22*x; + end + procedure p(x int) returns(y int) as + begin + y = 33*x; + suspend; + 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 + begin + return 222*x; + end + procedure p(x int) returns(y int) as + begin + y = 333*x; + suspend; + end + end + ^ + set term ;^ + commit; + + show package p1; + show package p2; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + P1 + Header source: + begin + function f(x int) returns int; + procedure p(x int) returns(y int); + end + + 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: + 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 + """ + +@pytest.mark.version('>=3.0') +def test_core_2881_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2886.py b/tests/bugs/test_core_2886.py new file mode 100644 index 00000000..5931b3f9 --- /dev/null +++ b/tests/bugs/test_core_2886.py @@ -0,0 +1,52 @@ +#coding:utf-8 +# +# id: bugs.core_2886 +# title: Query with "NOT IN " fails +# decription: +# tracker_id: CORE-2886 +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE T (ID INTEGER NOT NULL); + +CREATE VIEW V( ID) AS select ID from T; + +INSERT INTO T (ID) VALUES (1); +INSERT INTO T (ID) VALUES (2); +INSERT INTO T (ID) VALUES (3); + +COMMIT; +""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT ID FROM T +WHERE ID NOT IN + (SELECT ID FROM V WHERE ID = 1); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID +============ + 2 + 3 + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_2886_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2888.py b/tests/bugs/test_core_2888.py new file mode 100644 index 00000000..011243b8 --- /dev/null +++ b/tests/bugs/test_core_2888.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: bugs.core_2888 +# title: A memory corruption cause incorrect query evaluation and may crash the server +# decription: +# tracker_id: CORE-2888 +# min_versions: ['2.1.4'] +# versions: 2.1.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select 1 from rdb$database where 1 in (select (select current_connection from rdb$database) from rdb$database); +select 1 from rdb$database where 1 in (select (select 1 from rdb$database) from rdb$database); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Database: localhost:C: btest2 mpugs.core_2888.fdb, User: SYSDBA +SQL> SQL> + CONSTANT +============ + 1 + +SQL>""" + +@pytest.mark.version('>=2.1.4') +def test_core_2888_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2890.py b/tests/bugs/test_core_2890.py new file mode 100644 index 00000000..728e812e --- /dev/null +++ b/tests/bugs/test_core_2890.py @@ -0,0 +1,99 @@ +#coding:utf-8 +# +# id: bugs.core_2890 +# title: SQLSTATE should also be available as a PSQL context variable like GDSCODE/SQLCODE +# decription: +# ::: NOTE ::: +# Despite of ticket's issue that it was fixed to 2.5.1, test script from here will output +# NOT ALL rows in WI-V2.5.1.26351 (official 2.5.1 release): +# +# RES_SQLCODE -901 +# RES_GDSCODE 335544345 +# RES_SQLSTATE 40001 +# +# RES_SQLCODE -802 +# RES_GDSCODE 335544321 +# RES_SQLSTATE 22012 +# +# These data: +# RES_SQLCODE -803 +# RES_GDSCODE 335544665 +# RES_SQLSTATE 23000 +# -- will not be displayed. +# For this reason it was decided to specify min_version = 2.5.2 rather than 2.5.1 +# +# tracker_id: CORE-2890 +# min_versions: ['2.5.2'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core2890.fbk', init=init_script_1) + +test_script_1 = """ + commit; + set transaction no wait; + + update test set id = -id where id = 2; + + set list on; + + set term ^; + execute block returns(res_sqlcode int, res_gdscode int, res_sqlstate char(5)) as + begin + for + select res_sqlcode, res_gdscode, res_sqlstate + from sp_test('I') + into res_sqlcode, res_gdscode, res_sqlstate + do + suspend; + ------------------------------------- + for + select res_sqlcode, res_gdscode, res_sqlstate + from sp_test('D') + into res_sqlcode, res_gdscode, res_sqlstate + do + suspend; + ------------------------------------- + for + select res_sqlcode, res_gdscode, res_sqlstate + from sp_test('U') + into res_sqlcode, res_gdscode, res_sqlstate + do + suspend; + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RES_SQLCODE -803 + RES_GDSCODE 335544665 + RES_SQLSTATE 23000 + + RES_SQLCODE -913 + RES_GDSCODE 335544336 + RES_SQLSTATE 40001 + + RES_SQLCODE -802 + RES_GDSCODE 335544321 + RES_SQLSTATE 22012 + """ + +@pytest.mark.version('>=3.0') +def test_core_2890_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2893.py b/tests/bugs/test_core_2893.py new file mode 100644 index 00000000..b1f48773 --- /dev/null +++ b/tests/bugs/test_core_2893.py @@ -0,0 +1,109 @@ +#coding:utf-8 +# +# id: bugs.core_2893 +# title: Expression in a subquery may be treated as invariant and produce incorrect results +# decription: +# Confirmed wrong resultset on 2.1.2.18118. +# Added sample from core-3031. +# +# tracker_id: CORE-2893 +# min_versions: ['2.5.7'] +# versions: 2.5.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table test_z (c varchar(10)); + commit; + + insert into test_z values (1); + insert into test_z values (1); + insert into test_z values (2); + insert into test_z values (3); + commit; + + -- From CORE-3031: + create view v_test (f1, f2, f3) as + select '1.1', '1.2', '1.3' from rdb$database + union all + select '2.1', '2.2', '2.3' from rdb$database + union all + select '3.1', '3.2', '3.3' from rdb$database + ; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set count on; + set list on; + + select 'Test-1' as msg, t.* + from ( + select (select case when R.RDB$Relation_ID = 0 then 0 else 1 end from RDB$Database) TypeID + from RDB$Relations R + where R.RDB$Relation_ID < 2 + ) t; + + select 'Test-2' as msg, z.c + from test_z z + where + ( + select z.c || '' from rdb$database + ) = '1' + ; + commit; + + -- From CORE-3031: + select 'Test-3' as msg, t.* + from ( + select + t.f1 || '; ' || t.f2 || '; ' || t.f3 as f123_concat, + ( + select + '' || t.f3 + from rdb$database + ) as f3_concat + from v_test t + ) t; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG Test-1 + TYPEID 0 + MSG Test-1 + TYPEID 1 + Records affected: 2 + MSG Test-2 + C 1 + MSG Test-2 + C 1 + Records affected: 2 + MSG Test-3 + F123_CONCAT 1.1; 1.2; 1.3 + F3_CONCAT 1.3 + MSG Test-3 + F123_CONCAT 2.1; 2.2; 2.3 + F3_CONCAT 2.3 + MSG Test-3 + F123_CONCAT 3.1; 3.2; 3.3 + F3_CONCAT 3.3 + Records affected: 3 + """ + +@pytest.mark.version('>=2.5.7') +def test_core_2893_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2907.py b/tests/bugs/test_core_2907.py new file mode 100644 index 00000000..ccbe2e0d --- /dev/null +++ b/tests/bugs/test_core_2907.py @@ -0,0 +1,85 @@ +#coding:utf-8 +# +# id: bugs.core_2907 +# title: Unable to catch exceptions that are thrown inside a dynamic builded execute block. +# decription: +# tracker_id: CORE-2907 +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE OR ALTER EXCEPTION EX_TEST 'test'; + +SET TERM ^ ; +CREATE OR ALTER procedure sp_1 +as +declare variable v_stmt varchar(256); +begin + + v_stmt = 'execute block as '|| + 'begin '|| + ' exception ex_test; '|| + 'end'; + execute statement v_stmt; + +end +^ +SET TERM ; ^ + + + +SET TERM ^ ; +CREATE OR ALTER procedure sp_2 +as +begin + begin + execute procedure sp_1; + + when exception ex_test do + begin + exit; + end + end +end +^ +SET TERM ; ^ + +SET TERM ^ ; +CREATE OR ALTER procedure sp_3 +as +begin + begin + execute procedure sp_1; + when any do + begin + exit; + end + end +end +^ +SET TERM ; ^ +commit; + +""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """EXECUTE PROCEDURE SP_2; +EXECUTE PROCEDURE SP_3; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.0') +def test_core_2907_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_2910.py b/tests/bugs/test_core_2910.py new file mode 100644 index 00000000..37a87703 --- /dev/null +++ b/tests/bugs/test_core_2910.py @@ -0,0 +1,56 @@ +#coding:utf-8 +# +# id: bugs.core_2910 +# title: PK index is not used for derived tables +# decription: +# tracker_id: CORE-2910 +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """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_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +PLAN JOIN (R R$TMP NATURAL, T TMP INDEX (PK_TMP)) +""" + +@pytest.mark.version('>=2.5.0') +def test_core_2910_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2912.py b/tests/bugs/test_core_2912.py new file mode 100644 index 00000000..c8370be1 --- /dev/null +++ b/tests/bugs/test_core_2912.py @@ -0,0 +1,163 @@ +#coding:utf-8 +# +# id: bugs.core_2912 +# title: Exception when upper casing string with lowercase y trema (code 0xFF in ISO8859_1 ) +# decription: +# 02-mar-2021. Re-implemented in order to have ability to run this test on Linux. +# Ttest 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. +# +# Checked on: +# * Windows: 4.0.0.2377, 3.0.8.33420, 2.5.9.27152 +# * Linux: 4.0.0.2377, 3.0.8.33415 +# +# tracker_id: CORE-2912 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + 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_1 = db_factory(charset='ISO8859_1', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import codecs +# import subprocess +# import time +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql_txt=''' set names ISO8859_1; +# connect '%(dsn)s' user '%(user_name)s' password '%(user_password)s'; +# 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ÿ'); +# ''' % dict(globals(), **locals()) +# +# f_run_sql = open( os.path.join(context['temp_directory'], 'tmp_2912_iso8859_1.sql'), 'w' ) +# f_run_sql.write( sql_txt.decode('utf8').encode('iso-8859-1') ) +# flush_and_close( f_run_sql ) +# # result: file tmp_2912_iso8859_1.sql is encoded in iso8859_1 (aka 'latin-1') +# +# f_run_log = open( os.path.splitext(f_run_sql.name)[0]+'.log', 'w') +# f_run_err = open( os.path.splitext(f_run_sql.name)[0]+'.err', 'w') +# subprocess.call( [ context['isql_path'], '-q', '-i', f_run_sql.name ], +# stdout = f_run_log, +# stderr = f_run_err +# ) +# flush_and_close( f_run_log ) +# flush_and_close( f_run_err ) +# +# # result: output will be encoded in iso9959_1, error log must be empty. +# with codecs.open(f_run_log.name, 'r', encoding='iso-8859-1' ) as f: +# stdout_encoded_in_latin_1 = f.readlines() +# +# with codecs.open(f_run_err.name, 'r', encoding='iso-8859-1' ) as f: +# stderr_encoded_in_latin_1 = f.readlines() +# +# for i in stdout_encoded_in_latin_1: +# print( i.encode('utf8') ) +# +# # NO error must occur: +# ###################### +# for i in stderr_encoded_in_latin_1: +# print( 'UNEXPECTED STDERR: ', i.encode('utf8') ) +# +# # cleanup: +# ########### +# cleanup( (f_run_sql, f_run_log, f_run_err) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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.version('>=2.5.3') +@pytest.mark.xfail +def test_core_2912_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2913.py b/tests/bugs/test_core_2913.py new file mode 100644 index 00000000..d9237db9 --- /dev/null +++ b/tests/bugs/test_core_2913.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: bugs.core_2913 +# title: COLLATE expressions are applied incorrectly +# decription: +# tracker_id: CORE-2913 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select cast(_dos850 'X' as char(1) character set iso8859_1) collate iso8859_1 as x from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + X X + """ + +@pytest.mark.version('>=3.0') +def test_core_2913_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2916.py b/tests/bugs/test_core_2916.py new file mode 100644 index 00000000..b24ef2b3 --- /dev/null +++ b/tests/bugs/test_core_2916.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: bugs.core_2916 +# title: Broken error handling in the case of a conversion error happened during index creation +# decription: +# tracker_id: CORE-2916 +# min_versions: ['2.1.4'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table tab (col date); + insert into tab (col) values ( date '29.02.2004' ); + 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22018 + Expression evaluation error for index "***unknown***" on table "TAB" + -conversion error from string "2004-02-29" + Statement failed, SQLSTATE = 22018 + conversion error from string "2004-02-29" + """ + +@pytest.mark.version('>=4.0') +def test_core_2916_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_2920.py b/tests/bugs/test_core_2920.py new file mode 100644 index 00000000..84522499 --- /dev/null +++ b/tests/bugs/test_core_2920.py @@ -0,0 +1,72 @@ +#coding:utf-8 +# +# id: bugs.core_2920 +# title: Incorrect execution of volatile SQL statements inside EXECUTE STATEMENT +# decription: +# tracker_id: CORE-2920 +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table bugtest (id int); +insert into bugtest (id) values (123); +set term !!; +create procedure p_bugtest (in_id int) + returns (cnt int) +as + declare predicate varchar(1000); +begin + if (:in_id is null) then + predicate = ' ? is null'; + else + predicate = ' id = ?'; + + execute statement ('select count(*) from bugtest where' || predicate) (:in_id) + into :cnt; +end!! +set term !!; +commit;""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """execute procedure p_bugtest (123); +-- cnt = 1 +execute procedure p_bugtest (null); +-- cnt = 1 +execute procedure p_bugtest (123); +-- cnt = 1 +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CNT +============ + 1 + + + CNT +============ + 1 + + + CNT +============ + 1 + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_2920_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2922.py b/tests/bugs/test_core_2922.py new file mode 100644 index 00000000..5492fdad --- /dev/null +++ b/tests/bugs/test_core_2922.py @@ -0,0 +1,71 @@ +#coding:utf-8 +# +# id: bugs.core_2922 +# title: Character set used in constants is not registered as dependency +# decription: +# tracker_id: CORE-2922 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create or alter procedure p1 as + declare variable a varchar(10) character set win1250; + begin + rdb$set_context('user_session', 'x', :a); + end + ^ + create or alter procedure p2 as + begin + post_event _win1250'abc'; + end + ^ + set term ;^ + commit; + + -- show proc; + set width dep_nm 10; + set width dep_on 10; + set width dep_on_type 20; + set list on; + + select rd.rdb$dependent_name dep_name, rd.rdb$depended_on_name dep_on,rt.rdb$type_name dep_on_type + from rdb$dependencies rd + join rdb$types rt on + rd.rdb$depended_on_type = rt.rdb$type + and rt.rdb$type_name containing upper('COLLATION') + order by 1; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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') +def test_core_2922_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2923.py b/tests/bugs/test_core_2923.py new file mode 100644 index 00000000..1aaa96d3 --- /dev/null +++ b/tests/bugs/test_core_2923.py @@ -0,0 +1,111 @@ +#coding:utf-8 +# +# id: bugs.core_2923 +# title: Problem with dependencies between a procedure and a view using that procedure +# decription: +# tracker_id: CORE-2923 +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create procedure sp_test returns (i smallint) as + begin + i = 32767; + suspend; + end + ^ + + create view v0 as + select i + from sp_test + ^ + + alter procedure sp_test returns (i int) as + begin + i = 32768; + suspend; + end + ^ + set term ;^ + commit; + + --- + + create table t1 (n1 smallint); + + insert into t1(n1) values(32767); + commit; + + create view v1 as + select * + from t1; + + alter table t1 alter n1 type integer; + commit; + + insert into t1(n1) values(32768); + commit; + + --- + + create table t2 (n2 smallint); + + insert into t2(n2) values(32767); + commit; + + create domain d2 integer; + + create view v2 as + select * from t2; + + alter table t2 alter n2 type d2; + + insert into t2(n2) values(32768); + commit; + + --- + + set list on; + select '0' as test_no, v.* from v0 v + union all + select '1', v.* from v1 v + union all + select '2', v.* from v2 v + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TEST_NO 0 + I 32768 + TEST_NO 1 + I 32767 + TEST_NO 1 + I 32768 + TEST_NO 2 + I 32767 + TEST_NO 2 + I 32768 + """ + +@pytest.mark.version('>=3.0') +def test_core_2923_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2929.py b/tests/bugs/test_core_2929.py new file mode 100644 index 00000000..8d78a845 --- /dev/null +++ b/tests/bugs/test_core_2929.py @@ -0,0 +1,74 @@ +#coding:utf-8 +# +# id: bugs.core_2929 +# title: "Invalid ESCAPE sequence" when connecting to the database +# decription: +# tracker_id: CORE-2929 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set wng off; + set list on; + + recreate table t(id int, who_am_i varchar(31) default current_user, whats_my_role varchar(31) default current_role); + commit; + insert into t(id) values(0); + commit; + + create user "#" password '#'; + create role "##"; + commit; + + grant "##" to "#"; + commit; + + grant select, insert, update, delete on t to role "##"; + commit; + + connect '$(DSN)' user "#" password '#' role "##"; + insert into t(id) values(1); + insert into t(id) values(2); + update t set id = -id where id = 1; + delete from t where id = 0; + + select * from t order by id; + commit; + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + drop role "##"; + drop user "#"; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID -1 + WHO_AM_I # + WHATS_MY_ROLE ## + + ID 2 + WHO_AM_I # + WHATS_MY_ROLE ## + """ + +@pytest.mark.version('>=2.5') +def test_core_2929_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2930.py b/tests/bugs/test_core_2930.py new file mode 100644 index 00000000..8fc1b524 --- /dev/null +++ b/tests/bugs/test_core_2930.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_2930 +# title: DROP VIEW drops output parameters of used stored procedures +# decription: +# tracker_id: CORE-2930 +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """set term !; +create procedure p1 returns (n integer) as begin suspend; end! +create view v1 as select * from p1! +commit! +set term ;! +""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """show procedure p1; +drop view v1; +show procedure p1; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Procedure text: +============================================================================= + begin suspend; end +============================================================================= +Parameters: +N OUTPUT INTEGER +Procedure text: +============================================================================= + begin suspend; end +============================================================================= +Parameters: +N OUTPUT INTEGER +""" + +@pytest.mark.version('>=2.5.0') +def test_core_2930_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2932.py b/tests/bugs/test_core_2932.py new file mode 100644 index 00000000..5477c331 --- /dev/null +++ b/tests/bugs/test_core_2932.py @@ -0,0 +1,150 @@ +#coding:utf-8 +# +# id: bugs.core_2932 +# title: Wrong field position after ALTER POSITION +# decription: +# tracker_id: CORE-2932 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """ + create or alter view v_pos as select 1 id from rdb$database; + commit; + + recreate table test( + f01 int + ,f02 int + ,f03 int + ,f04 int + ,f05 int + ,f06 int + ,f07 int + ,f08 int + ,f09 int + ,f10 int + ); + commit; + + create or alter view v_pos as + -- NB: do NOT use direct values of rdb$field_position, they can on some phase + -- go with step more than 1 (i.e. not monotonically increased with step = 1). + -- Use dense_rank()over() instead: + select + cast( dense_rank()over(order by rf.rdb$field_position) as smallint ) fld_rnk + ,rf.rdb$field_name fld_name + from rdb$relation_fields rf + where rf.rdb$relation_name = 'TEST' + order by fld_rnk; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set width msg 6; + set width fld_rnk 7; + set width fld_name 8; + select 'step-1' msg, v.* from v_pos v; + + alter table test drop f01, drop f02, drop f03, drop f04; + commit; + + alter table test alter f10 position 3; + -- after this DDL must be: f05 f06 f10 f07 f08 f09 + commit; + + select 'step-2' msg, v.* from v_pos v; + + alter table test add n01 int, add n02 int, add n03 int, add n04 int, add n05 int, add n06 int; + commit; + + alter table test drop n01, drop n02, drop n03, drop n04; + -- after this DDL must be: f05 f06 f10 f07 f08 f09 n05 n06 + -- 1 2 3 4 5 6 7 8 + commit; + + select 'step-3' msg, v.* from v_pos v; + + + -- Result of this statement "alter table test alter f10 position 7, alter n06 position 3" + -- can be easy understanded if we split it on subsequent ones: + -- 1) alter table test alter f10 position 7; + -- ==> should give: + -- f05 f06 f07 f08 f09 n05 f10 n06 + -- 1 2 3 4 5 6 7 8 + -- 2) alter table test alter n06 position 3; + -- ==> should give: + -- f05 f06 n06 f07 f08 f09 n05 f10 + -- 1 2 3 4 5 6 7 8 + alter table test alter f10 position 7, alter n06 position 3; + -- alter table test alter f05 position 8; + commit; + + select 'step-4' msg, v.* from v_pos v; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG FLD_RNK FLD_NAME + ====== ======= ======== + step-1 1 F01 + step-1 2 F02 + step-1 3 F03 + step-1 4 F04 + step-1 5 F05 + step-1 6 F06 + step-1 7 F07 + step-1 8 F08 + step-1 9 F09 + step-1 10 F10 + + + MSG FLD_RNK FLD_NAME + ====== ======= ======== + step-2 1 F05 + step-2 2 F06 + step-2 3 F10 + step-2 4 F07 + step-2 5 F08 + step-2 6 F09 + + + MSG FLD_RNK FLD_NAME + ====== ======= ======== + step-3 1 F05 + step-3 2 F06 + step-3 3 F10 + step-3 4 F07 + step-3 5 F08 + step-3 6 F09 + step-3 7 N05 + step-3 8 N06 + + + MSG FLD_RNK FLD_NAME + ====== ======= ======== + step-4 1 F05 + step-4 2 F06 + step-4 3 N06 + step-4 4 F07 + step-4 5 F08 + step-4 6 F09 + step-4 7 N05 + step-4 8 F10 + """ + +@pytest.mark.version('>=3.0') +def test_core_2932_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2940.py b/tests/bugs/test_core_2940.py new file mode 100644 index 00000000..cb499daf --- /dev/null +++ b/tests/bugs/test_core_2940.py @@ -0,0 +1,251 @@ +#coding:utf-8 +# +# id: bugs.core_2940 +# title: Trace output could contain garbage data left from filtered out statements +# decription: +# 1. Obtain engine_version from built-in context variable. +# 2. Make config for trace in proper format according to FB engine version, with 'exclude_filter' parameter from ticket. +# 3. Launch trace session in separate child process using 'FBSVCMGR action_trace_start' +# 4. Run ISQL with test commands. Only one of these command does not contain token that is specified in 'exclude_filter' +# 5. Stop trace session. Output its log with filtering only statistics info. +# +# Checked on: WI-V2.5.5.26916 (SS, SC, CS); WI-V3.0.0.32008 (SS, SC, CS). Result: OK. +# Checked on: 3.0.1.32525, 4.0.0.238 // 07-jun-2016 +# ::: NB ::: +# Several delays (time.sleep) added in main thread because of OS buffering. Couldn't switch this buffering off. +# +# +# ::: NB ::: 07-jun-2016. +# +# WI-T4.0.0.238 will issue in trace log following statement with its statistics ("1 records fetched"): +# === +# with recursive role_tree as ( +# select rdb$relation_name as nm, 0 as ur from rdb$user_privileges +# where +# rdb$privilege = 'M' and rdb$field_name = 'D' +# and rdb$user = ? and rdb$user_type = 8 +# union all +# select rdb$role_name as nm, 1 as ur from rdb$roles +# where rdb$role_name =... +# +# param0 = varchar(93), "SYSDBA" +# param1 = varchar(93), "NONE" +# === +# We have to SKIP this statement statistics and start to check only "our" selects from rdb$database +# see usage of first_sttm_pattern and trace_stat_pattern. +# +# tracker_id: CORE-2940 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('^((?!records fetched).)*$', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import subprocess +# from subprocess import Popen +# import time +# import re +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# engine=str(db_conn.engine_version) +# db_conn.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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# +# #-------------------------------------------- +# +# +# txt25 = '''# Trace config, format for 2.5. Generated auto, do not edit! +# +# enabled true +# #include_filter +# exclude_filter %no_trace% +# log_connections true +# log_transactions true +# log_statement_finish true +# print_plan true +# print_perf true +# time_threshold 0 +# +# ''' +# +# # NOTES ABOUT TRACE CONFIG FOR 3.0: +# # 1) Header contains `database` clause in different format vs FB 2.5: its data must be enclosed with '{' '}' +# # 2) Name and value must be separated by EQUALITY sign ('=') in FB-3 trace.conf, otherwise we get runtime error: +# # element "<. . .>" have no attribute value set +# +# txt30 = '''# Trace config, format for 3.0. Generated auto, do not edit! +# database=%[\\\\\\\\/]bugs.core_2940.fdb +# { +# enabled = true +# #include_filter +# exclude_filter = %no_trace% +# log_connections = true +# log_transactions = true +# log_statement_finish = true +# print_plan = true +# print_perf = true +# time_threshold = 0 +# } +# ''' +# trccfg=open( os.path.join(context['temp_directory'],'tmp_trace_2940.cfg'), 'w') +# if engine.startswith('2.5'): +# trccfg.write(txt25) +# else: +# trccfg.write(txt30) +# trccfg.close() +# +# trclog=open( os.path.join(context['temp_directory'],'tmp_trace_2940.log'), 'w') +# trclog.close() +# trclst=open( os.path.join(context['temp_directory'],'tmp_trace_2940.lst'), 'w') +# trclst.close() +# +# ##################################################### +# # Starting trace session in new child process (async.): +# +# f_trclog=open(trclog.name,'w') +# # Execute a child program in a new process, redirecting STDERR to the same target as of STDOUT: +# p_trace=Popen([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_start", +# "trc_cfg", trccfg.name], +# stdout=f_trclog, stderr=subprocess.STDOUT) +# +# # Wait! Trace session is initialized not instantly! +# time.sleep(1) +# +# ##################################################### +# # Running ISQL with test commands: +# +# sqltxt=''' +# set list on; +# -- statistics for this statement SHOULD appear in trace log: +# select 1 k1 from rdb$database; +# commit; +# +# -- statistics for this statement should NOT appear in trace log: +# select 2 k2 from rdb$types rows 2 /* no_trace*/; +# +# -- statistics for this statement should NOT appear in trace log: +# select 3 no_trace from rdb$types rows 3; +# +# -- statistics for this statement should NOT appear in trace log: +# set term ^; +# execute block returns(k4 int) as +# begin +# for select 4 from rdb$types rows 4 into k4 do suspend; +# end -- no_trace +# ^ +# set term ;^ +# ''' +# +# runProgram('isql',[dsn,'-n'],sqltxt) +# +# # do NOT remove this otherwise trace log can contain only message about its start before being closed! +# time.sleep(3) +# +# ##################################################### +# # Getting ID of launched trace session and STOP it: +# +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# f_trclst=open(trclst.name,'w') +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_list"], +# stdout=f_trclst, stderr=subprocess.STDOUT +# ) +# flush_and_close( f_trclst ) +# +# trcssn=0 +# with open( trclst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# f_trclst=open(trclst.name,'a') +# f_trclst.seek(0,2) +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_stop", +# "trc_id",trcssn], +# stdout=f_trclst, stderr=subprocess.STDOUT +# ) +# flush_and_close( f_trclst ) +# +# # Terminate child process of launched trace session (though it should already be killed): +# p_trace.terminate() +# flush_and_close( f_trclog ) +# +# ##################################################### +# # Output log of trace session, with filtering only info about statistics ('fetches'): +# +# first_sttm_pattern=re.compile("select 1 k1") +# trace_stat_pattern=re.compile("1 records fetched") +# flag=0 +# with open( trclog.name,'r') as f: +# for line in f: +# if first_sttm_pattern.match(line): +# flag=1 +# if flag==1 and trace_stat_pattern.match(line): +# print(line) +# +# # Cleanup: +# ########## +# time.sleep(1) +# +# cleanup([i.name for i in (trccfg,trclst,trclog)]) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 1 records fetched + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_2940_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2943.py b/tests/bugs/test_core_2943.py new file mode 100644 index 00000000..6d23f900 --- /dev/null +++ b/tests/bugs/test_core_2943.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: bugs.core_2943 +# title: parsing error recursive query with two recursive parts +# decription: +# tracker_id: CORE-2943 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + with recursive + tree (NAME) as ( + select r.rdb$relation_name from rdb$relations r + union all + select r2.rdb$relation_name || tree.NAME from rdb$relations r2, tree + where 1 = 0 + ), + tree_2 as ( + select c.rdb$character_set_name from rdb$character_sets c + union all + select c2.rdb$character_set_name from rdb$character_sets c2, tree_2 + where 1 = 0 + ) + select * from tree, tree_2 where NAME=upper('RDB$PAGES') and RDB$CHARACTER_SET_NAME=upper('NONE'); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + NAME RDB$PAGES + RDB$CHARACTER_SET_NAME NONE + """ + +@pytest.mark.version('>=2.5') +def test_core_2943_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2952.py b/tests/bugs/test_core_2952.py new file mode 100644 index 00000000..2ccbde64 --- /dev/null +++ b/tests/bugs/test_core_2952.py @@ -0,0 +1,2284 @@ +#coding:utf-8 +# +# id: bugs.core_2952 +# title: Case-sensitive character class names in SIMILAR TO +# decription: +# tracker_id: CORE-2952 +# min_versions: ['3.0'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- NOTE: + -- 1. This test can NOT be applied on 2.5 because of error: + -- Statement failed, SQLSTATE = 42000 + -- Invalid SIMILAR TO pattern + -- 2. Seems that polish letter 'Ł' is NOT considered as having accent + set term ^; + execute block as + begin + begin + execute statement 'drop collation co_utf8_ci_ai'; + when any do begin end + end + + begin + execute statement 'drop collation co_utf8_cs_as'; + when any do begin end + end + + begin + execute statement 'drop collation co_utf8_ci_as'; + when any do begin end + end + end + ^ + set term ;^ + commit; + + create collation co_utf8_ci_ai for utf8 from unicode case insensitive accent insensitive; + create collation co_utf8_cs_as for utf8 from unicode case sensitive accent sensitive; + create collation co_utf8_ci_as for utf8 from unicode case insensitive accent sensitive; + commit; + + set list on; + + with recursive + d as ( + select cast('aeiouyAEIOUYáéíóúýàèìòùâêîôûãñõäëïöüÿçšąęźżăşţÁÉÍÓÚÝÀÈÌÒÙÂÊÎÔÛÃÑÕÄËÏÖÜŸÇŠĄĘŹŻĂŞŢ'||ascii_char(9)||ascii_char(10)||ascii_char(32) as varchar(100) character set utf8) s + from rdb$database + ) + ,r as(select 1 i from rdb$database union all select r.i+1 from r where r.i < 100) + ,e as( + select substring(d.s from r.i for 1) c + from d join r on r.i <= char_length(d.s) + ) + select + decode( e.c, ascii_char(9),' ', ascii_char(10),' ', ascii_char(32), '\\w', e.c ) c + -- ALPHA Latin letters a..z and A..Z. With an accent-insensitive collation, + -- this class also matches accented forms of these characters. + ,iif( e.c collate co_utf8_ci_ai similar to '[[:aLPHA:]]', 1, 0 ) s_alpha_ci_ai + ,iif( e.c collate co_utf8_cs_as similar to '[[:aLPHA:]]', 1, 0 ) s_alpha_cs_as + ,iif( e.c collate co_utf8_ci_as similar to '[[:aLPHA:]]', 1, 0 ) s_alpha_ci_as + -- [:LOWER:] Lowercase Latin letters a..z. Also matches uppercase with case-insensitive + -- collation and accented forms with accent-insensitive collation. + ,iif( e.c collate co_utf8_ci_ai similar to '[[:LoWer:]]', 1, 0 ) s_lower_ci_ai + ,iif( e.c collate co_utf8_cs_as similar to '[[:lOwEr:]]', 1, 0 ) s_lower_cs_as + ,iif( e.c collate co_utf8_ci_as similar to '[[:lowER:]]', 1, 0 ) s_lower_ci_as + -- [:UPPER:] Uppercase Latin letters A..Z. Also matches lowercase with case-insensitive + -- collation and accented forms with accent-insensitive collation. + ,iif( e.c collate co_utf8_ci_ai similar to '[[:uPPer:]]', 1, 0 ) s_upper_ci_ai + ,iif( e.c collate co_utf8_cs_as similar to '[[:uPpeR:]]', 1, 0 ) s_upper_cs_as + ,iif( e.c collate co_utf8_ci_as similar to '[[:UpPeR:]]', 1, 0 ) s_upper_ci_as + -- [:WHITESPACE:] Matches vertical tab (ASCII 9), linefeed (ASCII 10), horizontal + -- tab (ASCII 11), formfeed (ASCII 12), carriage return (ASCII 13) and space (ASCII 32). + ,iif( e.c similar to '[[:WhiTespacE:]]', 1, 0 ) s_white_space + from e + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + C a + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 1 + S_ALPHA_CI_AS 1 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 1 + S_LOWER_CI_AS 1 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 1 + S_WHITE_SPACE 0 + + C e + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 1 + S_ALPHA_CI_AS 1 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 1 + S_LOWER_CI_AS 1 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 1 + S_WHITE_SPACE 0 + + C i + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 1 + S_ALPHA_CI_AS 1 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 1 + S_LOWER_CI_AS 1 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 1 + S_WHITE_SPACE 0 + + C o + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 1 + S_ALPHA_CI_AS 1 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 1 + S_LOWER_CI_AS 1 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 1 + S_WHITE_SPACE 0 + + C u + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 1 + S_ALPHA_CI_AS 1 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 1 + S_LOWER_CI_AS 1 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 1 + S_WHITE_SPACE 0 + + C y + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 1 + S_ALPHA_CI_AS 1 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 1 + S_LOWER_CI_AS 1 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 1 + S_WHITE_SPACE 0 + + C A + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 1 + S_ALPHA_CI_AS 1 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 1 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 1 + S_UPPER_CI_AS 1 + S_WHITE_SPACE 0 + + C E + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 1 + S_ALPHA_CI_AS 1 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 1 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 1 + S_UPPER_CI_AS 1 + S_WHITE_SPACE 0 + + C I + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 1 + S_ALPHA_CI_AS 1 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 1 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 1 + S_UPPER_CI_AS 1 + S_WHITE_SPACE 0 + + C O + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 1 + S_ALPHA_CI_AS 1 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 1 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 1 + S_UPPER_CI_AS 1 + S_WHITE_SPACE 0 + + C U + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 1 + S_ALPHA_CI_AS 1 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 1 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 1 + S_UPPER_CI_AS 1 + S_WHITE_SPACE 0 + + C Y + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 1 + S_ALPHA_CI_AS 1 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 1 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 1 + S_UPPER_CI_AS 1 + S_WHITE_SPACE 0 + + C á + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C é + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C í + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ó + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ú + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ý + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C à + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C è + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ì + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ò + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ù + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C â + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ê + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C î + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ô + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C û + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ã + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ñ + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C õ + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ä + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ë + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ï + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ö + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ü + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ÿ + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ç + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C š + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ą + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ę + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + + C ź + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ż + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ă + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ş + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ţ + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Á + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C É + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Í + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ó + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ú + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ý + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C À + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C È + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ì + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ò + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ù + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Â + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ê + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Î + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ô + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Û + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ã + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ñ + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Õ + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ä + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ë + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ï + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ö + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ü + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ÿ + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ç + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Š + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ą + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ę + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + + C Ź + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ż + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ă + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ş + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ţ + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C + S_ALPHA_CI_AI 0 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 0 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 0 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 1 + + C + S_ALPHA_CI_AI 0 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 0 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 0 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 1 + + C \\w + S_ALPHA_CI_AI 0 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 0 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 0 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 1 + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_core_2952_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_2) + +test_script_2 = """ + -- NOTE: + -- 1. This test can NOT be applied on 2.5 because of error: + -- Statement failed, SQLSTATE = 42000 + -- Invalid SIMILAR TO pattern + -- 2. Added four characters: 'Ø' 'Ð' 'Ł' and 'Ŀ' - because of fixed CORE-4739 + + set term ^; + execute block as + begin + begin + execute statement 'drop collation co_utf8_ci_ai'; + when any do begin end + end + + begin + execute statement 'drop collation co_utf8_cs_as'; + when any do begin end + end + + begin + execute statement 'drop collation co_utf8_ci_as'; + when any do begin end + end + end + ^ + set term ;^ + commit; + + create collation co_utf8_ci_ai for utf8 from unicode case insensitive accent insensitive; + create collation co_utf8_cs_as for utf8 from unicode case sensitive accent sensitive; + create collation co_utf8_ci_as for utf8 from unicode case insensitive accent sensitive; + commit; + + set list on; + + with recursive + d as ( + select cast('aeiouyAEIOUYáéíóúýàèìòùâêîôûãñõäëïöüÿçšąęźżăşţÁÉÍÓÚÝÀÈÌÒÙÂÊÎÔÛÃÑÕÄËÏÖÜŸÇŠĄĘŹŻĂŞŢ' + || ascii_char(9) || ascii_char(10) || ascii_char(32) + || 'øðłŀØÐŁĿ' -- added 14.10.2019 + as varchar(100) character set utf8 + ) s + from rdb$database + ) + ,r as(select 1 i from rdb$database union all select r.i+1 from r where r.i < 100) + ,e as( + select substring(d.s from r.i for 1) c + from d join r on r.i <= char_length(d.s) + ) + select + decode( e.c, ascii_char(9),' ', ascii_char(10),' ', ascii_char(32), '\\w', e.c ) c + -- ALPHA Latin letters a..z and A..Z. With an accent-insensitive collation, + -- this class also matches accented forms of these characters. + ,iif( e.c collate co_utf8_ci_ai similar to '[[:aLPHA:]]', 1, 0 ) s_alpha_ci_ai + ,iif( e.c collate co_utf8_cs_as similar to '[[:aLPHA:]]', 1, 0 ) s_alpha_cs_as + ,iif( e.c collate co_utf8_ci_as similar to '[[:aLPHA:]]', 1, 0 ) s_alpha_ci_as + -- [:LOWER:] Lowercase Latin letters a..z. Also matches uppercase with case-insensitive + -- collation and accented forms with accent-insensitive collation. + ,iif( e.c collate co_utf8_ci_ai similar to '[[:LoWer:]]', 1, 0 ) s_lower_ci_ai + ,iif( e.c collate co_utf8_cs_as similar to '[[:lOwEr:]]', 1, 0 ) s_lower_cs_as + ,iif( e.c collate co_utf8_ci_as similar to '[[:lowER:]]', 1, 0 ) s_lower_ci_as + -- [:UPPER:] Uppercase Latin letters A..Z. Also matches lowercase with case-insensitive + -- collation and accented forms with accent-insensitive collation. + ,iif( e.c collate co_utf8_ci_ai similar to '[[:uPPer:]]', 1, 0 ) s_upper_ci_ai + ,iif( e.c collate co_utf8_cs_as similar to '[[:uPpeR:]]', 1, 0 ) s_upper_cs_as + ,iif( e.c collate co_utf8_ci_as similar to '[[:UpPeR:]]', 1, 0 ) s_upper_ci_as + -- [:WHITESPACE:] Matches vertical tab (ASCII 9), linefeed (ASCII 10), horizontal + -- tab (ASCII 11), formfeed (ASCII 12), carriage return (ASCII 13) and space (ASCII 32). + ,iif( e.c similar to '[[:WhiTespacE:]]', 1, 0 ) s_white_space + from e + ; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + C a + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 1 + S_ALPHA_CI_AS 1 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 1 + S_LOWER_CI_AS 1 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 1 + S_WHITE_SPACE 0 + + C e + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 1 + S_ALPHA_CI_AS 1 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 1 + S_LOWER_CI_AS 1 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 1 + S_WHITE_SPACE 0 + + C i + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 1 + S_ALPHA_CI_AS 1 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 1 + S_LOWER_CI_AS 1 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 1 + S_WHITE_SPACE 0 + + C o + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 1 + S_ALPHA_CI_AS 1 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 1 + S_LOWER_CI_AS 1 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 1 + S_WHITE_SPACE 0 + + C u + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 1 + S_ALPHA_CI_AS 1 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 1 + S_LOWER_CI_AS 1 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 1 + S_WHITE_SPACE 0 + + C y + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 1 + S_ALPHA_CI_AS 1 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 1 + S_LOWER_CI_AS 1 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 1 + S_WHITE_SPACE 0 + + C A + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 1 + S_ALPHA_CI_AS 1 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 1 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 1 + S_UPPER_CI_AS 1 + S_WHITE_SPACE 0 + + C E + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 1 + S_ALPHA_CI_AS 1 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 1 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 1 + S_UPPER_CI_AS 1 + S_WHITE_SPACE 0 + + C I + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 1 + S_ALPHA_CI_AS 1 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 1 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 1 + S_UPPER_CI_AS 1 + S_WHITE_SPACE 0 + + C O + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 1 + S_ALPHA_CI_AS 1 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 1 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 1 + S_UPPER_CI_AS 1 + S_WHITE_SPACE 0 + + C U + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 1 + S_ALPHA_CI_AS 1 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 1 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 1 + S_UPPER_CI_AS 1 + S_WHITE_SPACE 0 + + C Y + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 1 + S_ALPHA_CI_AS 1 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 1 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 1 + S_UPPER_CI_AS 1 + S_WHITE_SPACE 0 + + C á + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C é + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C í + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ó + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ú + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ý + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C à + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C è + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ì + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ò + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ù + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C â + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ê + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C î + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ô + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C û + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ã + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ñ + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C õ + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ä + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ë + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ï + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ö + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ü + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ÿ + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ç + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C š + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ą + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ę + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ź + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ż + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ă + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ş + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ţ + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Á + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C É + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Í + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ó + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ú + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ý + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C À + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C È + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ì + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ò + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ù + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Â + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ê + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Î + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ô + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Û + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ã + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ñ + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Õ + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ä + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ë + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ï + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ö + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ü + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ÿ + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ç + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Š + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ą + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ę + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ź + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ż + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ă + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ş + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ţ + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C + S_ALPHA_CI_AI 0 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 0 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 0 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 1 + + C + S_ALPHA_CI_AI 0 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 0 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 0 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 1 + + C \\w + S_ALPHA_CI_AI 0 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 0 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 0 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 1 + + C ø + S_ALPHA_CI_AI 0 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 0 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 0 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ð + S_ALPHA_CI_AI 0 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 0 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 0 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ł + S_ALPHA_CI_AI 0 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 0 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 0 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C ŀ + S_ALPHA_CI_AI 0 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 0 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 0 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ø + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ð + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ł + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + + C Ŀ + S_ALPHA_CI_AI 1 + S_ALPHA_CS_AS 0 + S_ALPHA_CI_AS 0 + S_LOWER_CI_AI 1 + S_LOWER_CS_AS 0 + S_LOWER_CI_AS 0 + S_UPPER_CI_AI 1 + S_UPPER_CS_AS 0 + S_UPPER_CI_AS 0 + S_WHITE_SPACE 0 + """ + +@pytest.mark.version('>=4.0') +def test_core_2952_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/bugs/test_core_2957.py b/tests/bugs/test_core_2957.py new file mode 100644 index 00000000..ade1f0b8 --- /dev/null +++ b/tests/bugs/test_core_2957.py @@ -0,0 +1,146 @@ +#coding:utf-8 +# +# id: bugs.core_2957 +# title: count(*) from big table returns negative result +# decription: +# NB: in fact, this test must check data types in SQLDA for columns that are results of aggregated functions +# COUNT and (maybe) SUM. +# As of 2.5, COUNT(*) is still displayed as `LONG` (sql_len = 4 bytes ==> integer, max 2^32-1) rather than INT64. +# Test was made only for 3.0 (as it was said in the ticket header, "Fixed version(s)") and I've added here +# also check for results of aggregating (for smallint, int and bigint) and ranging analytical functions. +# +# 30.10.2019. Separated code for 4.0 because of new output types: +# ** sum() - its type is "32752 numeric(38)"; +# ** added new column: sum() - it will have type "32762 decfloat(34)". +# Checked on: 4.0.0.1635 SS: 1.236s; 3.0.5.33182 SS: 1.001s. +# 25.06.2020, 4.0.0.2076: changed types in SQLDA from numeric to int128 // after discuss with Alex about CORE-6342. +# +# tracker_id: CORE-2957 +# min_versions: ['3.0'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!sqltype).)*$', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table test(id bigint, fx int, fs smallint); + commit; + set sqlda_display; + set planonly; + + select + count( id ) cnt_agg + ,sum( id ) sum_agg_n64 + ,sum( fx ) sum_agg_n32 + ,sum( fs ) sum_agg_n16 + from test; + + select + count( id )over() cnt_ovr + ,sum( id )over() sum_ovr_n64 + ,sum( fx )over() sum_ovr_n32 + ,sum( fs )over() sum_ovr_n16 + + ,row_number()over() cnt_ovr_n64 + ,rank()over() rnk_ovr_n64 + ,dense_rank()over() drn_ovr_n64 + from test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 01: sqltype: 580 INT64 scale: 0 subtype: 0 len: 8 + 02: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + 03: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + 04: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + + 01: sqltype: 580 INT64 scale: 0 subtype: 0 len: 8 + 02: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + 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 scale: 0 subtype: 0 len: 8 + 06: sqltype: 580 INT64 scale: 0 subtype: 0 len: 8 + 07: sqltype: 580 INT64 scale: 0 subtype: 0 len: 8 + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_core_2957_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [('^((?!sqltype).)*$', ''), ('[ \t]+', ' ')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + recreate table test(id bigint, fx int, fs smallint, dx decfloat(34), ds decfloat(16) ); + commit; + set sqlda_display; + set planonly; + + select + count( id ) cnt_agg + ,sum( id ) sum_agg_n64 + ,sum( fx ) sum_agg_n32 + ,sum( fs ) sum_agg_n16 + ,sum( dx ) sum_agg_df34 + ,sum( ds ) sum_agg_df16 + from test; + + select + count( id )over() cnt_ovr + ,sum( id )over() sum_ovr_n64 + ,sum( fx )over() sum_ovr_n32 + ,sum( fs )over() sum_ovr_n16 + ,sum( dx )over() sum_ovr_df34 + ,sum( ds )over() sum_ovr_df16 + + ,row_number()over() cnt_ovr_n64 + ,rank()over() rnk_ovr_n64 + ,dense_rank()over() drn_ovr_n64 + from test; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + 01: sqltype: 580 INT64 scale: 0 subtype: 0 len: 8 + 02: sqltype: 32752 INT128 Nullable scale: 0 subtype: 0 len: 16 + 03: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + 04: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + 05: sqltype: 32762 DECFLOAT(34) Nullable scale: 0 subtype: 0 len: 16 + 06: sqltype: 32762 DECFLOAT(34) Nullable scale: 0 subtype: 0 len: 16 + 01: sqltype: 580 INT64 scale: 0 subtype: 0 len: 8 + 02: sqltype: 32752 INT128 Nullable scale: 0 subtype: 0 len: 16 + 03: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + 04: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + 05: sqltype: 32762 DECFLOAT(34) Nullable scale: 0 subtype: 0 len: 16 + 06: sqltype: 32762 DECFLOAT(34) Nullable scale: 0 subtype: 0 len: 16 + 07: sqltype: 580 INT64 scale: 0 subtype: 0 len: 8 + 08: sqltype: 580 INT64 scale: 0 subtype: 0 len: 8 + 09: sqltype: 580 INT64 scale: 0 subtype: 0 len: 8 + """ + +@pytest.mark.version('>=4.0') +def test_core_2957_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/bugs/test_core_2965.py b/tests/bugs/test_core_2965.py new file mode 100644 index 00000000..1583a6eb --- /dev/null +++ b/tests/bugs/test_core_2965.py @@ -0,0 +1,64 @@ +#coding:utf-8 +# +# id: bugs.core_2965 +# title: Incorrect ROW_COUNT value after SINGULAR condition +# decription: +# tracker_id: CORE-2965 +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """set term !!; +execute block +returns(rcount integer) +as +declare tmpint integer; +begin + select rdb$relation_id from rdb$database into tmpint; + if (SINGULAR(select rdb$relation_id from rdb$database where rdb$relation_id is null)) then begin end + rcount = row_count; + suspend; +end!! +execute block +returns(rcount integer) +as +declare tmpint integer; +begin + select rdb$relation_id from rdb$database into tmpint; + if (SINGULAR(select * from rdb$relation_fields)) then begin end + rcount = row_count; + suspend; +end!!""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RCOUNT +============ + 1 + + + RCOUNT +============ + 1 + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_2965_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2966.py b/tests/bugs/test_core_2966.py new file mode 100644 index 00000000..33f40569 --- /dev/null +++ b/tests/bugs/test_core_2966.py @@ -0,0 +1,78 @@ +#coding:utf-8 +# +# id: bugs.core_2966 +# title: Wrong results or unexpected errors while sorting a large data set +# decription: +# tracker_id: CORE-2966 +# min_versions: ['2.1.6', '2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """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_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select col from t group by 1; +select cast(col as integer) from t group by 1; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +COL +=============================================================================== +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 + + + CAST +============ + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_2966_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2969.py b/tests/bugs/test_core_2969.py new file mode 100644 index 00000000..623a2642 --- /dev/null +++ b/tests/bugs/test_core_2969.py @@ -0,0 +1,1220 @@ +#coding:utf-8 +# +# id: bugs.core_2969 +# title: rdb$set_context does NOT allow to overwrite any vars after encountering limit (default=1000) of them +# decription: +# tracker_id: CORE-2969 +# min_versions: ['2.1.4'] +# versions: 2.1.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """Set term !!; +execute block returns(was_overwritten int, ctx_key varchar(30), ctx_val char(3)) +as + declare variable k int; +begin + k = 0; + while (k < 1000) do + begin + ctx_key = 'var_' || k; + + was_overwritten=rdb$set_context('USER_SESSION', :ctx_key, 'xxx'); + ctx_val = rdb$get_context('USER_SESSION', :ctx_key); + + k = k + 1; + end +end !! + +execute block returns(was_overwritten int, ctx_key varchar(30), ctx_val char(3)) +as + declare variable k int; +begin + k = 0; + while (k < 1000) do + begin + ctx_key = 'var_' || k; + + was_overwritten=rdb$set_context('USER_SESSION', :ctx_key, 'yyy'); + ctx_val = rdb$get_context('USER_SESSION', :ctx_key); + suspend; + + k = k + 1; + end +end !! + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Database: localhost:C:\\Users\\win7\\Firebird_tests\\fbt-repository\\tmp\\bugs.core_2969.fdb, User: SYSDBA +SQL> SQL> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> SQL> SQL> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_0 yyy + 1 var_1 yyy + 1 var_2 yyy + 1 var_3 yyy + 1 var_4 yyy + 1 var_5 yyy + 1 var_6 yyy + 1 var_7 yyy + 1 var_8 yyy + 1 var_9 yyy + 1 var_10 yyy + 1 var_11 yyy + 1 var_12 yyy + 1 var_13 yyy + 1 var_14 yyy + 1 var_15 yyy + 1 var_16 yyy + 1 var_17 yyy + 1 var_18 yyy + 1 var_19 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_20 yyy + 1 var_21 yyy + 1 var_22 yyy + 1 var_23 yyy + 1 var_24 yyy + 1 var_25 yyy + 1 var_26 yyy + 1 var_27 yyy + 1 var_28 yyy + 1 var_29 yyy + 1 var_30 yyy + 1 var_31 yyy + 1 var_32 yyy + 1 var_33 yyy + 1 var_34 yyy + 1 var_35 yyy + 1 var_36 yyy + 1 var_37 yyy + 1 var_38 yyy + 1 var_39 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_40 yyy + 1 var_41 yyy + 1 var_42 yyy + 1 var_43 yyy + 1 var_44 yyy + 1 var_45 yyy + 1 var_46 yyy + 1 var_47 yyy + 1 var_48 yyy + 1 var_49 yyy + 1 var_50 yyy + 1 var_51 yyy + 1 var_52 yyy + 1 var_53 yyy + 1 var_54 yyy + 1 var_55 yyy + 1 var_56 yyy + 1 var_57 yyy + 1 var_58 yyy + 1 var_59 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_60 yyy + 1 var_61 yyy + 1 var_62 yyy + 1 var_63 yyy + 1 var_64 yyy + 1 var_65 yyy + 1 var_66 yyy + 1 var_67 yyy + 1 var_68 yyy + 1 var_69 yyy + 1 var_70 yyy + 1 var_71 yyy + 1 var_72 yyy + 1 var_73 yyy + 1 var_74 yyy + 1 var_75 yyy + 1 var_76 yyy + 1 var_77 yyy + 1 var_78 yyy + 1 var_79 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_80 yyy + 1 var_81 yyy + 1 var_82 yyy + 1 var_83 yyy + 1 var_84 yyy + 1 var_85 yyy + 1 var_86 yyy + 1 var_87 yyy + 1 var_88 yyy + 1 var_89 yyy + 1 var_90 yyy + 1 var_91 yyy + 1 var_92 yyy + 1 var_93 yyy + 1 var_94 yyy + 1 var_95 yyy + 1 var_96 yyy + 1 var_97 yyy + 1 var_98 yyy + 1 var_99 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_100 yyy + 1 var_101 yyy + 1 var_102 yyy + 1 var_103 yyy + 1 var_104 yyy + 1 var_105 yyy + 1 var_106 yyy + 1 var_107 yyy + 1 var_108 yyy + 1 var_109 yyy + 1 var_110 yyy + 1 var_111 yyy + 1 var_112 yyy + 1 var_113 yyy + 1 var_114 yyy + 1 var_115 yyy + 1 var_116 yyy + 1 var_117 yyy + 1 var_118 yyy + 1 var_119 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_120 yyy + 1 var_121 yyy + 1 var_122 yyy + 1 var_123 yyy + 1 var_124 yyy + 1 var_125 yyy + 1 var_126 yyy + 1 var_127 yyy + 1 var_128 yyy + 1 var_129 yyy + 1 var_130 yyy + 1 var_131 yyy + 1 var_132 yyy + 1 var_133 yyy + 1 var_134 yyy + 1 var_135 yyy + 1 var_136 yyy + 1 var_137 yyy + 1 var_138 yyy + 1 var_139 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_140 yyy + 1 var_141 yyy + 1 var_142 yyy + 1 var_143 yyy + 1 var_144 yyy + 1 var_145 yyy + 1 var_146 yyy + 1 var_147 yyy + 1 var_148 yyy + 1 var_149 yyy + 1 var_150 yyy + 1 var_151 yyy + 1 var_152 yyy + 1 var_153 yyy + 1 var_154 yyy + 1 var_155 yyy + 1 var_156 yyy + 1 var_157 yyy + 1 var_158 yyy + 1 var_159 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_160 yyy + 1 var_161 yyy + 1 var_162 yyy + 1 var_163 yyy + 1 var_164 yyy + 1 var_165 yyy + 1 var_166 yyy + 1 var_167 yyy + 1 var_168 yyy + 1 var_169 yyy + 1 var_170 yyy + 1 var_171 yyy + 1 var_172 yyy + 1 var_173 yyy + 1 var_174 yyy + 1 var_175 yyy + 1 var_176 yyy + 1 var_177 yyy + 1 var_178 yyy + 1 var_179 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_180 yyy + 1 var_181 yyy + 1 var_182 yyy + 1 var_183 yyy + 1 var_184 yyy + 1 var_185 yyy + 1 var_186 yyy + 1 var_187 yyy + 1 var_188 yyy + 1 var_189 yyy + 1 var_190 yyy + 1 var_191 yyy + 1 var_192 yyy + 1 var_193 yyy + 1 var_194 yyy + 1 var_195 yyy + 1 var_196 yyy + 1 var_197 yyy + 1 var_198 yyy + 1 var_199 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_200 yyy + 1 var_201 yyy + 1 var_202 yyy + 1 var_203 yyy + 1 var_204 yyy + 1 var_205 yyy + 1 var_206 yyy + 1 var_207 yyy + 1 var_208 yyy + 1 var_209 yyy + 1 var_210 yyy + 1 var_211 yyy + 1 var_212 yyy + 1 var_213 yyy + 1 var_214 yyy + 1 var_215 yyy + 1 var_216 yyy + 1 var_217 yyy + 1 var_218 yyy + 1 var_219 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_220 yyy + 1 var_221 yyy + 1 var_222 yyy + 1 var_223 yyy + 1 var_224 yyy + 1 var_225 yyy + 1 var_226 yyy + 1 var_227 yyy + 1 var_228 yyy + 1 var_229 yyy + 1 var_230 yyy + 1 var_231 yyy + 1 var_232 yyy + 1 var_233 yyy + 1 var_234 yyy + 1 var_235 yyy + 1 var_236 yyy + 1 var_237 yyy + 1 var_238 yyy + 1 var_239 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_240 yyy + 1 var_241 yyy + 1 var_242 yyy + 1 var_243 yyy + 1 var_244 yyy + 1 var_245 yyy + 1 var_246 yyy + 1 var_247 yyy + 1 var_248 yyy + 1 var_249 yyy + 1 var_250 yyy + 1 var_251 yyy + 1 var_252 yyy + 1 var_253 yyy + 1 var_254 yyy + 1 var_255 yyy + 1 var_256 yyy + 1 var_257 yyy + 1 var_258 yyy + 1 var_259 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_260 yyy + 1 var_261 yyy + 1 var_262 yyy + 1 var_263 yyy + 1 var_264 yyy + 1 var_265 yyy + 1 var_266 yyy + 1 var_267 yyy + 1 var_268 yyy + 1 var_269 yyy + 1 var_270 yyy + 1 var_271 yyy + 1 var_272 yyy + 1 var_273 yyy + 1 var_274 yyy + 1 var_275 yyy + 1 var_276 yyy + 1 var_277 yyy + 1 var_278 yyy + 1 var_279 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_280 yyy + 1 var_281 yyy + 1 var_282 yyy + 1 var_283 yyy + 1 var_284 yyy + 1 var_285 yyy + 1 var_286 yyy + 1 var_287 yyy + 1 var_288 yyy + 1 var_289 yyy + 1 var_290 yyy + 1 var_291 yyy + 1 var_292 yyy + 1 var_293 yyy + 1 var_294 yyy + 1 var_295 yyy + 1 var_296 yyy + 1 var_297 yyy + 1 var_298 yyy + 1 var_299 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_300 yyy + 1 var_301 yyy + 1 var_302 yyy + 1 var_303 yyy + 1 var_304 yyy + 1 var_305 yyy + 1 var_306 yyy + 1 var_307 yyy + 1 var_308 yyy + 1 var_309 yyy + 1 var_310 yyy + 1 var_311 yyy + 1 var_312 yyy + 1 var_313 yyy + 1 var_314 yyy + 1 var_315 yyy + 1 var_316 yyy + 1 var_317 yyy + 1 var_318 yyy + 1 var_319 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_320 yyy + 1 var_321 yyy + 1 var_322 yyy + 1 var_323 yyy + 1 var_324 yyy + 1 var_325 yyy + 1 var_326 yyy + 1 var_327 yyy + 1 var_328 yyy + 1 var_329 yyy + 1 var_330 yyy + 1 var_331 yyy + 1 var_332 yyy + 1 var_333 yyy + 1 var_334 yyy + 1 var_335 yyy + 1 var_336 yyy + 1 var_337 yyy + 1 var_338 yyy + 1 var_339 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_340 yyy + 1 var_341 yyy + 1 var_342 yyy + 1 var_343 yyy + 1 var_344 yyy + 1 var_345 yyy + 1 var_346 yyy + 1 var_347 yyy + 1 var_348 yyy + 1 var_349 yyy + 1 var_350 yyy + 1 var_351 yyy + 1 var_352 yyy + 1 var_353 yyy + 1 var_354 yyy + 1 var_355 yyy + 1 var_356 yyy + 1 var_357 yyy + 1 var_358 yyy + 1 var_359 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_360 yyy + 1 var_361 yyy + 1 var_362 yyy + 1 var_363 yyy + 1 var_364 yyy + 1 var_365 yyy + 1 var_366 yyy + 1 var_367 yyy + 1 var_368 yyy + 1 var_369 yyy + 1 var_370 yyy + 1 var_371 yyy + 1 var_372 yyy + 1 var_373 yyy + 1 var_374 yyy + 1 var_375 yyy + 1 var_376 yyy + 1 var_377 yyy + 1 var_378 yyy + 1 var_379 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_380 yyy + 1 var_381 yyy + 1 var_382 yyy + 1 var_383 yyy + 1 var_384 yyy + 1 var_385 yyy + 1 var_386 yyy + 1 var_387 yyy + 1 var_388 yyy + 1 var_389 yyy + 1 var_390 yyy + 1 var_391 yyy + 1 var_392 yyy + 1 var_393 yyy + 1 var_394 yyy + 1 var_395 yyy + 1 var_396 yyy + 1 var_397 yyy + 1 var_398 yyy + 1 var_399 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_400 yyy + 1 var_401 yyy + 1 var_402 yyy + 1 var_403 yyy + 1 var_404 yyy + 1 var_405 yyy + 1 var_406 yyy + 1 var_407 yyy + 1 var_408 yyy + 1 var_409 yyy + 1 var_410 yyy + 1 var_411 yyy + 1 var_412 yyy + 1 var_413 yyy + 1 var_414 yyy + 1 var_415 yyy + 1 var_416 yyy + 1 var_417 yyy + 1 var_418 yyy + 1 var_419 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_420 yyy + 1 var_421 yyy + 1 var_422 yyy + 1 var_423 yyy + 1 var_424 yyy + 1 var_425 yyy + 1 var_426 yyy + 1 var_427 yyy + 1 var_428 yyy + 1 var_429 yyy + 1 var_430 yyy + 1 var_431 yyy + 1 var_432 yyy + 1 var_433 yyy + 1 var_434 yyy + 1 var_435 yyy + 1 var_436 yyy + 1 var_437 yyy + 1 var_438 yyy + 1 var_439 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_440 yyy + 1 var_441 yyy + 1 var_442 yyy + 1 var_443 yyy + 1 var_444 yyy + 1 var_445 yyy + 1 var_446 yyy + 1 var_447 yyy + 1 var_448 yyy + 1 var_449 yyy + 1 var_450 yyy + 1 var_451 yyy + 1 var_452 yyy + 1 var_453 yyy + 1 var_454 yyy + 1 var_455 yyy + 1 var_456 yyy + 1 var_457 yyy + 1 var_458 yyy + 1 var_459 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_460 yyy + 1 var_461 yyy + 1 var_462 yyy + 1 var_463 yyy + 1 var_464 yyy + 1 var_465 yyy + 1 var_466 yyy + 1 var_467 yyy + 1 var_468 yyy + 1 var_469 yyy + 1 var_470 yyy + 1 var_471 yyy + 1 var_472 yyy + 1 var_473 yyy + 1 var_474 yyy + 1 var_475 yyy + 1 var_476 yyy + 1 var_477 yyy + 1 var_478 yyy + 1 var_479 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_480 yyy + 1 var_481 yyy + 1 var_482 yyy + 1 var_483 yyy + 1 var_484 yyy + 1 var_485 yyy + 1 var_486 yyy + 1 var_487 yyy + 1 var_488 yyy + 1 var_489 yyy + 1 var_490 yyy + 1 var_491 yyy + 1 var_492 yyy + 1 var_493 yyy + 1 var_494 yyy + 1 var_495 yyy + 1 var_496 yyy + 1 var_497 yyy + 1 var_498 yyy + 1 var_499 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_500 yyy + 1 var_501 yyy + 1 var_502 yyy + 1 var_503 yyy + 1 var_504 yyy + 1 var_505 yyy + 1 var_506 yyy + 1 var_507 yyy + 1 var_508 yyy + 1 var_509 yyy + 1 var_510 yyy + 1 var_511 yyy + 1 var_512 yyy + 1 var_513 yyy + 1 var_514 yyy + 1 var_515 yyy + 1 var_516 yyy + 1 var_517 yyy + 1 var_518 yyy + 1 var_519 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_520 yyy + 1 var_521 yyy + 1 var_522 yyy + 1 var_523 yyy + 1 var_524 yyy + 1 var_525 yyy + 1 var_526 yyy + 1 var_527 yyy + 1 var_528 yyy + 1 var_529 yyy + 1 var_530 yyy + 1 var_531 yyy + 1 var_532 yyy + 1 var_533 yyy + 1 var_534 yyy + 1 var_535 yyy + 1 var_536 yyy + 1 var_537 yyy + 1 var_538 yyy + 1 var_539 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_540 yyy + 1 var_541 yyy + 1 var_542 yyy + 1 var_543 yyy + 1 var_544 yyy + 1 var_545 yyy + 1 var_546 yyy + 1 var_547 yyy + 1 var_548 yyy + 1 var_549 yyy + 1 var_550 yyy + 1 var_551 yyy + 1 var_552 yyy + 1 var_553 yyy + 1 var_554 yyy + 1 var_555 yyy + 1 var_556 yyy + 1 var_557 yyy + 1 var_558 yyy + 1 var_559 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_560 yyy + 1 var_561 yyy + 1 var_562 yyy + 1 var_563 yyy + 1 var_564 yyy + 1 var_565 yyy + 1 var_566 yyy + 1 var_567 yyy + 1 var_568 yyy + 1 var_569 yyy + 1 var_570 yyy + 1 var_571 yyy + 1 var_572 yyy + 1 var_573 yyy + 1 var_574 yyy + 1 var_575 yyy + 1 var_576 yyy + 1 var_577 yyy + 1 var_578 yyy + 1 var_579 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_580 yyy + 1 var_581 yyy + 1 var_582 yyy + 1 var_583 yyy + 1 var_584 yyy + 1 var_585 yyy + 1 var_586 yyy + 1 var_587 yyy + 1 var_588 yyy + 1 var_589 yyy + 1 var_590 yyy + 1 var_591 yyy + 1 var_592 yyy + 1 var_593 yyy + 1 var_594 yyy + 1 var_595 yyy + 1 var_596 yyy + 1 var_597 yyy + 1 var_598 yyy + 1 var_599 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_600 yyy + 1 var_601 yyy + 1 var_602 yyy + 1 var_603 yyy + 1 var_604 yyy + 1 var_605 yyy + 1 var_606 yyy + 1 var_607 yyy + 1 var_608 yyy + 1 var_609 yyy + 1 var_610 yyy + 1 var_611 yyy + 1 var_612 yyy + 1 var_613 yyy + 1 var_614 yyy + 1 var_615 yyy + 1 var_616 yyy + 1 var_617 yyy + 1 var_618 yyy + 1 var_619 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_620 yyy + 1 var_621 yyy + 1 var_622 yyy + 1 var_623 yyy + 1 var_624 yyy + 1 var_625 yyy + 1 var_626 yyy + 1 var_627 yyy + 1 var_628 yyy + 1 var_629 yyy + 1 var_630 yyy + 1 var_631 yyy + 1 var_632 yyy + 1 var_633 yyy + 1 var_634 yyy + 1 var_635 yyy + 1 var_636 yyy + 1 var_637 yyy + 1 var_638 yyy + 1 var_639 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_640 yyy + 1 var_641 yyy + 1 var_642 yyy + 1 var_643 yyy + 1 var_644 yyy + 1 var_645 yyy + 1 var_646 yyy + 1 var_647 yyy + 1 var_648 yyy + 1 var_649 yyy + 1 var_650 yyy + 1 var_651 yyy + 1 var_652 yyy + 1 var_653 yyy + 1 var_654 yyy + 1 var_655 yyy + 1 var_656 yyy + 1 var_657 yyy + 1 var_658 yyy + 1 var_659 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_660 yyy + 1 var_661 yyy + 1 var_662 yyy + 1 var_663 yyy + 1 var_664 yyy + 1 var_665 yyy + 1 var_666 yyy + 1 var_667 yyy + 1 var_668 yyy + 1 var_669 yyy + 1 var_670 yyy + 1 var_671 yyy + 1 var_672 yyy + 1 var_673 yyy + 1 var_674 yyy + 1 var_675 yyy + 1 var_676 yyy + 1 var_677 yyy + 1 var_678 yyy + 1 var_679 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_680 yyy + 1 var_681 yyy + 1 var_682 yyy + 1 var_683 yyy + 1 var_684 yyy + 1 var_685 yyy + 1 var_686 yyy + 1 var_687 yyy + 1 var_688 yyy + 1 var_689 yyy + 1 var_690 yyy + 1 var_691 yyy + 1 var_692 yyy + 1 var_693 yyy + 1 var_694 yyy + 1 var_695 yyy + 1 var_696 yyy + 1 var_697 yyy + 1 var_698 yyy + 1 var_699 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_700 yyy + 1 var_701 yyy + 1 var_702 yyy + 1 var_703 yyy + 1 var_704 yyy + 1 var_705 yyy + 1 var_706 yyy + 1 var_707 yyy + 1 var_708 yyy + 1 var_709 yyy + 1 var_710 yyy + 1 var_711 yyy + 1 var_712 yyy + 1 var_713 yyy + 1 var_714 yyy + 1 var_715 yyy + 1 var_716 yyy + 1 var_717 yyy + 1 var_718 yyy + 1 var_719 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_720 yyy + 1 var_721 yyy + 1 var_722 yyy + 1 var_723 yyy + 1 var_724 yyy + 1 var_725 yyy + 1 var_726 yyy + 1 var_727 yyy + 1 var_728 yyy + 1 var_729 yyy + 1 var_730 yyy + 1 var_731 yyy + 1 var_732 yyy + 1 var_733 yyy + 1 var_734 yyy + 1 var_735 yyy + 1 var_736 yyy + 1 var_737 yyy + 1 var_738 yyy + 1 var_739 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_740 yyy + 1 var_741 yyy + 1 var_742 yyy + 1 var_743 yyy + 1 var_744 yyy + 1 var_745 yyy + 1 var_746 yyy + 1 var_747 yyy + 1 var_748 yyy + 1 var_749 yyy + 1 var_750 yyy + 1 var_751 yyy + 1 var_752 yyy + 1 var_753 yyy + 1 var_754 yyy + 1 var_755 yyy + 1 var_756 yyy + 1 var_757 yyy + 1 var_758 yyy + 1 var_759 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_760 yyy + 1 var_761 yyy + 1 var_762 yyy + 1 var_763 yyy + 1 var_764 yyy + 1 var_765 yyy + 1 var_766 yyy + 1 var_767 yyy + 1 var_768 yyy + 1 var_769 yyy + 1 var_770 yyy + 1 var_771 yyy + 1 var_772 yyy + 1 var_773 yyy + 1 var_774 yyy + 1 var_775 yyy + 1 var_776 yyy + 1 var_777 yyy + 1 var_778 yyy + 1 var_779 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_780 yyy + 1 var_781 yyy + 1 var_782 yyy + 1 var_783 yyy + 1 var_784 yyy + 1 var_785 yyy + 1 var_786 yyy + 1 var_787 yyy + 1 var_788 yyy + 1 var_789 yyy + 1 var_790 yyy + 1 var_791 yyy + 1 var_792 yyy + 1 var_793 yyy + 1 var_794 yyy + 1 var_795 yyy + 1 var_796 yyy + 1 var_797 yyy + 1 var_798 yyy + 1 var_799 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_800 yyy + 1 var_801 yyy + 1 var_802 yyy + 1 var_803 yyy + 1 var_804 yyy + 1 var_805 yyy + 1 var_806 yyy + 1 var_807 yyy + 1 var_808 yyy + 1 var_809 yyy + 1 var_810 yyy + 1 var_811 yyy + 1 var_812 yyy + 1 var_813 yyy + 1 var_814 yyy + 1 var_815 yyy + 1 var_816 yyy + 1 var_817 yyy + 1 var_818 yyy + 1 var_819 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_820 yyy + 1 var_821 yyy + 1 var_822 yyy + 1 var_823 yyy + 1 var_824 yyy + 1 var_825 yyy + 1 var_826 yyy + 1 var_827 yyy + 1 var_828 yyy + 1 var_829 yyy + 1 var_830 yyy + 1 var_831 yyy + 1 var_832 yyy + 1 var_833 yyy + 1 var_834 yyy + 1 var_835 yyy + 1 var_836 yyy + 1 var_837 yyy + 1 var_838 yyy + 1 var_839 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_840 yyy + 1 var_841 yyy + 1 var_842 yyy + 1 var_843 yyy + 1 var_844 yyy + 1 var_845 yyy + 1 var_846 yyy + 1 var_847 yyy + 1 var_848 yyy + 1 var_849 yyy + 1 var_850 yyy + 1 var_851 yyy + 1 var_852 yyy + 1 var_853 yyy + 1 var_854 yyy + 1 var_855 yyy + 1 var_856 yyy + 1 var_857 yyy + 1 var_858 yyy + 1 var_859 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_860 yyy + 1 var_861 yyy + 1 var_862 yyy + 1 var_863 yyy + 1 var_864 yyy + 1 var_865 yyy + 1 var_866 yyy + 1 var_867 yyy + 1 var_868 yyy + 1 var_869 yyy + 1 var_870 yyy + 1 var_871 yyy + 1 var_872 yyy + 1 var_873 yyy + 1 var_874 yyy + 1 var_875 yyy + 1 var_876 yyy + 1 var_877 yyy + 1 var_878 yyy + 1 var_879 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_880 yyy + 1 var_881 yyy + 1 var_882 yyy + 1 var_883 yyy + 1 var_884 yyy + 1 var_885 yyy + 1 var_886 yyy + 1 var_887 yyy + 1 var_888 yyy + 1 var_889 yyy + 1 var_890 yyy + 1 var_891 yyy + 1 var_892 yyy + 1 var_893 yyy + 1 var_894 yyy + 1 var_895 yyy + 1 var_896 yyy + 1 var_897 yyy + 1 var_898 yyy + 1 var_899 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_900 yyy + 1 var_901 yyy + 1 var_902 yyy + 1 var_903 yyy + 1 var_904 yyy + 1 var_905 yyy + 1 var_906 yyy + 1 var_907 yyy + 1 var_908 yyy + 1 var_909 yyy + 1 var_910 yyy + 1 var_911 yyy + 1 var_912 yyy + 1 var_913 yyy + 1 var_914 yyy + 1 var_915 yyy + 1 var_916 yyy + 1 var_917 yyy + 1 var_918 yyy + 1 var_919 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_920 yyy + 1 var_921 yyy + 1 var_922 yyy + 1 var_923 yyy + 1 var_924 yyy + 1 var_925 yyy + 1 var_926 yyy + 1 var_927 yyy + 1 var_928 yyy + 1 var_929 yyy + 1 var_930 yyy + 1 var_931 yyy + 1 var_932 yyy + 1 var_933 yyy + 1 var_934 yyy + 1 var_935 yyy + 1 var_936 yyy + 1 var_937 yyy + 1 var_938 yyy + 1 var_939 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_940 yyy + 1 var_941 yyy + 1 var_942 yyy + 1 var_943 yyy + 1 var_944 yyy + 1 var_945 yyy + 1 var_946 yyy + 1 var_947 yyy + 1 var_948 yyy + 1 var_949 yyy + 1 var_950 yyy + 1 var_951 yyy + 1 var_952 yyy + 1 var_953 yyy + 1 var_954 yyy + 1 var_955 yyy + 1 var_956 yyy + 1 var_957 yyy + 1 var_958 yyy + 1 var_959 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_960 yyy + 1 var_961 yyy + 1 var_962 yyy + 1 var_963 yyy + 1 var_964 yyy + 1 var_965 yyy + 1 var_966 yyy + 1 var_967 yyy + 1 var_968 yyy + 1 var_969 yyy + 1 var_970 yyy + 1 var_971 yyy + 1 var_972 yyy + 1 var_973 yyy + 1 var_974 yyy + 1 var_975 yyy + 1 var_976 yyy + 1 var_977 yyy + 1 var_978 yyy + 1 var_979 yyy + +WAS_OVERWRITTEN CTX_KEY CTX_VAL +=============== ============================== ======= + 1 var_980 yyy + 1 var_981 yyy + 1 var_982 yyy + 1 var_983 yyy + 1 var_984 yyy + 1 var_985 yyy + 1 var_986 yyy + 1 var_987 yyy + 1 var_988 yyy + 1 var_989 yyy + 1 var_990 yyy + 1 var_991 yyy + 1 var_992 yyy + 1 var_993 yyy + 1 var_994 yyy + 1 var_995 yyy + 1 var_996 yyy + 1 var_997 yyy + 1 var_998 yyy + 1 var_999 yyy + +SQL> SQL>""" + +@pytest.mark.version('>=2.1.4') +def test_core_2969_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2971.py b/tests/bugs/test_core_2971.py new file mode 100644 index 00000000..7f20ff4f --- /dev/null +++ b/tests/bugs/test_core_2971.py @@ -0,0 +1,84 @@ +#coding:utf-8 +# +# id: bugs.core_2971 +# title: Invalid UPDATE OR INSERT usage may lead to successive "request depth exceeded. (Recursive definition?)" error +# decription: +# tracker_id: CORE-2971 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- This syntax works fine since 2.0.x: + recreate view v(x, y) as select 1 x, 2 y from rdb$database; + commit; + set term ^; + execute block as + begin + execute statement 'drop sequence g'; + when any do begin end + end + ^ + set term ;^ + commit; + + create sequence g; + recreate table t1 (n1 integer); + recreate table t2 (n2 integer); + + recreate view v(x, y) as select t1.n1 as x, t2.n2 as y from t1, t2; + commit; + + set term ^; + execute block as + declare n int = 1000; + begin + while (n>0) do + begin + n = n - 1; + execute statement ('update or insert into v values ( '|| gen_id(g,1) ||', gen_id(g,1))'); + -- ^ + -- For this statement trace 2.5 and 3.0 shows: + -- ERROR AT JStatement::prepare + -- ... + -- 335544569 : Dynamic SQL Error + -- 336003101 : UPDATE OR INSERT without MATCHING could not be used with views based on more than one table + -- We have to suppress ONLY exception with gdscode = 335544569 and raise if its gdscode has any other value. + when any do + begin + if ( gdscode not in (335544569) ) then exception; + end + end + + end + ^ + set term ;^ + rollback; + set list on; + select gen_id(g, 0) curr_gen from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CURR_GEN 1000 + """ + +@pytest.mark.version('>=2.5') +def test_core_2971_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2974.py b/tests/bugs/test_core_2974.py new file mode 100644 index 00000000..04e37b2e --- /dev/null +++ b/tests/bugs/test_core_2974.py @@ -0,0 +1,70 @@ +#coding:utf-8 +# +# id: bugs.core_2974 +# title: Unexpected "Invalid SIMILAR TO pattern" error +# decription: +# +# tracker_id: CORE-2974 +# min_versions: ['2.5'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + -- Should raise "Invalid SIMILAR TO pattern" error, as minus sign should be ecaped + select case when '-1' similar to '(-)%' then 1 else 0 end as chk_a + from rdb$database + ; + + -- Should raise "Invalid SIMILAR TO pattern" error because there is no "default" escape character: + select case when '-1' similar to '(\\-)%' then 1 else 0 end as chk_b + from rdb$database + ; + + -- Should NOT raise error: + select case when '-1' similar to '(\\-)%' escape '\\' then 1 else 0 end as chk_c + from rdb$database + ; + -- works ok + + -- Should NOT raise error: + select case when '-1' similar to '(\\+)%' then 1 else 0 end as chk_d + from rdb$database + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CHK_C 1 + CHK_D 0 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + Invalid SIMILAR TO pattern + + Statement failed, SQLSTATE = 42000 + Invalid SIMILAR TO pattern + """ + +@pytest.mark.version('>=2.5') +def test_core_2974_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2977.py b/tests/bugs/test_core_2977.py new file mode 100644 index 00000000..ebccf0b3 --- /dev/null +++ b/tests/bugs/test_core_2977.py @@ -0,0 +1,57 @@ +#coding:utf-8 +# +# id: bugs.core_2977 +# title: FB 2.1 incorrectly works with indexed fields of type DATE in OLD ODS (9.1) +# decription: +# 08.04.2021: number of DAY in the date representation becomes padded with '0' (NB: dialect 1 is used here!) +# Expected output was changed according to this after discuss with Adriano. +# +# tracker_id: CORE-2977 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=1, init=init_script_1) + +test_script_1 = """ + recreate table test(id int, opdate timestamp); + insert into test values(1, '31.12.2000'); + insert into test values(2, '01.01.2001'); + insert into test values(3, '02.01.2001'); + insert into test values(4, '03.01.2001'); + commit; + + create index test_opdate on test(opdate); + commit; + + set list on; + -- FOllowing query will have PLAN (TEST INDEX (TEST_OPDATE)) + select * from test where opdate <= '1/1/2001'; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + OPDATE 31-DEC-2000 + + ID 2 + OPDATE 01-JAN-2001 + """ + +@pytest.mark.version('>=2.5') +def test_core_2977_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2981.py b/tests/bugs/test_core_2981.py new file mode 100644 index 00000000..e49f252a --- /dev/null +++ b/tests/bugs/test_core_2981.py @@ -0,0 +1,400 @@ +#coding:utf-8 +# +# id: bugs.core_2981 +# title: Error in Trace plugin (use local symbols in query) +# decription: +# Test prepares trace config as it was mentioned in the ticket, then creates .sql with russian text in UTF8 encoding +# and run trace and ISQL. +# Finally, we compare content of firebird.log before and after running this query (it should be empty) and check that +# size of error log of trace session is zero. +# +# Checked on: WI-V2.5.7.27024, WI-V3.0.1.32570, WI-T4.0.0.316 -- all works OK. +# +# tracker_id: CORE-2981 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# import difflib +# from subprocess import Popen +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# engine = str(db_conn.engine_version) +# db_conn.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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# +# #-------------------------------------------- +# +# def svc_get_fb_log( engine, f_fb_log ): +# +# global subprocess +# +# if engine.startswith('2.5'): +# get_firebird_log_key='action_get_ib_log' +# else: +# get_firebird_log_key='action_get_fb_log' +# +# subprocess.call([ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# get_firebird_log_key +# ], +# stdout=f_fb_log, +# stderr=subprocess.STDOUT +# ) +# +# return +# +# #-------------------------------------------- +# +# +# txt25 = '''# Trace config, format for 2.5. Generated auto, do not edit! +# +# enabled true +# #connection_id 7 +# include_filter %(SELECT|INSERT|UPDATE|DELETE)% +# log_connections true +# log_transactions true +# log_statement_prepare true +# log_statement_free true +# log_statement_start true +# log_statement_finish true +# log_procedure_start true +# log_procedure_finish true +# log_trigger_start true +# log_trigger_finish true +# log_context true +# print_plan true +# print_perf true +# log_blr_requests false +# print_blr false +# log_dyn_requests false +# print_dyn false +# time_threshold 0 +# max_sql_length 5000 +# max_blr_length 500 +# max_dyn_length 500 +# max_arg_length 80 +# max_arg_count 30 +# +# +# enabled false +# log_services false +# log_service_query false +# +# ''' +# +# # NOTES ABOUT TRACE CONFIG FOR 3.0: +# # 1) Header contains `database` clause in different format vs FB 2.5: its data must be enclosed with '{' '}' +# # 2) Name and value must be separated by EQUALITY sign ('=') in FB-3 trace.conf, otherwise we get runtime error: +# # element "<. . .>" have no attribute value set +# +# txt30 = '''# Trace config, format for 3.0. Generated auto, do not edit! +# database=%[\\\\\\\\/]bugs.core_2981.fdb +# { +# enabled = true +# include_filter = %(SELECT|INSERT|UPDATE|DELETE)% +# log_connections = true +# log_transactions= true +# log_statement_prepare = true +# log_statement_free = true +# log_statement_start = true +# log_statement_finish = true +# log_procedure_start = true +# log_procedure_finish = true +# log_trigger_start = true +# log_trigger_finish = true +# log_context = true +# print_plan = true +# print_perf = true +# log_blr_requests = false +# print_blr = false +# log_dyn_requests = false +# print_dyn = false +# time_threshold = 0 +# max_sql_length = 5000 +# max_blr_length = 500 +# max_dyn_length = 500 +# max_arg_length = 80 +# max_arg_count = 30 +# } +# services { +# enabled = false +# log_services = false +# log_service_query = false +# } +# ''' +# +# f_trccfg=open( os.path.join(context['temp_directory'],'tmp_trace_2981.cfg'), 'w') +# if engine.startswith('2.5'): +# f_trccfg.write(txt25) +# else: +# f_trccfg.write(txt30) +# flush_and_close( f_trccfg ) +# +# # Get content of firebird.log BEFORE test: +# ########################################## +# +# f_fblog_before=open( os.path.join(context['temp_directory'],'tmp_2981_fblog_before.txt'), 'w') +# svc_get_fb_log( engine, f_fblog_before ) +# flush_and_close( f_fblog_before ) +# +# # Starting trace session in new child process (async.): +# ####################################################### +# +# f_trclog=open( os.path.join(context['temp_directory'],'tmp_trace_2981.log'), 'w') +# f_trcerr=open( os.path.join(context['temp_directory'],'tmp_trace_2981.err'), 'w') +# +# # Execute a child program in a new process, redirecting STDERR to the same target as of STDOUT: +# p_trace=Popen([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_start", +# "trc_cfg", f_trccfg.name], +# stdout=f_trclog, +# stderr=f_trcerr +# ) +# +# # Wait! Trace session is initialized not instantly! +# time.sleep(2) +# +# localized_query=''' +# set list on; +# select '*Лев Николаевич Толстой * +# +# *Анна Каренина * +# +# /Мне отмщение, и аз воздам/ +# +# *ЧАСТЬ ПЕРВАЯ* +# +# *I * +# +# Все счастливые семьи похожи друг на друга, каждая несчастливая +# семья несчастлива по-своему. +# Все смешалось в доме Облонских. Жена узнала, что муж был в связи +# с бывшею в их доме француженкою-гувернанткой, и объявила мужу, что +# не может жить с ним в одном доме. Положение это продолжалось уже +# третий день и мучительно чувствовалось и самими супругами, и всеми +# членами семьи, и домочадцами. Все члены семьи и домочадцы +# чувствовали, что нет смысла в их сожительстве и что на каждом +# постоялом дворе случайно сошедшиеся люди более связаны между собой, +# чем они, члены семьи и домочадцы Облонских. Жена не выходила из +# своих комнат, мужа третий день не было дома. Дети бегали по всему +# дому, как потерянные; англичанка поссорилась с экономкой и написала +# записку приятельнице, прося приискать ей новое место; повар ушел еще +# вчера со двора, во время обеда; черная кухарка и кучер просили расчета. +# На третий день после ссоры князь Степан Аркадьич Облонский -- +# Стива, как его звали в свете, -- в обычный час, то есть в восемь +# часов утра, проснулся не в спальне жены, а в своем кабинете, на +# сафьянном диване... Он повернул свое полное, выхоленное тело на +# пружинах дивана, как бы желая опять заснуть надолго, с другой +# стороны крепко обнял подушку и прижался к ней щекой; но вдруг +# вскочил, сел на диван и открыл глаза. +# "Да, да, как это было? -- думал он, вспоминая сон. -- Да, как это +# было? Да! Алабин давал обед в Дармштадте; нет, не в Дармштадте, а +# что-то американское. Да, но там Дармштадт был в Америке. Да, Алабин +# давал обед на стеклянных столах, да, -- и столы пели: Il mio tesoro, +# и не Il mio tesoro, а что-то лучше, и какие-то маленькие графинчики, +# и они же женщины", -- вспоминал он. +# Глаза Степана Аркадьича весело заблестели, и он задумался, +# улыбаясь. "Да, хорошо было, очень хорошо. Много еще там было +# отличного, да не скажешь словами и мыслями даже наяву не выразишь". +# И, заметив полосу света, пробившуюся сбоку одной из суконных стор, +# он весело скинул ноги с дивана, отыскал ими шитые женой (подарок ко +# дню рождения в прошлом году), обделанные в золотистый сафьян туфли и +# по старой, девятилетней привычке, не вставая, потянулся рукой к тому +# месту, где в спальне у него висел халат. И тут он вспомнил вдруг, +# как и почему он спит не в спальне жены, а в кабинете; улыбка исчезла +# с его лица, он сморщил лоб. +# "Ах, ах, ах! Ааа!.." -- замычал он, вспоминая все, что было. И +# его воображению представились опять все подробности ссоры с женою, +# вся безвыходность его положения и мучительнее всего собственная вина +# его. +# "Да! она не простит и не может простить. И всего ужаснее то, что +# виной всему я, виной я, а не виноват. В этом-то вся драма, -- думал +# он. -- Ах, ах, ах!" -- приговаривал он с отчаянием, вспоминая самые +# тяжелые для себя впечатления из этой ссоры. +# Неприятнее всего была та первая минута, когда он, вернувшись из +# театра, веселый и довольный, с огромною грушей для жены в руке, не +# нашел жены в гостиной; к удивлению, не нашел ее и в кабинете и, +# наконец, увидал ее в спальне с несчастною, открывшею все, запиской в +# руке. +# Она, эта вечно озабоченная, и хлопотливая, и недалекая, какою он +# считал ее, Долли, неподвижно сидела с запиской в руке и с выражением +# ужаса, отчаяния и гнева смотрела на него. +# -- Что это? это? -- спрашивала она, указывая на записку. +# И при этом воспоминании, как это часто бывает, мучала Степана +# Аркадьича не столько самое событие, сколько то, как он ответил на +# эти слова жены. +# С ним случилось в эту минуту то, что случается с людьми, когда +# они неожиданно уличены в чем-нибудь слишком постыдном. Он не сумел +# приготовить свое лицо к тому положению, в которое он становился +# перед женой после открытия его вины. Вместо того чтоб оскорбиться, +# отрекаться, оправдываться, просить прощения, оставаться даже +# равнодушным -- все было бы лучше того, что он сделал! -- его лицо +# совершенно невольно ("рефлексы головного мозга", -- подумал Степан +# Аркадьич, который любил физиологию), совершенно невольно вдруг +# улыбнулось привычною, доброю и потому глупою улыбкой. +# Эту глупую улыбку он не мог простить себе. Увидав эту улыбку, +# Долли вздрогнула, как от физической боли, разразилась, со +# свойственною ей горячностью, потоком жестоких слов и выбежала из +# комнаты. С тех пор она не хотела видеть мужа. +# "Всему виной эта глупая улыбка", -- думал Степан Аркадьич. +# "Но что же делать? что делать?" -- с отчаянием говорил он себе и +# не находил ответа. +# ' from rdb$database; +# ''' +# f_utf8 = open( os.path.join(context['temp_directory'],'tmp_2981_run.sql'), 'w') +# f_utf8.write(localized_query) +# flush_and_close( f_utf8 ) +# +# # RUN QUERY WITH NON-ASCII CHARACTERS +# ##################################### +# +# f_run_log = open( os.path.join(context['temp_directory'],'tmp_2981_run.log'), 'w') +# f_run_err = open( os.path.join(context['temp_directory'],'tmp_2981_run.err'), 'w') +# subprocess.call( [context['isql_path'], dsn, "-q", "-i", f_utf8.name, '-ch', 'utf8' ], +# stdout = f_run_log, +# stderr = f_run_err +# ) +# +# flush_and_close( f_run_log ) +# flush_and_close( f_run_err ) +# +# ##################################################### +# # Getting ID of launched trace session and STOP it: +# +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# f_trclst=open( os.path.join(context['temp_directory'],'tmp_trace_2981.lst'), 'w') +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_list"], +# stdout=f_trclst, +# stderr=subprocess.STDOUT +# ) +# flush_and_close( f_trclst ) +# +# trcssn=0 +# with open( f_trclst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# f_trclst=open(f_trclst.name,'a') +# f_trclst.seek(0,2) +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_stop", +# "trc_id",trcssn], +# stdout=f_trclst, stderr=subprocess.STDOUT +# ) +# flush_and_close( f_trclst ) +# +# # do NOT remove this delay: trase session can not be stopped immediatelly: +# time.sleep(2) +# +# # Terminate child process of launched trace session (though it should already be killed): +# p_trace.terminate() +# flush_and_close( f_trclog ) +# flush_and_close( f_trcerr ) +# +# +# # Get content of firebird.log AFTER test: +# ######################################### +# +# f_fblog_after=open( os.path.join(context['temp_directory'],'tmp_2981_fblog_after.txt'), 'w') +# svc_get_fb_log( engine, f_fblog_after ) +# flush_and_close( f_fblog_after ) +# +# # STDERR for ISQL (that created DB) and trace session - they both must be EMPTY: +# ################# +# f_list=[f_run_err, f_trcerr] +# for i in range(len(f_list)): +# f_name=f_list[i].name +# if os.path.getsize(f_name) > 0: +# with open( f_name,'r') as f: +# for line in f: +# print("Unexpected STDERR, file "+f_name+": "+line) +# +# # DIFFERENCE in the content of firebird.log should be EMPTY: +# #################### +# +# oldfb=open(f_fblog_before.name, 'r') +# newfb=open(f_fblog_after.name, 'r') +# +# difftext = ''.join(difflib.unified_diff( +# oldfb.readlines(), +# newfb.readlines() +# )) +# oldfb.close() +# newfb.close() +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_2981_diff.txt'), 'w') +# f_diff_txt.write(difftext) +# flush_and_close( f_diff_txt ) +# +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# print("Unexpected DIFF in firebird.log: "+line) +# +# +# +# # Cleanup: +# ########### +# time.sleep(1) +# cleanup( [i.name for i in (f_run_log, f_run_err, f_trccfg, f_trclst, f_trcerr, f_fblog_before,f_fblog_after, f_diff_txt, f_trclog, f_utf8)] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.1') +@pytest.mark.xfail +def test_core_2981_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_2985.py b/tests/bugs/test_core_2985.py new file mode 100644 index 00000000..02cc854c --- /dev/null +++ b/tests/bugs/test_core_2985.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_2985 +# title: The new 2.5 feature to alter COMPUTED columns doesn't handle dependencies well +# decription: +# tracker_id: CORE-2985 +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table test (id numeric, f1 varchar(20)); +create table test1(id1 numeric, ff computed((select f1 from test where id=id1))); +commit; +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """show table test1; +alter table test1 alter ff computed(cast(null as varchar(20))); +drop table test; +commit; +show table test1; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """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))) +""" + +@pytest.mark.version('>=2.5.0') +def test_core_2985_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2987.py b/tests/bugs/test_core_2987.py new file mode 100644 index 00000000..415d8114 --- /dev/null +++ b/tests/bugs/test_core_2987.py @@ -0,0 +1,168 @@ +#coding:utf-8 +# +# id: bugs.core_2987 +# title: Don't send full length of field over the wire when field is null +# decription: +# Checked on: WI-V3.0.0.32484 (SS/SC/CS), LI-T4.0.0.138 (SS) +# +# tracker_id: CORE-2987 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Measurement showed than on 3.0 (SS/SC/CS) transfer of NULLs is more than 5 (five) times + -- faster than text data with length = 32K. As of 2.5 (SC) than ration is about 1.7 ... 1.8. + -- Test fills up two tables: one with text data and another with only nulls. + -- Then we receive data from these tables via ES/EDS, evaluate elapsed time for both cases + -- and calculate its ratio. This ratio in 3.0 should be not less than 4x. + create or alter procedure sp_test returns(sel_data_ms int, sel_null_ms int) as begin end; + create or alter procedure sp_test as begin end; + + recreate global temporary table test1(f01 char(32760)) on commit delete rows; + recreate global temporary table test2(f01 char(32760)) on commit delete rows; + commit; + + + set term ^; + create or alter procedure sp_fill as + declare c_added_rows int = 2000; + begin + execute statement + 'insert into test1 ' + || 'with recursive r as (select 0 i from rdb$database union all select r.i+1 from r where r.i<99) ' + || 'select rpad('''', 32760, uuid_to_char(gen_uuid()) ) from r r1,r r2 rows ' || c_added_rows + on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') + as user 'SYSDBA' password 'masterkey' + role 'R001' ------------------------------- this will create new attach #1 that will be used later! + ; + execute statement + 'insert into test2 ' + || 'with recursive r as (select 0 i from rdb$database union all select r.i+1 from r where r.i<99) ' + || 'select null from r r1,r r2 rows ' || c_added_rows + on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') + as user 'SYSDBA' password 'masterkey' + role 'R002' ------------------------------- this will create new attach #2 that will be used later! + ; + end + ^ + + create or alter procedure sp_test returns( sel_data_ms int, sel_null_ms int, ratio numeric(10,2) ) as + declare v_f01 type of column test1.f01; + declare t0 timestamp; + declare t1 timestamp; + declare t2 timestamp; + begin + + t0='now'; + for + execute statement + 'select f01 from test1' on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') + as user 'SYSDBA' password 'masterkey' + role 'R001' --------------- here we use EXISTING attach #1 (from internal FB connection pool) + into v_f01 + do begin end + + t1='now'; + + for + execute statement + 'select f01 from test2' on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') + as user 'SYSDBA' password 'masterkey' + role 'R002' --------------- here we use EXISTING attach #2 (from internal FB connection pool) + into v_f01 + do begin end + + t2='now'; + + sel_data_ms = datediff(millisecond from t0 to t1); + sel_null_ms = datediff(millisecond from t1 to t2); + ratio = coalesce( sel_data_ms * 1.000 / nullif(sel_null_ms,0), 9999999.99); + + suspend; + + end + ^ + set term ;^ + --commit; + + set list on; + + --set stat on; + -- must be ~15 sec + execute procedure sp_fill; -- will add data into GTT test1 (in attach #1) and GTT test2 (in attach #2) + --set stat off; + + set term ^; + execute block returns( measure_result varchar(40) ) as + declare min_profit_ratio numeric(3,1) = 3.8; -- ##### T H R E S H O L D #### + declare sel_data_ms int; + declare sel_null_ms int; + declare ratio numeric(10,2); + begin + + -- These four calls will extract rows from GTT test1 (in attach #1) and from GTT test2 (in attach #2). + -- We have to register statistics only for 2nd...4th measurements due to probable file cache affects. + + select ratio, '' from sp_test into ratio, measure_result; + --- do not suspend now -- + select sel_data_ms, sel_null_ms, ratio, iif( ratio >= :min_profit_ratio, 'WINS >= '||:min_profit_ratio||'x', 'LOOSES, '||ratio||'x') + from sp_test + into sel_data_ms, sel_null_ms,ratio, measure_result; + suspend; + select sel_data_ms, sel_null_ms, ratio, iif( ratio >= :min_profit_ratio, 'WINS >= '||:min_profit_ratio||'x', 'LOOSES, '||ratio||'x') + from sp_test + into sel_data_ms, sel_null_ms,ratio, measure_result; + suspend; + select sel_data_ms, sel_null_ms, ratio, iif( ratio >= :min_profit_ratio, 'WINS >= '||:min_profit_ratio||'x', 'LOOSES, '||ratio||'x') + from sp_test + into sel_data_ms, sel_null_ms,ratio, measure_result; + 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MEASURE_RESULT WINS >= 3.8x + MEASURE_RESULT WINS >= 3.8x + MEASURE_RESULT WINS >= 3.8x + """ + +@pytest.mark.version('>=3.0') +def test_core_2987_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_2988.py b/tests/bugs/test_core_2988.py new file mode 100644 index 00000000..9cf84111 --- /dev/null +++ b/tests/bugs/test_core_2988.py @@ -0,0 +1,297 @@ +#coding:utf-8 +# +# id: bugs.core_2988 +# title: Concurrent transaction number not reported if lock timeout occurs +# decription: +# 08-aug-2018. +# ::: ACHTUNG ::: +# Important change has been added in FB 4.0. +# According to doc\\README.read_consistency.md, read committed isolation level +# was modified and new transaction with RC effectively is launched like: +# SET TRANSACTION READ COMMITTED READ CONSISTENCY +# Moreover, it is unable to start transaction in NO_record_version until +# config parameter ReadConsistency will be changed from 1(default) to 0. +# This mean that now it is unable to use NO_record_version setting in RC mode +# with default firebird.conf ==> we can not check behaviour of engine exactly +# as ticket says in its case-1: +# === +# set transaction read committed no record_version lock timeout 10; +# select * from test; +# === +# For this reason it was decided to create separate section for major version 4.0 +# and use UPDATE statement instead of 'select * from test' (UPDATE also must READ +# data before changing). +# +# Checked on: +# FB25SC, build 2.5.9.27115: OK, 3.750s. +# FB30SS, build 3.0.4.33022: OK, 4.343s. +# FB40SS, build 4.0.0.1154: OK, 4.875s. +# +# tracker_id: CORE-2988 +# min_versions: ['2.5.4'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('record not found for user:.*', ''), ('-concurrent transaction number is.*', '-concurrent transaction number is'), ('-At block line: [\\d]+, col: [\\d]+', '-At block line')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + drop user tmp$2988; + commit; + create user tmp$2988 password 'tmp$2988'; + commit; + + recreate table test (id integer); + insert into test values(1); + commit; + + revoke all on all from tmp$2988; + grant select,update on test to tmp$2988; + commit; + + set transaction lock timeout 1; + update test set id = id; + + set term ^; + execute block as + declare v_usr char(31) = 'tmp$2988'; + declare v_pwd varchar(20) = 'tmp$2988'; + declare v_connect varchar(255); + declare v_dummy int; + begin + execute statement ('update test set id = -1') + with autonomous transaction + as user v_usr password v_pwd + into v_dummy; + end + ^ + set term ;^ + rollback; + + set transaction read committed no record_version lock timeout 1; + update test set id = id; + + set term ^; + execute block as + declare v_usr char(31) = 'tmp$2988'; + declare v_pwd varchar(20) = 'tmp$2988'; + declare v_connect varchar(255); + declare v_dummy int; + begin + execute statement ('select id from test') + with autonomous transaction + as user v_usr password v_pwd + into v_dummy; + end + ^ + set term ;^ + rollback; + + set list on; + set transaction read committed no record_version lock timeout 1; + select id from test with lock; + + set term ^; + execute block as + declare v_usr char(31) = 'tmp$2988'; + declare v_pwd varchar(20) = 'tmp$2988'; + declare v_connect varchar(255); + declare v_dummy int; + begin + begin + v_dummy = 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 ('select id from test with lock') + with autonomous transaction + as user v_usr password v_pwd + into v_dummy; + end + ^ + drop user tmp$2988 + ^ + 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_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = HY000 + record not found for user: TMP$2988 + Warning: ALL on ALL is not granted to TMP$2988. + Statement failed, SQLSTATE = 40001 + deadlock + -update conflicts with concurrent update + -concurrent transaction number is 18 + -At block line: 7, col: 9 + + Statement failed, SQLSTATE = 40001 + deadlock + -read conflicts with concurrent update + -concurrent transaction number is 21 + -At block line: 7, col: 9 + + Statement failed, SQLSTATE = 40001 + deadlock + -read conflicts with concurrent update + -concurrent transaction number is 24 + -At block line: 7, col: 9 + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_core_2988_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [('^((?!concurrent transaction number is).)*$', ''), ('[\\-]{0,1}concurrent transaction number is [0-9]+', 'concurrent transaction number is')] + +init_script_2 = """ + create table test(id int, x int, constraint test_pk primary key(id) using index test_pk); + commit; + insert into test(id, x) values(1, 111); + commit; + """ + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +# test_script_2 +#--- +# +# import os +# db_conn.close() +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# con = fdb.connect(dsn = dsn) +# +# tx1 = con.trans() +# tx1.begin() +# cur1=tx1.cursor() +# cur1.execute( 'update test set x = ? where id = ?', (222, 1) ) +# +# +# # **INSTEAD** of ticket case-1: +# # set transaction read committed no record_version lock timeout N; +# # -- we start Tx with lock_timeout using custom TPB and try just to **update** record which is locked now +# # (but NOT 'SELECT ...'! It is useless with default value of confign parameter ReadConsistency = 1). +# # Message about concurrent transaction (which holds lock) in any case must appear in exception text. +# # NB: NO_rec_version is USELESS in default FB 4.0 config! +# +# +# # Linsk to doc for creating instance of custom TPB and start transaction which using it: +# # https://pythonhosted.org/fdb/reference.html#fdb.TPB +# # https://pythonhosted.org/fdb/reference.html#fdb.Connection.trans +# +# custom_tpb = fdb.TPB() +# custom_tpb.access_mode = fdb.isc_tpb_write +# custom_tpb.isolation_level = (fdb.isc_tpb_read_committed, fdb.isc_tpb_rec_version) # ::: NB ::: NO_rec_version is USELESS in default FB 4.0 config! +# custom_tpb.lock_timeout = 1 +# +# tx2 = con.trans( default_tpb = custom_tpb ) +# tx2.begin() +# cur2=tx2.cursor() +# +# try: +# cur2.execute( 'update test set x = ? where id = ?', (333, 1) ) +# except Exception,e: +# print('Exception in cur2:') +# print( '-'*30 ) +# for x in e: +# print(x) +# print( '-'*30 ) +# finally: +# tx2.commit() +# +# #---------------------------------------------------------- +# +# # This is for ticket case-2: +# # set transaction read committed lock timeout N; +# # select * from test with lock; +# +# custom_tpb.access_mode = fdb.isc_tpb_write +# custom_tpb.isolation_level = fdb.isc_tpb_concurrency +# custom_tpb.lock_timeout = 1 +# +# tx3 = con.trans( default_tpb = custom_tpb ) +# tx3.begin() +# cur3=tx3.cursor() +# +# try: +# cur3.execute( 'select x from test where id = ? with lock', (1,) ) +# for r in cur3: +# print( r[0] ) +# except Exception,e: +# print('Exception in cur3:') +# print( '-'*30 ) +# for x in e: +# print(x) +# print( '-'*30 ) +# finally: +# tx3.commit() +# +# tx1.commit() +# con.close() +# +# +#--- +#act_2 = python_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + - concurrent transaction number is 13 + - concurrent transaction number is 13 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_2988_2(db_2): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_3000.py b/tests/bugs/test_core_3000.py new file mode 100644 index 00000000..03fb5ebb --- /dev/null +++ b/tests/bugs/test_core_3000.py @@ -0,0 +1,52 @@ +#coding:utf-8 +# +# id: bugs.core_3000 +# title: Error on delete user "ADMIN" +# decription: +# Also added sample from core-3110 +# +# tracker_id: CORE-3000 +# min_versions: ['2.5.7'] +# versions: 2.5.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.7 +# resources: None + +substitutions_1 = [('-Token unknown - line.*', '-Token unknown')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Following users should NOT be created: + create user 'ADMIN' password '123'; + create user 'CHECK' password '123'; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Token unknown + -'ADMIN' + + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Token unknown + -'CHECK' + """ + +@pytest.mark.version('>=2.5.7') +def test_core_3000_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_3003.py b/tests/bugs/test_core_3003.py new file mode 100644 index 00000000..5e3830f3 --- /dev/null +++ b/tests/bugs/test_core_3003.py @@ -0,0 +1,69 @@ +#coding:utf-8 +# +# id: bugs.core_3003 +# title: Procedure suspend check may cause restore to fail +# decription: +# Checked on: +# 2.5.9.27126: OK, 0.859s. +# 3.0.5.33086: OK, 1.937s. +# 4.0.0.1378: OK, 7.516s. +# +# tracker_id: CORE-3003 +# min_versions: ['2.1'] +# versions: 2.1 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [('RDB\\$PROCEDURE_SOURCE.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='c3003-ods11.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + select rdb$procedure_name, rdb$procedure_source + from rdb$procedures + where upper( rdb$procedure_name ) in ( upper('sp_01'), upper('sp_02') ) + order by rdb$procedure_name + ; + + select RDB$PROCEDURE_NAME, RDB$PARAMETER_NAME, RDB$PARAMETER_TYPE,RDB$PARAMETER_MECHANISM + from rdb$procedure_parameters + where upper( rdb$procedure_name ) in ( upper('sp_01'), upper('sp_02') ) + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$PROCEDURE_NAME SP_01 + RDB$PROCEDURE_SOURCE 1a:1 + begin + n = 1; + end + + RDB$PROCEDURE_NAME SP_02 + RDB$PROCEDURE_SOURCE 1a:4 + declare n int; + begin + select n from sp_01 into n; + end + + RDB$PROCEDURE_NAME SP_01 + RDB$PARAMETER_NAME N + RDB$PARAMETER_TYPE 1 + RDB$PARAMETER_MECHANISM 0 + """ + +@pytest.mark.version('>=2.1') +def test_core_3003_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3008.py b/tests/bugs/test_core_3008.py new file mode 100644 index 00000000..0ba49ccd --- /dev/null +++ b/tests/bugs/test_core_3008.py @@ -0,0 +1,193 @@ +#coding:utf-8 +# +# id: bugs.core_3008 +# title: Add attachment's CHARACTER SET name into corresponding trace records +# decription: +# 1. Obtain engine_version from built-in context variable. +# 2. Make config for trace in proper format according to FB engine version, +# with adding invalid element 'foo' instead on boolean ('true' or 'false') +# 3. Launch trace session in separate child process using 'FBSVCMGR action_trace_start' +# 4. Run ISQL single 'QUIT;' command in order trace session will register connection. +# 5. Stop trace session. Output its log with filtering only messages related to connect/disconnect event. +# +# Checked on: WI-V2.5.5.26916 (SS, SC, CS); WI-V3.0.0.32008 (SS, SC, CS). Result: OK. +# ::: NB ::: +# Several delays (time.sleep) added in main thread because of OS buffering. Couldn't switch this buffering off. +# +# tracker_id: CORE-3008 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('^((?!ERROR|ELEMENT|SYSDBA:NONE).)*$', ''), ('.*SYSDBA:NONE', 'SYSDBA:NONE'), ('TCPV.*', 'TCP')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import subprocess +# from subprocess import Popen +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# +# # Obtain engine version, 2.5 or 3.0, for make trace config in appropriate format: +# engine=str(db_conn.engine_version) +# db_conn.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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# txt25 = '''# Trace config, format for 2.5. Generated auto, do not edit! +# +# enabled true +# time_threshold 0 +# log_connections true +# +# ''' +# +# # NOTES ABOUT TRACE CONFIG FOR 3.0: +# # 1) Header contains `database` clause in different format vs FB 2.5: its data must be enclosed with '{' '}' +# # 2) Name and value must be separated by EQUALITY sign ('=') in FB-3 trace.conf, otherwise we get runtime error: +# # element "<. . .>" have no attribute value set +# +# txt30 = '''# Trace config, format for 3.0. Generated auto, do not edit! +# database=%[\\\\\\\\/]bugs.core_3008.fdb +# { +# enabled = true +# time_threshold = 0 +# log_connections = true +# } +# ''' +# +# f_trccfg=open( os.path.join(context['temp_directory'],'tmp_trace_3008.cfg'), 'w') +# if engine.startswith('2.5'): +# f_trccfg.write(txt25) +# else: +# f_trccfg.write(txt30) +# f_trccfg.close() +# +# ##################################################### +# # Starting trace session in new child process (async.): +# +# f_trclog = open( os.path.join(context['temp_directory'],'tmp_trace_3008.log'), 'w') +# # Execute a child program in a new process, redirecting STDERR to the same target as of STDOUT: +# p_trace=Popen([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_start", +# "trc_cfg", f_trccfg.name], +# stdout=f_trclog, stderr=subprocess.STDOUT) +# +# # Wait! Trace session is initialized not instantly! +# time.sleep(1) +# +# sqltxt='''quit;''' +# +# runProgram('isql',[dsn,'-ch','utf8'],sqltxt) +# runProgram('isql',[dsn,'-ch','iso8859_1'],sqltxt) +# +# # do NOT remove this otherwise trace log can contain only message about its start before being closed! +# time.sleep(3) +# +# ##################################################### +# # Getting ID of launched trace session and STOP it: +# +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# f_trclst = open( os.path.join(context['temp_directory'],'tmp_trace_3008.lst'), 'w') +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_list"], +# stdout=f_trclst, stderr=subprocess.STDOUT +# ) +# flush_and_close( f_trclst ) +# +# trcssn=0 +# with open( f_trclst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# f_trclst=open(f_trclst.name,'a') +# f_trclst.seek(0,2) +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_stop", +# "trc_id",trcssn], +# stdout=f_trclst, stderr=subprocess.STDOUT +# ) +# flush_and_close( f_trclst ) +# +# # Terminate child process of launched trace session (though it should already be killed): +# p_trace.terminate() +# +# flush_and_close( f_trclog ) +# +# +# # Output log of trace for comparing it with expected: it must contain only TWO events: TRACE_INIT and TRACE_FINI +# # ::: NB ::: Content if trace log is converted to UPPER case in order to reduce change of mismatching with +# # updated trace output in some future versions: +# with open( f_trclog.name,'r') as f: +# print(f.read().upper()) +# +# +# # do NOT remove this delay otherwise get access error 'Windows 32' +# # (The process cannot access the file because it is being used by another process): +# time.sleep(1) +# +# cleanup( [i.name for i in (f_trccfg, f_trclst, f_trclog ) ] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + SYSDBA:NONE, UTF8, TCP + SYSDBA:NONE, UTF8, TCP + SYSDBA:NONE, ISO88591, TCP + SYSDBA:NONE, ISO88591, TCP + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_3008_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_3018.py b/tests/bugs/test_core_3018.py new file mode 100644 index 00000000..c0d82f92 --- /dev/null +++ b/tests/bugs/test_core_3018.py @@ -0,0 +1,67 @@ +#coding:utf-8 +# +# id: bugs.core_3018 +# title: Check ability to use RECREATE, ALTER and CREATE OR ALTER SEQUENCE/GENERATOR statements +# decription: +# NOTE: 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 +# +# For this reason, old code was removed and now test checks only ability to use statements rather than results of them. +# Checked on: 4.0.0.2119; 4.0.0.2164; 3.0.7.33356. +# +# tracker_id: CORE-3018 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('end of command.*', 'end of command')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Only FIRST of following statements must fail with + -- SQLSTATE = 42000 / Dynamic SQL Error / -SQL error code = -104 / -Unexpected end of command. + -- All subsequent must pass w/o errors. + create or alter sequence g01; + + create or alter sequence g02 start with 2; + + create or alter sequence g03 start with 2 increment by 3; + + create or alter sequence g04 restart increment by 4; + + --##################################################### + + recreate sequence g05; + + recreate sequence g06 start with 6; + + recreate sequence g07 start with 7 increment by 8; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Unexpected end of command + """ + +@pytest.mark.version('>=3.0') +def test_core_3018_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_3024.py b/tests/bugs/test_core_3024.py new file mode 100644 index 00000000..9d54953e --- /dev/null +++ b/tests/bugs/test_core_3024.py @@ -0,0 +1,70 @@ +#coding:utf-8 +# +# id: bugs.core_3024 +# title: Error "no current record for fetch operation" after ALTER VIEW +# decription: +# Confirmed error on: WI-V2.5.6.26962 (SC), fixed on: WI-V2.5.6.26963. +# Checked on WI-V3.0.0.32268 (SS, SC, CS). +# Checked on fdb version 1.5. +# +# tracker_id: CORE-3024 +# min_versions: ['2.5.6'] +# versions: 2.5.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.6 +# resources: None + +substitutions_1 = [('-', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# db_conn.close() +# +# att1=kdb.connect(dsn=dsn.encode(),user='SYSDBA',password='masterkey') +# att2=kdb.connect(dsn=dsn.encode(),user='SYSDBA',password='masterkey') +# +# trn1=att1.trans() +# +# cur1=trn1.cursor() +# +# cur1.execute("create table t(a int, b int, c int)") # att_12, tra_4 +# cur1.execute("create view v as select a,b from t") +# trn1.commit() +# +# cur1.execute("insert into t values(1,2,3)") # att_12, tra_5 +# cur1.execute("select * from v") +# trn1.commit() +# +# trn2=att2.trans() +# cur2=trn2.cursor() +# cur2.execute("select * from v") # att_13, tra_7 +# trn2.commit() +# +# cur1.execute("alter view v as select a, b, c from t") # att-12, tra_8 +# trn1.commit() +# +# cur2.execute("select * from v") # att_13, tra_9 +# printData(cur2) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A B C + 1 2 3 + """ + +@pytest.mark.version('>=2.5.6') +@pytest.mark.xfail +def test_core_3024_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_3029.py b/tests/bugs/test_core_3029.py new file mode 100644 index 00000000..7a80d0bc --- /dev/null +++ b/tests/bugs/test_core_3029.py @@ -0,0 +1,120 @@ +#coding:utf-8 +# +# id: bugs.core_3029 +# title: Bugcheck "Too many savepoints (287)" at rollback after exception at EXECUTE BLOCK with exception handler +# decription: +# tracker_id: CORE-3029 +# min_versions: ['2.5.1'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [('line.*', ''), ('col.*', '')] + +init_script_1 = """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_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Database: localhost:C:\\Users\\win7\\Firebird_tests\\fbt-repository\\tmp\\bugs.core_3029.fdb, User: SYSDBA +SQL> SQL> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> + ID DID DEP PID +============ ============ ============ ============ + 2 4 3 + 2 4 3 +SQL> SQL> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> CON> SQL> + ID DID DEP PID +============ ============ ============ ============ + 2 4 3 +SQL> SQL>""" +expected_stderr_1 = """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 +""" + +@pytest.mark.version('>=2.5.3') +def test_core_3029_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3038.py b/tests/bugs/test_core_3038.py new file mode 100644 index 00000000..757a3744 --- /dev/null +++ b/tests/bugs/test_core_3038.py @@ -0,0 +1,52 @@ +#coding:utf-8 +# +# id: bugs.core_3038 +# title: Wrong resultset +# decription: The insert failed because a column definition includes validation constraints. validation error for variable +# tracker_id: CORE-3038 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create domain money as numeric(15,4); + commit; + + create table cl_cashprice (id integer not null, price money not null); + commit; + + set term ^ ; + create procedure testp (i_id integer, i_price type of column cl_cashprice.price) + as + declare variable goodsprice money; + begin + goodsprice = null; + if (:goodsprice is not null) + then goodsprice = 6; + end^ + set term ; ^ + commit; + + execute procedure testp(1, 6); + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5') +def test_core_3038_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_3045.py b/tests/bugs/test_core_3045.py new file mode 100644 index 00000000..e64f82fe --- /dev/null +++ b/tests/bugs/test_core_3045.py @@ -0,0 +1,62 @@ +#coding:utf-8 +# +# id: bugs.core_3045 +# title: "conversion error from string" after change of field type from BIGINT to VARCHAR(21) +# decription: +# tracker_id: CORE-3045 +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE TEST1( + ID INTEGER, + TEST_FIELD BIGINT, + + PRIMARY KEY(ID) +); + +COMMIT; + +INSERT INTO TEST1(ID, TEST_FIELD) +VALUES(1, 234); + +COMMIT;""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ALTER TABLE TEST1 + ALTER TEST_FIELD TYPE VARCHAR(21); + +COMMIT; + +SELECT ID, TEST_FIELD +FROM TEST1 +WHERE TEST_FIELD = 'A'; +SELECT ID, TEST_FIELD +FROM TEST1 +WHERE TEST_FIELD != 'A'; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID TEST_FIELD +============ ===================== + 1 234 + +""" + +@pytest.mark.version('>=2.5.0') +def test_core_3045_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3047.py b/tests/bugs/test_core_3047.py new file mode 100644 index 00000000..757a36a5 --- /dev/null +++ b/tests/bugs/test_core_3047.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_3047 +# title: Wrong logic is used to resolve EXECUTE BLOCK parameters collations +# decription: +# tracker_id: CORE-3047 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- In 2.5 (checked on WI-V2.5.5.26861): + -- Statement failed, SQLSTATE = HY004 + -- Dynamic SQL Error + -- -SQL error code = -204 + -- -Data type unknown + -- -COLLATION WIN_PTBR for CHARACTER SET UTF8 is not defined + -- (See ticket issue: "WIN_PTBR is tried to be resolved agains database charset instead of client charset: incorrect") + -- In 3.0.0.31827 (WI- and LI-) works fine: + set term ^; + execute block returns (c varchar(10) collate win_ptbr) as + begin + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +def test_core_3047_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_3052.py b/tests/bugs/test_core_3052.py new file mode 100644 index 00000000..8ad290f0 --- /dev/null +++ b/tests/bugs/test_core_3052.py @@ -0,0 +1,77 @@ +#coding:utf-8 +# +# id: bugs.core_3052 +# title: Wrong resultset +# decription: Empty rowset when selecting from table with compound index on PXW_HUNDC-collated fields +# tracker_id: CORE-3052 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='WIN1250', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- NB: do NOT downgrate minimal version to 2.5 - at least for 2.5.4.26857 + -- following queries return zero rows. + + create domain xvar10n as varchar(160) character set WIN1250 not null collate PXW_HUNDC; + create domain xint as int; + commit; + + create table tmp_test ( + m1 xvar10n + ,m2 xvar10n + ,val xint + ); + commit; + + alter table tmp_test add constraint tmp_test_uk1 unique (m1, m2); + commit; + + insert into tmp_test (m1, m2, val) values ('A', 'C1', 1); + insert into tmp_test (m1, m2, val) values ('A', 'C2', 2); + insert into tmp_test (m1, m2, val) values ('A', 'D2', 3); + insert into tmp_test (m1, m2, val) values ('A', 'M3', 3); + + set list on; + select * + from tmp_test te + where te.m1 = 'A' and te.m2 like 'C%'; + + select * + from tmp_test te + where te.m1 = 'A' and te.m2 like 'D%'; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + M1 A + M2 C1 + VAL 1 + + M1 A + M2 C2 + VAL 2 + + M1 A + M2 D2 + VAL 3 + """ + +@pytest.mark.version('>=3.0') +def test_core_3052_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3055.py b/tests/bugs/test_core_3055.py new file mode 100644 index 00000000..74bf2afa --- /dev/null +++ b/tests/bugs/test_core_3055.py @@ -0,0 +1,2052 @@ +#coding:utf-8 +# +# id: bugs.core_3055 +# title: Variable/argument name could be absent or be wrong in error messages when more than 256 variables are used +# decription: +# tracker_id: CORE-3055 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('-At block line: [\\d]+, col: [\\d]+', '-At block line')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create domain dm_nn int not null; + commit; + set term ^; + execute block as + declare v_1 int; + declare v_2 int; + declare v_3 int; + declare v_4 int; + declare v_5 int; + declare v_6 int; + declare v_7 int; + declare v_8 int; + declare v_9 int; + declare v_10 int; + declare v_11 int; + declare v_12 int; + declare v_13 int; + declare v_14 int; + declare v_15 int; + declare v_16 int; + declare v_17 int; + declare v_18 int; + declare v_19 int; + declare v_20 int; + declare v_21 int; + declare v_22 int; + declare v_23 int; + declare v_24 int; + declare v_25 int; + declare v_26 int; + declare v_27 int; + declare v_28 int; + declare v_29 int; + declare v_30 int; + declare v_31 int; + declare v_32 int; + declare v_33 int; + declare v_34 int; + declare v_35 int; + declare v_36 int; + declare v_37 int; + declare v_38 int; + declare v_39 int; + declare v_40 int; + declare v_41 int; + declare v_42 int; + declare v_43 int; + declare v_44 int; + declare v_45 int; + declare v_46 int; + declare v_47 int; + declare v_48 int; + declare v_49 int; + declare v_50 int; + declare v_51 int; + declare v_52 int; + declare v_53 int; + declare v_54 int; + declare v_55 int; + declare v_56 int; + declare v_57 int; + declare v_58 int; + declare v_59 int; + declare v_60 int; + declare v_61 int; + declare v_62 int; + declare v_63 int; + declare v_64 int; + declare v_65 int; + declare v_66 int; + declare v_67 int; + declare v_68 int; + declare v_69 int; + declare v_70 int; + declare v_71 int; + declare v_72 int; + declare v_73 int; + declare v_74 int; + declare v_75 int; + declare v_76 int; + declare v_77 int; + declare v_78 int; + declare v_79 int; + declare v_80 int; + declare v_81 int; + declare v_82 int; + declare v_83 int; + declare v_84 int; + declare v_85 int; + declare v_86 int; + declare v_87 int; + declare v_88 int; + declare v_89 int; + declare v_90 int; + declare v_91 int; + declare v_92 int; + declare v_93 int; + declare v_94 int; + declare v_95 int; + declare v_96 int; + declare v_97 int; + declare v_98 int; + declare v_99 int; + declare v_100 int; + declare v_101 int; + declare v_102 int; + declare v_103 int; + declare v_104 int; + declare v_105 int; + declare v_106 int; + declare v_107 int; + declare v_108 int; + declare v_109 int; + declare v_110 int; + declare v_111 int; + declare v_112 int; + declare v_113 int; + declare v_114 int; + declare v_115 int; + declare v_116 int; + declare v_117 int; + declare v_118 int; + declare v_119 int; + declare v_120 int; + declare v_121 int; + declare v_122 int; + declare v_123 int; + declare v_124 int; + declare v_125 int; + declare v_126 int; + declare v_127 int; + declare v_128 int; + declare v_129 int; + declare v_130 int; + declare v_131 int; + declare v_132 int; + declare v_133 int; + declare v_134 int; + declare v_135 int; + declare v_136 int; + declare v_137 int; + declare v_138 int; + declare v_139 int; + declare v_140 int; + declare v_141 int; + declare v_142 int; + declare v_143 int; + declare v_144 int; + declare v_145 int; + declare v_146 int; + declare v_147 int; + declare v_148 int; + declare v_149 int; + declare v_150 int; + declare v_151 int; + declare v_152 int; + declare v_153 int; + declare v_154 int; + declare v_155 int; + declare v_156 int; + declare v_157 int; + declare v_158 int; + declare v_159 int; + declare v_160 int; + declare v_161 int; + declare v_162 int; + declare v_163 int; + declare v_164 int; + declare v_165 int; + declare v_166 int; + declare v_167 int; + declare v_168 int; + declare v_169 int; + declare v_170 int; + declare v_171 int; + declare v_172 int; + declare v_173 int; + declare v_174 int; + declare v_175 int; + declare v_176 int; + declare v_177 int; + declare v_178 int; + declare v_179 int; + declare v_180 int; + declare v_181 int; + declare v_182 int; + declare v_183 int; + declare v_184 int; + declare v_185 int; + declare v_186 int; + declare v_187 int; + declare v_188 int; + declare v_189 int; + declare v_190 int; + declare v_191 int; + declare v_192 int; + declare v_193 int; + declare v_194 int; + declare v_195 int; + declare v_196 int; + declare v_197 int; + declare v_198 int; + declare v_199 int; + declare v_200 int; + declare v_201 int; + declare v_202 int; + declare v_203 int; + declare v_204 int; + declare v_205 int; + declare v_206 int; + declare v_207 int; + declare v_208 int; + declare v_209 int; + declare v_210 int; + declare v_211 int; + declare v_212 int; + declare v_213 int; + declare v_214 int; + declare v_215 int; + declare v_216 int; + declare v_217 int; + declare v_218 int; + declare v_219 int; + declare v_220 int; + declare v_221 int; + declare v_222 int; + declare v_223 int; + declare v_224 int; + declare v_225 int; + declare v_226 int; + declare v_227 int; + declare v_228 int; + declare v_229 int; + declare v_230 int; + declare v_231 int; + declare v_232 int; + declare v_233 int; + declare v_234 int; + declare v_235 int; + declare v_236 int; + declare v_237 int; + declare v_238 int; + declare v_239 int; + declare v_240 int; + declare v_241 int; + declare v_242 int; + declare v_243 int; + declare v_244 int; + declare v_245 int; + declare v_246 int; + declare v_247 int; + declare v_248 int; + declare v_249 int; + declare v_250 int; + declare v_251 int; + declare v_252 int; + declare v_253 int; + declare v_254 int; + declare v_255 int; + declare v_256 int; + declare v_257 int; + declare v_258 int; + declare v_259 int; + declare v_260 int; + declare v_261 int; + declare v_262 int; + declare v_263 int; + declare v_264 int; + declare v_265 int; + declare v_266 int; + declare v_267 int; + declare v_268 int; + declare v_269 int; + declare v_270 int; + declare v_271 int; + declare v_272 int; + declare v_273 int; + declare v_274 int; + declare v_275 int; + declare v_276 int; + declare v_277 int; + declare v_278 int; + declare v_279 int; + declare v_280 int; + declare v_281 int; + declare v_282 int; + declare v_283 int; + declare v_284 int; + declare v_285 int; + declare v_286 int; + declare v_287 int; + declare v_288 int; + declare v_289 int; + declare v_290 int; + declare v_291 int; + declare v_292 int; + declare v_293 int; + declare v_294 int; + declare v_295 int; + declare v_296 int; + declare v_297 int; + declare v_298 int; + declare v_299 int; + declare v_300 int; + declare v_301 int; + declare v_302 int; + declare v_303 int; + declare v_304 int; + declare v_305 int; + declare v_306 int; + declare v_307 int; + declare v_308 int; + declare v_309 int; + declare v_310 int; + declare v_311 int; + declare v_312 int; + declare v_313 int; + declare v_314 int; + declare v_315 int; + declare v_316 int; + declare v_317 int; + declare v_318 int; + declare v_319 int; + declare v_320 int; + declare v_321 int; + declare v_322 int; + declare v_323 int; + declare v_324 int; + declare v_325 int; + declare v_326 int; + declare v_327 int; + declare v_328 int; + declare v_329 int; + declare v_330 int; + declare v_331 int; + declare v_332 int; + declare v_333 int; + declare v_334 int; + declare v_335 int; + declare v_336 int; + declare v_337 int; + declare v_338 int; + declare v_339 int; + declare v_340 int; + declare v_341 int; + declare v_342 int; + declare v_343 int; + declare v_344 int; + declare v_345 int; + declare v_346 int; + declare v_347 int; + declare v_348 int; + declare v_349 int; + declare v_350 int; + declare v_351 int; + declare v_352 int; + declare v_353 int; + declare v_354 int; + declare v_355 int; + declare v_356 int; + declare v_357 int; + declare v_358 int; + declare v_359 int; + declare v_360 int; + declare v_361 int; + declare v_362 int; + declare v_363 int; + declare v_364 int; + declare v_365 int; + declare v_366 int; + declare v_367 int; + declare v_368 int; + declare v_369 int; + declare v_370 int; + declare v_371 int; + declare v_372 int; + declare v_373 int; + declare v_374 int; + declare v_375 int; + declare v_376 int; + declare v_377 int; + declare v_378 int; + declare v_379 int; + declare v_380 int; + declare v_381 int; + declare v_382 int; + declare v_383 int; + declare v_384 int; + declare v_385 int; + declare v_386 int; + declare v_387 int; + declare v_388 int; + declare v_389 int; + declare v_390 int; + declare v_391 int; + declare v_392 int; + declare v_393 int; + declare v_394 int; + declare v_395 int; + declare v_396 int; + declare v_397 int; + declare v_398 int; + declare v_399 int; + declare v_400 int; + declare v_401 int; + declare v_402 int; + declare v_403 int; + declare v_404 int; + declare v_405 int; + declare v_406 int; + declare v_407 int; + declare v_408 int; + declare v_409 int; + declare v_410 int; + declare v_411 int; + declare v_412 int; + declare v_413 int; + declare v_414 int; + declare v_415 int; + declare v_416 int; + declare v_417 int; + declare v_418 int; + declare v_419 int; + declare v_420 int; + declare v_421 int; + declare v_422 int; + declare v_423 int; + declare v_424 int; + declare v_425 int; + declare v_426 int; + declare v_427 int; + declare v_428 int; + declare v_429 int; + declare v_430 int; + declare v_431 int; + declare v_432 int; + declare v_433 int; + declare v_434 int; + declare v_435 int; + declare v_436 int; + declare v_437 int; + declare v_438 int; + declare v_439 int; + declare v_440 int; + declare v_441 int; + declare v_442 int; + declare v_443 int; + declare v_444 int; + declare v_445 int; + declare v_446 int; + declare v_447 int; + declare v_448 int; + declare v_449 int; + declare v_450 int; + declare v_451 int; + declare v_452 int; + declare v_453 int; + declare v_454 int; + declare v_455 int; + declare v_456 int; + declare v_457 int; + declare v_458 int; + declare v_459 int; + declare v_460 int; + declare v_461 int; + declare v_462 int; + declare v_463 int; + declare v_464 int; + declare v_465 int; + declare v_466 int; + declare v_467 int; + declare v_468 int; + declare v_469 int; + declare v_470 int; + declare v_471 int; + declare v_472 int; + declare v_473 int; + declare v_474 int; + declare v_475 int; + declare v_476 int; + declare v_477 int; + declare v_478 int; + declare v_479 int; + declare v_480 int; + declare v_481 int; + declare v_482 int; + declare v_483 int; + declare v_484 int; + declare v_485 int; + declare v_486 int; + declare v_487 int; + declare v_488 int; + declare v_489 int; + declare v_490 int; + declare v_491 int; + declare v_492 int; + declare v_493 int; + declare v_494 int; + declare v_495 int; + declare v_496 int; + declare v_497 int; + declare v_498 int; + declare v_499 int; + declare v_500 int; + declare v_501 int; + declare v_502 int; + declare v_503 int; + declare v_504 int; + declare v_505 int; + declare v_506 int; + declare v_507 int; + declare v_508 int; + declare v_509 int; + declare v_510 int; + declare v_511 int; + declare v_512 int; + declare v_513 int; + declare v_514 int; + declare v_515 int; + declare v_516 int; + declare v_517 int; + declare v_518 int; + declare v_519 int; + declare v_520 int; + declare v_521 int; + declare v_522 int; + declare v_523 int; + declare v_524 int; + declare v_525 int; + declare v_526 int; + declare v_527 int; + declare v_528 int; + declare v_529 int; + declare v_530 int; + declare v_531 int; + declare v_532 int; + declare v_533 int; + declare v_534 int; + declare v_535 int; + declare v_536 int; + declare v_537 int; + declare v_538 int; + declare v_539 int; + declare v_540 int; + declare v_541 int; + declare v_542 int; + declare v_543 int; + declare v_544 int; + declare v_545 int; + declare v_546 int; + declare v_547 int; + declare v_548 int; + declare v_549 int; + declare v_550 int; + declare v_551 int; + declare v_552 int; + declare v_553 int; + declare v_554 int; + declare v_555 int; + declare v_556 int; + declare v_557 int; + declare v_558 int; + declare v_559 int; + declare v_560 int; + declare v_561 int; + declare v_562 int; + declare v_563 int; + declare v_564 int; + declare v_565 int; + declare v_566 int; + declare v_567 int; + declare v_568 int; + declare v_569 int; + declare v_570 int; + declare v_571 int; + declare v_572 int; + declare v_573 int; + declare v_574 int; + declare v_575 int; + declare v_576 int; + declare v_577 int; + declare v_578 int; + declare v_579 int; + declare v_580 int; + declare v_581 int; + declare v_582 int; + declare v_583 int; + declare v_584 int; + declare v_585 int; + declare v_586 int; + declare v_587 int; + declare v_588 int; + declare v_589 int; + declare v_590 int; + declare v_591 int; + declare v_592 int; + declare v_593 int; + declare v_594 int; + declare v_595 int; + declare v_596 int; + declare v_597 int; + declare v_598 int; + declare v_599 int; + declare v_600 int; + declare v_601 int; + declare v_602 int; + declare v_603 int; + declare v_604 int; + declare v_605 int; + declare v_606 int; + declare v_607 int; + declare v_608 int; + declare v_609 int; + declare v_610 int; + declare v_611 int; + declare v_612 int; + declare v_613 int; + declare v_614 int; + declare v_615 int; + declare v_616 int; + declare v_617 int; + declare v_618 int; + declare v_619 int; + declare v_620 int; + declare v_621 int; + declare v_622 int; + declare v_623 int; + declare v_624 int; + declare v_625 int; + declare v_626 int; + declare v_627 int; + declare v_628 int; + declare v_629 int; + declare v_630 int; + declare v_631 int; + declare v_632 int; + declare v_633 int; + declare v_634 int; + declare v_635 int; + declare v_636 int; + declare v_637 int; + declare v_638 int; + declare v_639 int; + declare v_640 int; + declare v_641 int; + declare v_642 int; + declare v_643 int; + declare v_644 int; + declare v_645 int; + declare v_646 int; + declare v_647 int; + declare v_648 int; + declare v_649 int; + declare v_650 int; + declare v_651 int; + declare v_652 int; + declare v_653 int; + declare v_654 int; + declare v_655 int; + declare v_656 int; + declare v_657 int; + declare v_658 int; + declare v_659 int; + declare v_660 int; + declare v_661 int; + declare v_662 int; + declare v_663 int; + declare v_664 int; + declare v_665 int; + declare v_666 int; + declare v_667 int; + declare v_668 int; + declare v_669 int; + declare v_670 int; + declare v_671 int; + declare v_672 int; + declare v_673 int; + declare v_674 int; + declare v_675 int; + declare v_676 int; + declare v_677 int; + declare v_678 int; + declare v_679 int; + declare v_680 int; + declare v_681 int; + declare v_682 int; + declare v_683 int; + declare v_684 int; + declare v_685 int; + declare v_686 int; + declare v_687 int; + declare v_688 int; + declare v_689 int; + declare v_690 int; + declare v_691 int; + declare v_692 int; + declare v_693 int; + declare v_694 int; + declare v_695 int; + declare v_696 int; + declare v_697 int; + declare v_698 int; + declare v_699 int; + declare v_700 int; + declare v_701 int; + declare v_702 int; + declare v_703 int; + declare v_704 int; + declare v_705 int; + declare v_706 int; + declare v_707 int; + declare v_708 int; + declare v_709 int; + declare v_710 int; + declare v_711 int; + declare v_712 int; + declare v_713 int; + declare v_714 int; + declare v_715 int; + declare v_716 int; + declare v_717 int; + declare v_718 int; + declare v_719 int; + declare v_720 int; + declare v_721 int; + declare v_722 int; + declare v_723 int; + declare v_724 int; + declare v_725 int; + declare v_726 int; + declare v_727 int; + declare v_728 int; + declare v_729 int; + declare v_730 int; + declare v_731 int; + declare v_732 int; + declare v_733 int; + declare v_734 int; + declare v_735 int; + declare v_736 int; + declare v_737 int; + declare v_738 int; + declare v_739 int; + declare v_740 int; + declare v_741 int; + declare v_742 int; + declare v_743 int; + declare v_744 int; + declare v_745 int; + declare v_746 int; + declare v_747 int; + declare v_748 int; + declare v_749 int; + declare v_750 int; + declare v_751 int; + declare v_752 int; + declare v_753 int; + declare v_754 int; + declare v_755 int; + declare v_756 int; + declare v_757 int; + declare v_758 int; + declare v_759 int; + declare v_760 int; + declare v_761 int; + declare v_762 int; + declare v_763 int; + declare v_764 int; + declare v_765 int; + declare v_766 int; + declare v_767 int; + declare v_768 int; + declare v_769 int; + declare v_770 int; + declare v_771 int; + declare v_772 int; + declare v_773 int; + declare v_774 int; + declare v_775 int; + declare v_776 int; + declare v_777 int; + declare v_778 int; + declare v_779 int; + declare v_780 int; + declare v_781 int; + declare v_782 int; + declare v_783 int; + declare v_784 int; + declare v_785 int; + declare v_786 int; + declare v_787 int; + declare v_788 int; + declare v_789 int; + declare v_790 int; + declare v_791 int; + declare v_792 int; + declare v_793 int; + declare v_794 int; + declare v_795 int; + declare v_796 int; + declare v_797 int; + declare v_798 int; + declare v_799 int; + declare v_800 int; + declare v_801 int; + declare v_802 int; + declare v_803 int; + declare v_804 int; + declare v_805 int; + declare v_806 int; + declare v_807 int; + declare v_808 int; + declare v_809 int; + declare v_810 int; + declare v_811 int; + declare v_812 int; + declare v_813 int; + declare v_814 int; + declare v_815 int; + declare v_816 int; + declare v_817 int; + declare v_818 int; + declare v_819 int; + declare v_820 int; + declare v_821 int; + declare v_822 int; + declare v_823 int; + declare v_824 int; + declare v_825 int; + declare v_826 int; + declare v_827 int; + declare v_828 int; + declare v_829 int; + declare v_830 int; + declare v_831 int; + declare v_832 int; + declare v_833 int; + declare v_834 int; + declare v_835 int; + declare v_836 int; + declare v_837 int; + declare v_838 int; + declare v_839 int; + declare v_840 int; + declare v_841 int; + declare v_842 int; + declare v_843 int; + declare v_844 int; + declare v_845 int; + declare v_846 int; + declare v_847 int; + declare v_848 int; + declare v_849 int; + declare v_850 int; + declare v_851 int; + declare v_852 int; + declare v_853 int; + declare v_854 int; + declare v_855 int; + declare v_856 int; + declare v_857 int; + declare v_858 int; + declare v_859 int; + declare v_860 int; + declare v_861 int; + declare v_862 int; + declare v_863 int; + declare v_864 int; + declare v_865 int; + declare v_866 int; + declare v_867 int; + declare v_868 int; + declare v_869 int; + declare v_870 int; + declare v_871 int; + declare v_872 int; + declare v_873 int; + declare v_874 int; + declare v_875 int; + declare v_876 int; + declare v_877 int; + declare v_878 int; + declare v_879 int; + declare v_880 int; + declare v_881 int; + declare v_882 int; + declare v_883 int; + declare v_884 int; + declare v_885 int; + declare v_886 int; + declare v_887 int; + declare v_888 int; + declare v_889 int; + declare v_890 int; + declare v_891 int; + declare v_892 int; + declare v_893 int; + declare v_894 int; + declare v_895 int; + declare v_896 int; + declare v_897 int; + declare v_898 int; + declare v_899 int; + declare v_900 int; + declare v_901 int; + declare v_902 int; + declare v_903 int; + declare v_904 int; + declare v_905 int; + declare v_906 int; + declare v_907 int; + declare v_908 int; + declare v_909 int; + declare v_910 int; + declare v_911 int; + declare v_912 int; + declare v_913 int; + declare v_914 int; + declare v_915 int; + declare v_916 int; + declare v_917 int; + declare v_918 int; + declare v_919 int; + declare v_920 int; + declare v_921 int; + declare v_922 int; + declare v_923 int; + declare v_924 int; + declare v_925 int; + declare v_926 int; + declare v_927 int; + declare v_928 int; + declare v_929 int; + declare v_930 int; + declare v_931 int; + declare v_932 int; + declare v_933 int; + declare v_934 int; + declare v_935 int; + declare v_936 int; + declare v_937 int; + declare v_938 int; + declare v_939 int; + declare v_940 int; + declare v_941 int; + declare v_942 int; + declare v_943 int; + declare v_944 int; + declare v_945 int; + declare v_946 int; + declare v_947 int; + declare v_948 int; + declare v_949 int; + declare v_950 int; + declare v_951 int; + declare v_952 int; + declare v_953 int; + declare v_954 int; + declare v_955 int; + declare v_956 int; + declare v_957 int; + declare v_958 int; + declare v_959 int; + declare v_960 int; + declare v_961 int; + declare v_962 int; + declare v_963 int; + declare v_964 int; + declare v_965 int; + declare v_966 int; + declare v_967 int; + declare v_968 int; + declare v_969 int; + declare v_970 int; + declare v_971 int; + declare v_972 int; + declare v_973 int; + declare v_974 int; + declare v_975 int; + declare v_976 int; + declare v_977 int; + declare v_978 int; + declare v_979 int; + declare v_980 int; + declare v_981 int; + declare v_982 int; + declare v_983 int; + declare v_984 int; + declare v_985 int; + declare v_986 int; + declare v_987 int; + declare v_988 int; + declare v_989 int; + declare v_990 int; + declare v_991 int; + declare v_992 int; + declare v_993 int; + declare v_994 int; + declare v_995 int; + declare v_996 int; + declare v_997 int; + declare v_998 int; + declare v_999 int; + declare v_1000 int; + declare v_1001 int; + declare v_1002 int; + declare v_1003 int; + declare v_1004 int; + declare v_1005 int; + declare v_1006 int; + declare v_1007 int; + declare v_1008 int; + declare v_1009 int; + declare v_1010 int; + declare v_1011 int; + declare v_1012 int; + declare v_1013 int; + declare v_1014 int; + declare v_1015 int; + declare v_1016 int; + declare v_1017 int; + declare v_1018 int; + declare v_1019 int; + declare v_1020 int; + declare v_1021 int; + declare v_1022 int; + declare v_1023 int; + declare v_1024 int; + declare v_1025 int; + declare v_1026 int; + declare v_1027 int; + declare v_1028 int; + declare v_1029 int; + declare v_1030 int; + declare v_1031 int; + declare v_1032 int; + declare v_1033 int; + declare v_1034 int; + declare v_1035 int; + declare v_1036 int; + declare v_1037 int; + declare v_1038 int; + declare v_1039 int; + declare v_1040 int; + declare v_1041 int; + declare v_1042 int; + declare v_1043 int; + declare v_1044 int; + declare v_1045 int; + declare v_1046 int; + declare v_1047 int; + declare v_1048 int; + declare v_1049 int; + declare v_1050 int; + declare v_1051 int; + declare v_1052 int; + declare v_1053 int; + declare v_1054 int; + declare v_1055 int; + declare v_1056 int; + declare v_1057 int; + declare v_1058 int; + declare v_1059 int; + declare v_1060 int; + declare v_1061 int; + declare v_1062 int; + declare v_1063 int; + declare v_1064 int; + declare v_1065 int; + declare v_1066 int; + declare v_1067 int; + declare v_1068 int; + declare v_1069 int; + declare v_1070 int; + declare v_1071 int; + declare v_1072 int; + declare v_1073 int; + declare v_1074 int; + declare v_1075 int; + declare v_1076 int; + declare v_1077 int; + declare v_1078 int; + declare v_1079 int; + declare v_1080 int; + declare v_1081 int; + declare v_1082 int; + declare v_1083 int; + declare v_1084 int; + declare v_1085 int; + declare v_1086 int; + declare v_1087 int; + declare v_1088 int; + declare v_1089 int; + declare v_1090 int; + declare v_1091 int; + declare v_1092 int; + declare v_1093 int; + declare v_1094 int; + declare v_1095 int; + declare v_1096 int; + declare v_1097 int; + declare v_1098 int; + declare v_1099 int; + declare v_1100 int; + declare v_1101 int; + declare v_1102 int; + declare v_1103 int; + declare v_1104 int; + declare v_1105 int; + declare v_1106 int; + declare v_1107 int; + declare v_1108 int; + declare v_1109 int; + declare v_1110 int; + declare v_1111 int; + declare v_1112 int; + declare v_1113 int; + declare v_1114 int; + declare v_1115 int; + declare v_1116 int; + declare v_1117 int; + declare v_1118 int; + declare v_1119 int; + declare v_1120 int; + declare v_1121 int; + declare v_1122 int; + declare v_1123 int; + declare v_1124 int; + declare v_1125 int; + declare v_1126 int; + declare v_1127 int; + declare v_1128 int; + declare v_1129 int; + declare v_1130 int; + declare v_1131 int; + declare v_1132 int; + declare v_1133 int; + declare v_1134 int; + declare v_1135 int; + declare v_1136 int; + declare v_1137 int; + declare v_1138 int; + declare v_1139 int; + declare v_1140 int; + declare v_1141 int; + declare v_1142 int; + declare v_1143 int; + declare v_1144 int; + declare v_1145 int; + declare v_1146 int; + declare v_1147 int; + declare v_1148 int; + declare v_1149 int; + declare v_1150 int; + declare v_1151 int; + declare v_1152 int; + declare v_1153 int; + declare v_1154 int; + declare v_1155 int; + declare v_1156 int; + declare v_1157 int; + declare v_1158 int; + declare v_1159 int; + declare v_1160 int; + declare v_1161 int; + declare v_1162 int; + declare v_1163 int; + declare v_1164 int; + declare v_1165 int; + declare v_1166 int; + declare v_1167 int; + declare v_1168 int; + declare v_1169 int; + declare v_1170 int; + declare v_1171 int; + declare v_1172 int; + declare v_1173 int; + declare v_1174 int; + declare v_1175 int; + declare v_1176 int; + declare v_1177 int; + declare v_1178 int; + declare v_1179 int; + declare v_1180 int; + declare v_1181 int; + declare v_1182 int; + declare v_1183 int; + declare v_1184 int; + declare v_1185 int; + declare v_1186 int; + declare v_1187 int; + declare v_1188 int; + declare v_1189 int; + declare v_1190 int; + declare v_1191 int; + declare v_1192 int; + declare v_1193 int; + declare v_1194 int; + declare v_1195 int; + declare v_1196 int; + declare v_1197 int; + declare v_1198 int; + declare v_1199 int; + declare v_1200 int; + declare v_1201 int; + declare v_1202 int; + declare v_1203 int; + declare v_1204 int; + declare v_1205 int; + declare v_1206 int; + declare v_1207 int; + declare v_1208 int; + declare v_1209 int; + declare v_1210 int; + declare v_1211 int; + declare v_1212 int; + declare v_1213 int; + declare v_1214 int; + declare v_1215 int; + declare v_1216 int; + declare v_1217 int; + declare v_1218 int; + declare v_1219 int; + declare v_1220 int; + declare v_1221 int; + declare v_1222 int; + declare v_1223 int; + declare v_1224 int; + declare v_1225 int; + declare v_1226 int; + declare v_1227 int; + declare v_1228 int; + declare v_1229 int; + declare v_1230 int; + declare v_1231 int; + declare v_1232 int; + declare v_1233 int; + declare v_1234 int; + declare v_1235 int; + declare v_1236 int; + declare v_1237 int; + declare v_1238 int; + declare v_1239 int; + declare v_1240 int; + declare v_1241 int; + declare v_1242 int; + declare v_1243 int; + declare v_1244 int; + declare v_1245 int; + declare v_1246 int; + declare v_1247 int; + declare v_1248 int; + declare v_1249 int; + declare v_1250 int; + declare v_1251 int; + declare v_1252 int; + declare v_1253 int; + declare v_1254 int; + declare v_1255 int; + declare v_1256 int; + declare v_1257 int; + declare v_1258 int; + declare v_1259 int; + declare v_1260 int; + declare v_1261 int; + declare v_1262 int; + declare v_1263 int; + declare v_1264 int; + declare v_1265 int; + declare v_1266 int; + declare v_1267 int; + declare v_1268 int; + declare v_1269 int; + declare v_1270 int; + declare v_1271 int; + declare v_1272 int; + declare v_1273 int; + declare v_1274 int; + declare v_1275 int; + declare v_1276 int; + declare v_1277 int; + declare v_1278 int; + declare v_1279 int; + declare v_1280 int; + declare v_1281 int; + declare v_1282 int; + declare v_1283 int; + declare v_1284 int; + declare v_1285 int; + declare v_1286 int; + declare v_1287 int; + declare v_1288 int; + declare v_1289 int; + declare v_1290 int; + declare v_1291 int; + declare v_1292 int; + declare v_1293 int; + declare v_1294 int; + declare v_1295 int; + declare v_1296 int; + declare v_1297 int; + declare v_1298 int; + declare v_1299 int; + declare v_1300 int; + declare v_1301 int; + declare v_1302 int; + declare v_1303 int; + declare v_1304 int; + declare v_1305 int; + declare v_1306 int; + declare v_1307 int; + declare v_1308 int; + declare v_1309 int; + declare v_1310 int; + declare v_1311 int; + declare v_1312 int; + declare v_1313 int; + declare v_1314 int; + declare v_1315 int; + declare v_1316 int; + declare v_1317 int; + declare v_1318 int; + declare v_1319 int; + declare v_1320 int; + declare v_1321 int; + declare v_1322 int; + declare v_1323 int; + declare v_1324 int; + declare v_1325 int; + declare v_1326 int; + declare v_1327 int; + declare v_1328 int; + declare v_1329 int; + declare v_1330 int; + declare v_1331 int; + declare v_1332 int; + declare v_1333 int; + declare v_1334 int; + declare v_1335 int; + declare v_1336 int; + declare v_1337 int; + declare v_1338 int; + declare v_1339 int; + declare v_1340 int; + declare v_1341 int; + declare v_1342 int; + declare v_1343 int; + declare v_1344 int; + declare v_1345 int; + declare v_1346 int; + declare v_1347 int; + declare v_1348 int; + declare v_1349 int; + declare v_1350 int; + declare v_1351 int; + declare v_1352 int; + declare v_1353 int; + declare v_1354 int; + declare v_1355 int; + declare v_1356 int; + declare v_1357 int; + declare v_1358 int; + declare v_1359 int; + declare v_1360 int; + declare v_1361 int; + declare v_1362 int; + declare v_1363 int; + declare v_1364 int; + declare v_1365 int; + declare v_1366 int; + declare v_1367 int; + declare v_1368 int; + declare v_1369 int; + declare v_1370 int; + declare v_1371 int; + declare v_1372 int; + declare v_1373 int; + declare v_1374 int; + declare v_1375 int; + declare v_1376 int; + declare v_1377 int; + declare v_1378 int; + declare v_1379 int; + declare v_1380 int; + declare v_1381 int; + declare v_1382 int; + declare v_1383 int; + declare v_1384 int; + declare v_1385 int; + declare v_1386 int; + declare v_1387 int; + declare v_1388 int; + declare v_1389 int; + declare v_1390 int; + declare v_1391 int; + declare v_1392 int; + declare v_1393 int; + declare v_1394 int; + declare v_1395 int; + declare v_1396 int; + declare v_1397 int; + declare v_1398 int; + declare v_1399 int; + declare v_1400 int; + declare v_1401 int; + declare v_1402 int; + declare v_1403 int; + declare v_1404 int; + declare v_1405 int; + declare v_1406 int; + declare v_1407 int; + declare v_1408 int; + declare v_1409 int; + declare v_1410 int; + declare v_1411 int; + declare v_1412 int; + declare v_1413 int; + declare v_1414 int; + declare v_1415 int; + declare v_1416 int; + declare v_1417 int; + declare v_1418 int; + declare v_1419 int; + declare v_1420 int; + declare v_1421 int; + declare v_1422 int; + declare v_1423 int; + declare v_1424 int; + declare v_1425 int; + declare v_1426 int; + declare v_1427 int; + declare v_1428 int; + declare v_1429 int; + declare v_1430 int; + declare v_1431 int; + declare v_1432 int; + declare v_1433 int; + declare v_1434 int; + declare v_1435 int; + declare v_1436 int; + declare v_1437 int; + declare v_1438 int; + declare v_1439 int; + declare v_1440 int; + declare v_1441 int; + declare v_1442 int; + declare v_1443 int; + declare v_1444 int; + declare v_1445 int; + declare v_1446 int; + declare v_1447 int; + declare v_1448 int; + declare v_1449 int; + declare v_1450 int; + declare v_1451 int; + declare v_1452 int; + declare v_1453 int; + declare v_1454 int; + declare v_1455 int; + declare v_1456 int; + declare v_1457 int; + declare v_1458 int; + declare v_1459 int; + declare v_1460 int; + declare v_1461 int; + declare v_1462 int; + declare v_1463 int; + declare v_1464 int; + declare v_1465 int; + declare v_1466 int; + declare v_1467 int; + declare v_1468 int; + declare v_1469 int; + declare v_1470 int; + declare v_1471 int; + declare v_1472 int; + declare v_1473 int; + declare v_1474 int; + declare v_1475 int; + declare v_1476 int; + declare v_1477 int; + declare v_1478 int; + declare v_1479 int; + declare v_1480 int; + declare v_1481 int; + declare v_1482 int; + declare v_1483 int; + declare v_1484 int; + declare v_1485 int; + declare v_1486 int; + declare v_1487 int; + declare v_1488 int; + declare v_1489 int; + declare v_1490 int; + declare v_1491 int; + declare v_1492 int; + declare v_1493 int; + declare v_1494 int; + declare v_1495 int; + declare v_1496 int; + declare v_1497 int; + declare v_1498 int; + declare v_1499 int; + declare v_1500 int; + declare v_1501 int; + declare v_1502 int; + declare v_1503 int; + declare v_1504 int; + declare v_1505 int; + declare v_1506 int; + declare v_1507 int; + declare v_1508 int; + declare v_1509 int; + declare v_1510 int; + declare v_1511 int; + declare v_1512 int; + declare v_1513 int; + declare v_1514 int; + declare v_1515 int; + declare v_1516 int; + declare v_1517 int; + declare v_1518 int; + declare v_1519 int; + declare v_1520 int; + declare v_1521 int; + declare v_1522 int; + declare v_1523 int; + declare v_1524 int; + declare v_1525 int; + declare v_1526 int; + declare v_1527 int; + declare v_1528 int; + declare v_1529 int; + declare v_1530 int; + declare v_1531 int; + declare v_1532 int; + declare v_1533 int; + declare v_1534 int; + declare v_1535 int; + declare v_1536 int; + declare v_1537 int; + declare v_1538 int; + declare v_1539 int; + declare v_1540 int; + declare v_1541 int; + declare v_1542 int; + declare v_1543 int; + declare v_1544 int; + declare v_1545 int; + declare v_1546 int; + declare v_1547 int; + declare v_1548 int; + declare v_1549 int; + declare v_1550 int; + declare v_1551 int; + declare v_1552 int; + declare v_1553 int; + declare v_1554 int; + declare v_1555 int; + declare v_1556 int; + declare v_1557 int; + declare v_1558 int; + declare v_1559 int; + declare v_1560 int; + declare v_1561 int; + declare v_1562 int; + declare v_1563 int; + declare v_1564 int; + declare v_1565 int; + declare v_1566 int; + declare v_1567 int; + declare v_1568 int; + declare v_1569 int; + declare v_1570 int; + declare v_1571 int; + declare v_1572 int; + declare v_1573 int; + declare v_1574 int; + declare v_1575 int; + declare v_1576 int; + declare v_1577 int; + declare v_1578 int; + declare v_1579 int; + declare v_1580 int; + declare v_1581 int; + declare v_1582 int; + declare v_1583 int; + declare v_1584 int; + declare v_1585 int; + declare v_1586 int; + declare v_1587 int; + declare v_1588 int; + declare v_1589 int; + declare v_1590 int; + declare v_1591 int; + declare v_1592 int; + declare v_1593 int; + declare v_1594 int; + declare v_1595 int; + declare v_1596 int; + declare v_1597 int; + declare v_1598 int; + declare v_1599 int; + declare v_1600 int; + declare v_1601 int; + declare v_1602 int; + declare v_1603 int; + declare v_1604 int; + declare v_1605 int; + declare v_1606 int; + declare v_1607 int; + declare v_1608 int; + declare v_1609 int; + declare v_1610 int; + declare v_1611 int; + declare v_1612 int; + declare v_1613 int; + declare v_1614 int; + declare v_1615 int; + declare v_1616 int; + declare v_1617 int; + declare v_1618 int; + declare v_1619 int; + declare v_1620 int; + declare v_1621 int; + declare v_1622 int; + declare v_1623 int; + declare v_1624 int; + declare v_1625 int; + declare v_1626 int; + declare v_1627 int; + declare v_1628 int; + declare v_1629 int; + declare v_1630 int; + declare v_1631 int; + declare v_1632 int; + declare v_1633 int; + declare v_1634 int; + declare v_1635 int; + declare v_1636 int; + declare v_1637 int; + declare v_1638 int; + declare v_1639 int; + declare v_1640 int; + declare v_1641 int; + declare v_1642 int; + declare v_1643 int; + declare v_1644 int; + declare v_1645 int; + declare v_1646 int; + declare v_1647 int; + declare v_1648 int; + declare v_1649 int; + declare v_1650 int; + declare v_1651 int; + declare v_1652 int; + declare v_1653 int; + declare v_1654 int; + declare v_1655 int; + declare v_1656 int; + declare v_1657 int; + declare v_1658 int; + declare v_1659 int; + declare v_1660 int; + declare v_1661 int; + declare v_1662 int; + declare v_1663 int; + declare v_1664 int; + declare v_1665 int; + declare v_1666 int; + declare v_1667 int; + declare v_1668 int; + declare v_1669 int; + declare v_1670 int; + declare v_1671 int; + declare v_1672 int; + declare v_1673 int; + declare v_1674 int; + declare v_1675 int; + declare v_1676 int; + declare v_1677 int; + declare v_1678 int; + declare v_1679 int; + declare v_1680 int; + declare v_1681 int; + declare v_1682 int; + declare v_1683 int; + declare v_1684 int; + declare v_1685 int; + declare v_1686 int; + declare v_1687 int; + declare v_1688 int; + declare v_1689 int; + declare v_1690 int; + declare v_1691 int; + declare v_1692 int; + declare v_1693 int; + declare v_1694 int; + declare v_1695 int; + declare v_1696 int; + declare v_1697 int; + declare v_1698 int; + declare v_1699 int; + declare v_1700 int; + declare v_1701 int; + declare v_1702 int; + declare v_1703 int; + declare v_1704 int; + declare v_1705 int; + declare v_1706 int; + declare v_1707 int; + declare v_1708 int; + declare v_1709 int; + declare v_1710 int; + declare v_1711 int; + declare v_1712 int; + declare v_1713 int; + declare v_1714 int; + declare v_1715 int; + declare v_1716 int; + declare v_1717 int; + declare v_1718 int; + declare v_1719 int; + declare v_1720 int; + declare v_1721 int; + declare v_1722 int; + declare v_1723 int; + declare v_1724 int; + declare v_1725 int; + declare v_1726 int; + declare v_1727 int; + declare v_1728 int; + declare v_1729 int; + declare v_1730 int; + declare v_1731 int; + declare v_1732 int; + declare v_1733 int; + declare v_1734 int; + declare v_1735 int; + declare v_1736 int; + declare v_1737 int; + declare v_1738 int; + declare v_1739 int; + declare v_1740 int; + declare v_1741 int; + declare v_1742 int; + declare v_1743 int; + declare v_1744 int; + declare v_1745 int; + declare v_1746 int; + declare v_1747 int; + declare v_1748 int; + declare v_1749 int; + declare v_1750 int; + declare v_1751 int; + declare v_1752 int; + declare v_1753 int; + declare v_1754 int; + declare v_1755 int; + declare v_1756 int; + declare v_1757 int; + declare v_1758 int; + declare v_1759 int; + declare v_1760 int; + declare v_1761 int; + declare v_1762 int; + declare v_1763 int; + declare v_1764 int; + declare v_1765 int; + declare v_1766 int; + declare v_1767 int; + declare v_1768 int; + declare v_1769 int; + declare v_1770 int; + declare v_1771 int; + declare v_1772 int; + declare v_1773 int; + declare v_1774 int; + declare v_1775 int; + declare v_1776 int; + declare v_1777 int; + declare v_1778 int; + declare v_1779 int; + declare v_1780 int; + declare v_1781 int; + declare v_1782 int; + declare v_1783 int; + declare v_1784 int; + declare v_1785 int; + declare v_1786 int; + declare v_1787 int; + declare v_1788 int; + declare v_1789 int; + declare v_1790 int; + declare v_1791 int; + declare v_1792 int; + declare v_1793 int; + declare v_1794 int; + declare v_1795 int; + declare v_1796 int; + declare v_1797 int; + declare v_1798 int; + declare v_1799 int; + declare v_1800 int; + declare v_1801 int; + declare v_1802 int; + declare v_1803 int; + declare v_1804 int; + declare v_1805 int; + declare v_1806 int; + declare v_1807 int; + declare v_1808 int; + declare v_1809 int; + declare v_1810 int; + declare v_1811 int; + declare v_1812 int; + declare v_1813 int; + declare v_1814 int; + declare v_1815 int; + declare v_1816 int; + declare v_1817 int; + declare v_1818 int; + declare v_1819 int; + declare v_1820 int; + declare v_1821 int; + declare v_1822 int; + declare v_1823 int; + declare v_1824 int; + declare v_1825 int; + declare v_1826 int; + declare v_1827 int; + declare v_1828 int; + declare v_1829 int; + declare v_1830 int; + declare v_1831 int; + declare v_1832 int; + declare v_1833 int; + declare v_1834 int; + declare v_1835 int; + declare v_1836 int; + declare v_1837 int; + declare v_1838 int; + declare v_1839 int; + declare v_1840 int; + declare v_1841 int; + declare v_1842 int; + declare v_1843 int; + declare v_1844 int; + declare v_1845 int; + declare v_1846 int; + declare v_1847 int; + declare v_1848 int; + declare v_1849 int; + declare v_1850 int; + declare v_1851 int; + declare v_1852 int; + declare v_1853 int; + declare v_1854 int; + declare v_1855 int; + declare v_1856 int; + declare v_1857 int; + declare v_1858 int; + declare v_1859 int; + declare v_1860 int; + declare v_1861 int; + declare v_1862 int; + declare v_1863 int; + declare v_1864 int; + declare v_1865 int; + declare v_1866 int; + declare v_1867 int; + declare v_1868 int; + declare v_1869 int; + declare v_1870 int; + declare v_1871 int; + declare v_1872 int; + declare v_1873 int; + declare v_1874 int; + declare v_1875 int; + declare v_1876 int; + declare v_1877 int; + declare v_1878 int; + declare v_1879 int; + declare v_1880 int; + declare v_1881 int; + declare v_1882 int; + declare v_1883 int; + declare v_1884 int; + declare v_1885 int; + declare v_1886 int; + declare v_1887 int; + declare v_1888 int; + declare v_1889 int; + declare v_1890 int; + declare v_1891 int; + declare v_1892 int; + declare v_1893 int; + declare v_1894 int; + declare v_1895 int; + declare v_1896 int; + declare v_1897 int; + declare v_1898 int; + declare v_1899 int; + declare v_1900 int; + declare v_1901 int; + declare v_1902 int; + declare v_1903 int; + declare v_1904 int; + declare v_1905 int; + declare v_1906 int; + declare v_1907 int; + declare v_1908 int; + declare v_1909 int; + declare v_1910 int; + declare v_1911 int; + declare v_1912 int; + declare v_1913 int; + declare v_1914 int; + declare v_1915 int; + declare v_1916 int; + declare v_1917 int; + declare v_1918 int; + declare v_1919 int; + declare v_1920 int; + declare v_1921 int; + declare v_1922 int; + declare v_1923 int; + declare v_1924 int; + declare v_1925 int; + declare v_1926 int; + declare v_1927 int; + declare v_1928 int; + declare v_1929 int; + declare v_1930 int; + declare v_1931 int; + declare v_1932 int; + declare v_1933 int; + declare v_1934 int; + declare v_1935 int; + declare v_1936 int; + declare v_1937 int; + declare v_1938 int; + declare v_1939 int; + declare v_1940 int; + declare v_1941 int; + declare v_1942 int; + declare v_1943 int; + declare v_1944 int; + declare v_1945 int; + declare v_1946 int; + declare v_1947 int; + declare v_1948 int; + declare v_1949 int; + declare v_1950 int; + declare v_1951 int; + declare v_1952 int; + declare v_1953 int; + declare v_1954 int; + declare v_1955 int; + declare v_1956 int; + declare v_1957 int; + declare v_1958 int; + declare v_1959 int; + declare v_1960 int; + declare v_1961 int; + declare v_1962 int; + declare v_1963 int; + declare v_1964 int; + declare v_1965 int; + declare v_1966 int; + declare v_1967 int; + declare v_1968 int; + declare v_1969 int; + declare v_1970 int; + declare v_1971 int; + declare v_1972 int; + declare v_1973 int; + declare v_1974 int; + declare v_1975 int; + declare v_1976 int; + declare v_1977 int; + declare v_1978 int; + declare v_1979 int; + declare v_1980 int; + declare v_1981 int; + declare v_1982 int; + declare v_1983 int; + declare v_1984 int; + declare v_1985 int; + declare v_1986 int; + declare v_1987 int; + declare v_1988 int; + declare v_1989 int; + declare v_1990 int; + declare v_1991 int; + declare v_1992 int; + declare v_1993 int; + declare v_1994 int; + declare v_1995 int; + declare v_1996 int; + declare v_1997 int; + declare v_1998 int; + declare v_1999 int; + declare v_2000 int; + declare v_nn dm_nn; + begin + v_nn = null; + end + ^ set term ;^ + -- ::: NB::: + -- *** All *** versions of 2.5 will produce here the NUMBER of variable rather than its name: + -- validation error for variable number 2001, value "*** null ***" + -- (though "Affected version/s 2.1.3, 3.0 Initial, 2.5 RC1, 2.5 RC2") + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + validation error for variable V_NN, value "*** null ***" + -At block line: 2004, col: 9 + """ + +@pytest.mark.version('>=3.0') +def test_core_3055_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_3056.py b/tests/bugs/test_core_3056.py new file mode 100644 index 00000000..a8938063 --- /dev/null +++ b/tests/bugs/test_core_3056.py @@ -0,0 +1,421 @@ +#coding:utf-8 +# +# id: bugs.core_3056 +# title: Problems may happen when issuing DDL commands in the same transaction after CREATE COLLATION was issued +# decription: +# tracker_id: CORE-3056 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- 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 + ,cs.rdb$character_set_name cset_name + ,co.rdb$base_collation_name base_coll + from rdb$relation_fields rf + join rdb$collations co on rf.rdb$collation_id = co.rdb$collation_id + 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 + 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 ^; + execute block as + declare stt varchar(255); + declare c_coll cursor for -- collations + (select rc.rdb$collation_name + from rdb$collations rc + where coalesce(rc.rdb$system_flag,0)=0 + ); + begin + open c_coll; --------------- d r o p c o l l a t i o n s ----------------- + while (1=1) do + begin + fetch c_coll into stt; + if (row_count = 0) then leave; + stt = 'drop collation '||stt; + execute statement (:stt); + end + close c_coll; + end + ^ + set term ;^ + drop table test; + + set autoddl off; -- ######### NOTE: all statements below will be run in the same Tx ######### + commit; + + set list on; + + -- This is sample from ticket: + create collation coll_01 for utf8 from unicode no pad; + --commit; -- (1) + + -- This statement should FAIL with error "COLLATION COLL_01 for CHARACTER SET NONE is not defined" + -- Before this ticked was fixed, text fields are implicitly assigned with charset = UTF8: + + create table test ( + k1 varchar(3) collate coll_01, + k2 char(1) collate coll_01, + primary key (k1, k2) + ); -- Result: table `test` should NOT be created! + + set count on; + + -- `select * from v_test_fields_ddl;`: must return 0 rows + set echo on; + select * from v_test_fields_ddl; + drop collation coll_01; + set echo off; + set count off; + + -- All the following statements should NOT fail: + + create collation coll_01 for win1251 from pxw_cyrl pad space case insensitive accent insensitive; + create collation coll_02 for win1251 from pxw_cyrl pad space case insensitive accent insensitive; + create collation coll_03 for win1251 from pxw_cyrl pad space case insensitive accent insensitive; + create collation coll_04 for win1251 from pxw_cyrl pad space case insensitive accent insensitive; + create collation coll_05 for win1251 from pxw_cyrl pad space case insensitive accent insensitive; + create collation coll_06 for win1251 from pxw_cyrl pad space case insensitive accent insensitive; + create collation coll_07 for win1251 from pxw_cyrl pad space case insensitive accent insensitive; + create collation coll_08 for win1251 from pxw_cyrl pad space case insensitive accent insensitive; + create collation coll_09 for win1251 from pxw_cyrl pad space case insensitive accent insensitive; + create collation coll_10 for win1251 from pxw_cyrl pad space case insensitive accent insensitive; + create collation coll_11 for win1251 from pxw_cyrl pad space case insensitive accent insensitive; + create collation coll_12 for win1251 from pxw_cyrl pad space case insensitive accent insensitive; + + create table test( + f01 varchar(2) character set win1251 collate coll_01 + ,f02 varchar(2) character set win1251 collate coll_02 + ,f03 varchar(2) character set win1251 collate coll_03 + ,f04 varchar(2) character set win1251 collate coll_04 + ,f05 varchar(2) character set win1251 collate coll_05 + ,f06 varchar(2) character set win1251 collate coll_06 + ,f07 varchar(2) character set win1251 collate coll_07 + ,f08 varchar(2) character set win1251 collate coll_08 + ,f09 varchar(2) character set win1251 collate coll_09 + ,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) + ); + + select * from v_test_fields_ddl; + + drop table test; + + drop collation coll_01; + drop collation coll_02; + drop collation coll_03; + drop collation coll_04; + drop collation coll_05; + drop collation coll_06; + drop collation coll_07; + drop collation coll_08; + drop collation coll_09; + drop collation coll_10; + drop collation coll_11; + drop collation coll_12; + + create collation coll_01 for utf8 from unicode no pad; + create collation coll_02 for utf8 from unicode no pad; + create collation coll_03 for utf8 from unicode no pad; + create collation coll_04 for utf8 from unicode no pad; + create collation coll_05 for utf8 from unicode no pad; + create collation coll_06 for utf8 from unicode no pad; + create collation coll_07 for utf8 from unicode no pad; + create collation coll_08 for utf8 from unicode no pad; + create collation coll_09 for utf8 from unicode no pad; + create collation coll_10 for utf8 from unicode no pad; + create collation coll_11 for utf8 from unicode no pad; + create collation coll_12 for utf8 from unicode no pad; + + create table test( + f01 varchar(2) character set utf8 collate coll_01 + ,f02 varchar(2) character set utf8 collate coll_02 + ,f03 varchar(2) character set utf8 collate coll_03 + ,f04 varchar(2) character set utf8 collate coll_04 + ,f05 varchar(2) character set utf8 collate coll_05 + ,f06 varchar(2) character set utf8 collate coll_06 + ,f07 varchar(2) character set utf8 collate coll_07 + ,f08 varchar(2) character set utf8 collate coll_08 + ,f09 varchar(2) character set utf8 collate coll_09 + ,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) + ); + + select * from v_test_fields_ddl; + drop table test; + + drop collation coll_01; + drop collation coll_02; + drop collation coll_03; + drop collation coll_04; + drop collation coll_05; + drop collation coll_06; + drop collation coll_07; + drop collation coll_08; + drop collation coll_09; + drop collation coll_10; + drop collation coll_11; + drop collation coll_12; + + -- this was tested both on windows ans linux, should be created OK + -- (all these collations are declared in the file 'fbintl.conf'): + create collation coll_01 for iso8859_1 from external ('DA_DA'); + create collation coll_02 for iso8859_1 from external ('DE_DE'); + create collation coll_03 for iso8859_1 from external ('DU_NL'); + create collation coll_04 for iso8859_1 from external ('EN_UK'); + create collation coll_05 for iso8859_1 from external ('EN_US'); + create collation coll_06 for iso8859_1 from external ('ES_ES'); + create collation coll_07 for iso8859_1 from external ('ES_ES_CI_AI'); + create collation coll_08 for iso8859_1 from external ('FI_FI'); + create collation coll_09 for iso8859_1 from external ('FR_CA'); + create collation coll_10 for iso8859_1 from external ('FR_FR'); + create collation coll_11 for iso8859_1 from external ('IS_IS'); + create collation coll_12 for iso8859_1 from external ('IT_IT'); + + create table test( + f01 varchar(2) character set iso8859_1 collate coll_01 + ,f02 varchar(2) character set iso8859_1 collate coll_02 + ,f03 varchar(2) character set iso8859_1 collate coll_03 + ,f04 varchar(2) character set iso8859_1 collate coll_04 + ,f05 varchar(2) character set iso8859_1 collate coll_05 + ,f06 varchar(2) character set iso8859_1 collate coll_06 + ,f07 varchar(2) character set iso8859_1 collate coll_07 + ,f08 varchar(2) character set iso8859_1 collate coll_08 + ,f09 varchar(2) character set iso8859_1 collate coll_09 + ,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) + ); + + select * from v_test_fields_ddl; + --select current_transaction from rdb$database; + + rollback; + set count on; + -- Both selects below must return 0 rows: + set echo on; + select * from v_test_fields_ddl; + select * from rdb$collations co where co.rdb$collation_name starting with 'COLL_'; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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_1 = """ + 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 + """ + +@pytest.mark.version('>=3.0') +def test_core_3056_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3057.py b/tests/bugs/test_core_3057.py new file mode 100644 index 00000000..c7189787 --- /dev/null +++ b/tests/bugs/test_core_3057.py @@ -0,0 +1,77 @@ +#coding:utf-8 +# +# id: bugs.core_3057 +# title: Allow the usage of blobs in COMPUTED BY expressions +# decription: +# tracker_id: CORE-3057 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('BLOB_ID_.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test( + b1 blob sub_type 1 character set utf8 collate unicode_ci_ai, + b2 blob sub_type 1 character set utf8 collate unicode_ci_ai, + bconcat1 computed by ( b1 || b2 ) -- this FAILS on 2.5.4 + ); + commit; + alter table test + add bconcat2 computed by ( b1 || b2 || bconcat1 ) + ,add brepl1_2 computed by ( replace(b1, b2, '1') ) + ,add brepl2_1 computed by ( replace(b2, b1, '2') ) + ; + commit; + --show table test; + insert into test(b1, b2) values( + 'ÁÉÍÓÚÝÀÈÌÒÙÂÊÎÔÛÃÑÕÄËÏÖÜŸÇŠĄĘŹŻĂŞŢ', + 'aeiouyaeiouaeiouanoaeiouycsaezzast' + ); + + set list on; + set blob all; + select + b1 as blob_id_b1, + b2 as blob_id_b2, + bconcat1 as blob_id_bconcat1, + bconcat2 as blob_id_bconcat2, + brepl1_2 as blob_id_repl1_2, + brepl2_1 as blob_id_repl2_1 + from test + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + BLOB_ID_B1 86:0 + ÁÉÍÓÚÝÀÈÌÒÙÂÊÎÔÛÃÑÕÄËÏÖÜŸÇŠĄĘŹŻĂŞŢ + BLOB_ID_B2 86:1 + aeiouyaeiouaeiouanoaeiouycsaezzast + BLOB_ID_BCONCAT1 0:12 + ÁÉÍÓÚÝÀÈÌÒÙÂÊÎÔÛÃÑÕÄËÏÖÜŸÇŠĄĘŹŻĂŞŢaeiouyaeiouaeiouanoaeiouycsaezzast + BLOB_ID_BCONCAT2 0:f + ÁÉÍÓÚÝÀÈÌÒÙÂÊÎÔÛÃÑÕÄËÏÖÜŸÇŠĄĘŹŻĂŞŢaeiouyaeiouaeiouanoaeiouycsaezzastÁÉÍÓÚÝÀÈÌÒÙÂÊÎÔÛÃÑÕÄËÏÖÜŸÇŠĄĘŹŻĂŞŢaeiouyaeiouaeiouanoaeiouycsaezzast + BLOB_ID_REPL1_2 0:8 + 1 + BLOB_ID_REPL2_1 0:5 + 2 + """ + +@pytest.mark.version('>=3.0') +def test_core_3057_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3058.py b/tests/bugs/test_core_3058.py new file mode 100644 index 00000000..35cec93c --- /dev/null +++ b/tests/bugs/test_core_3058.py @@ -0,0 +1,85 @@ +#coding:utf-8 +# +# id: bugs.core_3058 +# title: New generators are created with wrong value when more than 32K generators was previously created +# decription: +# tracker_id: CORE-3058 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + set term ^; + execute block + as + declare n int = 1; + declare x int; + declare k int; + declare c int; + begin + while (n < 33000) do + begin + k = 1000000 + cast(rand() * 1000000 as int); + + -- ::: NB ::: As of Firebird 3.0 we need to make EVERY operation (creation, select gen_id, dropping) + -- in AUTONOMOUS transaction because physically appearance of generator in database will be on COMMIT only. + -- It is not so in 2.5, but I left code common for both FB versions. Zotov. + in autonomous transaction do + execute statement 'create sequence s' || n; + + in autonomous transaction do + execute statement 'select gen_id(s' || n || ', ' || k || ') from rdb$database' into x; + + in autonomous transaction do + execute statement 'drop sequence s' || n; + + n = n + 1; + end + end + ^ + set term ;^ + rollback; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Updated code: remove dependency on: 1) version FB and 2) output of 'show sequence' command. + -- Also we check here that NO sequences exists at this point and after we create and drop sequence 's1' + set list on; + select iif( exists(select * from rdb$generators g where coalesce(g.rdb$system_flag,0) = 0), 'some_gen_exists!', 'none_gen_remains' ) as msg_1 + from rdb$database; + create sequence s1; + commit; + select gen_id(s1,0) as current_val_of_s1 from rdb$database; + commit; + drop sequence s1; + commit; + select iif( exists(select * from rdb$generators g where coalesce(g.rdb$system_flag,0) = 0), 'some_gen_exists!', 'none_gen_remains' ) as msg_2 + from rdb$database; + set list off; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG_1 none_gen_remains + CURRENT_VAL_OF_S1 0 + MSG_2 none_gen_remains + """ + +@pytest.mark.version('>=2.5.1') +@pytest.mark.slow +def test_core_3058_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3064.py b/tests/bugs/test_core_3064.py new file mode 100644 index 00000000..bad52aa7 --- /dev/null +++ b/tests/bugs/test_core_3064.py @@ -0,0 +1,67 @@ +#coding:utf-8 +# +# id: bugs.core_3064 +# title: Using both the procedure name and alias inside an explicit plan crashes the server +# decription: +# tracker_id: CORE-3064 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [('offset .*', '')] + +init_script_1 = """ + set term ^ ; + create or alter procedure get_dates ( + adate_from date, + adate_to date ) + returns ( + out_date date ) + as + declare variable d date; + begin + d = adate_from; + while (d<=adate_to) do + begin + out_date = d; + suspend; + d = d + 1; + end + end^ + set term ; ^ + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set planonly; + select * from get_dates( 'yesterday', 'today' ) PLAN (GET_DATES NATURAL); + select * from get_dates( 'yesterday', 'today' ) p PLAN (P NATURAL); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ +Statement failed, SQLSTATE = 42S02 +Dynamic SQL Error +-SQL error code = -104 +-Invalid command +-there is no alias or table named GET_DATES at this scope level +Statement failed, SQLSTATE = HY000 +invalid request BLR at offset 50 +-BLR syntax error: expected TABLE at offset 51, encountered 132 + """ + +@pytest.mark.version('>=2.5.1') +def test_core_3064_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_3073.py b/tests/bugs/test_core_3073.py new file mode 100644 index 00000000..4f09a711 --- /dev/null +++ b/tests/bugs/test_core_3073.py @@ -0,0 +1,83 @@ +#coding:utf-8 +# +# id: bugs.core_3073 +# title: Foreign key cascade with SET DEFAULT uses the default value of the moment of the FK creation +# decription: +# Confirmed bug on WI-T4.0.0.503. +# Checked on WI-T4.0.0.511 - works fine. +# +# tracker_id: CORE-3073 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table tdetl(x int); + recreate table tmain(x int); + commit; + set term ^; + execute block as + begin + execute statement 'drop domain dm_name'; + when any do begin end + end + ^ + set term ;^ + commit; + + create domain dm_name varchar(15) default 'Old Trafford'; + commit; + + recreate table tmain(name dm_name primary key); + recreate table tdetl(name dm_name references tmain on delete set default); + commit; + + alter domain dm_name set default 'New Vasyuki'; + commit; + + insert into tmain values('London'); + insert into tmain values('Old Trafford'); + insert into tmain values('New Vasyuki'); + + insert into tdetl values('London'); + insert into tdetl values('Old Trafford'); + + set list on; + + select 'before cascade on tdetl' as msg, d.* from tdetl d; + delete from tmain where name = 'London'; + select 'after cascade on tdetl' as msg, d.* from tdetl d; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG before cascade on tdetl + NAME London + MSG before cascade on tdetl + NAME Old Trafford + + MSG after cascade on tdetl + NAME New Vasyuki + MSG after cascade on tdetl + NAME Old Trafford + """ + +@pytest.mark.version('>=4.0') +def test_core_3073_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3076.py b/tests/bugs/test_core_3076.py new file mode 100644 index 00000000..23c7b1a4 --- /dev/null +++ b/tests/bugs/test_core_3076.py @@ -0,0 +1,328 @@ +#coding:utf-8 +# +# id: bugs.core_3076 +# title: Better performance for (table.field = :param or :param = -1) in where clause +# decription: +# Test adds 20'000 rows into a table with single field and two indices on it (asc & desc). +# Indexed field will have values which will produce very poor selectivity (~1/3). +# Then we check number of indexed and natural reads using mon$ tables and prepared view +# from .fbk. +# We check cases when SP count rows using equality (=), IN and BETWEEN expr. +# When we pass NULLs then procedure should produce zero or low value (<100) of indexed reads. +# When we pass not null value then SP should produce IR with number ~ 1/3 of total rows in the table. +# +# FB30SS, build 3.0.4.32972: OK, 2.734s. +# FB40SS, build 4.0.0.977: OK, 3.234s. +# +# 15.05.2018. TODO LATER, using Python: +# +# Alternate code for possible checking (use trace with and ensure that only IR will occur when input arg is not null): +# +# set term ^; +# execute block as +# begin +# begin execute statement 'drop sequence g'; when any do begin end end +# end +# ^ +# set term ;^ +# commit; +# create sequence g; +# commit; +# +# create or alter procedure sp_test as begin end; +# commit; +# recreate table test(x int, y int); +# commit; +# +# insert into test select mod( gen_id(g,1), 123), mod( gen_id(g,1), 321) from rdb$types,rdb$types rows 10000; +# commit; +# +# create index test_x on test(x); +# create index test_x_plus_y_asc on test computed by ( x - y ); +# create descending index test_x_plus_y_dec on test computed by ( x+y ); +# commit; +# +# set term ^; +# create or alter procedure sp_test( i1 int default null, i2 int default null ) as +# declare n int; +# declare s_x varchar(1000); +# declare s_y varchar(1000); +# begin +# s_x = 'select count(*) from test where x = :input_arg or :input_arg is null'; +# s_y = 'select count(*) from test where x + y <= :input_sum and x - y >= :input_arg or :input_sum is null'; +# execute statement (s_x) ( input_arg := :i1 ) into n; +# execute statement (s_y) ( input_arg := :i1, input_sum := :i2 ) into n; +# end +# ^ +# set term ;^ +# commit; +# +# execute procedure sp_test( 65, 99 ); +# +# Trace log should contain following statistics for two ES: +# +# Table Natural Index +# ***************************************************** +# TEST 82 +# +# Table Natural Index +# ***************************************************** +# TEST 90 +# +# +# +# tracker_id: CORE-3076 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='mon-stat-gathering-3_0.fbk', init=init_script_1) + +test_script_1 = """ + set bail on; + set term ^; + execute block as + begin + execute statement 'drop sequence g'; + when any do begin end + end + ^ + set term ;^ + commit; + create sequence g; + commit; + + create or alter procedure sp_test_x as begin end; + create or alter procedure sp_test_y as begin end; + commit; + + recreate table test(x int, y int); + recreate table tcnt(q int); -- this serves only for storing total number of rows in 'TEST' table. + commit; + + set term ^ ; + create or alter procedure sp_test_x(arg_a int, arg_b int) -- for testing ASCENDING index + as + declare c int; + begin + if ( :arg_a = 0 ) then + select count(*) from test where x = :arg_a or :arg_a is null into c; + else if ( :arg_a = 1 ) then + select count(*) from test where x in (:arg_a, :arg_b) or :arg_a is null into c; + else + select count(*) from test where x between :arg_a and :arg_b or :arg_a is null into c; + end + ^ + create or alter procedure sp_test_y(arg_a int, arg_b int) -- for testing DESCENDING index + as + declare c int; + begin + if ( :arg_a = 0 ) then + select count(*) from test where y = :arg_a or :arg_a is null into c; + else if ( :arg_a = 1 ) then + select count(*) from test where y in (:arg_a, :arg_b) or :arg_a is null into c; + else + select count(*) from test where y between :arg_a and :arg_b or :arg_a is null into c; + end + ^ + set term ; ^ + commit; + + insert into test (x, y) + select mod( gen_id(g,1), 3 ), mod( gen_id(g,1), 3 ) + from rdb$types, rdb$types + rows 20000; + insert into tcnt(q) select count(*) from test; + commit; + + create index test_x on test(x); + create descending index test_y on test(y); + commit; + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; -- mandatory! + + execute procedure sp_truncate_stat; + commit; + + -------------------------------- + + execute procedure sp_gather_stat; + commit; + + execute procedure sp_test_x(0, 0); ----- 1: where x = 0 or 0 is null // 'x' has ascending index + + execute procedure sp_gather_stat; + commit; + + -------------------------------- + + execute procedure sp_gather_stat; + commit; + + execute procedure sp_test_y(0, 0); ----- 2: where y = 0 or 0 is null // 'y' has descend index + + execute procedure sp_gather_stat; + commit; + + -------------------------------- + + execute procedure sp_gather_stat; + commit; + + execute procedure sp_test_x(1, 1); ----- 3: where x in (1, 1) or 1 is null // 'x' has ascending index + + execute procedure sp_gather_stat; + commit; + + -------------------------------- + + execute procedure sp_gather_stat; + commit; + + execute procedure sp_test_y(1, 1); ----- 4: where y in (1, 1) or 1 is null // 'y' has descend index + + execute procedure sp_gather_stat; + commit; + + -------------------------------- + + + execute procedure sp_gather_stat; + commit; + + execute procedure sp_test_x(2, 2); ----- 5: where x between 2 and 2 or 2 is null // 'x' has ascending index + + execute procedure sp_gather_stat; + commit; + + -------------------------------- + + execute procedure sp_gather_stat; + commit; + + execute procedure sp_test_y(2, 2); ----- 6: where y between 2 and 2 or 2 is null // 'y' has descend index + + execute procedure sp_gather_stat; + commit; + + -------------------------------- + + execute procedure sp_gather_stat; + commit; + + -- check that asc index will NOT be in use when count for :a is null + execute procedure sp_test_x(null, null); -- 7: where x between NULL and NULL or NULL is null // 'x' has ascending index + + execute procedure sp_gather_stat; + commit; + + -------------------------------- + + execute procedure sp_gather_stat; + commit; + + -- check that desc index will NOT be in use when count for :a is null + execute procedure sp_test_y(null, null); -- 8: : where y between NULL and NULL or NULL is null // 'y' has descend index + + execute procedure sp_gather_stat; + commit; + + SET LIST ON; + select * + from ( + select + 'When input arg is NOT null' as what_we_check, + rowset, + iif( natural_reads <= nr_threshold + and indexed_reads - total_rows/3.00 < ir_threshold -- max detected IR was: 6685 for c.total_rows=20'000 + ,'OK' + ,'POOR:'|| + ' NR=' || coalesce(natural_reads, '') || + ', IR='|| coalesce(indexed_reads, '') || + ', ir-cnt/3='|| coalesce(indexed_reads - total_rows/3.00, '') + ) as result + from ( + select + v.rowset + ,v.natural_reads + ,v.indexed_reads + ,c.q as total_rows + ,iif( rdb$get_context('SYSTEM','ENGINE_VERSION') starting with '3.', 0, 2 ) as nr_threshold -- max detected NR=2 for 4.0 (SS, CS) + ,iif( rdb$get_context('SYSTEM','ENGINE_VERSION') starting with '3.', 45, 45 ) as ir_threshold -- max detected=44 for 4.0 (SS, CS) + from v_agg_stat v cross join tcnt c + where rowset <= 6 + ) + + UNION ALL + + select + 'When input arg is NULL' as what_we_check, + rowset, + iif( natural_reads = total_rows + and indexed_reads < 100 -- 27.07.2016: detected IR=13 for FB 4.0.0.313 + ,'OK' + ,'POOR:'|| + ' NR=' || coalesce(natural_reads, '') || + ', IR='|| coalesce(indexed_reads, '') + ) as result + from ( + select v.rowset, v.natural_reads, v.indexed_reads, c.q as total_rows + from v_agg_stat v cross join tcnt c + where rowset > 6 + ) + ) + order by rowset; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHAT_WE_CHECK When input arg is NOT null + ROWSET 1 + RESULT OK + + WHAT_WE_CHECK When input arg is NOT null + ROWSET 2 + RESULT OK + + WHAT_WE_CHECK When input arg is NOT null + ROWSET 3 + RESULT OK + + WHAT_WE_CHECK When input arg is NOT null + ROWSET 4 + RESULT OK + + WHAT_WE_CHECK When input arg is NOT null + ROWSET 5 + RESULT OK + + WHAT_WE_CHECK When input arg is NOT null + ROWSET 6 + RESULT OK + + WHAT_WE_CHECK When input arg is NULL + ROWSET 7 + RESULT OK + + WHAT_WE_CHECK When input arg is NULL + ROWSET 8 + RESULT OK + """ + +@pytest.mark.version('>=3.0') +def test_core_3076_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3085.py b/tests/bugs/test_core_3085.py new file mode 100644 index 00000000..0ecfc60b --- /dev/null +++ b/tests/bugs/test_core_3085.py @@ -0,0 +1,87 @@ +#coding:utf-8 +# +# id: bugs.core_3085 +# title: Add clause ALTER DOMAIN {DROP | SET} NOT NULL +# decription: +# tracker_id: CORE-3085 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create domain dm_int int; + commit; + create table t(x dm_int); + commit; + + set term ^; + create procedure p(a dm_int) returns(msg varchar(30)) as + begin + msg='intro proc p: a=' || coalesce(a, 'null'); + suspend; + end + ^ + set term ;^ + commit; + + insert into t values(1); + insert into t values(2); + insert into t values(3); + commit; + + set list on; + + alter domain dm_int set not null; + commit; + + select msg from p(null); + update t 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; + commit; + + alter domain dm_int set not null; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG intro proc p: a=null + X + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + validation error for variable A, value "*** null ***" + -At procedure 'P' + Statement failed, SQLSTATE = 23000 + validation error for column "T"."X", value "*** null ***" + Statement failed, SQLSTATE = 22006 + unsuccessful metadata update + -Cannot make field X of table T NOT NULL because there are NULLs present + """ + +@pytest.mark.version('>=3.0') +def test_core_3085_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3090.py b/tests/bugs/test_core_3090.py new file mode 100644 index 00000000..d78c9c25 --- /dev/null +++ b/tests/bugs/test_core_3090.py @@ -0,0 +1,61 @@ +#coding:utf-8 +# +# id: bugs.core_3090 +# title: Incorrect LEFT JOIN result using table and derived constant subquery +# decription: +# tracker_id: CORE-3090 +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """recreate table test_err (id int); +insert into test_err (ID) values (1); +insert into test_err (ID) values (2); +commit; +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select * + from test_err t + left join (select 1 id from rdb$database) a on a.id = t.id; +select + RESULT +from (select + 'Well' as RESULT + from (select + (select 'Does not work' from RDB$DATABASE) as D + from RDB$DATABASE d) i + left join RDB$DATABASE on 1=0) j +left join RDB$DATABASE on 1=0; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID ID +============ ============ + 1 1 + 2 + + +RESULT +====== +Well + +""" + +@pytest.mark.version('>=3.0') +def test_core_3090_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3091.py b/tests/bugs/test_core_3091.py new file mode 100644 index 00000000..631509f2 --- /dev/null +++ b/tests/bugs/test_core_3091.py @@ -0,0 +1,82 @@ +#coding:utf-8 +# +# id: bugs.core_3091 +# title: Built-in function POWER(X, Y) does not work when the X argument is negative and the Y value is scaled numeric but integral +# decription: +# tracker_id: CORE-3091 +# min_versions: ['2.1.4'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select 'power( 3, 2 )', power( 3, 2 ) from RDB$DATABASE +union all +select 'power( -3, 2 )', power( -3, 2 ) from RDB$DATABASE +union all +select 'power( 3, -2 )', power( 3, -2 ) from RDB$DATABASE +union all +select 'power( -3, -2 )', power( -3, -2 ) from RDB$DATABASE +union all +select 'power( 3, 2.0 )', power( 3, 2.0 ) from RDB$DATABASE +union all +select 'power( 3, -2.0 )', power( 3, -2.0 ) from RDB$DATABASE +union all +select 'power( -3, 2.0 )', power( -3, 2.0 ) from RDB$DATABASE +union all +select 'power( -3, -2.0 )', power( -3, -2.0 ) from RDB$DATABASE +union all +select 'power( -3.0, 2 )', power( -3.0, 2 ) from RDB$DATABASE +union all +select 'power( -3.0, 2.0 )', power( -3.0, 2.0 ) from RDB$DATABASE +union all +select 'power( -3.0, -2.0 )', power( -3.0, -2.0 ) from RDB$DATABASE +union all +select 'power( 3.0, -2.0 )', power( 3.0, -2.0 ) from RDB$DATABASE +union all +select 'power( 3.0, 2.0 )', power( 3.0, 2.0 ) from RDB$DATABASE +union all +select 'power( 3.0, 2 )', power( 3.0, 2 ) from RDB$DATABASE +union all +select 'power( 3.0, -2 )', power( 3.0, -2 ) from RDB$DATABASE +;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + +=================== ======================= +power( 3, 2 ) 9.000000000000000 +power( -3, 2 ) 9.000000000000000 +power( 3, -2 ) 0.1111111111111111 +power( -3, -2 ) 0.1111111111111111 +power( 3, 2.0 ) 9.000000000000000 +power( 3, -2.0 ) 0.1111111111111111 +power( -3, 2.0 ) 9.000000000000000 +power( -3, -2.0 ) 0.1111111111111111 +power( -3.0, 2 ) 9.000000000000000 +power( -3.0, 2.0 ) 9.000000000000000 +power( -3.0, -2.0 ) 0.1111111111111111 +power( 3.0, -2.0 ) 0.1111111111111111 +power( 3.0, 2.0 ) 9.000000000000000 +power( 3.0, 2 ) 9.000000000000000 +power( 3.0, -2 ) 0.1111111111111111 + +""" + +@pytest.mark.version('>=3.0') +def test_core_3091_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3092.py b/tests/bugs/test_core_3092.py new file mode 100644 index 00000000..4d3caad9 --- /dev/null +++ b/tests/bugs/test_core_3092.py @@ -0,0 +1,77 @@ +#coding:utf-8 +# +# id: bugs.core_3092 +# title: ROW_COUNT is not cleared before the singleton INSERT statement +# decription: +# tracker_id: CORE-3092 +# min_versions: ['2.1.5'] +# versions: 2.1.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.5 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """ + CREATE TABLE DELME ( + A INTEGER, + B INTEGER + ); + COMMIT; + INSERT INTO DELME (A, B) + VALUES (1, 11); + INSERT INTO DELME (A, B) + VALUES (2, 22); + INSERT INTO DELME (A, B) + VALUES (3, 33); + COMMIT; + SET TERM ^; + create procedure uui + returns ( + result varchar(250)) + as + begin + result = ''; + + update delme set + b = 111 + where a = 1; + result = result||'update-1 '||row_count||'; '; + + update delme set + b = 222 + where a = 2; + result = result||'update-2 '||row_count||'; '; + + insert into delme(a,b) + values(4,44); + result = result||'insert-1 '||row_count||'; '; + end + ^ + SET TERM ^; + COMMIT; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + execute procedure uui; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT update-1 1; update-2 1; insert-1 1; + """ + +@pytest.mark.version('>=2.1.5') +def test_core_3092_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3094.py b/tests/bugs/test_core_3094.py new file mode 100644 index 00000000..7f9c14de --- /dev/null +++ b/tests/bugs/test_core_3094.py @@ -0,0 +1,113 @@ +#coding:utf-8 +# +# id: bugs.core_3094 +# title: Parameters doesn't work with NOT IN from a selectable procedure +# decription: +# tracker_id: CORE-3094 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter procedure sp_test as begin end; + recreate table con_miem ( + fgrupo int, + fmiembr int, + constraint con_miem_pk primary key (fgrupo, fmiembr) + ); + recreate table con_cuen ( + fcuenta int, + fnombre varchar(30), + constraint con_cuen_pk primary key (fcuenta) + ); + set term ^; + create or alter procedure sp_test (grupo integer) returns (fcuenta type of column con_miem.fmiembr) as + begin + for select fmiembr from con_miem where fgrupo=:grupo into :fcuenta do suspend; + end + ^ set term ;^ + commit; + + insert into con_cuen (fcuenta, fnombre) values (5000, 'cuenta 5000'); + insert into con_cuen (fcuenta, fnombre) values (6000, 'cuenta 6000'); + insert into con_cuen (fcuenta, fnombre) values (7101, 'cuenta 7101'); + insert into con_cuen (fcuenta, fnombre) values (7102, 'cuenta 7102'); + insert into con_cuen (fcuenta, fnombre) values (7103, 'cuenta 7103'); + insert into con_cuen (fcuenta, fnombre) values (7104, 'cuenta 7104'); + insert into con_cuen (fcuenta, fnombre) values (7105, 'cuenta 7105'); + insert into con_cuen (fcuenta, fnombre) values (7106, 'cuenta 7106'); + insert into con_cuen (fcuenta, fnombre) values (7108, 'cuenta 7108'); + insert into con_cuen (fcuenta, fnombre) values (7109, 'cuenta 7109'); + insert into con_cuen (fcuenta, fnombre) values (7110, 'cuenta 7110'); + insert into con_cuen (fcuenta, fnombre) values (7111, 'cuenta 7111'); + insert into con_cuen (fcuenta, fnombre) values (7112, 'cuenta 7112'); + insert into con_cuen (fcuenta, fnombre) values (7113, 'cuenta 7113'); + insert into con_cuen (fcuenta, fnombre) values (7114, 'cuenta 7114'); + insert into con_cuen (fcuenta, fnombre) values (7115, 'cuenta 7115'); + insert into con_cuen (fcuenta, fnombre) values (7116, 'cuenta 7116'); + insert into con_cuen (fcuenta, fnombre) values (7117, 'cuenta 7117'); + insert into con_cuen (fcuenta, fnombre) values (7118, 'cuenta 7118'); + insert into con_cuen (fcuenta, fnombre) values (7119, 'cuenta 7119'); + + + insert into con_miem (fgrupo, fmiembr) values (100, 5000); + insert into con_miem (fgrupo, fmiembr) values (100, 6000); + insert into con_miem (fgrupo, fmiembr) values (100, 7101); + insert into con_miem (fgrupo, fmiembr) values (100, 7102); + insert into con_miem (fgrupo, fmiembr) values (100, 7103); + insert into con_miem (fgrupo, fmiembr) values (100, 7104); + insert into con_miem (fgrupo, fmiembr) values (100, 7105); + insert into con_miem (fgrupo, fmiembr) values (100, 7106); + insert into con_miem (fgrupo, fmiembr) values (100, 7108); + insert into con_miem (fgrupo, fmiembr) values (100, 7109); + insert into con_miem (fgrupo, fmiembr) values (100, 7110); + insert into con_miem (fgrupo, fmiembr) values (100, 7111); + insert into con_miem (fgrupo, fmiembr) values (100, 7112); + insert into con_miem (fgrupo, fmiembr) values (100, 7113); + insert into con_miem (fgrupo, fmiembr) values (100, 7114); + insert into con_miem (fgrupo, fmiembr) values (100, 7115); + insert into con_miem (fgrupo, fmiembr) values (100, 7116); + insert into con_miem (fgrupo, fmiembr) values (100, 7117); + insert into con_miem (fgrupo, fmiembr) values (100, 7118); + insert into con_miem (fgrupo, fmiembr) values (100, 7119); + commit; + + set list on; + set term ^; + execute block returns (fcuenta type of column con_miem.fmiembr, fnombre type of column con_cuen.fnombre) + as + declare gro integer = 100; + begin + for + select fcuenta, fnombre + from con_cuen + where fcuenta not in ( select p.fcuenta from sp_test(:gro) p ) + into fcuenta, fnombre + do + begin + suspend; + end + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5') +def test_core_3094_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_3095.py b/tests/bugs/test_core_3095.py new file mode 100644 index 00000000..c1a72bb2 --- /dev/null +++ b/tests/bugs/test_core_3095.py @@ -0,0 +1,100 @@ +#coding:utf-8 +# +# id: bugs.core_3095 +# title: Client receive event's with count equal to 1 despite of how many times EVENT was POSTed in same transaction +# decription: +# We create stored procedure as it was specified in the ticket, and call it with input arg = 3. +# This mean that we have to receive THREE events after code which calls this SP will issue COMMIT. +# +# Confirmed on 2.5.0.26074 - only one event was delivered instead of three. +# Works OK since 2.5.1.26351. +# +# PS. Event handling code in this text was adapted from fdb manual: +# http://pythonhosted.org/fdb/usage-guide.html#database-events +# +# tracker_id: CORE-3095 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + set term ^; + create or alter procedure sp_test (a_evt_count int) as + begin + while (a_evt_count > 0) do + begin + post_event('loop'); + a_evt_count = a_evt_count - 1; + end + end + ^ + set term ;^ + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import threading +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # Utility function +# def send_events(command_list): +# cur = db_conn.cursor() +# for cmd in command_list: +# cur.execute(cmd) +# db_conn.commit() +# +# timed_event = threading.Timer(3.0, send_events, args=[["execute procedure sp_test(3)",]]) +# +# # Connection.event_conduit() takes a sequence of string event names as parameter, and returns +# # EventConduit instance. +# events = db_conn.event_conduit(['loop']) +# +# # To start listening for events it's necessary (starting from FDB version 1.4.2) +# # to call EventConduit.begin() method or use EventConduit's context manager interface +# # Immediately when begin() method is called, EventConduit starts to accumulate notifications +# # of any events that occur within the conduit's internal queue until the conduit is closed +# # (via the close() method) +# +# events.begin() +# +# timed_event.start() +# +# # Notifications about events are aquired through call to wait() method, that blocks the calling +# # thread until at least one of the events occurs, or the specified timeout (if any) expires, +# # and returns None if the wait timed out, or a dictionary that maps event_name -> event_occurrence_count. +# +# e = events.wait(10) +# +# events.close() +# +# print(e) +# db_conn.close() +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + {'loop': 3} + """ + +@pytest.mark.version('>=2.5.1') +@pytest.mark.xfail +def test_core_3095_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_3097.py b/tests/bugs/test_core_3097.py new file mode 100644 index 00000000..6856d058 --- /dev/null +++ b/tests/bugs/test_core_3097.py @@ -0,0 +1,147 @@ +#coding:utf-8 +# +# id: bugs.core_3097 +# title: Updating blob field cause server crash with ACCESS_VIOLATION exception +# decription: +# Checked on: WI-V2.5.6.27001, WI-V3.0.0.32487, WI-T4.0.0.141 +# +# tracker_id: CORE-3097 +# min_versions: ['2.5'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + recreate table test(id int, b blob); + commit; + + insert into test(id, b) values(32765, + '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890abcde' + ) + returning id, char_length(b), octet_length(b) + ; + + insert into test(id, b) values(32766, + '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890abcdef' + ) + returning id, char_length(b), octet_length(b) + ; + + insert into test(id, b) values(32767, + '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890abcdefg' + ) + returning id, char_length(b), octet_length(b) + ; + + + insert into test(id, b) values(32768, + '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890abcdefgh' + ) + returning id, char_length(b), octet_length(b) + ; + + + insert into test(id, b) values(32769, + '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890abcdefghi' + ) + returning id, char_length(b), octet_length(b) + ; + + + insert into test(id, b) values(65532, + '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890abcdef123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890qwerty' + ) + returning id, char_length(b), octet_length(b) + ; + + insert into test(id, b) values(65533, + '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890abcdef123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890qwertyu' + ) + returning id, char_length(b), octet_length(b) + ; + + insert into test(id, b) values(65534, + '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890abcdef123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890qwertyui' + ) + returning id, char_length(b), octet_length(b) + ; + + insert into test(id, b) values(65535, + '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890abcdef123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890qwertyuio' + ) + returning id, char_length(b), octet_length(b) + ; + + insert into test(id, b) values(65536, + '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890abcdef123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890qwertyuiop' + ) + returning id, char_length(b), octet_length(b) + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 32765 + CHAR_LENGTH 32765 + OCTET_LENGTH 32765 + + ID 32766 + CHAR_LENGTH 32766 + OCTET_LENGTH 32766 + + ID 32767 + CHAR_LENGTH 32767 + OCTET_LENGTH 32767 + + ID 32768 + CHAR_LENGTH 32768 + OCTET_LENGTH 32768 + + ID 32769 + CHAR_LENGTH 32769 + OCTET_LENGTH 32769 + + ID 65532 + CHAR_LENGTH 65532 + OCTET_LENGTH 65532 + + ID 65533 + CHAR_LENGTH 65533 + OCTET_LENGTH 65533 + + ID 65534 + CHAR_LENGTH 65534 + OCTET_LENGTH 65534 + + ID 65535 + CHAR_LENGTH 65535 + OCTET_LENGTH 65535 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -String literal with 65536 bytes exceeds the maximum length of 65535 bytes + """ + +@pytest.mark.version('>=3.0') +def test_core_3097_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3100.py b/tests/bugs/test_core_3100.py new file mode 100644 index 00000000..408b6fcf --- /dev/null +++ b/tests/bugs/test_core_3100.py @@ -0,0 +1,255 @@ +#coding:utf-8 +# +# id: bugs.core_3100 +# title: Wait mode and lock timeout of external transaction of EXECUTE STATEMENT not matched to corresponding parameters of local transaction +# decription: +# Checked on: 4.0.0.1635 SS, 4.0.0.1633 CS: OK, 2.319s; 3.0.5.33180 SS, 3.0.5.33178 CS: OK, 2.215s. +# tracker_id: CORE-3100 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('Statement failed, SQLSTATE.*', ''), ('record not found for user:.*', '')] + +init_script_1 = """ + create or alter procedure sp_add_trn_data (a_run_no smallint) as begin end; + commit; + + recreate table mon_trn( + run_no smallint, + att_id bigint, + trn_id bigint, + state bigint, + dts timestamp, + top_trn bigint, + oldest_trn bigint, + oldest_active bigint, + isolation_mode bigint, + lock_timeout bigint, + read_only bigint, + auto_commit bigint, + auto_undo bigint, + stat_id bigint, + usr char(31) character set unicode_fss + ); + commit; + + set term ^; + create or alter procedure sp_add_trn_data (a_run_no smallint) as + declare v_dbname type of column mon$database.mon$database_name; + declare v_stt varchar(1024); + declare v_usr1 type of column mon_trn.usr = 'tmp$c3100a'; + declare v_pwd1 varchar(20) = 'tmp$c3100a'; + declare v_usr2 type of column mon_trn.usr = 'tmp$c3100b'; + declare v_pwd2 varchar(20) = 'tmp$c3100b'; + begin + v_stt = + 'insert into mon_trn( ' + || ' run_no' + || ' ,att_id' + || ' ,trn_id' + || ' ,state' + || ' ,dts' + || ' ,top_trn' + || ' ,oldest_trn' + || ' ,oldest_active' + || ' ,isolation_mode' + || ' ,lock_timeout' + || ' ,read_only' + || ' ,auto_commit' + || ' ,auto_undo' + || ' ,stat_id' + || ' ,usr' + || ')' + || ' select' + || ' :x' + || ' ,t.mon$attachment_id' + || ' ,t.mon$transaction_id' + || ' ,t.mon$state' + || ' ,t.mon$timestamp' + || ' ,t.mon$top_transaction' + || ' ,t.mon$oldest_transaction' + || ' ,t.mon$oldest_active' + || ' ,t.mon$isolation_mode' + || ' ,t.mon$lock_timeout' + || ' ,t.mon$read_only' + || ' ,t.mon$auto_commit' + || ' ,t.mon$auto_undo' + || ' ,t.mon$stat_id' + || ' ,a.mon$user' + || ' from mon$transactions t join mon$attachments a using (mon$attachment_id)' + || ' where mon$transaction_id = current_transaction' + ; + + --- 1 --- direct statement, sysdba + insert into mon_trn( + run_no + ,att_id + ,trn_id + ,state + ,dts + ,top_trn + ,oldest_trn + ,oldest_active + ,isolation_mode + ,lock_timeout + ,read_only + ,auto_commit + ,auto_undo + ,stat_id + ,usr + ) + select + :a_run_no + ,t.mon$attachment_id + ,t.mon$transaction_id + ,t.mon$state + ,t.mon$timestamp + ,t.mon$top_transaction + ,t.mon$oldest_transaction + ,t.mon$oldest_active + ,t.mon$isolation_mode + ,t.mon$lock_timeout + ,t.mon$read_only + ,t.mon$auto_commit + ,t.mon$auto_undo + ,t.mon$stat_id + ,a.mon$user + from mon$transactions t join mon$attachments a using (mon$attachment_id) + where mon$transaction_id = current_transaction; + + select 'localhost:' || d.mon$database_name + from mon$database d + into v_dbname; + + --- 2 --- execute statement on EXTERNAL datasource, with new attachment because of user = tmp$c3100a + execute statement ( v_stt ) ( x:= :a_run_no ) + on external :v_dbname + as user :v_usr1 password :v_pwd1 + ; + + --- 3 --- execute statement on EXTERNAL datasource, AUTONOMOUS transaction, with new attachment because user = tmp$c3100b + execute statement ( v_stt ) ( x:= :a_run_no ) + on external :v_dbname + as user :v_usr2 password :v_pwd2 + with autonomous transaction + ; + end + ^ + set term ;^ + commit; + + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + drop user tmp$c3100a; + commit; + create user tmp$c3100a password 'tmp$c3100a'; + commit; + grant select,insert on mon_trn to tmp$c3100a; + commit; + + drop user tmp$c3100b; + commit; + create user tmp$c3100b password 'tmp$c3100b'; + commit; + grant select,insert on mon_trn to tmp$c3100b; + commit; + + -- Check for 'WAIT': + set transaction wait; + execute procedure sp_add_trn_data(1); + commit; + + -- Check for 'NO WAIT': + set transaction no wait; + execute procedure sp_add_trn_data(2); + commit; + + -- Check for 'LOCK TIMEOUT' value: + set transaction lock timeout 9; + execute procedure sp_add_trn_data(3); + commit; + + + -- Check for ISOLATION level: + set transaction read committed no wait; + execute procedure sp_add_trn_data(4); + commit; + + -- DO NOT: as of 26.03.2015, flag NO_AUTO_UNDO should *NOT* be copied + -- (commented after colsulting with Vlad) + -- Check for NO AUTO UNDO: + -- set transaction read committed no wait no auto undo; + -- execute procedure sp_add_trn_data(5); + -- commit; + + set list on; + select + m.run_no + ,count(distinct m.trn_id) trn_distinct_count + ,count(distinct m.lock_timeout) wait_distinct_count + ,count(distinct m.isolation_mode) isol_distinct_count + from mon_trn m + group by 1 + order by 1; + commit; + + drop user tmp$c3100a; + drop user tmp$c3100b; + 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RUN_NO 1 + TRN_DISTINCT_COUNT 3 + WAIT_DISTINCT_COUNT 1 + ISOL_DISTINCT_COUNT 1 + + RUN_NO 2 + TRN_DISTINCT_COUNT 3 + WAIT_DISTINCT_COUNT 1 + ISOL_DISTINCT_COUNT 1 + + RUN_NO 3 + TRN_DISTINCT_COUNT 3 + WAIT_DISTINCT_COUNT 1 + ISOL_DISTINCT_COUNT 1 + + RUN_NO 4 + TRN_DISTINCT_COUNT 3 + WAIT_DISTINCT_COUNT 1 + ISOL_DISTINCT_COUNT 1 + """ + +@pytest.mark.version('>=3.0') +def test_core_3100_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3101.py b/tests/bugs/test_core_3101.py new file mode 100644 index 00000000..e8105b70 --- /dev/null +++ b/tests/bugs/test_core_3101.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: bugs.core_3101 +# title: Cannot alter the domain after migrating from older versions +# decription: +# tracker_id: CORE-3101 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core3101-ods11.fbk', init=init_script_1) + +test_script_1 = """ + show domain state; + alter domain state set default 0; + commit; + show domain state; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + STATE SMALLINT Nullable + STATE SMALLINT Nullable + default 0 + """ + +@pytest.mark.version('>=2.5') +def test_core_3101_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3103.py b/tests/bugs/test_core_3103.py new file mode 100644 index 00000000..e3228df5 --- /dev/null +++ b/tests/bugs/test_core_3103.py @@ -0,0 +1,99 @@ +#coding:utf-8 +# +# id: bugs.core_3103 +# title: BAD PLAN with using LEFT OUTER JOIN in SUBSELECT. See also: CORE-3283 +# decription: Ticket subj: Select statement with more non indexed reads in version 2.5RC3 as in version 2.1.3 +# tracker_id: CORE-3103 +# min_versions: ['2.1.7'] +# versions: 2.1.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + execute block as + begin + begin execute statement 'drop sequence g'; when any do begin end end + end + ^ + set term ;^ + commit; + create sequence g; + commit; + + recreate table bauf(id int); + commit; + recreate table bstammdaten( + id int, maskenkey varchar(10), + constraint tmain_pk primary key(id) using index bstammdaten_id_pk + ); + commit; + recreate table bauf( + id int + ,bstammdaten_id_maskenkey int + ,constraint tdetl_pk primary key(id) using index bauf_pk + ,constraint tdetl_fk foreign key (bstammdaten_id_maskenkey) + references bstammdaten(id) + using index fk_bauf_bstammdaten_id + ); + commit; + + set term ^; + execute block as + declare n_main int = 5000; -- 42000; + declare i int = 0; + begin + while ( i < n_main ) do + begin + insert into bstammdaten(id, maskenkey) values(:i, iif(:i < :n_main / 100, '53', cast(rand()*100 as int) ) ); + insert into bauf(id, bstammdaten_id_maskenkey) values (gen_id(g,1), :i); + if ( rand() < 0.8 ) then + insert into bauf(id, bstammdaten_id_maskenkey) values (gen_id(g,1), :i); + i = i + 1; + end + end + ^set term ;^ + commit; + + create index bstammdaten_maskenkey on bstammdaten(maskenkey); + commit; + set statistics index fk_bauf_bstammdaten_id; + set statistics index bstammdaten_id_pk; + commit; + + + set planonly; + select count(*) from bauf + where id = + ( + select max(b.id) from bstammdaten a + left outer join bauf b on b.bstammdaten_id_maskenkey = a.id + where a.maskenkey='53' + ); + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN JOIN (A INDEX (BSTAMMDATEN_MASKENKEY), B INDEX (FK_BAUF_BSTAMMDATEN_ID)) + PLAN (BAUF INDEX (BAUF_PK)) + """ + +@pytest.mark.version('>=2.1.7') +def test_core_3103_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3131.py b/tests/bugs/test_core_3131.py new file mode 100644 index 00000000..d89e30b1 --- /dev/null +++ b/tests/bugs/test_core_3131.py @@ -0,0 +1,254 @@ +#coding:utf-8 +# +# id: bugs.core_3131 +# title: WIN1257_LV (Latvian) collation is wrong for 4 letters: A E I U. +# decription: +# ::: NOTE ::: +# In order to check correctness of following statements under ISQL itself (NOT under fbt_run), do following: +# 1) open some text editor that supports charset = win1257 and set encoding for new document = WIN1257 +# (e.g. in Notepad++ pull-down menu: "Encoding / Character sets / Baltic / Windows 1257") +# 2) type commands statements that contains diacritical marks (accents) and save to .sql +# 3) open this .sql in FAR editor and ensure that letters with diacritical marks are displayed as SINGLE characters +# 4) run isql -i +# In order to run this script under fbt_run: +# 1) open Notepad++ new .fbt document and set Encoding = "UTF8 without BOM" +# 2) copy-paste text from , ensure that letters with diacritical marks are readable +# (it should be pasted here in UTF8 encoding) +# 3) add in `expected_stdout` section required output by copy-paste from result of isql -i +# (it should be pasted here in UTF8 encoding) +# 4) save .fbt and ensure that it was saved in UTF8 encoding, otherwise exeption like +# "UnicodeDecodeError: 'utf8' codec can't decode byte 0xc3 in position 621: invalid continuation byte" +# will raise. +# +# 05-mar-2021. Re-implemented in order to have ability to run this test on Linux. +# Test encodes to UTF8 all needed statements (SET NAMES; CONNECT; DDL and DML) and stores this text in .sql file. +# NOTE: 'SET NAMES' contain character set that must be used for reproducing problem (WIN1257 in this test). +# Then ISQL is launched in separate (child) process which performs all necessary actions (using required charset). +# Result will be redirected to log(s) which will be opened further via codecs.open(...encoding='cp1257'). +# Finally, its content will be converted to UTF8 for showing in expected_stdout. +# +# Confirmed bug on 2.5.0.26074. Fixed on 2.5.1.26351 and up to 2.5.9.27152 +# +# Checked on: +# * Windows: 4.0.0.2377, 3.0.8.33423 +# * Linux: 4.0.0.2379, 3.0.8.33415 +# +# tracker_id: CORE-3131 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='WIN1257', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import codecs +# import subprocess +# import time +# engine = db_conn.engine_version +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql_txt=''' set bail on; +# set names win1257; +# connect '%(dsn)s' user '%(user_name)s' password '%(user_password)s'; +# +# create collation coll_1257_ci_ai +# for win1257 from win1257_lv +# no pad case insensitive accent sensitive; +# commit; +# +# create table test1257 ( +# letter varchar(2) collate coll_1257_ci_ai, +# sort_index smallint +# ); +# +# -- ### ONCE AGAIN ### +# -- 1) for checking this under ISQL following must be encoded in WIN1257 +# -- 2) for running under fbt_run utility following must be encoded in UTF8. +# insert into test1257 values ('Iz', 18); +# insert into test1257 values ('Īb', 19); +# insert into test1257 values ('Īz', 20); +# +# insert into test1257 values ('Ķz', 24); +# insert into test1257 values ('Ēz', 12); +# insert into test1257 values ('Gb', 13); +# +# insert into test1257 values ('Ģz', 16); +# insert into test1257 values ('Ib', 17); +# +# insert into test1257 values ('Gz', 14); +# insert into test1257 values ('Ģb', 15); +# +# insert into test1257 values ('Ņb', 31); +# insert into test1257 values ('Ņz', 32); +# insert into test1257 values ('Cb', 5); +# insert into test1257 values ('Ūb', 39); +# insert into test1257 values ('Ūz', 40); +# insert into test1257 values ('Zb', 41); +# insert into test1257 values ('Eb', 9); +# insert into test1257 values ('Ez', 10); +# insert into test1257 values ('Ēb', 11); +# +# insert into test1257 values ('Ub', 37); +# insert into test1257 values ('Uz', 38); +# +# insert into test1257 values ('Lz', 26); +# insert into test1257 values ('Ļb', 27); +# insert into test1257 values ('Ļz', 28); +# insert into test1257 values ('Kb', 21); +# insert into test1257 values ('Kz', 22); +# insert into test1257 values ('Šz', 36); +# insert into test1257 values ('Lb', 25); +# insert into test1257 values ('Cz', 6); +# insert into test1257 values ('Čb', 7); +# insert into test1257 values ('Čz', 8); +# +# insert into test1257 values ('Sb', 33); +# insert into test1257 values ('Sz', 34); +# insert into test1257 values ('Šb', 35); +# +# insert into test1257 values ('Nb', 29); +# insert into test1257 values ('Nz', 30); +# insert into test1257 values ('Ķb', 23); +# insert into test1257 values ('Zz', 42); +# insert into test1257 values ('Žb', 43); +# insert into test1257 values ('Žz', 44); +# +# insert into test1257 values ('Ab', 1); +# insert into test1257 values ('Az', 2); +# insert into test1257 values ('Āb', 3); +# insert into test1257 values ('Āz', 4); +# commit; +# +# set heading off; +# select * +# from test1257 tls +# order by tls.letter collate coll_1257_ci_ai; +# +# ''' % dict(globals(), **locals()) +# +# f_run_sql = open( os.path.join(context['temp_directory'], 'tmp_3131_win1257.sql'), 'w' ) +# f_run_sql.write( sql_txt.decode('utf8').encode('cp1257') ) +# flush_and_close( f_run_sql ) +# +# # result: file tmp_3131_win1257.sql is encoded in win1257 +# +# f_run_log = open( os.path.splitext(f_run_sql.name)[0]+'.log', 'w') +# subprocess.call( [ context['isql_path'], '-q', '-i', f_run_sql.name ], +# stdout = f_run_log, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_run_log ) # result: output will be encoded in win1257 +# +# with codecs.open(f_run_log.name, 'r', encoding='cp1257' ) as f: +# result_in_win1257 = f.readlines() +# +# for i in result_in_win1257: +# print( i.encode('utf8') ) +# +# # cleanup: +# ########### +# cleanup( (f_run_sql, f_run_log) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Ab 1 + Az 2 + Āb 3 + Āz 4 + Cb 5 + Cz 6 + Čb 7 + Čz 8 + Eb 9 + Ez 10 + Ēb 11 + Ēz 12 + Gb 13 + Gz 14 + Ģb 15 + Ģz 16 + Ib 17 + Iz 18 + Īb 19 + Īz 20 + Kb 21 + Kz 22 + Ķb 23 + Ķz 24 + Lb 25 + Lz 26 + Ļb 27 + Ļz 28 + Nb 29 + Nz 30 + Ņb 31 + Ņz 32 + Sb 33 + Sz 34 + Šb 35 + Šz 36 + Ub 37 + Uz 38 + Ūb 39 + Ūz 40 + Zb 41 + Zz 42 + Žb 43 + Žz 44 + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_3131_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_3137.py b/tests/bugs/test_core_3137.py new file mode 100644 index 00000000..67a8def5 --- /dev/null +++ b/tests/bugs/test_core_3137.py @@ -0,0 +1,73 @@ +#coding:utf-8 +# +# id: bugs.core_3137 +# title: Partial rollback is possible for a selectable procedure modifying data +# decription: +# tracker_id: CORE-3137 +# min_versions: ['2.1.4'] +# versions: 2.1.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create or alter procedure sp_01 returns (ret int) as begin end; + commit; + recreate table tab (col int); + commit; + insert into tab (col) values (1); + commit; + + set term ^; + create or alter procedure sp_01 returns (ret int) as + begin + update tab set col = 2; + begin + update tab set col = 3; + ret = 1; + suspend; + end + when any do + begin + ret = 0; + suspend; + end + end + ^ set term ;^ + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select col from tab; -- returns 1 + commit; + + select ret from sp_01; + rollback; + + select col from tab; -- returns 2!!! + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + COL 1 + RET 1 + COL 1 + """ + +@pytest.mark.version('>=2.1.4') +def test_core_3137_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3140.py b/tests/bugs/test_core_3140.py new file mode 100644 index 00000000..30d963ed --- /dev/null +++ b/tests/bugs/test_core_3140.py @@ -0,0 +1,181 @@ +#coding:utf-8 +# +# id: bugs.core_3140 +# title: Preserve comments for parameters after altering procedures +# decription: +# tracker_id: CORE-3140 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter procedure sp_01 as begin end; + commit; + set term ^; + execute block as + begin + begin execute statement 'drop domain dm_i'; when any do begin end end + begin execute statement 'drop domain dm_s'; when any do begin end end + begin execute statement 'drop domain dm_t'; when any do begin end end + begin execute statement 'drop domain dm_b'; when any do begin end end + end^ + set term ;^ + commit; + + create domain dm_i int; + create domain dm_s varchar(10); + create domain dm_t timestamp; + create domain dm_b blob; + + recreate table t_01(id int, s varchar(10), dts timestamp, b blob); + commit; + + set term ^; + create or alter procedure sp_01( + a_01 int + ,a_02 varchar(10) + ,a_03 timestamp + ,a_04 blob + ) returns ( + o_01 int + ,o_02 varchar(10) + ,o_03 timestamp + ,o_04 blob + ) as + begin + suspend; + end + ^ + set term ;^ + commit; + comment on parameter sp_01.a_01 is 'INPUT par. ''a_01'', mech = 0'; + comment on parameter sp_01.a_02 is 'INPUT par. ''a_02'', mech = 0'; + comment on parameter sp_01.a_03 is 'INPUT par. ''a_03'', mech = 0'; + comment on parameter sp_01.a_04 is 'INPUT par. ''a_04'', mech = 0'; + comment on parameter sp_01.o_01 is 'OUTPUT par. ''o_01'', mech = 0'; + comment on parameter sp_01.o_02 is 'OUTPUT par. ''o_02'', mech = 0'; + comment on parameter sp_01.o_03 is 'OUTPUT par. ''o_03'', mech = 0'; + comment on parameter sp_01.o_04 is 'OUTPUT par. ''o_04'', mech = 0'; + commit; + + set term ^; + alter procedure sp_01( + a_01 int + ,a_02 varchar(10) + ,a_03 timestamp + ,a_04 blob + ,a_05 type of dm_i + ,a_06 type of dm_s + ,a_07 type of dm_t + ,a_08 type of dm_b + ) returns ( + o_01 int + ,o_02 varchar(10) + ,o_03 timestamp + ,o_04 blob + ,o_05 type of column t_01.id + ,o_06 type of column t_01.id + ,o_07 type of column t_01.id + ,o_08 type of column t_01.id + ) as + begin + suspend; + end + ^ + set term ;^ + commit; + + comment on parameter sp_01.a_05 is 'added INPUT par ''a_05'', mech = 1'; + comment on parameter sp_01.a_06 is 'added INPUT par ''a_06'', mech = 1'; + comment on parameter sp_01.a_07 is 'added INPUT par ''a_07'', mech = 1'; + comment on parameter sp_01.a_08 is 'added INPUT par ''a_08'', mech = 1'; + + comment on parameter sp_01.o_05 is 'added OUTPUT par ''o_05'', mech = 1'; + comment on parameter sp_01.o_06 is 'added OUTPUT par ''o_06'', mech = 1'; + comment on parameter sp_01.o_07 is 'added OUTPUT par ''o_07'', mech = 1'; + comment on parameter sp_01.o_08 is 'added OUTPUT par ''o_08'', mech = 1'; + commit; + + set width par_name 31; + set width par_desc 50; + set list on; + select + cast(rdb$parameter_name as varchar(31)) par_name, + cast(rdb$description as varchar(50)) par_desc, + coalesce(rdb$parameter_mechanism, 0 ) par_mech + from rdb$procedure_parameters + where rdb$procedure_name='SP_01' + order by par_name; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PAR_NAME A_01 + PAR_DESC INPUT par. 'a_01', mech = 0 + PAR_MECH 0 + PAR_NAME A_02 + PAR_DESC INPUT par. 'a_02', mech = 0 + PAR_MECH 0 + PAR_NAME A_03 + PAR_DESC INPUT par. 'a_03', mech = 0 + PAR_MECH 0 + PAR_NAME A_04 + PAR_DESC INPUT par. 'a_04', mech = 0 + PAR_MECH 0 + PAR_NAME A_05 + PAR_DESC added INPUT par 'a_05', mech = 1 + PAR_MECH 1 + PAR_NAME A_06 + PAR_DESC added INPUT par 'a_06', mech = 1 + PAR_MECH 1 + PAR_NAME A_07 + PAR_DESC added INPUT par 'a_07', mech = 1 + PAR_MECH 1 + PAR_NAME A_08 + PAR_DESC added INPUT par 'a_08', mech = 1 + PAR_MECH 1 + PAR_NAME O_01 + PAR_DESC OUTPUT par. 'o_01', mech = 0 + PAR_MECH 0 + PAR_NAME O_02 + PAR_DESC OUTPUT par. 'o_02', mech = 0 + PAR_MECH 0 + PAR_NAME O_03 + PAR_DESC OUTPUT par. 'o_03', mech = 0 + PAR_MECH 0 + PAR_NAME O_04 + PAR_DESC OUTPUT par. 'o_04', mech = 0 + PAR_MECH 0 + PAR_NAME O_05 + PAR_DESC added OUTPUT par 'o_05', mech = 1 + PAR_MECH 1 + PAR_NAME O_06 + PAR_DESC added OUTPUT par 'o_06', mech = 1 + PAR_MECH 1 + PAR_NAME O_07 + PAR_DESC added OUTPUT par 'o_07', mech = 1 + PAR_MECH 1 + PAR_NAME O_08 + PAR_DESC added OUTPUT par 'o_08', mech = 1 + PAR_MECH 1 + """ + +@pytest.mark.version('>=2.5.1') +def test_core_3140_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3141.py b/tests/bugs/test_core_3141.py new file mode 100644 index 00000000..e5141616 --- /dev/null +++ b/tests/bugs/test_core_3141.py @@ -0,0 +1,156 @@ +#coding:utf-8 +# +# id: bugs.core_3141 +# title: The last column in a view is returning as a null value even when it's not +# decription: +# Confirmed wrong resultset on 2.5.0.26074. +# Checked on: +# 4.0.0.1635 SS: 1.701s. +# 3.0.5.33182 SS: 1.394s. +# 2.5.9.27146 SC: 0.524s. +# NB: new datatype in FB 4.0 was introduces: numeric(38,0). +# It leads to additional ident of values when we show them in form "SET LIST ON", +# so we have to ignore all internal spaces - see added 'substitution' section below. +# +# tracker_id: CORE-3141 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + create table test( + id integer, + datum date, + sfield varchar (10), + num1 numeric (10,2), + num2 numeric (10,2), + primary key (id) + ); + commit; + + insert into test values (1, '2013-06-04', 'A', 10, 0); + insert into test values (2, '2013-06-04', 'B', 0, 10); + insert into test values (3, '2013-06-04', 'A', 20, 0); + insert into test values (4, '2013-06-04', 'B', 0, 20); + + create view v_test1 as + select + t.datum, + iif ((select sum(num1-num2) from test where sfield = 'A' and datum <= t.datum) is null, 0, (select sum(num1-num2) from test where sfield = 'A' and datum <= t.datum)) A, + iif ((select sum(num1-num2) from test where sfield = 'A' and datum <= t.datum) is null, 0, (select sum(num1-num2) from test where sfield = 'B' and datum <= t.datum)) B, + iif ((select sum(num1-num2) from test where sfield = 'A' and datum <= t.datum) is null, 0, (select sum(num1-num2) from test where sfield = 'A' and datum <= t.datum)) A1, + iif ((select sum(num1-num2) from test where sfield = 'A' and datum <= t.datum) is null, 0, (select sum(num1-num2) from test where sfield = 'B' and datum <= t.datum)) B1 + from test t + group by t.datum; + + create view v_test2 as + select + t.datum, + 0 as A, + 0 as B, + 0 as A1, + 10 as B1 + from test t + group by t.datum; + commit; + + select 'test_1a' as msg, v.* from v_test1 v; + select 'test_1b' as msg, v.* from v_test2 v; + commit; + + drop view v_test1; + drop view v_test2; + drop table test; + + --------------------------------------------- + + -- From core-3159: + recreate view v_test1 as select 1 i from rdb$database; + commit; + + recreate table test1 ( + id integer default 0 not null, + variance numeric (10,2), + anumber integer default 0, + primary key (id) + ); + recreate table test2 ( + id integer default 0 not null, + primary key (id) + ); + + recreate view v_test1 (databasename, testvalue, placer) as + select id, (select sum (variance) from test1 where anumber = 10), 10 + from test2 + group by id; + commit; + + insert into test1 (id, variance, anumber) + values (1, 100.00, 10); + + insert into test1 (id, variance, anumber) + values (2, 150.00, 10); + + insert into test1 (id, variance, anumber) + values (3, 150.00, 12); + + commit; + + insert into test2 (id) values (10); + insert into test2 (id) values (12); + + commit; + + select 'test_2' as msg, v.* from v_test1 v; --this one doesn't + commit; + drop view v_test1; + drop table test1; + drop table test2; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG test_1a + DATUM 2013-06-04 + A 30.00 + B -30.00 + A1 30.00 + B1 -30.00 + MSG test_1b + DATUM 2013-06-04 + A 0 + B 0 + A1 0 + B1 10 + MSG test_2 + DATABASENAME 10 + TESTVALUE 250.00 + PLACER 10 + MSG test_2 + DATABASENAME 12 + TESTVALUE 250.00 + PLACER 10 + """ + +@pytest.mark.version('>=2.5.1') +def test_core_3141_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3164.py b/tests/bugs/test_core_3164.py new file mode 100644 index 00000000..b0feca2f --- /dev/null +++ b/tests/bugs/test_core_3164.py @@ -0,0 +1,71 @@ +#coding:utf-8 +# +# id: bugs.core_3164 +# title: Parameterized requests involving blob fields fails when connected using charset UTF8 +# decription: +# tracker_id: CORE-3164 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table test(fb blob); + commit; + insert into test values(rpad('', 7, 'foo') ); + insert into test values(rpad('', 8, 'bar') ); + commit; + + set list on; + + set term ^; + execute block returns(n int) as + declare v_blob blob; + begin + + for + select fb from test + into v_blob + do + begin + execute statement ('select octet_length(fb) from test where fb starting with ?') (:v_blob) into n; + suspend; + end + end + ^ + set term ;^ + -- Confirmed for 2.5.0 (WI-V2.5.0.26074): + -- Statement failed, SQLSTATE = 22001 + -- arithmetic exception, numeric overflow, or string truncation + -- -string right truncation + -- (instead of output N = 8 for second record) + -- Seems to be relatoed to core-3353 // Predicate (blob_field LIKE ?) describes the parameter as VARCHAR(30) rather than as BLOB + -- because of SQLDA content: + -- In 2.5.0: sqltype: 449 VARYING Nullable sqlscale: 0 sqlsubtype: 4 sqllen: 28 + -- In 2.5.1: sqltype: 521 BLOB Nullable sqlscale: 0 sqlsubtype: 0 sqllen: 8 + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + N 7 + N 8 + """ + +@pytest.mark.version('>=2.5.1') +def test_core_3164_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3168.py b/tests/bugs/test_core_3168.py new file mode 100644 index 00000000..daa0d110 --- /dev/null +++ b/tests/bugs/test_core_3168.py @@ -0,0 +1,271 @@ +#coding:utf-8 +# +# id: bugs.core_3168 +# title: exclude_filter doesn't work for section of the Trace facility +# decription: +# Note. It was encountered that FBSVCMGR does NOT wait for OS completes writing of its output on disk, +# (see CORE-4896), so we use delays - see calls of time.sleep(). +# +# Correct work was checked on: WI-V2.5.5.26916 (SS, SC) and WI-V3.0.0.31948 (SS, SC, CS) +# Refactored 17.12.2016 after encountering CORE-5424 ("restore process is impossible when trace ..."): +# added checking of STDERR logs for all fbsvcmgr actions. +# +# ----------------------------------------- +# Updated 27.03.2017: moved artificial delay (1 sec) at proper place. +# It should be just after +# subprocess.call('fbsvcmgr', 'localhost:service_mgr', 'action_trace_stop', ...) +# and BEFORE 'p_trace.terminate()' command. +# ----------------------------------------- +# +# Test time (approx): +# 2.5.7.27030: SC = 3" +# 3.0.232644 and 4.0.0.463: SS = SC = 6"; CS = 15" +# Checked on 2.5.8.27056, CLASSIC server: 3.6" (27-03-2017) +# +# 13.04.2021. Adapted for run both on Windows and Linux. Checked on: +# Windows: 3.0.8.33445, 4.0.0.2416 +# Linux: 3.0.8.33426, 4.0.0.2416 +# +# +# tracker_id: CORE-3168 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('^((?!ERROR|ELEMENT|PROPERTIES|STATS|BACKUP|RESTORE).)*$', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import time +# from fdb import services +# from subprocess import Popen +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # Obtain engine version: +# engine = str(db_conn.engine_version) # convert to text because 'float' object has no attribute 'startswith' +# db_conn.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 ) +# +# #-------------------------------------------- +# +# +# # ::: NB ::: Trace config file format in 3.0 differs from 2.5 one: +# # 1) header section must be enclosed in "[" and "]", +# # 2) parameter-value pairs must be separated with '=' sign: +# # services +# # { +# # parameter = value +# # } +# +# if engine.startswith('2.5'): +# txt = '''# Generated auto, do not edit! +# +# enabled true +# log_services true +# +# # This should prevent appearance of messages like "List Trace Session(s)" or "Start Trace Session(s)": +# exclude_filter "%(List|LIST|list|Start|START|start)[[:WHITESPACE:]]+(Trace|TRACE|trace)[[:WHITESPACE:]]+(Session|SESSION|session)%" +# +# # This should work even if we filter out messages about list/start trace session(s) +# # (and test also check corret work of THIS filter beside previous `exclude`): +# # include_filter "Database Stats" +# +# ''' +# else: +# txt = '''# Generated auto, do not edit! +# services +# { +# enabled = true +# log_services = true +# +# # This should prevent appearance of messages like "List Trace Session(s)" or "Start Trace Session(s)": +# exclude_filter = "%(List|LIST|list|Start|START|start)[[:WHITESPACE:]]+(Trace|TRACE|trace)[[:WHITESPACE:]]+(Session|SESSION|session)%" +# +# # This should work even if we filter out messages about list/start trace session(s) +# # (and test also check corret work of THIS filter beside previous `exclude`): +# # include_filter = "Database Stats" +# } +# ''' +# +# f_trc_cfg=open( os.path.join(context['temp_directory'],'tmp_trace_3168.cfg'), 'w') +# f_trc_cfg.write(txt) +# f_trc_cfg.close() +# +# # Instead of using 'start /min cmd /c fbsvcmgr ... 1>%2 2>&1' deciced to exploite Popen in order to run asynchronous process +# # without opening separate window. Output is catched into `trclog` file, which will be closed after call fbsvcmgr with argument +# # 'action_trace_stop' (see below): +# # See also: +# # https://docs.python.org/2/library/subprocess.html +# # http://stackoverflow.com/questions/11801098/calling-app-from-subprocess-call-with-arguments +# +# # ############################################################## +# # S T A R T T R A C E i n S E P A R A T E P R O C E S S +# # ############################################################## +# +# f_trc_log=open( os.path.join(context['temp_directory'],'tmp_trace_3168.log'), "w") +# f_trc_err=open( os.path.join(context['temp_directory'],'tmp_trace_3168.err'), "w") +# +# p_trace = Popen([ context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_start' , 'trc_cfg', f_trc_cfg.name],stdout=f_trc_log,stderr=f_trc_err) +# +# thisdb='$(DATABASE_LOCATION)bugs.core_3168.fdb' +# tmpbkp='$(DATABASE_LOCATION)bugs.core_3168_fbk.tmp' +# tmpres='$(DATABASE_LOCATION)bugs.core_3168_new.tmp' +# +# f_run_log=open( os.path.join(context['temp_directory'],'tmp_action_3168.log'), 'w') +# f_run_err=open( os.path.join(context['temp_directory'],'tmp_action_3168.err'), 'w') +# +# subprocess.call( [ context['fbsvcmgr_path'], 'localhost:service_mgr','action_properties','dbname', thisdb,'prp_sweep_interval', '1234321'], stdout=f_run_log,stderr=f_run_err) +# subprocess.call( [ context['fbsvcmgr_path'], 'localhost:service_mgr','action_db_stats', 'dbname', thisdb, 'sts_hdr_pages'], stdout=f_run_log,stderr=f_run_err) +# subprocess.call( [ context['fbsvcmgr_path'], 'localhost:service_mgr','action_backup', 'dbname', thisdb, 'bkp_file', tmpbkp], stdout=f_run_log,stderr=f_run_err) +# subprocess.call( [ context['fbsvcmgr_path'], 'localhost:service_mgr','action_restore', 'bkp_file', tmpbkp, 'dbname', tmpres, 'res_replace'], stdout=f_run_log,stderr=f_run_err) +# +# flush_and_close( f_run_log ) +# flush_and_close( f_run_err ) +# +# # do NOT try to get FB log! It can contain non-ascii messages which lead to runtime fault of fbtest! +# # (see CORE-5418): +# # runProgram(context['fbsvcmgr_path'],['localhost:service_mgr','action_get_fb_log']) +# +# +# # #################################################### +# # G E T A C T I V E T R A C E S E S S I O N I D +# # #################################################### +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# +# f_trc_lst = open( os.path.join(context['temp_directory'],'tmp_trace_3168.lst'), 'w') +# subprocess.call([context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_list'], stdout=f_trc_lst) +# flush_and_close( f_trc_lst ) +# +# # !!! DO NOT REMOVE THIS LINE !!! +# time.sleep(1) +# +# trcssn=0 +# with open( f_trc_lst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# +# # #################################################### +# # S E N D R E Q U E S T T R A C E T O S T O P +# # #################################################### +# +# fn_nul = open(os.devnull, 'w') +# subprocess.call([context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_stop','trc_id', trcssn], stdout=fn_nul) +# fn_nul.close() +# +# # ::: NB ::: Artificial delay, Added 27.03.2017. +# # Do NOT remove this line otherwise record with 'database restore' may not appear +# # in the final trace log (file buffer is flushed not instantly). +# time.sleep(1) +# +# +# # Doc about Popen.terminate(): +# # https://docs.python.org/2/library/subprocess.html +# # Stop the child. On Posix OSs the method sends SIGTERM to the child. +# # On Windows the Win32 API function TerminateProcess() is called to stop the child. +# +# # Doc about Win API TerminateProcess() function: +# # https://msdn.microsoft.com/en-us/library/windows/desktop/ms686714%28v=vs.85%29.aspx +# # The terminated process cannot exit until all pending I/O has been completed or canceled. +# # TerminateProcess is ____asynchronous____; it initiates termination and returns immediately. +# # ^^^^^^^^^^^^ +# +# p_trace.terminate() +# flush_and_close(f_trc_log) +# flush_and_close(f_trc_err) +# +# # Should be EMPTY: +# with open( f_trc_err.name,'r') as f: +# for line in f: +# if line.split(): +# print('fbsvcmgr(1) unexpected STDERR: '+line.upper() ) +# +# # Should be EMPTY: +# with open( f_run_err.name,'r') as f: +# for line in f: +# if line.split(): +# print('fbsvcmgr(2) unexpected STDERR: '+line.upper() ) +# +# # Output log of trace for comparing it with expected. +# # ::: NB ::: Content if trace log is converted to UPPER case in order to reduce change of mismatching with +# # updated trace output in some future versions: +# +# with open( f_trc_log.name,'r') as f: +# for line in f: +# if line.split(): +# print(line.upper()) +# +# # CLEANUP +# ######### +# time.sleep(1) +# cleanup( (f_trc_cfg, f_trc_lst, f_trc_log, f_trc_err, f_run_log, f_run_err, tmpbkp, tmpres) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + "DATABASE PROPERTIES" + "DATABASE STATS" + "BACKUP DATABASE" + "RESTORE DATABASE" + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_3168_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_3173.py b/tests/bugs/test_core_3173.py new file mode 100644 index 00000000..eab40904 --- /dev/null +++ b/tests/bugs/test_core_3173.py @@ -0,0 +1,103 @@ +#coding:utf-8 +# +# id: bugs.core_3173 +# title: Empty result when select from SP that contains two CTE (second of them with GROUP BY clause) and INNER join +# decription: +# tracker_id: CORE-3173 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create or alter procedure sp_main as begin end; + create or alter procedure sp_aux1 as begin end; + commit; + + recreate table zzz_tbl ( + id integer, + company_id integer, + hire_date date + ); + insert into zzz_tbl (id, company_id, hire_date) + values (123456, 654321, '01.10.2004'); + commit; + + set term ^; + create or alter procedure sp_aux1 returns (val integer) + as begin + val=1; + suspend; + end + ^ + commit ^ + + create or alter procedure sp_main ( + COMPANY_ID integer, + A_MONTH_BEG date) + returns ( + PERSON_ID integer) + AS + begin + for + with + inp as( + select + company_id + ,dateadd(1 month to p1)-1 p2 + from( + select + :company_id company_id,:a_month_beg p1 + --654321 company_id,cast('01.09.2010' as date) p1 + from + --rdb$database + sp_aux1 + )t + ) + + ,person_nfo as + ( + select n.id person_id,i.p2 + --from inp i join zzz_tbl n on n.company_id = i.company_id + from zzz_tbl n left join inp i on n.company_id = i.company_id + group by n.id,p2 + ) + + select f.person_id + from person_nfo f + join zzz_tbl nt on nt.hire_date <= f.p2 + into :person_id + do suspend; + end + + ^ set term ;^ + commit; + + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select * from sp_main(654321, '01.09.2010'); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PERSON_ID 123456 + """ + +@pytest.mark.version('>=2.5.1') +def test_core_3173_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3174.py b/tests/bugs/test_core_3174.py new file mode 100644 index 00000000..cccb4714 --- /dev/null +++ b/tests/bugs/test_core_3174.py @@ -0,0 +1,174 @@ +#coding:utf-8 +# +# id: bugs.core_3174 +# title: Expression index with TRIM may lead to incorrect indexed lookup +# decription: +# tracker_id: CORE-3174 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """ + create collation ps_yes for utf8 from unicode pad space; + create collation ps_no for utf8 from unicode no pad; + + create table t (id int, c_pad varchar(10), c_nopad varchar(10) character set utf8 collate ps_no); + commit; + insert into t(id, c_pad, c_nopad) values (1, '123', '123'); + insert into t(id, c_pad, c_nopad) values (2, ' 123', ' 123'); + insert into t(id, c_pad, c_nopad) values (3, '123 ', '123 '); + insert into t(id, c_pad, c_nopad) values (4, ' 123 ', ' 123 '); + commit; + + create index t_c_pad_trim_right on t computed by (trim(trailing from c_pad)); + create index t_c_pad_trim_left on t computed by (trim(leading from c_pad)); + create index t_c_nopad_trim_right on t computed by (trim(trailing from c_nopad)); + create index t_c_nopad_trim_left on t computed by (trim(leading from c_nopad)); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set plan on; + --set echo on; + + select '1.a' as test_no, id,'.' || c_pad || '.' as c_pad from t where trim(c_pad) = '123'; + select '1.b' as test_no, id,'.' || c_pad || '.' as c_pad from t where trim(trailing from c_pad) = trim(leading from c_pad); + select '1.c' as test_no, id,'.' || c_pad || '.' as c_pad from t where trim(trailing from c_pad) = '123'; + select '1.d' as test_no, id,'.' || c_pad || '.' as c_pad from t where trim(leading from c_pad) = '123'; + select '1.e' as test_no, id,'.' || c_pad || '.' as c_pad from t where trim(trailing from c_pad) starting with '123'; + select '1.f' as test_no, id,'.' || c_pad || '.' as c_pad from t where trim(leading from c_pad) starting with '123'; + + ------------------------------------------------------------------------- + + select '2.a' as test_no, id,'.' || c_nopad || '.' as c_nopad from t where trim(c_nopad) = '123'; + select '2.b' as test_no, id,'.' || c_nopad || '.' as c_nopad from t where trim(trailing from c_nopad) = trim(leading from c_nopad); + select '2.c' as test_no, id,'.' || c_nopad || '.' as c_nopad from t where trim(trailing from c_nopad) = '123'; + select '2.d' as test_no, id,'.' || c_nopad || '.' as c_nopad from t where trim(leading from c_nopad) = '123'; + select '2.f' as test_no, id,'.' || c_nopad || '.' as c_nopad from t where trim(trailing from c_nopad) starting with '123'; + select '2.g' as test_no, id,'.' || c_nopad || '.' as c_nopad from t where trim(leading from c_nopad) starting with '123'; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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)) + + TEST_NO ID C_NOPAD + ======= ============ ================================================ + 2.g 1 .123. + 2.g 2 . 123. + 2.g 3 .123 . + 2.g 4 . 123 . + """ + +@pytest.mark.version('>=3.0') +def test_core_3174_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3176.py b/tests/bugs/test_core_3176.py new file mode 100644 index 00000000..fba60bb8 --- /dev/null +++ b/tests/bugs/test_core_3176.py @@ -0,0 +1,55 @@ +#coding:utf-8 +# +# id: bugs.core_3176 +# title: View with "subselect" column join table and not use index +# decription: +# tracker_id: CORE-3176 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """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_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT * FROM tmp_view TV LEFT JOIN tmp T ON T.id=TV.id2; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Database: localhost:C:\\Users\\win7\\Firebird_tests\\fbt-repository\\tmp\\bugs.core_3176.fdb, User: SYSDBA +SQL> SQL> +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 + +SQL>""" + +@pytest.mark.version('>=2.5.1') +def test_core_3176_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3180.py b/tests/bugs/test_core_3180.py new file mode 100644 index 00000000..cd9dc60c --- /dev/null +++ b/tests/bugs/test_core_3180.py @@ -0,0 +1,55 @@ +#coding:utf-8 +# +# id: bugs.core_3180 +# title: ALTER VIEW with not matched columns in declaration and selection crashs the server +# decription: +# tracker_id: CORE-3180 +# min_versions: ['2.5.1'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create view TEST_VIEW (ID) as select 1 from rdb$database; +commit;""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """alter view TEST_VIEW (ID) as select 1, 2 from rdb$database; +COMMIT; +SHOW VIEW TEST_VIEW; + + + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Database: localhost:C:\\Users\\win7\\Firebird_tests bt-repository mpugs.core_3180.fdb, User: SYSDBA +SQL> SQL> SQL> ID INTEGER Expression +View Source: +==== ====== + select 1 from rdb$database +SQL> SQL> SQL> SQL>""" +expected_stderr_1 = """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 +""" + +@pytest.mark.version('>=3.0') +def test_core_3180_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3188.py b/tests/bugs/test_core_3188.py new file mode 100644 index 00000000..2c15783b --- /dev/null +++ b/tests/bugs/test_core_3188.py @@ -0,0 +1,168 @@ +#coding:utf-8 +# +# id: bugs.core_3188 +# title: page 0 is of wrong type (expected 6, found 1) +# decription: +# Confirmed on WI-V2.5.0.26074 +# exception: +# DatabaseError: +# Error while commiting transaction: +# - SQLCODE: -902 +# - database file appears corrupt (C:\\MIX\\FIREBIRD\\QA\\FBT-REPO\\TMP\\BUGS.CORE_3188.FDB) +# - wrong page type +# - page 0 is of wrong type (expected 6, found 1) +# -902 +# 335544335 +# +# New messages in firebird.log in 2.5.0 after running ticket statements: +# +# CSPROG (Client) Mon Feb 15 07:28:05 2016 +# INET/inet_error: connect errno = 10061 +# CSPROG Mon Feb 15 07:41:02 2016 +# Shutting down the server with 0 active connection(s) to 0 database(s), 1 active service(s) +# +# tracker_id: CORE-3188 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import difflib +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# engine = str(db_conn.engine_version) +# db_conn.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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# def svc_get_fb_log( engine, f_fb_log ): +# +# import subprocess +# +# # ::: NB ::: Service call for receive firebird.log works properly only since FB 2.5.2! +# +# if engine.startswith('2.5'): +# get_firebird_log_key='action_get_ib_log' +# else: +# get_firebird_log_key='action_get_fb_log' +# +# subprocess.call([ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# get_firebird_log_key +# ], +# stdout=f_fb_log, stderr=subprocess.STDOUT +# ) +# return +# +# #-------------------------------------------- +# +# +# # Start two attachments: +# con1 = kdb.connect(dsn=dsn) +# con2 = kdb.connect(dsn=dsn) +# +# # Session-1: +# c1 = con1.cursor() +# +# +# f_fblog_before=open( os.path.join(context['temp_directory'],'tmp_3188_fblog_before.txt'), 'w') +# svc_get_fb_log( engine, f_fblog_before ) +# flush_and_close( f_fblog_before ) +# +# c1.execute("create table test(id int primary key)") +# con1.commit() +# +# # Session-2: +# +# c2 = con2.cursor() +# c2.execute('drop table test') +# con2.commit() +# +# # cleanup +# con1.close() +# con2.close() +# +# f_fblog_after=open( os.path.join(context['temp_directory'],'tmp_3188_fblog_after.txt'), 'w') +# svc_get_fb_log( engine, f_fblog_after ) +# flush_and_close( f_fblog_after ) +# +# # Now we can compare two versions of firebird.log and check their difference. +# +# oldfb=open(f_fblog_before.name, 'r') +# newfb=open(f_fblog_after.name, 'r') +# +# difftext = ''.join(difflib.unified_diff( +# oldfb.readlines(), +# newfb.readlines() +# )) +# oldfb.close() +# newfb.close() +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_3188_diff.txt'), 'w') +# f_diff_txt.write(difftext) +# flush_and_close( f_diff_txt ) +# +# # Difference of firebird.log should be EMPTY: +# +# with open( f_diff_txt.name,'r') as f: +# print( f.read() ) +# f.close() +# +# ############################### +# # Cleanup. +# cleanup( [i.name for i in (f_fblog_before, f_fblog_after, f_diff_txt)] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.1') +@pytest.mark.xfail +def test_core_3188_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_3201.py b/tests/bugs/test_core_3201.py new file mode 100644 index 00000000..612b5a69 --- /dev/null +++ b/tests/bugs/test_core_3201.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: bugs.core_3201 +# title: ATAN2 returns incorrect value for (0, 0) +# decription: +# tracker_id: CORE-3201 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select ATAN2(0, 0) undef_atan from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + expression evaluation not supported + -Arguments for ATAN2 cannot both be zero + """ + +@pytest.mark.version('>=3.0') +def test_core_3201_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_3204.py b/tests/bugs/test_core_3204.py new file mode 100644 index 00000000..2f191c64 --- /dev/null +++ b/tests/bugs/test_core_3204.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: bugs.core_3204 +# title: Constraint violation error of CAST is not raised inside views +# decription: +# tracker_id: CORE-3204 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter view v1 as select 1 id from rdb$database; + commit; + set term ^; + execute block as + begin + execute statement 'drop domain d1'; + when any do begin end + end + ^ + set term ;^ + commit; + + create domain d1 integer not null; + commit; + + set list on; + + select cast(null as d1) from rdb$database; -- error: ok + commit; + + create or alter view v1 as select cast(null as d1) x from rdb$database; + commit; + + select * from v1; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + validation error for CAST, value "*** null ***" + Statement failed, SQLSTATE = 42000 + validation error for CAST, value "*** null ***" + """ + +@pytest.mark.version('>=3.0') +def test_core_3204_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_3210.py b/tests/bugs/test_core_3210.py new file mode 100644 index 00000000..9bc72d2d --- /dev/null +++ b/tests/bugs/test_core_3210.py @@ -0,0 +1,56 @@ +#coding:utf-8 +# +# id: bugs.core_3210 +# title: The cursor identified in the UPDATE or DELETE statement is not positioned on a row. no current record for fetch operation in SELECT query +# decription: +# tracker_id: CORE-3210 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core3210.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + select count(*) cnt + from ( + select + depozit.number || ' ' || + coalesce( + iif( + nast.bul_id is not null + , coalesce(bulgarians.name,'') || ' ' || coalesce(bulgarians.family,'') + , coalesce(foreigners.name_cyr,foreigners.name_lat) + ) + ,'' + ) as name + from + depozit left join nast on nast.id = depozit.nast_id + left join bulgarians on bulgarians.id = nast.bul_id + left join foreigners on foreigners.id = nast.for_id + order by 1 --- ==> no current record for fetch operation + ); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CNT 171 + """ + +@pytest.mark.version('>=2.5.1') +def test_core_3210_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3211.py b/tests/bugs/test_core_3211.py new file mode 100644 index 00000000..ed50b748 --- /dev/null +++ b/tests/bugs/test_core_3211.py @@ -0,0 +1,56 @@ +#coding:utf-8 +# +# id: bugs.core_3211 +# title: String truncation occurs when selecting from a view containing NOT IN inside +# decription: +# tracker_id: CORE-3211 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE T ( ID integer, FIELD1 varchar(30) ); +COMMIT; +CREATE VIEW VT ( ID ) +AS + select T1.ID from T as T1 where T1.FIELD1 not in ( select T2.FIELD1 from T as T2 where T2.FIELD1 = 'system1' ) +; +COMMIT; +INSERT INTO T (ID, FIELD1) VALUES (1, 'system'); +INSERT INTO T (ID, FIELD1) VALUES (2, 'system'); +INSERT INTO T (ID, FIELD1) VALUES (3, 'system'); +INSERT INTO T (ID, FIELD1) VALUES (4, 'system'); +INSERT INTO T (ID, FIELD1) VALUES (5, 'system'); +COMMIT;""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select * from VT;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Database: localhost:C:\\Users\\win7\\Firebird_tests\\fbt-repository\\tmp\\bugs.core_3211.fdb, User: SYSDBA +SQL> + ID +============ + 1 + 2 + 3 + 4 + 5 + +SQL>""" + +@pytest.mark.version('>=2.5.1') +def test_core_3211_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3222.py b/tests/bugs/test_core_3222.py new file mode 100644 index 00000000..e5c61062 --- /dev/null +++ b/tests/bugs/test_core_3222.py @@ -0,0 +1,58 @@ +#coding:utf-8 +# +# id: bugs.core_3222 +# title: View with "WITH CHECK OPTION" doesn't like TRIM function in WHERE +# decription: +# tracker_id: CORE-3222 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Foo ( + Bar INTEGER, + Str CHAR(31) +); +COMMIT; +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE VIEW VIEW_Foo ( + Bar +) AS SELECT + Bar + FROM Foo + WHERE(Trim(Str) = 'test') +WITH CHECK OPTION +; +COMMIT; +SHOW VIEW VIEW_Foo; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Database: localhost:C:\\Users\\win7\\Firebird_tests\\fbt-repository\\tmp\\bugs.core_3222.fdb, User: SYSDBA +SQL> CON> CON> CON> CON> CON> CON> CON> SQL> SQL> BAR INTEGER Nullable +View Source: +==== ====== + SELECT + Bar + FROM Foo + WHERE(Trim(Str) = 'test') +WITH CHECK OPTION +SQL>""" + +@pytest.mark.version('>=2.5.1') +def test_core_3222_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3227.py b/tests/bugs/test_core_3227.py new file mode 100644 index 00000000..6772d60c --- /dev/null +++ b/tests/bugs/test_core_3227.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_3227 +# title: ASCII_VAL() fails if argument contains multi-byte character anywhere +# decription: +# tracker_id: CORE-3227 +# min_versions: ['2.1.4'] +# versions: 2.1.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """select ascii_val (cast('Hoplala' as char(12) character set utf8)) from rdb$database; +select ascii_val (cast('Hopläla' as char(12) character set utf8)) from rdb$database; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +ASCII_VAL +========= + 72 + + +ASCII_VAL +========= + 72 + +""" + +@pytest.mark.version('>=2.1.4') +def test_core_3227_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3228.py b/tests/bugs/test_core_3228.py new file mode 100644 index 00000000..a146d90f --- /dev/null +++ b/tests/bugs/test_core_3228.py @@ -0,0 +1,70 @@ +#coding:utf-8 +# +# id: bugs.core_3228 +# title: RIGHT() fails with multibyte text blobs > 1024 chars +# decription: +# tracker_id: CORE-3228 +# min_versions: ['2.1.4'] +# versions: 2.1.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """with q (s) as ( + select + cast( + cast('AAA' as char(1021)) || 'ZZZ' + as blob sub_type text character set utf8 + ) + from rdb$database + ) + select right(s, 3) from q; +with q (s) as ( + select + cast( + cast('AAA' as char(1022)) || 'ZZZ' + as blob sub_type text character set utf8 + ) + from rdb$database + ) + select right(s, 3) from q;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Database: localhost:C: btest2 mpugs.core_3228.fdb, User: SYSDBA +SQL> CON> CON> CON> CON> CON> CON> CON> CON> + RIGHT +================= + 0:3 +============================================================================== +RIGHT: +ZZZ +============================================================================== + +SQL> CON> CON> CON> CON> CON> CON> CON> CON> + RIGHT +================= + 0:8 +============================================================================== +RIGHT: +ZZZ +============================================================================== + +SQL>""" + +@pytest.mark.version('>=2.1.4') +def test_core_3228_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3231.py b/tests/bugs/test_core_3231.py new file mode 100644 index 00000000..e9ac27d6 --- /dev/null +++ b/tests/bugs/test_core_3231.py @@ -0,0 +1,59 @@ +#coding:utf-8 +# +# id: bugs.core_3231 +# title: OVERLAY() fails when used with text BLOBs containing multi-byte chars +# decription: +# tracker_id: CORE-3231 +# min_versions: ['2.1.5'] +# versions: 2.1.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# c = db_conn.cursor() +# try: +# c.execute("with q(s) as (select cast('abcdefghijklmno' as blob sub_type 1 character set utf8) from rdb$database) select overlay (s placing cast('0123456789' as blob sub_type 1 character set utf8) from 5) from q") +# c.fetchall() +# except Exception,e: +# print ("Test non multi-bytes Failed") +# print (e) +# else: +# pass +# try: +# c.execute("with q(s) as (select cast('abcdefghijklmno' as blob sub_type 1 character set utf8) from rdb$database) select overlay (s placing cast(_iso8859_1 'áé' as blob sub_type 1 character set utf8) from 5) from q") +# c.fetchall() +# except Exception,e: +# print ("Test utf8 Failed") +# print (e) +# else: +# pass +# try: +# c.execute("with q(s) as (select cast('abcdefghijklmno' as blob sub_type 1 character set utf8) from rdb$database) select overlay (s placing cast(_iso8859_1 'áé' as blob sub_type 1 character set iso8859_1) from 5) from q") +# c.fetchall() +# except Exception,e: +# print ("Test iso8859_1 Failed") +# print (e) +# else: +# pass +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1.5') +@pytest.mark.xfail +def test_core_3231_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_3233.py b/tests/bugs/test_core_3233.py new file mode 100644 index 00000000..6a3a1a87 --- /dev/null +++ b/tests/bugs/test_core_3233.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_3233 +# title: LIKE, STARTING and CONTAINING fail if second operand >= 32K +# decription: +# tracker_id: CORE-3233 +# min_versions: ['2.1.5'] +# versions: 2.1.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table blobz (zin blob sub_type 1); +insert into blobz (zin) values ('woord'); +commit; +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select 1 from blobz where zin like cast(cast('woord' as char(32766)) as blob sub_type 1) || '!' or zin='woord'; +select 1 from blobz where zin like cast(cast('woord' as char(32767)) as blob sub_type 1) || '!' or zin='woord'; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Database: localhost:C: btestnew mpugs.core_3233.fdb, User: SYSDBA +SQL> + CONSTANT +============ + 1 + +SQL> + CONSTANT +============ + 1 + +SQL>""" + +@pytest.mark.version('>=2.1.5') +def test_core_3233_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3234.py b/tests/bugs/test_core_3234.py new file mode 100644 index 00000000..517bc094 --- /dev/null +++ b/tests/bugs/test_core_3234.py @@ -0,0 +1,217 @@ +#coding:utf-8 +# +# id: bugs.core_3234 +# title: Support for text BLOBs >= 32K as first argument for TRIM() +# decription: +# tracker_id: CORE-3234 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- For single-byte (ascii) charset this test was run also two blobs with length 50'000'000 (+3) bytes: result was OK. + -- Current settings check work of TRIM() on blobs with non-ascii characters with octet_length ~ 1'000'000 bytes. + -- Elapsed time on P-IV 3.0 GHz / RAM 2 Gb: ~7 second. + + recreate sequence g; + commit; + + set list on; + set term ^; + + execute block returns( + b1_octet_len int, + b2_octet_len int, + trimmed_octet_len int, + b1_char_len int, + b2_char_len int, + trimmed_char_len int + ) as + declare b1 blob sub_type 1 character set utf8 = ''; + declare b2 blob sub_type 1 character set utf8; + declare v_step int = 8190; + declare v_text varchar(255) character set utf8; + declare n int = 0; + declare k int = 500000; + begin + -- http://www.columbia.edu/kermit/cp1250.html + v_text = + '' + || '€' -- 128 08/00 200 80 EURO SYMBOL + || '‚' -- 130 08/02 202 82 LOW 9 SINGLE QUOTE + || '„' -- 132 08/04 204 84 LOW 9 DOUBLE QUOTE + || '…' -- 133 08/05 205 85 ELLIPSIS + || '†' -- 134 08/06 206 86 DAGGER + || '‡' -- 135 08/07 207 87 DOUBLE DAGGER + || '‰' -- 137 08/09 211 89 PER MIL SIGN + || 'Š' -- 138 08/10 212 8A CAPITAL LETTER S WITH CARON + || '‹' -- 139 08/11 213 8B LEFT SINGLE QUOTE BRACKET + || 'Ś' -- 140 08/12 214 8C CAPITAL LETTER S WITH ACUTE ACCENT + || 'Ť' -- 141 08/13 215 8D CAPITAL LETTER T WITH CARON + || 'Ž' -- 142 08/14 216 8E CAPITAL LETTER Z WITH CARON + || 'Ź' -- 143 08/15 217 8F CAPITAL LETTER Z WITH ACUTE ACCENT + || '‘' -- 145 09/01 221 91 HIGH 6 SINGLE QUOTE + || '’' -- 146 09/02 222 92 HIGH 9 SINGLE QUOTE + || '“' -- 147 09/03 223 93 HIGH 6 DOUBLE QUOTE + || '”' -- 148 09/04 224 94 HIGH 9 DOUBLE QUOTE + || '•' -- 149 09/05 225 95 LARGE CENTERED DOT + || '–' -- 150 09/06 226 96 EN DASH + || '—' -- 151 09/07 227 97 EM DASH + || '™' -- 153 09/09 231 99 TRADEMARK SIGN + || 'š' -- 154 09/10 232 9A SMALL LETTER S WITH CARON + || '›' -- 155 09/11 233 9B RIGHT SINGLE QUOTE BRACKET + || 'ś' -- 156 09/12 234 9C SMALL LETTER S WITH ACUTE ACCENT + || 'ť' -- 157 09/13 235 9D SMALL LETTER T WITH CARON + || 'ž' -- 158 09/14 236 9E SMALL LETTER Z WITH CARON + || 'ź' -- 159 09/15 237 9F SMALL LETTER Z WITH ACUTE ACCENT + || ' ' -- 160 10/00 240 A0 NO-BREAK SPACE + || 'ˇ' -- 161 10/01 241 A1 CARON + || '˘' -- 162 10/02 242 A2 BREVE + || 'Ł' -- 163 10/03 243 A3 CAPITAL LETTER L WITH STROKE + || '¤' -- 164 10/04 244 A4 CURRENCY SIGN + || 'Ą' -- 165 10/05 245 A5 CAPITAL LETTER A WITH OGONEK + || '¦' -- 166 10/06 246 A6 BROKEN BAR + || '§' -- 167 10/07 247 A7 PARAGRAPH SIGN + || '¨' -- 168 10/08 250 A8 DIAERESIS + || '©' -- 169 10/09 251 A9 COPYRIGHT SIGN + || 'Ş' -- 170 10/10 252 AA CAPITAL LETTER S WITH CEDILLA + || '«' -- 171 10/11 253 AB LEFT ANGLE QUOTATION MARK + || '¬' -- 172 10/12 254 AC NOT SIGN + || '­' -- 173 10/13 255 AD SOFT HYPHEN + || '®' -- 174 10/14 256 AE REGISTERED TRADE MARK SIGN + || 'Ż' -- 175 10/15 257 AF CAPITAL LETTER Z WITH DOT ABOVE + || '°' -- 176 11/00 260 B0 DEGREE SIGN, RING ABOVE + || '±' -- 177 11/01 261 B1 PLUS-MINUS SIGN + || '˛' -- 178 11/02 262 B2 OGONEK + || 'ł' -- 179 11/03 263 B3 SMALL LETTER L WITH STROKE + || '´' -- 180 11/04 264 B4 ACUTE ACCENT + || 'µ' -- 181 11/05 265 B5 MICRO SIGN + || '¶' -- 182 11/06 266 B6 PILCROW SIGN + || '·' -- 183 11/07 267 B7 MIDDLE DOT + || '¸' -- 184 11/08 270 B8 CEDILLA + || 'ą' -- 185 11/09 271 B9 SMALL LETTER A WITH OGONEK + || 'ş' -- 186 11/10 272 BA SMALL LETTER S WITH CEDILLA + || '»' -- 187 11/11 273 BB RIGHT ANGLE QUOTATION MARK + || 'Ľ' -- 188 11/12 274 BC CAPITAL LETTER L WITH CARON + || '˝' -- 189 11/13 275 BD DOUBLE ACUTE ACCENT + || 'ľ' -- 190 11/14 276 BE CAPITAL LETTER I WITH CARON + || 'ż' -- 191 11/15 277 BF SMALL LETTER Z WITH DOT ABOVE + || 'Ŕ' -- 192 12/00 300 C0 CAPITAL LETTER R WITH ACUTE ACCENT + || 'Á' -- 193 12/01 301 C1 CAPITAL LETTER A WITH ACUTE ACCENT + || 'Â' -- 194 12/02 302 C2 CAPITAL LETTER A WITH CIRCUMFLEX + || 'Ă' -- 195 12/03 303 C3 CAPITAL LETTER A WITH BREVE + || 'Ä' -- 196 12/04 304 C4 CAPITAL LETTER A WITH DIAERESIS + || 'Ĺ' -- 197 12/05 305 C5 CAPITAL LETTER L WITH ACUTE ACCENT + || 'Ć' -- 198 12/06 306 C6 CAPITAL LETTER C WITH ACUTE ACCENT + || 'Ç' -- 199 12/07 307 C7 CAPITAL LETTER C WITH CEDILLA + || 'Č' -- 200 12/08 310 C8 CAPITAL LETTER C WITH CARON + || 'É' -- 201 12/09 311 C9 CAPITAL LETTER E WITH ACUTE ACCENT + || 'Ę' -- 202 12/10 312 CA CAPITAL LETTER E WITH OGONEK + || 'Ë' -- 203 12/11 313 CB CAPITAL LETTER E WITH DIAERESIS + || 'Ě' -- 204 12/12 314 CC CAPITAL LETTER E WITH CARON + || 'Í' -- 205 12/13 315 CD CAPITAL LETTER I WITH ACUTE ACCENT + || 'Î' -- 206 12/14 316 CE CAPITAL LETTER I WITH CIRCUMFLEX ACCENT + || 'Ď' -- 207 12/15 317 CF CAPITAL LETTER D WITH CARON + || 'Đ' -- 208 13/00 320 D0 CAPITAL LETTER D WITH STROKE + || 'Ń' -- 209 13/01 321 D1 CAPITAL LETTER N WITH ACUTE ACCENT + || 'Ň' -- 210 13/02 322 D2 CAPITAL LETTER N WITH CARON + || 'Ó' -- 211 13/03 323 D3 CAPITAL LETTER O WITH ACUTE ACCENT + || 'Ô' -- 212 13/04 324 D4 CAPITAL LETTER O WITH CIRCUMFLEX + || 'Ő' -- 213 13/05 325 D5 CAPITAL LETTER O WITH DOUBLE ACUTE ACCENT + || 'Ö' -- 214 13/06 326 D6 CAPITAL LETTER O WITH DIAERESIS + || '×' -- 215 13/07 327 D7 MULTIPLICATION SIGN + || 'Ř' -- 216 13/08 330 D8 CAPITAL LETTER R WITH CARON + || 'Ů' -- 217 13/09 331 D9 CAPITAL LETTER U WITH RING ABOVE + || 'Ú' -- 218 13/10 332 DA CAPITAL LETTER U WITH ACUTE ACCENT + || 'Ű' -- 219 13/11 333 DB CAPITAL LETTER U WITH DOUBLE ACUTE ACCENT + || 'Ü' -- 220 13/12 334 DC CAPITAL LETTER U WITH DIAERESIS + || 'Ý' -- 221 13/13 335 DD CAPITAL LETTER Y WITH ACUTE ACCENT + || 'Ţ' -- 222 13/14 336 DE CAPITAL LETTER T WITH CEDILLA + || 'ß' -- 223 13/15 337 DF SMALL GERMAN LETTER SHARP s + || 'ŕ' -- 224 14/00 340 E0 SMALL LETTER R WITH ACUTE ACCENT + || 'á' -- 225 14/01 341 E1 SMALL LETTER A WITH ACUTE ACCENT + || 'â' -- 226 14/02 342 E2 SMALL LETTER A WITH CIRCUMFLEX + || 'ă' -- 227 14/03 343 E3 SMALL LETTER A WITH BREVE + || 'ä' -- 228 14/04 344 E4 SMALL LETTER A WITH DIAERESIS + || 'ĺ' -- 229 14/05 345 E5 SMALL LETTER L WITH ACUTE ACCENT + || 'ć' -- 230 14/06 346 E6 SMALL LETTER C WITH ACUTE ACCENT + || 'ç' -- 231 14/07 347 E7 SMALL LETTER C WITH CEDILLA + || 'č' -- 232 14/08 350 E8 SMALL LETTER C WITH CARON + || 'é' -- 233 14/09 351 E9 SMALL LETTER E WITH ACUTE ACCENT + || 'ę' -- 234 14/10 352 EA SMALL LETTER E WITH OGONEK + || 'ë' -- 235 14/11 353 EB SMALL LETTER E WITH DIAERESIS + || 'ě' -- 236 14/12 354 EC SMALL LETTER E WITH CARON + || 'í' -- 237 14/13 355 ED SMALL LETTER I WITH ACUTE ACCENT + || 'î' -- 238 14/14 356 EE SMALL LETTER I WITH CIRCUMFLEX ACCENT + || 'ď' -- 239 14/15 357 EF SMALL LETTER D WITH CARON + || 'đ' -- 240 15/00 360 F0 SMALL LETTER D WITH STROKE + || 'ń' -- 241 15/01 361 F1 SMALL LETTER N WITH ACUTE ACCENT + || 'ň' -- 242 15/02 362 F2 SMALL LETTER N WITH CARON + || 'ó' -- 243 15/03 363 F3 SMALL LETTER O WITH ACUTE ACCENT + || 'ô' -- 244 15/04 364 F4 SMALL LETTER O WITH CIRCUMFLEX + || 'ő' -- 245 15/05 365 F5 SMALL LETTER O WITH DOUBLE ACUTE ACCENT + || 'ö' -- 246 15/06 366 F6 SMALL LETTER O WITH DIAERESIS + || '÷' -- 247 15/07 367 F7 DIVISION SIGN + || 'ř' -- 248 15/08 370 F8 SMALL LETTER R WITH CARON + || 'ů' -- 249 15/09 371 F9 SMALL LETTER U WITH RING ABOVE + || 'ú' -- 250 15/10 372 FA SMALL LETTER U WITH ACUTE ACCENT + || 'ű' -- 251 15/11 373 FB SMALL LETTER U WITH DOUBLE ACUTE ACCENT + || 'ü' -- 252 15/12 374 FC SMALL LETTER U WITH DIAERESIS + || 'ý' -- 253 15/13 375 FD SMALL LETTER Y WITH ACUTE ACCENT + || 'ţ' -- 254 15/14 376 FE SMALL LETTER T WITH CEDILLA + || '˙' -- 255 15/15 377 FF DOT ABOVE + ; + + b2 = rpad( '', v_step, v_text ); + + while( n < k ) do + begin + b1 = b1 || b2; + n = gen_id(g, v_step); + end + -- Result: length of `b1` is much more than 32 Kb (about 5e5 for single-byte and 1e6 for utf8 encoding) + + b2 = b1 || 'Ąňňö‡Đő×íńî'; + b1_octet_len=octet_length(b1); + b2_octet_len=octet_length(b2); + trimmed_octet_len=octet_length( trim(b1 from b2) ); + + b1_char_len=char_length(b1); + b2_char_len=char_length(b2); + trimmed_char_len=char_length( trim(b1 from b2) ); + suspend; + + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + B1_OCTET_LEN 1082024 + B2_OCTET_LEN 1082047 + TRIMMED_OCTET_LEN 23 + B1_CHAR_LEN 507780 + B2_CHAR_LEN 507791 + TRIMMED_CHAR_LEN 11 + """ + +@pytest.mark.version('>=3.0') +def test_core_3234_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3238.py b/tests/bugs/test_core_3238.py new file mode 100644 index 00000000..68c8d8c0 --- /dev/null +++ b/tests/bugs/test_core_3238.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_3238 +# title: Makes GEN_UUID return a compliant RFC-4122 UUID +# decription: +# tracker_id: CORE-3238 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set term ^; + execute block returns(err_cnt int) as + declare n int = 100000; + declare s varchar(36); + begin + err_cnt = 0; + while( n > 0 ) do + begin + s = uuid_to_char( gen_uuid() ); + if ( NOT (substring(s from 15 for 1)='4' and substring(s from 20 for 1) in ('8','9','A','B')) ) + then err_cnt = err_cnt + 1; + n = n - 1; + end + suspend; + end + ^ set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ERR_CNT 0 + """ + +@pytest.mark.version('>=2.5.2') +def test_core_3238_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3239.py b/tests/bugs/test_core_3239.py new file mode 100644 index 00000000..17eba1f2 --- /dev/null +++ b/tests/bugs/test_core_3239.py @@ -0,0 +1,95 @@ +#coding:utf-8 +# +# id: bugs.core_3239 +# title: UTF8 UNICODE_CI collate can not be used in compound index +# decription: +# tracker_id: CORE-3239 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create collation co_utf8_ci_ai for utf8 from unicode case insensitive accent insensitive; + commit; + + create table test ( + rule_id integer not null + ,ci varchar(20) character set utf8 not null collate unicode_ci + ,ciai varchar(20) character set utf8 not null collate co_utf8_ci_ai + ,bfield boolean + ,pattern varchar(10) character set none + ,constraint test_pk primary key (rule_id, ci, ciai) using index test_int_ci_ciai + ,constraint test_unq unique(bfield, ciai, ci) using index test_bool_ciai_ci + ); + commit; + + -- áéíóúý àèìòù âêîôû ãñõ äëïöüÿ çš δθλξσψω ąęłźż + insert into test (rule_id, ci, ciai, bfield, pattern) values (1, 'âêîôû' , 'âÊîôû' , true , '_e_O%'); + insert into test (rule_id, ci, ciai, bfield, pattern) values (2, 'äëïöüÿ', 'Äëïöüÿ', false, '_e%ioU_'); + insert into test (rule_id, ci, ciai, bfield, pattern) values (3, 'áéíóúý', 'ÁéÍÓÚý', false, 'A__O_Y'); + insert into test (rule_id, ci, ciai, bfield, pattern) values (4, 'àèìòù' , 'àÈÌòù' , true , '___O_'); + commit; + + set list on; + set plan on; + --set echo on; + + select rule_id + from test + where bfield = false and ciai similar to pattern; + + select rule_id + from test + where + rule_id = 1 + and ci starting with 'ÂÊ' + and ciai similar to '%EIOU%'; + + select rule_id from test + where + bfield = false + and ciai similar to 'AEIOUY' + and ci similar to '%ÄË%ÜŸ'; + + select a.rule_id + from test a + join test b on a.rule_id = b.rule_id and a.ciai = b.ci + where a.bfield = true; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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') +def test_core_3239_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3242.py b/tests/bugs/test_core_3242.py new file mode 100644 index 00000000..bc0ba42f --- /dev/null +++ b/tests/bugs/test_core_3242.py @@ -0,0 +1,155 @@ +#coding:utf-8 +# +# id: bugs.core_3242 +# title: Recursive stored procedure shouldnt require execute right to call itself +# decription: +# Checked on: 4.0.0.1635: OK, 2.337s; 3.0.5.33180: OK, 2.497s. +# +# tracker_id: CORE-3242 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set wng off; + set bail on; + + -- Drop old account if it remains from prevoius run: + set term ^; + execute block as + begin + begin + execute statement 'drop user tmp$c3242' with autonomous transaction; + when any do begin end + end + end + ^ + set term ;^ + commit; + + create user tmp$c3242 password '123'; + commit; + + set term ^; + create or alter procedure sp_recur(i smallint) returns(o bigint) as + begin + if ( i > 1 ) then + o = i * (select o from sp_recur( :i - 1 )); + else + o = i; + + suspend; + + end + ^ + + create or alter function fn_recur(i smallint) returns bigint as + begin + if ( i > 1 ) then + return i * fn_recur( i-1 ); + else + return i; + end + ^ + + create or alter procedure sp_factorial(i smallint) returns (o bigint) as + begin + for select o from sp_recur( :i ) into o do suspend; + end + ^ + create or alter function fn_factorial(i smallint) returns bigint as + begin + return fn_recur( i ); + end + ^ + + recreate package pg_factorial as + begin + procedure pg_sp_factorial(i smallint) returns (o bigint); + function pg_fn_factorial(i smallint) returns bigint; + end + ^ + + create package body pg_factorial as + begin + procedure pg_sp_factorial(i smallint) returns(o bigint) as + begin + if ( i > 1 ) then + o = i * (select o from sp_recur( :i - 1 )); + else + o = i; + + suspend; + + end + + function pg_fn_factorial(i smallint) returns bigint as + begin + if ( i > 1 ) then + return i * fn_recur( i-1 ); + else + return i; + end + end + ^ + set term ;^ + commit; + + + --------------------------------------------------------------------------- + + revoke all on all from tmp$c3242; + commit; + + grant execute on function fn_factorial to tmp$c3242; + grant execute on procedure sp_factorial to tmp$c3242; + grant execute on package pg_factorial to tmp$c3242; + + grant execute on function fn_recur to function fn_factorial; + grant execute on procedure sp_recur to procedure sp_factorial; + grant execute on function fn_recur to package pg_factorial; + grant execute on procedure sp_recur to package pg_factorial; + commit; + + connect '$(DSN)' user tmp$c3242 password '123'; + + set list on; + select p.o as standalone_sp_result from sp_factorial(5) p; + select fn_factorial(7) as standalone_fn_result from rdb$database; + + select p.o as packaged_sp_result from pg_factorial.pg_sp_factorial(9) p; + select pg_factorial.pg_fn_factorial(11) as packaged_fn_result from rdb$database; + commit; + + connect '$(DSN)' user sysdba password 'masterkey'; + drop user tmp$c3242; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + STANDALONE_SP_RESULT 120 + STANDALONE_FN_RESULT 5040 + PACKAGED_SP_RESULT 362880 + PACKAGED_FN_RESULT 39916800 + """ + +@pytest.mark.version('>=3.0') +def test_core_3242_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3244.py b/tests/bugs/test_core_3244.py new file mode 100644 index 00000000..5b6e46da --- /dev/null +++ b/tests/bugs/test_core_3244.py @@ -0,0 +1,52 @@ +#coding:utf-8 +# +# id: bugs.core_3244 +# title: POSITION: Wrong result with '' if third argument present +# decription: +# tracker_id: CORE-3244 +# min_versions: ['2.1.4'] +# versions: 2.1.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select position ('', 'Broehaha') from rdb$database; +select position ('', 'Broehaha', 4) from rdb$database; +select position ('', 'Broehaha', 20) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Database: localhost:C: btest2 mpugs.core_3244.fdb, User: SYSDBA +SQL> + POSITION +============ + 1 + +SQL> + POSITION +============ + 4 + +SQL> + POSITION +============ + 0 + +SQL>""" + +@pytest.mark.version('>=2.1.4') +def test_core_3244_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3245.py b/tests/bugs/test_core_3245.py new file mode 100644 index 00000000..74d0cffd --- /dev/null +++ b/tests/bugs/test_core_3245.py @@ -0,0 +1,64 @@ +#coding:utf-8 +# +# id: bugs.core_3245 +# title: SUBSTRING on long blobs truncates result to 32767 if third argument not present +# decription: +# tracker_id: CORE-3245 +# min_versions: ['2.1.5'] +# versions: 2.1.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.5 +# resources: None + +substitutions_1 = [('blob_.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + with q (s) as ( + select cast(cast('abc' as char(32767)) as blob sub_type text) + || cast('def' as char(32767)) + || cast('ghi' as char(32767)) + || 'tail' + from rdb$database + ) + ,r (sub_for, sub_nofor) as ( + select substring(s from 8000 for 120000), + substring(s from 8000) + from q + ) + select + char_length(s) as "char_length(s)" + ,right(s, 3) as "blob_right(s,3)" + ,char_length(sub_for) as "char_length(sub_for)" + ,right(sub_for, 3) as "blob_right(sub_for, 3)" + ,char_length(sub_nofor) as "char_length(sub_nofor)" + ,right(sub_nofor, 3) as "blob_right(sub_nofor, 3)" + from q cross join r + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + char_length(s) 98305 + ail + char_length(sub_for) 90306 + ail + char_length(sub_nofor) 90306 + ail + """ + +@pytest.mark.version('>=2.1.5') +def test_core_3245_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3255.py b/tests/bugs/test_core_3255.py new file mode 100644 index 00000000..e7a6a183 --- /dev/null +++ b/tests/bugs/test_core_3255.py @@ -0,0 +1,89 @@ +#coding:utf-8 +# +# id: bugs.core_3255 +# title: The server could crash using views with GROUP BY +# decription: +# tracker_id: CORE-3255 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """SET TERM !; +create table t1 ( + n1 integer +)! + +create view v1 (x, n1) as + select 'a', n1 + from t1 +group by 1, n1! + +insert into t1 values (1)! +insert into t1 values (1)! +insert into t1 values (2)! +insert into t1 values (2)! +insert into t1 values (3)! + +commit! + +create or alter procedure p1 returns (x varchar(1), n1 integer) +as +begin + for select x, n1 from v1 into x, n1 do + suspend; +end! + +create or alter procedure p2 returns (x varchar(1), n1 integer) +as +begin + for select n1 from t1 into n1 do + begin + end + + for select n1, x from v1 into n1, x do + suspend; +end! + +commit! +SET TERM ;! +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select * from p2; +select * from p1; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Database: localhost:C:\\Users\\win7\\Firebird_tests\\fbt-repository\\tmp\\bugs.core_3255.fdb, User: SYSDBA +SQL> +X N1 +====== ============ +a 1 +a 2 +a 3 + +SQL> +X N1 +====== ============ +a 1 +a 2 +a 3 + +SQL>""" + +@pytest.mark.version('>=2.5.1') +def test_core_3255_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3256.py b/tests/bugs/test_core_3256.py new file mode 100644 index 00000000..c92080d8 --- /dev/null +++ b/tests/bugs/test_core_3256.py @@ -0,0 +1,193 @@ +#coding:utf-8 +# +# id: bugs.core_3256 +# title: Error "request depth exceeded" may appear while preparing a select query against a view with explicit plan +# decription: +# tracker_id: CORE-3256 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter view vt(id,name) as select 1 id, '' name from rdb$database; + commit; + + recreate table t1 (id integer not null,name integer not null); + alter table t1 add constraint pk_t1 primary key (id) + using index pk_t1 + ; + create or alter view vt(id,name) as select * from t1; + commit; + + -- repeat ~130 times + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + --- + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + --- + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + --- + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + --- + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + --- + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + --- + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + --- + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + --- + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + --- + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + --- + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + --- + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + --- + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + + -- The following statement leads to: + -- Statement failed, SQLSTATE = 54001 + -- unsuccessful metadata update + -- -request depth exceeded. (Recursive definition?) + -- Confirmed for 2.5.0 only, 26.02.2015. + --##################################################### + select * from vt where id=1 PLAN (vt T1 INDEX (PK_T1)); + --##################################################### + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.1') +def test_core_3256_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_3262.py b/tests/bugs/test_core_3262.py new file mode 100644 index 00000000..b8deff12 --- /dev/null +++ b/tests/bugs/test_core_3262.py @@ -0,0 +1,85 @@ +#coding:utf-8 +# +# id: bugs.core_3262 +# title: LIST() may overwrite last part of output with zero characters +# decription: +# tracker_id: CORE-3262 +# min_versions: ['2.1.4'] +# versions: 2.1.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table vc (s varchar(8000)); + commit; + + insert into vc values (cast('A' as char(4000)) || 'B'); + + set list on; + + select char_length(s), position('A' in s), position('B' in s) from vc; + + with q (l) as (select list(s) from vc) + select char_length(l), position('A' in l), position('B' in l) from q; + + + update vc set s = (cast('A' as char(5000)) || 'B'); + + select char_length(s), position('A' in s), position('B' in s) from vc; + + + with q (l) as (select list(s) from vc) + select char_length(l), position('A' in l), position('B' in l) from q; + + + with q (l) as (select reverse(list(s)) from vc) + select char_length(l), position('A' in l), position('B' in l) from q; + + with q (l) as (select list(s) from vc) + select ascii_val(substring(l from 4066 for 1)), ascii_val(substring(l from 4067 for 1)) from q; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CHAR_LENGTH 4001 + POSITION 1 + POSITION 4001 + + CHAR_LENGTH 4001 + POSITION 1 + POSITION 4001 + + CHAR_LENGTH 5001 + POSITION 1 + POSITION 5001 + + CHAR_LENGTH 5001 + POSITION 1 + POSITION 5001 + + CHAR_LENGTH 5001 + POSITION 5001 + POSITION 1 + + ASCII_VAL 32 + ASCII_VAL 32 + """ + +@pytest.mark.version('>=2.1.4') +def test_core_3262_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3277.py b/tests/bugs/test_core_3277.py new file mode 100644 index 00000000..c8de89c5 --- /dev/null +++ b/tests/bugs/test_core_3277.py @@ -0,0 +1,85 @@ +#coding:utf-8 +# +# id: bugs.core_3277 +# title: Wrong result for RIGHT(UTF8 varchar) +# decription: Text was taken from Gutenberg project, several European languages are used +# tracker_id: CORE-3277 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core3277.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + select s,left(s,10) ls10, right(s,10) rs10 from t; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +S moří; že zplodí bezpočtu hrdin, kteří ponesou svou hořící duši +LS10 moří; že z +RS10 ořící duši + +S käsiimme. Jospa vaan tapaisin heidän päällikkönsä! +LS10 käsiimme. +RS10 llikkönsä! + +S την καιροσκόπον πολιτικήν, όπως ερρύθμιζον αυτήν ηνωμένοι +LS10 την καιροσ +RS10 ν ηνωμένοι + +S Devido à existência de erros tipográficos neste +LS10 Devido à e +RS10 icos neste + +S На секунду он почувствовал, что разделяет чувство Агафьи +LS10 На секунду +RS10 тво Агафьи + +S Domin: (běží ke krbu) Spálila! (poklekne ke krbu a přehrabává v něm) Nic +LS10 Domin: (bě +RS10 v něm) Nic + +S Päällikkö karkasi kiinni läheisempään ja mättäsi hänet alas +LS10 Päällikkö +RS10 hänet alas + +S Sa du något? +LS10 Sa du någo +RS10 du något? + +S Ja, hvarför? Hur många lugna timmar tror du jag har haft på tretti år? +LS10 Ja, hvarfö +RS10 tretti år? + +S Αφού δε απέθανεν η προφορική ποίησις — ίσως κατά τον τέταρτον +LS10 Αφού δε απ +RS10 ν τέταρτον + +S Busman: Počet. Udělali jsme Robotů příliš mnoho. Namoutě, to se přece dalo +LS10 Busman: Po +RS10 přece dalo + +S Men dansken sa _nej_, han. För Vår Herre och fotografen, sa han, ä +LS10 Men danske +RS10 sa han, ä + """ + +@pytest.mark.version('>=2.5.1') +def test_core_3277_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3282.py b/tests/bugs/test_core_3282.py new file mode 100644 index 00000000..0ddfede1 --- /dev/null +++ b/tests/bugs/test_core_3282.py @@ -0,0 +1,33 @@ +#coding:utf-8 +# +# id: bugs.core_3282 +# title: EXECUTE STATEMENT parses the SQL text using wrong charset +# decription: +# tracker_id: CORE-3282 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core3282.fbk', init=init_script_1) + +test_script_1 = """ + execute procedure TESTSP; -- 2.5.0 only: get "Malformed string" when connect with cset=utf8, confirmed 26.02.2015 + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.1') +def test_core_3282_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_3283.py b/tests/bugs/test_core_3283.py new file mode 100644 index 00000000..fc445993 --- /dev/null +++ b/tests/bugs/test_core_3283.py @@ -0,0 +1,62 @@ +#coding:utf-8 +# +# id: bugs.core_3283 +# title: BAD PLAN with using LEFT OUTER JOIN in SUBSELECT +# decription: +# tracker_id: CORE-3283 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table ttt ( + id int + ,constraint ttt_pk primary key (id) using index ttt_id + ); + + insert into ttt (id) values (0); + insert into ttt (id) values (1); + insert into ttt (id) values (2); + insert into ttt (id) values (3); + insert into ttt (id) values (4); + insert into ttt (id) values (5); + commit; + + set planonly; + select t1.id from ttt t1 + where t1.id = + (select t3.id + from ttt t2 + left join ttt t3 on t3.id > t2.id + where t2.id = 3 + order by t3.id + rows 1 + ); + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN SORT (JOIN (T2 INDEX (TTT_ID), T3 INDEX (TTT_ID))) + PLAN (T1 INDEX (TTT_ID)) + """ + +@pytest.mark.version('>=2.5.1') +def test_core_3283_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3291.py b/tests/bugs/test_core_3291.py new file mode 100644 index 00000000..22bd4faf --- /dev/null +++ b/tests/bugs/test_core_3291.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_3291 +# title: New pseudocolumn (RDB$RECORD_VERSION) to get number of the transaction that created a record version +# decription: +# tracker_id: CORE-3291 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + recreate table test(id int); + insert into test values(1) returning current_transaction - rdb$record_version as diff_ins; + commit; + update test set id=-id returning current_transaction - rdb$record_version as diff_upd; + commit; + delete from test returning sign(current_transaction - rdb$record_version) as diff_del; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DIFF_INS 0 + DIFF_UPD 0 + DIFF_DEL 1 + """ + +@pytest.mark.version('>=3.0') +def test_core_3291_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3296.py b/tests/bugs/test_core_3296.py new file mode 100644 index 00000000..97dfd2cf --- /dev/null +++ b/tests/bugs/test_core_3296.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: bugs.core_3296 +# title: Error "context already in use" for the simple case function with a sub-select operand +# decription: +# tracker_id: CORE-3296 +# min_versions: ['2.1.5'] +# versions: 2.1.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE VAT_ZAK +( + ID Integer NOT NULL, + SYS_NR Integer, + CONSTRAINT PK_VAT_ZAK__ID PRIMARY KEY (ID) +); + +CREATE TABLE ELEMENTY +( + ID Integer NOT NULL, + ID_VAT_SPRZ Integer, +CONSTRAINT PK_ELEMENTY__ID PRIMARY KEY (ID) +); +COMMIT;""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """UPDATE +ELEMENTY E +SET +E.ID_VAT_SPRZ= +CASE +WHEN (SELECT V.SYS_NR FROM VAT_ZAK V WHERE V.ID=E.ID_VAT_SPRZ) = 1 THEN (SELECT V.ID FROM VAT_ZAK V WHERE V.SYS_NR=7) +WHEN (SELECT V.SYS_NR FROM VAT_ZAK V WHERE V.ID=E.ID_VAT_SPRZ) = 2 THEN (SELECT V.ID FROM VAT_ZAK V WHERE V.SYS_NR=8) +WHEN (SELECT V.SYS_NR FROM VAT_ZAK V WHERE V.ID=E.ID_VAT_SPRZ) = 3 THEN (SELECT V.ID FROM VAT_ZAK V WHERE V.SYS_NR=9) +ELSE E.ID_VAT_SPRZ END; +COMMIT; +UPDATE +ELEMENTY E +SET +E.ID_VAT_SPRZ= +CASE +(SELECT V.SYS_NR FROM VAT_ZAK V WHERE V.ID=E.ID_VAT_SPRZ) +WHEN 1 THEN (SELECT V.ID FROM VAT_ZAK V WHERE V.SYS_NR=7) +WHEN 2 THEN (SELECT V.ID FROM VAT_ZAK V WHERE V.SYS_NR=8) +WHEN 3 THEN (SELECT V.ID FROM VAT_ZAK V WHERE V.SYS_NR=9) +ELSE E.ID_VAT_SPRZ END; +COMMIT; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1.5') +def test_core_3296_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_3302.py b/tests/bugs/test_core_3302.py new file mode 100644 index 00000000..abf7e6c7 --- /dev/null +++ b/tests/bugs/test_core_3302.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: bugs.core_3302 +# title: Distinct aggregates return wrong (duplicated) data +# decription: Note: LIST() does not guarantee that returned values will be sorted so we can only count words in the resulting string and compare it with checked count +# tracker_id: CORE-3302 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table t( dt date); + commit; + insert into t values( '2011-01-07' ); + insert into t values( '2011-01-07' ); + insert into t values( '2011-01-07' ); + insert into t values( '2011-01-06' ); + insert into t values( '2011-01-06' ); + insert into t values( '2011-01-06' ); + insert into t values( '2011-01-08' ); + insert into t values( '2011-01-08' ); + insert into t values( '2011-01-08' ); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select char_length(s)-char_length(replace(s,',',''))+1 words_cnt, check_cnt + from ( + select + list(distinct + case extract(weekday from dt) + when 0 then 'Sun' when 1 then 'Mon' when 2 then 'Tue' + when 3 then 'Wed' when 4 then 'Thu' when 5 then 'Fri' + when 6 then 'Sat' end + ) s + ,count(distinct dt) check_cnt + from t + ) + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WORDS_CNT 3 + CHECK_CNT 3 + """ + +@pytest.mark.version('>=2.5.1') +def test_core_3302_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3305.py b/tests/bugs/test_core_3305.py new file mode 100644 index 00000000..e75b9fca --- /dev/null +++ b/tests/bugs/test_core_3305.py @@ -0,0 +1,52 @@ +#coding:utf-8 +# +# id: bugs.core_3305 +# title: "BLOB not found" error after creation/altering of the invalid trigger +# decription: +# tracker_id: CORE-3305 +# min_versions: ['2.5.3'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + 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; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + attempted update of read-only column T.V + Statement failed, SQLSTATE = 42000 + attempted update of read-only column T.V + """ + +@pytest.mark.version('>=4.0') +def test_core_3305_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_3306.py b/tests/bugs/test_core_3306.py new file mode 100644 index 00000000..7a2c3f9a --- /dev/null +++ b/tests/bugs/test_core_3306.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: bugs.core_3306 +# title: Invariant sub-query is treated as variant thus causing multiple invokations of a nested stored procedure +# decription: +# tracker_id: CORE-3306 +# min_versions: ['2.5.1'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """SET TERM !!; +Create Table tt_table(Field1 varchar(100))!! +Create Or Alter PROCEDURE SPR_TEST (pName Varchar(2000)) RETURNS (sValue Varchar(255)) AS +BEGIN + Insert Into tt_table(field1) values(:pName); + sValue=:pName; + suspend; +End!! +COMMIT!! +SET TERM ;!! +Select count(*) +from rdb$types +where rdb$field_name like (select sValue From spr_test('SIMSIM')); +COMMIT;""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """Select count(*) From tt_table; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + COUNT +===================== + 1 + +""" + +@pytest.mark.version('>=3.0') +def test_core_3306_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3310.py b/tests/bugs/test_core_3310.py new file mode 100644 index 00000000..a72dff76 --- /dev/null +++ b/tests/bugs/test_core_3310.py @@ -0,0 +1,48 @@ +#coding:utf-8 +# +# id: bugs.core_3310 +# title: RDB$GET_CONTEXT and between in view +# decription: +# tracker_id: CORE-3310 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='employee-ods12.fbk', init=init_script_1) + +test_script_1 = """ + create or alter view v_test + as + select s.po_number + from sales s + where + cast(coalesce(rdb$get_context('USER_SESSION', 'SELECTED_DATE'), '12.12.1993') as timestamp) + between + s.order_date and s.date_needed + ; + set list on; + select * from v_test v order by v.po_number rows 1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PO_NUMBER V9320630 + """ + +@pytest.mark.version('>=3.0') +def test_core_3310_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3311.py b/tests/bugs/test_core_3311.py new file mode 100644 index 00000000..a552e179 --- /dev/null +++ b/tests/bugs/test_core_3311.py @@ -0,0 +1,71 @@ +#coding:utf-8 +# +# id: bugs.core_3311 +# title: Error "data type unknown" while preparing UPDATE/DELETE statements with the parameterized ROWS clause +# decription: +# tracker_id: CORE-3311 +# min_versions: ['2.5.1'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table test(id int); + commit; + insert into test select rand()*1000 from rdb$types,(select 1 i from rdb$types rows 10); + commit; + create index test_id on test(id); + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set planonly; + select * from test rows ?; + select * from test where id between ? and ? order by id rows ? to ?; + update test set id=id rows ? to ?; + update test set id=id where id between ? and ? order by id rows ? to ?; + delete from test rows ? to ?; + delete from test where id between ? and ? order by id rows ? to ?; + merge into test t + using( + select id from test where id between ? and ? rows ? + ) s + on t.id=s.id + when matched then update set t.id=s.id; + merge into test t + using( + select id from test where id between ? and ? order by id rows ? + ) s + on t.id=s.id + when matched then update set t.id=s.id; + set planonly; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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)) + """ + +@pytest.mark.version('>=3.0') +def test_core_3311_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3312.py b/tests/bugs/test_core_3312.py new file mode 100644 index 00000000..3578b520 --- /dev/null +++ b/tests/bugs/test_core_3312.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_3312 +# title: Sub-optimal join plan when the slave table depends on the master one via the OR predicate +# decription: +# tracker_id: CORE-3312 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLANONLY ON; +select * +from rdb$relations r + join rdb$security_classes sc + on (r.rdb$security_class = sc.rdb$security_class + or r.rdb$default_class = sc.rdb$security_class); +select * +from rdb$relations r + join rdb$security_classes sc + on (r.rdb$security_class = sc.rdb$security_class and r.rdb$relation_id = 0) + or (r.rdb$default_class = sc.rdb$security_class and r.rdb$relation_id = 1); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Database: localhost:C:\\Users\\win7\\Firebird_tests\\fbt-repository\\tmp\\bugs.core_3312.fdb, User: SYSDBA +SQL> SQL> CON> CON> CON> CON> +PLAN JOIN (R NATURAL, SC INDEX (RDB$INDEX_7, RDB$INDEX_7)) +SQL> CON> CON> CON> CON> +PLAN JOIN (R INDEX (RDB$INDEX_1, RDB$INDEX_1), SC INDEX (RDB$INDEX_7, RDB$INDEX_7)) +SQL>""" + +@pytest.mark.version('>=2.5.1') +def test_core_3312_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3314.py b/tests/bugs/test_core_3314.py new file mode 100644 index 00000000..da525132 --- /dev/null +++ b/tests/bugs/test_core_3314.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_3314 +# title: Dependencies are not removed after dropping the procedure and the table it depends on in the same transaction +# decription: +# tracker_id: CORE-3314 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t (a int); +SET TERM !!; +create procedure p as begin delete from t; end!! +SET TERM !!; +commit; +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT 1 FROM RDB$DEPENDENCIES WHERE RDB$DEPENDED_ON_NAME='T'; +drop procedure p; +drop table t; +commit; +SELECT 1 FROM RDB$DEPENDENCIES WHERE RDB$DEPENDED_ON_NAME='T'; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Database: localhost:C:\\Users\\win7\\Firebird_tests\\fbt-repository\\tmp\\bugs.core_3314.fdb, User: SYSDBA +SQL> + CONSTANT +============ + 1 + +SQL> SQL> SQL> SQL> SQL>""" + +@pytest.mark.version('>=2.5.1') +def test_core_3314_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3323.py b/tests/bugs/test_core_3323.py new file mode 100644 index 00000000..0217f819 --- /dev/null +++ b/tests/bugs/test_core_3323.py @@ -0,0 +1,355 @@ +#coding:utf-8 +# +# id: bugs.core_3323 +# title: Ability to cancel waiting in lock manager +# decription: +# Fully reimplemented 10.01.2020. Reason: ISQL-"killer" could not find record in mon$attachments that should be deleted. +# +# Test asynchronously launches ISQL with script that will hang because of two concurrent attachments trying to update +# the same record (second attachment is created using ES/EDS). +# After this we have to launch second instance of ISQL which will attempt to kill both connections created in the 1st ISQL. +# +# The *most* problem here is properly determine time that we have to wait until 1st ISQL will really establish its connect! +# If this time is too short then second ISQL ("killer") will NOT able to see 1st ISQL in mon$attachments and will not be able +# to delete (because there will be NOT YET attachment to delete!). This mean that 2nd ISQL will finish without really check +# that it could kill hanged attachments. Test in this case will not finish if 1st ISQL uses tx with infinite WAIT! +# +# To be sure that 2nd ISQL ("killer") will be able to see 1st one ("hanged") we have to make pretty long PSQL-loop which tries +# to find any record in mon$attachment that is from concurrent connection (which user name we know for advance: 'tmp$c3323'). +# This PSQL loop must finish as fast as we find record that will be then deleted. +# +# Lot of runs show that there is a problem in 4.0.0 Classic: it requires too long time in PSQL loop to find such attachment. +# Time in 4.0 CS can be about 1-2 seconds and number of iterations will be greater than 100. +# No such problem in all 3.0 and in 4.0 for other modes. +# +# 24.12.2020 +# Waiting for completion of child ISQL async process is done by call .wait() instead of old (and "fragile") +# assumption about maximal time that it could last before forcedly terminate it. +# Checked on: +# 4.0.0.2307 SS: 4.348s. +# 4.0.0.2324 SS: 4.301s. +# 4.0.0.2324 CS: 4.959s. +# 3.0.8.33401 SS: 3.225s. +# 3.0.8.33401 SC: 2.236s. +# 3.0.8.33401 CS: 4.543s. +# 2.5.9.27152 SC: 1.006s. +# 2.5.9.27152 CS: 1.333s. +# +# +# +# tracker_id: CORE-3323 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [('Data source : Firebird::localhost:.*', 'Data source : Firebird::localhost'), ('After line.*', ''), ('.*Killed by database administrator.*', ''), ('-At block line:.*', '-At block line'), ('Execute statement error at isc_dsql_(execute2|prepare)', 'Execute statement error at isc_dsql')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import subprocess +# from subprocess import Popen +# import time +# +# #-------------------------------------------- +# +# 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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# clear_ext_pool_statement='' +# usr_plugin_clause='' +# +# if db_conn.engine_version >= 4.0: +# clear_ext_pool_statement = 'ALTER EXTERNAL CONNECTIONS POOL CLEAR ALL;' +# +# if db_conn.engine_version >= 3.0: +# # usr_plugin_clause='using plugin Legacy_userManager' +# usr_plugin_clause='using plugin Srp' +# +# db_conn.close() +# +# +# init_ddl=''' +# set term ^; +# execute block as +# begin +# begin +# execute statement 'drop user tmp$c3323 %(usr_plugin_clause)s' with autonomous transaction; +# when any do begin end +# end +# end^ +# set term ;^ +# commit; +# +# create user tmp$c3323 password '456' %(usr_plugin_clause)s; +# commit; +# +# recreate table test(id int); +# commit; +# insert into test values(1); +# commit; +# +# grant select,update on test to tmp$c3323; +# commit; +# ''' % locals() +# +# runProgram('isql', [dsn], init_ddl) +# +# +# lock_sql=''' +# set list on; +# commit; +# set transaction wait; +# +# update test set id = -id; +# select 'starting EB with lock-conflict' as "Point_A:" -------------- p o i n t [ A ] +# ,id as "id_at_point_A:" +# from test; +# +# set term ^; +# execute block as +# begin +# -- This statement will for sure finish with exception, but +# -- in 2.5.0 it will be 'lock-conflict' (and this was WRONG), +# -- while on 2.5.1 and above it should be 'connection shutdown'. +# +# -- 11.05.2017, FB 4.0 only! +# -- Following messages can appear after 'connection shutdown' +# -- (letter from dimitr, 08-may-2017 20:41): +# -- isc_att_shut_killed: Killed by database administrator +# -- isc_att_shut_idle: Idle timeout expired +# -- isc_att_shut_db_down: Database is shutdown +# -- isc_att_shut_engine: Engine is shutdown +# +# execute statement 'update test set id = - (1000 + id)' +# on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') +# as user 'TMP$C3323' password '456'; +# end +# ^ +# set term ;^ +# +# select 'finished EB with lock-conflict' as "Point_B" -------------- p o i n t [ B ] +# ,id as "id_at_point_B:" +# from test; +# rollback; +# ''' +# +# f_hanged_sql=open( os.path.join(context['temp_directory'],'tmp_3323_hang.sql'), 'w') +# f_hanged_sql.write(lock_sql) +# f_hanged_sql.close() +# +# f_hanged_log=open( os.path.join(context['temp_directory'],'tmp_3323_hang.log'), "w", buffering = 0) +# +# # Execute a child program in a new process, redirecting STDERR to the same target as of STDOUT: +# p_hanged_isql = Popen([context['isql_path'], dsn, "-ch", 'utf8', "-i" , f_hanged_sql.name],stdout=f_hanged_log, stderr=subprocess.STDOUT) +# +# usr=user_name +# pwd=user_password +# +# # Limit: how long "killer" must wait until "victim" will establish its connect, milliseconds. +# # It was encountered on Classic that this time can be valueable if heavy concurrent workload +# # presents on host where tests run: +# ############################################### +# MAX_WAIT_FOR_VICTIM_ESTABLISH_ITS_CONNECT=15000 +# ############################################### +# +# killer_script=''' +# set list on; +# +# select 'Intro script that must kill other attachment' as "point_C:" ------------------ p o i n t [ C ] +# from test; +# +# set term ^; +# execute block returns( found_other_attach_for_attempts int, found_other_attach_for_ms int ) as +# declare c smallint = 0; +# declare t timestamp; +# begin +# found_other_attach_for_attempts = 0; +# t = 'now'; +# while (c = 0) do +# begin +# found_other_attach_for_attempts = found_other_attach_for_attempts + 1; +# in autonomous transaction do +# select count(*) +# from ( +# select mon$attachment_id +# from mon$attachments a +# where mon$user = upper('TMP$C3323' ) +# rows 1 +# ) +# into c; +# found_other_attach_for_ms = datediff(millisecond from t to cast('now' as timestamp)); +# if (found_other_attach_for_ms > %(MAX_WAIT_FOR_VICTIM_ESTABLISH_ITS_CONNECT)s ) then +# begin +# suspend; -- output found_other_attach_for_attempts and found_other_attach_for_ms +# --###### +# leave; +# --###### +# end +# end +# end +# ^ +# set term ;^ +# rollback; +# +# +# select 'starting kill hanged connection' as "point_D:" ------------------ p o i n t [ D ] +# ,id as "id_at_point_D:" +# from test; +# +# select iif( a.mon$attachment_id is not null, '', '### UNEXPECTED: NULL ###' ) as attachment_to_be_killed +# from rdb$database +# left join mon$attachments a on mon$user = upper('TMP$C3323' ) +# ; +# +# select 'Running delete from mon$attachments statement' as "point_E:" ------------------ p o i n t [ E ] +# from rdb$database; +# +# set count on; +# delete from mon$attachments +# where mon$user = upper('TMP$C3323' ) +# ; +# set count off; +# commit; +# +# connect '$(DSN)' user '%(usr)s' password '%(pwd)s'; +# +# %(clear_ext_pool_statement)s +# +# select 'Reconnect and look for attachment of other user' as "point_F:" ------------------ p o i n t [ F ] +# ,id as "id_at_point_F:" +# from test; +# +# select iif( a.mon$attachment_id is null, '', '### UNEXPECTED NOT NULL: attach_id=' || a.mon$attachment_id || '; state=' || coalesce(a.mon$state, '') || ' ###' ) as still_alive_attachment_id +# from rdb$database r +# left join mon$attachments a on a.mon$user = upper('TMP$C3323'); +# commit; +# +# set blob all; +# +# select a.*, s.* +# from mon$attachments a left join mon$statements s using(mon$attachment_id) +# where a.mon$user = upper('TMP$C3323') +# ; +# +# select 'finished kill hanged connection' as "pointG:" ----------------- p o i n t [ G ] +# from rdb$database; +# commit; +# +# drop user tmp$c3323 %(usr_plugin_clause)s; +# commit; +# +# ''' % locals() +# +# +# f_killer_sql=open( os.path.join(context['temp_directory'],'tmp_3323_kill.sql'), 'w') +# f_killer_sql.write(killer_script) +# flush_and_close(f_killer_sql) +# +# +# # starting ISQL-KILLER: +# ####################### +# +# f_killer_log=open( os.path.join(context['temp_directory'],'tmp_3323_kill.log'), "w", buffering = 0) +# subprocess.call( [context['isql_path'], dsn, "-ch", "utf8", "-i" , f_killer_sql.name],stdout=f_killer_log, stderr=subprocess.STDOUT ) +# flush_and_close(f_killer_log) +# +# # ::::::::::::::::::::::::::::::::::::::::::::: +# # ::: A.C.H.T.U.N.G ::: +# # ::: DO NOT call p_hanged_isql.terminate() ::: +# # ::::::::::::::::::::::::::::::::::::::::::::: +# # Here we must W.A.I.T until ISQL-victim (which just has been killed) finished +# # with raising exception ("SQLSTATE = 42000 / connection shutdown") and fully +# # flushes its log on disk. +# +# # Wait until ISQL complete its mission: +# p_hanged_isql.wait() +# +# flush_and_close(f_hanged_log) +# +# with open( f_hanged_log.name,'r') as f: +# print(f.read()) +# +# with open( f_killer_log.name,'r') as f: +# print(f.read()) +# +# +# # We have to change DB state to full shutdown in order to prevent "Object in use" +# # while fbtest will try to drop these databases (set linger = 0 does not help!) +# ############################################################################### +# runProgram('gfix',[dsn,'-shut','full','-force','0']) +# runProgram('gfix',[dsn,'-online']) +# +# # CLEANUP +# ######### +# f_list=(f_hanged_sql,f_killer_sql,f_killer_log,f_hanged_log) +# cleanup( [f.name for f in f_list] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Point_A: starting EB with lock-conflict + id_at_point_A: -1 + Statement failed, SQLSTATE = 42000 + Execute statement error at isc_dsql_execute2 : + 335544856 : connection shutdown + Statement : update test set id = - (1000 + id) + Data source : Firebird::localhost + -At block line + Point_B finished EB with lock-conflict + id_at_point_B: -1 + point_C: Intro script that must kill other attachment + point_D: starting kill hanged connection + id_at_point_D: 1 + ATTACHMENT_TO_BE_KILLED + point_E: Running delete from mon$attachments statement + Records affected: 1 + point_F: Reconnect and look for attachment of other user + id_at_point_F: 1 + STILL_ALIVE_ATTACHMENT_ID + pointG: finished kill hanged connection + """ + +@pytest.mark.version('>=2.5.1') +@pytest.mark.xfail +def test_core_3323_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_3328.py b/tests/bugs/test_core_3328.py new file mode 100644 index 00000000..70a9e8b5 --- /dev/null +++ b/tests/bugs/test_core_3328.py @@ -0,0 +1,300 @@ +#coding:utf-8 +# +# id: bugs.core_3328 +# title: Client writes error messages into firebird.log when database is shutted down +# decription: +# Test retrieves FB engine version in order to issue proper command option for getting firebird.log content +# (in 2.5 this is 'action_get_ib_log' rather then expected 'action_get_fb_log' - note on letter 'i' instead 'f'). +# Initial content of firebird.log is saved into file, see var. 'f_fblog_before'. +# Then it starts child process (ISQL) which does some "heavy DML" activity and allows this ISQL to do it several seconds. +# After this, main thread calls FBSVCMGR with commands to move database to SHUTDOWN state and back to online. +# This should terminate child ISQL and after small delay one may to query new content of firebird.log. +# New firebird.log is saved into file, see var. 'f_fblog_after', so further its two versions can be compared. +# Comparison is done by using standard Python package 'difflib'. +# Difference between old and new firebird.log should _NOT_ contain lines with words 'gds__detach' or 'lost'. +# If these words absent - all fine, actual and expected output both have to be empty. +# +# 04-dec-2016. +# Checked on: WI-V2.5.7.27028, WI-V3.0.2.32642, WI-T4.0.0.460 (all on SS/SC/CS). +# Reduced time of ISQL working from 5 to 2 seconds. +# +# Samples of call with '-c ': +# +# fbt_run -b C:\\MIX +# irebird +# b25in bugs.core_3328 -o localhost/3255 -c C:\\MIX +# irebird +# b25in +# bclient.dll +# fbt_run -b C:\\MIX +# irebird +# b25Csin bugs.core_3328 -o localhost/3249 -c C:\\MIX +# irebird +# b25csin +# bclient.dll +# fbt_run -b C:\\MIX +# irebird +# b40Cs bugs.core_3328 -o localhost/3439 -c C:\\MIX +# irebird +# b40cs +# bclient.dll +# fbt_run -b C:\\MIX +# irebird +# b40sc bugs.core_3328 -o localhost/3430 -c C:\\MIX +# irebird +# b40sc +# bclient.dll & fbt_view -d results.trf +# +# tracker_id: CORE-3328 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [('attachments: [1-9]+', 'attachments: 1'), ('[\\s]+', ' ')] + +init_script_1 = """ + create table test(s varchar(36) unique); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import subprocess +# from subprocess import Popen +# import time +# import difflib +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_file=db_conn.database_name +# engine = str(db_conn.engine_version) # convert to text because 'float' object has no attribute 'startswith' +# db_conn.close() +# +# #--------------------------------------------------- +# def svc_get_fb_log( engine, f_fb_log ): +# +# import subprocess +# +# if engine.startswith('2.5'): +# get_firebird_log_key='action_get_ib_log' +# else: +# get_firebird_log_key='action_get_fb_log' +# +# subprocess.call( [ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# get_firebird_log_key +# ], +# stdout=f_fb_log, +# stderr=subprocess.STDOUT +# ) +# return +# +# +# #--------------------------------------------- +# +# 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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# +# # Get HOME dir of FB instance that is now checked. +# # We will concatenate this string with 'fbsvcmgr' command in order to choose +# # PROPER binary file when querying services API to shutdown/online DB +# # NOTE: this is NECESSARY if several instances are in work and we did not change +# # PATH variable before call this test! +# +# # NB, 06.12.2016: as of fdb 1.6.1 one need to EXPLICITLY specify user+password pair when doing connect +# # via to FB services API by services.connect() - see FB tracker, PYFB-69 +# # ("Can not connect to FB services if set ISC_USER & ISC_PASSWORD by os.environ[ ... ]") +# +# f_fblog_before=open( os.path.join(context['temp_directory'],'tmp_3328_fblog_before.txt'), 'w') +# svc_get_fb_log( engine, f_fblog_before ) +# flush_and_close( f_fblog_before ) +# +# sql_dml=''' +# show version; +# set term ^; +# execute block as +# declare v_role varchar(31); +# begin +# v_role = left(replace( uuid_to_char(gen_uuid()), '-', ''), 31); +# while (1=1) do +# begin +# insert into test(s) values( uuid_to_char( gen_uuid() ) ); +# end +# end +# ^ +# set term ;^ +# ''' +# +# f_client_sql = open( os.path.join(context['temp_directory'],'tmp_client_3328.sql'), 'w') +# f_client_sql.write(sql_dml) +# flush_and_close( f_client_sql ) +# +# f_client_log = open( os.path.join(context['temp_directory'],'tmp_client_3328.log'), 'w') +# p_client_dml=subprocess.Popen( [context['isql_path'], dsn, "-n", "-i", f_client_sql.name ], +# stdout = f_client_log, +# stderr = subprocess.STDOUT +# ) +# time.sleep(2) +# +# f_shutdown_log = open( os.path.join(context['temp_directory'],'tmp_shutdown_and_online_3328.log'), 'w') +# +# # Databases: +# # Number of attachments: 1 +# # Number of databases: 1 +# # Database in use: C:\\MIX\\FIREBIRD\\QA\\FBT-REPO\\TMP\\BUGS.CORE_3328.FDB +# subprocess.call( [context['fbsvcmgr_path'],"localhost:service_mgr", +# "info_svr_db_info", +# ], +# stdout = f_shutdown_log, +# stderr=subprocess.STDOUT +# ) +# +# subprocess.call( [context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "prp_shutdown_mode", "prp_sm_full", "prp_shutdown_db", "0", +# "dbname", db_file, +# ], +# stdout = f_shutdown_log, +# stderr = subprocess.STDOUT +# ) +# +# # Databases: +# # Number of attachments: 0 +# # Number of databases: 0 +# subprocess.call( [context['fbsvcmgr_path'],"localhost:service_mgr", +# "info_svr_db_info", +# ], +# stdout = f_shutdown_log, +# stderr=subprocess.STDOUT +# ) +# +# subprocess.call( [context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_db_stats", +# "dbname", db_file, "sts_hdr_pages" +# ], +# stdout = f_shutdown_log, +# stderr=subprocess.STDOUT +# ) +# +# subprocess.call( [context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "prp_db_online", +# "dbname", db_file, +# ], +# stdout = f_shutdown_log, +# stderr = subprocess.STDOUT +# ) +# +# subprocess.call( [context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_db_stats", +# "dbname", db_file, "sts_hdr_pages" +# ], +# stdout = f_shutdown_log, +# stderr=subprocess.STDOUT +# ) +# +# flush_and_close( f_shutdown_log ) +# +# +# f_fblog_after=open( os.path.join(context['temp_directory'],'tmp_3328_fblog_after.txt'), 'w') +# svc_get_fb_log( engine, f_fblog_after ) +# flush_and_close( f_fblog_after ) +# +# p_client_dml.terminate() +# flush_and_close( f_client_log ) +# +# # Now we can compare two versions of firebird.log and check their difference. +# +# oldfb=open(f_fblog_before.name, 'r') +# newfb=open(f_fblog_after.name, 'r') +# +# difftext = ''.join(difflib.unified_diff( +# oldfb.readlines(), +# newfb.readlines() +# )) +# oldfb.close() +# newfb.close() +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_3328_diff.txt'), 'w') +# f_diff_txt.write(difftext) +# flush_and_close( f_diff_txt ) +# +# # New lines in firebird.log must |NOT| contain these: +# # === +# # REMOTE INTERFACE/gds__detach: Unsuccesful detach from database. +# # Uncommitted work may have been lost +# # === +# # If such lines present - this is regression and we output them. +# # When all fine, final output is empty. +# # +# # BTW: for 3.0, firebird.log will contain such text: +# # INET/INET_ERROR: READ ERRNO = 10054, SERVER HOST = LOCALHOST, ADDRESS = 127.0.0.1/3333 +# # -- but this is checked by another .fbt +# +# with open( f_shutdown_log.name,'r') as f: +# for line in f: +# if ( 'unknown' in line.lower() or 'attributes' in line.lower() ): +# print(line) +# #or 'attachments' in line.lower() +# +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# if line.startswith('+') and ('gds__detach' in line or 'lost' in line): +# print(line.upper()) +# +# ############################### +# # Cleanup. +# cleanup( [i.name for i in (f_shutdown_log,f_client_sql,f_client_log,f_fblog_before,f_fblog_after,f_diff_txt) ] ) +# +# # NB: temply removed following lines from expected_stdout, +# # see core-5413, "fbsvcmgr info_svr_db_info does not see active attachments and databases in use (CLASSIC only)" +# # Number of attachments: 1 +# # Number of attachments: 0 +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Attributes force write, full shutdown + Attributes force write + """ + +@pytest.mark.version('>=2.5.1') +@pytest.mark.xfail +def test_core_3328_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_3330.py b/tests/bugs/test_core_3330.py new file mode 100644 index 00000000..214afd49 --- /dev/null +++ b/tests/bugs/test_core_3330.py @@ -0,0 +1,38 @@ +#coding:utf-8 +# +# id: bugs.core_3330 +# title: Server crashes while recreating the table with a NULL -> NOT NULL change +# decription: +# tracker_id: CORE-3330 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table test (a int); + commit; + insert into test (a) values (null); + commit; + recreate table test (b int not null); + commit; -- crash here + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +def test_core_3330_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_3335.py b/tests/bugs/test_core_3335.py new file mode 100644 index 00000000..257791ae --- /dev/null +++ b/tests/bugs/test_core_3335.py @@ -0,0 +1,79 @@ +#coding:utf-8 +# +# id: bugs.core_3335 +# title: Wrong results (internal wrapping occured) for the multi-byte blob SUBSTRING function and its boundary arguments +# decription: +# tracker_id: CORE-3335 +# min_versions: ['2.1.5'] +# versions: 2.1.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select substring(cast('abcdef' as blob sub_type text character set utf8) +from 1 for 2147483647) from rdb$database; +select substring(cast('abcdef' as blob sub_type text character set utf8) +from 2 for 2147483647) from rdb$database; +select substring(cast('abcdef' as blob sub_type text character set utf8) +from 3 for 2147483647) from rdb$database; +select substring(cast('abcdef' as blob sub_type text character set utf8) +from 3 for 2147483646) from rdb$database; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Database: localhost:C: btestnew mpugs.core_3335.fdb, User: SYSDBA +SQL> CON> + SUBSTRING +================= + 0:2 +============================================================================== +SUBSTRING: +abcdef +============================================================================== + +SQL> CON> + SUBSTRING +================= + 0:6 +============================================================================== +SUBSTRING: +bcdef +============================================================================== + +SQL> CON> + SUBSTRING +================= + 0:a +============================================================================== +SUBSTRING: +cdef +============================================================================== + +SQL> CON> + SUBSTRING +================= + 0:e +============================================================================== +SUBSTRING: +cdef +============================================================================== + +SQL>""" + +@pytest.mark.version('>=2.1.5') +def test_core_3335_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3338.py b/tests/bugs/test_core_3338.py new file mode 100644 index 00000000..4d307ffd --- /dev/null +++ b/tests/bugs/test_core_3338.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: bugs.core_3338 +# title: Regression: Code changes disabled support for expression indexes with COALESCE, CASE and DECODE +# decription: +# tracker_id: CORE-3338 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table t(n int); commit; + insert into t select rand()*100 from rdb$types; commit; + + create index t_n2_coalesce on t computed by ( coalesce(n*2,0) ); commit; + create index t_n2_decode on t computed by ( decode( mod(n, 3), 0, coalesce(n,0), 1, iif(mod(n,7)=0, 2, 3) ) ); commit; + + -- 2.5 raises: + -- Statement failed, SQLSTATE = HY000 + -- request synchronization error + -- (for both variants of followed CREATE INDEX statement) + + set planonly; + + select * from t where coalesce(n*2,0) = 0; + select * from t where decode( mod(n, 3), 0, coalesce(n,0), 1, iif(mod(n,7)=0, 2, 3) ) = 1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (T INDEX (T_N2_COALESCE)) + PLAN (T INDEX (T_N2_DECODE)) + """ + +@pytest.mark.version('>=3.0') +def test_core_3338_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3340.py b/tests/bugs/test_core_3340.py new file mode 100644 index 00000000..09532e28 --- /dev/null +++ b/tests/bugs/test_core_3340.py @@ -0,0 +1,64 @@ +#coding:utf-8 +# +# id: bugs.core_3340 +# title: Error in autonomous transaction with empty exception handler: can insert duplicate values into PK/UK column (leads to unrestorable backup) +# decription: +# tracker_id: CORE-3340 +# min_versions: ['2.5.1'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """recreate table tmp(id int not null primary key using index tmp_id_pk); +commit; +set transaction no wait isolation level read committed; +set term ^; +execute block as +begin + insert into tmp values(1); + insert into tmp values(2); + in autonomous transaction do begin + insert into tmp values(1); + when any do begin + --exception; + end + end +end^ +set term ;^ +commit; +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select id from tmp; +select count(*) from tmp; +commit;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID +============ + 1 + 2 + + + COUNT +===================== + 2 + +""" + +@pytest.mark.version('>=3.0') +def test_core_3340_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3343.py b/tests/bugs/test_core_3343.py new file mode 100644 index 00000000..f403562c --- /dev/null +++ b/tests/bugs/test_core_3343.py @@ -0,0 +1,93 @@ +#coding:utf-8 +# +# id: bugs.core_3343 +# title: RETURNING clause is not supported in positioned (WHERE CURRENT OF) UPDATE and DELETE statements +# decription: +# tracker_id: CORE-3343 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('VB_.*', '')] + +init_script_1 = """ + recreate table test_a(id integer, cnt integer); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + execute block + as + declare variable cnt integer; + begin + for select cnt from test_a + where id=1 + into :cnt as cursor c + do begin + update test_a + set cnt=cnt+1 + where current of c + returning cnt into :cnt; + end + end + ^ + set term ;^ + commit; + + -- from core-3709 (refactored: check results when operating with blob): + recreate table test( + i int + ,b blob sub_type 1 + ); + insert into test(i,b) values(1, 'qwe'); + commit; + + set blob all; + set list on; + + set term ^; + execute block returns(vb_old blob, vb_new blob) as + declare c cursor for ( select b from test where i = 1 ); + declare v_s varchar(20); + begin + open c; + while (1=1) do + begin + fetch c into :v_s; + if (row_count = 0) then leave; + update test set b = reverse(b) + where current of c + returning upper(old.b), upper(new.b) into vb_old, vb_new + ; + suspend; + end + close c; + end + ^ + set term ;^ + commit; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + QWE + EWQ + """ + +@pytest.mark.version('>=3.0') +def test_core_3343_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3353.py b/tests/bugs/test_core_3353.py new file mode 100644 index 00000000..324ed021 --- /dev/null +++ b/tests/bugs/test_core_3353.py @@ -0,0 +1,75 @@ +#coding:utf-8 +# +# id: bugs.core_3353 +# title: Predicate (blob_field LIKE ?) describes the parameter as VARCHAR(30) rather than as BLOB +# decription: +# tracker_id: CORE-3353 +# min_versions: ['2.5.1'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!sqltype).)*$', ''), ('[ ]+', ' '), ('[\t]*', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set sqlda_display on; + set planonly; + select rdb$procedure_source from rdb$procedures where rdb$procedure_source like ?; + -- NB: output in 3.0 will contain values of sqltype with ZERO in bit_0, + -- so it will be: 520 instead of previous 521. + -- (see also: core_4156.fbt) + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 01: sqltype: 520 BLOB Nullable scale: 0 subtype: 1 len: 8 charset: 3 UNICODE_FSS + 01: sqltype: 520 BLOB Nullable scale: 0 subtype: 1 len: 8 charset: 3 UNICODE_FSS + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_core_3353_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [('^((?!sqltype).)*$', ''), ('[ ]+', ' '), ('[\t]*', ' ')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set sqlda_display on; + set planonly; + select rdb$procedure_source from rdb$procedures where rdb$procedure_source like ?; + -- NB: output in 3.0 will contain values of sqltype with ZERO in bit_0, + -- so it will be: 520 instead of previous 521. + -- (see also: core_4156.fbt) + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + 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 + """ + +@pytest.mark.version('>=4.0') +def test_core_3353_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/bugs/test_core_3355.py b/tests/bugs/test_core_3355.py new file mode 100644 index 00000000..55c6bfb3 --- /dev/null +++ b/tests/bugs/test_core_3355.py @@ -0,0 +1,56 @@ +#coding:utf-8 +# +# id: bugs.core_3355 +# title: Wrong comparsion of DATE and TIMESTAMP if index is used +# decription: +# tracker_id: CORE-3355 +# min_versions: ['2.1.5'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table tdate (id integer not null primary key, val date); +create index tdateix1 on tdate (val); +commit; +insert into tdate values (0, '1997-12-31'); +insert into tdate values (1, '1998-01-01'); +insert into tdate values (2, '1998-01-02'); +insert into tdate values (3, '1998-01-03'); +insert into tdate values (4, '1998-01-04'); +insert into tdate values (5, '1998-01-05'); +commit; +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select count(*) from tdate where val >= timestamp'1998-01-04 12:00:00.0000'; +select count(*) from tdate where val < timestamp'1998-01-04 12:00:00.0000'; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + COUNT +===================== + 1 + + + COUNT +===================== + 5 + +""" + +@pytest.mark.version('>=3.0') +def test_core_3355_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3357.py b/tests/bugs/test_core_3357.py new file mode 100644 index 00000000..5079f4e7 --- /dev/null +++ b/tests/bugs/test_core_3357.py @@ -0,0 +1,104 @@ +#coding:utf-8 +# +# id: bugs.core_3357 +# title: Generators are set to 0 after restore +# decription: +# NOTE: 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 +# +# Because of this it was decided to create separate section for check FB 4.x results. +# Checked on 4.0.0.2164 +# +# tracker_id: CORE-3357 +# min_versions: ['2.5.0'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate sequence g1 start with 9223372036854775807 increment by -2147483647; + recreate sequence g2 start with -9223372036854775808 increment by 2147483647; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# db_conn.close() +# fbk = os.path.join(context['temp_directory'],'tmp.core_3942.fbk') +# runProgram('gbak',['-b','-user',user_name,'-password',user_password,dsn,fbk]) +# runProgram('gbak',['-rep','-user',user_name,'-password',user_password,fbk,dsn]) +# sql='''show sequ g1; +# show sequ g2; +# ''' +# runProgram('isql',[dsn,'-user',user_name,'-pas',user_password],sql) +# +# if os.path.isfile(fbk): +# os.remove(fbk) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Generator G1, current value: 9223372036854775807, initial value: 9223372036854775807, increment: -2147483647 + Generator G2, current value: -9223372036854775808, initial value: -9223372036854775808, increment: 2147483647 + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_3357_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """ + recreate sequence g1 start with 9223372036854775807 increment by -2147483647; + recreate sequence g2 start with -9223372036854775808 increment by 2147483647; + commit; + """ + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +# test_script_2 +#--- +# import os +# db_conn.close() +# fbk = os.path.join(context['temp_directory'],'tmp.core_3942.fbk') +# runProgram('gbak',['-b','-user',user_name,'-password',user_password,dsn,fbk]) +# runProgram('gbak',['-rep','-user',user_name,'-password',user_password,fbk,dsn]) +# sql='''show sequ g1; +# show sequ g2; +# ''' +# runProgram('isql',[dsn,'-user',user_name,'-pas',user_password],sql) +# +# if os.path.isfile(fbk): +# os.remove(fbk) +#--- +#act_2 = python_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + Generator G1, current value: -9223372034707292162, initial value: 9223372036854775807, increment: -2147483647 + Generator G2, current value: 9223372034707292161, initial value: -9223372036854775808, increment: 2147483647 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_3357_2(db_2): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_336.py b/tests/bugs/test_core_336.py new file mode 100644 index 00000000..f1210197 --- /dev/null +++ b/tests/bugs/test_core_336.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: bugs.core_336 +# title: DateTime math imprecision +# decription: +# tracker_id: CORE-336 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_336-21 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select (cast('01.01.2004 10:01:00' as timestamp)-cast('01.01.2004 10:00:00' as timestamp))+cast('01.01.2004 10:00:00' as timestamp) from rdb$database ; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ADD +========================= +2004-01-01 10:01:00.0000 + +""" + +@pytest.mark.version('>=2.1') +def test_core_336_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3360.py b/tests/bugs/test_core_3360.py new file mode 100644 index 00000000..5637bae3 --- /dev/null +++ b/tests/bugs/test_core_3360.py @@ -0,0 +1,75 @@ +#coding:utf-8 +# +# id: bugs.core_3360 +# title: update ... returning ... raises -551 (no perm to update) for a column present only in the returning clause +# decription: +# tracker_id: CORE-3360 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set wng off; + + -- Drop old account with name = 'tmp$c3360' if it remains from prevoius run: + set term ^; + execute block as + begin + begin + execute statement 'drop user tmp$c3360' with autonomous transaction; + when any do begin end + end + end^ + set term ;^ + commit; + + create user tmp$c3360 password '123'; + commit; + revoke all on all from tmp$c3360; + commit; + + recreate table test(id int, readonly_x int, readonly_y int, writeable_column int); + commit; + + insert into test(id, readonly_x, readonly_y, writeable_column) values(1, 100, 200, 300); + commit; + + grant select on test to tmp$c3360; + grant update (writeable_column) on test to tmp$c3360; + commit; + + connect '$(DSN)' user 'TMP$C3360' password '123'; + + update test set writeable_column = readonly_x - readonly_y where id = 1 returning writeable_column; + commit; + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + drop user tmp$c3360; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WRITEABLE_COLUMN -100 + """ + +@pytest.mark.version('>=2.5.3') +def test_core_3360_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3362_basic.py b/tests/bugs/test_core_3362_basic.py new file mode 100644 index 00000000..30914171 --- /dev/null +++ b/tests/bugs/test_core_3362_basic.py @@ -0,0 +1,1434 @@ +#coding:utf-8 +# +# id: bugs.core_3362_basic +# title: Cursors should ignore changes made by the same statement +# decription: +# This test verifies BASIC issues that were accumulated in miscenaleous tickets. +# More complex cases (which involve not only SQL but also PSQL features) will +# follow in separate .fbt(s) in order to keep size of each test in reasonable limits. +# Checked on WI-T4.0.0.371, WI-V3.0.1.32597. +# Checked on 4.0.0.2028 (after fix core-2274) -- see below, view v_t1_updatable. +# +# :::::::::::::::::::::::::::::::::::::::: NB :::::::::::::::::::::::::::::::::::: +# 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 replace 'alter sequence restart...' with subtraction of two gen values: +# c = gen_id(, -gen_id(, 0)) -- see procedure sp_restart_sequences. +# +# +# tracker_id: CORE-3362 +# min_versions: ['3.0.1'] +# versions: 3.0.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter procedure sp_restart_sequences as begin end; + set term ^; + execute block as + begin + begin + execute statement 'drop sequence g1'; + when any do begin end + end + begin + execute statement 'drop sequence g2'; + when any do begin end + end + end + ^ + set term ;^ + commit; + + create sequence g1; + create sequence g2; + commit; + + set term ^; + create or alter procedure sp_restart_sequences as + declare c bigint; + begin + c = gen_id(g1, -gen_id(g1, 0)); + c = gen_id(g2, -gen_id(g2, 0)); + end + ^ + set term ;^ + commit; + + set list on; + + + --########################################################################### + + -- CORE-92 infinite insertion cycle + + recreate table test(x int); + commit; + insert into test values(0); + commit; + + execute procedure sp_restart_sequences; + commit; + + insert into test(x) select gen_id(g2, 1) from test where gen_id(g1, 1) < 10; + set count on; + select 'core-92' as test_case, t.* from test t; + set count off; + commit; + + /******************************** + Expected output: + X 0 + X 1 + Records affected: 2 + *********************************/ + -- result: OK on WI-T4.0.0.371, WI-V3.0.1.32597 (2.5.x: 10 records, wrong) + + + --########################################################################### + + -- CORE-634 Bad treatment of FIRST/SKIP in subselect + + execute procedure sp_restart_sequences; + commit; + + recreate table test(x int); + commit; + + insert into test(x) select gen_id(g1, 1) from rdb$types rows 10; + commit; + + delete from test where x in (select first 5 x from test); + set count on; + select 'core-634, case-1' as test_case, t.* from test t; + set count off; + commit; + + + /******************************** + Expected output: + X 6 + X 7 + X 8 + X 9 + X 10 + Records affected: 5 + *********************************/ + -- result: OK on WI-T4.0.0.371, WI-V3.0.1.32597 (2.5.x: 0 records selected, i.e. all rows have been deleted, wrong) + + + recreate table test(id int, val char(5)); + commit; + + insert into test values(1, 'red'); + insert into test values(2, 'green'); + insert into test values(3, 'blue'); + insert into test values(2, 'green'); + + delete from test + where test.ID in (select id from test GROUP BY id HAVING count(id)>1); + + set count on; + select 'core-634, case-2' as test_case, t.* from test t; + set count off; + commit; + /******************************** + Expected output: + + ID VAL + == ===== + 1 red + 3 blue + *********************************/ + -- result: OK on WI-T4.0.0.371, WI-V3.0.1.32597 (2.5.x: 3 records selected, additional one: id,val={2,green}) + + --########################################################################### + + -- CORE-2799 Changing sort directon in delete statement cause deletion of all records in table + + execute procedure sp_restart_sequences; + commit; + + recreate table test(x int); + create index test_x_asc on test(x); + create descending index test_x_dec on test(x); + commit; + + insert into test(x) select gen_id(g1, 1) from rdb$types rows 5; + commit; + + -- Trying to remove row with minimal 'x'. In 2.5 this lead to removal ALL subsequent rows. + delete from test a where not exists(select * from test b where b.x < a.x) order by a.x asc; + -- adding "order by a.x+0;" forces 2.5 to work fine + set count on; + select 'core-2799, case-1' as test_case, t.* from test t; + set count off; + + /******************************** + Expected output: + X 2 + X 3 + X 4 + X 5 + Records affected: 4 + *********************************/ + -- result: OK on WI-T4.0.0.371, WI-V3.0.1.32597 (2.5.x: 0 records selected, i.e. all rows have been deleted, wrong) + + rollback; + + -- Trying to remove row with maximal 'x'. In 2.5 this lead to removal ALL subsequent rows. + delete from test a where not exists(select * from test b where b.x > a.x) order by a.x desc; + set count on; + select 'core-2799, case-2' as test_case, t.* from test t; + set count off; + /******************************** + Expected output: + X 1 + X 2 + X 3 + X 4 + Records affected: 4 + *********************************/ + -- result: OK on WI-T4.0.0.371, WI-V3.0.1.32597 (2.5.x: 0 records selected, i.e. all rows have been deleted, wrong) + + rollback; + + + --########################################################################### + + + + -- Add sample from ticket: + -- ####################### + + recreate table test2 ( + id integer not null primary key using index test2_id, + kod varchar(5) + ); + commit; + insert into test2(id, kod) values(1, 'abc'); + insert into test2(id, kod) values(2, 'abc'); + commit; + + -- on 2.5 this will remove ALL rows from test2: + delete from test2 t1 where exists(select * from test2 t2 where t2.id<>t1.id and t2.kod=t1.kod) order by t1.id asc; + set count on; + select 'core-2799, case-3' as test_case, t.* from test2 t; + set count off; + /******************************** + Expected output: + Records affected: 0 + *********************************/ + -- result: OK on WI-T4.0.0.371, WI-V3.0.1.32597 (2.5: one record remain in table test2 with id=2) + rollback; + + drop table test2; + commit; + + + --########################################################################### + + -- CORE-3317 Success of deleting rows depending on order of row insertion + + recreate table cls ( + id numeric(18) + constraint cls_id_ck_c not null, + id_parent numeric(18) + constraint cls_idparent_ck_c not null, + id_child numeric(18) + constraint cls_idchild_ck_c not null, + depth numeric(18) + constraint cls_depth_ck_c not null, + constraint cls_ui1_c unique(id_parent, depth, id_child), + constraint cls_ui2_c unique(id_child, id_parent), + constraint cls_pk_c primary key (id) + ); + commit; + + insert into cls values(1, 2, 2, 0); + insert into cls values(2, 7, 7, 0); + insert into cls values(3, 10, 10, 0); + insert into cls values(4, 2, 7, 1); + insert into cls values(5, 2, 10, 2); + insert into cls values(6, 7, 10, 1); + commit; + + delete + from cls + where id in ( + select c.id + from cls c + join cls p on c.id_parent = p.id_parent + where + p.id_child = 7 + and p.depth = 1 + and c.depth >= 1 + ); + + set count on; + select 'core-3317' as test_case, c.* from cls c order by id; + set count off; + + /******************************** + Expected output: + ID 1 + ID_PARENT 2 + ID_CHILD 2 + DEPTH 0 + + ID 2 + ID_PARENT 7 + ID_CHILD 7 + DEPTH 0 + + ID 3 + ID_PARENT 10 + ID_CHILD 10 + DEPTH 0 + + ID 6 + ID_PARENT 7 + ID_CHILD 10 + DEPTH 1 + + Records affected: 4 + *********************************/ + -- result: OK on WI-T4.0.0.371, WI-V3.0.1.32597 (compared with PG 9.4); 2.5.x: "records affected: 5", wrong + + rollback; + + drop table cls; + + + --########################################################################### + + -- CORE-3362. Cursors should ignore changes made by the same statement + + -- Issues of 18.10.2011 08:49. + + -- Case-1. + -- ~~~~~~ + + recreate table t(id int primary key, f01 int); + commit; + insert into t values(1, 100); + insert into t values(2, 200); + insert into t values(3, 300); + commit; + + update t set f01=(select sum(f01) from t); + + set count on; + select 'core-3362, case-1' as test_case, t.* from t order by id; + set count off; + + /******************************** + Expected output: + ID 1 + F01 600 + + ID 2 + F01 600 + + ID 3 + F01 600 + + Records affected: 3 + *********************************/ + -- result: OK on WI-T4.0.0.371, WI-V3.0.1.32597 (2.5.x: f01={600, 1100, 2000} - wrong) + + rollback; + + drop table t; + commit; + + + --########################################################################### + + + -- Case-2. + -- ~~~~~~~ + + recreate table t(id int primary key, f01 int); + commit; + -- "reverse" order of values in f01 for same IDs: from big to small + insert into t values(1, 300); + insert into t values(2, 200); + insert into t values(3, 100); + commit; + + update t set f01=(select sum(f01) from t); + + set count on; + select 'core-3362, case-2' as test_case, t.* from t; + set count off; + rollback; + + drop table t; + commit; + + /******************************** + Expected output: + ID 1 + F01 600 + + ID 2 + F01 600 + + ID 3 + F01 600 + + Records affected: 3 + *********************************/ + -- result: OK on WI-T4.0.0.371, WI-V3.0.1.32597 (2.5.x: f01={600, 900, 1600} - wrong) + + + --########################################################################### + + + -- Issue of 03.01.2014 05:07. + recreate table t( + i int, + x int, y int, + constraint t_pk primary key(x), + constraint t_fk foreign key(y) references t(x) on update cascade -- SELF-REFERENCING + ); + commit; + + insert into t(x, y) values(1, null); + insert into t(x, y) values(2, 1 ); + insert into t(x, y) values(3, 2 ); + insert into t(x, y) values(4, 3 ); + insert into t(x, y) values(5, 4 ); + update t set y=5 where x=1; -- "closure" of chain + update t set i=x; -- backup initial values of 'x' + commit; + -- select * from t; + + update t set x=y+1; + + set count on; + select 'core-3362, case-3' as test_case, t.* from t order by i; + set count off; + + /******************************** + Expected output (compared with PG 9.4) + I X Y + == ============ ============ + 1 6 5 + 2 2 6 + 3 3 2 + 4 4 3 + 5 5 4 + Records affected: 5 + *********************************/ + -- Result: OK on WI-T4.0.0.371, WI-V3.0.1.32597 2.5.x - wrong data at all. + -- 3.0.0.32030 = FAIL <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< F A I L <<<<<<<<<<<<<< + -- SQLSTATE = 23000 + -- violation of FOREIGN KEY constraint "T_FK" on table "T" + -- -Foreign key reference target does not exist + -- -unknown ISC error 335545072 + -- 3.0.0.31896 = FAIL (Beta-2 release) + -- 3.0.0.31374 = OK (Beta-1 release) + + rollback; + + drop table t; + commit; + + + --########################################################################### + + + + -- Issues of 03.01.2014 05:13. + -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + -- See also: http://www.sql.ru/forum/1068804/rezultat-count-f1-over-v-processe-update-set-f1-null-cursor-stability?hl= + -- Case-1. + -- ~~~~~~~ + + recreate table t(x int, y int); + commit; + insert into t values(1, 1); + insert into t values(2, 2); + insert into t values(3, 3); + insert into t values(4, 4); + insert into t values(5, 5); + commit; + + update t set x=null, y=(select c from (select count(x)over() c from t) rows 1); + + set count on; + select 'core-3362, case-4' as test_case, t.* from t; + set count off; + rollback; + + drop table t; + commit; + + /******************************** + Expected output + X + Y 5 + + X + Y 5 + + X + Y 5 + + X + Y 5 + + X + Y 5 + Records affected: 5 + *********************************/ + -- result: OK on WI-T4.0.0.371, WI-V3.0.1.32597; 2.5.x - can't be checked because of OVER() clause. + + + --########################################################################### + + + -- Case-2. + -- ~~~~~~~~~ + + recreate table t(x int, y int); + commit; + insert into t values(1, 1); + insert into t values(2, 2); + insert into t values(3, 3); + insert into t values(4, 4); + insert into t values(5, 5); + commit; + + update t + set y=(select (select sum(x) from t tx where tx.x<=tt.x) + from t tt + order by y desc rows 1 + ); + + set count on; + select 'core-3362, case-5' as test_case, t.* from t; + set count off; + + /******************************** + Expected output: + X 1 + Y 15 + + X 2 + Y 15 + + X 3 + Y 15 + + X 4 + Y 15 + + X 5 + Y 15 + + Records affected: 5 + *********************************/ + -- result: OK on WI-T4.0.0.371, WI-V3.0.1.32597; 2.5.x: wrong data in t.y: {15,1,1,1} + + rollback; + + drop table t; + commit; + + + + --########################################################################### + + + -- Additional issue: sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1068804&msg=15378766 (05.01.2014) + recreate table t(x int primary key, y int); + commit; + insert into t values(5,5); + insert into t values(4,5); + insert into t values(3,2); + insert into t values(2,2); + insert into t values(1,0); + commit; + + delete from t m where (select count(*)over() from t x where x.y=m.y rows 1) > 1; + + set count on; + select 'core-3362, case-6' as test_case, t.* from t; + set count off; + rollback; + + /******************************** + Expected output: + X 1 + Y 0 + + Records affected: 1 + *********************************/ + -- result: OK on WI-T4.0.0.371, WI-V3.0.1.32597; 2.5.x: can't be tested because of OVER() clause. + + drop table t; + commit; + + + --########################################################################### + + + + -- Issue 01.03.2014 02:22 + + recreate table t(id int primary key, x int); + commit; + insert into t(id, x) select row_number()over(), row_number()over() from rdb$types rows 3; + commit; + update t set x=null where x not in(select x from t where x is null); + + set count on; + select 'core-3362, case-7' as test_case, t.* from t; + set count off; + rollback; + + /******************************** + Expected output: + ID 1 + X + + ID 2 + X + + ID 3 + X + + Records affected: 3 + *********************************/ + -- result: OK on WI-T4.0.0.371, WI-V3.0.1.32597; 2.5.x: can't be tested because of OVER() clause. + + drop table t; + commit; + + + + --########################################################################### + + + + -- Issue 12.03.2014 04:56 + + recreate table t(x int, y int); + insert into t values(1, 100); + insert into t values(2, 200); + insert into t values(3, 300); + commit; + create view v as select y,count(*) cnt from t group by y; + commit; + + update t set y=null where 2 not in( select cnt from v ); + + set count on; + select 'core-3362, case-8.1' as test_case, t.* from t; + set count off; + + + /******************************** + Expected output: + ID 1 + X + + ID 2 + X + + ID 3 + X + + Records affected: 3 + *********************************/ + -- result: OK on WI-T4.0.0.371, WI-V3.0.1.32597; 2.5.x: wrong data in t.x: {null, null, 300} + + rollback; + + drop view v; + drop table t; + commit; + + + --########################################################################### + + -- 25.09.2016: case with NOT IN and ALL predicates, see letters to hvlad, dimitr from this date: + recreate table t(id int, x int); + commit; + + insert into t(id, x) values(1,10); + insert into t(id, x) values(2,20); + insert into t(id, x) values(3,30); + insert into t(id, x) values(4,40); + commit; + + update t s set x = null where x not in ( select x from t z where z.x > all(select x from t y where y.id<>z.id ) ); + set count on; + select 'core-3362, case-8.2' as test_case, t.* from t; + set count off; + /******************************** + Expected output: + ID 1 + X + + ID 2 + X + + ID 3 + X + + ID 4 + X 40 + + Records affected: 4 + *********************************/ + -- result: OK on 3.x, 4.0; 2.5.x: wrong for id=4: {4,null} + + rollback; + + -- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + -- :::::::::::::::::::::::::::::: M E R G E ::::::::::::::::::::::::: + -- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + + -- Issue 16.03.2014 09:51 + -- Also: http://www.sql.ru/forum/1082847/merge-ne-sovpadaut-rezultaty-fb-i-oracle-again-cursor-stability?hl= + + recreate table t(x int, y int); + + insert into t values(1, 5); + insert into t values(2, 4); + insert into t values(3, 3); + insert into t values(4, 2); + insert into t values(5, 1); + + recreate table t2(x int, y int); + + insert into t2 values(2, 4); + insert into t2 values(5, 1); + insert into t2 values(1, 5); + insert into t2 values(4, 2); + insert into t2 values(3, 3); + + -- This is only for illustrate required result: all rows should contain + -- new value y = 4 + -- update t set t.y = (select count(*) from t where x<>y) + -- where exists( select * from t2 s where t.x=s.y) + -- ; + -- rollback; + + merge into t using(select x,y from t2) s on t.x=s.y + when matched + then update set t.y=(select count(*) from t where x<>y); + + --set list off; + set count on; + select 'core-3362, case-9' as test_case, t.* from t order by x; + set count off; + rollback; + + /******************************** + Expected output: + X 1 + Y 4 + + X 2 + Y 4 + + X 3 + Y 4 + + X 4 + Y 4 + + X 5 + Y 4 + Records affected: 5 + *********************************/ + + -- Result: + -- OK on WI-T4.0.0.371, WI-V3.0.1.32597; 2.5.x: wrong data in t.y: {4,4,4,5,5} + -- 3.0.0.32030 = FAIL <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< F A I L <<<<<<<<<<<<<< + -- 3.0.0.32362 = OK. // confirmed on: WI-V3.0.0.32362, 26.02.2016 + + drop table t; + drop table t2; + commit; + + + --########################################################################### + + + + -- Issue 14.05.2015 10:54 + + recreate table test( + id int constraint test_pk_id primary key using index test_pk_id, + pid int constraint test_fk_pid2id references test(id) + on update SET NULL + ); + commit; + insert into test values( 5, null ); + insert into test values( 4, 5 ); + insert into test values( 3, 4 ); + insert into test values( 2, 3 ); + insert into test values( 1, 2 ); + commit; + update test set pid=1 where id=5; + commit; + + /* + content of table test now is: + ID PID + 5 1 + 4 5 + 3 4 + 2 3 + 1 2 + */ + update test set id = id + 1 order by id desc; + + set count on; + select 'core-3362, case-10' as test_case, t.* from test t order by id desc; + set count off; + rollback; + + drop table test; + commit; + + /******************************* + + EXPECTED result: + + ID PID + ==== ============ + 6 + 5 + 4 + 3 + 2 + + -- OK on WI-T4.0.0.371, WI-V3.0.1.32597 + -- By the way: PG 9.4 (update test set id = id + 1): + -- ERROR: duplicate key value violates unique constraint "test_pk_id" + -- DETAIL: Key (id)=(5) already exists. + **********************************/ + -- OK on WI-T4.0.0.371, WI-V3.0.1.32597 + + + --########################################################################### + + -- Issue 13.09.2014 09:33 + + + recreate table t1(id int); + recreate table t2(id int, x int); + commit; + insert into t1 values(1); + insert into t1 values(2); + insert into t1 values(3); + commit; + + merge into t2 using t1 on t1.id=t2.id when not matched then insert (id, x) values(t1.id, (select sum(id) from t2) ); + select 'core-3362, case-11a' as test_case, a.* from t2 a; + rollback; + + merge into t2 using t1 on t1.id=t2.id when not matched then insert (id, x) values(t1.id, (select min(id) from t2) ); + select 'core-3362, case-11b' as test_case, a.* from t2 a; + rollback; + + merge into t2 using t1 on t1.id=t2.id when not matched then insert (id, x) values(t1.id, (select max(id) from t2) ); + select 'core-3362, case-11c' as test_case, a.* from t2 a; + rollback; + + merge into t2 using t1 on t1.id=t2.id when not matched then insert (id, x) values(t1.id, (select count(*) from t2) ); + select 'core-3362, case-11d' as test_case, a.* from t2 a; + rollback; + + /* + Expected result: + ID X + ============ ============ + 1 + 2 + 3 + + ID X + ============ ============ + 1 + 2 + 3 + + ID X + ============ ============ + 1 + 2 + 3 + + ID X + ============ ============ + 1 0 + 2 0 + 3 0 + */ + -- OK on WI-T4.0.0.371, WI-V3.0.1.32597; totally wrong on 2.5.x + + + + --########################################################################### + + -- 25.09.2016: case with NOT IN and ALL predicates, see letters to hvlad, dimitr from this date: + + recreate table t1(id int, x int); + --recreate view v_t1_checked as select * from t1 where true with check option; -- temply (?) added 07.06.2020 because of fixed core-2274 + + -- 08.06.2020: 'WITH CHECK OPTION' no more helps. + -- We have to create 'truly-updatable' view in order to avoid + -- Statement failed, SQLSTATE = 21000 + -- Multiple source records cannot match the same target during MERGE + recreate view v_t1_updatable as select * from t1; + set term ^; + create or alter trigger v_t1_biud for v_t1_updatable active before insert or update or delete position 0 as + declare v_old_id int; + declare v_old_x int; + declare v_new_id int; + declare v_new_x int; + begin + if (not deleting) then + begin + if (inserting) then + insert into t1(id, x) values(new.id, new.x); + else + update t1 set id = new.id, x = new.x where id = old.id; + end + else + begin + delete from t1 where id = old.id; + end + end + ^ + set term ;^ + commit; + + insert into v_t1_updatable(id, x) values(1,10); + insert into v_t1_updatable(id, x) values(2,20); + insert into v_t1_updatable(id, x) values(3,30); + insert into v_t1_updatable(id, x) values(4,40); + commit; + + + merge into v_t1_updatable t + using t1 s on + t.x not in ( select x from t1 z where z.x is null or z.x > all(select x from t1 y where y.id<>z.id ) ) + when matched then update set x = null + ; + + select 'core-3362, case-12a' as test_case, a.* from t1 a; + + /* Expected result: + ID 1 + X + + ID 2 + X + + ID 3 + X + + ID 4 + X 40 + */ + -- OK on 3.x, wrong data on 2.5.x for id >= 2; + + rollback; + + + merge into v_t1_updatable t + using t1 s on + t.x not in ( select x from t1 z where z.x is null or z.x > all(select x from t1 y where y.id<>z.id ) ) + when matched then update set x = null + ; + + select 'core-3362, case-12b' as test_case, a.* from t1 a; + /* Expected result: + ID 1 + X + + ID 2 + X + + ID 3 + X + + ID 4 + X 40 + */ + -- OK on 3.x, wrong data on 2.5.x for id >= 2; + + rollback; + + + --########################################################################### + + -- 24.10.2016 from CORE-3862: + + recreate table icesling ( + id integer, + yearofbirth integer, + name varchar(30), + constraint someuniqueconstrain primary key (id) + ); + commit; + + insert into icesling (id, yearofbirth, name) values ('1', '1980', 'zeca'); + insert into icesling (id, yearofbirth, name) values ('2', '1980', 'chico'); + insert into icesling (id, yearofbirth, name) values ('3', '1983', 'leila'); + commit; + + set list on; + + -- the min() grouping is ignored and 2 records are deleted, only one shoud be deleted + set count on; + + delete + from icesling where id in ( + select min(i.id) from icesling i + where i.yearofbirth=1980 + ); + set count off; + + select 'core-3862' as test_case, t.* from icesling t; + rollback; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TEST_CASE core-92 + X 0 + + TEST_CASE core-92 + X 1 + + + Records affected: 2 + + TEST_CASE core-634, case-1 + X 6 + + TEST_CASE core-634, case-1 + X 7 + + TEST_CASE core-634, case-1 + X 8 + + TEST_CASE core-634, case-1 + X 9 + + TEST_CASE core-634, case-1 + X 10 + + + Records affected: 5 + + TEST_CASE core-634, case-2 + ID 1 + VAL red + + TEST_CASE core-634, case-2 + ID 3 + VAL blue + + + Records affected: 2 + + TEST_CASE core-2799, case-1 + X 2 + + TEST_CASE core-2799, case-1 + X 3 + + TEST_CASE core-2799, case-1 + X 4 + + TEST_CASE core-2799, case-1 + X 5 + + + Records affected: 4 + + TEST_CASE core-2799, case-2 + X 1 + + TEST_CASE core-2799, case-2 + X 2 + + TEST_CASE core-2799, case-2 + X 3 + + TEST_CASE core-2799, case-2 + X 4 + + + Records affected: 4 + Records affected: 0 + + TEST_CASE core-3317 + ID 1 + ID_PARENT 2 + ID_CHILD 2 + DEPTH 0 + + TEST_CASE core-3317 + ID 2 + ID_PARENT 7 + ID_CHILD 7 + DEPTH 0 + + TEST_CASE core-3317 + ID 3 + ID_PARENT 10 + ID_CHILD 10 + DEPTH 0 + + TEST_CASE core-3317 + ID 6 + ID_PARENT 7 + ID_CHILD 10 + DEPTH 1 + + + Records affected: 4 + + TEST_CASE core-3362, case-1 + ID 1 + F01 600 + + TEST_CASE core-3362, case-1 + ID 2 + F01 600 + + TEST_CASE core-3362, case-1 + ID 3 + F01 600 + + + Records affected: 3 + + TEST_CASE core-3362, case-2 + ID 1 + F01 600 + + TEST_CASE core-3362, case-2 + ID 2 + F01 600 + + TEST_CASE core-3362, case-2 + ID 3 + F01 600 + + + Records affected: 3 + + TEST_CASE core-3362, case-3 + I 1 + X 6 + Y 5 + + TEST_CASE core-3362, case-3 + I 2 + X 2 + Y 6 + + TEST_CASE core-3362, case-3 + I 3 + X 3 + Y 2 + + TEST_CASE core-3362, case-3 + I 4 + X 4 + Y 3 + + TEST_CASE core-3362, case-3 + I 5 + X 5 + Y 4 + + + Records affected: 5 + + TEST_CASE core-3362, case-4 + X + Y 5 + + TEST_CASE core-3362, case-4 + X + Y 5 + + TEST_CASE core-3362, case-4 + X + Y 5 + + TEST_CASE core-3362, case-4 + X + Y 5 + + TEST_CASE core-3362, case-4 + X + Y 5 + + + Records affected: 5 + + TEST_CASE core-3362, case-5 + X 1 + Y 15 + + TEST_CASE core-3362, case-5 + X 2 + Y 15 + + TEST_CASE core-3362, case-5 + X 3 + Y 15 + + TEST_CASE core-3362, case-5 + X 4 + Y 15 + + TEST_CASE core-3362, case-5 + X 5 + Y 15 + + + Records affected: 5 + + TEST_CASE core-3362, case-6 + X 1 + Y 0 + + + Records affected: 1 + + TEST_CASE core-3362, case-7 + ID 1 + X + + TEST_CASE core-3362, case-7 + ID 2 + X + + TEST_CASE core-3362, case-7 + ID 3 + X + + + Records affected: 3 + + TEST_CASE core-3362, case-8.1 + X 1 + Y + + TEST_CASE core-3362, case-8.1 + X 2 + Y + + TEST_CASE core-3362, case-8.1 + X 3 + Y + + + Records affected: 3 + + TEST_CASE core-3362, case-8.2 + ID 1 + X + + TEST_CASE core-3362, case-8.2 + ID 2 + X + + TEST_CASE core-3362, case-8.2 + ID 3 + X + + TEST_CASE core-3362, case-8.2 + ID 4 + X 40 + + + Records affected: 4 + + TEST_CASE core-3362, case-9 + X 1 + Y 4 + + TEST_CASE core-3362, case-9 + X 2 + Y 4 + + TEST_CASE core-3362, case-9 + X 3 + Y 4 + + TEST_CASE core-3362, case-9 + X 4 + Y 4 + + TEST_CASE core-3362, case-9 + X 5 + Y 4 + + + Records affected: 5 + + TEST_CASE core-3362, case-10 + ID 6 + PID + + TEST_CASE core-3362, case-10 + ID 5 + PID + + TEST_CASE core-3362, case-10 + ID 4 + PID + + TEST_CASE core-3362, case-10 + ID 3 + PID + + TEST_CASE core-3362, case-10 + ID 2 + PID + + + Records affected: 5 + + TEST_CASE core-3362, case-11a + ID 1 + X + + TEST_CASE core-3362, case-11a + ID 2 + X + + TEST_CASE core-3362, case-11a + ID 3 + X + + + + TEST_CASE core-3362, case-11b + ID 1 + X + + TEST_CASE core-3362, case-11b + ID 2 + X + + TEST_CASE core-3362, case-11b + ID 3 + X + + + + TEST_CASE core-3362, case-11c + ID 1 + X + + TEST_CASE core-3362, case-11c + ID 2 + X + + TEST_CASE core-3362, case-11c + ID 3 + X + + + + TEST_CASE core-3362, case-11d + ID 1 + X 0 + + TEST_CASE core-3362, case-11d + ID 2 + X 0 + + TEST_CASE core-3362, case-11d + ID 3 + X 0 + + TEST_CASE core-3362, case-12a + ID 1 + X + + TEST_CASE core-3362, case-12a + ID 2 + X + + TEST_CASE core-3362, case-12a + ID 3 + X + + TEST_CASE core-3362, case-12a + ID 4 + X 40 + + + + TEST_CASE core-3362, case-12b + ID 1 + X + + TEST_CASE core-3362, case-12b + ID 2 + X + + TEST_CASE core-3362, case-12b + ID 3 + X + + TEST_CASE core-3362, case-12b + ID 4 + X 40 + + Records affected: 1 + TEST_CASE core-3862 + ID 2 + YEAROFBIRTH 1980 + NAME chico + + TEST_CASE core-3862 + ID 3 + YEAROFBIRTH 1983 + NAME leila + + """ + +@pytest.mark.version('>=3.0.1') +def test_core_3362_basic_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3362_complex.py b/tests/bugs/test_core_3362_complex.py new file mode 100644 index 00000000..7fa3c87c --- /dev/null +++ b/tests/bugs/test_core_3362_complex.py @@ -0,0 +1,139 @@ +#coding:utf-8 +# +# id: bugs.core_3362_complex +# title: Cursors should ignore changes made by the same statement +# decription: +# This test verifies PSQL issues that were accumulated in miscenaleous tickets. +# +# tracker_id: CORE-3362 +# min_versions: ['3.0.1'] +# versions: 3.0.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.1 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('line: [\\d]+[,]{0,1} col: [\\d]+', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- see also: + -- https://www.sql.ru/forum/1319017/obnovlenie-zapisi-po-kursoru + -- Discussed 13.11.2019 with hvlad and dimitr (related to CORE-5794) + recreate table test ( + id int not null + ,data1 int + ,data2 int + ,data3 int + ,data4 int + ); + set term ^; + create or alter procedure sp_set_ctx(a_point varchar(20), a_data1 int, a_data2 int, a_data3 int, a_data4 int) as + begin + -- Store values of cursor fields in the context variable which name is passed here as 'a_point'. + rdb$set_context( + 'USER_SESSION', + a_point, + coalesce(cast( a_data1 as char(6)),'#null#') + || ' ' || coalesce(cast( a_data2 as char(6)),'#null#') + || ' ' || coalesce(cast( a_data3 as char(6)),'#null#') + || ' ' || coalesce(cast( a_data4 as char(6)),'#null#') + ); + end + ^ + + create or alter procedure sp_test1a as + begin + -- ::: NOTE ::: + -- Only IMPLICIT cursors are stable in 3.0+. + -- ############# + -- Do _NOT_ try to check following statements using explicit cursor + -- (i.e. OPEN ; FETCH ...; CLOSE ) + for + select t.id, t.data1, t.data2, t.data3, t.data4 from test t where t.id = 1 + as cursor c + do begin + + execute procedure sp_set_ctx('point_0', c.data1, c.data2, c.data3, c.data4 ); + + update test t set t.data1 = 100001 where current of c; + -- make "photo" of all cursor fields: + execute procedure sp_set_ctx('point_1', c.data1, c.data2, c.data3, c.data4 ); + + -- at this point value of c.data1 remains NULL from cursor POV because + -- "UPDATE WHERE CURRENT OF C" sees record as it was no changes at all: + update test t set t.data2 = 100002 where current of c; + -- make "photo" of all cursor fields: + execute procedure sp_set_ctx('point_2', c.data1, c.data2, c.data3, c.data4 ); + + -- at this point value of c.data1 and c.data2 remain NULL from cursor POV because + -- "UPDATE WHERE CURRENT OF C" sees record as it was no changes at all: + update test t set t.data3 = 100003 where current of c; + -- make "photo" of all cursor fields: + execute procedure sp_set_ctx('point_3', c.data1, c.data2, c.data3, c.data4 ); + + delete from test t where current of c; -- this must prevent following UPDATE from execution + + -- this must fail with "no current record for fetch operation": + update test t set t.data4 = 100004 where current of c; + execute procedure sp_set_ctx('point_4', c.data1, c.data2, c.data3, c.data4 ); + + + end + end + ^ + set term ;^ + + commit; + insert into test (id) values (1); + commit; + + set bail off; + set list on; + + execute procedure sp_test1a; + select * from test; + select mon$variable_name as ctx_name, mon$variable_value ctx_value from mon$context_variables where mon$attachment_id = current_connection; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + DATA1 + DATA2 + DATA3 + DATA4 + + CTX_NAME point_0 + CTX_VALUE #null# #null# #null# #null# + + CTX_NAME point_1 + CTX_VALUE 100001 #null# #null# #null# + + CTX_NAME point_2 + CTX_VALUE #null# 100002 #null# #null# + + CTX_NAME point_3 + CTX_VALUE #null# #null# 100003 #null# + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22000 + no current record for fetch operation + -At procedure 'SP_TEST1A' + """ + +@pytest.mark.version('>=3.0.1') +def test_core_3362_complex_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3364.py b/tests/bugs/test_core_3364.py new file mode 100644 index 00000000..15adf792 --- /dev/null +++ b/tests/bugs/test_core_3364.py @@ -0,0 +1,75 @@ +#coding:utf-8 +# +# id: bugs.core_3364 +# title: Blob filter to translate internal debug info into text representation +# decription: +# tracker_id: CORE-3364 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('RDB\\$DEBUG_INFO', ''), ('-', ''), ('[0-9]+[ ]+[0-9]+[ ]+[0-9]+', '')] + +init_script_1 = """ + set term ^; + create or alter procedure sp_test(a_n smallint) returns(n_fact bigint) as + begin + n_fact = iif(a_n > 0, a_n, 0); + + while (a_n > 1) do + begin + n_fact = n_fact * (a_n - 1); + a_n = a_n -1; + end + suspend; + end + ^ + set term ;^ + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set blob all; + select rdb$debug_info from rdb$procedures where upper(rdb$procedure_name) = upper('sp_test'); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$DEBUG_INFO 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 + """ + +@pytest.mark.version('>=3.0') +def test_core_3364_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3365.py b/tests/bugs/test_core_3365.py new file mode 100644 index 00000000..279e8b8d --- /dev/null +++ b/tests/bugs/test_core_3365.py @@ -0,0 +1,127 @@ +#coding:utf-8 +# +# id: bugs.core_3365 +# title: Extend syntax for ALTER USER CURRENT_USER +# decription: +# Replaced old code: removed EDS from here as it is not needed at all: +# we can use here trivial "connect '$(DSN)' ..." instead. +# Non-privileged user is created in this test and then we check that +# he is able to change his personal data: password, firstname and any of +# TAGS key-value pair (avaliable in Srp only). +# +# Checked on 4.0.0.1635: OK, 3.773s; 3.0.5.33180: OK, 2.898s. +# +# tracker_id: CORE-3365 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('=', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set count on; + + -- Drop any old account with name = 'TMP$C3365' if it remains from prevoius run: + set term ^; + execute block as + begin + begin + execute statement 'drop user tmp$c3365 using plugin Srp' with autonomous transaction; + when any do begin end + end + + begin + execute statement 'drop user tmp$c3365 using plugin Legacy_UserManager' with autonomous transaction; + when any do begin end + end + end^ + set term ;^ + commit; + + set width usrname 10; + set width firstname 10; + set width sec_plugin 20; + set width sec_attr_key 20; + set width sec_attr_val 20; + set width sec_plugin 20; + + recreate view v_usr_info as + select + su.sec$user_name as usrname + ,su.sec$first_name as firstname + ,su.sec$plugin as sec_plugin + ,sa.sec$key as sec_attr_key + ,sa.sec$value as sec_attr_val + from sec$users su left + join sec$user_attributes sa using(sec$user_name, sec$plugin) + where su.sec$user_name = upper('tmp$c3365'); + commit; + + grant select on v_usr_info to public; + commit; + + create user tmp$c3365 password 'Ir0nM@n' firstname 'John' + using plugin Srp + tags (initname='Ozzy', surname='Osbourne', groupname='Black Sabbath', birthday = '03.12.1948') + ; + commit; + + select 'before altering' as msg, v.* from v_usr_info v; + commit; + + connect '$(DSN)' user tmp$c3365 password 'Ir0nM@n'; + + alter current user + set password 'H1ghWaySt@r' firstname 'Ian' + using plugin Srp + tags (initname='Ian', surname='Gillan', groupname='Deep Purple', drop birthday) + ; + commit; + + connect '$(DSN)' user tmp$c3365 password 'H1ghWaySt@r'; + commit; + + select 'after altering' as msg, v.* from v_usr_info v; + commit; + + connect '$(DSN)' user SYSDBA password 'masterkey'; + drop user tmp$c3365 using plugin Srp; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG USRNAME FIRSTNAME SEC_PLUGIN SEC_ATTR_KEY SEC_ATTR_VAL + =============== ========== ========== ==================== ==================== ==================== + before altering TMP$C3365 John Srp BIRTHDAY 03.12.1948 + before altering TMP$C3365 John Srp GROUPNAME Black Sabbath + before altering TMP$C3365 John Srp INITNAME Ozzy + before altering TMP$C3365 John Srp SURNAME Osbourne + Records affected: 4 + + MSG USRNAME FIRSTNAME SEC_PLUGIN SEC_ATTR_KEY SEC_ATTR_VAL + ============== ========== ========== ==================== ==================== ==================== + after altering TMP$C3365 Ian Srp GROUPNAME Deep Purple + after altering TMP$C3365 Ian Srp INITNAME Ian + after altering TMP$C3365 Ian Srp SURNAME Gillan + Records affected: 3 + """ + +@pytest.mark.version('>=3.0') +def test_core_3365_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3373.py b/tests/bugs/test_core_3373.py new file mode 100644 index 00000000..eb862bad --- /dev/null +++ b/tests/bugs/test_core_3373.py @@ -0,0 +1,76 @@ +#coding:utf-8 +# +# id: bugs.core_3373 +# title: It is possible to store string with lenght 31 chars into column varchar(25) +# decription: +# tracker_id: CORE-3373 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table t1(c varchar(25)); + recreate table t2(c varchar(25)); + commit; + + set term ^; + execute block as + begin + execute statement 'drop domain dm_vc25'; + when any do + begin end + end + ^ + set term ;^ + commit; + + create domain dm_vc25 varchar(25) character set utf8; + commit; + recreate table t2(c dm_vc25); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set count on; + set echo on; + insert into t1(c) values ('1234567890123456789012345xxxxxx'); + insert into t2(c) values ('1234567890123456789012345xxxxxx'); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + insert into t1(c) values ('1234567890123456789012345xxxxxx'); + Records affected: 0 + insert into t2(c) values ('1234567890123456789012345xxxxxx'); + Records affected: 0 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22001 + arithmetic exception, numeric overflow, or string truncation + -string right truncation + -expected length 25, actual 31 + Statement failed, SQLSTATE = 22001 + arithmetic exception, numeric overflow, or string truncation + -string right truncation + -expected length 25, actual 31 + """ + +@pytest.mark.version('>=3.0') +def test_core_3373_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3374.py b/tests/bugs/test_core_3374.py new file mode 100644 index 00000000..94655113 --- /dev/null +++ b/tests/bugs/test_core_3374.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: bugs.core_3374 +# title: Server may crash or corrupt data if SELECT WITH LOCK is issued against records not in the latest format +# decription: Actually there is NO crash in 2.5.0, checked SS/SC/CS, WI-V2.5.0.26074. +# tracker_id: CORE-3374 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table test (col1 int, col2 varchar(10), col3 date); + insert into test values (1, 'qwerty', date '01.01.2015'); + alter table test drop col2; + set list on; + select * from test order by col1 with lock; -- crash here + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + COL1 1 + COL3 2015-01-01 + """ + +@pytest.mark.version('>=2.5.1') +def test_core_3374_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3394.py b/tests/bugs/test_core_3394.py new file mode 100644 index 00000000..ab49ed7f --- /dev/null +++ b/tests/bugs/test_core_3394.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: bugs.core_3394 +# title: Failed attempt to violate unique constraint could leave unneeded "lock conflict" error in status-vector +# decription: +# tracker_id: CORE-3394 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [('-At block line: [\\d]+, col: [\\d]+', '-At block line')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table t(id int, constraint t_pk primary key(id) using index t_id); + commit; + SET TRANSACTION READ COMMITTED RECORD_VERSION NO WAIT; + set term ^; + execute block as + begin + insert into t values(1); + in autonomous transaction do + insert into t values(1); + end + ^ + set term ;^ + rollback; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + 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 + """ + +@pytest.mark.version('>=2.5.1') +def test_core_3394_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_3398.py b/tests/bugs/test_core_3398.py new file mode 100644 index 00000000..294006ae --- /dev/null +++ b/tests/bugs/test_core_3398.py @@ -0,0 +1,34 @@ +#coding:utf-8 +# +# id: bugs.core_3398 +# title: GRANT ADMIN ROLE not accepted +# decription: +# tracker_id: CORE-3398 +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- See ticket issue: Alexander Peshkov added a comment - 21/Mar/11 03:10 PM + -- Does not require frontporting - FB3 is using another way to access security database + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +def test_core_3398_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_3399.py b/tests/bugs/test_core_3399.py new file mode 100644 index 00000000..02c32fe4 --- /dev/null +++ b/tests/bugs/test_core_3399.py @@ -0,0 +1,52 @@ +#coding:utf-8 +# +# id: bugs.core_3399 +# title: Allow write operations to temporary tables in read only transactions +# decription: +# tracker_id: CORE-3399 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core3399-read_only.fbk', init=init_script_1) + +test_script_1 = """ + -- ======= from the ticket: ======== + -- Implementation allows: + -- 1) writes into all kind of GTT's in read only transactions in read write database + -- and also + -- 2) make writabe GTT ON COMMIT DELETE in read only transactions in read only database. + -- ================================= + -- Database will be in the state "force write, no reserve, read only". + -- This test verifies only SECOND issue from ticket: allow GTT with attribute "on commit DELETE rows" + -- to be writeable when database is READ-ONLY. + commit; + set transaction read only; + insert into gtt_del_rows(id) values(1); + select * from gtt_del_rows; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID + ======= + 1 + """ + +@pytest.mark.version('>=2.5.1') +def test_core_3399_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3401.py b/tests/bugs/test_core_3401.py new file mode 100644 index 00000000..0ce7238e --- /dev/null +++ b/tests/bugs/test_core_3401.py @@ -0,0 +1,178 @@ +#coding:utf-8 +# +# id: bugs.core_3401 +# title: Collation errors with [type of] , type of column +# decription: +# tracker_id: CORE-3401 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + ----------------------------------------------------------------------------------------------- + -- NB-1. Initial test (which is in the tracker) considered only ASCII characters 'a' vs 'A'. + -- This test compares many NON-ascii characters with diacritical marks - it was done intentionally. + -- All the cases successfully PASSED on WI-T3.0.0.31767 (Win XP) and LI-T3.0.0.31719 (Ubuntu 14.10). + -- Firebird WI-V2.5.4.26857 FAILS in test-cases 1,2 and 4. + -- NB-2. Attribute 'connection_character_set': 'UTF8' - is MANDATORY in this test, + -- otherwise fbt_run raises exception: + -- traceback: + -- File "c:\\mix irebird\\qa btest btest.py", line 2103, in run + -- test_recipe.run(self,result) + -- File "c:\\mix irebird\\qa btest btest.py", line 731, in run + -- script = self.test_script.encode('ascii') + -- ---------------------------------------------------------------------- + -- exception: + -- UnicodeEncodeError: + -- ascii + -- . . . + -- 505 + -- 511 + -- ordinal not in range(128) + -- (no any exceptions when run corresponding script in ISQL with absent charset of connection). + ----------------------------------------------------------------------------------------------- + + create or alter procedure selproc_dom as begin end; + create or alter procedure selproc_typeof_col_ci_dir as begin end; + commit; + + recreate table t(id int); + commit; + + set term ^; + execute block as + begin + execute statement 'drop domain dom_ci'; + when any do begin end + end + ^ + set term ;^ + commit; + + -- Following letters was included in the character literals: + -- ÁÉÍÓÚÝ ÀÈÌÒÙ ÂÊÎÔÛ ÃÑÕ ÄËÏÖÜŸ ÇŠ ==> all latin letters with diacritical marks + -- (with acute, grave, circumflex, tilde, umlaute, cedil and caron) + -- ΔΘΛΞΣΨΩ ==> few letters from greek alphabet + -- ĄĘŁŹŻ ==> few letters from polish alphabet + -- ЙЁ ==> two letters from cyrillic (russian) with diacritical marks + -- ЊЋЏ ==> few letters from serbian alphabet + -- ĂŞŢ ==> few letters from romanian alphabet + + -- create a case-insensitive domain: + create domain dom_ci as varchar(150) character set utf8 collate unicode_ci; + commit; + + -- create two case-insensitive columns: one via the domain, one directly: + recreate table t( + col_ci_dom dom_ci, + col_ci_dir varchar(150) character set utf8 collate unicode_ci + ); + commit; + + set list on; + + -- (Case 1) test = when casting to type of column col_ci_dir: + with q(a_lower, a_upper) as ( + select cast('áéíóúý àèìòù âêîôû ãñõ äëïöüÿ çš δθλξσψω ąęłźż йё њћџ ăşţ' as type of column t.col_ci_dir), + cast('ÁÉÍÓÚÝ ÀÈÌÒÙ ÂÊÎÔÛ ÃÑÕ ÄËÏÖÜŸ ÇŠ ΔΘΛΞΣΨΩ ĄĘŁŹŻ ЙЁ ЊЋЏ ĂŞŢ' as type of column t.col_ci_dir) + from rdb$database + ) + select 'case-1' msg, case when a_lower = a_upper then 1 else 0 end equal + from q; + + ------------------------------------------------------------------------------------ + + -- (Case 2) test = in domain dom_ci, using local vars in an executable block: + -- (With "type of dom_ci" and "type of column t.col_ci_dom", the result is also 1. + -- But with "type of column t.col_ci_dir", the result is 0.) + set term ^; + execute block returns (msg varchar(10), equal smallint) + as + -- this worked fine: + -- declare ü dom_ci = ; + -- declare y dom_ci = ; + -- "But with "type of column t.col_ci_dir", the result is 0." + declare x type of column t.col_ci_dir = 'áéíóúý àèìòù âêîôû ãñõ äëïöüÿ çš δθλξσψω ąęłźż йё њћџ ăşţ'; + declare y type of column t.col_ci_dir = 'ÁÉÍÓÚÝ ÀÈÌÒÙ ÂÊÎÔÛ ÃÑÕ ÄËÏÖÜŸ ÇŠ ΔΘΛΞΣΨΩ ĄĘŁŹŻ ЙЁ ЊЋЏ ĂŞŢ'; + begin + msg='case-2'; + equal = case when x = y then 1 else 0 end; + suspend; + end + ^ + set term ;^ + + + ------------------------------------------------------------------------------------ + + -- (Case 3) test = in domain dom_ci, using stored procedure with input params: + set term ^; + create or alter procedure selproc_dom(x dom_ci, y dom_ci) returns (equal smallint) + as + begin + equal = case when x = y then 1 else 0 end; + suspend; + end + ^ + set term ;^ + commit; + select 'case-3' msg, p.equal + from selproc_dom( + 'áéíóúý àèìòù âêîôû ãñõ äëïöüÿ çš δθλξσψω ąęłźż йё њћџ ăşţ', + 'ÁÉÍÓÚÝ ÀÈÌÒÙ ÂÊÎÔÛ ÃÑÕ ÄËÏÖÜŸ ÇŠ ΔΘΛΞΣΨΩ ĄĘŁŹŻ ЙЁ ЊЋЏ ĂŞŢ' + ) p; + + + --------------------------------------------------------------------------------------- + + set term ^; + create or alter procedure selproc_typeof_col_ci_dir( + x type of column t.col_ci_dir, + y type of column t.col_ci_dir + ) + returns (equal smallint) as + begin + equal = case when x = y then 1 else 0 end; + suspend; + end + ^ + set term ;^ + commit; + select 'case-4' msg, p.* + from selproc_typeof_col_ci_dir( + 'áéíóúý àèìòù âêîôû ãñõ äëïöüÿ çš δθλξσψω ąęłźż йё њћџ ăşţ', + 'ÁÉÍÓÚÝ ÀÈÌÒÙ ÂÊÎÔÛ ÃÑÕ ÄËÏÖÜŸ ÇŠ ΔΘΛΞΣΨΩ ĄĘŁŹŻ ЙЁ ЊЋЏ ĂŞŢ' + ) p; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG case-1 + EQUAL 1 + MSG case-2 + EQUAL 1 + MSG case-3 + EQUAL 1 + MSG case-4 + EQUAL 1 + """ + +@pytest.mark.version('>=3.0') +def test_core_3401_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3413.py b/tests/bugs/test_core_3413.py new file mode 100644 index 00000000..97dbc418 --- /dev/null +++ b/tests/bugs/test_core_3413.py @@ -0,0 +1,200 @@ +#coding:utf-8 +# +# id: bugs.core_3413 +# title: Improve diagnostics of internal trace errors +# decription: +# 1. Obtain engine_version from built-in context variable. +# 2. Make config for trace in proper format according to FB engine version, +# with adding invalid element 'foo' instead on boolean ('true' or 'false') +# 3. Launch trace session in separate child process using 'FBSVCMGR action_trace_start' +# 4. Run ISQL with trivial command in order trace session will register error in its log. +# 5. Stop trace session. Output its log with filtering only messages related to error. +# +# Checked on: WI-V2.5.5.26916 (SS, SC, CS); WI-V3.0.0.32008 (SS, SC, CS). Result: OK. +# ::: NB ::: +# Several delays (time.sleep) added in main thread because of OS buffering. Couldn't switch this buffering off. +# +# tracker_id: CORE-3413 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [('^((?!ERROR|ELEMENT).)*$', ''), ('ERROR CREATING TRACE SESSION.*', 'ERROR CREATING TRACE SESSION'), ('.*"FOO" IS NOT A VALID.*', '"FOO" IS NOT A VALID')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import subprocess +# from subprocess import Popen +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_file=db_conn.database_name +# +# # Obtain engine version, 2.5 or 3.0, for make trace config in appropriate format: +# engine = str(db_conn.engine_version) +# +# db_conn.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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# +# txt25 = '''# Trace config, format for 2.5. Generated auto, do not edit! +# +# enabled true +# time_threshold 0 +# +# # Value for this parameter was intentionally choosen *** INVALID *** +# log_statement_finish foo +# +# ''' +# +# # NOTES ABOUT TRACE CONFIG FOR 3.0: +# # 1) Header contains `database` clause in different format vs FB 2.5: its data must be enclosed with '{' '}' +# # 2) Name and value must be separated by EQUALITY sign ('=') in FB-3 trace.conf, otherwise we get runtime error: +# # element "<. . .>" have no attribute value set +# +# txt30 = '''# Trace config, format for 3.0. Generated auto, do not edit! +# database=%[\\\\\\\\/]bugs.core_3413.fdb +# { +# enabled = true +# time_threshold = 0 +# +# # Value for this parameter was intentionally choosen *** INVALID *** +# log_statement_finish = foo +# } +# ''' +# +# f_trccfg=open( os.path.join(context['temp_directory'],'tmp_trace_3413.cfg'), 'w') +# if engine.startswith('2.5'): +# f_trccfg.write(txt25) +# else: +# f_trccfg.write(txt30) +# flush_and_close( f_trccfg ) +# +# ##################################################### +# # Starting trace session in new child process (async.): +# +# f_trclog=open( os.path.join(context['temp_directory'],'tmp_trace_3413.log'), 'w') +# +# # Execute a child program in a new process, redirecting STDERR to the same target as of STDOUT: +# p_trace=Popen([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_start", +# "trc_cfg", f_trccfg.name], +# stdout=f_trclog, stderr=subprocess.STDOUT) +# +# # Wait! Trace session is initialized not instantly! +# time.sleep(1) +# +# sqltxt=''' +# set list on; +# select 1 as c from rdb$database; +# ''' +# +# runProgram('isql',[dsn,'-user',user_name,'-pas',user_password],sqltxt) +# +# # do NOT remove this otherwise trace log can contain only message about its start before being closed! +# time.sleep(3) +# +# ##################################################### +# # Getting ID of launched trace session and STOP it: +# +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# f_trclst=open( os.path.join(context['temp_directory'],'tmp_trace_3413.lst'), 'w') +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_list"], +# stdout=f_trclst, stderr=subprocess.STDOUT +# ) +# flush_and_close( f_trclst ) +# +# trcssn=0 +# with open( f_trclst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# f_trclst=open(f_trclst.name,'a') +# f_trclst.seek(0,2) +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_stop", +# "trc_id",trcssn], +# stdout=f_trclst, stderr=subprocess.STDOUT +# ) +# flush_and_close( f_trclst ) +# +# # Terminate child process of launched trace session (though it should already be killed): +# p_trace.terminate() +# flush_and_close( f_trclog ) +# +# with open( f_trclog.name,'r') as f: +# for line in f: +# print(line.upper()) +# +# # do NOT remove this delay otherwise get access error 'Windows 32' +# # (The process cannot access the file because it is being used by another process): +# time.sleep(1) +# +# # Cleanup +# ############# +# cleanup( [i.name for i in (f_trccfg, f_trclst, f_trclog)] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ERROR CREATING TRACE SESSION FOR DATABASE + ERROR WHILE PARSING TRACE CONFIGURATION + ELEMENT "LOG_STATEMENT_FINISH": "FOO" IS NOT A VALID + """ + +@pytest.mark.version('>=2.5.1') +@pytest.mark.xfail +def test_core_3413_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_3416.py b/tests/bugs/test_core_3416.py new file mode 100644 index 00000000..171e6d51 --- /dev/null +++ b/tests/bugs/test_core_3416.py @@ -0,0 +1,144 @@ +#coding:utf-8 +# +# id: bugs.core_3416 +# title: Inserting Käse into a CHARACTER SET ASCII column succeeds +# decription: +# 02-mar-2021. Re-implemented in order to have ability to run this test on Linux. +# Ttest 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 = WIN1252 and perform needed DML. +# Result will be redirected to .log which will be opened via codecs.open(...encoding='cp1252'). +# Its content will be converted to UTF8 for showing in expected_stdout. +# +# Checked on: +# * Windows: 4.0.0.2377, 3.0.8.33420, 2.5.9.27152 +# * Linux: 4.0.0.2377, 3.0.8.33415 +# +# tracker_id: CORE-3416 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('After line .*', ''), ('[\t ]+', ' ')] + +init_script_1 = """ + create table tascii(s_ascii varchar(10) character set ascii); + create table tlatin(s_latin varchar(10) character set latin1); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import codecs +# import subprocess +# import time +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql_txt=''' set names WIN1252; +# connect '%(dsn)s' user '%(user_name)s' password '%(user_password)s'; +# set list on; +# set count on; +# set echo on; +# insert into tascii values ('Käse'); +# select s_ascii from tascii; +# +# insert into tlatin values ('Käse'); +# select s_latin from tlatin; +# ''' % dict(globals(), **locals()) +# +# f_run_sql = open( os.path.join(context['temp_directory'], 'tmp_3416_win1252.sql'), 'w' ) +# f_run_sql.write( sql_txt.decode('utf8').encode('cp1252') ) +# flush_and_close( f_run_sql ) +# # result: file tmp_3416_win1252.sql is encoded in win1252 +# +# f_run_log = open( os.path.splitext(f_run_sql.name)[0]+'.log', 'w') +# subprocess.call( [ context['isql_path'], '-q', '-i', f_run_sql.name ], +# stdout = f_run_log, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_run_log ) # result: output will be encoded in win1252 +# +# with codecs.open(f_run_log.name, 'r', encoding='cp1252' ) as f: +# result_in_cp1252 = f.readlines() +# +# for i in result_in_cp1252: +# print( i.encode('utf8') ) +# +# # cleanup: +# ########### +# cleanup( (f_run_sql, f_run_log) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + insert into tascii values ('Käse'); + + Statement failed, SQLSTATE = 22018 + arithmetic exception, numeric overflow, or string truncation + -Cannot transliterate character between character sets + + Records affected: 0 + + select s_ascii from tascii; + Records affected: 0 + + insert into tlatin values ('Käse'); + Records affected: 1 + + select s_latin from tlatin; + S_LATIN Käse + Records affected: 1 + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_3416_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_3418.py b/tests/bugs/test_core_3418.py new file mode 100644 index 00000000..825b8f65 --- /dev/null +++ b/tests/bugs/test_core_3418.py @@ -0,0 +1,48 @@ +#coding:utf-8 +# +# id: bugs.core_3418 +# title: Database trigger created as INACTIVE is active +# decription: +# tracker_id: CORE-3418 +# min_versions: ['2.1.5'] +# versions: 2.1.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.5 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """ + set term ^ ; + create or alter trigger trg$start inactive on transaction start position 0 as + begin + rdb$set_context('USER_SESSION', 'TRANS_ID', current_transaction); + end + ^ + set term ; ^ + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select rdb$get_context('USER_SESSION', 'TRANS_ID') as ctx_var from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CTX_VAR + """ + +@pytest.mark.version('>=2.1.5') +def test_core_3418_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3419.py b/tests/bugs/test_core_3419.py new file mode 100644 index 00000000..feee006c --- /dev/null +++ b/tests/bugs/test_core_3419.py @@ -0,0 +1,78 @@ +#coding:utf-8 +# +# id: bugs.core_3419 +# title: Recurse leads to hangs/crash server +# decription: +# tracker_id: CORE-3419 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [('line: [0-9]+, col: [0-9]+', 'line: , col: ')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set autoddl off; + commit; + recreate table test(id int); + commit; + set term ^; + -- This trigger will fire 1001 times before exception raising: + create or alter trigger trg_trans_start + active on transaction start position 0 + as + begin + in autonomous transaction do + insert into test(id) values(1); + end + ^ + set term ;^ + commit; + set transaction; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + 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('>=2.5.1') +def test_core_3419_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_3420.py b/tests/bugs/test_core_3420.py new file mode 100644 index 00000000..9ba19dbf --- /dev/null +++ b/tests/bugs/test_core_3420.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: bugs.core_3420 +# title: BOOLEAN not present in system table RDB$TYPES +# decription: +# tracker_id: CORE-3420 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select + rdb$field_name, + rdb$type, + rdb$type_name, + rdb$system_flag + from rdb$types t + where upper(t.rdb$type_name) = upper('boolean') + order by t.rdb$field_name; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 23 + RDB$TYPE_NAME BOOLEAN + RDB$SYSTEM_FLAG 1 + RDB$FIELD_NAME RDB$FUNCTION_TYPE + RDB$TYPE 1 + RDB$TYPE_NAME BOOLEAN + RDB$SYSTEM_FLAG 1 + """ + +@pytest.mark.version('>=3.0') +def test_core_3420_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3421.py b/tests/bugs/test_core_3421.py new file mode 100644 index 00000000..c29a3773 --- /dev/null +++ b/tests/bugs/test_core_3421.py @@ -0,0 +1,78 @@ +#coding:utf-8 +# +# id: bugs.core_3421 +# title: [FB3] AV with "UPDATE OR INSERT" +# decription: +# tracker_id: CORE-3421 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!sqltype|DTS_DIFF).)*$', ''), ('[ ]+', ' '), ('[\t]*', ' ')] + +init_script_1 = """ + create or alter procedure sp_test as begin end; + commit; + 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 + 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; + end + ^ + set term ;^ + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + 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) + as + begin + execute procedure sp_test(1, rpad('',512,'9876543210mnbvcxzasdfghjklpoiuytrewq')) returning_values o_id, o_s01; + suspend; + end + ^ + set term ;^ + execute procedure sp_test(1, rpad('',512,'abcdefghjklmnopqrstuwwxyz012345678')); + select * from sp_test(1, rpad('',512,'0123456789abcdefghjklmnopqrstuwwxyz')); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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 + 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 + 02: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 512 charset: 0 NONE + """ + +@pytest.mark.version('>=3.0') +def test_core_3421_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3423.py b/tests/bugs/test_core_3423.py new file mode 100644 index 00000000..58727a25 --- /dev/null +++ b/tests/bugs/test_core_3423.py @@ -0,0 +1,58 @@ +#coding:utf-8 +# +# id: bugs.core_3423 +# title: [FB3] Wrong RDB$PARAMETER_MECHANISM +# decription: +# tracker_id: CORE-3423 +# min_versions: ['2.1.7'] +# versions: 2.1.7 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create or alter procedure sp_test(IN_ARG INTEGER) returns (OUT_ARG INTEGER) as + begin + OUT_ARG=IN_ARG; + end + ^ + set term ;^ + commit; + + set list on; + -- NB: engine treats nulls and zeroes as the same value, so it is enough to check that + -- parameter mechanism is either null or zero only: + select + pp.rdb$parameter_name p_name + ,iif( coalesce(pp.rdb$parameter_mechanism,0) = 0, 'ZERO_OR_NULL', 'BAD_VALUE' ) p_mechanism + from rdb$procedure_parameters pp + where pp.rdb$procedure_name = upper('SP_TEST'); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + P_NAME IN_ARG + P_MECHANISM ZERO_OR_NULL + + P_NAME OUT_ARG + P_MECHANISM ZERO_OR_NULL + """ + +@pytest.mark.version('>=2.1.7') +def test_core_3423_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3427.py b/tests/bugs/test_core_3427.py new file mode 100644 index 00000000..6d0dbbd4 --- /dev/null +++ b/tests/bugs/test_core_3427.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_3427 +# title: Server crashing with UTF8 blobs +# decription: +# tracker_id: CORE-3427 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table tbl (blob_field blob sub_type text character set utf8 collate unicode_ci_ai); + -- See ticket: seems that this crash depended on concrete data, so it was decided to copy these text from ticket: + insert into tbl values ('крупнейший европейский журнал о компьютерах. Вышел на рынок компьютерных изданий с уникальной концепцией и предназначен для людей, которые интересуются компьютерами, Интернетом, средствами телекоммуникаций, аудио-, видео- и фототехникой. Каждые две недели читателям предлагаются новости индустрии, тесты оборудования и программ, обучающие курсы и практические советы. Издание интересно как новичкам, так и опытным пользователям.'); + commit; + -- Confirmed crash on 2.5.0, fine on 2.5.1 and later (02.04.2015): + set list on; + select count(*) cnt + from tbl + where blob_field like '%test%'; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CNT 0 + """ + +@pytest.mark.version('>=2.5.1') +def test_core_3427_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3431.py b/tests/bugs/test_core_3431.py new file mode 100644 index 00000000..057b0483 --- /dev/null +++ b/tests/bugs/test_core_3431.py @@ -0,0 +1,95 @@ +#coding:utf-8 +# +# id: bugs.core_3431 +# title: ISQL pads UTF-8 data incorrectly +# decription: +# tracker_id: CORE-3431 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create or alter procedure p1 returns ( + c1 char(5) character set utf8, + c2 char(10) character set utf8, + vc1 varchar(5) character set utf8, + vc2 varchar(10) character set utf8 + ) + as + begin + vc1 = '12345'; + c1 = vc1; + c2 = vc1; + vc2 = vc1; + suspend; + + vc1 = 'áé'; + c1 = vc1; + c2 = vc1; + vc2 = vc1; + suspend; + + vc1 = '123'; + c1 = vc1; + c2 = vc1; + vc2 = vc1; + suspend; + + vc1 = '12345'; + c1 = vc1; + c2 = vc1; + vc2 = vc1; + suspend; + + vc1 = '1234'; + c1 = vc1; + c2 = vc1; + vc2 = vc1; + suspend; + + vc1 = 'áéíóú'; + c1 = vc1; + c2 = vc1; + vc2 = vc1; + suspend; + end + ^ + set term ;^ + commit; + + -- Padding in WI-T3.0.0.31767 looks OK: checked output on NotePad++ 6.6.9 + select * from p1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + C1 C2 VC1 VC2 + ====== ========== ====== ========== + 12345 12345 12345 12345 + áé áé áé áé + 123 123 123 123 + 12345 12345 12345 12345 + 1234 1234 1234 1234 + áéíóú áéíóú áéíóú áéíóú + """ + +@pytest.mark.version('>=3.0') +def test_core_3431_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3435.py b/tests/bugs/test_core_3435.py new file mode 100644 index 00000000..2dbc5a47 --- /dev/null +++ b/tests/bugs/test_core_3435.py @@ -0,0 +1,1784 @@ +#coding:utf-8 +# +# id: bugs.core_3435 +# title: Lateral derived tables +# decription: +# Test is based on public database from sql-ex.ru and several example queries from sql-tutorial.ru: +# http://www.sql-tutorial.ru/ru/book_cross_apply/page2.html +# +# Example queries are published here with kind permission of Sergey Moiseenko, 07.04.2020 11:46. +# ::: NB ::: +# This is INITIAL test of LATERAL-JOIN functional. Additional examples will be implemented later. +# +# Checked on 4.0.0.1865 SS: 1.360s. +# +# tracker_id: CORE-3435 +# min_versions: [] +# versions: 4.0.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('===.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='sql-ex-open-data.fbk', init=init_script_1) + +test_script_1 = """ + set term ^; + create or alter function fn_get_next_laptop_model(a_code type of column laptop.code ) returns varchar(50) deterministic as + begin + return ( select p.model from laptop p where p.code > :a_code order by p.code rows 1 ); + end + ^ + create or alter function fn_get_next_laptop_speed(a_code type of column laptop.code ) returns int deterministic as + begin + return ( select p.speed from laptop p where p.code > :a_code order by p.code rows 1 ); + end + ^ + create or alter function fn_get_next_laptop_price(a_code type of column laptop.code ) returns numeric(12,2) deterministic as + begin + return ( select p.price from laptop p where p.code > :a_code order by p.code rows 1 ); + end + ^ + set term ;^ + commit; + + -------------------------------- + + select 'test-1' as msg, l1.*, x.* + from laptop l1 + cross join lateral + ( + select max(price) max_price, min(price) min_price + from laptop l2 + join product p1 on l2.model = p1.model + where p1.maker = + ( + select p2.maker + from product p2 + where p2.model = l1.model + ) + ) x; + + ---------------------- + + select 'test-2' as msg, l1.code as curr_core, x.code as lead_code + from laptop l1 + left join lateral + ( + select first 1 l2.* + from laptop l2 + where + l1.model < l2.model + or (l1.model = l2.model and l1.code < l2.code) + order by l2.model, l2.code + ) x on 1=1 + order by l1.model + ; + + -------------------------- + + select 'test-3' as msg, x.* + from + ( + select distinct + p.type + from product p + ) pr1 + cross join lateral + ( + select first 3 pr2.* + from product pr2 + where pr1.type=pr2.type + order by pr2.model + ) x; + + --------------------------- + + -- Check ability to use in LATERAL datasource procedural objects instead of usual tables: + + select 'test-4' as msg, p.code, p.model, p.speed, p.price, x.* + from laptop p + left join lateral ( + select + fn_get_next_laptop_model(p.code) as model_for_next_code + ,fn_get_next_laptop_speed(p.code) as speed_for_next_code + ,fn_get_next_laptop_price(p.code) as price_for_next_code + from rdb$database + ) x on 1=1; + + ---------------------------- + + -- Check ability to use recursive datasource as LATERAL: + + with recursive + r1 as ( + select 1 i, cast(1 as decfloat(34)) f from rdb$database + union all + select r.i+1, r.f * (r.i+1) from r1 as r where r.i < 10 + ) + --select * from r1 + + select 'test-5' as msg, r1.i, sum( rx.xf ) factorials_running_total + from r1 + inner join lateral ( + select rx.f as xf + from r1 as rx + where rx.i <= r1.i + ) rx + on true + group by 1,2 + order by 3 desc; + + ------------------------------ + + -- Check ability to run query with 255 contexts. + + /****************************************************** + batch for generating this query: + ################################ + @echo off + setlocal enabledelayedexpansion enableextensions + + set sql=%~dpn0.tmp.sql + del !sql! 2>nul + set n_max=254 + + ( + echo set list on; + echo select + for /l %%i in (0,1,!n_max!) do ( + if %%i EQU 0 ( + echo. r%%i.i%%i + ) else ( + echo. ,r%%i.i%%i + ) + ) + echo from ( + echo select 1 i0 + echo from rdb$database r0 + echo ^) r0 + ) >>!sql! + + + for /l %%i in (0,1,!n_max!) do ( + set p=%%i + set /a x=%%i+1 + ( + echo cross join lateral ( + echo select r!p!.i!p!+1 as i!x! + echo from rdb$database + echo ^) r!x! + ) >>!sql! + ) + echo ;>>!sql! + ***************************************************/ + + set list on; + select + r0.i0 + ,r1.i1 + ,r2.i2 + ,r3.i3 + ,r4.i4 + ,r5.i5 + ,r6.i6 + ,r7.i7 + ,r8.i8 + ,r9.i9 + ,r10.i10 + ,r11.i11 + ,r12.i12 + ,r13.i13 + ,r14.i14 + ,r15.i15 + ,r16.i16 + ,r17.i17 + ,r18.i18 + ,r19.i19 + ,r20.i20 + ,r21.i21 + ,r22.i22 + ,r23.i23 + ,r24.i24 + ,r25.i25 + ,r26.i26 + ,r27.i27 + ,r28.i28 + ,r29.i29 + ,r30.i30 + ,r31.i31 + ,r32.i32 + ,r33.i33 + ,r34.i34 + ,r35.i35 + ,r36.i36 + ,r37.i37 + ,r38.i38 + ,r39.i39 + ,r40.i40 + ,r41.i41 + ,r42.i42 + ,r43.i43 + ,r44.i44 + ,r45.i45 + ,r46.i46 + ,r47.i47 + ,r48.i48 + ,r49.i49 + ,r50.i50 + ,r51.i51 + ,r52.i52 + ,r53.i53 + ,r54.i54 + ,r55.i55 + ,r56.i56 + ,r57.i57 + ,r58.i58 + ,r59.i59 + ,r60.i60 + ,r61.i61 + ,r62.i62 + ,r63.i63 + ,r64.i64 + ,r65.i65 + ,r66.i66 + ,r67.i67 + ,r68.i68 + ,r69.i69 + ,r70.i70 + ,r71.i71 + ,r72.i72 + ,r73.i73 + ,r74.i74 + ,r75.i75 + ,r76.i76 + ,r77.i77 + ,r78.i78 + ,r79.i79 + ,r80.i80 + ,r81.i81 + ,r82.i82 + ,r83.i83 + ,r84.i84 + ,r85.i85 + ,r86.i86 + ,r87.i87 + ,r88.i88 + ,r89.i89 + ,r90.i90 + ,r91.i91 + ,r92.i92 + ,r93.i93 + ,r94.i94 + ,r95.i95 + ,r96.i96 + ,r97.i97 + ,r98.i98 + ,r99.i99 + ,r100.i100 + ,r101.i101 + ,r102.i102 + ,r103.i103 + ,r104.i104 + ,r105.i105 + ,r106.i106 + ,r107.i107 + ,r108.i108 + ,r109.i109 + ,r110.i110 + ,r111.i111 + ,r112.i112 + ,r113.i113 + ,r114.i114 + ,r115.i115 + ,r116.i116 + ,r117.i117 + ,r118.i118 + ,r119.i119 + ,r120.i120 + ,r121.i121 + ,r122.i122 + ,r123.i123 + ,r124.i124 + ,r125.i125 + ,r126.i126 + ,r127.i127 + ,r128.i128 + ,r129.i129 + ,r130.i130 + ,r131.i131 + ,r132.i132 + ,r133.i133 + ,r134.i134 + ,r135.i135 + ,r136.i136 + ,r137.i137 + ,r138.i138 + ,r139.i139 + ,r140.i140 + ,r141.i141 + ,r142.i142 + ,r143.i143 + ,r144.i144 + ,r145.i145 + ,r146.i146 + ,r147.i147 + ,r148.i148 + ,r149.i149 + ,r150.i150 + ,r151.i151 + ,r152.i152 + ,r153.i153 + ,r154.i154 + ,r155.i155 + ,r156.i156 + ,r157.i157 + ,r158.i158 + ,r159.i159 + ,r160.i160 + ,r161.i161 + ,r162.i162 + ,r163.i163 + ,r164.i164 + ,r165.i165 + ,r166.i166 + ,r167.i167 + ,r168.i168 + ,r169.i169 + ,r170.i170 + ,r171.i171 + ,r172.i172 + ,r173.i173 + ,r174.i174 + ,r175.i175 + ,r176.i176 + ,r177.i177 + ,r178.i178 + ,r179.i179 + ,r180.i180 + ,r181.i181 + ,r182.i182 + ,r183.i183 + ,r184.i184 + ,r185.i185 + ,r186.i186 + ,r187.i187 + ,r188.i188 + ,r189.i189 + ,r190.i190 + ,r191.i191 + ,r192.i192 + ,r193.i193 + ,r194.i194 + ,r195.i195 + ,r196.i196 + ,r197.i197 + ,r198.i198 + ,r199.i199 + ,r200.i200 + ,r201.i201 + ,r202.i202 + ,r203.i203 + ,r204.i204 + ,r205.i205 + ,r206.i206 + ,r207.i207 + ,r208.i208 + ,r209.i209 + ,r210.i210 + ,r211.i211 + ,r212.i212 + ,r213.i213 + ,r214.i214 + ,r215.i215 + ,r216.i216 + ,r217.i217 + ,r218.i218 + ,r219.i219 + ,r220.i220 + ,r221.i221 + ,r222.i222 + ,r223.i223 + ,r224.i224 + ,r225.i225 + ,r226.i226 + ,r227.i227 + ,r228.i228 + ,r229.i229 + ,r230.i230 + ,r231.i231 + ,r232.i232 + ,r233.i233 + ,r234.i234 + ,r235.i235 + ,r236.i236 + ,r237.i237 + ,r238.i238 + ,r239.i239 + ,r240.i240 + ,r241.i241 + ,r242.i242 + ,r243.i243 + ,r244.i244 + ,r245.i245 + ,r246.i246 + ,r247.i247 + ,r248.i248 + ,r249.i249 + ,r250.i250 + ,r251.i251 + ,r252.i252 + ,r253.i253 + ,r254.i254 + from ( + select 1 i0 + from rdb$database r0 + ) r0 + cross join lateral ( + select r0.i0+1 as i1 + from rdb$database + ) r1 + cross join lateral ( + select r1.i1+1 as i2 + from rdb$database + ) r2 + cross join lateral ( + select r2.i2+1 as i3 + from rdb$database + ) r3 + cross join lateral ( + select r3.i3+1 as i4 + from rdb$database + ) r4 + cross join lateral ( + select r4.i4+1 as i5 + from rdb$database + ) r5 + cross join lateral ( + select r5.i5+1 as i6 + from rdb$database + ) r6 + cross join lateral ( + select r6.i6+1 as i7 + from rdb$database + ) r7 + cross join lateral ( + select r7.i7+1 as i8 + from rdb$database + ) r8 + cross join lateral ( + select r8.i8+1 as i9 + from rdb$database + ) r9 + cross join lateral ( + select r9.i9+1 as i10 + from rdb$database + ) r10 + cross join lateral ( + select r10.i10+1 as i11 + from rdb$database + ) r11 + cross join lateral ( + select r11.i11+1 as i12 + from rdb$database + ) r12 + cross join lateral ( + select r12.i12+1 as i13 + from rdb$database + ) r13 + cross join lateral ( + select r13.i13+1 as i14 + from rdb$database + ) r14 + cross join lateral ( + select r14.i14+1 as i15 + from rdb$database + ) r15 + cross join lateral ( + select r15.i15+1 as i16 + from rdb$database + ) r16 + cross join lateral ( + select r16.i16+1 as i17 + from rdb$database + ) r17 + cross join lateral ( + select r17.i17+1 as i18 + from rdb$database + ) r18 + cross join lateral ( + select r18.i18+1 as i19 + from rdb$database + ) r19 + cross join lateral ( + select r19.i19+1 as i20 + from rdb$database + ) r20 + cross join lateral ( + select r20.i20+1 as i21 + from rdb$database + ) r21 + cross join lateral ( + select r21.i21+1 as i22 + from rdb$database + ) r22 + cross join lateral ( + select r22.i22+1 as i23 + from rdb$database + ) r23 + cross join lateral ( + select r23.i23+1 as i24 + from rdb$database + ) r24 + cross join lateral ( + select r24.i24+1 as i25 + from rdb$database + ) r25 + cross join lateral ( + select r25.i25+1 as i26 + from rdb$database + ) r26 + cross join lateral ( + select r26.i26+1 as i27 + from rdb$database + ) r27 + cross join lateral ( + select r27.i27+1 as i28 + from rdb$database + ) r28 + cross join lateral ( + select r28.i28+1 as i29 + from rdb$database + ) r29 + cross join lateral ( + select r29.i29+1 as i30 + from rdb$database + ) r30 + cross join lateral ( + select r30.i30+1 as i31 + from rdb$database + ) r31 + cross join lateral ( + select r31.i31+1 as i32 + from rdb$database + ) r32 + cross join lateral ( + select r32.i32+1 as i33 + from rdb$database + ) r33 + cross join lateral ( + select r33.i33+1 as i34 + from rdb$database + ) r34 + cross join lateral ( + select r34.i34+1 as i35 + from rdb$database + ) r35 + cross join lateral ( + select r35.i35+1 as i36 + from rdb$database + ) r36 + cross join lateral ( + select r36.i36+1 as i37 + from rdb$database + ) r37 + cross join lateral ( + select r37.i37+1 as i38 + from rdb$database + ) r38 + cross join lateral ( + select r38.i38+1 as i39 + from rdb$database + ) r39 + cross join lateral ( + select r39.i39+1 as i40 + from rdb$database + ) r40 + cross join lateral ( + select r40.i40+1 as i41 + from rdb$database + ) r41 + cross join lateral ( + select r41.i41+1 as i42 + from rdb$database + ) r42 + cross join lateral ( + select r42.i42+1 as i43 + from rdb$database + ) r43 + cross join lateral ( + select r43.i43+1 as i44 + from rdb$database + ) r44 + cross join lateral ( + select r44.i44+1 as i45 + from rdb$database + ) r45 + cross join lateral ( + select r45.i45+1 as i46 + from rdb$database + ) r46 + cross join lateral ( + select r46.i46+1 as i47 + from rdb$database + ) r47 + cross join lateral ( + select r47.i47+1 as i48 + from rdb$database + ) r48 + cross join lateral ( + select r48.i48+1 as i49 + from rdb$database + ) r49 + cross join lateral ( + select r49.i49+1 as i50 + from rdb$database + ) r50 + cross join lateral ( + select r50.i50+1 as i51 + from rdb$database + ) r51 + cross join lateral ( + select r51.i51+1 as i52 + from rdb$database + ) r52 + cross join lateral ( + select r52.i52+1 as i53 + from rdb$database + ) r53 + cross join lateral ( + select r53.i53+1 as i54 + from rdb$database + ) r54 + cross join lateral ( + select r54.i54+1 as i55 + from rdb$database + ) r55 + cross join lateral ( + select r55.i55+1 as i56 + from rdb$database + ) r56 + cross join lateral ( + select r56.i56+1 as i57 + from rdb$database + ) r57 + cross join lateral ( + select r57.i57+1 as i58 + from rdb$database + ) r58 + cross join lateral ( + select r58.i58+1 as i59 + from rdb$database + ) r59 + cross join lateral ( + select r59.i59+1 as i60 + from rdb$database + ) r60 + cross join lateral ( + select r60.i60+1 as i61 + from rdb$database + ) r61 + cross join lateral ( + select r61.i61+1 as i62 + from rdb$database + ) r62 + cross join lateral ( + select r62.i62+1 as i63 + from rdb$database + ) r63 + cross join lateral ( + select r63.i63+1 as i64 + from rdb$database + ) r64 + cross join lateral ( + select r64.i64+1 as i65 + from rdb$database + ) r65 + cross join lateral ( + select r65.i65+1 as i66 + from rdb$database + ) r66 + cross join lateral ( + select r66.i66+1 as i67 + from rdb$database + ) r67 + cross join lateral ( + select r67.i67+1 as i68 + from rdb$database + ) r68 + cross join lateral ( + select r68.i68+1 as i69 + from rdb$database + ) r69 + cross join lateral ( + select r69.i69+1 as i70 + from rdb$database + ) r70 + cross join lateral ( + select r70.i70+1 as i71 + from rdb$database + ) r71 + cross join lateral ( + select r71.i71+1 as i72 + from rdb$database + ) r72 + cross join lateral ( + select r72.i72+1 as i73 + from rdb$database + ) r73 + cross join lateral ( + select r73.i73+1 as i74 + from rdb$database + ) r74 + cross join lateral ( + select r74.i74+1 as i75 + from rdb$database + ) r75 + cross join lateral ( + select r75.i75+1 as i76 + from rdb$database + ) r76 + cross join lateral ( + select r76.i76+1 as i77 + from rdb$database + ) r77 + cross join lateral ( + select r77.i77+1 as i78 + from rdb$database + ) r78 + cross join lateral ( + select r78.i78+1 as i79 + from rdb$database + ) r79 + cross join lateral ( + select r79.i79+1 as i80 + from rdb$database + ) r80 + cross join lateral ( + select r80.i80+1 as i81 + from rdb$database + ) r81 + cross join lateral ( + select r81.i81+1 as i82 + from rdb$database + ) r82 + cross join lateral ( + select r82.i82+1 as i83 + from rdb$database + ) r83 + cross join lateral ( + select r83.i83+1 as i84 + from rdb$database + ) r84 + cross join lateral ( + select r84.i84+1 as i85 + from rdb$database + ) r85 + cross join lateral ( + select r85.i85+1 as i86 + from rdb$database + ) r86 + cross join lateral ( + select r86.i86+1 as i87 + from rdb$database + ) r87 + cross join lateral ( + select r87.i87+1 as i88 + from rdb$database + ) r88 + cross join lateral ( + select r88.i88+1 as i89 + from rdb$database + ) r89 + cross join lateral ( + select r89.i89+1 as i90 + from rdb$database + ) r90 + cross join lateral ( + select r90.i90+1 as i91 + from rdb$database + ) r91 + cross join lateral ( + select r91.i91+1 as i92 + from rdb$database + ) r92 + cross join lateral ( + select r92.i92+1 as i93 + from rdb$database + ) r93 + cross join lateral ( + select r93.i93+1 as i94 + from rdb$database + ) r94 + cross join lateral ( + select r94.i94+1 as i95 + from rdb$database + ) r95 + cross join lateral ( + select r95.i95+1 as i96 + from rdb$database + ) r96 + cross join lateral ( + select r96.i96+1 as i97 + from rdb$database + ) r97 + cross join lateral ( + select r97.i97+1 as i98 + from rdb$database + ) r98 + cross join lateral ( + select r98.i98+1 as i99 + from rdb$database + ) r99 + cross join lateral ( + select r99.i99+1 as i100 + from rdb$database + ) r100 + cross join lateral ( + select r100.i100+1 as i101 + from rdb$database + ) r101 + cross join lateral ( + select r101.i101+1 as i102 + from rdb$database + ) r102 + cross join lateral ( + select r102.i102+1 as i103 + from rdb$database + ) r103 + cross join lateral ( + select r103.i103+1 as i104 + from rdb$database + ) r104 + cross join lateral ( + select r104.i104+1 as i105 + from rdb$database + ) r105 + cross join lateral ( + select r105.i105+1 as i106 + from rdb$database + ) r106 + cross join lateral ( + select r106.i106+1 as i107 + from rdb$database + ) r107 + cross join lateral ( + select r107.i107+1 as i108 + from rdb$database + ) r108 + cross join lateral ( + select r108.i108+1 as i109 + from rdb$database + ) r109 + cross join lateral ( + select r109.i109+1 as i110 + from rdb$database + ) r110 + cross join lateral ( + select r110.i110+1 as i111 + from rdb$database + ) r111 + cross join lateral ( + select r111.i111+1 as i112 + from rdb$database + ) r112 + cross join lateral ( + select r112.i112+1 as i113 + from rdb$database + ) r113 + cross join lateral ( + select r113.i113+1 as i114 + from rdb$database + ) r114 + cross join lateral ( + select r114.i114+1 as i115 + from rdb$database + ) r115 + cross join lateral ( + select r115.i115+1 as i116 + from rdb$database + ) r116 + cross join lateral ( + select r116.i116+1 as i117 + from rdb$database + ) r117 + cross join lateral ( + select r117.i117+1 as i118 + from rdb$database + ) r118 + cross join lateral ( + select r118.i118+1 as i119 + from rdb$database + ) r119 + cross join lateral ( + select r119.i119+1 as i120 + from rdb$database + ) r120 + cross join lateral ( + select r120.i120+1 as i121 + from rdb$database + ) r121 + cross join lateral ( + select r121.i121+1 as i122 + from rdb$database + ) r122 + cross join lateral ( + select r122.i122+1 as i123 + from rdb$database + ) r123 + cross join lateral ( + select r123.i123+1 as i124 + from rdb$database + ) r124 + cross join lateral ( + select r124.i124+1 as i125 + from rdb$database + ) r125 + cross join lateral ( + select r125.i125+1 as i126 + from rdb$database + ) r126 + cross join lateral ( + select r126.i126+1 as i127 + from rdb$database + ) r127 + cross join lateral ( + select r127.i127+1 as i128 + from rdb$database + ) r128 + cross join lateral ( + select r128.i128+1 as i129 + from rdb$database + ) r129 + cross join lateral ( + select r129.i129+1 as i130 + from rdb$database + ) r130 + cross join lateral ( + select r130.i130+1 as i131 + from rdb$database + ) r131 + cross join lateral ( + select r131.i131+1 as i132 + from rdb$database + ) r132 + cross join lateral ( + select r132.i132+1 as i133 + from rdb$database + ) r133 + cross join lateral ( + select r133.i133+1 as i134 + from rdb$database + ) r134 + cross join lateral ( + select r134.i134+1 as i135 + from rdb$database + ) r135 + cross join lateral ( + select r135.i135+1 as i136 + from rdb$database + ) r136 + cross join lateral ( + select r136.i136+1 as i137 + from rdb$database + ) r137 + cross join lateral ( + select r137.i137+1 as i138 + from rdb$database + ) r138 + cross join lateral ( + select r138.i138+1 as i139 + from rdb$database + ) r139 + cross join lateral ( + select r139.i139+1 as i140 + from rdb$database + ) r140 + cross join lateral ( + select r140.i140+1 as i141 + from rdb$database + ) r141 + cross join lateral ( + select r141.i141+1 as i142 + from rdb$database + ) r142 + cross join lateral ( + select r142.i142+1 as i143 + from rdb$database + ) r143 + cross join lateral ( + select r143.i143+1 as i144 + from rdb$database + ) r144 + cross join lateral ( + select r144.i144+1 as i145 + from rdb$database + ) r145 + cross join lateral ( + select r145.i145+1 as i146 + from rdb$database + ) r146 + cross join lateral ( + select r146.i146+1 as i147 + from rdb$database + ) r147 + cross join lateral ( + select r147.i147+1 as i148 + from rdb$database + ) r148 + cross join lateral ( + select r148.i148+1 as i149 + from rdb$database + ) r149 + cross join lateral ( + select r149.i149+1 as i150 + from rdb$database + ) r150 + cross join lateral ( + select r150.i150+1 as i151 + from rdb$database + ) r151 + cross join lateral ( + select r151.i151+1 as i152 + from rdb$database + ) r152 + cross join lateral ( + select r152.i152+1 as i153 + from rdb$database + ) r153 + cross join lateral ( + select r153.i153+1 as i154 + from rdb$database + ) r154 + cross join lateral ( + select r154.i154+1 as i155 + from rdb$database + ) r155 + cross join lateral ( + select r155.i155+1 as i156 + from rdb$database + ) r156 + cross join lateral ( + select r156.i156+1 as i157 + from rdb$database + ) r157 + cross join lateral ( + select r157.i157+1 as i158 + from rdb$database + ) r158 + cross join lateral ( + select r158.i158+1 as i159 + from rdb$database + ) r159 + cross join lateral ( + select r159.i159+1 as i160 + from rdb$database + ) r160 + cross join lateral ( + select r160.i160+1 as i161 + from rdb$database + ) r161 + cross join lateral ( + select r161.i161+1 as i162 + from rdb$database + ) r162 + cross join lateral ( + select r162.i162+1 as i163 + from rdb$database + ) r163 + cross join lateral ( + select r163.i163+1 as i164 + from rdb$database + ) r164 + cross join lateral ( + select r164.i164+1 as i165 + from rdb$database + ) r165 + cross join lateral ( + select r165.i165+1 as i166 + from rdb$database + ) r166 + cross join lateral ( + select r166.i166+1 as i167 + from rdb$database + ) r167 + cross join lateral ( + select r167.i167+1 as i168 + from rdb$database + ) r168 + cross join lateral ( + select r168.i168+1 as i169 + from rdb$database + ) r169 + cross join lateral ( + select r169.i169+1 as i170 + from rdb$database + ) r170 + cross join lateral ( + select r170.i170+1 as i171 + from rdb$database + ) r171 + cross join lateral ( + select r171.i171+1 as i172 + from rdb$database + ) r172 + cross join lateral ( + select r172.i172+1 as i173 + from rdb$database + ) r173 + cross join lateral ( + select r173.i173+1 as i174 + from rdb$database + ) r174 + cross join lateral ( + select r174.i174+1 as i175 + from rdb$database + ) r175 + cross join lateral ( + select r175.i175+1 as i176 + from rdb$database + ) r176 + cross join lateral ( + select r176.i176+1 as i177 + from rdb$database + ) r177 + cross join lateral ( + select r177.i177+1 as i178 + from rdb$database + ) r178 + cross join lateral ( + select r178.i178+1 as i179 + from rdb$database + ) r179 + cross join lateral ( + select r179.i179+1 as i180 + from rdb$database + ) r180 + cross join lateral ( + select r180.i180+1 as i181 + from rdb$database + ) r181 + cross join lateral ( + select r181.i181+1 as i182 + from rdb$database + ) r182 + cross join lateral ( + select r182.i182+1 as i183 + from rdb$database + ) r183 + cross join lateral ( + select r183.i183+1 as i184 + from rdb$database + ) r184 + cross join lateral ( + select r184.i184+1 as i185 + from rdb$database + ) r185 + cross join lateral ( + select r185.i185+1 as i186 + from rdb$database + ) r186 + cross join lateral ( + select r186.i186+1 as i187 + from rdb$database + ) r187 + cross join lateral ( + select r187.i187+1 as i188 + from rdb$database + ) r188 + cross join lateral ( + select r188.i188+1 as i189 + from rdb$database + ) r189 + cross join lateral ( + select r189.i189+1 as i190 + from rdb$database + ) r190 + cross join lateral ( + select r190.i190+1 as i191 + from rdb$database + ) r191 + cross join lateral ( + select r191.i191+1 as i192 + from rdb$database + ) r192 + cross join lateral ( + select r192.i192+1 as i193 + from rdb$database + ) r193 + cross join lateral ( + select r193.i193+1 as i194 + from rdb$database + ) r194 + cross join lateral ( + select r194.i194+1 as i195 + from rdb$database + ) r195 + cross join lateral ( + select r195.i195+1 as i196 + from rdb$database + ) r196 + cross join lateral ( + select r196.i196+1 as i197 + from rdb$database + ) r197 + cross join lateral ( + select r197.i197+1 as i198 + from rdb$database + ) r198 + cross join lateral ( + select r198.i198+1 as i199 + from rdb$database + ) r199 + cross join lateral ( + select r199.i199+1 as i200 + from rdb$database + ) r200 + cross join lateral ( + select r200.i200+1 as i201 + from rdb$database + ) r201 + cross join lateral ( + select r201.i201+1 as i202 + from rdb$database + ) r202 + cross join lateral ( + select r202.i202+1 as i203 + from rdb$database + ) r203 + cross join lateral ( + select r203.i203+1 as i204 + from rdb$database + ) r204 + cross join lateral ( + select r204.i204+1 as i205 + from rdb$database + ) r205 + cross join lateral ( + select r205.i205+1 as i206 + from rdb$database + ) r206 + cross join lateral ( + select r206.i206+1 as i207 + from rdb$database + ) r207 + cross join lateral ( + select r207.i207+1 as i208 + from rdb$database + ) r208 + cross join lateral ( + select r208.i208+1 as i209 + from rdb$database + ) r209 + cross join lateral ( + select r209.i209+1 as i210 + from rdb$database + ) r210 + cross join lateral ( + select r210.i210+1 as i211 + from rdb$database + ) r211 + cross join lateral ( + select r211.i211+1 as i212 + from rdb$database + ) r212 + cross join lateral ( + select r212.i212+1 as i213 + from rdb$database + ) r213 + cross join lateral ( + select r213.i213+1 as i214 + from rdb$database + ) r214 + cross join lateral ( + select r214.i214+1 as i215 + from rdb$database + ) r215 + cross join lateral ( + select r215.i215+1 as i216 + from rdb$database + ) r216 + cross join lateral ( + select r216.i216+1 as i217 + from rdb$database + ) r217 + cross join lateral ( + select r217.i217+1 as i218 + from rdb$database + ) r218 + cross join lateral ( + select r218.i218+1 as i219 + from rdb$database + ) r219 + cross join lateral ( + select r219.i219+1 as i220 + from rdb$database + ) r220 + cross join lateral ( + select r220.i220+1 as i221 + from rdb$database + ) r221 + cross join lateral ( + select r221.i221+1 as i222 + from rdb$database + ) r222 + cross join lateral ( + select r222.i222+1 as i223 + from rdb$database + ) r223 + cross join lateral ( + select r223.i223+1 as i224 + from rdb$database + ) r224 + cross join lateral ( + select r224.i224+1 as i225 + from rdb$database + ) r225 + cross join lateral ( + select r225.i225+1 as i226 + from rdb$database + ) r226 + cross join lateral ( + select r226.i226+1 as i227 + from rdb$database + ) r227 + cross join lateral ( + select r227.i227+1 as i228 + from rdb$database + ) r228 + cross join lateral ( + select r228.i228+1 as i229 + from rdb$database + ) r229 + cross join lateral ( + select r229.i229+1 as i230 + from rdb$database + ) r230 + cross join lateral ( + select r230.i230+1 as i231 + from rdb$database + ) r231 + cross join lateral ( + select r231.i231+1 as i232 + from rdb$database + ) r232 + cross join lateral ( + select r232.i232+1 as i233 + from rdb$database + ) r233 + cross join lateral ( + select r233.i233+1 as i234 + from rdb$database + ) r234 + cross join lateral ( + select r234.i234+1 as i235 + from rdb$database + ) r235 + cross join lateral ( + select r235.i235+1 as i236 + from rdb$database + ) r236 + cross join lateral ( + select r236.i236+1 as i237 + from rdb$database + ) r237 + cross join lateral ( + select r237.i237+1 as i238 + from rdb$database + ) r238 + cross join lateral ( + select r238.i238+1 as i239 + from rdb$database + ) r239 + cross join lateral ( + select r239.i239+1 as i240 + from rdb$database + ) r240 + cross join lateral ( + select r240.i240+1 as i241 + from rdb$database + ) r241 + cross join lateral ( + select r241.i241+1 as i242 + from rdb$database + ) r242 + cross join lateral ( + select r242.i242+1 as i243 + from rdb$database + ) r243 + cross join lateral ( + select r243.i243+1 as i244 + from rdb$database + ) r244 + cross join lateral ( + select r244.i244+1 as i245 + from rdb$database + ) r245 + cross join lateral ( + select r245.i245+1 as i246 + from rdb$database + ) r246 + cross join lateral ( + select r246.i246+1 as i247 + from rdb$database + ) r247 + cross join lateral ( + select r247.i247+1 as i248 + from rdb$database + ) r248 + cross join lateral ( + select r248.i248+1 as i249 + from rdb$database + ) r249 + cross join lateral ( + select r249.i249+1 as i250 + from rdb$database + ) r250 + cross join lateral ( + select r250.i250+1 as i251 + from rdb$database + ) r251 + cross join lateral ( + select r251.i251+1 as i252 + from rdb$database + ) r252 + cross join lateral ( + select r252.i252+1 as i253 + from rdb$database + ) r253 + cross join lateral ( + select r253.i253+1 as i254 + from rdb$database + ) r254 + cross join lateral ( + select r254.i254+1 as i255 + from rdb$database + ) r255 + ; + + + + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG CODE MODEL SPEED RAM HD PRICE SCREEN MAX_PRICE MIN_PRICE + test-1 1 1298 350 32 4.000000000000000 700.00 11 1150.00 700.00 + test-1 2 1321 500 64 8.000000000000000 970.00 12 970.00 970.00 + test-1 3 1750 750 128 12.00000000000000 1200.00 14 1200.00 1200.00 + test-1 4 1298 600 64 10.00000000000000 1050.00 15 1150.00 700.00 + test-1 5 1752 750 128 10.00000000000000 1150.00 14 1150.00 700.00 + test-1 6 1298 450 64 10.00000000000000 950.00 12 1150.00 700.00 + + MSG CURR_CORE LEAD_CODE + test-2 1 4 + test-2 4 6 + test-2 6 2 + test-2 2 3 + test-2 3 5 + test-2 5 + + MSG MAKER MODEL TYPE + test-3 A 1298 Laptop + test-3 C 1321 Laptop + test-3 B 1750 Laptop + test-3 B 1121 PC + test-3 A 1232 PC + test-3 A 1233 PC + test-3 A 1276 Printer + test-3 D 1288 Printer + test-3 A 1401 Printer + + MSG CODE MODEL SPEED PRICE MODEL_FOR_NEXT_CODE SPEED_FOR_NEXT_CODE PRICE_FOR_NEXT_CODE + test-4 1 1298 350 700.00 1321 500 970.00 + test-4 2 1321 500 970.00 1750 750 1200.00 + test-4 3 1750 750 1200.00 1298 600 1050.00 + test-4 4 1298 600 1050.00 1752 750 1150.00 + test-4 5 1752 750 1150.00 1298 450 950.00 + test-4 6 1298 450 950.00 + + + MSG I FACTORIALS_RUNNING_TOTAL + test-5 10 4037913 + test-5 9 409113 + test-5 8 46233 + test-5 7 5913 + test-5 6 873 + test-5 5 153 + test-5 4 33 + test-5 3 9 + test-5 2 3 + test-5 1 1 + + I0 1 + I1 2 + I2 3 + I3 4 + I4 5 + I5 6 + I6 7 + I7 8 + I8 9 + I9 10 + I10 11 + I11 12 + I12 13 + I13 14 + I14 15 + I15 16 + I16 17 + I17 18 + I18 19 + I19 20 + I20 21 + I21 22 + I22 23 + I23 24 + I24 25 + I25 26 + I26 27 + I27 28 + I28 29 + I29 30 + I30 31 + I31 32 + I32 33 + I33 34 + I34 35 + I35 36 + I36 37 + I37 38 + I38 39 + I39 40 + I40 41 + I41 42 + I42 43 + I43 44 + I44 45 + I45 46 + I46 47 + I47 48 + I48 49 + I49 50 + I50 51 + I51 52 + I52 53 + I53 54 + I54 55 + I55 56 + I56 57 + I57 58 + I58 59 + I59 60 + I60 61 + I61 62 + I62 63 + I63 64 + I64 65 + I65 66 + I66 67 + I67 68 + I68 69 + I69 70 + I70 71 + I71 72 + I72 73 + I73 74 + I74 75 + I75 76 + I76 77 + I77 78 + I78 79 + I79 80 + I80 81 + I81 82 + I82 83 + I83 84 + I84 85 + I85 86 + I86 87 + I87 88 + I88 89 + I89 90 + I90 91 + I91 92 + I92 93 + I93 94 + I94 95 + I95 96 + I96 97 + I97 98 + I98 99 + I99 100 + I100 101 + I101 102 + I102 103 + I103 104 + I104 105 + I105 106 + I106 107 + I107 108 + I108 109 + I109 110 + I110 111 + I111 112 + I112 113 + I113 114 + I114 115 + I115 116 + I116 117 + I117 118 + I118 119 + I119 120 + I120 121 + I121 122 + I122 123 + I123 124 + I124 125 + I125 126 + I126 127 + I127 128 + I128 129 + I129 130 + I130 131 + I131 132 + I132 133 + I133 134 + I134 135 + I135 136 + I136 137 + I137 138 + I138 139 + I139 140 + I140 141 + I141 142 + I142 143 + I143 144 + I144 145 + I145 146 + I146 147 + I147 148 + I148 149 + I149 150 + I150 151 + I151 152 + I152 153 + I153 154 + I154 155 + I155 156 + I156 157 + I157 158 + I158 159 + I159 160 + I160 161 + I161 162 + I162 163 + I163 164 + I164 165 + I165 166 + I166 167 + I167 168 + I168 169 + I169 170 + I170 171 + I171 172 + I172 173 + I173 174 + I174 175 + I175 176 + I176 177 + I177 178 + I178 179 + I179 180 + I180 181 + I181 182 + I182 183 + I183 184 + I184 185 + I185 186 + I186 187 + I187 188 + I188 189 + I189 190 + I190 191 + I191 192 + I192 193 + I193 194 + I194 195 + I195 196 + I196 197 + I197 198 + I198 199 + I199 200 + I200 201 + I201 202 + I202 203 + I203 204 + I204 205 + I205 206 + I206 207 + I207 208 + I208 209 + I209 210 + I210 211 + I211 212 + I212 213 + I213 214 + I214 215 + I215 216 + I216 217 + I217 218 + I218 219 + I219 220 + I220 221 + I221 222 + I222 223 + I223 224 + I224 225 + I225 226 + I226 227 + I227 228 + I228 229 + I229 230 + I230 231 + I231 232 + I232 233 + I233 234 + I234 235 + I235 236 + I236 237 + I237 238 + I238 239 + I239 240 + I240 241 + I241 242 + I242 243 + I243 244 + I244 245 + I245 246 + I246 247 + I247 248 + I248 249 + I249 250 + I250 251 + I251 252 + I252 253 + I253 254 + I254 255 + """ + +@pytest.mark.version('>=4.0.0') +def test_core_3435_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3446.py b/tests/bugs/test_core_3446.py new file mode 100644 index 00000000..51929455 --- /dev/null +++ b/tests/bugs/test_core_3446.py @@ -0,0 +1,346 @@ +#coding:utf-8 +# +# id: bugs.core_3446 +# title: Allow conversion from/to BLOBs and others types in the API functions (XSQLVAR or blr messages) +# decription: We try to write varchar value into blob field and vice-versa, using execute statement with parameters of corresp. types +# tracker_id: CORE-3446 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [('B_NEW.*', '')] + +init_script_1 = """ +recreate table test( s varchar(8187) character set utf8 collate unicode_ci_ai, b blob sub_type 1 character set utf8 collate unicode_ci_ai); +commit; + +insert into test (s, b ) +values( +'Sur le boulevard Montmorency, au n° 53, s''élève une maison portant, +encastré dans son balcon, un profil lauré de Louis XV, en bronze +doré, qui a tout l''air d''être le médaillon, dont était décorée la +tribune de musique de la salle à manger de Luciennes, représenté dans +l''aquarelle de Moreau que l''on voit au Louvre. Cette tête, que quelques +promeneurs regardent d''un œil farouche, n''est point,--ai-je besoin de +le dire?--une affiche des opinions politiques du propriétaire, elle est +tout bonnement l''enseigne d''un des nids les plus pleins de choses du +XVIIIe siècle qui existent à Paris. + +La porte noire, que surmonte un élégant dessus de grille de chapelle +jésuite en fer forgé, la porte ouverte, du bas de l''escalier, de +l''entrée du vestibule, du seuil de la maison, le visiteur est accueilli +par des terres cuites, des bronzes, des dessins, des porcelaines du +siècle aimable par excellence, mêlés à des objets de l''Extrême-Orient, +qui se trouvaient faire si bon ménage dans les collections de Madame de +Pompadour et de tous les _curieux_ et les _curiolets_ du temps. + +La vie d''aujourd''hui est une vie de combattivité; elle demande dans +toutes les carrières une concentration, un effort, un travail, qui, en +son foyer enferment l''homme, dont l''existence n''est plus extérieure +comme au XVIIIe siècle, n''est plus papillonnante parmi la société +depuis ses dix-sept ans jusqu''à sa mort. De notre temps on va bien +encore dans le monde, mais toute la vie ne s''y dépense plus, et le +_chez-soi_ a cessé d''être l''hôtel garni où l''on ne faisait que coucher. +Dans cette vie assise au coin du feu, renfermée, sédentaire, la +créature humaine, et la première venue, a été poussée à vouloir les +quatre murs de son _home_ agréables, plaisants, amusants aux yeux; et +cet entour et ce décor de son intérieur, elle l''a cherché et trouvé +naturellement dans l''objet d''art pur ou dans l''objet d''art industriel, +plus accessible au goût de tous. Du même coup, ces habitudes moins +mondaines amenaient un amoindrissement du rôle de la femme dans la +pensée masculine; elle n''était plus pour nous l''occupation galante de +toute notre existence, cette occupation qui était autrefois la carrière +du plus grand nombre, et, à la suite de cette modification dans les +mœurs, il arrivait ceci: c''est que l''intérêt de l''homme, s''en allant +de l''être charmant, se reportait en grande partie sur les jolis objets +inanimés dont la passion revêt un peu de la nature et du caractère +de l''amour. Au XVIIIe siècle, il n''y a pas de _bibeloteurs_ jeunes: +c''est là la différence des deux siècles. Pour notre génération, la +_bricabracomanie_ n''est qu''un bouche-trou de la femme qui ne possède +plus l''imagination de l''homme, et j''ai fait à mon égard cette remarque, +que, lorsque par hasard mon cœur s''est trouvé occupé, l''objet d''art ne +m''était de rien. + +Oui, cette passion devenue générale, ce plaisir solitaire, auquel se +livre presque toute une nation, doit son développement au vide, à +l''ennui du cœur, et aussi, il faut le reconnaître, à la tristesse +des jours actuels, à l''incertitude des lendemains, à l''enfantement, +les pieds devant, de la société nouvelle, à des soucis et à des +préoccupations qui poussent, comme à la veille d''un déluge, les désirs +et les envies à se donner la jouissance immédiate de tout ce qui les +charme, les séduit, les tente: l''oubli du moment dans l''assouvissement +artistique. + +Ce sont ces causes, et incontestablement l''éducation de l''œil des +gens du XIXe siècle, et encore un sentiment tout nouveau, la tendresse +presque humaine pour les _choses_, qui font, à l''heure qu''il est, de +presque tout le monde, des collectionneurs et de moi en particulier le +plus passionné de tous les collectionneurs. + +Un riant pavé en marbre blanc et en marbre rouge du Languedoc, avec, +pour revêtement aux murs et au plafond, un cuir moderne peuplé de +perroquets fantastiques dorés et peints sur un fond vert d''eau. + +Sur ce cuir, dans un désordre cherché, dans un pittoresque +d''antichambre et d''atelier, toutes sortes de choses voyantes et +claquantes, de brillants cuivres découpés, des poteries dorées, des +broderies du Japon et encore des objets bizarres, inattendus, étonnant +par leur originalité, leur exotisme, et vis-à-vis d''un certain nombre +desquels je me fais un peu l''effet du bon Père Buffier quand il disait: +«Voilà des choses que je ne sais pas, il faut que je fasse un livre +dessus.» + +Ça, une petite jardinière à suspension, fabriquée d''une coloquinte +excentrique, dont la tige tournante et recroquevillée est une tige de +bronze qui a la flexibilité d''une liane; cette grande planchette fruste +de bois, toute parcourue des tortils d''un feuillage de lierre, exécuté +en nacre et en écaille: le porte-éventail qui tient dans l''appartement +l''éventail ouvert contre le mur; cette petite boule de porcelaine +jaune impérial si délicatement treillagée: la cage au grillon ou à +la mouche bourdonnante, que le Chinois aime suspendre au chevet de +son lit; et cette plaque de faïence figurant une branche de pêcher en +fleur, modelée à jour dans un cadre de bois en forme d''écran, vous +représente la décoration de l''angle religieux et mystique d''une chambre +de prostituée de maison de thé, l''espèce de tableau d''autel devant +lequel elle place une fleur dans un vase. + +Des broderies du Japon, ai-je dit plus haut, c''est là, dans leurs +cadres de bambous, la riche, la splendide, l''_éclairante_ décoration +des murs du vestibule et un peu de toute la maison. Ces carrés de soie +brodés appelés _fusha_ ou _foukousa_ font la chatoyante couverture +sous laquelle on a l''habitude, dans l''Empire du Lever du Soleil, +d''envoyer tout présent quelconque, et le plus minime, fût-il même de +deux œufs[1]. Les anciens _foukousas_ fabriqués à Kioto[2] sont des +produits d''un art tout particulier au Japon, et auxquels l''Europe +ne peut rien opposer: de la peinture, de vrais tableaux composés +et exécutés en soie par un brodeur, où sur les fonds aux adorables +nuances, et telles qu''en donne le satin ou le crêpe, un oiseau, un +poisson, une fleur se détache dans le haut relief d''une broderie. +Et rien là dedans du travail d''un art mécanique, du dessin bête de +vieille fille de nos broderies à nous, mais des silhouettes d''êtres +pleins de vie, avec leurs pattes d''oiseau d''un si grand style, avec +leurs nageoires de poisson d''un si puissant contournement. Quelquefois +des parties peintes, peintes à l''encre de Chine, s''associent de la +manière la plus heureuse à la broderie. Je connais, chez Mme Auguste +Sichel, une fusée de fleurs brodée dans un vase en sparterie peint ou +imprimé, qui est bien la plus harmonieuse chose qu''il soit possible +de voir. M. de Nittis a fait un écran, d''un admirable et singulier +carré, où deux grues, brodées en noir sur un fond rose saumoné, ont, +comme accompagnement et adoucissement de la broderie, des demi-teintes +doucement lavées d''encre de Chine sur l''étoffe enchanteresse. Et dans +ce vestibule, il y a, sur un fond lilas, des carpes nageant au milieu +de branchages de presle brodées en or, et dont le ventre apparaît comme +argenté par un reflet de bourbe: un effet obtenu par une réserve au +milieu du fond tout teinté et obscuré d''encre de Chine. Il est même un +certain nombre de foukousas absolument peints. J''ai coloriée, sur un +crêpe gris, dans l''orbe d''un soleil rouge comme du feu, l''échancrure +pittoresque d''un passage de sept grues, exécuté avec la science que les +Japonais possèdent du vol de l''échassier. J''ai encore, jetées sur un +fond maïs, sans aucun détail de terrain, deux grandes grues blanches, +à la petite crête rougie de vermillon, au cou, aux pattes, à la queue, +teintés d''encre de Chine. Et ne vous étonnez pas de rencontrer si +souvent sur les broderies la grue, cet oiseau qui apparaît dans le +haut du ciel aux Japonais comme un messager céleste, et qu''ils saluent +de l''appellation: _O Tsouri Sama_, Sa Seigneurie la Grue. + +[1] Il n''est guère besoin de dire que le carré est toujours +rapporté à son maître par le porteur du présent. + +[2] Les foukousas modernes seraient aujourd''hui fabriqués à +Togané, d''où on les expédierait à Yedo. +' +, ----------- +'Sur le boulevard Montmorency, au n° 53, s''élève une maison portant, +encastré dans son balcon, un profil lauré de Louis XV, en bronze +doré, qui a tout l''air d''être le médaillon, dont était décorée la +tribune de musique de la salle à manger de Luciennes, représenté dans +l''aquarelle de Moreau que l''on voit au Louvre. Cette tête, que quelques +promeneurs regardent d''un œil farouche, n''est point,--ai-je besoin de +le dire?--une affiche des opinions politiques du propriétaire, elle est +tout bonnement l''enseigne d''un des nids les plus pleins de choses du +XVIIIe siècle qui existent à Paris. + +La porte noire, que surmonte un élégant dessus de grille de chapelle +jésuite en fer forgé, la porte ouverte, du bas de l''escalier, de +l''entrée du vestibule, du seuil de la maison, le visiteur est accueilli +par des terres cuites, des bronzes, des dessins, des porcelaines du +siècle aimable par excellence, mêlés à des objets de l''Extrême-Orient, +qui se trouvaient faire si bon ménage dans les collections de Madame de +Pompadour et de tous les _curieux_ et les _curiolets_ du temps. + +La vie d''aujourd''hui est une vie de combattivité; elle demande dans +toutes les carrières une concentration, un effort, un travail, qui, en +son foyer enferment l''homme, dont l''existence n''est plus extérieure +comme au XVIIIe siècle, n''est plus papillonnante parmi la société +depuis ses dix-sept ans jusqu''à sa mort. De notre temps on va bien +encore dans le monde, mais toute la vie ne s''y dépense plus, et le +_chez-soi_ a cessé d''être l''hôtel garni où l''on ne faisait que coucher. +Dans cette vie assise au coin du feu, renfermée, sédentaire, la +créature humaine, et la première venue, a été poussée à vouloir les +quatre murs de son _home_ agréables, plaisants, amusants aux yeux; et +cet entour et ce décor de son intérieur, elle l''a cherché et trouvé +naturellement dans l''objet d''art pur ou dans l''objet d''art industriel, +plus accessible au goût de tous. Du même coup, ces habitudes moins +mondaines amenaient un amoindrissement du rôle de la femme dans la +pensée masculine; elle n''était plus pour nous l''occupation galante de +toute notre existence, cette occupation qui était autrefois la carrière +du plus grand nombre, et, à la suite de cette modification dans les +mœurs, il arrivait ceci: c''est que l''intérêt de l''homme, s''en allant +de l''être charmant, se reportait en grande partie sur les jolis objets +inanimés dont la passion revêt un peu de la nature et du caractère +de l''amour. Au XVIIIe siècle, il n''y a pas de _bibeloteurs_ jeunes: +c''est là la différence des deux siècles. Pour notre génération, la +_bricabracomanie_ n''est qu''un bouche-trou de la femme qui ne possède +plus l''imagination de l''homme, et j''ai fait à mon égard cette remarque, +que, lorsque par hasard mon cœur s''est trouvé occupé, l''objet d''art ne +m''était de rien. + +Oui, cette passion devenue générale, ce plaisir solitaire, auquel se +livre presque toute une nation, doit son développement au vide, à +l''ennui du cœur, et aussi, il faut le reconnaître, à la tristesse +des jours actuels, à l''incertitude des lendemains, à l''enfantement, +les pieds devant, de la société nouvelle, à des soucis et à des +préoccupations qui poussent, comme à la veille d''un déluge, les désirs +et les envies à se donner la jouissance immédiate de tout ce qui les +charme, les séduit, les tente: l''oubli du moment dans l''assouvissement +artistique. + +Ce sont ces causes, et incontestablement l''éducation de l''œil des +gens du XIXe siècle, et encore un sentiment tout nouveau, la tendresse +presque humaine pour les _choses_, qui font, à l''heure qu''il est, de +presque tout le monde, des collectionneurs et de moi en particulier le +plus passionné de tous les collectionneurs. + +Un riant pavé en marbre blanc et en marbre rouge du Languedoc, avec, +pour revêtement aux murs et au plafond, un cuir moderne peuplé de +perroquets fantastiques dorés et peints sur un fond vert d''eau. + +Sur ce cuir, dans un désordre cherché, dans un pittoresque +d''antichambre et d''atelier, toutes sortes de choses voyantes et +claquantes, de brillants cuivres découpés, des poteries dorées, des +broderies du Japon et encore des objets bizarres, inattendus, étonnant +par leur originalité, leur exotisme, et vis-à-vis d''un certain nombre +desquels je me fais un peu l''effet du bon Père Buffier quand il disait: +«Voilà des choses que je ne sais pas, il faut que je fasse un livre +dessus.» + +Ça, une petite jardinière à suspension, fabriquée d''une coloquinte +excentrique, dont la tige tournante et recroquevillée est une tige de +bronze qui a la flexibilité d''une liane; cette grande planchette fruste +de bois, toute parcourue des tortils d''un feuillage de lierre, exécuté +en nacre et en écaille: le porte-éventail qui tient dans l''appartement +l''éventail ouvert contre le mur; cette petite boule de porcelaine +jaune impérial si délicatement treillagée: la cage au grillon ou à +la mouche bourdonnante, que le Chinois aime suspendre au chevet de +son lit; et cette plaque de faïence figurant une branche de pêcher en +fleur, modelée à jour dans un cadre de bois en forme d''écran, vous +représente la décoration de l''angle religieux et mystique d''une chambre +de prostituée de maison de thé, l''espèce de tableau d''autel devant +lequel elle place une fleur dans un vase. + +Des broderies du Japon, ai-je dit plus haut, c''est là, dans leurs +cadres de bambous, la riche, la splendide, l''_éclairante_ décoration +des murs du vestibule et un peu de toute la maison. Ces carrés de soie +brodés appelés _fusha_ ou _foukousa_ font la chatoyante couverture +sous laquelle on a l''habitude, dans l''Empire du Lever du Soleil, +d''envoyer tout présent quelconque, et le plus minime, fût-il même de +deux œufs[1]. Les anciens _foukousas_ fabriqués à Kioto[2] sont des +produits d''un art tout particulier au Japon, et auxquels l''Europe +ne peut rien opposer: de la peinture, de vrais tableaux composés +et exécutés en soie par un brodeur, où sur les fonds aux adorables +nuances, et telles qu''en donne le satin ou le crêpe, un oiseau, un +poisson, une fleur se détache dans le haut relief d''une broderie. +Et rien là dedans du travail d''un art mécanique, du dessin bête de +vieille fille de nos broderies à nous, mais des silhouettes d''êtres +pleins de vie, avec leurs pattes d''oiseau d''un si grand style, avec +leurs nageoires de poisson d''un si puissant contournement. Quelquefois +des parties peintes, peintes à l''encre de Chine, s''associent de la +manière la plus heureuse à la broderie. Je connais, chez Mme Auguste +Sichel, une fusée de fleurs brodée dans un vase en sparterie peint ou +imprimé, qui est bien la plus harmonieuse chose qu''il soit possible +de voir. M. de Nittis a fait un écran, d''un admirable et singulier +carré, où deux grues, brodées en noir sur un fond rose saumoné, ont, +comme accompagnement et adoucissement de la broderie, des demi-teintes +doucement lavées d''encre de Chine sur l''étoffe enchanteresse. Et dans +ce vestibule, il y a, sur un fond lilas, des carpes nageant au milieu +de branchages de presle brodées en or, et dont le ventre apparaît comme +argenté par un reflet de bourbe: un effet obtenu par une réserve au +milieu du fond tout teinté et obscuré d''encre de Chine. Il est même un +certain nombre de foukousas absolument peints. J''ai coloriée, sur un +crêpe gris, dans l''orbe d''un soleil rouge comme du feu, l''échancrure +pittoresque d''un passage de sept grues, exécuté avec la science que les +Japonais possèdent du vol de l''échassier. J''ai encore, jetées sur un +fond maïs, sans aucun détail de terrain, deux grandes grues blanches, +à la petite crête rougie de vermillon, au cou, aux pattes, à la queue, +teintés d''encre de Chine. Et ne vous étonnez pas de rencontrer si +souvent sur les broderies la grue, cet oiseau qui apparaît dans le +haut du ciel aux Japonais comme un messager céleste, et qu''ils saluent +de l''appellation: _O Tsouri Sama_, Sa Seigneurie la Grue. + +[1] Il n''est guère besoin de dire que le carré est toujours +rapporté à son maître par le porteur du présent. + +[2] Les foukousas modernes seraient aujourd''hui fabriqués à +Togané, d''où on les expédierait à Yedo. +' +); +commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set blob all; + set term ^; + execute block returns(s_new type of column test.s, b_new type of column test.b) as + declare v_char type of column test.s; + declare v_blob type of column test.b; + begin + select s, b from test rows 1 into v_char, v_blob; + execute statement ( 'select ''|'' || replace(s, :x_blob, '''') || ''|'' s_empty, ''|'' || replace( b, :x_char, '''') || ''|'' b_empty ' + ||' from test where s = :x_blob and b = :x_char' + -- ^ ^ ^ ^ + -- char blob blob char + ) + ( x_char := v_char, x_blob := v_blob ) + into s_new, b_new; + suspend; + end + ^ set term ;^ + -- 2.5.0: + -- Statement failed, SQLSTATE = 0A000 + -- Dynamic SQL Error + -- -SQL error code = -303 + -- -feature is not supported + -- -BLOB and array data types are not supported for move operation + -- 2.5.1 and 2.5.2: client crash, "INET/inet_error: connect errno = 10061" + -- 2.5.3 and later: works OK, but limit of varchar field is 8187 characters, + -- otherwise get exception: + -- Statement failed, SQLSTATE = 54000 + -- Dynamic SQL Error + -- -SQL error code = -204 + -- -Implementation limit exceeded + -- -block size exceeds implementation restriction + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + S_NEW || + B_NEW 0:f + || + """ + +@pytest.mark.version('>=2.5.3') +def test_core_3446_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3447.py b/tests/bugs/test_core_3447.py new file mode 100644 index 00000000..3e1b455d --- /dev/null +++ b/tests/bugs/test_core_3447.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: bugs.core_3447 +# title: Collation is not installed with icu > 4.2 +# decription: +# tracker_id: CORE-3447 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test( + name1 varchar(32) character set utf8 collate ucs_basic, + name2 varchar(32) character set utf8 collate unicode, + name3 varchar(32) character set utf8 collate unicode_ci, + name4 varchar(32) character set utf8 collate unicode_ci_ai + ); + commit; + show table test; + -- Passed on: WI-V2.5.5.26871, WI-T3.0.0.31844; LI-V2.5.3.26788, LI-T3.0.0.31842 + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + NAME1 VARCHAR(32) CHARACTER SET UTF8 Nullable + COLLATE UCS_BASIC + NAME2 VARCHAR(32) CHARACTER SET UTF8 Nullable + COLLATE UNICODE + NAME3 VARCHAR(32) CHARACTER SET UTF8 Nullable + COLLATE UNICODE_CI + NAME4 VARCHAR(32) CHARACTER SET UTF8 Nullable + COLLATE UNICODE_CI_AI + """ + +@pytest.mark.version('>=2.5.1') +def test_core_3447_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3450.py b/tests/bugs/test_core_3450.py new file mode 100644 index 00000000..efc9fa23 --- /dev/null +++ b/tests/bugs/test_core_3450.py @@ -0,0 +1,115 @@ +#coding:utf-8 +# +# id: bugs.core_3450 +# title: Inefficient optimization (regression) +# decription: +# ::: NB ::: +# 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! +# +# tracker_id: CORE-3450 +# min_versions: ['2.5.7'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter procedure sp_2 as begin end; + + recreate table test_1 (f1 int, f2 int, f3 int); + create index test_1_f1 on test_1(f1); + create index test_1_f2 on test_1(f2); + commit; + + recreate table test_2 (f1 int, f2 int); + create index test_2_f1 on test_2(f1); + create index test_2_f2 on test_2(f2); + commit; + + recreate table test_3 (f1 int); + create index test_3_f1 on test_3(f1); + commit; + + set term ^; + create or alter procedure sp_1 returns (f1 int) + as begin + f1=1; + suspend; + end + ^ + + create or alter procedure sp_2 as + declare i int; + declare t1_lim int = 1000; + declare t2_lim int = 100; + declare t3_lim int = 10; + begin + i=0; + while (i=3.0') +def test_core_3450_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3453.py b/tests/bugs/test_core_3453.py new file mode 100644 index 00000000..82b0d7a6 --- /dev/null +++ b/tests/bugs/test_core_3453.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_3453 +# title: Added not null timestamp col with default causes error on select of old null records +# decription: +# tracker_id: CORE-3453 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table "Temp" ("Dummy" int); + commit; + insert into "Temp" ("Dummy") values (1); + commit; + alter table "Temp" add "New" timestamp default '0001-01-01' not null; + commit; + set list on; + select * from "Temp"; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Dummy 1 + New 0001-01-01 00:00:00.0000 + """ + +@pytest.mark.version('>=2.5') +def test_core_3453_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3461.py b/tests/bugs/test_core_3461.py new file mode 100644 index 00000000..599e5a3c --- /dev/null +++ b/tests/bugs/test_core_3461.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: bugs.core_3461 +# title: DDL operations fail after backup/restore +# decription: +# tracker_id: CORE-3461 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core3461.fbk', init=init_script_1) + +test_script_1 = """ + set autoddl off; + set term ^ ; + drop table test_tbl ^ + alter procedure test_proc(id integer) as begin end ^ + alter table test_tbl2 add id2 integer ^ + alter procedure test_tbl_proc as + declare id integer; + declare id2 integer; + begin + select id, id2 from test_tbl2 into :id, :id2; + end ^ + commit^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.1') +def test_core_3461_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_3474.py b/tests/bugs/test_core_3474.py new file mode 100644 index 00000000..5e386c5b --- /dev/null +++ b/tests/bugs/test_core_3474.py @@ -0,0 +1,67 @@ +#coding:utf-8 +# +# id: bugs.core_3474 +# title: Regression in joins on procedures +# decription: +# tracker_id: CORE-3474 +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('-At line.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='employee-ods12.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + select e.emp_no emp_1, e.last_name name_1, p.proj_name proj_1 + from employee e + left join + ( get_emp_proj(e.emp_no) proc + join project p on p.proj_id = proc.proj_id + ) on 1=1 + order by 1,2,3 + rows 1; + + select e.emp_no emp_2, e.last_name name_2, p.proj_name proj_2 + from + ( + employee e + left join get_emp_proj(e.emp_no) proc on 1=1 + ) + left join project p on p.proj_id = proc.proj_id + order by 1,2,3 + rows 1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + EMP_2 2 + NAME_2 Nelson + PROJ_2 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42S22 + Dynamic SQL Error + -SQL error code = -206 + -Column unknown + -E.EMP_NO + """ + +@pytest.mark.version('>=3.0') +def test_core_3474_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3475.py b/tests/bugs/test_core_3475.py new file mode 100644 index 00000000..53e18ec1 --- /dev/null +++ b/tests/bugs/test_core_3475.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: bugs.core_3475 +# title: Parameters inside the CAST function are described as not nullable +# decription: +# tracker_id: CORE-3475 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!sqltype).)*$', ''), ('[ ]+', ' '), ('[\t]*', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set planonly; + set sqlda_display; + select cast(null as int) v1, cast(? as int) v2 from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 01: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + 01: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + 02: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + """ + +@pytest.mark.version('>=3.0') +def test_core_3475_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3476.py b/tests/bugs/test_core_3476.py new file mode 100644 index 00000000..98feec39 --- /dev/null +++ b/tests/bugs/test_core_3476.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_3476 +# title: LIST function wrongly concatenates binary blobs +# decription: +# tracker_id: CORE-3476 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select ascii_val( left(list(f,''),1) ) v1, ascii_val( right(list(f,''),1) ) v2 + from ( + select cast(ascii_char(0xff) as blob sub_type 0) as f + from rdb$database + union all + select cast(ascii_char(0xde) as blob sub_type 0) as f + from rdb$database + ); + -- NB: proper result will be only in 3.0, WI-V2.5.4.26853 produces: + -- V1 46 + -- V2 46 + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + V1 255 + V2 222 + """ + +@pytest.mark.version('>=3.0') +def test_core_3476_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3479.py b/tests/bugs/test_core_3479.py new file mode 100644 index 00000000..2d7b14d1 --- /dev/null +++ b/tests/bugs/test_core_3479.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: bugs.core_3479 +# title: ASCII_VAL raises error instead of return 0 for empty strings +# decription: Added two expressions with "non-typical" arguments +# tracker_id: CORE-3479 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select ascii_val('') v1, ascii_val(ascii_char(0)) v2, ascii_val(ascii_char(null)) v3 from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + V1 0 + V2 0 + V3 + """ + +@pytest.mark.version('>=2.5.1') +def test_core_3479_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3489.py b/tests/bugs/test_core_3489.py new file mode 100644 index 00000000..c0067665 --- /dev/null +++ b/tests/bugs/test_core_3489.py @@ -0,0 +1,141 @@ +#coding:utf-8 +# +# id: bugs.core_3489 +# title: Blob transliteration may not happen inside the union +# decription: +# 02-mar-2021. Re-implemented in order to have ability to run this test on Linux. +# Ttest 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 = WIN1251 and perform needed DML. +# Result will be redirected to .log which will be opened via codecs.open(...encoding='cp1251'). +# Its content will be converted to UTF8 for showing in expected_stdout. +# +# Confirmed bug on 2.5.0.26074: two lines with "raw" (not transliterated) data were displayed. +# Works OK on 2.5.1.26351: two readable lines will be issued. +# +# tracker_id: CORE-3489 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [('MSG_BLOB_ID.*', '')] + +init_script_1 = """ + 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_1 = db_factory(charset='WIN1251', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import codecs +# import subprocess +# import time +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# sql_txt=''' set names WIN1251; +# connect '%(dsn)s' user '%(user_name)s' password '%(user_password)s'; +# 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; +# ''' % dict(globals(), **locals()) +# +# f_run_sql = open( os.path.join(context['temp_directory'], 'tmp_3489_win1251.sql'), 'w' ) +# f_run_sql.write( sql_txt.decode('utf8').encode('cp1251') ) +# flush_and_close( f_run_sql ) +# # result: file tmp_3489_win1251.sql is encoded in win1251 +# +# f_run_log = open( os.path.splitext(f_run_sql.name)[0]+'.log', 'w') +# subprocess.call( [ context['isql_path'], '-q', '-i', f_run_sql.name ], +# stdout = f_run_log, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_run_log ) # result: output will be encoded in win1251 +# +# with codecs.open(f_run_log.name, 'r', encoding='cp1251' ) as f: +# result_in_cp1251 = f.readlines() +# +# for i in result_in_cp1251: +# print( i.encode('utf8') ) +# +# # cleanup: +# ########### +# cleanup( (f_run_sql, f_run_log) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Это проверка на вывод строки "Йцукёнг" + Это проверка на вывод строки "Йцукёнг" + Records affected: 2 + """ + +@pytest.mark.version('>=2.5.1') +@pytest.mark.xfail +def test_core_3489_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_3490.py b/tests/bugs/test_core_3490.py new file mode 100644 index 00000000..ee50fb08 --- /dev/null +++ b/tests/bugs/test_core_3490.py @@ -0,0 +1,80 @@ +#coding:utf-8 +# +# id: bugs.core_3490 +# title: Concurrency problem when using named cursors +# decription: +# ::: NB ::: +# Result in 3.0 and 4.0 has been changed "backward" to 2.5 after CORE-5773 was fixed. +# Expected stdout adjusted to FB 2.5, test now contains single section +# (done after discuss with dimitr, letter 29-mar-2018 12:18). +# +# Checked on: +# FB25Cs, build 2.5.8.27067: OK, 1.250s. +# FB25SC, build 2.5.9.27107: OK, 0.797s. +# FB30SS, build 3.0.4.32939: OK, 0.968s. +# FB40SS, build 4.0.0.943: OK, 1.297s. +# +# tracker_id: CORE-3490 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table my_table (a integer, b integer,c integer); + insert into my_table(a,b,c) values (1,1,1); + commit; + set transaction no wait; + + set term ^ ; + execute block as + declare my_cursor cursor for + ( select b from my_table + where a = 1 + for update of b with lock + ); + declare b integer; + + begin + open my_cursor; + fetch my_cursor into :b; + + update my_table set c = 2 + where a = 1; + + UPDATE MY_TABLE SET A = 0 WHERE A = 1; + + update my_table set b = 2 + where current of my_cursor; + end + ^ + set term ;^ + set list on; + select * from my_table; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A 0 + B 2 + C 2 + """ + +@pytest.mark.version('>=2.5.2') +def test_core_3490_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3491.py b/tests/bugs/test_core_3491.py new file mode 100644 index 00000000..848f9dd3 --- /dev/null +++ b/tests/bugs/test_core_3491.py @@ -0,0 +1,58 @@ +#coding:utf-8 +# +# id: bugs.core_3491 +# title: Altering of a TYPE OF COLUMN parameter affects the original column +# decription: +# tracker_id: CORE-3491 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """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_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """show table aaa; +set term !!; +create or alter procedure bbb +returns (b varchar(10)) +as +begin + suspend; +end!! +set term ;!! +commit; +show table aaa; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """SQL> A INTEGER Nullable +SQL> A INTEGER Nullable +""" + +@pytest.mark.version('>=2.5.1') +def test_core_3491_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3493.py b/tests/bugs/test_core_3493.py new file mode 100644 index 00000000..ac7e67b0 --- /dev/null +++ b/tests/bugs/test_core_3493.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: bugs.core_3493 +# title: Adding a value to a timestamp below '16.11.1858 00:00:01' throws 'value exceeds the range for valid timestamp' +# decription: +# tracker_id: CORE-3493 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT CAST('01.01.0200 12:00:00' as timestamp) + 1 from rdb$database; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """SQL> + ADD +========================= +0200-01-02 12:00:00.0000 +""" + +@pytest.mark.version('>=2.5.1') +def test_core_3493_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3502.py b/tests/bugs/test_core_3502.py new file mode 100644 index 00000000..6ae3d045 --- /dev/null +++ b/tests/bugs/test_core_3502.py @@ -0,0 +1,61 @@ +#coding:utf-8 +# +# id: bugs.core_3502 +# title: DROP VIEW ignores the existing non-column dependencies +# decription: +# tracker_id: CORE-3502 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + set autoddl on; + commit; + create or alter procedure p as begin end; + commit; + + create or alter view v (id) as select rdb$relation_id from rdb$database; + commit; + + set term ^; + create or alter procedure p as + declare id int; + begin + select id from v rows 1 into id; + end^ + set term ;^ + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + execute procedure p; + commit; + drop view v; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -COLUMN V.ID + -there are 1 dependencies + """ + +@pytest.mark.version('>=2.5.1') +def test_core_3502_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_3503.py b/tests/bugs/test_core_3503.py new file mode 100644 index 00000000..733b7983 --- /dev/null +++ b/tests/bugs/test_core_3503.py @@ -0,0 +1,51 @@ +#coding:utf-8 +# +# id: bugs.core_3503 +# title: ALTER VIEW crashes the server if the new version has an artificial (aggregate or union) stream at the position of a regular context in the older version +# decription: +# Checked on: +# 4.0.0.1635 SS: 1.890s. +# 3.0.5.33182 SS: 1.207s. +# 2.5.9.27146 SC: 0.360s. +# +# tracker_id: CORE-3503 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core3503.fbk', init=init_script_1) + +test_script_1 = """ + create or alter view v_test (id) + as + select rdb$relation_id from rdb$relations + union all + select rdb$relation_id from rdb$relations; + commit; -- here the crash happens + set list on; + select (select count(id) from v_test) / count(*) c + from rdb$relations; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + C 2 + """ + +@pytest.mark.version('>=2.5.1') +def test_core_3503_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3509.py b/tests/bugs/test_core_3509.py new file mode 100644 index 00000000..00a759bd --- /dev/null +++ b/tests/bugs/test_core_3509.py @@ -0,0 +1,58 @@ +#coding:utf-8 +# +# id: bugs.core_3509 +# title: Alter procedure allows to add the parameter with the same name +# decription: +# tracker_id: CORE-3509 +# min_versions: ['2.5.1'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + set term ^; + create or alter procedure duplicate_output_args returns (a_dup int) as + begin + a_dup = 1; + Suspend; + end^ + set term ;^ + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create or alter procedure duplicate_output_args returns( a_dup int, a_dup int) as + begin + a_dup = 1; + Suspend; + end + ^ + set term ;^ + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + CREATE OR ALTER PROCEDURE DUPLICATE_OUTPUT_ARGS failed + -SQL error code = -901 + -duplicate specification of A_DUP - not supported + """ + +@pytest.mark.version('>=3.0') +def test_core_3509_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_3517.py b/tests/bugs/test_core_3517.py new file mode 100644 index 00000000..2b1a7e09 --- /dev/null +++ b/tests/bugs/test_core_3517.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: bugs.core_3517 +# title: Server crash with built in function LPAD with string as second parameter +# decription: +# tracker_id: CORE-3517 +# min_versions: ['2.1.5'] +# versions: 2.1.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select LPAD('abc', '0', 3) FROM RDB$DATABASE; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +LPAD +====== + + +""" + +@pytest.mark.version('>=2.1.5') +def test_core_3517_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3523.py b/tests/bugs/test_core_3523.py new file mode 100644 index 00000000..0c1b879f --- /dev/null +++ b/tests/bugs/test_core_3523.py @@ -0,0 +1,48 @@ +#coding:utf-8 +# +# id: bugs.core_3523 +# title: SIMILAR TO: False matches on descending ranges +# decription: +# tracker_id: CORE-3523 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """select 1 from rdb$database where 'm' similar to '[p-k]' +union +select 2 from rdb$database where 'z' similar to '[p-k]' +union +select 3 from rdb$database where 'm' not similar to '[p-k]' +union +select 4 from rdb$database where 'z' not similar to '[p-k]'; + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """SQL> + CONSTANT +============ + 3 + 4 + +SQL>""" + +@pytest.mark.version('>=2.5.1') +def test_core_3523_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3526.py b/tests/bugs/test_core_3526.py new file mode 100644 index 00000000..ea8423e4 --- /dev/null +++ b/tests/bugs/test_core_3526.py @@ -0,0 +1,57 @@ +#coding:utf-8 +# +# id: bugs.core_3526 +# title: Support for WHEN SQLSTATE +# decription: +# Checked on: +# 3.0.4.32939: OK, 1.266s. +# 4.0.0.943: OK, 1.484s. +# +# tracker_id: CORE-3526 +# min_versions: ['3.0.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set term ^; + execute block returns(msg varchar(1000)) as + declare c smallint = 32767; + begin + msg=''; + begin + c = c+1; + when SQLSTATE '22003' do + begin + msg = 'got exception with sqlstate = ' || sqlstate || '; ' ; + end + end + suspend; + end + ^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG got exception with sqlstate = 22003; + """ + +@pytest.mark.version('>=3.0') +def test_core_3526_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3530.py b/tests/bugs/test_core_3530.py new file mode 100644 index 00000000..9199124b --- /dev/null +++ b/tests/bugs/test_core_3530.py @@ -0,0 +1,79 @@ +#coding:utf-8 +# +# id: bugs.core_3530 +# title: BETWEEN operand/clause not supported for COMPUTED columns -- "feature is not supported" +# decription: +# Checked on WI-V3.0.2.32670, WI-T4.0.0.503 - all fine. +# +# tracker_id: CORE-3530 +# min_versions: ['3.0.2'] +# versions: 3.0.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test2(id int); + commit; + + recreate table test( + x int, + y int + ); + + recreate table test2( + id int, + z computed by + ( + coalesce( ( select sum( + case + when (x = -1) then + 999 + else + (coalesce(x, 0) - coalesce(y, 0)) + end + ) + from test + where x = test2.id + ), + 0 + ) + ) + ); + commit; + + set plan on; + set count on; + --set echo on; + -- Before 3.0.2 following statement failed with: + -- Statement failed, SQLSTATE = 0A000 + -- feature is not supported + select * from test2 where z between 1 and 2; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (TEST NATURAL) + PLAN (TEST NATURAL) + PLAN (TEST NATURAL) + PLAN (TEST2 NATURAL) + Records affected: 0 + """ + +@pytest.mark.version('>=3.0.2') +def test_core_3530_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3537.py b/tests/bugs/test_core_3537.py new file mode 100644 index 00000000..8e285041 --- /dev/null +++ b/tests/bugs/test_core_3537.py @@ -0,0 +1,455 @@ +#coding:utf-8 +# +# id: bugs.core_3537 +# title: There is no need to undo changes made in GTT created with ON COMMIT DELETE ROWS option when transaction is rolled back +# decription: +# 19.12.2016. +# After discuss with hvlad it was decided to use fetches & marks values that are issued in trace +# ROLLBACK_TRANSACTION statistics and evaluate ratio of these values with: +# 1) number of inserted rows(see 'NUM_ROWS_TO_BE_ADDED' constant); +# 2) number of data pages that table occupies (it's retieved via 'gstat -t T_FIX_TAB'). +# +# We use three tables with the same DDL: permanent ('t_fix_tab'), GTT PRESERVE and GTT DELETE rows. +# All these tables are subject to DML which does insert rows. +# Permanent table is used for retrieving statistics of data pages that are in use after this DML. +# Number of rows that we add into tables should not be very high, otherwise rollback will be done via TIP, +# i.e. without real undone actions ==> we will not see proper ratios. +# After serveral runs it was decided to use value = 45000 (rows). +# +# All ratios should belong to some range with +/-5% of possible difference from one run to another. +# Concrete values of ratio were found after several runs on 2.5.7, 3.0.2 & 4.0.0 +# +# Checked on 2.5.7.27030 (SS/SC), WI-V3.0.2.32644 (SS/SC/CS) and WI-T4.0.0.468 (SS/SC); 4.0.0.633 (CS/SS) +# +# Notes. +# 1. We can estimate volume of UNDO changes in trace statistics for ROLLBACK event. +# This statistics was added since 2.5.2 (see CORE-3598). +# 2. We have to use 'gstat -t
'instead of 'fbsvcmgr sts_table <...>'in 2.5.x - see CORE-5426. +# +# 19.08.2020. Fixed wrong expression for difference evaluation in percents. Checked on: +# 4.0.0.2164 SS: 8.674s. +# 4.0.0.2119 SS: 9.736s. +# 4.0.0.2164 CS: 10.328s. +# 3.0.7.33356 SS: 7.333s. +# 3.0.7.33356 CS: 9.700s. +# 2.5.9.27150 SC: 5.884s. +# +# +# tracker_id: CORE-3537 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ +set bail on; +set echo on; + create or alter procedure sp_fill_fix_tab as begin end; + create or alter procedure sp_fill_gtt_del_rows as begin end; + create or alter procedure sp_fill_gtt_sav_rows as begin end; + + recreate view v_field_len as + select rf.rdb$relation_name as rel_name, f.rdb$field_length as fld_len + from rdb$relation_fields rf + join rdb$fields f on rf.rdb$field_source = f.rdb$field_name + ; + + recreate table t_fix_tab( + s1 varchar(50) + -- unique using index t_fix_tab_s1 + ); + + recreate global temporary table t_gtt_del_rows( + s1 varchar(50) + -- unique using index t_gtt_del_rows_s1 + ) on commit DELETE rows; + + recreate global temporary table t_gtt_sav_rows( + s1 varchar(50) + -- unique using index t_gtt_sav_rows_s1 + ) on commit PRESERVE rows; + + commit; + + set term ^; + create or alter procedure sp_fill_fix_tab(a_rows int) as + declare k int; + declare w int; + begin + k=a_rows; + select v.fld_len from v_field_len v where v.rel_name=upper('t_fix_tab') into w; + while(k>0) do + begin + insert into t_fix_tab(s1) values( rpad('', :w, uuid_to_char(gen_uuid()) ) ); + if (mod(k-1, 5000) = 0) then + rdb$set_context('USER_SESSION','DBG_FILL_FIX_TAB',a_rows - k); -- to be watched in the trace log (4DEBUG) + k = k - 1; + end + end + ^ + create or alter procedure sp_fill_gtt_del_rows(a_rows int) as + declare k int; + declare w int; + begin + k=a_rows; + select v.fld_len from v_field_len v where v.rel_name=upper('t_gtt_del_rows') into w; + while(k>0) do + begin + insert into t_gtt_del_rows(s1) values( rpad('', :w, uuid_to_char(gen_uuid()) ) ); + if (mod(k-1, 5000) = 0) then + rdb$set_context('USER_SESSION','DBG_FILL_GTT_DEL',a_rows - k); -- to be watched in the trace log (4DEBUG) + k = k - 1; + end + rdb$set_context('USER_SESSION','DBG_FILL_GTT_DEL',a_rows); + end + ^ + create or alter procedure sp_fill_gtt_sav_rows(a_rows int) as + declare k int; + declare w int; + begin + k=a_rows; + select v.fld_len from v_field_len v where v.rel_name=upper('t_gtt_sav_rows') into w; + while(k>0) do + begin + insert into t_gtt_sav_rows(s1) values( rpad('', :w, uuid_to_char(gen_uuid()) ) ); + if (mod(k-1, 5000) = 0) then + rdb$set_context('USER_SESSION','DBG_FILL_GTT_SAV',a_rows - k); -- to be watched in the trace log (4DEBUG) + k = k - 1; + end + rdb$set_context('USER_SESSION','DBG_FILL_GTT_SAV',a_rows); + end + ^ + set term ;^ + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import time +# from fdb import services +# from subprocess import Popen +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # Obtain engine version: +# engine = str(db_conn.engine_version) # convert to text because 'float' object has no attribute 'startswith' +# db_file = db_conn.database_name +# db_conn.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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# # Change FW to OFF in order to speed up initial data filling: +# ################## +# +# fn_nul = open(os.devnull, 'w') +# +# subprocess.call([ context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "prp_write_mode", "prp_wm_async", +# "dbname", db_file ], +# stdout = fn_nul, +# stderr = subprocess.STDOUT +# ) +# +# fn_nul.close() +# +# +# +# # ::: NB ::: Trace config file format in 3.0 differs from 2.5 one: +# # 1) header section must be enclosed in "[" and "]", +# # 2) parameter-value pairs must be separated with '=' sign: +# # services +# # { +# # parameter = value +# # } +# +# if engine.startswith('2.5'): +# txt = '''# Generated auto, do not edit! +# +# enabled false +# +# +# +# enabled true +# time_threshold 0 +# log_transactions true +# log_initfini false +# print_perf true +# +# ''' +# else: +# txt = '''# Generated auto, do not edit! +# database=%[\\\\\\\\/]security?.fdb +# { +# enabled = false +# } +# database=%[\\\\\\\\/]bugs.core_3537.fdb +# { +# enabled = true +# time_threshold = 0 +# log_transactions = true +# print_perf = true +# +# #log_connections = true +# #log_context = true +# log_initfini = false +# } +# ''' +# +# f_trc_cfg=open( os.path.join(context['temp_directory'],'tmp_trace_3537.cfg'), 'w') +# f_trc_cfg.write(txt) +# flush_and_close( f_trc_cfg ) +# +# ############################ +# NUM_ROWS_TO_BE_ADDED = 45000 +# ############################ +# +# con1 = fdb.connect(dsn=dsn) +# cur1=con1.cursor() +# +# # Make initial data filling into PERMANENT table for retrieving later number of data pages +# # (it should be the same for any kind of tables, including GTTs): +# cur1.callproc('sp_fill_fix_tab', (NUM_ROWS_TO_BE_ADDED,)) +# con1.commit() +# con1.close() +# +# # ############################################################## +# # S T A R T T R A C E i n S E P A R A T E P R O C E S S +# # ############################################################## +# +# f_trc_log=open( os.path.join(context['temp_directory'],'tmp_trace_3537.log'), "w") +# f_trc_err=open( os.path.join(context['temp_directory'],'tmp_trace_3537.err'), "w") +# +# p_trace = Popen( [ context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_start' , 'trc_cfg', f_trc_cfg.name],stdout=f_trc_log,stderr=f_trc_err) +# +# time.sleep(1) +# +# con1 = fdb.connect(dsn=dsn) +# cur1=con1.cursor() +# cur1.callproc('sp_fill_gtt_sav_rows', (NUM_ROWS_TO_BE_ADDED,)) +# con1.rollback() +# con1.close() +# +# con1 = fdb.connect(dsn=dsn) +# cur1=con1.cursor() +# cur1.callproc('sp_fill_gtt_del_rows', (NUM_ROWS_TO_BE_ADDED,)) +# con1.rollback() +# con1.close() +# +# +# # #################################################### +# # G E T A C T I V E T R A C E S E S S I O N I D +# # #################################################### +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# +# f_trc_lst = open( os.path.join(context['temp_directory'],'tmp_trace_3537.lst'), 'w') +# subprocess.call([context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_list'], stdout=f_trc_lst) +# flush_and_close( f_trc_lst ) +# +# # !!! DO NOT REMOVE THIS LINE !!! +# time.sleep(1) +# +# trcssn=0 +# with open( f_trc_lst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# f.close() +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# +# # #################################################### +# # S E N D R E Q U E S T T R A C E T O S T O P +# # #################################################### +# if trcssn>0: +# fn_nul = open(os.devnull, 'w') +# subprocess.call([context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_stop','trc_id', trcssn], stdout=fn_nul) +# fn_nul.close() +# # DO NOT REMOVE THIS LINE: +# time.sleep(2) +# +# +# p_trace.terminate() +# flush_and_close( f_trc_log ) +# flush_and_close( f_trc_err ) +# +# ################### +# # Obtain statistics for table T_FIX_TAB in order to estimate numberof data pages +# ################### +# +# f_stat_log = open( os.path.join(context['temp_directory'],'tmp_stat_3537.log'), 'w') +# f_stat_err = open( os.path.join(context['temp_directory'],'tmp_stat_3537.err'), 'w') +# +# subprocess.call( [ context['gstat_path'], dsn, "-t", 't_fix_tab'.upper() ], +# stdout = f_stat_log, +# stderr = f_stat_err +# ) +# flush_and_close( f_stat_log ) +# flush_and_close( f_stat_err ) +# +# # Following files should be EMPTY: +# ################# +# +# f_list=[f_stat_err, f_trc_err] +# for i in range(len(f_list)): +# f_name=f_list[i].name +# if os.path.getsize(f_name) > 0: +# with open( f_name,'r') as f: +# for line in f: +# print("Unexpected STDERR, file "+f_name+": "+line) +# +# +# dp_cnt = -1 +# with open( f_stat_log.name,'r') as f: +# for line in f: +# if 'data pages' in line.lower(): +# # Data pages: 1098, data page slots: 1098, average fill: 74% ==> 1098 +# dp_cnt = int(line.replace(',',' ').split()[2]) +# +# gtt_sav_fetches=-1 +# gtt_sav_marks = -1 +# gtt_del_fetches=-1 +# gtt_del_marks = -1 +# gtt_del_trace = '' +# gtt_sav_trace = '' +# +# with open( f_trc_log.name,'r') as f: +# for line in f: +# if 'fetch' in line: +# # 2.5.7: +# # ['370', 'ms,', '1100', 'read(s),', '1358', 'write(s),', '410489', 'fetch(es),', '93294', 'mark(s)'] +# # ['2', 'ms,', '1', 'read(s),', '257', 'write(s),', '1105', 'fetch(es),', '1102', 'mark(s)'] +# # 3.0.2: +# # 618 ms, 1 read(s), 2210 write(s), 231593 fetch(es), 92334 mark(s) +# # 14 ms, 1109 write(s), 7 fetch(es), 4 mark(s) +# words = line.split() +# for k in range(len(words)): +# if words[k].startswith('fetch'): +# if gtt_sav_fetches == -1: +# gtt_sav_fetches = int( words[k-1] ) +# gtt_sav_trace = line.strip() +# else: +# gtt_del_fetches = int( words[k-1] ) +# gtt_del_trace = line.strip() +# +# if words[k].startswith('mark'): +# if gtt_sav_marks==-1: +# gtt_sav_marks = int( words[k-1] ) +# else: +# gtt_del_marks = int( words[k-1] ) +# +# # 2.5.7 3.0.2, 4.0.0 +# # --------------------- +# ''' +# ratio_fetches_to_row_count_for_GTT_PRESERVE_ROWS = (1.00 * gtt_sav_fetches / NUM_ROWS_TO_BE_ADDED, 9.1219, 5.1465 ) +# ratio_fetches_to_row_count_for_GTT_DELETE_ROWS = (1.00 * gtt_del_fetches / NUM_ROWS_TO_BE_ADDED, 0.0245, 0.00015 ) +# ratio_marks_to_row_count_for_GTT_PRESERVE_ROWS = (1.00 * gtt_sav_marks / NUM_ROWS_TO_BE_ADDED, 2.0732, 2.05186 ) +# ratio_marks_to_row_count_for_GTT_DELETE_ROWS = (1.00 * gtt_del_marks / NUM_ROWS_TO_BE_ADDED, 0.0245, 0.000089 ) +# +# ratio_fetches_to_datapages_for_GTT_PRESERVE_ROWS = (1.00 * gtt_sav_fetches / dp_cnt, 373.85, 209.776 ) +# ratio_fetches_to_datapages_for_GTT_DELETE_ROWS = (1.00 * gtt_del_fetches / dp_cnt, 1.0063, 0.00634 ) +# ratio_marks_to_datapages_for_GTT_PRESERVE_ROWS = (1.00 * gtt_sav_marks / dp_cnt, 84.9672, 83.6358 ) +# ratio_marks_to_datapages_for_GTT_DELETE_ROWS = (1.00 * gtt_del_marks / dp_cnt, 1.0036, 0.00362 ) +# ''' +# # 2.5.7 3.0.2, 4.0.0 +# # ------------------------ +# check_data={ +# 'ratio_fetches_to_row_count_for_GTT_PRESERVE_ROWS' : (1.00 * gtt_sav_fetches / NUM_ROWS_TO_BE_ADDED, 9.1219, 5.1465 ) +# ,'ratio_fetches_to_row_count_for_GTT_DELETE_ROWS' : (1.00 * gtt_del_fetches / NUM_ROWS_TO_BE_ADDED, 0.0245, 0.00015 ) +# ,'ratio_marks_to_row_count_for_GTT_PRESERVE_ROWS' : (1.00 * gtt_sav_marks / NUM_ROWS_TO_BE_ADDED, 2.0732, 2.05186 ) +# ,'ratio_marks_to_row_count_for_GTT_DELETE_ROWS' : (1.00 * gtt_del_marks / NUM_ROWS_TO_BE_ADDED, 0.0245, 0.000089 ) +# ,'ratio_fetches_to_datapages_for_GTT_PRESERVE_ROWS' : (1.00 * gtt_sav_fetches / dp_cnt, 373.85, 209.776 ) +# ,'ratio_fetches_to_datapages_for_GTT_DELETE_ROWS' : (1.00 * gtt_del_fetches / dp_cnt, 1.0063, 0.00634 ) +# ,'ratio_marks_to_datapages_for_GTT_PRESERVE_ROWS' : (1.00 * gtt_sav_marks / dp_cnt, 84.9672, 83.6358 ) +# ,'ratio_marks_to_datapages_for_GTT_DELETE_ROWS' : (1.00 * gtt_del_marks / dp_cnt, 1.0036, 0.00362 ) +# } +# +# +# i = 1 if engine.startswith('2.5') else 2 +# +# MAX_DIFF_PERCENT=5.00 +# # ^ +# ############################# +# ### T H R E S H O L D ### +# ############################# +# +# fail = False +# for k, v in sorted(check_data.iteritems()): +# msg = ( 'Check ' + k + ': ' + +# ( 'OK' if v[i] * ((100 - MAX_DIFF_PERCENT)/100) <= v[0] <= v[i] * (100+MAX_DIFF_PERCENT)/100 +# else 'value '+str(v[0])+' not in range '+str( v[i] ) + ' +/-'+str(MAX_DIFF_PERCENT)+'%' +# ) +# ) +# print(msg) +# failed_flag = ('not in range' in msg) +# +# if failed_flag: +# print('Trace for GTT PRESERVE rows: ' + gtt_sav_trace) +# print('Trace for GTT DELETE rows: ' + gtt_del_trace) +# +# # CLEANUP +# ######### +# cleanup( [i.name for i in (f_trc_cfg, f_trc_log, f_trc_err, f_stat_log, f_stat_err, f_trc_lst) ] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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 + """ + +@pytest.mark.version('>=2.5.2') +@pytest.mark.xfail +def test_core_3537_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_3545.py b/tests/bugs/test_core_3545.py new file mode 100644 index 00000000..7ca41c3a --- /dev/null +++ b/tests/bugs/test_core_3545.py @@ -0,0 +1,170 @@ +#coding:utf-8 +# +# id: bugs.core_3545 +# title: Inconsistent domain's constraint validation in PSQL +# decription: +# tracker_id: CORE-3545 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('-At block line: [\\d]+, col: [\\d]+', '-At block line')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + execute block as + begin + begin execute statement 'drop table test'; when any do begin end end + begin execute statement 'drop domain dm_text'; when any do begin end end + begin execute statement 'drop domain dm_nums'; when any do begin end end + begin execute statement 'drop collation co_nums'; when any do begin end end + end + ^ set term ;^ + commit; + + create domain dm_text varchar(2) check (value < '5'); + create collation co_nums for utf8 from unicode 'NUMERIC-SORT=1'; + create domain dm_nums varchar(3) character set utf8 check (value < '50') collate co_nums; + create table test(id int, n dm_nums); + commit; + + -- This should NOT produce error: domain 'dm_text' check text values without + -- taking in account their numeric-sort aspect, so '40' will be LESS than '5' + -- because of *alphabetical* comparison of these strings: + set term ^; + execute block as + declare v1 dm_text = '40'; + begin + end + ^ + + -- This also should NOT produce error: variable 'v1' will be implicitly casted + -- to varchar(2), i.e. '40' and then alphabetical comparison will be in action: + execute block as + declare v1 dm_text = 40; + begin + end + ^ + set term ;^ + ---------------------------------------------------------------------------------------------------------- + -- Block has been added 24.08.2015 due to message in http://sourceforge.net/p/firebird/code/62113 + -- ("Fixed (again) CORE-3545 - Inconsistent domain's constraint validation in PSQL. Related to CORE-3947") + -- See tracker message of 28/May/15 02:11 PM about trouble with accepting incorrect values. + ---------------------------------------------------------------------------------------------------------- + + set list on; + + insert into test(id, n) values(1, 4); + insert into test(id, n) values(2, 399); + insert into test(id, n) values(2, 50); + + insert into test(id, n) values(3, '4'); + insert into test(id, n) values(3,'399'); + insert into test(id, n) values(4, '50'); + + + select * from test; + commit; + + --set echo on; + + -- EB where no casting is required variables are assigned immediately to text literals. + -- Should FAIL due to "var2_assignment_without_cast = '50';" - it violates constraint of domain dm_nums + set term ^; + execute block returns(var1_assignment_without_cast dm_nums, var2_assignment_without_cast dm_nums) as + begin + var1_assignment_without_cast = '4'; + var2_assignment_without_cast = '50'; + suspend; + end + ^ + + -- EB where no casting is required variables are assigned immediately to text literals: + -- Should FAIL due to "var2_assignment_without_cast = '399';" - it violates constraint of domain dm_nums + execute block returns(var1_assignment_without_cast dm_nums, var2_assignment_without_cast dm_nums) as + begin + var1_assignment_without_cast = '4'; + var2_assignment_without_cast = '399'; + suspend; + end + ^ + + -- EB where casting to domain type (varchar) is required due to integer values in right parts. + -- Should FAIL due to "var2_cast_int_to_domain = 50;" - it violates constraint of domain dm_nums + execute block returns(var1_cast_int_to_domain dm_nums, var2_cast_int_to_domain dm_nums) as + begin + var1_cast_int_to_domain = 4; + var2_cast_int_to_domain = 50; + suspend; + end + ^ + + -- EB where casting to domain type (varchar) is required due to integer values in right parts. + -- Should FAIL due to "var2_cast_int_to_domain = 399;" - it violates constraint of domain dm_nums + execute block returns(var1_cast_int_to_domain dm_nums, var2_cast_int_to_domain dm_nums) as + begin + var1_cast_int_to_domain = 4; + var2_cast_int_to_domain = 399; + suspend; + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + N 4 + + ID 3 + N 4 + """ +expected_stderr_1 = """ + 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" + + Statement failed, SQLSTATE = 42000 + validation error for variable VAR2_ASSIGNMENT_WITHOUT_CAST, value "50" + -At block line: 4, col: 7 + + Statement failed, SQLSTATE = 42000 + validation error for variable VAR2_ASSIGNMENT_WITHOUT_CAST, value "399" + -At block line: 4, col: 7 + + Statement failed, SQLSTATE = 42000 + validation error for variable VAR2_CAST_INT_TO_DOMAIN, value "50" + -At block line: 4, col: 7 + + Statement failed, SQLSTATE = 42000 + validation error for variable VAR2_CAST_INT_TO_DOMAIN, value "399" + -At block line: 4, col: 7 + """ + +@pytest.mark.version('>=3.0') +def test_core_3545_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3546.py b/tests/bugs/test_core_3546.py new file mode 100644 index 00000000..baa45886 --- /dev/null +++ b/tests/bugs/test_core_3546.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: bugs.core_3546 +# title: Aliases for the RETURNING clause +# decription: +# tracker_id: CORE-3546 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table t(id int, x int default 123, y int default 456); + commit; + set list on; + insert into t(id) values(1) returning x+y as i234567890123456789012345678901; + insert into t(id) values(2) returning x-y "/** That's result of (x-y) **/"; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + I234567890123456789012345678901 579 + /** That's result of (x-y) **/ -333 + """ + +@pytest.mark.version('>=3.0') +def test_core_3546_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3547.py b/tests/bugs/test_core_3547.py new file mode 100644 index 00000000..a6ffccf3 --- /dev/null +++ b/tests/bugs/test_core_3547.py @@ -0,0 +1,145 @@ +#coding:utf-8 +# +# id: bugs.core_3547 +# title: Floating-point negative zero doesn't match positive zero in the index +# decription: +# tracker_id: CORE-3547 +# min_versions: ['2.5.1'] +# versions: 2.5.1, 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table t_float_no_pk (col float); + commit; + insert into t_float_no_pk (col) values (0e0); + insert into t_float_no_pk (col) values (-0e0); + commit; + + recreate table t1_double_as_pk (col double precision, constraint t1_double_pk primary key(col) using index t1_double_pk); + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select count(*) "where id = 0" from rdb$relations where rdb$relation_id = 0; + select count(*) "where id = 0e0" from rdb$relations where rdb$relation_id = 0e0; + select count(*) "where id = (1e0 - 1e0)" from rdb$relations where rdb$relation_id = (1e0 - 1e0); + select count(*) "where id = -0e0" from rdb$relations where rdb$relation_id = -0e0; + select count(*) "where id = -(1e0 - 1e0)" from rdb$relations where rdb$relation_id = -(1e0 - 1e0); + select count(*) "where 0e0 = -0e0" from rdb$database where 0e0 = -0e0; + + insert into t1_double_as_pk (col) values (0e0); + commit; + insert into t1_double_as_pk (col) values (-0e0); + commit; + select count(distinct col) "t_float_no_pk: count(dist col)" from t_float_no_pk; + select count(*) "t_double_pk: col, count(*)" from t1_double_as_pk group by col; + -- :: NB ::: Problematic key representaion for 0e0 differ in Windows vs Linux! + -- NIX: -Problematic key value is ("COL" = 0.000000000000000) + -- WIN: -Problematic key value is ("COL" = 0.0000000000000000) + -- ^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + where id = 0 1 + where id = 0e0 1 + where id = (1e0 - 1e0) 1 + where id = -0e0 1 + where id = -(1e0 - 1e0) 1 + where 0e0 = -0e0 1 + t_float_no_pk: count(dist col) 1 + t_double_pk: col, count(*) 1 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "T1_DOUBLE_PK" on table "T1_DOUBLE_AS_PK" + -Problematic key value is ("COL" = 0.0000000000000000) + """ + +@pytest.mark.version('>=2.5.1,<2.5.1') +@pytest.mark.platform('Windows') +def test_core_3547_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 2.5.1 +# resources: None + +substitutions_2 = [] + +init_script_2 = """ + recreate table t_float_no_pk (col float); + commit; + insert into t_float_no_pk (col) values (0e0); + insert into t_float_no_pk (col) values (-0e0); + commit; + + recreate table t1_double_as_pk (col double precision, constraint t1_double_pk primary key(col) using index t1_double_pk); + commit; + """ + +db_2 = db_factory(page_size=4096, sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set list on; + select count(*) "where id = 0" from rdb$relations where rdb$relation_id = 0; + select count(*) "where id = 0e0" from rdb$relations where rdb$relation_id = 0e0; + select count(*) "where id = (1e0 - 1e0)" from rdb$relations where rdb$relation_id = (1e0 - 1e0); + select count(*) "where id = -0e0" from rdb$relations where rdb$relation_id = -0e0; + select count(*) "where id = -(1e0 - 1e0)" from rdb$relations where rdb$relation_id = -(1e0 - 1e0); + select count(*) "where 0e0 = -0e0" from rdb$database where 0e0 = -0e0; + + insert into t1_double_as_pk (col) values (0e0); + commit; + insert into t1_double_as_pk (col) values (-0e0); + commit; + select count(distinct col) "t_float_no_pk: count(dist col)" from t_float_no_pk; + select count(*) "t_double_pk: col, count(*)" from t1_double_as_pk group by col; + -- :: NB ::: Problematic key representaion for 0e0 differ in Windows vs Linux! + -- NIX: -Problematic key value is ("COL" = 0.000000000000000) + -- WIN: -Problematic key value is ("COL" = 0.0000000000000000) + -- ^ + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + where id = 0 1 + where id = 0e0 1 + where id = (1e0 - 1e0) 1 + where id = -0e0 1 + where id = -(1e0 - 1e0) 1 + where 0e0 = -0e0 1 + t_float_no_pk: count(dist col) 1 + t_double_pk: col, count(*) 1 + """ +expected_stderr_2 = """ + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "T1_DOUBLE_PK" on table "T1_DOUBLE_AS_PK" + -Problematic key value is ("COL" = 0.000000000000000) + """ + +@pytest.mark.version('>=2.5.1') +@pytest.mark.platform('Linux', 'MacOS', 'Solaris', 'FreeBSD', 'HP-UX') +def test_core_3547_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_expected_stderr == act_2.clean_stderr + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/bugs/test_core_3548.py b/tests/bugs/test_core_3548.py new file mode 100644 index 00000000..92024bce --- /dev/null +++ b/tests/bugs/test_core_3548.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: bugs.core_3548 +# title: GFIX returns an error after correctly shutting down a database +# decription: Affected only local connections +# tracker_id: CORE-3548 +# min_versions: ['2.5.5'] +# versions: 2.5.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.5 +# resources: None + +substitutions_1 = [('^((?!Attribute|connection).)*$', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# db_conn.close() +# runProgram('gfix',['$(DATABASE_LOCATION)bugs.core_3548.fdb','-shut','full','-force','0','-user',user_name,'-password',user_password]) +# runProgram('gstat',['$(DATABASE_LOCATION)bugs.core_3548.fdb','-h','-user',user_name,'-password',user_password]) +# runProgram('gfix',['$(DATABASE_LOCATION)bugs.core_3548.fdb','-online','-user',user_name,'-password',user_password]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Attributes force write, full shutdown + """ + +@pytest.mark.version('>=2.5.5') +@pytest.mark.xfail +def test_core_3548_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_3549.py b/tests/bugs/test_core_3549.py new file mode 100644 index 00000000..99e5aa7d --- /dev/null +++ b/tests/bugs/test_core_3549.py @@ -0,0 +1,74 @@ +#coding:utf-8 +# +# id: bugs.core_3549 +# title: Database corruption after end of session : page xxx is of wrong type expected 4 found 7 +# decription: +# tracker_id: CORE-3549 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- NOTE: could NOT reproduce on official 2.5.1 (WI-V2.5.1.26351, issued 03-oct-2011). + -- Fix for this ticket in 2.5.1 was before official 2.5.1 release: 17-jul-2011, rev. 53327 + set list on; + select rdb$page_type pg_type, count(distinct rdb$page_sequence) pg_seq_distinct + from rdb$pages + where rdb$relation_id = 0 and rdb$page_type=3 -- page_type = '3' --> TIP + group by 1; + + commit; + set autoddl off; + create global temporary table gtt_test(x int) on commit preserve rows; + create index gtt_test_x on gtt_test(x); + commit; + + set term ^; + execute block as + declare variable i integer = 0; + begin + while (i < 16384) do -- start page_size * 4 transactions + begin + in autonomous transaction do + execute statement 'insert into gtt_test values (1)'; + i = i + 1; + end + end + ^ + set term ;^ + + select rdb$page_type pg_type, count(distinct rdb$page_sequence) pg_seq_distinct + from rdb$pages + where rdb$relation_id = 0 and rdb$page_type=3 + group by 1; + commit; + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PG_TYPE 3 + PG_SEQ_DISTINCT 1 + PG_TYPE 3 + PG_SEQ_DISTINCT 2 + """ + +@pytest.mark.version('>=2.5.1') +def test_core_3549_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3553.py b/tests/bugs/test_core_3553.py new file mode 100644 index 00000000..741d96f5 --- /dev/null +++ b/tests/bugs/test_core_3553.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: bugs.core_3553 +# title: Nested loop plan is chosen instead of the sort merge for joining independent streams using keys of different types +# decription: +# tracker_id: CORE-3553 +# min_versions: ['2.1.5'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +select count(*) +from rdb$database d1 join rdb$database d2 + on cast(d1.rdb$relation_id as char(10)) = cast(d2.rdb$relation_id as char(20)); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +PLAN HASH (D2 NATURAL, D1 NATURAL) + + COUNT +===================== + 1 + +""" + +@pytest.mark.version('>=3.0') +def test_core_3553_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3554.py b/tests/bugs/test_core_3554.py new file mode 100644 index 00000000..d7f0bb49 --- /dev/null +++ b/tests/bugs/test_core_3554.py @@ -0,0 +1,117 @@ +#coding:utf-8 +# +# id: bugs.core_3554 +# title: Server crashes during prepare or throws incorrect parsing error if the remotely passed SQL query is empty +# decription: +# Checked on: +# 4.0.0.1635 SS: 1.364s. +# 4.0.0.1633 CS: 1.674s. +# 3.0.5.33180 SS: 0.822s. +# 3.0.5.33178 CS: 1.233s. +# +# tracker_id: CORE-3554 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('Data source : Firebird::localhost:.*', 'Data source : Firebird::localhost:'), ('.*Unexpected end of command.*', '.*Unexpected end of command'), ('-At block line: [\\d]+, col: [\\d]+', '-At block line')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- See issues in ticket: + -- "application either passes the empty SQL text to prepare, or passes a "too long" SQL text (64KB or 128KB etc) + -- so its length becomes zero as a result of conversion into USHORT (unsigned 16-bit integer) which represents + -- the supported SQL text length." + -- Test was made only for 3.0 because 2.5 allows to pass in ES much longer string than 32K. + + -- 30.07.2015: at least since build #31948 first ES (which passes literal of length = 32766 bytes) no more fails. + -- Previous expected std_err: + -- Statement failed, SQLSTATE = 42000 + -- Dynamic SQL Error + -- -SQL error code = -104 + -- -String literal with 32766 bytes exceeds the maximum length of 32765 bytes + -- has been removed. + -- Also, std_err has been changed for 2nd ES (which passes empty literal). Was: + -- Statement failed, SQLSTATE = 42000 + -- Execute statement error at isc_dsql_prepare : + -- 335544608 : Unexpected end of command + -- Statement : + -- Data source : Firebird::localhost:C:\\FBTESTING\\QA\\FBT-REPO\\TMP\\E30.FDB + + set list on; + set term ^; + execute block returns(n int) as + declare b blob; + begin + -- Try to pass statement with total char length (including delimiters, `select` and `from rdb$database`) = 32766 bytes. + -- This should raise exception in 3.0: + execute statement 'select ''1qwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyq1'' from rdb$database' + on external ('localhost:'||rdb$get_context('SYSTEM','DB_NAME')) as user 'sysdba' password 'masterkey' role 'R2' + into b; + + n = octet_length(b); + suspend; + end + ^ + + execute block returns(n int) as + begin + -- Try to pass empty statement. This should raise exception, but server must not crach: + execute statement '' + on external ('localhost:'||rdb$get_context('SYSTEM','DB_NAME')) as user 'sysdba' password 'masterkey' role 'R2' + ; + 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + N 32739 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + Execute statement error at isc_dsql_prepare : + 335544569 : Dynamic SQL Error + 335544436 : SQL error code = -104 + 335544851 : Unexpected end of command - line 1, column 1 + Statement : + Data source : Firebird::localhost:C:\\MIX irebird\\QA bt-repo mp\\E30.FDB + -At block line: 4, col: 7 + """ + +@pytest.mark.version('>=3.0') +def test_core_3554_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3557.py b/tests/bugs/test_core_3557.py new file mode 100644 index 00000000..1116c7e6 --- /dev/null +++ b/tests/bugs/test_core_3557.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: bugs.core_3557 +# title: AV in engine when preparing query against dropping table +# decription: +# tracker_id: CORE-3557 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core3557.fbk', init=init_script_1) + +test_script_1 = """ + -- Confirmed for 2.5.0 only: server crashes on running the following EB. 26.02.2015 + -- All subsequent releases should produce no stdout & stderr. + set term ^; + execute block as + begin + execute statement 'drop table t'; + in autonomous transaction do + execute statement ('insert into t values (1)'); + end + ^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.1') +def test_core_3557_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_3569.py b/tests/bugs/test_core_3569.py new file mode 100644 index 00000000..55b110d3 --- /dev/null +++ b/tests/bugs/test_core_3569.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: bugs.core_3569 +# title: CHAR(32767) present in XSQLVAR with length 32765 +# decription: +# tracker_id: CORE-3569 +# min_versions: ['2.5.2'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!sqltype|literal).)*$', ''), ('[ ]+', ' '), ('[\t]*', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set sqlda_display on; + set planonly; + + select + '1qwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyq#abcdefghjklmnopqrstu012345' + from rdb$database; + + select + '1qwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyq#abcdefghjklmnopqrstu0123456' + from rdb$database; + + select + '1qwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyq#abcdefghjklmnopqrstu01234567' + from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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 + """ + +@pytest.mark.version('>=3.0') +def test_core_3569_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3579.py b/tests/bugs/test_core_3579.py new file mode 100644 index 00000000..8010cba1 --- /dev/null +++ b/tests/bugs/test_core_3579.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: bugs.core_3579 +# title: Can not drop table when computed field depends on later created another field +# decription: +# tracker_id: CORE-3579 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core3579.fbk', init=init_script_1) + +test_script_1 = """ + drop table Test; + show table; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + There are no tables in this database + """ + +@pytest.mark.version('>=2.5.2') +def test_core_3579_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_3594.py b/tests/bugs/test_core_3594.py new file mode 100644 index 00000000..bf84431a --- /dev/null +++ b/tests/bugs/test_core_3594.py @@ -0,0 +1,80 @@ +#coding:utf-8 +# +# id: bugs.core_3594 +# title: Include expected and actual string lenght into error message for sqlcode -802 +# decription: +# tracker_id: CORE-3594 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('line: .*', 'line'), ('col: .*', 'col')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter procedure sp_overflowed_1 as begin end; + set term ^; + create or alter procedure sp_detailed_info returns(msg varchar(60)) as + begin + msg = '....:....1....:....2....:....3....:....4....:....5....:....6'; + suspend; + end + ^ + + create or alter procedure sp_overflowed_1 returns(msg varchar(50)) as + begin + execute procedure sp_detailed_info returning_values msg; + suspend; + end + + ^ + create or alter procedure sp_overflowed_2 returns(msg varchar(59)) as + begin + msg = '....:....1....:....2....:....3....:....4....:....5....:....6'; + suspend; + end + ^ + set term ;^ + commit; + + set heading off; + select * from sp_overflowed_1; + select * from sp_overflowed_2; + + -- On 2.5.x info about expected and actual length is absent: + -- Statement failed, SQLSTATE = 22001 + -- arithmetic exception, numeric overflow, or string truncation + -- -string right truncation + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + 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 + + 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 + """ + +@pytest.mark.version('>=3.0') +def test_core_3594_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_3598.py b/tests/bugs/test_core_3598.py new file mode 100644 index 00000000..f80041bf --- /dev/null +++ b/tests/bugs/test_core_3598.py @@ -0,0 +1,262 @@ +#coding:utf-8 +# +# id: bugs.core_3598 +# title: TRACE: add statistics of actions that were after transaction finished +# decription: +# Test verifies only FB 3.0 and above. +# Three tables are created: permanent, GTT with on commit PRESERVE rows and on commit DELETE rows. +# +# Trace config is created with *prohibition* of any activity related to security.fdb +# but allow to log transactions-related events (commits and rollbacks) for working database. +# Trace is started before furthe actions. +# +# Then we launch ISQL and apply two DML for each of these tables: +# 1) insert row + commit; +# 2) insert row + rollback. +# +# 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. +# Checked on Windows and Linux, builds: +# 4.0.0.2377 SS: 7.741s. +# 4.0.0.2377 CS: 8.746s. +# 3.0.8.33420 SS: 6.784s. +# 3.0.8.33420 CS: 8.262s. +# +# tracker_id: CORE-3598 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table tfix(id int); + recreate global temporary table gtt_ssn(id int) on commit preserve rows; + recreate global temporary table gtt_tra(id int) on commit delete rows; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import subprocess +# from subprocess import Popen +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # Obtain engine version: +# engine = str(db_conn.engine_version) +# db_file = db_conn.database_name +# db_conn.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'): +# # 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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# # NOTES ABOUT TRACE CONFIG FOR 3.0: +# # 1) Header contains `database` clause in different format vs FB 2.5: its data must be enclosed with '{' '}' +# # 2) Name and value must be separated by EQUALITY sign ('=') in FB-3 trace.conf, otherwise we get runtime error: +# # element "<. . .>" have no attribute value set +# +# txt30 = '''# Trace config, format for 3.0. Generated auto, do not edit! +# database='%[\\\\\\\\/](security[[:digit:]].fdb)|(security.db) +# { +# enabled = false +# } +# +# database=%[\\\\\\\\/]bugs.core_3598.fdb +# { +# enabled = true +# time_threshold = 0 +# log_initfini = false +# log_transactions = true +# # log_statement_finish = true +# print_perf = true +# } +# ''' +# +# f_trccfg=open( os.path.join(context['temp_directory'],'tmp_trace_3598.cfg'), 'w') +# if engine.startswith('2.5'): +# f_trccfg.write(txt25) +# else: +# f_trccfg.write(txt30) +# flush_and_close( f_trccfg ) +# +# ##################################################### +# # Starting trace session in new child process (async.): +# +# f_trclog = open( os.path.join(context['temp_directory'],'tmp_trace_3598.log'), 'w') +# # Execute a child program in a new process, redirecting STDERR to the same target as of STDOUT: +# p_trace=Popen([context['fbsvcmgr_path'], "localhost:service_mgr", "action_trace_start", "trc_cfg", f_trccfg.name], stdout=f_trclog, stderr=subprocess.STDOUT) +# +# # Wait! Trace session is initialized not instantly! +# time.sleep(1) +# +# ##################################################### +# # Running ISQL with test commands: +# +# sqltxt=''' +# set autoddl off; +# set echo on; +# set count on; +# set bail on; +# connect '%(dsn)s'; +# insert into tfix(id) values(1); +# commit; +# insert into tfix(id) values(2); +# rollback; +# insert into gtt_ssn(id) values(1); +# commit; +# insert into gtt_ssn(id) values(2); +# rollback; +# insert into gtt_tra(id) values(1); +# commit; +# insert into gtt_tra(id) values(2); +# rollback; +# ''' % dict(globals(), **locals()) +# +# f_run_sql = open( os.path.join(context['temp_directory'],'tmp_run_5685.sql'), 'w') +# f_run_sql.write( sqltxt ) +# flush_and_close( f_run_sql ) +# +# f_run_log = open( os.path.join(context['temp_directory'],'tmp_run_5685.log'), 'w') +# +# subprocess.call( [ context['isql_path'],'-q', '-i', f_run_sql.name ], +# stdout = f_run_log, +# stderr = subprocess.STDOUT +# ) +# +# flush_and_close( f_run_log ) +# +# # do NOT remove this otherwise trace log can contain only message about its start before being closed! +# time.sleep(2) +# +# ##################################################### +# # Getting ID of launched trace session and STOP it: +# +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# f_trclst=open( os.path.join(context['temp_directory'],'tmp_trace_3598.lst'), 'w') +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", "action_trace_list"],stdout=f_trclst, stderr=subprocess.STDOUT) +# flush_and_close( f_trclst ) +# +# trcssn=0 +# with open( f_trclst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# f_trclst=open(f_trclst.name,'a') +# f_trclst.seek(0,2) +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", "action_trace_stop","trc_id",trcssn],stdout=f_trclst, stderr=subprocess.STDOUT) +# flush_and_close( f_trclst ) +# +# # 23.02.2021. DELAY FOR AT LEAST 1 SECOND REQUIRED HERE! +# # Otherwise trace log can remain empty. +# time.sleep(1) +# +# # Terminate child process of launched trace session (though it should already be killed): +# p_trace.terminate() +# flush_and_close( f_trclog ) +# +# ################################################################### +# +# # Output log of trace session, with filtering only interested info: +# +# # Pwerformance header text (all excessive spaces will be removed before comparison - see below): +# perf_header='Table Natural Index Update Insert Delete Backout Purge Expunge' +# +# checked_events= { +# ') COMMIT_TRANSACTION' : 'commit' +# ,') ROLLBACK_TRANSACTION' : 'rollback' +# ,') EXECUTE_STATEMENT' : 'execute_statement' +# ,') START_TRANSACTION' : 'start_transaction' +# } +# +# i,k = 0,0 +# watched_event = '' +# with open( f_trclog.name,'r') as f: +# for line in f: +# k += 1 +# e = ''.join( [v.upper() for x,v in checked_events.items() if x in line] ) +# watched_event = e if e else watched_event +# +# if ' ms,' in line and ('fetch' in line or 'mark' in line): # One of these *always* must be in trace statistics. +# print('Statement statistics detected for %s' % watched_event) +# i = i +1 +# if ' '.join(line.split()).upper() == ' '.join(perf_header.split()).upper(): +# print('Found performance block header') +# if line.startswith('TFIX') or line.startswith('GTT_SSN') or line.startswith('GTT_TRA'): +# print('Found table statistics for %s' % line.split()[0] ) +# +# # Cleanup: +# ########## +# time.sleep(1) +# cleanup( (f_trccfg, f_trclst,f_trclog,f_run_log,f_run_sql) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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 + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_3598_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_3599.py b/tests/bugs/test_core_3599.py new file mode 100644 index 00000000..9ad39f20 --- /dev/null +++ b/tests/bugs/test_core_3599.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: bugs.core_3599 +# title: Possible drop role RDB$ADMIN +# decription: +# tracker_id: CORE-3599 +# min_versions: ['2.5.2'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + DROP ROLE RDB$ADMIN; + COMMIT; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -DROP ROLE RDB$ADMIN failed + -Cannot delete system SQL role RDB$ADMIN + """ + +@pytest.mark.version('>=3.0') +def test_core_3599_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_3601.py b/tests/bugs/test_core_3601.py new file mode 100644 index 00000000..698b5f87 --- /dev/null +++ b/tests/bugs/test_core_3601.py @@ -0,0 +1,329 @@ +#coding:utf-8 +# +# id: bugs.core_3601 +# title: Incorrect TEXT BLOB charset transliteration on VIEW with trigger +# decription: Test for 2.5 verifies that all OK when connection charset = win1250, test for 3.0 - for connection charset = UTF8 +# tracker_id: CORE-3601 +# min_versions: ['2.5.2'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('MEMO_UTF8.*', ''), ('MEMO_WIN1250.*', '')] + +init_script_1 = """ + -- This part of test (for 3.0) should be encoded in UTF8 as for running under ISQL and under fbt-run. + recreate view v_t_test as select 1 id from rdb$database; + commit; + recreate table t_test (id int); + commit; + set term ^; + execute block as + begin + begin execute statement 'drop domain MEMO_UTF8'; when any do begin end end + begin execute statement 'drop domain MEMO_WIN1250'; when any do begin end end + begin execute statement 'drop sequence gen_test'; when any do begin end end + end + ^ set term ;^ + commit; + + create sequence gen_test; + + create domain memo_utf8 as + blob sub_type 1 segment size 100 character set utf8; + + create domain memo_win1250 as + blob sub_type 1 segment size 100 character set win1250; + commit; + + recreate table t_test ( + id bigint not null, + action varchar(80), + memo_utf8 memo_utf8, + memo_win1250 memo_win1250, + constraint pk_t_test primary key (id) + ); + commit; + + create or alter view v_t_test as + select + t.id, + t.action, + t.memo_utf8, + t.memo_win1250 + from t_test t + ; + + + set term ^ ; + create or alter trigger v_t_test_bd for v_t_test + active before insert or update or delete position 0 + as + begin + if (inserting) then + insert into t_test( + id, + action, + memo_utf8, + memo_win1250) + values( + coalesce( new.id, gen_id(gen_test,1) ), + new.action, + new.memo_utf8, + new.memo_win1250); + else if (updating) then + update t_test set + id = new.id, + action = new.action, + memo_utf8 = new.memo_utf8, + memo_win1250 = new.memo_win1250 + where id = old.id; + else + delete from t_test + where id = old.id; + end + ^ + set term ; ^ + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + execute block as + declare v_text blob sub_type 1 segment size 100 character set utf8; -- ###### B L O B C H A R S E T = U T F 8 ##### + begin + + -- http://www.columbia.edu/kermit/cp1250.html + v_text = + '' + || '€' -- 128 08/00 200 80 EURO SYMBOL + || '‚' -- 130 08/02 202 82 LOW 9 SINGLE QUOTE + || '„' -- 132 08/04 204 84 LOW 9 DOUBLE QUOTE + || '…' -- 133 08/05 205 85 ELLIPSIS + || '†' -- 134 08/06 206 86 DAGGER + || '‡' -- 135 08/07 207 87 DOUBLE DAGGER + || '‰' -- 137 08/09 211 89 PER MIL SIGN + || 'Š' -- 138 08/10 212 8A CAPITAL LETTER S WITH CARON + || '‹' -- 139 08/11 213 8B LEFT SINGLE QUOTE BRACKET + || 'Ś' -- 140 08/12 214 8C CAPITAL LETTER S WITH ACUTE ACCENT + || 'Ť' -- 141 08/13 215 8D CAPITAL LETTER T WITH CARON + || 'Ž' -- 142 08/14 216 8E CAPITAL LETTER Z WITH CARON + || 'Ź' -- 143 08/15 217 8F CAPITAL LETTER Z WITH ACUTE ACCENT + || '‘' -- 145 09/01 221 91 HIGH 6 SINGLE QUOTE + || '’' -- 146 09/02 222 92 HIGH 9 SINGLE QUOTE + || '“' -- 147 09/03 223 93 HIGH 6 DOUBLE QUOTE + || '”' -- 148 09/04 224 94 HIGH 9 DOUBLE QUOTE + || '•' -- 149 09/05 225 95 LARGE CENTERED DOT + || '–' -- 150 09/06 226 96 EN DASH + || '—' -- 151 09/07 227 97 EM DASH + || '™' -- 153 09/09 231 99 TRADEMARK SIGN + || 'š' -- 154 09/10 232 9A SMALL LETTER S WITH CARON + || '›' -- 155 09/11 233 9B RIGHT SINGLE QUOTE BRACKET + || 'ś' -- 156 09/12 234 9C SMALL LETTER S WITH ACUTE ACCENT + || 'ť' -- 157 09/13 235 9D SMALL LETTER T WITH CARON + || 'ž' -- 158 09/14 236 9E SMALL LETTER Z WITH CARON + || 'ź' -- 159 09/15 237 9F SMALL LETTER Z WITH ACUTE ACCENT + || ' ' -- 160 10/00 240 A0 NO-BREAK SPACE + || 'ˇ' -- 161 10/01 241 A1 CARON + || '˘' -- 162 10/02 242 A2 BREVE + || 'Ł' -- 163 10/03 243 A3 CAPITAL LETTER L WITH STROKE + || '¤' -- 164 10/04 244 A4 CURRENCY SIGN + || 'Ą' -- 165 10/05 245 A5 CAPITAL LETTER A WITH OGONEK + || '¦' -- 166 10/06 246 A6 BROKEN BAR + || '§' -- 167 10/07 247 A7 PARAGRAPH SIGN + || '¨' -- 168 10/08 250 A8 DIAERESIS + || '©' -- 169 10/09 251 A9 COPYRIGHT SIGN + || 'Ş' -- 170 10/10 252 AA CAPITAL LETTER S WITH CEDILLA + || '«' -- 171 10/11 253 AB LEFT ANGLE QUOTATION MARK + || '¬' -- 172 10/12 254 AC NOT SIGN + || '­' -- 173 10/13 255 AD SOFT HYPHEN + || '®' -- 174 10/14 256 AE REGISTERED TRADE MARK SIGN + || 'Ż' -- 175 10/15 257 AF CAPITAL LETTER Z WITH DOT ABOVE + || '°' -- 176 11/00 260 B0 DEGREE SIGN, RING ABOVE + || '±' -- 177 11/01 261 B1 PLUS-MINUS SIGN + || '˛' -- 178 11/02 262 B2 OGONEK + || 'ł' -- 179 11/03 263 B3 SMALL LETTER L WITH STROKE + || '´' -- 180 11/04 264 B4 ACUTE ACCENT + || 'µ' -- 181 11/05 265 B5 MICRO SIGN + || '¶' -- 182 11/06 266 B6 PILCROW SIGN + || '·' -- 183 11/07 267 B7 MIDDLE DOT + || '¸' -- 184 11/08 270 B8 CEDILLA + || 'ą' -- 185 11/09 271 B9 SMALL LETTER A WITH OGONEK + || 'ş' -- 186 11/10 272 BA SMALL LETTER S WITH CEDILLA + || '»' -- 187 11/11 273 BB RIGHT ANGLE QUOTATION MARK + || 'Ľ' -- 188 11/12 274 BC CAPITAL LETTER L WITH CARON + || '˝' -- 189 11/13 275 BD DOUBLE ACUTE ACCENT + || 'ľ' -- 190 11/14 276 BE CAPITAL LETTER I WITH CARON + || 'ż' -- 191 11/15 277 BF SMALL LETTER Z WITH DOT ABOVE + || 'Ŕ' -- 192 12/00 300 C0 CAPITAL LETTER R WITH ACUTE ACCENT + || 'Á' -- 193 12/01 301 C1 CAPITAL LETTER A WITH ACUTE ACCENT + || 'Â' -- 194 12/02 302 C2 CAPITAL LETTER A WITH CIRCUMFLEX + || 'Ă' -- 195 12/03 303 C3 CAPITAL LETTER A WITH BREVE + || 'Ä' -- 196 12/04 304 C4 CAPITAL LETTER A WITH DIAERESIS + || 'Ĺ' -- 197 12/05 305 C5 CAPITAL LETTER L WITH ACUTE ACCENT + || 'Ć' -- 198 12/06 306 C6 CAPITAL LETTER C WITH ACUTE ACCENT + || 'Ç' -- 199 12/07 307 C7 CAPITAL LETTER C WITH CEDILLA + || 'Č' -- 200 12/08 310 C8 CAPITAL LETTER C WITH CARON + || 'É' -- 201 12/09 311 C9 CAPITAL LETTER E WITH ACUTE ACCENT + || 'Ę' -- 202 12/10 312 CA CAPITAL LETTER E WITH OGONEK + || 'Ë' -- 203 12/11 313 CB CAPITAL LETTER E WITH DIAERESIS + || 'Ě' -- 204 12/12 314 CC CAPITAL LETTER E WITH CARON + || 'Í' -- 205 12/13 315 CD CAPITAL LETTER I WITH ACUTE ACCENT + || 'Î' -- 206 12/14 316 CE CAPITAL LETTER I WITH CIRCUMFLEX ACCENT + || 'Ď' -- 207 12/15 317 CF CAPITAL LETTER D WITH CARON + || 'Đ' -- 208 13/00 320 D0 CAPITAL LETTER D WITH STROKE + || 'Ń' -- 209 13/01 321 D1 CAPITAL LETTER N WITH ACUTE ACCENT + || 'Ň' -- 210 13/02 322 D2 CAPITAL LETTER N WITH CARON + || 'Ó' -- 211 13/03 323 D3 CAPITAL LETTER O WITH ACUTE ACCENT + || 'Ô' -- 212 13/04 324 D4 CAPITAL LETTER O WITH CIRCUMFLEX + || 'Ő' -- 213 13/05 325 D5 CAPITAL LETTER O WITH DOUBLE ACUTE ACCENT + || 'Ö' -- 214 13/06 326 D6 CAPITAL LETTER O WITH DIAERESIS + || '×' -- 215 13/07 327 D7 MULTIPLICATION SIGN + || 'Ř' -- 216 13/08 330 D8 CAPITAL LETTER R WITH CARON + || 'Ů' -- 217 13/09 331 D9 CAPITAL LETTER U WITH RING ABOVE + || 'Ú' -- 218 13/10 332 DA CAPITAL LETTER U WITH ACUTE ACCENT + || 'Ű' -- 219 13/11 333 DB CAPITAL LETTER U WITH DOUBLE ACUTE ACCENT + || 'Ü' -- 220 13/12 334 DC CAPITAL LETTER U WITH DIAERESIS + || 'Ý' -- 221 13/13 335 DD CAPITAL LETTER Y WITH ACUTE ACCENT + || 'Ţ' -- 222 13/14 336 DE CAPITAL LETTER T WITH CEDILLA + || 'ß' -- 223 13/15 337 DF SMALL GERMAN LETTER SHARP s + || 'ŕ' -- 224 14/00 340 E0 SMALL LETTER R WITH ACUTE ACCENT + || 'á' -- 225 14/01 341 E1 SMALL LETTER A WITH ACUTE ACCENT + || 'â' -- 226 14/02 342 E2 SMALL LETTER A WITH CIRCUMFLEX + || 'ă' -- 227 14/03 343 E3 SMALL LETTER A WITH BREVE + || 'ä' -- 228 14/04 344 E4 SMALL LETTER A WITH DIAERESIS + || 'ĺ' -- 229 14/05 345 E5 SMALL LETTER L WITH ACUTE ACCENT + || 'ć' -- 230 14/06 346 E6 SMALL LETTER C WITH ACUTE ACCENT + || 'ç' -- 231 14/07 347 E7 SMALL LETTER C WITH CEDILLA + || 'č' -- 232 14/08 350 E8 SMALL LETTER C WITH CARON + || 'é' -- 233 14/09 351 E9 SMALL LETTER E WITH ACUTE ACCENT + || 'ę' -- 234 14/10 352 EA SMALL LETTER E WITH OGONEK + || 'ë' -- 235 14/11 353 EB SMALL LETTER E WITH DIAERESIS + || 'ě' -- 236 14/12 354 EC SMALL LETTER E WITH CARON + || 'í' -- 237 14/13 355 ED SMALL LETTER I WITH ACUTE ACCENT + || 'î' -- 238 14/14 356 EE SMALL LETTER I WITH CIRCUMFLEX ACCENT + || 'ď' -- 239 14/15 357 EF SMALL LETTER D WITH CARON + || 'đ' -- 240 15/00 360 F0 SMALL LETTER D WITH STROKE + || 'ń' -- 241 15/01 361 F1 SMALL LETTER N WITH ACUTE ACCENT + || 'ň' -- 242 15/02 362 F2 SMALL LETTER N WITH CARON + || 'ó' -- 243 15/03 363 F3 SMALL LETTER O WITH ACUTE ACCENT + || 'ô' -- 244 15/04 364 F4 SMALL LETTER O WITH CIRCUMFLEX + || 'ő' -- 245 15/05 365 F5 SMALL LETTER O WITH DOUBLE ACUTE ACCENT + || 'ö' -- 246 15/06 366 F6 SMALL LETTER O WITH DIAERESIS + || '÷' -- 247 15/07 367 F7 DIVISION SIGN + || 'ř' -- 248 15/08 370 F8 SMALL LETTER R WITH CARON + || 'ů' -- 249 15/09 371 F9 SMALL LETTER U WITH RING ABOVE + || 'ú' -- 250 15/10 372 FA SMALL LETTER U WITH ACUTE ACCENT + || 'ű' -- 251 15/11 373 FB SMALL LETTER U WITH DOUBLE ACUTE ACCENT + || 'ü' -- 252 15/12 374 FC SMALL LETTER U WITH DIAERESIS + || 'ý' -- 253 15/13 375 FD SMALL LETTER Y WITH ACUTE ACCENT + || 'ţ' -- 254 15/14 376 FE SMALL LETTER T WITH CEDILLA + || '˙' -- 255 15/15 377 FF DOT ABOVE + ; + insert into t_test( + id, + action, + memo_utf8, + memo_win1250) + values( + gen_id(gen_test,1), + 'insert directly in the table, connect charset = utf8, blob charset = utf8', + :v_text, + :v_text); + + insert into v_t_test( + action, + memo_utf8, -- isc_put_segment on V_T_TEST.MEMO_UTF8 with buffer as utf-8 is OK + memo_win1250 -- isc_put_segment on V_T_TEST.MEMO_WIN1250 with buffer as utf-8 not transliterate character set and stores in table incorrect as utf-8 + ) + values( + 'insert through the view, connect charset = utf8, blob charset = utf8', + :v_text, -- to be written in memo_utf8 + :v_text -- to be written in memo_win1250 + ); + + insert into v_t_test( + action, + memo_utf8, -- isc_put_segment on V_T_TEST.MEMO_UTF8 with buffer as utf-8 is OK + memo_win1250 -- isc_put_segment on V_T_TEST.MEMO_WIN1250 with buffer as utf-8 not transliterate character set and stores in table incorrect as utf-8 + ) + values( + 'insert through the view, connect charset = utf8, blob charset = win1250', + cast( :v_text as blob sub_type 1 character set win1250), -- to be written in memo_utf8 + cast( :v_text as blob sub_type 1 character set win1250) -- to be written in memo_win1250 + ); + + end + ^ + set term ;^ + + -- Confirmed on WI-V2.5.1.26351: insert into TABLE works fine, but insert into view produces: + -- Statement failed, SQLSTATE = 22018 + -- arithmetic exception, numeric overflow, or string truncation + -- -Cannot transliterate character between character sets + -- On Win1250 connection: + + set blob all; + set list on; + select + id, + action, + memo_utf8, + octet_length(memo_utf8) oct_utf8, + char_length(memo_utf8) chr_utf8, + memo_win1250, + octet_length(memo_win1250) oct_w1250, + char_length(memo_win1250) chr_w1250 + from v_t_test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + ACTION insert directly in the table, connect charset = utf8, blob charset = utf8 + MEMO_UTF8 82:0 + €‚„…†‡‰Š‹ŚŤŽŹ‘’“”•–—™š›śťžź ˇ˘Ł¤Ą¦§¨©Ş«¬­®Ż°±˛ł´µ¶·¸ąş»Ľ˝ľżŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖ×ŘŮÚŰÜÝŢßŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙ + OCT_UTF8 262 + CHR_UTF8 123 + MEMO_WIN1250 0:17 + €‚„…†‡‰Š‹ŚŤŽŹ‘’“”•–—™š›śťžź ˇ˘Ł¤Ą¦§¨©Ş«¬­®Ż°±˛ł´µ¶·¸ąş»Ľ˝ľżŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖ×ŘŮÚŰÜÝŢßŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙ + OCT_W1250 123 + CHR_W1250 123 + + ID 2 + ACTION insert through the view, connect charset = utf8, blob charset = utf8 + MEMO_UTF8 82:3 + €‚„…†‡‰Š‹ŚŤŽŹ‘’“”•–—™š›śťžź ˇ˘Ł¤Ą¦§¨©Ş«¬­®Ż°±˛ł´µ¶·¸ąş»Ľ˝ľżŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖ×ŘŮÚŰÜÝŢßŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙ + OCT_UTF8 262 + CHR_UTF8 123 + MEMO_WIN1250 0:1e + €‚„…†‡‰Š‹ŚŤŽŹ‘’“”•–—™š›śťžź ˇ˘Ł¤Ą¦§¨©Ş«¬­®Ż°±˛ł´µ¶·¸ąş»Ľ˝ľżŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖ×ŘŮÚŰÜÝŢßŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙ + OCT_W1250 123 + CHR_W1250 123 + + ID 3 + ACTION insert through the view, connect charset = utf8, blob charset = win1250 + MEMO_UTF8 82:6 + €‚„…†‡‰Š‹ŚŤŽŹ‘’“”•–—™š›śťžź ˇ˘Ł¤Ą¦§¨©Ş«¬­®Ż°±˛ł´µ¶·¸ąş»Ľ˝ľżŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖ×ŘŮÚŰÜÝŢßŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙ + OCT_UTF8 262 + CHR_UTF8 123 + MEMO_WIN1250 0:25 + €‚„…†‡‰Š‹ŚŤŽŹ‘’“”•–—™š›śťžź ˇ˘Ł¤Ą¦§¨©Ş«¬­®Ż°±˛ł´µ¶·¸ąş»Ľ˝ľżŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖ×ŘŮÚŰÜÝŢßŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙ + OCT_W1250 123 + CHR_W1250 123 + """ + +@pytest.mark.version('>=3.0') +def test_core_3601_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3610.py b/tests/bugs/test_core_3610.py new file mode 100644 index 00000000..504ca43e --- /dev/null +++ b/tests/bugs/test_core_3610.py @@ -0,0 +1,99 @@ +#coding:utf-8 +# +# id: bugs.core_3610 +# title: Can insert DUPLICATE keys in UNIQUE index +# decription: +# Checked on: +# 4.0.0.1635 SS: 1.368s. +# 4.0.0.1633 CS: 2.094s. +# 3.0.5.33180 SS: 0.907s. +# 3.0.5.33178 CS: 1.345s. +# 2.5.9.27119 SS: 0.299s. +# 2.5.9.27146 SC: 0.294s. +# +# tracker_id: CORE-3610 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [('Data source : Firebird::localhost:.*', 'Data source : Firebird::localhost:'), ('335544382 : Problematic key', '335545072 : Problematic key'), ('-At block line: [\\d]+, col: [\\d]+', '-At block line')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test(id int not null, f01 int, constraint test_unq unique(f01) using index test_unq); + commit; + insert into test values(1, 1 ); + insert into test values(2,null); + insert into test values(3,null); + commit; + set transaction read committed record_version no wait; + update test set f01=null where id=1; + set term ^; + execute block as + begin + execute statement ('update test set f01 = ? where id = ?') (1, 3) + with autonomous transaction + on external ( 'localhost:'||rdb$get_context('SYSTEM','DB_NAME') ) + as user 'sysdba' password 'masterkey' role 'role_02' + ; + end + ^ + 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; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + F01 1 + ID 2 + F01 + ID 3 + F01 + """ +expected_stderr_1 = """ + 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: 3, col: 9 + """ + +@pytest.mark.version('>=2.5.2') +def test_core_3610_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3611.py b/tests/bugs/test_core_3611.py new file mode 100644 index 00000000..94904779 --- /dev/null +++ b/tests/bugs/test_core_3611.py @@ -0,0 +1,110 @@ +#coding:utf-8 +# +# id: bugs.core_3611 +# title: Wrong data while retrieving from CTEs (or derived tables) with same column names +# decription: +# tracker_id: CORE-3611 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table t( + tab_name char(31) character set unicode_fss, + sum1_abc int, + sum1_oth int, + sum2_abc int, + sum2_oth int + ); + commit; + + insert into t(tab_name, sum1_abc, sum1_oth) + with + fields_abc as ( + select rdb$relation_name, count(*) cnt + from rdb$relation_fields + where rdb$field_name<'rdb$d' + group by 1 + ), + fields_other as ( + select rdb$relation_name, count(*) cnt + from rdb$relation_fields + where rdb$field_name>='rdb$d' + group by 1 + ) + ,fields_all as ( + select + substring(r.rdb$relation_name from 1 for 5) tab_name, + sum(f1.cnt) sum_abc, + sum(f2.cnt) sum_other + from rdb$relations r + left join fields_abc f1 on f1.rdb$relation_name=r.rdb$relation_name + left join fields_other f2 on f2.rdb$relation_name=r.rdb$relation_name + where r.rdb$flags is null + group by 1 + ) + select tab_name, sum_abc, sum_other from fields_all + ; + + insert into t(tab_name, sum2_abc, sum2_oth) + with + fields_abc as ( + select rdb$relation_name, count(*) cnt + from rdb$relation_fields + where rdb$field_name<'rdb$d' + group by 1 + ), + fields_other as ( + select rdb$relation_name, count(*) cnt____________ + from rdb$relation_fields + where rdb$field_name>='rdb$d' + group by 1 + ) + ,fields_all as ( + select substring(r.rdb$relation_name from 1 for 5) tab_name, + sum(f1.cnt) sum_abc, + sum(f2.cnt____________) sum_other + from rdb$relations r + left join fields_abc f1 on f1.rdb$relation_name=r.rdb$relation_name + left join fields_other f2 on f2.rdb$relation_name=r.rdb$relation_name + where r.rdb$flags is null + group by 1 + ) + select tab_name, sum_abc, sum_other from fields_all + ; + commit; + + select + tab_name + ,min(sum1_abc) as sum1_abc + ,min(sum2_abc) as sum2_abc + ,min(sum1_oth) as sum1_oth + ,min(sum2_oth) as sum2_oth + from t + group by tab_name + having + min(sum1_abc) is distinct from min(sum2_abc) + or + min(sum1_oth) is distinct from min(sum2_oth) + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.2') +def test_core_3611_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_3614.py b/tests/bugs/test_core_3614.py new file mode 100644 index 00000000..beb82b44 --- /dev/null +++ b/tests/bugs/test_core_3614.py @@ -0,0 +1,127 @@ +#coding:utf-8 +# +# id: bugs.core_3614 +# title: Plan returned for query with recursive CTE return wrong count of parenthesis +# decription: +# +# tracker_id: CORE-3614 +# min_versions: ['3.0.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table test_tree( + id integer not null, + id_header integer, + constraint pk_test_tree__id primary key (id) + ); + + create index ixa_test_tree__id_header on test_tree (id_header); + commit; + + insert into test_tree values ('1', null); + insert into test_tree values ('2', null); + insert into test_tree values ('3', null); + insert into test_tree values ('4', '1'); + insert into test_tree values ('5', '4'); + insert into test_tree values ('6', '2'); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# #--------------------------------------------- +# +# 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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# sql=''' +# set planonly; +# with recursive +# r_tree as +# ( +# select tt.id as a, cast(tt.id as varchar(100)) as asum +# from test_tree tt +# where tt.id_header is null +# +# union all +# +# select tt.id as a, rt.asum || '_' || tt.id +# from test_tree tt join r_tree rt on rt.a = tt.id_header +# ) +# select * +# from r_tree rt2 join test_tree tt2 on tt2.id=rt2.a +# ; +# ''' +# f_isql_cmd=open( os.path.join(context['temp_directory'],'tmp_isql_3614.sql'), 'w') +# f_isql_cmd.write(sql) +# flush_and_close( f_isql_cmd ) +# +# f_isql_log=open( os.path.join(context['temp_directory'],'tmp_isql_3614.log'), 'w') +# +# subprocess.call( [ context['isql_path'], dsn, '-i', f_isql_cmd.name], stdout=f_isql_log, stderr=subprocess.STDOUT) +# +# flush_and_close( f_isql_log ) +# +# # Let buffer be flushed on disk before we open log and parse it: +# time.sleep(1) +# +# # For every line which contains word 'PLAN' we count number of '(' and ')' occurences: they must be equal. +# # We display difference only when it is not so, thus 'expected_stdout' section must be EMPTY. +# with open( f_isql_log.name,'r') as f: +# for line in f: +# if 'PLAN' in line and line.count( '(' ) - line.count( ')' ) != 0: +# print( 'Difference in opening vs close parenthesis: ' + str( line.count( '(' ) - line.count( ')' ) ) ) +# +# cleanup( [i.name for i in (f_isql_cmd, f_isql_log)] ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_3614_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_3617.py b/tests/bugs/test_core_3617.py new file mode 100644 index 00000000..f2e98b9d --- /dev/null +++ b/tests/bugs/test_core_3617.py @@ -0,0 +1,67 @@ +#coding:utf-8 +# +# id: bugs.core_3617 +# title: Window Function: cume_dist() +# decription: Could not find any interesting sample with this function. Decided to use string comparison with unicode_ci_ai collation. +# tracker_id: CORE-3617 +# min_versions: [] +# versions: 4.0 +# qmid: bugs.core_3617 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create domain dm_utf8 varchar(20) character set utf8 collate unicode_ci_ai; + commit; + recreate table test_ciai( id int, s dm_utf8 ); + commit; + + insert into test_ciai values(1, 'CANción'); + insert into test_ciai values(2, 'peluqueria'); + insert into test_ciai values(3, 'peluQUEría'); + insert into test_ciai values(4, 'cancíON'); + commit; + + set list on; + + select s, id, cume_dist()over(order by s) as c_dist + from test_ciai + order by cume_dist()over(order by id desc); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + S cancíON + ID 4 + C_DIST 0.5000000000000000 + + S peluQUEría + ID 3 + C_DIST 1.000000000000000 + + S peluqueria + ID 2 + C_DIST 1.000000000000000 + + S CANción + ID 1 + C_DIST 0.5000000000000000 + """ + +@pytest.mark.version('>=4.0') +def test_core_3617_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3618.py b/tests/bugs/test_core_3618.py new file mode 100644 index 00000000..2d950a90 --- /dev/null +++ b/tests/bugs/test_core_3618.py @@ -0,0 +1,167 @@ +#coding:utf-8 +# +# id: bugs.core_3618 +# title: Window Function: ntile(num_buckets integer) +# decription: +# Cheched on 4.0.0.318. +# +# tracker_id: CORE-3618 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('line \\d+, column \\d+', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test(x int, y int, unique(x,y) using index test_unq_x_y); + commit; + + insert into test values(null, null); + insert into test values(null, null); + insert into test values(null, null); + insert into test values(null, 101); + insert into test values(null, 102); + insert into test values(null, 103); + insert into test values(null, 104); + insert into test values(1111, 105); + insert into test values(1112, 106); + commit; + set list on; + -- from doc: NTILE argument is restricted to + -- integral positive literal, + -- variable (:var) + -- and DSQL parameter (question mark). + + -- This should PASS (even when argument is specified with decimal dot, but without scale): + select x,y,ntile(3.)over(order by x,y) as n from test order by x,y; + + -- This should PASS: + set term ^; + execute block as + declare n int = 3; + declare c int; + begin + select count(*) + from ( + select ntile( :n )over(order by x, y) as i from test + ) x + where x.i = :n + into c; + end + ^ + + -- This should PASS: + execute block returns(x int, y int, n int) as + begin + for + execute statement ( 'select x,y, ntile(?)over(order by x, y) from test' ) ( 2 ) + into x,y,n + do + suspend; + end^ + set term ;^ + + -- These should FAIL: + select x,y,ntile(null)over(order by x) from test; + select x,y,ntile(0)over(order by x) from test; + select x,y,ntile(-1)over(order by x) from test; + select x,y,ntile(3.0)over(order by x) from test order by x,y; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + X + Y + N 1 + X + Y + N 1 + X + Y + N 1 + X + Y 101 + N 2 + X + Y 102 + N 2 + X + Y 103 + N 2 + X + Y 104 + N 3 + X 1111 + Y 105 + N 3 + X 1112 + Y 106 + N 3 + + X + Y + N 1 + X + Y + N 1 + X + Y + N 1 + X + Y 101 + N 1 + X + Y 102 + N 1 + X + Y 103 + N 2 + X + Y 104 + N 2 + X 1111 + Y 105 + N 2 + X 1112 + Y 106 + N 2 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Token unknown - + -null + + Statement failed, SQLSTATE = 42000 + Argument #1 for NTILE must be positive + + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Token unknown - + -- + + Statement failed, SQLSTATE = 42000 + Arguments for NTILE must be integral types or NUMERIC/DECIMAL without scale + """ + +@pytest.mark.version('>=4.0') +def test_core_3618_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3625.py b/tests/bugs/test_core_3625.py new file mode 100644 index 00000000..586582c8 --- /dev/null +++ b/tests/bugs/test_core_3625.py @@ -0,0 +1,179 @@ +#coding:utf-8 +# +# id: bugs.core_3625 +# title: MON$IO_STATS doesn't report page writes performed asynchronously (at the AST level) +# decription: +# Thanks to dimitr for suggestions about how this test can be implemented. +# We have to read some part of data from table by "att_watcher", make small change in this table +# by "att_worker" and finaly do commit + once again read this table in "att_watcher". +# Counter mon$page_writes that will be obtained twise by "att_watcher" (before its two changes) +# must differ. +# +# ::: NOTE-1 ::: +# We have to analyze counter mon$page_writes for attachment that is called "att_watcher" here, +# despite that it does NOT change any in queried table! +# +# ::: NOTE-2 ::: +# Superserver should *not* be processed by this test because page cache is shared between all +# attachments thus counter mon$page_writes is NOT changed in this scenario. +# For this reason in SS we can only "simulate" proper outcome. +# We define server mode (SS/SC/CS) by queries to mon$ tables ana analyzing results, result will +# be stored in variable 'fba'. +# +# Checked on: +# 4.0.0.1740 SC: 1.228s. +# 4.0.0.1714 CS: 8.047s. +# 3.0.5.33221 SC: 2.557s. +# 3.0.6.33236 CS: 1.372s. +# 2.5.9.27149 SC: 0.218s. +# 2.5.9.27143 CS: 0.645s. +# +# +# tracker_id: CORE-3625 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [('[ ]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.close() +# +# v_check_ddl=''' +# recreate view v_check as +# select i.mon$page_writes as iostat_pg_writes +# from mon$attachments a +# left join mon$io_stats i on a.mon$stat_id = i.mon$stat_id +# where +# a.mon$attachment_id <> current_connection +# and a.mon$remote_protocol is not null +# and i.mon$stat_group = 1 -- <<< ATTACHMENTS level +# ; +# ''' +# +# # Connection-"worker": +# con1=fdb.connect( dsn = dsn ) +# #print(con1.firebird_version) +# +# con1.execute_immediate( v_check_ddl ) +# con1.commit() +# con1.execute_immediate('recreate table test(x int)') +# con1.commit() +# con1.execute_immediate('insert into test(x) values(1)') +# con1.commit() +# +# #------------------------------------------------------- +# +# # Connection-"watcher": +# con2=fdb.connect( dsn = dsn ) +# +# ############################################################### +# ### G E T S E R V E R M O D E: S S / S C / C S ? ### +# ############################################################### +# cur1 = con1.cursor() +# +# sql_mon_query=''' +# select count(distinct a.mon$server_pid), min(a.mon$remote_protocol), max(iif(a.mon$remote_protocol is null,1,0)) +# from mon$attachments a +# where a.mon$attachment_id in (%s, %s) or upper(a.mon$user) = upper('%s') +# ''' % (con1.attachment_id, con2.attachment_id, 'cache writer') +# +# cur1.execute( sql_mon_query ) +# for r in cur1.fetchall(): +# server_cnt=r[0] +# server_pro=r[1] +# cache_wrtr=r[2] +# +# if server_pro == None: +# fba='Embedded' +# elif cache_wrtr == 1: +# fba='SS' +# elif server_cnt == 2: +# fba='CS' +# else: +# +# f1=con1.db_info(fdb.isc_info_fetches) +# +# cur2=con2.cursor() +# cur2.execute('select 1 from rdb$database') +# for r in cur2.fetchall(): +# pass +# +# f2=con1.db_info(fdb.isc_info_fetches) +# +# fba = 'SC' if f1 ==f2 else 'SS' +# +# #print('Server mode: ', fba) +# cur1.close() +# +# ######################################################### +# +# if fba == 'SS': +# ### !!!!!!!!!!!!! ### +# ################## A C H T U N G ######################## +# ### !!!!!!!!!!!!! ### +# ### SUPERSERVER SHOULD *NOT* BE PROCESSED BY THIS TEST ### +# ### COUNTER MON$PAGE_WRITES IS NOT CHANGED DURING RUN, ### +# ### SO WE CAN ONLY "SIMULATE" PROPER OUTCOME FOR THIS! ### +# ############################################################# +# page_writes_at_point_2, page_writes_at_point_1 = 0,1 +# else: +# +# # Do following in connection-WATCHER: +# # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# cur2=con2.cursor() +# con1.execute_immediate('update test set x = 2 rows 1') +# +# cur2.execute('select * from v_check') # get FIRST value of mon$page_writes +# for r in cur2: +# page_writes_at_point_1 = r[0] +# +# # Again do in connection-worker: add small change to the data, +# # otherwise watcher will not get any difference in mon$page_writes: +# con1.execute_immediate('update test set x = 3 rows 1') +# +# cur2.execute('select * from test') +# for r in cur2: +# pass # print('query data:', r[0]) +# +# con2.commit() +# cur2.execute('select * from v_check') # get SECOND value of mon$page_writes +# for r in cur2: +# page_writes_at_point_2 = r[0] +# cur2.close() +# +# +# con2.close() +# con1.close() +# +# print('PAGE_WRITES DIFFERENCE SIGN: ', abs(page_writes_at_point_2 - page_writes_at_point_1) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PAGE_WRITES DIFFERENCE SIGN: 1 + """ + +@pytest.mark.version('>=2.5.2') +@pytest.mark.xfail +def test_core_3625_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_3627.py b/tests/bugs/test_core_3627.py new file mode 100644 index 00000000..e9eb8609 --- /dev/null +++ b/tests/bugs/test_core_3627.py @@ -0,0 +1,58 @@ +#coding:utf-8 +# +# id: bugs.core_3627 +# title: Server crashes with access violation when inserting row into table with unique index +# decription: +# tracker_id: CORE-3627 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Confirmed crash on WI-V2.5.1.26351: + -- Statement failed, SQLSTATE = 08006 + -- Unable to complete network request to host "localhost". + -- -Error reading data from the connection. + + recreate table testtable + ( + "ID" integer not null, + "CLASSID" integer, + primary key ("ID") + ); + insert into TestTable values(1, 1); + insert into TestTable values(2, 2); + commit; + + alter table testtable add ksgfk integer; + create unique index classidksgidx on testtable (classid, ksgfk); + + insert into testtable values(3,1,null); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + 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) + """ + +@pytest.mark.version('>=2.5.3') +def test_core_3627_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_3639.py b/tests/bugs/test_core_3639.py new file mode 100644 index 00000000..affbd95e --- /dev/null +++ b/tests/bugs/test_core_3639.py @@ -0,0 +1,630 @@ +#coding:utf-8 +# +# id: bugs.core_3639 +# title: Allow the use of multiple WHEN MATCHED / NOT MATCHED clauses in MERGE, as per the SQL 2008 specification +# decription: +# tracker_id: CORE-3639 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """ + recreate table ta(id int primary key, x int, y int); + recreate table tb(id int primary key, x int, y int); + commit; + insert into ta(id, x, y) values(1, 100, 111); + insert into ta(id, x, y) values(2, 200, 222); + insert into ta(id, x, y) values(3, 300, 333); + insert into ta(id, x, y) values(4, 400, 444); + insert into ta(id, x, y) values(5, 500, 555); + + insert into tb(id, x, y) values(1, 10, 11); + insert into tb(id, x, y) values(4, 40, 44); + insert into tb(id, x, y) values(5, 50, 55); + commit; + + recreate table s(id int, x int); + commit; + insert into s(id, x) select row_number()over(), rand()*1000000 from rdb$types; + commit; + recreate table t(id int primary key, x int); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- 1. Check ability to compile MERGE with 254 trivial `when` expressions: + -- Batch for generating SQL with MERGE and arbitrary number of WHEN sections: + -- @echo off + -- set sql=%~n0.sql + -- del %sql% 2>nul + -- set n=254 + -- echo recreate table s(id int, x int); commit;>>%sql% + -- echo insert into s(id, x) select row_number()over(), rand()*1000000 from rdb$types; commit;>>%sql% + -- echo recreate table t(id int primary key, x int); commit;>>%sql% + -- + -- echo merge into t using s on s.id = t.id>>%sql% + -- for /l %%i in (1, 1, %n%) do ( + -- echo when NOT matched and s.id = %%i then insert values(s.id, s.x^)>>%sql% + -- ) + -- echo ;>>%sql% + -- + -- + -- echo merge into t using s on s.id = t.id>>%sql% + -- for /l %%i in (1, 1, %n%) do ( + -- echo when matched and s.id = %%i then update set t.x = t.x + s.x>>%sql% + -- ) + -- echo ;>>%sql% + -- + -- echo rollback;>>%sql% + -- echo set count on;>>%sql% + -- echo select * from t;>>%sql% + -- + -- isql localhost/3333:e30 -i %sql% + + merge into t using s on s.id = t.id + when NOT matched and s.id = 1 then insert values(s.id, s.x) + when NOT matched and s.id = 2 then insert values(s.id, s.x) + when NOT matched and s.id = 3 then insert values(s.id, s.x) + when NOT matched and s.id = 4 then insert values(s.id, s.x) + when NOT matched and s.id = 5 then insert values(s.id, s.x) + when NOT matched and s.id = 6 then insert values(s.id, s.x) + when NOT matched and s.id = 7 then insert values(s.id, s.x) + when NOT matched and s.id = 8 then insert values(s.id, s.x) + when NOT matched and s.id = 9 then insert values(s.id, s.x) + when NOT matched and s.id = 10 then insert values(s.id, s.x) + when NOT matched and s.id = 11 then insert values(s.id, s.x) + when NOT matched and s.id = 12 then insert values(s.id, s.x) + when NOT matched and s.id = 13 then insert values(s.id, s.x) + when NOT matched and s.id = 14 then insert values(s.id, s.x) + when NOT matched and s.id = 15 then insert values(s.id, s.x) + when NOT matched and s.id = 16 then insert values(s.id, s.x) + when NOT matched and s.id = 17 then insert values(s.id, s.x) + when NOT matched and s.id = 18 then insert values(s.id, s.x) + when NOT matched and s.id = 19 then insert values(s.id, s.x) + when NOT matched and s.id = 20 then insert values(s.id, s.x) + when NOT matched and s.id = 21 then insert values(s.id, s.x) + when NOT matched and s.id = 22 then insert values(s.id, s.x) + when NOT matched and s.id = 23 then insert values(s.id, s.x) + when NOT matched and s.id = 24 then insert values(s.id, s.x) + when NOT matched and s.id = 25 then insert values(s.id, s.x) + when NOT matched and s.id = 26 then insert values(s.id, s.x) + when NOT matched and s.id = 27 then insert values(s.id, s.x) + when NOT matched and s.id = 28 then insert values(s.id, s.x) + when NOT matched and s.id = 29 then insert values(s.id, s.x) + when NOT matched and s.id = 30 then insert values(s.id, s.x) + when NOT matched and s.id = 31 then insert values(s.id, s.x) + when NOT matched and s.id = 32 then insert values(s.id, s.x) + when NOT matched and s.id = 33 then insert values(s.id, s.x) + when NOT matched and s.id = 34 then insert values(s.id, s.x) + when NOT matched and s.id = 35 then insert values(s.id, s.x) + when NOT matched and s.id = 36 then insert values(s.id, s.x) + when NOT matched and s.id = 37 then insert values(s.id, s.x) + when NOT matched and s.id = 38 then insert values(s.id, s.x) + when NOT matched and s.id = 39 then insert values(s.id, s.x) + when NOT matched and s.id = 40 then insert values(s.id, s.x) + when NOT matched and s.id = 41 then insert values(s.id, s.x) + when NOT matched and s.id = 42 then insert values(s.id, s.x) + when NOT matched and s.id = 43 then insert values(s.id, s.x) + when NOT matched and s.id = 44 then insert values(s.id, s.x) + when NOT matched and s.id = 45 then insert values(s.id, s.x) + when NOT matched and s.id = 46 then insert values(s.id, s.x) + when NOT matched and s.id = 47 then insert values(s.id, s.x) + when NOT matched and s.id = 48 then insert values(s.id, s.x) + when NOT matched and s.id = 49 then insert values(s.id, s.x) + when NOT matched and s.id = 50 then insert values(s.id, s.x) + when NOT matched and s.id = 51 then insert values(s.id, s.x) + when NOT matched and s.id = 52 then insert values(s.id, s.x) + when NOT matched and s.id = 53 then insert values(s.id, s.x) + when NOT matched and s.id = 54 then insert values(s.id, s.x) + when NOT matched and s.id = 55 then insert values(s.id, s.x) + when NOT matched and s.id = 56 then insert values(s.id, s.x) + when NOT matched and s.id = 57 then insert values(s.id, s.x) + when NOT matched and s.id = 58 then insert values(s.id, s.x) + when NOT matched and s.id = 59 then insert values(s.id, s.x) + when NOT matched and s.id = 60 then insert values(s.id, s.x) + when NOT matched and s.id = 61 then insert values(s.id, s.x) + when NOT matched and s.id = 62 then insert values(s.id, s.x) + when NOT matched and s.id = 63 then insert values(s.id, s.x) + when NOT matched and s.id = 64 then insert values(s.id, s.x) + when NOT matched and s.id = 65 then insert values(s.id, s.x) + when NOT matched and s.id = 66 then insert values(s.id, s.x) + when NOT matched and s.id = 67 then insert values(s.id, s.x) + when NOT matched and s.id = 68 then insert values(s.id, s.x) + when NOT matched and s.id = 69 then insert values(s.id, s.x) + when NOT matched and s.id = 70 then insert values(s.id, s.x) + when NOT matched and s.id = 71 then insert values(s.id, s.x) + when NOT matched and s.id = 72 then insert values(s.id, s.x) + when NOT matched and s.id = 73 then insert values(s.id, s.x) + when NOT matched and s.id = 74 then insert values(s.id, s.x) + when NOT matched and s.id = 75 then insert values(s.id, s.x) + when NOT matched and s.id = 76 then insert values(s.id, s.x) + when NOT matched and s.id = 77 then insert values(s.id, s.x) + when NOT matched and s.id = 78 then insert values(s.id, s.x) + when NOT matched and s.id = 79 then insert values(s.id, s.x) + when NOT matched and s.id = 80 then insert values(s.id, s.x) + when NOT matched and s.id = 81 then insert values(s.id, s.x) + when NOT matched and s.id = 82 then insert values(s.id, s.x) + when NOT matched and s.id = 83 then insert values(s.id, s.x) + when NOT matched and s.id = 84 then insert values(s.id, s.x) + when NOT matched and s.id = 85 then insert values(s.id, s.x) + when NOT matched and s.id = 86 then insert values(s.id, s.x) + when NOT matched and s.id = 87 then insert values(s.id, s.x) + when NOT matched and s.id = 88 then insert values(s.id, s.x) + when NOT matched and s.id = 89 then insert values(s.id, s.x) + when NOT matched and s.id = 90 then insert values(s.id, s.x) + when NOT matched and s.id = 91 then insert values(s.id, s.x) + when NOT matched and s.id = 92 then insert values(s.id, s.x) + when NOT matched and s.id = 93 then insert values(s.id, s.x) + when NOT matched and s.id = 94 then insert values(s.id, s.x) + when NOT matched and s.id = 95 then insert values(s.id, s.x) + when NOT matched and s.id = 96 then insert values(s.id, s.x) + when NOT matched and s.id = 97 then insert values(s.id, s.x) + when NOT matched and s.id = 98 then insert values(s.id, s.x) + when NOT matched and s.id = 99 then insert values(s.id, s.x) + when NOT matched and s.id = 100 then insert values(s.id, s.x) + when NOT matched and s.id = 101 then insert values(s.id, s.x) + when NOT matched and s.id = 102 then insert values(s.id, s.x) + when NOT matched and s.id = 103 then insert values(s.id, s.x) + when NOT matched and s.id = 104 then insert values(s.id, s.x) + when NOT matched and s.id = 105 then insert values(s.id, s.x) + when NOT matched and s.id = 106 then insert values(s.id, s.x) + when NOT matched and s.id = 107 then insert values(s.id, s.x) + when NOT matched and s.id = 108 then insert values(s.id, s.x) + when NOT matched and s.id = 109 then insert values(s.id, s.x) + when NOT matched and s.id = 110 then insert values(s.id, s.x) + when NOT matched and s.id = 111 then insert values(s.id, s.x) + when NOT matched and s.id = 112 then insert values(s.id, s.x) + when NOT matched and s.id = 113 then insert values(s.id, s.x) + when NOT matched and s.id = 114 then insert values(s.id, s.x) + when NOT matched and s.id = 115 then insert values(s.id, s.x) + when NOT matched and s.id = 116 then insert values(s.id, s.x) + when NOT matched and s.id = 117 then insert values(s.id, s.x) + when NOT matched and s.id = 118 then insert values(s.id, s.x) + when NOT matched and s.id = 119 then insert values(s.id, s.x) + when NOT matched and s.id = 120 then insert values(s.id, s.x) + when NOT matched and s.id = 121 then insert values(s.id, s.x) + when NOT matched and s.id = 122 then insert values(s.id, s.x) + when NOT matched and s.id = 123 then insert values(s.id, s.x) + when NOT matched and s.id = 124 then insert values(s.id, s.x) + when NOT matched and s.id = 125 then insert values(s.id, s.x) + when NOT matched and s.id = 126 then insert values(s.id, s.x) + when NOT matched and s.id = 127 then insert values(s.id, s.x) + when NOT matched and s.id = 128 then insert values(s.id, s.x) + when NOT matched and s.id = 129 then insert values(s.id, s.x) + when NOT matched and s.id = 130 then insert values(s.id, s.x) + when NOT matched and s.id = 131 then insert values(s.id, s.x) + when NOT matched and s.id = 132 then insert values(s.id, s.x) + when NOT matched and s.id = 133 then insert values(s.id, s.x) + when NOT matched and s.id = 134 then insert values(s.id, s.x) + when NOT matched and s.id = 135 then insert values(s.id, s.x) + when NOT matched and s.id = 136 then insert values(s.id, s.x) + when NOT matched and s.id = 137 then insert values(s.id, s.x) + when NOT matched and s.id = 138 then insert values(s.id, s.x) + when NOT matched and s.id = 139 then insert values(s.id, s.x) + when NOT matched and s.id = 140 then insert values(s.id, s.x) + when NOT matched and s.id = 141 then insert values(s.id, s.x) + when NOT matched and s.id = 142 then insert values(s.id, s.x) + when NOT matched and s.id = 143 then insert values(s.id, s.x) + when NOT matched and s.id = 144 then insert values(s.id, s.x) + when NOT matched and s.id = 145 then insert values(s.id, s.x) + when NOT matched and s.id = 146 then insert values(s.id, s.x) + when NOT matched and s.id = 147 then insert values(s.id, s.x) + when NOT matched and s.id = 148 then insert values(s.id, s.x) + when NOT matched and s.id = 149 then insert values(s.id, s.x) + when NOT matched and s.id = 150 then insert values(s.id, s.x) + when NOT matched and s.id = 151 then insert values(s.id, s.x) + when NOT matched and s.id = 152 then insert values(s.id, s.x) + when NOT matched and s.id = 153 then insert values(s.id, s.x) + when NOT matched and s.id = 154 then insert values(s.id, s.x) + when NOT matched and s.id = 155 then insert values(s.id, s.x) + when NOT matched and s.id = 156 then insert values(s.id, s.x) + when NOT matched and s.id = 157 then insert values(s.id, s.x) + when NOT matched and s.id = 158 then insert values(s.id, s.x) + when NOT matched and s.id = 159 then insert values(s.id, s.x) + when NOT matched and s.id = 160 then insert values(s.id, s.x) + when NOT matched and s.id = 161 then insert values(s.id, s.x) + when NOT matched and s.id = 162 then insert values(s.id, s.x) + when NOT matched and s.id = 163 then insert values(s.id, s.x) + when NOT matched and s.id = 164 then insert values(s.id, s.x) + when NOT matched and s.id = 165 then insert values(s.id, s.x) + when NOT matched and s.id = 166 then insert values(s.id, s.x) + when NOT matched and s.id = 167 then insert values(s.id, s.x) + when NOT matched and s.id = 168 then insert values(s.id, s.x) + when NOT matched and s.id = 169 then insert values(s.id, s.x) + when NOT matched and s.id = 170 then insert values(s.id, s.x) + when NOT matched and s.id = 171 then insert values(s.id, s.x) + when NOT matched and s.id = 172 then insert values(s.id, s.x) + when NOT matched and s.id = 173 then insert values(s.id, s.x) + when NOT matched and s.id = 174 then insert values(s.id, s.x) + when NOT matched and s.id = 175 then insert values(s.id, s.x) + when NOT matched and s.id = 176 then insert values(s.id, s.x) + when NOT matched and s.id = 177 then insert values(s.id, s.x) + when NOT matched and s.id = 178 then insert values(s.id, s.x) + when NOT matched and s.id = 179 then insert values(s.id, s.x) + when NOT matched and s.id = 180 then insert values(s.id, s.x) + when NOT matched and s.id = 181 then insert values(s.id, s.x) + when NOT matched and s.id = 182 then insert values(s.id, s.x) + when NOT matched and s.id = 183 then insert values(s.id, s.x) + when NOT matched and s.id = 184 then insert values(s.id, s.x) + when NOT matched and s.id = 185 then insert values(s.id, s.x) + when NOT matched and s.id = 186 then insert values(s.id, s.x) + when NOT matched and s.id = 187 then insert values(s.id, s.x) + when NOT matched and s.id = 188 then insert values(s.id, s.x) + when NOT matched and s.id = 189 then insert values(s.id, s.x) + when NOT matched and s.id = 190 then insert values(s.id, s.x) + when NOT matched and s.id = 191 then insert values(s.id, s.x) + when NOT matched and s.id = 192 then insert values(s.id, s.x) + when NOT matched and s.id = 193 then insert values(s.id, s.x) + when NOT matched and s.id = 194 then insert values(s.id, s.x) + when NOT matched and s.id = 195 then insert values(s.id, s.x) + when NOT matched and s.id = 196 then insert values(s.id, s.x) + when NOT matched and s.id = 197 then insert values(s.id, s.x) + when NOT matched and s.id = 198 then insert values(s.id, s.x) + when NOT matched and s.id = 199 then insert values(s.id, s.x) + when NOT matched and s.id = 200 then insert values(s.id, s.x) + when NOT matched and s.id = 201 then insert values(s.id, s.x) + when NOT matched and s.id = 202 then insert values(s.id, s.x) + when NOT matched and s.id = 203 then insert values(s.id, s.x) + when NOT matched and s.id = 204 then insert values(s.id, s.x) + when NOT matched and s.id = 205 then insert values(s.id, s.x) + when NOT matched and s.id = 206 then insert values(s.id, s.x) + when NOT matched and s.id = 207 then insert values(s.id, s.x) + when NOT matched and s.id = 208 then insert values(s.id, s.x) + when NOT matched and s.id = 209 then insert values(s.id, s.x) + when NOT matched and s.id = 210 then insert values(s.id, s.x) + when NOT matched and s.id = 211 then insert values(s.id, s.x) + when NOT matched and s.id = 212 then insert values(s.id, s.x) + when NOT matched and s.id = 213 then insert values(s.id, s.x) + when NOT matched and s.id = 214 then insert values(s.id, s.x) + when NOT matched and s.id = 215 then insert values(s.id, s.x) + when NOT matched and s.id = 216 then insert values(s.id, s.x) + when NOT matched and s.id = 217 then insert values(s.id, s.x) + when NOT matched and s.id = 218 then insert values(s.id, s.x) + when NOT matched and s.id = 219 then insert values(s.id, s.x) + when NOT matched and s.id = 220 then insert values(s.id, s.x) + when NOT matched and s.id = 221 then insert values(s.id, s.x) + when NOT matched and s.id = 222 then insert values(s.id, s.x) + when NOT matched and s.id = 223 then insert values(s.id, s.x) + when NOT matched and s.id = 224 then insert values(s.id, s.x) + when NOT matched and s.id = 225 then insert values(s.id, s.x) + when NOT matched and s.id = 226 then insert values(s.id, s.x) + when NOT matched and s.id = 227 then insert values(s.id, s.x) + when NOT matched and s.id = 228 then insert values(s.id, s.x) + when NOT matched and s.id = 229 then insert values(s.id, s.x) + when NOT matched and s.id = 230 then insert values(s.id, s.x) + when NOT matched and s.id = 231 then insert values(s.id, s.x) + when NOT matched and s.id = 232 then insert values(s.id, s.x) + when NOT matched and s.id = 233 then insert values(s.id, s.x) + when NOT matched and s.id = 234 then insert values(s.id, s.x) + when NOT matched and s.id = 235 then insert values(s.id, s.x) + when NOT matched and s.id = 236 then insert values(s.id, s.x) + when NOT matched and s.id = 237 then insert values(s.id, s.x) + when NOT matched and s.id = 238 then insert values(s.id, s.x) + when NOT matched and s.id = 239 then insert values(s.id, s.x) + when NOT matched and s.id = 240 then insert values(s.id, s.x) + when NOT matched and s.id = 241 then insert values(s.id, s.x) + when NOT matched and s.id = 242 then insert values(s.id, s.x) + when NOT matched and s.id = 243 then insert values(s.id, s.x) + when NOT matched and s.id = 244 then insert values(s.id, s.x) + when NOT matched and s.id = 245 then insert values(s.id, s.x) + when NOT matched and s.id = 246 then insert values(s.id, s.x) + when NOT matched and s.id = 247 then insert values(s.id, s.x) + when NOT matched and s.id = 248 then insert values(s.id, s.x) + when NOT matched and s.id = 249 then insert values(s.id, s.x) + when NOT matched and s.id = 250 then insert values(s.id, s.x) + when NOT matched and s.id = 251 then insert values(s.id, s.x) + when NOT matched and s.id = 252 then insert values(s.id, s.x) + when NOT matched and s.id = 253 then insert values(s.id, s.x) + when NOT matched and s.id = 254 then insert values(s.id, s.x) + ; + merge into t using s on s.id = t.id + when matched and s.id = 1 then update set t.x = t.x + s.x + when matched and s.id = 2 then update set t.x = t.x + s.x + when matched and s.id = 3 then update set t.x = t.x + s.x + when matched and s.id = 4 then update set t.x = t.x + s.x + when matched and s.id = 5 then update set t.x = t.x + s.x + when matched and s.id = 6 then update set t.x = t.x + s.x + when matched and s.id = 7 then update set t.x = t.x + s.x + when matched and s.id = 8 then update set t.x = t.x + s.x + when matched and s.id = 9 then update set t.x = t.x + s.x + when matched and s.id = 10 then update set t.x = t.x + s.x + when matched and s.id = 11 then update set t.x = t.x + s.x + when matched and s.id = 12 then update set t.x = t.x + s.x + when matched and s.id = 13 then update set t.x = t.x + s.x + when matched and s.id = 14 then update set t.x = t.x + s.x + when matched and s.id = 15 then update set t.x = t.x + s.x + when matched and s.id = 16 then update set t.x = t.x + s.x + when matched and s.id = 17 then update set t.x = t.x + s.x + when matched and s.id = 18 then update set t.x = t.x + s.x + when matched and s.id = 19 then update set t.x = t.x + s.x + when matched and s.id = 20 then update set t.x = t.x + s.x + when matched and s.id = 21 then update set t.x = t.x + s.x + when matched and s.id = 22 then update set t.x = t.x + s.x + when matched and s.id = 23 then update set t.x = t.x + s.x + when matched and s.id = 24 then update set t.x = t.x + s.x + when matched and s.id = 25 then update set t.x = t.x + s.x + when matched and s.id = 26 then update set t.x = t.x + s.x + when matched and s.id = 27 then update set t.x = t.x + s.x + when matched and s.id = 28 then update set t.x = t.x + s.x + when matched and s.id = 29 then update set t.x = t.x + s.x + when matched and s.id = 30 then update set t.x = t.x + s.x + when matched and s.id = 31 then update set t.x = t.x + s.x + when matched and s.id = 32 then update set t.x = t.x + s.x + when matched and s.id = 33 then update set t.x = t.x + s.x + when matched and s.id = 34 then update set t.x = t.x + s.x + when matched and s.id = 35 then update set t.x = t.x + s.x + when matched and s.id = 36 then update set t.x = t.x + s.x + when matched and s.id = 37 then update set t.x = t.x + s.x + when matched and s.id = 38 then update set t.x = t.x + s.x + when matched and s.id = 39 then update set t.x = t.x + s.x + when matched and s.id = 40 then update set t.x = t.x + s.x + when matched and s.id = 41 then update set t.x = t.x + s.x + when matched and s.id = 42 then update set t.x = t.x + s.x + when matched and s.id = 43 then update set t.x = t.x + s.x + when matched and s.id = 44 then update set t.x = t.x + s.x + when matched and s.id = 45 then update set t.x = t.x + s.x + when matched and s.id = 46 then update set t.x = t.x + s.x + when matched and s.id = 47 then update set t.x = t.x + s.x + when matched and s.id = 48 then update set t.x = t.x + s.x + when matched and s.id = 49 then update set t.x = t.x + s.x + when matched and s.id = 50 then update set t.x = t.x + s.x + when matched and s.id = 51 then update set t.x = t.x + s.x + when matched and s.id = 52 then update set t.x = t.x + s.x + when matched and s.id = 53 then update set t.x = t.x + s.x + when matched and s.id = 54 then update set t.x = t.x + s.x + when matched and s.id = 55 then update set t.x = t.x + s.x + when matched and s.id = 56 then update set t.x = t.x + s.x + when matched and s.id = 57 then update set t.x = t.x + s.x + when matched and s.id = 58 then update set t.x = t.x + s.x + when matched and s.id = 59 then update set t.x = t.x + s.x + when matched and s.id = 60 then update set t.x = t.x + s.x + when matched and s.id = 61 then update set t.x = t.x + s.x + when matched and s.id = 62 then update set t.x = t.x + s.x + when matched and s.id = 63 then update set t.x = t.x + s.x + when matched and s.id = 64 then update set t.x = t.x + s.x + when matched and s.id = 65 then update set t.x = t.x + s.x + when matched and s.id = 66 then update set t.x = t.x + s.x + when matched and s.id = 67 then update set t.x = t.x + s.x + when matched and s.id = 68 then update set t.x = t.x + s.x + when matched and s.id = 69 then update set t.x = t.x + s.x + when matched and s.id = 70 then update set t.x = t.x + s.x + when matched and s.id = 71 then update set t.x = t.x + s.x + when matched and s.id = 72 then update set t.x = t.x + s.x + when matched and s.id = 73 then update set t.x = t.x + s.x + when matched and s.id = 74 then update set t.x = t.x + s.x + when matched and s.id = 75 then update set t.x = t.x + s.x + when matched and s.id = 76 then update set t.x = t.x + s.x + when matched and s.id = 77 then update set t.x = t.x + s.x + when matched and s.id = 78 then update set t.x = t.x + s.x + when matched and s.id = 79 then update set t.x = t.x + s.x + when matched and s.id = 80 then update set t.x = t.x + s.x + when matched and s.id = 81 then update set t.x = t.x + s.x + when matched and s.id = 82 then update set t.x = t.x + s.x + when matched and s.id = 83 then update set t.x = t.x + s.x + when matched and s.id = 84 then update set t.x = t.x + s.x + when matched and s.id = 85 then update set t.x = t.x + s.x + when matched and s.id = 86 then update set t.x = t.x + s.x + when matched and s.id = 87 then update set t.x = t.x + s.x + when matched and s.id = 88 then update set t.x = t.x + s.x + when matched and s.id = 89 then update set t.x = t.x + s.x + when matched and s.id = 90 then update set t.x = t.x + s.x + when matched and s.id = 91 then update set t.x = t.x + s.x + when matched and s.id = 92 then update set t.x = t.x + s.x + when matched and s.id = 93 then update set t.x = t.x + s.x + when matched and s.id = 94 then update set t.x = t.x + s.x + when matched and s.id = 95 then update set t.x = t.x + s.x + when matched and s.id = 96 then update set t.x = t.x + s.x + when matched and s.id = 97 then update set t.x = t.x + s.x + when matched and s.id = 98 then update set t.x = t.x + s.x + when matched and s.id = 99 then update set t.x = t.x + s.x + when matched and s.id = 100 then update set t.x = t.x + s.x + when matched and s.id = 101 then update set t.x = t.x + s.x + when matched and s.id = 102 then update set t.x = t.x + s.x + when matched and s.id = 103 then update set t.x = t.x + s.x + when matched and s.id = 104 then update set t.x = t.x + s.x + when matched and s.id = 105 then update set t.x = t.x + s.x + when matched and s.id = 106 then update set t.x = t.x + s.x + when matched and s.id = 107 then update set t.x = t.x + s.x + when matched and s.id = 108 then update set t.x = t.x + s.x + when matched and s.id = 109 then update set t.x = t.x + s.x + when matched and s.id = 110 then update set t.x = t.x + s.x + when matched and s.id = 111 then update set t.x = t.x + s.x + when matched and s.id = 112 then update set t.x = t.x + s.x + when matched and s.id = 113 then update set t.x = t.x + s.x + when matched and s.id = 114 then update set t.x = t.x + s.x + when matched and s.id = 115 then update set t.x = t.x + s.x + when matched and s.id = 116 then update set t.x = t.x + s.x + when matched and s.id = 117 then update set t.x = t.x + s.x + when matched and s.id = 118 then update set t.x = t.x + s.x + when matched and s.id = 119 then update set t.x = t.x + s.x + when matched and s.id = 120 then update set t.x = t.x + s.x + when matched and s.id = 121 then update set t.x = t.x + s.x + when matched and s.id = 122 then update set t.x = t.x + s.x + when matched and s.id = 123 then update set t.x = t.x + s.x + when matched and s.id = 124 then update set t.x = t.x + s.x + when matched and s.id = 125 then update set t.x = t.x + s.x + when matched and s.id = 126 then update set t.x = t.x + s.x + when matched and s.id = 127 then update set t.x = t.x + s.x + when matched and s.id = 128 then update set t.x = t.x + s.x + when matched and s.id = 129 then update set t.x = t.x + s.x + when matched and s.id = 130 then update set t.x = t.x + s.x + when matched and s.id = 131 then update set t.x = t.x + s.x + when matched and s.id = 132 then update set t.x = t.x + s.x + when matched and s.id = 133 then update set t.x = t.x + s.x + when matched and s.id = 134 then update set t.x = t.x + s.x + when matched and s.id = 135 then update set t.x = t.x + s.x + when matched and s.id = 136 then update set t.x = t.x + s.x + when matched and s.id = 137 then update set t.x = t.x + s.x + when matched and s.id = 138 then update set t.x = t.x + s.x + when matched and s.id = 139 then update set t.x = t.x + s.x + when matched and s.id = 140 then update set t.x = t.x + s.x + when matched and s.id = 141 then update set t.x = t.x + s.x + when matched and s.id = 142 then update set t.x = t.x + s.x + when matched and s.id = 143 then update set t.x = t.x + s.x + when matched and s.id = 144 then update set t.x = t.x + s.x + when matched and s.id = 145 then update set t.x = t.x + s.x + when matched and s.id = 146 then update set t.x = t.x + s.x + when matched and s.id = 147 then update set t.x = t.x + s.x + when matched and s.id = 148 then update set t.x = t.x + s.x + when matched and s.id = 149 then update set t.x = t.x + s.x + when matched and s.id = 150 then update set t.x = t.x + s.x + when matched and s.id = 151 then update set t.x = t.x + s.x + when matched and s.id = 152 then update set t.x = t.x + s.x + when matched and s.id = 153 then update set t.x = t.x + s.x + when matched and s.id = 154 then update set t.x = t.x + s.x + when matched and s.id = 155 then update set t.x = t.x + s.x + when matched and s.id = 156 then update set t.x = t.x + s.x + when matched and s.id = 157 then update set t.x = t.x + s.x + when matched and s.id = 158 then update set t.x = t.x + s.x + when matched and s.id = 159 then update set t.x = t.x + s.x + when matched and s.id = 160 then update set t.x = t.x + s.x + when matched and s.id = 161 then update set t.x = t.x + s.x + when matched and s.id = 162 then update set t.x = t.x + s.x + when matched and s.id = 163 then update set t.x = t.x + s.x + when matched and s.id = 164 then update set t.x = t.x + s.x + when matched and s.id = 165 then update set t.x = t.x + s.x + when matched and s.id = 166 then update set t.x = t.x + s.x + when matched and s.id = 167 then update set t.x = t.x + s.x + when matched and s.id = 168 then update set t.x = t.x + s.x + when matched and s.id = 169 then update set t.x = t.x + s.x + when matched and s.id = 170 then update set t.x = t.x + s.x + when matched and s.id = 171 then update set t.x = t.x + s.x + when matched and s.id = 172 then update set t.x = t.x + s.x + when matched and s.id = 173 then update set t.x = t.x + s.x + when matched and s.id = 174 then update set t.x = t.x + s.x + when matched and s.id = 175 then update set t.x = t.x + s.x + when matched and s.id = 176 then update set t.x = t.x + s.x + when matched and s.id = 177 then update set t.x = t.x + s.x + when matched and s.id = 178 then update set t.x = t.x + s.x + when matched and s.id = 179 then update set t.x = t.x + s.x + when matched and s.id = 180 then update set t.x = t.x + s.x + when matched and s.id = 181 then update set t.x = t.x + s.x + when matched and s.id = 182 then update set t.x = t.x + s.x + when matched and s.id = 183 then update set t.x = t.x + s.x + when matched and s.id = 184 then update set t.x = t.x + s.x + when matched and s.id = 185 then update set t.x = t.x + s.x + when matched and s.id = 186 then update set t.x = t.x + s.x + when matched and s.id = 187 then update set t.x = t.x + s.x + when matched and s.id = 188 then update set t.x = t.x + s.x + when matched and s.id = 189 then update set t.x = t.x + s.x + when matched and s.id = 190 then update set t.x = t.x + s.x + when matched and s.id = 191 then update set t.x = t.x + s.x + when matched and s.id = 192 then update set t.x = t.x + s.x + when matched and s.id = 193 then update set t.x = t.x + s.x + when matched and s.id = 194 then update set t.x = t.x + s.x + when matched and s.id = 195 then update set t.x = t.x + s.x + when matched and s.id = 196 then update set t.x = t.x + s.x + when matched and s.id = 197 then update set t.x = t.x + s.x + when matched and s.id = 198 then update set t.x = t.x + s.x + when matched and s.id = 199 then update set t.x = t.x + s.x + when matched and s.id = 200 then update set t.x = t.x + s.x + when matched and s.id = 201 then update set t.x = t.x + s.x + when matched and s.id = 202 then update set t.x = t.x + s.x + when matched and s.id = 203 then update set t.x = t.x + s.x + when matched and s.id = 204 then update set t.x = t.x + s.x + when matched and s.id = 205 then update set t.x = t.x + s.x + when matched and s.id = 206 then update set t.x = t.x + s.x + when matched and s.id = 207 then update set t.x = t.x + s.x + when matched and s.id = 208 then update set t.x = t.x + s.x + when matched and s.id = 209 then update set t.x = t.x + s.x + when matched and s.id = 210 then update set t.x = t.x + s.x + when matched and s.id = 211 then update set t.x = t.x + s.x + when matched and s.id = 212 then update set t.x = t.x + s.x + when matched and s.id = 213 then update set t.x = t.x + s.x + when matched and s.id = 214 then update set t.x = t.x + s.x + when matched and s.id = 215 then update set t.x = t.x + s.x + when matched and s.id = 216 then update set t.x = t.x + s.x + when matched and s.id = 217 then update set t.x = t.x + s.x + when matched and s.id = 218 then update set t.x = t.x + s.x + when matched and s.id = 219 then update set t.x = t.x + s.x + when matched and s.id = 220 then update set t.x = t.x + s.x + when matched and s.id = 221 then update set t.x = t.x + s.x + when matched and s.id = 222 then update set t.x = t.x + s.x + when matched and s.id = 223 then update set t.x = t.x + s.x + when matched and s.id = 224 then update set t.x = t.x + s.x + when matched and s.id = 225 then update set t.x = t.x + s.x + when matched and s.id = 226 then update set t.x = t.x + s.x + when matched and s.id = 227 then update set t.x = t.x + s.x + when matched and s.id = 228 then update set t.x = t.x + s.x + when matched and s.id = 229 then update set t.x = t.x + s.x + when matched and s.id = 230 then update set t.x = t.x + s.x + when matched and s.id = 231 then update set t.x = t.x + s.x + when matched and s.id = 232 then update set t.x = t.x + s.x + when matched and s.id = 233 then update set t.x = t.x + s.x + when matched and s.id = 234 then update set t.x = t.x + s.x + when matched and s.id = 235 then update set t.x = t.x + s.x + when matched and s.id = 236 then update set t.x = t.x + s.x + when matched and s.id = 237 then update set t.x = t.x + s.x + when matched and s.id = 238 then update set t.x = t.x + s.x + when matched and s.id = 239 then update set t.x = t.x + s.x + when matched and s.id = 240 then update set t.x = t.x + s.x + when matched and s.id = 241 then update set t.x = t.x + s.x + when matched and s.id = 242 then update set t.x = t.x + s.x + when matched and s.id = 243 then update set t.x = t.x + s.x + when matched and s.id = 244 then update set t.x = t.x + s.x + when matched and s.id = 245 then update set t.x = t.x + s.x + when matched and s.id = 246 then update set t.x = t.x + s.x + when matched and s.id = 247 then update set t.x = t.x + s.x + when matched and s.id = 248 then update set t.x = t.x + s.x + when matched and s.id = 249 then update set t.x = t.x + s.x + when matched and s.id = 250 then update set t.x = t.x + s.x + when matched and s.id = 251 then update set t.x = t.x + s.x + when matched and s.id = 252 then update set t.x = t.x + s.x + when matched and s.id = 253 then update set t.x = t.x + s.x + when matched and s.id = 254 then update set t.x = t.x + s.x + ; + rollback; + set count on; + select * from t; + set count off; + + -- 2. Check correctness of results: + select * from tb; + merge into tb t + using ta s + on s.id = t.id + when matched and t.id < 2 then delete + when matched then update set t.x = t.x + s.x, t.y = t.y - s.y + when not matched and s.x < 250 then insert values(-s.id, s.x, s.y) + when not matched then insert values(s.id, s.x, s.y) + ; + select * from tb; + rollback; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + + ID X Y + ============ ============ ============ + 1 10 11 + 4 40 44 + 5 50 55 + + + ID X Y + ============ ============ ============ + 4 440 -400 + 5 550 -500 + -2 200 222 + 3 300 333 + """ + +@pytest.mark.version('>=3.0') +def test_core_3639_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3647.py b/tests/bugs/test_core_3647.py new file mode 100644 index 00000000..dcc33e30 --- /dev/null +++ b/tests/bugs/test_core_3647.py @@ -0,0 +1,293 @@ +#coding:utf-8 +# +# id: bugs.core_3647 +# title: Window Function: frame (rows / range) clause +# decription: +# I decided to compare results with some trivial tests that can be found in WWW for old Oracle SCOTT scheme. +# DDL and data for this can be found in several places, e.g.: +# * https://code.google.com/archive/p/adf-samples-demos/downloads +# * http://www.orafaq.com/wiki/SCOTT +# * http://www.sql.ru/forum/26520/shema-scott-a +# +# Note that sources contain different values for EMP.HIRE_DATE for two records +# with empno = 7788 and 7876 ('Scott' and 'Adams'). +# Also, some sources can contain for record with empno = 7839 ('king') field emp.comm = 0 or null. +# This script uses following values: +# scott: hiredate = 09-dec-1982; adams: hireate = 12-jan-1983; king: comm = null. +# +# If some other tests of window (analytical) functions will require the same script +# this DDL will be moved to separate .fbk for sharing between them. +# +# Checked on WI-T4.0.0.356 +# 21.12.2020: added 'EMPNO' (primary key column) to ORDER BY list inside OVER() clauses. +# Otherwise records in 'sample2-a' can appear in unpredictable order. +# Checked on: 4.0.0.2300, 4.0.0.2296 +# +# tracker_id: CORE-3647 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """ + recreate table emp (id int); + recreate table dept (id int); + commit; + + set term ^; + execute block as + begin + begin + execute statement 'drop sequence emp_table_seq'; + when any do begin end + end + begin + execute statement 'drop sequence dept_table_seq'; + when any do begin end + end + end + ^ + set term ;^ + commit; + + create sequence emp_table_seq start with 1000; + create sequence dept_table_seq start with 41; + + recreate table dept ( + deptno smallint, + dname varchar(14), + loc varchar(13), + constraint dept_pk primary key (deptno) + ); + + insert into dept values (10, 'accounting', 'new york'); + insert into dept values (20, 'research', 'dallas'); + insert into dept values (30, 'sales', 'chicago'); + insert into dept values (40, 'operations', 'boston'); + commit; + + recreate table emp ( + empno smallint not null, + ename varchar(10), + job varchar(9), + mgr smallint, + hiredate date, + sal numeric(7, 2), + comm numeric(7, 2), + deptno smallint, + constraint employee_pk primary key (empno), + constraint works_in_dept foreign key (deptno) references dept on delete set null + ); + + -- https://code.google.com/archive/p/adf-samples-demos/downloads + insert into emp values(7369, 'smith', 'clerk', 7902,'17-dec-1980', 800, null, 20); + insert into emp values(7499, 'allen', 'salesman', 7698,'20-feb-1981', 1600, 300, 30); + insert into emp values(7521, 'ward', 'salesman', 7698,'22-feb-1981', 1250, 500, 30); + insert into emp values(7566, 'jones', 'manager', 7839,'2-apr-1981', 2975, null, 20); + insert into emp values(7654, 'martin', 'salesman', 7698,'28-sep-1981', 1250, 1400, 30); + insert into emp values(7698, 'blake', 'manager', 7839,'1-may-1981', 2850, null, 30); + insert into emp values(7782, 'clark', 'manager', 7839,'9-jun-1981', 2450, null, 10); + insert into emp values(7788, 'scott', 'analyst', 7566,'09-dec-1982', 3000, null, 20); -- <<< 19-apr-1987 ? + insert into emp values(7839, 'king', 'president', null,'17-nov-1981', 5000, null, 10); + insert into emp values(7844, 'turner', 'salesman', 7698,'8-sep-1981', 1500, 0, 30); + insert into emp values(7876, 'adams', 'clerk', 7788,'12-jan-1983', 1100, null, 20); -- << 23-may-1987 ? + insert into emp values(7900, 'james', 'clerk', 7698,'3-dec-1981', 950, null, 30); + insert into emp values(7902, 'ford', 'analyst', 7566,'3-dec-1981', 3000, null, 20); + insert into emp values(7934, 'miller', 'clerk', 7782,'23-jan-1982', 1300, null, 10); + commit; + + /* + -- http://www.orafaq.com/wiki/SCOTT + SCOTT> SELECT * FROM emp ORDER BY empno; + EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO + ---------- ---------- --------- ---------- ----------- ---------- ---------- ---------- + 7369 SMITH CLERK 7902 17-DEC-1980 800 20 + 7499 ALLEN SALESMAN 7698 20-FEB-1981 1600 300 30 + 7521 WARD SALESMAN 7698 22-FEB-1981 1250 500 30 + 7566 JONES MANAGER 7839 02-APR-1981 2975 20 + 7654 MARTIN SALESMAN 7698 28-SEP-1981 1250 1400 30 + 7698 BLAKE MANAGER 7839 01-MAY-1981 2850 30 + 7782 CLARK MANAGER 7839 09-JUN-1981 2450 10 + 7788 SCOTT ANALYST 7566 19-APR-1987 3000 20 <<< 9-dec-1982 ? + 7839 KING PRESIDENT 17-NOV-1981 5000 10 + 7844 TURNER SALESMAN 7698 08-SEP-1981 1500 0 30 + 7876 ADAMS CLERK 7788 23-MAY-1987 1100 20 <<< 12-jan-1983 ? + 7900 JAMES CLERK 7698 03-DEC-1981 950 30 + 7902 FORD ANALYST 7566 03-DEC-1981 3000 20 + 7934 MILLER CLERK 7782 23-JAN-1982 1300 10 + 14 rows selected. + + -- http://www.sql.ru/forum/26520/shema-scott-a + + insert into emp values(7369, 'smith', 'clerk', 7902,to_date('17-dec-1980', 'dd-mon-yyyy'), 800, null, 20); + insert into emp values(7499, 'allen', 'salesman', 7698,to_date('20-feb-1981', 'dd-mon-yyyy'), 1600, 300, 30); + insert into emp values(7521, 'ward', 'salesman', 7698,to_date('22-feb-1981', 'dd-mon-yyyy'), 1250, 500, 30); + insert into emp values(7566, 'jones', 'manager', 7839,to_date('2-apr-1981', 'dd-mon-yyyy'), 2975, null, 20); + insert into emp values(7654, 'martin', 'salesman', 7698,to_date('28-sep-1981', 'dd-mon-yyyy'), 1250, 1400, 30); + insert into emp values(7698, 'blake', 'manager', 7839,to_date('1-may-1981', 'dd-mon-yyyy'), 2850, null, 30); + insert into emp values(7782, 'clark', 'manager', 7839,to_date('9-jun-1981', 'dd-mon-yyyy'), 2450, null, 10); + insert into emp values(7788, 'scott', 'analyst', 7566,to_date('09-dec-1982', 'dd-mon-yyyy'), 3000, null, 20); + insert into emp values(7839, 'king', 'president', null,to_date('17-nov-1981', 'dd-mon-yyyy'), 5000, null, 10); + insert into emp values(7844, 'turner', 'salesman', 7698,to_date('8-sep-1981', 'dd-mon-yyyy'), 1500, 0, 30); + insert into emp values(7876, 'adams', 'clerk', 7788,to_date('12-jan-1983', 'dd-mon-yyyy'), 1100, null, 20); + insert into emp values(7900, 'james', 'clerk', 7698,to_date('3-dec-1981', 'dd-mon-yyyy'), 950, null, 30); + insert into emp values(7902, 'ford', 'analyst', 7566,to_date('3-dec-1981', 'dd-mon-yyyy'), 3000, null, 20); + insert into emp values(7934, 'miller', 'clerk', 7782,to_date('23-jan-1982', 'dd-mon-yyyy'), 1300, null, 10); + */ + + create index deptno_on_emp on emp(deptno); + commit; + + set term ^; + create or alter trigger dept_bi + active before insert on dept as + begin + if ( new.deptno is null or new.deptno < 0) then + new.deptno = gen_id(dept_table_seq, 1); + end + ^ + + create or alter trigger emp_table_bi + active before insert on emp as + begin + if (:new.empno is null or :new.empno < 0) then + new.empno = gen_id(emp_Table_seq, 1); + end + ^ + set term ;^ + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- set list on; + + -- https://community.oracle.com/thread/1020352 + select + --empno, ename, job, mgr, hiredate, sal, comm, deptno, + 'sample1' as info + ,empno + ,ename + ,sal + ,last_value(sal)over( + partition by deptno order by empno + rows between unbounded preceding and 1 preceding + ) last_sal + from emp + order by empno + ; + + + -- http://www.orafaq.com/node/55 + select + 'sample2-a' as info + ,empno + ,deptno + ,hire_year + ,count(*) over ( + partition by hire_year + order by hiredate, empno rows between 3 preceding and 1 following) from_p3_to_f1 + ,count(*) over ( + partition by hire_year + order by hiredate, empno rows between unbounded preceding and current row) from_pu_to_c + ,count(*) over ( + partition by hire_year + order by hiredate, empno rows between 3 preceding and 1 preceding) from_p2_to_p1 + ,count(*) over ( + partition by hire_year + order by hiredate, empno rows between 1 following and 3 following) from_f1_to_f3 + from (select e.*, extract(year from e.hiredate) hire_year from emp e ) + order by empno + ; + + + -- For each employee give the count of employees getting half more that their + -- salary and also the count of employees in the departments 20 and 30 getting half + -- less than their salary. + select + 'sample2-b' as info + ,deptno + ,empno + ,sal + ,count(*) over ( + partition by deptno order by sal range + between unbounded preceding and (sal/2) preceding + ) cnt_lt_half + ,count(*) over ( + partition by deptno order by sal range + between (sal/2) following and unbounded following + ) cnt_mt_half + from emp + order by empno + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + INFO EMPNO ENAME SAL LAST_SAL + ======= ======= ========== ============ ============ + sample1 7369 smith 800.00 + sample1 7499 allen 1600.00 + sample1 7521 ward 1250.00 1600.00 + sample1 7566 jones 2975.00 800.00 + sample1 7654 martin 1250.00 1250.00 + sample1 7698 blake 2850.00 1250.00 + sample1 7782 clark 2450.00 + sample1 7788 scott 3000.00 2975.00 + sample1 7839 king 5000.00 2450.00 + sample1 7844 turner 1500.00 2850.00 + sample1 7876 adams 1100.00 3000.00 + sample1 7900 james 950.00 1500.00 + sample1 7902 ford 3000.00 1100.00 + sample1 7934 miller 1300.00 5000.00 + + INFO EMPNO DEPTNO HIRE_YEAR FROM_P3_TO_F1 FROM_PU_TO_C FROM_P2_TO_P1 FROM_F1_TO_F3 + ========= ======= ======= ========= ===================== ===================== ===================== ===================== + sample2-a 7369 20 1980 1 1 0 0 + sample2-a 7499 30 1981 2 1 0 3 + sample2-a 7521 30 1981 3 2 1 3 + sample2-a 7566 20 1981 4 3 2 3 + sample2-a 7654 30 1981 5 7 3 3 + sample2-a 7698 30 1981 5 4 3 3 + sample2-a 7782 10 1981 5 5 3 3 + sample2-a 7788 20 1982 2 2 1 0 + sample2-a 7839 10 1981 5 8 3 2 + sample2-a 7844 30 1981 5 6 3 3 + sample2-a 7876 20 1983 1 1 0 0 + sample2-a 7900 30 1981 5 9 3 1 + sample2-a 7902 20 1981 4 10 3 0 + sample2-a 7934 10 1982 2 1 0 1 + + INFO DEPTNO EMPNO SAL CNT_LT_HALF CNT_MT_HALF + ========= ======= ======= ============ ===================== ===================== + sample2-b 20 7369 800.00 0 3 + sample2-b 30 7499 1600.00 0 1 + sample2-b 30 7521 1250.00 0 1 + sample2-b 20 7566 2975.00 2 0 + sample2-b 30 7654 1250.00 0 1 + sample2-b 30 7698 2850.00 3 0 + sample2-b 10 7782 2450.00 0 1 + sample2-b 20 7788 3000.00 2 0 + sample2-b 10 7839 5000.00 2 0 + sample2-b 30 7844 1500.00 0 1 + sample2-b 20 7876 1100.00 0 3 + sample2-b 30 7900 950.00 0 3 + sample2-b 20 7902 3000.00 2 0 + sample2-b 10 7934 1300.00 0 2 + """ + +@pytest.mark.version('>=4.0') +def test_core_3647_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3650.py b/tests/bugs/test_core_3650.py new file mode 100644 index 00000000..01aa4401 --- /dev/null +++ b/tests/bugs/test_core_3650.py @@ -0,0 +1,73 @@ +#coding:utf-8 +# +# id: bugs.core_3650 +# title: recreation of collation for utf8 from unicode with option NUMERIC-SORT=1 leads to FB death +# decription: +# tracker_id: CORE-3650 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table tns(f int); -- drop dependencies if any + commit; + set term ^; + execute block as + begin + execute statement 'drop collation ns_coll;'; + when any do begin end + end^ + set term ;^ + commit; + create collation ns_coll for utf8 from unicode 'NUMERIC-SORT=1'; + recreate table tns(s varchar(50) character set utf8 collate ns_coll); + commit; + + recreate table tns(f int); -- drop dependencies if any + commit; + set term ^; + execute block as + begin + execute statement 'drop collation ns_coll;'; + when any do begin end + end^ + set term ;^ + commit; + create collation ns_coll for utf8 from unicode 'NUMERIC-SORT=1'; + rollback; -- !!NB!! + + set term ^; + execute block as + begin + execute statement 'drop collation ns_coll;'; + when any do begin end + end^ + set term ;^ + commit; -- this commit kills FB service + show collation; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + There are no user-defined collations in this database + """ + +@pytest.mark.version('>=2.5.2') +def test_core_3650_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_3658.py b/tests/bugs/test_core_3658.py new file mode 100644 index 00000000..a1062138 --- /dev/null +++ b/tests/bugs/test_core_3658.py @@ -0,0 +1,206 @@ +#coding:utf-8 +# +# id: bugs.core_3658 +# title: FBSVCMGR connects to server as OS user name rather than value of ISC_USER environment variable +# decription: +# ### W A R N I N G ### +# 1) This test uses asynchronous call of external routine (fbsvcmgr) using subprocess.Popen unit, +# see: subprocess.call(["fbsvcmgr", ... ], stdout=...) +# 2) It was encountered that FBSVCMGR do NOT wait for OS completes writing of its output on disk, +# (see CORE-4896), thus forced to use delays (see calls `time.sleep()`). +# 3) Correct work was checked on: WI-V2.5.6.26963; WI-V3.0.0.32281 (SS/SC/CS). +# +# 01-mar-2021: re-implemented after start runs on Linux. +# Replaced substitutions with simple pattern matching check using 're' package. +# Checked on: +# 4.0.0.2377 SS: 5.808s. +# 4.0.0.2377 CS: 6.574s. +# 3.0.8.33420 SS: 5.121s. +# 3.0.8.33420 CS: 6.649s. +# 2.5.9.27152 SC: 4.410s. +# +# tracker_id: CORE-3658 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import subprocess +# from subprocess import Popen +# import time +# import re +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # Obtain engine version: +# engine = str(db_conn.engine_version) # convert to text because 'float' object has no attribute 'startswith' +# db_file = db_conn.database_name +# db_conn.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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# txt25 = '''# Trace config, format for 2.5. Generated auto, do not edit! +# +# enabled true +# log_services true +# log_errors true +# +# ''' +# +# # NOTES ABOUT TRACE CONFIG FOR 3.0: +# # 1) Header contain clauses in different format vs FB 2.5: its header's data must be enclosed with '{' '}'; +# # 2) Name and value must be separated by EQUALITY sign ('=') in FB-3 trace.conf, otherwise we get runtime error: +# # element "<. . .>" have no attribute value set +# txt30 = '''# Trace config, format for 2.5. Generated auto, do not edit! +# services +# { +# enabled = true +# log_services = true +# log_errors = true +# } +# ''' +# +# f_trccfg=open( os.path.join(context['temp_directory'],'tmp_trace_3658.cfg'), 'w') +# if engine.startswith('2.5'): +# f_trccfg.write(txt25) +# else: +# f_trccfg.write(txt30) +# flush_and_close( f_trccfg ) +# +# +# # ############################################################## +# # S T A R T T R A C E i n S E P A R A T E P R O C E S S +# # ############################################################## +# +# f_trclog=open( os.path.join(context['temp_directory'],'tmp_trace_3658.log'), 'w') +# p = Popen([ context['fbsvcmgr_path'], "localhost:service_mgr" , "action_trace_start" , "trc_cfg" , f_trccfg.name], stdout=f_trclog, stderr=subprocess.STDOUT) +# time.sleep(2) +# +# # #################################################### +# # G E T A C T I V E T R A C E S E S S I O N I D +# # #################################################### +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# +# f_trclst=open( os.path.join(context['temp_directory'],'tmp_trace_3658.lst'), 'w') +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", "action_trace_list"], stdout=f_trclst, stderr=subprocess.STDOUT) +# flush_and_close( f_trclst ) +# +# # !!! DO NOT REMOVE THIS LINE !!! +# time.sleep(1) +# +# trcssn=0 +# with open( f_trclst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# +# # #################################################### +# # S E N D R E Q U E S T T R A C E T O S T O P +# # #################################################### +# fn_nul = open(os.devnull, 'w') +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", "action_trace_stop","trc_id", trcssn], stdout=fn_nul) +# fn_nul.close() +# +# # 23.02.2021. DELAY FOR AT LEAST 1 SECOND REQUIRED HERE! +# # Otherwise trace log can remain empty. +# time.sleep(1) +# +# # Doc about Popen.terminate(): +# # https://docs.python.org/2/library/subprocess.html +# # Stop the child. On Posix OSs the method sends SIGTERM to the child. +# # On Windows the Win32 API function TerminateProcess() is called to stop the child. +# +# # Doc about Win API TerminateProcess() function: +# # https://msdn.microsoft.com/en-us/library/windows/desktop/ms686714%28v=vs.85%29.aspx +# # The terminated process cannot exit until all pending I/O has been completed or canceled. +# # TerminateProcess is ____asynchronous____; it initiates termination and returns immediately. +# # ^^^^^^^^^^^^ +# p.terminate() +# flush_and_close( f_trclog ) +# +# # Output log of trace for comparing it with expected. +# # ::: NB ::: Content if trace log is converted to UPPER case in order to reduce change of mismatching with +# # updated trace output in some future versions: +# +# # Windows: +# # 2.5.x: service_mgr, (Service 00000000007C9B88, SYSDBA, TCPv4:127.0.0.1/59583, C:\\FBsCin +# bsvcmgr.exe:6888) +# # 3.0.x: service_mgr, (Service 000000000818B140, SYSDBA, TCPv6:::1/59557, C:\\FBSS +# bsvcmgr.exe:7044) +# # 4.0.x: service_mgr, (Service 0000000010B51DC0, SYSDBA, TCPv6:::1/59569, C:\\FB SS +# bsvcmgr.exe:5616) +# # Linux: +# # service_mgr, (Service 0x7f46c4027c40, SYSDBA, TCPv4:127.0.0.1/51226, /var/tmp/fb40tmp/bin/fbsvcmgr:20947) +# +# p=re.compile('service_mgr,[ ]+\\(\\s*Service[ ]+\\S+[,]?[ ]+sysdba[,]?', re.IGNORECASE) +# with open( f_trclog.name,'r') as f: +# for line in f: +# if p.search(line): +# print('Expected line found.') +# +# cleanup( [i.name for i in (f_trccfg, f_trclog, f_trclst) ] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +Expected line found. +Expected line found. +Expected line found. +Expected line found. + """ + +@pytest.mark.version('>=2.5.2') +@pytest.mark.xfail +def test_core_3658_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_3672.py b/tests/bugs/test_core_3672.py new file mode 100644 index 00000000..1b2f30ae --- /dev/null +++ b/tests/bugs/test_core_3672.py @@ -0,0 +1,69 @@ +#coding:utf-8 +# +# id: bugs.core_3672 +# title: computed index by substring function for long columns +# decription: +# tracker_id: CORE-3672 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test( + col1 varchar(8190) character set utf8 collate unicode_ci_ai + ,col2 computed by ( substring(col1 from 1 for 169) ) + ,col3 computed by ( substring(trim( col2 from col1 ) from 1 for 169) ) + ); + commit; + + -- Index on UTF8-field which should be collate in CI_AI manner, will contain 6 bytes per one character (hereafter this is 'N'). + -- This mean that maximum length of key for default page_size = 4096 is: + -- 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) ); + commit; + -- Confirmed for 2.5.5: "-key size exceeds implementation restriction" + + show index test_col1_idx_a; + show index test_col1_idx_b; + show index test_col2_idx_a; + show index test_col2_idx_b; + show index test_col3_idx_a; + show index test_col3_idx_b; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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') +def test_core_3672_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3675.py b/tests/bugs/test_core_3675.py new file mode 100644 index 00000000..d500c221 --- /dev/null +++ b/tests/bugs/test_core_3675.py @@ -0,0 +1,55 @@ +#coding:utf-8 +# +# id: bugs.core_3675 +# title: CREATE INDEX considers NULL and empty string being the same in compound indices +# decription: +# tracker_id: CORE-3675 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core3675.fbk', init=init_script_1) + +test_script_1 = """ + show table t; + select * from t; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +F1 VARCHAR(1) Nullable +F2 VARCHAR(1) Nullable +F3 VARCHAR(1) Nullable +F4 VARCHAR(1) Nullable +CONSTRAINT T1_UNQ: + Unique key (F1, F2, F3, F4) +F1 F2 F3 F4 +====== ====== ====== ====== +a b c d +a c d +a c d +a b d +a b +a b +a b +a + + """ + +@pytest.mark.version('>=2.5.2') +def test_core_3675_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3683.py b/tests/bugs/test_core_3683.py new file mode 100644 index 00000000..2508e999 --- /dev/null +++ b/tests/bugs/test_core_3683.py @@ -0,0 +1,248 @@ +#coding:utf-8 +# +# id: bugs.core_3683 +# title: Wrong results if the recursive query contains an embedded GROUP BY clause +# decription: +# Confirmed bug on: 2.5.1.26351 +# Works OK on: 2.5.2.26540; 2.5.9.27103; 3.0.3.32861; 3.0.4.32912; 4.0.0.890. +# +# tracker_id: CORE-3683 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + recreate view v_test as select 1 x from rdb$database; + commit; + + -- ###################################### from CORE_3683 ################################# + + recreate table tmp_result(seq smallint, step int, routes varchar(32000) ); + + recreate table rdeps(parent varchar(32),child varchar(32), parent_type int, child_type int, f01 int); + commit; + + recreate view v_test as + with recursive + rd as( + select + d.parent parent + ,d.child + from rdeps d + group by d.parent,d.child -- <<< we need this grouping to eliminate duplicates + ) + ,cr as( + select 0 step,parent,child,cast(parent as varchar(32000))||'->'||child routes + from rd + where rd.parent='MOSCOW' + + UNION ALL + + select x.step+1,rd.parent,rd.child,x.routes||'->'||rd.child + from cr x + join rd on x.child=rd.parent + ) + select step,routes from cr order by step,routes + ; + + + insert into rdeps values( 'MOSCOW', 'TULA', 0, 5, 21); + insert into rdeps values( 'MOSCOW', 'TULA', 0, 5, 22); + + insert into rdeps values( 'TULA', 'OREL', 5, 5, 51); + insert into rdeps values( 'TULA', 'OREL', 5, 5, 52); + + insert into rdeps values( 'TULA', 'LIPETSK', 5, 2, 71); + insert into rdeps values( 'TULA', 'LIPETSK', 5, 2, 72); + + insert into rdeps values( 'TULA', 'RYAZAN', 5, 5, 61); + insert into rdeps values( 'TULA', 'RYAZAN', 5, 5, 62); + + insert into rdeps values( 'OREL', 'KURSK', 5, 5, 81); + insert into rdeps values( 'OREL', 'KURSK', 5, 5, 82); + + insert into rdeps values( 'LIPETSK','VORONEZH', 5, 2, 71); + insert into rdeps values( 'LIPETSK','VORONEZH', 5, 2, 72); + + insert into rdeps values( 'RYAZAN','MUROM', 5, 5, 61); + insert into rdeps values( 'RYAZAN','MUROM', 5, 5, 62); + + commit; + + set count on; + + insert into tmp_result(seq, step, routes) select 1, step,routes from v_test; + --select * from v_test; + commit; + + -- AFTER ADDING INDEX RESULT BECAME CORRECT: + -- ######################################### + create index rdeps_unq on rdeps(parent, child, f01); + commit; + + + insert into tmp_result(seq, step, routes) select 2, step,routes from v_test; + commit; + + -- check query: should return zero rows. + select a_step, a_routes, b_step, b_routes + from ( + select a.step as a_step, a.routes as a_routes + from tmp_result a where a.seq=1 + ) a + full join + ( + select b.step as b_step, b.routes as b_routes + from tmp_result b where b.seq=2 + ) b + on a.a_step = b.b_step and a.a_routes = b.b_routes + where a.a_step is null or b.b_step is null + ; + commit; + + set count off; + + --############################################# FROM CORE_3698: ###################################### + + recreate table contacts ( + id integer not null, + age integer, + name varchar(255), + customer integer not null + ); + + recreate table customers ( + id integer not null, + name varchar(255), + parentid integer + ); + + insert into customers (id, name, parentid) values (1, 'dent', null); + insert into customers (id, name, parentid) values (2, 'troprosys usa', null); + insert into customers (id, name, parentid) values (3, 'gralpingro gmbh', null); + insert into customers (id, name, parentid) values (4, 'systed', null); + insert into customers (id, name, parentid) values (5, 'tian', null); + insert into customers (id, name, parentid) values (6, 'logy asia', null); + insert into customers (id, name, parentid) values (7, 'nalf devices', null); + insert into customers (id, name, parentid) values (8, 'coak', null); + insert into customers (id, name, parentid) values (9, 'boo consulting', null); + insert into customers (id, name, parentid) values (10, 'gral-berlin', 3); + insert into customers (id, name, parentid) values (11, 'gral-hamburg', 3); + insert into customers (id, name, parentid) values (12, 'gral-munich', 3); + insert into customers (id, name, parentid) values (13, 'gral-cologne', 3); + insert into customers (id, name, parentid) values (14, 'logy-japan', 6); + insert into customers (id, name, parentid) values (15, 'logy-tokyo', 14); + insert into customers (id, name, parentid) values (16, 'logy-kyoto', 14); + insert into customers (id, name, parentid) values (17, 'logy-tokyo-west', 15); + insert into customers (id, name, parentid) values (18, 'logy-tokyo-east', 15); + + commit; + + insert into contacts (id, age, name, customer) values (1, 21, 'abc', 11); + insert into contacts (id, age, name, customer) values (2, 82, 'paige chen', 8); + insert into contacts (id, age, name, customer) values (10, 23, 'whatever', 17); + insert into contacts (id, age, name, customer) values (11, 22, 'someone', 17); + insert into contacts (id, age, name, customer) values (12, 23, 'manager', 17); + insert into contacts (id, age, name, customer) values (13, 44, 'manager', 17); + insert into contacts (id, age, name, customer) values (15, 55, 'ceo', 9); + + commit; + alter table contacts add constraint pk_contacts primary key (id); + alter table customers add constraint pk_customers primary key (id); + + alter table contacts add constraint fk_contacts_1 foreign key (customer) references customers (id); + commit; + + recreate table tmp_result(seq smallint, id int, name varchar(255), avgage numeric(12,2) ); + + set count on; + /** Test Case 1, Returns 18 Rows **/ + insert into tmp_result(seq, id, name, avgage) + with recursive c (id,name,avgage) + as + + ( + select customers.id, customers.name, 0 as avgage from customers + where customers.parentid is null + union all + select customers.id, customers.name, 0 as avgage from customers + join c as parent on parent.id = customers.parentid + ) + select 1, c.* from c + ; + + + /** Test Case 2, Returns 15 Rows **/ + + insert into tmp_result(seq, id, name, avgage) + with recursive c (id,name,avgage) + as + + ( + select customers.id, customers.name, average.age as avgage from customers + join (select customers.id as customersid, AVG( 0 * COALESCE(contacts.age,0)) as age + from customers + left join contacts on contacts.customer = customers.id + group by 1) as average on average.customersid = customers.id + where customers.parentid is null + union all + select customers.id, customers.name, average.age as avgage from customers + join c as parent on parent.id = customers.parentid + join (select customers.id as customersid, AVG( 0 * COALESCE(contacts.age,0)) as age + from customers + left join contacts on contacts.customer = customers.id + group by 1) as average on average.customersid = customers.id + ) + + select 2, c.* from c + ; + + -------------------------------------------------------------- + + -- check query: should return zero rows. + select a_id, a_name, a_avgage, b_id, b_name, b_avgage + from ( + select a.id as a_id, a.name as a_name, a.avgage as a_avgage + from tmp_result a where seq=1 + ) a + full join + ( + select b.id as b_id, b.name as b_name, b.avgage as b_avgage + from tmp_result b where seq=2 + ) b + on a.a_id is not distinct from b.b_id + where a.a_id is null or b.b_id is null + ; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 7 + Records affected: 7 + Records affected: 0 + Records affected: 18 + Records affected: 18 + Records affected: 0 + """ + +@pytest.mark.version('>=2.5.2') +def test_core_3683_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3690.py b/tests/bugs/test_core_3690.py new file mode 100644 index 00000000..13c3718b --- /dev/null +++ b/tests/bugs/test_core_3690.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: bugs.core_3690 +# title: Wrong warning message for ambiguous query +# decription: NB: dialect 1 allows such queries for backward compatibility reasons +# tracker_id: CORE-3690 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select m.mon$sql_dialect from mon$database m; + select 0*rdb$relation_id as id from rdb$database,rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MON$SQL_DIALECT 3 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42702 + Dynamic SQL Error + -SQL error code = -204 + -Ambiguous field name between table RDB$DATABASE and table RDB$DATABASE + -RDB$RELATION_ID + """ + +@pytest.mark.version('>=2.5.3') +def test_core_3690_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3691.py b/tests/bugs/test_core_3691.py new file mode 100644 index 00000000..7e93f3bd --- /dev/null +++ b/tests/bugs/test_core_3691.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_3691 +# title: Missing constraint name in foreign key error message in FB 2.1.4 +# decription: +# tracker_id: CORE-3691 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Note. Info about problematic key exists since 2.5.3 + recreate table tmain(id int primary key using index tmain_pk); + commit; + insert into tmain values(1); + commit; + recreate table tdetl(id int primary key using index tdetl_pk, pid int); + commit; + insert into tdetl values(1,2); + commit; + alter table tdetl add constraint tdetl_fk foreign key(pid) references tmain(id); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + 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('>=2.5.3') +def test_core_3691_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_3692.py b/tests/bugs/test_core_3692.py new file mode 100644 index 00000000..9e947489 --- /dev/null +++ b/tests/bugs/test_core_3692.py @@ -0,0 +1,99 @@ +#coding:utf-8 +# +# id: bugs.core_3692 +# title: Cannot drop a NOT NULL constraint on a field participating in the UNIQUE constraint +# decription: +# tracker_id: CORE-3692 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table cset (cname varchar(250) character set none not null); + commit; + alter table cset add constraint uq_cset unique (cname); + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ +show table cset; + + set term ^; + execute block as + declare v_stt varchar(70); + begin + for + with + inp as(select 'cset' nm from rdb$database) + ,pk_defs as( -- obtain PK constraint and get fields that assembles it + select + rc.rdb$relation_name rel_name + ,rc.rdb$constraint_name pk_name + ,rc.rdb$index_name pk_idx + ,rs.rdb$field_name fld_name + ,rs.rdb$field_position fld_pos + from rdb$relation_constraints rc + join rdb$index_segments rs on rc.rdb$index_name=rs.rdb$index_name + join inp i on rc.rdb$relation_name containing i.nm + where rc.rdb$constraint_type containing 'PRIMARY' + ) + -- select * from pk_defs + ,chk_list as( + select + rc.rdb$relation_name rel_name + ,rc.rdb$constraint_name sub_name + ,rc.rdb$constraint_type sub_type + ,'alter table '||trim(rc.rdb$relation_name)||' drop constraint '||trim(rc.rdb$constraint_name)||'; -- '||trim(rc.rdb$constraint_type) stt + ,ck.rdb$trigger_name + ,p.pk_name -- not null ==> field is included in PK, skip it + ,decode(rc.rdb$constraint_type, 'UNIQUE', 99, 0) sort_weitgh + from rdb$relation_constraints rc + join inp i on rc.rdb$relation_name containing i.nm + left join rdb$check_constraints ck on rc.rdb$constraint_name=ck.rdb$constraint_name + left join pk_defs p on rc.rdb$relation_name=p.rel_name and ck.rdb$trigger_name=p.fld_name + where + rc.rdb$relation_name not like 'RDB$%' + and rc.rdb$relation_name not like 'MON$%' + and rc.rdb$relation_name not like 'IBE$%' + and rc.rdb$constraint_type not containing 'PRIMARY' + and p.pk_name is null -- ==> this field is NOT included in PK constraint + order by rc.rdb$relation_name, decode(rc.rdb$constraint_type, 'UNIQUE', 99, 0) + ) + select cast(stt as varchar(70)) stt from chk_list + into v_stt + do begin + execute statement (v_stt); + end + + end + ^ set term ;^ + commit; + + show table cset; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +CNAME VARCHAR(250) Not Null +CONSTRAINT UQ_CSET: + Unique key (CNAME) +CNAME VARCHAR(250) Nullable + """ + +@pytest.mark.version('>=2.5.2') +def test_core_3692_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3694.py b/tests/bugs/test_core_3694.py new file mode 100644 index 00000000..6c09d717 --- /dev/null +++ b/tests/bugs/test_core_3694.py @@ -0,0 +1,56 @@ +#coding:utf-8 +# +# id: bugs.core_3694 +# title: internal Firebird consistency check in query with grouping by subquery+stored procedure+aggregate +# decription: +# tracker_id: CORE-3694 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- As of 27-apr-2015,, this error exists at least up to WI-V2.5.5.26861 + -- (not only in 2.5.1 as it is issued in the ticket). + set term ^; + create or alter procedure dummy_proc(val integer) returns(result integer) as + begin + result = val; + suspend; + end + ^ + set term ;^ + commit; + + -- wrong query (uses an aggregate function in a group by clause) + select ( select result from dummy_proc(sum(t.rdb$type)) ) as is_correct + ,count(*) from rdb$types t + group by is_correct; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Cannot use an aggregate or window function in a GROUP BY clause + """ + +@pytest.mark.version('>=3.0') +def test_core_3694_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_3697.py b/tests/bugs/test_core_3697.py new file mode 100644 index 00000000..c716e440 --- /dev/null +++ b/tests/bugs/test_core_3697.py @@ -0,0 +1,82 @@ +#coding:utf-8 +# +# id: bugs.core_3697 +# title: String truncation error when selecting from a VIEW with UNION inside +# decription: +# tracker_id: CORE-3697 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core3697-ods11.fbk', init=init_script_1) + +test_script_1 = """ + -- Confirmed on 2.5.1: + -- Statement failed, SQLSTATE = 22001 + -- arithmetic exception, numeric overflow, or string truncation + -- -string right truncation + + create or alter view TREE_TEST ( + ID, TEXT, PARENTID, CONDITIONS, + STMT, RULFNAME ) + as + select 0, 'Организации', NULL, '', '' + , 'KODORG' + from rdb$database + union + select uidorg + , nameorg + , '0' + , ' G.UIDORG = ' || '''' || uidorg || '''' + , '' + , 'KODORG' + from org_delivery + ; + commit; + + set list on; + select id, text, parentid, conditions, stmt, rulfname + from tree_test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 0 + TEXT Организации + PARENTID + CONDITIONS + STMT + RULFNAME KODORG + + ID 7707083893 380000460 + TEXT АНГАРСКОЕ ОТДЕЛЕНИЕ № 7690 + PARENTID 0 + CONDITIONS G.UIDORG = '7707083893 380000460' + STMT + RULFNAME KODORG + + ID 7724261610 380000326 + TEXT ПОЧТАМТ + PARENTID 0 + CONDITIONS G.UIDORG = '7724261610 380000326' + STMT + RULFNAME KODORG + """ + +@pytest.mark.version('>=2.5.2') +def test_core_3697_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3722.py b/tests/bugs/test_core_3722.py new file mode 100644 index 00000000..f53dc2dd --- /dev/null +++ b/tests/bugs/test_core_3722.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_3722 +# title: IS NOT DISTINCT FROM NULL doesn't use index +# decription: +# tracker_id: CORE-3722 +# min_versions: ['2.1.5'] +# versions: 2.1.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t (a varchar(5)); +create index t_a on t (a); +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """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('', ''); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Database: localhost:C: btestnew mpugs.core_3722.fdb, User: SYSDBA +SQL> SQL> +PLAN (T INDEX (T_A)) +SQL> +PLAN (T INDEX (T_A)) +SQL> +PLAN (T INDEX (T_A)) +SQL> +PLAN (T INDEX (T_A)) +SQL>""" + +@pytest.mark.version('>=2.1.5') +def test_core_3722_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3732.py b/tests/bugs/test_core_3732.py new file mode 100644 index 00000000..7ff9dec9 --- /dev/null +++ b/tests/bugs/test_core_3732.py @@ -0,0 +1,169 @@ +#coding:utf-8 +# +# id: bugs.core_3732 +# title: Segfault when closing attachment to database +# decription: +# Confirmed bug on: WI-V2.5.1.26351. Works fine on WI-V2.5.2.26540 +# On 2.5.1: +# 1) test finished with: +# ERROR: bugs.core_3732 +# Test cleanup: Exception raised while dropping database. +# FAILED (errors=1) +# 2) firebird.log did contain: +# REMOTE INTERFACE/gds__detach: Unsuccesful detach from database. +# Uncommitted work may have been lost +# +# tracker_id: CORE-3732 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [('STATEMENT FAILED, SQLSTATE = HY000', ''), ('RECORD NOT FOUND FOR USER: TMP\\$C3732', ''), ('AFTER LINE.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import sys +# import subprocess +# import time +# import difflib +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # Obtain engine version: +# engine = str(db_conn.engine_version) # convert to text because 'float' object has no attribute 'startswith' +# db_file = db_conn.database_name +# db_conn.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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# def svc_get_fb_log( engine, f_fb_log ): +# +# import subprocess +# +# if engine.startswith('2.5'): +# get_firebird_log_key='action_get_ib_log' +# else: +# get_firebird_log_key='action_get_fb_log' +# +# subprocess.call([ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# get_firebird_log_key +# ], +# stdout=f_fb_log, stderr=subprocess.STDOUT +# ) +# +# return +# +# #-------------------------------------------- +# +# f_fblog_before=open( os.path.join(context['temp_directory'],'tmp_3732_fblog_before.txt'), 'w') +# svc_get_fb_log( engine, f_fblog_before ) +# flush_and_close( f_fblog_before ) +# +# sql_ddl=''' +# drop user tmp$c3732; +# commit; +# create role REPL_ADMIN; +# create user tmp$c3732 password '12345'; +# grant repl_admin to tmp$c3732; +# revoke all on all from tmp$c3732; +# drop user tmp$c3732; +# exit; +# ''' +# +# f_ddl_sql = open( os.path.join(context['temp_directory'],'tmp_ddl_3732.sql'), 'w') +# f_ddl_sql.write(sql_ddl) +# flush_and_close( f_ddl_sql ) +# +# f_ddl_log = open( os.path.join(context['temp_directory'],'tmp_ddl_3732.log'), 'w') +# subprocess.call( [ context['isql_path'], dsn, "-q", "-i",f_ddl_sql.name ], +# stdout=f_ddl_log, +# stderr=subprocess.STDOUT +# ) +# flush_and_close( f_ddl_log ) +# +# f_fblog_after=open( os.path.join(context['temp_directory'],'tmp_3732_fblog_after.txt'), 'w') +# svc_get_fb_log( engine, f_fblog_after ) +# flush_and_close( f_fblog_after ) +# +# # Now we can compare two versions of firebird.log and check their difference. +# +# oldfb=open(f_fblog_before.name, 'r') +# newfb=open(f_fblog_after.name, 'r') +# +# difftext = ''.join(difflib.unified_diff( +# oldfb.readlines(), +# newfb.readlines() +# )) +# oldfb.close() +# newfb.close() +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_3732_diff.txt'), 'w') +# f_diff_txt.write(difftext) +# flush_and_close( f_diff_txt ) +# +# # This should be empty: +# ####################### +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# print( line.upper() ) +# +# # This should be empty: +# ####################### +# with open( f_ddl_log.name,'r') as f: +# for line in f: +# print(line.upper()) +# +# # CLEANUP +# ######### +# time.sleep(1) +# cleanup( [i.name for i in (f_fblog_before, f_ddl_sql, f_ddl_log, f_fblog_after, f_diff_txt) ] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.2') +@pytest.mark.xfail +def test_core_3732_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_3733.py b/tests/bugs/test_core_3733.py new file mode 100644 index 00000000..4d5b35e8 --- /dev/null +++ b/tests/bugs/test_core_3733.py @@ -0,0 +1,32 @@ +#coding:utf-8 +# +# id: bugs.core_3733 +# title: GBAK fails to fix system generators while restoring +# decription: +# tracker_id: CORE-3733 +# min_versions: [] +# versions: 2.5.2 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core3733.fbk', init=init_script_1) + +test_script_1 = """ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.2') +def test_core_3733_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_3735.py b/tests/bugs/test_core_3735.py new file mode 100644 index 00000000..ceffcaa9 --- /dev/null +++ b/tests/bugs/test_core_3735.py @@ -0,0 +1,192 @@ +#coding:utf-8 +# +# id: bugs.core_3735 +# title: Unprivileged user can delete from RDB$DATABASE, RDB$COLLATIONS, RDB$CHARACTER_SETS +# decription: +# tracker_id: CORE-3735 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('-Effective user is.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- See also more complex test in CORE-4731 // Prohibit an ability to issue DML or DDL statements on RDB$ tables + set wng off; + create or alter user tmp$c3735 password '123'; + commit; + revoke all on all from tmp$c3735; + commit; + + connect '$(DSN)' user tmp$c3735 password '123'; + + --show version; + + set list on; + set blob all; + select current_user from rdb$database; + show grants; + set count on; + + --set echo 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; + + connect '$(DSN)' user sysdba password 'masterkey'; + drop user tmp$c3735; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + USER TMP$C3735 + """ +expected_stderr_1 = """ + 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_core_3735_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3736.py b/tests/bugs/test_core_3736.py new file mode 100644 index 00000000..42dab6ef --- /dev/null +++ b/tests/bugs/test_core_3736.py @@ -0,0 +1,171 @@ +#coding:utf-8 +# +# id: bugs.core_3736 +# title: WITH LOCK clause is allowed for users with read-only rights on some table, thus blocking others from updating this table +# decription: +# Checked on: +# 4.0.0.1635 SS: 1.500s. +# 4.0.0.1633 CS: 2.032s. +# 3.0.5.33180 SS: 1.078s. +# 3.0.5.33178 CS: 1.408s. +# +# tracker_id: CORE-3736 +# min_versions: [] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!335544352|335544878).)*$', ''), ('number is.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set wng off; + create or alter user tmp$c3736_ro password 'tmp$c3736_ro'; -- user with read-only access to the table + create or alter user tmp$c3736_ud password 'tmp$c3736_ud'; -- user with access for UPDATE and DELETE on the table + commit; + + revoke all on all from tmp$c3736_ro; + revoke all on all from tmp$c3736_ud; + commit; + + recreate table t_read_only_for_non_sys(id int); + commit; + insert into t_read_only_for_non_sys values(1); + insert into t_read_only_for_non_sys values(2); + insert into t_read_only_for_non_sys values(3); + insert into t_read_only_for_non_sys values(4); + insert into t_read_only_for_non_sys values(5); + commit; + + grant select on t_read_only_for_non_sys to tmp$c3736_ro; + commit; + grant update,delete,select on t_read_only_for_non_sys to tmp$c3736_ud; + commit; + + set transaction no wait; + + update t_read_only_for_non_sys set id = id where id >= 4; + + set term ^; + execute block returns( who_am_i type of column sec$users.sec$user_name, my_action varchar(20), what_i_see int ) + as + declare v_dbname type of column mon$database.mon$database_name; + declare v_usr_ro type of column sec$users.sec$user_name = 'tmp$c3736_ro'; + declare v_pwd_ro varchar(20) = 'tmp$c3736_ro'; + declare v_connect varchar(255); + begin + select 'localhost:' || d.mon$database_name + from mon$database d + into v_dbname; + + for + execute statement 'select current_user, ''select_read_only'', id from t_read_only_for_non_sys' -- for update with lock' + on external (v_dbname) + as user (v_usr_ro) password (v_pwd_ro) + into who_am_i, my_action, what_i_see + do + suspend; + + for + execute statement 'select current_user, ''select_with_lock'', id from t_read_only_for_non_sys for update with lock' + on external (v_dbname) + as user (v_usr_ro) password (v_pwd_ro) + into who_am_i, my_action, what_i_see + do + suspend; + + + end + ^ + set term ;^ + rollback; + + set transaction no wait; + + update t_read_only_for_non_sys set id = id where id >= 4; + + set term ^; + execute block returns( who_am_i type of column sec$users.sec$user_name, my_action varchar(20), what_i_see int ) + as + declare v_dbname type of column mon$database.mon$database_name; + declare v_usr_ud type of column sec$users.sec$user_name = 'tmp$c3736_ud'; + declare v_pwd_ud varchar(20) = 'tmp$c3736_ud'; + declare v_connect varchar(255); + begin + select 'localhost:' || d.mon$database_name + from mon$database d + into v_dbname; + + for + execute statement 'select current_user, ''select_with_lock'', id from t_read_only_for_non_sys for update with lock' + on external (v_dbname) + as user (v_usr_ud) password (v_pwd_ud) + into who_am_i, my_action, what_i_see + do + suspend; + + end + ^ + 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; + + -- Do not forget about cleanup - remember that other tests can query sec$users or run `show users`! + drop user tmp$c3736_ro; + drop user tmp$c3736_ud; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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_1 = """ + 335544352 : no permission for UPDATE access to TABLE T_READ_ONLY_FOR_NON_SYS + 335544878 : concurrent transaction number is 806 + """ + +@pytest.mark.version('>=3.0') +def test_core_3736_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3737.py b/tests/bugs/test_core_3737.py new file mode 100644 index 00000000..550352c3 --- /dev/null +++ b/tests/bugs/test_core_3737.py @@ -0,0 +1,64 @@ +#coding:utf-8 +# +# id: bugs.core_3737 +# title: EXECUTE BLOCK parameters definitions are not respected and may cause wrong behavior related to character sets +# decription: +# tracker_id: CORE-3737 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set term ^; + execute block returns(len_1252 int, len_utf8 int) as + declare s varchar(16) character set utf8 = 'ÃÂÁÀÄÅÇØßÐÑÞÆŠŒŽ'; -- http://en.wikipedia.org/wiki/Windows-1252 + begin + execute statement ( + 'execute block (c varchar(16) character set win1252 = ?) returns (n int) as ' + || 'begin ' + || ' n = octet_length(c); ' + || ' suspend; ' + || 'end') (s) + into len_1252; + + execute statement ( + 'execute block (c varchar(16) character set utf8 = ?) returns (n int) as ' + || 'begin ' + || ' n = octet_length(c); ' + || ' suspend; ' + || 'end') (s) + into len_utf8; + suspend; + + end + ^ + set term ;^ + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + LEN_1252 16 + LEN_UTF8 32 + """ + +@pytest.mark.version('>=3.0') +def test_core_3737_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3740.py b/tests/bugs/test_core_3740.py new file mode 100644 index 00000000..651b794d --- /dev/null +++ b/tests/bugs/test_core_3740.py @@ -0,0 +1,1546 @@ +#coding:utf-8 +# +# id: bugs.core_3740 +# title: SELECT using IN list with 153 or more elements causes crash +# decription: +# tracker_id: CORE-3740 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + -- Note-1. Firebird 2.5.0 and 2.5.1 -- also WORK fine on the following script + -- (despite ticket's issue "affected version(s) 2.5.1"), so these versions also can be tested here. + -- Note-2. As of march-2015 (build 3.0.0.31756), there is some kind of regression in performance + -- of parsing huge literal lists in comparison with all 2.5.x versions, see CORE-4728. + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select 1 x from + rdb$database where 1500 in( + 2147483647 + ,2147483646 + ,2147483645 + ,2147483644 + ,2147483643 + ,2147483642 + ,2147483641 + ,2147483640 + ,2147483639 + ,2147483638 + ,2147483637 + ,2147483636 + ,2147483635 + ,2147483634 + ,2147483633 + ,2147483632 + ,2147483631 + ,2147483630 + ,2147483629 + ,2147483628 + ,2147483627 + ,2147483626 + ,2147483625 + ,2147483624 + ,2147483623 + ,2147483622 + ,2147483621 + ,2147483620 + ,2147483619 + ,2147483618 + ,2147483617 + ,2147483616 + ,2147483615 + ,2147483614 + ,2147483613 + ,2147483612 + ,2147483611 + ,2147483610 + ,2147483609 + ,2147483608 + ,2147483607 + ,2147483606 + ,2147483605 + ,2147483604 + ,2147483603 + ,2147483602 + ,2147483601 + ,2147483600 + ,2147483599 + ,2147483598 + ,2147483597 + ,2147483596 + ,2147483595 + ,2147483594 + ,2147483593 + ,2147483592 + ,2147483591 + ,2147483590 + ,2147483589 + ,2147483588 + ,2147483587 + ,2147483586 + ,2147483585 + ,2147483584 + ,2147483583 + ,2147483582 + ,2147483581 + ,2147483580 + ,2147483579 + ,2147483578 + ,2147483577 + ,2147483576 + ,2147483575 + ,2147483574 + ,2147483573 + ,2147483572 + ,2147483571 + ,2147483570 + ,2147483569 + ,2147483568 + ,2147483567 + ,2147483566 + ,2147483565 + ,2147483564 + ,2147483563 + ,2147483562 + ,2147483561 + ,2147483560 + ,2147483559 + ,2147483558 + ,2147483557 + ,2147483556 + ,2147483555 + ,2147483554 + ,2147483553 + ,2147483552 + ,2147483551 + ,2147483550 + ,2147483549 + ,2147483548 + ,2147483547 + ,2147483546 + ,2147483545 + ,2147483544 + ,2147483543 + ,2147483542 + ,2147483541 + ,2147483540 + ,2147483539 + ,2147483538 + ,2147483537 + ,2147483536 + ,2147483535 + ,2147483534 + ,2147483533 + ,2147483532 + ,2147483531 + ,2147483530 + ,2147483529 + ,2147483528 + ,2147483527 + ,2147483526 + ,2147483525 + ,2147483524 + ,2147483523 + ,2147483522 + ,2147483521 + ,2147483520 + ,2147483519 + ,2147483518 + ,2147483517 + ,2147483516 + ,2147483515 + ,2147483514 + ,2147483513 + ,2147483512 + ,2147483511 + ,2147483510 + ,2147483509 + ,2147483508 + ,2147483507 + ,2147483506 + ,2147483505 + ,2147483504 + ,2147483503 + ,2147483502 + ,2147483501 + ,2147483500 + ,2147483499 + ,2147483498 + ,2147483497 + ,2147483496 + ,2147483495 + ,2147483494 + ,2147483493 + ,2147483492 + ,2147483491 + ,2147483490 + ,2147483489 + ,2147483488 + ,2147483487 + ,2147483486 + ,2147483485 + ,2147483484 + ,2147483483 + ,2147483482 + ,2147483481 + ,2147483480 + ,2147483479 + ,2147483478 + ,2147483477 + ,2147483476 + ,2147483475 + ,2147483474 + ,2147483473 + ,2147483472 + ,2147483471 + ,2147483470 + ,2147483469 + ,2147483468 + ,2147483467 + ,2147483466 + ,2147483465 + ,2147483464 + ,2147483463 + ,2147483462 + ,2147483461 + ,2147483460 + ,2147483459 + ,2147483458 + ,2147483457 + ,2147483456 + ,2147483455 + ,2147483454 + ,2147483453 + ,2147483452 + ,2147483451 + ,2147483450 + ,2147483449 + ,2147483448 + ,2147483447 + ,2147483446 + ,2147483445 + ,2147483444 + ,2147483443 + ,2147483442 + ,2147483441 + ,2147483440 + ,2147483439 + ,2147483438 + ,2147483437 + ,2147483436 + ,2147483435 + ,2147483434 + ,2147483433 + ,2147483432 + ,2147483431 + ,2147483430 + ,2147483429 + ,2147483428 + ,2147483427 + ,2147483426 + ,2147483425 + ,2147483424 + ,2147483423 + ,2147483422 + ,2147483421 + ,2147483420 + ,2147483419 + ,2147483418 + ,2147483417 + ,2147483416 + ,2147483415 + ,2147483414 + ,2147483413 + ,2147483412 + ,2147483411 + ,2147483410 + ,2147483409 + ,2147483408 + ,2147483407 + ,2147483406 + ,2147483405 + ,2147483404 + ,2147483403 + ,2147483402 + ,2147483401 + ,2147483400 + ,2147483399 + ,2147483398 + ,2147483397 + ,2147483396 + ,2147483395 + ,2147483394 + ,2147483393 + ,2147483392 + ,2147483391 + ,2147483390 + ,2147483389 + ,2147483388 + ,2147483387 + ,2147483386 + ,2147483385 + ,2147483384 + ,2147483383 + ,2147483382 + ,2147483381 + ,2147483380 + ,2147483379 + ,2147483378 + ,2147483377 + ,2147483376 + ,2147483375 + ,2147483374 + ,2147483373 + ,2147483372 + ,2147483371 + ,2147483370 + ,2147483369 + ,2147483368 + ,2147483367 + ,2147483366 + ,2147483365 + ,2147483364 + ,2147483363 + ,2147483362 + ,2147483361 + ,2147483360 + ,2147483359 + ,2147483358 + ,2147483357 + ,2147483356 + ,2147483355 + ,2147483354 + ,2147483353 + ,2147483352 + ,2147483351 + ,2147483350 + ,2147483349 + ,2147483348 + ,2147483347 + ,2147483346 + ,2147483345 + ,2147483344 + ,2147483343 + ,2147483342 + ,2147483341 + ,2147483340 + ,2147483339 + ,2147483338 + ,2147483337 + ,2147483336 + ,2147483335 + ,2147483334 + ,2147483333 + ,2147483332 + ,2147483331 + ,2147483330 + ,2147483329 + ,2147483328 + ,2147483327 + ,2147483326 + ,2147483325 + ,2147483324 + ,2147483323 + ,2147483322 + ,2147483321 + ,2147483320 + ,2147483319 + ,2147483318 + ,2147483317 + ,2147483316 + ,2147483315 + ,2147483314 + ,2147483313 + ,2147483312 + ,2147483311 + ,2147483310 + ,2147483309 + ,2147483308 + ,2147483307 + ,2147483306 + ,2147483305 + ,2147483304 + ,2147483303 + ,2147483302 + ,2147483301 + ,2147483300 + ,2147483299 + ,2147483298 + ,2147483297 + ,2147483296 + ,2147483295 + ,2147483294 + ,2147483293 + ,2147483292 + ,2147483291 + ,2147483290 + ,2147483289 + ,2147483288 + ,2147483287 + ,2147483286 + ,2147483285 + ,2147483284 + ,2147483283 + ,2147483282 + ,2147483281 + ,2147483280 + ,2147483279 + ,2147483278 + ,2147483277 + ,2147483276 + ,2147483275 + ,2147483274 + ,2147483273 + ,2147483272 + ,2147483271 + ,2147483270 + ,2147483269 + ,2147483268 + ,2147483267 + ,2147483266 + ,2147483265 + ,2147483264 + ,2147483263 + ,2147483262 + ,2147483261 + ,2147483260 + ,2147483259 + ,2147483258 + ,2147483257 + ,2147483256 + ,2147483255 + ,2147483254 + ,2147483253 + ,2147483252 + ,2147483251 + ,2147483250 + ,2147483249 + ,2147483248 + ,2147483247 + ,2147483246 + ,2147483245 + ,2147483244 + ,2147483243 + ,2147483242 + ,2147483241 + ,2147483240 + ,2147483239 + ,2147483238 + ,2147483237 + ,2147483236 + ,2147483235 + ,2147483234 + ,2147483233 + ,2147483232 + ,2147483231 + ,2147483230 + ,2147483229 + ,2147483228 + ,2147483227 + ,2147483226 + ,2147483225 + ,2147483224 + ,2147483223 + ,2147483222 + ,2147483221 + ,2147483220 + ,2147483219 + ,2147483218 + ,2147483217 + ,2147483216 + ,2147483215 + ,2147483214 + ,2147483213 + ,2147483212 + ,2147483211 + ,2147483210 + ,2147483209 + ,2147483208 + ,2147483207 + ,2147483206 + ,2147483205 + ,2147483204 + ,2147483203 + ,2147483202 + ,2147483201 + ,2147483200 + ,2147483199 + ,2147483198 + ,2147483197 + ,2147483196 + ,2147483195 + ,2147483194 + ,2147483193 + ,2147483192 + ,2147483191 + ,2147483190 + ,2147483189 + ,2147483188 + ,2147483187 + ,2147483186 + ,2147483185 + ,2147483184 + ,2147483183 + ,2147483182 + ,2147483181 + ,2147483180 + ,2147483179 + ,2147483178 + ,2147483177 + ,2147483176 + ,2147483175 + ,2147483174 + ,2147483173 + ,2147483172 + ,2147483171 + ,2147483170 + ,2147483169 + ,2147483168 + ,2147483167 + ,2147483166 + ,2147483165 + ,2147483164 + ,2147483163 + ,2147483162 + ,2147483161 + ,2147483160 + ,2147483159 + ,2147483158 + ,2147483157 + ,2147483156 + ,2147483155 + ,2147483154 + ,2147483153 + ,2147483152 + ,2147483151 + ,2147483150 + ,2147483149 + ,2147483148 + ,2147483147 + ,2147483146 + ,2147483145 + ,2147483144 + ,2147483143 + ,2147483142 + ,2147483141 + ,2147483140 + ,2147483139 + ,2147483138 + ,2147483137 + ,2147483136 + ,2147483135 + ,2147483134 + ,2147483133 + ,2147483132 + ,2147483131 + ,2147483130 + ,2147483129 + ,2147483128 + ,2147483127 + ,2147483126 + ,2147483125 + ,2147483124 + ,2147483123 + ,2147483122 + ,2147483121 + ,2147483120 + ,2147483119 + ,2147483118 + ,2147483117 + ,2147483116 + ,2147483115 + ,2147483114 + ,2147483113 + ,2147483112 + ,2147483111 + ,2147483110 + ,2147483109 + ,2147483108 + ,2147483107 + ,2147483106 + ,2147483105 + ,2147483104 + ,2147483103 + ,2147483102 + ,2147483101 + ,2147483100 + ,2147483099 + ,2147483098 + ,2147483097 + ,2147483096 + ,2147483095 + ,2147483094 + ,2147483093 + ,2147483092 + ,2147483091 + ,2147483090 + ,2147483089 + ,2147483088 + ,2147483087 + ,2147483086 + ,2147483085 + ,2147483084 + ,2147483083 + ,2147483082 + ,2147483081 + ,2147483080 + ,2147483079 + ,2147483078 + ,2147483077 + ,2147483076 + ,2147483075 + ,2147483074 + ,2147483073 + ,2147483072 + ,2147483071 + ,2147483070 + ,2147483069 + ,2147483068 + ,2147483067 + ,2147483066 + ,2147483065 + ,2147483064 + ,2147483063 + ,2147483062 + ,2147483061 + ,2147483060 + ,2147483059 + ,2147483058 + ,2147483057 + ,2147483056 + ,2147483055 + ,2147483054 + ,2147483053 + ,2147483052 + ,2147483051 + ,2147483050 + ,2147483049 + ,2147483048 + ,2147483047 + ,2147483046 + ,2147483045 + ,2147483044 + ,2147483043 + ,2147483042 + ,2147483041 + ,2147483040 + ,2147483039 + ,2147483038 + ,2147483037 + ,2147483036 + ,2147483035 + ,2147483034 + ,2147483033 + ,2147483032 + ,2147483031 + ,2147483030 + ,2147483029 + ,2147483028 + ,2147483027 + ,2147483026 + ,2147483025 + ,2147483024 + ,2147483023 + ,2147483022 + ,2147483021 + ,2147483020 + ,2147483019 + ,2147483018 + ,2147483017 + ,2147483016 + ,2147483015 + ,2147483014 + ,2147483013 + ,2147483012 + ,2147483011 + ,2147483010 + ,2147483009 + ,2147483008 + ,2147483007 + ,2147483006 + ,2147483005 + ,2147483004 + ,2147483003 + ,2147483002 + ,2147483001 + ,2147483000 + ,2147482999 + ,2147482998 + ,2147482997 + ,2147482996 + ,2147482995 + ,2147482994 + ,2147482993 + ,2147482992 + ,2147482991 + ,2147482990 + ,2147482989 + ,2147482988 + ,2147482987 + ,2147482986 + ,2147482985 + ,2147482984 + ,2147482983 + ,2147482982 + ,2147482981 + ,2147482980 + ,2147482979 + ,2147482978 + ,2147482977 + ,2147482976 + ,2147482975 + ,2147482974 + ,2147482973 + ,2147482972 + ,2147482971 + ,2147482970 + ,2147482969 + ,2147482968 + ,2147482967 + ,2147482966 + ,2147482965 + ,2147482964 + ,2147482963 + ,2147482962 + ,2147482961 + ,2147482960 + ,2147482959 + ,2147482958 + ,2147482957 + ,2147482956 + ,2147482955 + ,2147482954 + ,2147482953 + ,2147482952 + ,2147482951 + ,2147482950 + ,2147482949 + ,2147482948 + ,2147482947 + ,2147482946 + ,2147482945 + ,2147482944 + ,2147482943 + ,2147482942 + ,2147482941 + ,2147482940 + ,2147482939 + ,2147482938 + ,2147482937 + ,2147482936 + ,2147482935 + ,2147482934 + ,2147482933 + ,2147482932 + ,2147482931 + ,2147482930 + ,2147482929 + ,2147482928 + ,2147482927 + ,2147482926 + ,2147482925 + ,2147482924 + ,2147482923 + ,2147482922 + ,2147482921 + ,2147482920 + ,2147482919 + ,2147482918 + ,2147482917 + ,2147482916 + ,2147482915 + ,2147482914 + ,2147482913 + ,2147482912 + ,2147482911 + ,2147482910 + ,2147482909 + ,2147482908 + ,2147482907 + ,2147482906 + ,2147482905 + ,2147482904 + ,2147482903 + ,2147482902 + ,2147482901 + ,2147482900 + ,2147482899 + ,2147482898 + ,2147482897 + ,2147482896 + ,2147482895 + ,2147482894 + ,2147482893 + ,2147482892 + ,2147482891 + ,2147482890 + ,2147482889 + ,2147482888 + ,2147482887 + ,2147482886 + ,2147482885 + ,2147482884 + ,2147482883 + ,2147482882 + ,2147482881 + ,2147482880 + ,2147482879 + ,2147482878 + ,2147482877 + ,2147482876 + ,2147482875 + ,2147482874 + ,2147482873 + ,2147482872 + ,2147482871 + ,2147482870 + ,2147482869 + ,2147482868 + ,2147482867 + ,2147482866 + ,2147482865 + ,2147482864 + ,2147482863 + ,2147482862 + ,2147482861 + ,2147482860 + ,2147482859 + ,2147482858 + ,2147482857 + ,2147482856 + ,2147482855 + ,2147482854 + ,2147482853 + ,2147482852 + ,2147482851 + ,2147482850 + ,2147482849 + ,2147482848 + ,2147482847 + ,2147482846 + ,2147482845 + ,2147482844 + ,2147482843 + ,2147482842 + ,2147482841 + ,2147482840 + ,2147482839 + ,2147482838 + ,2147482837 + ,2147482836 + ,2147482835 + ,2147482834 + ,2147482833 + ,2147482832 + ,2147482831 + ,2147482830 + ,2147482829 + ,2147482828 + ,2147482827 + ,2147482826 + ,2147482825 + ,2147482824 + ,2147482823 + ,2147482822 + ,2147482821 + ,2147482820 + ,2147482819 + ,2147482818 + ,2147482817 + ,2147482816 + ,2147482815 + ,2147482814 + ,2147482813 + ,2147482812 + ,2147482811 + ,2147482810 + ,2147482809 + ,2147482808 + ,2147482807 + ,2147482806 + ,2147482805 + ,2147482804 + ,2147482803 + ,2147482802 + ,2147482801 + ,2147482800 + ,2147482799 + ,2147482798 + ,2147482797 + ,2147482796 + ,2147482795 + ,2147482794 + ,2147482793 + ,2147482792 + ,2147482791 + ,2147482790 + ,2147482789 + ,2147482788 + ,2147482787 + ,2147482786 + ,2147482785 + ,2147482784 + ,2147482783 + ,2147482782 + ,2147482781 + ,2147482780 + ,2147482779 + ,2147482778 + ,2147482777 + ,2147482776 + ,2147482775 + ,2147482774 + ,2147482773 + ,2147482772 + ,2147482771 + ,2147482770 + ,2147482769 + ,2147482768 + ,2147482767 + ,2147482766 + ,2147482765 + ,2147482764 + ,2147482763 + ,2147482762 + ,2147482761 + ,2147482760 + ,2147482759 + ,2147482758 + ,2147482757 + ,2147482756 + ,2147482755 + ,2147482754 + ,2147482753 + ,2147482752 + ,2147482751 + ,2147482750 + ,2147482749 + ,2147482748 + ,2147482747 + ,2147482746 + ,2147482745 + ,2147482744 + ,2147482743 + ,2147482742 + ,2147482741 + ,2147482740 + ,2147482739 + ,2147482738 + ,2147482737 + ,2147482736 + ,2147482735 + ,2147482734 + ,2147482733 + ,2147482732 + ,2147482731 + ,2147482730 + ,2147482729 + ,2147482728 + ,2147482727 + ,2147482726 + ,2147482725 + ,2147482724 + ,2147482723 + ,2147482722 + ,2147482721 + ,2147482720 + ,2147482719 + ,2147482718 + ,2147482717 + ,2147482716 + ,2147482715 + ,2147482714 + ,2147482713 + ,2147482712 + ,2147482711 + ,2147482710 + ,2147482709 + ,2147482708 + ,2147482707 + ,2147482706 + ,2147482705 + ,2147482704 + ,2147482703 + ,2147482702 + ,2147482701 + ,2147482700 + ,2147482699 + ,2147482698 + ,2147482697 + ,2147482696 + ,2147482695 + ,2147482694 + ,2147482693 + ,2147482692 + ,2147482691 + ,2147482690 + ,2147482689 + ,2147482688 + ,2147482687 + ,2147482686 + ,2147482685 + ,2147482684 + ,2147482683 + ,2147482682 + ,2147482681 + ,2147482680 + ,2147482679 + ,2147482678 + ,2147482677 + ,2147482676 + ,2147482675 + ,2147482674 + ,2147482673 + ,2147482672 + ,2147482671 + ,2147482670 + ,2147482669 + ,2147482668 + ,2147482667 + ,2147482666 + ,2147482665 + ,2147482664 + ,2147482663 + ,2147482662 + ,2147482661 + ,2147482660 + ,2147482659 + ,2147482658 + ,2147482657 + ,2147482656 + ,2147482655 + ,2147482654 + ,2147482653 + ,2147482652 + ,2147482651 + ,2147482650 + ,2147482649 + ,2147482648 + ,2147482647 + ,2147482646 + ,2147482645 + ,2147482644 + ,2147482643 + ,2147482642 + ,2147482641 + ,2147482640 + ,2147482639 + ,2147482638 + ,2147482637 + ,2147482636 + ,2147482635 + ,2147482634 + ,2147482633 + ,2147482632 + ,2147482631 + ,2147482630 + ,2147482629 + ,2147482628 + ,2147482627 + ,2147482626 + ,2147482625 + ,2147482624 + ,2147482623 + ,2147482622 + ,2147482621 + ,2147482620 + ,2147482619 + ,2147482618 + ,2147482617 + ,2147482616 + ,2147482615 + ,2147482614 + ,2147482613 + ,2147482612 + ,2147482611 + ,2147482610 + ,2147482609 + ,2147482608 + ,2147482607 + ,2147482606 + ,2147482605 + ,2147482604 + ,2147482603 + ,2147482602 + ,2147482601 + ,2147482600 + ,2147482599 + ,2147482598 + ,2147482597 + ,2147482596 + ,2147482595 + ,2147482594 + ,2147482593 + ,2147482592 + ,2147482591 + ,2147482590 + ,2147482589 + ,2147482588 + ,2147482587 + ,2147482586 + ,2147482585 + ,2147482584 + ,2147482583 + ,2147482582 + ,2147482581 + ,2147482580 + ,2147482579 + ,2147482578 + ,2147482577 + ,2147482576 + ,2147482575 + ,2147482574 + ,2147482573 + ,2147482572 + ,2147482571 + ,2147482570 + ,2147482569 + ,2147482568 + ,2147482567 + ,2147482566 + ,2147482565 + ,2147482564 + ,2147482563 + ,2147482562 + ,2147482561 + ,2147482560 + ,2147482559 + ,2147482558 + ,2147482557 + ,2147482556 + ,2147482555 + ,2147482554 + ,2147482553 + ,2147482552 + ,2147482551 + ,2147482550 + ,2147482549 + ,2147482548 + ,2147482547 + ,2147482546 + ,2147482545 + ,2147482544 + ,2147482543 + ,2147482542 + ,2147482541 + ,2147482540 + ,2147482539 + ,2147482538 + ,2147482537 + ,2147482536 + ,2147482535 + ,2147482534 + ,2147482533 + ,2147482532 + ,2147482531 + ,2147482530 + ,2147482529 + ,2147482528 + ,2147482527 + ,2147482526 + ,2147482525 + ,2147482524 + ,2147482523 + ,2147482522 + ,2147482521 + ,2147482520 + ,2147482519 + ,2147482518 + ,2147482517 + ,2147482516 + ,2147482515 + ,2147482514 + ,2147482513 + ,2147482512 + ,2147482511 + ,2147482510 + ,2147482509 + ,2147482508 + ,2147482507 + ,2147482506 + ,2147482505 + ,2147482504 + ,2147482503 + ,2147482502 + ,2147482501 + ,2147482500 + ,2147482499 + ,2147482498 + ,2147482497 + ,2147482496 + ,2147482495 + ,2147482494 + ,2147482493 + ,2147482492 + ,2147482491 + ,2147482490 + ,2147482489 + ,2147482488 + ,2147482487 + ,2147482486 + ,2147482485 + ,2147482484 + ,2147482483 + ,2147482482 + ,2147482481 + ,2147482480 + ,2147482479 + ,2147482478 + ,2147482477 + ,2147482476 + ,2147482475 + ,2147482474 + ,2147482473 + ,2147482472 + ,2147482471 + ,2147482470 + ,2147482469 + ,2147482468 + ,2147482467 + ,2147482466 + ,2147482465 + ,2147482464 + ,2147482463 + ,2147482462 + ,2147482461 + ,2147482460 + ,2147482459 + ,2147482458 + ,2147482457 + ,2147482456 + ,2147482455 + ,2147482454 + ,2147482453 + ,2147482452 + ,2147482451 + ,2147482450 + ,2147482449 + ,2147482448 + ,2147482447 + ,2147482446 + ,2147482445 + ,2147482444 + ,2147482443 + ,2147482442 + ,2147482441 + ,2147482440 + ,2147482439 + ,2147482438 + ,2147482437 + ,2147482436 + ,2147482435 + ,2147482434 + ,2147482433 + ,2147482432 + ,2147482431 + ,2147482430 + ,2147482429 + ,2147482428 + ,2147482427 + ,2147482426 + ,2147482425 + ,2147482424 + ,2147482423 + ,2147482422 + ,2147482421 + ,2147482420 + ,2147482419 + ,2147482418 + ,2147482417 + ,2147482416 + ,2147482415 + ,2147482414 + ,2147482413 + ,2147482412 + ,2147482411 + ,2147482410 + ,2147482409 + ,2147482408 + ,2147482407 + ,2147482406 + ,2147482405 + ,2147482404 + ,2147482403 + ,2147482402 + ,2147482401 + ,2147482400 + ,2147482399 + ,2147482398 + ,2147482397 + ,2147482396 + ,2147482395 + ,2147482394 + ,2147482393 + ,2147482392 + ,2147482391 + ,2147482390 + ,2147482389 + ,2147482388 + ,2147482387 + ,2147482386 + ,2147482385 + ,2147482384 + ,2147482383 + ,2147482382 + ,2147482381 + ,2147482380 + ,2147482379 + ,2147482378 + ,2147482377 + ,2147482376 + ,2147482375 + ,2147482374 + ,2147482373 + ,2147482372 + ,2147482371 + ,2147482370 + ,2147482369 + ,2147482368 + ,2147482367 + ,2147482366 + ,2147482365 + ,2147482364 + ,2147482363 + ,2147482362 + ,2147482361 + ,2147482360 + ,2147482359 + ,2147482358 + ,2147482357 + ,2147482356 + ,2147482355 + ,2147482354 + ,2147482353 + ,2147482352 + ,2147482351 + ,2147482350 + ,2147482349 + ,2147482348 + ,2147482347 + ,2147482346 + ,2147482345 + ,2147482344 + ,2147482343 + ,2147482342 + ,2147482341 + ,2147482340 + ,2147482339 + ,2147482338 + ,2147482337 + ,2147482336 + ,2147482335 + ,2147482334 + ,2147482333 + ,2147482332 + ,2147482331 + ,2147482330 + ,2147482329 + ,2147482328 + ,2147482327 + ,2147482326 + ,2147482325 + ,2147482324 + ,2147482323 + ,2147482322 + ,2147482321 + ,2147482320 + ,2147482319 + ,2147482318 + ,2147482317 + ,2147482316 + ,2147482315 + ,2147482314 + ,2147482313 + ,2147482312 + ,2147482311 + ,2147482310 + ,2147482309 + ,2147482308 + ,2147482307 + ,2147482306 + ,2147482305 + ,2147482304 + ,2147482303 + ,2147482302 + ,2147482301 + ,2147482300 + ,2147482299 + ,2147482298 + ,2147482297 + ,2147482296 + ,2147482295 + ,2147482294 + ,2147482293 + ,2147482292 + ,2147482291 + ,2147482290 + ,2147482289 + ,2147482288 + ,2147482287 + ,2147482286 + ,2147482285 + ,2147482284 + ,2147482283 + ,2147482282 + ,2147482281 + ,2147482280 + ,2147482279 + ,2147482278 + ,2147482277 + ,2147482276 + ,2147482275 + ,2147482274 + ,2147482273 + ,2147482272 + ,2147482271 + ,2147482270 + ,2147482269 + ,2147482268 + ,2147482267 + ,2147482266 + ,2147482265 + ,2147482264 + ,2147482263 + ,2147482262 + ,2147482261 + ,2147482260 + ,2147482259 + ,2147482258 + ,2147482257 + ,2147482256 + ,2147482255 + ,2147482254 + ,2147482253 + ,2147482252 + ,2147482251 + ,2147482250 + ,2147482249 + ,2147482248 + ,2147482247 + ,2147482246 + ,2147482245 + ,2147482244 + ,2147482243 + ,2147482242 + ,2147482241 + ,2147482240 + ,2147482239 + ,2147482238 + ,2147482237 + ,2147482236 + ,2147482235 + ,2147482234 + ,2147482233 + ,2147482232 + ,2147482231 + ,2147482230 + ,2147482229 + ,2147482228 + ,2147482227 + ,2147482226 + ,2147482225 + ,2147482224 + ,2147482223 + ,2147482222 + ,2147482221 + ,2147482220 + ,2147482219 + ,2147482218 + ,2147482217 + ,2147482216 + ,2147482215 + ,2147482214 + ,2147482213 + ,2147482212 + ,2147482211 + ,2147482210 + ,2147482209 + ,2147482208 + ,2147482207 + ,2147482206 + ,2147482205 + ,2147482204 + ,2147482203 + ,2147482202 + ,2147482201 + ,2147482200 + ,2147482199 + ,2147482198 + ,2147482197 + ,2147482196 + ,2147482195 + ,2147482194 + ,2147482193 + ,2147482192 + ,2147482191 + ,2147482190 + ,2147482189 + ,2147482188 + ,2147482187 + ,2147482186 + ,2147482185 + ,2147482184 + ,2147482183 + ,2147482182 + ,2147482181 + ,2147482180 + ,2147482179 + ,2147482178 + ,2147482177 + ,2147482176 + ,2147482175 + ,2147482174 + ,2147482173 + ,2147482172 + ,2147482171 + ,2147482170 + ,2147482169 + ,2147482168 + ,2147482167 + ,2147482166 + ,2147482165 + ,2147482164 + ,2147482163 + ,2147482162 + ,2147482161 + ,2147482160 + ,2147482159 + ,2147482158 + ,2147482157 + ,2147482156 + ,2147482155 + ,2147482154 + ,2147482153 + ,2147482152 + ,2147482151 + ,2147482150 + ,2147482149 + ,1500 + ); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + X 1 + """ + +@pytest.mark.version('>=2.5') +def test_core_3740_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3753.py b/tests/bugs/test_core_3753.py new file mode 100644 index 00000000..14472e9c --- /dev/null +++ b/tests/bugs/test_core_3753.py @@ -0,0 +1,82 @@ +#coding:utf-8 +# +# id: bugs.core_3753 +# title: The trigger together with the operator MERGE if in a condition of connection ON contains new is not compiled +# decription: +# tracker_id: CORE-3753 +# min_versions: ['2.1.7'] +# versions: 2.1.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + execute block as + begin + begin execute statement 'drop trigger horse_ai'; when any do begin end end + end + ^ + set term ;^ + + recreate table cover(id int); + commit; + + recreate table horse ( + code_horse integer constraint pk_horse primary key, + code_father integer default -2 not null, + code_mother integer default -3 not null, + name varchar(50) + ); + + recreate table cover ( + code_cover integer constraint pk_cover primary key + ,code_father integer not null + ,code_mother integer not null + ,code_horse integer not null + ,constraint fk_cover_ref_father foreign key (code_father) references horse (code_horse) + ,constraint fk_cover_ref_horse foreign key (code_horse) references horse (code_horse) + ,constraint fk_cover_ref_mother foreign key (code_mother) references horse (code_horse) + ); + commit; + + set term ^; + create or alter trigger horse_ai for horse active after insert position 0 as + begin + merge into cover + using rdb$database as tbl + on cover.code_father = new.code_father and + cover.code_mother = new.code_mother + when matched then + update set + code_horse = new.code_horse + when not matched then + insert (code_horse, + code_father, + code_mother) + values (new.code_horse, + new.code_father, + new.code_mother); + end + ^ + set term ;^ + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1.7') +def test_core_3753_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_3754.py b/tests/bugs/test_core_3754.py new file mode 100644 index 00000000..e36624d4 --- /dev/null +++ b/tests/bugs/test_core_3754.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: bugs.core_3754 +# title: SIMILAR TO works wrongly +# decription: See also: sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1026749&msg=14380584 +# tracker_id: CORE-3754 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table test_a(id integer, cnt integer); + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + select iif( '1' similar to '(1|2){0,}', 1, 0)as result from rdb$database + union all + select iif( '1' similar to '(1|2){0,1}', 1, 0)from rdb$database + union all + select iif( '1' similar to '(1|2){1}', 1, 0)from rdb$database + union all + select iif( '123' similar to '(1|12[3]?){1}', 1, 0)from rdb$database + union all + select iif( '123' similar to '(1|12[3]?)+', 1, 0) from rdb$database + union all + select iif( 'qwertyqwertyqwe' similar to '(%qwe%){2,}', 1, 0) from rdb$database + union all + select iif( 'qwertyqwertyqwe' similar to '(%(qwe)%){2,}', 1, 0) from rdb$database + union all + select iif( 'qqqqqqqqqqqqqqq' similar to '(%q%){2,}', 1, 0) from rdb$database + ; + -- BTW: result in WI-T3.0.0.31681 matches to Postgress 9.3, checked 24.02.2015 + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + """ + +@pytest.mark.version('>=3.0') +def test_core_3754_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3761.py b/tests/bugs/test_core_3761.py new file mode 100644 index 00000000..548b7ab6 --- /dev/null +++ b/tests/bugs/test_core_3761.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_3761 +# title: Conversion error when using a blob as an argument for the EXCEPTION statement +# decription: +# tracker_id: CORE-3761 +# min_versions: ['2.5'] +# versions: 2.5.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.6 +# resources: None + +substitutions_1 = [('-At block line: [\\d]+, col: [\\d]+', '-At block line')] + +init_script_1 = """ + CREATE EXCEPTION CHECK_EXCEPTION 'Check exception'; + COMMIT; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + SET TERM ^; + EXECUTE BLOCK AS + BEGIN + EXCEPTION CHECK_EXCEPTION CAST ('WORD' AS BLOB SUB_TYPE TEXT); + END^^ + SET TERM ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = HY000 + exception 1 + -CHECK_EXCEPTION + -WORD + -At block line: 4, col: 2 + """ + +@pytest.mark.version('>=2.5.6') +def test_core_3761_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_3777.py b/tests/bugs/test_core_3777.py new file mode 100644 index 00000000..2a3385c7 --- /dev/null +++ b/tests/bugs/test_core_3777.py @@ -0,0 +1,63 @@ +#coding:utf-8 +# +# id: bugs.core_3777 +# title: Conversion error from string when using GROUP BY +# decription: +# tracker_id: CORE-3777 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE TABLE2 ( + ID INTEGER NOT NULL, + NAME VARCHAR(50) +); +ALTER TABLE TABLE2 ADD CONSTRAINT PK_TABLE2 PRIMARY KEY (ID); +COMMIT; +CREATE TABLE TABLE1 ( + ID INTEGER NOT NULL, + ID_NAME INTEGER, + NAME COMPUTED BY (COALESCE((SELECT NAME FROM TABLE2 WHERE ID = ID_NAME) || '.', '')), + OTHER_FIELD INTEGER +); +ALTER TABLE TABLE1 ADD CONSTRAINT PK_TABLE1 PRIMARY KEY (ID); +COMMIT; +INSERT INTO TABLE2 (ID, NAME) VALUES (1, 'qqq'); +INSERT INTO TABLE2 (ID, NAME) VALUES (2, 'www'); +INSERT INTO TABLE2 (ID, NAME) VALUES (3, 'eee'); +COMMIT; +INSERT INTO TABLE1 (ID, ID_NAME, OTHER_FIELD) VALUES (1, 1, 100); +INSERT INTO TABLE1 (ID, ID_NAME, OTHER_FIELD) VALUES (2, 2, 101); +INSERT INTO TABLE1 (ID, ID_NAME, OTHER_FIELD) VALUES (3, 3, 102); +COMMIT;""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT T.NAME FROM TABLE1 T GROUP BY T.NAME,T.OTHER_FIELD; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """SQL> +NAME +=================================================== +eee. +qqq. +www. + +SQL>""" + +@pytest.mark.version('>=2.5.2') +def test_core_3777_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3779.py b/tests/bugs/test_core_3779.py new file mode 100644 index 00000000..e55410e8 --- /dev/null +++ b/tests/bugs/test_core_3779.py @@ -0,0 +1,61 @@ +#coding:utf-8 +# +# id: bugs.core_3779 +# title: Report OS user name in MON$ATTACHMENTS +# decription: +# We compare values in mon$attachment with those that can be obtained using pure Python calls (without FB). +# NB: on Windows remote_os_user contains value in lower case ('zotov'), exact value was: 'Zotov'. +# +# tracker_id: CORE-3779 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import socket +# import getpass +# +# cur=db_conn.cursor() +# cur.execute('select mon$remote_host, mon$remote_os_user from mon$attachments where mon$attachment_id=current_connection') +# for r in cur: +# if r[0].upper() == socket.gethostname().upper(): +# print('Check of remote_host: passed') +# else: +# print('FAILED check remote_host: got |'+r[0]+'| instead of |'+socket.gethostname()+'|') +# +# if r[1].upper() == getpass.getuser().upper(): +# print('Check of remote_os_user: passed') +# else: +# print('FAILED check remote_os_user: got |'+r[1]+'| instead of |'+getpass.getuser()+'|') +# +# cur.close() +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Check of remote_host: passed + Check of remote_os_user: passed + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_3779_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_3798.py b/tests/bugs/test_core_3798.py new file mode 100644 index 00000000..84aa7ffd --- /dev/null +++ b/tests/bugs/test_core_3798.py @@ -0,0 +1,58 @@ +#coding:utf-8 +# +# id: bugs.core_3798 +# title: fb server die when carry out the LEFT + INNER JOIN +# decription: +# tracker_id: CORE-3798 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table table1 ( + id integer not null, + name varchar(30), + id_breed integer + ); + alter table table1 add constraint pk_table1 primary key (id); + + recreate table table2 ( + id integer not null, + id_table1 integer + ); + alter table table2 add constraint pk_table2 primary key (id); + + recreate table table3 ( + id integer not null, + id_breed integer + ); + alter table table3 add constraint pk_table3 primary key (id); + commit; + + select table2.id + from table2 + left join table1 on table1.id = table2.id_table1 + inner join table3 on table1.id_breed = table3.id_breed + where table1.id = 1 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +def test_core_3798_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_3799.py b/tests/bugs/test_core_3799.py new file mode 100644 index 00000000..c113183d --- /dev/null +++ b/tests/bugs/test_core_3799.py @@ -0,0 +1,122 @@ +#coding:utf-8 +# +# id: bugs.core_3799 +# title: with caller privileges option do not work with autonomous transaction option +# decription: +# Checked on: 4.0.0.1635: OK, 1.505s; 3.0.5.33180: OK, 1.555s; 2.5.9.27119: OK, 0.308s. +# +# tracker_id: CORE-3799 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set wng off; + -- Drop old account if it remains from prevoius run: + set term ^; + execute block as + begin + begin + execute statement 'drop user tmp$c3799' with autonomous transaction; + when any do begin end + end + end + ^ + set term ;^ + commit; + + create user tmp$c3799 password '123'; + commit; + + revoke all on all from tmp$c3799; + commit; + + create or alter procedure sp_test as begin end; + recreate table test(whoami rdb$user, my_trn int default current_transaction, outer_trn int); + commit; + + set term ^ ; + create or alter procedure sp_test as + begin + execute statement ('insert into test(whoami, outer_trn) values(:x, :y)') + ( x := current_user , y := current_transaction ) + with caller privileges + with autonomous transaction; + end + ^ + set term ;^ + commit; + + grant insert,select on table test to procedure sp_test; + grant execute on procedure sp_test to user tmp$c3799; + commit; + + ------------------------------------------------------------------------------------------------- + + set term ^; + execute block as + declare v_usr rdb$user = 'tmp$c3799'; + declare v_pwd rdb$user = '123'; + begin + execute statement 'execute procedure sp_test' as user v_usr password v_pwd; + end + ^ + set term ^; + commit; + + + ------------------------------------------------------------------------------------------------- + --connect '$(DSN)' user 'tmp$c3799' password '123'; + --execute procedure sp_test; + --commit; + ------------------------------------------------------------------------------------------------- + + set list on; + select whoami as "Who am I ?", sign( my_trn - outer_trn ) "Did I work in AUTONOMOUS Tx ?" + from test; + 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; + + drop user tmp$c3799; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Who am I ? TMP$C3799 + Did I work in AUTONOMOUS Tx ? 1 + """ + +@pytest.mark.version('>=2.5.2') +def test_core_3799_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3801.py b/tests/bugs/test_core_3801.py new file mode 100644 index 00000000..ee107eb9 --- /dev/null +++ b/tests/bugs/test_core_3801.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: bugs.core_3801 +# title: Warnings could be put twice in status-vector +# decription: +# tracker_id: CORE-3801 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=1, init=init_script_1) + +test_script_1 = """ + set term ^ ; + execute block as + declare d date; + begin + d = "now"; + end + ^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + SQL warning code = 301 + -DATE data type is now called TIMESTAMP + """ + +@pytest.mark.version('>=2.5.2') +def test_core_3801_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_3806.py b/tests/bugs/test_core_3806.py new file mode 100644 index 00000000..c34be4ac --- /dev/null +++ b/tests/bugs/test_core_3806.py @@ -0,0 +1,56 @@ +#coding:utf-8 +# +# id: bugs.core_3806 +# title: Wrong data returned if a sub-query or a computed field refers to the base table in the ORDER BY clause +# decription: +# tracker_id: CORE-3806 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t (col1 int, col2 int, col3 int); +insert into t values (100, 200, 300); +insert into t values (101, 201, 301); +insert into t values (102, 202, 302); +commit; +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """alter table t drop col1; +select col2, col3 from t as t1; +select col2, col3 from t as t1 where exists (select * from t as t2 order by t1.col2 ); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """SQL> + COL2 COL3 +============ ============ + 200 300 + 201 301 + 202 302 + +SQL> + COL2 COL3 +============ ============ + 200 300 + 201 301 + 202 302 + +SQL>""" + +@pytest.mark.version('>=2.5.2') +def test_core_3806_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3807.py b/tests/bugs/test_core_3807.py new file mode 100644 index 00000000..c5031941 --- /dev/null +++ b/tests/bugs/test_core_3807.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: bugs.core_3807 +# title: Error "Invalid expression in the select list" can be unexpectedly raised if a string literal is used inside a GROUP BY clause in a multi-byte connection +# decription: +# tracker_id: CORE-3807 +# min_versions: ['2.1.5'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """select + 'Current time is ' || cast(a.t as varchar(15)) +from + (select '16:06:03.0000' t from rdb$database) a +group by + 'Current time is ' || cast(a.t as varchar(15)); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +CONCATENATION +=============================== +Current time is 16:06:03.0000 + +""" + +@pytest.mark.version('>=3.0') +def test_core_3807_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3808.py b/tests/bugs/test_core_3808.py new file mode 100644 index 00000000..4e856fc0 --- /dev/null +++ b/tests/bugs/test_core_3808.py @@ -0,0 +1,73 @@ +#coding:utf-8 +# +# id: bugs.core_3808 +# title: Provide ability to return all columns using RETURNING (eg RETURNING *) +# decription: +# Ability to use 'returning *' is verified both in DSL and PSQL. +# Checked on: 4.0.0.1455: OK, 1.337s. +# +# 30.10.2019. NB: new datatype in FB 4.0 was introduces: numeric(38,0). +# It can lead to additional ident of values when we show them in form "SET LIST ON", +# so we have to ignore all internal spaces - see added 'substitution' section below. +# +# tracker_id: CORE-3808 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + recreate table test(id int default 2, x computed by ( id*2 ), y computed by ( x*x ), z computed by ( y*y ) ); + commit; + + insert into test default values returning *; + + update test set id=3 where id=2 returning *; + + set term ^; + execute block returns( deleted_id int, deleted_x bigint, deleted_y bigint, deleted_z bigint ) as + begin + delete from test where id=3 returning * into deleted_id, deleted_x, deleted_y, deleted_z; + suspend; + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 2 + X 4 + Y 16 + Z 256 + + ID 3 + X 6 + Y 36 + Z 1296 + + DELETED_ID 3 + DELETED_X 6 + DELETED_Y 36 + DELETED_Z 1296 + """ + +@pytest.mark.version('>=4.0') +def test_core_3808_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3820.py b/tests/bugs/test_core_3820.py new file mode 100644 index 00000000..7711f242 --- /dev/null +++ b/tests/bugs/test_core_3820.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: bugs.core_3820 +# title: RDB$TYPES contain duplicate character sets +# decription: +# tracker_id: CORE-3820 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + select rdb$field_name, rdb$type_name, count(rdb$type_name) + from rdb$types + group by rdb$field_name, rdb$type_name + having count(rdb$type_name) > 1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +def test_core_3820_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_3829.py b/tests/bugs/test_core_3829.py new file mode 100644 index 00000000..ee36c874 --- /dev/null +++ b/tests/bugs/test_core_3829.py @@ -0,0 +1,470 @@ +#coding:utf-8 +# +# id: bugs.core_3829 +# title: Bad alias table choice joining CTE +# decription: +# Confirmed wrong result on 2.5.1; no problem on 2.5.7 and above +# +# 30.10.2019. NB: new datatype in FB 4.0 was introduces: numeric(38,0). +# It can lead to additional ident of values when we show them in form "SET LIST ON", +# so we have to ignore all internal spaces - see added 'substitution' section below. +# Checked on: +# 4.0.0.1635 SS: 1.848s. +# 3.0.5.33182 SS: 1.531s. +# 2.5.9.27146 SC: 0.572s. +# +# tracker_id: CORE-3829 +# min_versions: ['2.5.7'] +# versions: 2.5.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.7 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core3829.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + with totalk (kk1, variant, tt, qq, mm, ff, f1, f2, f3, f4, f5) as + ( + select ll.kk1, ll.variant, + sum (iif(ll.selector_y_n='Y', 1, 0)), + count(*), -- <<<< problem here + -- count(1), -- <<<< this doesn't work either + -- sum(1), -- <<<<< this neither + -- sum(iif(ll.variant=1,1,1)), -- <<<< workaround + sum (iif(ll.selector_m_f='M' and ll.selector_y_n='Y', 1, 0)), + sum (iif(ll.selector_m_f='F' and ll.selector_y_n='Y', 1, 0)), + sum(iif(ll.selector_1_5='1' and ll.selector_y_n='Y', 1, 0)), + sum(iif(ll.selector_1_5='2' and ll.selector_y_n='Y', 1, 0)), + sum(iif(ll.selector_1_5='3' and ll.selector_y_n='Y', 1, 0)), + sum(iif(ll.selector_1_5='4' and ll.selector_y_n='Y', 1, 0)), + sum(iif(ll.selector_1_5='5' and ll.selector_y_n='Y', 1, 0)) + from testcte ll + group by 1, 2 + ) + select + ff.kk1, + ff.descrkk, + sum(t1.tt) "TT 1", + sum(t2.tt) "TT 2", + sum(t1.qq) "QQ 1", + sum(t2.qq) "QQ 2", + sum(t1.mm) "MM 1", + sum(t2.mm) "MM 2", + sum(t1.ff) "FF 1", + sum(t2.ff) "FF 2", + sum(t1.f1) "G1 1", + sum(t2.f1) "G1 2", + sum(t1.f2) "G2 1", + sum(t2.f2) "G2 2", + sum(t1.f3) "G3 1", + sum(t2.f3) "G3 2", + sum(t1.f4) "G4 1", + sum(t2.f4) "G4 2", + sum(t1.f5) "G5 1", + sum(t2.f5) "G5 2" + from testmain ff + left outer join totalk t1 on t1.kk1=ff.kk1 and t1.variant = 1 + left outer join totalk t2 on t2.kk1=ff.kk1 and t2.variant = 2 + group by 1, 2 + ; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + + KK1 A1 + DESCRKK A A A A A + TT 1 44 + TT 2 52 + QQ 1 103 + QQ 2 111 + MM 1 24 + MM 2 23 + FF 1 20 + FF 2 29 + G1 1 9 + G1 2 10 + G2 1 10 + G2 2 5 + G3 1 10 + G3 2 13 + G4 1 9 + G4 2 13 + G5 1 6 + G5 2 11 + + KK1 A2 + DESCRKK AA AA AA + TT 1 41 + TT 2 47 + QQ 1 103 + QQ 2 98 + MM 1 25 + MM 2 25 + FF 1 16 + FF 2 22 + G1 1 7 + G1 2 10 + G2 1 9 + G2 2 8 + G3 1 7 + G3 2 7 + G4 1 9 + G4 2 10 + G5 1 9 + G5 2 12 + + KK1 A3 + DESCRKK AAA AAA + TT 1 55 + TT 2 47 + QQ 1 107 + QQ 2 114 + MM 1 26 + MM 2 20 + FF 1 29 + FF 2 27 + G1 1 5 + G1 2 13 + G2 1 10 + G2 2 7 + G3 1 14 + G3 2 11 + G4 1 12 + G4 2 6 + G5 1 14 + G5 2 10 + + KK1 A4 + DESCRKK AAAA + TT 1 56 + TT 2 56 + QQ 1 113 + QQ 2 109 + MM 1 31 + MM 2 31 + FF 1 25 + FF 2 25 + G1 1 10 + G1 2 16 + G2 1 11 + G2 2 9 + G3 1 10 + G3 2 10 + G4 1 10 + G4 2 11 + G5 1 15 + G5 2 10 + + KK1 A5 + DESCRKK AAAAA + TT 1 55 + TT 2 51 + QQ 1 118 + QQ 2 117 + MM 1 29 + MM 2 27 + FF 1 26 + FF 2 24 + G1 1 15 + G1 2 6 + G2 1 10 + G2 2 13 + G3 1 10 + G3 2 5 + G4 1 10 + G4 2 12 + G5 1 10 + G5 2 15 + + KK1 A6 + DESCRKK AAAAAA + TT 1 + TT 2 + QQ 1 + QQ 2 + MM 1 + MM 2 + FF 1 + FF 2 + G1 1 + G1 2 + G2 1 + G2 2 + G3 1 + G3 2 + G4 1 + G4 2 + G5 1 + G5 2 + + KK1 B1 + DESCRKK B B B B B + TT 1 69 + TT 2 72 + QQ 1 116 + QQ 2 129 + MM 1 33 + MM 2 46 + FF 1 36 + FF 2 26 + G1 1 15 + G1 2 14 + G2 1 9 + G2 2 14 + G3 1 13 + G3 2 19 + G4 1 15 + G4 2 17 + G5 1 17 + G5 2 8 + + KK1 B2 + DESCRKK BB BB BB + TT 1 58 + TT 2 61 + QQ 1 118 + QQ 2 124 + MM 1 24 + MM 2 27 + FF 1 34 + FF 2 34 + G1 1 10 + G1 2 15 + G2 1 10 + G2 2 14 + G3 1 14 + G3 2 10 + G4 1 16 + G4 2 8 + G5 1 8 + G5 2 14 + + KK1 B3 + DESCRKK BBB BBB + TT 1 54 + TT 2 62 + QQ 1 126 + QQ 2 115 + MM 1 32 + MM 2 28 + FF 1 22 + FF 2 34 + G1 1 16 + G1 2 14 + G2 1 10 + G2 2 10 + G3 1 6 + G3 2 9 + G4 1 12 + G4 2 14 + G5 1 10 + G5 2 15 + + KK1 B4 + DESCRKK BBBB + TT 1 + TT 2 + QQ 1 + QQ 2 + MM 1 + MM 2 + FF 1 + FF 2 + G1 1 + G1 2 + G2 1 + G2 2 + G3 1 + G3 2 + G4 1 + G4 2 + G5 1 + G5 2 + + KK1 B5 + DESCRKK BBBBB + TT 1 + TT 2 + QQ 1 + QQ 2 + MM 1 + MM 2 + FF 1 + FF 2 + G1 1 + G1 2 + G2 1 + G2 2 + G3 1 + G3 2 + G4 1 + G4 2 + G5 1 + G5 2 + + KK1 B6 + DESCRKK BBBBBB + TT 1 + TT 2 + QQ 1 + QQ 2 + MM 1 + MM 2 + FF 1 + FF 2 + G1 1 + G1 2 + G2 1 + G2 2 + G3 1 + G3 2 + G4 1 + G4 2 + G5 1 + G5 2 + + KK1 C1 + DESCRKK C C C C C + TT 1 60 + TT 2 65 + QQ 1 117 + QQ 2 121 + MM 1 36 + MM 2 32 + FF 1 24 + FF 2 33 + G1 1 11 + G1 2 18 + G2 1 7 + G2 2 9 + G3 1 16 + G3 2 17 + G4 1 14 + G4 2 9 + G5 1 12 + G5 2 12 + + KK1 C2 + DESCRKK CC CC CC + TT 1 66 + TT 2 60 + QQ 1 123 + QQ 2 113 + MM 1 33 + MM 2 29 + FF 1 33 + FF 2 31 + G1 1 18 + G1 2 12 + G2 1 12 + G2 2 15 + G3 1 12 + G3 2 9 + G4 1 12 + G4 2 14 + G5 1 12 + G5 2 10 + + KK1 C3 + DESCRKK CCC CCC + TT 1 57 + TT 2 76 + QQ 1 123 + QQ 2 134 + MM 1 34 + MM 2 33 + FF 1 23 + FF 2 43 + G1 1 15 + G1 2 11 + G2 1 13 + G2 2 22 + G3 1 8 + G3 2 15 + G4 1 11 + G4 2 16 + G5 1 10 + G5 2 12 + + KK1 C4 + DESCRKK CCCC + TT 1 66 + TT 2 52 + QQ 1 121 + QQ 2 102 + MM 1 35 + MM 2 27 + FF 1 31 + FF 2 25 + G1 1 11 + G1 2 11 + G2 1 16 + G2 2 13 + G3 1 13 + G3 2 10 + G4 1 12 + G4 2 11 + G5 1 14 + G5 2 7 + + KK1 C5 + DESCRKK CCCCC + TT 1 58 + TT 2 51 + QQ 1 113 + QQ 2 112 + MM 1 29 + MM 2 17 + FF 1 29 + FF 2 34 + G1 1 8 + G1 2 15 + G2 1 14 + G2 2 8 + G3 1 11 + G3 2 11 + G4 1 12 + G4 2 6 + G5 1 13 + G5 2 11 + + KK1 C6 + DESCRKK CCCCCC + TT 1 + TT 2 + QQ 1 + QQ 2 + MM 1 + MM 2 + FF 1 + FF 2 + G1 1 + G1 2 + G2 1 + G2 2 + G3 1 + G3 2 + G4 1 + G4 2 + G5 1 + G5 2 + """ + +@pytest.mark.version('>=2.5.7') +def test_core_3829_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3834.py b/tests/bugs/test_core_3834.py new file mode 100644 index 00000000..5d5985ae --- /dev/null +++ b/tests/bugs/test_core_3834.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: bugs.core_3834 +# title: Usage of a NATURAL JOIN with a derived table crashes the server +# decription: +# tracker_id: CORE-3834 +# min_versions: ['2.5.2'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core3834.fbk', init=init_script_1) + +test_script_1 = """ + set planonly; + select r.revision + from ( select r.revision, r.stageid from tilemaps r ) r + natural join logs g + where stageid = ? + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN HASH (G NATURAL, R R NATURAL) + """ + +@pytest.mark.version('>=3.0') +def test_core_3834_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3858.py b/tests/bugs/test_core_3858.py new file mode 100644 index 00000000..7f27dc2e --- /dev/null +++ b/tests/bugs/test_core_3858.py @@ -0,0 +1,98 @@ +#coding:utf-8 +# +# id: bugs.core_3858 +# title: Very poor performance of SIMILAR TO on some arguments + unable to disconnect via DELETE FROM MON$ATTACHMENTS +# decription: +# Confirmed normal work (evaluation for less than 2 ms) on WI-T4.0.0.1598 +# Note. Part of pattern: "[[:ALNUM:]\\_\\-]" -- looks strange but it is correct. +# And it should NOT be changed to somewhat like "[[:ALNUM:]]\\_\\-": previoud FB versions hanged exactly +# because of this "strange and wrong" pattern. +# +# tracker_id: CORE-3858 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + + set term ^; + execute block as + begin + rdb$set_context( 'USER_SESSION','DTS_START', cast('now' as timestamp) ); + rdb$set_context( 'USER_SESSION','MAX_THRESHOLD_MS', 500 ); + -- ^ + -- | + -- ############################# + -- MAX ALLOWED EXECUTION TIME,MS + -- ############################# + end + ^ + set term ;^ + + select 1 as result from rdb$database where + ' + group by + MATCODE, + MATNAME, + NOTE, + GROUPCODE, + STATE, + MATPROD, + MATFULL, + KOLVO, + EDIZM, + MATGRPCOD, + CODE, + TEXTTOHIST, + INV_ROOMDOC, + INV_ROOM, + PARENTCODE, + INVIS + ' + similar to + '%group[[:WHITESPACE:]]+by[[:WHITESPACE:]]+([[:ALNUM:]]|_)+([[:WHITESPACE:]]*,[[:WHITESPACE:]]*[[:ALNUM:]]+){12,}[[:WHITESPACE:]]*%' + ; + + + set count off; + select + iif( evaluated_ms <= max_allowed_ms + ,'acceptable' + ,'TOO LONG: ' || evaluated_ms || ' ms - this is more then threshold = ' || max_allowed_ms || ' ms' + ) as duration + from ( + select + datediff( millisecond from cast(rdb$get_context( 'USER_SESSION','DTS_START') as timestamp) to current_timestamp ) evaluated_ms + ,cast( rdb$get_context( 'USER_SESSION','MAX_THRESHOLD_MS' ) as int ) as max_allowed_ms + from rdb$database + ); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT 1 + Records affected: 1 + DURATION acceptable + """ + +@pytest.mark.version('>=4.0') +def test_core_3858_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3860.py b/tests/bugs/test_core_3860.py new file mode 100644 index 00000000..ae70dbf8 --- /dev/null +++ b/tests/bugs/test_core_3860.py @@ -0,0 +1,56 @@ +#coding:utf-8 +# +# id: bugs.core_3860 +# title: Trace API: Faulty database filter crashes server +# decription: +# Confirmed crash on 2.5.1.26351, got on console: +# === +# Unable to complete network request to host "localhost". +# -Error reading data from the connection. +# === +# For 2.5.x we prepare trace config with invalid pattern for database section, launch trace and do trivial query to some database table. +# Trace STDOUT (beside "Trace session ID 5 started") should contain several blocks like this: +# === +# Error creating trace session for service manager attachment: +# error while parsing trace configuration +# line 8: expected closing element, got "database" +# ==== +# We create array of patterns for each of these messages and search in it each line of trace STDOUT. +# Every line should be found in this patterns array, otherwise this is UNEXPECTED case. +# Finally, if every line will be found then we have no unexpected result and 'expected_stdout' should be EMPTY. +# Checked on: +# 2.5.8.27067: OK, 7.000s. +# 2.5.9.27107: OK, 6.438s. +# For 3.0+ we just remain test body empty (there is nothing to check because of changed trace config format). +# +# tracker_id: CORE-3860 +# min_versions: ['2.5.2'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_3860_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_3874.py b/tests/bugs/test_core_3874.py new file mode 100644 index 00000000..9b44978c --- /dev/null +++ b/tests/bugs/test_core_3874.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_3874 +# title: Computed column appears in non-existant rows of left join +# decription: +# tracker_id: CORE-3874 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE TEST_TABLE +( + ID INTEGER, + COMPUTED_COL VARCHAR(6) COMPUTED BY ('FAILED') +); +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT t.COMPUTED_COL +FROM RDB$DATABASE r +LEFT JOIN TEST_TABLE t +ON r.RDB$RELATION_ID = t.ID; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """COMPUTED_COL +============ + +""" + +@pytest.mark.version('>=2.5.3') +def test_core_3874_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3881.py b/tests/bugs/test_core_3881.py new file mode 100644 index 00000000..41f93d5c --- /dev/null +++ b/tests/bugs/test_core_3881.py @@ -0,0 +1,89 @@ +#coding:utf-8 +# +# id: bugs.core_3881 +# title: Extend the error reported for index/constraint violations to include the problematic key value +# decription: +# tracker_id: CORE-3881 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [('-At trigger.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table tmain( + id int constraint tmain_pk primary key using index tmain_pk + ,mka int + ,mkb int + ,constraint tmain_mka_mkb_constraint_unq unique(mka, mkb) using index tmain_mka_mkb_constraint_unq + ,constraint tmain_fka foreign key (mka) references tmain(id) on update set null using index tmain_fka + ,constraint tmain_fkb foreign key (mkb) references tmain(id) on update set null using index tmain_fkb + ); + create unique descending index tmain_difference_unq_idx on tmain computed by( (coalesce(mka,0) - coalesce(mkb,0)) ); + commit; + + insert into tmain(id, mka, mkb) values( 100, 100, null); + insert into tmain(id, mka, mkb) values( 200, null, 200); + insert into tmain(id, mka, mkb) values( 300, 200, null); + commit; + + + -- This statement should violate primary key constraint: + insert into tmain(id, mka, mkb) select 600-id, 600-id, mkb from tmain where id<>200; + + -- This will violate unique constraint `tmain_mka_mkb_constraint_unq` defined on two nullable fields:(mka, mkb): + insert into tmain(id, mka, mkb) values(500, null,200); + + -- This will violate unique computed-by index `tmain_difference_unq_idx` because NULLS are treated in its expression as ZEROES: + update tmain set mka=null, mkb=null; + + -- This will violate unique constraint `tmain_mka_mkb_constraint_unq` defined on two nullable fields:(mka, mkb): + update tmain set mka=coalesce(mka, 200), mkb=coalesce(mkb, 200); + + -- This will force CASCADE trigger to make updating values in fields `mka` and `mkb` to NULLS. + -- But it means that these NULLS will be treated as ZEROEs in expression of computed-by index `tmain_difference_unq_idx` + -- and thus again will violate its uniquness: + update tmain set id=0 where id=200; -- uniq idx tmain_difference_unq_idx, At trigger 'CHECK_nn' + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + 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) + + 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) + + 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 + 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' + """ + +@pytest.mark.version('>=2.5.3') +def test_core_3881_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_3883.py b/tests/bugs/test_core_3883.py new file mode 100644 index 00000000..959f6468 --- /dev/null +++ b/tests/bugs/test_core_3883.py @@ -0,0 +1,61 @@ +#coding:utf-8 +# +# id: bugs.core_3883 +# title: Ambiguous field name in the trigger when it does a select from the table +# decription: +# tracker_id: CORE-3883 +# min_versions: ['2.0.7'] +# versions: 2.0.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table regtype ( + code_regtype int constraint pk_regtype primary key, + name varchar(20), + multirecord smallint + ); + + recreate table reg ( + code_reg int constraint pk_reg primary key, + code_regtype int, + code_horse int + ); + + create exception e_duplicate_reg 'duplicate registration info'; + + set term ^ ; + create or alter trigger reg_bi0 for reg + active before insert position 0 as + begin + if (exists(select 1 + from reg + inner join regtype on reg.code_regtype = regtype.code_regtype + where reg.code_horse = new.code_horse and + reg.code_regtype = new.code_regtype and + regtype.multirecord = 0)) then + exception e_duplicate_reg; + end + ^ + set term ;^ + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.0.7') +def test_core_3883_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_3884.py b/tests/bugs/test_core_3884.py new file mode 100644 index 00000000..163c031f --- /dev/null +++ b/tests/bugs/test_core_3884.py @@ -0,0 +1,204 @@ +#coding:utf-8 +# +# id: bugs.core_3884 +# title: Server crashes on preparing empty query when trace is enabled +# decription: +# Could reproduce crash only once. All other attempts were useless - FB lives. +# +# tracker_id: CORE-3884 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('Unexpected end of command.*', 'Unexpected end of command')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import re +# import subprocess +# import time +# from fdb import services +# from subprocess import Popen +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # Obtain engine version: +# engine = str(db_conn.engine_version) # convert to text because 'float' object has no attribute 'startswith' +# db_file = db_conn.database_name +# # do NOT: db_conn.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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# txt25 = '''# Trace config, format for 2.5. Generated auto, do not edit! +# +# enabled true +# time_threshold 0 +# log_statement_prepare true +# # exclude_filter '%execute block%' +# # did not work in 2.5.1: include_filter '%(INSERT|UPDATE|DELETE|SELECT)%' +# log_statement_finish true +# +# ''' +# +# # NOTES ABOUT TRACE CONFIG FOR 3.0: +# # 1) Header contains `database` clause in different format vs FB 2.5: its data must be enclosed with '{' '}' +# # 2) Name and value must be separated by EQUALITY sign ('=') in FB-3 trace.conf, otherwise we get runtime error: +# # element "<. . .>" have no attribute value set +# +# txt30 = '''# Trace config, format for 3.0. Generated auto, do not edit! +# database=%[\\\\\\\\/]bugs.core_3884.fdb +# { +# enabled = true +# time_threshold = 0 +# log_statement_finish = true +# } +# ''' +# +# f_trc_cfg=open( os.path.join(context['temp_directory'],'tmp_trace_3884.cfg'), 'w') +# if engine.startswith('2.5'): +# f_trc_cfg.write(txt25) +# else: +# f_trc_cfg.write(txt30) +# f_trc_cfg.close() +# +# # ############################################################## +# # S T A R T T R A C E i n S E P A R A T E P R O C E S S +# # ############################################################## +# +# f_trc_log=open( os.path.join(context['temp_directory'],'tmp_trace_3884.log'), "w") +# f_trc_err=open( os.path.join(context['temp_directory'],'tmp_trace_3884.err'), "w") +# +# p_trace = Popen( [ context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_start' , 'trc_cfg', f_trc_cfg.name],stdout=f_trc_log,stderr=f_trc_err) +# +# # this delay need for trace start and finish its output about invalid section in its config file: +# time.sleep(2) +# +# # #################################################### +# # G E T A C T I V E T R A C E S E S S I O N I D +# # #################################################### +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# +# f_trc_lst = open( os.path.join(context['temp_directory'],'tmp_trace_3884.lst'), 'w') +# subprocess.call([context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_list'], stdout=f_trc_lst) +# flush_and_close( f_trc_lst ) +# +# # !!! DO NOT REMOVE THIS LINE !!! +# time.sleep(1) +# +# trcssn=0 +# with open( f_trc_lst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# +# +# #............................................................................. +# +# sql_cmd=''' execute block returns(n int) as +# declare s varchar(100) = 'SELECT count(*) from rdb$database'; +# begin +# execute statement s into n; +# suspend; +# end +# ''' +# +# #sql_cmd=' \\n \\n\\n ' +# sql_cmd='' +# +# cur=db_conn.cursor() +# try: +# cur.execute( sql_cmd ) +# for r in cur: +# n = r[0] +# except Exception,e: +# for i in e[0].split('\\n'): +# print('error text:',i) +# finally: +# cur.close() +# +# db_conn.commit() +# #............................................................................. +# +# +# # #################################################### +# # S E N D R E Q U E S T T R A C E T O S T O P +# # #################################################### +# if trcssn>0: +# fn_nul = open(os.devnull, 'w') +# subprocess.call([context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_stop','trc_id', trcssn], stdout=fn_nul) +# fn_nul.close() +# # DO NOT REMOVE THIS LINE: +# time.sleep(2) +# +# +# p_trace.terminate() +# flush_and_close( f_trc_log ) +# flush_and_close( f_trc_err ) +# +# +# # CLEANUP +# ######### +# time.sleep(1) +# cleanup( [i.name for i in (f_trc_cfg, f_trc_log, f_trc_err, f_trc_lst) ] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + error text: Error while preparing SQL statement: + error text: - SQLCODE: -104 + error text: - Unexpected end of command - line 1, column 1 + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_3884_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_3894.py b/tests/bugs/test_core_3894.py new file mode 100644 index 00000000..ce932030 --- /dev/null +++ b/tests/bugs/test_core_3894.py @@ -0,0 +1,59 @@ +#coding:utf-8 +# +# id: bugs.core_3894 +# title: Wrong numbers in error message for decreasing char/varchar columns +# decription: +# tracker_id: CORE-3894 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set autoddl off; + recreate table test(id int); + commit; + + alter table test add s01 varchar(8188) character set utf8; + commit; + + alter table test alter column s01 type varchar(8189) character set utf8; + alter table test alter column s01 type varchar(8190) character set utf8; + alter table test alter column s01 type varchar(8189) character set utf8; + commit; + + show table test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID INTEGER Nullable + S01 VARCHAR(8190) CHARACTER SET UTF8 Nullable + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER TABLE TEST failed + -New size specified for column S01 must be at least 8190 characters. + """ + +@pytest.mark.version('>=3.0') +def test_core_3894_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3895.py b/tests/bugs/test_core_3895.py new file mode 100644 index 00000000..318b723d --- /dev/null +++ b/tests/bugs/test_core_3895.py @@ -0,0 +1,114 @@ +#coding:utf-8 +# +# id: bugs.core_3895 +# title: High memory usage when PSQL code SELECT's from stored procedure which modified some data +# decription: +# Test does calls of selectable SP which performs DML inside itself. +# After every call we store value of db_info(fdb.isc_info_current_memory) as new element in list. +# After all calls finish we scan list for difference between adjacent elements which exceeds +# threshold. +# Value of this threshold depends on FB engine version. +# +# On current FB versions memory usage is incremented (after every call of SP, w/o commit) by: +# 1) ~ 1800 bytes for 2.5.7 +# 2) ~ 14500 bytes for 3.0 +# +# Confirmed excessive memory usage on WI-V2.5.2.26540 (requires additional ~100 Kb). +# +# tracker_id: CORE-3895 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + set term ^; + create or alter procedure sp_main returns (id integer) as begin suspend; end + ^ + create or alter procedure sp_select_and_insert (p_id integer) returns (id integer) as begin suspend; end + ^ + commit + ^ + recreate table test (id integer) + ^ + + create or alter procedure sp_select_and_insert (p_id integer) returns (id integer) as + begin + insert into test(id) values(:p_id); + id = p_id; + suspend; + end + ^ + + create or alter procedure sp_main returns (id integer) + as + declare i int = 0; + begin + while (i < 1000) do begin + select id from sp_select_and_insert(:i) into :id; + i = i + 1; + end + suspend; + end + ^ + commit + ^ + set term ;^ + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import fdb +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # Obtain engine version: +# cur1=db_conn.cursor() +# cur1.execute("select rdb$get_context('SYSTEM','ENGINE_VERSION') as engine_version from rdb$database") +# for row in cur1: +# engine = row[0] +# cur1.close() +# +# sql_check="select id from sp_main" +# cur2=db_conn.cursor() +# +# mem_usage=[] +# run_cnt=20 +# +# for i in range(0, run_cnt): +# cur2.execute(sql_check) +# for r in cur2: +# pass +# mem_usage.append( db_conn.db_info(fdb.isc_info_current_memory) ) +# cur2.close() +# db_conn.close() +# +# max_mem_leak=4096 if engine.startswith('2.5') else 16384 +# +# for i in range(1, run_cnt): +# m0=mem_usage[i-1] +# m1=mem_usage[i] +# if m1 - m0 >= max_mem_leak: +# print('Unexpected memory leak: '+str(m1-m0)+' bytes, exceeds threshold = '+str(max_mem_leak) ) # 2.5.2: 108532 ... 108960; 2.5.7: 1192 ... 1680 +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.3') +@pytest.mark.xfail +def test_core_3895_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_3899.py b/tests/bugs/test_core_3899.py new file mode 100644 index 00000000..a71ad618 --- /dev/null +++ b/tests/bugs/test_core_3899.py @@ -0,0 +1,48 @@ +#coding:utf-8 +# +# id: bugs.core_3899 +# title: row_number(), rank() and dense_rank() return BIGINT datatype in dialect 1 +# decription: +# tracker_id: CORE-3899 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!sqltype:|name:).)*$', ''), ('[ ]+', ' '), ('[\t]*', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=1, init=init_script_1) + +test_script_1 = """ + set sqlda_display on; + set planonly; + select row_number()over() rno, rank()over() rnk, dense_rank()over() drk + from rdb$database; + -- NB: on dialect-3 output is: + -- sqltype: 580 INT64 ... + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 01: sqltype: 480 DOUBLE scale: 0 subtype: 0 len: 8 + : name: ROW_NUMBER alias: RNO + 02: sqltype: 480 DOUBLE scale: 0 subtype: 0 len: 8 + : name: RANK alias: RNK + 03: sqltype: 480 DOUBLE scale: 0 subtype: 0 len: 8 + : name: DENSE_RANK alias: DRK + """ + +@pytest.mark.version('>=3.0') +def test_core_3899_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3902.py b/tests/bugs/test_core_3902.py new file mode 100644 index 00000000..fee99e26 --- /dev/null +++ b/tests/bugs/test_core_3902.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_3902 +# title: Derived fields may not be optimized via an index +# decription: +# tracker_id: CORE-3902 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLANONLY; +select rdb$database.rdb$relation_id from rdb$database + left outer join + ( select rdb$relations.rdb$relation_id as tempid + from rdb$relations ) temp (tempid) + on temp.tempid = rdb$database.rdb$relation_id; +select rdb$database.rdb$relation_id from rdb$database + left outer join + ( select rdb$relations.rdb$relation_id + from rdb$relations ) temp + on temp.rdb$relation_id = rdb$database.rdb$relation_id; + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """SQL> +PLAN JOIN (RDB$DATABASE NATURAL, TEMP RDB$RELATIONS INDEX (RDB$INDEX_1)) +SQL> +PLAN JOIN (RDB$DATABASE NATURAL, TEMP RDB$RELATIONS INDEX (RDB$INDEX_1)) +SQL>""" + +@pytest.mark.version('>=2.5.3') +def test_core_3902_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3919.py b/tests/bugs/test_core_3919.py new file mode 100644 index 00000000..16cee1d4 --- /dev/null +++ b/tests/bugs/test_core_3919.py @@ -0,0 +1,120 @@ +#coding:utf-8 +# +# id: bugs.core_3919 +# title: Improve SIMILAR TO performance +# decription: +# Confirmed normal work on WI-T4.0.0.1598. Moreover, SIMILAR TO is about 5x faster than LIKE comparison in this test. +# +# CAUTION. +# This test must be run only on 4.0+, despite that its 'Fix version' = 3.0 Alpha 1. +# Performance of SIMILAR TO statement is extremely poor in comparison with LIKE operator: +# COUNT through the table of 102 records requires 27 seconds vs 16 ms (checked on WI-V6.3.6.33246). +# +# tracker_id: CORE-3919 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core3919.fbk', init=init_script_1) + +test_script_1 = """ + set heading off; + set list on; + set term ^; + execute block returns( + ratio_of_time varchar(255) + ) as + declare i int; + declare j int; + declare t0 timestamp; + declare t1 timestamp; + declare elap_ms_using_like int; + declare elap_ms_using_similar_to int; + declare s varchar(32761); + declare ratio_similar_vs_like numeric(15,4); + declare MAX_RATIO numeric(15,4) = 2; + -- ^ + -- ############# + -- MAX THRESHOLD + -- ############# + declare n_count int = 100; -- do not set it to values less than 10: duration should not be zero! + begin + + t0 = cast('now' as timestamp); + select count(*) as like_count, sum(char_length(b)) as like_sum_len + from test t, (select 1 i from rdb$types rows (:n_count) ) n + where + t.b like '%a%' or + t.b like '%b%' or + t.b like '%c%' or + t.b like '%d%' or + t.b like '%e%' or + t.b like '%f%' or + t.b like '%g%' or + t.b like '%h%' or + t.b like '%i%' or + t.b like '%j%' or + t.b like '%k%' or + t.b like '%l%' or + t.b like '%m%' or + t.b like '%n%' or + t.b like '%o%' or + t.b like '%p%' or + t.b like '%q%' or + t.b like '%r%' or + t.b like '%s%' or + t.b like '%t%' or + t.b like '%u%' or + t.b like '%v%' or + t.b like '%w%' or + t.b like '%x%' or + t.b like '%y%' or + t.b like '%z%' + into i,j + ; + t1 = cast('now' as timestamp); + elap_ms_using_like = datediff(millisecond from t0 to t1); + + t0 = cast('now' as timestamp); + select count(*) as similar_to_count, sum(char_length(b)) as similar_to_sum_len + from test t, (select 1 i from rdb$types rows (:n_count) ) n + where t.b similar to '%[a-z]%' + into i,j + ; + t1 = cast('now' as timestamp); + elap_ms_using_similar_to = datediff(millisecond from t0 to t1); + + ratio_similar_vs_like = 1.0000 * elap_ms_using_similar_to / elap_ms_using_like; + + ratio_of_time = iif( ratio_similar_vs_like < MAX_RATIO + ,'acceptable' + ,'TOO LONG: '|| ratio_similar_vs_like ||' times. This is more than max threshold = ' || MAX_RATIO || ' times' + ) + ; + suspend; + end + ^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RATIO_OF_TIME acceptable + """ + +@pytest.mark.version('>=4.0') +def test_core_3919_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3924.py b/tests/bugs/test_core_3924.py new file mode 100644 index 00000000..7e81f106 --- /dev/null +++ b/tests/bugs/test_core_3924.py @@ -0,0 +1,55 @@ +#coding:utf-8 +# +# id: bugs.core_3924 +# title: Bugcheck 291 (cannot find record back version) if GTT is modified concurrently using at least one read-committed read-only transaction +# decription: +# tracker_id: CORE-3924 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [('-concurrent.*', ''), ('-At block line: [\\d]+, col: [\\d]+', '-At block line')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate global temporary table gt(f01 int) on commit preserve rows; + commit; + insert into gt values(1); + commit; + set transaction read only read committed record_version; + delete from gt; + set term ^; + execute block as + begin + in autonomous transaction + do update gt set f01=-1; + end + ^ + set term ;^ + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 40001 + deadlock + -update conflicts with concurrent update + -At block line: 1, col: 53 + """ + +@pytest.mark.version('>=2.5.3') +def test_core_3924_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_3925.py b/tests/bugs/test_core_3925.py new file mode 100644 index 00000000..9cbc72b5 --- /dev/null +++ b/tests/bugs/test_core_3925.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_3925 +# title: Creating self-referential FK crashes database (bug-check) whether constraint violation had place +# decription: +# Confirmed on WI-V3.0.5.33118, WI-T4.0.0.1496: "SQLSTATE = 08006 / Error reading..." on last DELETE statement +# Checked on WI-V3.0.5.33123, WI-T4.0.0.1501 (both SS an CS): works OK, got only SQLSTATE = 23000 when try to add FK. +# DELETE statement does not raise error. +# +# tracker_id: CORE-3925 +# min_versions: ['3.0.5'] +# versions: 3.0.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table test(key integer not null primary key, ref integer); + insert into test(key,ref) values(1,-1); + commit; + alter table test add constraint fk_key_ref foreign key (ref) references test(key); + delete from test; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + 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_core_3925_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_3929.py b/tests/bugs/test_core_3929.py new file mode 100644 index 00000000..30ff9f19 --- /dev/null +++ b/tests/bugs/test_core_3929.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: bugs.core_3929 +# title: Invalid "attempted update of read-only column" error when trying select minvalue from list with more than 255 elements +# decription: +# tracker_id: CORE-3929 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + select minvalue( + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,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 + ) from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + Maximum (255) number of arguments exceeded for function MINVALUE + """ + +@pytest.mark.version('>=3.0') +def test_core_3929_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_3934.py b/tests/bugs/test_core_3934.py new file mode 100644 index 00000000..62a00d56 --- /dev/null +++ b/tests/bugs/test_core_3934.py @@ -0,0 +1,312 @@ +#coding:utf-8 +# +# id: bugs.core_3934 +# title: Value of log_sweep parameter in trace configuration is ignored by trace plugin (assumed always true) +# decription: +# Test check TWO cases: +# 1) whether log_sweep = true actually lead to logging of sweep events +# 2) whether log_sweep = fales actually prevents from logging of any sweep events (which is ticket issue). +# Checked on (23.08.2020): +# 4.0.0.2173 SS: 19.215s. +# 4.0.0.2173 CS: 20.203s. +# 3.0.7.33357 SS: 18.329s. +# 3.0.7.33357 CS: 19.876s. +# 2.5.9.27152 SS: 17.876s. +# 2.5.9.27152 CS: 18.017s. +# +# tracker_id: CORE-3934 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# from subprocess import Popen +# import re +# +# engine = str(db_conn.engine_version) +# db_conn.close() +# +# #################### ::: NOTE ::: ####################### +# # Increase value of 'MIN_DELAY_AFTER_TRACE_START' # +# # if test will fail with difference which means that # +# # ALL needed rows that did not appear in actual stdout. # +# # This mean that trace log remained EMPTY during test, # +# # which in turn could occured because of too small delay # +# # between trace start and moment when single attachment # +# # to 'ready-for-sweep' database was done. # +# ########################################################## +# MIN_DELAY_AFTER_TRACE_START = 5 +# +# # Minimal delay after we finish connection to database +# # (that fires SWEEP) and before issuing command to stop trace +# ############################### +# MIN_DELAY_BEFORE_TRACE_STOP = 2 +# +# # Minimal delay for trace log be flushed on disk after +# # we issue command 'fbsvcmgr action_trace_stop': +# ############################### +# MIN_DELAY_AFTER_TRACE_STOP = 1 +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# #----------------------------------- +# +# 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() +# os.fsync(file_handle.fileno()) +# +# file_handle.close() +# +# #-------------------------------------------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# def make_trace_config( engine, is_sweep_logged, trccfg_name ): +# +# txt25 = ''' +# +# enabled true +# log_initfini false +# time_threshold 0 +# log_connections true +# log_sweep %(is_sweep_logged)s +# +# ''' % locals() +# +# # NOTES ABOUT TRACE CONFIG FOR 3.0: +# # 1) Header contains `database` clause in different format vs FB 2.5: its data must be enclosed with '{' '}' +# # 2) Name and value must be separated by EQUALITY sign ('=') in FB-3 trace.conf, otherwise we get runtime error: +# # element "<. . .>" have no attribute value set +# +# txt30 = ''' +# database=%%[\\\\\\\\/]bugs.core_3934.fdb +# { +# enabled = true +# log_initfini = false +# time_threshold = 0 +# log_connections = true +# log_sweep = %(is_sweep_logged)s +# } +# ''' % locals() +# +# trccfg=open( trccfg_name, 'w') +# if engine.startswith('2.5'): +# trccfg.write(txt25) +# else: +# trccfg.write(txt30) +# trccfg.close() +# +# return +# +# #-------------------------------------------- +# +# def stop_trace_session(): +# +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# global os +# global subprocess +# +# +# f_trclst=open( os.path.join(context['temp_directory'],'tmp_trace_3934.lst'), 'w') +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", "action_trace_list"], +# stdout=f_trclst, +# stderr=subprocess.STDOUT +# ) +# f_trclst.close() +# +# trcssn=0 +# with open( f_trclst.name,'r') as f: +# for line in f: +# if 'Session ID' in line: +# trcssn=line.split()[2] +# break +# +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# f_trclst=open(f_trclst.name,'a') +# f_trclst.seek(0,2) +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", "action_trace_stop", "trc_id",trcssn], +# stdout=f_trclst, stderr=subprocess.STDOUT +# ) +# f_trclst.close() +# +# os.remove(f_trclst.name) +# +# return +# +# +# ############################################################################### +# ### ### +# ### C A S E - 1: l o g _ s w e e p = t r u e ### +# ### ### +# ############################################################################### +# +# # Make trace config with ENABLING sweep logging and syntax that appropriates current engine: +# trccfg_swp_enable=os.path.join(context['temp_directory'],'tmp_trace_3934_swp_enable.cfg') +# make_trace_config( engine, 'true', trccfg_swp_enable ) +# +# ##################################################### +# # Starting trace session in new child process (async.): +# f_trclog_swp_enable=open( os.path.join(context['temp_directory'],'tmp_trace_3934_swp_enable.log'), 'w') +# p_trace=Popen( [ context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_start", +# "trc_cfg", trccfg_swp_enable +# ], +# stdout=f_trclog_swp_enable, +# stderr=subprocess.STDOUT +# ) +# +# # Wait _AT_LEAST_ 4..5 seconds in 2.5 because trace session is initialized not instantly. +# # If this delay is less then 2 second then trace log will be EMPTY (got on 2.5 SS and Cs). +# time.sleep( MIN_DELAY_AFTER_TRACE_START ) +# +# +# ################################## +# ### r u n s w e e p ### +# ################################## +# runProgram('gfix', ['-sweep', dsn]) +# +# +# # do NOT remove this otherwise trace log can contain only message about its start before being closed! +# time.sleep(MIN_DELAY_BEFORE_TRACE_STOP) +# +# ##################################################### +# # Getting ID of launched trace session and STOP it: +# +# stop_trace_session() +# time.sleep(MIN_DELAY_AFTER_TRACE_STOP) +# +# # Terminate child process of launched trace session (though it should already be killed): +# p_trace.terminate() +# flush_and_close( f_trclog_swp_enable ) +# +# +# ############################################################################### +# ### ### +# ### C A S E - 2: l o g _ s w e e p = f al s e ### +# ### ### +# ############################################################################### +# +# # Make trace config with DISABLING sweep logging and syntax that appropriates current engine: +# trccfg_swp_disable=os.path.join(context['temp_directory'],'tmp_trace_3934_swp_disable.cfg') +# make_trace_config( engine, 'false', trccfg_swp_disable ) +# +# ##################################################### +# # Starting trace session in new child process (async.): +# f_trclog_swp_disable=open( os.path.join(context['temp_directory'],'tmp_trace_3934_swp_disable.log'), 'w') +# p_trace=Popen( [context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_start", +# "trc_cfg", trccfg_swp_disable +# ], +# stdout=f_trclog_swp_disable, +# stderr=subprocess.STDOUT +# ) +# +# # Wait _AT_LEAST_ 4..5 seconds in 2.5 because trace session is initialized not instantly. +# # If this delay is less then 2 second then trace log will be EMPTY (got on 2.5 SS and Cs). +# +# time.sleep( MIN_DELAY_AFTER_TRACE_START ) +# +# ################################## +# ### r u n s w e e p ### +# ################################## +# runProgram('gfix', ['-sweep', dsn]) +# +# # do NOT remove this otherwise trace log can contain only message about its start before being closed! +# time.sleep(MIN_DELAY_BEFORE_TRACE_STOP) +# +# ##################################################### +# # Getting ID of launched trace session and STOP it: +# stop_trace_session() +# time.sleep(MIN_DELAY_AFTER_TRACE_STOP) +# +# # Terminate child process of launched trace session (though it should already be killed): +# p_trace.terminate() +# flush_and_close( f_trclog_swp_disable ) +# +# +# ############# +# # O U T P U T +# ############# +# # case-1 +# # ------- +# p=re.compile('\\s+sweep_(start|progress|finish)(\\s+|$)', re.IGNORECASE) +# sweep_found_when_enabled = False +# with open( f_trclog_swp_enable.name,'r') as f: +# for line in f: +# if p.search(line): +# sweep_found_when_enabled = True +# break +# # Expected result: sweep_found_when_enabled = True, i.e. trace log cotains SWEEP-related text. +# if not sweep_found_when_enabled: +# print('UNEXPECTED MISSING OF SWEEP-RELATED TEXT.') +# else: +# print('Result is expected when log_sweep = true') +# #------------------------------------------------------- +# +# # case-2 +# # ------- +# # Although this log is not empty, it must NOT contain any info about sweep, +# sweep_missed_when_disabled = True +# with open( f_trclog_swp_disable.name,'r') as f: +# for line in f: +# if p.search(line): +# sweep_missed_when_disabled = False +# break +# if not sweep_missed_when_disabled: +# print('UNEXPECTED PRESENCE OF SWEEP-RELATED TEXT') +# else: +# print('Result is expected when log_sweep = false') +# #------------------------------------------------------- +# +# ############################### +# # Cleanup. +# time.sleep(1) +# f_list = [x.name for x in (f_trclog_swp_enable, f_trclog_swp_disable )] + [trccfg_swp_enable, trccfg_swp_disable] +# cleanup( f_list ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Result is expected when log_sweep = true + Result is expected when log_sweep = false + """ + +@pytest.mark.version('>=2.5.2') +@pytest.mark.xfail +def test_core_3934_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_3937.py b/tests/bugs/test_core_3937.py new file mode 100644 index 00000000..ed184233 --- /dev/null +++ b/tests/bugs/test_core_3937.py @@ -0,0 +1,62 @@ +#coding:utf-8 +# +# id: bugs.core_3937 +# title: DeActivate/Activate INDEX or RESTORE not possible with NULL in unique index. +# decription: +# tracker_id: CORE-3937 +# min_versions: ['2.5.7'] +# versions: 2.5.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create generator gen_new_table_id; + recreate table testtable ( + id integer not null, + field1 integer not null, + field2 integer not null, + field3 varchar(10), + field4 varchar(10) + ); + alter table testtable add constraint pk_testtable primary key (id); + create unique index testtable_idx1 on testtable (field1, field2, field3, field4); + alter index testtable_idx1 inactive; + + set term ^ ; + create or alter trigger testtable_bi for testtable + active before insert position 0 + as + begin + if (new.id is null) then + new.id = gen_id(gen_new_table_id,1); + end + ^ + set term ;^ + --commit; + + insert into testtable (field1, field2, field3, field4) values (1, 2, null, null); + insert into testtable (field1, field2, field3, field4) values (1, 2, '', ''); + commit; + + alter index testtable_idx1 inactive; + alter index testtable_idx1 active; -- NOTE: could NOT reproduce error on WI-V2.5.1.26351 + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.7') +def test_core_3937_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_3942.py b/tests/bugs/test_core_3942.py new file mode 100644 index 00000000..de5a5065 --- /dev/null +++ b/tests/bugs/test_core_3942.py @@ -0,0 +1,63 @@ +#coding:utf-8 +# +# id: bugs.core_3942 +# title: Restore from gbak backup using service doesn't report an error +# decription: +# Checked on: +# WI-V2.5.6.26994 SC +# WI-V3.0.0.32474 SS/SC/CS +# LI-T4.0.0.130 // 11.04.2016 +# WI-T4.0.0.132 // 12.04.2016 +# +# tracker_id: CORE-3942 +# min_versions: ['2.5'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('gbak: ERROR:.*database.*already exists.*', 'gbak: ERROR:database already exists.*'), ('database.*already exists.*', ''), ('-Exiting before completion due to errors', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# db_conn.close() +# fdb='$(DATABASE_LOCATION)bugs.core_3942.fdb' +# fbk = os.path.join(context['temp_directory'],'tmp.core_3942.fbk') +# runProgram('gbak',['-b','-user',user_name,'-password',user_password,dsn,fbk]) +# print ('Trying to overwrite existing database file using gbak -se...') +# runProgram('gbak',['-c','-se','localhost:service_mgr','-user',user_name,'-password',user_password,fbk,fdb]) +# print ('Trying to overwrite existing database file using fbsvcmgr...') +# runProgram('fbsvcmgr',['localhost:service_mgr','user','SYSDBA','password','masterkey','action_restore','dbname',fdb,'bkp_file',fbk]) +# if os.path.isfile(fbk): +# os.remove(fbk) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Trying to overwrite existing database file using gbak -se... + Trying to overwrite existing database file using fbsvcmgr... + """ +expected_stderr_1 = """ + gbak: ERROR:database C:/FBTESTING/qa/fbt-repo/tmp/bugs.core_3942.fdb already exists. To replace it, use the -REP switch + gbak: ERROR: Exiting before completion due to errors + gbak:Exiting before completion due to errors + database C:/FBTESTING/qa/fbt-repo/tmp/bugs.core_3942.fdb already exists. To replace it, use the -REP switch + + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_3942_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_3947.py b/tests/bugs/test_core_3947.py new file mode 100644 index 00000000..946cb6bd --- /dev/null +++ b/tests/bugs/test_core_3947.py @@ -0,0 +1,61 @@ +#coding:utf-8 +# +# id: bugs.core_3947 +# title: Wrong results when the column with collation using option (NUMERIC-SORT=1) is in where clause +# decription: Changing in 3.0, comment in tracker 05/Oct/12 04:52: NUMERIC-SORT UNIQUE indexes will not be usable for ORDER, only for lookups. +# tracker_id: CORE-3947 +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + -- See also: sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1093394&msg=15987488 + create collation coll_ns for utf8 from unicode 'NUMERIC-SORT=1'; + commit; + create domain dm_ns as varchar(10) character set utf8 collate coll_ns; + commit; + + recreate table t( + s1 dm_ns + ,s2 dm_ns + ,s3 dm_ns + ); commit; + + create index t_s1_non_unq on t(s1); + create UNIQUE index t_s2_unq_asc on t(s2); + create UNIQUE DESCENDING index t_s3_unq_des on t(s3); + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set plan on; + select * from t order by s1; + select * from t order by s2; + select * from t order by s3 desc; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (T ORDER T_S1_NON_UNQ) + PLAN SORT (T NATURAL) + PLAN SORT (T NATURAL) + """ + +@pytest.mark.version('>=3.0') +def test_core_3947_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3959.py b/tests/bugs/test_core_3959.py new file mode 100644 index 00000000..a9325e08 --- /dev/null +++ b/tests/bugs/test_core_3959.py @@ -0,0 +1,172 @@ +#coding:utf-8 +# +# id: bugs.core_3959 +# title: Repeat Temporary Table access from ReadOnly Transaction and ReadWrite transaction causes Internal Firebird consistency check (cannot find record back version (291), file: vio.cpp line: 4905) +# decription: +# Bug in WI-V2.5.1.26351: execution of last line ('print( cur1a.fetchall() )') leads FB to crash, log: +# === +# Access violation. +# The code attempted to access a virtual +# address without privilege to do so. +# This exception will cause the Firebird server +# to terminate abnormally. +# === +# No problem in 2.5.7 and 3.0.x +# +# tracker_id: CORE-3959 +# min_versions: ['2.5.7'] +# versions: 2.5.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create or alter procedure fu_x1 as begin end; + create or alter procedure save_x1 as begin end; + commit; + + recreate global temporary table x1 ( + id integer, + name varchar(10) + ) on commit preserve rows; + + + set term ^; + alter procedure fu_x1 returns ( + sid integer, + sname varchar(10)) as + begin + delete from x1; + + insert into x1 values (1,'1'); + insert into x1 values (2,'2'); + insert into x1 values (3,'3'); + insert into x1 values (4,'4'); + insert into x1 values (5,'5'); + + for + select x1.id, x1.name + from x1 + into sid, sname + do + suspend; + end + ^ + alter procedure save_x1 ( + pid integer, + pname varchar(10)) + as + begin + update x1 set name = :pname + where x1.id = :pid; + if (row_count = 0) then + insert into x1 values( :pid, :pname); + end + ^ + set term ;^ + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import fdb +# os.environ["ISC_USER"] = 'SYSDBA' +# os.environ["ISC_PASSWORD"] = 'masterkey' +# +# db_conn.close() +# +# txparam1 = ( [ fdb.isc_tpb_read_committed, fdb.isc_tpb_rec_version, fdb.isc_tpb_nowait, fdb.isc_tpb_read ] ) +# txparam2 = ( [ fdb.isc_tpb_read_committed, fdb.isc_tpb_rec_version, fdb.isc_tpb_nowait ] ) +# +# con1 = fdb.connect(dsn=dsn) +# #print(con1.firebird_version) +# +# print('step-1') +# tx1a=con1.trans( default_tpb = txparam1 ) +# print('step-2') +# cur1a = tx1a.cursor() +# +# print('step-3') +# cur1a.execute("select sid, sname from FU_X1") +# print('step-4') +# +# tx1b=con1.trans( default_tpb = txparam2 ) +# +# print('step-5') +# cur1b = tx1b.cursor() +# print('step-6') +# cur1b.callproc("save_x1", ('2', 'foo')) +# +# print('step-7') +# tx1b.commit() +# +# #cur1b.callproc("save_x1", (3, 'bar')) +# #tx1b.commit() +# +# print('step-8') +# cur1a.execute("select sid, sname from FU_X1") +# print('step-9') +# print( cur1a.fetchall() ) +# +# ''' +# Output in 2.5.1: +# step-1 +# ... +# step-9 +# Traceback (most recent call last): +# File "c3959-run.py", line 42, in +# print( cur1a.fetchall() ) +# File "C:\\Python27\\lib\\site-packages +# db +# bcore.py", line 3677, in fetchall +# return [row for row in self] +# File "C:\\Python27\\lib\\site-packages +# db +# bcore.py", line 3440, in next +# row = self.fetchone() +# File "C:\\Python27\\lib\\site-packages +# db +# bcore.py", line 3637, in fetchone +# return self._ps._fetchone() +# File "C:\\Python27\\lib\\site-packages +# db +# bcore.py", line 3325, in _fetchone +# "Cursor.fetchone:") +# fdb.fbcore.DatabaseError: ('Cursor.fetchone: +# - SQLCODE: -902 +# - Unable to complete network request to host "localhost". +# - Error reading data from the connection.', -902, 335544721) +# ''' +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + step-1 + step-2 + step-3 + step-4 + step-5 + step-6 + step-7 + step-8 + step-9 + [(1, '1'), (2, '2'), (3, '3'), (4, '4'), (5, '5')] + """ + +@pytest.mark.version('>=2.5.7') +@pytest.mark.xfail +def test_core_3959_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_3963.py b/tests/bugs/test_core_3963.py new file mode 100644 index 00000000..f704335d --- /dev/null +++ b/tests/bugs/test_core_3963.py @@ -0,0 +1,237 @@ +#coding:utf-8 +# +# id: bugs.core_3963 +# title: isql doesn't know the difference between UDF's and psql-functions +# decription: +# *** FOR FB 3.X ONLY *** +# Test uses UDF 'strlen' declared in ib_udf.sql script which for sure present in every FB snapshot. +# After this, we try to create PSQL function with the same signature but evaluate its returning value +# as double size of input argument (in order to distinguish these functions by their results). +# +# *** FOR FB 4.X AND ABOVE *** +# Added separate code for running on FB 4.0.x. +# 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/ +# Checked on: +# 3.0.5.33086: OK, 1.454s. +# 4.0.0.1172: OK, 7.781s. +# 4.0.0.1340: OK, 3.844s. +# 4.0.0.1378: OK, 3.485s. +# +# tracker_id: CORE-3963 +# min_versions: ['3.0'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + --set echo on; + + -- Should PASS: + set term ^; + create function strlen(s varchar(32765)) returns int as begin return 2 * char_length(s); end + ^ + set term ;^ + select strlen('tratata') from rdb$database; + commit; + + -- Should FAIL: + DECLARE EXTERNAL FUNCTION strlen CSTRING(32767) RETURNS INTEGER BY VALUE ENTRY_POINT 'IB_UDF_strlen' MODULE_NAME 'ib_udf'; + + drop function strlen; -- kill PSQL function + commit; + + + -- Should PASS: + DECLARE EXTERNAL FUNCTION strlen CSTRING(32767) RETURNS INTEGER BY VALUE ENTRY_POINT 'IB_UDF_strlen' MODULE_NAME 'ib_udf'; + + select strlen('tratata') from rdb$database; + commit; + + -- Should FAIL: + set term ^; + create function strlen(s varchar(32765)) returns int as begin return 2 * char_length(s); end + ^ + set term ;^ + + select strlen('tratata') from rdb$database; + commit; + + drop function strlen; -- kill UDF function + commit; + + + -- Should PASS: + set term ^; + create function strlen(s varchar(32765)) returns int as begin return 2 * char_length(s); end + ^ + set term ;^ + select strlen('tratata') from rdb$database; + commit; + + drop function strlen; + commit; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + STRLEN 14 + STRLEN 7 + STRLEN 7 + STRLEN 14 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE FUNCTION STRLEN failed + -Function STRLEN already exists + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE FUNCTION STRLEN failed + -Function STRLEN already exists + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_core_3963_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set list on; + + -- See declaration sample in plugins\\udr\\UdfBackwardCompatibility.sql: + + create function the_frac( + val double precision + ) returns double precision + external name 'udf_compat!UC_frac' + engine udr; + commit; + + set sqlda_display on; + + select the_frac( -pi() ) from rdb$database; + commit; + + -- should FAIL: + set term ^; + create function the_frac( val double precision ) returns double precision as + begin + return val - cast(val as int); + end + ^ + set term ;^ + commit; + + -- should PASS: + drop function the_frac; + commit; + + -- should FAIL: + select the_frac( -pi() ) from rdb$database; + commit; + + + -- should PASS: + set term ^; + create function the_frac( val double precision ) returns double precision as + begin + return val - cast(val as int); + end + ^ + set term ;^ + commit; + + -- should PASS: + select the_frac( -pi() ) from rdb$database; + commit; + + -- should FAIL: + create function the_frac( + val double precision + ) returns double precision + external name 'udf_compat!UC_frac' + engine udr; + commit; + + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + + 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: + + THE_FRAC -0.1415926535897931 + + + + 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: + + THE_FRAC -0.1415926535897931 + + """ +expected_stderr_2 = """ + 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 + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE FUNCTION THE_FRAC failed + -Function THE_FRAC already exists + """ + +@pytest.mark.version('>=4.0') +def test_core_3963_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_expected_stderr == act_2.clean_stderr + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/bugs/test_core_3964.py b/tests/bugs/test_core_3964.py new file mode 100644 index 00000000..0a7d549d --- /dev/null +++ b/tests/bugs/test_core_3964.py @@ -0,0 +1,56 @@ +#coding:utf-8 +# +# id: bugs.core_3964 +# title: It is not possible to create a ddl-trigger with "any DDL statement" clause +# decription: +# tracker_id: CORE-3964 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table mp$modified_tables (relation_name char(31)); + commit; + create index mp$modified_tables_idx on mp$modified_tables (relation_name); + commit; + + set term ^; + create trigger taa_sql1 + active after any ddl statement position 0 as + begin + if ( + rdb$get_context('DDL_TRIGGER', 'OBJECT_TYPE') = 'TABLE' + and + ( + rdb$get_context('DDL_TRIGGER', 'EVENT_TYPE') in ('CREATE', 'DROP') + or + rdb$get_context('DDL_TRIGGER', 'SQL_SOURCE') containing 'FIELD' + ) + ) then + insert into mp$modified_tables (relation_name) + values (rdb$get_context('DDL_TRIGGER', 'OBJECT_NAME')); + end + ^ + set term ;^ + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +def test_core_3964_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_3965.py b/tests/bugs/test_core_3965.py new file mode 100644 index 00000000..5dc83d4f --- /dev/null +++ b/tests/bugs/test_core_3965.py @@ -0,0 +1,100 @@ +#coding:utf-8 +# +# id: bugs.core_3965 +# title: Creating a procedure containing "case when" expression leads to a server crash +# decription: +# tracker_id: CORE-3965 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='employee-ods12.fbk', init=init_script_1) + +test_script_1 = """ + -- Table 'sales' for this SP is taken from standard samples database 'employee.fdb' which comes with every FB build. + set term ^; + create or alter procedure p_beteiligung_order ( + gid char(36) character set iso8859_1 collate iso8859_1, + ordernr integer, + dir smallint, + mit_fuehrender char(1) character set iso8859_1 collate iso8859_1) + as + declare variable cur_ordernr integer; + declare variable max_ordernr integer; + declare variable fk_ref char(36); + begin + + if (mit_fuehrender is null) then + mit_fuehrender = 'F'; + + + select r.qty_ordered, r.item_type + from sales r + where r.po_number = :gid + into :cur_ordernr, :fk_ref; + + if (ordernr is null) then + ordernr = cur_ordernr + coalesce(dir, 0); + + if (ordernr <= case mit_fuehrender + when 'T' then 1 + else 2 + end) then + ordernr = case mit_fuehrender + when 'T' then 1 + else 2 + end; + else + begin + select max(r.qty_ordered) + from sales r + where r.item_type = :fk_ref + into :max_ordernr; + if (ordernr > max_ordernr) then + ordernr = max_ordernr; + end + + if (ordernr = cur_ordernr) then + exit; + else + if (ordernr < cur_ordernr) then + update sales r + set r.qty_ordered = r.qty_ordered + 1 + where r.item_type = :fk_ref and + r.qty_ordered between :ordernr and :cur_ordernr; + else + update sales r + -- ::: NB ::: in the ticket it was: "set r.qty_ordered = r.ordernr - 1" - but there is NO such field in the table SALES! + set r.qty_ordered = :ordernr - 1 + where r.qty_ordered = :fk_ref and + r.qty_ordered between :cur_ordernr and :ordernr; + + update sales r + set r.qty_ordered = :ordernr + where r.po_number = :gid; + + end^ + set term ;^ + commit; + + drop procedure p_beteiligung_order; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +def test_core_3965_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_3966.py b/tests/bugs/test_core_3966.py new file mode 100644 index 00000000..035c3d8a --- /dev/null +++ b/tests/bugs/test_core_3966.py @@ -0,0 +1,122 @@ +#coding:utf-8 +# +# id: bugs.core_3966 +# title: Creating a stored procedure with an "update or insert" statement with MATCHING fails +# decription: +# tracker_id: CORE-3966 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='employee-ods12.fbk', init=init_script_1) + +test_script_1 = """ + -- Table 'sales' for this SP is taken from standard samples database 'employee.fdb' which comes with every FB build. + set term ^; + create or alter procedure p_beteiligung_iu ( + gid char(36) character set iso8859_1 collate iso8859_1, + gid_beteiligungs_verhaeltnis char(36) character set iso8859_1 collate iso8859_1, + gid_vrinfo char(36) character set iso8859_1 collate iso8859_1, + gid_agnr char(36) character set iso8859_1 collate iso8859_1, + anteil numeric(18,3), + ordernr integer, + gueltig_ab date, + gueltig_bis date, + fuehrende_praemie char(1) character set iso8859_1 collate iso8859_1, + fuehrende_courtage char(1) character set iso8859_1 collate iso8859_1, + gid_zahlart char(36) character set iso8859_1 collate iso8859_1, + gid_policen_beteiligte char(36) character set iso8859_1 collate iso8859_1, + vsnrvr varchar(36) character set iso8859_1 collate iso8859_1, + vsnr varchar(36) character set iso8859_1 collate iso8859_1 + ) + as + declare variable von date; + declare variable bis date; + declare variable gid_policen char(36); + declare variable gid_policen_or_detail char(36); + declare variable alle_sollst_neumachen char(1); + declare variable gid_beteiligung char(36); + declare variable d char(1); + declare variable po_number char(8); + declare variable cust_no integer; + declare variable sales_rep smallint; + declare variable order_status varchar(7); + declare variable order_date timestamp; + declare variable ship_date timestamp; + declare variable date_needed timestamp; + declare variable paid char(1); + declare variable qty_ordered integer; + declare variable total_value decimal(9,2); + declare variable discount float; + declare variable item_type varchar(12); + declare variable aged numeric(18,9); + begin + if (ordernr is null) then + begin + select max(b.qty_ordered) + 1 + from sales b + where b.item_type = :gid_beteiligungs_verhaeltnis + into :ordernr; + end + update or insert into sales (po_number, cust_no, sales_rep, order_status, order_date, ship_date, date_needed, paid, + qty_ordered, total_value, discount, item_type) + values (:po_number, :cust_no, :sales_rep, :order_status, :order_date, :ship_date, :date_needed, :paid, :qty_ordered, + :total_value, :discount, :item_type) + matching (po_number) + returning (po_number) + into :po_number; + + end + ^ + -- from core-3968: + create or alter procedure empiu ( + emp_no smallint, + first_name varchar(15), + last_name varchar(20), + phone_ext varchar(4), + hire_date timestamp, + dept_no char(3), + job_code varchar(5), + job_grade smallint, + job_country varchar(15), + salary numeric(10,2), + proj_id type of column project.proj_id) + as + begin + select first 1 p.proj_id from project p where p.proj_id=:proj_id into :proj_id; + update or insert into employee_project (emp_no, proj_id) + values (:emp_no, :proj_id) + matching (emp_no, proj_id); + + update or insert into employee (emp_no, first_name, last_name, phone_ext, hire_date, dept_no, job_code, job_grade, + job_country, salary) + values (:emp_no, :first_name, :last_name, :phone_ext, :hire_date, :dept_no, :job_code, :job_grade, :job_country, + :salary) + matching (emp_no); + end + ^ + set term ;^ + commit; + + drop procedure p_beteiligung_iu; + drop procedure EMPIU; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +def test_core_3966_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_3967.py b/tests/bugs/test_core_3967.py new file mode 100644 index 00000000..ad778d2c --- /dev/null +++ b/tests/bugs/test_core_3967.py @@ -0,0 +1,51 @@ +#coding:utf-8 +# +# id: bugs.core_3967 +# title: subselect with reference to outer select fails +# decription: +# tracker_id: CORE-3967 +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='employee-ods12.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + select r1.rdb$relation_name rel_name + from rdb$relation_fields f1 + join rdb$relations r1 on f1.rdb$relation_name = r1.rdb$relation_name + where + f1.rdb$field_name = upper('emp_no') and + not exists( + select r2.rdb$relation_name + from rdb$relation_fields f2 + join rdb$relations r2 on f2.rdb$relation_name=r1.rdb$relation_name + where f2.rdb$field_name = upper('phone_ext') + ) + order by 1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + REL_NAME EMPLOYEE_PROJECT + REL_NAME SALARY_HISTORY + """ + +@pytest.mark.version('>=3.0') +def test_core_3967_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3972.py b/tests/bugs/test_core_3972.py new file mode 100644 index 00000000..6e4da4aa --- /dev/null +++ b/tests/bugs/test_core_3972.py @@ -0,0 +1,52 @@ +#coding:utf-8 +# +# id: bugs.core_3972 +# title: Allow the selection of SQL_INT64, SQL_DATE and SQL_TIME in dialect 1 +# decription: +# tracker_id: CORE-3972 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=1, init=init_script_1) + +test_script_1 = """ + recreate table t1 (n1 numeric(12,3)); + commit; + insert into t1 values (1.23); + insert into t1 values (10.23); + insert into t1 values (3.567); + commit; + set list on; + select mon$sql_dialect from mon$database; + select n1, n1 / 2 from t1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MON$SQL_DIALECT 1 + N1 1.230 + DIVIDE 0.6150000000000000 + N1 10.230 + DIVIDE 5.115000000000000 + N1 3.567 + DIVIDE 1.783500000000000 + """ + +@pytest.mark.version('>=3.0') +def test_core_3972_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3973.py b/tests/bugs/test_core_3973.py new file mode 100644 index 00000000..5730d7f5 --- /dev/null +++ b/tests/bugs/test_core_3973.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: bugs.core_3973 +# title: Original table name and column name and owner missing from SQLDA for aliased column in grouped query +# decription: +# tracker_id: CORE-3973 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!name|table).)*$', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set planonly; + set sqlda_display on; + select rdb$relation_id as r_id, rdb$character_set_name + from rdb$database + group by rdb$relation_id, rdb$character_set_name; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + : name: RDB$RELATION_ID alias: R_ID + : table: RDB$DATABASE owner: SYSDBA + : name: RDB$CHARACTER_SET_NAME alias: RDB$CHARACTER_SET_NAME + : table: RDB$DATABASE owner: SYSDBA + """ + +@pytest.mark.version('>=3.0') +def test_core_3973_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3977.py b/tests/bugs/test_core_3977.py new file mode 100644 index 00000000..e73b9b33 --- /dev/null +++ b/tests/bugs/test_core_3977.py @@ -0,0 +1,286 @@ +#coding:utf-8 +# +# id: bugs.core_3977 +# title: DELETE FROM MON$STATEMENTS does not interrupt a longish fetch +# decription: +# Refactored 08-may-2017. +# Checked on 2.5.8.27061, 3.0.2.32708 and 4.0.0.633 (Classic & Super). +# +# Refactored 02.11.2019: restored DB state must be changed to full shutdown in order to make sure tha all attachments are gone. +# Otherwise one may get: +# Error while dropping database +# - SQLCODE: -901 +# - lock time-out on wait transaction +# - object E:\\QA\\FBT-REPO\\TMP\\BUGS.CORE_3977.FDB is in use +# This is actual for 4.0+ SS/SC when ExtConnPoolLifeTime > 0. +# Checked on: +# 4.0.0.1639 SS: 5.299s. +# 4.0.0.1633 CS: 6.037s. +# 3.0.5.33183 SS: 4.795s. +# 3.0.5.33178 CS: 5.192s. +# 2.5.9.27119 SS: 3.491s. +# 2.5.9.27146 SC: 3.617s. +# +# tracker_id: CORE-3977 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [('^((?!RECORDS AFFECTED:|RESULT_MSG).)*$', '')] + +init_script_1 = """ + create sequence g; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# #import sys +# import subprocess +# from subprocess import Popen +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # dsn localhost/3400:C:\\FBTESTING\\qa +# bt-repo mpugs.core_NNNN.fdb +# # db_conn.database_name C:\\FBTESTING\\QA\\FBT-REPO\\TMP\\BUGS.CORE_NNNN.FDB +# # $(DATABASE_LOCATION)... C:/FBTESTING/qa/fbt-repo/tmp/bugs.core_NNN.fdb +# +# this_fdb=db_conn.database_name +# db_conn.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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# # Script for ISQL that will do 'heavy select': +# +# usr=user_name +# pwd=user_password +# +# sql_cmd=''' +# alter sequence g restart with 0; +# commit; +# +# set term ^; +# execute block as +# declare x int; +# begin +# for +# execute statement ('select gen_id(g,1) from rdb$types,rdb$types,rdb$types') +# on external +# 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') +# as user '%(usr)s' password '%(pwd)s' +# into x +# do begin +# end +# end +# ^ +# set term ;^ +# ''' % locals() +# +# f_query_to_be_killedcmd=open( os.path.join(context['temp_directory'],'tmp_isql_3977.sql'), 'w') +# f_query_to_be_killedcmd.write(sql_cmd) +# flush_and_close( f_query_to_be_killedcmd ) +# +# ############################################################ +# # Starting ISQL in separate process with doing 'heavy query' +# +# f_query_to_be_killedlog=open( os.path.join(context['temp_directory'],'tmp_isql_3977.log'), 'w') +# +# p_heavy_dml = Popen( [ context['isql_path'] , dsn, "-i", f_query_to_be_killedcmd.name ], +# stdout=f_query_to_be_killedlog, +# stderr=subprocess.STDOUT +# ) +# +# # Here we have to wait for sure that ISQL could establish its connect and starts DML +# # before we start DELETE FROM MON$ATTACHMENTS +# +# time.sleep(2) +# +# ###################################### +# # Run 2nd isql and issue there DELETE FROM MON$ATATSMENTS command. First ISQL process should be terminated for short time. +# +# v_mon_sttm_sql=''' +# commit; +# set list on; +# +# select * +# from mon$statements +# where +# mon$attachment_id != current_connection +# and mon$sql_text containing 'gen_id(' +# --order by mon$stat_id +# ; +# +# set count on; +# +# delete from mon$statements +# where +# mon$attachment_id != current_connection +# and mon$sql_text containing 'gen_id(' +# --order by mon$stat_id +# ; +# quit; +# ''' +# +# f_delete_from_mon_sttm_sql=open( os.path.join(context['temp_directory'],'tmp_dels_3977.sql'), 'w') +# f_delete_from_mon_sttm_sql.write(v_mon_sttm_sql) +# flush_and_close( f_delete_from_mon_sttm_sql ) +# +# f_delete_from_mon_sttm_log=open( os.path.join(context['temp_directory'],'tmp_dels_3977.log'), 'w') +# +# subprocess.call( [context['isql_path'], dsn, "-i", f_delete_from_mon_sttm_sql.name ], +# stdout=f_delete_from_mon_sttm_log, +# stderr=subprocess.STDOUT +# ) +# +# f_delete_from_mon_sttm_log.close() +# +# p_heavy_dml.terminate() +# flush_and_close( f_query_to_be_killedlog ) +# +# ######################################### +# # Run checking query: what is resuling value of sequence 'g' ? +# # (it must be > 0 and < total number of records to be handled). +# +# sql_cmd=''' +# --set echo on; +# set list on; +# set count on; +# select iif( current_gen > 0 and current_gen < total_rows, +# 'OK: query was interrupted in the middle point.', +# 'WRONG! Query to be interrupted ' +# || iif(current_gen <= 0, 'did not start.', 'already gone, current_gen = '||current_gen ) +# ) as result_msg +# from ( +# select gen_id(g,0) as current_gen, c.n * c.n * c.n as total_rows +# from ( select (select count(*) from rdb$types) as n from rdb$database) c +# ); +# ''' +# +# f_check_result_cmd=open( os.path.join(context['temp_directory'],'tmp_chkr_3977.sql'), 'w') +# f_check_result_cmd.write(sql_cmd) +# flush_and_close( f_check_result_cmd ) +# +# f_check_result_log=open( os.path.join(context['temp_directory'],'tmp_chkr_3977.log'), 'w') +# +# subprocess.call( [context['isql_path'], dsn, "-i", f_check_result_cmd.name ], +# stdout=f_check_result_log, +# stderr=subprocess.STDOUT +# ) +# +# flush_and_close( f_check_result_log ) +# +# with open(f_delete_from_mon_sttm_log.name) as f: +# for line in f: +# if not 'EXECUTE STATEMENT' in line.upper(): +# print('DEL FROM MON$STTM: ', ' '.join(line.upper().split()) ) +# +# with open(f_query_to_be_killedlog.name) as f: +# for line in f: +# print('QUERY THAT KILLED: ', ' '.join(line.upper().split()) ) +# +# with open(f_check_result_log.name) as f: +# for line in f: +# print('CHECK RESULTS LOG: ', ' '.join(line.upper().split()) ) +# +# +# ######################## +# # Cleanup +# time.sleep(1) +# +# # 02.11.2019: add full shutdown to forcedly drop all attachments. +# ## |||||||||||||||||||||||||||| +# ## ###################################||| 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 +# ## ############################################################################################# +# +# f_shutdown_log=open( os.path.join(context['temp_directory'],'tmp_3977_shutdown.log'), 'w') +# +# subprocess.call( [context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "prp_shutdown_mode", "prp_sm_full", "prp_shutdown_db", "0", "dbname", this_fdb, +# ], +# stdout = f_shutdown_log, +# stderr = subprocess.STDOUT +# ) +# subprocess.call( [context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "prp_db_online", "dbname", this_fdb, +# ], +# stdout = f_shutdown_log, +# stderr = subprocess.STDOUT +# ) +# +# flush_and_close( f_shutdown_log ) +# +# with open( f_shutdown_log.name,'r') as f: +# for line in f: +# if line.split(): +# print( 'UNEXPECTED OUTPUT IN DB SHUTDOWN LOG: ' + (' '.join(line.split()).upper()) ) +# +# +# +# # CLEANUP +# ######### +# time.sleep(1) +# cleanup( [i.name for i in (f_query_to_be_killedcmd, f_query_to_be_killedlog, f_delete_from_mon_sttm_sql, f_delete_from_mon_sttm_log, f_check_result_cmd, f_check_result_log, f_shutdown_log ) ] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DEL FROM MON$STTM: RECORDS AFFECTED: 2 + CHECK RESULTS LOG: RESULT_MSG OK: QUERY WAS INTERRUPTED IN THE MIDDLE POINT. + CHECK RESULTS LOG: RECORDS AFFECTED: 1 + """ + +@pytest.mark.version('>=2.5.3') +@pytest.mark.xfail +def test_core_3977_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_3991.py b/tests/bugs/test_core_3991.py new file mode 100644 index 00000000..55bd9170 --- /dev/null +++ b/tests/bugs/test_core_3991.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: bugs.core_3991 +# title: "attempted update of read-only column" when trying update editable view without triggers +# decription: +# +# tracker_id: CORE-3991 +# min_versions: ['2.5.7'] +# versions: 2.5.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter view v_test as select 1 id from rdb$database; + commit; + recreate table test_table (id int); + create or alter view v_test as select id from test_table; + commit; + + insert into v_test(id) values(10); + commit; + + set count on; + update v_test set id = 10; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 1 + """ + +@pytest.mark.version('>=2.5.7') +def test_core_3991_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3992.py b/tests/bugs/test_core_3992.py new file mode 100644 index 00000000..3184910a --- /dev/null +++ b/tests/bugs/test_core_3992.py @@ -0,0 +1,60 @@ +#coding:utf-8 +# +# id: bugs.core_3992 +# title: No records in the table rdb$dependencies for ddl trigger +# decription: +# tracker_id: CORE-3992 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table ddl_log ( + id integer, + ddl_event varchar(25), + sql blob sub_type text + ); + + set term ^; + create or alter trigger ddl_log_trigger after any ddl statement + as + begin + insert into ddl_log(sql, ddl_event) + values (rdb$get_context('DDL_TRIGGER', 'SQL_TEXT'), + rdb$get_context('DDL_TRIGGER', 'DDL_EVENT') ); + end + ^ + set term ;^ + commit; + + set list on; + + select sign(count(*)) "is_any_rows_there ?" + from rdb$dependencies d + where upper('ddl_log_trigger') in (d.rdb$dependent_name, d.rdb$depended_on_name); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + is_any_rows_there ? 1 + """ + +@pytest.mark.version('>=3.0') +def test_core_3992_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3997.py b/tests/bugs/test_core_3997.py new file mode 100644 index 00000000..20a8a8c9 --- /dev/null +++ b/tests/bugs/test_core_3997.py @@ -0,0 +1,64 @@ +#coding:utf-8 +# +# id: bugs.core_3997 +# title: Join using RDB$DB_KEY produce NATURAL plan +# decription: +# Confirmed on WI-V2.5.1.26351, it issues: +# PLAN JOIN (T_KEY NATURAL, T NATURAL) +# +# tracker_id: CORE-3997 +# min_versions: ['2.5.7'] +# versions: 2.5.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table t (f integer); + recreate table t_key (k char(8) character set octets); + commit; + + set term ^; + execute block as + declare i int = 10000; + begin + While (i>0) do + begin + insert into t values (:i); + i = i-1; + end + end^ + set term ;^ + commit; + + insert into t_key select rdb$db_key from t where f=1; + commit; + + set planonly; + select f + from t join t_key on + t.rdb$db_key=t_key.k; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN JOIN (T_KEY NATURAL, T INDEX ()) + """ + +@pytest.mark.version('>=2.5.7') +def test_core_3997_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3998.py b/tests/bugs/test_core_3998.py new file mode 100644 index 00000000..4fde63b1 --- /dev/null +++ b/tests/bugs/test_core_3998.py @@ -0,0 +1,75 @@ +#coding:utf-8 +# +# id: bugs.core_3998 +# title: Parametrized execute statement fails +# decription: +# tracker_id: CORE-3998 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """ + create table t ( + id integer not null, + dir varchar(100) default '' not null, + note varchar(100) default '' not null + ); + commit; + insert into t (id, dir, note) values (1, 'a', 'b'); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + execute block + as + declare variable dir varchar(100); + declare variable note varchar(100); + declare variable id integer; + begin + id = 1; + dir = 'a'; + note = 'bbbb'; + + execute statement (' + update t set + note = :note + where + id = :id and dir = :dir + ') + ( + id := :id, + note := :note, + dir := :dir + ); + end ^ + set term ;^ + commit; + set list on; + select * from t; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + DIR a + NOTE bbbb + """ + +@pytest.mark.version('>=2.5.3') +def test_core_3998_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_3999.py b/tests/bugs/test_core_3999.py new file mode 100644 index 00000000..6322a923 --- /dev/null +++ b/tests/bugs/test_core_3999.py @@ -0,0 +1,69 @@ +#coding:utf-8 +# +# id: bugs.core_3999 +# title: Bug in unique constraints and / or NUMERIC-SORT collation +# decription: +# Confirmed on WI-V2.5.7.27026, it issues: +# Statement failed, SQLSTATE = 23000 +# violation of PRIMARY or UNIQUE KEY constraint "UK_PRODUCTS" on table "PRODUCTS" +# +# tracker_id: CORE-3999 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table products(productno char(1)); + commit; + set term ^; + execute block as + begin + execute statement 'drop collation unicode_num_ci_ai'; + when any do begin end + end^ + set term ;^ + commit; + create collation unicode_num_ci_ai for utf8 from unicode_ci_ai 'numeric-sort=1'; + recreate table products(productno varchar(100) character set utf8 collate unicode_num_ci_ai); + alter table products add constraint uk_products unique (productno) using index uk_products; + commit; + insert into products values('s01'); + insert into products values('s1'); + insert into products values('01'); + insert into products values('001'); + insert into products values('-01'); + insert into products values('-001'); + commit; + set list on; + select distinct productno from products; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PRODUCTNO -001 + PRODUCTNO -01 + PRODUCTNO 001 + PRODUCTNO 01 + PRODUCTNO s01 + PRODUCTNO s1 + """ + +@pytest.mark.version('>=3.0') +def test_core_3999_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4002.py b/tests/bugs/test_core_4002.py new file mode 100644 index 00000000..aba80506 --- /dev/null +++ b/tests/bugs/test_core_4002.py @@ -0,0 +1,115 @@ +#coding:utf-8 +# +# id: bugs.core_4002 +# title: Error message "index unexpectedly deleted" in database trigger on commit transaction +# decription: +# tracker_id: CORE-4002 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create or alter trigger trg_commit active on transaction commit position 999 as + begin + end; + + create or alter procedure test_gg as begin end; + commit; + + recreate global temporary table g2(id int); + commit; + + recreate global temporary table g1 ( + id int primary key, + tt varchar(100) not null, + bb blob sub_type 1 segment size 80 not null + ) on commit delete rows; + commit; + + recreate global temporary table g2 ( + id int primary key , + id_g1 int not null references g1, + tt varchar(100) not null, + bb blob sub_type 1 segment size 80 not null + ) on commit delete rows; + commit; + + set term ^ ; + + create or alter procedure test_gg + as + declare i int = 0; + begin + in autonomous transaction do + while (i<100) do + begin + insert into g1 (id, tt, bb) values (:i, rand(), rand()); + + insert into g2 (id, id_g1, tt, bb) values (:i*1000+1, :i, rand(), rand()); + insert into g2 (id, id_g1, tt, bb) values (:i*1000+2, :i, rand(), rand()); + insert into g2 (id, id_g1, tt, bb) values (:i*1000+3, :i, rand(), rand()); + insert into g2 (id, id_g1, tt, bb) values (:i*1000+4, :i, rand(), rand()); + insert into g2 (id, id_g1, tt, bb) values (:i*1000+5, :i, rand(), rand()); + + i=i+1; + end + end^ + + commit^ + + create or alter trigger trg_commit + active on transaction commit position 999 + as + declare variable id integer; + declare variable tt varchar(100); + declare variable bb blob sub_type 1; + + declare variable id_g1 integer; + declare variable tt_2 varchar(100); + declare variable bb_2 blob sub_type 1; + + declare i int=0; + begin + for select id, tt, bb + from g1 + order by id + into :id, :tt, :bb + do + begin + for select id_g1, tt, bb + from g2 + where id_g1=:id + order by id + into :id_g1, :tt_2, :bb_2 + do + begin + i=i+1; + end + end + end^ + set term ;^ + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + execute procedure test_gg; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.3') +def test_core_4002_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_4005.py b/tests/bugs/test_core_4005.py new file mode 100644 index 00000000..2e4bc59b --- /dev/null +++ b/tests/bugs/test_core_4005.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: bugs.core_4005 +# title: wrong error message with recursive CTE +# decription: +# tracker_id: CORE-4005 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + with recursive + c1 as ( + select 0 as i from rdb$database + union all + select i + 1 from c1 where i < 1 + ) + ,c2 as ( + select i, 0 as j from c1 + union all + select j * 10 + c1.i, c2.j + 1 + from c1 c1 + join c2 c2 on c2.j < 1 + ) + select count(i) as cnt from c2 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CNT 6 + """ + +@pytest.mark.version('>=2.5.3') +def test_core_4005_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4006.py b/tests/bugs/test_core_4006.py new file mode 100644 index 00000000..acc5977a --- /dev/null +++ b/tests/bugs/test_core_4006.py @@ -0,0 +1,52 @@ +#coding:utf-8 +# +# id: bugs.core_4006 +# title: using a result from a procedure in a substring expression leads to server crash +# decription: +# tracker_id: CORE-4006 +# min_versions: ['2.1.7'] +# versions: 2.1.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^ ; + create or alter procedure p_str_rpos + returns ( + result integer) + as + begin + result=14; + suspend; + end^ + set term ; ^ + commit; + + set list on; + select substring('somestringwith \\ no meaning' from 1 for result) r + from p_str_rpos; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + R somestringwith + """ + +@pytest.mark.version('>=2.1.7') +def test_core_4006_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4018.py b/tests/bugs/test_core_4018.py new file mode 100644 index 00000000..9639b268 --- /dev/null +++ b/tests/bugs/test_core_4018.py @@ -0,0 +1,133 @@ +#coding:utf-8 +# +# id: bugs.core_4018 +# title: Using system domain in procedures arguments/returns cause the proc to be unchangeable +# decription: +# tracker_id: CORE-4018 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set blob all; + set count on; + + set term ^; + create procedure sp_test returns(info rdb$source) as + begin + info = 'foo'; + suspend; + end + ^ + set term ;^ + commit; + + select 'point-1' as msg, rdb$parameter_name, rdb$parameter_type, rdb$field_source + from rdb$procedure_parameters + where rdb$procedure_name = upper('sp_test') + order by rdb$parameter_name, rdb$parameter_type; + + select 'point-2' as msg, rdb$procedure_source + from rdb$procedures + where rdb$procedure_name = upper('sp_test'); + commit; + + set term ^; + alter procedure sp_test(whoami rdb$user) returns(memo_info rdb$description) as + begin + memo_info = 'bar'; + suspend; + end + ^ + set term ;^ + commit; + + select 'point-3' as msg, rdb$parameter_name, rdb$parameter_type, rdb$field_source + from rdb$procedure_parameters + where rdb$procedure_name = upper('sp_test') + order by rdb$parameter_name, rdb$parameter_type; + + select 'point-4' as msg, rdb$procedure_source + from rdb$procedures + where rdb$procedure_name = upper('sp_test'); + commit; + + drop procedure sp_test; + commit; + + -- no rows must be issued: + select 'point-5' as msg, rdb$parameter_name, rdb$parameter_type, rdb$field_source + from rdb$procedure_parameters + where rdb$procedure_name = upper('sp_test'); + + -- no rows must be issued: + select 'point-6' as msg, rdb$procedure_source + from rdb$procedures + where rdb$procedure_name = upper('sp_test'); + commit; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG point-1 + RDB$PARAMETER_NAME INFO + RDB$PARAMETER_TYPE 1 + RDB$FIELD_SOURCE RDB$SOURCE + Records affected: 1 + + + MSG point-2 + RDB$PROCEDURE_SOURCE 1a:1e0 + begin + info = 'foo'; + suspend; + end + Records affected: 1 + + + MSG point-3 + RDB$PARAMETER_NAME MEMO_INFO + RDB$PARAMETER_TYPE 1 + RDB$FIELD_SOURCE RDB$DESCRIPTION + + MSG point-3 + RDB$PARAMETER_NAME WHOAMI + RDB$PARAMETER_TYPE 0 + RDB$FIELD_SOURCE RDB$USER + Records affected: 2 + + + MSG point-4 + RDB$PROCEDURE_SOURCE 1a:1e3 + begin + memo_info = 'bar'; + suspend; + end + Records affected: 1 + + Records affected: 0 + + Records affected: 0 + """ + +@pytest.mark.version('>=3.0') +def test_core_4018_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4027.py b/tests/bugs/test_core_4027.py new file mode 100644 index 00000000..73969b96 --- /dev/null +++ b/tests/bugs/test_core_4027.py @@ -0,0 +1,89 @@ +#coding:utf-8 +# +# id: bugs.core_4027 +# title: Creating table with computed fields containing "SELECT FIRST" produces corrupted result +# decription: Broken output in ISQL command SHOW TABLE for computed-by field(s). +# tracker_id: CORE-4027 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- NB: fixed only in 3.0 (checked 30.03.2015) + recreate table test (id int); + commit; + + recreate table contragents ( + agent_id int not null + ,agent_name varchar(25) not null + ); + commit; + + recreate table turnovers( + po_number char(8) not null + ,agent_id int not null + ,order_date timestamp default 'now' not null + ); + commit; + + 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 + ) + ) + ); + commit; + show table test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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 + ) + ) + """ + +@pytest.mark.version('>=3.0') +def test_core_4027_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4036.py b/tests/bugs/test_core_4036.py new file mode 100644 index 00000000..61d34532 --- /dev/null +++ b/tests/bugs/test_core_4036.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: bugs.core_4036 +# title: Bugcheck or database corruption when attempting to store long incompressible data into a table +# decription: +# tracker_id: CORE-4036 +# min_versions: ['2.1.6'] +# versions: 2.1.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table tw(s01 varchar(32600), s02 varchar(32600)); +commit;""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """insert into tw select rpad('',32600, gen_uuid()),rpad('',32600, gen_uuid()) from rdb$database; +commit; +set heading off; +SELECT count(*) from tw; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """1 +""" + +@pytest.mark.version('>=2.1.6') +def test_core_4036_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4038.py b/tests/bugs/test_core_4038.py new file mode 100644 index 00000000..6c59c72c --- /dev/null +++ b/tests/bugs/test_core_4038.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: bugs.core_4038 +# title: Broken optimization for the stored dbkeys +# decription: +# tracker_id: CORE-4038 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t (dbkey char(8) character set octets); +create index it on t (dbkey); +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLANONLY; +select * from t as t1 + left join t as t2 on t2.dbkey = t1.rdb$db_key; + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN JOIN (T1 NATURAL, T2 INDEX (IT)) +""" + +@pytest.mark.version('>=2.5.3') +def test_core_4038_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4054.py b/tests/bugs/test_core_4054.py new file mode 100644 index 00000000..1d793619 --- /dev/null +++ b/tests/bugs/test_core_4054.py @@ -0,0 +1,139 @@ +#coding:utf-8 +# +# id: bugs.core_4054 +# title: role not passed on external execute stmt +# decription: +# Checked on: +# 4.0.0.1635 SS: 1.359s. +# 4.0.0.1633 CS: 1.832s. +# 3.0.5.33180 SS: 0.879s. +# 3.0.5.33178 CS: 1.221s. +# 2.5.9.27119 SS: 0.272s. +# 2.5.9.27146 SC: 0.290s. +# +# tracker_id: CORE-4054 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set wng off; + -- Drop old account if it remains from prevoius run: + set term ^; + execute block as + begin + begin + execute statement 'drop user tmp$c4054' with autonomous transaction; + when any do begin end + end + end + ^ + set term ;^ + commit; + + create user tmp$c4054 password '123'; + commit; + revoke all on all from tmp$c4054; + commit; + + create table test(id int); + commit; + insert into test(id) values(789654123); + commit; + + set term ^; + execute block as + begin + execute statement 'drop role r4054'; + when any do + begin + end + end + ^ + set term ;^ + commit; + create role r4054; + commit; + + + grant select on test to role r4054; + commit; + + grant r4054 to tmp$c4054; + commit; + + set list on; + set term ^; + execute block returns (who_am_i varchar(30), whats_my_role varchar(30), what_i_see int) as + declare v_dbname type of column mon$database.mon$database_name; + declare v_usr rdb$user = 'tmp$c4054'; + declare v_pwd rdb$user = '123'; + declare v_role type of column rdb$roles.rdb$role_name; + begin + v_dbname = 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME'); + + --###################### + v_role = upper('r4054'); -- !!! ACHTUNG !!! ROLE NAME MUST BE ALWAYS PASSED IN UPPER CASE !!! + --###################### + -- Explanation can be seen here (russian): + -- http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1074439&msg=15494916 + for + execute statement 'select current_user, current_role, t.id from test t' + on external v_dbname + as user v_usr + password v_pwd + role v_role -- ####### ONCE AGAIN: ALWAYS PASS ROLE NAME IN *UPPER* CASE! ########## + into who_am_i, whats_my_role, what_i_see + 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; + + -- Do not forget about cleanup - remember that other tests can query sec$users or run `show users`! + drop user tmp$c4054; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHO_AM_I TMP$C4054 + WHATS_MY_ROLE R4054 + WHAT_I_SEE 789654123 + """ + +@pytest.mark.version('>=2.5.3') +def test_core_4054_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4058.py b/tests/bugs/test_core_4058.py new file mode 100644 index 00000000..531ca24b --- /dev/null +++ b/tests/bugs/test_core_4058.py @@ -0,0 +1,214 @@ +#coding:utf-8 +# +# id: bugs.core_4058 +# title: Remote Stack Buffer Overflow in Firebird SQL Server (when specially crafted packet is sent via socket API) +# decription: +# Bug was fixed on 2.5.5.26952. +# On 2.5.2.26540, 2.5.3.26780 and 2.5.4.26856 following lines appear in firebird.log +# after execution of this test: +# === +# CSPROG Sun Aug 21 09:49:12 2016 +# *** DUMP *** +# +# CSPROG Sun Aug 21 09:49:12 2016 +# Tag=-1 Offset=18 Length=34 Eof=0 +# +# CSPROG Sun Aug 21 09:49:12 2016 +# Clump 5 at offset 0: AAAABBBBCCCCDDDD +# +# CSPROG Sun Aug 21 09:49:12 2016 +# Fatal exception during clumplet dump: Invalid clumplet buffer structure: buffer end before end of clumplet - clumplet too long +# +# CSPROG Sun Aug 21 09:49:12 2016 +# Plain dump starting with offset 18: <05><15>localhost.loca +# === +# Checked on: +# 4.0.0.1635 SS: 4.251s. +# 4.0.0.1633 CS: 4.948s. +# 3.0.5.33180 SS: 3.868s. +# 3.0.5.33178 CS: 4.312s. +# 2.5.9.27119 SS: 3.269s. +# 2.5.9.27146 SC: 3.280s. +# +# +# tracker_id: CORE-4058 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import sys +# import socket +# import os +# import time +# import difflib +# import subprocess +# from fdb import services +# +# os.environ["ISC_USER"] = 'none' +# os.environ["ISC_PASSWORD"] = 'QwaSeDTy' +# db_file = db_conn.database_name +# engine = str(db_conn.engine_version) +# +# db_conn.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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# def svc_get_fb_log( engine, f_fb_log ): +# +# import subprocess +# +# if engine.startswith('2.5'): +# get_firebird_log_key='action_get_ib_log' +# else: +# get_firebird_log_key='action_get_fb_log' +# +# subprocess.call([ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# "-user", user_name, +# "-password", user_password, +# get_firebird_log_key +# ], +# stdout=f_fb_log, stderr=subprocess.STDOUT +# ) +# return +# +# #-------------------------------------------- +# +# # Get HOME dir of FB instance that is now checked. +# # We will concatenate this string with 'fbsvcmgr' command in order to choose +# # PROPER binary file when querying services API to shutdown/online DB +# # NOTE: this is NECESSARY if several instances are in work and we did not change +# # PATH variable before call this test! +# +# # NB, 06.12.2016: as of fdb 1.6.1 one need to EXPLICITLY specify user+password pair when doing connect +# # via to FB services API by services.connect() - see FB tracker, PYFB-69 +# # ("Can not connect to FB services if set ISC_USER & ISC_PASSWORD by os.environ[ ... ]") +# +# fb_home = services.connect(host='localhost', user= user_name, password= user_password).get_home_directory() +# +# fb_conf = os.path.join( fb_home, 'firebird.conf') +# +# ################################################# +# # Parsing firebird.conf for getting port number: +# ################################################# +# with open( fb_conf,'r') as f: +# for line in f: +# if 'remoteserviceport' in line.lower(): +# fb_port = line.split('=')[1].strip() +# +# +# f_fblog_before=open( os.path.join(context['temp_directory'],'tmp_4058_fblog_before.txt'), 'w') +# svc_get_fb_log( engine, f_fblog_before ) +# flush_and_close( f_fblog_before ) +# +# ######################################################### +# data_1 = "" +# data_1 += "00000001000000130000000200000024" +# data_1 += "00000010433a5c746573745f66697265" +# data_1 += "626972640000000400000022" +# data_1 += "0510" +# data_1 += "41414141424242424343434344444444" +# data_1 += "05156c6f63616c" +# data_1 += "686f73742e6c6f63616c646f6d61696e" +# data_1 += "06000000000000090000000100000002" +# data_1 += "00000005000000020000000a00000001" +# data_1 += "000000020000000500000004ffff800b" +# data_1 += "00000001000000020000000500000006" +# data_1 += "000000010000000200000005" +# data_1 += "0000000800" +# +# s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +# s.connect( ('localhost', int(fb_port) ) ) +# s.send(data_1.decode('hex')) +# s.close() +# +# # ------------------------------------------------------------------------------------------ +# +# f_fblog_after=open( os.path.join(context['temp_directory'],'tmp_4058_fblog_after.txt'), 'w') +# svc_get_fb_log( engine, f_fblog_after ) +# flush_and_close( f_fblog_after ) +# +# # Now we can compare two versions of firebird.log and check their difference. +# ################################# +# +# oldfb=open(f_fblog_before.name, 'r') +# newfb=open(f_fblog_after.name, 'r') +# +# difftext = ''.join(difflib.unified_diff( +# oldfb.readlines(), +# newfb.readlines() +# )) +# oldfb.close() +# newfb.close() +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_4058_diff.txt'), 'w') +# f_diff_txt.write(difftext) +# flush_and_close( f_diff_txt ) +# +# # NB: difflib.unified_diff() can show line(s) that present in both files, without marking that line(s) with "+". +# # Usually these are 1-2 lines that placed just BEFORE difference starts. +# # So we have to check output before display diff content: lines that are really differ must start with "+". +# +# # This should be empty: +# ####################### +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# if line.startswith('+'): +# print('UNEXPECTED NEW LINE IN FIREBIRD.LOG: '+line.upper()) +# +# # CLEANUP +# ######### +# time.sleep(1) +# +# cleanup( [i.name for i in (f_fblog_before, f_fblog_after, f_diff_txt) ] ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.2') +@pytest.mark.xfail +def test_core_4058_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4061.py b/tests/bugs/test_core_4061.py new file mode 100644 index 00000000..85a2249f --- /dev/null +++ b/tests/bugs/test_core_4061.py @@ -0,0 +1,75 @@ +#coding:utf-8 +# +# id: bugs.core_4061 +# title: isql does not insert boolean values correctly, always shown as False +# decription: +# tracker_id: CORE-4061 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table x( + id smallint generated by default as identity, + a varchar(10), + b boolean, + c boolean, + primary key(id) + ); + commit; + insert into x(a,b,c) values ('f1',true, false); + insert into x(a,b,c) values ('f2',1=1, null is null); + insert into x(a,b,c) values ('f3', null is not null, null = null); + insert into x(a,b,c) values ('f4', null is not distinct from null, null and null and not null); + insert into x(a,b,c) values ('f5', true is not distinct from not false, not false is not distinct from not not true ); + set list on; + select * from x; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + A f1 + B + C + + ID 2 + A f2 + B + C + + ID 3 + A f3 + B + C + + ID 4 + A f4 + B + C + + ID 5 + A f5 + B + C + """ + +@pytest.mark.version('>=3.0') +def test_core_4061_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4067.py b/tests/bugs/test_core_4067.py new file mode 100644 index 00000000..92445a7b --- /dev/null +++ b/tests/bugs/test_core_4067.py @@ -0,0 +1,72 @@ +#coding:utf-8 +# +# id: bugs.core_4067 +# title: Creating external function (udf) to not existing dll - and then procedure with it - crash server +# decription: +# +# tracker_id: CORE-4067 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# tmpfdb_1=os.path.join(context['temp_directory'],'tmp_4067_1.fdb') +# +# sql_chk=''' +# set sql dialect 1; +# create database 'localhost:%(tmpfdb_1)s' page_size 4096 default character set win1251 collation win1251; +# set list on; +# select mon$sql_dialect as x from mon$database; +# ''' % locals() +# +# f_list=[tmpfdb_1] +# +# # Cleanup BEFORE running script: +# ################ +# +# for i in range(len(f_list)): +# if os.path.isfile(f_list[i]): +# os.remove(f_list[i]) +# +# runProgram('isql',['-q'], sql_chk) +# +# # Final cleanup: +# ################ +# +# for i in range(len(f_list)): +# if os.path.isfile(f_list[i]): +# os.remove(f_list[i]) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + X 1 + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_4067_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4068.py b/tests/bugs/test_core_4068.py new file mode 100644 index 00000000..853d991f --- /dev/null +++ b/tests/bugs/test_core_4068.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: bugs.core_4068 +# title: create package fails on creating header as soon as there is at least 1 procedure name +# decription: +# tracker_id: CORE-4068 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create or alter package fb$out + as + begin + procedure enable; + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +def test_core_4068_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_4070.py b/tests/bugs/test_core_4070.py new file mode 100644 index 00000000..a7106784 --- /dev/null +++ b/tests/bugs/test_core_4070.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: bugs.core_4070 +# title: NOT-NULL-column can be used as primary key and filled with NULL-values +# decription: +# tracker_id: CORE-4070 +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test01(uid char(16) character set octets collate octets); + alter table test01 add constraint test01_pk primary key (uid); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + 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 + """ + +@pytest.mark.version('>=3.0') +def test_core_4070_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_4073.py b/tests/bugs/test_core_4073.py new file mode 100644 index 00000000..aece362d --- /dev/null +++ b/tests/bugs/test_core_4073.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_4073 +# title: Constant columns getting empty value with subselect from procedure +# decription: +# tracker_id: CORE-4073 +# min_versions: ['2.1.7'] +# versions: 2.1.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create domain d_vc10 varchar(10); + commit; + set term ^; + create or alter procedure P_TEST returns (TEXT D_VC10) as + begin + TEXT = '12345'; suspend; + end^ + set term ;^ + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select A, TEXT from (select '2' as A, TEXT from P_TEST); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A 2 + TEXT 12345 + """ + +@pytest.mark.version('>=2.1.7') +def test_core_4073_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4074.py b/tests/bugs/test_core_4074.py new file mode 100644 index 00000000..4bd784cc --- /dev/null +++ b/tests/bugs/test_core_4074.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_4074 +# title: Computed by columns and position function +# decription: +# tracker_id: CORE-4074 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table test01 ( + f01 computed by ( 'fabio ' || position('x','schunig') ), + f02 numeric(8,2) default 0 + ); + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F01 Computed by: ( 'fabio ' || position('x','schunig') ) + F02 NUMERIC(8, 2) Nullable default 0 + """ + +@pytest.mark.version('>=3.0') +def test_core_4074_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4075.py b/tests/bugs/test_core_4075.py new file mode 100644 index 00000000..1080ec81 --- /dev/null +++ b/tests/bugs/test_core_4075.py @@ -0,0 +1,73 @@ +#coding:utf-8 +# +# id: bugs.core_4075 +# title: Server bugchecks or crashes on exception in calculated index +# decription: +# 18.10.2016: added test case from CORE-4603. +# 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 ...") +# Checked on: build 4.0.0.744: OK, 1.500s. +# +# tracker_id: CORE-4075 +# min_versions: ['2.5.4'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table TEST (BIT smallint); + create index IDX_TEST_BIT on TEST computed by (bin_shl(1, TEST.BIT-1)); + + -- from CORE-4603: + recreate table T_TABLE ( + F_YEAR varchar(4), + F_MONTH_DAY varchar(5) + ); + create index T_INDEX on T_TABLE computed by (cast(F_YEAR || '.' || F_MONTH_DAY as date)); + commit; + + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + insert into test values (0); + + -- from core-4603: + insert into T_TABLE (F_YEAR, F_MONTH_DAY) values ('2014', '02.33'); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + 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 + + Statement failed, SQLSTATE = 22018 + Expression evaluation error for index "T_INDEX" on table "T_TABLE" + -conversion error from string "2014.02.33" + """ + +@pytest.mark.version('>=4.0') +def test_core_4075_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_4081.py b/tests/bugs/test_core_4081.py new file mode 100644 index 00000000..534e36df --- /dev/null +++ b/tests/bugs/test_core_4081.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: bugs.core_4081 +# title: Regression: Built-in functions and subselect no longer supported in "update or insert" value list +# decription: +# tracker_id: CORE-4081 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table test (uid varchar(64)); + commit; + + update or insert into test (uid) values ( uuid_to_char(gen_uuid()) ) + matching (uid); + + update or insert into test (uid) + values ( (select uuid_to_char(gen_uuid()) from rdb$database) ) + matching (uid); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +def test_core_4081_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_4082.py b/tests/bugs/test_core_4082.py new file mode 100644 index 00000000..80cc8e2a --- /dev/null +++ b/tests/bugs/test_core_4082.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_4082 +# title: Wrong value of expected length in the sring right truncation error +# decription: +# NB. Ticket title: Wrong error message (should point out the proper expected length) +# +# tracker_id: CORE-4082 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('-At block line: [\\d]+, col: [\\d]+', '-At block line')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + execute block as + declare u varchar(14); + begin + u = gen_uuid(); + end + ^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22001 + arithmetic exception, numeric overflow, or string truncation + -string right truncation + -expected length 14, actual 16 + -At block line: 4, col: 9 + """ + +@pytest.mark.version('>=3.0') +def test_core_4082_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_4083.py b/tests/bugs/test_core_4083.py new file mode 100644 index 00000000..c4e97097 --- /dev/null +++ b/tests/bugs/test_core_4083.py @@ -0,0 +1,83 @@ +#coding:utf-8 +# +# id: bugs.core_4083 +# title: Full outer join in derived table with coalesce (iif) +# decription: +# tracker_id: CORE-4083 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select + A_SOME_FIELD, + B_SOME_FIELD, + C_SOME_FIELD, + COALESCE_FIELD + from + ( + select + A.SOME_FIELD as A_SOME_FIELD, + B.SOME_FIELD as B_SOME_FIELD, + C.SOME_FIELD as C_SOME_FIELD, + coalesce(A.SOME_FIELD, B.SOME_FIELD, c.SOME_FIELD) as COALESCE_FIELD + from + (select null as SOME_FIELD from RDB$DATABASE) A + full join + (select 1 as SOME_FIELD from RDB$DATABASE) B on B.SOME_FIELD = A.SOME_FIELD + full join + (select null as SOME_FIELD from RDB$DATABASE) C on C.SOME_FIELD = B.SOME_FIELD + ) x + order by 1,2,3,4 + ; + + select a.*, b.* + from + (select 1 as field1 from rdb$database) a + full join + (select 2 as field2 from rdb$database) b on b.field2=a.field1 + order by 1,2 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A_SOME_FIELD + B_SOME_FIELD + C_SOME_FIELD + COALESCE_FIELD + A_SOME_FIELD + B_SOME_FIELD + C_SOME_FIELD + COALESCE_FIELD + A_SOME_FIELD + B_SOME_FIELD 1 + C_SOME_FIELD + COALESCE_FIELD 1 + + FIELD1 + FIELD2 2 + FIELD1 1 + FIELD2 + """ + +@pytest.mark.version('>=2.5.3') +def test_core_4083_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4084.py b/tests/bugs/test_core_4084.py new file mode 100644 index 00000000..0a0585d2 --- /dev/null +++ b/tests/bugs/test_core_4084.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: bugs.core_4084 +# title: Regression: Group by fails if subselect-column is involved +# decription: +# tracker_id: CORE-4084 +# min_versions: ['2.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set planonly; + select + iif(d is null, 10, 0) + sys as sys, + count(*) + from ( + select + ( select d.rdb$relation_id from rdb$database d ) as d, + coalesce(r.rdb$system_flag, 0) as sys + from rdb$relations r + ) + group by 1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (D NATURAL) + PLAN SORT (R NATURAL) + """ + +@pytest.mark.version('>=3.0') +def test_core_4084_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4091.py b/tests/bugs/test_core_4091.py new file mode 100644 index 00000000..c67d09a2 --- /dev/null +++ b/tests/bugs/test_core_4091.py @@ -0,0 +1,326 @@ +#coding:utf-8 +# +# id: bugs.core_4091 +# title: Incorrect full join result with ROW_NUMBER() Function in CTE +# decription: +# NOTE! We have to avoid usage of current RDB$DB_KEY values because they can change. +# Instead, we have to create tables XTYPES and XFORMATS with data from RDB$-tables +# that were in any empty adtabase created on WI-T3.0.0.30566 Firebird 3.0 Alpha 1. +# +# Confirmed bug on WI-T3.0.0.30566: FULL JOIN expression ("on a.rn = b.rn") +# was ignored and query produced 251 rows instead of expected 2. +# Fixed at least since WI-T3.0.0.30809 Firebird 3.0 Alpha 2. +# +# Checked on: +# 3.0.0.32136; 3.0.0.31374; 3.0.0.32483; 3.0.7.33358; 4.0.0.2180 +# +# tracker_id: CORE-4091 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table rtypes( dbkey char(16) character set octets, xtype smallint ); + recreate table rformats( dbkey char(16) character set octets, xformat smallint ); + commit; + + insert into rtypes(dbkey, xtype) values('0B00000001000000', 14); + insert into rtypes(dbkey, xtype) values('0B00000002000000', 7); + insert into rtypes(dbkey, xtype) values('0B00000003000000', 8); + insert into rtypes(dbkey, xtype) values('0B00000004000000', 9); + insert into rtypes(dbkey, xtype) values('0B00000005000000', 10); + insert into rtypes(dbkey, xtype) values('0B00000006000000', 27); + insert into rtypes(dbkey, xtype) values('0B00000007000000', 35); + insert into rtypes(dbkey, xtype) values('0B00000008000000', 37); + insert into rtypes(dbkey, xtype) values('0B00000009000000', 261); + insert into rtypes(dbkey, xtype) values('0B0000000A000000', 40); + insert into rtypes(dbkey, xtype) values('0B0000000B000000', 45); + insert into rtypes(dbkey, xtype) values('0B0000000C000000', 12); + insert into rtypes(dbkey, xtype) values('0B0000000D000000', 13); + insert into rtypes(dbkey, xtype) values('0B0000000E000000', 16); + insert into rtypes(dbkey, xtype) values('0B0000000F000000', 23); + insert into rtypes(dbkey, xtype) values('0B00000010000000', 0); + insert into rtypes(dbkey, xtype) values('0B00000011000000', 1); + insert into rtypes(dbkey, xtype) values('0B00000012000000', 2); + insert into rtypes(dbkey, xtype) values('0B00000013000000', 3); + insert into rtypes(dbkey, xtype) values('0B00000014000000', 4); + insert into rtypes(dbkey, xtype) values('0B00000015000000', 5); + insert into rtypes(dbkey, xtype) values('0B00000016000000', 6); + insert into rtypes(dbkey, xtype) values('0B00000017000000', 7); + insert into rtypes(dbkey, xtype) values('0B00000018000000', 8); + insert into rtypes(dbkey, xtype) values('0B00000019000000', 9); + insert into rtypes(dbkey, xtype) values('0B0000001A000000', 0); + insert into rtypes(dbkey, xtype) values('0B0000001B000000', 1); + insert into rtypes(dbkey, xtype) values('0B0000001C000000', 0); + insert into rtypes(dbkey, xtype) values('0B0000001D000000', 1); + insert into rtypes(dbkey, xtype) values('0B0000001E000000', 2); + insert into rtypes(dbkey, xtype) values('0B0000001F000000', 3); + insert into rtypes(dbkey, xtype) values('0B00000020000000', 4); + insert into rtypes(dbkey, xtype) values('0B00000021000000', 5); + insert into rtypes(dbkey, xtype) values('0B00000022000000', 1); + insert into rtypes(dbkey, xtype) values('0B00000023000000', 2); + insert into rtypes(dbkey, xtype) values('0B00000024000000', 3); + insert into rtypes(dbkey, xtype) values('0B00000025000000', 4); + insert into rtypes(dbkey, xtype) values('0B00000026000000', 5); + insert into rtypes(dbkey, xtype) values('0B00000027000000', 6); + insert into rtypes(dbkey, xtype) values('0B00000028000000', 8192); + insert into rtypes(dbkey, xtype) values('0B00000029000000', 8193); + insert into rtypes(dbkey, xtype) values('0B0000002A000000', 8194); + insert into rtypes(dbkey, xtype) values('0B0000002B000000', 8195); + insert into rtypes(dbkey, xtype) values('0B0000002C000000', 8196); + insert into rtypes(dbkey, xtype) values('0B0000002D000000', 0); + insert into rtypes(dbkey, xtype) values('0B0000002E000000', 1); + insert into rtypes(dbkey, xtype) values('0B0000002F000000', 2); + insert into rtypes(dbkey, xtype) values('0B00000030000000', 3); + insert into rtypes(dbkey, xtype) values('0B00000031000000', 4); + insert into rtypes(dbkey, xtype) values('0B000000F0000000', 5); + insert into rtypes(dbkey, xtype) values('0B000000F1000000', 6); + insert into rtypes(dbkey, xtype) values('0B000000F2000000', 7); + insert into rtypes(dbkey, xtype) values('0B000000F3000000', 8); + insert into rtypes(dbkey, xtype) values('0B000000F4000000', 9); + insert into rtypes(dbkey, xtype) values('0B000000F5000000', 10); + insert into rtypes(dbkey, xtype) values('0B000000F6000000', 11); + insert into rtypes(dbkey, xtype) values('0B000000F7000000', 12); + insert into rtypes(dbkey, xtype) values('0B000000F8000000', 13); + insert into rtypes(dbkey, xtype) values('0B000000F9000000', 14); + insert into rtypes(dbkey, xtype) values('0B000000FA000000', 15); + insert into rtypes(dbkey, xtype) values('0B000000FB000000', 16); + insert into rtypes(dbkey, xtype) values('0B000000FC000000', 17); + insert into rtypes(dbkey, xtype) values('0B000000FD000000', 18); + insert into rtypes(dbkey, xtype) values('0B000000FE000000', 19); + insert into rtypes(dbkey, xtype) values('0B000000FF000000', 1); + insert into rtypes(dbkey, xtype) values('0B00000000010000', 2); + insert into rtypes(dbkey, xtype) values('0B00000001010000', 3); + insert into rtypes(dbkey, xtype) values('0B00000002010000', 0); + insert into rtypes(dbkey, xtype) values('0B00000003010000', 1); + insert into rtypes(dbkey, xtype) values('0B00000004010000', 2); + insert into rtypes(dbkey, xtype) values('0B00000005010000', 3); + insert into rtypes(dbkey, xtype) values('0B00000006010000', 4); + insert into rtypes(dbkey, xtype) values('0B00000007010000', 5); + insert into rtypes(dbkey, xtype) values('0B00000008010000', 0); + insert into rtypes(dbkey, xtype) values('0B00000009010000', 1); + insert into rtypes(dbkey, xtype) values('0B0000000A010000', 2); + insert into rtypes(dbkey, xtype) values('0B0000000B010000', 3); + insert into rtypes(dbkey, xtype) values('0B0000000C010000', 4); + insert into rtypes(dbkey, xtype) values('0B0000000D010000', 5); + insert into rtypes(dbkey, xtype) values('0B0000000E010000', 0); + insert into rtypes(dbkey, xtype) values('0B0000000F010000', 1); + insert into rtypes(dbkey, xtype) values('0B00000010010000', 2); + insert into rtypes(dbkey, xtype) values('0B00000011010000', 0); + insert into rtypes(dbkey, xtype) values('0B00000012010000', 1); + insert into rtypes(dbkey, xtype) values('0B00000013010000', 0); + insert into rtypes(dbkey, xtype) values('0B00000014010000', 1); + insert into rtypes(dbkey, xtype) values('0B00000015010000', 2); + insert into rtypes(dbkey, xtype) values('0B00000016010000', 0); + insert into rtypes(dbkey, xtype) values('0B00000017010000', 1); + insert into rtypes(dbkey, xtype) values('0B00000018010000', 2); + insert into rtypes(dbkey, xtype) values('0B00000019010000', 3); + insert into rtypes(dbkey, xtype) values('0B0000001A010000', 0); + insert into rtypes(dbkey, xtype) values('0B0000001B010000', 1); + insert into rtypes(dbkey, xtype) values('0B0000001C010000', 2); + insert into rtypes(dbkey, xtype) values('0B0000001D010000', 3); + insert into rtypes(dbkey, xtype) values('0B0000001E010000', 0); + insert into rtypes(dbkey, xtype) values('0B0000001F010000', 1); + insert into rtypes(dbkey, xtype) values('0B000000DF010000', 2); + insert into rtypes(dbkey, xtype) values('0B000000E0010000', 0); + insert into rtypes(dbkey, xtype) values('0B000000E1010000', 1); + insert into rtypes(dbkey, xtype) values('0B000000E2010000', 2); + insert into rtypes(dbkey, xtype) values('0B000000E3010000', 3); + insert into rtypes(dbkey, xtype) values('0B000000E4010000', 4); + insert into rtypes(dbkey, xtype) values('0B000000E5010000', 0); + insert into rtypes(dbkey, xtype) values('0B000000E6010000', 1); + insert into rtypes(dbkey, xtype) values('0B000000E7010000', 0); + insert into rtypes(dbkey, xtype) values('0B000000E8010000', 1); + insert into rtypes(dbkey, xtype) values('0B000000E9010000', 0); + insert into rtypes(dbkey, xtype) values('0B000000EA010000', 1); + insert into rtypes(dbkey, xtype) values('0B000000EB010000', 0); + insert into rtypes(dbkey, xtype) values('0B000000EC010000', 1); + insert into rtypes(dbkey, xtype) values('0B000000ED010000', 0); + insert into rtypes(dbkey, xtype) values('0B000000EE010000', 1); + insert into rtypes(dbkey, xtype) values('0B000000EF010000', 0); + insert into rtypes(dbkey, xtype) values('0B000000F0010000', 1); + insert into rtypes(dbkey, xtype) values('0B000000F1010000', 2); + insert into rtypes(dbkey, xtype) values('0B000000F2010000', 1); + insert into rtypes(dbkey, xtype) values('0B000000F3010000', 2); + insert into rtypes(dbkey, xtype) values('0B000000F4010000', 3); + insert into rtypes(dbkey, xtype) values('0B000000F5010000', 4); + insert into rtypes(dbkey, xtype) values('0B000000F6010000', 5); + insert into rtypes(dbkey, xtype) values('0B000000F7010000', 6); + insert into rtypes(dbkey, xtype) values('0B000000F8010000', 7); + insert into rtypes(dbkey, xtype) values('0B000000F9010000', 8); + insert into rtypes(dbkey, xtype) values('0B000000FA010000', 9); + insert into rtypes(dbkey, xtype) values('0B000000FB010000', 10); + insert into rtypes(dbkey, xtype) values('0B000000FC010000', 0); + insert into rtypes(dbkey, xtype) values('0B000000FD010000', 1); + insert into rtypes(dbkey, xtype) values('0B000000FE010000', 0); + insert into rtypes(dbkey, xtype) values('0B000000FF010000', 1); + insert into rtypes(dbkey, xtype) values('0B00000000020000', 0); + insert into rtypes(dbkey, xtype) values('0B00000001020000', 1); + insert into rtypes(dbkey, xtype) values('0B00000002020000', 0); + insert into rtypes(dbkey, xtype) values('0B00000003020000', 1); + insert into rtypes(dbkey, xtype) values('0B00000004020000', 2); + insert into rtypes(dbkey, xtype) values('0B00000005020000', 3); + insert into rtypes(dbkey, xtype) values('0B00000006020000', 4); + insert into rtypes(dbkey, xtype) values('0B00000007020000', 5); + insert into rtypes(dbkey, xtype) values('0B00000008020000', 6); + insert into rtypes(dbkey, xtype) values('0B00000009020000', 10); + insert into rtypes(dbkey, xtype) values('0B0000000A020000', 11); + insert into rtypes(dbkey, xtype) values('0B0000000B020000', 12); + insert into rtypes(dbkey, xtype) values('0B0000000C020000', 21); + insert into rtypes(dbkey, xtype) values('0B0000000D020000', 22); + insert into rtypes(dbkey, xtype) values('0B0000000E020000', 23); + insert into rtypes(dbkey, xtype) values('0B000000CE020000', 34); + insert into rtypes(dbkey, xtype) values('0B000000CF020000', 35); + insert into rtypes(dbkey, xtype) values('0B000000D0020000', 36); + insert into rtypes(dbkey, xtype) values('0B000000D1020000', 37); + insert into rtypes(dbkey, xtype) values('0B000000D2020000', 38); + insert into rtypes(dbkey, xtype) values('0B000000D3020000', 39); + insert into rtypes(dbkey, xtype) values('0B000000D4020000', 40); + insert into rtypes(dbkey, xtype) values('0B000000D5020000', 45); + insert into rtypes(dbkey, xtype) values('0B000000D6020000', 46); + insert into rtypes(dbkey, xtype) values('0B000000D7020000', 13); + insert into rtypes(dbkey, xtype) values('0B000000D8020000', 47); + insert into rtypes(dbkey, xtype) values('0B000000D9020000', 14); + insert into rtypes(dbkey, xtype) values('0B000000DA020000', 50); + insert into rtypes(dbkey, xtype) values('0B000000DB020000', 9); + insert into rtypes(dbkey, xtype) values('0B000000DC020000', 15); + insert into rtypes(dbkey, xtype) values('0B000000DD020000', 16); + insert into rtypes(dbkey, xtype) values('0B000000DE020000', 17); + insert into rtypes(dbkey, xtype) values('0B000000DF020000', 18); + insert into rtypes(dbkey, xtype) values('0B000000E0020000', 48); + insert into rtypes(dbkey, xtype) values('0B000000E1020000', 49); + insert into rtypes(dbkey, xtype) values('0B000000E2020000', 51); + insert into rtypes(dbkey, xtype) values('0B000000E3020000', 52); + insert into rtypes(dbkey, xtype) values('0B000000E4020000', 53); + insert into rtypes(dbkey, xtype) values('0B000000E5020000', 54); + insert into rtypes(dbkey, xtype) values('0B000000E6020000', 55); + insert into rtypes(dbkey, xtype) values('0B000000E7020000', 19); + insert into rtypes(dbkey, xtype) values('0B000000E8020000', 58); + insert into rtypes(dbkey, xtype) values('0B000000E9020000', 59); + insert into rtypes(dbkey, xtype) values('0B000000EA020000', 60); + insert into rtypes(dbkey, xtype) values('0B000000EB020000', 44); + insert into rtypes(dbkey, xtype) values('0B000000EC020000', 56); + insert into rtypes(dbkey, xtype) values('0B000000ED020000', 57); + insert into rtypes(dbkey, xtype) values('0B000000EE020000', 63); + insert into rtypes(dbkey, xtype) values('0B000000EF020000', 64); + insert into rtypes(dbkey, xtype) values('0B000000F0020000', 65); + insert into rtypes(dbkey, xtype) values('0B000000F1020000', 66); + insert into rtypes(dbkey, xtype) values('0B000000F2020000', 67); + insert into rtypes(dbkey, xtype) values('0B000000F3020000', 68); + insert into rtypes(dbkey, xtype) values('0B000000F4020000', 69); + insert into rtypes(dbkey, xtype) values('0B000000F5020000', 1); + insert into rtypes(dbkey, xtype) values('0B000000F6020000', 2); + insert into rtypes(dbkey, xtype) values('0B000000F7020000', 2); + insert into rtypes(dbkey, xtype) values('0B000000F8020000', 3); + insert into rtypes(dbkey, xtype) values('0B000000F9020000', 3); + insert into rtypes(dbkey, xtype) values('0B000000FA020000', 4); + insert into rtypes(dbkey, xtype) values('0B000000FB020000', 5); + insert into rtypes(dbkey, xtype) values('0B000000FC020000', 6); + insert into rtypes(dbkey, xtype) values('0B000000BD030000', 10); + insert into rtypes(dbkey, xtype) values('0B000000BE030000', 11); + insert into rtypes(dbkey, xtype) values('0B000000BF030000', 12); + insert into rtypes(dbkey, xtype) values('0B000000C0030000', 21); + insert into rtypes(dbkey, xtype) values('0B000000C1030000', 21); + insert into rtypes(dbkey, xtype) values('0B000000C2030000', 21); + insert into rtypes(dbkey, xtype) values('0B000000C3030000', 22); + insert into rtypes(dbkey, xtype) values('0B000000C4030000', 22); + insert into rtypes(dbkey, xtype) values('0B000000C5030000', 22); + insert into rtypes(dbkey, xtype) values('0B000000C6030000', 23); + insert into rtypes(dbkey, xtype) values('0B000000C7030000', 23); + insert into rtypes(dbkey, xtype) values('0B000000C8030000', 23); + insert into rtypes(dbkey, xtype) values('0B000000C9030000', 34); + insert into rtypes(dbkey, xtype) values('0B000000CA030000', 34); + insert into rtypes(dbkey, xtype) values('0B000000CB030000', 34); + insert into rtypes(dbkey, xtype) values('0B000000CC030000', 35); + insert into rtypes(dbkey, xtype) values('0B000000CD030000', 35); + insert into rtypes(dbkey, xtype) values('0B000000CE030000', 36); + insert into rtypes(dbkey, xtype) values('0B000000CF030000', 36); + insert into rtypes(dbkey, xtype) values('0B000000D0030000', 37); + insert into rtypes(dbkey, xtype) values('0B000000D1030000', 37); + insert into rtypes(dbkey, xtype) values('0B000000D2030000', 38); + insert into rtypes(dbkey, xtype) values('0B000000D3030000', 38); + insert into rtypes(dbkey, xtype) values('0B000000D4030000', 39); + insert into rtypes(dbkey, xtype) values('0B000000D5030000', 39); + insert into rtypes(dbkey, xtype) values('0B000000D6030000', 39); + insert into rtypes(dbkey, xtype) values('0B000000D7030000', 40); + insert into rtypes(dbkey, xtype) values('0B000000D8030000', 40); + insert into rtypes(dbkey, xtype) values('0B000000D9030000', 40); + insert into rtypes(dbkey, xtype) values('0B000000DA030000', 45); + insert into rtypes(dbkey, xtype) values('0B000000DB030000', 46); + insert into rtypes(dbkey, xtype) values('0B000000DC030000', 13); + insert into rtypes(dbkey, xtype) values('0B000000DD030000', 47); + insert into rtypes(dbkey, xtype) values('0B000000DE030000', 14); + insert into rtypes(dbkey, xtype) values('0B000000DF030000', 9); + insert into rtypes(dbkey, xtype) values('0B000000E0030000', 15); + insert into rtypes(dbkey, xtype) values('0B000000E1030000', 16); + insert into rtypes(dbkey, xtype) values('0B000000E2030000', 17); + insert into rtypes(dbkey, xtype) values('0B000000E3030000', 18); + insert into rtypes(dbkey, xtype) values('0B000000E4030000', 48); + insert into rtypes(dbkey, xtype) values('0B000000E5030000', 49); + insert into rtypes(dbkey, xtype) values('0B000000E6030000', 51); + insert into rtypes(dbkey, xtype) values('0B000000E7030000', 52); + insert into rtypes(dbkey, xtype) values('0B000000E8030000', 53); + insert into rtypes(dbkey, xtype) values('0B000000E9030000', 54); + insert into rtypes(dbkey, xtype) values('0B000000EA030000', 55); + insert into rtypes(dbkey, xtype) values('0B000000AC040000', 58); + insert into rtypes(dbkey, xtype) values('0B000000AD040000', 59); + insert into rtypes(dbkey, xtype) values('0B000000AE040000', 60); + insert into rtypes(dbkey, xtype) values('0B000000AF040000', 65); + insert into rtypes(dbkey, xtype) values('0B000000B0040000', 44); + insert into rtypes(dbkey, xtype) values('0B000000B1040000', 44); + insert into rtypes(dbkey, xtype) values('0B000000B2040000', 44); + insert into rtypes(dbkey, xtype) values('0B000000B3040000', 56); + insert into rtypes(dbkey, xtype) values('0B000000B4040000', 56); + insert into rtypes(dbkey, xtype) values('0B000000B5040000', 56); + insert into rtypes(dbkey, xtype) values('0B000000B6040000', 57); + insert into rtypes(dbkey, xtype) values('0B000000B7040000', 57); + insert into rtypes(dbkey, xtype) values('0B000000B8040000', 57); + commit; + + insert into rformats(dbkey, xformat) values('08000000F0000000', 1); + insert into rformats(dbkey, xformat) values('08000000F1000000', 1); + commit; + + set count on; + with A as ( + select t.xtype, row_number()over(order by t.dbkey) as RN from rtypes t + ), + B as ( + select f.xformat, row_number()over(order by f.dbkey) as RN from rformats f + ) + select a.xtype as "rtypes.type", a.rn as "rtypes.rn", b.rn as "rformats.rn", b.xformat as "rformats.format" + from a + full outer join b on a.rn = b.rn + where b.xformat is not null + order by 1,2,3,4 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + rtypes.type rtypes.rn rformats.rn rformats.format + =========== ===================== ===================== =============== + 0 2 2 1 + 2 1 1 1 + Records affected: 2 + """ + +@pytest.mark.version('>=3.0') +def test_core_4091_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4093.py b/tests/bugs/test_core_4093.py new file mode 100644 index 00000000..0a726bb3 --- /dev/null +++ b/tests/bugs/test_core_4093.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: bugs.core_4093 +# title: Server crashes while converting an overscaled numeric to a string +# decription: +# tracker_id: CORE-4093 +# min_versions: ['2.5.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + select cast( cast(0 as numeric(38, 38)) * cast(0 as numeric(38, 38)) * cast(0 as numeric(38, 38)) as varchar(100) ) from rdb$database; + select cast( cast(0 as numeric(38, 38)) * cast(0 as numeric(38, 38)) * cast(0 as numeric(38, 38)) as numeric(38, 38) ) from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 0E-114 + 0.00000000000000000000000000000000000000 + """ + +@pytest.mark.version('>=4.0') +def test_core_4093_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4094.py b/tests/bugs/test_core_4094.py new file mode 100644 index 00000000..4687ffdc --- /dev/null +++ b/tests/bugs/test_core_4094.py @@ -0,0 +1,266 @@ +#coding:utf-8 +# +# id: bugs.core_4094 +# title: Wrong parameters order in trace output +# decription: +# WI-V2.5.2.26540: confirmed wrong parameters sequence in trace log: 1,4,3,2. +# +# ::: NB ::: 07-jun-2016. +# +# WI-T4.0.0.238 will issue in trace log following parametrized statement: +# === +# with recursive role_tree as ( +# select rdb$relation_name as nm, 0 as ur from rdb$user_privileges +# where +# rdb$privilege = 'M' and rdb$field_name = 'D' +# and rdb$user = ? and rdb$user_type = 8 +# union all +# select rdb$role_name as nm, 1 as ur from rdb$roles +# where rdb$role_name =... +# +# param0 = varchar(93), "SYSDBA" +# param1 = varchar(93), "NONE" +# === +# +# This statement will issued BEFORE our call of stored procedure, so we have to analyze +# lines from trace only AFTER we found pattern 'execute procedure sp_test'. +# +# +# tracker_id: CORE-4094 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + set term ^; + create or alter procedure sp_test(a int, b int, c int, d int) as + declare n int; + begin + execute statement ( + 'select + (select 123 from rdb$database where rdb$relation_id=:a) + from rdb$database + cross join + ( + select 123 as pdk + from rdb$database + where rdb$relation_id=:b and rdb$relation_id=:c and rdb$relation_id=:d + ) + rows 1' + ) + ( a := :a, b := :b, c := :c, d := :d ) + into n; + end + ^ + set term ;^ + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# from subprocess import Popen +# import re +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# engine = str(db_conn.engine_version) +# db_conn.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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# # Minimal delay after we issue command fbsvcmgr action_trace_start +# # and before we launch execution of checked code +# ########################################### +# min_delay_after_trace_start = 1 +# +# # Minimal delay after we finish connection to database +# # and before issuing command to stop trace +# ########################################## +# min_delay_before_trace_stop = 1 +# +# # Minimal delay for trace log be flushed on disk after +# # we issue command 'fbsvcmgr action_trace_stop': +# ############################### +# min_delay_after_trace_stop = 1 +# +# def make_trace_config( engine, f_trccfg ): +# +# txt25 = ''' +# enabled true +# time_threshold 0 +# log_statement_start true +# +# ''' +# +# # NOTES ABOUT TRACE CONFIG FOR 3.0: +# # 1) Header contains `database` clause in different format vs FB 2.5: its data must be enclosed with '{' '}' +# # 2) Name and value must be separated by EQUALITY sign ('=') in FB-3 trace.conf, otherwise we get runtime error: +# # element "<. . .>" have no attribute value set +# +# +# txt30 = ''' database=%[\\\\\\\\/]bugs.core_4094.fdb +# { +# enabled = true +# time_threshold = 0 +# log_statement_start = true +# } +# ''' +# +# if engine.startswith('2.5'): +# f_trccfg.write(txt25) +# else: +# f_trccfg.write(txt30) +# +# return +# +# def stop_trace_session(): +# +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# global os, subprocess +# global flush_and_close +# +# f_trclst=open( os.path.join(context['temp_directory'],'tmp_trace_4094.lst'), 'w') +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", "action_trace_list"], +# stdout=f_trclst, +# stderr=subprocess.STDOUT +# ) +# flush_and_close( f_trclst ) +# +# trcssn=0 +# with open( f_trclst.name,'r') as f: +# for line in f: +# if 'Session ID' in line: +# trcssn=line.split()[2] +# break +# +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# f_trclst=open(f_trclst.name,'a') +# f_trclst.seek(0,2) +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", "action_trace_stop", "trc_id",trcssn], +# stdout=f_trclst, stderr=subprocess.STDOUT +# ) +# flush_and_close( f_trclst ) +# +# os.remove(f_trclst.name) +# +# return +# +# ########## r u n ######### +# +# # Make trace config: +# +# f_trccfg=open( os.path.join(context['temp_directory'],'tmp_trace_4094.cfg'), 'w') +# make_trace_config( engine, f_trccfg ) +# flush_and_close( f_trccfg ) +# +# f_trclog=open( os.path.join(context['temp_directory'],'tmp_trace_4094.log'), 'w') +# +# ##################################################### +# # Starting trace session in new child process (async.): +# +# # Execute a child program in a new process, redirecting STDERR to the same target as of STDOUT: +# p_trace=Popen( [ context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_start", +# "trc_cfg", f_trccfg.name +# ], +# stdout=f_trclog, +# stderr=subprocess.STDOUT +# ) +# +# # If this delay is too low then trace log will be EMPTY (got on 2.5 SS and Cs). +# time.sleep( min_delay_after_trace_start ) +# +# #################################################### +# # Make connection to database and perform script that +# # calls two functions: standalone and packaged: +# #################################################### +# +# runProgram('isql',[dsn, '-n', '-q'], "execute procedure sp_test( 1, 2, 3, 4);" ) +# +# # do NOT remove this otherwise trace log can contain only message about its start before being closed! +# time.sleep(min_delay_before_trace_stop) +# +# ##################################################### +# # Getting ID of launched trace session and STOP it: +# +# stop_trace_session() +# time.sleep(min_delay_after_trace_stop) +# +# # Terminate child process of launched trace session (though it should already be killed): +# p_trace.terminate() +# flush_and_close( f_trclog ) +# +# +# ############# +# # O U T P U T +# ############# +# spcall_pattern=re.compile("execute procedure ") +# params_pattern = re.compile("param[0-9]{1} = ") +# flag=0 +# with open( f_trclog.name,'r') as f: +# for line in f: +# if spcall_pattern.match(line): +# flag=1 +# if flag==1 and params_pattern.match(line): +# print(line) +# +# # Cleanup. +# ########## +# cleanup( [i.name for i in (f_trclog,f_trccfg) ] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + param0 = smallint, "1" + param1 = smallint, "2" + param2 = smallint, "3" + param3 = smallint, "4" + """ + +@pytest.mark.version('>=2.5.3') +@pytest.mark.xfail +def test_core_4094_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4102.py b/tests/bugs/test_core_4102.py new file mode 100644 index 00000000..70721351 --- /dev/null +++ b/tests/bugs/test_core_4102.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: bugs.core_4102 +# title: Bad optimization of OR predicates applied to unions +# decription: +# tracker_id: CORE-4102 +# min_versions: ['2.5.3'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (X R INDEX (RDB$INDEX_1, RDB$INDEX_1), X R INDEX (RDB$INDEX_1, RDB$INDEX_1)) +""" + +@pytest.mark.version('>=3.0') +def test_core_4102_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4107.py b/tests/bugs/test_core_4107.py new file mode 100644 index 00000000..700462b6 --- /dev/null +++ b/tests/bugs/test_core_4107.py @@ -0,0 +1,79 @@ +#coding:utf-8 +# +# id: bugs.core_4107 +# title: wrong resultset (subquery + derived table + union) +# decription: +# tracker_id: CORE-4107 +# min_versions: ['2.1.6'] +# versions: 2.1.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.6 +# resources: None + +substitutions_1 = [('Statement failed.*', 'Statement failed')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Fixed on FB 3.0 since 2015-07-12 + -- http://sourceforge.net/p/firebird/code/61970 + -- Checked on WI-V3.0.0.31940. + set list on; + select T.VAL1, + ( + select 'something' from rdb$database where 2 = T.ID + union + select null from rdb$database where 1 = 0 + ) as VAL2 + from ( + select 1 as VAL1, 1 as ID from rdb$database + union all + select 2 as VAL1, 2 as ID from rdb$database + ) as T + group by 1; + + select T.VAL1, + min(( + select 'something' from rdb$database where 2 = T.ID + union + select null from rdb$database where 1 = 0 + )) as VAL2 + from ( + select 1 as VAL1, 1 as ID from rdb$database + union all + select 2 as VAL1, 2 as ID from rdb$database + ) as T + group by 1; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + VAL1 1 + VAL2 + + VAL1 2 + VAL2 something + """ +expected_stderr_1 = """ + 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) + """ + +@pytest.mark.version('>=2.1.6') +def test_core_4107_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4108.py b/tests/bugs/test_core_4108.py new file mode 100644 index 00000000..1a0b9ab9 --- /dev/null +++ b/tests/bugs/test_core_4108.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: bugs.core_4108 +# title: Regression: Server crashes when executing sql query "delete from mytable order by id desc rows 2" +# decription: +# tracker_id: CORE-4108 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table mytable ( + id integer not null primary key, + name varchar(30) + ); + + insert into mytable(id, name) + select 1, 'a' from rdb$database + union all + select 2, 'b' from rdb$database + union all + select 3, 'c' from rdb$database; + + delete from mytable order by id desc rows 2; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +def test_core_4108_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_4113.py b/tests/bugs/test_core_4113.py new file mode 100644 index 00000000..8b708a2d --- /dev/null +++ b/tests/bugs/test_core_4113.py @@ -0,0 +1,173 @@ +#coding:utf-8 +# +# id: bugs.core_4113 +# title: EXECUTE BLOCK prepare fails +# decription: length of the generated BLR oveflows the 64KB limit and some engine parts are not ready for that +# tracker_id: CORE-4113 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core4113.fbk', init=init_script_1) + +test_script_1 = """ + -- Confirmed for 2.5.2: error raises, text: + -- Statement failed, SQLSTATE = 42000 + -- attempted update of read-only column + set term ^; + EXECUTE BLOCK + AS + BEGIN + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154191752,72472957,5,NULL,1013437,-0.78,0,0,'EUR',0,0,0,'EUR',0,0,0,'EUR',0,0,0,'EUR',0,0,0,'EUR',0,0,0,'EUR',0,0,0,'EUR','SEVA','2012.07.11 11:42:44.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154191758,72472957,4,NULL,1013443,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-277400,0,0,'HUF','SEVA','2012.07.11 11:42:44.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154191853,72472957,4,NULL,1013527,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-243840,0,0,'HUF','SEVA','2012.07.11 11:42:44.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154191854,72472957,4,NULL,1013528,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-687292,0,0,'HUF','SEVA','2012.07.11 11:42:44.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154191931,72472957,4,NULL,1013663,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-122060,0,0,'HUF','SEVA','2012.07.11 11:42:44.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154191944,72472957,4,NULL,1013715,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-970636,0,0,'HUF','SEVA','2012.07.11 11:42:44.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154191947,72472957,4,NULL,1013719,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-1281112,0,0,'HUF','SEVA','2012.07.11 11:42:44.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154191948,72472957,4,NULL,1013720,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-775776,0,0,'HUF','SEVA','2012.07.11 11:42:44.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154191983,72472957,4,NULL,1013788,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-1129021,0,0,'HUF','SEVA','2012.07.11 11:42:44.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154192050,72472957,4,NULL,1013999,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-1970606,0,0,'HUF','SEVA','2012.07.11 11:42:44.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154192063,72472957,4,NULL,1014052,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-1340866,0,0,'HUF','SEVA','2012.07.11 11:42:45.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154192085,72472957,4,NULL,1014083,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-440690,0,0,'HUF','SEVA','2012.07.11 11:42:45.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154192296,72472957,4,NULL,1014491,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-245123,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-495224,0,0,'HUF','SEVA','2012.07.11 11:42:45.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154192297,72472957,4,NULL,1014493,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-668819,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:45.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154192305,72472957,4,NULL,1014506,0,0,0,'HUF',-45467,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:45.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154192310,72472957,4,NULL,1014525,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-322508,0,0,'HUF','SEVA','2012.07.11 11:42:45.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154192455,72472957,4,NULL,1014830,-235750,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-13581,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:45.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154192457,72472957,4,NULL,1014835,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-275104,0,0,'HUF','SEVA','2012.07.11 11:42:45.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154192499,72472957,4,NULL,1014962,0,0,0,'HUF',-1061199,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:45.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154192532,72472957,4,NULL,1015022,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-806958,0,0,'HUF',0,0,0,'HUF',-525765,0,0,'HUF','SEVA','2012.07.11 11:42:45.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154192570,72472957,4,NULL,1015113,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-1235544,0,0,'HUF','SEVA','2012.07.11 11:42:45.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154192610,72472957,4,NULL,1015208,0,0,0,'HUF',0,0,0,'HUF',-138840,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-578558,0,0,'HUF','SEVA','2012.07.11 11:42:45.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154192705,72472957,4,NULL,1015371,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-130950,0,0,'HUF','SEVA','2012.07.11 11:42:45.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154192870,72472957,4,NULL,1015715,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-353600,0,0,'HUF','SEVA','2012.07.11 11:42:45.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193105,72472957,4,NULL,1016488,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-1809160,0,0,'HUF','SEVA','2012.07.11 11:42:45.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193114,72472957,4,NULL,1016560,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-114268,0,0,'HUF','SEVA','2012.07.11 11:42:45.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193235,72472957,4,NULL,1017081,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-4231146,0,0,'HUF','SEVA','2012.07.11 11:42:45.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193413,72472957,4,NULL,1017544,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-58420,0,0,'HUF','SEVA','2012.07.11 11:42:45.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193487,72472957,4,NULL,1017756,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-585216,0,0,'HUF','SEVA','2012.07.11 11:42:45.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193512,72472957,4,NULL,1017828,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-219714,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193624,72472957,4,NULL,1018123,-16606,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-628840,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193632,72472957,4,NULL,1018132,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-648310,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193637,72472957,4,NULL,1018138,0,0,0,'HUF',0,0,0,'HUF',-743915,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-1459222,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193641,72472957,4,NULL,1018142,0,0,0,'HUF',0,0,0,'HUF',-406527,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-2209419,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193642,72472957,4,NULL,1018143,0,0,0,'HUF',-20879,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193657,72472957,4,NULL,1018168,0,0,0,'HUF',-197986,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193666,72472957,4,NULL,1018180,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-44161,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193668,72472957,4,NULL,1018181,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-72708,0,0,'HUF',-81236,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193675,72472957,4,NULL,1018188,0,0,0,'HUF',-27889,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193684,72472957,4,NULL,1018199,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-929576,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193690,72472957,4,NULL,1018207,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-650138,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193709,72472957,4,NULL,1018228,0,0,0,'HUF',-4696,0,0,'HUF',-39584,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193713,72472957,4,NULL,1018233,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-259080,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193717,72472957,4,NULL,1018238,0,0,0,'HUF',-27313,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193728,72472957,4,NULL,1018245,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-221000,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193740,72472957,4,NULL,1018261,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-38132,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193756,72472957,4,NULL,1018279,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-2031,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193757,72472957,4,NULL,1018280,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-6045,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193769,72472957,4,NULL,1018294,0,0,0,'HUF',-75844,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193772,72472957,4,NULL,1018297,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-2637040,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193781,72472957,4,NULL,1018307,0,0,0,'HUF',0,0,0,'HUF',-60581,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-69508,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193793,72472957,4,NULL,1018321,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-17899,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193812,72472957,4,NULL,1018347,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-55090,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193817,72472957,4,NULL,1018353,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-248293,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-354040,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193818,72472957,4,NULL,1018354,0,0,0,'HUF',0,0,0,'HUF',-178900,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193823,72472957,4,NULL,1018361,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-268088,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193880,72472957,4,NULL,1018429,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-360153,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193898,72472957,4,NULL,1018453,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-616356,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193924,72472957,4,NULL,1018490,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-141150,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193927,72472957,4,NULL,1018494,0,0,0,'HUF',0,0,0,'HUF',-26725,0,0,'HUF',-38620,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193933,72472957,4,NULL,1018502,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-416939,0,0,'HUF',0,0,0,'HUF',-722197,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154193964,72472957,4,NULL,1018554,0,2200,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154194006,72472957,4,NULL,1018609,0,0,0,'HUF',-317570,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:46.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154194042,72472957,4,NULL,1018660,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-262780,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:47.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154194181,72472957,4,NULL,1018886,0,0,0,'HUF',0,0,0,'HUF',-102235,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:47.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154194214,72472957,4,NULL,1073415,-34698,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:47.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154194271,72472957,4,NULL,1080235,-3,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:47.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154194317,72472957,4,NULL,1089836,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-12700,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:47.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154194370,72472957,4,NULL,1097521,-2,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:47.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154194379,72472957,4,NULL,1098475,0,0,0,'HUF',0,0,0,'HUF',-33020,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:47.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154194442,72472957,4,NULL,1110047,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-497840,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:47.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154194520,72472957,4,NULL,1133034,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-63850,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:47.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154194544,72472957,4,NULL,1140414,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-4575658,0,0,'HUF','SEVA','2012.07.11 11:42:47.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154194629,72472957,4,NULL,1371814,0,0,0,'HUF',0,0,0,'HUF',-223012,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:47.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154194642,72472957,4,NULL,1382602,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-46774,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:47.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154194702,72472957,4,NULL,1716160,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-576968,0,0,'HUF','SEVA','2012.07.11 11:42:47.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154194851,72472957,4,NULL,2023799,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-11700,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:47.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154195014,72472957,4,NULL,2293468,-1,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:47.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154195073,72472957,4,NULL,2407801,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-541020,0,0,'HUF','SEVA','2012.07.11 11:42:47.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154195126,72472957,4,NULL,2562533,0,0,0,'HUF',0,0,0,'HUF',-52560,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:47.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154195227,72472957,4,NULL,2645180,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-80645,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-30480,0,0,'HUF','SEVA','2012.07.11 11:42:47.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154195346,72472957,4,NULL,3132987,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-619847,0,0,'HUF','SEVA','2012.07.11 11:42:47.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154195387,72472957,4,NULL,3231740,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-336448,0,0,'HUF','SEVA','2012.07.11 11:42:47.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154195497,72472957,4,NULL,3441458,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-533400,0,0,'HUF','SEVA','2012.07.11 11:42:48.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154195525,72472957,4,NULL,3510459,0,0,0,'HUF',0,0,0,'HUF',-110700,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:48.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154195584,72472957,4,NULL,3738694,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-488747,0,0,'HUF',-3425368,0,0,'HUF','SEVA','2012.07.11 11:42:48.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154195667,72472957,4,NULL,3907680,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-62484,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:48.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154195718,72472957,4,NULL,3993781,0,0,0,'HUF',0,0,0,'HUF',-25710,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:48.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154195889,72472957,4,NULL,5070965,0,0,0,'HUF',-251460,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:48.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154195964,72472957,4,NULL,5463262,0,0,0,'HUF',0,0,0,'HUF',-196936,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:48.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154196288,72472957,4,NULL,6975444,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-29210,0,0,'HUF','SEVA','2012.07.11 11:42:48.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154196488,72472957,4,NULL,8356232,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-635953,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:48.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154196489,72472957,4,NULL,8357354,0,0,0,'HUF',-79429,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:48.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154196562,72472957,4,NULL,8473315,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-1069340,0,0,'HUF','SEVA','2012.07.11 11:42:48.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154196855,72472957,4,NULL,10637619,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-260350,0,0,'HUF',-31750,0,0,'HUF',0,0,0,'HUF',-1009834,0,0,'HUF','SEVA','2012.07.11 11:42:48.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154196859,72472957,4,NULL,10645554,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-2994723,0,0,'HUF','SEVA','2012.07.11 11:42:48.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154196942,72472957,4,NULL,14413268,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-537966,0,0,'HUF','SEVA','2012.07.11 11:42:48.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154196997,72472957,4,NULL,16940551,0,0,0,'HUF',-1016,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:48.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154197121,72472957,4,NULL,19053644,0,0,0,'HUF',0,0,0,'HUF',-838889,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-1697013,0,0,'HUF','SEVA','2012.07.11 11:42:48.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154197196,72472957,4,NULL,19883046,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-577960,0,0,'HUF','SEVA','2012.07.11 11:42:48.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154197252,72472957,4,NULL,20767175,0,0,0,'HUF',-927948,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:48.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154197253,72472957,4,NULL,20985273,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-292100,0,0,'HUF','SEVA','2012.07.11 11:42:48.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154197276,72472957,4,NULL,21760596,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-8500,0,0,'HUF','SEVA','2012.07.11 11:42:48.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154197309,72472957,4,NULL,22075259,0,0,0,'HUF',-113632,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:48.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154197310,72472957,4,NULL,22075308,-84500,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:48.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154197362,72472957,4,NULL,22766463,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-2365375,0,0,'HUF','SEVA','2012.07.11 11:42:48.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154197451,72472957,4,NULL,23333118,0,0,0,'HUF',0,0,0,'HUF',-1074992,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-1315689,0,0,'HUF','SEVA','2012.07.11 11:42:48.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154197687,72472957,4,NULL,25974904,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-533400,0,0,'HUF','SEVA','2012.07.11 11:42:48.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154197899,72472957,4,NULL,32523417,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-250000,0,0,'HUF','SEVA','2012.07.11 11:42:48.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154197965,72472957,4,NULL,32693837,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-1351598,0,0,'HUF','SEVA','2012.07.11 11:42:48.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154198968,72472957,4,NULL,37856878,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-232336,0,0,'HUF','SEVA','2012.07.11 11:42:49.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154199353,72472957,4,NULL,38258595,0,0,0,'HUF',-61090,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:49.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154200009,72472957,4,NULL,41108038,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-101346,0,0,'HUF','SEVA','2012.07.11 11:42:49.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154200521,72472957,4,NULL,42605207,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-1244727,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:49.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154200575,72472957,4,NULL,45141618,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-11487,0,0,'HUF','SEVA','2012.07.11 11:42:49.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154200976,72472957,4,NULL,47986372,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-533400,0,0,'HUF','SEVA','2012.07.11 11:42:49.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154201222,72472957,4,NULL,48391634,0,0,0,'HUF',-137526,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:49.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154201769,72472957,4,NULL,49822715,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-76200,0,0,'HUF','SEVA','2012.07.11 11:42:49.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154201911,72472957,4,NULL,50567490,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-40625,0,0,'HUF','SEVA','2012.07.11 11:42:49.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154202435,72472957,4,NULL,53616685,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-3493344,0,0,'HUF','SEVA','2012.07.11 11:42:50.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154202622,72472957,4,NULL,58094847,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-308726,0,0,'HUF','SEVA','2012.07.11 11:42:50.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154202702,72472957,4,NULL,58400388,0,0,0,'HUF',-171704,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:50.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154202750,72472957,4,NULL,63408605,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-114249,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF','SEVA','2012.07.11 11:42:50.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154202763,72472957,4,NULL,68278494,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-152400,0,0,'HUF','SEVA','2012.07.11 11:42:50.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154202783,72472957,4,NULL,69204553,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-91440,0,0,'HUF','SEVA','2012.07.11 11:42:50.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154203430,72472957,4,NULL,71858201,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-139446,0,0,'HUF','SEVA','2012.07.11 11:42:50.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154203550,72472957,4,NULL,72385783,0,0,0,'HUF',0,0,0,'HUF',-2789555,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-2144395,0,0,'HUF','SEVA','2012.07.11 11:42:50.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154203649,72472957,4,NULL,72722818,0,0,0,'HUF',0,0,0,'HUF',-891667,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-219316,0,0,'HUF','SEVA','2012.07.11 11:42:50.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154203929,72472957,4,NULL,73852324,0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',0,0,0,'HUF',-9525,0,0,'HUF','SEVA','2012.07.11 11:42:50.000','SEVA','2012.07.11 11:42:55.000'); + INSERT INTO CO_CASHFLOW_T(ID,F_ID,SZINT,MIN_KOD,U_ID,T0,K0,U0,D0,T1,K1,U1,D1,T2,K2,U2,D2,T3,K3,U3,D3,T4,K4,U4,D4,T5,K5,U5,D5,T6,K6,U6,D6,CRU,CRD,LMU,LMD)VALUES(154204030,72472957,0,NULL,0,-371560,2200,0,'HUF',-3522648,0,0,'HUF',-7934348,0,0,'HUF',-3444084,0,0,'HUF',-4011190,0,0,'HUF',-1868666,0,0,'HUF',-61820720,0,0,'HUF','SEVA','2012.07.11 11:42:55.000',NULL,NULL); + END + ^ + set term ;^ + rollback; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.3') +def test_core_4113_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_4114.py b/tests/bugs/test_core_4114.py new file mode 100644 index 00000000..a812e797 --- /dev/null +++ b/tests/bugs/test_core_4114.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_4114 +# title: SIMILAR TO does not work with x-prefixed literals +# decription: +# Checked on: +# 2.5.9.27115: OK, 1.390s. +# 3.0.4.32972: OK, 3.594s. +# 4.0.0.1201: OK, 2.875s. +# +# tracker_id: CORE-4114 +# min_versions: ['2.5'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select + iif(' ' similar to '[[:WHITESPACE:]]', 'T', 'F') as f1, + iif(_win1252 x'20' similar to '[[:WHITESPACE:]]', 'T', 'F') as f2, + iif(_win1252 x'20' similar to '%', 'T', 'F') as f3 + from RDB$DATABASE ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F1 T + F2 T + F3 T + """ + +@pytest.mark.version('>=2.5.0') +def test_core_4114_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4115.py b/tests/bugs/test_core_4115.py new file mode 100644 index 00000000..7a5f3bb0 --- /dev/null +++ b/tests/bugs/test_core_4115.py @@ -0,0 +1,624 @@ +#coding:utf-8 +# +# id: bugs.core_4115 +# title: EXECUTE BLOCK execution cause server crash +# decription: +# Confirmed lost of connection (but *not* crash) on 2.5.2.26540. +# Last lines in trace: +# INSERT INTO PU_BTET(ID,PBIZ_ID,... )VALUES(1711941,1559865, ...); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,... +# (i.e. it occurs when performing EXECUTE BLOCK) +# STDERR contains: +# Statement failed, SQLSTATE = 08006 +# Unable to complete network request to host "localhost". +# -Error reading data from the connection. +# No such problem on 2.5.7.27050 +# +# 02-mar-2021. Re-implemented in order to have ability to run this test on Linux. +# Ttest 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 = WIN1250 and perform needed DML. +# Result will be redirected to .log which will be opened via codecs.open(...encoding='cp1250'). +# Its content will be converted to UTF8 for showing in expected_stdout. +# +# Checked on: +# * Windows: 4.0.0.2377, 3.0.8.33420, 2.5.9.27152 +# * Linux: 4.0.0.2377, 3.0.8.33415 +# +# tracker_id: CORE-4115 +# min_versions: ['2.5.7'] +# versions: 2.5.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='WIN1250', sql_dialect=1, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import codecs +# import subprocess +# import time +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# # Code to be executed further in separate ISQL process: +# ############################# +# sql_txt=''' set bail on; +# set names WIN1250; +# connect '%(dsn)s' user '%(user_name)s' password '%(user_password)s'; +# +# create domain xadoszam as varchar(20); +# create domain xarf10 as numeric(15, 10); +# create domain xarf10n as numeric(15, 10) not null; +# create domain xarfoly as numeric(15, 4); +# create domain xbinary as blob sub_type 0 segment size 80; +# create domain xblnev as varchar(15); +# create domain xcrcn as varchar(30) not null; +# create domain xcrdn as timestamp not null; +# create domain xcrsn as varchar(30) not null; +# create domain xcrun as varchar(30) not null; +# create domain xdat as timestamp; +# create domain xdatum as timestamp; +# create domain xdatumn as timestamp not null; +# create domain xdnem as varchar(3); +# create domain xegysn as numeric(15, 4) not null; +# create domain xert as numeric(15, 2); +# create domain xert10 as numeric(15, 10); +# create domain xert4 as numeric(15, 4); +# create domain xert4n as numeric(15, 4) not null; +# create domain xert6 as numeric(15, 6); +# create domain xertdev as numeric(15, 4); +# create domain xertdevn as numeric(15, 4) not null; +# create domain xertgy as numeric(15, 2); +# create domain xertn as numeric(15, 2) not null; +# create domain xfloat52 as numeric(5, 2); +# create domain xid as integer; +# create domain xidn as integer not null; +# create domain xiktn as integer not null; +# create domain ximage as blob sub_type 0 segment size 80; +# create domain xinfo as varchar(1000); +# create domain xinfo2 as varchar(2000); +# create domain xint as integer; +# create domain xintn as integer not null; +# create domain xkarfoly as numeric(15, 6); +# create domain xkod as varchar(12); +# create domain xkodn as varchar(12) not null; +# create domain xlmc as varchar(30); +# create domain xlmd as timestamp; +# create domain xlms as varchar(30); +# create domain xlmu as varchar(30); +# create domain xmegj1 as blob sub_type text segment size 80; +# create domain xmegyseg as varchar(6); +# create domain xmenny as numeric(15, 3); +# create domain xmennyn as numeric(15, 3) not null; +# create domain xmeny as numeric(9, 3); +# create domain xnyelv as varchar(2); +# create domain xpfjsz as varchar(34); +# create domain xpidn as integer not null; +# create domain xpoz as integer; +# create domain xreport as blob sub_type text segment size 80; +# create domain xszamlamaszk as varchar(50); +# create domain xszazalek as numeric(6, 2); +# create domain xszazalekn as numeric(6, 2) not null; +# create domain xszla as varchar(9); +# create domain xszlan as varchar(9) not null; +# create domain xszoveg as blob sub_type text segment size 80; +# create domain xszovegn as blob sub_type text segment size 80 not null; +# create domain xtblnev as varchar(15); +# create domain xthnev as varchar(100); +# create domain xthnevn as varchar(100) not null; +# create domain xtimestamp as timestamp; +# create domain xtimestampn as timestamp not null; +# create domain xtort as numeric(15, 4); +# create domain xtortn as numeric(15, 4) not null; +# create domain xtrnevn as varchar(20) not null; +# create domain xvar1 as varchar(1); +# create domain xvar10 as varchar(10); +# create domain xvar100 as varchar(100); +# create domain xvar1000 as varchar(1000); +# create domain xvar10000 as varchar(10000); +# create domain xvar1000n as varchar(1000) not null; +# create domain xvar100n as varchar(100) not null; +# create domain xvar10n as varchar(10) not null; +# create domain xvar11 as varchar(11); +# create domain xvar12 as varchar(12); +# create domain xvar12n as varchar(12) not null; +# create domain xvar13 as varchar(13); +# create domain xvar13n as varchar(13) not null; +# create domain xvar14 as varchar(14); +# create domain xvar140 as varchar(140); +# create domain xvar14n as varchar(14) not null; +# create domain xvar16 as varchar(16); +# create domain xvar1n as varchar(1) not null; +# create domain xvar2 as varchar(2); +# create domain xvar20 as varchar(20); +# create domain xvar200 as varchar(200); +# create domain xvar200n as varchar(200) not null; +# create domain xvar20n as varchar(20) not null; +# create domain xvar24 as varchar(24); +# create domain xvar25 as varchar(25); +# create domain xvar25n as varchar(25) not null; +# create domain xvar2n as varchar(2) not null; +# create domain xvar3 as varchar(3); +# create domain xvar30 as varchar(30); +# create domain xvar300 as varchar(300); +# create domain xvar300n as varchar(300) not null; +# create domain xvar30n as varchar(30) not null; +# create domain xvar32 as varchar(32); +# create domain xvar32000 as varchar(32000); +# create domain xvar34 as varchar(34); +# create domain xvar3n as varchar(3) not null; +# create domain xvar4 as varchar(4); +# create domain xvar40 as varchar(40); +# create domain xvar40n as varchar(40) not null; +# create domain xvar4n as varchar(4) not null; +# create domain xvar5 as varchar(5); +# create domain xvar50 as varchar(50); +# create domain xvar500 as varchar(500); +# create domain xvar500n as varchar(500) not null; +# create domain xvar50n as varchar(50) not null; +# create domain xvar5n as varchar(5) not null; +# create domain xvar6 as varchar(6); +# create domain xvar60n as varchar(60) not null; +# create domain xvar63 as varchar(63); +# create domain xvar6n as varchar(6) not null; +# create domain xvar70 as varchar(70); +# create domain xvar70n as varchar(70) not null; +# create domain xvar7n as varchar(7) not null; +# create domain xvar8 as varchar(8); +# create domain xvar80 as varchar(80); +# create domain xvar80n as varchar(80) not null; +# create domain xvar8n as varchar(8) not null; +# create domain xvar9 as varchar(9); +# create domain xvert as varchar(8); +# commit work; +# +# create table pu_btet (id xidn, +# pbiz_id xidn, +# gysor xintn, +# tipus xvar1n, +# afa_kulcs xvar5, +# alap xertn, +# ado xertn, +# egys_ar xert4, +# dev_alap xert4, +# dev_ado xert4, +# devegys_ar xert4, +# db xmenny, +# szoveg xvar50, +# megjegyzes xmegj1, +# cru xcrun, +# crd xcrdn, +# lmu xlmu, +# lmd xlmd, +# termek_id xid, +# tjegyz_id xid, +# bto_id xid, +# mert_id xid, +# artip_kod xvar14, +# enged_id xid, +# gysor_tol xint, +# gysor_ig xint, +# afa_ossze xvar1, +# pbtetkapcs xvar5, +# kamozgnem_id xid, +# melleklet_db xint, +# sarzs xvar12, +# lejar xdatum, +# felszab xdatum, +# pu_afatipus_id xid, +# afa_alap xert, +# afa_ado xert, +# afa_akulcs xvar5, +# db2 xmenny, +# mert_id2 xid, +# mert_seged xvar1, +# jutalek xert, +# hull xvar1, +# kod1 xvar40, +# kod2 xvar40, +# kod3 xvar40, +# kod4 xvar40, +# kod5 xvar40, +# eloleg_biz_id xid, +# lista_ar xert4, +# egys_ar_diff xert4, +# pu_ar_id xid, +# akcio_szazalek xszazalek, +# akciozott_ar xert4, +# pu_mn_id xid, +# afa_szla xszla, +# afa_eszla xszla, +# afa_minosit1 xkod, +# afa_minosit2 xkod, +# bado xert, +# balap xert, +# bdev xvar3, +# barf xarf10, +# ef_alap xert, +# ef_ado xert, +# ef_egys_ar xert4, +# ef_dev_alap xert, +# ef_dev_ado xert, +# ef_dev_egys_ar xert4, +# ef_szazalek xert, +# malap xert, +# mado xert, +# mdev xdnem, +# marfdatum xdatum, +# idoszakszla_datum xvar50, +# tovabbszamla_ugyf_id xid, +# telj xdatum, +# telj_arfolyam xarf10, +# szarmhely xvar2, +# ktrk_kod xvar20, +# richtextmegj xszoveg, +# db_keszlet xmenny, +# mert_id_keszlet xid, +# auto_arfkul_eloleg_btet_id xid, +# szallitojegy_szam xvar20); +# set term ^ ; +# +# create trigger insertpu_btet for pu_btet inactive before insert position 0 +# as begin +# new.cru = user; +# new.crd = 'now'; +# end^ +# +# create trigger updatepu_btet for pu_btet active before update position 0 +# as begin +# new.lmu = user; +# new.lmd = 'now'; +# end^ +# set term ;^ +# commit work; +# +# set term ^; +# execute block as +# begin +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712188,1560100,1,'N','15',59424,8914,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712187,1560099,1,'N','15',5467,820,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712186,1560098,1,'N','15',12991,1949,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712185,1560097,1,'N','15',30145,4522,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712184,1560096,1,'N','15',6455,968,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712183,1560095,1,'N','15',28020,4203,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712182,1560094,1,'N','15',4630,694,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712181,1560093,1,'N','15',36930,5540,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712180,1560092,1,'N','15',10734,1610,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712179,1560091,1,'N','15',3292,494,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712178,1560090,1,'N','15',27993,4199,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712177,1560089,1,'N','15',3195,479,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712176,1560088,1,'N','15',6520,978,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712175,1560087,1,'N','15',12399,1860,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712174,1560086,1,'N','15',17525,2629,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712173,1560085,1,'N','15',27000,4050,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712172,1560084,1,'N','15',28982,4347,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712171,1560083,1,'N','15',62384,9358,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712170,1560082,1,'N','15',29794,4469,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712169,1560081,1,'N','15',38982,5847,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712168,1560080,1,'N','15',32526,4879,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712167,1560079,1,'N','15',37630,5645,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712166,1560078,1,'N','15',3390,509,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712165,1560077,1,'N','15',75737,11361,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712164,1560076,1,'N','15',24257,3639,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712163,1560075,1,'N','15',44000,6600,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712162,1560074,1,'N','15',65663,9849,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712161,1560073,1,'N','15',33673,5051,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712160,1560072,1,'N','15',14943,2242,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712159,1560071,1,'N','15',4127,619,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712158,1560070,1,'N','15',35404,5311,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712157,1560069,1,'N','15',33337,5000,0,0,0,'2507-2511','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712156,1560068,1,'N','15',65810,9872,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712155,1560067,1,'N','25',84931,21233,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712154,1560066,1,'N','25',35486,8872,0,0,0,'656121,122','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712153,1560065,1,'N','25',46162,11541,0,0,0,'53479','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712152,1560064,1,'N','25',17183,4296,0,0,0,'700301,304','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712151,1560063,1,'N','25',38130,9532,0,0,0,'700117,700296','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712150,1560062,1,'N','25',48936,12234,0,0,0,'428','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712149,1560061,1,'N','25',38138,9534,0,0,0,'54431','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712148,1560060,1,'N','25',39791,9948,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712147,1560059,1,'N','25',92128,23032,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712146,1560058,1,'N','25',19069,4767,0,0,0,'429','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712145,1560057,1,'N','15',41340,6201,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712144,1560056,1,'N','15',76320,11448,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712143,1560055,1,'N','15',41460,6219,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712142,1560054,1,'N','25',20750,5188,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712141,1560053,1,'N','25',4152,1038,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712140,1560052,1,'N','25',240,60,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712139,1560051,1,'N','25',43223,10806,0,0,0,'53435','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712138,1560050,1,'N','25',9818,2455,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712137,1560049,1,'N','25',65693,16423,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712136,1560048,1,'N','25',36700,9175,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712135,1560047,1,'N','15',5534,830,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712134,1560046,1,'N','25',1550,388,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712133,1560045,1,'N','15',9036,1355,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712132,1560044,1,'N','25',12039,3010,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712131,1560043,1,'N','25',20280,5070,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712130,1560042,1,'N','15',124416,18662,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712129,1560041,1,'N','25',8420,2105,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712128,1560040,1,'N','25',78348,19587,0,0,0,'997915.602576','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712127,1560039,1,'N','25',7300,1825,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712126,1560038,1,'N','25',6393,1598,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712125,1560037,1,'N','25',8200,2050,0,0,0,'997916.602575','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712124,1560036,1,'N','25',46660,11665,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712123,1560035,1,'N','25',3228,807,0,0,0,'997917.602574','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712122,1560034,1,'N','15',303913,45587,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712121,1560033,1,'N','25',2032100,508025,0,0,0,'807851','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712120,1560032,1,'N','15',33571,5036,0,0,0,'61124-126','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712119,1560031,1,'N','25',40825,10206,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712118,1560030,1,'N','15',38106,5716,0,0,0,'128-130','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712117,1560029,1,'N','15',21545,3232,0,0,0,'2512','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712116,1560028,1,'N','25',30798,7700,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712115,1560027,2,'N','25',8588,2147,0,0,0,'28758','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712114,1560027,1,'N','15',20753,3113,0,0,0,'28758','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712113,1560026,2,'N','25',42716,10679,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712112,1560026,1,'N','15',31593,4739,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712111,1560025,1,'N','25',58080,14520,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712110,1560024,2,'N','25',11536,2884,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712109,1560024,1,'N','15',65790,9869,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712108,1560023,1,'N','25',42028,10507,0,0,0,'707335.708232','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712107,1560022,1,'N','15',216186,32428,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712106,1560021,1,'N','15',14112,2117,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712105,1560020,1,'N','15',26591,3989,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712104,1560019,1,'N','25',13980,3495,0,0,0,'708234','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712103,1560018,1,'N','25',172058,43015,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712102,1560017,1,'N','25',40842,10211,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712101,1560016,1,'N','25',248637,62159,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712100,1560015,2,'N','25',133760,33440,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712099,1560015,1,'N','15',527385,79108,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712098,1560014,1,'N','25',511560,127890,0,0,0,'3522','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712097,1560013,1,'N','15',7507,1126,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712096,1560012,1,'N','15',22440,3366,0,0,0,'28634','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712095,1560011,1,'N','25',29237,7309,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712094,1560010,1,'N','15',12647,1897,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712093,1560009,1,'N','15',52600,7890,0,0,0,'75098-99','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712092,1560008,1,'N','25',357092,89273,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712091,1560007,1,'N','15',44649,6697,0,0,0,'75094-5.75092','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712090,1560006,1,'N','15',22651,3398,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712089,1560005,1,'N','15',46998,7050,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712088,1560004,2,'N','25',98323,24581,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712087,1560004,1,'N','15',302600,45390,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712086,1560003,1,'N','15',95588,14338,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712085,1560002,1,'N','15',106649,15997,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712084,1560001,1,'N','15',290751,43613,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:13.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712083,1560000,1,'N','15',96480,14472,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712082,1559999,1,'N','15',54363,8155,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712081,1559998,1,'N','15',109602,16440,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712080,1559997,1,'N','25',986468,246617,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712079,1559996,1,'N','15',51440,7716,0,0,0,'15077,079','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712078,1559995,1,'N','15',61132,9170,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712077,1559994,1,'N','15',71938,10791,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712076,1559993,2,'N','25',357860,89465,0,0,0,'11916','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712075,1559993,1,'N','15',194888,29233,0,0,0,'11916','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712074,1559992,1,'N','15',70543,10581,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712073,1559991,1,'N','15',232673,34901,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712072,1559990,1,'N','15',67939,10191,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712071,1559989,1,'N','15',67430,10114,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712070,1559988,1,'N','15',257317,38597,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712069,1559987,1,'N','15',63028,9454,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712068,1559986,1,'N',' 5',52895,2645,0,0,0,'17559-560','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712067,1559985,1,'N','25',186876,46719,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712066,1559984,1,'N','15',49979,7497,0,0,0,'23025.28','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712065,1559983,1,'N','15',940004,141001,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712064,1559982,1,'N','15',36301,5445,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712063,1559981,1,'N','15',59507,8926,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712062,1559980,1,'N','15',107136,16070,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712061,1559979,1,'N','25',357696,89424,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712060,1559978,1,'N','15',15251,2288,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712059,1559977,2,'N','25',137352,34338,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712058,1559977,1,'N','15',29920,4488,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712057,1559976,1,'N','15',57186,8578,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712056,1559975,1,'N','25',176048,44012,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712055,1559974,1,'N','15',18968,2845,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712054,1559973,1,'N','15',53789,8068,0,0,0,'61318-320','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712053,1559972,1,'N','15',22820,3423,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712052,1559971,1,'N','15',35130,5270,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712051,1559970,1,'N','15',55930,8390,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712050,1559969,1,'N','15',338290,50743,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712049,1559968,1,'N','15',13678,2052,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712048,1559967,1,'N','15',159118,23868,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712047,1559966,1,'N','15',32627,4894,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712046,1559965,1,'N','15',12000,1800,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712045,1559964,1,'N','15',42680,6402,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712044,1559963,1,'N','15',22775,3416,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712043,1559962,1,'N','15',53105,7966,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712042,1559961,1,'N','25',32469,8117,0,0,0,'45618,620','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712041,1559960,1,'N','15',130094,19514,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712040,1559959,1,'N','15',14701,2205,0,0,0,'52361','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712039,1559958,1,'N','15',12912,1937,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1712038,1559957,1,'N','NK',10662,0,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712037,1559956,1,'N','15',27643,4146,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712036,1559955,2,'N','NK',14216,0,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712035,1559955,1,'N','25',799,200,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712034,1559954,2,'N','NK',30517,0,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712033,1559954,1,'N','25',400,100,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712032,1559953,2,'N','NK',56586,0,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712031,1559953,1,'N','25',1199,300,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1712030,1559952,1,'N','NK',10662,0,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1712029,1559951,1,'N','NK',24427,0,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1712028,1559950,1,'N','NK',45391,0,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712027,1559949,1,'N','15',81129,12169,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712026,1559948,1,'N','15',79560,11934,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712025,1559947,1,'N','15',14364,2155,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712024,1559946,1,'N','15',11522,1728,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712023,1559945,1,'N','15',28106,4216,0,0,0,'20546,549','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712022,1559944,1,'N','15',622689,93403,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712021,1559943,1,'N','15',58940,8841,0,0,0,'20540-41','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712020,1559942,1,'N','15',34094,5114,0,0,0,'20574-575','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712019,1559941,1,'N','15',31861,4779,0,0,0,'2518-22','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712018,1559940,1,'N','15',23012,3452,0,0,0,'2513-16','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712017,1559939,1,'N','25',40570,10142,0,0,0,'401922-926','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712016,1559938,1,'N','25',33346,8336,0,0,0,'401918-920','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712015,1559937,1,'N','15',91396,13709,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712014,1559936,1,'N','25',10790,2698,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712013,1559935,1,'N','25',108257,27064,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712012,1559934,1,'N','15',2270,341,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712011,1559933,2,'N','25',11076,2769,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712010,1559933,1,'N','15',21260,3189,0,0,0,'NINCS SZÖVEG','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712009,1559932,2,'N','25',7673,1918,0,0,0,'28755,784','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD)VALUES(1712008,1559932,1,'N','15',16161,2424,0,0,0,'28755,784','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000'); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1712007,1559931,1,'N','NK',143734,0,0,0,0,'Bónuszba beszámitva D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1712006,1559930,1,'N','NK',663448,0,0,0,0,'Bónuszba beszámitva D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1712005,1559929,1,'N','NK',401818,0,0,0,0,'Bónuszba beszámitva D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1712004,1559928,1,'N','NK',87800,0,0,0,0,'Bónuszba beszámitva D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1712003,1559927,1,'N','NK',56250,0,0,0,0,'Bónuszba beszámitva D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1712002,1559926,1,'N','NK',307720,0,0,0,0,'Bónuszba beszámitva D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1712001,1559925,1,'N','NK',64338,0,0,0,0,'Bónuszba beszámitva D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1712000,1559924,1,'N','NK',70564,0,0,0,0,'Bónuszba beszámitva D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711999,1559923,1,'N','NK',459,0,0,0,0,'Visszáru szla D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711998,1559922,1,'N','NK',1080,0,0,0,0,'Visszáru szla D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711997,1559921,1,'N','NK',1150,0,0,0,0,'Visszáru szla D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711996,1559920,1,'N','NK',2800,0,0,0,0,'Visszáru szla D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711995,1559919,1,'N','NK',6480,0,0,0,0,'Visszáru szla D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711994,1559918,1,'N','NK',4670,0,0,0,0,'Visszáru szla D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711993,1559917,1,'N','NK',800,0,0,0,0,'Visszáru szla D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711992,1559916,1,'N','NK',15300,0,0,0,0,'Visszáru szla D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711991,1559915,1,'N','NK',523202,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711990,1559914,1,'N','NK',844886,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711989,1559913,1,'N','NK',646060,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711988,1559912,1,'N','NK',2197306,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711987,1559911,1,'N','NK',111715,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711986,1559910,1,'N','NK',6836,0,0,0,0,' D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711985,1559909,1,'N','NK',49479,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711984,1559908,1,'N','NK',337500,0,0,0,0,'Milek D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711983,1559907,1,'N','NK',110850,0,0,0,0,'Milek D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711982,1559906,1,'N','NK',130800,0,0,0,0,'Ergomat D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711981,1559905,1,'N','NK',82992,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711980,1559904,1,'N','NK',128144,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711979,1559903,1,'N','NK',37245,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711978,1559902,1,'N','NK',25374,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711977,1559901,1,'N','NK',132515,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711976,1559900,1,'N','NK',20250,0,0,0,0,'Elektro-top D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711975,1559899,1,'N','NK',37098,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711974,1559898,1,'N','NK',95067,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711973,1559897,1,'N','NK',99276,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711972,1559896,1,'N','NK',119538,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711971,1559895,1,'N','NK',124008,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711970,1559894,1,'N','NK',124356,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711969,1559893,1,'N','NK',221511,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711968,1559892,1,'N','NK',58665,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711967,1559891,1,'N','NK',37446,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711966,1559890,1,'N','NK',70422,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711965,1559889,1,'N','NK',157506,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711964,1559888,1,'N','NK',68310,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711963,1559887,1,'N','NK',87085,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711962,1559886,1,'N','NK',6698,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711961,1559885,1,'N','NK',6698,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711960,1559884,1,'N','NK',6698,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711959,1559883,1,'N','NK',6698,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711958,1559882,1,'N','NK',6698,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711957,1559881,1,'N','NK',6698,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711956,1559880,1,'N','NK',6120,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711955,1559879,1,'N','NK',78091,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711954,1559878,1,'N','NK',67735,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711953,1559877,1,'N','NK',67335,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711952,1559876,1,'N','NK',80344,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711951,1559875,1,'N','NK',1000484,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711950,1559874,1,'N','NK',87634,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711949,1559873,1,'N','NK',73417,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711948,1559872,1,'N','NK',110644,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711947,1559871,1,'N','NK',38715,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711946,1559870,1,'N','NK',185,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711945,1559869,1,'N','NK',498140,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711944,1559868,1,'N','NK',354749,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711943,1559867,1,'N','NK',123206,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711942,1559866,1,'N','NK',47458,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711941,1559865,1,'N','NK',52165,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# INSERT INTO PU_BTET(ID,PBIZ_ID,GYSOR,TIPUS,AFA_KULCS,ALAP,ADO,EGYS_AR,DEVEGYS_AR,DB,SZOVEG,CRU,CRD,LMU,LMD,PU_AFATIPUS_ID)VALUES(1711940,1559864,1,'N','NK',103244,0,0,0,0,'Számla kiegyenlitése D 193','SYSDBA','2005.10.07 07:38:12.000','SYSDBA','2007.06.15 08:47:42.000',1726469); +# end +# ^ +# set term ;^ +# commit; +# +# set list on; +# select count(*) from pu_btet; +# ''' % dict(globals(), **locals()) +# +# f_run_sql = open( os.path.join(context['temp_directory'], 'tmp_4115_win1250.sql'), 'w' ) +# +# # REMOVE INDENTATION IN .SQL to prevent limitation on length of single command (execute block). +# # Write into .sql file each line without leading and trailing spaces, +# # with decoding from utf8 to win1250: +# ##################################### +# for i in sql_txt.split('\\n'): +# f_run_sql.write( ''.join( (i.strip().decode('utf8').encode('cp1250'), '\\n' ) ) ) +# +# flush_and_close( f_run_sql ) +# +# # result: file tmp_3489_win1250.sql is encoded in win1250 +# +# f_run_log = open( os.path.splitext(f_run_sql.name)[0]+'.log', 'w') +# subprocess.call( [ context['isql_path'], '-q', '-i', f_run_sql.name ], +# stdout = f_run_log, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_run_log ) # result: output will be encoded in win1250 +# +# with codecs.open(f_run_log.name, 'r', encoding='cp1250' ) as f: +# result_in_cp1250 = f.readlines() +# +# for i in result_in_cp1250: +# print( i.encode('utf8') ) +# +# # cleanup: +# ########### +# cleanup( (f_run_sql, f_run_log) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + COUNT 249 + """ + +@pytest.mark.version('>=2.5.7') +@pytest.mark.xfail +def test_core_4115_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4117.py b/tests/bugs/test_core_4117.py new file mode 100644 index 00000000..a9f977c3 --- /dev/null +++ b/tests/bugs/test_core_4117.py @@ -0,0 +1,104 @@ +#coding:utf-8 +# +# id: bugs.core_4117 +# title: COMPUTED BY field is evaluated as NULL if used as an exception parameter directly +# decription: Exception with computed by field as parameter produces error message without this field value if this field is not a part of excpression +# tracker_id: CORE-4117 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [('line: [0-9]+, col: [0-9]+', '')] + +init_script_1 = """ + recreate table test1 (id int not null, c computed by (id * 10)); + recreate table test2 (id int not null, c computed by (id * 10)); + commit; + + set term ^; + execute block as + begin + begin + execute statement 'drop exception ex_bad_computed_field_value'; + when any do begin end + end + end + ^ + set term ;^ + commit; + + create exception ex_bad_computed_field_value ''; + commit; + insert into test1 (id) values (1); + insert into test2 (id) values (1); + commit; + + -- 1. exception with computed by field as parameter + set term ^; + create or alter trigger test1_bu for test1 active before update position 0 as + begin + exception ex_bad_computed_field_value new.c; + end + ^ + set term ;^ + commit; + + -- 2. exception with computed by field as a part of expression + set term ^; + create or alter trigger test2_bu for test2 active before update position 0 as + begin + exception ex_bad_computed_field_value new.c + 0; -- any expression + end + ^ + set term ;^ + commit; + + -- Confirmed on 2.5.2: statement update test1 ... will raise exception WITHOUT value: + -- Statement failed, SQLSTATE = 42000 + -- exception 1 + -- -EX_BAD_COMPUTED_FIELD_VALUE + -- -At trigger 'TEST1_BU' line: 3, col: 7 + + -- Compare with 2.5.5: + -- Statement failed, SQLSTATE = 42000 + -- exception 2 + -- -EX_BAD_COMPUTED_FIELD_VALUE + -- -20 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< this is added here <<<<<<<<<<<<< + -- -At trigger 'TEST1_BU' line: 3, col: 7 + + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + update test1 set id = 2; + update test2 set id = 2; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = HY000 + exception 1 + -EX_BAD_COMPUTED_FIELD_VALUE + -20 + -At trigger 'TEST1_BU' line: 3, col: 7 + Statement failed, SQLSTATE = HY000 + exception 1 + -EX_BAD_COMPUTED_FIELD_VALUE + -20 + -At trigger 'TEST2_BU' line: 3, col: 7 + """ + +@pytest.mark.version('>=2.5.3') +def test_core_4117_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_4118.py b/tests/bugs/test_core_4118.py new file mode 100644 index 00000000..0525df2d --- /dev/null +++ b/tests/bugs/test_core_4118.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: bugs.core_4118 +# title: Expression index may be not used for derived fields or view fields +# decription: +# tracker_id: CORE-4118 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table t (id int, d timestamp); +create index itd on t computed (cast(d as date)); +COMMIT; +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """SQL> +PLAN (T INDEX (ITD)) +SQL> +PLAN (T INDEX (ITD)) +SQL>""" + +@pytest.mark.version('>=2.5.3') +def test_core_4118_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4119.py b/tests/bugs/test_core_4119.py new file mode 100644 index 00000000..3c46a56a --- /dev/null +++ b/tests/bugs/test_core_4119.py @@ -0,0 +1,136 @@ +#coding:utf-8 +# +# id: bugs.core_4119 +# title: Metadata source becomes wrong after twice transliteration to the metadata charset +# decription: +# Could not find 3.0 Initial. +# Checked on 3.0.0.31374 Beta1 - all OK. +# +# 02-mar-2021. Re-implemented in order to have ability to run this test on Linux. +# Ttest 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 = WIN1251 and perform needed DML. +# Result will be redirected to .log which will be opened via codecs.open(...encoding='cp1251'). +# Its content will be converted to UTF8 for showing in expected_stdout. +# +# Checked on: +# * Windows: 4.0.0.2377, 3.0.8.33420, 2.5.9.27152 +# * Linux: 4.0.0.2377, 3.0.8.33415 +# +# tracker_id: CORE-4119 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(charset='WIN1251', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import codecs +# import subprocess +# import time +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# # Code to be executed further in separate ISQL process: +# ############################# +# sql_txt=''' set bail on; +# set names WIN1251; +# connect '%(dsn)s' user '%(user_name)s' password '%(user_password)s'; +# +# set term ^; +# create procedure myproc as +# begin +# -- Моя процедура +# end^ +# set term ;^ +# show procedure myproc; +# ''' % dict(globals(), **locals()) +# +# f_run_sql = open( os.path.join(context['temp_directory'], 'tmp_4119_win1251.sql'), 'w' ) +# f_run_sql.write( sql_txt.decode('utf8').encode('cp1251') ) +# flush_and_close( f_run_sql ) +# +# # result: file tmp_4119_win1251.sql is encoded in win1251 +# +# f_run_log = open( os.path.splitext(f_run_sql.name)[0]+'.log', 'w') +# subprocess.call( [ context['isql_path'], '-q', '-i', f_run_sql.name ], +# stdout = f_run_log, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_run_log ) # result: output will be encoded in win1251 +# +# with codecs.open(f_run_log.name, 'r', encoding='cp1251' ) as f: +# result_in_cp1251 = f.readlines() +# +# for i in result_in_cp1251: +# print( i.encode('utf8') ) +# +# # cleanup: +# ########### +# cleanup( (f_run_sql, f_run_log) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Procedure text: + ============================================================================= + begin + -- Моя процедура + end + ============================================================================= + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4119_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4122.py b/tests/bugs/test_core_4122.py new file mode 100644 index 00000000..48af764c --- /dev/null +++ b/tests/bugs/test_core_4122.py @@ -0,0 +1,145 @@ +#coding:utf-8 +# +# id: bugs.core_4122 +# title: Metadata export with isql (option -ex) does not export functions properly +# decription: +# tracker_id: CORE-4122 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [("CREATE DATABASE '.*' PAGE_SIZE 4096 DEFAULT CHARACTER SET NONE", "CREATE DATABASE '' PAGE_SIZE 4096 DEFAULT CHARACTER SET NONE")] + +init_script_1 = """ + set term ^ ; + create or alter package PKG_TEST + as + begin + function F_TEST_INSIDE_PKG + returns smallint; + end^ + set term ; ^ + + set term ^ ; + recreate package body PKG_TEST + as + begin + function F_TEST_INSIDE_PKG + returns smallint + as + begin + return 1; + end + end^ + set term ; ^ + + set term ^ ; + create or alter function F_TEST_OUTSIDE_PKG + returns smallint + as + begin + return -1; + end^ + + set term ; ^ + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# # +# runProgram('isql',['-x',dsn,'-user',user_name,'-pass',user_password]) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + SET SQL DIALECT 3; + + /* CREATE DATABASE 'localhost/3330:C:\\FBTESTING\\qa bt-repo mp\\core4122.fdb' PAGE_SIZE 4096 DEFAULT CHARACTER SET NONE; */ + + + COMMIT WORK; + + COMMIT WORK; + SET AUTODDL OFF; + SET TERM ^ ; + + /* Stored functions headers */ + CREATE OR ALTER FUNCTION 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: PKG_TEST, Owner: SYSDBA */ + CREATE PACKAGE 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 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: PKG_TEST, Owner: SYSDBA */ + CREATE PACKAGE BODY PKG_TEST AS + begin + function F_TEST_INSIDE_PKG + returns smallint + as + begin + return 1; + end + end^ + + SET TERM ; ^ + COMMIT WORK; + SET AUTODDL ON; + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4122_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4123.py b/tests/bugs/test_core_4123.py new file mode 100644 index 00000000..b468d7f6 --- /dev/null +++ b/tests/bugs/test_core_4123.py @@ -0,0 +1,470 @@ +#coding:utf-8 +# +# id: bugs.core_4123 +# title: Firebird crash when executing an stored procedure called by a trigger that converts string to upper +# decription: +# Confirmed problem on 2.5.2.26540 when trying convert iso8859_1 `y` with diersis sign to upper: +# Statement failed, SQLSTATE = 22001 +# arithmetic exception, numeric overflow, or string truncation +# -string right truncation +# Checked on 2.5.326780 -- all OK. +# +# 02-mar-2021. Re-implemented in order to have ability to run this test on Linux. +# Test encodes to UTF8 all needed statements (SET NAMES; CONNECT; DDL and DML) and stores this text in .sql file. +# NOTE: 'SET NAMES' contain character set that must be used for reproducing problem (ISO8859_1 in this test). +# Then ISQL is launched in separate (child) process which performs all necessary actions (using required charset). +# Result will be redirected to log(s) which will be opened further via codecs.open(...encoding='iso-8859-1'). +# Finally, its content will be converted to UTF8 for showing in expected_stdout. +# +# Checked on: +# * Windows: 4.0.0.2377, 3.0.8.33420, 2.5.9.27152 +# * Linux: 4.0.0.2377, 3.0.8.33415 +# +# tracker_id: CORE-4123 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import codecs +# import subprocess +# import time +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# # Code to be executed further in separate ISQL process: +# ############################# +# sql_txt=''' set bail on; +# set names iso8859_1; +# connect '%(dsn)s' user '%(user_name)s' password '%(user_password)s'; +# +# set list on; +# with recursive +# d as ( +# select s, char_length(s) n +# from ( +# -- http://www.ic.unicamp.br/~stolfi/EXPORT/www/ISO-8859-1-Encoding.html +# -- ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ +# select 'ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ' as s +# from rdb$database +# ) +# ) +# ,r as(select 1 as i from rdb$database union all select r.i+1 from r where r.i<128) +# ,c as( +# select +# substring(d.s from r.i for 1) as char_as_is +# ,upper( substring(d.s from r.i for 1) ) char_upper +# ,lower( substring(d.s from r.i for 1) ) char_lower +# from d, r +# where r.i <= d.n +# ) +# select c.char_as_is, char_upper, char_lower, iif(char_upper = char_lower, '1',' ') is_upper_equ_lower +# from c +# order by 1 +# ; +# ''' % dict(globals(), **locals()) +# +# f_run_sql = open( os.path.join(context['temp_directory'], 'tmp_4123_iso8859_1.sql'), 'w' ) +# f_run_sql.write( sql_txt.decode('utf8').encode('iso-8859-1') ) +# flush_and_close( f_run_sql ) +# +# # result: file tmp_4123_iso8859_1.sql is encoded in iso8859_1 +# +# f_run_log = open( os.path.splitext(f_run_sql.name)[0]+'.log', 'w') +# subprocess.call( [ context['isql_path'], '-q', '-i', f_run_sql.name ], +# stdout = f_run_log, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_run_log ) # result: output will be encoded in iso8859_1 +# +# with codecs.open(f_run_log.name, 'r', encoding='iso-8859-1' ) as f: +# result_in_iso8859_1 = f.readlines() +# +# for i in result_in_iso8859_1: +# print( i.encode('utf8') ) +# +# # cleanup: +# ########### +# cleanup( (f_run_sql, f_run_log) ) +# +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CHAR_AS_IS À + CHAR_UPPER À + CHAR_LOWER à + IS_UPPER_EQU_LOWER + + CHAR_AS_IS Á + CHAR_UPPER Á + CHAR_LOWER á + IS_UPPER_EQU_LOWER + + CHAR_AS_IS  + CHAR_UPPER  + CHAR_LOWER â + IS_UPPER_EQU_LOWER + + CHAR_AS_IS à + CHAR_UPPER à + CHAR_LOWER ã + IS_UPPER_EQU_LOWER + + CHAR_AS_IS Ä + CHAR_UPPER Ä + CHAR_LOWER ä + IS_UPPER_EQU_LOWER + + CHAR_AS_IS Å + CHAR_UPPER Å + CHAR_LOWER å + IS_UPPER_EQU_LOWER + + CHAR_AS_IS Æ + CHAR_UPPER Æ + CHAR_LOWER æ + IS_UPPER_EQU_LOWER + + CHAR_AS_IS Ç + CHAR_UPPER Ç + CHAR_LOWER ç + IS_UPPER_EQU_LOWER + + CHAR_AS_IS È + CHAR_UPPER È + CHAR_LOWER è + IS_UPPER_EQU_LOWER + + CHAR_AS_IS É + CHAR_UPPER É + CHAR_LOWER é + IS_UPPER_EQU_LOWER + + CHAR_AS_IS Ê + CHAR_UPPER Ê + CHAR_LOWER ê + IS_UPPER_EQU_LOWER + + CHAR_AS_IS Ë + CHAR_UPPER Ë + CHAR_LOWER ë + IS_UPPER_EQU_LOWER + + CHAR_AS_IS Ì + CHAR_UPPER Ì + CHAR_LOWER ì + IS_UPPER_EQU_LOWER + + CHAR_AS_IS Í + CHAR_UPPER Í + CHAR_LOWER í + IS_UPPER_EQU_LOWER + + CHAR_AS_IS Î + CHAR_UPPER Î + CHAR_LOWER î + IS_UPPER_EQU_LOWER + + CHAR_AS_IS Ï + CHAR_UPPER Ï + CHAR_LOWER ï + IS_UPPER_EQU_LOWER + + CHAR_AS_IS Ð + CHAR_UPPER Ð + CHAR_LOWER ð + IS_UPPER_EQU_LOWER + + CHAR_AS_IS Ñ + CHAR_UPPER Ñ + CHAR_LOWER ñ + IS_UPPER_EQU_LOWER + + CHAR_AS_IS Ò + CHAR_UPPER Ò + CHAR_LOWER ò + IS_UPPER_EQU_LOWER + + CHAR_AS_IS Ó + CHAR_UPPER Ó + CHAR_LOWER ó + IS_UPPER_EQU_LOWER + + CHAR_AS_IS Ô + CHAR_UPPER Ô + CHAR_LOWER ô + IS_UPPER_EQU_LOWER + + CHAR_AS_IS Õ + CHAR_UPPER Õ + CHAR_LOWER õ + IS_UPPER_EQU_LOWER + + CHAR_AS_IS Ö + CHAR_UPPER Ö + CHAR_LOWER ö + IS_UPPER_EQU_LOWER + + CHAR_AS_IS × + CHAR_UPPER × + CHAR_LOWER × + IS_UPPER_EQU_LOWER 1 + + CHAR_AS_IS Ø + CHAR_UPPER Ø + CHAR_LOWER ø + IS_UPPER_EQU_LOWER + + CHAR_AS_IS Ù + CHAR_UPPER Ù + CHAR_LOWER ù + IS_UPPER_EQU_LOWER + + CHAR_AS_IS Ú + CHAR_UPPER Ú + CHAR_LOWER ú + IS_UPPER_EQU_LOWER + + CHAR_AS_IS Û + CHAR_UPPER Û + CHAR_LOWER û + IS_UPPER_EQU_LOWER + + CHAR_AS_IS Ü + CHAR_UPPER Ü + CHAR_LOWER ü + IS_UPPER_EQU_LOWER + + CHAR_AS_IS Ý + CHAR_UPPER Ý + CHAR_LOWER ý + IS_UPPER_EQU_LOWER + + CHAR_AS_IS Þ + CHAR_UPPER Þ + CHAR_LOWER þ + IS_UPPER_EQU_LOWER + + CHAR_AS_IS ß + CHAR_UPPER ß + CHAR_LOWER ß + IS_UPPER_EQU_LOWER 1 + + CHAR_AS_IS à + CHAR_UPPER À + CHAR_LOWER à + IS_UPPER_EQU_LOWER + + CHAR_AS_IS á + CHAR_UPPER Á + CHAR_LOWER á + IS_UPPER_EQU_LOWER + + CHAR_AS_IS â + CHAR_UPPER  + CHAR_LOWER â + IS_UPPER_EQU_LOWER + + CHAR_AS_IS ã + CHAR_UPPER à + CHAR_LOWER ã + IS_UPPER_EQU_LOWER + + CHAR_AS_IS ä + CHAR_UPPER Ä + CHAR_LOWER ä + IS_UPPER_EQU_LOWER + + CHAR_AS_IS å + CHAR_UPPER Å + CHAR_LOWER å + IS_UPPER_EQU_LOWER + + CHAR_AS_IS æ + CHAR_UPPER Æ + CHAR_LOWER æ + IS_UPPER_EQU_LOWER + + CHAR_AS_IS ç + CHAR_UPPER Ç + CHAR_LOWER ç + IS_UPPER_EQU_LOWER + + CHAR_AS_IS è + CHAR_UPPER È + CHAR_LOWER è + IS_UPPER_EQU_LOWER + + CHAR_AS_IS é + CHAR_UPPER É + CHAR_LOWER é + IS_UPPER_EQU_LOWER + + CHAR_AS_IS ê + CHAR_UPPER Ê + CHAR_LOWER ê + IS_UPPER_EQU_LOWER + + CHAR_AS_IS ë + CHAR_UPPER Ë + CHAR_LOWER ë + IS_UPPER_EQU_LOWER + + CHAR_AS_IS ì + CHAR_UPPER Ì + CHAR_LOWER ì + IS_UPPER_EQU_LOWER + + CHAR_AS_IS í + CHAR_UPPER Í + CHAR_LOWER í + IS_UPPER_EQU_LOWER + + CHAR_AS_IS î + CHAR_UPPER Î + CHAR_LOWER î + IS_UPPER_EQU_LOWER + + CHAR_AS_IS ï + CHAR_UPPER Ï + CHAR_LOWER ï + IS_UPPER_EQU_LOWER + + CHAR_AS_IS ð + CHAR_UPPER Ð + CHAR_LOWER ð + IS_UPPER_EQU_LOWER + + CHAR_AS_IS ñ + CHAR_UPPER Ñ + CHAR_LOWER ñ + IS_UPPER_EQU_LOWER + + CHAR_AS_IS ò + CHAR_UPPER Ò + CHAR_LOWER ò + IS_UPPER_EQU_LOWER + + CHAR_AS_IS ó + CHAR_UPPER Ó + CHAR_LOWER ó + IS_UPPER_EQU_LOWER + + CHAR_AS_IS ô + CHAR_UPPER Ô + CHAR_LOWER ô + IS_UPPER_EQU_LOWER + + CHAR_AS_IS õ + CHAR_UPPER Õ + CHAR_LOWER õ + IS_UPPER_EQU_LOWER + + CHAR_AS_IS ö + CHAR_UPPER Ö + CHAR_LOWER ö + IS_UPPER_EQU_LOWER + + CHAR_AS_IS ÷ + CHAR_UPPER ÷ + CHAR_LOWER ÷ + IS_UPPER_EQU_LOWER 1 + + CHAR_AS_IS ø + CHAR_UPPER Ø + CHAR_LOWER ø + IS_UPPER_EQU_LOWER + + CHAR_AS_IS ù + CHAR_UPPER Ù + CHAR_LOWER ù + IS_UPPER_EQU_LOWER + + CHAR_AS_IS ú + CHAR_UPPER Ú + CHAR_LOWER ú + IS_UPPER_EQU_LOWER + + CHAR_AS_IS û + CHAR_UPPER Û + CHAR_LOWER û + IS_UPPER_EQU_LOWER + + CHAR_AS_IS ü + CHAR_UPPER Ü + CHAR_LOWER ü + IS_UPPER_EQU_LOWER + + CHAR_AS_IS ý + CHAR_UPPER Ý + CHAR_LOWER ý + IS_UPPER_EQU_LOWER + + CHAR_AS_IS þ + CHAR_UPPER Þ + CHAR_LOWER þ + IS_UPPER_EQU_LOWER + + CHAR_AS_IS ÿ + CHAR_UPPER ÿ + CHAR_LOWER ÿ + IS_UPPER_EQU_LOWER 1 + """ + +@pytest.mark.version('>=2.5.3') +@pytest.mark.xfail +def test_core_4123_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4125.py b/tests/bugs/test_core_4125.py new file mode 100644 index 00000000..57795af9 --- /dev/null +++ b/tests/bugs/test_core_4125.py @@ -0,0 +1,67 @@ +#coding:utf-8 +# +# id: bugs.core_4125 +# title: Using COLLATE UNICODE_CI_AI in WHERE clause (not indexed) is extremely slow +# decription: +# tracker_id: CORE-4125 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create or alter view test as + with recursive + r as (select 0 i from rdb$database union all select r.i+1 from r where r.i<98) + select cast(r1.i*100 + r0.i as varchar(10)) as fx + from r r1, r r0; + commit; + """ + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Checked on 2.5.1: ratio = ~105, on 2.5.2: ~132, since 2.5.3: ~1. + set list on; + set term ^; + execute block returns(result varchar(50) ) as + declare t0 timestamp; + declare t1 timestamp; + declare t2 timestamp; + declare n int; + declare r numeric(18,3); + begin + t0='now'; + select count(*) from test where fx collate unicode_ci like '%8%' into n; + t1='now'; + select count(*) from test where fx collate unicode_ci_ai like '%8%' into n; + t2='now'; + n = datediff(millisecond from t1 to t2); + r = 1.000 * n / nullif(datediff(millisecond from t0 to t1), 0); + if (r is null and n < 100 or r <= 5) then result = 'TIME RATIO IS OK.'; + else result = 'BAD RATIO: '||coalesce(r,' > 100 vs 0.'); + + suspend; + end + ^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT TIME RATIO IS OK. + """ + +@pytest.mark.version('>=2.5.3') +def test_core_4125_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4126.py b/tests/bugs/test_core_4126.py new file mode 100644 index 00000000..9ef3014c --- /dev/null +++ b/tests/bugs/test_core_4126.py @@ -0,0 +1,300 @@ +#coding:utf-8 +# +# id: bugs.core_4126 +# title: gbak -r fails in restoring all stored procedures/functions in packages +# decription: +# Test creates table and procedure + function - both standalone and packaged. +# Then we do (with saving result in logs): +# 1) checking query; +# 2) isql -x +# After this we try to backup and restore - STDERR should be empty. +# Finally, we try again to run checking query and extract metadata - and compare +# their result with previously stored one. +# Difference between them should be EMPTY with excluding name of databases. +# +# tracker_id: CORE-4126 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('CREATE DATABASE.*', 'CREATE DATABASE'), ('CREATE COLLATION .*', 'CREATE COLLATION')] + +init_script_1 = """ + create or alter procedure p01 as begin end; + create or alter function f01() returns int as begin end; + recreate package pg_01 as begin end; + commit; + + recreate table test (x smallint); + commit; + + set term ^; + execute block as + begin + begin + execute statement 'drop domain dm_nums'; + when any do begin end + end + begin + execute statement 'drop collation nums_coll'; + when any do begin end + end + end + ^ + set term ;^ + commit; + + create collation nums_coll for utf8 from unicode case insensitive 'NUMERIC-SORT=1'; + create domain dm_nums as varchar(10) character set utf8 collate nums_coll; + commit; + + recreate table test (id int, s dm_nums); + commit; + + set term ^; + create or alter procedure p01(a_id int) returns (o_s type of dm_nums ) as + begin + for select reverse(s) from test where id = :a_id into o_s do suspend; + end + ^ + create or alter function f01(a_id int) returns dm_nums as + begin + return reverse((select s from test where id = :a_id)); + end + ^ + recreate package pg_01 as + begin + procedure p01(a_id int) returns (o_s type of dm_nums ); + function f01(a_id int) returns dm_nums; + end + ^ + create package body pg_01 as + begin + procedure p01(a_id int) returns (o_s type of dm_nums ) as + begin + for select s from test where id = :a_id into o_s do suspend; + end + function f01(a_id int) returns dm_nums as + begin + return (select s from test where id = :a_id); + end + end + ^ + set term ;^ + commit; + + insert into test(id, s) values(1, '1234'); + insert into test(id, s) values(2, '125'); + insert into test(id, s) values(3, '16'); + commit; + + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# import difflib +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_file=db_conn.database_name +# db_conn.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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# tmpfbk1=os.path.join(context['temp_directory'],'tmp_4126.fbk') +# if os.path.isfile(tmpfbk1): +# os.remove(tmpfbk1) +# +# tmpfdb1=os.path.join(context['temp_directory'],'tmp_4126.fdb') +# if os.path.isfile(tmpfdb1): +# os.remove(tmpfdb1) +# +# dml_test = ''' set list on; +# +# select t.id, p.o_s as standalone_proc_result +# from test t left join p01(t.id) p on 1=1 +# order by 2; +# +# select t.id, f01(t.id) as standalone_func_result from test t +# order by 2; +# +# select t.id, p.o_s as packaged_proc_result +# from test t left join pg_01.p01(t.id) p on 1=1 +# order by 2; +# +# select t.id, pg_01.f01(t.id) as packaged_func_result from test t +# order by 2; +# ''' +# fbb='' +# +# +# # FIRST RUN DML_TEST +# #################### +# +# f_run_dml_sql = open( os.path.join(context['temp_directory'],'tmp_4126_dml.sql'), 'w') +# f_run_dml_sql.write(dml_test) +# flush_and_close( f_run_dml_sql ) +# +# f_run_dml_log_1 = open( os.path.join(context['temp_directory'],'tmp_4126_dml_1.log'), 'w') +# subprocess.call( [context['isql_path'], dsn, "-i", f_run_dml_sql.name, "-ch", "utf8" ], +# stdout = f_run_dml_log_1, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_run_dml_log_1 ) +# +# +# # EXTRACT METADATA-1 +# #################### +# +# f_extract_meta1_sql = open( os.path.join(context['temp_directory'],'tmp_4126_meta1.log'), 'w') +# subprocess.call( [context['isql_path'], dsn, "-x"], +# stdout = f_extract_meta1_sql, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_extract_meta1_sql ) +# +# # TRY TO BACKUP AND RESTORE +# ########################### +# +# f_backup_log=open( os.path.join(context['temp_directory'],'tmp_4126_backup.log'), "w") +# f_backup_err=open( os.path.join(context['temp_directory'],'tmp_4126_backup.err'), "w") +# +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_backup", "verbose", +# "dbname", db_file, +# "bkp_file", tmpfbk1 +# ], +# stdout=f_backup_log, stderr=f_backup_err) +# flush_and_close( f_backup_log ) +# flush_and_close( f_backup_err ) +# +# f_restore_log=open( os.path.join(context['temp_directory'],'tmp_4126_restore.log'), "w") +# f_restore_err=open( os.path.join(context['temp_directory'],'tmp_4126_restore.err'), "w") +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_restore", "res_replace", "verbose", +# "bkp_file", tmpfbk1, +# "dbname", tmpfdb1 +# ], +# stdout=f_restore_log, stderr=f_restore_err) +# flush_and_close( f_restore_log ) +# flush_and_close( f_restore_err ) +# +# # EXTRACT METADATA-2 +# #################### +# +# f_extract_meta2_sql = open( os.path.join(context['temp_directory'],'tmp_4126_meta2.log'), 'w') +# subprocess.call( [context['isql_path'], 'localhost:'+tmpfdb1, "-x"], +# stdout = f_extract_meta2_sql, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_extract_meta2_sql ) +# +# # AGAIN RUN DML_TEST +# #################### +# +# f_run_dml_log_2 = open( os.path.join(context['temp_directory'],'tmp_4126_dml_2.log'), 'w') +# subprocess.call( [context['isql_path'], 'localhost:'+tmpfdb1, "-i", f_run_dml_sql.name, "-ch", "utf8" ], +# stdout = f_run_dml_log_2, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_run_dml_log_2 ) +# +# +# # 7. CHECKS +# ########### +# # 1) STDERR for backup and restore - they all must be EMPTY. +# +# f_list=[f_backup_err, f_restore_err] +# for i in range(len(f_list)): +# f_name=f_list[i].name +# if os.path.getsize(f_name) > 0: +# with open( f_name,'r') as f: +# for line in f: +# print("Unexpected STDERR, file "+f_name+": "+line) +# +# # 2) diff between dml_1.log and dml_2.log should be EMPTY. +# # 3) diff between meta1.log and meta2.log should be EMPTY. +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_4126_diff.txt'), 'w') +# f_old=[] +# f_new=[] +# +# f_old.append(f_extract_meta1_sql) # DDL: what we have BEFORE database backup +# f_old.append(f_run_dml_log_1) # DML: result of querying tables before DB backup +# f_new.append(f_extract_meta2_sql) # DDL: what we have AFTER database restore +# f_new.append(f_run_dml_log_2) # DML: result of querying tables AFTER database restore +# +# for i in range(len(f_old)): +# old_file=open(f_old[i].name,'r') +# new_file=open(f_new[i].name,'r') +# +# f_diff_txt.write( ''.join( difflib.unified_diff( old_file.readlines(), new_file.readlines() ) ) ) +# +# old_file.close() +# new_file.close() +# +# flush_and_close( f_diff_txt ) +# +# # Should be EMPTY: +# ################## +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# if line.split() and not('---' in line or '+++' in line or '@@' in line or 'SET SQL DIALECT' in line or 'CREATE DATABASE' in line or 'collation'.upper() in line.upper()): +# print( 'Unexpected diff: ' + line ) +# +# +# # Cleanup: +# ########## +# cleanup( [i.name for i in (f_backup_log, f_backup_err, f_restore_log, f_restore_err, f_extract_meta1_sql, f_extract_meta2_sql, f_run_dml_sql, f_run_dml_log_1, f_run_dml_log_2, f_diff_txt) ] ) +# +# os.remove(tmpfdb1) +# os.remove(tmpfbk1) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4126_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4127.py b/tests/bugs/test_core_4127.py new file mode 100644 index 00000000..e0f9f6a4 --- /dev/null +++ b/tests/bugs/test_core_4127.py @@ -0,0 +1,57 @@ +#coding:utf-8 +# +# id: bugs.core_4127 +# title: Server crashes instead of reporting the error "key size exceeds implementation restriction" +# decription: +# tracker_id: CORE-4127 +# min_versions: ['2.5.3'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table tab1 (col1 int, col2 char(10)); + create index itab1 on tab1 (col1, col2); + commit; + insert into tab1 values(1, 'a'); + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select * from tab1 + where col1 = 1 and col2 = rpad('a', 32765) + union all + -- This part of query will NOT raise + -- Statement failed, SQLSTATE = 54000 + -- arithmetic exception, numeric overflow, or string truncation + -- -Implementation limit exceeded + -- since WI-V3.0.0.31981 + select * from tab1 + where col1 = 1 and col2 = rpad('a', 32766); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + COL1 1 + COL2 a + COL1 1 + COL2 a + """ + +@pytest.mark.version('>=3.0') +def test_core_4127_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4131.py b/tests/bugs/test_core_4131.py new file mode 100644 index 00000000..87dada65 --- /dev/null +++ b/tests/bugs/test_core_4131.py @@ -0,0 +1,52 @@ +#coding:utf-8 +# +# id: bugs.core_4131 +# title: Error when processing an empty data set by window function, if reading indexed +# decription: +# tracker_id: CORE-4131 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test(x char(31) character set unicode_fss unique using index test_x); + commit; + insert into test values('qwerty'); + commit; + + set list on; + set plan on; + select row_number() over(order by x) as rn, x + from test + where x = 'qwerty' + ; + -- 3.0.0.30472: + -- cursor identified in the UPDATE or DELETE statement is not positioned on a row. no current record for fetch operation + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN SORT (TEST INDEX (TEST_X)) + RN 1 + X qwerty + """ + +@pytest.mark.version('>=3.0') +def test_core_4131_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4135.py b/tests/bugs/test_core_4135.py new file mode 100644 index 00000000..35ec11a7 --- /dev/null +++ b/tests/bugs/test_core_4135.py @@ -0,0 +1,520 @@ +#coding:utf-8 +# +# id: bugs.core_4135 +# title: In SS sweep blocks establishment of concurrent attachments +# decription: +# We create DB-level trigger in order to log attachments info. +# Also, we create a table with long-key indexed fields for sweep have a big time to be completed. +# Then we insert data into this table and create indices on its fields. +# After this we delete just inserted rows and make commit thus providing lot of job to GC. +# +# When we call on next step sweep, it must work a very long time (maybe several minutes) - +# this was checked on host with common PC characteristics: P-IV 3.0 GHz, SATA). +# +# We launch SWEEP by async. call of FBSVCMGR and save current timestamp in 'DTS_BEG_FOR_ATTACHMENTS' variable. +# We allow sweep to work several seconds alone (see 'WAIT_BEFORE_RUN_1ST_ATT') and then run loop with launching +# ISQL attachments, all of them - also in async. mode. +# +# Each ISQL connect will add one row to the log-table ('mon_attach_data') by ON-CONNECT trigger - and we'll +# query later its data: how many ISQL did establish connections while sweep worked. +# +# After loop we wait several seconds in order to be sure that all ISQL are loaded (see 'WAIT_FOR_ALL_ATT_DONE'). +# +# Then we save new value of current timestamp in 'DTS_END_FOR_ATTACHMENTS' variable. +# After this we call FBSVCMGR with arguments to make SHUTDOWN of database, thus killing all existing attachments +# (SWEEP will be also interrupted in that case). This is done in SYNC mode (control will not return from SHUTDOWN +# process until it will be fully completed). +# +# Then we return database to ONLINE state and make single ISQL connect with '-nod' switch. +# This (last) attachment to database will query data of Log table 'mon_attach_data' and check that number of +# records (i.e. ACTUALLY etsablished attachment) is equal to which we check (see 'PLANNED_ATTACH_CNT'). +# +# Checked 07-jun-2016 on: +# 3.0.0.32527, SS/SC/CS. +# 4.0.0.238, SS/SC/CS. +# +# 11-JUN-2020. +# We also launch trace just before sweep with logging: +# 1) sweep activity +# 2) execute_trigger_finish events +# At the final point we make parsing of trace log and check that: +# 1) no attachments were made *before* sweep start; NB: WAIT_BEFORE_RUN_1ST_ATT must be increased if this is not so. +# 2) number of attachments AFTER sweep start and BEFORE its finish equals to required ('PLANNED_ATTACH_CNT'). +# Checked again on: 3.0.6.33296 SS ; V3.0.6.33289 CS ; 4.0.0.2037 SS ; 4.0.0.2025 CS +# +# 04-JUL-2020. +# Reduced PLANNED_ATTACH_CNT from 30 to 5 because 4.0 Classic remains fail. +# +# tracker_id: CORE-4135 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# from subprocess import Popen +# import time +# import datetime +# from datetime import datetime +# import re +# import shutil +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_file = db_conn.database_name +# +# db_conn.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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# +# ######################## +# ### s e t t i n g s ### +# ######################## +# +# # How many rows must be inserted to the test table: +# RECORDS_TO_ADD = 10000 +# +# # Length of indexed fields. +# # NB, 11.06.2020: sweep can make its work very fast +# # so we have to increase length of indexed fields +# # Checked on 4.0.0.2025 Classic +# INDEXED_FLD_LEN = 500 +# +# # How many attachments we want to establish +# # during sweep will work: +# PLANNED_ATTACH_CNT = 5 +# +# # How many seconds we allow to all PLANNED_ATTACH_CNT +# # sessions for establishing their connections: +# WAIT_FOR_ALL_ATT_DONE = 10 +# +# # How many seconds we allow SWEEP to work alone, +# # i.e. before 1st ISQL make its attachment: +# WAIT_BEFORE_RUN_1ST_ATT = 5 +# +# ##################### +# +# fb_home = services.connect(host='localhost').get_home_directory() +# +# sql_ddl=''' recreate table mon_attach_data ( +# mon_attachment_id bigint +# ,mon_timestamp timestamp default 'now' +# ); +# +# recreate table test ( +# s01 varchar(%(INDEXED_FLD_LEN)s) +# ,s02 varchar(%(INDEXED_FLD_LEN)s) +# ,s03 varchar(%(INDEXED_FLD_LEN)s) +# ); +# +# set term ^; +# create or alter trigger trg_connect active on connect position 0 as +# begin +# -- IN AUTONOMOUS TRANSACTION DO +# insert into mon_attach_data ( mon_attachment_id ) values (current_connection); +# end +# ^ +# set term ;^ +# commit; +# ''' % locals() +# +# sql_ddl_cmd=open( os.path.join(context['temp_directory'],'tmp_ddl_4135.sql'), 'w') +# sql_ddl_cmd.write(sql_ddl) +# flush_and_close( sql_ddl_cmd ) +# +# sql_ddl_log=open( os.path.join(context['temp_directory'],'tmp_ddl_4135.log'), 'w') +# subprocess.call( [context['isql_path'], dsn, "-i", sql_ddl_cmd.name], +# stdout=sql_ddl_log, +# stderr=subprocess.STDOUT +# ) +# flush_and_close( sql_ddl_log ) +# +# #-------------------------------------------------- +# +# sql_data=''' set term ^; +# execute block as +# declare n int = %(RECORDS_TO_ADD)s; +# begin +# while (n>0) do +# insert into test(s01, s02, s03) +# values( rpad('', %(INDEXED_FLD_LEN)s, uuid_to_char(gen_uuid()) ), +# rpad('', %(INDEXED_FLD_LEN)s, uuid_to_char(gen_uuid()) ), +# rpad('', %(INDEXED_FLD_LEN)s, uuid_to_char(gen_uuid()) ) +# ) returning :n-1 into n; +# end^ +# set term ;^ +# commit; +# +# create index test_a on test(s01,s02,s03); +# create index test_b on test(s02,s03,s01); +# create index test_c on test(s03,s02,s01); +# create index test_d on test(s01,s03,s02); +# create index test_e on test(s02,s01,s03); +# create index test_f on test(s03,s01,s02); +# commit; +# +# delete from test; +# commit; -- ==> lot of garbage in indexed pages will be after this. +# ''' % locals() +# +# +# # Temporay change FW to OFF in order to make DML faster: +# fn_nul = open(os.devnull, 'w') +# +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_properties", "dbname", db_file, +# "prp_write_mode", "prp_wm_async"], +# stdout=fn_nul, stderr=subprocess.STDOUT) +# +# +# sql_data_cmd=open( os.path.join(context['temp_directory'],'tmp_data_4135.sql'), 'w') +# sql_data_cmd.write(sql_data) +# flush_and_close( sql_data_cmd ) +# +# sql_data_log=open( os.path.join(context['temp_directory'],'tmp_data_4135.log'), 'w') +# subprocess.call( [context['isql_path'], dsn, "-nod", "-i", sql_data_cmd.name], +# stdout=sql_data_log, +# stderr=subprocess.STDOUT) +# flush_and_close( sql_data_log ) +# +# # Restore FW to ON (make sweep to do its work "harder"): +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_properties", "dbname", db_file, +# "prp_write_mode", "prp_wm_sync"], +# stdout=fn_nul, stderr=subprocess.STDOUT) +# fn_nul.close() +# +# #-------------------------------------------------- +# txt = ''' +# database=%[\\\\\\\\/]security?.fdb +# { +# enabled = false +# } +# database=%[\\\\\\\\/]bugs.core_4135.fdb +# { +# enabled = true +# log_initfini = false +# log_errors = true +# log_sweep = true +# # log_connections = true +# log_trigger_finish = true +# time_threshold = 0 +# } +# ''' +# +# f_trc_cfg=open( os.path.join(context['temp_directory'],'tmp_trace_4135.cfg'), 'w') +# f_trc_cfg.write(txt) +# flush_and_close( f_trc_cfg ) +# +# # ############################################################## +# # S T A R T T R A C E i n S E P A R A T E P R O C E S S +# # ############################################################## +# +# f_trc_log=open( os.path.join(context['temp_directory'],'tmp_trace_4135.log'), "w") +# f_trc_err=open( os.path.join(context['temp_directory'],'tmp_trace_4135.err'), "w") +# +# # ::: NB ::: DO NOT USE 'localhost:service_mgr' here! Use only local protocol: +# p_trace = Popen( [ context['fbsvcmgr_path'], 'service_mgr', 'action_trace_start' , 'trc_cfg', f_trc_cfg.name],stdout=f_trc_log,stderr=f_trc_err) +# +# +# time.sleep(1) +# +# # #################################################### +# # G E T A C T I V E T R A C E S E S S I O N I D +# # #################################################### +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# +# f_trc_lst = open( os.path.join(context['temp_directory'],'tmp_trace_4135.lst'), 'w') +# subprocess.call([context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_list'], stdout=f_trc_lst) +# flush_and_close( f_trc_lst ) +# +# # !!! DO NOT REMOVE THIS LINE !!! +# time.sleep(1) +# +# trcssn=0 +# with open( f_trc_lst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# f.close() +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# +# #-------------------------------------------------- +# +# # Now we run SWEEP in child process (asynchronous) and while it will in work - try to establish several attachments. +# ################## +# +# fbsvc_log=open( os.path.join(context['temp_directory'],'tmp_svc_4135.log'), 'w') +# fbsvc_log.write("Starting sweep") +# fbsvc_log.write("") +# fbsvc_log.seek(0,2) +# p_sweep=subprocess.Popen([ context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_repair", "dbname", db_file, "rpr_sweep_db"], +# stdout=fbsvc_log, stderr=subprocess.STDOUT +# ) +# +# time.sleep( WAIT_BEFORE_RUN_1ST_ATT ) +# +# #--------------------------------------------------------- +# +# # Save current timestamp: this is point BEFORE we try to establish attachmentas using several ISQL sessions: +# DTS_BEG_FOR_ATTACHMENTS = datetime.strftime(datetime.now(), '%Y-%m-%d %H:%M:%S') +# +# # Try to establish several attachments to database while sweep is in work: +# +# sqlatt=open( os.path.join(context['temp_directory'],'tmp_att_4135.sql'), 'w') +# sql_wrk=''' +# set heading off; +# set term ^; +# execute block returns(att bigint) as +# begin +# att = current_connection; +# suspend; +# end +# ^ +# set term ;^ +# commit; +# ''' +# sqlatt.write(sql_wrk) +# sqlatt.close() +# +# f_list=[] +# p_list=[] +# for i in range(0, PLANNED_ATTACH_CNT): +# sqllog=open( os.path.join(context['temp_directory'],'tmp_att_4135_'+str(i)+'.log'), 'w') +# f_list.append(sqllog) +# +# for i in range(len(f_list)): +# p_isql=Popen( [ context['isql_path'] , dsn, "-n", "-i", sqlatt.name ], +# stdout=f_list[i], +# stderr=subprocess.STDOUT +# ) +# p_list.append(p_isql) +# +# # Here we have to wait a little in order to all ISQL will establish their attachments: +# # 4.0.0.238 Classic: one needed to increased time from 3 to 5 seconds otherwise NOT ALL +# # ISQL attachments can be etsablished! +# +# # 11.06.2020: 4.0 Classic requires valuable delay here! +# time.sleep( WAIT_FOR_ALL_ATT_DONE ) +# +# # Save current timestamp: we assume that now ALL isql sessions already FINISHED to establish attachment (or the whole job and quited): +# DTS_END_FOR_ATTACHMENTS = datetime.strftime(datetime.now(), '%Y-%m-%d %H:%M:%S') +# +# #--------------------------------------------------------- +# +# # Move database to shutdown in order to stop sweep, and then extract header info: +# +# dbshut_log=open( os.path.join(context['temp_directory'],'tmp_sht_4135.log'), 'w') +# dbshut_log.write("Call DB shutdown") +# dbshut_log.write("") +# dbshut_log.seek(0,2) +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_properties", "dbname", db_file, +# "prp_shutdown_mode", "prp_sm_full", "prp_force_shutdown", "0"], +# stdout=dbshut_log, stderr=subprocess.STDOUT) +# +# dbshut_log.seek(0,2) +# +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_db_stats", "dbname", db_file, "sts_hdr_pages"], +# stdout=dbshut_log, stderr=subprocess.STDOUT) +# +# # Kill all child ISQL processes: +# for i in range(len(f_list)): +# p_list[i].terminate() +# flush_and_close( f_list[i] ) +# +# p_sweep.terminate() +# +# #--------------------------------------------------------- +# +# # #################################################### +# # S E N D R E Q U E S T T R A C E T O S T O P +# # #################################################### +# if trcssn>0: +# fn_nul = open(os.devnull, 'w') +# subprocess.call([context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_stop','trc_id', trcssn], stdout=fn_nul) +# fn_nul.close() +# # DO NOT REMOVE THIS LINE: +# time.sleep(1) +# +# p_trace.terminate() +# flush_and_close( f_trc_log ) +# flush_and_close( f_trc_err ) +# +# #--------------------------------------------------------- +# +# # Return database online in order to check number of attachments that were established while sweep was in work: +# +# dbshut_log.seek(0,2) +# dbshut_log.write("Return DB to online") +# dbshut_log.seek(0,2) +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_properties", "dbname", db_file, "prp_db_online"], +# stdout=dbshut_log, stderr=subprocess.STDOUT) +# +# dbshut_log.seek(0,2) +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_db_stats", "dbname", db_file, "sts_hdr_pages"], +# stdout=dbshut_log, stderr=subprocess.STDOUT) +# +# flush_and_close( dbshut_log ) +# flush_and_close( fbsvc_log ) +# +# +# # 4debug only, remove later: +# ############################ +# #bk_file="$(DATABASE_LOCATION)tmp_4135_copy.fdb" +# #shutil.copy2( db_file, bk_file ) +# +# #--------------------------------------------------------- +# +# # Check: number of ISQL attachments between DTS_BEG_FOR_ATTACHMENTS and DTS_END_FOR_ATTACHMENTS must be equal to 'PLANNED_ATTACH_CNT' +# +# # SuperServer has two system attachments with mon$user='Garbage Collector' and 'Cache Writer', +# # we have to SKIP them from counting: +# +# sql_data=''' set list on; +# select iif( cnt = %(PLANNED_ATTACH_CNT)s +# ,'EXPECTED' -- OK, number of attachments is equal to expected value. +# ,'POOR: only ' || cnt || ' attachments established for %(WAIT_FOR_ALL_ATT_DONE)s seconds, expected: %(PLANNED_ATTACH_CNT)s' +# ) as "DB-logged attachments:" +# from ( +# select count(*) as cnt +# from mon_attach_data d +# where d.mon_timestamp between '%(DTS_BEG_FOR_ATTACHMENTS)s' and '%(DTS_END_FOR_ATTACHMENTS)s' +# ); +# +# /* +# -- 4debug, do not delete: +# set list off; +# set count on; +# select d.* +# from mon_attach_data d +# where d.mon_timestamp between '%(DTS_BEG_FOR_ATTACHMENTS)s' and '%(DTS_END_FOR_ATTACHMENTS)s'; +# -- */ +# +# commit; +# ''' % locals() +# +# sqlchk=open( os.path.join(context['temp_directory'],'tmp_chk_4135.sql'), 'w') +# sqlchk.write( sql_data ) +# flush_and_close( sqlchk ) +# +# sqllog=open( os.path.join(context['temp_directory'],'tmp_chk_4135.log'), 'w') +# subprocess.call( [ context['isql_path'] , dsn, "-pag", "99999", "-nod", "-i", sqlchk.name ], +# stdout=sqllog, stderr=subprocess.STDOUT +# ) +# flush_and_close( sqllog ) +# +# with open(sqllog.name) as f: +# print( f.read() ) +# +# allowed_patterns = [ +# re.compile('EXECUTE_TRIGGER_FINISH', re.IGNORECASE) +# ,re.compile('SWEEP_START', re.IGNORECASE) +# ,re.compile('SWEEP_FINISH', re.IGNORECASE) +# ,re.compile('SWEEP_FAILED', re.IGNORECASE) +# ] +# +# # All events 'EXECUTE_TRIGGER_FINISH' must occus between SWEEP_START and SWEEP_FAILED +# +# found_swp_start = False +# found_swp_finish = False +# triggers_count_before_swp_start = 0 +# triggers_count_before_swp_finish = 0 +# with open(f_trc_log.name, 'r') as f: +# for line in f: +# for p in allowed_patterns: +# result = p.search(line) +# if result: +# what_found = result.group(0) +# if 'SWEEP_START' in what_found: +# found_swp_start = True +# if 'SWEEP_FINISH' in what_found or 'SWEEP_FAILED' in what_found: +# found_swp_finish = True +# if 'EXECUTE_TRIGGER_FINISH' in what_found: +# triggers_count_before_swp_start += (1 if not found_swp_start else 0) +# triggers_count_before_swp_finish += ( 1 if found_swp_start and not found_swp_finish else 0 ) +# +# time.sleep(1) +# +# #print('Trace log parsing. Found triggers before sweep start:', triggers_count_before_swp_start ) +# #print('Trace log parsing. Found triggers before sweep finish:', triggers_count_before_swp_finish ) +# print('Trace log parsing. Found triggers before sweep start:', 'EXPECTED (no triggers found).' if triggers_count_before_swp_start == 0 else 'UNEXPECTED: %(triggers_count_before_swp_start)s instead of 0.' % locals() ) +# print('Trace log parsing. Found triggers before sweep finish:', 'EXPECTED (equals to planned).' if triggers_count_before_swp_finish == PLANNED_ATTACH_CNT else 'UNEXPECTED: %(triggers_count_before_swp_finish)s instead of %(PLANNED_ATTACH_CNT)s.' % locals() ) +# +# #--------------------------------------------------------- +# +# #CLEANUP +# ######### +# time.sleep(1) +# +# cleanup( [i.name for i in f_list] ) +# cleanup( [i.name for i in (dbshut_log, fbsvc_log, sqllog, sql_data_log, sql_data_cmd, sql_ddl_log, sql_ddl_cmd, sqlchk, sqlatt, f_trc_log, f_trc_err, f_trc_cfg, f_trc_lst) ] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DB-logged attachments: EXPECTED + Trace log parsing. Found triggers before sweep start: EXPECTED (no triggers found). + Trace log parsing. Found triggers before sweep finish: EXPECTED (equals to planned). + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4135_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4136.py b/tests/bugs/test_core_4136.py new file mode 100644 index 00000000..ba83bb50 --- /dev/null +++ b/tests/bugs/test_core_4136.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_4136 +# title: Sharp-S character treated incorrectly in UNICODE_CI_AI collation +# decription: +# tracker_id: CORE-4136 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select + case when 'Übergeek' collate unicode_ci_ai like 'ÜB%' collate unicode_ci_ai + then 'match' else 'MISMATCH' end as test_1, + case when 'Übergeek' collate unicode_ci_ai like 'üb%' collate unicode_ci_ai + then 'match' else 'MISMATCH' end as test_2, + case when 'Fußball' collate unicode_ci_ai like 'fu%' collate unicode_ci_ai + then 'match' else 'MISMATCH' end as test_3, + case when 'Fußball' collate unicode_ci_ai like 'fuß%' collate unicode_ci_ai + then 'match' else 'MISMATCH' end as test_4, + case when upper ('Fußball') like upper ('fuß%') + then 'match' else 'MISMATCH' end as test_5 + from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TEST_1 match + TEST_2 match + TEST_3 match + TEST_4 match + TEST_5 match + """ + +@pytest.mark.version('>=2.5.3') +def test_core_4136_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4137.py b/tests/bugs/test_core_4137.py new file mode 100644 index 00000000..fa364c5b --- /dev/null +++ b/tests/bugs/test_core_4137.py @@ -0,0 +1,89 @@ +#coding:utf-8 +# +# id: bugs.core_4137 +# title: Wrong metadata output script generate by isql / CHARACTER SETISO8859_1 sintax error +# decription: NB: missed space in the clause CHARACTER SETISO8859_1 +# tracker_id: CORE-4137 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('.*CREATE DATABASE.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(charset='ISO8859_1', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# sql_ddl=''' +# alter character set iso8859_1 set default collation pt_br; +# commit; +# +# set term ^ ; +# create or alter procedure test ( +# p01 char(10) character set iso8859_1 +# ) returns ( +# o01 varchar(30) character set iso8859_1 +# ) as begin +# exit; +# end +# ^ +# set term ;^ +# commit; +# ''' +# runProgram('isql',[dsn, '-ch', 'iso8859_1'], sql_ddl) +# runProgram('isql',['-x',dsn]) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + SET SQL DIALECT 3; + /* Character sets */ + ALTER CHARACTER SET ISO8859_1 SET DEFAULT COLLATION PT_BR; + COMMIT WORK; + COMMIT WORK; + SET AUTODDL OFF; + SET TERM ^ ; + /* Stored procedures headers */ + CREATE OR ALTER PROCEDURE TEST (P01 CHAR(10) CHARACTER SET ISO8859_1) + RETURNS (O01 VARCHAR(30) CHARACTER SET ISO8859_1) + AS + BEGIN EXIT; END ^ + SET TERM ; ^ + COMMIT WORK; + SET AUTODDL ON; + COMMIT WORK; + SET AUTODDL OFF; + SET TERM ^ ; + /* Stored procedures bodies */ + ALTER PROCEDURE TEST (P01 CHAR(10) CHARACTER SET ISO8859_1) + RETURNS (O01 VARCHAR(30) CHARACTER SET ISO8859_1) + AS + begin + exit; + end ^ + SET TERM ; ^ + COMMIT WORK; + SET AUTODDL ON; + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4137_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4139.py b/tests/bugs/test_core_4139.py new file mode 100644 index 00000000..f9cbcde4 --- /dev/null +++ b/tests/bugs/test_core_4139.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: bugs.core_4139 +# title: Error "invalid stream" can be raised in some cases while matching a computed index +# decription: +# tracker_id: CORE-4139 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create table A (ID int); +create table B (ID int); +create index IDX on A computed by (ID); +""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """SET HEADING OFF; +select min( (select 1 from A where cast(ID as int) = B.ID) ) from B; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """""" + +@pytest.mark.version('>=2.5.3') +def test_core_4139_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4140.py b/tests/bugs/test_core_4140.py new file mode 100644 index 00000000..56b9646e --- /dev/null +++ b/tests/bugs/test_core_4140.py @@ -0,0 +1,159 @@ +#coding:utf-8 +# +# id: bugs.core_4140 +# title: EXECUTE BLOCK's TYPE OF parameters with NONE charset may have be transformed to the connection charset +# decription: +# tracker_id: CORE-4140 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create domain dm_utf8 varchar(50) character set utf8 collate unicode_ci_ai; + create domain dm_none varchar(50); + recreate table test(s varchar(50) character set none); + commit; + insert into test values('ÃÂÁÀÄÅÇØßÐÑÞÆŠŒŽ'); -- http://en.wikipedia.org/wiki/Windows-1252 + commit; + --show version; + set term ^; + execute block returns( msg varchar(35), txt_str type of dm_none, oct_len int, chr_len int) as + begin + msg = 'inp=dm_none, out=test.s, arg=utf8'; + execute statement ( + 'execute block (c type of dm_none = ?) returns (txt_str type of column test.s, oct_len int, chr_len int) as ' + || 'begin ' + || ' txt_str = (select s from test where s starting with :c); ' + || ' oct_len = octet_length(txt_str); ' + || ' chr_len = char_length(txt_str); ' + || ' suspend; ' + || 'end') ( _utf8 'ÃÂÁÀÄÅÇØßÐÑÞÆŠŒŽ' ) + into txt_str, oct_len, chr_len; + suspend; + + msg = 'inp=dm_none, out=test.s, arg=w1252'; + execute statement ( + 'execute block (c type of dm_none = ?) returns (txt_str type of column test.s, oct_len int, chr_len int) as ' + || 'begin ' + || ' txt_str = (select s from test where s starting with :c); ' + || ' oct_len = octet_length(txt_str); ' + || ' chr_len = char_length(txt_str); ' + || ' suspend; ' + || 'end') ( _win1252 'ÃÂÁÀÄÅÇØßÐÑÞÆŠŒŽ' ) + into txt_str, oct_len, chr_len; + suspend; + + + msg = 'inp=test.s, out=dm_none, arg=utf8'; + execute statement ( + 'execute block (c type of column test.s = ?) returns ( txt_str type of dm_none, oct_len int, chr_len int) as ' + || 'begin ' + || ' txt_str = (select s from test where s starting with :c); ' + || ' oct_len = octet_length(txt_str); ' + || ' chr_len = char_length(txt_str); ' + || ' suspend; ' + || 'end') ( _utf8 'ÃÂÁÀÄÅÇØßÐÑÞÆŠŒŽ' ) + into txt_str, oct_len, chr_len; + suspend; + + msg = 'inp=test.s, out=dm_none, arg=w1252'; + execute statement ( + 'execute block (c type of column test.s = ?) returns ( txt_str type of dm_none, oct_len int, chr_len int) as ' + || 'begin ' + || ' txt_str = (select s from test where s starting with :c); ' + || ' oct_len = octet_length(txt_str); ' + || ' chr_len = char_length(txt_str); ' + || ' suspend; ' + || 'end') ( _win1252 'ÃÂÁÀÄÅÇØßÐÑÞÆŠŒŽ' ) + into txt_str, oct_len, chr_len; + suspend; + + /* + msg = 'inp=utf8, out=utf8, arg=utf8'; + execute statement ( + 'execute block (c type of dm_utf8 = ?) returns ( txt_str type of dm_utf8, oct_len int, chr_len int) as ' + || 'begin ' + || ' txt_str = (select s from test where s starting with :c); ' + || ' oct_len = octet_length(txt_str); ' + || ' chr_len = char_length(txt_str); ' + || ' suspend; ' + || 'end') ( _utf8 'ÃÂÁÀÄÅÇØßÐÑÞÆŠŒŽ' ) + into txt_str, oct_len, chr_len; + suspend; + */ + + msg = 'inp=utf8, out=utf8, arg=w1252'; + execute statement ( + 'execute block (c type of dm_utf8 = ?) returns ( txt_str type of dm_utf8, oct_len int, chr_len int) as ' + || 'begin ' + || ' txt_str = (select s from test where s starting with :c); ' + || ' oct_len = octet_length(txt_str); ' + || ' chr_len = char_length(txt_str); ' + || ' suspend; ' + || 'end') ( _win1252 'ÃÂÁÀÄÅÇØßÐÑÞÆŠŒŽ' ) + into txt_str, oct_len, chr_len; + suspend; + + + msg = 'inp=test.s, out=test.s, arg=utf8'; + execute statement ( + 'execute block (c type of column test.s = ?) returns ( txt_str type of column test.s, oct_len int, chr_len int) as ' + || 'begin ' + || ' txt_str = (select s from test where s starting with :c); ' + || ' oct_len = octet_length(txt_str); ' + || ' chr_len = char_length(txt_str); ' + || ' suspend; ' + || 'end') ( _utf8 'ÃÂÁÀÄÅÇØßÐÑÞÆŠŒŽ' ) + into txt_str, oct_len, chr_len; + suspend; + + msg = 'inp=test.s, out=test.s, arg=w1252'; + execute statement ( + 'execute block (c type of column test.s = ?) returns ( txt_str type of column test.s, oct_len int, chr_len int) as ' + || 'begin ' + || ' txt_str = (select s from test where s starting with :c); ' + || ' oct_len = octet_length(txt_str); ' + || ' chr_len = char_length(txt_str); ' + || ' suspend; ' + || 'end') ( _win1252 'ÃÂÁÀÄÅÇØßÐÑÞÆŠŒŽ' ) + into txt_str, oct_len, chr_len; + suspend; + + end + ^ + set term ;^ + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG TXT_STR OCT_LEN CHR_LEN + =================================== ================================================== ============ ============ + inp=dm_none, out=test.s, arg=utf8 ÃÂÁÀÄÅÇØßÐÑÞÆŠŒŽ 32 32 + inp=dm_none, out=test.s, arg=w1252 ÃÂÁÀÄÅÇØßÐÑÞÆŠŒŽ 32 32 + inp=test.s, out=dm_none, arg=utf8 ÃÂÁÀÄÅÇØßÐÑÞÆŠŒŽ 32 32 + inp=test.s, out=dm_none, arg=w1252 ÃÂÁÀÄÅÇØßÐÑÞÆŠŒŽ 32 32 + inp=utf8, out=utf8, arg=w1252 + inp=test.s, out=test.s, arg=utf8 ÃÂÁÀÄÅÇØßÐÑÞÆŠŒŽ 32 32 + inp=test.s, out=test.s, arg=w1252 ÃÂÁÀÄÅÇØßÐÑÞÆŠŒŽ 32 32 + """ + +@pytest.mark.version('>=3.0') +def test_core_4140_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4142.py b/tests/bugs/test_core_4142.py new file mode 100644 index 00000000..01632dd8 --- /dev/null +++ b/tests/bugs/test_core_4142.py @@ -0,0 +1,60 @@ +#coding:utf-8 +# +# id: bugs.core_4142 +# title: Regression: Server crashes while preparing a query with DISTINCT and ORDER BY +# decription: +# tracker_id: CORE-4142 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """ + recreate table trel(id smallint, name char(31) character set unicode_fss collate unicode_fss); + commit; + insert into trel(id, name) select row_number()over(), 'RDB$NAME_' || row_number()over() + from rdb$types + rows 9; + commit; + alter table trel add constraint trel_name_unq unique (name); + create index trel_id on trel(id); + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + select distinct id + 0 id, name + from trel + order by name; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID NAME + == ========== + 1 RDB$NAME_1 + 2 RDB$NAME_2 + 3 RDB$NAME_3 + 4 RDB$NAME_4 + 5 RDB$NAME_5 + 6 RDB$NAME_6 + 7 RDB$NAME_7 + 8 RDB$NAME_8 + 9 RDB$NAME_9 + """ + +@pytest.mark.version('>=3.0') +def test_core_4142_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4144.py b/tests/bugs/test_core_4144.py new file mode 100644 index 00000000..5ed9b933 --- /dev/null +++ b/tests/bugs/test_core_4144.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: bugs.core_4144 +# title: Error "context already in use (BLR error)" when preparing a query with UNION +# decription: +# tracker_id: CORE-4144 +# min_versions: ['2.1.6'] +# versions: 2.1.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """set heading off; +select n + from + ( + select d.rdb$relation_id as n from rdb$database d + union all + select d.rdb$relation_id as n from rdb$database d + ) +union all +select cast(1 as bigint) from rdb$database d; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """128 +128 +1 +""" + +@pytest.mark.version('>=2.1.6') +def test_core_4144_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4149.py b/tests/bugs/test_core_4149.py new file mode 100644 index 00000000..aeab1e4f --- /dev/null +++ b/tests/bugs/test_core_4149.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_4149 +# title: New permission types are not displayed by ISQL +# decription: +# tracker_id: CORE-4149 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test(id int); + commit; + grant select on test to public; + commit; + show grants; + + create sequence g_test; + commit; + + grant usage on sequence g_test to public; + commit; + show grants; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + /* 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 + """ + +@pytest.mark.version('>=3.0') +def test_core_4149_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4155.py b/tests/bugs/test_core_4155.py new file mode 100644 index 00000000..2c8f521a --- /dev/null +++ b/tests/bugs/test_core_4155.py @@ -0,0 +1,75 @@ +#coding:utf-8 +# +# id: bugs.core_4155 +# title: External routines DDL in Packages wrongly report error for termination with semi-colon +# decription: +# Confirmed compile error on WI-T3.0.0.30566 Alpha 1, got there: +# Statement failed, SQLSTATE = 42000 / Dynamic SQL Error +# -SQL error code = -104 / -Token unknown... +# -; +# No such error in 3.0.5 and 4.0.x, but one cannot check 3.05 functionality because there is no +# %FB3x_HOME%\\plugins\\udr\\udrcpp_example.dll in all 3.x snapshots since at least 3.0.0. +# This lead to: "Statement failed, SQLSTATE = HY000 / UDR module not loaded" +# Sent letter to dimitr 30.04.2019 14:01, waiting for reply. +# +# Checked on 4.0.0.1501: OK, 1.621s. +# +# tracker_id: CORE-4155 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create or alter package pkg + as + begin + function sum_args ( + n1 integer, + n2 integer, + n3 integer + ) returns integer; + end + ^ + recreate package body pkg + as + begin + function sum_args ( + n1 integer, + n2 integer, + n3 integer + ) returns integer + external name 'udrcpp_example!sum_args' + engine udr; -- error with the semi-colon and works without it + end + ^ + set term ;^ + commit; + set list on; + select pkg.sum_args(111,555,777) from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + SUM_ARGS 1443 + """ + +@pytest.mark.version('>=4.0') +def test_core_4155_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4156.py b/tests/bugs/test_core_4156.py new file mode 100644 index 00000000..4b81b995 --- /dev/null +++ b/tests/bugs/test_core_4156.py @@ -0,0 +1,48 @@ +#coding:utf-8 +# +# id: bugs.core_4156 +# title: RDB$GET_CONTEXT/RDB$SET_CONTEXT parameters incorrectly described as CHAR NOT NULL instead of VARCHAR NULLABLE +# decription: +# tracker_id: CORE-4156 +# min_versions: ['2.1.7'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!sqltype).)*$', ''), ('[ ]+', ' '), ('[\t]*', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set planonly; + set sqlda_display on; + select rdb$set_context( ?, ?, ?) x from rdb$database; + -- NB: output in 3.0 will contain values of sqltype with ZERO in bit_0, + -- so it will be: 448 instead of previous 449, and 496 instead of 497. + -- Result is value that equal to constant from src/dsql/sqlda_pub.h, i.e: + -- #define SQL_VARYING 448 + -- #define SQL_LONG 496 + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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_core_4156_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4158.py b/tests/bugs/test_core_4158.py new file mode 100644 index 00000000..001f4f01 --- /dev/null +++ b/tests/bugs/test_core_4158.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_4158 +# title: Regression: LIKE with escape does not work +# decription: +# tracker_id: CORE-4158 +# min_versions: ['2.0.7'] +# versions: 2.0.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table tab1 ( + id int constraint pk_tab1 primary key, + val varchar(30) + ); + + insert into tab1 (id, val) values (1, 'abcdef'); + insert into tab1 (id, val) values (2, 'abc_ef'); + insert into tab1 (id, val) values (3, 'abc%ef'); + insert into tab1 (id, val) values (4, 'abc&%ef'); + insert into tab1 (id, val) values (5, 'abc&_ef'); + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select id, val from tab1 where val like 'abc&%ef' escape '&'; + select id, val from tab1 where val like 'abc&_ef' escape '&'; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 3 + VAL abc%ef + ID 2 + VAL abc_ef + """ + +@pytest.mark.version('>=2.0.7') +def test_core_4158_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4160.py b/tests/bugs/test_core_4160.py new file mode 100644 index 00000000..4dc142eb --- /dev/null +++ b/tests/bugs/test_core_4160.py @@ -0,0 +1,95 @@ +#coding:utf-8 +# +# id: bugs.core_4160 +# title: Parameterized exception does not accept not ASCII characters as parameter +# decription: +# tracker_id: CORE-4160 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('-At procedure.*', '')] + +init_script_1 = """ + create or alter procedure sp_alert(a_lang char(2), a_new_amount int) as begin end; + commit; + recreate exception ex_negative_remainder ' @1 (@2)'; + commit; + """ + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create or alter procedure sp_alert(a_lang char(2), a_new_amount int) as + begin + if (a_lang = 'cz') then + exception ex_negative_remainder using ('Czech: New Balance bude menší než nula', a_new_amount); + else if (a_lang = 'pt') then + exception ex_negative_remainder using ('Portuguese: New saldo será menor do que zero', a_new_amount); + else if (a_lang = 'dm') then + exception ex_negative_remainder using ('Danish: New Balance vil være mindre end nul', a_new_amount); + else if (a_lang = 'gc') then + exception ex_negative_remainder using ('Greek: Νέα ισορροπία θα είναι κάτω από το μηδέν', a_new_amount); + else if (a_lang = 'fr') then + exception ex_negative_remainder using ('French: Nouveau solde sera inférieur à zéro', a_new_amount); + else + exception ex_negative_remainder using ('Russian: Новый остаток будет меньше нуля', a_new_amount); + end + ^ + set term ;^ + commit; + execute procedure sp_alert('cz', -1); + execute procedure sp_alert('pt', -2); + execute procedure sp_alert('dm', -3); + execute procedure sp_alert('gc', -4); + execute procedure sp_alert('fr', -5); + execute procedure sp_alert('jp', -6); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = HY000 + exception 1 + -EX_NEGATIVE_REMAINDER + - Czech: New Balance bude menší než nula (-1) + + Statement failed, SQLSTATE = HY000 + exception 1 + -EX_NEGATIVE_REMAINDER + - Portuguese: New saldo será menor do que zero (-2) + + Statement failed, SQLSTATE = HY000 + exception 1 + -EX_NEGATIVE_REMAINDER + - Danish: New Balance vil være mindre end nul (-3) + + Statement failed, SQLSTATE = HY000 + exception 1 + -EX_NEGATIVE_REMAINDER + - Greek: Νέα ισορροπία θα είναι κάτω από το μηδέν (-4) + + Statement failed, SQLSTATE = HY000 + exception 1 + -EX_NEGATIVE_REMAINDER + - French: Nouveau solde sera inférieur à zéro (-5) + + Statement failed, SQLSTATE = HY000 + exception 1 + -EX_NEGATIVE_REMAINDER + - Russian: Новый остаток будет меньше нуля (-6) + """ + +@pytest.mark.version('>=3.0') +def test_core_4160_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_4161.py b/tests/bugs/test_core_4161.py new file mode 100644 index 00000000..ed8abe20 --- /dev/null +++ b/tests/bugs/test_core_4161.py @@ -0,0 +1,164 @@ +#coding:utf-8 +# +# id: bugs.core_4161 +# title: User can not insert records into table with column "generated by default as identity" in its DDL +# decription: +# tracker_id: CORE-4161 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set wng off; + set list on; + + create or alter user tmp$core4161 password '123'; + commit; + revoke all on all from tmp$core4161; + commit; + + recreate table autoid_test(id int generated by default as identity primary key, f01 int); + insert into autoid_test(f01) values(100); + insert into autoid_test(f01) values(200); + insert into autoid_test(f01) values(300); + commit; + + recreate table backup_data(id int, f01 int); + insert into backup_data(id, f01) select id, f01 from autoid_test; + commit; + + grant insert,update,delete,select on autoid_test to tmp$core4161; + grant select on backup_data to tmp$core4161; + commit; + + set term ^; + execute block returns( who_am_i type of column sec$users.sec$user_name, mine_id int, mine_f01 int ) + as + declare v_dbname type of column mon$database.mon$database_name; + declare v_usr type of column sec$users.sec$user_name = 'tmp$core4161'; + declare v_pwd varchar(20) = '123'; + declare v_connect varchar(255); + declare v_dummy int; + begin + select 'localhost:' || d.mon$database_name + from mon$database d + into v_dbname; + + execute statement 'select count(*) from autoid_test' + on external (v_dbname) + as user (v_usr) password (v_pwd) + into v_dummy; + + execute statement ('update autoid_test set f01=-f01 where id = :x') (x := 1) + on external (v_dbname) + as user (v_usr) password (v_pwd); + + execute statement ('delete from autoid_test where id >= :x') (x := 1) + on external (v_dbname) + as user (v_usr) password (v_pwd); + + execute statement ('insert into autoid_test(f01) values(:x)') (x := 555) + on external (v_dbname) + as user (v_usr) password (v_pwd); + + execute statement ('insert into autoid_test(id, f01) values(:i, :x)') (i := -1, x := -555) + on external (v_dbname) + as user (v_usr) password (v_pwd); + + execute statement ('insert into autoid_test(f01) select f01 from backup_data') + on external (v_dbname) + as user (v_usr) password (v_pwd); + + for + execute statement 'select current_user, id, f01 from autoid_test' + on external (v_dbname) + as user (v_usr) password (v_pwd) + into who_am_i, mine_id, mine_f01 + do + suspend; + + end + ^ + set term ;^ + rollback; + + select current_user as who_am_i, id as mine_id, f01 as mine_f01 + from autoid_test; + 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; + + -- Do not forget about cleanup - remember that other tests can query sec$users or run `show users`! + drop user tmp$core4161; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHO_AM_I TMP$CORE4161 + MINE_ID 4 + MINE_F01 555 + + WHO_AM_I TMP$CORE4161 + MINE_ID -1 + MINE_F01 -555 + + WHO_AM_I TMP$CORE4161 + MINE_ID 5 + MINE_F01 100 + + WHO_AM_I TMP$CORE4161 + MINE_ID 6 + MINE_F01 200 + + WHO_AM_I TMP$CORE4161 + MINE_ID 7 + MINE_F01 300 + + + + WHO_AM_I SYSDBA + MINE_ID 1 + MINE_F01 100 + + WHO_AM_I SYSDBA + MINE_ID 2 + MINE_F01 200 + + WHO_AM_I SYSDBA + MINE_ID 3 + MINE_F01 300 + """ + +@pytest.mark.version('>=3.0') +def test_core_4161_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4164.py b/tests/bugs/test_core_4164.py new file mode 100644 index 00000000..050b669a --- /dev/null +++ b/tests/bugs/test_core_4164.py @@ -0,0 +1,77 @@ +#coding:utf-8 +# +# id: bugs.core_4164 +# title: Owner name is missing for generators/exceptions restored from a backup +# decription: +# tracker_id: CORE-4164 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """ + -- Scenario for this test: + -- create sequence g; + -- create exception e 'blablabla'; + -- commit; + -- grant usage on sequence g to tmp$4164; + -- grant usage on exception e to tmp$4164; + -- grant usage on sequence g to mgr$4164 with grant option; + -- grant usage on exception e to mgr$4164 with grant option; + -- commit; + -- ==> and then do backup. + """ + +db_1 = db_factory(from_backup='core4164.fbk', init=init_script_1) + +test_script_1 = """ + set width usr 10; + set width grantor 10; + set width priv 4; + set width with_grant 6; + set width obj_name 10; + set width fld_name 15; + + select + p.rdb$user usr + ,p.rdb$grantor grantor + ,p.rdb$privilege priv + -- ::: NB ::: Field rdb$grant_option will contain NULLs after restoring, + -- but and 0 are considered by engine as the same in RDB$ tables. + -- Decided to apply `coalesce` after consulting with Dmitry, letter 27.03.2015 19:26 + ,coalesce(p.rdb$grant_option, 0) with_grant + ,p.rdb$relation_name obj_name + ,p.rdb$user_type usr_type + ,p.rdb$object_type obj_type + ,p.rdb$field_name fld_name + from rdb$user_privileges p + where upper(trim(p.rdb$relation_name)) in ( upper('g'), upper('e') ) + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + USR GRANTOR PRIV WITH_GRANT OBJ_NAME USR_TYPE OBJ_TYPE FLD_NAME + ========== ========== ==== ============ ========== ======== ======== =============== + SYSDBA SYSDBA G 1 G 8 14 + SYSDBA SYSDBA G 1 E 8 7 + TMP$4164 SYSDBA G 0 G 8 14 + TMP$4164 SYSDBA G 0 E 8 7 + MGR$4164 SYSDBA G 1 G 8 14 + MGR$4164 SYSDBA G 1 E 8 7 + """ + +@pytest.mark.version('>=3.0') +def test_core_4164_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4165.py b/tests/bugs/test_core_4165.py new file mode 100644 index 00000000..7e869a61 --- /dev/null +++ b/tests/bugs/test_core_4165.py @@ -0,0 +1,93 @@ +#coding:utf-8 +# +# id: bugs.core_4165 +# title: Replace the hierarchical union execution with the plain one +# decription: +# tracker_id: CORE-4165 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('record length.*', ''), ('key length.*', '')] + +init_script_1 = """ + recreate table t1(id int); + recreate table t2(id int); + recreate table t3(id int); + commit; + insert into t1 select rand()*100 from rdb$types,rdb$types; + commit; + insert into t2 select * from t1; + insert into t3 select * from t1; + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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 + """ + +@pytest.mark.version('>=3.0') +def test_core_4165_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4172.py b/tests/bugs/test_core_4172.py new file mode 100644 index 00000000..1edbe5a3 --- /dev/null +++ b/tests/bugs/test_core_4172.py @@ -0,0 +1,285 @@ +#coding:utf-8 +# +# id: bugs.core_4172 +# title: Creating external function (udf) to not existing dll - and then procedure with it - crash server +# decription: +# +# *** FOR FB 4.X AND ABOVE *** +# Added separate code for running on FB 4.0.x: we use create UDR function statement and specify +# non-existent library 'unknown_udf!UC_div'. The statement per se will pass and rdb$functions +# *will* contain record for just created function. But following COMMT will raise exception: +# Statement failed, SQLSTATE = HY000 +# UDR module not loaded +# +# Then we rollback and query rdb$functions again. No record about this function must be there. +# +# STDERR is ignored in this test because of localized message about missed library. +# Checked on: +# 4.0.0.1172: OK, 7.344s. +# 4.0.0.1340: OK, 2.797s. +# 4.0.0.1378: OK, 3.062s. +# +# tracker_id: CORE-4172 +# min_versions: ['3.0'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('.* at offset.*', '.* at offset')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# tmpfdb_1=os.path.join(context['temp_directory'],'tmp_4172_1.fdb') +# tmpfdb_2=os.path.join(context['temp_directory'],'tmp_4172_2.fdb') +# +# sql_chk=''' +# create database '%(tmpfdb_2)s'; +# commit; +# create database '%(tmpfdb_1)s'; +# +# set autoddl off; +# commit; +# +# declare external function dummy_ext +# integer +# returns integer by value +# entry_point 'dummy_ext' +# module_name 'non_existing_udf.dll'; +# commit; +# +# set term ^; +# create procedure sp_test ( a_id integer ) returns ( o_name integer ) as +# begin +# o_name = dummy_ext(a_id); +# suspend; +# end +# ^ +# set term ;^ +# commit; +# +# rollback; +# +# connect '%(tmpfdb_2)s'; +# set list on; +# select 1 as x from rdb$database; +# ''' % locals() +# +# f_list=[tmpfdb_1, tmpfdb_2] +# +# # Cleanup BEFORE running script: +# ################ +# cleanup( f_list ) +# +# runProgram( context['isql_path'],['-q'], sql_chk) +# +# # Final cleanup: +# ################ +# time.sleep(1) +# cleanup( f_list ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + X 1 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 39000 + invalid request BLR at offset + -function DUMMY_EXT is not defined + -module name or entrypoint could not be found + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4172_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +# test_script_2 +#--- +# +# import os +# import time +# import subprocess +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# +# # STDERR: Statement failed, SQLSTATE = HY000 +# # STDERR: UDR module not loaded +# #allowed_patterns = ( re.compile( '\\.*SQLSTATE\\s*=\\s*HY000', re.IGNORECASE), +# # re.compile( '\\.*UDR\\s+module\\s+not\\s+(found|loaded)\\.*', re.IGNORECASE), +# # ) +# +# sql_text=''' +# recreate view v_check as +# select rdb$function_name, rdb$entrypoint, rdb$engine_name, rdb$legacy_flag +# from rdb$functions +# where rdb$system_flag is distinct from 1 and rdb$function_name starting with upper( 'the_' ) +# ; +# commit; +# +# set list on; +# set term ^; +# execute block returns( o_gdscode int ) as +# begin +# begin +# execute statement +# q'{ +# create function the_div ( +# n1 integer, +# n2 integer +# ) returns double precision +# external name 'unknown_udf!UC_div' +# engine udr +# }'; +# -- was: external name 'udf_compat!UC_div' +# +# when any do +# begin +# o_gdscode = gdscode; +# end +# end +# suspend; +# end +# ^ +# set term ;^ +# +# commit; +# +# set blob all; +# set count on; +# +# select * from v_check; +# rollback; +# +# select * from v_check; +# rollback; +# ''' +# +# f_sql_chk = open( os.path.join(context['temp_directory'],'tmp_4172.sql') , 'w') +# f_sql_chk.write(sql_text) +# flush_and_close( f_sql_chk ) +# +# f_sql_log=open( os.path.join(context['temp_directory'],'tmp_4172.log'), 'w') +# fn_nul = open(os.devnull, 'w') +# subprocess.call( [ context['isql_path'], dsn, '-i', f_sql_chk.name], stdout = f_sql_log, stderr = fn_nul) +# +# flush_and_close( f_sql_log ) +# fn_nul.close() +# +# with open( f_sql_log.name,'r') as f: +# for line in f: +# if line.split(): +# print( ' '.join( line.split() ) ) +# +# # CLEANUP +# ######### +# time.sleep(1) +# cleanup( [i.name for i in (f_sql_chk, f_sql_log) ] ) +# +# +#--- +#act_2 = python_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + O_GDSCODE + RDB$FUNCTION_NAME THE_DIV + RDB$ENTRYPOINT unknown_udf!UC_div + RDB$ENGINE_NAME UDR + RDB$LEGACY_FLAG 0 + Records affected: 1 + Records affected: 0 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_4172_2(db_2): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4173.py b/tests/bugs/test_core_4173.py new file mode 100644 index 00000000..ddbddc35 --- /dev/null +++ b/tests/bugs/test_core_4173.py @@ -0,0 +1,51 @@ +#coding:utf-8 +# +# id: bugs.core_4173 +# title: Setting generator value twice in single transaction will set it to zero +# decription: +# tracker_id: CORE-4173 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set autoddl off; + set list on; + create generator g; + commit; + set generator g to 111; + commit; + select gen_id(g,0) value_on_step_1 from rdb$database; + set generator g to 222; + set generator g to 333; + select gen_id(g,0) value_on_step_2 from rdb$database; + commit; + select gen_id(g,0) value_on_step_3 from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + VALUE_ON_STEP_1 111 + VALUE_ON_STEP_2 333 + VALUE_ON_STEP_3 333 + """ + +@pytest.mark.version('>=2.5') +def test_core_4173_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4177.py b/tests/bugs/test_core_4177.py new file mode 100644 index 00000000..6f0f7621 --- /dev/null +++ b/tests/bugs/test_core_4177.py @@ -0,0 +1,146 @@ +#coding:utf-8 +# +# id: bugs.core_4177 +# title: Problem with some boolean expressions not being allowed +# decription: +# tracker_id: CORE-4177 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + --set echo on; + + select 1 x1 + from rdb$database + where (1=1) is true; + + select 1 x2 + from rdb$database + where true = true = true is not false is not distinct from not false is not false is not distinct from not false is not distinct from not false = not false is not distinct from not false ; + + select 1 x3 + from rdb$database + where not false and not false = not not not not true and not not not false = not not true and not not not not not not not false; + + + select 1 x4a + from rdb$database + where not false and not false is not false; + + + select 1 x4b + from rdb$database + where not false and not false = not not not false; + + -- Fails as of 3.0.0.31906 (30.06.2015). + -- select 1 x4c + -- from rdb$database + -- where not false and not false is not not not false; + + -- Works fine (but failed before; uncomment 30.06.2015): + select 1 x4d + from rdb$database + where not false and not false is not distinct from not false; + + + -- Following lines were commented before, now (3.0.0.31906, 30.06.2015) they work fine: + + select 1 y1 + from rdb$database + where (1=1) is true; + + select 1 y2 + from rdb$database + where true = true = true is not false is not distinct from not false is not false is not distinct from not false is not distinct from not false = not false is not distinct from not false ; + + select 1 y3 + from rdb$database + where not false and not false = not not not not true and not not not false = not not true and not not not not not not not false; + + + select 1 y4a + from rdb$database + where not false and not false is not false; + + + select 1 y4b + from rdb$database + where not false and not false = not not not false; + + + recreate table test1(id int, x boolean); + insert into test1 values(107, false); + insert into test1 values(109, false); + insert into test1 values(117, true ); + insert into test1 values(121, true ); + insert into test1 values(122, false); + insert into test1 values(128, true ); + insert into test1 values(137, false); + insert into test1 values(144, false); + + select * from test1 where x between true and true; + select * from test1 where x between true and (not false); + select * from test1 where x between (not false) and true; + select * from test1 where x between (not false) and (not false); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + X1 1 + X2 1 + X3 1 + X4A 1 + X4B 1 + X4D 1 + Y1 1 + Y2 1 + Y3 1 + Y4A 1 + Y4B 1 + ID 117 + X + ID 121 + X + ID 128 + X + ID 117 + X + ID 121 + X + ID 128 + X + ID 117 + X + ID 121 + X + ID 128 + X + ID 117 + X + ID 121 + X + ID 128 + X + """ + +@pytest.mark.version('>=3.0') +def test_core_4177_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4180.py b/tests/bugs/test_core_4180.py new file mode 100644 index 00000000..fa7faa68 --- /dev/null +++ b/tests/bugs/test_core_4180.py @@ -0,0 +1,91 @@ +#coding:utf-8 +# +# id: bugs.core_4180 +# title: CREATE COLLATION does not verify base collation charset +# decription: +# tracker_id: CORE-4180 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table tci(id int); + commit; + + set term ^; + execute block as + begin + begin + execute statement 'drop collation ci_coll'; + when any do begin end + end + + begin + execute statement 'drop collation win1252_unicode'; + when any do begin end + end + end + ^ set term ;^ + commit; + + create collation win1252_unicode for win1252; -- this is special collation named (charset_unicode) + create collation ci_coll for win1252 from win1252_unicode case insensitive; + commit; + + recreate table tci(id int, name varchar(30) character set win1252 collate ci_coll); + commit; + insert into tci(id, name) values(9, 'one Row'); + insert into tci(id, name) values(7, 'One row'); + insert into tci(id, name) values(0, 'oNE row'); + insert into tci(id, name) values(1, 'one ROw'); + insert into tci(id, name) values(5, 'one roW'); + insert into tci(id, name) values(4, 'oNe roW'); + insert into tci(id, name) values(2, 'onE ROw'); + insert into tci(id, name) values(3, 'ONE ROW'); + insert into tci(id, name) values(8, 'oNE rOW'); + insert into tci(id, name) values(1, 'one row'); + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select n1, n2, min(n1) n3, max(n2) n4 + from ( + select n1, n2 + from ( + select min(name) n1, max(name) n2 from tci group by name + union all + select distinct name, name from tci + union all + select distinct max(name), max(name) from tci + ) + order by rand() + ) + group by n1, n2; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +N1 one row +N2 one row +N3 ONE ROW +N4 ONE ROW + """ + +@pytest.mark.version('>=3.0') +def test_core_4180_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4184.py b/tests/bugs/test_core_4184.py new file mode 100644 index 00000000..01fb6741 --- /dev/null +++ b/tests/bugs/test_core_4184.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: bugs.core_4184 +# title: Executing empty EXECUTE BLOCK with NotNull output parameter raised error +# decription: +# tracker_id: CORE-4184 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + execute block + returns (id integer not null) + as + begin + end; + -- Output in 2.5.0 ... 2.5.4: + -- ID + --============ + --Statement failed, SQLSTATE = 42000 + --validation error for variable ID, value "*** null ***" + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +def test_core_4184_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_4198.py b/tests/bugs/test_core_4198.py new file mode 100644 index 00000000..17762ec3 --- /dev/null +++ b/tests/bugs/test_core_4198.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: bugs.core_4198 +# title: Incorrect "token unknown" error when the SQL string ends with a hex number literal +# decription: +# tracker_id: CORE-4198 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select 1 v_passed from rdb$database where 1 = 0x1 ; + select 2 v_failed from rdb$database where 1 = 0x1; -- confirmed fail on 3.0 Alpha1 (passes OK on Alpha2) + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + V_PASSED 1 + V_FAILED 2 + """ + +@pytest.mark.version('>=2.5.3') +def test_core_4198_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4199.py b/tests/bugs/test_core_4199.py new file mode 100644 index 00000000..ab0a062e --- /dev/null +++ b/tests/bugs/test_core_4199.py @@ -0,0 +1,56 @@ +#coding:utf-8 +# +# id: bugs.core_4199 +# title: Add optional START WITH clause to identity columns +# decription: +# We create table with identity column and use 'START WITH' clause for it. +# Then we add three rows in this table and calculate difference betwee max and min +# values of this identity column. In must be equal 2. +# +# ::: NB ::: +# Behaviour of FB 4.x was changed since 06-aug-2020 when core-6084 was fixed: +# now FB 4.x will assign to ID column values which less than FB 3.x for 1. +# For this reason it was changed avoid check for concrete values. +# Rather, it is enough to verify only difference between max and min ID. +# +# Checked on 4.0.0.2164, 3.0.7.33356. +# +# tracker_id: CORE-4199 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test(id int generated by default as identity (start with 1000) ); + commit; + insert into test default values; + insert into test default values; + insert into test default values; + set heading off; + select max(id)-min(id) from test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 2 + """ + +@pytest.mark.version('>=3.0') +def test_core_4199_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4200.py b/tests/bugs/test_core_4200.py new file mode 100644 index 00000000..b199411d --- /dev/null +++ b/tests/bugs/test_core_4200.py @@ -0,0 +1,114 @@ +#coding:utf-8 +# +# id: bugs.core_4200 +# title: An uncommitted select of the pseudo table sec$users blocks new database connections +# decription: +# Checked on: 4.0.0.1635: OK, 1.866s; 3.0.5.33180: OK, 1.869s. +# +# tracker_id: CORE-4200 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('=', '')] + +init_script_1 = """ + -- Drop old account if it remains from prevoius run: + set term ^; + execute block as + begin + begin + execute statement 'drop user tmp$c4200_leg using plugin Legacy_UserManager' with autonomous transaction; + when any do begin end + end + begin + execute statement 'drop user tmp$c4200_srp using plugin Srp' with autonomous transaction; + when any do begin end + end + end + ^ + set term ;^ + commit; + + create user tmp$c4200_leg password '123' using plugin Legacy_UserManager; + create user tmp$c4200_srp password '123' using plugin Srp; + commit; + + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# db_conn.close() +# +# custom_tpb = fdb.TPB() +# custom_tpb.access_mode = fdb.isc_tpb_read +# custom_tpb.isolation_level = (fdb.isc_tpb_read_committed, fdb.isc_tpb_rec_version) +# custom_tpb.lock_resolution = fdb.isc_tpb_nowait +# +# con1=fdb.connect(dsn = dsn, user = 'SYSDBA', password = 'masterkey') +# trn1=con1.trans( default_tpb = custom_tpb ) +# cur1=trn1.cursor() +# cur1.execute('select sec$user_name from sec$users') +# for r in cur1: +# pass +# +# #custom_con = fdb.Connection() +# #custom_con._default_tpb = custom_tpb +# +# con2=fdb.connect( dsn = dsn, user = 'tmp$c4200_leg', password = '123') #, connection_class = custom_con) +# con3=fdb.connect( dsn = dsn, user = 'tmp$c4200_srp', password = '123') #, connection_class = custom_con) +# +# check_sql='select mon$user as who_am_i, mon$auth_method as auth_method from mon$attachments' +# +# trn2=con2.trans( default_tpb = custom_tpb ) +# cur2=trn2.cursor() +# cur2.execute(check_sql) +# +# trn3=con3.trans( default_tpb = custom_tpb ) +# cur3=trn3.cursor() +# cur3.execute(check_sql) +# +# for c in (cur2, cur3): +# cur_cols=c.description +# for r in c: +# for i in range(0,len(cur_cols)): +# print( cur_cols[i][0],':', r[i] ) +# c.close() +# +# trn2.rollback() +# trn3.rollback() +# +# con2.close() +# con3.close() +# +# cur1.close() +# con1.execute_immediate('drop user tmp$c4200_leg using plugin Legacy_UserManager') +# con1.execute_immediate('drop user tmp$c4200_srp using plugin Srp') +# con1.commit() +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHO_AM_I : TMP$C4200_LEG + AUTH_METHOD : Legacy_Auth + WHO_AM_I : TMP$C4200_SRP + AUTH_METHOD : Srp + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4200_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4201.py b/tests/bugs/test_core_4201.py new file mode 100644 index 00000000..bc6a6a49 --- /dev/null +++ b/tests/bugs/test_core_4201.py @@ -0,0 +1,69 @@ +#coding:utf-8 +# +# id: bugs.core_4201 +# title: Regression: Computed field returns null value inside BI trigger +# decription: +# tracker_id: CORE-4201 +# min_versions: ['2.0'] +# versions: 2.0.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table test ( + field1 integer not null, + fld_calc computed by (field1+1), + field2 integer + ); + commit; + + set term ^ ; + + create trigger test_bi0 for test + active before insert position 0 + as + begin + new.field2 = new.fld_calc; + rdb$set_context('USER_TRANSACTION','NEW_FLD1', new.field1); + rdb$set_context('USER_TRANSACTION','FLD_CALC', new.fld_calc); + rdb$set_context('USER_TRANSACTION','NEW_FLD2', new.field2); + end + ^ + set term ; ^ + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + insert into test (field1) values (1); + + set list on; + select + cast(rdb$get_context('USER_TRANSACTION','NEW_FLD1') as bigint) as new_fld1 + ,cast(rdb$get_context('USER_TRANSACTION','FLD_CALC') as bigint) as fld_calc + ,cast(rdb$get_context('USER_TRANSACTION','NEW_FLD2') as bigint) as new_fld2 + from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + NEW_FLD1 1 + FLD_CALC 2 + NEW_FLD2 2 + """ + +@pytest.mark.version('>=2.0.7') +def test_core_4201_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4203.py b/tests/bugs/test_core_4203.py new file mode 100644 index 00000000..7235ce59 --- /dev/null +++ b/tests/bugs/test_core_4203.py @@ -0,0 +1,68 @@ +#coding:utf-8 +# +# id: bugs.core_4203 +# title: Cannot create packaged routines with [VAR]CHAR parameters +# decription: +# tracker_id: CORE-4203 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create package test1 as + begin + function f1(x char(3)) returns char(6) ; + end + ^ + commit ^ + + create package body test1 as + begin + function f1(x char(3)) returns char(6) as + begin + return x; + end + end + ^ + + show package test1 + ^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TEST1 + Header source: + begin + function f1(x char(3)) returns char(6) ; + end + + Body source: + begin + function f1(x char(3)) returns char(6) as + begin + return x; + end + end + """ + +@pytest.mark.version('>=3.0') +def test_core_4203_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4204.py b/tests/bugs/test_core_4204.py new file mode 100644 index 00000000..76931be0 --- /dev/null +++ b/tests/bugs/test_core_4204.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: bugs.core_4204 +# title: Error when compiling the procedure containing the statement if (x = (select ...)) +# decription: +# tracker_id: CORE-4204 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create or alter procedure Test_C + as + declare variable X varchar(16); + begin + + if (x = (select '123' from Rdb$Database)) then + begin + exit; + end + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.3') +def test_core_4204_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_4205.py b/tests/bugs/test_core_4205.py new file mode 100644 index 00000000..e98fe05f --- /dev/null +++ b/tests/bugs/test_core_4205.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: bugs.core_4205 +# title: ISQL -x does not output the START WITH clause of generators/sequences +# decription: +# tracker_id: CORE-4205 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!CREATE GENERATOR).)*$', '')] + +init_script_1 = """ + recreate sequence tmp_gen_42051 start with 9223372036854775807 increment by -2147483647; + recreate sequence tmp_gen_42052 start with -9223372036854775808 increment by 2147483647; + recreate sequence tmp_gen_42053 start with 9223372036854775807 increment by 2147483647; + recreate sequence tmp_gen_42054 start with -9223372036854775808 increment by -2147483647; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# db_conn.close() +# runProgram('isql',[dsn,'-x','-user',user_name,'-password',user_password]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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') +@pytest.mark.xfail +def test_core_4205_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4206.py b/tests/bugs/test_core_4206.py new file mode 100644 index 00000000..96786400 --- /dev/null +++ b/tests/bugs/test_core_4206.py @@ -0,0 +1,72 @@ +#coding:utf-8 +# +# id: bugs.core_4206 +# title: Add RESTART [WITH] clause for alter identity columns +# decription: +# ::: NB ::: +# Behaviour of FB 4.x was changed since 06-aug-2020 when core-6084 was fixed: +# now FB 4.x will assign to ID column values which less than FB 3.x for 1. +# For this reason it was changed avoid check for concrete values. +# Rather, it is enough to verify only difference between max and min ID. +# +# Checked on 4.0.0.2164, 3.0.7.33356. +# +# tracker_id: CORE-4206 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', ''), ('[\t ]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test( + id int generated by default as identity + ,x int + ); + commit; + insert into test(x) values(1); + insert into test(x) values(1); + insert into test(x) values(1); + commit; + + alter table test alter id restart with 40; + commit; + + insert into test(x) values(2); + insert into test(x) values(2); + insert into test(x) values(2); + commit; + + set list on; + select x,max(id)-min(id) as id_diff + from test + group by x + order by x; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + X 1 + ID_DIFF 2 + + X 2 + ID_DIFF 2 + """ + +@pytest.mark.version('>=3.0') +def test_core_4206_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4210.py b/tests/bugs/test_core_4210.py new file mode 100644 index 00000000..9fa35aaf --- /dev/null +++ b/tests/bugs/test_core_4210.py @@ -0,0 +1,106 @@ +#coding:utf-8 +# +# id: bugs.core_4210 +# title: Preserve comments for output parameters after altering procedures +# decription: +# tracker_id: CORE-4210 +# min_versions: ['2.5.3'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + create or alter procedure sp_test as begin end; + commit; + recreate table test(id int); + commit; + set term ^; + execute block as + begin + begin execute statement 'drop domain dm_int'; when any do begin end end + begin execute statement 'drop domain dm_dts'; when any do begin end end + end + ^ + set term ;^ + commit; + + create domain dm_int int not null; + create domain dm_dts timestamp; + commit; + + recreate table test(id dm_int, dts dm_dts); + commit; + + create or alter procedure sp_test ( + a_id1 dm_int, + a_dts1 type of dm_dts + ) returns ( + o_id1 type of column test.id, + o_dts1 type of column test.dts + ) as + begin + end + ; + comment on parameter sp_test.a_id1 is 'input id1'; + comment on parameter sp_test.a_dts1 is 'input timestamp1'; + comment on parameter sp_test.o_id1 is 'output id1'; + comment on parameter sp_test.o_dts1 is 'output timestamp1'; + commit; + + select '' "Before altering proc:" from rdb$database; + show comments; + + alter procedure sp_test ( + a_id1 dm_int, ------------------- OLD name ==> old comment also has to be preserved + a_dts2 type of column test.id + ) returns ( + o_id1 type of column test.id, --- OLD name ==> old comment also has to be preserved + o_dts2 type of column test.dts + ) as + begin + end; + commit; + + select '' "After altering proc:" from rdb$database; + comment on parameter sp_test.a_dts2 is 'input timestamp2'; + comment on parameter sp_test.o_dts2 is 'output timestamp2'; + show comments; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Before altering proc: + + 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; + + After altering proc: + + 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; + """ + +@pytest.mark.version('>=3.0') +def test_core_4210_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4212.py b/tests/bugs/test_core_4212.py new file mode 100644 index 00000000..f4269b4f --- /dev/null +++ b/tests/bugs/test_core_4212.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: bugs.core_4212 +# title: Dropping FK on GTT crashes server +# decription: +# tracker_id: CORE-4212 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core4212.fbk', init=init_script_1) + +test_script_1 = """ +-- 'database': 'Existing', +-- 'database_name': 'core4212-25.fdb', + + set autoddl off; + commit; + alter table t2 drop constraint t2_fk; + rollback; + show table t2; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID VARCHAR(8) Nullable + CONSTRAINT T2_FK: + Foreign key (ID) References T1 (ID) + """ + +@pytest.mark.version('>=2.5.3') +def test_core_4212_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4214.py b/tests/bugs/test_core_4214.py new file mode 100644 index 00000000..24a99525 --- /dev/null +++ b/tests/bugs/test_core_4214.py @@ -0,0 +1,56 @@ +#coding:utf-8 +# +# id: bugs.core_4214 +# title: GTT should not reference permanent relation +# decription: +# tracker_id: CORE-4214 +# min_versions: ['2.5.3'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set autoddl off; + commit; + create global temporary table gtt_main(x int, y int, constraint gtt_main_unq unique(x,y) using index gtt_main_unq); + create table fix_main(x int, y int, constraint fix_main_unq unique(x,y) using index fix_main_unq); + create global temporary table gtt_detl(x int, y int, + constraint gtt_detl_fk_to_gtt foreign key(x,y) references gtt_main(x, y), + constraint gtt_detl_fk_to_fix foreign key(x,y) references fix_main(x, y) + ); + create table fix_detl(x int, y int, + constraint fix_detl_fk_to_fix foreign key(x,y) references fix_main(x, y), + constraint fix_detl_fk_to_gtt foreign key(x,y) references gtt_main(x, y) + ); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + 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 + """ + +@pytest.mark.version('>=3.0') +def test_core_4214_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_4216.py b/tests/bugs/test_core_4216.py new file mode 100644 index 00000000..72f3d49e --- /dev/null +++ b/tests/bugs/test_core_4216.py @@ -0,0 +1,133 @@ +#coding:utf-8 +# +# id: bugs.core_4216 +# title: Memory leak with TRIGGER ON TRANSACTION COMMIT +# decription: +# We create database-level trigger on COMMIT and run loop of 3000 iterations with invoking autonomous transaction. +# Before and after this loop we register memory_used & memory_allocated in order to compare these values after. +# Ratio must be close to 1.05...1.1. +# +# Confirmed valuable memory leak on WI-V2.5.2.26540: memmory_used was increased for ~2.75 times after 3000 iterations. +# MEM_USED_RATIO MEM_ALLOC_RATIO +# ============== ===================== +# 2.7671 2.0729 +# +# FB25SC, build 2.5.8.27090: OK, 2.078s. +# FB30SS, build 3.0.3.32901: OK, 3.063s. +# FB40SS, build 4.0.0.875: OK, 3.704s. +# +# tracker_id: CORE-4216 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + + recreate view v_memo as select 1 i from rdb$database; + commit; + + set term ^; + create or alter trigger trg_commit inactive on transaction commit as + declare c smallint; + begin + select rdb$relation_id from rdb$relations order by rdb$relation_id desc rows 1 into c; + end + ^ + execute block as + begin + execute statement 'drop sequence g'; + when any do begin end + end + ^ + set term ;^ + commit; + + create sequence g; + commit; + + recreate view v_memo as + select + cast( gen_id(g,1) as smallint) as sn, + cast( mon$stat_id as int) as stat_id, + cast( mon$stat_group as int) as stat_gr, + cast( mon$memory_used as int) as mem_used, + cast( mon$memory_allocated as int) as mem_alloc + from mon$memory_usage + where mon$memory_used = (select max(mon$memory_used) from mon$memory_usage) + ; + commit; + + recreate table tlog(sn smallint, stat_id int, stat_gr int, mem_used int, mem_alloc int); + commit; + + alter trigger trg_commit active; + commit; + -------------------------------------- + + insert into tlog select * from v_memo; + commit; + + set term ^; + execute block as + declare n int = 3000; + begin + while ( n > 0 ) do + in autonomous transaction do + select :n - 1 from rdb$database into n; + end + ^ + set term ;^ + + insert into tlog select * from v_memo; + commit; + + -- select * from tlog; + set list on; + select + iif( mem_used_ratio < max_allowed_ratio, 'OK, acceptable.', 'BAD ratio of mem_used: ' || mem_used_ratio || ' - exceeds threshold = ' || max_allowed_ratio) as mem_used_ratio + ,iif( mem_alloc_ratio < max_allowed_ratio, 'OK, acceptable.', 'BAD ratio of mem_alloc: ' || mem_alloc_ratio || ' - exceeds threshold = ' || max_allowed_ratio ) as mem_alloc_ratio + from ( + select + --max(iif(sn=1, mem_used,0)) mu_1 + --,max(iif(sn=2, mem_used,0)) mu_2 + --,max(iif(sn=1, mem_alloc,0)) ma_1 + --,max(iif(sn=2, mem_alloc,0)) ma_2 + cast( 1.0000 * max(iif(sn=2, mem_used,0)) / max(iif(sn=1, mem_used,0)) as numeric(12,4) ) mem_used_ratio + ,cast( 1.0000 * max(iif(sn=2, mem_alloc,0)) / max(iif(sn=1, mem_alloc,0)) as numeric(12,4) ) mem_alloc_ratio + ,1.10 as max_allowed_ratio + -- ^ + -- ########################## + -- ### T H R E S H O L D ### + -- ########################## + from tlog + ) + ; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MEM_USED_RATIO OK, acceptable. + MEM_ALLOC_RATIO OK, acceptable. + """ + +@pytest.mark.version('>=2.5.3') +def test_core_4216_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4218.py b/tests/bugs/test_core_4218.py new file mode 100644 index 00000000..a9bbe1f8 --- /dev/null +++ b/tests/bugs/test_core_4218.py @@ -0,0 +1,97 @@ +#coding:utf-8 +# +# id: bugs.core_4218 +# title: Add database owner to mon$database +# decription: +# tracker_id: CORE-4218 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# import time +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# #db_check=db_conn.database_name +# db_conn.close() +# +# create_user_ddl=''' +# create or alter user TMP_U4218 password '123' revoke admin role; +# grant create database to user TMP_U4218; +# ''' +# +# runProgram('isql',[dsn,'-q'],create_user_ddl) +# +# db_check = os.path.join(context['temp_directory'],'tmp_check_4218.fdb') +# if os.path.isfile(db_check): +# os.remove(db_check) +# +# create_db_sql=''' +# create database 'localhost:%(db_check)s' user 'TMP_U4218' password '123'; +# set list on; +# select current_user as who_am_i, mon$owner as who_is_owner from mon$database; +# commit; +# connect 'localhost:%(db_check)s'; +# select current_user as who_am_i, mon$owner as who_is_owner from mon$database; +# commit; +# drop user TMP_U4218; +# commit; +# revoke create database from user TMP_U4218; +# commit; +# drop database; +# quit; +# ''' % locals() +# +# sqlddl=open( os.path.join(context['temp_directory'],'tmp_create_db_4218.sql'), 'w') +# sqlddl.write(create_db_sql) +# sqlddl.close() +# +# sqllog=open( os.path.join(context['temp_directory'],'tmp_create_db_4218.log'), 'w') +# subprocess.call([ context['isql_path'], "-q", "-i", sqlddl.name],stdout=sqllog, stderr=subprocess.STDOUT) +# sqllog.close() +# +# with open(sqllog.name) as f: +# print( f.read() ) +# +# time.sleep(1) +# +# f_list=[sqlddl, sqllog] +# for i in range(len(f_list)): +# if os.path.isfile(f_list[i].name): +# os.remove(f_list[i].name) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHO_AM_I TMP_U4218 + WHO_IS_OWNER TMP_U4218 + WHO_AM_I SYSDBA + WHO_IS_OWNER TMP_U4218 + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4218_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4224.py b/tests/bugs/test_core_4224.py new file mode 100644 index 00000000..3b5bc3b9 --- /dev/null +++ b/tests/bugs/test_core_4224.py @@ -0,0 +1,146 @@ +#coding:utf-8 +# +# id: bugs.core_4224 +# title: Database replace through services API fails +# decription: +# 13.04.2021. Adapted for run both on Windows and Linux. Checked on: +# Windows: 3.0.8.33445, 4.0.0.2416 +# Linux: 3.0.8.33426, 4.0.0.2416 +# +# tracker_id: CORE-4224 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.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 ) +# +# #-------------------------------------------- +# +# tmpsrc='$(DATABASE_LOCATION)bugs.core_4224.fdb' +# tmpbkp='$(DATABASE_LOCATION)tmp_core_4224.fbk' +# +# fn_bkp_log=open( os.path.join(context['temp_directory'],'tmp_4224_backup.log'), 'w') +# fn_bkp_err=open( os.path.join(context['temp_directory'],'tmp_4224_backup.err'), 'w') +# +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_backup", "dbname", tmpsrc, "bkp_file", tmpbkp ], +# stdout=fn_bkp_log, stderr=fn_bkp_err) +# flush_and_close( fn_bkp_log ) +# flush_and_close( fn_bkp_err ) +# +# src_timestamp1 = -1 +# if os.path.isfile(tmpsrc): +# src_timestamp1 = os.path.getmtime(tmpsrc) +# +# fn_res_log=open( os.path.join(context['temp_directory'],'tmp_4224_restore.log'), 'w') +# fn_res_err=open( os.path.join(context['temp_directory'],'tmp_4224_restore.err'), 'w') +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_restore", "res_replace", "verbose", "bkp_file", tmpbkp, "dbname", tmpsrc ], +# stdout=fn_res_log, stderr=fn_res_err) +# flush_and_close( fn_res_log ) +# flush_and_close( fn_res_err ) +# +# src_timestamp2 = -2 +# if os.path.isfile(tmpsrc): +# src_timestamp2 = os.path.getmtime(tmpsrc) +# +# # Log ERRORS on BACKUP should be EMPTY: +# with open( fn_bkp_err.name,'r') as f: +# for line in f: +# if line.split(): +# print("UNEXPECTED BACKUP STDERR: " + line) +# +# +# # Log ERRORS on RESTORE should also be EMPTY: +# with open( fn_res_err.name,'r') as f: +# for line in f: +# if line.split(): +# print("UNEXPECTED RESTORE STDERR: " + line) +# +# # If restore will fail due to source database in use, its error logs will be like this: +# # RESTORE STDERR: could not drop database <...> (database might be in use) +# # -Exiting before completion due to errors +# # Problems on backup or restore. Timestamps difference is 0.0 +# +# # Difference of timestamps should be positive number: +# src_timestamps_diff = src_timestamp2 - src_timestamp1 +# +# if src_timestamps_diff > 0: +# print("OK: 'fbsvcmgr action_restore res_replace' DID change database file.") +# else: +# print("Problems on backup or restore. Timestamps difference is "+str(src_timestamps_diff)) +# +# ##################################################################### +# # Cleanup: +# +# # do NOT remove this pause otherwise some of logs will not be enable for deletion and test will finish with +# # Exception raised while executing Python test script. exception: WindowsError: 32 +# time.sleep(1) +# cleanup( (fn_bkp_log, fn_bkp_err, fn_res_log, fn_res_err, tmpbkp) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + OK: 'fbsvcmgr action_restore res_replace' DID change database file. + """ + +@pytest.mark.version('>=2.5.3') +@pytest.mark.xfail +def test_core_4224_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4227.py b/tests/bugs/test_core_4227.py new file mode 100644 index 00000000..b61983ec --- /dev/null +++ b/tests/bugs/test_core_4227.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: bugs.core_4227 +# title: Regression: Wrong evaluation of BETWEEN and boolean expressions due to parser conflict +# decription: +# tracker_id: CORE-4227 +# min_versions: ['2.0'] +# versions: 2.0.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select 1 x from rdb$database where rdb$relation_id between 1 and 500 and rdb$description is null; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + X 1 + """ + +@pytest.mark.version('>=2.0.7') +def test_core_4227_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4229.py b/tests/bugs/test_core_4229.py new file mode 100644 index 00000000..2cff6b27 --- /dev/null +++ b/tests/bugs/test_core_4229.py @@ -0,0 +1,231 @@ +#coding:utf-8 +# +# id: bugs.core_4229 +# title: Bidirectional cursor is not positioned by the first call of FETCH LAST +# decription: +# tracker_id: CORE-4229 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table test (name char(31) character set unicode_fss); + commit; + insert into test (name) values ('rdb$view_context'); + insert into test (name) values ('rdb$context_name'); + insert into test (name) values ('rdb$description'); + insert into test (name) values ('rdb$edit_string'); + insert into test (name) values ('rdb$field_id'); + insert into test (name) values ('rdb$field_name'); + insert into test (name) values ('rdb$system_flag'); + insert into test (name) values ('rdb$system_nullflag'); + insert into test (name) values ('rdb$index_id'); + insert into test (name) values ('rdb$index_name'); + insert into test (name) values ('rdb$field_length'); + insert into test (name) values ('rdb$field_position'); + insert into test (name) values ('rdb$field_scale'); + insert into test (name) values ('rdb$field_type'); + insert into test (name) values ('rdb$format'); + insert into test (name) values ('rdb$dbkey_length'); + insert into test (name) values ('rdb$page_number'); + insert into test (name) values ('rdb$page_sequence'); + insert into test (name) values ('rdb$page_type'); + insert into test (name) values ('rdb$query_header'); + insert into test (name) values ('rdb$relation_id'); + insert into test (name) values ('rdb$relation_name'); + insert into test (name) values ('rdb$segment_count'); + insert into test (name) values ('rdb$segment_length'); + insert into test (name) values ('rdb$source'); + insert into test (name) values ('rdb$field_sub_type'); + insert into test (name) values ('rdb$view_blr'); + insert into test (name) values ('rdb$validation_blr'); + insert into test (name) values ('rdb$value'); + insert into test (name) values ('rdb$security_class'); + insert into test (name) values ('rdb$acl'); + insert into test (name) values ('rdb$file_name'); + insert into test (name) values ('rdb$file_name2'); + insert into test (name) values ('rdb$file_sequence'); + insert into test (name) values ('rdb$file_start'); + insert into test (name) values ('rdb$file_length'); + insert into test (name) values ('rdb$file_flags'); + insert into test (name) values ('rdb$trigger_blr'); + insert into test (name) values ('rdb$trigger_name'); + insert into test (name) values ('rdb$generic_name'); + insert into test (name) values ('rdb$function_name'); + insert into test (name) values ('rdb$external_name'); + insert into test (name) values ('rdb$type_name'); + insert into test (name) values ('rdb$dimensions'); + insert into test (name) values ('rdb$runtime'); + insert into test (name) values ('rdb$trigger_sequence'); + insert into test (name) values ('rdb$generic_type'); + insert into test (name) values ('rdb$trigger_type'); + insert into test (name) values ('rdb$object_type'); + insert into test (name) values ('rdb$mechanism'); + insert into test (name) values ('rdb$descriptor'); + insert into test (name) values ('rdb$function_type'); + insert into test (name) values ('rdb$transaction_id'); + insert into test (name) values ('rdb$transaction_state'); + insert into test (name) values ('rdb$timestamp'); + insert into test (name) values ('rdb$transaction_description'); + insert into test (name) values ('rdb$message'); + insert into test (name) values ('rdb$message_number'); + insert into test (name) values ('rdb$user'); + insert into test (name) values ('rdb$privilege'); + insert into test (name) values ('rdb$external_description'); + insert into test (name) values ('rdb$shadow_number'); + insert into test (name) values ('rdb$generator_name'); + insert into test (name) values ('rdb$generator_id'); + insert into test (name) values ('rdb$bound'); + insert into test (name) values ('rdb$dimension'); + insert into test (name) values ('rdb$statistics'); + insert into test (name) values ('rdb$null_flag'); + insert into test (name) values ('rdb$constraint_name'); + insert into test (name) values ('rdb$constraint_type'); + insert into test (name) values ('rdb$deferrable'); + insert into test (name) values ('rdb$match_option'); + insert into test (name) values ('rdb$rule'); + insert into test (name) values ('rdb$file_partitions'); + insert into test (name) values ('rdb$procedure_blr'); + insert into test (name) values ('rdb$procedure_id'); + insert into test (name) values ('rdb$procedure_parameters'); + insert into test (name) values ('rdb$procedure_name'); + insert into test (name) values ('rdb$parameter_name'); + insert into test (name) values ('rdb$parameter_number'); + insert into test (name) values ('rdb$parameter_type'); + insert into test (name) values ('rdb$character_set_name'); + insert into test (name) values ('rdb$character_set_id'); + insert into test (name) values ('rdb$collation_name'); + insert into test (name) values ('rdb$collation_id'); + insert into test (name) values ('rdb$number_of_characters'); + insert into test (name) values ('rdb$exception_name'); + insert into test (name) values ('rdb$exception_number'); + insert into test (name) values ('rdb$file_p_offset'); + insert into test (name) values ('rdb$field_precision'); + insert into test (name) values ('rdb$backup_id'); + insert into test (name) values ('rdb$backup_level'); + insert into test (name) values ('rdb$guid'); + insert into test (name) values ('rdb$scn'); + insert into test (name) values ('rdb$specific_attributes'); + insert into test (name) values ('rdb$plugin'); + insert into test (name) values ('rdb$relation_type'); + insert into test (name) values ('rdb$procedure_type'); + insert into test (name) values ('rdb$attachment_id'); + insert into test (name) values ('rdb$statement_id'); + insert into test (name) values ('rdb$call_id'); + insert into test (name) values ('rdb$stat_id'); + insert into test (name) values ('rdb$pid'); + insert into test (name) values ('rdb$state'); + insert into test (name) values ('rdb$ods_number'); + insert into test (name) values ('rdb$page_size'); + insert into test (name) values ('rdb$page_buffers'); + insert into test (name) values ('rdb$shutdown_mode'); + insert into test (name) values ('rdb$sql_dialect'); + insert into test (name) values ('rdb$sweep_interval'); + insert into test (name) values ('rdb$counter'); + insert into test (name) values ('rdb$remote_protocol'); + insert into test (name) values ('rdb$remote_address'); + insert into test (name) values ('rdb$isolation_mode'); + insert into test (name) values ('rdb$lock_timeout'); + insert into test (name) values ('rdb$backup_state'); + insert into test (name) values ('rdb$stat_group'); + insert into test (name) values ('rdb$debug_info'); + insert into test (name) values ('rdb$parameter_mechanism'); + insert into test (name) values ('rdb$source_info'); + insert into test (name) values ('rdb$context_var_name'); + insert into test (name) values ('rdb$context_var_value'); + insert into test (name) values ('rdb$engine_name'); + insert into test (name) values ('rdb$package_name'); + insert into test (name) values ('rdb$function_id'); + insert into test (name) values ('rdb$function_blr'); + insert into test (name) values ('rdb$argument_name'); + insert into test (name) values ('rdb$argument_mechanism'); + insert into test (name) values ('rdb$identity_type'); + insert into test (name) values ('rdb$boolean'); + insert into test (name) values ('sec$user_name'); + insert into test (name) values ('sec$key'); + insert into test (name) values ('sec$value'); + insert into test (name) values ('sec$name_part'); + insert into test (name) values ('rdb$client_version'); + insert into test (name) values ('rdb$remote_version'); + insert into test (name) values ('rdb$host_name'); + insert into test (name) values ('rdb$os_user'); + insert into test (name) values ('rdb$generator_value'); + insert into test (name) values ('rdb$auth_method'); + insert into test (name) values ('rdb$linger'); + insert into test (name) values ('rdb$map_name'); + insert into test (name) values ('rdb$map_using'); + insert into test (name) values ('rdb$map_db'); + insert into test (name) values ('rdb$map_from_type'); + insert into test (name) values ('rdb$map_from'); + insert into test (name) values ('rdb$map_to'); + insert into test (name) values ('rdb$generator_increment'); + insert into test (name) values ('rdb$plan'); + insert into test (name) values ('rdb$1'); + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + set term ^; + execute block returns (name type of column test.name, rc int) + as + declare c scroll cursor for (select t.name from test t); + begin + open c; + fetch first from c + into :name; + rc = row_count; + suspend; + + fetch last from c + into :name; + rc = row_count; + suspend; + + close c; + end + ^ + + execute block returns (name type of column test.name, rc int) + as + declare c scroll cursor for (select t.name from test t); + begin + open c; + fetch last from c + into :name; + rc = row_count; + suspend; + + close c; + end + ^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + NAME rdb$view_context + RC 1 + NAME rdb$1 + RC 1 + NAME rdb$1 + RC 1 + """ + +@pytest.mark.version('>=3.0') +def test_core_4229_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4233.py b/tests/bugs/test_core_4233.py new file mode 100644 index 00000000..94b667f3 --- /dev/null +++ b/tests/bugs/test_core_4233.py @@ -0,0 +1,78 @@ +#coding:utf-8 +# +# id: bugs.core_4233 +# title: In PSQL modules with declared cursors engine could assign value to the wrong variable +# decription: +# tracker_id: CORE-4233 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """ + set term ^; + create or alter procedure hidden_vars + returns (out_a int, out_b1 int, out_b2 int) + as + declare a int; + declare c cursor for + (select + coalesce( (select count(*) from rdb$relations), -1) + -- Aliasing of expression results in derived tables is mandatory in 3.0 + -- otherwise get error about metadata updating: + -- -no column name specified for column number 1 in derived table + -- + as tabs_cnt -- <<<<<<<<<<<<<<< nb <<<<<<<<<<< + from rdb$database + ); + declare b int = 0; + begin + out_b1 = b; + + open c; + fetch c into :a; + close c; + + out_a = a; + out_b2 = b; + b = b + 1; + suspend; + end ^ + set term ; ^ + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + select out_b1, out_b2 from hidden_vars; + select out_b1, out_b2 from hidden_vars; + select out_b1, out_b2 from hidden_vars; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ OUT_B1 OUT_B2 +============ ============ + 0 0 + OUT_B1 OUT_B2 +============ ============ + 0 0 + OUT_B1 OUT_B2 +============ ============ + 0 0 + """ + +@pytest.mark.version('>=2.5.3') +def test_core_4233_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4234.py b/tests/bugs/test_core_4234.py new file mode 100644 index 00000000..b35bdeae --- /dev/null +++ b/tests/bugs/test_core_4234.py @@ -0,0 +1,67 @@ +#coding:utf-8 +# +# id: bugs.core_4234 +# title: Error with IF (subfunc()) when subfunc returns a boolean +# decription: +# tracker_id: CORE-4234 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set term ^; + execute block returns (c integer) as + declare variable b boolean; + declare function f1() returns boolean as + begin + return true; + end + begin + c = 0; + b = f1(); + if (b) then c = 1; + suspend; + end + ^ + + execute block returns (c integer) as + declare variable b boolean; + declare function f1() returns boolean as + begin + return true; + end + begin + c = 0; + b = f1(); + if (f1()) then c = 2; + suspend; + end + ^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + C 1 + C 2 + """ + +@pytest.mark.version('>=3.0') +def test_core_4234_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4236.py b/tests/bugs/test_core_4236.py new file mode 100644 index 00000000..f400298e --- /dev/null +++ b/tests/bugs/test_core_4236.py @@ -0,0 +1,284 @@ +#coding:utf-8 +# +# id: bugs.core_4236 +# title: Database shutdown is reported as successfully completed before all active connections are in fact interrupted +# decription: +# Test restores database with single table of following DDL: +# create table test(s varchar(1000)); +# create index test_s on test(s); +# Than we start asynchronously several ISQL attachments which will do 'heavy DML' job: insert lot of rows in this table. +# After some delay (IMO, it should be at least 15..20 seconds) we start process of SHUTDOWN but with target mode = 'single' +# instead of 'full'. +# After control will return from shutdown command, we can ensure that database has no any access and its file is closed +# - this is done by call FBSVCMGR utility with arguments: action_repair rpr_validate_db rpr_full. This will launch process +# of database validation and it requires exclusive access, like 'gfix -v -full'. +# If validation will be able to open database in exclusive mode and do its job than NO any output will be produced. +# Any problem with exclusive DB access will lead to error with text like: "database shutdown". +# Finally, we check that: +# 1) output of validation is really EMPTY - no any rows should present between two intentionally added lines +# ("Validation start" and "validation finish" - they will be added only to improve visual perception of log); +# 2) Every launched ISQL was really able to perform its task: at least to insert 100 row in the table, this result should +# be reflected in its log by message 'INS_PROGRESS ...' - it is suspended from EB every 100 rows. +# 3) Every launched ISQL was really received exception with SQLCODE = HY000 - it also should be added at the end of ISQL log. +# +# Checked on WI-V3.0.0.32253, SS/SC/CS (OS=Win XP), with 30 attachments that worked for 30 seconds. +# NB: Issue about hang CS was found during this test implementation, fixed here: +# http://sourceforge.net/p/firebird/code/62737 +# +# Refactored 13-aug-2020: +# validation result is verified by inspecting difflib.unified_diff() result between firebird.log that was +# before and after validation: it must contain phrase "Validation finished: 0 errors" +# (we check that both validation *did* complete and absense of errors in DB). +# Checked on 4.0.0.2144 CS, 4.0.0.2151 SS. +# +# tracker_id: CORE-4236 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('VALIDATION FINISHED: 0 ERRORS.*', 'VALIDATION FINISHED: 0 ERRORS')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core4236.fbk', init=init_script_1) + +# test_script_1 +#--- +# import os +# import sys +# import subprocess +# from subprocess import Popen +# import time +# import re +# import difflib +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_file=db_conn.database_name +# db_conn.close() +# +# PLANNED_DML_ATTACHMENTS = 20 +# WAIT_FOR_ALL_CONNECTIONS_START_JOB = 20 +# +# #----------------------------------- +# +# 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() +# os.fsync(file_handle.fileno()) +# +# file_handle.close() +# +# #-------------------------------------------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# def svc_get_fb_log( f_fb_log ): +# +# global subprocess +# subprocess.call( [ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# "action_get_fb_log" +# ], +# stdout=f_fb_log, stderr=subprocess.STDOUT +# ) +# return +# +# #-------------------------------------------- +# +# dmltxt=''' +# set bail on; +# set list on; +# set term ^; +# execute block returns(ins_progress int) as +# declare n int = 100000; +# begin +# ins_progress=0; +# while ( n > 0 ) do +# begin +# insert into test(s) values( rpad('', 500, uuid_to_char(gen_uuid())) ); +# +# ins_progress = ins_progress + 1; +# if ( mod(ins_progress, 100) = 0 ) then suspend; +# +# n = n - 1; +# end +# end +# ^ set term ;^ +# quit; +# ''' +# +# f_sql_cmd=open( os.path.join(context['temp_directory'],'tmp_dml_4236.sql'), 'w') +# f_sql_cmd.write(dmltxt) +# flush_and_close(f_sql_cmd) +# +# isql_logs_list = [] +# isql_pids_list = [] +# +# ######################################################################################## +# # S T A R T I N G S E V E R A L I S Q L s W I T H H E A V Y D M L J O B +# ######################################################################################## +# +# for i in range(0, PLANNED_DML_ATTACHMENTS): +# sqllog=open( os.path.join(context['temp_directory'],'tmp_dml_4236_'+str(i)+'.log'), 'w') +# isql_logs_list.append(sqllog) +# +# for i in range(len(isql_logs_list)): +# p_isql=Popen( [ context['isql_path'] , "localhost:"+db_file, "-i", f_sql_cmd.name ], +# stdout=isql_logs_list[i], stderr=subprocess.STDOUT +# ) +# isql_pids_list.append(p_isql) +# +# # Delay: let ISQL sessions do their job: +# ######## +# time.sleep( WAIT_FOR_ALL_CONNECTIONS_START_JOB ) +# +# # Move database to shutdown with ability to run after it validation (prp_sm_single): +# +# ########################################################################################### +# # S H U T D O W N D A T A B A S E W I T H T A R G E T A C C E S S = 'S I N G L E' +# ########################################################################################### +# f_shutdown_log=open( os.path.join(context['temp_directory'],'tmp_shutdown_4236.log'), 'w') +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_properties", "dbname", db_file, +# "prp_shutdown_mode", "prp_sm_single", +# "prp_force_shutdown", "0"], +# stdout=f_shutdown_log, stderr=subprocess.STDOUT) +# flush_and_close( f_shutdown_log ) +# +# # At this point no further I/O should be inside database, including internal engine actions +# # that relate to backouts. This mean that we *must* have ability to run DB validation in +# # _exclusive_ mode, like gfix -v -full does. +# +# # Only for DEBUG: when this line is uncommented, validation should FAIL with message: database shutdown. +# # Normally this line should be commented. +# # conx = kdb.connect(dsn='localhost:'+db_file, user='SYSDBA', password='masterkey') +# +# # ........................ get firebird.log _before_ validation .............................. +# f_fblog_before=open( os.path.join(context['temp_directory'],'tmp_4236_fblog_before.txt'), 'w') +# svc_get_fb_log( f_fblog_before ) +# flush_and_close( f_fblog_before ) +# +# +# # Run validation that requires exclusive database access. +# # This process normally should produce NO output at all, it is "silent". +# # If database currently is in use by engine or some attachments than it shoudl fail +# # with message "database shutdown." +# +# ###################################################################### +# # V A L I D A T I O N W I T H E X C L U S I V E A C C E S S +# ###################################################################### +# f_validate_log=open( os.path.join(context['temp_directory'],'tmp_validate_4236.log'), 'w') +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_repair", "dbname", db_file, +# "rpr_validate_db", "rpr_full"], +# stdout=f_validate_log, stderr=subprocess.STDOUT) +# flush_and_close( f_validate_log ) +# +# # ........................ get firebird.log _before_ validation .............................. +# f_fblog_after=open( os.path.join(context['temp_directory'],'tmp_4236_fblog_after.txt'), 'w') +# svc_get_fb_log( f_fblog_after ) +# flush_and_close( f_fblog_after ) +# +# +# # Compare firebird.log versions BEFORE and AFTER validation: +# ###################### +# +# oldfb=open(f_fblog_before.name, 'r') +# newfb=open(f_fblog_after.name, 'r') +# +# difftext = ''.join(difflib.unified_diff( +# oldfb.readlines(), +# newfb.readlines() +# )) +# oldfb.close() +# newfb.close() +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_4236_diff.txt'), 'w') +# f_diff_txt.write(difftext) +# flush_and_close( f_diff_txt ) +# +# # We are ionteresting only for line that contains result of validation: +# p=re.compile('validation[ ]+finished(:){0,1}[ ]+\\d+[ ]errors', re.IGNORECASE) +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# if line.startswith('+') and p.search(line): +# print( 'DIFF IN FIREBIRD.LOG: ' + (' '.join(line.split()).upper()) ) +# +# #/////////////////////////////////////////////////////////////////////////////////// +# +# for i in range(len(isql_pids_list)): +# isql_pids_list[i].terminate() +# +# for i in range(len(isql_logs_list)): +# flush_and_close( isql_logs_list[i] ) +# +# actual_dml_attachments = 0 +# logged_shutdown_count = 0 +# +# for i in range(len(isql_logs_list)): +# f = open(isql_logs_list[i].name, 'r') +# sqllog=f.read() +# f.close() +# +# if 'INS_PROGRESS' in sqllog: +# actual_dml_attachments += 1 +# if 'SQLSTATE = HY000' in sqllog: +# logged_shutdown_count += 1 +# +# print("Check-1: how many DML attachments really could do their job ?") +# if PLANNED_DML_ATTACHMENTS == actual_dml_attachments: +# print("Result: OK, launched = actual") +# else: +# print("Result: BAD, launched<>actual") +# +# print("Check-2: how many sessions got SQLSTATE = HY000 on shutdown ?") +# if PLANNED_DML_ATTACHMENTS == logged_shutdown_count: +# print("Result: OK, launched = actual") +# else: +# print("Result: BAD, launched<>actual") +# +# # CLEANUP: +# ########## +# f_list = [x.name for x in [ f_sql_cmd,f_shutdown_log,f_validate_log,f_fblog_before,f_fblog_after,f_diff_txt ] + isql_logs_list ] #### + [ isql_logs_list ] ] +# cleanup( f_list ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DIFF IN FIREBIRD.LOG: + VALIDATION FINISHED: 0 ERRORS, 0 WARNINGS, 0 FIXED + Check-1: how many DML attachments really could do their job ? + Result: OK, launched = actual + Check-2: how many sessions got SQLSTATE = HY000 on shutdown ? + Result: OK, launched = actual + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4236_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4240.py b/tests/bugs/test_core_4240.py new file mode 100644 index 00000000..7ec311d3 --- /dev/null +++ b/tests/bugs/test_core_4240.py @@ -0,0 +1,99 @@ +#coding:utf-8 +# +# id: bugs.core_4240 +# title: Regression: recursive query in SQL query returns incorrect results if more than one branch bypass +# decription: +# tracker_id: CORE-4240 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('=', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + with recursive h + as (select 1 as code_horse, + 2 as code_father, + 3 as code_mother + from rdb$database + union all + select 2 as code_horse, + 4 as code_father, + 5 as code_mother + from rdb$database + union all + select 3 as code_horse, + 4 as code_father, + 5 as code_mother + from rdb$database + union all + select 4 as code_horse, + null as code_father, + null as code_mother + from rdb$database + union all + select 5 as code_horse, + null as code_father, + null as code_mother + from rdb$database), + r + as (select h.code_horse as code_horse, + h.code_father as code_father, + h.code_mother as code_mother, + cast('' as varchar(10)) as mark, + 0 as depth + from h + where h.code_horse = 1 + union all + select h.code_horse as code_horse, + h.code_father as code_father, + h.code_mother as code_mother, + 'f' || r.mark as mark, + r.depth + 1 as depth + from r + join h on r.code_father = h.code_horse + where r.depth < 5 + union all + select h.code_horse as code_horse, + h.code_father as code_father, + h.code_mother as code_mother, + 'm' || r.mark as mark, + r.depth + 1 as depth + from r + join h on r.code_mother = h.code_horse + where r.depth < 5) + select * + from r + order by 1,2,3,4,5 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CODE_HORSE CODE_FATHER CODE_MOTHER MARK DEPTH + 1 2 3 0 + 2 4 5 f 1 + 3 4 5 m 1 + 4 ff 2 + 4 fm 2 + 5 mf 2 + 5 mm 2 + """ + +@pytest.mark.version('>=3.0') +def test_core_4240_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4244.py b/tests/bugs/test_core_4244.py new file mode 100644 index 00000000..d1e885e7 --- /dev/null +++ b/tests/bugs/test_core_4244.py @@ -0,0 +1,61 @@ +#coding:utf-8 +# +# id: bugs.core_4244 +# title: Problem with creation procedure which contain adding text in DOS864 charset +# decription: +# tracker_id: CORE-4244 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create or alter procedure sp_test as + 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 + ^ + 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; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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 + """ + +@pytest.mark.version('>=2.5.2') +def test_core_4244_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4247.py b/tests/bugs/test_core_4247.py new file mode 100644 index 00000000..3e00b67b --- /dev/null +++ b/tests/bugs/test_core_4247.py @@ -0,0 +1,81 @@ +#coding:utf-8 +# +# id: bugs.core_4247 +# title: Delete "where current of" cursor fails for tables with newly added fields +# decription: Scenario has been taken from attachment to this ticket +# tracker_id: CORE-4247 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create table test_table (id integer not null, desc varchar(10)); + alter table test_table add constraint pk_test_table primary key (id); + commit; + + insert into test_table (id, desc) values (1, 'a'); + insert into test_table (id, desc) values (2, 'b'); + insert into test_table (id, desc) values (3, 'c'); + insert into test_table (id, desc) values (4, 'd'); + insert into test_table (id, desc) values (5, 'e'); + insert into test_table (id, desc) values (6, 'f'); + insert into test_table (id, desc) values (7, 'g'); + insert into test_table (id, desc) values (8, 'h'); + insert into test_table (id, desc) values (9, 'i'); + insert into test_table (id, desc) values (10, 'k'); + commit; + + alter table test_table add seqno integer; + commit; + + -- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + -- without this update - everything works + update test_table set seqno=id where id>=5; + commit; + + set term ^ ; + create or alter procedure test_cursor + as + declare variable id integer; + declare variable desc varchar(10); + declare variable seqno integer; + begin + for + select id, desc, seqno from test_table + order by seqno -- if seqno values are unique - it works. With "order by id" works + into + :id, :desc, :seqno + as cursor data_cursor + do begin + delete from test_table where current of data_cursor; -- this fails !!! + -- with dummy suspend stored procedure works even it does not require to return any results + --suspend; + end + end^ + set term ; ^ + + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + execute procedure test_cursor; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.3') +def test_core_4247_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_4252.py b/tests/bugs/test_core_4252.py new file mode 100644 index 00000000..8496cc0a --- /dev/null +++ b/tests/bugs/test_core_4252.py @@ -0,0 +1,69 @@ +#coding:utf-8 +# +# id: bugs.core_4252 +# title: Add table name to text of validation contraint error message, to help identify error context +# decription: +# tracker_id: CORE-4252 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [('line:.*', ''), ('col:.*', '')] + +init_script_1 = """ + create or alter procedure sp_test(a_arg smallint) as begin end; + commit; + + recreate table t1(x int not null ); + recreate table "T2"("X" int not null ); + commit; + + set term ^; + create or alter procedure sp_test(a_arg smallint) as + begin + if ( a_arg = 1 ) then insert into t1(x) values(null); + else insert into "T2"("X") values(null); + end + ^ + set term ;^ + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + show table t1; + show table "T2"; + execute procedure sp_test(1); + execute procedure sp_test(2); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + X INTEGER Not Null + X INTEGER Not Null + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 23000 + validation error for column "T1"."X", value "*** null ***" + -At procedure 'SP_TEST' line: 3, col: 26 + Statement failed, SQLSTATE = 23000 + validation error for column "T2"."X", value "*** null ***" + -At procedure 'SP_TEST' line: 4, col: 8 + """ + +@pytest.mark.version('>=2.5.3') +def test_core_4252_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4255.py b/tests/bugs/test_core_4255.py new file mode 100644 index 00000000..1b079962 --- /dev/null +++ b/tests/bugs/test_core_4255.py @@ -0,0 +1,79 @@ +#coding:utf-8 +# +# id: bugs.core_4255 +# title: Parametrized queries using RDB$DB_KEY do not work +# decription: +# tracker_id: CORE-4255 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- test by Mark: + recreate table dbkeytest + ( + id integer primary key, + seen boolean default false + ); + commit; + insert into dbkeytest (id) values (1); + insert into dbkeytest (id) values (2); + insert into dbkeytest (id) values (3); + insert into dbkeytest (id) values (4); + commit; + + -- actual test: + set term ^; + execute block + as + declare thekey char(8); + declare theid integer; + begin + for select id, rdb$db_key from dbkeytest into theid, thekey do + begin + execute statement ('update dbkeytest set seen = true where rdb$db_key = ?') (thekey); + end + end + ^ + set term ;^ + commit; + + select * from dbkeytest; + + -- one else test (suggested by Dmitry) in this ticket: + select 1 x from rdb$database where rdb$db_key = cast((select rdb$db_key from rdb$database) as varchar(8)); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID SEEN + ============ ======= + 1 + 2 + 3 + 4 + + X + ============ + 1 + """ + +@pytest.mark.version('>=3.0') +def test_core_4255_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4258.py b/tests/bugs/test_core_4258.py new file mode 100644 index 00000000..97177f7b --- /dev/null +++ b/tests/bugs/test_core_4258.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: bugs.core_4258 +# title: Regression: Wrong boundary for minimum value for BIGINT/DECIMAL(18) +# decription: +# tracker_id: CORE-4258 +# min_versions: ['2.1'] +# versions: 2.1.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table test(x decimal(18), y bigint); + commit; + insert into test values( -9223372036854775808, -9223372036854775808); + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select * from test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + X -9223372036854775808 + Y -9223372036854775808 + """ + +@pytest.mark.version('>=2.1.7') +def test_core_4258_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_426.py b/tests/bugs/test_core_426.py new file mode 100644 index 00000000..5e0adcc8 --- /dev/null +++ b/tests/bugs/test_core_426.py @@ -0,0 +1,147 @@ +#coding:utf-8 +# +# id: bugs.core_426 +# title: Wrong sort order when using es_ES collate +# decription: Check if sort order for collate ES_ES is the one of DRAE , the oficial organization for standarization of spanish +# tracker_id: CORE-426 +# min_versions: [] +# versions: 2.1 +# qmid: bugs.core_426 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """SET NAMES ISO8859_1; +CREATE TABLE TAB (A CHAR(3) CHARACTER SET ISO8859_1); +COMMIT; +INSERT INTO TAB VALUES ('zo'); +INSERT INTO TAB VALUES ('ze'); +INSERT INTO TAB VALUES ('yo'); +INSERT INTO TAB VALUES ('ye'); +INSERT INTO TAB VALUES ('xo'); +INSERT INTO TAB VALUES ('xe'); +INSERT INTO TAB VALUES ('vo'); +INSERT INTO TAB VALUES ('ve'); +INSERT INTO TAB VALUES ('uo'); +INSERT INTO TAB VALUES ('ue'); +INSERT INTO TAB VALUES ('to'); +INSERT INTO TAB VALUES ('te'); +INSERT INTO TAB VALUES ('so'); +INSERT INTO TAB VALUES ('se'); +INSERT INTO TAB VALUES ('ro'); +INSERT INTO TAB VALUES ('re'); +INSERT INTO TAB VALUES ('qo'); +INSERT INTO TAB VALUES ('qe'); +INSERT INTO TAB VALUES ('po'); +INSERT INTO TAB VALUES ('pe'); +INSERT INTO TAB VALUES ('oo'); +INSERT INTO TAB VALUES ('oe'); +INSERT INTO TAB VALUES ('no'); +INSERT INTO TAB VALUES ('ne'); +INSERT INTO TAB VALUES ('mo'); +INSERT INTO TAB VALUES ('me'); +INSERT INTO TAB VALUES ('llo'); +INSERT INTO TAB VALUES ('lle'); +INSERT INTO TAB VALUES ('lo'); +INSERT INTO TAB VALUES ('le'); +INSERT INTO TAB VALUES ('ko'); +INSERT INTO TAB VALUES ('ke'); +INSERT INTO TAB VALUES ('jo'); +INSERT INTO TAB VALUES ('je'); +INSERT INTO TAB VALUES ('io'); +INSERT INTO TAB VALUES ('ie'); +INSERT INTO TAB VALUES ('ho'); +INSERT INTO TAB VALUES ('he'); +INSERT INTO TAB VALUES ('go'); +INSERT INTO TAB VALUES ('fe'); +INSERT INTO TAB VALUES ('fo'); +INSERT INTO TAB VALUES ('fe'); +INSERT INTO TAB VALUES ('eo'); +INSERT INTO TAB VALUES ('ee'); +INSERT INTO TAB VALUES ('do'); +INSERT INTO TAB VALUES ('de'); +INSERT INTO TAB VALUES ('cho'); +INSERT INTO TAB VALUES ('cha'); +INSERT INTO TAB VALUES ('co'); +INSERT INTO TAB VALUES ('ce'); +INSERT INTO TAB VALUES ('bo'); +INSERT INTO TAB VALUES ('be'); +INSERT INTO TAB VALUES ('ao'); +INSERT INTO TAB VALUES ('ae');""" + +db_1 = db_factory(charset='ISO8859_1', sql_dialect=3, init=init_script_1) + +test_script_1 = """SET HEADING OFF; +SELECT A FROM TAB ORDER BY A COLLATE ES_ES; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ae +ao +be +bo +ce +cha +cho +co +de +do +ee +eo +fe +fe +fo +go +he +ho +ie +io +je +jo +ke +ko +le +lle +llo +lo +me +mo +ne +no +oe +oo +pe +po +qe +qo +re +ro +se +so +te +to +ue +uo +ve +vo +xe +xo +ye +yo +ze +zo + +""" + +@pytest.mark.version('>=2.1') +def test_core_426_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4261b.py b/tests/bugs/test_core_4261b.py new file mode 100644 index 00000000..dfe781ce --- /dev/null +++ b/tests/bugs/test_core_4261b.py @@ -0,0 +1,210 @@ +#coding:utf-8 +# +# id: bugs.core_4261b +# title: Check result when joined fields are created via row_number() function +# decription: +# tracker_id: CORE-4261 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """ + recreate table bbb(id int); commit; + recreate table yyy(id int primary key, c varchar(3)); commit; + recreate table bbb(tm timestamp, qi int, vi int references yyy, bv int, constraint bbb_pk primary key (tm, qi, vi)); + commit; + insert into yyy (id, c) values ( 1, 'rio'); + insert into yyy (id, c) values ( 2, 'rio'); + insert into yyy (id, c) values ( 3, 'rio'); + insert into yyy (id, c) values ( 4, 'foo'); + insert into yyy (id, c) values ( 5, 'foo'); + insert into yyy (id, c) values ( 6, 'foo'); + insert into yyy (id, c) values ( 7, 'bar'); + insert into yyy (id, c) values ( 8, 'bar'); + insert into yyy (id, c) values ( 9, 'bar'); + insert into yyy (id, c) values (10, 'rio'); + insert into yyy (id, c) values (11, 'rio'); + insert into yyy (id, c) values (12, 'rio'); + insert into yyy (id, c) values (13, 'foo'); + insert into yyy (id, c) values (14, 'foo'); + insert into yyy (id, c) values (15, 'bar'); + insert into yyy (id, c) values (16, 'bar'); + insert into yyy (id, c) values (17, 'rio'); + insert into yyy (id, c) values (18, 'foo'); + insert into yyy (id, c) values (19, 'bar'); + insert into yyy (id, c) values (20, 'rio'); + insert into yyy (id, c) values (21, 'foo'); + insert into yyy (id, c) values (22, 'bar'); + insert into yyy (id, c) values (23, 'rio'); + insert into yyy (id, c) values (24, 'foo'); + insert into yyy (id, c) values (25, 'bar'); + insert into yyy (id, c) values (26, 'bar'); + insert into yyy (id, c) values (27, 'rio'); + insert into yyy (id, c) values (28, 'foo'); + insert into yyy (id, c) values (29, 'rio'); + insert into yyy (id, c) values (30, 'foo'); + insert into yyy (id, c) values (31, 'rio'); + insert into yyy (id, c) values (32, 'foo'); + insert into yyy (id, c) values (33, 'bar'); + insert into yyy (id, c) values (34, 'rio'); + insert into yyy (id, c) values (35, 'foo'); + insert into yyy (id, c) values (36, 'bar'); + insert into yyy (id, c) values (37, 'rio'); + insert into yyy (id, c) values (38, 'foo'); + insert into yyy (id, c) values (39, 'bar'); + insert into yyy (id, c) values (40, 'rio'); + insert into yyy (id, c) values (41, 'rio'); + insert into yyy (id, c) values (42, 'foo'); + insert into yyy (id, c) values (43, 'bar'); + insert into yyy (id, c) values (44, 'rio'); + insert into yyy (id, c) values (45, 'foo'); + insert into yyy (id, c) values (46, 'bar'); + insert into yyy (id, c) values (47, 'bar'); + insert into yyy (id, c) values (48, 'foo'); + insert into yyy (id, c) values (49, 'rio'); + insert into yyy (id, c) values (50, 'foo'); + insert into yyy (id, c) values (51, 'bar'); + insert into yyy (id, c) values (52, 'rio'); + insert into yyy (id, c) values (53, 'foo'); + insert into yyy (id, c) values (54, 'bar'); + commit; + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:01', 1, 1, 155); + insert into bbb (tm, qi, vi, bv) values ('23-jun-2003 01:12:02', 1, 1, 100); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:03', 2, 2, 255); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:04', 3, 3, 255); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:05', 1, 4, 255); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:06', 2, 5, 255); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:07', 3, 6, 255); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:08', 1, 7, 255); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:09', 2, 8, 255); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:10', 3, 9, 255); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:11', 4, 10, 50); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:12', 5, 11, 100); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:13', 5, 12, 155); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:14', 5, 13, 155); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:15', 5, 14, 100); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:16', 5, 15, 50); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:17', 5, 16, 205); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:18', 6, 10, 155); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:19', 6, 17, 100); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:20', 6, 18, 255); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:21', 6, 19, 255); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:22', 7, 17, 155); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:23', 7, 20, 100); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:24', 7, 21, 255); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:25', 7, 22, 255); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:26', 8, 10, 50); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:27', 9, 23, 255); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:28', 9, 24, 255); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:29', 9, 25, 100); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:30', 9, 26, 155); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:31', 10, 25, 155); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:31', 10, 26, 100); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:33', 10, 27, 10); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:34', 10, 28, 10); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:35', 10, 29, 245); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:36', 10, 30, 245); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:37', 11, 31, 100); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:38', 11, 32, 100); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:39', 11, 33, 100); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:40', 11, 34, 155); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:41', 11, 35, 155); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:42', 11, 36, 155); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:43', 12, 31, 155); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:44', 12, 32, 155); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:45', 12, 33, 155); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:46', 12, 34, 100); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:47', 12, 35, 100); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:12:48', 12, 36, 100); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:13:01', 4, 37, 20); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:13:02', 8, 38, 20); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:13:03', 13, 39, 123); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:13:04', 14, 39, 111); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:13:05', 14, 40, 50); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:13:06', 15, 41, 50); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:13:07', 15, 41, 50); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:13:08', 15, 42, 50); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:13:09', 15, 42, 50); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:13:10', 16, 42, 50); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:13:11', 16, 42, 50); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:13:12', 16, 43, 50); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:13:13', 16, 43, 50); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:13:14', 16, 47, 50); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:13:15', 17, 44, 10); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:13:16', 17, 44, 10); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:13:17', 17, 45, 10); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:13:18', 17, 45, 10); + insert into bbb (tm, qi, vi, bv) values ('1-feb-2003 01:13:19', 18, 45, 10); + insert into bbb (tm, qi, vi, bv) values ('1-mar-2003 01:13:20', 18, 45, 10); + insert into bbb (tm, qi, vi, bv) values ('1-apr-2003 01:13:21', 18, 46, 10); + insert into bbb (tm, qi, vi, bv) values ('1-may-2003 01:13:22', 18, 46, 10); + insert into bbb (tm, qi, vi, bv) values ('11-jun-2003 01:13:23', 19, 44, 10); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:13:24', 19, 44, 10); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:13:25', 19, 45, 10); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:13:26', 19, 45, 10); + insert into bbb (tm, qi, vi, bv) values ('1-feb-2003 01:13:27', 20, 45, 10); + insert into bbb (tm, qi, vi, bv) values ('1-mar-2003 01:13:28', 20, 45, 10); + insert into bbb (tm, qi, vi, bv) values ('1-apr-2003 01:13:29', 20, 46, 10); + insert into bbb (tm, qi, vi, bv) values ('1-may-2003 01:13:30', 20, 46, 10); + insert into bbb (tm, qi, vi, bv) values ('1-feb-2003 01:13:31', 21, 49, 50); + insert into bbb (tm, qi, vi, bv) values ('2-feb-2003 01:13:32', 21, 49, 50); + insert into bbb (tm, qi, vi, bv) values ('3-feb-2003 01:13:33', 21, 50, 50); + insert into bbb (tm, qi, vi, bv) values ('4-feb-2003 01:13:34', 21, 50, 50); + insert into bbb (tm, qi, vi, bv) values ('5-feb-2003 01:13:35', 21, 48, 1); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2000 01:13:36', 22, 50, 50); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2001 01:13:37', 22, 50, 50); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2002 01:13:38', 22, 51, 50); + insert into bbb (tm, qi, vi, bv) values ('1-jun-2002 01:13:39', 22, 51, 50); + insert into bbb (tm, qi, vi, bv) values ('1-jan-2003 01:13:05', 4, 37, 185); + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + with + c as( + select + b.qi, v.c + ,row_number()over(order by b.qi, b.tm, b.vi) r + from bbb b join yyy v on v.id = b.vi + ) + select t1.r r1, t2.r r2, t3.r r3 + from c t1 + left join c t2 on t1.qi = t2.qi and t1.r = t2.r-1 + left join c t3 on t2.qi = t3.qi and t1.r = t3.r-2 + where t1.c = 'rio' and t2.c = 'foo' and t3.c = 'bar' + order by 1,2,3; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + R1 R2 R3 +===================== ===================== ===================== + 1 2 3 + 5 6 7 + 8 9 10 + 21 22 23 + 25 26 27 + 30 31 32 + 40 41 42 + 43 44 45 + 46 47 48 + 49 50 51 + """ + +@pytest.mark.version('>=3.0') +def test_core_4261b_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4262.py b/tests/bugs/test_core_4262.py new file mode 100644 index 00000000..9485af31 --- /dev/null +++ b/tests/bugs/test_core_4262.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: bugs.core_4262 +# title: Context parsing error with derived tables and CASE functions +# decription: +# tracker_id: CORE-4262 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """set planonly; +select col as col1, col as col2 +from ( + select case when exists (select 1 from rdb$database ) then 1 else 0 end as col + from rdb$relations +); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +PLAN (RDB$DATABASE NATURAL) +PLAN (RDB$RELATIONS NATURAL) +""" + +@pytest.mark.version('>=3.0') +def test_core_4262_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4269.py b/tests/bugs/test_core_4269.py new file mode 100644 index 00000000..b6fe7a65 --- /dev/null +++ b/tests/bugs/test_core_4269.py @@ -0,0 +1,90 @@ +#coding:utf-8 +# +# id: bugs.core_4269 +# title: Wrong output when field with result of windowed function is used in query with useless WHERE 0=0 and GROUP BY clause +# decription: +# tracker_id: CORE-4269 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table tb_a(q int, v int); commit; + insert into tb_a + with + x as( + select 1 q, 1 v from rdb$database union all + select 1 q, 7 v from rdb$database + ) + select * from x; + commit; + recreate table tv_a(v int, n varchar(10), c varchar(10) ); commit; + insert into tv_a + with + x as( + select 1 v, 'a1' n, 'r' c from rdb$database union all + select 7 v, 'a7' n, 'b' c from rdb$database + ) + select * from x; + commit; + """ + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + 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; + with + tc as( + select + tb_a.q, tb_a.v, tv_a.c, + dense_rank () over (partition by tv_a.c order by tb_a.v) rk, + case when tv_a.c = 'r' then tv_a.n end r + from tb_a + join tv_a on tv_a.v = tb_a.v + where tb_a.q=1 + ) + + select q, rk , max(r) as max_r + from tc + where 0=0 + group by q, rk + + UNION ALL + + select q, rk , max(r) + from tc + group by q, rk; + set list off; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +CONNECTION_CSET UTF8 +DB_DEFAULT_CSET UTF8 +Q 1 +RK 1 +MAX_R a1 +Q 1 +RK 1 +MAX_R a1 +""" + +@pytest.mark.version('>=3.0') +def test_core_4269_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4270.py b/tests/bugs/test_core_4270.py new file mode 100644 index 00000000..b8450dbf --- /dev/null +++ b/tests/bugs/test_core_4270.py @@ -0,0 +1,57 @@ +#coding:utf-8 +# +# id: bugs.core_4270 +# title: Error in case of subquery with windowed function + where IN(select ...) +# decription: +# tracker_id: CORE-4270 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table t0(q int); commit; + create index t0_q on t0(q); + commit; + insert into t0(q) values (1); + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select a.qx + from + ( + select qx + from + ( + select 1 qx + ,count(*)over() as c + from t0 + where t0.q in (select 1 from rdb$database) + ) r + ) a + join t0 b on a.qx = b.q; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + QX 1 + """ + +@pytest.mark.version('>=3.0') +def test_core_4270_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4271.py b/tests/bugs/test_core_4271.py new file mode 100644 index 00000000..2e633795 --- /dev/null +++ b/tests/bugs/test_core_4271.py @@ -0,0 +1,274 @@ +#coding:utf-8 +# +# id: bugs.core_4271 +# title: Engine crashs in case of re-creation of an erratic package body +# decription: +# tracker_id: CORE-4271 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + set term ^; + create or alter package pkg_sequence + as + begin + procedure initialize(min_value int, max_value int, step int); + function get_current_value returns int; + function next_value returns int; + function is_end returns boolean; + end + ^ + + recreate package body pkg_sequence + as + begin + function get_max returns int as + begin + return cast(rdb$get_context('USER_SESSION', 'MAX_VALUE') as int); + end + + function set_max(avalue int) returns int as + begin + rdb$set_context('USER_SESSION', 'MAX_VALUE', avalue); + return avalue; + end + + function get_min returns int as + begin + return cast(rdb$get_context('USER_SESSION', 'MIN_VALUE') as int); + end + + function set_min(avalue int) returns int as + begin + rdb$set_context('USER_SESSION', 'MIN_VALUE', avalue); + return avalue; + end + + function get_step returns int as + begin + return cast(rdb$get_context('USER_SESSION', 'STEP_VALUE') as int); + end + + function set_step(avalue int) returns int + as + begin + rdb$set_context('USER_SESSION', 'STEP_VALUE', avalue); + return avalue; + end + + function get_current_value returns int as + begin + return cast(rdb$get_context('USER_SESSION', 'CURRENT_VALUE') as int); + end + + function set_current_value(avalue int) returns int as + begin + rdb$set_context('USER_SESSION', 'CURRENT_VALUE', avalue); + return avalue; + end + + function next_value returns int as + begin + if (not is_end()) then + set_current_value(get_current_value() + get_step()); + return get_current_value(); + end + + function is_end returns boolean as + begin + return get_current_value() > get_max(); + end + + procedure initialize(min_value int, max_value int, step int) + as + begin + set_min(min_value); + set_max(max_value); + set_step(step); + set_current_value(min_value); + end + end + ^ + + execute block returns ( out int) as + begin + execute procedure pkg_sequence.initialize(10, 140, 5); + out = pkg_sequence.get_current_value(); + suspend; + while (not pkg_sequence.is_end()) do + begin + out = pkg_sequence.next_value(); + suspend; + end + end + ^ + + + recreate package body pkg_sequence + as + begin + + function get_max returns int as + begin + return cast(rdb$get_context('USER_SESSION', 'MAX_VALUE') as int); + end + + function set_max(avalue int) returns int as + begin + rdb$set_context('USER_SESSION', 'MAX_VALUE', avalue); + return avalue; + end + + function get_min returns int as + begin + return cast(rdb$get_context('USER_SESSION', 'MIN_VALUE') as int); + end + + function set_min(avalue int) returns int as + begin + rdb$set_context('USER_SESSION', 'MIN_VALUE', avalue); + return avalue; + end + + function get_step returns int as + begin + return cast(rdb$get_context('USER_SESSION', 'STEP_VALUE') as int); + end + + function set_step(avalue int) returns int as + begin + rdb$set_context('USER_SESSION', 'STEP_VALUE', avalue); + return avalue; + end + + function get_current_value returns int as + begin + return cast(rdb$get_context('USER_SESSION', 'CURRENT_VALUE') as int); + end + + function set_current_value(avalue int) returns int + as + begin + rdb$set_context('USER_SESSION', 'CURRENT_VALUE', avalue); + return avalue; + end + + function next_value returns int as + begin + if (not is_end()) then + set_current_value(get_current_value() + get_step()); + return get_current_value(); + end + + function is_end returns boolean as + begin + return get_current_value() > get_max(); + end + + procedure initialize(min_value int, max_value int, step int) as + begin + set_min(min_value); + set_max(max_value); + set_step(step); + set_current_value(min_value); + end + end + ^ + + execute block returns (out int) as + begin + execute procedure pkg_sequence.initialize(10, 140, 5); + out = pkg_sequence.get_current_value(); + suspend; + + while (not pkg_sequence.is_end()) do + begin + out = pkg_sequence.next_value(); + suspend; + end + end + ^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + OUT 10 + OUT 15 + OUT 20 + OUT 25 + OUT 30 + OUT 35 + OUT 40 + OUT 45 + OUT 50 + OUT 55 + OUT 60 + OUT 65 + OUT 70 + OUT 75 + OUT 80 + OUT 85 + OUT 90 + OUT 95 + OUT 100 + OUT 105 + OUT 110 + OUT 115 + OUT 120 + OUT 125 + OUT 130 + OUT 135 + OUT 140 + OUT 145 + OUT 10 + OUT 15 + OUT 20 + OUT 25 + OUT 30 + OUT 35 + OUT 40 + OUT 45 + OUT 50 + OUT 55 + OUT 60 + OUT 65 + OUT 70 + OUT 75 + OUT 80 + OUT 85 + OUT 90 + OUT 95 + OUT 100 + OUT 105 + OUT 110 + OUT 115 + OUT 120 + OUT 125 + OUT 130 + OUT 135 + OUT 140 + OUT 145 + """ + +@pytest.mark.version('>=3.0') +def test_core_4271_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4276.py b/tests/bugs/test_core_4276.py new file mode 100644 index 00000000..f163511c --- /dev/null +++ b/tests/bugs/test_core_4276.py @@ -0,0 +1,167 @@ +#coding:utf-8 +# +# id: bugs.core_4276 +# title: Error on create table with "CHARACTER SET DOS775" field +# decription: +# Confirmed problem on 2.5.3.26780: +# Statement failed, SQLSTATE = 2C000 +# bad parameters on attach or create database +# -CHARACTER SET DOS775 is not defined +# Checked on 3.0.0.32136 RC1 - all OK. +# +# 02-mar-2021. Re-implemented in order to have ability to run this test on Linux. +# Test encodes to UTF8 all needed statements (SET NAMES; CONNECT; DDL and DML) and stores this text in .sql file. +# NOTE: 'SET NAMES' contain character set that must be used for reproducing problem (DOS775 in this test). +# Then ISQL is launched in separate (child) process which performs all necessary actions (using required charset). +# Result will be redirected to log(s) which will be opened further via codecs.open(...encoding='cp775'). +# Finally, its content will be converted to UTF8 for showing in expected_stdout. +# +# Checked on: +# * Windows: 4.0.0.2377, 3.0.8.33420, 2.5.9.27152 +# * Linux: 4.0.0.2377, 3.0.8.33415 +# +# +# tracker_id: CORE-4276 +# min_versions: ['2.5.5'] +# versions: 2.5.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.5 +# resources: None + +substitutions_1 = [('BLOB_CONTENT.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# +# import os +# import codecs +# import subprocess +# import time +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# # Code to be executed further in separate ISQL process: +# ############################# +# sql_txt=''' +# set bail on; +# set names dos775; +# connect '%(dsn)s' user '%(user_name)s' password '%(user_password)s'; +# +# 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.' +# ); +# set list on; +# set blob all; +# select "ąčęėįšųūž", "Õisu ja kariste järved" as blob_content +# from "ĄČĘĢÆĖŠŚÖÜØ£"; +# +# ''' % dict(globals(), **locals()) +# +# f_run_sql = open( os.path.join(context['temp_directory'], 'tmp_4276_dos775.sql'), 'w' ) +# f_run_sql.write( sql_txt.decode('utf8').encode('cp775') ) +# flush_and_close( f_run_sql ) +# +# # result: file tmp_4276_dos775.sql is encoded in dos775 +# +# f_run_log = open( os.path.splitext(f_run_sql.name)[0]+'.log', 'w') +# subprocess.call( [ context['isql_path'], '-q', '-i', f_run_sql.name ], +# stdout = f_run_log, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_run_log ) # result: output will be encoded in dos775 +# +# with codecs.open(f_run_log.name, 'r', encoding='cp775' ) as f: +# result_in_dos775 = f.readlines() +# +# for i in result_in_dos775: +# print( i.encode('utf8') ) +# +# # cleanup: +# ########### +# cleanup( (f_run_sql, f_run_log) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ĄČĘĢÆĖŠŚÖÜØ£ + ąčęėįšųūž 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. + """ + +@pytest.mark.version('>=2.5.5') +@pytest.mark.xfail +def test_core_4276_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4280.py b/tests/bugs/test_core_4280.py new file mode 100644 index 00000000..98312fb2 --- /dev/null +++ b/tests/bugs/test_core_4280.py @@ -0,0 +1,75 @@ +#coding:utf-8 +# +# id: bugs.core_4280 +# title: FB3: Stored function accepts duplicate input arguments +# decription: +# 02.02.2019. Replaced 'show func' with query to RDB$FUNCTIONS table: we have just to ensure that no function did appear in DB. +# (removed 'show func' because its output is mutable and can be directed either to STDERR or STDOUT in diff. FB versions). +# Checked on: +# 4.0.0.1421: OK, 1.512s. +# 3.0.5.33097: OK, 0.907s. +# 3.0.2.32658: OK, 0.840s. +# 3.0.4.33054: OK, 1.368s. +# +# tracker_id: CORE-4280 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create view v_check as + select + rf.rdb$function_name as func_name + ,rf.rdb$legacy_flag as legacy_flag + from rdb$functions rf where rf.rdb$function_name = upper('psql_func_test') + ; + commit; + + set term ^; + create function psql_func_test(x integer, y boolean, x integer) -- argument `x` appears twice + returns integer as + begin + return x + 1; + end + ^ + set term ;^ + commit; + + set list on; + set count on; + select * from v_check; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + CREATE FUNCTION PSQL_FUNC_TEST failed + -SQL error code = -901 + -duplicate specification of X - not supported + """ + +@pytest.mark.version('>=3.0') +def test_core_4280_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4281.py b/tests/bugs/test_core_4281.py new file mode 100644 index 00000000..f709b056 --- /dev/null +++ b/tests/bugs/test_core_4281.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: bugs.core_4281 +# title: FB 3: TYPE OF arguments of stored functions will hang firebird engine if depending domain or column is changed +# decription: +# tracker_id: CORE-4281 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create domain testdomain as integer; + commit; + + create function testfunction (arg1 type of testdomain) returns integer as + begin + end; + + commit; + alter domain testdomain type bigint; + commit; + + show domain testdomain; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TESTDOMAIN BIGINT Nullable + """ + +@pytest.mark.version('>=3.0') +def test_core_4281_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4285.py b/tests/bugs/test_core_4285.py new file mode 100644 index 00000000..f03c2b2c --- /dev/null +++ b/tests/bugs/test_core_4285.py @@ -0,0 +1,196 @@ +#coding:utf-8 +# +# id: bugs.core_4285 +# title: Choose the best matching index for navigation +# decription: +# When ORDER plan is in game, the optimizer chooses the first index candidate that matches the ORDER BY / GROUP BY clause. +# This is not the best approach when multiple index choices are available +# +# 22.12.2019. Refactored: split code and expected_std* for each major FB version; add some data to the test table. +# Checked on: +# 4.0.0.1694: 1.598s // NB: output in 4.0 became match to 3.x since 4.0.0.1694 +# 4.0.0.1637: 1.515s. +# 3.0.5.33215: 1.094s. +# NB: 3.0.5.33212 - FAILED, another index(es) are chosen! +# +# 25.07.2020: removed section for 4.0 because expected size must be equal in both major FB version, as it is given for 3.0. +# (letter from dimitr, 25.07.2020 12:42). Checked on 3.0.7.33348, 4.0.0.2119 +# +# +# tracker_id: CORE-4285 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + set bail on; + recreate table test (col1 int, col2 int, col3 int); + commit; + insert into test(col1, col2, col3) + with recursive + r as ( + select 0 as i from rdb$database + union all + select r.i+1 from r + where r.i < 49 + ) + select mod(r1.i,1000), mod(r1.i,100), mod(r1.i,10) + from r as r1, r as r2 + where 1=1 + ; + commit; + + create index test_col1 on test (col1); + create index test_col12 on test (col1, col2); + create index test_col21 on test (col2, col1); + create index test_col123 on test (col1, col2, col3); + create index test_col132 on test (col1, col3, col2); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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; + + 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_core_4285_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4289.py b/tests/bugs/test_core_4289.py new file mode 100644 index 00000000..dfb48433 --- /dev/null +++ b/tests/bugs/test_core_4289.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: bugs.core_4289 +# title: Regression: NOT-null field from derived table became NULL when is referred outside DT +# decription: +# tracker_id: CORE-4289 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ +set list on; +select q.n, case when q.n=0 then 'zero' when q.n<>0 then 'NON-zero' else 'Hm!..' end what_is_n +from (select 0 N from RDB$DATABASE) q; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +N 0 +WHAT_IS_N zero + """ + +@pytest.mark.version('>=3.0') +def test_core_4289_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4292.py b/tests/bugs/test_core_4292.py new file mode 100644 index 00000000..c36e22bd --- /dev/null +++ b/tests/bugs/test_core_4292.py @@ -0,0 +1,310 @@ +#coding:utf-8 +# +# id: bugs.core_4292 +# title: Server ignores asynchronous (monitoring or cancellation) requests while preparing a query with lot of windowed functions +# decription: +# Preparing stage of test query will last lot of time even on power host. +# We launch separate (child) process with ISQL and allow him to start preparing this query during several +# seconds. Then we launch second child process with ISQL and try to kill first one. +# Before this ticket was fixed it was NOT possible neither to cancel it by using MON$ATTACHMENTS nor even +# query MON$ tables at all (until this 'complex query' preparing finish). +# +# Checked on WI-V3.0.0.32081, SS / SC / CS. Result: all fine. +# 11.05.2017: checked on WI-T4.0.0.638 - added filtering to messages about shutdown state, see comments below. +# +# tracker_id: CORE-4292 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('.*line.*', ''), ('.*Killed by database administrator.*', ''), ('[\t ]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import subprocess +# from subprocess import Popen +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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() +# os.fsync(file_handle.fileno()) +# +# file_handle.close() +# +# #-------------------------------------------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# heavy_sql = ''' +# set bail on; +# set list on; +# set count on; +# with a as ( +# select rf.rdb$field_id fid, rr.rdb$relation_id rid, rr.rdb$relation_name rnm +# from rdb$relation_fields rf join rdb$relations rr on rf.rdb$relation_name=rr.rdb$relation_name +# ) +# ,b as ( +# select fid, rnm, rid, iif(rid is null, 1, r) r +# from (--f +# select fid, rnm, rid, +# iif(lag(fid) over(partition by rid order by fid) is not null +# and lag(r) over(partition by rid order by fid) >= r +# , r + 1, r) r +# from (--e +# select fid, rnm, rid, +# iif(lag(fid) over(partition by rid order by fid) is not null +# and lag(r) over(partition by rid order by fid) >= r +# , r + 1, r) r +# from (--d +# select fid, rnm, rid, +# iif(lag(fid) over(partition by rid order by fid) is not null +# and lag(r) over(partition by rid order by fid) >= r +# , r + 1, r) r +# from (--c +# select fid, rnm, rid, +# iif(lag(fid) over(partition by rid order by fid) is not null +# and lag(r) over(partition by rid order by fid) >= r +# ,r + 1, r) r +# from (--b +# select fid, rnm, rid, +# iif( lag(fid) over(partition by rid order by fid) is not null +# and lag(r) over(partition by rid order by fid) >= r +# ,r + 1, r) r +# from ( +# select a.*, 1 r +# from a +# ) a +# ) b +# ) c +# ) d +# ) e +# ) f +# ) +# -- select max(r) r from b group by fid having max(r) < 6; -- ok +# +# ,c +# as ( +# select fid, rnm, rid, iif(rid is null, 1, r) r +# from (--f +# select fid, rnm, rid, +# iif(lag(fid) over(partition by rid order by fid) is not null +# and lag(r) over(partition by rid order by fid) >= r +# , r + 1, r) r +# from (--e +# select fid, rnm, rid, +# iif(lag(fid) over(partition by rid order by fid) is not null +# and lag(r) over(partition by rid order by fid) >= r +# , r + 1, r) r +# from (--d +# select fid, rnm, rid, +# iif(lag(fid) over(partition by rid order by fid) is not null +# and lag(r) over(partition by rid order by fid) >= r +# , r + 1, r) r +# from (--c +# select fid, rnm, rid, +# iif(lag(fid) over(partition by rid order by fid) is not null +# and lag(r) over(partition by rid order by fid) >= r +# ,r + 1, r) r +# from (--b +# select fid, rnm, rid, +# iif( lag(fid) over(partition by rid order by fid) is not null +# and lag(r) over(partition by rid order by fid) >= r +# ,r + 1, r) r +# from ( +# select fid, rnm, rid, max(r) over(partition by fid) r from b +# ) a +# ) b +# ) c +# ) d +# ) e +# ) f +# ) +# -- select * from c -- ok +# +# ,d +# as ( +# select fid, rnm, rid, iif(rid is null, 1, r) r +# from (--f +# select fid, rnm, rid, +# iif( lag(fid) over(partition by rid order by fid) is not null +# and lag(r) over(partition by rid order by fid) >= r +# , r + 1, r) r +# from (--e +# select fid, rnm, rid, +# iif( lag(fid) over(partition by rid order by fid) is not null +# and lag(r) over(partition by rid order by fid) >= r +# , r + 1, r) r +# from (--d +# select fid, rnm, rid, +# iif( lag(fid) over(partition by rid order by fid) is not null +# and lag(r) over(partition by rid order by fid) >= r +# , r + 1, r) r +# from (--c +# select fid, rnm, rid, +# iif( lag(fid) over(partition by rid order by fid) is not null +# and lag(r) over(partition by rid order by fid) >= r +# ,r + 1, r) r +# from (--b +# select fid, rnm, rid, +# iif( lag(fid) over(partition by rid order by fid) is not null +# and lag(r) over(partition by rid order by fid) >= r +# ,r + 1, r) r +# from ( +# select fid, rnm, rid, max(r) over(partition by fid) r from c +# ) a +# ) b +# ) c +# ) d +# ) e +# ) f +# ) +# select * from d rows 0; +# set count off; +# select 'WORKER FINISHED TOO FAST! DELAY IN TEST MUST BE REDUCED!' msg from rdb$database; +# +# ''' +# f_worker_sql=open(os.path.join(context['temp_directory'],'tmp_worker_4292.sql'),'w') +# f_worker_sql.write(heavy_sql) +# flush_and_close( f_worker_sql ) +# +# f_worker_log=open( os.path.join(context['temp_directory'],'tmp_worker_4292.log'), 'w') +# +# # Execute a child program in a new process, redirecting STDERR to the same target as of STDOUT: +# p_worker = Popen([ context['isql_path'], dsn, "-i", f_worker_sql.name], stdout=f_worker_log, stderr=subprocess.STDOUT ) +# +# time.sleep(4) +# +# killer_sql=''' +# set list on; +# set count on; +# /* +# select a.*, s.* +# from mon$attachments a +# left join mon$statements s on a.mon$attachment_id = s.mon$attachment_id +# where +# a.mon$attachment_id <> current_connection +# and a.mon$system_flag is distinct from 1 +# ; +# */ +# select count(*) as "Found worker ?" +# from mon$attachments a +# where +# a.mon$attachment_id <> current_connection +# and a.mon$system_flag is distinct from 1 +# ; +# +# delete from mon$attachments +# where +# mon$attachment_id <> current_connection +# and mon$system_flag is distinct from 1 +# returning +# sign(mon$attachment_id) as deleted_mon_att_id, +# mon$user as deleted_mon_user, +# iif(mon$remote_protocol containing 'tcp', 'tcp', null) as deleted_mon_protocol, +# iif(mon$remote_process containing 'isql', 'isql', null) as deleted_mon_process, +# mon$system_flag as deleted_mon_sys_flag +# ; +# ''' +# +# # 11.05.2017, FB 4.0 only! +# # Following messages can appear after 'connection shutdown' +# # (letter from dimitr, 08-may-2017 20:41): +# # isc_att_shut_killed: Killed by database administrator +# # isc_att_shut_idle: Idle timeout expired +# # isc_att_shut_db_down: Database is shutdown +# # isc_att_shut_engine: Engine is shutdown +# +# +# f_killer_sql=open( os.path.join(context['temp_directory'],'tmp_killer_4292.sql'), 'w') +# f_killer_sql.write(killer_sql) +# flush_and_close( f_killer_sql ) +# +# # Execute a child program in a new process, redirecting STDERR to the same target as of STDOUT: +# +# f_killer_log=open( os.path.join(context['temp_directory'],'tmp_killer_4292.log'), 'w') +# p_killer = Popen([context['isql_path'] , dsn, "-i" , f_killer_sql.name], stdout=f_killer_log, stderr=subprocess.STDOUT ) +# +# # Make delay at least on 6 seconds after that point. +# # Otherwise temp database will not be removed and we get: +# # Exception AttributeError: "'Connection' object has no attribute '_Connection__ic'" +# # in > ignored +# # Test cleanup: Exception raised while dropping database. +# +# time.sleep(6) +# +# p_worker.terminate() +# flush_and_close( f_worker_log ) +# +# p_killer.terminate() +# flush_and_close( f_killer_log ) +# +# with open( f_killer_log.name,'r') as f: +# for line in f: +# if line.split(): +# print('KILLER LOG: ' + line) +# +# with open( f_worker_log.name,'r') as f: +# for line in f: +# if line.split(): +# print('WORKER LOG: ' + line) +# +# +# # CLEANUP +# ######### +# time.sleep(1) +# cleanup( [i.name for i in (f_worker_sql,f_worker_log,f_killer_sql,f_killer_log)] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + KILLER LOG: Found worker ? 1 + KILLER LOG: Records affected: 1 + KILLER LOG: DELETED_MON_ATT_ID 1 + KILLER LOG: DELETED_MON_USER SYSDBA + KILLER LOG: DELETED_MON_PROTOCOL tcp + KILLER LOG: DELETED_MON_PROCESS isql + KILLER LOG: DELETED_MON_SYS_FLAG 0 + WORKER LOG: Statement failed, SQLSTATE = 08003 + WORKER LOG: connection shutdown + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4292_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4298.py b/tests/bugs/test_core_4298.py new file mode 100644 index 00000000..a9966713 --- /dev/null +++ b/tests/bugs/test_core_4298.py @@ -0,0 +1,251 @@ +#coding:utf-8 +# +# id: bugs.core_4298 +# title: fbsvcmgr doesn't recognise sts_record_versions and other sts switches +# decription: +# Test creates table and add 5 rows to it. Than we run in child async. process ISQL with EB which has ES/EDS +# and will stay in pause due to update conflict in lock-timeout transaction (Python currently can not operate +# with several attachments which open cursors with DML - this will crash). +# When EB will be paused, we start another ISQL which will add one row to the same table and finish. +# At this point table will have 5 versions and this should be shown in the output of fbsvcmgr when it is run +# with 'action_db_stats sts_record_versions' keys. +# Finally, we terminate hanged ISQL process and proceed with logs (STDOUR and STDERR) of fbsvcmgr. +# Log of errors should be empty, log of STDOUT should contain text with non-zero number of versions. +# Checked on: +# WI-V2.5.5.26942 (SS), WI-V2.5.5.26952 (sC); +# WI-V3.0.0.32239 (SS), WI-V3.0.0.32208 (Cs, sC). +# ### NOTE ### +# Classic keeps database file opened when hanged ISQL is killed by teminate(), thus leading to access error +# when fbtest tries to remove database by dropping it (get "Windows error (32)"). For that reason we have +# to allow ISQL that stays in pause to finish by Tx timeout expiration and close itself his own process. +# +# Checked on (28.10.2019): +# 4.0.0.1635 SS: 7.720s. +# 4.0.0.1633 CS: 7.378s. +# 3.0.5.33180 SS: 7.313s. +# 3.0.5.33178 CS: 6.720s. +# 2.5.9.27119 SS: 6.506s. +# 2.5.9.27146 SC: 5.388s. +# +# 13.04.2021. Adapted for run both on Windows and Linux. Checked on: +# Windows: 3.0.8.33445, 4.0.0.2416 +# Linux: 3.0.8.33426, 4.0.0.2416 +# +# +# tracker_id: CORE-4298 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [('Average version length: [\\d]+.[\\d]+, total versions: 5, max versions: 1', 'total versions: 5, max versions: 1')] + +init_script_1 = """ + recreate table test(id int, x int); + commit; + insert into test values(1, 100); + insert into test values(2, 200); + insert into test values(3, 300); + insert into test values(4, 400); + insert into test values(5, 500); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# from subprocess import Popen +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # Obtain engine version: +# engine = str(db_conn.engine_version) # convert to text because 'float' object has no attribute 'startswith' +# +# #-------------------------------------------- +# +# 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 ) +# +# #-------------------------------------------- +# +# sqltxt=''' +# set term ^; +# execute block as +# begin +# execute statement 'drop role TMP$R4298'; +# when any do begin end +# end ^ +# set term ;^ +# commit; +# +# +# commit; +# set transaction lock timeout 15; +# update test set x = -x; +# set term ^; +# execute block as +# begin +# execute statement 'update test set x = -x' +# on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') +# as user '%s' password '%s' role 'TMP$R4298'; +# when any do +# begin +# end +# end +# ^ +# set term ;^ +# rollback; +# +# ''' % (user_name, user_password) +# +# +# f_hanged_sql=open( os.path.join(context['temp_directory'],'tmp_4298_hang.sql'), 'w') +# f_hanged_sql.write(sqltxt) +# flush_and_close( f_hanged_sql ) +# +# f_hanged_log=open( os.path.join(context['temp_directory'],'tmp_4298_hang.log'), 'w') +# +# # Execute a child program in a new process, redirecting STDERR to the same target as of STDOUT: +# p_hang = Popen([context['isql_path'], dsn, "-i" , f_hanged_sql.name], stdout=f_hanged_log, stderr=subprocess.STDOUT) +# +# time.sleep(1) +# +# runProgram('isql',[dsn],'insert into test(id, x) values(-1, -100); commit;') +# +# this_fdb='$(DATABASE_LOCATION)bugs.core_4298.fdb' +# +# f_stat_log=open( os.path.join(context['temp_directory'],'tmp_4298_dbstat.log'), 'w') +# f_stat_err=open( os.path.join(context['temp_directory'],'tmp_4298_dbstat.err'), 'w') +# +# subprocess.call( [ context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_db_stats", "dbname", this_fdb, +# "sts_record_versions" +# ], +# stdout=f_stat_log, +# stderr=f_stat_err +# ) +# +# flush_and_close( f_stat_log ) +# flush_and_close( f_stat_err ) +# +# # do NOT remove this pause: Classic 3.0 keeps database opened even after we kill hanged ISQL by p_hang.terminate(). +# # So we have to wait enough for 1st ISQL process that currently will hangs about 4 seconds to be CORRECTLY closed +# # by itself: +# +# time.sleep(3) +# +# # These kill and close commands are also needed here, despite that corresponding ISQL has been already closed itself. +# # It is so at least for Cs 3.0: +# p_hang.terminate() +# flush_and_close( f_hanged_log ) +# +# # ERRORS log of obtaining DB statistics should be EMPTY: +# with open( f_stat_err.name,'r') as f: +# for line in f: +# if line.split(): +# print("UNEXPECTED STDERR for 'action_db_stats': " + line) +# +# # STDOUT of obtaining DB statistics should NOT be EMPTY: +# with open(f_stat_log.name,'r') as f: +# for line in f: +# if 'versions:' in line.lower(): +# print(line) +# +# ##################################################################### +# # 28.10.2019: add full shutdown to forcedly drop all attachments. +# ## |||||||||||||||||||||||||||| +# ## ###################################||| 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 +# ## ############################################################################################# +# +# f_shutdown_log=open( os.path.join(context['temp_directory'],'tmp_4298_shutdown.log'), 'w') +# +# subprocess.call( [context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "prp_shutdown_mode", "prp_sm_full", "prp_shutdown_db", "0", "dbname", this_fdb, +# ], +# stdout = f_shutdown_log, +# stderr = subprocess.STDOUT +# ) +# subprocess.call( [context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "prp_db_online", "dbname", this_fdb, +# ], +# stdout = f_shutdown_log, +# stderr = subprocess.STDOUT +# ) +# +# flush_and_close( f_shutdown_log ) +# +# with open( f_shutdown_log.name,'r') as f: +# for line in f: +# if line.split(): +# print( 'UNEXPECTED OUTPUT IN DB SHUTDOWN LOG: ' + (' '.join(line.split()).upper()) ) +# +# +# # Cleanup: +# ########## +# # do NOT remove this pause otherwise some of logs will not be enable for deletion and test will finish with +# # Exception raised while executing Python test script. exception: WindowsError: 32 +# time.sleep(1) +# +# cleanup( (f_hanged_sql, f_hanged_log, f_stat_log, f_stat_err, f_shutdown_log) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Average version length: 9.00, total versions: 5, max versions: 1 + """ + +@pytest.mark.version('>=2.5.2') +@pytest.mark.xfail +def test_core_4298_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4299.py b/tests/bugs/test_core_4299.py new file mode 100644 index 00000000..60745605 --- /dev/null +++ b/tests/bugs/test_core_4299.py @@ -0,0 +1,55 @@ +#coding:utf-8 +# +# id: bugs.core_4299 +# title: Inappropriate self-reference of column when using "with check option" with extract(...) +# decription: +# tracker_id: CORE-4299 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + -- Source description found here: + -- http://stackoverflow.com/questions/20505769/inappropriate-self-reference-of-column-when-using-with-check-option-in-fireb + create or alter view foo as select current_date dt from rdb$database; + commit; + + recreate table bar(dt date); + commit; + insert into bar(dt) values ('28.03.2011'); + commit; + + create or alter view foo as + select * from bar + where extract(year from bar.dt) = '2011' + with check option + ; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select * from foo; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DT 2011-03-28 + """ + +@pytest.mark.version('>=2.5.3') +def test_core_4299_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4301.py b/tests/bugs/test_core_4301.py new file mode 100644 index 00000000..de9cd05f --- /dev/null +++ b/tests/bugs/test_core_4301.py @@ -0,0 +1,56 @@ +#coding:utf-8 +# +# id: bugs.core_4301 +# title: Non-ASCII data in SEC$USERS is not read correctly +# decription: +# tracker_id: CORE-4301 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- 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'; + commit; + set list on; + select u.sec$user_name, u.sec$first_name + from sec$users u + where upper(u.sec$user_name) in (upper('u30a'), upper('u30b')); + commit; + drop user u30a; + drop user u30b; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + SEC$USER_NAME U30A + SEC$FIRST_NAME Полиграф Шариков + SEC$USER_NAME U30B + SEC$FIRST_NAME Léopold Frédéric + """ + +@pytest.mark.version('>=3.0') +def test_core_4301_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4302.py b/tests/bugs/test_core_4302.py new file mode 100644 index 00000000..1747c2a9 --- /dev/null +++ b/tests/bugs/test_core_4302.py @@ -0,0 +1,137 @@ +#coding:utf-8 +# +# id: bugs.core_4302 +# title: Lookup (or scan) in descending index could be very inefficient for some keys +# decription: +# ### NB, 16-apr-2016 ### +# 1. Bug of this ticket was introduced _after_ FB 3.0 Alpha1 release and was fixed 21-dec-2013. +# I could not reproduce poor statistics (too big value of fetches) on WI-T3.0.0.30566 (Alpha1 release), +# so temporary build was created based on snapshot of 20-dec-2013 (on POSIX): LI-T3.0.0.30800. +# This snapshot DOES reproduce problem: number of fetches for val=1 or val=3 is less than 30 +# while for val=2 produces number of fetches more than 210'000. +# For 2.5.x number of fetches is about 59...67, so common threshold was choosen to value 70. +# 2. Test was refactored: querying to database 'mon-stat-gathering-N_M.fdb' was removed, all necessary +# output one may achieve by trivial view (v_mon) that queries mon$io_stats and and table (t_mon) that +# serves as log. +# +# Reproduced on LI-T3.0.0.30800 (snapshot on 20-dec-2013). +# Current results were checked on Windows (2.5.6.26994, 3.0.0.32484, 4.0.0.138) and POSIX (4.0.0.138) +# +# tracker_id: CORE-4302 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table t_mon(rn smallint, pg_fetches bigint); + + recreate view v_mon as + select i.mon$page_fetches as pg_fetches + from mon$attachments a + left join mon$io_stats i on a.mon$stat_id=i.mon$stat_id + where a.mon$attachment_id = current_connection; + + recreate table t1 (id int, val int); + commit; + + set term ^; + execute block as + declare i int = 0; + begin + while (i < 100000) do + begin + insert into t1 values (:i, mod(:i, 10)); + i = i + 1; + end + end + ^ + set term ;^ + commit; + + create descending index t1_desc_idx on t1 (val); + commit; + + set list on; + + insert into t_mon(rn, pg_fetches) values( 1, (select pg_fetches from v_mon)); + select * from t1 where val <= 1 order by val desc rows 1; + commit; + insert into t_mon(rn, pg_fetches) values( 2, (select pg_fetches from v_mon)); + commit; + + insert into t_mon(rn, pg_fetches) values( 3, (select pg_fetches from v_mon)); + select * from t1 where val <= 2 order by val desc rows 1; + commit; + insert into t_mon(rn, pg_fetches) values( 4, (select pg_fetches from v_mon)); + commit; + + insert into t_mon(rn, pg_fetches) values( 5, (select pg_fetches from v_mon)); + select * from t1 where val <= 3 order by val desc rows 1; + commit; + insert into t_mon(rn, pg_fetches) values( 6, (select pg_fetches from v_mon)); + commit; + + select + rn as measure + ,iif( fetches_diff < max_allowed, 'OK, less then ', 'BAD: '|| fetches_diff ||' - greater then ') || max_allowed as fetches_count + from ( + select + rn + ,fetches_at_end - fetches_at_beg as fetches_diff + ,70 as max_allowed + -- ^ ################################################### + -- | # # + -- +------- # T H R E S H O L D F O R F E T C H E S # + -- # # + -- ################################################### + from ( + select rn, max(iif(bg=1, pg_fetches, null)) as fetches_at_beg, max(iif(bg=1, null, pg_fetches)) as fetches_at_end + from ( + select 1+(rn-1)/2 as rn, mod(rn,2) as bg, pg_fetches + from t_mon + ) + group by rn + ) + ) + order by measure; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + VAL 1 + ID 2 + VAL 2 + ID 3 + VAL 3 + + MEASURE 1 + FETCHES_COUNT OK, less then 70 + + MEASURE 2 + FETCHES_COUNT OK, less then 70 + + MEASURE 3 + FETCHES_COUNT OK, less then 70 + + """ + +@pytest.mark.version('>=2.5.3') +def test_core_4302_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4302_addi.py b/tests/bugs/test_core_4302_addi.py new file mode 100644 index 00000000..d52e0ab5 --- /dev/null +++ b/tests/bugs/test_core_4302_addi.py @@ -0,0 +1,201 @@ +#coding:utf-8 +# +# id: bugs.core_4302_addi +# title: ### ADDITIONAL TEST ### Lookup (or scan) in descending index could be very inefficient for some keys +# decription: +# This is ADDITIONAL test for issue in ticket: "Pavel Zotov added a comment - 23/Dec/13 04:02 PM". +# Separate fix was required for this issue, see comments in +# https://sourceforge.net/p/firebird/mailman/message/31785278/ +# === +# + 2013-12-25 10:57 hvlad +# + M src/jrd/btr.cpp +# +Additional fix for bug CORE-4302 : Lookup (or scan) in descending index could be very inefficient... +# === +# Excessive fetches count reproduced on WI-T3.0.0.30566 (Alpha1 release). +# Current results were checked on Windows (2.5.6.26994, 3.0.0.32484, 4.0.0.138) and POSIX (4.0.0.138) +# 29.07.2016. On 4.0.0.316 number of fetches is ~99 thus new threshold was added for engine = 4.0. +# +# :::::::::::::::::::::::::::::::::::::::: NB :::::::::::::::::::::::::::::::::::: +# 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 replace 'alter sequence restart...' with subtraction of two gen values: +# c = gen_id(, -gen_id(, 0)) -- see procedure sp_restart_sequences. +# +# Checked on: +# 4.0.0.2164 SS: 3.232s. +# 4.0.0.2119 SS: 3.128s. +# 4.0.0.2164 CS: 3.286s. +# 3.0.7.33356 SS: 2.550s. +# 3.0.7.33356 CS: 3.325s. +# 2.5.9.27150 SC: 2.597s. +# +# tracker_id: CORE-4302 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter procedure sp_restart_sequences as begin end; + recreate table td(id int, s varchar(50)); + commit; + set term ^; + execute block as + begin + begin + execute statement 'drop sequence g'; + when any do begin end + end + end^ + set term ;^ + commit; + create sequence g; + commit; + + set term ^; + create or alter procedure sp_restart_sequences as + declare c bigint; + begin + c = gen_id(g, -gen_id(g, 0)); + end + ^ + set term ;^ + commit; + + recreate table t_mon(rn smallint, pg_fetches bigint); + + recreate view v_mon as + select i.mon$page_fetches as pg_fetches + from mon$attachments a + left join mon$io_stats i on a.mon$stat_id=i.mon$stat_id + where a.mon$attachment_id = current_connection; + + set term ^; + execute block as + declare n int = 10000; + declare m int; + begin + m=n; while(m>0) do insert into td(id, s) values( gen_id(g,1), 'q' ) returning :m-1 into m; + m=n; while(m>0) do insert into td(id, s) values( gen_id(g,1), 'qw' ) returning :m-1 into m; + m=n; while(m>0) do insert into td(id, s) values( gen_id(g,1), 'qwe' ) returning :m-1 into m; + m=n; while(m>0) do insert into td(id, s) values( gen_id(g,1), 'qwer' ) returning :m-1 into m; + m=n; while(m>0) do insert into td(id, s) values( gen_id(g,1), 'qwert' ) returning :m-1 into m; + m=n; while(m>0) do insert into td(id, s) values( gen_id(g,1), 'qwerty' ) returning :m-1 into m; + m=n; while(m>0) do insert into td(id, s) values( gen_id(g,1), 'qwertyu' ) returning :m-1 into m; + m=n; while(m>0) do insert into td(id, s) values( gen_id(g,1), 'qwertyui' ) returning :m-1 into m; + m=n; while(m>0) do insert into td(id, s) values( gen_id(g,1), 'qwertyuio' ) returning :m-1 into m; + m=n; while(m>0) do insert into td(id, s) values( gen_id(g,1), 'qwertyuiop' ) returning :m-1 into m; + end^ set term ;^ + commit; + + create descending index td_s_des on td(s); commit; + execute procedure sp_restart_sequences; + commit; + + insert into t_mon(rn, pg_fetches) values( gen_id(g,1), (select pg_fetches from v_mon)); + + set term ^; + execute block as + declare c int; + begin + select count(*) from rdb$database where exists(select * from td where s='qwertyuiop') into c; + end + ^ + set term ;^ + commit; + + insert into t_mon(rn, pg_fetches) values( gen_id(g,1), (select pg_fetches from v_mon)); + commit; + + insert into t_mon(rn, pg_fetches) values( gen_id(g,1), (select pg_fetches from v_mon)); + + set term ^; + execute block as + declare c int; + begin + select count(*) from rdb$database where exists(select * from td where s='qwertyuioo') into c; -- note: `o` duplicated at the end of key + end + ^ + set term ;^ + commit; + + insert into t_mon(rn, pg_fetches) values( gen_id(g,1), (select pg_fetches from v_mon)); + commit; + + set list on; + select + rn as measure + ,iif( fetches_diff < max_allowed, + 'OK, less then max_allowed', + 'BAD: '|| fetches_diff ||' - greater then ' || max_allowed || ' for engine = ' || rdb$get_context('SYSTEM','ENGINE_VERSION') + ) as fetches_count + from ( + select + rn + ,fetches_at_end - fetches_at_beg as fetches_diff + ,max_for_25 + ,max_for_30 + ,cast( iif( rdb$get_context('SYSTEM','ENGINE_VERSION') >= '4.0', + max_for_40, + iif( rdb$get_context('SYSTEM','ENGINE_VERSION') >= '3.0', + max_for_30, + max_for_25 + ) + ) + as int + ) as max_allowed + from ( + select + rn + ,max(iif(bg=1, pg_fetches, null)) as fetches_at_beg + ,max(iif(bg=1, null, pg_fetches)) as fetches_at_end + ,140 as max_for_25 + ,70 as max_for_30 + ,110 as max_for_40 -- 29.07.2016 + -- ^ #################################################### + -- | # # + -- +------- # T H R E S H O L D S F O R F E T C H E S # + -- # # + -- #################################################### + from ( + select 1+(rn-1)/2 as rn, mod(rn,2) as bg, pg_fetches + from t_mon + ) + group by rn + ) + ) + order by measure; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MEASURE 1 + FETCHES_COUNT OK, less then max_allowed + + MEASURE 2 + FETCHES_COUNT OK, less then max_allowed + """ + +@pytest.mark.version('>=2.5.3') +def test_core_4302_addi_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4304.py b/tests/bugs/test_core_4304.py new file mode 100644 index 00000000..a200ffba --- /dev/null +++ b/tests/bugs/test_core_4304.py @@ -0,0 +1,55 @@ +#coding:utf-8 +# +# id: bugs.core_4304 +# title: Engine crashes when attempt to REcreate table with FK after syntax error before such recreating +# decription: +# tracker_id: CORE-4304 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='NONE', sql_dialect=3, init=init_script_1) + +test_script_1 = """ +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; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +X INTEGER Not Null +Y INTEGER Nullable +CONSTRAINT T1_FK: + Foreign key (Y) References T1 (X) +CONSTRAINT T1_PK: + Primary key (X) + """ +expected_stderr_1 = """ +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 + """ + +@pytest.mark.version('>=3.0') +def test_core_4304_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4307.py b/tests/bugs/test_core_4307.py new file mode 100644 index 00000000..7b74524c --- /dev/null +++ b/tests/bugs/test_core_4307.py @@ -0,0 +1,48 @@ +#coding:utf-8 +# +# id: bugs.core_4307 +# title: Fields present only in WHERE clause of views WITH CHECK OPTION causes invalid CHECK CONSTRAINT violation +# decription: +# tracker_id: CORE-4307 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table t1 (n1 integer, n2 integer); + insert into t1 values (1, 2); + insert into t1 values (1, 3); + insert into t1 values (1, 4); + insert into t1 values (2, 2); + insert into t1 values (2, 3); + insert into t1 values (2, 4); + insert into t1 values (3, 2); + insert into t1 values (3, 3); + insert into t1 values (3, 4); + commit; + recreate view v1 as select n1 from t1 where n1 < n2 with check option; + commit; + update v1 set n1 = n1 - 1; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + update v1 set n1 = n1 - 1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +def test_core_4307_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_4310.py b/tests/bugs/test_core_4310.py new file mode 100644 index 00000000..c037377c --- /dev/null +++ b/tests/bugs/test_core_4310.py @@ -0,0 +1,55 @@ +#coding:utf-8 +# +# id: bugs.core_4310 +# title: DateAdd(): change input argument from INT to BIGINT +# decription: +# See also test for CORE-6241. +# +# tracker_id: CORE-4310 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!sqltype|DTS1|DTS2|SQLSTATE|exceed|range|valid).)*$', ''), ('[ ]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set sqlda_display on; + set planonly; + select dateadd( ? millisecond to ?) from rdb$database; + set planonly; + set plan off; + set sqlda_display off; + set list on; + + select + dateadd( 315537897599998 millisecond to timestamp '01.01.0001 00:00:00.001' ) dts1 + ,dateadd( -315537897599998 millisecond to timestamp '31.12.9999 23:59:59.999' ) dts2 + from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 01: sqltype: 580 INT64 scale: -1 subtype: 0 len: 8 + 02: sqltype: 510 TIMESTAMP scale: 0 subtype: 0 len: 8 + 01: sqltype: 510 TIMESTAMP scale: 0 subtype: 0 len: 8 + DTS1 9999-12-31 23:59:59.9990 + DTS2 0001-01-01 00:00:00.0010 + """ + +@pytest.mark.version('>=3.0') +def test_core_4310_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4315.py b/tests/bugs/test_core_4315.py new file mode 100644 index 00000000..137c3f1a --- /dev/null +++ b/tests/bugs/test_core_4315.py @@ -0,0 +1,93 @@ +#coding:utf-8 +# +# id: bugs.core_4315 +# title: Usage of field(s) alias in view WITH CHECK OPTION leads to incorrect compile error or incorrect internal triggers +# decription: +# tracker_id: CORE-4315 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('RDB\\$TRIGGER_BLR.*', '')] + +init_script_1 = """ + recreate view v1 as select 1 id from rdb$database; + commit; + recreate table t1 (n1 integer, n2 integer); + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- 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; + recreate view v1 as select x.n1 from t1 x where x.n1 < x.n2 with check option; + + -- Compiled without errors but generates incorrect internal triggers + recreate view v1 as select n1 a from t1 where n1 < n2 with check option; + commit; + + set blob all; + set list on; + select rdb$trigger_blr + from rdb$triggers + where upper(trim(rdb$relation_name))=upper('v1') + order by rdb$trigger_name; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +RDB$TRIGGER_BLR c:2d2 + 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:2d3 + 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_core_4315_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4318.py b/tests/bugs/test_core_4318.py new file mode 100644 index 00000000..464d9470 --- /dev/null +++ b/tests/bugs/test_core_4318.py @@ -0,0 +1,115 @@ +#coding:utf-8 +# +# id: bugs.core_4318 +# title: Regression: Predicates involving PSQL variables/parameters are not pushed inside the aggregation +# decription: +# tracker_id: CORE-4318 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table t2 ( + id integer not null, + t1_id integer + ); + commit; + + recreate table t1 ( + id integer not null + ); + commit; + + set term ^; + + execute block + as + declare variable i integer = 0; + begin + while (i < 1000) do begin + i = i + 1; + + insert into t2(id, t1_id) values(:i, mod(:i, 10)); + + merge into t1 using ( + select mod(:i, 10) as f from rdb$database + ) src on t1.id = src.f + when not matched then + insert (id) values(src.f); + + end -- while (i < 1000) do begin + + end^ + set term ;^ + commit; + + alter table t1 add constraint pk_t1 primary key (id); + alter table t2 add constraint pk_t2 primary key (id); + alter table t2 add constraint fk_t2_ref_t1 foreign key (t1_id) references t1(id); + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set explain on; + set planonly; + + set term ^; + execute block + returns ( + s integer + ) + as + declare variable v integer = 1; + begin + with t as ( + select t1_id as t1_id, sum(id) as s + 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Select Expression + -> 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_core_4318_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4319.py b/tests/bugs/test_core_4319.py new file mode 100644 index 00000000..458f9cb1 --- /dev/null +++ b/tests/bugs/test_core_4319.py @@ -0,0 +1,168 @@ +#coding:utf-8 +# +# id: bugs.core_4319 +# title: Engine crashes when trace config contains line "connection_id=NN" and we attempt to connect to non-existent database/alias +# decription: +# Test receives version of FB (2.5 or 3.0) and prepares text file that will serve as TRACE config. +# This text file will contain trivial content appropriate to FB version with 'connection_id=NNN' key. +# +# Than we make async start of trace session using FBTRACEMGR utility and after small pause (~1 sec) +# run ISQL with attempt to make connect to non-existent alias. +# +# Confirmed crash on WI-T3.0.0.30566 (Alpha 1). Note: utility fbsvcmgr can not start when trace config +# contains connection_id: standard Windows crash report appears with such data: +# ... +# AppName: fbsvcmgr.exe AppVer: 3.0.0.30566 ModName: msvcr100.dll +# ModVer: 10.0.30319.1 Offset: 0008ae6e +# ... +# +# tracker_id: CORE-4319 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [('TRACE SESSION ID.*', 'TRACE SESSION ID')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# from subprocess import Popen +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # Obtain engine version, 2.5 or 3.0, for make trace config in appropriate format: +# engine=str(db_conn.engine_version) +# db_conn.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() +# os.fsync(file_handle.fileno()) +# +# file_handle.close() +# +# #-------------------------------------------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# +# txt25 = '''# Trace config, format for 2.5. Generated auto, do not edit! +# +# enabled true +# log_errors true +# time_threshold 0 +# connection_id 1234 +# log_connections true +# +# ''' +# +# # NOTES ABOUT TRACE CONFIG FOR 3.0: +# # 1) Header contains `database` clause in different format vs FB 2.5: its data must be enclosed with '{' '}' +# # 2) Name and value must be separated by EQUALITY sign ('=') in FB-3 trace.conf, otherwise we get runtime error: +# # element "<. . .>" have no attribute value set +# +# txt30 = '''# Trace config, format for 3.0. Generated auto, do not edit! +# database=%[\\\\\\\\/]bugs.core_4319.fdb +# { +# enabled = true +# log_errors = true +# time_threshold = 0 +# connection_id = 1234 +# log_connections = true +# } +# ''' +# +# f_trccfg=open( os.path.join(context['temp_directory'],'tmp_trace_4319.cfg'), 'w') +# if engine.startswith('2.5'): +# f_trccfg.write(txt25) +# else: +# f_trccfg.write(txt30) +# flush_and_close( f_trccfg ) +# +# ##################################################### +# # Starting trace session in new child process (async.): +# # Execute a child program in a new process, redirecting STDERR to the same target as of STDOUT: +# +# f_trclog=open( os.path.join(context['temp_directory'],'tmp_trace_4319.log'), 'w') +# p_trace=Popen([ context['fbtracemgr_path'], +# "-se", "localhost:service_mgr", +# "-sta", "-c", f_trccfg.name], +# stdout=f_trclog, stderr=subprocess.STDOUT) +# +# # Wait! Trace session is initialized not instantly! +# time.sleep(1) +# +# +# f_sqltxt=open( os.path.join(context['temp_directory'],'tmp_connect_4319.sql'), 'w') +# f_sqltxt.write("connect 'localhost:some_non_existent' user 'SYSDBA' password 'masterkey'; show database; show version;") +# flush_and_close( f_sqltxt ) +# +# f_sqllog=open( os.path.join(context['temp_directory'],'tmp_connect_4319.log'), 'w') +# p_isql = subprocess.call([ context['isql_path'], dsn, "-i", f_sqltxt.name ], +# stdout=f_sqllog, stderr=subprocess.STDOUT) +# flush_and_close( f_sqllog ) +# +# # Terminate child process of launched trace session: +# +# time.sleep(1) +# +# p_trace.terminate() +# flush_and_close( f_trclog ) +# +# with open( f_trclog.name,'r') as f: +# for line in f: +# print(line.upper()) +# +# with open( f_sqllog.name,'r') as f: +# for line in f: +# if 'SQLSTATE = 08001' in line: +# print(line.upper()) +# +# # CLEANUP +# ########## +# time.sleep(1) +# cleanup( [i.name for i in (f_sqltxt, f_sqllog, f_trccfg, f_trclog)] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TRACE SESSION ID STARTED + STATEMENT FAILED, SQLSTATE = 08001 + """ + +@pytest.mark.version('>=2.5.3') +@pytest.mark.xfail +def test_core_4319_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4321.py b/tests/bugs/test_core_4321.py new file mode 100644 index 00000000..98f42efd --- /dev/null +++ b/tests/bugs/test_core_4321.py @@ -0,0 +1,75 @@ +#coding:utf-8 +# +# id: bugs.core_4321 +# title: Regression: ISQL does not destroy the SQL statement +# decription: +# tracker_id: CORE-4321 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- 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; + + 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 + ; + commit; + select count(*) c from mon$statements s + where s.mon$sql_text containing 'select 1 x' + ; + + 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 count(*) c from mon$statements s + where s.mon$sql_text containing 'select 1 x' + ; + commit; + + select count(*) c from mon$statements s + where s.mon$sql_text containing 'select 1 x' + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + X 1 + X 1 + X 1 + C 1 + C 1 + X 1 + X 1 + X 1 + X 1 + C 1 + C 1 + """ + +@pytest.mark.version('>=2.5') +def test_core_4321_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4322.py b/tests/bugs/test_core_4322.py new file mode 100644 index 00000000..38db02c0 --- /dev/null +++ b/tests/bugs/test_core_4322.py @@ -0,0 +1,60 @@ +#coding:utf-8 +# +# id: bugs.core_4322 +# title: Engine crashes when use aggregate or window functions in recursive query (instead of producing compiling error) +# decription: +# tracker_id: CORE-4322 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='NONE', sql_dialect=3, init=init_script_1) + +test_script_1 = """ +with recursive +r as( + select 0 i,count(*)over() c + from rdb$database + union all + select r.i+1,sum(i)over() from r where r.i<10 +) +select * from r; + +with recursive +r as( + select 0 i,count(*) c from rdb$database + union all + select r.i + 1, 0 from r where sum(r.i) = 0 +) +select * from r; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ +Statement failed, SQLSTATE = 42000 +Dynamic SQL Error +-SQL error code = -104 +-Recursive member of CTE cannot use aggregate or window function +Statement failed, SQLSTATE = 42000 +Dynamic SQL Error +-SQL error code = -104 +-Cannot use an aggregate or window function in a WHERE clause, use HAVING (for aggregate only) instead + """ + +@pytest.mark.version('>=3.0') +def test_core_4322_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_4326.py b/tests/bugs/test_core_4326.py new file mode 100644 index 00000000..dcdd6437 --- /dev/null +++ b/tests/bugs/test_core_4326.py @@ -0,0 +1,115 @@ +#coding:utf-8 +# +# id: bugs.core_4326 +# title: Keyword SET should not be required in ALTER USER statement +# decription: +# Checked on: +# 4.0.0.1635 SS: OK, 1.555s. +# 4.0.0.1633 CS: OK, 1.966s. +# 3.0.5.33180 SS: OK, 0.970s. +# 3.0.5.33178 CS: OK, 1.435s. +# +# tracker_id: CORE-4326 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter user tmp$c4326 password '123'; + commit; + alter user tmp$c4326 password '456' firstname 'Deep' lastname 'Purple'; + commit; + + create or alter view v_user_info as + select sec$user_name uname, sec$first_name fname, sec$last_name lname from sec$users + where sec$user_name = upper('tmp$c4326'); + commit; + + set list on; + + select * from v_user_info; + + commit; + set transaction read committed; + set term ^; + execute block returns( + uname type of column sec$users.sec$user_name + ,fname type of column sec$users.sec$first_name + ,lname type of column sec$users.sec$last_name + ) as + declare v_usr type of column sec$users.sec$user_name = 'tmp$c4326'; + declare v_pwd varchar(20) = '456'; + + begin + execute statement 'alter current user password ''IronMan'' firstname ''Black'' lastname ''Sabbath''' + with autonomous transaction + on external ( 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') ) + as user v_usr password v_pwd; + + for select uname, fname, lname from v_user_info into uname, fname, lname do suspend; + + execute statement 'alter current user password ''Kashmir'' firstname ''Led'' lastname ''Zeppelin''' + on external ( 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') ) + as user v_usr password 'IronMan'; + + end + ^ + set term ;^ + commit; + + select * from v_user_info; + 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; + + drop user tmp$c4326; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + UNAME TMP$C4326 + FNAME Deep + LNAME Purple + + UNAME TMP$C4326 + FNAME Black + LNAME Sabbath + + UNAME TMP$C4326 + FNAME Led + LNAME Zeppelin + """ + +@pytest.mark.version('>=3.0') +def test_core_4326_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4330.py b/tests/bugs/test_core_4330.py new file mode 100644 index 00000000..4f35217e --- /dev/null +++ b/tests/bugs/test_core_4330.py @@ -0,0 +1,73 @@ +#coding:utf-8 +# +# id: bugs.core_4330 +# title: not correct result function LAG, if OFFSET value are assigned from a table +# decription: +# tracker_id: CORE-4330 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + with t(a, b) as + ( + select 1, null from rdb$database + union all + select 2, 1 from rdb$database + union all + select 3, 2 from rdb$database + union all + select 4, 3 from rdb$database + union all + select 5, 2 from rdb$database + ) + select + a, + b, + lag(a, b)over(order by a) as la + from t ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A 1 + B + LA + + A 2 + B 1 + LA 1 + + A 3 + B 2 + LA 1 + + A 4 + B 3 + LA 1 + + A 5 + B 2 + LA 3 + """ + +@pytest.mark.version('>=3.0') +def test_core_4330_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4331.py b/tests/bugs/test_core_4331.py new file mode 100644 index 00000000..33a74839 --- /dev/null +++ b/tests/bugs/test_core_4331.py @@ -0,0 +1,89 @@ +#coding:utf-8 +# +# id: bugs.core_4331 +# title: LAG, LEAD and NTH_VALUE raise error when the second argument is NULL +# decription: +# tracker_id: CORE-4331 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test(id int primary key, x int, y int); + commit; + insert into test values(101, 1, 10); + insert into test values(102, 2, 20); + insert into test values(103, 3, 30); + insert into test values(104, 4, 40); + insert into test values(105, 5, 50); + insert into test values(106, 6, 60); + insert into test values(107, 7, 70); + commit; + + set list on; + select + id + ,lag(x,null)over(order by id) x_lag + ,lead(x,null)over(order by id) x_lead + ,nth_value(x,null)over(order by id) x_nth + from test t + order by id; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 101 + X_LAG + X_LEAD + X_NTH + + ID 102 + X_LAG + X_LEAD + X_NTH + + ID 103 + X_LAG + X_LEAD + X_NTH + + ID 104 + X_LAG + X_LEAD + X_NTH + + ID 105 + X_LAG + X_LEAD + X_NTH + + ID 106 + X_LAG + X_LEAD + X_NTH + + ID 107 + X_LAG + X_LEAD + X_NTH + """ + +@pytest.mark.version('>=3.0') +def test_core_4331_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4337.py b/tests/bugs/test_core_4337.py new file mode 100644 index 00000000..2e1d455b --- /dev/null +++ b/tests/bugs/test_core_4337.py @@ -0,0 +1,560 @@ +#coding:utf-8 +# +# id: bugs.core_4337 +# title: gfix -sweep makes "reconnect" when it is removed from mon$attachments by delete command (issued in another window) +# decription: +# We create table with very long char field and fill it with uuid data. +# Then we create index for this field and finally - delete all rows. +# Such table will require valuable time to be swept, about 4 seconds. +# +# After this, we launch asynchronously ISQL which makes delay ~2 seconds inside itself. +# Also, we launch trace for logging. +# +# After this we run 'gfix -sweep' in another process (synchronously). +# When delay in ISQL expires, ISQL connection executes 'DELETE FROM MON$ATTACHMENT' command +# which should kill gfix connection. This command is issued with 'set count on' for additional +# check that isql really could find this record in momn$attachments table. +# +# Process of GFIX should raise error 'connection shutdown'. +# Trace log should contain line with text 'SWEEP_FAILED' and after this line we should NOT +# discover any lines with 'ATTACH_DATABASE' event - this is especially verified. +# +# Finally, we compare content of firebird.log: new lines in it should contain messages about +# interrupted sweep ('error during sweep' and 'connection shutdown'). +# +# Checked on WI-V3.0.2.32620 (SS/SC/CS), 4.0.0.420 (SS/SC). +# Total time of test run is ~25 seconds (data filling occupies about 3 seconds). +# +# 11.05.2017: checked on WI-T4.0.0.638 - added filtering to messages about shutdown state, see comments below. +# 26.09.2017: adjusted expected_stdout section to current FB 3.0+ versions: firebird.log now does contain info +# about DB name which was swept (see CORE-5610, "Provide info about database (or alias) which was in use...") +# Checked on: +# 30Cs, build 3.0.3.32805: OK, 34.937s. +# 30SS, build 3.0.3.32805: OK, 21.063s. +# 40CS, build 4.0.0.748: OK, 31.313s. +# 40SS, build 4.0.0.748: OK, 22.578s. +# +# tracker_id: CORE-4337 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('[ ]+', ' '), ('TRACE_LOG:.* SWEEP_START', 'TRACE_LOG: SWEEP_START'), ('TRACE_LOG:.* SWEEP_FAILED', 'TRACE_LOG: SWEEP_FAILED'), ('TRACE_LOG:.* ERROR AT JPROVIDER::ATTACHDATABASE', 'TRACE_LOG: ERROR AT JPROVIDER::ATTACHDATABASE'), ('.*KILLED BY DATABASE ADMINISTRATOR.*', ''), ('TRACE_LOG:.*GFIX.EXE.*', 'TRACE_LOG: GFIX.EXE'), ('OIT [0-9]+', 'OIT'), ('OAT [0-9]+', 'OAT'), ('OST [0-9]+', 'OST'), ('NEXT [0-9]+', 'NEXT'), ('FIREBIRD.LOG:.* ERROR DURING SWEEP OF .*BUGS.CORE_4337.FDB.*', 'ERROR DURING SWEEP OF BUGS.CORE_4337.FDB')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=16384, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# from subprocess import Popen +# import difflib +# import re +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_file=db_conn.database_name +# engine=str(db_conn.engine_version) +# db_conn.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() +# os.fsync(file_handle.fileno()) +# +# file_handle.close() +# +# #-------------------------------------------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# def svc_get_fb_log( engine, f_fb_log ): +# +# global subprocess +# +# if engine.startswith('2.5'): +# get_firebird_log_key='action_get_ib_log' +# else: +# get_firebird_log_key='action_get_fb_log' +# +# subprocess.call([ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# get_firebird_log_key +# ], +# stdout=f_fb_log, stderr=subprocess.STDOUT +# ) +# return +# +# #-------------------------------------------- +# +# # Change FW to OFF in order to speed up initial data filling: +# ################## +# +# fn_nul = open(os.devnull, 'w') +# subprocess.call([ context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "prp_write_mode", "prp_wm_async", +# "dbname", db_file ], +# stdout = fn_nul, +# stderr = subprocess.STDOUT +# ) +# fn_nul.close() +# +# f_work_sql=open( os.path.join(context['temp_directory'],'tmp_work_4337.sql'), 'w') +# +# sql_dml=''' +# set list on; +# select current_time from rdb$database; +# recreate table t(s01 varchar(4000)); +# commit; +# set term ^; +# execute block as +# declare n int = 20000; +# declare w int; +# begin +# select f.rdb$field_length +# from rdb$relation_fields rf +# join rdb$fields f on rf.rdb$field_source=f.rdb$field_name +# where rf.rdb$relation_name=upper('t') +# into w; +# +# while (n>0) do +# insert into t(s01) values( rpad('', :w, uuid_to_char(gen_uuid())) ) returning :n-1 into n; +# end^ +# set term ;^ +# commit; +# select count(*) check_total_cnt, min(char_length(s01)) check_min_length from t; +# +# create index t_s01 on t(s01); +# commit; +# +# delete from t; +# commit; +# -- overall time for data filling , create index and delete all rows: ~ 3 seconds. +# -- This database requires about 4 seconds to be swept (checked on P-IV 3.0 GHz). +# select current_time from rdb$database; +# --show database; +# quit; +# ''' +# +# f_work_sql.write(sql_dml) +# flush_and_close( f_work_sql ) +# +# f_work_log=open( os.path.join(context['temp_directory'],'tmp_work_4337.log'), 'w') +# f_work_err=open( os.path.join(context['temp_directory'],'tmp_work_4337.err'), 'w') +# subprocess.call( [context['isql_path'], dsn, "-i", f_work_sql.name], +# stdout = f_work_log, +# stderr = f_work_err +# ) +# +# flush_and_close( f_work_log ) +# flush_and_close( f_work_err ) +# +# # REDUCE number of cache buffers in DB header in order to sweep make its work as long as possible +# ################################ +# ''' +# +# temply disabled, see CORE-5385: +# "Attempt to change number of buffers in DB header leads to crash (either using gfix -b ... or fbsvcmgr prp_page_buffers ... ). Only 4.0 SuperServer is affected." +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# fn_nul = open(os.devnull, 'w') +# subprocess.call([ context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "prp_page_buffers", "100", +# "dbname", db_file ], +# stdout = fn_nul, +# stderr = subprocess.STDOUT +# ) +# fn_nul.close() +# ''' +# +# +# # Change FW to ON (in order to make sweep life harder :)) +# ################## +# +# fn_nul = open(os.devnull, 'w') +# subprocess.call([ context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "prp_write_mode", "prp_wm_sync", +# "dbname", db_file ], +# stdout = fn_nul, +# stderr = subprocess.STDOUT +# ) +# fn_nul.close() +# +# f_fblog_before=open( os.path.join(context['temp_directory'],'tmp_4337_fblog_before.txt'), 'w') +# svc_get_fb_log( engine, f_fblog_before ) +# flush_and_close( f_fblog_before ) +# +# +# trc30_cfg = '''# Trace config, format for 3.0. Generated auto, do not edit! +# database=%[\\\\\\\\/]bugs.core_4337.fdb +# { +# enabled = true +# log_sweep = true +# log_errors = true +# log_connections = true +# } +# services { +# enabled = false +# log_services = true +# log_service_query = true +# } +# ''' +# +# f_trccfg=open( os.path.join(context['temp_directory'],'tmp_trace_4337.cfg'), 'w') +# f_trccfg.write(trc30_cfg) +# flush_and_close( f_trccfg ) +# +# # Starting trace session in new child process (async.): +# ####################################################### +# +# f_trclog=open( os.path.join(context['temp_directory'],'tmp_trace_4337.log'), 'w') +# f_trcerr=open( os.path.join(context['temp_directory'],'tmp_trace_4337.err'), 'w') +# +# p_trace=Popen([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_start", +# "trc_cfg", f_trccfg.name], +# stdout=f_trclog, +# stderr=f_trcerr +# ) +# +# # Wait! Trace session is initialized not instantly! +# time.sleep(1) +# +# +# # Launch (async.) ISQL which will make small delay and then kill GFIX attachment: +# ###################### +# +# sql_mon=''' +# set list on; +# +# recreate table tmp4wait(id int); +# commit; +# insert into tmp4wait(id) values(1); +# commit; +# +# set transaction lock timeout 2; ------------------ D E L A Y +# update tmp4wait set id=id; +# select 'Waiting for GFIX start SWEEP' as " " from rdb$database; +# set term ^; +# execute block as +# begin +# in autonomous transaction do +# begin +# update tmp4wait set id=id; +# when any do +# begin +# -- NOP -- +# end +# end +# end +# ^ +# set term ;^ +# commit; +# --select MON$PAGE_BUFFERS from mon$database; +# select 'Starting to delete GFIX process from mon$attachments' as " " from rdb$database; +# set count on; +# delete from mon$attachments +# where mon$remote_process containing 'gfix' +# ; +# commit; +# set count off; +# select 'Finished deleting GFIX process from mon$attachments' as " " from rdb$database; +# ''' +# +# f_wait_sql=open( os.path.join(context['temp_directory'],'tmp_wait_4337.sql'), 'w') +# f_wait_sql.write(sql_mon) +# flush_and_close( f_wait_sql ) +# +# f_wait_log=open( os.path.join(context['temp_directory'],'tmp_wait_4337.log'), 'w') +# f_wait_err=open( os.path.join(context['temp_directory'],'tmp_wait_4337.err'), 'w') +# p_isql = subprocess.Popen( [ context['isql_path'], dsn, "-i", f_wait_sql.name], +# stdout = f_wait_log, +# stderr = f_wait_err +# ) +# +# +# # Launch GFIX -SWEEP (sync.). It should be killed by ISQL which we have launched previously +# # after delay in its script will expire: +# ######################################## +# +# f_gfix_log=open( os.path.join(context['temp_directory'],'tmp_gfix_4337.log'), 'w') +# f_gfix_log.write('Point before GFIX -SWEEP.'+os.linesep) +# f_gfix_log.seek(0,2) +# subprocess.call( [ context['gfix_path'], dsn, "-sweep"], +# stdout = f_gfix_log, +# stderr = subprocess.STDOUT +# ) +# +# +# f_gfix_log.seek(0,2) +# f_gfix_log.write('Point after GFIX -SWEEP.') +# +# # Small delay to be sure that ISQL was successfully completed. +# ############## +# +# time.sleep(2) +# +# p_isql.terminate() +# +# flush_and_close( f_wait_log ) +# flush_and_close( f_wait_err ) +# flush_and_close( f_gfix_log ) +# +# +# ##################################################### +# # Getting ID of launched trace session and STOP it: +# +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# f_trclst=open( os.path.join(context['temp_directory'],'tmp_trace_4337.lst'), 'w') +# +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_list"], +# stdout=f_trclst, stderr=subprocess.STDOUT +# ) +# f_trclst.close() +# +# trcssn=0 +# with open( f_trclst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# f_trclst=open(f_trclst.name,'a') +# f_trclst.seek(0,2) +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_stop", +# "trc_id",trcssn], +# stdout=f_trclst, stderr=subprocess.STDOUT +# ) +# flush_and_close( f_trclst ) +# +# p_trace.terminate() +# flush_and_close( f_trclog ) +# flush_and_close( f_trcerr ) +# +# # Make DB shutdown and bring online because some internal server process still can be active! +# # If we skip this step than runtime error related to dropping test DB can occur! +# ######################################### +# +# f_db_reset_log=open( os.path.join(context['temp_directory'],'tmp_reset_4337.log'), 'w') +# +# f_db_reset_log.write('Point before DB shutdown.'+os.linesep) +# f_db_reset_log.seek(0,2) +# subprocess.call( [context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "prp_shutdown_mode", "prp_sm_full", "prp_shutdown_db", "0", +# "dbname", db_file, +# ], +# stdout = f_db_reset_log, +# stderr = subprocess.STDOUT +# ) +# f_db_reset_log.write(os.linesep+'Point after DB shutdown.'+os.linesep) +# +# subprocess.call( [context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "prp_db_online", +# "dbname", db_file, +# ], +# stdout = f_db_reset_log, +# stderr = subprocess.STDOUT +# ) +# +# f_db_reset_log.write(os.linesep+'Point after DB online.'+os.linesep) +# flush_and_close( f_db_reset_log ) +# +# +# # Get content of firebird.log AFTER test finish. +# ############################# +# +# f_fblog_after=open( os.path.join(context['temp_directory'],'tmp_4337_fblog_after.txt'), 'w') +# svc_get_fb_log( engine, f_fblog_after ) +# flush_and_close( f_fblog_after ) +# +# # _!_!_!_!_!_!_!_!_!_! do NOT reduce this delay: firebird.log get new messages NOT instantly !_!_!_!_!_!_!_!_ +# # Currently firebird.log can stay with OLD content if heavy concurrent workload exists on the same host! +# # ??? DISABLED 18.02.2021, BUT STILL IN DOUBT... time.sleep(5) +# +# # Compare firebird.log versions BEFORE and AFTER this test: +# ###################### +# +# oldfb=open(f_fblog_before.name, 'r') +# newfb=open(f_fblog_after.name, 'r') +# +# difftext = ''.join(difflib.unified_diff( +# oldfb.readlines(), +# newfb.readlines() +# )) +# oldfb.close() +# newfb.close() +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_4337_diff.txt'), 'w') +# f_diff_txt.write(difftext) +# flush_and_close( f_diff_txt ) +# +# # Check logs: +# ############# +# +# # 1. Log of GFIX -SWEEP should contain: +# ''' +# Point before GFIX -SWEEP. +# connection shutdown +# Point after GFIX -SWEEP. +# ''' +# +# # 11.05.2017, FB 4.0 only! +# # Following messages can appear after 'connection shutdown' +# # (letter from dimitr, 08-may-2017 20:41): +# # isc_att_shut_killed: Killed by database administrator +# # isc_att_shut_idle: Idle timeout expired +# # isc_att_shut_db_down: Database is shutdown +# # isc_att_shut_engine: Engine is shutdown +# +# with open( f_gfix_log.name,'r') as f: +# for line in f: +# if line.strip(): +# print( line.upper() ) +# +# +# # 2. Log of ISQL that was launched to kill 'GFIX -SWEEP' attachment should contain: +# ''' +# MSG Waiting for GFIX start SWEEP +# MSG Starting to delete GFIX process from mon$attachments +# Records affected: 1 +# MSG Finished deleting GFIX process from mon$attachments +# ''' +# with open( f_wait_log.name,'r') as f: +# for line in f: +# if line.strip(): +# print( 'ISQL LOG: ' + line.upper() ) +# +# +# # 3. Log of TRACE should contain 'SWEEP_FAILED' only 'DETACH_DATABASE' event after this line: +# ''' +# 2016-10-26T21:49:06.4040 (2184:00D33200) SWEEP_FAILED +# C:\\MIX\\FIREBIRD\\QA\\FBT-REPO\\TMP\\BUGS.CORE_4337.FDB (ATT_16, SYSDBA:NONE, NONE, TCPv4:127.0.0.1/1406) +# C:\\MIX\\Firebird +# b40\\gfix.exe:4700 +# 2061 ms, 17273 read(s), 781 write(s), 538838 fetch(es), 146541 mark(s) +# +# 2016-10-26T21:49:06.4040 (2184:00D33200) ERROR AT JProvider::attachDatabase +# C:\\MIX\\FIREBIRD\\QA\\FBT-REPO\\TMP\\BUGS.CORE_4337.FDB (ATT_16, SYSDBA:NONE, NONE, TCPv4:127.0.0.1/1406) +# C:\\MIX\\Firebird +# b40\\gfix.exe:4700 +# 335544856 : connection shutdown +# +# 2016-10-26T21:49:06.4040 (2184:00D33200) DETACH_DATABASE +# C:\\MIX\\FIREBIRD\\QA\\FBT-REPO\\TMP\\BUGS.CORE_4337.FDB (ATT_16, SYSDBA:NONE, NONE, TCPv4:127.0.0.1/1406) +# C:\\MIX\\Firebird +# b40\\gfix.exe:4700 +# ''' +# +# found_sweep_failed=0 +# with open( f_trclog.name,'r') as f: +# for line in f: +# if 'SWEEP_FAILED' in line: +# print( 'TRACE_LOG:' + (' '.join(line.split()).upper()) ) +# found_sweep_failed = 1 +# +# if found_sweep_failed == 1 and ('ATTACH_DATABASE' in line): +# print( 'TRACE: ATTACH DETECTED AFTER SWEEP FAILED! ' ) +# print( 'TRACE_LOG:' + (' '.join(line.split()).upper()) ) +# +# +# # Output should contain only ONE message with 'SWEEP_FAILED', and NO any rows related to ATTACH_DATABASE. +# +# # 4. Difference between old and current firebird.log should be like this: +# ''' +# + +# +CSPROG Wed Oct 26 21:49:04 2016 +# + Sweep is started by SYSDBA +# + Database "C:\\MIX\\FIREBIRD\\QA\\FBT-REPO\\TMP\\BUGS.CORE_4337.FDB" +# + OIT 21, OAT 22, OST 19, Next 25 +# + +# + +# +CSPROG Wed Oct 26 21:49:06 2016 +# + Error during sweep: +# + connection shutdown +# ''' +# +# # 5. Log of fbsvcmgr when it did shutdown DB and bring it back online should be EMPTY. +# # NB: difflib.unified_diff() can show line(s) that present in both files, without marking that line(s) with "+". +# # Usually these are 1-2 lines that placed just BEFORE difference starts. +# # So we have to check output before display diff content: lines that are really differ must start with "+". +# +# pattern = re.compile("\\+[\\s]+OIT[ ]+[0-9]+,[\\s]*OAT[\\s]+[0-9]+,[\\s]*OST[\\s]+[0-9]+,[\\s]*NEXT[\\s]+[0-9]+") +# # OIT 160, OAT 159, OST 159, Next 161 +# +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# if line.startswith('+'): +# if 'sweep'.upper() in line.upper() or 'connection'.upper() in line.upper() or pattern.match(line.upper()): +# print( 'FIREBIRD.LOG: ' + (' '.join(line.split()).upper()) ) +# +# # 6. ERROR logs of ISQL for initial data filling should be EMPTY: +# with open( f_work_err.name,'r') as f: +# for line in f: +# print('UNEXPECTED ERROR IN ISQL WHEN DID INITIAL DATA FILLING: ' + line) +# +# # 7. ERROR logs of ISQL for initial data filling should be EMPTY: +# with open( f_wait_err.name,'r') as f: +# for line in f: +# print('UNEXPECTED ERROR IN ISQL WHEN MADE DELAY AND WAITING: ' + line) +# +# +# # Cleanup. +# ############################### +# time.sleep(1) +# cleanup( [i.name for i in (f_work_sql,f_work_log,f_work_err,f_fblog_before,f_trccfg,f_trclog,f_trcerr,f_wait_sql,f_wait_log,f_wait_err,f_gfix_log,f_trclst,f_db_reset_log,f_fblog_after,f_diff_txt) ] ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + POINT BEFORE GFIX -SWEEP. + CONNECTION SHUTDOWN + POINT AFTER GFIX -SWEEP. + ISQL LOG: WAITING FOR GFIX START SWEEP + ISQL LOG: STARTING TO DELETE GFIX PROCESS FROM MON$ATTACHMENTS + ISQL LOG: RECORDS AFFECTED: 1 + ISQL LOG: FINISHED DELETING GFIX PROCESS FROM MON$ATTACHMENTS + TRACE_LOG: SWEEP_FAILED + FIREBIRD.LOG: + SWEEP IS STARTED BY SYSDBA + FIREBIRD.LOG: + OIT, OAT, OST, NEXT + FIREBIRD.LOG: + ERROR DURING SWEEP OF BUGS.CORE_4337.FDB + FIREBIRD.LOG: + CONNECTION SHUTDOWN + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4337_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4342.py b/tests/bugs/test_core_4342.py new file mode 100644 index 00000000..e4e21df2 --- /dev/null +++ b/tests/bugs/test_core_4342.py @@ -0,0 +1,168 @@ +#coding:utf-8 +# +# id: bugs.core_4342 +# title: Non-privileged user can delete records from RDB$SECURITY_CLASSES table +# decription: +# tracker_id: CORE-4342 +# min_versions: ['3.0'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter user boss password '123'; + create or alter user mngr password '456'; + commit; + + -- 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; + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + drop user mngr; + drop user boss; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + USER SYSDBA + ACL_COUNT 1 + + USER MNGR + ACL_COUNT 1 + """ +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 + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_core_4342_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + create or alter user boss password '123'; + create or alter user mngr password '456'; + commit; + + -- 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; + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + drop user mngr; + drop user boss; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + USER SYSDBA + ACL_COUNT 1 + + USER MNGR + ACL_COUNT 1 + """ +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 + """ + +@pytest.mark.version('>=4.0') +def test_core_4342_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_expected_stderr == act_2.clean_stderr + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/bugs/test_core_4344.py b/tests/bugs/test_core_4344.py new file mode 100644 index 00000000..c8171497 --- /dev/null +++ b/tests/bugs/test_core_4344.py @@ -0,0 +1,119 @@ +#coding:utf-8 +# +# id: bugs.core_4344 +# title: Error "no current record for fetch operation" when table inner join procedure inner join table +# decription: +# tracker_id: CORE-4344 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create or alter procedure sp_get_f01(a_id int) returns(f01 int) as begin end; + create or alter procedure sp_get_f02(a_id int) returns(f01 int) as begin end; + create or alter procedure sp_get_f03(a_id int) returns(f01 int) as begin end; + create or alter procedure sp_get_f04(a_id int) returns(f01 int) as begin end; + create or alter procedure sp_get_f05(a_id int) returns(f01 int) as begin end; + + recreate table test( + id int primary key using index test_pk + ,f01 int + ,f02 int + ,f03 int + ,f04 int + ,f05 int + ); + commit; + insert into test(id, f01, f02, f03, f04, f05) values( 1, 11, 22, 33, 44, 55); + insert into test(id, f01, f02, f03, f04, f05) values( 2, 111, 222, 333, 444, 555); + insert into test(id, f01, f02, f03, f04, f05) values( 3,1111,2222,3333,4444,5555); + commit; + + set term ^; + create or alter procedure sp_get_f01(a_id int) returns(f01 int) as + begin + for select f01 from test where id = :a_id into f01 do suspend; + end + ^ + create or alter procedure sp_get_f02(a_id int) returns(f02 int) as + begin + for select f02 from test where id = :a_id into f02 do suspend; + end + ^ + create or alter procedure sp_get_f03(a_id int) returns(f03 int) as + begin + for select f03 from test where id = :a_id into f03 do suspend; + end + ^ + create or alter procedure sp_get_f04(a_id int) returns(f04 int) as + begin + for select f04 from test where id = :a_id into f04 do suspend; + end + ^ + create or alter procedure sp_get_f05(a_id int) returns(f05 int) as + begin + for select f05 from test where id = :a_id into f05 do suspend; + end + ^ + set term ;^ + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select t1.id + from test t1 + join sp_get_f01(t1.id) on 1=1 + join test t2 using(id) + join sp_get_f02(t2.id) on 1=1 + join test t3 using(id) + join sp_get_f03(t3.id) on 1=1 + join test t4 using(id) + join sp_get_f04(t4.id) on 1=1 + join test t5 using(id) + join sp_get_f05(t5.id) on 1=1 + join sp_get_f04(t4.id) on 1=1 + join sp_get_f03(t4.id) on 1=1 + join sp_get_f05(t5.id) on 1=1 + join sp_get_f04(t4.id) on 1=1 + join sp_get_f03(t4.id) on 1=1 + join test u5 using(id) + join test u4 using(id) + join sp_get_f02(t4.id) on 1=1 + join sp_get_f02(t4.id) on 1=1 + join sp_get_f02(t4.id) on 1=1 + join test u3 using(id) + join test u2 using(id) + join sp_get_f01(t4.id) on 1=1 + join sp_get_f01(t4.id) on 1=1 + join sp_get_f01(t4.id) on 1=1 + join test u1 using(id) + join sp_get_f01(t4.id) on 1=1 + join test v1 using(id) + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + ID 2 + ID 3 + """ + +@pytest.mark.version('>=3.0') +def test_core_4344_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4345.py b/tests/bugs/test_core_4345.py new file mode 100644 index 00000000..972d0899 --- /dev/null +++ b/tests/bugs/test_core_4345.py @@ -0,0 +1,352 @@ +#coding:utf-8 +# +# id: bugs.core_4345 +# title: Ability to trace stored functions execution +# decription: +# Test checks two cases: 1) when execution of function is ENABLED and 2) DISABLED. +# In 1st case we search in trace log rows which prove that function execution was actually logged, +# and in 2nd case we have to ensure that trace log does NOT contain text about this event. +# Both standalone and packaged functions are checked. +# +# Checked on WI-V3.0.0.32328 (SS/SC/CS); WI-T4.0.0.633 +# +# 08-may-2017. +# Refactored: additional filtering using regexp (pattern.search(line)) in order to avoid take in account +# start transaction events in trace (number of starting Tx became differ since 29-mar-2017 when some changes +# in PIPE mechanism were done, see: +# https://github.com/FirebirdSQL/firebird/commit/e1232d8015b199e33391dd2550e7c5f7e3f08493 ) +# +# +# tracker_id: CORE-4345 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!PARAM0|EXECUTE_FUNCTION_START|EXECUTE_FUNCTION_FINISH|SA_FUNC|PG_FUNC).)*$', ''), ('LOG_FUNC_ENABLED.*EXECUTE_FUNCTION_START', 'LOG_FUNC_ENABLED EXECUTE_FUNCTION_START'), ('LOG_FUNC_ENABLED.*EXECUTE_FUNCTION_FINISH', 'LOG_FUNC_ENABLED EXECUTE_FUNCTION_FINISH')] + +init_script_1 = """ + set term ^; + create or alter function sa_func(a int) returns bigint as + begin + return a * a; + end + ^ + recreate package pg_test as + begin + function pg_func(a int) returns bigint; + end + ^ + create package body pg_test as + begin + function pg_func(a int) returns bigint as + begin + return a * a; + end + end + ^ + set term ;^ + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# from subprocess import Popen +# import shutil +# import re +# +# trace_timestamp_prefix='[.*\\s+]*20[0-9]{2}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{3,4}\\s+\\(.+\\)' +# func_start_ptn=re.compile( trace_timestamp_prefix + '\\s+(FAILED){0,1}\\s*EXECUTE_FUNCTION_START$', re.IGNORECASE) +# func_finish_ptn=re.compile( trace_timestamp_prefix + '\\s+(FAILED){0,1}\\s*EXECUTE_FUNCTION_FINISH$', re.IGNORECASE) +# func_name_ptn=re.compile('Function\\s+(SA_FUNC|PG_TEST.PG_FUNC):$') +# func_param_prn=re.compile('param[0-9]+\\s+=\\s+', re.IGNORECASE) +# +# +# db_conn.close() +# +# # Minimal delay after we issue command fbsvcmgr action_trace_start +# # and before we launch execution of checked code +# ########################################### +# min_delay_after_trace_start = 1 +# +# # Minimal delay after we finish connection to database +# # and before issuing command to stop trace +# ########################################## +# min_delay_before_trace_stop = 1 +# +# # Minimal delay for trace log be flushed on disk after +# # we issue command 'fbsvcmgr action_trace_stop': +# ############################### +# min_delay_after_trace_stop = 1 +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# def make_trace_config( is_func_logged, trccfg_name ): +# +# # NOTES ABOUT TRACE CONFIG FOR 3.0: +# # 1) Header contains `database` clause in different format vs FB 2.5: its data must be enclosed with '{' '}' +# # 2) Name and value must be separated by EQUALITY sign ('=') in FB-3 trace.conf, otherwise we get runtime error: +# # element "<. . .>" have no attribute value set +# +# if is_func_logged.upper() == 'TRUE': +# txt30 = ''' +# database=%[\\\\\\\\/]bugs.core_4345.fdb +# { +# enabled = true +# time_threshold = 0 +# log_connections = true +# log_transactions = true +# log_function_start = true +# log_function_finish = true +# } +# ''' +# else: +# txt30 = ''' +# database=%[\\\\\\\\/]bugs.core_4345.fdb +# { +# enabled = true +# time_threshold = 0 +# log_connections = true +# log_transactions = true +# log_function_start = false +# } +# ''' +# +# trccfg=open( trccfg_name, 'w') +# trccfg.write(txt30) +# trccfg.close() +# +# return +# +# def stop_trace_session(): +# +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# import os +# import subprocess +# +# f_trclst=open( os.path.join(context['temp_directory'],'tmp_trace_4345.lst'), 'w') +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", "action_trace_list"], +# stdout=f_trclst, +# stderr=subprocess.STDOUT +# ) +# f_trclst.close() +# +# trcssn=0 +# with open( f_trclst.name,'r') as f: +# for line in f: +# if 'Session ID' in line: +# trcssn=line.split()[2] +# break +# f.close() +# +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# f_trclst=open(f_trclst.name,'a') +# f_trclst.seek(0,2) +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", "action_trace_stop", "trc_id",trcssn], +# stdout=f_trclst, stderr=subprocess.STDOUT +# ) +# f_trclst.close() +# +# os.remove(f_trclst.name) +# +# return +# +# +# sql_fnc=''' +# set list on; +# set term ^; +# execute block as -- returns( sa_func_result bigint, pg_func_result bigint ) as +# declare sa_func_result bigint; +# declare pg_func_result bigint; +# begin +# sa_func_result = sa_func( %s ); +# pg_func_result = pg_test.pg_func( %s ); +# --suspend; +# end +# ^ +# set term ;^ +# commit; +# ''' +# # % (123, 456) +# +# +# ############################################################################## +# ### ### +# ### C A S E - 1: l o g _ f u n c = t r u e ### +# ### ### +# ############################################################################## +# +# # Make trace config with ENABLING logging of func. execution: +# +# trccfg_log_enable=os.path.join(context['temp_directory'],'tmp_trace_4345_log_enable.cfg') +# +# make_trace_config( 'true', trccfg_log_enable ) +# +# f_trclog_log_enable=open( os.path.join(context['temp_directory'],'tmp_trace_4345_log_enable.log'), 'w') +# +# ##################################################### +# # Starting trace session in new child process (async.): +# +# # Execute a child program in a new process, redirecting STDERR to the same target as of STDOUT: +# p_trace=Popen( [ context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_start", +# "trc_cfg", trccfg_log_enable +# ], +# stdout=f_trclog_log_enable, +# stderr=subprocess.STDOUT +# ) +# +# # Wait _AT_LEAST_ 4..5 seconds in 2.5 because trace session is initialized not instantly. +# # If this delay is less then 2 second then trace log will be EMPTY (got on 2.5 SS and Cs). +# time.sleep( min_delay_after_trace_start ) +# +# #################################################### +# # Make connection to database and perform script that +# # calls two functions: standalone and packaged: +# #################################################### +# +# runProgram('isql',[dsn, '-n', '-q'], sql_fnc % (123, 456) ) +# +# # do NOT remove this otherwise trace log can contain only message about its start before being closed! +# time.sleep(min_delay_before_trace_stop) +# +# ##################################################### +# # Getting ID of launched trace session and STOP it: +# +# stop_trace_session() +# time.sleep(min_delay_after_trace_stop) +# +# # Terminate child process of launched trace session (though it should already be killed): +# p_trace.terminate() +# f_trclog_log_enable.close() +# +# +# ############# +# # O U T P U T +# ############# +# +# with open( f_trclog_log_enable.name,'r') as f: +# for line in f: +# if ( func_start_ptn.search(line) +# or func_finish_ptn.search(line) +# or func_name_ptn.search(line) +# or func_param_prn.search(line) ): +# print('LOG_FUNC_ENABLED '+line.upper()) +# f.close() +# +# ############################################################################# +# ### ### +# ### C A S E - 2: l o g _ f u n c = f al s e ### +# ### ### +# ############################################################################# +# +# # Make trace config with DISABLING logging of func. execution: +# +# trccfg_log_disable=os.path.join(context['temp_directory'],'tmp_trace_4345_log_disable.cfg') +# make_trace_config( 'false', trccfg_log_disable ) +# +# ##################################################### +# # Starting trace session in new child process (async.): +# +# # Execute a child program in a new process, redirecting STDERR to the same target as of STDOUT: +# +# f_trclog_log_disable=open( os.path.join(context['temp_directory'],'tmp_trace_4345_log_disable.log'), 'w') +# +# p_trace=Popen( [context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_start", +# "trc_cfg", trccfg_log_disable +# ], +# stdout=f_trclog_log_disable, +# stderr=subprocess.STDOUT +# ) +# +# # Wait _AT_LEAST_ 4..5 seconds in 2.5 because trace session is initialized not instantly. +# # If this delay is less then 2 second then trace log will be EMPTY (got on 2.5 SS and Cs). +# +# time.sleep( min_delay_after_trace_start ) +# +# +# #################################################### +# # Make connection to database and perform script that +# # calls two functions: standalone and packaged: +# #################################################### +# +# runProgram('isql',[dsn, '-n', '-q'], sql_fnc % (789, 987) ) +# +# # do NOT remove this otherwise trace log can contain only message about its start before being closed! +# time.sleep(min_delay_before_trace_stop) +# +# ##################################################### +# # Getting ID of launched trace session and STOP it: +# stop_trace_session() +# time.sleep(min_delay_after_trace_stop) +# +# +# # Terminate child process of launched trace session (though it should already be killed): +# p_trace.terminate() +# f_trclog_log_disable.close() +# +# ############# +# # O U T P U T +# ############# +# +# with open( f_trclog_log_disable.name,'r') as f: +# for line in f: +# if ( func_start_ptn.search(line) +# or func_finish_ptn.search(line) +# or func_name_ptn.search(line) +# or func_param_prn.search(line) ): +# print('LOG_FUNC_DISABLED '+line.upper()) +# f.close() +# +# time.sleep(1) +# +# ############################### +# # Cleanup. +# +# f_list = (f_trclog_log_enable, f_trclog_log_disable) +# for i in range(len(f_list)): +# if os.path.isfile(f_list[i].name): +# os.remove(f_list[i].name) +# +# os.remove(trccfg_log_enable) +# os.remove(trccfg_log_disable) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + LOG_FUNC_ENABLED 2016-02-10T15:10:43.5940 (1700:00C52280) EXECUTE_FUNCTION_START + LOG_FUNC_ENABLED FUNCTION SA_FUNC: + LOG_FUNC_ENABLED PARAM0 = INTEGER, "123" + LOG_FUNC_ENABLED 2016-02-10T15:10:43.5940 (1700:00C52280) EXECUTE_FUNCTION_FINISH + LOG_FUNC_ENABLED FUNCTION SA_FUNC: + LOG_FUNC_ENABLED PARAM0 = INTEGER, "123" + LOG_FUNC_ENABLED PARAM0 = BIGINT, "15129" + LOG_FUNC_ENABLED 2016-02-10T15:10:43.5940 (1700:00C52280) EXECUTE_FUNCTION_START + LOG_FUNC_ENABLED FUNCTION PG_TEST.PG_FUNC: + LOG_FUNC_ENABLED PARAM0 = INTEGER, "456" + LOG_FUNC_ENABLED 2016-02-10T15:10:43.5940 (1700:00C52280) EXECUTE_FUNCTION_FINISH + LOG_FUNC_ENABLED FUNCTION PG_TEST.PG_FUNC: + LOG_FUNC_ENABLED PARAM0 = INTEGER, "456" + LOG_FUNC_ENABLED PARAM0 = BIGINT, "207936" + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4345_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4350.py b/tests/bugs/test_core_4350.py new file mode 100644 index 00000000..05dcded4 --- /dev/null +++ b/tests/bugs/test_core_4350.py @@ -0,0 +1,119 @@ +#coding:utf-8 +# +# id: bugs.core_4350 +# title: Support the SQL Standard ALTER SEQUENCE .. RESTART (without WITH clause) +# decription: +# :::::::::::::::::::::::::::::::::::::::: NB :::::::::::::::::::::::::::::::::::: +# 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 +# Checked on 4.0.0.2164, 3.0.7.33356 +# +# tracker_id: CORE-4350 +# min_versions: ['3.0'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate sequence g1 start with 9223372036854775807 increment by -2147483647; + recreate sequence g2 start with -9223372036854775808 increment by 2147483647; + recreate sequence g3 start with 9223372036854775807 increment by 2147483647; + recreate sequence g4 start with -9223372036854775808 increment by -2147483647; + commit; + set list on; + select next value for g1, next value for g2, next value for g3, next value for g4 + from rdb$database; + + alter sequence g1 restart; + alter sequence g2 restart; + alter sequence g3 restart; + alter sequence g4 restart; + commit; + + show sequ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +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_core_4350_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [('=.*', ''), ('[ \t]+', ' ')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + recreate sequence g1 start with 9223372036854775807 increment by -2147483647; + recreate sequence g2 start with -9223372036854775808 increment by 2147483647; + recreate sequence g3 start with 9223372036854775807 increment by 2147483647; + recreate sequence g4 start with -9223372036854775808 increment by -2147483647; + commit; + set list on; + select next value for g1, next value for g2, next value for g3, next value for g4 + from rdb$database; + + alter sequence g1 restart; + alter sequence g2 restart; + alter sequence g3 restart; + alter sequence g4 restart; + commit; + + show sequ; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +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') +def test_core_4350_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/bugs/test_core_4351.py b/tests/bugs/test_core_4351.py new file mode 100644 index 00000000..7d2d4221 --- /dev/null +++ b/tests/bugs/test_core_4351.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: bugs.core_4351 +# title: Incorrect default value when adding a new column +# decription: +# tracker_id: CORE-4351 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test(id int); + commit; + insert into test values(1); + commit; + alter table test add pwd varchar(50) character set utf8 default 'MdX8fLruCUQ=' not null collate utf8; + commit; + set list on; + select * from test; + -- WI-V2.1.7.18553: pwd = 'MdX' + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + PWD MdX8fLruCUQ= + """ + +@pytest.mark.version('>=2.5') +def test_core_4351_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4354.py b/tests/bugs/test_core_4354.py new file mode 100644 index 00000000..7f491d9d --- /dev/null +++ b/tests/bugs/test_core_4354.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_4354 +# title: Parsing of recursive query returns error "Column does not belong to referenced table" for source that HAS such column +# decription: +# tracker_id: CORE-4354 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='NONE', sql_dialect=3, init=init_script_1) + +test_script_1 = """ +with recursive +b as ( + select 0 rc + from rdb$database qa + + union all + + select b.rc+1 + from b + join rdb$database q1 on q1.rdb$relation_id*0=b.rc*0 + join rdb$database q2 on q2.rdb$relation_id*0=b.rc*0 + where b.rc=0 +) +select * from b; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RC +============ + 0 + 1 + """ + +@pytest.mark.version('>=3.0') +def test_core_4354_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4359.py b/tests/bugs/test_core_4359.py new file mode 100644 index 00000000..7d83a483 --- /dev/null +++ b/tests/bugs/test_core_4359.py @@ -0,0 +1,160 @@ +#coding:utf-8 +# +# id: bugs.core_4359 +# title: non-priviledged user can insert and update rdb$database +# decription: +# tracker_id: CORE-4359 +# min_versions: ['3.0'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Test scenario attempts to modify (or lock record) from RDB$DATABASE + -- both for SYSDBA and non-privileged user. + set count on; + + 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; + create or alter user boss password '123'; + commit; + + 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; + + commit; + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + drop user boss; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + Records affected: 0 + Records affected: 0 + """ +expected_stderr_1 = """ + 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 + + Statement failed, SQLSTATE = 28000 + no permission for INSERT access to TABLE RDB$DATABASE + + Statement failed, SQLSTATE = 28000 + no permission for DELETE access to TABLE RDB$DATABASE + + Statement failed, SQLSTATE = 28000 + no permission for UPDATE access to TABLE RDB$DATABASE + + Statement failed, SQLSTATE = HY000 + Cannot select system table RDB$DATABASE for update WITH LOCK + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_core_4359_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + -- Test scenario attempts to modify (or lock record) from RDB$DATABASE + -- both for SYSDBA and non-privileged user. + set count on; + + 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; + create or alter user boss password '123'; + commit; + + 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; + + commit; + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + drop user boss; + + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + Records affected: 0 + Records affected: 0 + Records affected: 0 + """ +expected_stderr_2 = """ + 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 + + Statement failed, SQLSTATE = 28000 + no permission for INSERT 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 BOSS + + Statement failed, SQLSTATE = 28000 + no permission for UPDATE access to TABLE RDB$DATABASE + -Effective user is BOSS + + Statement failed, SQLSTATE = HY000 + Cannot select system table RDB$DATABASE for update WITH LOCK + """ + +@pytest.mark.version('>=4.0') +def test_core_4359_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_expected_stderr == act_2.clean_stderr + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/bugs/test_core_4360.py b/tests/bugs/test_core_4360.py new file mode 100644 index 00000000..a1f1a256 --- /dev/null +++ b/tests/bugs/test_core_4360.py @@ -0,0 +1,48 @@ +#coding:utf-8 +# +# id: bugs.core_4360 +# title: SELECT from derived table which contains GROUP BY on field with literal value returns wrong result +# decription: +# tracker_id: CORE-4360 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='NONE', sql_dialect=3, init=init_script_1) + +test_script_1 = """ +select c from( select 'a' c from rdb$database group by 'a' ); +select c from( select 123 c from rdb$database group by 1 ); +select c from( select dateadd(999 millisecond to timestamp '31.12.9999 23:59:59') c from rdb$database group by 1 ); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +C +====== +a + C +============ + 123 + C +========================= +9999-12-31 23:59:59.9990 + """ + +@pytest.mark.version('>=3.0') +def test_core_4360_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4365.py b/tests/bugs/test_core_4365.py new file mode 100644 index 00000000..e3fbf32e --- /dev/null +++ b/tests/bugs/test_core_4365.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_4365 +# title: Equality predicate distribution does not work for some complex queries +# decription: +# tracker_id: CORE-4365 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('RDB\\$INDEX_[0-9]+', 'RDB\\$INDEX')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set planonly; + select * + from ( + select r.rdb$relation_id as id + from rdb$relations r + join ( + select g1.rdb$generator_id as id from rdb$generators g1 + union all + select g2.rdb$generator_id as id from rdb$generators g2 + ) rf on rf.id = r.rdb$relation_id + left join rdb$procedures p on p.rdb$procedure_id = rf.id + ) x + where id = 1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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)) + """ + +@pytest.mark.version('>=3.0') +def test_core_4365_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4366.py b/tests/bugs/test_core_4366.py new file mode 100644 index 00000000..8a1cc3d6 --- /dev/null +++ b/tests/bugs/test_core_4366.py @@ -0,0 +1,62 @@ +#coding:utf-8 +# +# id: bugs.core_4366 +# title: Wrong result of WHERE predicate when it contains NULL IS NOT DISTINCT FROM (select min(NULL) from ...) +# decription: +# tracker_id: CORE-4366 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ +recreate table tf(id int primary key, nm varchar(3)); commit; +insert into tf values(5, 'qwe'); +insert into tf values(1, 'rty'); +insert into tf values(2, 'asd'); +insert into tf values(4, 'fgh'); +insert into tf values(3, 'mnb'); +insert into tf values(7, 'bvc'); +insert into tf values(9, 'zxc'); +insert into tf values(0, 'lkj'); +insert into tf values(6, 'oiu'); +insert into tf values(8, 'fgh'); +commit; + """ + +db_1 = db_factory(page_size=4096, charset='NONE', sql_dialect=3, init=init_script_1) + +test_script_1 = """ +select nm from tf where null is not distinct from (select min(null) from tf) order by id rows 10; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +NM +====== +lkj +rty +asd +mnb +fgh +qwe +oiu +bvc +fgh +zxc + """ + +@pytest.mark.version('>=3.0') +def test_core_4366_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4369.py b/tests/bugs/test_core_4369.py new file mode 100644 index 00000000..0d16781c --- /dev/null +++ b/tests/bugs/test_core_4369.py @@ -0,0 +1,270 @@ +#coding:utf-8 +# +# id: bugs.core_4369 +# title: BUGCHECK(177) for MERGE with multiple matches +# decription: +# Checked (again, 07.06.2020) on 3.0.6.33296. +# +# 07.06.2020. NOTE: separate section for FB 4.x was added since fix for core-2274 issued: +# MERGE can not change the same record multiple times. +# For this reason we have to check only presense of ERROR in 4.x and that result is the same after merge and rollback. +# Checked on 4.0.0.2022 +# +# tracker_id: CORE-4369 +# min_versions: ['3.0'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate sequence g; + + recreate table t1 ( + id int, + val int + ); + + recreate table t2 ( + id int, + val int, + seq_inside_merge int + ); + commit; + + insert into t1 (id, val) select row_number() over(), 1000 from rdb$types rows 17; -- '17' ==> 'N', see below formula for seq_inside_merge + insert into t2(id, val, seq_inside_merge) select id, val, 0 from t1; + commit; + + alter sequence g restart with 0; + commit; + + merge into t2 as t + using t1 as s + on 1 = 1 + when matched then update set t.val = t.val + s.val, t.seq_inside_merge = next value for g + ; + + set list on; + select * from t2 order by id; + -- 1st value of `SEQ_INSIDE_MERGE` = N * (N-1) + 1 + -- All subsequent values are incremented by 1. + -- Confirmed result in WI-T3.0.0.31374 Beta-1: + -- "internal Firebird consistency check (applied differences will not fit in record (177), file: sqz.cpp line: 147)" + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + VAL 2000 + SEQ_INSIDE_MERGE 273 + + ID 2 + VAL 2000 + SEQ_INSIDE_MERGE 274 + + ID 3 + VAL 2000 + SEQ_INSIDE_MERGE 275 + + ID 4 + VAL 2000 + SEQ_INSIDE_MERGE 276 + + ID 5 + VAL 2000 + SEQ_INSIDE_MERGE 277 + + ID 6 + VAL 2000 + SEQ_INSIDE_MERGE 278 + + ID 7 + VAL 2000 + SEQ_INSIDE_MERGE 279 + + ID 8 + VAL 2000 + SEQ_INSIDE_MERGE 280 + + ID 9 + VAL 2000 + SEQ_INSIDE_MERGE 281 + + ID 10 + VAL 2000 + SEQ_INSIDE_MERGE 282 + + ID 11 + VAL 2000 + SEQ_INSIDE_MERGE 283 + + ID 12 + VAL 2000 + SEQ_INSIDE_MERGE 284 + + ID 13 + VAL 2000 + SEQ_INSIDE_MERGE 285 + + ID 14 + VAL 2000 + SEQ_INSIDE_MERGE 286 + + ID 15 + VAL 2000 + SEQ_INSIDE_MERGE 287 + + ID 16 + VAL 2000 + SEQ_INSIDE_MERGE 288 + + ID 17 + VAL 2000 + SEQ_INSIDE_MERGE 289 + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_core_4369_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + recreate sequence g; + + recreate table t1 ( + id int, + val int + ); + + recreate table t2 ( + id int, + val int, + seq_inside_merge int + ); + commit; + + insert into t1 (id, val) select row_number() over(), 1000 from rdb$types rows 17; -- '17' ==> 'N', see below formula for seq_inside_merge + insert into t2(id, val, seq_inside_merge) select id, val, 0 from t1; + commit; + + alter sequence g restart with 0; + commit; + + merge into t2 as t + using t1 as s + on 1 = 1 + when matched then update set t.val = t.val + s.val, t.seq_inside_merge = next value for g + ; + + -- all values should remain unchanged: + set list on; + select * from t2 order by id; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + ID 1 + VAL 1000 + SEQ_INSIDE_MERGE 0 + + ID 2 + VAL 1000 + SEQ_INSIDE_MERGE 0 + + ID 3 + VAL 1000 + SEQ_INSIDE_MERGE 0 + + ID 4 + VAL 1000 + SEQ_INSIDE_MERGE 0 + + ID 5 + VAL 1000 + SEQ_INSIDE_MERGE 0 + + ID 6 + VAL 1000 + SEQ_INSIDE_MERGE 0 + + ID 7 + VAL 1000 + SEQ_INSIDE_MERGE 0 + + ID 8 + VAL 1000 + SEQ_INSIDE_MERGE 0 + + ID 9 + VAL 1000 + SEQ_INSIDE_MERGE 0 + + ID 10 + VAL 1000 + SEQ_INSIDE_MERGE 0 + + ID 11 + VAL 1000 + SEQ_INSIDE_MERGE 0 + + ID 12 + VAL 1000 + SEQ_INSIDE_MERGE 0 + + ID 13 + VAL 1000 + SEQ_INSIDE_MERGE 0 + + ID 14 + VAL 1000 + SEQ_INSIDE_MERGE 0 + + ID 15 + VAL 1000 + SEQ_INSIDE_MERGE 0 + + ID 16 + VAL 1000 + SEQ_INSIDE_MERGE 0 + + ID 17 + VAL 1000 + SEQ_INSIDE_MERGE 0 + + """ +expected_stderr_2 = """ + Statement failed, SQLSTATE = 21000 + Multiple source records cannot match the same target during MERGE + """ + +@pytest.mark.version('>=4.0') +def test_core_4369_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_expected_stderr == act_2.clean_stderr + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/bugs/test_core_4371.py b/tests/bugs/test_core_4371.py new file mode 100644 index 00000000..783c26cc --- /dev/null +++ b/tests/bugs/test_core_4371.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: bugs.core_4371 +# title: Create function/sp which references to non-existent exception <...> +# decription: +# tracker_id: CORE-4371 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create or alter function fn_test returns int as begin end^ + set term ;^ + commit; + + set term ^; + create or alter function fn_test returns int as + begin + exception ex_some_non_existent_name; + return 1; + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ +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 + """ + +@pytest.mark.version('>=3.0') +def test_core_4371_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_4373.py b/tests/bugs/test_core_4373.py new file mode 100644 index 00000000..260b82e6 --- /dev/null +++ b/tests/bugs/test_core_4373.py @@ -0,0 +1,73 @@ +#coding:utf-8 +# +# id: bugs.core_4373 +# title: Duplicate names in package are not checked +# decription: +# tracker_id: CORE-4373 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^ ; + + create package new_package + as + begin + procedure external_proc; + procedure external_proc; + procedure external_proc; + end^ + + + create package body new_package + as + begin + procedure external_proc as + begin + end + + procedure internal_proc as + begin + end + procedure internal_proc as + begin + end + procedure internal_proc as + begin + end + end^ + + set term ; ^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + CREATE PACKAGE NEW_PACKAGE failed + -Duplicate PROCEDURE EXTERNAL_PROC + + Statement failed, SQLSTATE = 42000 + CREATE PACKAGE BODY NEW_PACKAGE failed + -Duplicate PROCEDURE INTERNAL_PROC + """ + +@pytest.mark.version('>=3.0') +def test_core_4373_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_4374.py b/tests/bugs/test_core_4374.py new file mode 100644 index 00000000..f2df85ae --- /dev/null +++ b/tests/bugs/test_core_4374.py @@ -0,0 +1,142 @@ +#coding:utf-8 +# +# id: bugs.core_4374 +# title: Truncation error when using EXECUTE STATEMENT with a blob +# decription: +# tracker_id: CORE-4374 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- ::: 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 ^; + execute block as + begin + execute statement 'drop procedure test_proc'; + when any do begin end + end + ^ + commit + ^ + execute block as -- returns (proc_ddl_length int) as + declare sql blob sub_type text; + declare single_sttm varchar(10); + + -- for 32 bit: + /*********************** + declare sn int = 32760; + declare big_block_for_incr varchar(32760); + declare max_length_for_big_blocks int = 1048576; + declare small_incr_amount int = 2674; -- detected maximum for 3.0 Beta2 (WI-T3.0.0.31807) + ***********************/ + + -- for 64 bit: + --/* + declare sn int = 8192; + declare big_block_for_incr varchar(8192); + declare max_length_for_big_blocks int = 794500; + declare small_incr_amount int = 19; + --*/ + begin + sql = 'create or alter procedure test_proc returns(id integer) as '||ascii_char(10)||'begin '; + max_length_for_big_blocks = max_length_for_big_blocks - char_length(sql || 'end'); + + single_sttm = 'suspend;' || ascii_char(10); + big_block_for_incr = rpad('', trunc( sn / char_length(single_sttm) ) * char_length(single_sttm), single_sttm); + + while (max_length_for_big_blocks > sn) do + begin + sql = sql || big_block_for_incr; + max_length_for_big_blocks = max_length_for_big_blocks - char_length(big_block_for_incr); + end + + sql = sql || rpad('', small_incr_amount * char_length(single_sttm), single_sttm); + sql = sql ||'end'; + + --proc_ddl_length = octet_length(sql); + rdb$set_context('USER_SESSION', 'PROC_DDL_LENGTH', octet_length(sql)); + --suspend; + + execute statement :SQL; + + end + ^ + set term ;^ + commit; + + + set term ^; + execute block returns(returned_rows int, proc_ddl_length int, proc_src_length int, approx_blr_length int) as + begin + execute statement 'select count(*) cnt from test_proc' + into returned_rows; + + proc_ddl_length = cast( rdb$get_context('USER_SESSION', 'PROC_DDL_LENGTH') as int); + + select octet_length(rdb$procedure_source) + 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RETURNED_ROWS 87379 + PROC_DDL_LENGTH 786480 + PROC_SRC_LENGTH 786420 + APPROX_BLR_LENGTH 2359000 + """ + +@pytest.mark.version('>=3.0') +def test_core_4374_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4375.py b/tests/bugs/test_core_4375.py new file mode 100644 index 00000000..998fb3dd --- /dev/null +++ b/tests/bugs/test_core_4375.py @@ -0,0 +1,85 @@ +#coding:utf-8 +# +# id: bugs.core_4375 +# title: Procedure executes infinitely if contains more than 32767 statements inside any BEGIN/END block +# decription: +# tracker_id: CORE-4375 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + -- On Alpha2 (WI-T3.0.0.30809): + -- Statement failed, SQLSTATE = 42000 + -- Dynamic SQL Error + -- -SQL error code = -104 + -- -Invalid command + -- -no column name specified for column number 1 in derived table C + -- On Beta2 (WI-T3.0.0.31807) works OK: + set term ^; + execute block returns (SQL blob sub_type text) as + begin + select + 'create or alter procedure test_proc returns(id integer) as + begin ' + || list(' + suspend; -- '||id, '') + ||' + end' + + from (select row_number()over() id from rdb$types a, rdb$types b rows 50000) c + into :SQL; + execute statement :SQL; + --suspend; + end + ^ + set term ;^ + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select count(*) cnt from test_proc; + + set term ^; + execute block returns(cnt int) as + declare v_proc_src blob; + begin + execute statement 'select count(*) cnt from test_proc' into cnt; + suspend; + + select rdb$procedure_source from rdb$procedures where rdb$procedure_name = upper('test_proc') + into v_proc_src; + select octet_length(:v_proc_src) - octet_length(replace(:v_proc_src, ascii_char(10), '')) + from rdb$database + into cnt; + suspend; + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CNT 50000 + CNT 50000 + CNT 50001 + """ + +@pytest.mark.version('>=3.0') +def test_core_4375_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4376.py b/tests/bugs/test_core_4376.py new file mode 100644 index 00000000..0579b296 --- /dev/null +++ b/tests/bugs/test_core_4376.py @@ -0,0 +1,95 @@ +#coding:utf-8 +# +# id: bugs.core_4376 +# title: Preparation of erroneous DDL statement does not show the main command failed +# decription: +# Checked on 4.0.0.2416; 3.0.0.32483 +# +# tracker_id: CORE-4376 +# min_versions: ['3.0.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('-At line[:]{0,1}[\\s]+[\\d]+,[\\s]+column[:]{0,1}[\\s]+[\\d]+', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test1(id int, name varchar(30)); + commit; + + set term ^; + create or alter procedure sp_test(a_id int) returns (o_name varchar(30)) as + begin + select text from test where id = :a_id into o_name; + suspend; + end + ^ + + create or alter package pkg_test as + begin + procedure sp_test1a(a_id int) returns (o_name varchar(30)); + procedure sp_test1b(a_id int) returns (o_name varchar(30)); + procedure sp_test1c(a_id int) returns (o_name varchar(30)); + end + ^ + + recreate package body pkg_test as + begin + + procedure sp_test1a(a_id int) returns (o_name varchar(30)) as + begin + select name from test1 where id = :a_id into o_name; + suspend; + end + + procedure sp_test1b(a_id int) returns (o_name varchar(30)) as + begin + select non_existent_field from test1 where id = :a_id into o_name; + suspend; + end + + procedure sp_test1c(a_id int) returns (o_name varchar(30)) as + begin + select name from non_existent_table where id = :a_id into o_name; + suspend; + end + end + ^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42S02 + unsuccessful metadata update + -CREATE OR ALTER PROCEDURE SP_TEST failed + -Dynamic SQL Error + -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 + -Dynamic SQL Error + -SQL error code = -206 + -Column unknown + -NON_EXISTENT_FIELD + -At line 12, column 16 + """ + +@pytest.mark.version('>=3.0') +def test_core_4376_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_4379.py b/tests/bugs/test_core_4379.py new file mode 100644 index 00000000..283c0972 --- /dev/null +++ b/tests/bugs/test_core_4379.py @@ -0,0 +1,145 @@ +#coding:utf-8 +# +# id: bugs.core_4379 +# title: Poor performance of explicit cursors containing correlated subqueries in the select list +# decription: +# tracker_id: CORE-4379 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate sequence g; + commit; + recreate table t(id int primary key using index t_pk_idx, f01 int); + commit; + delete from t; + insert into t select gen_id(g,1), gen_id(g,0)*10 from rdb$types,rdb$types + rows 20000; + commit; + """ + +db_1 = db_factory(from_backup='mon-stat-gathering-3_0.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + + execute procedure sp_truncate_stat; + commit; + execute procedure sp_gather_stat; + commit; + + set plan on; + update t a set f01 = (select f01 from t x where x.id>a.id order by id rows 1); + set plan off; + rollback; + + execute procedure sp_gather_stat; + commit; + + select natural_reads, indexed_reads from v_agg_stat_tabs where table_name = upper('T'); + + -------------------------- + + execute procedure sp_truncate_stat; + commit; + execute procedure sp_gather_stat; + commit; + + set plan on; + set term ^; + execute block as + declare c_cur cursor for (select (select f01 from t x where x.id>a.id order by id rows 1) as next_f01 from t a); + declare v_next_f01 int; + begin + open c_cur; + while (1=1) do + begin + fetch c_cur into v_next_f01; + if (row_count = 0) then leave; + update t set f01 = :v_next_f01 where current of c_cur; + end + close c_cur; + end + ^ + set term ;^ + set plan off; + rollback; + + execute procedure sp_gather_stat; + commit; + + -- On LI-T3.0.0.30981 (29-mar02014) it was 200029999 indexed reads here: + select natural_reads, indexed_reads from v_agg_stat_tabs where table_name = upper('T'); + + ----------------------------- + + execute procedure sp_truncate_stat; + commit; + execute procedure sp_gather_stat; + commit; + + set plan on; + set term ^; + execute block as + declare v_key char(8); + declare c_cur cursor for (select a.rdb$db_key as r_key, (select f01 from t x where x.id>a.id order by id rows 1) as next_f01 from t a); + declare v_next_f01 int; + begin + open c_cur; + while (1=1) do + begin + fetch c_cur into v_key, v_next_f01; + if (row_count = 0) then leave; + update t set f01 = :v_next_f01 where rdb$db_key = :v_key; + end + close c_cur; + end + ^ + set term ;^ + set plan off; + rollback; + + execute procedure sp_gather_stat; + commit; + + -- On LI-T3.0.0.30981 (29-mar02014) it was 200049999 indexed reads here: + select natural_reads, indexed_reads from v_agg_stat_tabs where table_name = upper('T'); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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) + PLAN (T INDEX ()) + NATURAL_READS 20000 + INDEXED_READS 59999 + """ + +@pytest.mark.version('>=3.0') +def test_core_4379_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4380.py b/tests/bugs/test_core_4380.py new file mode 100644 index 00000000..f771e516 --- /dev/null +++ b/tests/bugs/test_core_4380.py @@ -0,0 +1,140 @@ +#coding:utf-8 +# +# id: bugs.core_4380 +# title: ISQL truncates blob when reading an empty segment +# decription: +# Checked on: 4.0.0.138 (both Windows and POSIX); 3.0.0.32484. +# +# tracker_id: CORE-4380 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + set term ^; + create procedure sp_test_master(a_id int) returns(o_txt varchar(20)) as + begin + end + ^ + set term ;^ + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import subprocess +# import re +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # -- NB: i'm not sure that this test properly reflects the trouble described in the ticket. +# # -- At least on 3.0 Alpha 1, Alpha 2 and Beta 2 (31807) output is identical. +# # -- Note that value in "BLR to Source mapping" under 'Column' was changed to reflect +# # -- real offset from the beginning of line in THIS .fbt file (right shifted on 4 character). +# +# sql_script=''' set blob all; +# set list on; +# select rdb$debug_info from rdb$procedures; +# ''' +# +# f_blob_sql = open( os.path.join(context['temp_directory'],'tmp_blob_4380.sql'), 'w') +# f_blob_sql.write(sql_script) +# f_blob_sql.close() +# +# f_blob_log = open( os.path.join(context['temp_directory'],'tmp_blob_4380.log'), 'w') +# +# subprocess.call( [ context['isql_path'], dsn, "-i", f_blob_sql.name], +# stdout = f_blob_log, +# stderr = subprocess.STDOUT +# ) +# f_blob_log.close() +# +# # RDB$DEBUG_INFO 1a:1e1 +# # Parameters: +# # Number Name Type +# # -------------------------------------------------- +# # 0 A_ID INPUT +# # 0 O_TXT OUTPUT +# # +# # Variables: +# # Number Name +# # ------------------------------------------- +# # 0 O_TXT +# # +# # BLR to Source mapping: +# # BLR offset Line Column +# # -------------------------------- +# # 42 2 79 +# # ^ ^ ^ +# # | | | +# # +-----------+----------+---- all of them can vary! +# +# # Print content of log with filtering lines:we are interesting only for rows +# # which contain words: {'Parameters', 'Number', 'Variables', 'BLR'}. +# # For last line (with three numbers for offset, line and col) we just check +# # matching of row to appropriate pattern. +# +# # NB: we remove all exsessive spaces from printed lines. +# +# pattern = re.compile("[\\s]+[0-9]+[\\s]+[0-9]+[\\s]+[0-9]+") +# +# with open( f_blob_log.name,'r') as f: +# for line in f: +# line = line.upper() +# +# if ('PARAMETER' in line or +# 'NUMBER' in line or +# 'INPUT' in line or +# 'OUTPUT' in line or +# 'VARIABLE' in line or +# 'BLR' in line): +# print(' '.join(line.split()).upper()) +# +# if pattern.match(line): +# print('VALUES: ') +# +# ################################################ +# # Cleanup +# +# f_list=[] +# f_list.append(f_blob_sql) +# f_list.append(f_blob_log) +# +# for i in range(len(f_list)): +# if os.path.isfile(f_list[i].name): +# os.remove(f_list[i].name) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PARAMETERS: + NUMBER NAME TYPE + 0 A_ID INPUT + 0 O_TXT OUTPUT + VARIABLES: + NUMBER NAME + BLR TO SOURCE MAPPING: + BLR OFFSET LINE COLUMN + VALUES: + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4380_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4381.py b/tests/bugs/test_core_4381.py new file mode 100644 index 00000000..220258ad --- /dev/null +++ b/tests/bugs/test_core_4381.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_4381 +# title: Incorrect line/column information in runtime errors +# decription: +# tracker_id: CORE-4381 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ +set term ^; + + + +create or alter procedure p1 returns (x integer) as +begin + select + 'a' + from rdb$database + into x; +end +^ + +execute procedure p1 +^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22018 + conversion error from string "a" + -At procedure 'P1' line: 3, col: 28 + """ + +@pytest.mark.version('>=3.0') +def test_core_4381_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_4382.py b/tests/bugs/test_core_4382.py new file mode 100644 index 00000000..710c7de1 --- /dev/null +++ b/tests/bugs/test_core_4382.py @@ -0,0 +1,75 @@ +#coding:utf-8 +# +# id: bugs.core_4382 +# title: User savepoints are not released on commit +# decription: +# Added separate code for 4.0: one need to be sure that all changes have been flushed on disk before we launch gstat. +# See letter from hvlad, 02.02.2019 22:30. +# ::: NOTE ::: +# !! It looks strange but if we put preparing statement in 'init_script' section than result of 'gstat -i' will be WRONG, +# even if we do db_conn.close() before runProgram('gstat' ...) !! +# Checked on: +# 4.0.0.1421: OK, 3.340s. // SS, SC, CS +# 3.0.5.33097: OK, 1.113s. +# 2.5.9.27127: OK, 0.650s. +# +# tracker_id: CORE-4382 +# min_versions: ['2.5.4'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('^((?!nodes).)*$', ''), ('Root page: [0-9]+,', ''), ('Depth', 'depth')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.close() +# +# sql_prep=''' +# 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=4; +# savepoint c; +# update g_test set f=5; +# savepoint d; +# update g_test set f=6; +# savepoint e; +# update g_test set f=7; +# commit; +# select * from g_test; +# ''' +# runProgram( 'isql',[ '-q', dsn], sql_prep ), +# runProgram( 'gstat',['-i', dsn] ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Root page: 203, depth: 1, leaf buckets: 1, nodes: 1 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_4382_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4386.py b/tests/bugs/test_core_4386.py new file mode 100644 index 00000000..6ef172e0 --- /dev/null +++ b/tests/bugs/test_core_4386.py @@ -0,0 +1,179 @@ +#coding:utf-8 +# +# id: bugs.core_4386 +# title: Report more details for "object in use" errors +# decription: +# Checked on 3.0.6.33242 (intermediate build) after discuss with dimitr. +# +# tracker_id: CORE-4386 +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.close() +# +# CUSTOM_TX_PARAMS = ( [ fdb.isc_tpb_read_committed, fdb.isc_tpb_no_rec_version, fdb.isc_tpb_nowait ] ) +# +# sql_ddl=''' +# set bail on; +# create or alter procedure sp_worker as begin end; +# create or alter procedure sp_test as begin end; +# create or alter view v_test as select 1 x from rdb$database; +# commit; +# +# recreate table test1(id int,x int); +# recreate table test2(id int,x int); +# commit; +# +# create index test1_id on test1(id); +# commit; +# create descending index test2_id_x_desc on test2(id,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 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) +# into x +# do +# suspend; +# end +# ^ +# create or alter procedure sp_test(a_id int) returns(x int) as +# begin +# for +# execute statement ('select x from sp_worker(?)') (:a_id) +# into x +# do +# suspend; +# end +# ^ +# set term ;^ +# commit; +# +# insert into test1 values(11,111); +# insert into test1 values(21,222); +# insert into test1 values(31,333); +# insert into test1 values(41,444); +# commit; +# +# insert into test2 select * from test1; +# commit; +# ''' +# +# runProgram('isql', [ dsn ], sql_ddl) +# +# con1=fdb.connect(dsn = dsn) +# cur1=con1.cursor() +# cur1.execute('select x from sp_test(21)') +# for r in cur1: +# pass +# +# 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' +# ] +# +# for i,c in enumerate(drop_commands): +# con2=fdb.connect(dsn = dsn) +# tx = con2.trans( default_tpb = CUSTOM_TX_PARAMS ) +# ############################################# +# # READ COMMITTED | NO_RECORD_VERSION | NOWAIT +# ############################################# +# tx.begin() +# cur2=tx.cursor() +# +# try: +# cur2.execute( c ) +# tx.commit() +# except Exception as e: +# print(e[0]) +# print(e[2]) +# finally: +# cur2.close() +# con2.close() +# +# cur1.close() +# con1.close() +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Error while commiting transaction: + - SQLCODE: -901 + - lock conflict on no wait transaction + - unsuccessful metadata update + - object PROCEDURE "SP_TEST" is in use + 335544345 + + Error while commiting transaction: + - SQLCODE: -901 + - lock conflict on no wait transaction + - unsuccessful metadata update + - object PROCEDURE "SP_WORKER" is in use + 335544345 + + Error while commiting transaction: + - SQLCODE: -901 + - lock conflict on no wait transaction + - unsuccessful metadata update + - object VIEW "V_TEST" is in use + 335544345 + + Error while commiting transaction: + - SQLCODE: -901 + - lock conflict on no wait transaction + - unsuccessful metadata update + - object TABLE "TEST2" is in use + 335544345 + + Error while commiting transaction: + - SQLCODE: -901 + - lock conflict on no wait transaction + - unsuccessful metadata update + - object INDEX "TEST1_ID" is in use + 335544345 + + Error while commiting transaction: + - SQLCODE: -901 + - lock conflict on no wait transaction + - unsuccessful metadata update + - object INDEX "TEST2_ID_X_DESC" is in use + 335544345 + """ + +@pytest.mark.version('>=3.0.6') +@pytest.mark.xfail +def test_core_4386_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4388.py b/tests/bugs/test_core_4388.py new file mode 100644 index 00000000..5b492554 --- /dev/null +++ b/tests/bugs/test_core_4388.py @@ -0,0 +1,160 @@ +#coding:utf-8 +# +# id: bugs.core_4388 +# title: SELECT WITH LOCK may enter an infinite loop for a single record +# decription: +# Caution: could not reproduce on neither WI-T3.0.0.30566 Firebird 3.0 Alpha 1 nor WI-T3.0.0.30809 Firebird 3.0 Alpha 2. +# Any advice about how this test should be properly written will be appreciated. +# Added separate code for 4.0 because isc_update_conflict now can be primary code of exception reason +# (after consulting with Vlad, letter 06-aug-2018 16:27). +# +# 01-apr-2020. Expected STDERR section for 4.0.x was changed BACK TO PREVIOUS set of messages, i.e.: +# 1. Statement failed, SQLSTATE = 40001 +# 2. deadlock <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< THIS LINE APPEARED SINCE 4.0.0.1848 +# 3. update conflicts with concurrent update +# 4. concurrent transaction number is ... +# Confirmed by Alex, letter 31.03.2020 12:01. +# +# Checked on: +# 3.0.4.33022: OK, 5.453s. +# 4.0.0.1158: OK, 5.313s. +# +# 21.09.2020: removed separate section for 4.0 because error messages equal to FB 3.x. Changed 'substitution' section. +# +# Waiting for completion of child ISQL async process is done by call .wait() instead of old (and "fragile") +# assumption about maximal time that it could last before forcedly terminate it. +# +# Replaced direct specification of executable 'isql' with context['isql_path'] in order to remove dependence on PATH +# (suggested by dimitr, letter 28.08.2020, 13:42; otherwise directory with isql must be added into PATH list). +# +# +# tracker_id: CORE-4388 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('(-)?concurrent\\s+transaction\\s+number(\\s+is)?\\s+\\d+', 'concurrent transaction'), ('After\\s+line\\s+\\d+.*', '')] + +init_script_1 = """ + create table test(id int primary key, x int); + commit; + insert into test values(1, 100); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import subprocess +# from subprocess import Popen +# import time +# import fdb +# +# db_conn.close() +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# #----------------------------------- +# +# 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() +# os.fsync(file_handle.fileno()) +# +# file_handle.close() +# +# #-------------------------------------------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# +# #-------------------------------------------- +# +# att1 = fdb.connect( dsn = dsn) +# +# # Delete record but not yet commit - it's a time +# # to make another connection: +# att1.execute_immediate("delete from test where id = 1") +# +# sql_cmd=''' +# set list on; +# -- set echo on; +# commit; +# set transaction lock timeout 20; +# select x from test where id = 1 with lock; +# ''' +# +# f_select_with_lock_sql = open( os.path.join(context['temp_directory'],'tmp_4388_select_with_lock.sql'), 'w') +# f_select_with_lock_sql.write(sql_cmd) +# f_select_with_lock_sql.close() +# +# #context['isql_path'] +# +# f_select_with_lock_log = open( os.path.join(context['temp_directory'],'tmp_4388_select_with_lock.log'), 'w') +# +# p_hanged_isql=subprocess.Popen( [ context['isql_path'], dsn, "-n", "-i", f_select_with_lock_sql.name ], +# stdout = f_select_with_lock_log, +# stderr = subprocess.STDOUT +# ) +# +# # Let ISQL to be loaded and establish its attachment: +# time.sleep(2) +# +# # Return to att1 and make COMMIT of deleted record: +# ############# +# att1.commit() +# att1.close() +# ############# +# +# # Wait until ISQL complete its mission: +# p_hanged_isql.wait() +# +# flush_and_close(f_select_with_lock_log) +# +# with open(f_select_with_lock_log.name,'r') as f: +# print(f.read()) +# f.close() +# +# ############################### +# # Cleanup. +# time.sleep(1) +# f_list = [ i.name for i in (f_select_with_lock_sql, f_select_with_lock_log) ] +# cleanup( f_list ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Statement failed, SQLSTATE = 40001 + deadlock + -update conflicts with concurrent update + -concurrent transaction number is 13 + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4388_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4396.py b/tests/bugs/test_core_4396.py new file mode 100644 index 00000000..d7c47e8e --- /dev/null +++ b/tests/bugs/test_core_4396.py @@ -0,0 +1,93 @@ +#coding:utf-8 +# +# id: bugs.core_4396 +# title: incorrect result query if it is execute through "execute statement" +# decription: +# Checked on: +# 4.0.0.1635 SS: 1.091s. +# 4.0.0.1633 CS: 1.367s. +# 3.0.5.33180 SS: 0.795s. +# 3.0.5.33178 CS: 1.015s. +# +# tracker_id: CORE-4396 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test(run smallint, rn smallint, id int); + commit; + + insert into test(run, rn, id) + select 1, row_number()over(), r.rdb$relation_id + from rdb$relations r + order by rdb$relation_id rows 3; + commit; + + set term ^; + execute block returns ( id integer ) as + declare r int; + declare i int; + begin + for + execute statement + 'select row_number()over(), rdb$relation_id from rdb$relations order by rdb$relation_id rows 3' + on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') + as user 'sysdba' password 'masterkey' + into r, i + do insert into test(run, rn, id) values(2, :r, :i); + end + ^ + set term ;^ + commit; + + set list on; + select count(*) cnt + from ( + select rn,id --,min(run),max(run) + from test + group by 1,2 + having max(run)-min(run)<>1 + ) x; + 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CNT 0 + """ + +@pytest.mark.version('>=3.0') +def test_core_4396_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4398.py b/tests/bugs/test_core_4398.py new file mode 100644 index 00000000..2db4349a --- /dev/null +++ b/tests/bugs/test_core_4398.py @@ -0,0 +1,59 @@ +#coding:utf-8 +# +# id: bugs.core_4398 +# title: Provide ability to specify extra-long name of log when doing gbak to avoid "attempt to store 256 bytes in a clumplet" message +# decription: +# tracker_id: CORE-4398 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# +# print ('Starting backup...') +# fbk = os.path.join(context['temp_directory'],'backup.fbk') +# lbk = os.path.join(context['temp_directory'],'A012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890.log') +# fdn = 'localhost:'+os.path.join(context['temp_directory'],'tmp4398.tmp') +# #runProgram('gbak',['-b','-se','localhost:service_mgr','-v','-y',lbk, '-user',user_name,'-password',user_password,dsn,fbk]) +# runProgram('gbak',['-b','-user',user_name,'-password',user_password,'-v','-y',lbk,dsn,fbk]) +# print ('Backup finished.') +# if os.path.isfile(fbk): +# print ('Delete backup file...') +# os.remove(fbk) +# print ('Backup file deleted.') +# print ('Delete log file...') +# os.remove(lbk) +# print ('Log file deleted.') +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Starting backup... + Backup finished. + Delete backup file... + Backup file deleted. + Delete log file... + Log file deleted. + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4398_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4403.py b/tests/bugs/test_core_4403.py new file mode 100644 index 00000000..71f4c073 --- /dev/null +++ b/tests/bugs/test_core_4403.py @@ -0,0 +1,265 @@ +#coding:utf-8 +# +# id: bugs.core_4403 +# title: Allow referencing cursors as record variables in PSQL +# decription: +# tracker_id: CORE-4403 +# min_versions: ['3.0'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + 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); + commit; + insert into t1 values(1, 10, 11); + commit; + insert into t2 values(2, 10, 22); + commit; + insert into t3 values(3, 10, 33); + commit; + set term ^; + create or alter procedure sp_test(a_x int) returns(o_y int) as + begin + o_y = 2 * a_x; + suspend; + end + ^ + set term ;^ + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set term ^; + execute block returns( + t1_id int, t1_x int, t1_y int + ,t2_id int, t2_x int, t2_y int + ,t3_id int, t3_x int, t3_y int + ) as + begin + for + select id, x, y from t1 as cursor c1 + do begin + for select id, x, y from t2 where x = :c1.x as cursor c2 do + begin + for select id, x, y from t3 where x = :c1.x as cursor c3 do + begin + + t1_id = c1.id; + t1_x = c1.x; + t1_y = c1.y; + + t2_id = c2.id; + t2_x = c2.x; + t2_y = c2.y; + + t3_id = c3.id; + t3_x = c3.x; + t3_y = c3.y; + + suspend; + end + end + end + end + ^ + + -- This should raise exception "attempted update of read-only column", sample has been taken from: + -- sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1158905&msg=17704102 + execute block as + begin + for select x, y from t1 as cursor ce do ce.x = ce.y + 1; + 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 + select x, y from t1 + as cursor ce + do begin + old_y = ce.y; + execute procedure sp_test(ce.x) returning_values(ce.y); + new_y = ce.y; + suspend; + end + end + ^ + -- ********************/ + + set term ;^ + commit; + set list off; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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 + """ +expected_stderr_1 = """ + 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_core_4403_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """ + 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); + commit; + insert into t1 values(1, 10, 11); + commit; + insert into t2 values(2, 10, 22); + commit; + insert into t3 values(3, 10, 33); + commit; + set term ^; + create or alter procedure sp_test(a_x int) returns(o_y int) as + begin + o_y = 2 * a_x; + suspend; + end + ^ + set term ;^ + commit; + """ + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set list on; + set term ^; + execute block returns( + t1_id int, t1_x int, t1_y int + ,t2_id int, t2_x int, t2_y int + ,t3_id int, t3_x int, t3_y int + ) as + begin + for + select id, x, y from t1 as cursor c1 + do begin + for select id, x, y from t2 where x = :c1.x as cursor c2 do + begin + for select id, x, y from t3 where x = :c1.x as cursor c3 do + begin + + t1_id = c1.id; + t1_x = c1.x; + t1_y = c1.y; + + t2_id = c2.id; + t2_x = c2.x; + t2_y = c2.y; + + t3_id = c3.id; + t3_x = c3.x; + t3_y = c3.y; + + suspend; + end + end + end + end + ^ + + -- This should raise exception "attempted update of read-only column", sample has been taken from: + -- sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1158905&msg=17704102 + execute block as + begin + for select x, y from t1 as cursor ce do ce.x = ce.y + 1; + 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 + select x, y from t1 + as cursor ce + do begin + old_y = ce.y; + execute procedure sp_test(ce.x) returning_values(ce.y); + new_y = ce.y; + suspend; + end + end + ^ + --********************/ + + set term ;^ + commit; + set list off; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + 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 + """ +expected_stderr_2 = """ + Statement failed, SQLSTATE = 42000 + attempted update of read-only column CE.X + + Statement failed, SQLSTATE = 42000 + attempted update of read-only column CE.Y + """ + +@pytest.mark.version('>=4.0') +def test_core_4403_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_expected_stderr == act_2.clean_stderr + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/bugs/test_core_4409.py b/tests/bugs/test_core_4409.py new file mode 100644 index 00000000..443de7ee --- /dev/null +++ b/tests/bugs/test_core_4409.py @@ -0,0 +1,163 @@ +#coding:utf-8 +# +# id: bugs.core_4409 +# title: Enhancement in precision of calculations with NUMERIC/DECIMAL +# decription: +# Checked on 4.0.0.767: OK, 0.828s. +# Reproduced wrong result on 4.0.0.748. +# See also letter to Alex, 12-jul-2017 09:49 (prototype for this test). +# -------------------- +# ::: NB ::: +# After fix CORE-5700 ("DECFLOAT underflow should yield zero instead of an error"), 02-feb-2018, expected result was +# changed: all expressions with "almost zero" result should NOT raise any error. +# See also: +# https://github.com/FirebirdSQL/firebird/commit/a372f319f61d88151f5a34c4ee4ecdab6fe052f3 +# +# tracker_id: CORE-4409 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('0.0000000000000000', '0.000000000000000')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate sequence g; + commit; + + set list on; + --set sqlda_display on; + --set echo on; + + select gen_id(g,1) as "Test #", cast( 1e-308 as double precision ) positive_zero_e_308 from rdb$database; + + select gen_id(g,1) as "Test #", cast( 1e-309 as double precision ) positive_zero_e_309 from rdb$database; + + select gen_id(g,1) as "Test #", cast( 1e-310 as double precision ) positive_zero_e_310 from rdb$database; + + select gen_id(g,1) as "Test #", cast( 1e-320 as double precision ) positive_zero_e_320 from rdb$database; + + select gen_id(g,1) as "Test #", cast( 1e-321 as double precision ) positive_zero_e_321 from rdb$database; + + select gen_id(g,1) as "Test #", cast( 1e-322 as double precision ) positive_zero_e_322 from rdb$database; + + select gen_id(g,1) as "Test #", cast( 1e-323 as double precision ) positive_zero_e_323 from rdb$database; + + select gen_id(g,1) as "Test #", cast( 3.70550e-324 as double precision ) positive_zero_e324a from rdb$database; + + select gen_id(g,1) as "Test #", cast( 3.70549234380e-324 as double precision ) positive_zero_e324b from rdb$database; + + select gen_id(g,1) as "Test #", cast( 3.70549234381e-324 as double precision ) positive_zero_e324c from rdb$database; + + select gen_id(g,1) as "Test #", cast( 3.70548e-324 as double precision ) positive_zero_e324d from rdb$database; + + select gen_id(g,1) as "Test #", cast( 1e-324 as double precision ) positive_zero_e324e from rdb$database; + + select gen_id(g,1) as "Test #", cast( 1e-6176 as double precision ) positive_zero_e324f from rdb$database; + + select gen_id(g,1) as "Test #", cast( 1e-6177 as double precision ) positive_zero_e324g from rdb$database; + + select gen_id(g,1) as "Test #", cast( 1.79769313486231e+308 as double precision ) positive_inf_e308a from rdb$database; + + select gen_id(g,1) as "Test #", cast( 1.79769313486232e+308 as double precision ) positive_inf_e308b from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + + Test # 1 + POSITIVE_ZERO_E_308 9.999999999999999e-309 + + + + Test # 2 + POSITIVE_ZERO_E_309 0.0000000000000000 + + + + Test # 3 + POSITIVE_ZERO_E_310 0.0000000000000000 + + + + Test # 4 + POSITIVE_ZERO_E_320 0.0000000000000000 + + + + Test # 5 + POSITIVE_ZERO_E_321 0.0000000000000000 + + + + Test # 6 + POSITIVE_ZERO_E_322 0.0000000000000000 + + + + Test # 7 + POSITIVE_ZERO_E_323 0.0000000000000000 + + + + Test # 8 + POSITIVE_ZERO_E324A 0.0000000000000000 + + + + Test # 9 + POSITIVE_ZERO_E324B 0.0000000000000000 + + + + Test # 10 + POSITIVE_ZERO_E324C 0.0000000000000000 + + + + Test # 11 + POSITIVE_ZERO_E324D 0.0000000000000000 + + + + Test # 12 + POSITIVE_ZERO_E324E 0.0000000000000000 + + + + Test # 13 + POSITIVE_ZERO_E324F 0.0000000000000000 + + + + Test # 14 + POSITIVE_ZERO_E324G 0.0000000000000000 + + + + Test # 15 + POSITIVE_INF_E308A 1.797693134862310e+308 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22003 + Floating-point overflow. The exponent of a floating-point operation is greater than the magnitude allowed. + """ + +@pytest.mark.version('>=4.0') +def test_core_4409_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4415.py b/tests/bugs/test_core_4415.py new file mode 100644 index 00000000..927bb2f5 --- /dev/null +++ b/tests/bugs/test_core_4415.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: bugs.core_4415 +# title: Useless extraction of generic DDL trigger +# decription: +# tracker_id: CORE-4415 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('\\+.*', ''), ('\\=.*', ''), ('Trigger text.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter trigger tr before any ddl statement as begin end; + show trigger tr; + -- Confirmed excessive output in WI-T3.0.0.30809 Firebird 3.0 Alpha 2. Was: + -- TR, Sequence: 0, Type: BEFORE CREATE TABLE OR ALTER TABLE OR DROP TABLE OR ... OR , Active // length = 967 characters. + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TR, Sequence: 0, Type: BEFORE ANY DDL STATEMENT, Active + as begin end + """ + +@pytest.mark.version('>=3.0') +def test_core_4415_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4417.py b/tests/bugs/test_core_4417.py new file mode 100644 index 00000000..01b5345d --- /dev/null +++ b/tests/bugs/test_core_4417.py @@ -0,0 +1,33 @@ +#coding:utf-8 +# +# id: bugs.core_4417 +# title: gbak: cannot commit index ; primary key with german umlaut +# decription: Test verifies only ability to restore database w/o errors. +# tracker_id: CORE-4417 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core4417-ods-11_2.fbk', init=init_script_1) + +test_script_1 = """ + -- Confirmed crash of restoring on WI-V2.5.2.26540: message about abnnormal program termination appeared. + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.3') +def test_core_4417_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_4418.py b/tests/bugs/test_core_4418.py new file mode 100644 index 00000000..543abf78 --- /dev/null +++ b/tests/bugs/test_core_4418.py @@ -0,0 +1,118 @@ +#coding:utf-8 +# +# id: bugs.core_4418 +# title: Regression: Can not run ALTER TABLE DROP CONSTRAINT after recent changes in svn +# decription: Added some extra DDL statements to be run within single Tx and then to be rollbacked. +# tracker_id: CORE-4418 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('COLL-VERSION=\\d+\\.\\d+\\.\\d+\\.\\d+', 'COLL-VERSION=xx'), ('COLL-VERSION=\\d+\\.\\d+', 'COLL-VERSION=xx')] + +init_script_1 = """ +recreate table td(id int); +recreate table tm(id int); +commit; + +set term ^; +execute block as +begin + begin + execute statement 'drop domain dm_ids'; + when any do begin end + end + begin + execute statement 'drop domain dm_nums'; + when any do begin end + end + begin + execute statement 'drop collation nums_coll'; + when any do begin end + end +end +^set term ;^ +commit; + +create collation nums_coll for utf8 from unicode case insensitive 'NUMERIC-SORT=1'; +commit; +create domain dm_nums as varchar(20) character set utf8 collate nums_coll; +commit; +create domain dm_ids as bigint; +commit; + +recreate table tm( + id dm_ids, + nm dm_nums, + constraint tm_pk primary key(id) +); + +recreate table td( + id dm_ids, + pid dm_ids, + nm dm_nums, + constraint td_pk primary key(id), + constraint td_fk foreign key(pid) references tm +); + +set autoddl off; +commit; + +alter table td drop constraint td_fk; +alter table td drop constraint td_pk; +alter table tm drop constraint tm_pk; +drop table td; +drop table tm; +drop domain dm_nums; +drop domain dm_ids; +drop collation nums_coll; + +rollback; + """ + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ +show table tm; +show table td; +show domain dm_ids; +show domain dm_nums; +show collation nums_coll; +-- oel64: coll-version=49.192.5.41 +-- winxp: coll-version=58.0.6.50 + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +ID (DM_IDS) BIGINT Not Null +NM (DM_NUMS) VARCHAR(20) CHARACTER SET UTF8 Nullable + COLLATE NUMS_COLL +CONSTRAINT TM_PK: + Primary key (ID) +ID (DM_IDS) BIGINT Not Null +PID (DM_IDS) BIGINT Nullable +NM (DM_NUMS) VARCHAR(20) CHARACTER SET UTF8 Nullable + COLLATE NUMS_COLL +CONSTRAINT TD_FK: + Foreign key (PID) References TM (ID) +CONSTRAINT TD_PK: + Primary key (ID) +DM_IDS BIGINT Nullable +DM_NUMS VARCHAR(20) CHARACTER SET UTF8 Nullable + COLLATE NUMS_COLL +NUMS_COLL, CHARACTER SET UTF8, FROM EXTERNAL ('UNICODE'), PAD SPACE, CASE INSENSITIVE, 'COLL-VERSION=xx;NUMERIC-SORT=1' + """ + +@pytest.mark.version('>=3.0') +def test_core_4418_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4419.py b/tests/bugs/test_core_4419.py new file mode 100644 index 00000000..16155b54 --- /dev/null +++ b/tests/bugs/test_core_4419.py @@ -0,0 +1,101 @@ +#coding:utf-8 +# +# id: bugs.core_4419 +# title: Server crashes while sorting records longer than 128KB +# decription: +# tracker_id: CORE-4419 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=1, init=init_script_1) + +test_script_1 = """ + recreate table lines1 (line varchar(2000)); + + insert into lines1 (line) values('2007' || ascii_char(9) || 'abcabcabc' || ascii_char(9) || 'xx'); + insert into lines1 (line) values('2007' || ascii_char(9) || 'defdefdef' || ascii_char(9) || 'xx'); + insert into lines1 (line) values('2007' || ascii_char(9) || 'ghighighi' || ascii_char(9) || 'xx'); + insert into lines1 (line) values('2008' || ascii_char(9) || 'defdefdef' || ascii_char(9) || 'xx'); + + -- note that spaces between line values should be tabs, , ascii_char(9) + commit; + + recreate table lines2 (line varchar(2000)); + + insert into lines2 (line) values('2007' || ascii_char(9) || 'abcabcabc' || ascii_char(9) || 'xx'); + insert into lines2 (line) values('2007' || ascii_char(9) || 'defgdefg' || ascii_char(9) || 'xx'); + insert into lines2 (line) values('2007' || ascii_char(9) || 'ghighighi' || ascii_char(9) || 'xx'); + insert into lines2 (line) values('2008' || ascii_char(9) || 'abcabcabc' || ascii_char(9) || 'xx'); + insert into lines2 (line) values('2008' || ascii_char(9) || 'defdefdef' || ascii_char(9) || 'xx'); + commit; + + + set term ^; + create function split ( + s varchar(32000), + n integer = 1 + ) + returns varchar(32000) + as + declare startpos integer; + declare pos integer; + begin + -- extract tab separated parts from string + pos = 0; + while (n > 0) do + begin + startpos = pos + 1; + pos = position(ascii_char(9), :s, :startpos); + if (pos = 0) then break; + n = n - 1; + end + if (pos > 0) then + return nullif(substring(s from :startpos for pos - startpos), ''); + -- get part after last tab + else if (n = 1) then + return nullif(substring(s from :startpos), ''); + end + ^ + set term ;^ + commit; + + set list on; + select u.f1, u.f2 + from (select split(line) f1, split(line, 2) f2 from lines1 + union + select split(line), split(line, 2) from lines2) u + join (select split(line) f1, split(line, 2) f2 from lines1) a on a.f1 = u.f1 and a.f2 = u.f2 + join (select split(line) f1, split(line, 2) f2 from lines2) b on b.f1 = u.f1 and b.f2 = u.f2 + order by 1, 2; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F1 2007 + F2 abcabcabc + + F1 2007 + F2 ghighighi + + F1 2008 + F2 defdefdef + """ + +@pytest.mark.version('>=3.0') +def test_core_4419_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4422.py b/tests/bugs/test_core_4422.py new file mode 100644 index 00000000..a10a5681 --- /dev/null +++ b/tests/bugs/test_core_4422.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: bugs.core_4422 +# title: FB crashes when using row_number()over( PARTITION BY x) in ORDER by clause +# decription: +# tracker_id: CORE-4422 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + select 1 as n + from rdb$database + order by row_number()over( PARTITION BY 1); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + N +============ + 1 + """ + +@pytest.mark.version('>=3.0') +def test_core_4422_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4424.py b/tests/bugs/test_core_4424.py new file mode 100644 index 00000000..6a654f2d --- /dev/null +++ b/tests/bugs/test_core_4424.py @@ -0,0 +1,166 @@ +#coding:utf-8 +# +# id: bugs.core_4424 +# title: Rollback to wrong savepoint if several exception handlers on the same level are executed +# decription: +# Checked on WI-T4.0.0.331. +# +# tracker_id: CORE-4424 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test (f_value int); + recreate table err_log(f_value int, code_point varchar(100)); + commit; + + set term ^; + create trigger test_aiu for test after update or insert as + declare a int; + begin + if ( new.f_value >= 10 ) then a = 1/0; + end + ^ + set term ;^ + commit; + + insert into test values (1); + commit; + + set term ^; + execute block as + declare a int; + declare g int; + declare s varchar(100); + begin + update test set f_value=2; + begin + update test set f_value=3; + begin + update test set f_value=4; + begin + update test set f_value=5; + begin + update test set f_value=6; + begin + update test set f_value=10; + -- NO 'when' here! Exception should pass to upper blobk with 'set f_value=6' + end + -- NO 'when' here! Exception should pass to upper blobk with 'set f_value=5' + end + -- NO 'when' here! Exception should pass to upper blobk with 'set f_value=4' + end + -- At this point: + -- 1) table 'test' must contain f_value = 4 + -- 2) we just get exception from most nested level. + -- Now we must log which 'when' sections was in use for handling exception. + -- Also, we want to check that exception *INSIDE* last 'when' section will be also handled. + when gdscode arith_except do + begin + s = 'Fall in point_A: "WHEN GDS ARITH"'; + rdb$set_context('USER_SESSION', s, 'gds='||gdscode ); + insert into err_log (f_value, code_point) + select f_value, :s || ', gdscode='||gdscode + from test; + end + when sqlcode -802 do + begin + s = 'Fall in point_B: "WHEN SQLCODE ' ||sqlcode || '"'; + rdb$set_context('USER_SESSION', s, 'gds='||gdscode ); + insert into err_log (f_value, code_point) + select f_value, :s || ', gdscode='||gdscode + from test; + end + when any do + begin + s = 'Fall in point_C: "WHEN ANY", 1st (inner)'; + rdb$set_context('USER_SESSION', s, 'gds='||gdscode ); + insert into err_log (f_value, code_point) + select f_value, :s || ', gdscode='||gdscode + from test; + end + when any do + begin + + rdb$set_context('USER_SESSION','Fall in point_D: "WHEN ANY", 2nd (inner)', 'gds='||gdscode ); + + a = 1/0; -- ### ::: !!! NB !!! ::: ### EXCEPTION WILL BE HERE! + + -- NB: + -- Previous statement should raise anothernew exception + -- which will force engine to UNDO test.f_value from 4 to 3. + -- FB 3.0 will NOT do this (checked on WI-V3.0.1.32575), FB 4.0 works fine. + end + end + when any do + begin + s = 'Fall in point_E: "WHEN ANY", final (outer)'; + rdb$set_context('USER_SESSION', s, 'gds='||gdscode ); + insert into err_log (f_value, code_point) + select f_value, :s || ', gds='||gdscode + from test; + end + end + end + ^ + set term ;^ + commit; + set list on; + + set width ctx_name 40; + set width ctx_val 15; + + + select f_value from test; + + select f_value, code_point from err_log; + + select mon$variable_name as ctx_name, mon$variable_value as ctx_val + from mon$context_variables c + where c.mon$attachment_id = current_connection; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F_VALUE 3 + + + + F_VALUE 3 + CODE_POINT Fall in point_E: "WHEN ANY", final (outer), gds=335544321 + + + + CTX_NAME Fall in point_A: "WHEN GDS ARITH" + CTX_VAL gds=335544321 + + CTX_NAME Fall in point_C: "WHEN ANY", 1st (inner) + CTX_VAL gds=0 + + CTX_NAME Fall in point_D: "WHEN ANY", 2nd (inner) + CTX_VAL gds=0 + + CTX_NAME Fall in point_E: "WHEN ANY", final (outer) + CTX_VAL gds=335544321 + """ + +@pytest.mark.version('>=4.0') +def test_core_4424_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4425.py b/tests/bugs/test_core_4425.py new file mode 100644 index 00000000..b85d3c3f --- /dev/null +++ b/tests/bugs/test_core_4425.py @@ -0,0 +1,83 @@ +#coding:utf-8 +# +# id: bugs.core_4425 +# title: User-collations based on UNICODE are not upgrade to newer ICU version on restore +# decription: +# Test uses .fbk which was created on linux host and has collation with following DDL: +# create collation nums_coll for utf8 from unicode case insensitive 'NUMERIC-SORT=1'; +# +# SHOW COLLATION on linux host did show: COLL-VERSION=49.192.5.41. +# +# We restore this database and try to use existing collation again. +# Checked on WI-V3.0.1.32573, WI-T4.0.0.331. +# +# tracker_id: CORE-4425 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core4425.fbk', init=init_script_1) + +test_script_1 = """ + create domain dm_nums2 as varchar(20) character set utf8 collate nums_coll; + commit; + create table test2(s1 dm_nums2, s2 dm_nums2); + commit; + + insert into test2 values('123qWe', '123QwE'); + insert into test2 values('1zXcvU', '1ZXcvu'); + insert into test2 values('12XcvU', '12xCVu'); + + commit; + set list on; + select 'old table:' as msg, s1,s2,s1=s2 from test order by s1; + select 'new table:' as msg, s1,s2,s1=s2 from test2 order by s2; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG old table: + S1 1zXcvU + S2 1ZXcvu + + MSG old table: + S1 12XcvU + S2 12xCVu + + MSG old table: + S1 123qWe + S2 123QwE + + + MSG new table: + S1 1zXcvU + S2 1ZXcvu + + MSG new table: + S1 12XcvU + S2 12xCVu + + MSG new table: + S1 123qWe + S2 123QwE + + """ + +@pytest.mark.version('>=3.0') +def test_core_4425_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4430.py b/tests/bugs/test_core_4430.py new file mode 100644 index 00000000..10f7db72 --- /dev/null +++ b/tests/bugs/test_core_4430.py @@ -0,0 +1,55 @@ +#coding:utf-8 +# +# id: bugs.core_4430 +# title: Properties of user created in Legacy_UserManager padded with space up to 10 character +# decription: +# tracker_id: CORE-4430 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Confirmed padded output in WI-T3.0.0.30809 Firebird 3.0 Alpha 2: + -- SEC$USER_NAME TMP$C4430 + -- FIRST_NAME_WITH_DOT john . + -- LAST_NAME_WITH_DOT smith . + + create user tmp$c4430 password '123' firstname 'john' lastname 'smith'; + commit; + set list on; + select + sec$user_name, + sec$first_name || '.' first_name_with_dot, + sec$last_name || '.' last_name_with_dot + from sec$users + where sec$user_name = upper('tmp$c4430'); + drop user tmp$c4430; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + SEC$USER_NAME TMP$C4430 + FIRST_NAME_WITH_DOT john. + LAST_NAME_WITH_DOT smith. + """ + +@pytest.mark.version('>=3.0') +def test_core_4430_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4434.py b/tests/bugs/test_core_4434.py new file mode 100644 index 00000000..a25a40bf --- /dev/null +++ b/tests/bugs/test_core_4434.py @@ -0,0 +1,64 @@ +#coding:utf-8 +# +# id: bugs.core_4434 +# title: Extend the use of colon prefix for read/assignment OLD/NEW fields and assignment to variables +# decription: +# Checked on: +# fb30Cs, build 3.0.4.32947: OK, 1.609s. +# FB30SS, build 3.0.4.32963: OK, 0.843s. +# FB40CS, build 4.0.0.955: OK, 1.953s. +# FB40SS, build 4.0.0.967: OK, 1.094s. +# +# tracker_id: CORE-4434 +# min_versions: ['3.0.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table t1(x int, n int); + commit; + insert into t1(x) values(777); + commit; + + set term ^; + create trigger t1_bu before update on t1 as + declare v int; + begin + :v = :old.x * 2; + :new.n = :v; + end + ^ + set term ;^ + commit; + + set list on; + update t1 set x = -x rows 1; + select * from t1; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + X -777 + N 1554 + """ + +@pytest.mark.version('>=3.0') +def test_core_4434_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4436.py b/tests/bugs/test_core_4436.py new file mode 100644 index 00000000..0c84d5bd --- /dev/null +++ b/tests/bugs/test_core_4436.py @@ -0,0 +1,73 @@ +#coding:utf-8 +# +# id: bugs.core_4436 +# title: Support for different hash algorithms in HASH system function +# decription: +# Test verifies only: +# 1) ability to use syntax: hash( using ) +# 2) non-equality of hash results for sha1, sha256 and sha512 using _TRIVIAL_ sample from ticket. +# build 4.0.0.713: OK, 1.094s. +# +# Note that for strings: +# '20177527e04e05d5e7b448c1ab2b872f86831d0b' and '20177527e04e05d5e7b448c1ab2b872f86831d0b' +# - current imlpementation of SHA1, SHA256 and SHA512 gives the same hash value. +# (See: https://stackoverflow.com/questions/3475648/sha1-collision-demo-example ) +# +# NOTE. Since build 4.0.0.2180 (27.08.2020) we have to use *new* function for cryptograpic hashes +# when addition argument for algorithm is used: crypt_hash(). +# +# tracker_id: CORE-4436 +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + recreate table test(s varchar(32765)); + commit; + insert into test(s) values('4-20100433-01775-LOTES'); + insert into test(s) values('1-20100433-01765-LOTES'); + commit; + + select -(count(s) - count(distinct hash(s))) as hash_default_result from test; + + select -(count(s) - count(distinct crypt_hash(s using sha1))) as hash_sha1_result from test; + select -(count(s) - count(distinct crypt_hash(s using sha256))) as hash_sha256_result from test; + select -(count(s) - count(distinct crypt_hash(s using sha512))) as hash_sha512_result from test; + + /* + Used before 27.08.2020: + select -(count(s) - count(distinct hash(s using sha1))) as hash_sha1_result from test; + select -(count(s) - count(distinct hash(s using sha256))) as hash_sha256_result from test; + select -(count(s) - count(distinct hash(s using sha512))) as hash_sha512_result from test; + */ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + HASH_DEFAULT_RESULT -1 + HASH_SHA1_RESULT 0 + HASH_SHA256_RESULT 0 + HASH_SHA512_RESULT 0 + """ + +@pytest.mark.version('>=4.0') +def test_core_4436_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4439.py b/tests/bugs/test_core_4439.py new file mode 100644 index 00000000..e10f2f87 --- /dev/null +++ b/tests/bugs/test_core_4439.py @@ -0,0 +1,209 @@ +#coding:utf-8 +# +# id: bugs.core_4439 +# title: Raise the 1024 connections limit (FD_SETSIZE) on Windows SS/SC +# decription: +# Test tries to establish MAX_CONN_CNT = 2047 connections and then close all of them. +# Connections are established with specifying 'buffers' parameter and its value if set to minimal allowed: 50 +# (this reduces server memory consumption when check SuperClassic). +# +# Every result of establishing / closing connection is logged by writing messages: +# * Connection # %d of %d was established +# * Connection # %d of %d has been closed +# +# After processing all iterations, test closes log and count lines from this log which match to +# apropriate pattern. Total number of lines must be equal 2*MAX_CONN_CNT. +# +# If any other messages present in the log or number of lines differs from 2*MAX_CONN_CNT then error message +# will be reported. Otherwise console output remains EMPTY. +# +# NOTE-1. +# if number of established connections is more than 2047 then 1st of them will not be served by network server +# (this is network server current implementation; it can be changed later, see letter from Vlad, 10.01.2021 15:40). +# +# NOTE-2. +# If current FB server mode is 'Classic' then test actually does nothing and console output also remains empty. +# Test in such case looks as 'always successful' but actually it does not performed! +# +# Checked on: +# 4.0.0.2324 SS: 80.987s. Peak memory: 2.4 Gb +# 4.0.0.2324 SC: 96.190s. Peak memory: 4.2 Gb +# 3.0.8.33401 SS: 72.804s. Peak memory: 1.6 Gb +# 3.0.8.33401 SC: 70.862s. Peak memory: 2.4 Gb +# 2.5.9.27152 SS: 30.047s. +# 2.5.9.27152 SC: 30.501s. +# +# tracker_id: CORE-4439 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import re +# import subprocess +# import datetime as py_dt +# from datetime import datetime +# +# from fdb import services +# +# #----------------------------- +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# fb_home = services.connect(host='localhost', user= user_name, password= user_password).get_home_directory() +# fb_bins = fb_home + ('bin' if db_conn.engine_version == 2.5 else '') +# +# #-------------------------------------------- +# +# 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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# exit(1) +# +# #----------------------------------------------- +# +# def get_fb_arch(a_dsn): +# try: +# con1 = fdb.connect(dsn = a_dsn) +# con2 = fdb.connect(dsn = a_dsn) +# +# cur1 = con1.cursor() +# +# sql=( +# "select count(distinct a.mon$server_pid), min(a.mon$remote_protocol), max(iif(a.mon$remote_protocol is null,1,0))" +# +" from mon$attachments a" +# +" where a.mon$attachment_id in (%s, %s) or upper(a.mon$user) = upper('%s')" +# % (con1.attachment_id, con2.attachment_id, 'cache writer') +# ) +# +# cur1.execute(sql) +# for r in cur1.fetchall(): +# server_cnt=r[0] +# server_pro=r[1] +# cache_wrtr=r[2] +# +# if server_pro == None: +# fba='Embedded' +# elif cache_wrtr == 1: +# fba='SS' +# elif server_cnt == 2: +# fba='CS' +# else: +# +# f1=con1.db_info(fdb.isc_info_fetches) +# +# cur2=con2.cursor() +# cur2.execute('select 1 from rdb$database') +# for r in cur2.fetchall(): +# pass +# +# f2=con1.db_info(fdb.isc_info_fetches) +# +# fba = 'SC' if f1 ==f2 else 'SS' +# +# #print(fba, con1.engine_version, con1.version) +# return fba +# +# finally: +# con1.close() +# con2.close() +# +# #------------------------------------------------- +# +# MAX_CONN_CNT=2047 +# +# DB_NAME=db_conn.database_name +# db_conn.close() +# +# fb_arch= get_fb_arch(dsn) +# +# if fb_arch in ('SS', 'SC'): +# f_this_log = open( os.path.join(context['temp_directory'],'tmp_c4439.log'), 'w') +# con_list=[] +# for i in range(0,MAX_CONN_CNT): +# con_list.append( fdb.connect( dsn = dsn, buffers = 50 ) ) +# f_this_log.write('Connection # %d of %d was established\\n' % (i+1, MAX_CONN_CNT) ) +# +# # subprocess.call( [ os.path.join( fb_bins, 'fb_lock_print' ), '-c', '-d', DB_NAME ], stdout = f_this_log, stderr = subprocess.STDOUT ) +# +# for i, c in enumerate(con_list): +# c.close() +# f_this_log.write('Connection # %d of %d has been closed\\n' % (i+1, MAX_CONN_CNT) ) +# +# subprocess.call( [ os.path.join( fb_bins, 'gfix' ), '-shut', 'full', '-force', '0', dsn ], stdout = f_this_log, stderr = subprocess.STDOUT ) +# subprocess.call( [ os.path.join( fb_bins, 'gfix' ), '-online', dsn ], stdout = f_this_log, stderr = subprocess.STDOUT ) +# +# flush_and_close( f_this_log ) +# +# # Parse log: we must find lines in it with text like 'Connection ... was established' +# # and same number of lines with text like 'Connection ... closed'. All other messages must be considered +# # as unexpected. +# p = re.compile('Connection\\s+#\\s+\\d+\\s+of\\s+\\d+\\s+.*\\s+(established|closed)', re.IGNORECASE) +# n_matches = 0 +# with open(f_this_log.name, 'r') as f: +# for line in f: +# if line: +# if p.search(line): +# n_matches += 1 +# else: +# print('UNEXPECTED OUTPUT: '+line) +# +# if n_matches == 2 * MAX_CONN_CNT: +# # do NOT print anything if all OK! +# pass +# else: +# print('Number of matches: %d - NOT EQUAL to expected: %d' % (n_matches, 2 * MAX_CONN_CNT) ) +# +# cleanup( (f_this_log.name,) ) +# +# else: +# # Classic server: we must NOT check this mode. +# pass +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.3') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_4439_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4440.py b/tests/bugs/test_core_4440.py new file mode 100644 index 00000000..ca5dbd1d --- /dev/null +++ b/tests/bugs/test_core_4440.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: bugs.core_4440 +# title: isql crash without connect when execute command "show version" +# decription: +# tracker_id: CORE-4440 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!SYSDBA).)*$', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + show version; + set list on; + select current_user from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + USER SYSDBA + """ + +@pytest.mark.version('>=3.0') +def test_core_4440_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4447.py b/tests/bugs/test_core_4447.py new file mode 100644 index 00000000..d259174a --- /dev/null +++ b/tests/bugs/test_core_4447.py @@ -0,0 +1,62 @@ +#coding:utf-8 +# +# id: bugs.core_4447 +# title: Positioned UPDATE statement prohibits index usage for the subsequent cursor field references +# decription: +# tracker_id: CORE-4447 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table ts(id int, x int, y int, z int, constraint ts_pk_id primary key (id) ); + recreate table tt(x int, y int, z int, constraint tt_pk_xy primary key (x,y) ); + commit; + + insert into ts + select row_number()over(), rand()*10, rand()*10, rand()*10 + from rdb$types; + commit; + + insert into tt select distinct x,y,0 from ts; + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set planonly; + set term ^; + execute block as + begin + for select id,x,y,z from ts as cursor c + do begin + update ts set id = id where current of c; -- <<<<<<<<<<<<<<< ::: NB ::: we lock record in source using "current of" clause + update tt t set t.z = t.z + c.z where t.x=c.x and t.y = c.y; + end + end + ^ set term ;^ + set planonly; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (T INDEX (TT_PK_XY)) + PLAN (C TS NATURAL) + """ + +@pytest.mark.version('>=3.0') +def test_core_4447_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4451.py b/tests/bugs/test_core_4451.py new file mode 100644 index 00000000..21592817 --- /dev/null +++ b/tests/bugs/test_core_4451.py @@ -0,0 +1,210 @@ +#coding:utf-8 +# +# id: bugs.core_4451 +# title: Allow output to trace explain plan form. +# decription: +# Checked on +# 4.0.0.1685 SS: 7.985s. +# 4.0.0.1685 CS: 8.711s. +# 3.0.5.33206 SS: 7.281s. +# 3.0.5.33206 CS: 8.278s. +# +# tracker_id: CORE-4451 +# min_versions: ['3.0.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('[ \t]+[\\d]+[ \t]+ms', '')] + +init_script_1 = """ + recreate table test(x int); + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# from subprocess import Popen +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# fdb_file=db_conn.database_name +# db_conn.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() +# os.fsync(file_handle.fileno()) +# +# file_handle.close() +# +# #-------------------------------------------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# +# +# ##################################################################### +# # Prepare config for trace session that will be launched by call of FBSVCMGR: +# +# txt = ''' database= # %[\\\\\\\\/]bugs.core_4451.fdb +# { +# enabled = true +# time_threshold = 0 +# log_initfini = false +# print_plan = true +# explain_plan = true +# log_statement_prepare = true +# include_filter=%(from|join)[[:whitespace:]]test% +# } +# ''' +# f_trccfg=open( os.path.join(context['temp_directory'],'tmp_trace_4451.cfg'), 'w') +# f_trccfg.write(txt) +# flush_and_close( f_trccfg ) +# +# ##################################################################### +# # Async. launch of trace session using FBSVCMGR action_trace_start: +# +# f_trclog=open( os.path.join(context['temp_directory'],'tmp_trace_4451.log'), 'w') +# +# # Execute a child program in a new process, redirecting STDERR to the same target as of STDOUT: +# p_svcmgr = Popen( [ context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_start", +# "trc_cfg", f_trccfg.name +# ], +# stdout=f_trclog, +# stderr=subprocess.STDOUT +# ) +# +# # Wait! Trace session is initialized not instantly! +# time.sleep(2) +# +# ##################################################################### +# +# # Determine active trace session ID (for further stop): +# +# f_trclst=open( os.path.join(context['temp_directory'],'tmp_trace_4451.lst'), 'w') +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_list"], +# stdout=f_trclst, stderr=subprocess.STDOUT +# ) +# flush_and_close( f_trclst ) +# +# # Session ID: 5 +# # user: +# # date: 2015-08-27 15:24:14 +# # flags: active, trace +# +# trcssn=0 +# with open( f_trclst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# +# # Result: `trcssn` is ID of active trace session. +# # We have to terminate trace session that is running on server BEFORE we termitane process `p_svcmgr` +# if trcssn==0: +# print("Error parsing trace session ID.") +# flush_and_close( f_trclog ) +# else: +# ##################################################################### +# +# # Preparing script for ISQL: +# +# sql_cmd='''select count(*) from test;''' +# +# so=sys.stdout +# se=sys.stderr +# +# sys.stdout = open(os.devnull, 'w') +# sys.stderr = sys.stdout +# +# runProgram('isql',[dsn],sql_cmd) +# +# sys.stdout = so +# sys.stderr = se +# +# # do NOT reduce this delay! +# time.sleep(2) +# +# ##################################################################### +# +# # Stop trace session: +# +# f_trclst=open(f_trclst.name, "a") +# f_trclst.seek(0,2) +# subprocess.call( [ context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_stop", +# "trc_id",trcssn +# ], +# stdout=f_trclst, +# stderr=subprocess.STDOUT +# ) +# flush_and_close( f_trclst ) +# +# p_svcmgr.terminate() +# flush_and_close( f_trclog ) +# +# # do NOT remove this delay: +# time.sleep(1) +# +# show_line = 0 +# with open(f_trclog.name) as f: +# for line in f: +# show_line = ( show_line + 1 if ('^' * 79) in line or show_line>0 else show_line ) +# if show_line > 1: +# print(line) +# +# # cleanup: +# ########## +# time.sleep(1) +# cleanup( [i.name for i in (f_trclst, f_trccfg, f_trclog) ] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Select Expression + -> Aggregate + -> Table "TEST" Full Scan + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4451_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4452.py b/tests/bugs/test_core_4452.py new file mode 100644 index 00000000..ec3acc46 --- /dev/null +++ b/tests/bugs/test_core_4452.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: bugs.core_4452 +# title: Can`t create two collations with different names if autoddl OFF in FB 2.5.3 +# decription: +# tracker_id: CORE-4452 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('COLL-VERSION=\\d+\\.\\d+\\.\\d+\\.\\d+', 'COLL-VERSION=xx'), ('COLL-VERSION=\\d+\\.\\d+', 'COLL-VERSION=xx')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ +show collation; +set autoddl off; +commit; +create collation name_coll for utf8 from unicode CASE INSENSITIVE; +create collation nums_coll for utf8 from unicode CASE INSENSITIVE 'NUMERIC-SORT=1'; +commit; +show collation; +drop collation name_coll; +drop collation nums_coll; +commit; +create collation name_coll for utf8 from unicode CASE INSENSITIVE; +create collation nums_coll for utf8 from unicode CASE INSENSITIVE 'NUMERIC-SORT=1'; +commit; +show collation; +drop collation name_coll; +drop collation nums_coll; +commit; +show collation; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +NAME_COLL, CHARACTER SET UTF8, FROM EXTERNAL ('UNICODE'), PAD SPACE, CASE INSENSITIVE, 'COLL-VERSION=xx' +NUMS_COLL, CHARACTER SET UTF8, FROM EXTERNAL ('UNICODE'), PAD SPACE, CASE INSENSITIVE, 'COLL-VERSION=xx;NUMERIC-SORT=1' + +NAME_COLL, CHARACTER SET UTF8, FROM EXTERNAL ('UNICODE'), PAD SPACE, CASE INSENSITIVE, 'COLL-VERSION=xx' +NUMS_COLL, CHARACTER SET UTF8, FROM EXTERNAL ('UNICODE'), PAD SPACE, CASE INSENSITIVE, 'COLL-VERSION=xx;NUMERIC-SORT=1' + """ +expected_stderr_1 = """ +There are no user-defined collations in this database +There are no user-defined collations in this database + """ + +@pytest.mark.version('>=3.0') +def test_core_4452_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4453.py b/tests/bugs/test_core_4453.py new file mode 100644 index 00000000..de102798 --- /dev/null +++ b/tests/bugs/test_core_4453.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_4453 +# title: Regression: NOT NULL constraint, declared in domain, does not work +# decription: +# tracker_id: CORE-4453 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + -- 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); + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + insert into t_01(x) values(100); + select * from t_01 where s is null; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 23000 + validation error for column "T_01"."S", value "*** null ***" + """ + +@pytest.mark.version('>=3.0') +def test_core_4453_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_4457.py b/tests/bugs/test_core_4457.py new file mode 100644 index 00000000..5ae8aa8f --- /dev/null +++ b/tests/bugs/test_core_4457.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: bugs.core_4457 +# title: DATEADD should support fractional value for MILLISECOND +# decription: +# tracker_id: CORE-4457 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select cast(dateadd(-1 * extract(millisecond from ts) millisecond to ts) as varchar(30)) dts, extract(millisecond from ts) ms + from ( + select timestamp'2014-06-09 13:50:17.4971' as ts + from rdb$database + ) a; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DTS 2014-06-09 13:50:17.0000 + MS 497.1 + """ + +@pytest.mark.version('>=3.0') +def test_core_4457_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4460.py b/tests/bugs/test_core_4460.py new file mode 100644 index 00000000..d68fc989 --- /dev/null +++ b/tests/bugs/test_core_4460.py @@ -0,0 +1,67 @@ +#coding:utf-8 +# +# id: bugs.core_4460 +# title: Expressions containing some built-in functions may be badly optimized +# decription: +# tracker_id: CORE-4460 +# min_versions: ['2.5.3'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('RDB\\$INDEX_[0-9]+', 'RDB\\$INDEX_')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set planonly; + select * from ( + select rdb$relation_name from rdb$relations + union + select rdb$field_name from rdb$fields + ) as dt (name) where dt.name='' + ; + select * from ( + select rdb$relation_name from rdb$relations + union + select rdb$field_name from rdb$fields + ) as dt (name) where dt.name = left('', 0) + ; + + select * from ( + select rdb$relation_name from rdb$relations + union + select rdb$field_name from rdb$fields + ) as dt (name) where dt.name = minvalue('', '') + ; + + select * from ( + select rdb$relation_name from rdb$relations + union + select rdb$field_name from rdb$fields + ) as dt (name) where dt.name = rpad('', 0, '') + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN SORT (DT RDB$RELATIONS INDEX (RDB$INDEX_0), DT RDB$FIELDS INDEX (RDB$INDEX_2)) + PLAN SORT (DT RDB$RELATIONS INDEX (RDB$INDEX_0), DT RDB$FIELDS INDEX (RDB$INDEX_2)) + PLAN SORT (DT RDB$RELATIONS INDEX (RDB$INDEX_0), DT RDB$FIELDS INDEX (RDB$INDEX_2)) + PLAN SORT (DT RDB$RELATIONS INDEX (RDB$INDEX_0), DT RDB$FIELDS INDEX (RDB$INDEX_2)) + """ + +@pytest.mark.version('>=3.0') +def test_core_4460_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4461.py b/tests/bugs/test_core_4461.py new file mode 100644 index 00000000..68769cc8 --- /dev/null +++ b/tests/bugs/test_core_4461.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: bugs.core_4461 +# title: nbackup prints error messages to stdout instead stderr +# decription: +# tracker_id: CORE-4461 +# min_versions: ['2.5.4'] +# versions: 2.5.4 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.4 +# resources: None + +substitutions_1 = [('Failure: Database error', '')] + +init_script_1 = """ + -- NB: line `Failure: Database error` exists only in 2.5.x output. + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# runProgram('nbackup',['-user','nonExistentFoo','-pas','invalidBar','-L',dsn]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + [ + PROBLEM ON "attach database". + Your user name and password are not defined. Ask your database administrator to set up a Firebird login. + SQLCODE:-902 + ] + """ + +@pytest.mark.version('>=2.5.4') +@pytest.mark.xfail +def test_core_4461_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4462.py b/tests/bugs/test_core_4462.py new file mode 100644 index 00000000..d1479e85 --- /dev/null +++ b/tests/bugs/test_core_4462.py @@ -0,0 +1,270 @@ +#coding:utf-8 +# +# id: bugs.core_4462 +# title: Make it possible to restore compressed .nbk files without explicitly decompressing them +# decription: +# Test uses three preliminarily created .zip files: +# 1. 7zip-standalone-binary.zip -- contains standalone console utility 7za.exe +# 2. zstd-standalone-binary.zip -- contains standalone console utility zstd.exe +# 3. standard_sample_databases.zip -- contains SQL statements for Firebird EMPLOYEE and Oracle "HR" schema. +# +# We extract files from all of these .zip archives and do following: +# * apply Firebird SQL script which creates the same DB as standard EMPLOYEE; +# * invoke "nbackup -b 0 ..." and use Python PIPE mechanism for redirecting STDOUT to 7za.exe utility which, +# in turn, will accept data from this stream and compress them to .7z file. +# This eventually creates .7z file with compressed .nbk0 file. +# +# * apply SQL script from Oracle "HR" schema which adds several other tables and data; +# * invoke "nbackup -b 1 ..." and use again Python PIPE mechanism for redirecting STDOUT to 7za.exe utility. +# This will create one more .7z file with compressed .nbk1 file. +# * invoke "nbackup -decompress ..." with specifying command for running 7za.exe which will extract every file +# from those which are specified in the command, i.e: +# +# nbackup -decompress "c:\\path oz.exe x -y" +# +# * validate just restored database and check content of firebird.log: it should NOT contain any errors or warnings. +# +# ::: NB ::: +# +# This is *initial* implementation! We use trivial database with ascii-only metadata and data. +# Also, we use only 7za.exe compressor and zstd.exe is not yet used. +# +# Later this test may be expanded for check non-ascii metadata and/or data. +# Checked on: +# 4.0.0.1713 SS: 7.094s. +# 4.0.0.1691 CS: 9.969s. +# 3.0.5.33218 SS: 4.750s. +# 3.0.5.33212 CS: 6.976s. +# +# tracker_id: CORE-4462 +# min_versions: ['3.0.5'] +# versions: 3.0.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import zipfile +# import time +# import re +# import difflib +# import subprocess +# from subprocess import PIPE +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# #-------------------------------------------- +# +# def svc_get_fb_log( fb_home, f_fb_log ): +# +# global subprocess +# subprocess.call( [ fb_home + "fbsvcmgr", +# "localhost:service_mgr", +# "action_get_fb_log" +# ], +# stdout=f_fb_log, stderr=subprocess.STDOUT +# ) +# return +# +# #-------------------------------------------- +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# #-------------------------------------------- +# +# fb_home = services.connect(host='localhost', user= user_name, password= user_password).get_home_directory() +# this_db = db_conn.database_name +# +# fdb_for_restore = os.path.join(context['temp_directory'],'tmp_4462_restored.fdb') +# nbk0_name = '.'.join( (os.path.splitext( this_db )[0], 'nbk0') ) +# nbk1_name = '.'.join( (os.path.splitext( this_db )[0], 'nbk1') ) +# zip0_name = nbk0_name + '.7z' +# zip1_name = nbk1_name + '.7z' +# +# f_list = ( fdb_for_restore, nbk0_name, nbk1_name, zip0_name, zip1_name ) +# cleanup( f_list ) +# +# db_conn.close() +# +# for z in ( '7zip-standalone-binary.zip', 'zstd-standalone-binary.zip', 'standard_sample_databases.zip'): +# zf = zipfile.ZipFile( os.path.join(context['files_location'], z ) ) +# zf.extractall( context['temp_directory'] ) +# zf.close() +# # Result: scripts sample-DB_-_firebird.sql, sample-DB_-_oracle.sql and +# # standalone binaries for 7-zip and zstd have been extracted into context['temp_directory'] +# +# p7z_exe = os.path.join(context['temp_directory'],'7za.exe') +# zstd_exe = os.path.join(context['temp_directory'],'zstd.exe') +# +# ################################################################################################################ +# +# f_sql_log=open( os.path.join(context['temp_directory'],'tmp_4462_init.log'), 'w', buffering = 0) +# subprocess.call( [ fb_home + 'isql', dsn, '-i', os.path.join(context['temp_directory'],'sample-DB_-_firebird.sql') ], stdout = f_sql_log, stderr = subprocess.STDOUT) +# f_sql_log.close() +# +# # https://docs.python.org/2/library/subprocess.html#replacing-shell-pipeline +# # output=`dmesg | grep hda` +# # becomes: +# # p1 = Popen(["dmesg"], stdout=PIPE) +# # p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE) +# # p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits. +# # output = p2.communicate()[0] +# +# # nbackup.exe -b 0 employee stdout | 7za u -siemployee.nbk0 C:\\FBSS\\employee.nbk0.7z +# +# p_sender = subprocess.Popen( [ fb_home+'nbackup', '-b', '0', this_db, 'stdout' ], stdout=PIPE) +# p_getter = subprocess.Popen( [ os.path.join(context['temp_directory'],'7za.exe'), 'u', '-bb3', '-bt', '-bse2', '-si' + os.path.split(nbk0_name)[1], zip0_name ], stdin = p_sender.stdout, stdout = PIPE ) +# p_sender.stdout.close() +# p_getter_stdout, p_getter_stderr = p_getter.communicate() +# +# # result: file with name = %FBT_REPO% mp\\BUGS.CORE_4462.nbk0.7z must be created at this point +# +# f_nbk0_to_7z_log = open( os.path.join(context['temp_directory'],'tmp_4462_nbk0_to_7z.log'), 'w', buffering = 0) +# f_nbk0_to_7z_log.write( p_getter_stdout if p_getter_stdout else '' ) +# f_nbk0_to_7z_log.write( p_getter_stderr if p_getter_stderr else '' ) +# f_nbk0_to_7z_log.close() +# +# ################################################################################################################ +# +# f_sql_log=open( os.path.join(context['temp_directory'],'tmp_4462_init.log'), 'a', buffering = 0) +# subprocess.call( [ fb_home + 'isql', dsn, '-i', os.path.join(context['temp_directory'],'sample-DB_-_oracle.sql') ], stdout = f_sql_log, stderr = subprocess.STDOUT) +# f_sql_log.close() +# +# p_sender = subprocess.Popen( [ fb_home+'nbackup', '-b', '1', this_db, 'stdout' ], stdout=PIPE) +# p_getter = subprocess.Popen( [ os.path.join(context['temp_directory'],'7za.exe'), 'u', '-bb3', '-bt', '-bse2', '-si' + os.path.split(nbk1_name)[1], zip1_name ], stdin = p_sender.stdout, stdout = PIPE ) +# p_sender.stdout.close() +# p_getter_stdout, p_getter_stderr = p_getter.communicate() +# +# # result: file with name = %FBT_REPO% mp\\BUGS.CORE_4462.nbk1.7z must be created at this point +# +# +# f_nbk1_to_7z_log = open( os.path.join(context['temp_directory'],'tmp_4462_nbk1_to_7z.log'), 'w', buffering = 0) +# f_nbk1_to_7z_log.write( p_getter_stdout if p_getter_stdout else '' ) +# f_nbk1_to_7z_log.write( p_getter_stderr if p_getter_stderr else '' ) +# f_nbk1_to_7z_log.close() +# +# ################################################################################################################ +# +# # Now we can restore database from compressed .7z files by invocation of nbackup with '-de[compress]' command key: +# # nbackup -decompress "7za x -so" -r C:\\FBSS\\examples\\emp-restored\\employee-from-7z.fdb C:\\compressed_backup\\employee.nbk0.7z C:\\compressed_backup\\employee.nbk1.7z +# +# f_restore_log=open( os.path.join(context['temp_directory'],'tmp_4462_nbackup_restore_from_7z.log'), 'w', buffering = 0) +# subprocess.call( [ fb_home + 'nbackup', '-decompress', ' '.join( (p7z_exe,'x', '-y', '-so') ), '-r', fdb_for_restore, zip0_name, zip1_name ], stdout = f_restore_log, stderr = subprocess.STDOUT) +# f_restore_log.close() +# +# +# # Get firebird.log content BEFORE running validation: +# ################################# +# f_fblog_before=open( os.path.join(context['temp_directory'],'tmp_4462_fblog_before.txt'), 'w', buffering = 0) +# svc_get_fb_log( fb_home, f_fblog_before ) +# f_fblog_before.close() +# +# +# # Run VALIDATION of just restored database: +# ################ +# f_validation_log=open( os.path.join(context['temp_directory'],'tmp_4462_gfix_validate.log'), 'w', buffering = 0) +# subprocess.call( [ fb_home + 'gfix', '-v', '-full', fdb_for_restore], stdout=f_validation_log, stderr=subprocess.STDOUT) +# f_validation_log.close() +# +# +# # Get firebird.log content AFTER running validation: +# ################################ +# f_fblog_after=open( os.path.join(context['temp_directory'],'tmp_4462_fblog_after.txt'), 'w', buffering = 0) +# svc_get_fb_log( fb_home, f_fblog_after ) +# f_fblog_after.close() +# +# oldfb=open(f_fblog_before.name, 'r') +# newfb=open(f_fblog_after.name, 'r') +# +# difftext = ''.join(difflib.unified_diff( +# oldfb.readlines(), +# newfb.readlines() +# )) +# oldfb.close() +# newfb.close() +# +# f_diff_fblog=open( os.path.join(context['temp_directory'],'tmp_4462_fblog_diff.txt'), 'w', buffering = 0) +# f_diff_fblog.write(difftext) +# f_diff_fblog.close() +# +# pattern = re.compile('.*VALIDATION.*|.*ERROR:.*') +# +# # NB: difflib.unified_diff() can show line(s) that present in both files, without marking that line(s) with "+". +# # Usually these are 1-2 lines that placed just BEFORE difference starts. +# # So we have to check output before display diff content: lines that are really differ must start with "+". +# +# # Check: difference between old and new firebird.log should contain +# # only lines about validation start and finish, without errors: +# ############################################################### +# +# with open( f_diff_fblog.name,'r') as f: +# for line in f: +# if line.startswith('+'): +# if pattern.match(line.upper()): +# print( ' '.join(line.split()).upper() ) +# +# # Final checks: +# ############### +# # tmp_4462_gfix_validate.log tmp_4462_nbackup_restore_from_7z.log +# # Log for "nbackup -decompress -r ..." must be EMPTY: +# with open( f_restore_log.name,'r') as f: +# for line in f: +# if line: +# print('UNEXPECTED ERROR IN ' + f_restore_log.name + ': ' + line ) +# +# # Log of "gfix -v -full" must be EMPTY (this means that no errors and no warning were found): +# with open( f_validation_log.name,'r') as f: +# for line in f: +# if line: +# print('UNEXPECTED ERROR IN ' + f_validation_log.name + ': ' + line ) +# +# +# f_list = [ +# fdb_for_restore +# ,nbk0_name +# ,nbk1_name +# ,zip0_name +# ,zip1_name +# ,p7z_exe +# ,zstd_exe +# ,os.path.join(context['temp_directory'],'sample-DB_-_firebird.sql') +# ,os.path.join(context['temp_directory'],'sample-DB_-_oracle.sql') +# ] +# +# f_list += [ i.name for i in (f_sql_log, f_nbk0_to_7z_log,f_nbk1_to_7z_log,f_restore_log,f_fblog_before,f_fblog_after,f_validation_log,f_diff_fblog) ] +# +# cleanup( f_list ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + + VALIDATION STARTED + + VALIDATION FINISHED: 0 ERRORS, 0 WARNINGS, 0 FIXED + """ + +@pytest.mark.version('>=3.0.5') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_4462_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4464.py b/tests/bugs/test_core_4464.py new file mode 100644 index 00000000..dce32027 --- /dev/null +++ b/tests/bugs/test_core_4464.py @@ -0,0 +1,168 @@ +#coding:utf-8 +# +# id: bugs.core_4464 +# title: Duplicate tags for CREATE/ALTER USER not handled correctly +# decription: +# Refactored 16-may-2018 for usage plugin Srp. +# Checked on: +# 30Cs, build 3.0.4.32972: OK, 1.734s. +# 30SS, build 3.0.4.32972: OK, 1.156s. +# 40CS, build 4.0.0.955: OK, 2.516s. +# 40SS, build 4.0.0.977: OK, 1.656s. +# +# tracker_id: CORE-4464 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=\\+', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + execute block as + begin + begin + execute statement 'drop user tmp$c4464_1 using plugin Srp' with autonomous transaction; + when any do begin end + end + + begin + execute statement 'drop user tmp$c4464_2 using plugin Srp' with autonomous transaction; + when any do begin end + end + + begin + execute statement 'drop user tmp$c4464_3 using plugin Srp' with autonomous transaction; + when any do begin end + end + end^ + set term ;^ + commit; + + --set echo on; + --show users; + + -- Should fail with: + -- Statement failed, SQLSTATE = 42702 + -- Duplicated user attribute INITNAME + -- - because of duplicate specification of added attr. 'initname': + create user tmp$c4464_1 password '123' + using plugin Srp + tags (initname='Ozzy', surname='Osbourne', groupname='Black Sabbath', initname='John') + ; + rollback; -- !! -- + + -- Should work OK: + create user tmp$c4464_1 password '123' + using plugin Srp + tags (initname='John', surname='Osbourne', groupname='Black Sabbath', aka='Ozzy'); + ; + + -- Should work OK: + create user tmp$c4464_2 password '456' + using plugin Srp + tags (initname='Ian', surname='Gillan', groupname='Deep Purple') + ; + + create user tmp$c4464_3 password '789' + using plugin Srp + ; + commit; + + + -- Should fail with: + -- Statement failed, SQLSTATE = 42702 + -- Duplicated user attribute INITNAME + -- - because of duplicate specification of deleted attr. 'initname': + alter user tmp$c4464_2 + using plugin Srp + tags (drop initname, drop surname, drop groupname, drop initname); + commit; + + -- Should fail with: + -- Statement failed, SQLSTATE = 42702 + -- Duplicated user attribute INITNAME + -- - because of duplicate tag to be added: initname + alter user tmp$c4464_3 + using plugin Srp + tags (initname='Ozzy', surname='Osbourne', groupname='Black Sabbath', initname='Foo'); + commit; + + + -- Should fail with: + -- Statement failed, SQLSTATE = 42702 + -- Duplicated user attribute INITNAME + -- - because of duplicate specification of removed and than added attr. 'initname': + alter user tmp$c4464_3 + using plugin Srp + tags (drop initname, surname='Gillan', groupname='Deep Purple', initname='Ian'); + commit; + + set width usrname 12; + set width tag_key 20; + set width tag_val 25; + set width sec_plg 7; + select + u.sec$user_name as usrname + ,a.sec$key tag_key + ,a.sec$value as tag_val + ,sec$plugin sec_plg + from sec$users u + left join sec$user_attributes a using( sec$user_name, sec$plugin ) + where u.sec$user_name in ( upper('tmp$c4464_1'), upper('tmp$c4464_2'), upper('tmp$c4464_3') ) + order by 1,2,3; + commit; + + drop user tmp$c4464_1 using plugin Srp; + drop user tmp$c4464_2 using plugin Srp; + drop user tmp$c4464_3 using plugin Srp; + commit; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + USRNAME TAG_KEY TAG_VAL SEC_PLG + ============ ==================== ========================= ======= + TMP$C4464_1 AKA Ozzy Srp + TMP$C4464_1 GROUPNAME Black Sabbath Srp + TMP$C4464_1 INITNAME John Srp + TMP$C4464_1 SURNAME Osbourne Srp + TMP$C4464_2 GROUPNAME Deep Purple Srp + TMP$C4464_2 INITNAME Ian Srp + TMP$C4464_2 SURNAME Gillan Srp + TMP$C4464_3 Srp + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42702 + Duplicated user attribute INITNAME + + Statement failed, SQLSTATE = 42702 + Duplicated user attribute INITNAME + + Statement failed, SQLSTATE = 42702 + Duplicated user attribute INITNAME + + Statement failed, SQLSTATE = 42702 + Duplicated user attribute INITNAME + """ + +@pytest.mark.version('>=3.0') +def test_core_4464_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4466.py b/tests/bugs/test_core_4466.py new file mode 100644 index 00000000..b31118e6 --- /dev/null +++ b/tests/bugs/test_core_4466.py @@ -0,0 +1,134 @@ +#coding:utf-8 +# +# id: bugs.core_4466 +# title: Add DROP NOT NULL to ALTER COLUMN +# decription: This test does NOT verifies work when table has some data. It only checks ability to issue DDL statement +# tracker_id: CORE-4466 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set autoddl off; + commit; + + create or alter view v_test_fields as + select rf.rdb$field_name fld_name, coalesce(rf.rdb$null_flag, 0) is_NOT_null + from rdb$relation_fields rf + where rf.rdb$relation_name = upper('TEST') + order by rf.rdb$field_position; + commit; + + set width fld_name 10; + + recreate table test( + si smallint not null + ,ni int not null + ,bi bigint not null + ,nf numeric(18,0) not null + ,dp double precision not null + ,dt date not null + ,tm time not null + ,ts timestamp not null + ,ss varchar(100) not null + ,bs blob not null + ); + commit; + + select 'init metadata' msg, v.* from v_test_fields v; + + alter table test + alter si drop not null + ,alter ni drop not null + ,alter bi drop not null + ,alter nf drop not null + ,alter dp drop not null + ,alter dt drop not null + ,alter tm drop not null + ,alter ts drop not null + ,alter ss drop not null + ,alter bs drop not null + ; + + select 'drop not null' msg,v.* from v_test_fields v; + + alter table test + alter si set not null + ,alter ni set not null + ,alter bi set not null + ,alter nf set not null + ,alter dp set not null + ,alter dt set not null + ,alter tm set not null + ,alter ts set not null + ,alter ss set not null + ,alter bs set not null + ; + + select 'reset not null' msg, v.* from v_test_fields v; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG FLD_NAME IS_NOT_NULL + ============= ========== ============ + init metadata SI 1 + init metadata NI 1 + init metadata BI 1 + init metadata NF 1 + init metadata DP 1 + init metadata DT 1 + init metadata TM 1 + init metadata TS 1 + init metadata SS 1 + init metadata BS 1 + + + MSG FLD_NAME IS_NOT_NULL + ============= ========== ============ + drop not null SI 0 + drop not null NI 0 + drop not null BI 0 + drop not null NF 0 + drop not null DP 0 + drop not null DT 0 + drop not null TM 0 + drop not null TS 0 + drop not null SS 0 + drop not null BS 0 + + + MSG FLD_NAME IS_NOT_NULL + ============== ========== ============ + reset not null SI 1 + reset not null NI 1 + reset not null BI 1 + reset not null NF 1 + reset not null DP 1 + reset not null DT 1 + reset not null TM 1 + reset not null TS 1 + reset not null SS 1 + reset not null BS 1 + + """ + +@pytest.mark.version('>=3.0') +def test_core_4466_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4468.py b/tests/bugs/test_core_4468.py new file mode 100644 index 00000000..21a38bc9 --- /dev/null +++ b/tests/bugs/test_core_4468.py @@ -0,0 +1,288 @@ +#coding:utf-8 +# +# id: bugs.core_4468 +# title: FB3: CREATE USER GRANT ADMIN ROLE does not work +# decription: +# tracker_id: CORE-4468 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('.*delete record.*', 'delete record'), ('TABLE PLG\\$VIEW_USERS', 'TABLE PLG'), ('TABLE PLG\\$SRP_VIEW', 'TABLE PLG'), ('-OZZY_OSBOURNE is not grantor of (role|Role|ROLE) on RDB\\$ADMIN to OZZY_OSBOURNE.', '-OZZY_OSBOURNE is not grantor of ROLE on RDB$ADMIN to OZZY_OSBOURNE.'), ('-Effective user is.*', '')] + +init_script_1 = """ + -- ::: NB ::: Name of table in STDERR depends on value of UserManager = { Srp | Legacy_UserManager }. + -- For 'Srp' it will be 'PLG$SRP_VIEW', for Legacy_UserManager -- PLG$VIEW_USERS. + -- Because of this, section 'substitution' has been added in order to ignore rest part of line + -- after words 'TABLE PLG'. + -- Also, text in message about deletion fault differs in case of UserManager setting: + -- 'find/delete record error' - for Legacy_UserManager + -- '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 + from rdb$database + left join sec$users u on u.sec$user_name in ( upper('ozzy_osbourne'), upper('bon_scott') ); + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set wng off; + set list on; + set count on; + + select 'start' msg, v.* from v_users v; + commit; + + create or alter user ozzy_osbourne password '123' + grant admin role -- this is mandatory because it gives him admin role in Security DB + ; + revoke all on all from ozzy_osbourne; + grant rdb$admin to ozzy_osbourne; -- this is also mandatory: it gives him admin role in ($dsn) database + commit; + + select 'step-1' msg, v.* from v_users v; + commit; + + -- When 'ozzy_osbourne' connects to database ($dsn), there is no way for engine to recognize that this user + -- has been granted with admin role in 'CREATE USER ... GRANT ADMIN ROLE' statement. So, user has to specify + -- `role 'RDB$ADMIN'` in order to connect as ADMIN. + -- But with RDB$ADMIN only he can create objects in THAT database (tables etc), but not other USERS! + -- Thats why he should also be granted with admin role in 'CREATE USER ...' - see above. + connect '$(DSN)' user 'OZZY_OSBOURNE' password '123' role 'RDB$ADMIN'; + commit; + + -- Users are stored in Security DB, *not* in "this" database! + -- So, following statement will pass only if 'ozzy_osbourne' has been granted by 'admin role' + -- in his own 'create user' phase: + create or alter user bon_scott password '456' revoke admin role; + commit; + + select 'step-2' msg, v.* from v_users v; + + alter user bon_scott grant admin role; + commit; + show grants; + + select 'step-3' msg, v.* from v_users v; + + grant rdb$admin to bon_scott; + commit; + + show grants; + + alter user bon_scott revoke admin role; + commit; + + select 'step-4' msg, v.* from v_users v; + commit; + + revoke rdb$admin from bon_scott; + commit; + + show grants; + + drop user bon_scott; + commit; + + select 'step-5' msg, v.* from v_users v; + commit; + + -- User removes admin role from himself: + + -- 1. This will FAIL: + -- -REVOKE failed + -- -OZZY_OSBOURNE is not grantor of Role on RDB$ADMIN to OZZY_OSBOURNE. + revoke rdb$admin from ozzy_osbourne; + commit; + + -- 2 This will PASS, and it MUST be so (see letter from Alex, 03-jun-2015 19:46) + alter user ozzy_osbourne revoke admin role; + commit; + + show grants; + + select 'step-6' 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: + -- Statement failed, SQLSTATE = 28000 + -- find/delete record error + -- -no permission for DELETE access to TABLE PLG$VIEW_USERS + drop user ozzy_osbourne; + commit; + + select 'step-7' msg, v.* from v_users v; + commit; + + -- Trying reconnect with role RDB$ADMIN: + connect '$(DSN)' user 'OZZY_OSBOURNE' password '123' role 'RDB$ADMIN'; + commit; + + select 'step-8' msg, v.* from v_users v; + commit; + + show grants; + commit; + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + drop user ozzy_osbourne; + commit; + + select 'final' msg, v.* from v_users v; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG start + WHO_AM_I SYSDBA + WHATS_MY_ROLE NONE + NON_SYSDBA_USER_NAME + NON_SYSDBA_HAS_ADMIN_ROLE + + + Records affected: 1 + + MSG step-1 + WHO_AM_I SYSDBA + WHATS_MY_ROLE NONE + NON_SYSDBA_USER_NAME OZZY_OSBOURNE + NON_SYSDBA_HAS_ADMIN_ROLE + + Records affected: 1 + + + MSG step-2 + WHO_AM_I OZZY_OSBOURNE + WHATS_MY_ROLE RDB$ADMIN + NON_SYSDBA_USER_NAME OZZY_OSBOURNE + NON_SYSDBA_HAS_ADMIN_ROLE + + MSG step-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 RDB$ADMIN TO OZZY_OSBOURNE + + MSG step-3 + WHO_AM_I OZZY_OSBOURNE + WHATS_MY_ROLE RDB$ADMIN + NON_SYSDBA_USER_NAME OZZY_OSBOURNE + NON_SYSDBA_HAS_ADMIN_ROLE + + MSG step-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 RDB$ADMIN TO BON_SCOTT GRANTED BY OZZY_OSBOURNE + GRANT RDB$ADMIN TO OZZY_OSBOURNE + + MSG step-4 + WHO_AM_I OZZY_OSBOURNE + WHATS_MY_ROLE RDB$ADMIN + NON_SYSDBA_USER_NAME OZZY_OSBOURNE + NON_SYSDBA_HAS_ADMIN_ROLE + + MSG step-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 RDB$ADMIN TO OZZY_OSBOURNE + + MSG step-5 + 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 RDB$ADMIN TO OZZY_OSBOURNE + + MSG step-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 + + MSG step-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 step-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 RDB$ADMIN TO OZZY_OSBOURNE + + MSG final + WHO_AM_I SYSDBA + WHATS_MY_ROLE NONE + NON_SYSDBA_USER_NAME + NON_SYSDBA_HAS_ADMIN_ROLE + + + Records affected: 1 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -REVOKE failed + -OZZY_OSBOURNE is not grantor of Role on RDB$ADMIN to OZZY_OSBOURNE. + + Statement failed, SQLSTATE = 28000 + delete record error + -no permission for DELETE access to TABLE PLG$VIEW_USERS + """ + +@pytest.mark.version('>=3.0') +def test_core_4468_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4469.py b/tests/bugs/test_core_4469.py new file mode 100644 index 00000000..f493314c --- /dev/null +++ b/tests/bugs/test_core_4469.py @@ -0,0 +1,66 @@ +#coding:utf-8 +# +# id: bugs.core_4469 +# title: Add field in SEC$USERS reflecting whether a user has RDB$ADMIN role in security database +# decription: +# tracker_id: CORE-4469 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('Statement failed, SQLSTATE = HY000', ''), ('record not found for user:.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + drop user boss1; + drop user boss2; + commit; + + create user boss1 password '123' grant admin role; + commit; + select SEC$ADMIN is_admin_boss1 from sec$users where sec$user_name = upper('boss1'); + + + create user boss2 password '456'; + commit; + select SEC$ADMIN is_admin_boss2a from sec$users where sec$user_name = upper('boss2'); + + alter user boss2 grant admin role; + commit; + select SEC$ADMIN is_admin_boss2b from sec$users where sec$user_name = upper('boss2'); + + alter user boss2 revoke admin role; + commit; + select SEC$ADMIN is_admin_boss2c from sec$users where sec$user_name = upper('boss2'); + + drop user boss1; + drop user boss2; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + IS_ADMIN_BOSS1 + IS_ADMIN_BOSS2A + IS_ADMIN_BOSS2B + IS_ADMIN_BOSS2C + """ + +@pytest.mark.version('>=3.0') +def test_core_4469_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4470.py b/tests/bugs/test_core_4470.py new file mode 100644 index 00000000..1785bfe9 --- /dev/null +++ b/tests/bugs/test_core_4470.py @@ -0,0 +1,299 @@ +#coding:utf-8 +# +# id: bugs.core_4470 +# title: gbak fails to restore database containing dependency between views and packaged functions +# decription: +# Confirmed on WI-T3.0.0.30809 Firebird 3.0 Alpha 2: +# gbak: ERROR:action cancelled by trigger (0) to preserve data integrity +# gbak: ERROR: could not find object for GRANT +# gbak:Exiting before completion due to errors +# ============================================ +# 28.10.2019: +# 1. Replaced PSQL function name 'localtime()' with 'fn_local_time()': first of them became keyword in FB 4.0 +# 2.Checked on: +# 4.0.0.1635 SS: 3.384s. +# 4.0.0.1633 CS: 3.438s. +# 3.0.5.33180 SS: 2.137s. +# 3.0.5.33178 CS: 2.490s. +# +# tracker_id: CORE-4470 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + set bail on; + set autoddl on; + + create domain dbigint as bigint; + create domain dblob as blob sub_type 0 segment size 80; + create domain did as bigint not null; + create domain dinteger as integer; + create domain dn31 as numeric(3, 1); + create domain dn41 as numeric(4, 1); + create domain dn51 as numeric(5, 1); + create domain dreal as double precision; + create domain dsmallint as smallint; + create domain dtime as timestamp; + create domain dvc255 as varchar(255); + create domain dvc512 as varchar(512); + commit; + set autoddl off; + + set term ^; + + create package wf as + begin + function cest (t dtime) returns dtime; + function cet (t dtime) returns dtime; + function fn_local_time (t dtime) returns dtime; + function dewpoint (temp dreal, hum dsmallint) returns dreal; + function yesterday returns dtime; + function altitude returns dreal; + function current_xml returns dvc512; + function relpressure(airpressureabsolute dreal,temperature dreal,altitude dreal, humidity dreal) returns dreal; + end^ + + set term ;^ + commit work; + + set autoddl on; + + create table constants (id did generated by default as identity not null, + typ dvc255, + val dvc255, + keys dbigint, + primary key (id)); + + create table raw (id did generated by default as identity not null, + readtime dtime not null, + delay dsmallint, + hum_in dsmallint, + temp_in dreal, + hum_out dsmallint, + temp_out dreal, + abs_pressure dreal, + wind_ave dreal, + wind_gust dreal, + wind_dir dsmallint, + rain dreal, + status dsmallint, + illuminance dreal, + uv dsmallint, + primary key (id), + constraint unq1_raw unique (readtime)); + + create table timezone (jahr dsmallint not null, + gmt_from dtime, + gmt_thru dtime, + constraint pk_timezone primary key (jahr)); + + create index raw_idx1 on raw (hum_in); + create descending index raw_idx10 on raw (abs_pressure); + create descending index raw_idx11 on raw (readtime); + create descending index raw_idx12 on raw (rain); + create index raw_idx2 on raw (temp_in); + create index raw_idx3 on raw (hum_out); + create index raw_idx4 on raw (temp_out); + create index raw_idx5 on raw (abs_pressure); + create index raw_idx6 on raw (wind_ave); + create index raw_idx7 on raw (wind_gust); + create index raw_idx8 on raw (wind_dir); + create index raw_idx9 on raw (rain); + + create view meteo (timestamp_utc, timestamp_local, tempint, humint, temp, hum, wind, wind_dir, wind_gust, wind_gust_dir, dew_point, rain, rain_rate, pressure, uv_index, solar_rad) as + select readtime, wf.fn_local_time(readtime), temp_in, hum_in, temp_out, hum_out, wind_ave / 3.6 , 22.5 * wind_dir, wind_gust / 3.6 , + 22.5 * wind_dir, wf.dewpoint(temp_out, hum_out), cast(rain - lead(rain) over(order by readtime desc) as numeric (6,3)) , 0, + 2.8+wf.relpressure(abs_pressure, temp_out, wf.altitude(), hum_out), 0, 0 + from raw; + commit; + + set autoddl off; + set term ^; + + create package body wf as + begin + + function CEST (T dtime)returns dtime + AS + begin + return dateadd (2 hour to t); + end + + function CET (T dtime)returns dtime + AS + begin + return dateadd (1 hour to t); + end + + function altitude returns dreal + as + begin + return (select c.val from constants c where c.typ='Altitude'); + end + + function fn_local_time (t dtime)returns dtime + as + declare variable jahr dsmallint; + declare variable gmt_from dtime; + declare variable gmt_thru dtime; + begin + select tz.gmt_from, tz.gmt_thru + from timezone tz where tz.jahr=extract(year from :t) + into :gmt_from, :gmt_thru; + if (t between :gmt_from and :gmt_thru) then + begin + return dateadd (2 hour to t); + end + else + return dateadd (1 hour to t); + end + + function relpressure (airpressureabsolute dreal, temperature dreal, altitude dreal, humidity dreal) returns dreal + as + declare variable g_n dreal; + declare variable gam dreal; + declare variable r dreal; + declare variable m dreal; + declare variable r_0 dreal; + declare variable t_0 dreal; + declare variable c dreal; + declare variable e_0 dreal; + declare variable f_rel dreal; + declare variable e_d dreal; + + begin + g_n = 9.80665;-- erdbeschleunigung (m/s^2) + gam = 0.0065;--temperaturabnahme in k pro geopotentiellen metern (k/gpm) + r = 287.06;--gaskonstante fur trockene luft (r = r_0 / m) + m = 0.0289644;--molare masse trockener luft (j/kgk) + r_0 = 8.314472;--allgemeine gaskonstante (j/molk) + t_0 = 273.15;--umrechnung von c in k + c = 0.11;--dwd-beiwert fur die berucksichtigung der luftfeuchte + e_0 = 6.11213;-- (hpa) + f_rel = humidity / 100;--relative luftfeuchte (0-1.0) + e_d = f_rel * e_0 * exp((17.5043 * temperature) / (241.2 + temperature));--momentaner stationsdampfdruck (hpa) + return airpressureabsolute * exp((g_n * altitude) / (r * (temperature + t_0 + c * e_d + ((gam * altitude) / 2)))); + end + + function yesterday returns dtime + as + begin + return dateadd (-1 day to current_date); + end + + function dewpoint (temp dreal, hum dsmallint) + returns dreal + as + declare variable gamma dreal; + declare variable a dreal; + declare variable b dreal; + begin + if ((coalesce(temp,0)=0) or (coalesce(hum,0)=0)) then + return 0; + else + begin + return temp - ((100 - hum) / 5.0); + end + end + + function current_xml returns dvc512 + as + declare variable timestamp_utc type of column meteo.timestamp_utc; + declare variable timestamp_local type of column meteo.timestamp_local; + declare variable tempint type of column meteo.tempint; + declare variable humint type of column meteo.humint; + declare variable temp type of column meteo.temp; + declare variable hum type of column meteo.hum; + declare variable wind type of column meteo.wind; + declare variable wind_dir type of column meteo.wind_dir; + declare variable wind_gust type of column meteo.wind_gust; + declare variable wind_gust_dir type of column meteo.wind_gust_dir; + declare variable dew_point type of column meteo.dew_point; + declare variable rain type of column meteo.rain; + declare variable rain_rate type of column meteo.rain_rate; + declare variable pressure type of column meteo.pressure; + declare variable uv_index type of column meteo.uv_index; + declare variable solar_rad type of column meteo.solar_rad; + + begin + + select first 1 timestamp_utc,timestamp_local, tempint, humint, temp, hum, wind, wind_dir, wind_gust, wind_gust_dir, dew_point, + rain, rain_rate, pressure, uv_index, solar_rad + from meteo order by timestamp_utc desc + into :timestamp_utc, :timestamp_local, :tempint, :humint, :temp, :hum, :wind, :wind_dir, :wind_gust, :wind_gust_dir, + :dew_point, :rain, :rain_rate, :pressure, :uv_index, :solar_rad; + + + return ''|| + tempint|| + ''|| + humint|| + ''|| + temp|| + ''|| + hum|| + ''|| + rain_rate|| + ''|| + wind|| + ''|| + wind_dir|| + ''|| + wind_gust|| + ''|| + pressure|| + ''; + end + + end^ + + set term ;^ + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# +# fbk = os.path.join(context['temp_directory'],'core_4470-backup.fbk') +# fbn = os.path.join(context['temp_directory'],'core_4470-restored.fdb') +# print('Creating backup...') +# runProgram('gbak',['-b','-user',user_name,'-password',user_password,dsn,fbk]) +# print('Creating restore...') +# runProgram('gbak',['-rep','-user',user_name,'-password',user_password,fbk,fbn]) +# script = '''show view; show package;''' +# runProgram('isql',[fbn,'-q','-user',user_name,'-password',user_password],script) +# if os.path.isfile(fbk): +# os.remove(fbk) +# if os.path.isfile(fbn): +# os.remove(fbn) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Creating backup... + Creating restore... + METEO + WF + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4470_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4472.py b/tests/bugs/test_core_4472.py new file mode 100644 index 00000000..3aa004c3 --- /dev/null +++ b/tests/bugs/test_core_4472.py @@ -0,0 +1,165 @@ +#coding:utf-8 +# +# id: bugs.core_4472 +# title: Message "Modifying function which is currently in use" when running script with AUTODDL=OFF and is called from INTERNAL function declared in other unit +# decription: +# Test call delivering of firebird.log TWICE: before and after running ISQL. +# Then we compare only size of obtained logs rather than content (differencs of size should be zero). +# Result on WI-V3.0.0.32239, WI-V3.0.0.32239: Ok. +# +# Result on WI-T3.0.0.30809 (Alpha2): +# Unexpected call to register plugin Remote, type 2 - ignored +# Unexpected call to register plugin Loopback, type 2 - ignored +# Unexpected call to register plugin Legacy_Auth, type 12 - ignored +# Unexpected call to register plugin Srp, type 12 - ignored +# Unexpected call to register plugin Win_Sspi, type 12 - ignored +# Unexpected call to register plugin Arc4, type 16 - ignored +# INET/inet_error: read errno = 10054 +# Modifying function FN_01 which is currently in use by active user requests +# +# 13.04.2021. Adapted for run both on Windows and Linux. Checked on: +# Windows: 3.0.8.33445, 4.0.0.2416 +# Linux: 3.0.8.33426, 4.0.0.2416 +# +# tracker_id: CORE-4472 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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 ) +# +# #-------------------------------------------- +# +# +# fb_log_before=open( os.path.join(context['temp_directory'],'tmp_fb_log_4472_before.log'), 'w') +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr","action_get_fb_log"], +# stdout=fb_log_before, stderr=subprocess.STDOUT) +# flush_and_close( fb_log_before ) +# +# sqltxt=''' +# set autoddl off; +# commit; +# set term ^; +# create or alter function fn_01() returns int +# as begin +# return 1; +# end +# ^ +# +# create or alter procedure sp_01 +# as +# declare function fn_internal_01 returns int as +# begin +# if ( fn_01() > 0 ) then return 1; +# else return 0; +# end +# begin +# end +# ^ +# set term ;^ +# commit; +# ''' +# +# f_sqllog=open( os.path.join(context['temp_directory'],'tmp_isql_4472.log'), 'w') +# f_sqllog.close() +# runProgram('isql',[ dsn, '-q','-m','-o',f_sqllog.name],sqltxt) +# +# fb_log_after=open( os.path.join(context['temp_directory'],'tmp_fb_log_4472_after.log'), 'w') +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", "action_get_fb_log"], +# stdout=fb_log_after, stderr=subprocess.STDOUT) +# flush_and_close( fb_log_after ) +# +# # This log should be EMPTY: +# with open( f_sqllog.name,'r') as f: +# for line in f: +# if line.split() and not 'Database:' in line: +# # This line must be ignored: +# # Database: localhost/3333:C:\\FBTESTING\\qa +# bt-repo mpugs.core_4472.fdb, User: SYSDBA +# print('UNEXPECTED: ' + line) +# +# +# # This difference should be ZERO: +# fb_log_diff=os.path.getsize(fb_log_after.name)-os.path.getsize(fb_log_before.name) +# +# if fb_log_diff == 0: +# print("OK: log was not changed.") +# else: +# print("BAD: log was increased by "+str(fb_log_diff)+" bytes.") +# +# ##################################################################### +# # Cleanup: +# +# # do NOT remove this pause otherwise some of logs will not be enable for deletion and test will finish with +# # Exception raised while executing Python test script. exception: WindowsError: 32 +# time.sleep(1) +# +# cleanup( (fb_log_before, fb_log_after, f_sqllog ) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + OK: log was not changed. + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4472_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4473.py b/tests/bugs/test_core_4473.py new file mode 100644 index 00000000..0da0aa35 --- /dev/null +++ b/tests/bugs/test_core_4473.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_4473 +# title: Restore of pre ODS 11.1 database can leave RDB$RELATION_TYPE null +# decription: +# 25SC, build 2.5.8.27065: OK, 0.860s. +# 30SS, build 3.0.3.32738: OK, 1.344s. +# 40SS, build 4.0.0.680: OK, 1.344s. +# +# tracker_id: CORE-4473 +# min_versions: ['2.5.8'] +# versions: 2.5.8 +# qmid: bugs.core_4473 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.8 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core_4473-ods10_1.fbk', init=init_script_1) + +test_script_1 = """ + -- Source DB was created under FB 1.5.6 (ODS 10.1) and contains following objects: + -- create table test_t(x int); + -- create view test_v(x) as select x from test_t; + -- Value of rdb$relations.rdb$relation_type for these objects must be zero rather than null. + + set list on; + select rdb$relation_type + from rdb$relations + where + rdb$relation_name starting with upper('test') + and rdb$system_flag is distinct from 1 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$RELATION_TYPE 0 + RDB$RELATION_TYPE 0 + """ + +@pytest.mark.version('>=2.5.8') +def test_core_4473_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4477.py b/tests/bugs/test_core_4477.py new file mode 100644 index 00000000..d4841f10 --- /dev/null +++ b/tests/bugs/test_core_4477.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: bugs.core_4477 +# title: Field RDB$MAP_TO_TYPE is not present in RDB$TYPES +# decription: +# tracker_id: CORE-4477 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select rdb$field_name,rdb$type,rdb$type_name,rdb$system_flag from rdb$types where upper(rdb$field_name) = upper('rdb$map_to_type') order by rdb$type; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$FIELD_NAME RDB$MAP_TO_TYPE + RDB$TYPE 0 + RDB$TYPE_NAME USER + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$MAP_TO_TYPE + RDB$TYPE 1 + RDB$TYPE_NAME ROLE + RDB$SYSTEM_FLAG 1 + """ + +@pytest.mark.version('>=3.0') +def test_core_4477_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4480.py b/tests/bugs/test_core_4480.py new file mode 100644 index 00000000..a38dd555 --- /dev/null +++ b/tests/bugs/test_core_4480.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_4480 +# title: ISQL issues warning: "Bad debug info format" when connect to database with stored function after it`s restoring +# decription: +# tracker_id: CORE-4480 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + -- Note: core4480.fbk was created by WI-T3.0.0.30809 Firebird 3.0 Alpha 2. + -- Retoring of this file in WI-T3.0.0.30809 finishes with: + -- gbak: WARNING:function FN_A is not defined + -- gbak: WARNING: module name or entrypoint could not be found + -- gbak: WARNING:function FN_A is not defined + -- gbak: WARNING: module name or entrypoint could not be found + -- 2) Attempt `execute procedure sp_a;` - leads to: + -- Statement failed, SQLSTATE = 39000 + -- invalid request BLR at offset 29 + -- -function FN_A is not defined + -- -module name or entrypoint could not be found + -- -Error while parsing procedure SP_A's BLR + """ + +db_1 = db_factory(from_backup='core4480.fbk', init=init_script_1) + +test_script_1 = """ + execute procedure sp_a; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +def test_core_4480_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_4483.py b/tests/bugs/test_core_4483.py new file mode 100644 index 00000000..c97dce8f --- /dev/null +++ b/tests/bugs/test_core_4483.py @@ -0,0 +1,288 @@ +#coding:utf-8 +# +# id: bugs.core_4483 +# title: Changed data not visible in WHEN-section if exception occured inside SP that has been called from this code +# decription: +# tracker_id: CORE-4483 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- ISSUE-1: if procedure_A calls procedure_B and the latter makes some DML changes but then fails + -- then proc_A does NOT see any changes that were made by proc_B. + -- See letter to dimitr, 02-feb-2015 23:47, attachment: 'core-4483_test1.sql'. + + set term ^; + create or alter procedure P1 as begin end^ + create or alter procedure P2 as begin end^ + create or alter procedure P3 as begin end^ + create or alter procedure P4 as begin end^ + create or alter procedure P5 as begin end^ + create or alter procedure P6 as begin end^ + commit^ + + recreate table t(id int primary key)^ + commit^ + + -- P1...P4 -- procedures WITHOUT when blocks and correct code: + create or alter procedure P1 as begin insert into t values(1); end^ + create or alter procedure P2 as begin insert into t values(2); end^ + create or alter procedure P3 as begin insert into t values(3); end^ + create or alter procedure P4 as begin insert into t values(4); end^ + + + -- P5 -- single proc WITH when block (but with correct code); + create or alter procedure P5 as + begin + insert into t values(5); + rdb$set_context('USER_SESSION','PROC_P5_BEFORE_P6_CALL', (select list(id) from t)); --- [ 2 ] + execute procedure P6; + when any do + begin + rdb$set_context('USER_SESSION','PROC_P5_WHEN_BLK_AFTER_P6_CALL', (select list(id) from t)); --- [ 4 ] + exception; + end + end^ + + -- P6 -- deepest procedure with INCORRECT code (where exception occurs): + create or alter procedure P6 as + declare i int; + begin + insert into t values(6); + -- ### ERRONEOUS CODE ### + i = rdb$set_context('USER_SESSION','PROC_P6_ERROR_LINE', (select list(id) from t)) / 0; --- [ 3a ] + when any do + begin + rdb$set_context('USER_SESSION','PROC_P6_WHEN_BLK_CATCHING_ERR', (select list(id) from t)); --- [ 3b ] + exception; + end + end^ + commit^ + set term ;^ + commit; + + set transaction no wait; + set term ^; + execute block + as + declare i int; + begin + delete from t; + execute procedure P1; + execute procedure P2; + execute procedure P3; + execute procedure P4; + rdb$set_context('USER_SESSION','MAIN_EB_AFTER_CALL_P1_P4', (select list(id) from t)); --- [ 1 ] + + execute procedure P5; -- ==> update context vars 'PROC_P5_BEFORE_P6_CALL' and 'PROC_P5_WHEN_BLK_AFTER_P6_CALL' + + when any do + begin + rdb$set_context('USER_SESSION','MAIN_EB_WHEN_BLK_AFTER_P5_EXC', (select list(id) from t)); --- [ 4 ] + --exception; + end + end + ^ set term ^; + + SET LIST ON; + select + rdb$get_context('USER_SESSION','MAIN_EB_AFTER_CALL_P1_P4') "main EB after P1,P2,P3,P4" -- [ 1 ] + ,rdb$get_context('USER_SESSION','PROC_P5_BEFORE_P6_CALL') "proc P5 before call P6" -- [ 2 ] + ,rdb$get_context('USER_SESSION','PROC_P6_ERROR_LINE') "proc P6 error source line" -- [ 3a ] + ,rdb$get_context('USER_SESSION','PROC_P6_WHEN_BLK_CATCHING_ERR') "proc P6 WHEN blk: catch exceptn" -- [ 3b ] + ,rdb$get_context('USER_SESSION','PROC_P5_WHEN_BLK_AFTER_P6_CALL') "proc P5 WHEN blk: catch exceptn" -- [ 4 ] + ,rdb$get_context('USER_SESSION','MAIN_EB_WHEN_BLK_AFTER_P5_EXC') "main EB WHEN blk: catch exceptn" -- [ 5 ] + from rdb$database; + + select count(*) t_count from t; + commit; + + -- ############################################################################################# + + -- ISSUE-2: if some procedure performs several DML statements (s1, s2, s3, ..., sN) and N-th DML + -- fails and control falls into WHEN-block of this SP then we can not see any changes that we + -- have done inside THIS procedure. + -- See letter to dimitr, 02-feb-2015 23:47, attachment: 'core-4483_test2.sql'. + + set term ^; + create or alter procedure p1 as begin end^ + create or alter procedure p2 as begin end^ + create or alter procedure p3 as begin end^ + create or alter procedure p4 as begin end^ + create or alter procedure p5 as begin end^ + create or alter procedure p6 as begin end^ + commit^ + + recreate table t(id int)^ + + create or alter procedure p1 as + begin + insert into t values(1); + insert into t values(12); + insert into t values(133); + rdb$set_context('USER_SESSION','P1_CODE_BEFO_CALL_P2',(select list(id) from t)); + execute procedure p2; + when any do + begin + -- here we must be able to see ALL changes that current procedure has done, i.e. + -- records with ID = 1, 12 and 133 must be visible for us at this point. + rdb$set_context('USER_SESSION','P1_CATCH_BLK_SEES',(select list(id) from t)); + --exception; + end + end^ + + create or alter procedure p2 as + begin + insert into t values(2); + insert into t values(22); + insert into t values(233); + rdb$set_context('USER_SESSION','P2_CODE_BEFO_CALL_P3',(select list(id) from t)); + execute procedure p3; + when any do + begin + -- here we must be able to see ALL changes that current procedure has done, i.e. + -- records with ID = 2, 22 and 233 must be visible for us at this point. + rdb$set_context('USER_SESSION','P2_CATCH_BLK_SEES',(select list(id) from t)); + exception; + end + end^ + + create or alter procedure p3 as + begin + insert into t values(3); + insert into t values(32); + insert into t values(333); + rdb$set_context('USER_SESSION','P3_CODE_BEFO_CALL_P4',(select list(id) from t)); + execute procedure p4; + when any do + begin + -- here we must be able to see ALL changes that current procedure has done, i.e. + -- records with ID = 3, 32 and 333 must be visible for us at this point. + rdb$set_context('USER_SESSION','P3_CATCH_BLK_SEES',(select list(id) from t)); + exception; + end + end^ + + create or alter procedure p4 as + begin + insert into t values(4); + insert into t values(42); + insert into t values(433); + rdb$set_context('USER_SESSION','P4_CODE_BEFO_CALL_P5',(select list(id) from t)); + execute procedure p5; + when any do + begin + -- here we must be able to see ALL changes that current procedure has done, i.e. + -- records with ID = 4, 42 and 433 must be visible for us at this point. + rdb$set_context('USER_SESSION','P4_CATCH_BLK_SEES',(select list(id) from t)); + exception; + end + end^ + + create or alter procedure p5 as + begin + insert into t values(5); + insert into t values(52); + insert into t values(533); + rdb$set_context('USER_SESSION','P5_CODE_BEFO_CALL_P6',(select list(id) from t)); + execute procedure p6; + when any do + begin + -- here we must be able to see ALL changes that current procedure has done, i.e. + -- records with ID = 5, 52 and 533 must be visible for us at this point. + rdb$set_context('USER_SESSION','P5_CATCH_BLK_SEES',(select list(id) from t)); + exception; + end + end^ + + create or alter procedure p6 as + declare i int; + begin + insert into t values(6); + insert into t values(62); + insert into t values(633); + rdb$set_context('USER_SESSION','P6_CODE_BEFO_ZERO_DIV',(select list(id) from t)); + i = 1/0; + when any do + begin + -- here we must be able to see ALL changes that current procedure has done, i.e. + -- records with ID = 6, 62 and 633 must be visible for us at this point. + rdb$set_context('USER_SESSION','P6_CATCH_BLK_SEES',(select list(id) from t)); + exception; + end + end^ + + commit^ + set term ;^ + + execute procedure p1; + + set list on; + select + rdb$get_context('USER_SESSION', 'P6_CODE_BEFO_ZERO_DIV') as "IDs in p6 before zero div" + ,rdb$get_context('USER_SESSION', 'P6_CATCH_BLK_SEES') as "IDs in p6 catch blk" + + ,rdb$get_context('USER_SESSION', 'P5_CODE_BEFO_CALL_P6') as "IDs in p5 before p6 call" + ,rdb$get_context('USER_SESSION', 'P5_CATCH_BLK_SEES') as "IDs in p5 catch blk" + + ,rdb$get_context('USER_SESSION', 'P4_CODE_BEFO_CALL_P5') as "IDs in p4 before p5 call" + ,rdb$get_context('USER_SESSION', 'P4_CATCH_BLK_SEES') as "IDs in p4 catch blk" + + ,rdb$get_context('USER_SESSION', 'P3_CODE_BEFO_CALL_P4') as "IDs in p3 before p4 call" + ,rdb$get_context('USER_SESSION', 'P3_CATCH_BLK_SEES') as "IDs in p3 catch blk" + + ,rdb$get_context('USER_SESSION', 'P2_CODE_BEFO_CALL_P3') as "IDs in p2 before p3 call" + ,rdb$get_context('USER_SESSION', 'P2_CATCH_BLK_SEES') as "IDs in p2 catch blk" + + ,rdb$get_context('USER_SESSION', 'P1_CODE_BEFO_CALL_P2') as "IDs in p1 before p2 call" + ,rdb$get_context('USER_SESSION', 'P1_CATCH_BLK_SEES') as "IDs in p1 catch blk" + + from rdb$database; + set list off; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + main EB after P1,P2,P3,P4 1,2,3,4 + proc P5 before call P6 1,2,3,4,5 + proc P6 error source line 1,2,3,4,5,6 + proc P6 WHEN blk: catch exceptn 1,2,3,4,5,6 + proc P5 WHEN blk: catch exceptn 1,2,3,4,5 + main EB WHEN blk: catch exceptn 1,2,3,4 + T_COUNT 4 + + IDs in p6 before zero div 1,12,133,2,22,233,3,32,333,4,42,433,5,52,533,6,62,633 + IDs in p6 catch blk 1,12,133,2,22,233,3,32,333,4,42,433,5,52,533,6,62,633 + IDs in p5 before p6 call 1,12,133,2,22,233,3,32,333,4,42,433,5,52,533 + IDs in p5 catch blk 1,12,133,2,22,233,3,32,333,4,42,433,5,52,533 + IDs in p4 before p5 call 1,12,133,2,22,233,3,32,333,4,42,433 + IDs in p4 catch blk 1,12,133,2,22,233,3,32,333,4,42,433 + IDs in p3 before p4 call 1,12,133,2,22,233,3,32,333 + IDs in p3 catch blk 1,12,133,2,22,233,3,32,333 + IDs in p2 before p3 call 1,12,133,2,22,233 + IDs in p2 catch blk 1,12,133,2,22,233 + IDs in p1 before p2 call 1,12,133 + IDs in p1 catch blk 1,12,133 + """ + +@pytest.mark.version('>=4.0') +def test_core_4483_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4484.py b/tests/bugs/test_core_4484.py new file mode 100644 index 00000000..b0b37a4c --- /dev/null +++ b/tests/bugs/test_core_4484.py @@ -0,0 +1,146 @@ +#coding:utf-8 +# +# id: bugs.core_4484 +# title: Description (COMMENT ON) for package procedures and functions, and its parameters +# decription: Test verifies ability to store comments and also to encode them in UTF8 +# tracker_id: CORE-4484 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('TEXT_BLOB.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create or alter package pg_test + as + begin + procedure sp_test(i_x int) returns (o_z int); + function fn_test(i_x int) returns int; + end + ^ + + recreate package body pg_test + as + begin + procedure sp_test(i_x int) returns (o_z int) as + begin + o_z = i_x * 2; + end + function fn_test(i_x int) returns int as + begin + return i_x * 2; + end + end + ^ + set term ;^ + commit; + + comment on package pg_test is 'MITÄ TÄMÄN'; + comment on procedure pg_test.sp_test is 'ÁÉÍÓÚÝ'; + comment on function pg_test.fn_test is 'ÂÊÎÔÛ'; + comment on procedure parameter pg_test.sp_test.i_x is 'ÃÑÕ ÄËÏÖÜŸ'; + comment on procedure parameter pg_test.sp_test.o_z is 'ÇŠ ΔΘΛΞΣΨΩ'; + comment on function parameter pg_test.fn_test.i_x is 'ĄĘŁŹŻ ЙЁ ЊЋЏ ĂŞŢ'; + commit; + + set list on; + set blob all; + + select 'package itself' descr_for_what,rp.rdb$package_name obj_name, rp.rdb$description text_blob + from rdb$packages rp + where rp.rdb$package_name=upper('pg_test') + + union all + + select * + from ( + select 'package proc' descr_for_what, pp.rdb$procedure_name, pp.rdb$description + from rdb$procedures pp + where pp.rdb$package_name=upper('pg_test') + order by pp.rdb$procedure_name + ) + + union all + + select * + from ( + select 'package func' descr_for_what, pf.rdb$function_name, pf.rdb$description + from rdb$functions pf + where pf.rdb$package_name = upper('pg_test') + order by pf.rdb$function_name + ) + + union all + + select 'package proc pars' descr_for_what, p_name, p_memo + from ( + select p2.rdb$parameter_name p_name, p2.rdb$description p_memo + from rdb$procedure_parameters p2 + where p2.rdb$package_name = upper('pg_test') + order by p2.rdb$parameter_name + ) + + + union all + + select 'package func args', a_name, f_memo + from ( + select f2.rdb$argument_name a_name, f2.rdb$description f_memo + from rdb$function_arguments f2 + where f2.rdb$package_name = upper('pg_test') and f2.rdb$argument_name is not null + order by f2.rdb$argument_name + ) + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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 + ĄĘŁŹŻ ЙЁ ЊЋЏ ĂŞŢ + """ + +@pytest.mark.version('>=3.0') +def test_core_4484_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4487.py b/tests/bugs/test_core_4487.py new file mode 100644 index 00000000..4ad705a0 --- /dev/null +++ b/tests/bugs/test_core_4487.py @@ -0,0 +1,213 @@ +#coding:utf-8 +# +# id: bugs.core_4487 +# title: Maintain package body after ALTER/RECREATE PACKAGE +# decription: +# tracker_id: CORE-4487 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('HDR_SOURCE.*', ''), ('BODY_SOURCE.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter view v_pg_meta as + select + rp.rdb$package_header_source hdr_source + ,rp.rdb$package_body_source body_source + ,rp.rdb$valid_body_flag body_valid + from rdb$packages rp + where rp.rdb$package_name = upper('pg_test'); + + set list on; + set blob all; + + set term ^; + create or alter package pg_test + as + begin + function fn_test_01 returns smallint; + function fn_test_02 returns smallint; + end + ^ + + recreate package body pg_test + as + begin + function fn_test_01 returns smallint as + begin + return 1; + end + + function fn_test_02 returns smallint as + begin + return 2; + end + end + ^ + set term ;^ + commit; + ----------------------------------------- + select 1 as step, v.* from v_pg_meta v; + ------------------------------------------ + + set term ^; + create or alter package pg_test + as + begin + function fn_test_01 returns smallint; + function fn_test_02(a_val smallint) returns smallint; + end + ^ + set term ;^ + commit; + ----------------------------------------- + set term ^; + create or alter package pg_test + as + begin + function fn_test_01 returns smallint; + -- Adding IN-argument to func must lead package body to invalid state: + function fn_test_02(a_val smallint) returns smallint; + end + ^ + set term ;^ + commit; + ----------------------------------------- + select 2 as step, v.* from v_pg_meta v; + ------------------------------------------ + + set term ^; + create or alter package pg_test + as + begin + function fn_test_03 returns bigint; + end + ^ + set term ;^ + commit; + ----------------------------------------- + select 3 as step, v.* from v_pg_meta v; + ------------------------------------------ + + set term ^; + create or alter package pg_test + as + begin + -- Restoring exactly the same singnatures of both functions + -- does NOT make package body to VALID state: + function fn_test_01 returns smallint; + function fn_test_02 returns smallint; + end + ^ + set term ;^ + commit; + ----------------------------------------- + select 4 as step, v.* from v_pg_meta v; + ------------------------------------------ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + STEP 1 + HDR_SOURCE 2a:1 + begin + function fn_test_01 returns smallint; + function fn_test_02 returns smallint; + end + BODY_SOURCE 2a:4 + begin + function fn_test_01 returns smallint as + begin + return 1; + end + function fn_test_02 returns smallint as + begin + return 2; + end + end + BODY_VALID 1 + + + + STEP 2 + HDR_SOURCE 2a:1 + begin + function fn_test_01 returns smallint; + -- Adding IN-argument to func must lead package body to invalid state: + function fn_test_02(a_val smallint) returns smallint; + end + BODY_SOURCE 2a:4 + begin + function fn_test_01 returns smallint as + begin + return 1; + end + function fn_test_02 returns smallint as + begin + return 2; + end + end + BODY_VALID 0 + + + + STEP 3 + HDR_SOURCE 2a:2 + begin + function fn_test_03 returns bigint; + end + BODY_SOURCE 2a:4 + begin + function fn_test_01 returns smallint as + begin + return 1; + end + function fn_test_02 returns smallint as + begin + return 2; + end + end + BODY_VALID 0 + + + + STEP 4 + HDR_SOURCE 2a:1 + begin + -- Restoring exactly the same singnatures of both functions + -- does NOT make package body to VALID state: + function fn_test_01 returns smallint; + function fn_test_02 returns smallint; + end + BODY_SOURCE 2a:4 + begin + function fn_test_01 returns smallint as + begin + return 1; + end + function fn_test_02 returns smallint as + begin + return 2; + end + end + BODY_VALID 0 + """ + +@pytest.mark.version('>=3.0') +def test_core_4487_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4488.py b/tests/bugs/test_core_4488.py new file mode 100644 index 00000000..16c38f61 --- /dev/null +++ b/tests/bugs/test_core_4488.py @@ -0,0 +1,171 @@ +#coding:utf-8 +# +# id: bugs.core_4488 +# title: Cursor references must always represent the CURRENT state of the record, without caching when this record is read +# decription: +# See doc\\sql.extensions\\README.cursor_variables.txt: +# 7) Reading from a cursor variable returns the current field values. That means an UPDATE (with +# WHERE CURRENT OF) also updates the fields for subsequent reads. And DELETE (with WHERE +# CURRENT OF) makes subsequent reads to return NULL. +# +# tracker_id: CORE-4488 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """ + recreate table t_source(id int, x int, y int, z int); commit; + recreate table t_target(id int, x int, y int, z int); commit; + insert into t_source values(1, 10, 100, 1000); + insert into t_source values(2, 20, 200, 2000); + insert into t_source values(3, 30, 300, 3000); + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + --------------- 1 ----------------- + select '' as "old data of t_source:", (select count(*) from t_source) "rows in t_source", s.* + from rdb$database b left join t_source s on 1=1; + set term ^; + execute block + as + begin + for + select + id, + x as x, + y as y, + z as z + from t_source s + as cursor cs + do begin + delete from t_source where current of cs; -- yes, we DELETE record BEFORE insert it's values because now they all are stored in cursor 'CS' variables + insert into t_target values( cs.id, cs.x, cs.y, cs.z ); + end + end + ^ set term ;^ + select '' as "1. New data of t_source:", (select count(*) from t_source) "rows in t_source", s.* + from rdb$database b left join t_source s on 1=1; + select '' as "1. New data of t_target:", (select count(*) from t_target) "rows in t_target", t.* + from rdb$database b left join t_target t on 1=1; + rollback; + + --------------- 2 ----------------- + set term ^; + execute block + as + begin + for + select + id, + x+1 as x, + y+2 as y, + z+3 as z + from t_source s + as cursor cs + do begin + delete from t_source where current of cs; + insert into t_target values( cs.id, cs.x, cs.y, cs.z ); + end + end + ^ set term ;^ + + select '' as "2. New data of t_source:", (select count(*) from t_source) "rows in t_source", s.* + from rdb$database b left join t_source s on 1=1; + select '' as "2. New data of t_target:", (select count(*) from t_target) "rows in t_target", t.* + from rdb$database b left join t_target t on 1=1; + + rollback; + + --------------- 3 ----------------- + set term ^; + execute block + as + begin + for + select + id, + x as x, + y as y, + z+1 as z + from t_source s + as cursor cs + do begin + update t_source set y=x, z=y, x=z where current of cs; + insert into t_target values( cs.id, cs.x, cs.y, cs.z ); + end + end + ^ set term ;^ + + select '' as "3. New data of t_source:", (select count(*) from t_source) "rows in t_source", s.* + from rdb$database b left join t_source s on 1=1; + select '' as "3. New data of t_target:", (select count(*) from t_target) "rows in t_target", t.* + from rdb$database b left join t_target t on 1=1; + + rollback; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + old data of t_source: rows in t_source ID X Y Z + ===================== ===================== ============ ============ ============ ============ + 3 1 10 100 1000 + 3 2 20 200 2000 + 3 3 30 300 3000 + + + 1. New data of t_source: rows in t_source ID X Y Z + ======================== ===================== ============ ============ ============ ============ + 0 + + + 1. New data of t_target: rows in t_target ID X Y Z + ======================== ===================== ============ ============ ============ ============ + 3 + 3 + 3 + + + 2. New data of t_source: rows in t_source ID X Y Z + ======================== ===================== ============ ============ ============ ============ + 0 + + + 2. New data of t_target: rows in t_target ID X Y Z + ======================== ===================== ============ ============ ============ ============ + 3 + 3 + 3 + + + 3. New data of t_source: rows in t_source ID X Y Z + ======================== ===================== ============ ============ ============ ============ + 3 1 1000 10 100 + 3 2 2000 20 200 + 3 3 3000 30 300 + + + 3. New data of t_target: rows in t_target ID X Y Z + ======================== ===================== ============ ============ ============ ============ + 3 1 1000 10 101 + 3 2 2000 20 201 + 3 3 3000 30 301 + """ + +@pytest.mark.version('>=3.0') +def test_core_4488_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4492.py b/tests/bugs/test_core_4492.py new file mode 100644 index 00000000..b58bfb16 --- /dev/null +++ b/tests/bugs/test_core_4492.py @@ -0,0 +1,71 @@ +#coding:utf-8 +# +# id: bugs.core_4492 +# title: OR/IN predicates for RDB$DBKEY lead to NATURAL plan +# decription: +# Checked on: +# 30SS, build 3.0.3.32856: OK, 1.156s. +# 40SS, build 4.0.0.834: OK, 1.109s. +# +# 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. +# +# tracker_id: CORE-4492 +# min_versions: ['3.0.3'] +# versions: 3.0.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + + recreate view v_unioned as + select rdb$relation_id as rel_id, rdb$db_key as db_key from rdb$relations + union all + select rdb$relation_id, rdb$db_key from rdb$relations + ; + + set planonly; + --set echo on; + + select 1 from rdb$relations where rdb$db_key in (?, ?); + select 2 from rdb$relations a join rdb$relations b on a.rdb$db_key = b.rdb$db_key; + select 3 from v_unioned v where v.db_key in (?, ?); + select 4 from v_unioned a join v_unioned b on a.db_key = b.db_key; + + -- 27.12.2017: this works fine (fixed by dimitr, see letter 01.12.2017 09:57): + select 5 from rdb$relations where rdb$db_key is not distinct from ?; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (RDB$RELATIONS INDEX ()) + PLAN JOIN (A NATURAL, B INDEX ()) + PLAN (V RDB$RELATIONS INDEX (), V RDB$RELATIONS INDEX ()) + PLAN HASH (B RDB$RELATIONS NATURAL, B RDB$RELATIONS NATURAL, A RDB$RELATIONS NATURAL, A RDB$RELATIONS NATURAL) + PLAN (RDB$RELATIONS INDEX ()) + """ + +@pytest.mark.version('>=3.0.3') +def test_core_4492_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4493.py b/tests/bugs/test_core_4493.py new file mode 100644 index 00000000..f4213f72 --- /dev/null +++ b/tests/bugs/test_core_4493.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: bugs.core_4493 +# title: Index not found for RECREATE TRIGGER +# decription: +# tracker_id: CORE-4493 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table mvt(id int primary key, ac int, amount numeric(12,2)); + recreate table account(id int primary key, balance numeric(12,2)); + commit; + + set term ^; + recreate trigger tai_mvt active after insert or update position 1 on mvt as + begin + update account a set a.balance = a.balance + new.amount + where a.id = new.ac; + end + ^ + set term ;^ + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +def test_core_4493_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_4497.py b/tests/bugs/test_core_4497.py new file mode 100644 index 00000000..a61503c1 --- /dev/null +++ b/tests/bugs/test_core_4497.py @@ -0,0 +1,122 @@ +#coding:utf-8 +# +# id: bugs.core_4497 +# title: Regression in 3.0.x: wrong handling in FOR-cursor when NOT EXISTS( select from ) statement is used to check results obtained from SP +# decription: +# tracker_id: CORE-4497 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create or alter procedure sp_test as begin end; + create or alter procedure z_pget as begin end; + commit; + + create or alter view z_vdbg as select 1 as not_handled_agent_id from rdb$database; + commit; + + recreate global temporary table z_gtt(id int, agent_id int) on commit delete rows; + recreate table z_doc(id int, agent_id int); + commit; + + insert into z_doc(id, agent_id) values (101, 7); + commit; + + set term ^; + create or alter procedure z_pget + returns ( + clo_doc_id int, + clo_agent_id int) + as + begin + + delete from z_gtt; + insert into z_gtt select * from z_doc; + + for + select f.id, f.agent_id + from z_gtt f + order by f.id + into clo_doc_id, clo_agent_id + do + suspend; + end + ^ + + create or alter procedure sp_test returns( doc_for_handling int, agent_for_handling int ) + as + declare v_agent_id int; + begin + for + select p.clo_doc_id, p.clo_agent_id from z_pget p + into doc_for_handling, v_agent_id + do begin + agent_for_handling = null; + if ( NOT exists( + select * + from z_vdbg v + where v.not_handled_agent_id = + (select h.agent_id + from z_doc h + where h.id= :doc_for_handling + ) + ) + + ) then + begin + agent_for_handling = v_agent_id; + end + suspend; + end + end + ^ + set term ;^ + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + insert into z_doc(id, agent_id) values (100, 1); + select * from sp_test; + rollback; + + insert into z_doc(id, agent_id) values (102, 1); + select * from sp_test; + rollback; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DOC_FOR_HANDLING 100 + AGENT_FOR_HANDLING + + DOC_FOR_HANDLING 101 + AGENT_FOR_HANDLING 7 + + + DOC_FOR_HANDLING 101 + AGENT_FOR_HANDLING 7 + + DOC_FOR_HANDLING 102 + AGENT_FOR_HANDLING + """ + +@pytest.mark.version('>=2.5') +def test_core_4497_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4498.py b/tests/bugs/test_core_4498.py new file mode 100644 index 00000000..a0531cba --- /dev/null +++ b/tests/bugs/test_core_4498.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: bugs.core_4498 +# title: FB 3.0 crashes when getting an explained plan for a DBKEY based retrieval +# decription: +# tracker_id: CORE-4498 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + out nul; + set explain; + select 1 from rdb$relations where rdb$db_key = cast('1234' as char(8) character set octets); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Select Expression + -> Filter + -> Table "RDB$RELATIONS" Access By ID + -> DBKEY + """ + +@pytest.mark.version('>=3.0') +def test_core_4498_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4503.py b/tests/bugs/test_core_4503.py new file mode 100644 index 00000000..06705a5e --- /dev/null +++ b/tests/bugs/test_core_4503.py @@ -0,0 +1,128 @@ +#coding:utf-8 +# +# id: bugs.core_4503 +# title: ISQL command SHOW USERS display only me +# decription: +# 29.07.2016: instead of issuing SHOW USERS which has unstable output (can be changed multiple times!) +# it was decided to replace it with SQL query which actually is done by this command. +# This query can be easily found in trace when we run SHOW USERS. +# Also, we limit output with only those users who is enumerated here thus one may do not warry about +# another user logins which could left in securitiN.fdb after some test failed. +# +# 29.03.2018: changed user names, replaced count of SYSDBA attachments with literal 1. +# Checked on: +# fb30Cs, build 3.0.4.32924: OK, 3.781s. +# FB30SS, build 3.0.4.32939: OK, 1.312s. +# FB40CS, build 4.0.0.918: OK, 4.547s. +# FB40SS, build 4.0.0.943: OK, 2.094s. +# +# tracker_id: CORE-4503 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create or alter user TMP$C4503_BILL password '123'; + create or alter user TMP$C4503_JOHN password '456'; + create or alter user TMP$C4503_MICK password '789'; + create or alter user TMP$C4503_BOSS password '000'; + + -- do NOT remove or change name 'test' - it is used in several old tests, see resources/test_user.fbr: + -- core_1083.fbt core_1845.fbt core_1148.fbt core_2729.fbt -- all of them can create user 'TEST' and do not remove it. + create or alter user test password 'test'; + drop user test; -- immediatelly remove this name + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# con_0a = kdb.connect(dsn=dsn.encode()) +# con_0b = kdb.connect(dsn=dsn.encode()) +# +# con_1a = kdb.connect(dsn=dsn.encode(),user='TMP$C4503_BILL',password='123') +# con_1b = kdb.connect(dsn=dsn.encode(),user='TMP$C4503_BILL',password='123') +# con_1c = kdb.connect(dsn=dsn.encode(),user='TMP$C4503_BILL',password='123') +# con_1d = kdb.connect(dsn=dsn.encode(),user='TMP$C4503_BILL',password='123') +# con_1e = kdb.connect(dsn=dsn.encode(),user='TMP$C4503_BILL',password='123') +# +# con_2a = kdb.connect(dsn=dsn.encode(),user='TMP$C4503_JOHN',password='456') +# con_2b = kdb.connect(dsn=dsn.encode(),user='TMP$C4503_JOHN',password='456') +# con_2c = kdb.connect(dsn=dsn.encode(),user='TMP$C4503_JOHN',password='456') +# con_2d = kdb.connect(dsn=dsn.encode(),user='TMP$C4503_JOHN',password='456') +# +# con_3a = kdb.connect(dsn=dsn.encode(),user='TMP$C4503_MICK',password='789') +# script = ''' +# set list on; +# -- "SHOW USERS" command actually runs following query: +# select +# case +# when coalesce(mon$user, sec$user_name) = current_user +# then '#' +# when sec$user_name is distinct from null +# then ' ' +# else '-' +# end is_current_user +# ,coalesce(m.mon$user, u.sec$user_name) user_name +# ,iif( m.mon$user = upper('SYSDBA'), 1, count(m.mon$user) ) keeps_attachments +# from mon$attachments m +# full join sec$users u on m.mon$user = u.sec$user_name +# where +# coalesce(mon$system_flag, 0) = 0 +# and coalesce(m.mon$user, u.sec$user_name) in ( upper('TMP$C4503_BILL'), upper('TMP$C4503_BOSS'), upper('TMP$C4503_JOHN'), upper('TMP$C4503_MICK'), upper('SYSDBA') ) +# group by mon$user, sec$user_name +# order by coalesce(mon$user, sec$user_name); +# commit; +# +# drop user TMP$C4503_BILL; +# drop user TMP$C4503_JOHN; +# drop user TMP$C4503_MICK; +# drop user TMP$C4503_BOSS; +# ''' +# runProgram('isql',[dsn,'-q'],script) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + IS_CURRENT_USER # + USER_NAME SYSDBA + KEEPS_ATTACHMENTS 1 + + IS_CURRENT_USER + USER_NAME TMP$C4503_BILL + KEEPS_ATTACHMENTS 5 + + IS_CURRENT_USER + USER_NAME TMP$C4503_BOSS + KEEPS_ATTACHMENTS 0 + + IS_CURRENT_USER + USER_NAME TMP$C4503_JOHN + KEEPS_ATTACHMENTS 4 + + IS_CURRENT_USER + USER_NAME TMP$C4503_MICK + KEEPS_ATTACHMENTS 1 + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4503_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4507.py b/tests/bugs/test_core_4507.py new file mode 100644 index 00000000..5f4db051 --- /dev/null +++ b/tests/bugs/test_core_4507.py @@ -0,0 +1,57 @@ +#coding:utf-8 +# +# id: bugs.core_4507 +# title: Unable delete procedure source on Firebird 3.0 Alpha 2.0 +# decription: +# tracker_id: CORE-4507 +# min_versions: ['2.0.7'] +# versions: 2.0.7 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.7 +# resources: None + +substitutions_1 = [('RDB\\$PROCEDURE_SOURCE.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create or alter procedure sp_test(x int, y int) returns(z bigint) as + begin + z = x + y; + suspend; + end + ^set term ;^ + commit; + + set blob all; + set list on; + select rdb$procedure_source from rdb$procedures where rdb$procedure_name = upper('sp_test'); + + update rdb$procedures set rdb$procedure_source = null where rdb$procedure_name = upper('sp_test'); + commit; + select iif(rdb$procedure_source is null, 'NO_SOURCE', 'HAS_SOURCE') sp_src from rdb$procedures where rdb$procedure_name = upper('sp_test'); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + begin + z = x + y; + suspend; + end + SP_SRC NO_SOURCE + """ + +@pytest.mark.version('>=2.0.7') +def test_core_4507_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4524.py b/tests/bugs/test_core_4524.py new file mode 100644 index 00000000..1b39fd37 --- /dev/null +++ b/tests/bugs/test_core_4524.py @@ -0,0 +1,377 @@ +#coding:utf-8 +# +# id: bugs.core_4524 +# title: New gbak option to enable encryption during restore +# decription: +# Part of this test was copied from core_6071.fbt. +# We create new database and try to encrypt it using IBSurgeon Demo Encryption package +# ( https://ib-aid.com/download-demo-firebird-encryption-plugin/ ; https://ib-aid.com/download/crypt/CryptTest.zip ) +# License file plugins\\dbcrypt.conf with unlimited expiration was provided by IBSurgeon to Firebird Foundation (FF). +# This file was preliminary stored in FF Test machine. +# Test assumes that this file and all neccessary libraries already were stored into FB_HOME and %FB_HOME%\\plugins. +# +# We create several generators in the test DB and get number of generators page using query to RDB$PAGES (page_type=9). +# Also we get page_size and using these data we can obtain binary content of generatord page. This content futher is parsed +# in order to verify that generators names are readable (while DB is not yet encrypted). +# +# Then we encrypt DB and make delay after this for ~1..2 seconds BEFORE detach from database. +# +# After this we: +# 1. Change temp DB state to full shutdown and bring it online - in order to be sure that we will able to drop this file later; +# 2. Make backup of this temp DB, using gbak utility and '-KEYHOLDER ' command switch. +# 3. Make restore from just created backup. +# 4. Make validation of just restored database by issuing command "gfix -v -full ..." +# ( i.e. validate both data and metadata rather than online val which can check user data only). +# 5. Open restored DB as binary file and attempt to read again generators names - this must fail, their names must be encrypted. +# 6. Check that NO errors occured on any above mentioned steps. Also check that backup and restore STDOUT logs contain expected +# text about successful completition +# +# 13.04.2021. Adapted for run both on Windows and Linux. Checked on: +# Windows: 4.0.0.2416 +# Linux: 4.0.0.2416 +# Note: different names for encryption plugin and keyholde rare used for Windows vs Linux: +# PLUGIN_NAME = 'dbcrypt' if os.name == 'nt' else '"fbSampleDbCrypt"' +# KHOLDER_NAME = 'KeyHolder' if os.name == 'nt' else "fbSampleKeyHolder" +# +# +# tracker_id: CORE-4524 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('\\d+ BYTES WRITTEN', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import time +# import subprocess +# import binascii +# import re +# import fdb +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.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 ) +# +# #-------------------------------------------- +# +# def check_page_for_readable_values(dbname, gen_page_number, pg_size, check_sequence_values): +# +# global binascii +# +# db_handle = open( dbname, "rb") +# db_handle.seek( gen_page_number * pg_size ) +# page_content = db_handle.read( pg_size ) +# # read_binary_content( db_handle, gen_page_number * pg_size, pg_size ) +# db_handle.close() +# page_as_hex=binascii.hexlify( page_content ) +# +# # Iterate for each sequence value: +# for n in check_sequence_values: +# +# # Get HEX representation of digital value. +# # NOTE: format( 830624, 'x') is 'caca0' contains five (odd number!) characters. +# hex_string = format(abs(n),'x') +# +# # Here we 'pad' hex representation to EVEN number of digits in it, +# # otherwise binascii.hexlify fails with "Odd-length string error": +# hex_string = ''.join( ('0' * ( len(hex_string)%2 ), hex_string ) ) +# +# # ::: NOTE ::: +# # Generator value is stored in REVERSED bytes order. +# # dec 830624 --> hex 0x0caca0 --> 0c|ac|a0 --> stored in page as three bytes: {a0; ac; 0c} +# +# # Decode string that is stored in variable 'hex_string' to HEX number, +# # REVERSE its bytes and convert it to string again for further search +# # in page content: +# n_as_reversed_hex = binascii.hexlify( hex_string.decode('hex')[::-1] ) +# +# print(n, n_as_reversed_hex, 'FOUND.' if n_as_reversed_hex in page_as_hex else 'NOT FOUND.' ) +# # print(n, n_as_reversed_hex, 'UNEXPECTEDLY FOUND AT POS. ' + '{:5d}'.format( page_as_hex.index(n_as_reversed_hex) ) if n_as_reversed_hex in page_as_hex else 'Not found (expected).' ) +# +# #-------------------------------------------- +# +# tmpfdb='$(DATABASE_LOCATION)'+'tmp_core_4524.encrypted.fdb' +# tmpres='$(DATABASE_LOCATION)'+'tmp_core_4524.restored.fdb' +# tmpbkp='$(DATABASE_LOCATION)'+'tmp_core_4524.encrypted.fbk' +# +# cleanup( (tmpfdb, tmpres) ) +# +# con = fdb.create_database( dsn = 'localhost:'+tmpfdb ) +# +# con.execute_immediate('create sequence gen_ba0bab start with 12192683') +# con.execute_immediate('create sequence gen_badf00d start with 195948557') +# con.execute_immediate('create sequence gen_caca0 start with 830624') +# con.execute_immediate('create sequence gen_c0ffee start with 12648430') +# con.execute_immediate('create sequence gen_dec0de start with 14598366') +# con.execute_immediate('create sequence gen_decade start with 14600926') +# con.execute_immediate('create sequence gen_7FFFFFFF start with 2147483647') +# con.commit() +# +# cur=con.cursor() +# get_current_seq_values=''' +# execute block returns( gen_curr bigint) as +# declare gen_name rdb$generator_name; +# begin +# for +# select rdb$generator_name from rdb$generators where rdb$system_flag is distinct from 1 order by rdb$generator_id +# into gen_name +# do begin +# execute statement 'execute block returns(g bigint) as begin g = gen_id('|| gen_name ||', 0); suspend; end' into gen_curr; +# suspend; +# end +# end +# ''' +# +# # Obtain current values of user generators: +# # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# cur.execute(get_current_seq_values) +# check_sequence_values=[] +# for r in cur: +# check_sequence_values += r[0], +# #print('check_sequence_values=',check_sequence_values) +# +# +# # Obtain page size and number of generators page: +# # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# cur.execute('select m.mon$page_size,min(rdb$page_number) from mon$database m cross join rdb$pages p where p.rdb$page_type = 9 group by 1') +# pg_size, gen_page_number = -1,-1 +# for r in cur: +# pg_size=r[0] +# gen_page_number=r[1] +# # print(r[0],r[1]) +# cur.close() +# +# +# # Read gen page, convert it to hex and check whether generator values can be found there or no: +# # Expected result: YES for all values because DB not encrypted now. +# # ~~~~~~~~~~~~~~~ +# check_page_for_readable_values(tmpfdb, gen_page_number, pg_size, check_sequence_values) +# +# ################################################ +# ### e n c r y p t d a t a b a s e ### +# ################################################ +# +# # 14.04.2021. +# # Name of encryption plugin depends on OS: +# # * for Windows we (currently) use plugin by IBSurgeon, its name is 'dbcrypt'; +# # * for Linux we use: +# # ** 'DbCrypt_example' for FB 3.x +# # ** 'fbSampleDbCrypt' for FB 4.x+ +# # +# PLUGIN_NAME = 'dbcrypt' if os.name == 'nt' else '"fbSampleDbCrypt"' +# KHOLDER_NAME = 'KeyHolder' if os.name == 'nt' else "fbSampleKeyHolder" +# cur = con.cursor() +# cur.execute('alter database encrypt with %(PLUGIN_NAME)s key Red' % locals()) +# ### DOES NOT WORK ON LINUX! ISSUES 'TOKEN UNKNOWN' !! >>> con.execute_immediate('alter database encrypt with %(PLUGIN_NAME)s key Red' % locals()) // sent letter to Alex and dimitr, 14.04.2021 +# con.commit() +# time.sleep(2) +# # ^ +# # +-------- !! ALLOW BACKGROUND ENCRYPTION PROCESS TO COMPLETE ITS JOB !! +# +# ####################################### +# # Added 14.04.2021: check that database is actually encrypted. +# # Column MON$DATABASE.MON$CRYPT_STATE can have following values: +# # 0 = NOT encrypteed; +# # 1 = encrypted +# # 2 = encryption process is running now +# # 3 = decryption process is running now +# ####################################### +# cur.execute("select iif(mon$crypt_state=1, 'Database ENCRYPTED.', '### ERROR: DATABASE REMAINS UNENCRYPTED ###, MON$CRYPT_STATE = ' || mon$crypt_state) as msg from mon$database") +# for r in cur: +# print( r[0] ) +# con.close() +# cur.close() +# +# #-------------------------- shutdown temp DB and bring it online -------------------- +# +# f_dbshut_log = open( os.path.join(context['temp_directory'],'tmp_dbshut_4524.log'), 'w') +# subprocess.call( [ context['gfix_path'], 'localhost:'+tmpfdb, "-shut", "full", "-force", "0" ], +# stdout = f_dbshut_log, +# stderr = subprocess.STDOUT +# ) +# subprocess.call( [ context['gfix_path'], 'localhost:'+tmpfdb, "-online" ], +# stdout = f_dbshut_log, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_dbshut_log ) +# +# #--------------------------- backup and restore -------------------------------------- +# fn_bkp_log=open( os.path.join(context['temp_directory'],'tmp_backup_4524.log'), 'w') +# fn_bkp_err=open( os.path.join(context['temp_directory'],'tmp_backup_4524.err'), 'w') +# +# # /var/tmp/fb40tmp/bin/gbak -b -v -keyholder fbSampleKeyHolder -crypt fbSampleDbCrypt localhost:/path/to/encrypted.fdb /path/to/encrypted.fbk +# +# subprocess.call([ context['gbak_path'] +# ,"-b" +# ,"-v" +# ,"-KEYHOLDER", KHOLDER_NAME # "KeyHolder" | "fbSampleKeyHolder" +# ,"-crypt", PLUGIN_NAME.replace('"','') # DbCrypt | fbSampleDbCrypt +# ,'localhost:' + tmpfdb +# ,tmpbkp +# ], +# stdout=fn_bkp_log, stderr=fn_bkp_err) +# +# flush_and_close( fn_bkp_log ) +# flush_and_close( fn_bkp_err ) +# +# +# fn_res_log=open( os.path.join(context['temp_directory'],'tmp_restore_4524.log'), 'w') +# fn_res_err=open( os.path.join(context['temp_directory'],'tmp_restore_4524.err'), 'w') +# +# # C:\\FB SS\\gbak.exe -rep -KEYHOLDER KeyHolder C:\\FBTESTING\\qa\\misc\\C4524.fbk /:C:\\FBTESTING\\qa\\misc\\c4524.restored.FDB +# subprocess.call([ context['gbak_path'] +# ,"-rep" +# ,"-v" +# ,"-KEYHOLDER", KHOLDER_NAME # "KeyHolder" | "fbSampleKeyHolder" +# ,tmpbkp +# ,'localhost:' + tmpres +# ], +# stdout=fn_res_log, stderr=fn_res_err) +# +# flush_and_close( fn_res_log ) +# flush_and_close( fn_res_err ) +# +# #-------------------------- validate just restored database -------------------- +# +# f_valid_log = open( os.path.join(context['temp_directory'],'tmp_valid_4524.log'), 'w') +# subprocess.call( [ context['gfix_path'], 'localhost:'+tmpres, "-v", "-full" ], +# stdout = f_valid_log, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_valid_log ) +# +# #----------------------------------------------- +# +# # Read gen page in RESTORED database, convert it to hex and check whether generator values can be found there or no. +# # Expected result: NOT for all values because DB was encrypted. +# # ~~~~~~~~~~~~~~~~ +# check_page_for_readable_values(tmpres, gen_page_number, pg_size, check_sequence_values) +# +# #----------------------------------------------- +# +# # Check that all was fine: +# +# with open(f_dbshut_log.name,'r') as f: +# for line in f: +# if line.split(): +# print('UNEXPECTED SHUTDOWN OUTPUT: ' + line) +# +# with open(fn_bkp_err.name,'r') as f: +# for line in f: +# if line.split(): +# print('UNEXPECTED BACKUP STDERR: ' + line) +# +# with open(fn_res_err.name,'r') as f: +# for line in f: +# if line.split(): +# print('UNEXPECTED RESTORE STDERR: ' + line) +# +# with open(f_dbshut_log.name,'r') as f: +# for line in f: +# if line.split(): +# print('UNEXPECTED VALIDATION OUTPUT: ' + line) +# +# +# # gbak -b should finish with line: +# # gbak:closing file, committing, and finishing. 512 bytes written +# gbak_backup_finish_ptn=re.compile('gbak:closing\\s+file,\\s+committing,\\s+and\\s+finishing.*', re.IGNORECASE) +# with open(fn_bkp_log.name,'r') as f: +# for line in f: +# if gbak_backup_finish_ptn.search(line): +# print('EXPECTED BACKUP FINISH FOUND: '+line.upper() ) +# +# +# # gbak -c should finish with lines: +# # gbak:finishing, closing, and going home +# # gbak:adjusting the ONLINE and FORCED WRITES flags +# +# gbak_restore_finish_ptn=re.compile('gbak:adjusting\\s+the\\s+ONLINE\\s+and\\s+FORCED\\s+WRITES\\s+.*', re.IGNORECASE) +# with open(fn_res_log.name,'r') as f: +# for line in f: +# if gbak_restore_finish_ptn.search(line): +# print('EXPECTED RESTORE FINISH FOUND: '+line.upper() ) +# +# +# # cleanup +# ########## +# time.sleep(1) +# f_list = [ i.name for i in ( f_dbshut_log, fn_bkp_log, fn_bkp_err, fn_res_log, fn_res_err, f_valid_log ) ] + [ tmpfdb, tmpres, tmpbkp ] +# cleanup( f_list ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 12192682 aa0bba FOUND. + 195948556 0cf0ad0b FOUND. + 830623 9fac0c FOUND. + 12648429 edffc0 FOUND. + 14598365 ddc0de FOUND. + 14600925 ddcade FOUND. + 2147483646 feffff7f FOUND. + + Database ENCRYPTED. + + 12192682 aa0bba NOT FOUND. + 195948556 0cf0ad0b NOT FOUND. + 830623 9fac0c NOT FOUND. + 12648429 edffc0 NOT FOUND. + 14598365 ddc0de NOT FOUND. + 14600925 ddcade NOT FOUND. + 2147483646 feffff7f NOT FOUND. + EXPECTED BACKUP FINISH FOUND: GBAK:CLOSING FILE, COMMITTING, AND FINISHING. + EXPECTED RESTORE FINISH FOUND: GBAK:ADJUSTING THE ONLINE AND FORCED WRITES FLAGS + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_4524_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4528.py b/tests/bugs/test_core_4528.py new file mode 100644 index 00000000..8dc733f6 --- /dev/null +++ b/tests/bugs/test_core_4528.py @@ -0,0 +1,121 @@ +#coding:utf-8 +# +# id: bugs.core_4528 +# title: Allow hash/merge joins for non-field (dbkey or derived expression) equalities +# decription: NB: currently join oth three and more sources made by USING or NATURAL clauses will use NL. See CORE-4809 +# tracker_id: CORE-4528 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table tn(x int primary key using index tn_x); + commit; + insert into tn select row_number()over() from rdb$types; + commit; + + -- this will NOT pruduce HJ, at least for WI-T3.0.0.31840 + -- select * from (select rdb$db_key a from tn) r join (select rdb$db_key b from tn) s on r.a||'' = s.b||''; + + set planonly; + --set echo on; + + -- ### 1. Columns from derived tables ### + + select count(*) + from (select x a from tn) r + join (select x a from tn) s on r.a + 0 = s.a + 0; + + select count(*) + from (select x a from tn) r + join (select x a from tn) s on r.a + 0 = s.a + 0 + join (select x a from tn) t on s.a + 0 = t.a + 0; + + -- ### 2. RDB$DB_KEY ### + + ----------- test `traditional` join form ----------------- + select count(*) + from (select rdb$db_key||'' a from tn) r + join (select rdb$db_key||'' a from tn) s on r.a = s.a; + + select count(*) + from (select rdb$db_key||'' a from tn) r + join (select rdb$db_key||'' a from tn) s on r.a = s.a + join (select rdb$db_key||'' a from tn) t on s.a = t.a; + + select count(*) + from (select rdb$db_key||'' a from tn) r + join (select rdb$db_key||'' a from tn) s on r.a = s.a + join (select rdb$db_key||'' a from tn) t on s.a = t.a + join (select rdb$db_key||'' a from tn) u on t.a = u.a; + + ----------- test join on named columns form ----------------- + select count(*) + from (select rdb$db_key||'' a from tn) r + join (select rdb$db_key||'' a from tn) s using(a); + + -- Currently these will produce NESTED LOOPS, SEE CORE-4809. + -- Uncomment these statements and correct expected_output when + -- (and if) core-4809 will be fixed: + --select count(*) + --from (select rdb$db_key||'' a from tn) r + --join (select rdb$db_key||'' a from tn) s using(a) + --join (select rdb$db_key||'' a from tn) t using(a); + -- + --select count(*) + --from (select rdb$db_key||'' a from tn) r + --join (select rdb$db_key||'' a from tn) s using(a) + --join (select rdb$db_key||'' a from tn) t using(a) + --join (select rdb$db_key||'' a from tn) u using(a); + + ----------- test natural join form ----------------- + + select count(*) + from (select rdb$db_key||'' a from tn) r + natural join (select rdb$db_key||'' a from tn) s; + + -- Currently these will produce NESTED LOOPS, SEE CORE-4809. + -- Uncomment these statements and correct expected_output when + -- (and if) core-4809 will be fixed: + --select count(*) + --from (select rdb$db_key||'' a from tn) r + --natural join (select rdb$db_key||'' a from tn) s + --natural join (select rdb$db_key||'' a from tn) t; + -- + --select count(*) + --from (select rdb$db_key||'' a from tn) r + --natural join (select rdb$db_key||'' a from tn) s + --natural join (select rdb$db_key||'' a from tn) t + --natural join (select rdb$db_key||'' a from tn) u; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN HASH (S TN NATURAL, R TN NATURAL) + PLAN HASH (HASH (T TN NATURAL, S TN NATURAL), R TN NATURAL) + PLAN HASH (S TN NATURAL, R TN NATURAL) + PLAN HASH (HASH (T TN NATURAL, S TN NATURAL), R TN NATURAL) + PLAN HASH (HASH (HASH (U TN NATURAL, T TN NATURAL), S TN NATURAL), R TN NATURAL) + PLAN HASH (S TN NATURAL, R TN NATURAL) + PLAN HASH (S TN NATURAL, R TN NATURAL) + """ + +@pytest.mark.version('>=3.0') +def test_core_4528_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4529.py b/tests/bugs/test_core_4529.py new file mode 100644 index 00000000..d06fefd5 --- /dev/null +++ b/tests/bugs/test_core_4529.py @@ -0,0 +1,59 @@ +#coding:utf-8 +# +# id: bugs.core_4529 +# title: Allow to use index when GROUP BY on field which has DESCENDING index +# decription: +# 4.0.0.804: OK, 1.484s. // Before this build plan was: "PLAN SORT (T NATURAL)" +# +# tracker_id: CORE-4529 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table t(x int, y int); + commit; + + insert into t select rand()*5, rand()*5 + from rdb$types; + commit; + + create DESCENDING index t_x_desc on t(x); + create DESCENDING index t_c_desc on t computed by( x+y ); + commit; + + set planonly; + + select x,max(y) from t group by x; + select x,min(y) from t group by x; + + select count(x) from t group by ( x+y ); + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (T ORDER T_X_DESC) + PLAN (T ORDER T_X_DESC) + PLAN (T ORDER T_C_DESC) + """ + +@pytest.mark.version('>=4.0') +def test_core_4529_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4530.py b/tests/bugs/test_core_4530.py new file mode 100644 index 00000000..06ee62e7 --- /dev/null +++ b/tests/bugs/test_core_4530.py @@ -0,0 +1,52 @@ +#coding:utf-8 +# +# id: bugs.core_4530 +# title: DB_KEY based join of two tables may be ineffective +# decription: Order of expressions in the join condition could negatively affect the generated plan and thus performance +# tracker_id: CORE-4530 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table t (id int, constraint t_pk primary key(id) using index t_pk_idx); + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set planonly; + + -- This query had bad generated plan before fix core-4530: + -- PLAN JOIN (X A ORDER RDB$PRIMARY4, Z NATURAL) + select count(*) + from (select id, rdb$db_key k from t a order by id) x + left join t z on x.k = z.rdb$db_key; -------------------- left side: `x.k`, right side: `z.rdb$db_key` + + select count(*) + from (select id, rdb$db_key k from t a order by id) x + left join t z on z.rdb$db_key = x.k; -------------------- left side: `z.rdb$db_key`, right side: `x.k` + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN JOIN (X A ORDER T_PK_IDX, Z INDEX ()) + PLAN JOIN (X A ORDER T_PK_IDX, Z INDEX ()) + """ + +@pytest.mark.version('>=3.0') +def test_core_4530_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4539.py b/tests/bugs/test_core_4539.py new file mode 100644 index 00000000..0b4c51be --- /dev/null +++ b/tests/bugs/test_core_4539.py @@ -0,0 +1,59 @@ +#coding:utf-8 +# +# id: bugs.core_4539 +# title: Server does not accept the right plan +# decription: +# tracker_id: CORE-4539 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table horse( + id int primary key + ,color_id int, name varchar(10) + ); + recreate table color( + id int + ,name varchar(10) + ); + commit; + create index color_name on color(name); + commit; + + ------------- + -- Confirmed on WI-T3.0.0.31374 Firebird 3.0 Beta 1 + -- Statement failed, SQLSTATE = 42000 + -- index COLOR_NAME cannot be used in the specified plan + set planonly; + select count(*) + from horse h + join color c on h.color_id = c.id + where h.name = c.name + plan join (h natural, c index (color_name)); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN JOIN (H NATURAL, C INDEX (COLOR_NAME)) + """ + +@pytest.mark.version('>=3.0') +def test_core_4539_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4544.py b/tests/bugs/test_core_4544.py new file mode 100644 index 00000000..0011ba59 --- /dev/null +++ b/tests/bugs/test_core_4544.py @@ -0,0 +1,228 @@ +#coding:utf-8 +# +# id: bugs.core_4544 +# title: Allow hiding source code of procedures and triggers in FB 3 +# decription: +# tracker_id: CORE-4544 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('SOURCE_BLOB.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test(id int primary key, x int); + recreate table tlog(id int, x int); + + recreate sequence g; + + set term ^; + create or alter procedure sp_test1 as + declare c int; + begin + select count(*) from rdb$types into c; + end + ^ + + create or alter function fn_test1 returns int as + begin + return 111; + end + ^ + + create or alter trigger trg_test_1 active before insert on test as + begin + new.id = gen_id(g,1); + end + ^ + + create or alter package pkg_test1 as + begin + procedure sp_test1; + function fn_test1 returns int; + end + ^ + + recreate package body pkg_test1 as + begin + procedure sp_test1 as + declare c int; + begin + select count(*) from rdb$types into c; + end + + function fn_test1 returns int as + begin + return 111; + end + end + ^ + + set term ;^ + commit; + + set blob all; + set list on; + + select rdb$procedure_name, rdb$procedure_source as source_blob + from rdb$procedures where rdb$system_flag is distinct from 1; + + select rdb$function_name, rdb$function_source as source_blob + from rdb$functions where rdb$system_flag is distinct from 1; + + select rdb$trigger_name, rdb$trigger_source as source_blob + from rdb$triggers where rdb$system_flag is distinct from 1; + + select rdb$package_name, rdb$package_body_source as source_blob + from rdb$packages where rdb$system_flag is distinct from 1; + + set count on; + set echo on; + + update rdb$procedures set rdb$procedure_source = null + where + rdb$system_flag is distinct from 1 + and rdb$procedure_source is not null + ; + + update rdb$functions set rdb$function_source = null + where + rdb$system_flag is distinct from 1 + and rdb$function_source is not null + ; + + update rdb$triggers set rdb$trigger_source = null + where + rdb$system_flag is distinct from 1 + and rdb$trigger_source is not null + ; + + update rdb$packages set rdb$package_body_source = null + where + rdb$system_flag is distinct from 1 + and rdb$package_body_source is not null + ; + + set echo off; + commit; + + + select rdb$procedure_name, rdb$procedure_source as source_blob + from rdb$procedures + where rdb$system_flag is distinct from 1 and rdb$procedure_source is not null; + + select rdb$function_name, rdb$function_source as source_blob + from rdb$functions + where rdb$system_flag is distinct from 1 and rdb$function_source is not null; + + select rdb$trigger_name, rdb$trigger_source as source_blob + from rdb$triggers + where rdb$system_flag is distinct from 1 and rdb$trigger_source is not null; + + select rdb$package_name, rdb$package_body_source as source_blob + from rdb$packages where rdb$system_flag is distinct from 1 and rdb$package_body_source is not null; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$PROCEDURE_NAME SP_TEST1 + SOURCE_BLOB 1a:1e0 + declare c int; + begin + select count(*) from rdb$types into c; + end + + RDB$PROCEDURE_NAME SP_TEST1 + SOURCE_BLOB + + + + RDB$FUNCTION_NAME FN_TEST1 + SOURCE_BLOB e:1e0 + begin + return 111; + end + + RDB$FUNCTION_NAME FN_TEST1 + SOURCE_BLOB + + + + RDB$TRIGGER_NAME TRG_TEST_1 + SOURCE_BLOB c:3d0 + as + begin + new.id = gen_id(g,1); + end + + + + RDB$PACKAGE_NAME PKG_TEST1 + SOURCE_BLOB 2a:1 + begin + procedure sp_test1 as + declare c int; + begin + select count(*) from rdb$types into c; + end + + function fn_test1 returns int as + begin + return 111; + end + end + + + + update rdb$procedures set rdb$procedure_source = null + where + rdb$system_flag is distinct from 1 + and rdb$procedure_source is not null + ; + Records affected: 1 + + update rdb$functions set rdb$function_source = null + where + rdb$system_flag is distinct from 1 + and rdb$function_source is not null + ; + Records affected: 1 + + update rdb$triggers set rdb$trigger_source = null + where + rdb$system_flag is distinct from 1 + and rdb$trigger_source is not null + ; + Records affected: 1 + + update rdb$packages set rdb$package_body_source = null + where + rdb$system_flag is distinct from 1 + and rdb$package_body_source is not null + ; + Records affected: 1 + + set echo off; + Records affected: 0 + Records affected: 0 + Records affected: 0 + Records affected: 0 + """ + +@pytest.mark.version('>=3.0') +def test_core_4544_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4555.py b/tests/bugs/test_core_4555.py new file mode 100644 index 00000000..1e6b8a02 --- /dev/null +++ b/tests/bugs/test_core_4555.py @@ -0,0 +1,83 @@ +#coding:utf-8 +# +# id: bugs.core_4555 +# title: DDL trigger remains active after dropped +# decription: +# tracker_id: CORE-4555 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', ''), ('line:\\s[0-9]+,', 'line: x'), ('col:\\s[0-9]+', 'col: y')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create exception ddl_exception 'You have no right to create exceptions. Learn DDL triggers first!'; + commit; + set term ^; + create or alter trigger t_ddl + active before create exception + as + begin + if (current_user <> 'DUDE') then + exception ddl_exception; + end + ^ + set term ;^ + commit; + + create exception user_exception 'Invalid remainder found for case-1.'; + commit; + + drop trigger t_ddl; + commit; + + create exception user_exception 'Invalid remainder found for case-2.' + ; + commit; + + set list on; + set count on; + select rdb$exception_name, rdb$message + from rdb$exceptions + order by rdb$exception_name; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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_1 = """ + Statement failed, SQLSTATE = HY000 + 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: 6, col: 9 + """ + +@pytest.mark.version('>=3.0') +def test_core_4555_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4557.py b/tests/bugs/test_core_4557.py new file mode 100644 index 00000000..7d9a99ab --- /dev/null +++ b/tests/bugs/test_core_4557.py @@ -0,0 +1,80 @@ +#coding:utf-8 +# +# id: bugs.core_4557 +# title: FB 3.0 crashes on EXIT (or QUIT) command if use UTF8-collation + create domain based on it + issue SHOW DOMAIN +# decription: +# tracker_id: CORE-4557 +# min_versions: ['3.0'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + 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_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + show domain; -- FB crashes if this will be uncommented + exit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DM_NAME DM_NUMS + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_core_4557_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """ + 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_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + show domain; -- FB crashes if this will be uncommented + exit; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + DM_NAME + DM_NUMS + """ + +@pytest.mark.version('>=4.0') +def test_core_4557_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/bugs/test_core_4561.py b/tests/bugs/test_core_4561.py new file mode 100644 index 00000000..af231974 --- /dev/null +++ b/tests/bugs/test_core_4561.py @@ -0,0 +1,80 @@ +#coding:utf-8 +# +# id: bugs.core_4561 +# title: BUGCHECK(183) when use cursor with "order by ID+0" and "for update with lock" +# decription: +# tracker_id: CORE-4561 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Confirmed on WI-T3.0.0.31852 (CS/SC/SS): + -- Statement failed, SQLSTATE = XX000 + -- internal Firebird consistency check (wrong record length (183), file: vio.cpp line: 1310) + -- Statement failed, SQLSTATE = XX000 + -- internal Firebird consistency check (can't continue after bugcheck) + -- . . . + recreate table tm(id int); + commit; + insert into tm(id) values(1); + insert into tm(id) values(2); -- at least TWO records need to be added + commit; + + set list on; + set term ^; + execute block returns(deleted_count int) as + begin + deleted_count = 0; + for + select id + from tm + order by id+0 -- "+0" is mandatory for getting BCA + for update with lock -- and this also is mandatory + as cursor c + do begin + delete from tm where current of c; + deleted_count = deleted_count + 1; + end + suspend; + end^ + set term ;^ + + set count on; + set echo on; + select * from tm; + rollback; + select * from tm; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DELETED_COUNT 2 + select * from tm; + Records affected: 0 + rollback; + select * from tm; + ID 1 + ID 2 + Records affected: 2 + """ + +@pytest.mark.version('>=3.0') +def test_core_4561_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4566.py b/tests/bugs/test_core_4566.py new file mode 100644 index 00000000..44f08716 --- /dev/null +++ b/tests/bugs/test_core_4566.py @@ -0,0 +1,76 @@ +#coding:utf-8 +# +# id: bugs.core_4566 +# title: Incorrect size of the output parameter/argument when execute block, procedure or function use system field in metadata charset +# decription: +# tracker_id: CORE-4566 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='WIN1251', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create or alter function get_mnemonic ( + afield_name type of column rdb$types.rdb$field_name, + atype type of column rdb$types.rdb$type) + returns type of column rdb$types.rdb$type_name + as + begin + return (select rdb$type_name + from rdb$types + where + rdb$field_name = :afield_name + and rdb$type = :atype + order by rdb$type_name + ); + end + ^ + set term ;^ + commit; + + set list on; + + select get_mnemonic('MON$SHUTDOWN_MODE', 1) as mnemonic from rdb$database; + --select cast(get_mnemonic('MON$SHUTDOWN_MODE', 1) as varchar(100)) as mnemonic from rdb$database; + + set term ^; + execute block returns (FIELD_NAME RDB$FIELD_NAME) as + begin + for select rdb$type_name + from rdb$types + where rdb$type_name starting with 'BLOB_FILTER' + order by rdb$type_name + rows 1 + into field_name + do + suspend; + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MNEMONIC MULTI_USER_SHUTDOWN + FIELD_NAME BLOB_FILTER + """ + +@pytest.mark.version('>=3.0') +def test_core_4566_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4569.py b/tests/bugs/test_core_4569.py new file mode 100644 index 00000000..b874ae61 --- /dev/null +++ b/tests/bugs/test_core_4569.py @@ -0,0 +1,51 @@ +#coding:utf-8 +# +# id: bugs.core_4569 +# title: BIN_SHL and BIN_SHR does not work in Dialect 1 +# decription: +# tracker_id: CORE-4569 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=1, init=init_script_1) + +test_script_1 = """ + set list on; + select bin_shl(1073741824, 2) bin_shl from rdb$database + union all + select bin_shl(1, 32) from rdb$database + union all + select bin_shl(0, 1) from rdb$database + union all + select bin_shl(-1073741824, 2) from rdb$database + union all + select bin_shl(-1, 32) from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + BIN_SHL 4294967296 + BIN_SHL 4294967296 + BIN_SHL 0 + BIN_SHL -4294967296 + BIN_SHL -4294967296 + """ + +@pytest.mark.version('>=3.0') +def test_core_4569_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4570.py b/tests/bugs/test_core_4570.py new file mode 100644 index 00000000..2ba71c58 --- /dev/null +++ b/tests/bugs/test_core_4570.py @@ -0,0 +1,69 @@ +#coding:utf-8 +# +# id: bugs.core_4570 +# title: Wrong error at ALTER PACKAGE +# decription: +# tracker_id: CORE-4570 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create package p1 + as + begin + function f(x int) returns int; + end + ^ + create package body p1 + as + begin + function f1(x int) returns int; + + function f(x int) returns int + as + begin + return f1(x) * x; + end + + function f1(x int) returns int + as + begin + return 1; + end + end + ^ + commit + ^ + + alter package p1 + as + begin + function f(x int) returns int; + function g(x int) returns int; + end + ^ + commit + ^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +def test_core_4570_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_4571.py b/tests/bugs/test_core_4571.py new file mode 100644 index 00000000..44747d00 --- /dev/null +++ b/tests/bugs/test_core_4571.py @@ -0,0 +1,169 @@ +#coding:utf-8 +# +# id: bugs.core_4571 +# title: Can't select from table with ICU column when database (.FDB) is created on LINUX with icu 4.2.1 and then copied to WINDOWS +# decription: +# Database for this test was created beforehand on Linux host. +# DDL: +# create collation nums_coll for utf8 from unicode case insensitive 'NUMERIC-SORT=1'; +# create domain dm_nums as varchar(20) character set utf8 collate nums_coll; +# recreate table wares(id bigint generated by default as identity, numb dm_nums unique using index wares_numb_unq); +# +# Table 'wares' then filled-up with some utf8 data and then *raw* .fdb file was copied on Windows host. +# +# insert into wares(numb) values('lengéscsillapító'); +# insert into wares(numb) values('viselő'); +# insert into wares(numb) values('bærende'); +# insert into wares(numb) values('ρουλεμάν'); +# insert into wares(numb) values('αμορτισέρ'); +# insert into wares(numb) values('støtdemper'); +# +# Connect to this database without repairing ICU and querying table WARES will produce error: +# === +# SQL> select * from wares; +# Statement failed, SQLSTATE = 22021 +# COLLATION NUMS_COLL for CHARACTER SET UTF8 is not installed +# === +# +# This test makes unzip of 'raw' .fdb and run fbsvcmgr with key 'rpr_icu' in order to fix ICU incompatibility. +# Result of fbsvcmgr (STDOUT and STDERR) should be empty. +# Than we run ISQL and query table with UTF8 data - several rows with varchar field which is filled by text +# from Hungarian, Norwegian and Greek languages. +# +# WARNING! 'Raw' database should be recreated in case of changing ODS structure, otherwise one may get: +# === +# File "c: +# irebirdqa +# btest +# btest.py", line 827, in run +# exec substitute_macros(self.test_script) in global_ns, local_ns +# +# File "", line 29, in +# +# File "c:\\python27\\lib\\subprocess.py", line 540, in check_call +# raise CalledProcessError(retcode, cmd) +# === +# +# Linux ICU info: +# $ rpm -qa | grep icu +# icu4j-eclipse-4.2.1-5.el6.x86_64 +# libicu-4.2.1-9.1.el6_2.x86_64 +# +# Database initially was created on LI-V3.0.0.32239, then re-created 20.10.2016 on LI-T4.0.0.419 because ODS was changed. +# Checked on OS = Windows XP: WI-V3.0.1.32570, WI-T4.0.0.321 +# 20.10.2016: checked on WI-T4.0.0.420 +# 22.04.2020: checked on WI-T4.0.0.1920 - updated .fdb because of new system tables. +# +# tracker_id: CORE-4571 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import zipfile +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # Obtain ODS major version: +# cur1 = db_conn.cursor() +# cur1.execute("select mon$ods_major as ods from mon$database") +# for row in cur1: +# ods = str(row[0]) +# db_conn.close() +# +# zf = zipfile.ZipFile( os.path.join(context['files_location'],'core_4571.zip') ) +# tmpfdb = 'core_4571-ods'+ods+'.fdb' +# zf.extract( tmpfdb, '$(DATABASE_LOCATION)') +# zf.close() +# +# tmpfdb='$(DATABASE_LOCATION)'+tmpfdb +# +# f_svc_rpr=open( os.path.join(context['temp_directory'],'tmp_icu_repair_4571.log'), 'w') +# subprocess.check_call(["fbsvcmgr","localhost:service_mgr", +# "action_repair", +# "dbname",tmpfdb, +# "rpr_icu"], +# stdout=f_svc_rpr, +# stderr=subprocess.STDOUT) +# f_svc_rpr.close() +# +# sqltxt='''set list on; select id, numb from wares order by numb;''' +# +# f_sql_log=open( os.path.join(context['temp_directory'],'tmp_isql_4571.log'), 'w') +# f_sql_log.close() +# runProgram('isql', ['localhost:'+tmpfdb,'-q', '-o',f_sql_log.name], sqltxt) +# +# with open( f_svc_rpr.name,'r') as f: +# print(f.read()) +# f.close() +# +# with open( f_sql_log.name,'r') as f: +# print(f.read()) +# f.close() +# +# # Checked result on Linux: +# # ID NUMB +# # == =================== +# # 3 bærende +# # 1 lengéscsillapító +# # 6 støtdemper +# # 2 viselő +# # 5 αμορτισέρ +# # 4 ρουλεμάν +# +# ##################################################################### +# # Cleanup: +# +# # do NOT remove this pause otherwise some of logs will not be enable for deletion and test will finish with +# # Exception raised while executing Python test script. exception: WindowsError: 32 +# time.sleep(1) +# +# f_list=[f_svc_rpr, f_sql_log] +# for i in range(len(f_list)): +# if os.path.isfile(f_list[i].name): +# os.remove(f_list[i].name) +# os.remove(tmpfdb) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 3 + NUMB bærende + ID 1 + NUMB lengéscsillapító + ID 6 + NUMB støtdemper + ID 2 + NUMB viselő + ID 5 + NUMB αμορτισέρ + ID 4 + NUMB ρουλεμάν + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_4571_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4572.py b/tests/bugs/test_core_4572.py new file mode 100644 index 00000000..23c35ac2 --- /dev/null +++ b/tests/bugs/test_core_4572.py @@ -0,0 +1,68 @@ +#coding:utf-8 +# +# id: bugs.core_4572 +# title: Regression: Incorrect result in subquery with aggregate +# decription: +# tracker_id: CORE-4572 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create or alter function fn_multiplier ( a_val int, a_times int ) returns bigint + as + begin + return a_val * a_times; + end + ^ + + create or alter procedure sp_multiplier (a_val int, a_times int ) + returns (result bigint) + as + begin + result = a_val * a_times; + end + ^ + set term ;^ + commit; + + -- Confirmed on WI-T3.0.0.31374 Firebird 3.0 Beta 1: + -- Statement failed, SQLSTATE = 39000 + -- invalid request BLR at offset 50 + -- -function FN_MULTIPLIER could not be matched + select fn_multiplier(191) as t from rdb$database; + + execute procedure sp_multiplier(191); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 07001 + Dynamic SQL Error + -Input parameter mismatch for function FN_MULTIPLIER + + Statement failed, SQLSTATE = 07001 + Dynamic SQL Error + -Input parameter mismatch for procedure SP_MULTIPLIER + """ + +@pytest.mark.version('>=3.0') +def test_core_4572_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_4574.py b/tests/bugs/test_core_4574.py new file mode 100644 index 00000000..cb775aa9 --- /dev/null +++ b/tests/bugs/test_core_4574.py @@ -0,0 +1,67 @@ +#coding:utf-8 +# +# id: bugs.core_4574 +# title: Regression: Incorrect result in subquery with aggregate +# decription: +# 30.10.2019. NB: new datatype in FB 4.0 was introduces: numeric(38,0). +# It can lead to additional ident of values when we show them in form "SET LIST ON", +# so we have to ignore all internal spaces - see added 'substitution' section below. +# Checked on: +# 4.0.0.1635 SS: 1.197s. +# 3.0.5.33182 SS: 0.848s. +# 2.5.9.27146 SC: 0.188s. +# +# tracker_id: CORE-4574 +# min_versions: ['2.1.7'] +# versions: 2.1.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1.7 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + with + a as ( + select 1 id from rdb$database + union all + select 2 from rdb$database + union all + select 3 from rdb$database + ), + b as ( + select 1 id1, null id2 from rdb$database + union all + select 2, null from rdb$database + union all + select 3, null from rdb$database + ) + select + sum((select count(*) from B where B.ID1 = A.ID)) s1 + ,sum((select count(*) from B where B.ID2 = A.ID)) s2 + -- must be (3,0) (FB2.5) , but not (3,3) (FB3.0) + from a; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + S1 3 + S2 0 + """ + +@pytest.mark.version('>=2.1.7') +def test_core_4574_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4578.py b/tests/bugs/test_core_4578.py new file mode 100644 index 00000000..f31281d6 --- /dev/null +++ b/tests/bugs/test_core_4578.py @@ -0,0 +1,91 @@ +#coding:utf-8 +# +# id: bugs.core_4578 +# title: INPUT file not properly closed +# decription: +# Confirmed bug in ISQL 3.0.0.31374 (Beta1 release): script that has been performed by "IN" command +# is NOT deleted by "shell del ..." and can be used again, so the output will be: +# ID 1 +# mp_4578_in.sql +# ID 1 +# +# +# tracker_id: CORE-4578 +# min_versions: ['2.5.4'] +# versions: 2.5.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.4 +# resources: None + +substitutions_1 = [('Unable to open.*', 'Unable to open')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import time +# +# db_conn.close() +# +# txt_in = '''set list on; +# recreate table test(id int); +# commit; +# insert into test values(1); +# select id from test; +# commit; +# ''' +# tmp_input_sql=open( os.path.join(context['temp_directory'],'tmp_4578_in.sql'), 'w') +# tmp_input_sql.write(txt_in) +# tmp_input_sql.close() +# +# sql_main_file=open( os.path.join(context['temp_directory'],'tmp_4578_go.sql'), 'w') +# +# sql_main_file.write("set bail on;\\n" ) +# sql_main_file.write("in "+tmp_input_sql.name+";\\n" ) +# sql_main_file.write("shell del "+tmp_input_sql.name+" 2>nul;\\n" ) +# sql_main_file.write("in "+tmp_input_sql.name+";\\n" ) +# +# sql_main_file.close() +# +# sql_main_log=open( os.path.join(context['temp_directory'],'tmp_isql_4578.log'), 'w') +# p_isql = subprocess.call([ "isql" , dsn, "-user" , "SYSDBA" , "-password", "masterkey", "-i", sql_main_file.name ], stdout=sql_main_log, stderr=subprocess.STDOUT) +# sql_main_log.close() +# +# time.sleep(1) +# +# with open( sql_main_log.name,'r') as f: +# print(f.read()) +# f.close() +# +# # do NOT remove this pause otherwise log of trace will not be enable for deletion and test will finish with +# # Exception raised while executing Python test script. exception: WindowsError: 32 +# time.sleep(1) +# +# os.remove(sql_main_log.name) +# os.remove(sql_main_file.name) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + Unable to open + """ + +@pytest.mark.version('>=2.5.4') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_4578_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4582.py b/tests/bugs/test_core_4582.py new file mode 100644 index 00000000..cf62ae79 --- /dev/null +++ b/tests/bugs/test_core_4582.py @@ -0,0 +1,124 @@ +#coding:utf-8 +# +# id: bugs.core_4582 +# title: Within linger period one can not change some database properties +# decription: +# Confirmed on WI-T3.0.0.31374 Beta 1: running GFIX -buffers N has NO affect if this is done within linger period +# Results for 22.05.2017: +# fb30Cs, build 3.0.3.32725: OK, 4.703ss. +# fb30SC, build 3.0.3.32725: OK, 2.469ss. +# FB30SS, build 3.0.3.32725: OK, 1.922ss. +# FB40CS, build 4.0.0.645: OK, 5.047ss. +# FB40SC, build 4.0.0.645: OK, 2.703ss. +# FB40SS, build 4.0.0.645: OK, 2.187ss. +# +# tracker_id: CORE-4582 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!:::MSG:::|buffers|before|after|Attributes).)*$', ''), ('Page buffers([\t]|[ ])+', 'Page buffers '), ('Attributes([\t]|[ ])+', 'Attributes '), ('N/A', 'YES')] + +init_script_1 = """ + -- Result of this test on WI-T3.0.0.31374 Beta 1: + -- Expected standard output from Python does not match actual output. + -- - GFIX could change buffers ? => YES + -- ? ^^^ + -- + GFIX could change buffers ? => NO! + -- ? ^^^ + + set term ^; + -- Aux procedure that determines: is current connection to SuperServer ? + -- If yes, returns current value of page buffers, otherwise (SC/CS) always return -1, in order to + -- make final output = 'N/A' and give 'substitutions' section handle this case as acceptable. + create or alter procedure sp_get_buff returns(mon_buffers int) as + begin + mon_buffers = -1; + if ( exists( select * from mon$attachments where mon$user containing 'cache writer' and mon$system_flag = 1 ) ) + then + select mon$page_buffers from mon$database into mon_buffers; + + suspend; + + end + ^ + set term ;^ + commit; + recreate table log(buf_before int, buf_after int); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.close() +# +# script=''' +# insert into log(buf_before) select mon_buffers from sp_get_buff; +# commit; +# alter database set linger to 15; +# commit; +# set list on; +# select rdb$linger as ":::MSG::: linger_time" from rdb$database; +# ''' +# +# print (':::MSG::: Starting ISQL setting new value for linger...') +# runProgram('isql',[dsn],script) +# print (':::MSG::: ISQL setting new value for linger finished.') +# +# print (':::MSG::: Starting GFIX setting new value for page buffers...') +# runProgram('gfix',[dsn,'-buffers','3791']) +# runProgram('gfix',[dsn,'-w','async']) +# runProgram('gfix',[dsn,'-mode','read_only']) +# runProgram('gfix',[dsn,'-sh','single', '-at', '20']) +# runProgram('gstat',['-h',dsn]) +# runProgram('gfix',[dsn,'-online']) +# runProgram('gfix',[dsn,'-mode','read_write']) +# print (':::MSG::: GFIX setting new value for page buffers finished.') +# print (':::MSG::: Starting ISQL for extract old and new value of page buffers...') +# script=''' +# set list on; +# update log set buf_after = (select mon_buffers from sp_get_buff); +# commit; +# select iif( g.buf_before > 0, +# iif( g.buf_before is distinct from g.buf_after, 'YES', 'NO!' ), +# 'N/A' +# ) as "GFIX could change buffers ? =>" +# from log g; +# ''' +# runProgram('isql',[dsn],script) +# print (':::MSG::: ISQL for extract old and new value of page finished.') +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + :::MSG::: Starting ISQL setting new value for linger... + :::MSG::: linger_time 15 + :::MSG::: ISQL setting new value for linger finished. + :::MSG::: Starting GFIX setting new value for page buffers... + Page buffers 3791 + Attributes single-user maintenance, read only + :::MSG::: GFIX setting new value for page buffers finished. + :::MSG::: Starting ISQL for extract old and new value of page buffers... + GFIX could change buffers ? => YES + :::MSG::: ISQL for extract old and new value of page finished. + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4582_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4585.py b/tests/bugs/test_core_4585.py new file mode 100644 index 00000000..f9ecc839 --- /dev/null +++ b/tests/bugs/test_core_4585.py @@ -0,0 +1,52 @@ +#coding:utf-8 +# +# id: bugs.core_4585 +# title: Can't create column check constraint when the column is domain based +# decription: +# tracker_id: CORE-4585 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create domain x int; + create table test( + x x constraint test_x_chk check(x>0) + ); + insert into test(x) values(1); + insert into test(x) values(0); + set list on; + select * from test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + X 1 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 23000 + Operation violates CHECK constraint TEST_X_CHK on view or table TEST + -At trigger 'CHECK_1' + """ + +@pytest.mark.version('>=3.0') +def test_core_4585_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4590.py b/tests/bugs/test_core_4590.py new file mode 100644 index 00000000..4994ed0e --- /dev/null +++ b/tests/bugs/test_core_4590.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: bugs.core_4590 +# title: Change type of returning value of CHAR_LENGTH, BIT_LENGTH and OCTET_LENGTH of BLOBs to bigint +# decription: +# tracker_id: CORE-4590 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!sqltype).)*$', ''), ('[ ]+', ' '), ('[\t]*', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set sqlda_display; + set planonly; + select + char_length(rdb$description) clen + ,bit_length(rdb$description) blen + ,octet_length(rdb$description) olen + from rdb$database; + -- No more output of charset name for NON-text field, see: + -- http://sourceforge.net/p/firebird/code/61779 // 10.06.2015 + -- Enhance metadata display - show charset only for fields where it makes sense + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 01: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + 02: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + 03: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + """ + +@pytest.mark.version('>=3.0') +def test_core_4590_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4599.py b/tests/bugs/test_core_4599.py new file mode 100644 index 00000000..0207058c --- /dev/null +++ b/tests/bugs/test_core_4599.py @@ -0,0 +1,847 @@ +#coding:utf-8 +# +# id: bugs.core_4599 +# title: REPLACE function works incorrectly with multibyte charsets +# decription: Integral test for comparison latin-1 characters with diacritical marks and their ascii-equivalents, all kinds of string matching +# tracker_id: CORE-4599 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + with recursive + d as ( + select + -- The following is full list of latin-1 letters with diacritical marks + -- ***EXCEPT*** those which are enumerated in CORE-4739 and currently + -- do NOT pass comparison using accent insensitive collation: + -- Ø = U+00D8 // LATIN CAPITAL LETTER O WITH STROKE' (U+00D8), used in danish & iceland alphabets; + -- Ð = U+00D0 // LATIN CAPITAL LETTER ETH' (U+00D0), iceland + -- Ŀ = U+013F // LATIN CAPITAL LETTER L WITH MIDDLE DOT' (U+013F), catalone (valencian) + -- Ł = U+0141 // LATIN CAPITAL LETTER L WITH STROKE' (U+0141), polish + cast( 'ĄÁÃÀÅĂÂÄÇĘÊĖÈËÉĢÏÍÎÌĽÑÒŐÕÔÖÓŞŠŢÚÙÛŰÜŸÝŹŻ' as varchar(80) character set utf8) collate unicode_ci_ai utf8_chr + ,cast( 'AAAAAAAACEEEEEEGIIIILNOOOOOOSSTUUUUUYYZZ' as varchar(80) character set utf8) collate unicode_ci_ai ascii_up + ,cast( 'aaaaaaaaceeeeeegiiiilnoooooosstuuuuuyyzz' as varchar(80) character set utf8) collate unicode_ci_ai ascii_lo + from rdb$database + ) + ,r as(select 1 i from rdb$database union all select r.i+1 from r where r.i < 100) + ,e as( + select + substring(d.utf8_chr from r.i for 1) utf8_chr + ,substring(d.ascii_up from r.i for 1) ascii_up + ,substring(d.ascii_lo from r.i for 1) ascii_lo + from d join r on r.i <= char_length(d.utf8_chr) + ) + ,f as ( + select + e.utf8_chr as utf_char + ,e.ascii_up as ascii_char + ------------------------------------------------------------------ + ,iif( e.utf8_chr = e.ascii_up, 1, 0 ) equal_test_up + ,iif( position(e.ascii_up, e.utf8_chr) >0 , 1, 0 ) position_test_up + ,iif( e.utf8_chr starting with e.ascii_up, 1, 0 ) start_with_test_up + ,iif( e.utf8_chr like e.ascii_up, 1, 0 ) like_test_up + ,iif( e.utf8_chr similar to e.ascii_up, 1, 0 ) similar_to_ascii_test_up + ,iif( e.utf8_chr similar to '[[:ALPHA:]]', 1, 0 ) similar_to_alpha_test_up + ,'.'||replace(e.utf8_chr, e.ascii_up,'*')||'.' replace_utf8_to_ascii_up + ,iif( overlay(e.utf8_chr placing e.ascii_up from 1) = e.ascii_up, 1, 0 ) overlay_utf8_to_ascii_up + ----------------------------------------------------------------- + ,iif( e.utf8_chr = e.ascii_lo, 1, 0 ) equal_test_lo + ,iif( position(e.ascii_lo, e.utf8_chr) >0 , 1, 0 ) position_test_lo + ,iif( e.utf8_chr starting with e.ascii_lo, 1, 0 ) start_with_test_lo + ,iif( e.utf8_chr like e.ascii_lo, 1, 0 ) like_test_lo + ,iif( e.utf8_chr similar to e.ascii_lo, 1, 0 ) similar_to_ascii_test_lo + ,iif( e.utf8_chr similar to '[[:lower:]]', 1, 0 ) similar_to_alpha_test_lo + ,'.'||replace(e.utf8_chr, e.ascii_lo,'*')||'.' replace_utf8_to_ascii_lo + ,iif( overlay(e.utf8_chr placing e.ascii_lo from 1) = e.ascii_lo, 1, 0) overlay_utf8_to_ascii_lo + from e + ) + select * + from f + order by utf_char + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + UTF_CHAR Á + ASCII_CHAR A + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR À + ASCII_CHAR A + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Ă + ASCII_CHAR A + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR  + ASCII_CHAR A + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Å + ASCII_CHAR A + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Ä + ASCII_CHAR A + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR à + ASCII_CHAR A + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Ą + ASCII_CHAR A + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Ç + ASCII_CHAR C + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR É + ASCII_CHAR E + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR È + ASCII_CHAR E + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Ê + ASCII_CHAR E + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Ë + ASCII_CHAR E + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Ė + ASCII_CHAR E + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Ę + ASCII_CHAR E + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Ģ + ASCII_CHAR G + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Í + ASCII_CHAR I + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Ì + ASCII_CHAR I + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Î + ASCII_CHAR I + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Ï + ASCII_CHAR I + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Ľ + ASCII_CHAR L + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Ñ + ASCII_CHAR N + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Ó + ASCII_CHAR O + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Ò + ASCII_CHAR O + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Ô + ASCII_CHAR O + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Ö + ASCII_CHAR O + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Ő + ASCII_CHAR O + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Õ + ASCII_CHAR O + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Š + ASCII_CHAR S + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Ş + ASCII_CHAR S + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Ţ + ASCII_CHAR T + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Ú + ASCII_CHAR U + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Ù + ASCII_CHAR U + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Û + ASCII_CHAR U + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Ü + ASCII_CHAR U + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Ű + ASCII_CHAR U + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Ý + ASCII_CHAR Y + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Ÿ + ASCII_CHAR Y + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Ź + ASCII_CHAR Z + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + + UTF_CHAR Ż + ASCII_CHAR Z + EQUAL_TEST_UP 1 + POSITION_TEST_UP 1 + START_WITH_TEST_UP 1 + LIKE_TEST_UP 1 + SIMILAR_TO_ASCII_TEST_UP 1 + SIMILAR_TO_ALPHA_TEST_UP 1 + REPLACE_UTF8_TO_ASCII_UP .*. + OVERLAY_UTF8_TO_ASCII_UP 1 + EQUAL_TEST_LO 1 + POSITION_TEST_LO 1 + START_WITH_TEST_LO 1 + LIKE_TEST_LO 1 + SIMILAR_TO_ASCII_TEST_LO 1 + SIMILAR_TO_ALPHA_TEST_LO 1 + REPLACE_UTF8_TO_ASCII_LO .*. + OVERLAY_UTF8_TO_ASCII_LO 1 + """ + +@pytest.mark.version('>=2.5.3') +def test_core_4599_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4604.py b/tests/bugs/test_core_4604.py new file mode 100644 index 00000000..d42fa0c3 --- /dev/null +++ b/tests/bugs/test_core_4604.py @@ -0,0 +1,113 @@ +#coding:utf-8 +# +# id: bugs.core_4604 +# title: EXECUTE STATEMENT rise varchar char_length() size +# decription: +# Checked on: +# 4.0.0.1635 SS: 1.006s. +# 4.0.0.1633 CS: 1.389s. +# 3.0.5.33180 SS: 0.677s. +# 3.0.5.33178 CS: 0.932s. +# 2.5.9.27119 SS: 0.189s. +# 2.5.9.27146 SC: 0.192s. +# +# tracker_id: CORE-4604 +# min_versions: ['2.5.4'] +# versions: 2.5.4 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set term ^; + execute block returns (str_size integer) + as + declare variable tmp_guid varchar(38); + declare variable tmp_sqltext varchar(300); + declare v_dbname type of column mon$database.mon$database_name; + declare v_usr varchar(31) = 'SYSDBA'; + declare v_pwd varchar(31) = 'masterkey'; + begin + + v_dbname = 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME'); + + --------------------------------------------------------------- + + tmp_guid = uuid_to_char(gen_uuid()); + + str_size = char_length(tmp_guid); + suspend; + + --------------------------------------------------------------- + + tmp_sqltext = 'select ''' || tmp_guid || ''' from rdb$database'; + + execute statement (:TMP_SQLTEXT) + into :tmp_guid; + + str_size = char_length(tmp_guid); + suspend; + + --------------------------------------------------------------- + + execute statement (:TMP_SQLTEXT) + on external v_dbname as user v_usr password v_pwd + into :tmp_guid; + + str_size = char_length(tmp_guid); + + -- Confirmed on WI-T3.0.0.31374 Firebird 3.0 Beta 1/tcp (csprog)/P13 + -- STR_SIZE 36 + -- STR_SIZE 36 + -- STR_SIZE 144 + + 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + STR_SIZE 36 + STR_SIZE 36 + STR_SIZE 36 + """ + +@pytest.mark.version('>=2.5.4') +def test_core_4604_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4607.py b/tests/bugs/test_core_4607.py new file mode 100644 index 00000000..753dbf0b --- /dev/null +++ b/tests/bugs/test_core_4607.py @@ -0,0 +1,78 @@ +#coding:utf-8 +# +# id: bugs.core_4607 +# title: Add support for having more than one UserManager in firebird.conf and use them from SQL +# decription: +# Line "UserManager = Srp,..." has been added since ~MAR-2018 in firebird.conf before every fbt_run launch. +# Initial attempt to use Srp failed for following COREs tests: 2307, 3365, 4200, 4301, 4469 - and error +# was the same for all of them: +# === +# -Install incomplete, please read chapter "Initializing security +# database" in Quick Start Guide +# === +# (reply from dimitr, letter 31.05.2015 17:44). +# +# Checked on: +# fb30Cs, build 3.0.4.32972: OK, 0.844s. +# FB30SS, build 3.0.4.32988: OK, 1.203s. +# FB40CS, build 4.0.0.955: OK, 2.016s. +# FB40SS, build 4.0.0.1008: OK, 1.328s. +# +# tracker_id: CORE-4607 +# min_versions: ['3.0.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + create view v_test as + select sec$user_name, sec$plugin + from sec$users + where upper(sec$user_name) starting with upper('tmp$c4607') + order by 1,2 + ; + commit; + create or alter user tmp$c4607_leg password '123' using plugin Legacy_UserManager; + create or alter user tmp$c4607_srp password '456' using plugin Srp; + commit; + select * from v_test; + commit; + drop user tmp$c4607_leg using plugin Legacy_UserManager; + drop user tmp$c4607_srp using plugin Srp; + commit; + select * from v_test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + SEC$USER_NAME TMP$C4607_LEG + SEC$PLUGIN Legacy_UserManager + + SEC$USER_NAME TMP$C4607_SRP + SEC$PLUGIN Srp + + Records affected: 2 + + Records affected: 0 + """ + +@pytest.mark.version('>=3.0') +def test_core_4607_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4618.py b/tests/bugs/test_core_4618.py new file mode 100644 index 00000000..6dd55306 --- /dev/null +++ b/tests/bugs/test_core_4618.py @@ -0,0 +1,176 @@ +#coding:utf-8 +# +# id: bugs.core_4618 +# title: Rollback doesn`t undo changes when MERGE statement updates the same target rows multiple times and PLAN MERGE is used +# decription: +# Checked (again, 07.06.2020) on 3.0.6.33296. +# +# 07.06.2020. NOTE: separate section for FB 4.x was added since fix for core-2274 issued: +# MERGE can not change the same record multiple times. +# For this reason we have to check only presense of ERROR in 4.x and that result is the same after merge and rollback. +# Checked on 4.0.0.2022 +# +# tracker_id: CORE-4618 +# min_versions: ['3.0'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + execute block as begin + begin execute statement 'create sequence g'; when any do begin end end + end + ^ set term ;^ + commit; + alter sequence g restart with 0; + commit; + recreate table t(id int, x int, y int); + commit; + insert into t(id) select gen_id(g,1) from rdb$types rows 3; + update t set x=mod(id,2), y=mod(id,3); + commit; + + select 'before_merge' msg, t.* from t; + + --set plan on; + merge into t + using t s + on t.x=s.x + when matched then update set t.x = t.x+s.y, t.y = t.y - s.x; + set plan off; + + select 'after_merge' msg, t.* from t; + + rollback; + + select 'after_rollback' msg, t.* from t; + + -- ::: NB ::: Seems that trouble was NOT only because of PLAN MERGE. + -- Compare with WI-T3.0.0.31374 Firebird 3.0 Beta 1 - here HASH also is used! + -- MSG ID X Y + -- ============ ============ ============ ============ + -- before_merge 1 1 1 + -- before_merge 2 0 2 + -- before_merge 3 1 0 + -- + -- PLAN HASH (T NATURAL, S NATURAL) + -- + -- MSG ID X Y + -- =========== ============ ============ ============ + -- after_merge 1 2 -1 + -- after_merge 2 2 2 + -- after_merge 3 2 -2 + -- + -- MSG ID X Y + -- ============== ============ ============ ============ + -- after_rollback 1 2 -255 + -- after_rollback 2 0 2 + -- after_rollback 3 2 0 + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG ID X Y + ============ ============ ============ ============ + before_merge 1 1 1 + before_merge 2 0 2 + before_merge 3 1 0 + + MSG ID X Y + =========== ============ ============ ============ + after_merge 1 2 0 + after_merge 2 2 2 + after_merge 3 2 -1 + + MSG ID X Y + ============== ============ ============ ============ + after_rollback 1 1 1 + after_rollback 2 0 2 + after_rollback 3 1 0 + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_core_4618_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [('[ \t]+', ' '), ('=', '')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + recreate table test(id int, x int, y int); + create descending index test_x_dec on test(x); + commit; + insert into test(id, x, y) values(1, 1, 1); + insert into test(id, x, y) values(2, 0, 2); + insert into test(id, x, y) values(3, 1, 0); + commit; + + select 'before_merge' msg, t.* from test t; + + merge into test t + using test s on t.x=s.x + when matched then update set t.x = t.x+s.y, t.y = t.y - s.x; + + select 'after_merge' msg, t.* from test t; + rollback; + select 'after_rollback' msg, t.* from test t; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + MSG ID X Y + ============ ============ ============ ============ + before_merge 1 1 1 + before_merge 2 0 2 + before_merge 3 1 0 + + + MSG ID X Y + =========== ============ ============ ============ + after_merge 1 1 1 + after_merge 2 0 2 + after_merge 3 1 0 + + + MSG ID X Y + ============== ============ ============ ============ + after_rollback 1 1 1 + after_rollback 2 0 2 + after_rollback 3 1 0 + + """ +expected_stderr_2 = """ + Statement failed, SQLSTATE = 21000 + Multiple source records cannot match the same target during MERGE + """ + +@pytest.mark.version('>=4.0') +def test_core_4618_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_expected_stderr == act_2.clean_stderr + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/bugs/test_core_4622.py b/tests/bugs/test_core_4622.py new file mode 100644 index 00000000..0ff2bea4 --- /dev/null +++ b/tests/bugs/test_core_4622.py @@ -0,0 +1,75 @@ +#coding:utf-8 +# +# id: bugs.core_4622 +# title: Regression: Trigger with UPDATE OR INSERT statement and IIF() not working as expected +# decription: +# tracker_id: CORE-4622 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + execute block as + begin + execute statement 'drop trigger v_test_bu'; + when any do begin end + end + ^ + set term ;^ + commit; + + create or alter view v_test as select 1 id from rdb$database; + commit; + ------------------------------------------------------------- + recreate table test ( + id integer not null, + a integer, + b integer, + constraint pk_test primary key (id) + ); + commit; + insert into test values(1, 100, 200); + commit; + + create or alter view v_test as + select id, a, b from test; + commit; + + set term ^; + create or alter trigger v_test_bu for v_test + active before update position 0 + as + begin + -- Confirmed on WI-T3.0.0.31374 Firebird 3.0 Beta 1: + -- Statement failed, SQLSTATE = HY000 + -- invalid request BLR at offset 51 + -- -undefined variable number + update or insert into test ( id , a , b) + values ( iif( mod( new.id,2)=0, -new.id, new.id ), new.a, new.b) + matching( id ); + end + ^ + set term ;^ + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5') +def test_core_4622_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_4623.py b/tests/bugs/test_core_4623.py new file mode 100644 index 00000000..c85e65d4 --- /dev/null +++ b/tests/bugs/test_core_4623.py @@ -0,0 +1,67 @@ +#coding:utf-8 +# +# id: bugs.core_4623 +# title: Regression: SP "Domain" and "Type Of" based variables referring BLOB with sub_type < 0 no longer work +# decription: +# tracker_id: CORE-4623 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter procedure sp_test as begin end; + recreate table test (id int); + commit; + set term ^; + execute block as + begin + execute statement 'drop domain dm_01'; + when any do begin end + end + ^ + set term ;^ + commit; + + create domain dm_01 as blob sub_type -32768 segment size 32000; + recreate table test (b_field dm_01); + commit; + + set term ^; + create or alter procedure sp_test ( + b01 blob sub_type -32768 segment size 32000, + b02 type of column test.b_field, + b03 dm_01 + ) as + begin + end + ^ + create or alter trigger test_bi0 for test active before insert position 0 as + declare b01 blob sub_type -32768 segment size 32000; + declare b02 type of column test.b_field; + declare b03 dm_01; + begin + end + ^ + set term ;^ + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5') +def test_core_4623_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_4634.py b/tests/bugs/test_core_4634.py new file mode 100644 index 00000000..aa0e75d7 --- /dev/null +++ b/tests/bugs/test_core_4634.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: bugs.core_4634 +# title: Regression: ORDER BY via an index + WHERE clause: error "no current record for fetch operation" +# decription: +# tracker_id: CORE-4634 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='employee-ods12.fbk', init=init_script_1) + +test_script_1 = """ + -- Confirmed for WI-T3.0.0.31374 Firebird 3.0 Beta 1: + -- Statement failed, SQLSTATE = 22000 + -- no current record for fetch operation + set list on; + select * + from sales + where (order_status like '1%' or order_status like '%1%') + order by order_status + rows 1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +def test_core_4634_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_4645.py b/tests/bugs/test_core_4645.py new file mode 100644 index 00000000..49edd5a0 --- /dev/null +++ b/tests/bugs/test_core_4645.py @@ -0,0 +1,63 @@ +#coding:utf-8 +# +# id: bugs.core_4645 +# title: internal Firebird consistency check (cannot find tip page (165), file: tra.cpp line: 2375) +# decription: +# Both STDOUT and STDERR in this test should be empty. +# Confirmed: +# 1) bugcheck exception on 3.0.0.32378; 4.0.0.98: +# Statement failed, SQLSTATE = XX000 +# internal Firebird consistency check (cannot find tip page (165), file: tra.cpp line: 2303) +# Statement failed, SQLSTATE = XX000 +# internal Firebird consistency check (can't continue after bugcheck) +# 2) normal work on 3.0.0.32471; 4.0.0.127. +# +# tracker_id: CORE-4645 +# min_versions: ['2.5'] +# versions: 2.5.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# db_conn.close() +# runProgram('gfix',[dsn,'-user',user_name,'-pas',user_password,'-mode','read_only']) +# script=''' +# commit; +# set transaction read committed; +# set term ^; +# execute block as +# declare n int = 20000; +# begin +# while (n>0) do +# in autonomous transaction do +# select :n-1 from rdb$database into n; +# end +# ^ +# set term ;^ +# commit; +# ''' +# runProgram('isql',[dsn,'-user',user_name,'-password',user_password],script) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.6') +@pytest.mark.xfail +def test_core_4645_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4648.py b/tests/bugs/test_core_4648.py new file mode 100644 index 00000000..108e5fe3 --- /dev/null +++ b/tests/bugs/test_core_4648.py @@ -0,0 +1,94 @@ +#coding:utf-8 +# +# id: bugs.core_4648 +# title: no permission for CREATE access to DATABASE (for RDB$ADMIN) +# decription: +# tracker_id: CORE-4648 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + set wng off; + create or alter user tmp$c4648 password '123' revoke admin role; + commit; + revoke all on all from tmp$c4648; + -- 'create ... grant admin role' or 'grant rdb$admin' are NOT neccessary + -- for enabling to creating database by non-sysdba user: + grant create database to user tmp$c4648; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# +# print ('Starting backup...') +# fbk = os.path.join(context['temp_directory'],'tmp4648.fbk') +# fdn = 'localhost:'+os.path.join(context['temp_directory'],'tmp4648.tmp') +# runProgram('gbak',['-b','-user',user_name,'-password',user_password,dsn,fbk]) +# print ('Backup finished.') +# print ('Starting restore using NON sysdba user account...') +# runProgram('gbak',['-rep','-user','TMP$C4648','-password','123',fbk,fdn]) +# print ('Restore using NON sysdba user account finished.') +# if os.path.isfile(fbk): +# print ('Delete backup file...') +# os.remove(fbk) +# print ('Backup file deleted.') +# +# script = ''' +# set list on; +# select +# a.mon$user as "Who am I:" +# ,left(a.mon$remote_protocol,3) as "Used protocol:" +# ,iif(m.mon$database_name containing 'tmp4648.tmp','YES','NO! ' || m.mon$database_name ) as "Connected to restored DB ?" +# ,m.mon$owner as "Owner of DB is:" +# from mon$attachments a, mon$database m +# where a.mon$attachment_id=current_connection; +# commit; +# drop database; +# ''' +# print ('Starting ISQL using NON sysdba user account...') +# runProgram('isql',[fdn,'-q','-user','tmp$c4648','-pas','123'],script) +# print ('ISQL using NON sysdba user account finished.') +# +# script='''revoke create database from user tmp$c4648; +# drop user tmp$c4648; +# commit; +# ''' +# runProgram('isql',[dsn,'-q','-user',user_name,'-password',user_password],script) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Starting backup... + Backup finished. + Starting restore using NON sysdba user account... + Restore using NON sysdba user account finished. + Delete backup file... + Backup file deleted. + Starting ISQL using NON sysdba user account... + Who am I: TMP$C4648 + Used protocol: TCP + Connected to restored DB ? YES + Owner of DB is: TMP$C4648 + ISQL using NON sysdba user account finished. + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4648_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4653.py b/tests/bugs/test_core_4653.py new file mode 100644 index 00000000..d8df3945 --- /dev/null +++ b/tests/bugs/test_core_4653.py @@ -0,0 +1,110 @@ +#coding:utf-8 +# +# id: bugs.core_4653 +# title: Crash on infinite mutual SP calls (instead of "Too many concurrent executions of the same request.") +# decription: 20150108: crach every even run, WI-T3.0.0.31529, Win XP SP3 +# tracker_id: CORE-4653 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', ''), ('line.*', ''), ('col.*', '')] + +init_script_1 = """ + set term ^; + create or alter procedure p03(a_i int) returns (z int) as + begin + z = 0 ; + suspend; + end^ + commit^ + + create or alter procedure p02(a_i int) returns (z int) as + begin + z = (select z from p03(:a_i)) + 1; + suspend; + end^ + commit^ + + create or alter procedure p03(a_i int) returns (z int) as + begin + z = (select z from p02(:a_i)) + 1; + suspend; + end^ + commit^ + + create or alter procedure p01(a_i int) returns (z int) as + begin + z = (select z from p02(:a_i)) + 1; + suspend; + end^ + commit^ + set term ;^ + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- 07.03.2015: updated expected_stderr - it was changed and now is identical in 2.5 & 3.0 + -- Old stderr: + -- Statement failed, SQLSTATE = HY001 + -- Stack overflow. The resource requirements of the runtime stack have exceeded the memory available to it. + + select * from p01(1); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Z + ============ + """ +expected_stderr_1 = """ + 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... + """ + +@pytest.mark.version('>=3.0') +def test_core_4653_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4665.py b/tests/bugs/test_core_4665.py new file mode 100644 index 00000000..94e0ee2e --- /dev/null +++ b/tests/bugs/test_core_4665.py @@ -0,0 +1,120 @@ +#coding:utf-8 +# +# id: bugs.core_4665 +# 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 } +# decription: +# tracker_id: CORE-4665 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test (id int, unit varchar(10), y int, z int); + commit; + delete from test; + + insert into test( id, unit, y, z) values (1, 'foo', 9999, 23636); + insert into test( id, unit, y, z) values (2, 'foo', 8888, 22520); + insert into test( id, unit, y, z) values (3, 'foo', 5555, 21822); + insert into test( id, unit, y, z) values (4, 'foo', 3333, 17682); + + insert into test( id, unit, y, z) values (5, 'fooo', 1111, 22); + insert into test( id, unit, y, z) values (6, 'fooo', 111, 222); + insert into test( id, unit, y, z) values (7, 'fooo', 11, 2222); + insert into test( id, unit, y, z) values (8, 'fooo', 1, 22222); + commit; + + create index test_unit_y_asc on test( unit, y ); + commit; + + set plan on; + + select 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 + from test t + where t.unit starting with 'foo' + order by t.y; + set plan off; + + commit; + drop index test_unit_y_asc; + commit; + + create descending index test_unit_y_desc on test( unit, y); + commit; + + set plan on; + select id, t.unit, t.y, t.z + from test t + where t.unit starting with 'foo' + order by t.y; + set plan off; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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 + """ + +@pytest.mark.version('>=3.0') +def test_core_4665_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4668.py b/tests/bugs/test_core_4668.py new file mode 100644 index 00000000..98b796af --- /dev/null +++ b/tests/bugs/test_core_4668.py @@ -0,0 +1,112 @@ +#coding:utf-8 +# +# id: bugs.core_4668 +# title: Select from mon$table_stats doesn`t work on SC and CS +# decription: +# tracker_id: CORE-4668 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter view v_stat as select 1 id from rdb$database; + recreate table t(id int, s varchar(36)); commit; + insert into t select row_number()over(), uuid_to_char(gen_uuid()) from rdb$types,rdb$types rows 2000; + commit; + create index t_s on t(s); + commit; + + create or alter view v_stat as + select + r.mon$record_inserts rec_ins + ,r.mon$record_updates rec_upd + ,r.mon$record_deletes rec_del + ,r.mon$record_backouts rec_bko + ,r.mon$record_purges rec_pur + ,r.mon$record_expunges rec_exp + ----------- + ,r.mon$record_seq_reads read_nat + ,r.mon$record_idx_reads read_idx + ,r.mon$record_rpt_reads read_rpt + ,r.mon$backversion_reads read_bkv + ,r.mon$fragment_reads read_frg + ------------ + ,a.mon$stat_id + from mon$record_stats r + join mon$table_stats t on r.mon$stat_id = t.mon$record_stat_id + join mon$attachments a on t.mon$stat_id = a.mon$stat_id + where + a.mon$attachment_id = current_connection + and t.mon$table_name = upper('t') + ; + commit; + + set list on; + + set count on; + select read_nat, read_idx, rec_ins, rec_upd, rec_del from v_stat; -- , rec_pur, rec_exp from v_stat; + set count off; + + --delete from t rows 1000; commit; -- purge/expunge: can`t get exact values in SS because of background GC thread! + + select count(*) from t + union all + select count(*) from t where s>='' + ; + + insert into t select row_number()over(), uuid_to_char(gen_uuid()) from rdb$types,rdb$types rows 500; + update t set s = null rows 100; + update t set s = null order by s rows 100; + delete from t rows 200; + delete from t order by s rows 200; + commit; + + set count on; + select read_nat, read_idx, rec_ins, rec_upd, rec_del from v_stat; -- , rec_pur, rec_exp from v_stat; + + -- Confirmed wrong result on WI-T3.0.0.31374 + -- Records affected: 0 + -- COUNT 2000 + -- COUNT 2000 + -- Records affected: 0 + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + READ_NAT 0 + READ_IDX 0 + REC_INS 2000 + REC_UPD 0 + REC_DEL 0 + Records affected: 1 + + COUNT 2000 + COUNT 2000 + + READ_NAT 2300 + READ_IDX 2300 + REC_INS 2500 + REC_UPD 200 + REC_DEL 400 + Records affected: 1 + """ + +@pytest.mark.version('>=3.0') +def test_core_4668_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4673.py b/tests/bugs/test_core_4673.py new file mode 100644 index 00000000..a386aa6b --- /dev/null +++ b/tests/bugs/test_core_4673.py @@ -0,0 +1,69 @@ +#coding:utf-8 +# +# id: bugs.core_4673 +# title: Computed index based on a computed column stores NULL for all its keys +# decription: +# tracker_id: CORE-4673 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table tc( + id int primary key + ,x int + ,y int + ,z_expr computed by (x+y) + ,z_noex computed by (y) + ); + commit; + insert into tc values( 1, 101, 201 ); + commit; + create index tc_lpad_z_expr on tc computed by( lpad('' || z_expr , 10, 0) ); + + -- Added 2nd COMPUTED_BY index WITHOUT any expression, + -- see dimitr's issue in the ticket, 02/Feb/15 08:52 AM. + -- See also several samples (rus): + -- sql.ru/forum/actualutils.aspx?action=gotomsg&tid=945713&msg=12655568 + create index tc_lpad_z_noex on tc computed by( z_noex ); + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set plan on; + set list on; + select count(*) check_cnt from tc where tc.z_noex = 201 + union all + select count(*) from tc where 0 + tc.z_noex = 201 + union all + select count(*) cnt from tc where lpad('' || tc.z_expr, 10, 0) between '0000000302' and '0000000302' + union all + select count(*) from tc where '' || lpad('' || tc.z_expr, 10, 0) between '0000000302' and '0000000302'; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (TC INDEX (TC_LPAD_Z_NOEX), TC NATURAL, TC INDEX (TC_LPAD_Z_EXPR), TC NATURAL) + CHECK_CNT 1 + CHECK_CNT 1 + CHECK_CNT 1 + CHECK_CNT 1 + """ + +@pytest.mark.version('>=3.0') +def test_core_4673_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4675.py b/tests/bugs/test_core_4675.py new file mode 100644 index 00000000..979bc14a --- /dev/null +++ b/tests/bugs/test_core_4675.py @@ -0,0 +1,130 @@ +#coding:utf-8 +# +# id: bugs.core_4675 +# title: Conditions like WHERE = . do not use existing index +# decription: +# tracker_id: CORE-4675 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + commit; + set transaction no wait; + recreate table t1(id int primary key using index pk_t1_id, x int, y int); + commit; + + set transaction no wait; + recreate table t2(id int primary key using index pk_t2_id, x int, y int); + commit; + + insert into t1 + select r, mod(r, 10), (r/100)*100 + from ( + select row_number()over() r + from rdb$types a, (select 1 i from rdb$types rows 40) b + rows 1000 + ); + commit; + create index t1_x on t1(x); + commit; + + insert into t2 select * from t1; + commit; + + create index t2_x on t2(x); + commit; + """ + +db_1 = db_factory(from_backup='mon-stat-gathering-3_0.fbk', init=init_script_1) + +test_script_1 = """ + execute procedure sp_truncate_stat; + commit; + execute procedure sp_gather_stat; ------- catch statistics BEFORE measured statement(s) + commit; + + set transaction no wait; + set term ^; + execute block as + declare a_x int; + declare v_id int; + declare v_x int; + declare v_y int; + declare c_upd1 cursor for (select id, x, y from t1 where x = :a_x); + declare c_upd2 cursor for (select id, x, y from t2 where x = :a_x); + begin + a_x = 5; + + open c_upd1; + while (1=1) do begin + fetch c_upd1 into v_id, v_x, v_y; + if (row_count = 0) then leave; + update t1 v set y = c_upd1.x, x = c_upd1.y + where v.id = :v_id; ----------------- ::: key is specified by VARIABLE which has value from FETCH statement + end + close c_upd1; + + open c_upd2; + while (1=1) do begin + fetch c_upd2; -- into v_id, v_x, v_y; + if (row_count = 0) then leave; + update t2 v set y = c_upd2.x, x = c_upd2.y + where v.id = c_upd2.id; ------------- ::: key is specified by CURSOR field using "cursor name + dot + field" syntax + end + close c_upd2; + + end + ^ set term ;^ + rollback; + + execute procedure sp_gather_stat; ------- catch statistics AFTER measured statement(s) + commit; + + set list on; + set width table_name 31; + + -- Show results (differences of saved monitoring counters): + -- ======================================================== + + select v.table_name, v.natural_reads, v.indexed_reads + from v_agg_stat_tabs v + where upper(v.table_name) in ( upper('T1'), upper('T2') ); + + -- Output for WI-T6.3.0.31374 (Beta 1 official): + -- TABLE_NAME T1 + -- NATURAL_READS 0 + -- INDEXED_READS 200 + -- + -- TABLE_NAME T2 + -- NATURAL_READS 100000 <<<< this is bad and has been fixed in CORE_4675 + -- INDEXED_READS 100 + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TABLE_NAME T1 + NATURAL_READS 0 + INDEXED_READS 200 + + TABLE_NAME T2 + NATURAL_READS 0 + INDEXED_READS 200 + """ + +@pytest.mark.version('>=3.0') +def test_core_4675_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4678.py b/tests/bugs/test_core_4678.py new file mode 100644 index 00000000..93a4ab51 --- /dev/null +++ b/tests/bugs/test_core_4678.py @@ -0,0 +1,73 @@ +#coding:utf-8 +# +# id: bugs.core_4678 +# title: Regression: incorrect calculation of byte-length for view columns +# decription: +# tracker_id: CORE-4678 +# min_versions: ['2.5.4'] +# versions: 2.5.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table test(id int); + commit; + + set term ^; + execute block as + begin + execute statement 'drop sequence gen_memo_id'; + when any do begin end + end ^ + set term ;^ + commit; + + create generator gen_memo_id; + + recreate table test ( + id int not null, + memo blob sub_type 1 segment size 100 character set ascii + ); + create index memo_idx1 on test computed by (upper(trim(cast(substring(memo from 1 for 128) as varchar(128))))); + + set term ^ ; + create or alter trigger test_bi for test + active before insert position 0 + as + begin + if (new.id is null) then + new.id = gen_id(gen_memo_id,1); + end + ^ + set term ; ^ + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + insert into test(memo) values( 'foo-rio-bar' ); + rollback; + -- Confirmed on WI-V2.5.2.26540 (official release): + -- exception on ROLLBACK raises with text: + -- === + -- Statement failed, SQLSTATE = HY000 + -- BLOB not found + -- === + -- No reconnect is required, all can be done in one ISQL attachment. + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.4') +def test_core_4678_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_4684.py b/tests/bugs/test_core_4684.py new file mode 100644 index 00000000..db2f8df5 --- /dev/null +++ b/tests/bugs/test_core_4684.py @@ -0,0 +1,140 @@ +#coding:utf-8 +# +# id: bugs.core_4684 +# title: Error while preparing a complex query ("Too many Contexts of Relation/Procedure/Views. Maximum allowed is 256") +# decription: +# tracker_id: CORE-4684 +# min_versions: ['2.5'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table tdetl(id int primary key, pid int); + recreate table tmain(id int primary key, x int, constraint tmain_x_gtz check(x>0)); + commit; + alter table tdetl add constraint tdetl_fk foreign key(pid) references tmain(id) on delete cascade; + commit; + set term ^; + create or alter trigger tdetl_bi for tdetl active before insert as begin end ^ + create or alter trigger tdetl_ai for tdetl active after insert as begin end ^ + create or alter trigger tmain_bi for tmain inactive before insert as begin end ^ + create or alter trigger tmain_ai for tmain active after insert as begin end ^ + set term ;^ + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + with recursive + c as ( + select + rc.rdb$relation_name child_tab + ,rc.rdb$constraint_name child_fk + ,ru.rdb$const_name_uq parent_uk + ,rp.rdb$relation_name parent_tab + from rdb$relation_constraints rc + join rdb$ref_constraints ru on + rc.rdb$constraint_name = ru.rdb$constraint_name + and rc.rdb$constraint_type = 'FOREIGN KEY' + join rdb$relation_constraints rp + on ru.rdb$const_name_uq = rp.rdb$constraint_name + where rc.rdb$relation_name <> rp.rdb$relation_name + ) + ,d as( + select + 0 i + ,child_tab + ,child_fk + ,parent_uk + ,parent_tab + from c c0 + where not exists( select * from c cx where cx.parent_tab= c0.child_tab ) + + union all + + select + d.i+1 + ,c.child_tab + ,c.child_fk + ,c.parent_uk + ,c.parent_tab + from d + join c on d.parent_tab = c.child_tab + ) + ,e as( + select + i + ,child_tab + ,child_fk + ,parent_uk + ,parent_tab + ,(select max(i) from d) as mi + from d + ) + ,f as( + select distinct + 0 i + ,child_tab + from e where i=0 + + UNION DISTINCT + + select + 1 + ,child_tab + from (select child_tab from e where i>0 order by i) + + UNION DISTINCT + + select + 2 + ,parent_tab + from e + where i=mi + ) + ,t as( + select + rt.rdb$trigger_name trg_name -- f.child_tab, rt.rdb$trigger_name, rt.rdb$trigger_type + from f + join rdb$triggers rt on f.child_tab = rt.rdb$relation_name + where rt.rdb$system_flag=0 and rt.rdb$trigger_inactive=0 + ) + select 'alter trigger '||trim(trg_name)||' inactive' sql_expr + from t + union all + select 'delete from '||trim(child_tab) + from f + union all + select 'alter trigger '||trim(trg_name)||' active' + from t; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +alter trigger TDETL_BI inactive +alter trigger TDETL_AI inactive +alter trigger TMAIN_AI inactive +delete from TDETL +delete from TMAIN +alter trigger TDETL_BI active +alter trigger TDETL_AI active +alter trigger TMAIN_AI active + """ + +@pytest.mark.version('>=2.5') +def test_core_4684_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4690.py b/tests/bugs/test_core_4690.py new file mode 100644 index 00000000..51f942d3 --- /dev/null +++ b/tests/bugs/test_core_4690.py @@ -0,0 +1,197 @@ +#coding:utf-8 +# +# id: bugs.core_4690 +# title: DISTINCT vs non-DISTINCT affects the result of IN subquery +# decription: +# tracker_id: CORE-4690 +# min_versions: ['2.5.4'] +# versions: 2.5.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table comi_ingr (id int); + recreate table comidas(id int); + recreate table ingredientes(id int); + recreate table paises(id int); + commit; + + set term ^; + execute block as + begin + begin execute statement 'drop domain dcad30'; when any do begin end end + begin execute statement 'drop domain dcodingrediente'; when any do begin end end + begin execute statement 'drop domain dreal'; when any do begin end end + begin execute statement 'drop domain dtipoingre'; when any do begin end end + begin execute statement 'drop domain dcodpais'; when any do begin end end + begin execute statement 'drop domain dentero'; when any do begin end end + begin execute statement 'drop domain dcad50'; when any do begin end end + begin execute statement 'drop domain dcodcomida'; when any do begin end end + begin execute statement 'drop domain dfecha'; when any do begin end end + begin execute statement 'drop domain dcodcoming'; when any do begin end end + begin execute statement 'drop domain dcodreceta'; when any do begin end end + end + ^ + set term ;^ + commit; + + create domain dcad30 as varchar(30) default ''; + create domain dcodingrediente as integer; + create domain dreal as decimal(7, 2) default 0; + create domain dtipoingre as char(1) default 'v' check (value in ('v','a','m')); + create domain dcodpais as integer; + create domain dentero as integer default 0; + create domain dcad50 as varchar(50) default ''; + create domain dcodcomida as integer; + create domain dfecha as date; + create domain dcodcoming as integer; + create domain dcodreceta as integer; + commit; + + recreate table ingredientes ( + cod_ingrediente dcodingrediente not null, + nombre dcad30 not null, + tipo dtipoingre not null, + imp_unidad dreal not null, + constraint pk_ingredientes primary key (cod_ingrediente) + ); + + recreate table paises ( + cod_pais dcodpais not null, + nombre dcad30 not null, + n_habitantes dentero not null, + constraint pk_paises primary key (cod_pais) + ); + + recreate table comidas ( + cod_comida dcodcomida not null, + cod_pais dcodpais not null, + nombre dcad50 not null, + fecha_creacion dfecha not null, + precio dreal not null, + fecha_ult dfecha, + constraint pk_comidas primary key (cod_comida), + constraint fk_comidas1 foreign key (cod_pais) references paises(cod_pais) on update cascade + ); + + + recreate table comi_ingr ( + cod_comi_ingr dcodcoming not null, + cod_ingrediente dcodingrediente not null, + cod_comida dcodcomida not null, + n_unidades dreal not null, + constraint pk_comi_ingr primary key (cod_comi_ingr), + constraint fk_comi_ingr1 foreign key (cod_ingrediente) references ingredientes(cod_ingrediente) on update cascade, + constraint fk_comi_ingr2 foreign key (cod_comida) references comidas(cod_comida) on update cascade + ); + commit; + + insert into ingredientes values (1, 'tomate', 'v', 1); + insert into ingredientes values (2, 'sal', 'm', 0.5); + insert into ingredientes values (3, 'magro', 'a', 5); + insert into ingredientes values (4, 'pimiento verde', 'v', 0.8); + insert into ingredientes values (5, 'lomo', 'a', 6.5); + commit; + + + insert into paises values (1, 'espana', 48000000); + insert into paises values (2, 'marruecos', 33000000); + insert into paises values (3, 'eeuu', 300000000); + insert into paises values (4, 'francia', 66000000); + commit; + + + insert into comidas values (4, 1, 'migas', '2014-12-13', 3, null); + insert into comidas values (5, 3, 'chuletones a la brasa', '2015-02-01', 10, '2015-02-11'); + insert into comidas values (1, 1, 'estofado de cerdo', '2006-09-24', 7, '2014-11-06'); + insert into comidas values (2, 1, 'pisto', '2014-09-12', 4, '2014-12-09'); + insert into comidas values (3, 2, 'cuscus', '2014-09-12', 4.5, '2014-12-02'); + commit; + + + insert into comi_ingr values (8, 3, 5, 0.01); + insert into comi_ingr values (7, 2, 5, 1); + insert into comi_ingr values (1, 1, 1, 0.25); + insert into comi_ingr values (2, 3, 1, 1); + insert into comi_ingr values (3, 2, 1, 0.05); + insert into comi_ingr values (4, 1, 2, 0.5); + insert into comi_ingr values (5, 4, 2, 0.5); + insert into comi_ingr values (6, 2, 3, 0.01); + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select a.cod_ingrediente as ca, b.cod_ingrediente as cb + from ( + select * + from ingredientes i + where + i.cod_ingrediente < + all + ( + select cod_pais -- 2 3 4 + from paises + where nombre != 'espana' + ) + and + i.cod_ingrediente + in + ( + select ci.cod_ingrediente -- 1 3 2 1 4 + from comi_ingr ci + join comidas c on (ci.cod_comida=c.cod_comida) + join paises p on (p.cod_pais=c.cod_pais) + where p.nombre='espana' + ) + ) a + natural full join + ( + select i.* + from ingredientes i + where + i.cod_ingrediente < + all + ( + select cod_pais + from paises + where nombre != 'espana' + ) + and + i.cod_ingrediente + in + ( + select DISTINCT + ci.cod_ingrediente -- 1 2 3 4 + from comi_ingr ci + join comidas c on (ci.cod_comida=c.cod_comida) + join paises p on (p.cod_pais=c.cod_pais) + where p.nombre='espana' + ) + ) b + ; + set list off; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CA 1 + CB 1 + """ + +@pytest.mark.version('>=2.5.4') +def test_core_4690_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4693.py b/tests/bugs/test_core_4693.py new file mode 100644 index 00000000..e28c7e15 --- /dev/null +++ b/tests/bugs/test_core_4693.py @@ -0,0 +1,73 @@ +#coding:utf-8 +# +# id: bugs.core_4693 +# title: CTE Aliases ('Column unknown' when recursive CTE contain join with *alias* rather than table name) +# decription: +# tracker_id: CORE-4693 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table gd_goodgroup ( + id integer, + parent integer, + name varchar(20) + ); + commit; + + insert into gd_goodgroup(id, parent, name) values( 1, null, 'Big Brother'); + insert into gd_goodgroup(id, parent, name) values( 2, 1, 'Middle Manager #1'); + insert into gd_goodgroup(id, parent, name) values( 3, 1, 'Middle Manager #2'); + insert into gd_goodgroup(id, parent, name) values( 4, 2, 'Worker #1'); + insert into gd_goodgroup(id, parent, name) values( 5, 2, 'Worker #2'); + insert into gd_goodgroup(id, parent, name) values( 6, 3, 'Worker #3'); + commit; + + set list on; + + with recursive + group_tree as ( + select id, parent, name, cast('' as varchar(255)) as indent + from gd_goodgroup + where parent is null + + union all + + select g.id, g.parent, g.name, h.indent || rpad('', 2) + from gd_goodgroup g join group_tree h + on g.parent = h.id + ) + select gt.indent || gt.name as info + from group_tree gt; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + INFO Big Brother + INFO Middle Manager #1 + INFO Worker #1 + INFO Worker #2 + INFO Middle Manager #2 + INFO Worker #3 + """ + +@pytest.mark.version('>=2.5') +def test_core_4693_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4694.py b/tests/bugs/test_core_4694.py new file mode 100644 index 00000000..d274bfa5 --- /dev/null +++ b/tests/bugs/test_core_4694.py @@ -0,0 +1,62 @@ +#coding:utf-8 +# +# id: bugs.core_4694 +# title: "Column unknown" error while preparing a recursive query if the recursive part contains ALIASED datasource in the join with anchor table +# decription: Fixed on 3.0 since rev 60747, 2015-02-20 16:56:04 +# tracker_id: CORE-4694 +# min_versions: ['2.5.4'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table xcall_stack ( + xcall_id int + ,xcaller_id int + ); + commit; + + set planonly; + + with recursive + r as ( + select c.xcall_id + from xcall_stack c + where c.xcaller_id is null + + UNION ALL + + select + c.xcall_id + from xcall_stack c + join r + AS h -- <<<<<<<<<<<<<<<<<<<<<< ::: NB ::: `r` is aliased + on c.xcaller_id = h.xcall_id + ) + select r.xcall_id + from r; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (R C NATURAL, R C NATURAL) + """ + +@pytest.mark.version('>=3.0') +def test_core_4694_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4702.py b/tests/bugs/test_core_4702.py new file mode 100644 index 00000000..4da0d710 --- /dev/null +++ b/tests/bugs/test_core_4702.py @@ -0,0 +1,106 @@ +#coding:utf-8 +# +# id: bugs.core_4702 +# title: Regression: Join order in v3 is less optimal than in v2.x +# decription: +# tracker_id: CORE-4702 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table trial_line ( + code_trial_line integer not null, + code_trial integer not null + ); + + recreate table trial ( + code_trial integer not null, + code_prize integer not null, + bydate date + ); + + + recreate table prize ( + code_prize integer not null, + name varchar(70) not null + ); + commit; + + + insert into prize(code_prize, name) + with recursive t (n) as ( + select 1 from rdb$database + union all + select n+1 from t where n < 1000 + ) + select n+8000, '' from t; + commit; + + insert into trial(code_trial, code_prize, bydate) + with recursive t (n) as ( + select 1 from rdb$database + union all + select n+1 from t where n < 1000 + ) + select t1.n + (t2.n-1)*1000, mod(t1.n, 20)+8001, dateadd(t1.n day to date '01.01.2000') + from t t1, t t2 + where t1.n + (t2.n-1)*1000 < 100000; + commit; + + insert into trial_line(code_trial_line, code_trial) + with recursive t (n) as ( + select 1 from rdb$database + union all + select n+1 from t where n < 1000 + ) + select t1.n + (t2.n-1)*1000, mod(t1.n + (t2.n-1)*1000, 99998)+1 + from t t1, t t2 + where t1.n + (t2.n-1)*1000 < 150000; + commit; + + alter table trial add constraint pk_trial primary key (code_trial); + alter table prize add constraint pk_prize primary key (code_prize); + alter table trial_line add constraint pk_trial_line primary key (code_trial_line); + + alter table trial_line add constraint fk_trial_line_trial foreign key (code_trial) references trial (code_trial); + alter table trial add constraint fk_trial_prize foreign key (code_prize) references prize (code_prize); + + create index idx_bydate on trial(bydate); + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set planonly; + select count(*) + from + trial + join prize on prize.code_prize = trial.code_prize + join trial_line on trial_line.code_trial = trial.code_trial + where trial.bydate between date '01.01.2000' and date '31.12.2000'; + -- Confirmed ineffective plan in WI-T3.0.0.31374 Firebird 3.0 Beta 1: + -- PLAN JOIN (TRIAL INDEX (IDX_BYDATE), TRIAL_LINE INDEX (FK_TRIAL_LINE_TRIAL), PRIZE INDEX (PK_PRIZE)) + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN JOIN (TRIAL INDEX (IDX_BYDATE), PRIZE INDEX (PK_PRIZE), TRIAL_LINE INDEX (FK_TRIAL_LINE_TRIAL)) + """ + +@pytest.mark.version('>=3.0') +def test_core_4702_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4706.py b/tests/bugs/test_core_4706.py new file mode 100644 index 00000000..f21fe7bb --- /dev/null +++ b/tests/bugs/test_core_4706.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: bugs.core_4706 +# title: ISQL pads blob columns wrongly when the column alias has more than 17 characters +# decription: +# tracker_id: CORE-4706 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set blob all; + select cast('a' as blob) a, 1, cast('a' as blob) x2345678901234567890, 2 from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A CONSTANT X2345678901234567890 CONSTANT + 0:2 1 0:1 2 +A: +a +X2345678901234567890: +a + """ + +@pytest.mark.version('>=3.0') +def test_core_4706_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4707.py b/tests/bugs/test_core_4707.py new file mode 100644 index 00000000..7147cf8e --- /dev/null +++ b/tests/bugs/test_core_4707.py @@ -0,0 +1,209 @@ +#coding:utf-8 +# +# id: bugs.core_4707 +# title: Implement ability to validate tables and indices online (without exclusive access to database) +# decription: +# Checked on: 4.0.0.1635 SS: 7.072s; 4.0.0.1633 CS: 7.923s; 3.0.5.33180 SS: 6.599s; 3.0.5.33178 CS: 7.189s. 2.5.9.27119 SS: 5.951s; 2.5.9.27146 SC: 5.748s. +# +# tracker_id: CORE-4707 +# min_versions: ['2.5.5'] +# versions: 2.5.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.5 +# resources: None + +substitutions_1 = [('[\\d]{2}:[\\d]{2}:[\\d]{2}.[\\d]{2}', ''), ('Relation [\\d]{3,4}', 'Relation')] + +init_script_1 = """ + set term ^; + execute block as + begin + execute statement 'drop sequence g'; + when any do begin end + end^ + set term ;^ + commit; + create sequence g; + commit; + recreate table test1(id int, s varchar(1000)); + recreate table test2(id int primary key using index test2_pk, s varchar(1000), t computed by (s) ); + recreate table test3(id int); + commit; + + insert into test1(id, s) select gen_id(g,1), rpad('', 1000, gen_id(g,0) ) from rdb$types rows 100; + insert into test2(id, s) select id, s from test1; + commit; + + create index test2_s on test2(s); + create index test2_c on test2 computed by(s); + create index test2_t on test2 computed by(t); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import subprocess +# from subprocess import Popen +# import time +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # Obtain engine version: +# engine = str(db_conn.engine_version) # convert to text because 'float' object has no attribute 'startswith' +# db_file = db_conn.database_name +# db_conn.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() +# os.fsync(file_handle.fileno()) +# +# file_handle.close() +# +# #-------------------------------------------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# +# # Following script will hang for sevral seconds (see 'lock timeout' argument - and this will serve as pause +# # during which we can launch fbsvcmgr to validate database: +# lock_sql=''' +# set term ^; +# execute block as +# begin +# execute statement 'drop role tmp$r4707'; +# when any do begin end +# end ^ +# set term ;^ +# commit; +# +# set transaction wait; +# +# delete from test1; +# insert into test3(id) values(1); +# set list on; +# select 'Starting EB with infinite pause.' as isql_msg from rdb$database; +# set term ^; +# execute block as +# begin +# execute statement 'update test1 set id=-id' +# on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') +# as user '%s' password '%s' +# role 'TMP$R4707' -- this will force to create new attachment, and its Tx will be paused on INFINITE time. +# ; +# when any do begin end +# end ^ +# set term ;^ +# select 'EB with pause finished.' as msg_2 from rdb$database; +# ''' % (user_name, user_password) +# +# f_hang_sql=open( os.path.join(context['temp_directory'],'tmp_4707_hang.sql'), 'w') +# f_hang_sql.write(lock_sql) +# flush_and_close( f_hang_sql ) +# +# +# ################ ############################################################################## +# # Make asynchronous call of ISQL which will stay several seconds in pause due to row-level lock +# # ############################################################################################# +# # Execute a child program in a new process, redirecting STDERR to the same target as of STDOUT: +# f_hang_log=open( os.path.join(context['temp_directory'],'tmp_4707_hang.log'), 'w') +# p_hang = Popen([context['isql_path'], dsn, "-i", f_hang_sql.name],stdout=f_hang_log, stderr=subprocess.STDOUT) +# +# # Here we should wait while ISQL will establish its connect (in separate child window, call asynchronous) and +# # stay in pause: +# time.sleep(2) +# +# ############################################################################################# +# # Make SYNC. call of fbsvcmgr in order to validate database which has locks on some relations +# ############################################################################################# +# f_svc_log=open( os.path.join(context['temp_directory'],'tmp_4707_svc.log'), 'w') +# subprocess.call([ context['fbsvcmgr_path'], 'localhost:service_mgr','action_validate','dbname', db_file,'val_lock_timeout','1'],stdout=f_svc_log, stderr=subprocess.STDOUT) +# flush_and_close( f_svc_log ) +# +# ####################################################### +# # TERMINATE separate (child) process of ISQL that hangs +# ####################################################### +# p_hang.terminate() +# flush_and_close( f_hang_log ) +# +# with open( f_hang_log.name,'r') as f: +# print(f.read()) +# +# with open( f_svc_log.name,'r') as f: +# print(f.read()) +# +# # cleanup: +# ########## +# time.sleep(1) +# cleanup( [i.name for i in (f_hang_sql, f_hang_log, f_svc_log) ] ) +# +# ## |||||||||||||||||||||||||||| +# ## ###################################||| 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 +# ## ############################################################################################# +# con4cleanup=fdb.connect( dsn = dsn, user = user_name, password = user_password ) +# con4cleanup.execute_immediate('delete from mon$attachments where mon$attachment_id != current_connection') +# con4cleanup.commit() +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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 + """ + +@pytest.mark.version('>=2.5.5') +@pytest.mark.xfail +def test_core_4707_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4708.py b/tests/bugs/test_core_4708.py new file mode 100644 index 00000000..320c6001 --- /dev/null +++ b/tests/bugs/test_core_4708.py @@ -0,0 +1,130 @@ +#coding:utf-8 +# +# id: bugs.core_4708 +# title: Content of MON$EXPLAINED_PLAN in MON$STATEMENTS is truncated if exceeds the 32KB limit +# decription: +# tracker_id: CORE-4708 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('MON_EXPLAINED_PLAN_TAIL.*', 'MON_EXPLAINED_PLAN_TAIL')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set blob all; + -- This query has explained plan with length ~47 Kb (checked on WI-V3.0.0.32253). + -- Instead of checking explained plan text it is enough only to ensure that its + -- LENGTH is more than 32K and that text is not cuted off, i.e. it should end with + -- phrase: Table "MON$STATEMENTS" Full Scan + -- Another sample of query that has long plan see in core_5061.fbt + with recursive + rx as ( + select 1 as i from rdb$database + union all + select r.i+1 from rx r where r.i < 2 + ) + ,r2 as ( + select row_number() over() i + from rx r + full join rx r2 on r2.i=r.i + group by r.i + having count(*)>0 + order by r.i rows 1 + ) + select + iif( char_length(mon$explained_plan) > 32767, 'MORE THAN 32K', 'LESS THEN 32K' ) as mon_explained_plan_len + ,right(mon$explained_plan,32) as mon_explained_plan_tail + ,(select count(*) from r2) + ,(select count(*) from r2) + ,(select count(*) from r2) + ,(select count(*) from r2) + ,(select count(*) from r2) + ,(select count(*) from r2) + ,(select count(*) from r2) + ,(select count(*) from r2) + ,(select count(*) from r2) + ,(select count(*) from r2) + + ,(select count(*) from r2) + ,(select count(*) from r2) + ,(select count(*) from r2) + ,(select count(*) from r2) + ,(select count(*) from r2) + ,(select count(*) from r2) + ,(select count(*) from r2) + ,(select count(*) from r2) + ,(select count(*) from r2) + ,(select count(*) from r2) + + ,(select count(*) from r2) + ,(select count(*) from r2) + ,(select count(*) from r2) + ,(select count(*) from r2) + ,(select count(*) from r2) + ,(select count(*) from r2) + ,(select count(*) from r2) + ,(select count(*) from r2) + --,(select count(*) from r2) + from mon$statements s + where + s.mon$attachment_id = current_connection + -- 08-may-2017: need for 4.0 Classic! + -- Currently there is also query with RDB$AUTH_MAPPING data in mon$statements: + and s.mon$sql_text containing 'select 1 as i' + ; + -- Table "MON$STATEMENTS" Full Scan + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MON_EXPLAINED_PLAN_LEN MORE THAN 32K + MON_EXPLAINED_PLAN_TAIL 0:4 + MON$STATEMENTS" as "S" Full Scan + COUNT 1 + COUNT 1 + COUNT 1 + COUNT 1 + COUNT 1 + COUNT 1 + COUNT 1 + COUNT 1 + COUNT 1 + COUNT 1 + COUNT 1 + COUNT 1 + COUNT 1 + COUNT 1 + COUNT 1 + COUNT 1 + COUNT 1 + COUNT 1 + COUNT 1 + COUNT 1 + COUNT 1 + COUNT 1 + COUNT 1 + COUNT 1 + COUNT 1 + COUNT 1 + COUNT 1 + COUNT 1 + """ + +@pytest.mark.version('>=3.0') +def test_core_4708_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4710.py b/tests/bugs/test_core_4710.py new file mode 100644 index 00000000..a2103634 --- /dev/null +++ b/tests/bugs/test_core_4710.py @@ -0,0 +1,337 @@ +#coding:utf-8 +# +# id: bugs.core_4710 +# title: invalid request BLR at offset 361 context already in use (BLR error) +# decription: +# tracker_id: CORE-4710 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set planonly; + select + (select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + --,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) /* #2 */ + --,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) /* #1 */ + from + rdb$database; + + select + (select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) /* #2 */ + --,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) /* #1 */ + from + rdb$database; + + + select + (select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) /* #2 */ + ,(select row_number() over() from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id group by r.rdb$relation_id having count(*)>0 order by r.rdb$relation_id rows 1 to 1) /* #1 */ + from + rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN SORT (SORT (JOIN (JOIN (R2 NATURAL, R NATURAL), JOIN (R NATURAL, R2 NATURAL)))) + PLAN (RDB$DATABASE NATURAL) + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 54001 + Dynamic SQL Error + -Too many Contexts of Relation/Procedure/Views. Maximum allowed is 256 + + Statement failed, SQLSTATE = 54001 + Dynamic SQL Error + -Too many Contexts of Relation/Procedure/Views. Maximum allowed is 256 + """ + +@pytest.mark.version('>=3.0') +def test_core_4710_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4713.py b/tests/bugs/test_core_4713.py new file mode 100644 index 00000000..c18d4351 --- /dev/null +++ b/tests/bugs/test_core_4713.py @@ -0,0 +1,58 @@ +#coding:utf-8 +# +# id: bugs.core_4713 +# title: "BLOB not found" error at rollback after insert into table with expression index +# decription: +# tracker_id: CORE-4713 +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table T1 ( bx blob sub_type text ); + + create index t1_idx on T1 computed by (cast(substring(bx from 1 for 1000) as varchar(1000))); + commit; + + set term ^; + execute block as + declare n int = 250; + begin + while (n>0) do insert into t1(bx) values( rpad( 'QWERTY', 1000, uuid_to_char(gen_uuid()) ) ) returning :n-1 into n; + end + ^ + set term ;^ + + rollback; + -- 2.5.3 (WI-V2.5.3.26780): no error. + -- 2.5.2 (WI-V2.5.2.26540): + -- Statement failed, SQLSTATE = HY000 + -- BLOB not found + -- -BLOB not found + -- -BLOB not found + -- -BLOB not found + -- Statement failed, SQLSTATE = 08003 + -- invalid transaction handle (expecting explicit transaction start) + -- 2.5.1 (WI-V2.5.1.26351): + -- the same as 2.5.2 + crash ("08006 / -Error reading data from the connection") + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.3') +def test_core_4713_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_4715.py b/tests/bugs/test_core_4715.py new file mode 100644 index 00000000..57ab5d75 --- /dev/null +++ b/tests/bugs/test_core_4715.py @@ -0,0 +1,66 @@ +#coding:utf-8 +# +# id: bugs.core_4715 +# title: Restore of shadowed database fails using -k ("restore without shadow") switch +# decription: +# tracker_id: CORE-4715 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!HASH_IN_SOURCE|RDB\\$SHADOW_NUMBER|HASH_IN_RESTORED|Attributes).)*$', ''), ('[ ]+', ' '), ('[\t]*', ' ')] + +init_script_1 = """ + -- Confirmed on WI-T3.0.0.31374: + -- command "gbak -rep -k c4715.fbk -user SYSDBA -pas masterke localhost/3000:\\c4715-new.FDB" + -- produces: + -- gbak: ERROR:DELETE operation is not allowed for system table RDB$FILES + -- gbak:Exiting before completion due to errors + recreate table test(s varchar(30)); + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# +# shd=os.path.join(context['temp_directory'],'core_4715.shd') +# script = '''create shadow 1 '%s'; commit; insert into test select 'line #'||lpad(row_number()over(), 3, '0') from rdb$types rows 200; commit; set list on; select hash(list(s)) hash_in_source from test; select * from rdb$files;''' % shd +# runProgram('isql',[dsn,'-q','-user',user_name,'-password',user_password],script) +# runProgram('gstat',[shd,'-h','-user',user_name,'-password',user_password]) +# fbk = os.path.join(context['temp_directory'],'core_4715-shadowed.fbk') +# fbn = os.path.join(context['temp_directory'],'core_4715-restored.fdb') +# runProgram('gbak',['-b','-user',user_name,'-password',user_password,dsn,fbk]) +# runProgram('gbak',['-rep','-k','-user',user_name,'-password',user_password,fbk,fbn]) +# script = '''set list on; select hash(list(s)) hash_in_restored from test;''' +# runProgram('isql',[fbn,'-q','-user',user_name,'-password',user_password],script) +# if os.path.isfile(fbk): +# os.remove(fbk) +# if os.path.isfile(fbn): +# os.remove(fbn) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +Creating shadow... +HASH_IN_SOURCE 1499836372373901520 +RDB$SHADOW_NUMBER 1 +Attributes force write, active shadow +HASH_IN_RESTORED 1499836372373901520 + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4715_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4719.py b/tests/bugs/test_core_4719.py new file mode 100644 index 00000000..1a44cc39 --- /dev/null +++ b/tests/bugs/test_core_4719.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: bugs.core_4719 +# title: Message "Statement failed, SQLSTATE = 00000 + unknown ISC error 0" appears when issuing REVOKE ALL ON ALL FROM +# decription: +# tracker_id: CORE-4719 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('Statement failed, SQLSTATE.*', ''), ('record not found for user:.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + drop user tmp$c4719; + commit; + create user tmp$c4719 password '123'; + commit; + revoke all on all from tmp$c4719; + commit; + drop user tmp$c4719; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Warning: ALL on ALL is not granted to TMP$C4719. + """ + +@pytest.mark.version('>=2.5') +def test_core_4719_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_4725.py b/tests/bugs/test_core_4725.py new file mode 100644 index 00000000..eec625fd --- /dev/null +++ b/tests/bugs/test_core_4725.py @@ -0,0 +1,254 @@ +#coding:utf-8 +# +# id: bugs.core_4725 +# title: Inconsistencies with ALTER DOMAIN and ALTER TABLE with DROP NOT NULL and PRIMARY KEYs +# decription: +# tracker_id: CORE-4725 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- 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) + + set list on; + set heading off; + + recreate table test00(x integer); + recreate table test01(x integer); + recreate table test02(x integer); + recreate table test03(x integer); + recreate table test04(x integer); + recreate table test05(x integer); + recreate table test06(x integer); + commit; + + set term ^; + execute block as + begin + begin execute statement 'drop domain dm_01'; when any do begin end end + begin execute statement 'drop domain dm_02'; when any do begin end end + begin execute statement 'drop domain dm_03'; when any do begin end end + begin execute statement 'drop domain dm_04'; when any do begin end end + begin execute statement 'drop domain dm_05'; when any do begin end end + begin execute statement 'drop domain dm_06'; when any do begin end end + end + ^ + set term ;^ + commit; + + create domain dm_01 integer; + create domain dm_02 integer not null; + create domain dm_03 integer not null; + create domain dm_04 integer not null; + create domain dm_05 integer; + create domain dm_06 integer; + commit; + + ------------------------------------------------------------------------------------------------------------ + + recreate table test00(x integer); + alter table test00 alter x set not null, add constraint t_pk primary key(x); + commit; + + -- should produce "SQLSTATE = 27000 / Column used in a PRIMARY constraint must be NOT NULL.": + alter table test00 alter x drop not null; -- correct error + commit; + + select 'After try to drop NN on FIELD, NN was added by ALTER SET NOT NULL' info_00 + from rdb$database; + + show table test00; + + ------------------------------------------------------------------------------------------------------------ + + recreate table test01(x dm_01 not null); + alter table test01 add constraint test01_pk primary key (x); + commit; + + -- should produce "SQLSTATE = 27000 / Column used in a PRIMARY constraint must be NOT NULL.": + alter table test01 alter x drop not null; -- correct error + commit; + + select 'After try to drop NN on FIELD, NN was added directly in CREATE TABLE ( not null)' info_01 + from rdb$database; + + show table test01; + + + ------------------------------------------------------------------------------------------------------------ + + recreate table test02(x dm_02); + alter table test02 add constraint test02_pk primary key (x); + commit; + + -- ::: !!! ::: + -- This statement will NOT produce any error or warning but field will remain NOT null. + -- Confirmed by ASF in core-4725 22.04.2015 + alter table test02 alter x drop not null; -- correct pass + commit; + + select 'After try to drop NN on FIELD, NN was inherited from DOMAIN' info_02 + from rdb$database; + + show table test02; + + + ------------------------------------------------------------------------------------------------------------ + + recreate table test03(x dm_03); + alter table test03 add constraint test03_pk primary key (x); + commit; + + -- should produce "SQLSTATE = 42000 / Domain used in the PRIMARY KEY constraint of table TEST03 must be NOT NULL" + alter domain dm_03 drop not null; -- incorrect pass !!! + + commit; + + select 'After try to drop NN on DOMAIN but dependent table exists' info_03 + from rdb$database; + + show domain dm_03; + show table test03; + + ------------------------------------------------------------------------------------------------------------ + + recreate table test04(x dm_04 not null); + alter table test04 add constraint test04_pk primary key (x); + commit; + + -- ::: !!! ::: + -- This statement will NOT produce any error or warning but field will remain NOT null. + -- Confirmed by ASF in core-4725 22.04.2015 + alter table test04 alter x drop not null; -- ASF: "incorrect error !!!" // though it seems strange to me... :-/ + commit; + + select 'After try to drop NN on FIELD based on not-null domain, but NN was also specified in the field DDL' info_04 + from rdb$database; + + show table test04; + + ------------------------------------------------------------------------------------------------------------ + + recreate table test05(x dm_05); + commit; + insert into test05 values(1); + insert into test05 values(null); + insert into test05 values(3); + commit; + + -- Should produce "SQLSTATE = 22006 / Cannot make field X of table TEST05 NOT NULL because there are NULLs present" + alter domain dm_05 set not null; + commit; + + select 'After try to set NN on DOMAIN when at least one table exists with NULL in its data' info_05 + from rdb$database; + show domain dm_05; + + + ------------------------------------------------------------------------------------------------------------ + + recreate table test06(x dm_06); + commit; + insert into test06 values(1); + insert into test06 values(2); + insert into test06 values(3); + commit; + + -- Should pass: + alter domain dm_06 set not null; + commit; + + select 'After try to set NN on DOMAIN when NO table exists with NULL in its data' info_06 + from rdb$database; + show domain dm_06; + + -- Should produce "SQLSTATE = 23000 / validation error for column "TEST06"."X", value "*** null ***"" + update test06 set x = null where x = 2; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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) + + 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) + + 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) + + 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) + + 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) + + 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_1 = """ + 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 ***" + """ + +@pytest.mark.version('>=3.0') +def test_core_4725_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4726.py b/tests/bugs/test_core_4726.py new file mode 100644 index 00000000..c9de6e38 --- /dev/null +++ b/tests/bugs/test_core_4726.py @@ -0,0 +1,149 @@ +#coding:utf-8 +# +# id: bugs.core_4726 +# title: Provide ability to do: REcreate user password +# decription: +# Checked on 4.0.0.1629, CS and SS: OK, 1.788s. +# +# ::: NOTE ::: +# Clause 'GRANT / REVOKE ADMIN ROLE' must be specified __BEFORE__ 'USING PLUGIN' clause! +# Perhaps, documentation need to be corrected. +# Sent letter to alex and dimitr, 16.10.2019 20:30. +# +# tracker_id: CORE-4726 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('=', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set width usrname 10; + set width firstname 10; + set width sec_plugin 20; + set width sec_attr_key 20; + set width sec_attr_val 20; + set width sec_plugin 20; + + + recreate user tmp$c4726 password '123' using plugin Srp; + recreate user tmp$c4726 password '123' using plugin Srp; + drop user tmp$c4726 using plugin Srp; + commit; + + recreate view v_users as + select + su.sec$user_name as usrname + ,su.sec$first_name as firstname + ,su.sec$plugin as sec_plugin + ,su.sec$admin as sec_is_admin + ,su.sec$active as su_active + ,sa.sec$key as sec_attr_key + ,sa.sec$value as sec_attr_val + from sec$users su left + join sec$user_attributes sa using(sec$user_name, sec$plugin) + where su.sec$user_name = upper('TMP$C4726'); + commit; + + -- set echo on; + + ----------------------------- Create Or Alter tests ----------------------------------- + + create or alter user tmp$c4726 password '123' + inactive + grant admin role -- 16.10.2019: must be specified BEFORE 'using plugin ...' clause! + using plugin Srp + tags (initname='Ozzy', surname='Osbourne', groupname='Black Sabbath', birthday = '03.12.1948') + -- grant admin role -- 16.10.2019: parsing error if will be here + ; + + commit; + select 1 as step, v.* from v_users v; + + create or alter user tmp$c4726 password '123' + active + revoke admin role + using plugin Srp + tags (initname='Ian', surname='Gillan', groupname='Deep Purple', drop birthday) + ; + commit; + select 2 as step, v.* from v_users v; + + drop user tmp$c4726 using plugin Srp; + commit; + + ---------------------------------- REcreate test --------------------------------------- + + recreate user tmp$c4726 password '123' + inactive + grant admin role + using plugin Srp + tags (initname='John', surname='Bonham', groupname='Led Zeppelin', birthday = '31.05.1948') + ; + commit; + select 3 as step, v.* from v_users v; + + recreate user tmp$c4726 password '123' active + revoke admin role + using plugin Srp + tags (initname='Roger', surname='Waters', groupname='Pink Floyd', drop birthday) + ; + commit; + + select 4 as step, v.* from v_users v; + + drop user tmp$c4726 using plugin Srp; + commit; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + STEP USRNAME FIRSTNAME SEC_PLUGIN SEC_IS_ADMIN SU_ACTIVE SEC_ATTR_KEY SEC_ATTR_VAL + + 1 TMP$C4726 Srp BIRTHDAY 03.12.1948 + 1 TMP$C4726 Srp GROUPNAME Black Sabbath + 1 TMP$C4726 Srp INITNAME Ozzy + 1 TMP$C4726 Srp SURNAME Osbourne + + + STEP USRNAME FIRSTNAME SEC_PLUGIN SEC_IS_ADMIN SU_ACTIVE SEC_ATTR_KEY SEC_ATTR_VAL + + 2 TMP$C4726 Srp GROUPNAME Deep Purple + 2 TMP$C4726 Srp INITNAME Ian + 2 TMP$C4726 Srp SURNAME Gillan + + + STEP USRNAME FIRSTNAME SEC_PLUGIN SEC_IS_ADMIN SU_ACTIVE SEC_ATTR_KEY SEC_ATTR_VAL + + 3 TMP$C4726 Srp BIRTHDAY 31.05.1948 + 3 TMP$C4726 Srp GROUPNAME Led Zeppelin + 3 TMP$C4726 Srp INITNAME John + 3 TMP$C4726 Srp SURNAME Bonham + + + STEP USRNAME FIRSTNAME SEC_PLUGIN SEC_IS_ADMIN SU_ACTIVE SEC_ATTR_KEY SEC_ATTR_VAL + + 4 TMP$C4726 Srp GROUPNAME Pink Floyd + 4 TMP$C4726 Srp INITNAME Roger + 4 TMP$C4726 Srp SURNAME Waters + + """ + +@pytest.mark.version('>=4.0') +def test_core_4726_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4729.py b/tests/bugs/test_core_4729.py new file mode 100644 index 00000000..1a39a4bd --- /dev/null +++ b/tests/bugs/test_core_4729.py @@ -0,0 +1,59 @@ +#coding:utf-8 +# +# id: bugs.core_4729 +# title: Add a flag to mon$database helping to decide what type of security database is used - default, self or other +# decription: +# tracker_id: CORE-4729 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set wng off; + set list on; + + create or alter user ozzy password 'osb'; + revoke all on all from ozzy; + commit; + + -- Check that info can be seen by SYSDBA: + select current_user,mon$sec_database from mon$database; + commit; + + -- Check that info can be seen by non-privileged user: + connect '$(DSN)' user ozzy password 'osb'; + select current_user,mon$sec_database from mon$database; + commit; + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + drop user ozzy; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + USER SYSDBA + MON$SEC_DATABASE Default + USER OZZY + MON$SEC_DATABASE Default + """ + +@pytest.mark.version('>=3.0') +def test_core_4729_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4731.py b/tests/bugs/test_core_4731.py new file mode 100644 index 00000000..6596c24f --- /dev/null +++ b/tests/bugs/test_core_4731.py @@ -0,0 +1,295 @@ +#coding:utf-8 +# +# id: bugs.core_4731 +# title: Prohibit an ability to issue DML or DDL statements on RDB$ tables +# decription: +# Integral test for verifying ability to change system tables by non-privileged user and by those +# who have been granted with RDB$ADMIN role. +# Main idea: read system tables (hereafter - 'ST') metadata and generate all possible DML and DDL +# statements that are intended to: +# a) restrict ST by creating new table with foreign key to selected ST (if it has PK or UK); +# b) change data by issuing INSERT / UPDATE / DELETE statements; also try SELECT ... WITH LOCK; +# c) change metadata: add column, alter column (drop NULL constraint, add new contraint, add DEFAULT value), +# drop column; +# d) aux. actions: attempt to drop ST. +# *** 11-apr-2018: EXCLUDED attempt to create index on ST: now it is allowed, see CORE-5746 *** +# e) make indirect changes: apply ALTER SEQUENCE statement for system generators +# +# Test contains following statements and procedures: +# 1) creating two users, one of them is granted with role RDB$ADMIN. +# Both these users are granted to create/alter/drop any kinds of database objects. +# 2) creating several user objects (domain, exception, collation, sequence, master/detail tables, trigger, +# view, stanalone procedure and standalone function and package). These objects are created in order +# to add some data in system tables that can be later actually affected by vulnerable expressions; +# 3) proc sp_gen_expr_for_creating_fkeys: +# reads definition of every system table and if it has PK/UK than generate expressions for item "a": +# they will create completely new table with set of fields which id appropriate to build FOREIGN KEY +# to selected ST. Generated expressions are added to special table `vulnerable_on_sys_tables`; +# 4) proc sp_gen_expr_for_direct_change: +# reads definition of every system table and generates DML and DDL expressions for items "b" ... "e" described +# in the previous section. These expressions are also added to table `vulnerable_on_sys_tables`; +# 5) proc sp_run_vulnerable_expressions: +# reads expressions from table `vulnerable_on_sys_tables` and tries to run each of them via ES/EDS with user +# and role that are passed as input arguments. If expression raises exception than this SP will log its gdscode +# in WHEN ANY block and expression then is suppressed. +# If expression PASSES successfully than this SP *also* will log this event. +# 6) two calls of sp_run_vulnerable_expressions: one for non-privileged user and second for user with role RDB$ADMIN. +# 7) select values of raised gdscodes (distinct) in order to check that only ONE gdscode occured (335544926). +# 8) select expressions that were PASSED without exceptions. +# +# Checked on: +# 3.0.4.32947: OK, SS: 22s, CS: 37s +# 4.0.0.955: OK, SS: 35s, CS: 33s +# +# REFACTORED 18.02.2020: most of initial code was moved into $files_location/core_4731.sql; changed test_type to 'Python'. +# Checked 18.02.2020 afte refactoring: +# 4.0.0.1773 SS: 11.759s. +# 4.0.0.1773 SC: 15.374s. +# 4.0.0.1773 CS: 13.561s. +# 3.0.6.33247 SS: 8.431s. +# 3.0.6.33247 SC: 11.419s. +# 3.0.6.33247 CS: 10.846s. +# +# tracker_id: CORE-4731 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# import time +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# this_db = db_conn.database_name +# db_conn.close() +# +# dba_privileged_name = 'tmp_c4731_cooldba' +# non_privileged_name = 'tmp_c4731_manager' +# +# #----------------------------------- +# +# 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() +# os.fsync(file_handle.fileno()) +# +# file_handle.close() +# +# #-------------------------------------------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# +# f_sql=open(os.path.join(context['files_location'],'core_4731.sql'),'r') +# sql_for_prepare = f_sql.read() +# f_sql.close() +# +# f_pre_sql = open( os.path.join(context['temp_directory'],'tmp_core_4731_pre.sql'), 'w') +# f_pre_sql.write( sql_for_prepare % dict(globals(), **locals()) ) +# flush_and_close( f_pre_sql ) +# +# f_pre_log = open( '.'.join( (os.path.splitext( f_pre_sql.name )[0], 'log') ), 'w') +# f_pre_err = open( '.'.join( (os.path.splitext( f_pre_sql.name )[0], 'err') ), 'w') +# subprocess.call( [ context['isql_path'], dsn, '-q', '-i', f_pre_sql.name ], stdout = f_pre_log, stderr = f_pre_err) +# flush_and_close( f_pre_log ) +# flush_and_close( f_pre_err ) +# +# runProgram( context['gfix_path'],[dsn, '-shut','full','-force','0'] ) +# runProgram( context['gfix_path'],[dsn, '-online'] ) +# +# sql_run=''' +# -- ################################################################################### +# -- R U N A S N O N - P R I V I L E G E D U S E R +# -- ################################################################################### +# execute procedure sp_run_vulnerable_expressions('%(non_privileged_name)s', '123', 'NONE'); +# +# -- Note: as of build 3.0.31810, we can SKIP restoring of 'pure-state' of RDB$ tables +# -- after this SP because non-privileged user can NOT change enything. +# -- All his attempts should FAIL, system tables should be in unchanged state. +# +# set list off; +# set heading off; +# +# select '-- Executed with role: '||trim(( select actual_role from vulnerable_on_sys_tables rows 1 )) +# ||'. Expressions that passes WITHOUT errors:' as msg +# from rdb$database +# ; +# +# commit; -- 11-04-2018, do not remove! +# set transaction no wait; +# +# set list on; +# select count(*) as "-- count_of_passed: " +# from v_passed; +# +# set list on; +# select * from v_passed; +# +# set list on; +# select distinct vulnerable_gdscode as "-- gdscode list for blocked:" +# from vulnerable_on_sys_tables +# where vulnerable_gdscode is distinct from -1; +# +# -- ######################################################################################### +# -- R U N A S U S E R W H O I S G R A N T E D W I T H R B D $ A D M I N +# -- ######################################################################################### +# execute procedure sp_run_vulnerable_expressions('%(dba_privileged_name)s', '123', 'RDB$ADMIN'); +# +# set list off; +# set heading off; +# +# select '-- Executed with role: '||trim(( select actual_role from vulnerable_on_sys_tables rows 1 )) +# ||'. Expressions that passes WITHOUT errors:' as msg +# from rdb$database +# ; +# commit; -- 11-04-2018, do not remove! +# +# set list on; +# select count(*) as "-- count_of_passed: " +# from v_passed; +# +# set list on; +# select * from v_passed; +# +# set list on; +# select distinct vulnerable_gdscode as "-- gdscode list for blocked:" +# from vulnerable_on_sys_tables +# where vulnerable_gdscode is distinct from -1; +# +# ---------------- +# commit; +# +# connect '%(dsn)s' user '%(user_name)s' password '%(user_password)s'; +# +# -- |||||||||||||||||||||||||||| +# -- ###################################||| 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; +# +# drop user %(dba_privileged_name)s; +# drop user %(non_privileged_name)s; +# commit; +# ''' % dict(globals(), **locals()) +# +# f_sql_run = open( os.path.join(context['temp_directory'],'tmp_core_4731_run.sql'), 'w') +# f_sql_run.write( sql_run % dict(globals(), **locals()) ) +# flush_and_close( f_sql_run ) +# +# f_run_log = open( '.'.join( (os.path.splitext( f_sql_run.name )[0], 'log') ), 'w') +# f_run_err = open( '.'.join( (os.path.splitext( f_sql_run.name )[0], 'err') ), 'w') +# subprocess.call( [ context['isql_path'], dsn, '-q', '-i', f_sql_run.name ], stdout = f_run_log, stderr = f_run_err) +# flush_and_close( f_run_log ) +# flush_and_close( f_run_err ) +# +# # Check results: +# # ============== +# +# # 1. Print UNEXPECTED output: +# ############################# +# for f in (f_pre_log, f_pre_err): +# with open( f.name,'r') as f: +# for line in f: +# if line.strip(): +# print( 'UNEXPECTED '+('STDOUT' if f == f_pre_log else 'STDERR')+' WHEN PREPARE DB: ' + line ) +# +# with open( f_run_err.name,'r') as f: +# for line in f: +# if line.strip(): +# print( 'UNEXPECTED STDERR WHEN RUN: ' + line ) +# +# # 2. Print EXPECTED output: +# ########################### +# with open( f_run_log.name,'r') as f: +# for line in f: +# if line.strip(): +# print( line ) +# +# # Cleanup +# ######### +# cleanup( [ i.name for i in (f_pre_sql,f_pre_log,f_pre_err,f_sql_run,f_run_log,f_run_err) ] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + -- 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: 23 + 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 + VULNERABLE_EXPR insert into RDB$TYPES(RDB$FIELD_NAME , RDB$TYPE , RDB$TYPE_NAME , RDB$DESCRIPTION , RDB$SYSTEM_FLAG) values(null, null, null, null, null) returning rdb$db_key; -- length of returned rdb$dbkey=8 + VULNERABLE_EXPR update RDB$TYPES t set t.RDB$DESCRIPTION = 'test_for_blob' where coalesce(rdb$system_flag,0)=0 rows 1 returning t.rdb$db_key; -- length of returned rdb$dbkey=8 + VULNERABLE_EXPR update RDB$TYPES t set t.RDB$DESCRIPTION = 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$TYPES t set t.RDB$FIELD_NAME = 'C' where coalesce(rdb$system_flag,0)=0 rows 1 returning t.rdb$db_key; -- length of returned rdb$dbkey=8 + VULNERABLE_EXPR update RDB$TYPES t set t.RDB$FIELD_NAME = 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$TYPES t set t.RDB$SYSTEM_FLAG = 32767 where coalesce(rdb$system_flag,0)=0 rows 1 returning t.rdb$db_key; -- length of returned rdb$dbkey=8 + VULNERABLE_EXPR update RDB$TYPES t set t.RDB$TYPE = 32767 where coalesce(rdb$system_flag,0)=0 rows 1 returning t.rdb$db_key; -- length of returned rdb$dbkey=8 + VULNERABLE_EXPR update RDB$TYPES t set t.RDB$TYPE = 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$TYPES t set t.RDB$TYPE_NAME = 'C' where coalesce(rdb$system_flag,0)=0 rows 1 returning t.rdb$db_key; -- length of returned rdb$dbkey=8 + VULNERABLE_EXPR update RDB$TYPES t set t.RDB$TYPE_NAME = 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') +@pytest.mark.xfail +def test_core_4731_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4733.py b/tests/bugs/test_core_4733.py new file mode 100644 index 00000000..8c54849d --- /dev/null +++ b/tests/bugs/test_core_4733.py @@ -0,0 +1,106 @@ +#coding:utf-8 +# +# id: bugs.core_4733 +# title: Command "Alter table alter TYPE and makes incorrect assignments in to ZERO / JULIAN_DATE / ASCII(0) for types INT, TIMESTAMP and VARCHAR +# decription: +# tracker_id: CORE-4733 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- 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_nn_int int NOT null; + create domain dm_nn_dts timestamp NOT null; + create domain dm_nn_utf varchar(10) character set utf8 NOT null; + create domain dm_nn_boo boolean NOT null; + + set list on; + + create table test(num int, dts timestamp, str varchar(10) character set utf8, boo boolean); + commit; + + insert into test values(null, null, null, null); + commit; + + alter table test + alter num type dm_nn_int + ,alter dts type dm_nn_dts + ,alter str type dm_nn_utf + ,alter boo type dm_nn_boo + ; + commit; + + show table test; + + delete from test returning num, dts, str, boo; + commit; + + alter table test + alter num type dm_nn_int + ,alter dts type dm_nn_dts + ,alter str type dm_nn_utf + ,alter boo type dm_nn_boo + ; + + commit; + insert into test values(null, null, null, null); + commit; + show table test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + NUM INTEGER Nullable + DTS TIMESTAMP Nullable + STR VARCHAR(10) CHARACTER SET UTF8 Nullable + BOO BOOLEAN Nullable + + NUM + DTS + STR + BOO + + + 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_1 = """ + 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 + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."NUM", value "*** null ***" + """ + +@pytest.mark.version('>=3.0') +def test_core_4733_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4735.py b/tests/bugs/test_core_4735.py new file mode 100644 index 00000000..5742589f --- /dev/null +++ b/tests/bugs/test_core_4735.py @@ -0,0 +1,59 @@ +#coding:utf-8 +# +# id: bugs.core_4735 +# title: Expression 'where bool_field IS true | false' should also use index as 'where bool_field = true | false' (if such index exists) +# decription: +# Changed expected PLAN of execution after dimitr's letter 28.01.2019 17:28: +# 'is NOT ' and 'is distinct from ' should use PLAN NATURAL. +# +# tracker_id: CORE-4735 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test(x boolean, unique(x) using index test_x); + commit; + + set plan on; + select 1 from test where x = true ; + select 1 from test where x is true ; + select 0 from test where x = false ; + select 0 from test where x is false ; + select 1 from test where x is not true ; -- this must have plan NATURAL, 26.01.2019 + select 1 from test where x is distinct from true ; -- this must have plan NATURAL, 26.01.2019 + select 1 from test where x is not false ; -- this must have plan NATURAL, 26.01.2019 + select 1 from test where x is distinct from false ; -- this must have plan NATURAL, 26.01.2019 + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (TEST INDEX (TEST_X)) + PLAN (TEST INDEX (TEST_X)) + PLAN (TEST INDEX (TEST_X)) + PLAN (TEST INDEX (TEST_X)) + PLAN (TEST NATURAL) + PLAN (TEST NATURAL) + PLAN (TEST NATURAL) + PLAN (TEST NATURAL) + """ + +@pytest.mark.version('>=3.0') +def test_core_4735_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4738.py b/tests/bugs/test_core_4738.py new file mode 100644 index 00000000..0408adee --- /dev/null +++ b/tests/bugs/test_core_4738.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: bugs.core_4738 +# title: Command "Alter table alter type " does not work: "BLR syntax error: expected valid BLR code at offset 15, encountered 255" +# decription: +# tracker_id: CORE-4738 +# min_versions: ['2.0.7'] +# versions: 2.0.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create domain dm_id int; + commit; + + create table test(num int); + commit; + + alter table test alter num type dm_id; + commit; + + show table test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + NUM (DM_ID) INTEGER Nullable + """ + +@pytest.mark.version('>=2.0.7') +def test_core_4738_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4739.py b/tests/bugs/test_core_4739.py new file mode 100644 index 00000000..1fe4e003 --- /dev/null +++ b/tests/bugs/test_core_4739.py @@ -0,0 +1,79 @@ +#coding:utf-8 +# +# id: bugs.core_4739 +# title: Accent insensitive comparison: diacritical letters with DIAGONAL crossing stroke pass only test on EQUALITY to their non-accented forms +# decription: +# Confirmed successful result on 4.0.0.1627 +# All builds before that failed on four characters: 'Ø' 'Ð' 'Ł' and 'Ŀ'. +# +# tracker_id: CORE-4739 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create collation co_utf8_ci_ai for utf8 from unicode case insensitive accent insensitive; + commit; + + set list on; + set count on; + + with recursive + d as ( + select + cast( 'ḂĊḊḞĠṀṖṠṪ' || 'ẀẂŴŶ' || 'ŠŽ' || 'Ø' || 'Ð' || 'Ł' || 'Ŀ' || 'ĘĄĂÂÎŢŐŰĖÅĽĢÁÉÍÓÚÝÀÈÌÒÙÂÊÎÔÛÃÑÕÄËÏÖÜŸÇŠĄĘŹŻĂŞŢ' as varchar(80) character set utf8) s + ,cast( 'BCDFGMPST' || 'WWWY' || 'SZ' || 'O' || 'D' || 'L' || 'L' || 'EAAAITOUEALGAEIOUYAEIOUAEIOUANOAEIOUYCSAEZZAST' as varchar(80) character set utf8) ascii_only_char + from rdb$database + ) + ,r as(select 1 i from rdb$database union all select r.i+1 from r where r.i < 100) + ,e as( + select + substring(d.s from r.i for 1) non_ascii_char + ,substring(d.ascii_only_char from r.i for 1) ascii_only_char + from d join r on r.i <= char_length(d.s) + ) + ,f as ( + select + e.non_ascii_char --as utf_char + ,e.ascii_only_char + ,iif( e.non_ascii_char collate co_utf8_ci_ai = e.ascii_only_char, 1, 0 ) equal_test + ,iif( e.non_ascii_char collate co_utf8_ci_ai between e.ascii_only_char and e.ascii_only_char, 1, 0 ) between_test + ,iif( position(e.ascii_only_char, e.non_ascii_char collate co_utf8_ci_ai) >0 , 1, 0 ) pos_test + ,iif( e.non_ascii_char collate co_utf8_ci_ai starting with e.ascii_only_char, 1, 0 ) start_with_test + ,iif( e.non_ascii_char collate co_utf8_ci_ai like e.ascii_only_char, 1, 0 ) like_test + ,iif( e.non_ascii_char collate co_utf8_ci_ai containing e.ascii_only_char, 1, 0 ) containing_test + ,iif( e.non_ascii_char collate co_utf8_ci_ai similar to e.ascii_only_char, 1, 0 ) similar_to_letter_test + ,iif( e.non_ascii_char collate co_utf8_ci_ai similar to '[[:ALPHA:]]', 1, 0 ) similar_to_alpha_test + from e + ) + select * + from f + where minvalue( equal_test, between_test, pos_test, start_with_test, like_test, containing_test, similar_to_letter_test, similar_to_alpha_test ) = 0 + order by non_ascii_char + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ + +@pytest.mark.version('>=4.0') +def test_core_4739_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4740.py b/tests/bugs/test_core_4740.py new file mode 100644 index 00000000..af786845 --- /dev/null +++ b/tests/bugs/test_core_4740.py @@ -0,0 +1,132 @@ +#coding:utf-8 +# +# id: bugs.core_4740 +# title: SIMILAR TO with quantifier {n,} in the pattern: 1) fails on 2.5 ("Invalid pattern"), 2) strange result in 3.0 +# decription: +# tracker_id: CORE-4740 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + with + d(txt,ptn) as( + select + 'abcZ', '[[:lower:]]{1,}Z' from rdb$database union all select + 'abcz', '[[:lower:]]{1,}z' from rdb$database union all select + 'abcz', '[[:lower:]]*z' from rdb$database union all select + 'abcz', '[[:lower:]]+z' from rdb$database union all select + 'aggagg', '([[:lOwEr:]]{1}gg){2,}' from rdb$database union all select + 'aggagg', '([[:lOWeR:]]{1,}gg){2,}' from rdb$database union all select + 'aggagg', '(a{1}gg){2}' from rdb$database union all select + 'aggagg', '(a{0,}gg){2}' from rdb$database union all select + 'aggagg', '(a{1}__){2}' from rdb$database union all select + 'aggagg', '(a{1}__){1,}' from rdb$database union all select + 'aggagg', '(a{1}[b-z]{2}){2}' from rdb$database union all select + 'XabaXa', '([X](a|b){1,3}){2}' from rdb$database union all select + 'XabaXaba', '([X](a|b){3}){2}' from rdb$database union all select + 'XabaX', '([X](a|b){0,3}){1,}' from rdb$database union all select + 'XabaX', '([X](a|b){0,3}){2}' from rdb$database union all select + 'XaX', '([X](a){0,1}){2}' from rdb$database union all select + 'XaXa', '([X](a){1}){2}' from rdb$database union all select + 'XaXa', '([X]a{1}){2}' from rdb$database + ) + select txt, ptn, case when trim(txt) similar to trim(ptn) then 1 else 0 end is_match + from d; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TXT abcZ + PTN [[:lower:]]{1,}Z + IS_MATCH 1 + + TXT abcz + PTN [[:lower:]]{1,}z + IS_MATCH 1 + + TXT abcz + PTN [[:lower:]]*z + IS_MATCH 1 + + TXT abcz + PTN [[:lower:]]+z + IS_MATCH 1 + + TXT aggagg + PTN ([[:lOwEr:]]{1}gg){2,} + IS_MATCH 1 + + TXT aggagg + PTN ([[:lOWeR:]]{1,}gg){2,} + IS_MATCH 1 + + TXT aggagg + PTN (a{1}gg){2} + IS_MATCH 1 + + TXT aggagg + PTN (a{0,}gg){2} + IS_MATCH 1 + + TXT aggagg + PTN (a{1}__){2} + IS_MATCH 1 + + TXT aggagg + PTN (a{1}__){1,} + IS_MATCH 1 + + TXT aggagg + PTN (a{1}[b-z]{2}){2} + IS_MATCH 1 + + TXT XabaXa + PTN ([X](a|b){1,3}){2} + IS_MATCH 1 + + TXT XabaXaba + PTN ([X](a|b){3}){2} + IS_MATCH 1 + + TXT XabaX + PTN ([X](a|b){0,3}){1,} + IS_MATCH 1 + + TXT XabaX + PTN ([X](a|b){0,3}){2} + IS_MATCH 1 + + TXT XaX + PTN ([X](a){0,1}){2} + IS_MATCH 1 + + TXT XaXa + PTN ([X](a){1}){2} + IS_MATCH 1 + + TXT XaXa + PTN ([X]a{1}){2} + IS_MATCH 1 + """ + +@pytest.mark.version('>=3.0') +def test_core_4740_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4743.py b/tests/bugs/test_core_4743.py new file mode 100644 index 00000000..6a3a5f63 --- /dev/null +++ b/tests/bugs/test_core_4743.py @@ -0,0 +1,371 @@ +#coding:utf-8 +# +# id: bugs.core_4743 +# title: Granted role does not work with non-ascii username +# decription: +# Test creates non-ascii user and role, and also several kind of DB objects (table, procedure, function etc). +# Then role is granted to user, and privileges for DB objects are granted to this role. +# All these actions are done in ISQL which is launched as separate (child) process. +# No errors must be raised in it (see 'f_ddl_log' - it must remain empty). +# +# Further, we try to establish connection to the test DB using non-ascii user and role. +# +# ::: NB ::: +# Attempt to use ISQL for connect with non-ascii login will FAIL with: +# Statement failed, SQLSTATE = 22021 +# Bad international character in tag isc_dpb_user_name +# -Cannot transliterate character between character sets +# -Invalid or incomplete multibyte or wide character +# +# Fortunately, this can be done without problems using fdb.connect(). +# +# After connect, we obtain: +# * name of current user and his role (both of them must be non-ascii); +# * privileges that was granted to this user (see query to v_current_privileges); +# +# Finally, we disconnect, generate SQL script for drop this user and run ISQL for this +# (we have to do this because it seems that there is no way to drop NON-ASCII user via FDB Services). +# +# NOTE: Python package 'io' is used here instead of codecs (the latter is obsolete in Python). +# +# Checked on: 4.0.0.2416 (Windows and Linux) +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: bugs.core_4743 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[\t ]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import io +# #import codecs +# import subprocess +# import time +# +# db_conn.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 ) +# +# #-------------------------------------------- +# +# sql_txt=''' set bail on; +# set names utf8; +# connect '%(dsn)s' user '%(user_name)s' password '%(user_password)s'; +# +# create or alter user "Вася Пупкин" password '123' using plugin Srp; +# create role "Старший дворник"; +# commit; +# +# grant "Старший дворник" to "Вася Пупкин"; +# commit; +# +# create table "Документы"(id int primary key, pid int references "Документы"); +# create exception "НЕ_число" 'Ваша строка не может быть преобразована в число.'; +# create sequence "ИД_документа"; +# set term ^; +# create procedure "Хранимка" as +# begin +# end +# ^ +# create function "СтрВЧисло"(a_text varchar(100)) returns int as +# begin +# return 0; +# end +# ^ +# +# create or alter package "Утилиты" as +# begin +# procedure pg_sp_worker; +# end +# ^ +# recreate package body "Утилиты" as +# begin +# procedure pg_sp_worker as +# begin +# end +# end +# ^ +# set term ;^ +# commit; +# +# create or alter view v_current_privileges as +# select +# g.rdb$user as who_is_granted +# ,g.rdb$relation_name as obj_name +# ,decode( g.rdb$object_type +# ,0,'table' +# ,1,'view' +# ,2,'trigger' +# ,5,'procedure' +# ,7,'exception' +# ,9,'domain' +# ,11,'charset' +# ,13,'role' +# ,14,'generator' +# ,15,'function' +# ,16,'blob filt' +# ,18,'package' +# ,22,'systable' +# ,cast(g.rdb$object_type as varchar(50)) +# ) as obj_type +# ,max(iif(g.rdb$privilege='S','YES',' ')) as "privilege:select" +# ,max(iif(g.rdb$privilege='I','YES',' ')) as "privilege:insert" +# ,max(iif(g.rdb$privilege='U','YES',' ')) as "privilege:update" +# ,max(iif(g.rdb$privilege='D','YES',' ')) as "privilege:delete" +# ,max(iif(g.rdb$privilege='G','YES',' ')) as "privilege:usage" +# ,max(iif(g.rdb$privilege='X','YES',' ')) as "privilege:exec" +# ,max(iif(g.rdb$privilege='R','YES',' ')) as "privilege:refer" +# ,max(iif(g.rdb$privilege='C','YES',' ')) as "privilege:create" +# ,max(iif(g.rdb$privilege='L','YES',' ')) as "privilege:alter" +# ,max(iif(g.rdb$privilege='O','YES',' ')) as "privilege:drop" +# ,max(iif(g.rdb$privilege='M','YES',' ')) as "privilege:member" +# from rdb$user_privileges g +# where g.rdb$user in( current_user, current_role ) +# group by 1,2,3; +# +# grant select on v_current_privileges to "Старший дворник"; +# grant select,insert,update,delete,references on "Документы" to "Старший дворник"; +# grant usage on exception "НЕ_число" to "Старший дворник"; +# grant usage on sequence "ИД_документа" to "Старший дворник"; +# grant execute on procedure "Хранимка" to "Старший дворник"; +# grant execute on function "СтрВЧисло" to "Старший дворник"; +# grant execute on package "Утилиты" to "Старший дворник"; +# grant create table to "Старший дворник"; +# grant alter any table to "Старший дворник"; +# grant drop any table to "Старший дворник"; +# commit; +# +# /* +# DO NOT try to use ISQL for connecti using non-ascii user name! It will fail with: +# ===== +# Statement failed, SQLSTATE = 22021 +# Bad international character in tag isc_dpb_user_name +# -Cannot transliterate character between character sets +# -Invalid or incomplete multibyte or wide character +# ===== +# XXX DOES NOT WORK XXX >>> connect '%(dsn)s' user "Вася Пупкин" password '123' role "Старший дворник"; +# Instead, FDB connect() method must be used for this. +# */ +# ''' % dict(globals(), **locals()) +# +# f_ddl_sql = open( os.path.join(context['temp_directory'], 'tmp_4743_utf8_ddl.sql'), 'w' ) +# f_ddl_sql.write( sql_txt ) +# flush_and_close( f_ddl_sql ) +# +# f_ddl_log = open( os.path.splitext(f_ddl_sql.name)[0]+'.log', 'w') +# subprocess.call( [ context['isql_path'], '-q', '-i', f_ddl_sql.name ], +# stdout = f_ddl_log, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_ddl_log ) +# +# with io.open(f_ddl_log.name, 'r', encoding='utf8' ) as f: +# result_log = f.readlines() +# +# for i in result_log: +# print( i.encode('utf8') ) # do not miss '.encode()' here, otherwise get: "ordinal not in range(128)" +# +# f_run_log = io.open( os.path.join(context['temp_directory'], 'tmp_4743_utf8_run.log'), 'w', encoding = 'utf8' ) +# +# con = fdb.connect(dsn = dsn, user = "Вася Пупкин", password = '123', role = 'Старший дворник', charset = 'utf8', utf8params = True) +# cur = con.cursor() +# cur.execute('select m.mon$user,m.mon$role from mon$attachments m where m.mon$attachment_id = current_connection') +# col = cur.description +# for r in cur: +# for i in range(0,len(col)): +# f_run_log.write( ' '.join((col[i][0],':',r[i], '\\n')) ) +# +# cur.execute('select v.* from v_current_privileges v') +# col = cur.description +# for r in cur: +# for i in range(0,len(col)): +# if 'privilege:' not in col[i][0] or 'privilege:' in col[i][0] and r[i] == 'YES': +# f_run_log.write( ' '.join((col[i][0],':',r[i], '\\n')) ) +# +# flush_and_close( f_run_log ) +# +# # Check that privileges actually work for current (non-ascii) user / role: +# ##################################### +# # All following actions must not raise any exception: +# +# ''' +# ### DEFERRED ### +# Got exception on Linux: +# - SQLCODE: -104 +# - Dynamic SQL Error +# - SQL error code = -104 +# - Token unknown - line 1, column 13 +# - "Документы" +# -104 +# 335544569 +# +# con.execute_immediate('insert into "Документы"(id) values(gen_id("ИД_документа",1))') +# cur.callproc('"Хранимка"') +# cur.execute('select "СтрВЧисло"(?) from rdb$database', (123,)) +# for r in cur: +# pass +# +# cur.callproc('"Утилиты".pg_sp_worker') +# ''' +# +# cur.close() +# con.close() +# +# # Generate SQL script for DROP non-ascii user. +# ############################################## +# sql_txt=''' +# set bail on; +# set names utf8; +# set list on; +# -- set echo on; +# connect '%(dsn)s' user '%(user_name)s' password '%(user_password)s'; +# select count(*) non_ascii_user_before_drop from sec$users where sec$user_name ='Вася Пупкин'; +# drop user "Вася Пупкин" using plugin Srp; +# commit; +# select count(*) non_ascii_user_after_drop from sec$users where sec$user_name ='Вася Пупкин'; +# ''' % dict(globals(), **locals()) +# +# f_drop_sql = open( os.path.join(context['temp_directory'], 'tmp_4743_utf8_drop.sql'), 'w' ) +# f_drop_sql.write( sql_txt ) +# flush_and_close( f_drop_sql ) +# +# f_drop_log = open( os.path.splitext(f_drop_sql.name)[0]+'.log', 'w') +# subprocess.call( [ context['isql_path'], '-q', '-i', f_drop_sql.name ], +# stdout = f_drop_log, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_drop_log ) +# +# with io.open(f_run_log.name, 'r', encoding='utf8' ) as f: +# result_in_utf8 = f.readlines() +# +# for i in result_in_utf8: +# print( i.encode('utf8') ) +# +# with open(f_drop_log.name,'r') as f: +# for line in f: +# print(line) +# +# # cleanup: +# ########### +# time.sleep(2) +# +# # DO NOT use here: cleanup( (f_ddl_sql, f_ddl_log, f_drop_sql, f_drop_log, f_run_log) ) -- +# # Unrecognized type of element: - can not be treated as file. +# # type(f_names_list[i])= Traceback (most recent call last): +# +# cleanup( [i.name for i in (f_ddl_sql, f_ddl_log, f_drop_sql, f_drop_log, f_run_log)] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MON$USER : Вася Пупкин + MON$ROLE : Старший дворник + + WHO_IS_GRANTED : Вася Пупкин + OBJ_NAME : Старший дворник + OBJ_TYPE : role + privilege:member : YES + + WHO_IS_GRANTED : Старший дворник + OBJ_NAME : SQL$TABLES + OBJ_TYPE : systable + privilege:create : YES + privilege:alter : YES + privilege:drop : YES + + WHO_IS_GRANTED : Старший дворник + OBJ_NAME : V_CURRENT_PRIVILEGES + OBJ_TYPE : table + privilege:select : YES + + WHO_IS_GRANTED : Старший дворник + OBJ_NAME : Документы + OBJ_TYPE : table + privilege:select : YES + privilege:insert : YES + privilege:update : YES + privilege:delete : YES + privilege:refer : YES + + WHO_IS_GRANTED : Старший дворник + OBJ_NAME : ИД_документа + OBJ_TYPE : generator + privilege:usage : YES + + WHO_IS_GRANTED : Старший дворник + OBJ_NAME : НЕ_число + OBJ_TYPE : exception + privilege:usage : YES + + WHO_IS_GRANTED : Старший дворник + OBJ_NAME : СтрВЧисло + OBJ_TYPE : function + privilege:exec : YES + + WHO_IS_GRANTED : Старший дворник + OBJ_NAME : Утилиты + OBJ_TYPE : package + privilege:exec : YES + + WHO_IS_GRANTED : Старший дворник + OBJ_NAME : Хранимка + OBJ_TYPE : procedure + privilege:exec : YES + + NON_ASCII_USER_BEFORE_DROP 1 + NON_ASCII_USER_AFTER_DROP 0 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_4743_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4744.py b/tests/bugs/test_core_4744.py new file mode 100644 index 00000000..1e713876 --- /dev/null +++ b/tests/bugs/test_core_4744.py @@ -0,0 +1,128 @@ +#coding:utf-8 +# +# id: bugs.core_4744 +# 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 +# decription: +# tracker_id: CORE-4744 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + select rdb$character_set_name from rdb$database; + + commit; + + create or alter view v_table_field_cset as + select + rf.rdb$relation_name tab_name + ,rf.rdb$field_name fld_name + ,cs.rdb$character_set_name fld_cset + ,rb.RDB$CHARACTER_SET_NAME db_default_cset + from rdb$relation_fields rf + join rdb$fields ff on rf.rdb$field_source = ff.rdb$field_name + left join rdb$character_sets cs on ff.rdb$character_set_id = cs.rdb$character_set_id + cross join rdb$database rb + ; + commit; + + -------- CHANGE DATABASE DEFAULT CHARSET, COMMAND # 1 -------- + + alter database set default character set dos850; + commit; + + create table tab_850( txt_850 varchar(10)); commit; + select * from v_table_field_cset where tab_name=upper('tab_850'); + + -------- CHANGE DATABASE DEFAULT CHARSET, COMMAND # 2 -------- + + alter database set default character set dos866; + commit; + + create table tab_866( txt_866 varchar(10)); commit; + select * from v_table_field_cset where tab_name=upper('tab_866'); + + -------- CHANGE DATABASE DEFAULT CHARSET, COMMAND # 3 -------- + + alter database set default character set win1252; + commit; + + create table tab_1252( txt_1252 varchar(10)); commit; + select * from v_table_field_cset where tab_name=upper('tab_1252'); + + -------- CHANGE DATABASE DEFAULT CHARSET TO NON-EXISTED VALUE -------- + + alter database set default character set FOO_BAR_8859_4; + commit; + + create table tab_foo( txt_8859_4 varchar(10) ); + commit; + create table tab_bar( txt_8859_4 varchar(10) character set FOO_BAR_8859_4); + commit; + + select * from v_table_field_cset where tab_name=upper('tab_foo'); + select * from v_table_field_cset where tab_name=upper('tab_bar'); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$CHARACTER_SET_NAME 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 + + TAB_NAME TAB_FOO + FLD_NAME TXT_8859_4 + FLD_CSET WIN1252 + DB_DEFAULT_CSET WIN1252 + """ +expected_stderr_1 = """ + 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 + """ + +@pytest.mark.version('>=3.0') +def test_core_4744_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4747.py b/tests/bugs/test_core_4747.py new file mode 100644 index 00000000..374ba870 --- /dev/null +++ b/tests/bugs/test_core_4747.py @@ -0,0 +1,114 @@ +#coding:utf-8 +# +# id: bugs.core_4747 +# title: Error "invalid BLOB ID" can occur when retrieving MON$STATEMENTS.MON$SQL_TEXT using ES/EDS and db_connect argument is not specified +# decription: +# 21.05.2017: +# FB25Cs, build 2.5.8.27062: OK, 0.703ss. +# FB25SC, build 2.5.8.27062: OK, 0.406ss. +# fb25sS, build 2.5.8.27062: OK, 0.468ss. +# fb30Cs, build 3.0.3.32725: OK, 2.516ss. +# fb30SC, build 3.0.3.32725: OK, 1.438ss. +# FB30SS, build 3.0.3.32725: OK, 1.016ss. +# FB40CS, build 4.0.0.645: OK, 2.172ss. +# FB40SC, build 4.0.0.645: OK, 1.250ss. +# FB40SS, build 4.0.0.645: OK, 1.172ss. +# +# tracker_id: CORE-4747 +# min_versions: ['2.5.6'] +# versions: 2.5.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.6 +# resources: None + +substitutions_1 = [('RUNNING_STT_ID[ ]+[0-9]+', 'RUNNING_STT_ID'), ('RUNNING_TRN_ID[ ]+[0-9]+', 'RUNNING_TRN_ID'), ('RUNNING_STT_TEXT.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set blob all; + + recreate table test(sid int, tid int, txt blob); + commit; + + -- NB, 21.05.2017: 4.0 Classic now has record in mon$statements with data from RDB$AUTH_MAPPING table. + -- We have to prevent appearance of this row in resultset which is to be analyzed, thus adding clause: + -- "where s.mon$sql_text containing 'test' ..." + + insert into test(sid, tid, txt) select s.mon$statement_id, s.mon$transaction_id, s.mon$sql_text from mon$statements s where s.mon$sql_text containing 'test' rows 1; + commit; + + set term ^; + execute block returns( msg varchar(10), running_stt_id int, running_trn_id int, running_stt_text blob) as + declare v_dbname varchar(255); + declare v_stt1 varchar(1024) = 'select t.sid, t.tid, t.txt from test t'; + declare v_stt2 varchar(1024) = 'select s.mon$statement_id, s.mon$transaction_id, s.mon$sql_text from mon$statements s where s.mon$sql_text containing ''test'' and s.mon$transaction_id = current_transaction rows 1'; + declare v_usr rdb$user = 'sysdba'; + declare v_pwd varchar(20) = 'masterkey'; + declare v_trn int; + begin + -- NOTE: v_dbname is NOT initialized with database connection string. + + msg = 'point-1'; + execute statement (v_stt1) + on external (v_dbname) + as user :v_usr password :v_pwd + into running_stt_id, running_trn_id, running_stt_text; + suspend; + + msg = 'point-2'; + execute statement (v_stt2) + on external (v_dbname) + as user :v_usr password :v_pwd + into running_stt_id, running_trn_id, running_stt_text ; + 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG point-1 + RUNNING_STT_ID 111 + RUNNING_TRN_ID 219 + RUNNING_STT_TEXT 91:0 + insert into test(sid, tid, txt) select s.mon$statement_id, s.mon$transaction_id, s.mon$sql_text from mon$statements s where s.mon$sql_text containing 'test' rows 1 + + MSG point-2 + RUNNING_STT_ID 140 + RUNNING_TRN_ID 224 + RUNNING_STT_TEXT 0:1 + select s.mon$statement_id, s.mon$transaction_id, s.mon$sql_text from mon$statements s where s.mon$sql_text containing 'test' and s.mon$transaction_id = current_transaction rows 1 + """ + +@pytest.mark.version('>=2.5.6') +def test_core_4747_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4748.py b/tests/bugs/test_core_4748.py new file mode 100644 index 00000000..c567428a --- /dev/null +++ b/tests/bugs/test_core_4748.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: bugs.core_4748 +# title: Can not restore in FB 3.0 SuperServer from .fbk which source .fdb was created on 2.5.4 and moved to READ-ONLY before backed up +# decription: +# tracker_id: CORE-4748 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core_4748_read_only_25.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + select mon$read_only as restored_ro from mon$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESTORED_RO 1 + """ + +@pytest.mark.version('>=3.0') +def test_core_4748_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4752.py b/tests/bugs/test_core_4752.py new file mode 100644 index 00000000..bab78486 --- /dev/null +++ b/tests/bugs/test_core_4752.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_4752 +# title: EXECUTE STATEMENT using BLOB parameters results in "Invalid BLOB ID" error +# decription: +# tracker_id: CORE-4752 +# min_versions: ['2.5.5'] +# versions: 2.5.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table tb(id int, b1 blob); + commit; + insert into tb(id) values(1); + insert into tb(id) values(2); + insert into tb(id) values(3); + commit; + + set term ^; + execute block as + declare v_stt varchar(255); + declare v_blob_a blob = 'qwertyuioplkjhgfdsazxcvbnm'; + declare v_blob_b blob = '1234567890asdfghjklmnbvcxz'; + begin + v_stt = 'update tb set b1 = case when id in (1,2) then cast(? as blob) else cast(? as blob) end'; + execute statement ( v_stt ) ( v_blob_a, v_blob_b ); + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.5') +def test_core_4752_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_4754.py b/tests/bugs/test_core_4754.py new file mode 100644 index 00000000..4a25d530 --- /dev/null +++ b/tests/bugs/test_core_4754.py @@ -0,0 +1,114 @@ +#coding:utf-8 +# +# id: bugs.core_4754 +# title: Bugcheck 167 (invalid SEND request) while working with GTT from several attachments (using EXECUTE STATEMENT ... ON EXTERNAL and different roles) +# decription: +# We start two transactions and do DML ('insert ...') in 1st and DDL ('create index ...') in second. +# Then we issue COMMIT in DDL transaction. This should raise 'lock conflict ... table "" is in use'. +# On 2.5.4 this COMMIT in DDL did NOT raise any error and subsequent reconnect and DML raised bugcheck. +# +# Checked on 2.5.6.27013, 3.0.1.32524 - works OK. +# Bugcheck can be reproduced on 2.5.4.26856. +# +# PS. Old ticket name: +# Manipulations with GTT from several attachments (using ES/EDS and different roles) leads to: +# "internal Firebird consistency check (invalid SEND request (167), file: JrdStatement.cpp line: 325)" +# +# tracker_id: CORE-4754 +# min_versions: ['2.5.5'] +# versions: 2.5.5 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate global temporary table gtt_session(x int, y int) on commit preserve rows; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import fdb +# +# db_conn.close() +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# #db_file="$(DATABASE_LOCATION)bugs.core_4754.fdb" +# +# customTPB = ( [ fdb.isc_tpb_read_committed, fdb.isc_tpb_rec_version, fdb.isc_tpb_nowait ] ) +# con1 = fdb.connect(dsn=dsn) +# #print(con1.firebird_version) +# +# tx1a=con1.trans( default_tpb = customTPB ) +# tx1b=con1.trans( default_tpb = customTPB ) +# cur1a = tx1a.cursor() +# cur1b = tx1b.cursor() +# msg='' +# try: +# cur1a.execute( "insert into gtt_session select rand()*10, rand()*10 from rdb$types" ) +# cur1b.execute( "create index gtt_session_x_y on gtt_session computed by ( x+y )" ) +# tx1b.commit() # WI-V2.5.6.27013 issues here: lock conflict on no wait transaction unsuccessful metadata update object TABLE "GTT_SESSION" is in use -901 335544345 +# tx1a.commit() +# except Exception as e: +# print('Error-1:') +# msg = e[0] +# print(msg) +# +# con1.close() +# +# +# # --------------------------------------------------------------- +# +# if not msg.split(): +# # 2.5.5: control should NOT pass here at all! +# con2 = fdb.connect(dsn=dsn) +# try: +# tx2a = con2.trans() +# cur2a = tx2a.cursor() +# ''' +# Following INSERT statement will raise on WI-V2.5.4.26856: +# fdb.fbcore.DatabaseError: ('Error while executing SQL statement: +# - SQLCODE: -902 +# - internal Firebird consistency +# check (invalid SEND request (167), file: exe.cpp line: 614)', -902, 335544333) +# Exception fdb.fbcore.DatabaseError: DatabaseError("Error while rolling back transaction: +# - SQLCODE: -902 +# - intern +# al Firebird consistency check (can't continue after bugcheck)", -902, 335544333) in > ignored +# ''' +# cur2a.execute( "insert into gtt_session select rand()*11, rand()*11 from rdb$types" ) +# except Exception as e: +# print('Error-2:') +# print(e[0]) +# con2.close() +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Error-1: + Error while commiting transaction: + - SQLCODE: -901 + - lock conflict on no wait transaction + - unsuccessful metadata update + - object TABLE "GTT_SESSION" is in use + """ + +@pytest.mark.version('>=2.5.5') +@pytest.mark.xfail +def test_core_4754_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4755.py b/tests/bugs/test_core_4755.py new file mode 100644 index 00000000..70c39304 --- /dev/null +++ b/tests/bugs/test_core_4755.py @@ -0,0 +1,103 @@ +#coding:utf-8 +# +# id: bugs.core_4755 +# title: Parameterized exception: wrong output when number of arguments greater than 7 +# decription: +# tracker_id: CORE-4755 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('-At block line: [\\d]+, col: [\\d]+', '-At block line')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate exception ex_something_wrong 'Arguments for raising exeption: @1 @2 @3 @4 @5 @6 @7 @8 @9'; + commit; + set term ^; + execute block as + declare v_1 int = 10001; + declare v_2 int = 10002; + declare v_3 int = 10003; + declare v_4 int = 10004; + declare v_5 int = 10005; + declare v_6 int = 10006; + declare v_7 int = 10007; + declare v_8 int = 10008; + declare v_9 int = 10009; + begin + exception ex_something_wrong using( + v_1 + ,v_2 + ,v_3 + ,v_4 + ,v_5 + ,v_6 + ,v_7 + ,v_8 + ,v_9 + ); + end + ^ + set term ;^ + commit; + + recreate exception ex_too_much_detailed 'Arguments for raising exeption: @1 @2 @3 @4 @5 @6 @7 @8 @9 @10'; + commit; + set term ^; + execute block as + declare v_1 int = 10001; + declare v_2 int = 10002; + declare v_3 int = 10003; + declare v_4 int = 10004; + declare v_5 int = 10005; + declare v_6 int = 10006; + declare v_7 int = 10007; + declare v_8 int = 10008; + declare v_9 int = 10009; + declare v_10 int = 10010; + begin + exception ex_too_much_detailed using( + v_1 + ,v_2 + ,v_3 + ,v_4 + ,v_5 + ,v_6 + ,v_7 + ,v_8 + ,v_9 + ,v_10 + ); + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + 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 + Statement failed, SQLSTATE = 07002 + Number of arguments (10) exceeds the maximum (9) number of EXCEPTION USING arguments + """ + +@pytest.mark.version('>=3.0') +def test_core_4755_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_4760.py b/tests/bugs/test_core_4760.py new file mode 100644 index 00000000..5e152111 --- /dev/null +++ b/tests/bugs/test_core_4760.py @@ -0,0 +1,174 @@ +#coding:utf-8 +# +# id: bugs.core_4760 +# title: Can not create user with non-ascii (multi-byte) characters in it's name +# decription: +# User with name Εὐκλείδης ('Euclid') encoded in UTF8 is used in this test. +# +# NB-1: connection is made using FDB connect() method: ISQL (and also its CONNECT statement) has +# problems when trying to use non-ascii names. +# NB-2: separate SQL script is generated for DROP this user. +# +# Checked on: 4.0.0.2416 (Windows and Linux) +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: bugs.core_4760 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[\t ]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import io +# import subprocess +# import time +# +# db_conn.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 ) +# +# #-------------------------------------------- +# +# sql_txt=''' set bail on; +# set names utf8; +# connect '%(dsn)s' user '%(user_name)s' password '%(user_password)s'; +# +# create or alter user "Εὐκλείδης" password '123' using plugin Srp; +# ''' % dict(globals(), **locals()) +# +# f_ddl_sql = open( os.path.join(context['temp_directory'], 'tmp_4760_utf8_ddl.sql'), 'w' ) +# f_ddl_sql.write( sql_txt ) +# flush_and_close( f_ddl_sql ) +# +# f_ddl_log = open( os.path.splitext(f_ddl_sql.name)[0]+'.log', 'w') +# subprocess.call( [ context['isql_path'], '-q', '-i', f_ddl_sql.name ], +# stdout = f_ddl_log, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_ddl_log ) +# +# with io.open(f_ddl_log.name, 'r', encoding='utf8' ) as f: +# result_log = f.readlines() +# +# for i in result_log: +# print( i.encode('utf8') ) # do not miss '.encode()' here, otherwise get: "ordinal not in range(128)" +# +# f_run_log = io.open( os.path.join(context['temp_directory'], 'tmp_4760_utf8_run.log'), 'w', encoding = 'utf8' ) +# +# con = fdb.connect(dsn = dsn, user = "Εὐκλείδης", password = '123', charset = 'utf8', utf8params = True) +# cur = con.cursor() +# cur.execute('select m.mon$user from mon$attachments m where m.mon$attachment_id = current_connection') +# col = cur.description +# for r in cur: +# for i in range(0,len(col)): +# f_run_log.write( ' '.join((col[i][0],':',r[i], '\\n')) ) +# +# cur.close() +# con.close() +# flush_and_close(f_run_log) +# +# # Generate SQL script for DROP non-ascii user. +# ############################################## +# sql_txt=''' +# set bail on; +# set names utf8; +# set list on; +# -- set echo on; +# connect '%(dsn)s' user '%(user_name)s' password '%(user_password)s'; +# select count(*) non_ascii_user_before_drop from sec$users where sec$user_name ='Εὐκλείδης'; +# drop user "Εὐκλείδης" using plugin Srp; +# commit; +# select count(*) non_ascii_user_after_drop from sec$users where sec$user_name ='Εὐκλείδης'; +# ''' % dict(globals(), **locals()) +# +# f_drop_sql = open( os.path.join(context['temp_directory'], 'tmp_4760_utf8_drop.sql'), 'w' ) +# f_drop_sql.write( sql_txt ) +# flush_and_close( f_drop_sql ) +# +# f_drop_log = open( os.path.splitext(f_drop_sql.name)[0]+'.log', 'w') +# subprocess.call( [ context['isql_path'], '-q', '-i', f_drop_sql.name ], +# stdout = f_drop_log, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_drop_log ) +# +# with io.open(f_run_log.name, 'r', encoding='utf8' ) as f: +# result_in_utf8 = f.readlines() +# +# +# for i in result_in_utf8: +# print( i.encode('utf8') ) +# +# with open(f_drop_log.name,'r') as f: +# for line in f: +# print(line) +# +# # cleanup: +# ########### +# time.sleep(2) +# +# # DO NOT use here: cleanup( (f_ddl_sql, f_ddl_log, f_drop_sql, f_drop_log, f_run_log) ) -- +# # Unrecognized type of element: - can not be treated as file. +# # type(f_names_list[i])= Traceback (most recent call last): +# +# cleanup( [i.name for i in (f_ddl_sql, f_ddl_log, f_drop_sql, f_drop_log, f_run_log)] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MON$USER : Εὐκλείδης + NON_ASCII_USER_BEFORE_DROP 1 + NON_ASCII_USER_AFTER_DROP 0 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_4760_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4766.py b/tests/bugs/test_core_4766.py new file mode 100644 index 00000000..87b7b5e7 --- /dev/null +++ b/tests/bugs/test_core_4766.py @@ -0,0 +1,262 @@ +#coding:utf-8 +# +# id: bugs.core_4766 +# title: AV when trying to manage users list using EXECUTE STATEMENT on behalf of non-sysdba user which has RDB$ADMIN role +# decription: +# 05.01.2020. Refactored in order to make its code more flexible because 3.0 and 4.0 have significant differences in stdout/stderr. +# Common SQL code was stored in fbt-repo +# iles\\core_4766.sql with embedding variable names there from here: +# %(current_auth_plugin)s, %(dsn)s et al. +# +# Content of this file is stored in variable 'sql_text' and this variable is changed using common Python rule for substitutions: +# sql_text % dict(globals(), **locals() +# +# Then we save this variable to temporarily .sql script and run it. +# This action is done for two possible values of auth plugin (see var. current_auth_plugin): Srp and Legacy_UserManager. +# +# As result, we have to compare only expected* data for different FB major versions. +# +# ::: NB ::: +# Only Legacy_UserManager is checked for FB 4.0. Srp has totally different behaviour, at least for 4.0.0.1714. +# Sent letter to dimitr and alex, 05.01.2020 22:00. +# +# Crash is reproduced on WI-T3.0.0.31374 Firebird 3.0 Beta 1 (build 24-nov-2014). +# +# Checked on: +# 4.0.0.1743 SS: 1.452s. +# 4.0.0.1740 SC: 1.870s. +# 4.0.0.1714 CS: 10.240s. +# 3.0.6.33236 SS: 1.220s. +# 3.0.5.33221 SC: 5.416s. +# 3.0.5.33084 CS: 2.891s. +# +# +# tracker_id: CORE-4766 +# min_versions: ['3.0'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('TCPv.*', 'TCP'), ('.*After line \\d+.*', ''), ('find/delete', 'delete'), ('TABLE PLG\\$.*', 'TABLE PLG')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# this_db = db_conn.database_name +# db_conn.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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# #-------------------------------------------- +# +# f_sql=open(os.path.join(context['files_location'],'core_4766.sql'),'r') +# sql_text = f_sql.read() +# f_sql.close() +# +# for current_auth_plugin in ('Srp', 'Legacy_UserManager'): +# f_sql_chk = open( os.path.join(context['temp_directory'],'tmp_core_4766.' + current_auth_plugin[:3] + '.sql'), 'w') +# f_sql_chk.write( sql_text % dict(globals(), **locals()) ) +# flush_and_close( f_sql_chk ) +# +# f_sql_log = open( '.'.join( (os.path.splitext( f_sql_chk.name )[0], 'log') ), 'w') +# subprocess.call( [ context['isql_path'], '-q', '-i', f_sql_chk.name ], stdout = f_sql_log, stderr = subprocess.STDOUT) +# flush_and_close( f_sql_log ) +# +# with open( f_sql_log.name,'r') as f: +# for line in f: +# if line.strip(): +# print( current_auth_plugin[:3] + ': ' + line ) +# +# cleanup( (f_sql_log.name, f_sql_chk.name) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +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 + + + 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: 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 + + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4766_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + +# version: 4.0 +# resources: None + +substitutions_2 = [('TCPv.*', 'TCP'), ('.*After line \\d+.*', ''), ('find/delete', 'delete'), ('TABLE PLG\\$.*', 'TABLE PLG')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +# test_script_2 +#--- +# +# import os +# import sys +# import subprocess +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# this_db = db_conn.database_name +# db_conn.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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# +# #-------------------------------------------- +# +# f_sql=open(os.path.join(context['files_location'],'core_4766.sql'),'r') +# sql_text = f_sql.read() +# f_sql.close() +# +# # ::: NB ::: +# # Only Legacy_UserManager is checked for FB 4.0. Srp has totally different behaviour, at least for 4.0.0.1714. +# # Sent letter to dimitr and alex, 05.01.2020 22:00. +# +# for current_auth_plugin in ('Legacy_UserManager',): +# f_sql_chk = open( os.path.join(context['temp_directory'],'tmp_core_4766.' + current_auth_plugin[:3] + '.sql'), 'w') +# f_sql_chk.write( sql_text % dict(globals(), **locals()) ) +# flush_and_close( f_sql_chk ) +# +# f_sql_log = open( '.'.join( (os.path.splitext( f_sql_chk.name )[0], 'log') ), 'w') +# subprocess.call( [ context['isql_path'], '-q', '-i', f_sql_chk.name ], stdout = f_sql_log, stderr = subprocess.STDOUT) +# flush_and_close( f_sql_log ) +# +# with open( f_sql_log.name,'r') as f: +# for line in f: +# if line.strip(): +# print( current_auth_plugin[:3] + ': ' + line ) +# +# cleanup( (f_sql_log.name, f_sql_chk.name) ) +# +# ''' +# 'substitutions':[ +# ('TCPv.*', 'TCP'), +# ('.*After line \\d+.*', ''), +# ('find/delete', 'delete'), +# ('TABLE PLG\\$.*', 'TABLE PLG') +# ] +# ''' +# +# +#--- +#act_2 = python_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + 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: -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: -Effective user is TMP_4766_BOSS + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_4766_2(db_2): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4767.py b/tests/bugs/test_core_4767.py new file mode 100644 index 00000000..1ac393c7 --- /dev/null +++ b/tests/bugs/test_core_4767.py @@ -0,0 +1,79 @@ +#coding:utf-8 +# +# id: bugs.core_4767 +# title: CREATE USER ... TAGS ( attr = 'prefix #suffix' ): suffix will be removed from storage because of character '#' in the value of attribute +# decription: +# Checked on: +# FB30SS, build 3.0.4.32985: OK, 0.985s. +# FB40SS, build 4.0.0.1000: OK, 1.281s. +# +# tracker_id: CORE-4767 +# min_versions: ['3.0.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + create or alter view v_user_tags as + select + a.sec$key tag + ,a.sec$value val + from sec$users u + left join sec$user_attributes a on u.sec$user_name = a.sec$user_name + where upper(u.sec$user_name) = upper('tmp$c4767') and upper(u.sec$plugin) = upper('Srp') + ; + commit; + + create or alter user tmp$c4767 password '123' using plugin Srp tags ( + attr00001='attr #00001' + ,attr00002='#' + ,attr00003='##' + ,attr00004='$' + ,attr00005='$$' + ); + commit; + + select * from v_user_tags; + commit; + + drop user tmp$c4767 using plugin Srp; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TAG ATTR00001 + VAL attr #00001 + + TAG ATTR00002 + VAL # + + TAG ATTR00003 + VAL ## + + TAG ATTR00004 + VAL $ + + TAG ATTR00005 + VAL $$ + """ + +@pytest.mark.version('>=3.0') +def test_core_4767_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4768.py b/tests/bugs/test_core_4768.py new file mode 100644 index 00000000..11c1b4ab --- /dev/null +++ b/tests/bugs/test_core_4768.py @@ -0,0 +1,144 @@ +#coding:utf-8 +# +# id: bugs.core_4768 +# title: CREATE USER ... TAGS ( argument_1 = 'value1', ..., argument_N = 'valueN' ) - wrong results of statement when there are many arguments +# decription: +# Checked on: +# FB30SS, build 3.0.4.32985: OK, 7.672s. +# FB40SS, build 4.0.0.1000: OK, 13.094s. +# +# tracker_id: CORE-4768 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# #-------------------------------------------- +# +# 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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# +# #-------------------------------------------- +# +# +# TAGS_COUNT=100000 +# #^^^^^^^^^^^^^^^^--- TAGS COUNT: THRESHOLD +# +# f_chk_sql=open( os.path.join(context['temp_directory'],'tmp_tags_4768.sql'), 'w') +# f_chk_sql.write('set bail on;\\n') +# f_chk_sql.write("create or alter user tmp$c4768_1 password '123' using plugin Srp tags (\\n") +# +# for i in range(0,TAGS_COUNT): +# f_chk_sql.write( (' ,' if i>0 else ' ') + 'arg_'+str(i)+"='val"+str(i)+"'\\n" ) +# f_chk_sql.write(');\\n') +# f_chk_sql.write('commit;\\n') +# +# sql_check='''set count on; +# set list on; +# select +# u.sec$user_name as usr_name +# ,u.sec$plugin sec_plugin +# ,upper(min( a.sec$key )) tag_min +# ,upper(min( a.sec$value )) val_min +# ,upper(max( a.sec$key )) tag_max +# ,upper(max( a.sec$value )) val_max +# ,count(*) tag_cnt +# from sec$users u +# left join sec$user_attributes a on u.sec$user_name = a.sec$user_name +# where u.sec$user_name = upper('tmp$c4768_1') +# group by 1,2 +# ; +# commit; +# drop user tmp$c4768_1 using plugin Srp; +# commit; +# ''' +# +# f_chk_sql.write(sql_check) +# f_chk_sql.write('commit;\\n') +# +# flush_and_close( f_chk_sql ) +# +# +# f_tags_log = open( os.path.join(context['temp_directory'],'tmp_tags_4768.log'), 'w') +# f_tags_err = open( os.path.join(context['temp_directory'],'tmp_tags_4768.err'), 'w') +# +# subprocess.call( [ context['isql_path'], dsn, "-q", "-i", f_chk_sql.name], +# stdout = f_tags_log, +# stderr = f_tags_err +# ) +# +# flush_and_close( f_tags_log ) +# flush_and_close( f_tags_err ) +# +# with open(f_tags_log.name) as f: +# for line in f: +# print(line) +# +# with open(f_tags_err.name) as f: +# for line in f: +# print('UNEXPECTED STDERR: ' + line) +# +# # CLEANUP: +# ########## +# time.sleep(1) +# cleanup( [i.name for i in ( f_chk_sql, f_tags_log, f_tags_err ) ] ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + USR_NAME TMP$C4768_1 + SEC_PLUGIN Srp + TAG_MIN ARG_0 + VAL_MIN VAL0 + TAG_MAX ARG_99999 + VAL_MAX VAL99999 + TAG_CNT 100000 + Records affected: 1 + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4768_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4774.py b/tests/bugs/test_core_4774.py new file mode 100644 index 00000000..ece44199 --- /dev/null +++ b/tests/bugs/test_core_4774.py @@ -0,0 +1,48 @@ +#coding:utf-8 +# +# id: bugs.core_4774 +# title: Table aliasing is unnecessary required when doing UPDATE ... RETURNING RDB$ pseudo-columns +# decription: +# tracker_id: CORE-4774 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table t(id int, x int); + commit; + insert into t values(1, 100); + commit; + set planonly; + insert into t(id, x) values(2, 200) returning rdb$db_key; + delete from t where id=1 returning rdb$db_key; + update t set x=-x where id=2 returning rdb$db_key; + update t set x=-x where id=2 returning rdb$record_version; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (T NATURAL) + PLAN (T NATURAL) + PLAN (T NATURAL) + """ + +@pytest.mark.version('>=3.0') +def test_core_4774_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4781.py b/tests/bugs/test_core_4781.py new file mode 100644 index 00000000..3f6d5679 --- /dev/null +++ b/tests/bugs/test_core_4781.py @@ -0,0 +1,726 @@ +#coding:utf-8 +# +# id: bugs.core_4781 +# title: Maximum string length (32765 bytes) is not validated +# decription: +# tracker_id: CORE-4781 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test(bf blob); + commit; + + -- At least since 31948 following **TWO** INSERT statements work OK. + -- Before that build 2nd `insert` statement with literal length = 32766 raised exception: + -- Statement failed, SQLSTATE = 42000 + -- Dynamic SQL Error + -- -SQL error code = -104 + -- -String literal with 32766 bytes exceeds the maximum length of 32765 bytes + + -- ### NB ### do NOT insert indent (leading spaces) inside literal value below: + insert into test values( +' +000001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +001001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +002001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +003001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +004001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +005001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +006001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +007001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +008001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +009001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +010001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +011001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +012001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +013001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +014001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +015001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +016001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +017001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +018001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +019001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +020001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +021001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +022001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +023001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +024001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +025001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +026001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +027001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +028001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +029001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +030001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +031001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +032001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsj' +); +commit; + +insert into test values( +' +000001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +001001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +002001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +003001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +004001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +005001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +006001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +007001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +008001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +009001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +010001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +011001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +012001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +013001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +014001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +015001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +016001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +017001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +018001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +019001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +020001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +021001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +022001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +023001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +024001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +025001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +026001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +027001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +028001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +029001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +030001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +031001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +032001__dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsjksi2ljkqwejklwo19ll.ajqa28976a;1kla +ldlkdw89dw89d2kssdjkcsuic3892343kbmvasjhcvsdyucg872348234ejwehsj#' + ); + commit; + + set blob all; + set list on; + select + bf is null bf_is_null, + octet_length(bf), + char_length(bf) + from test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + BF_IS_NULL + OCTET_LENGTH 32765 + CHAR_LENGTH 32765 + BF_IS_NULL + OCTET_LENGTH 32766 + CHAR_LENGTH 32766 + """ + +@pytest.mark.version('>=3.0') +def test_core_4781_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4782.py b/tests/bugs/test_core_4782.py new file mode 100644 index 00000000..2171d536 --- /dev/null +++ b/tests/bugs/test_core_4782.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: bugs.core_4782 +# title: Command `SHOW TABLE` fails when the table contains field with unicode collationin its DDL +# decription: +# tracker_id: CORE-4782 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- 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; + commit; + show view v_test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$RELATION_ID (RDB$RELATION_ID) SMALLINT Nullable + View Source: + ==== ====== + select d.rdb$relation_id from rdb$database d + """ + +@pytest.mark.version('>=3.0') +def test_core_4782_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4786.py b/tests/bugs/test_core_4786.py new file mode 100644 index 00000000..a3b42b43 --- /dev/null +++ b/tests/bugs/test_core_4786.py @@ -0,0 +1,143 @@ +#coding:utf-8 +# +# id: bugs.core_4786 +# title: Problematic key value (when attempt to insert duplicate in PK/UK) is not shown where length of key >= 127 characters +# decription: +# tracker_id: CORE-4786 +# min_versions: ['2.5.5'] +# versions: 2.5.5 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test_none(s varchar(250) character set none constraint test_cset_none_unq unique using index test_cset_none_unq); + commit; + insert into test_none values( rpad('', 245, '0123456789') || 'ABCDE' ); + insert into test_none values( rpad('', 245, '0123456789') || 'ABCDE'); + commit; + + recreate table test_utf8(s varchar(169) character set utf8 constraint test_cset_utf8_unq unique using index test_cset_utf8_unq); + commit; + + -- One byte per character (not so interesting, but error message should display ALL of them, from 1st to last): + insert into test_utf8 values( rpad('', 164, 'A')||'BCDEF' ); + insert into test_utf8 values( rpad('', 164, 'A')||'BCDEF' ); + + -- Two bytes per character: character from latin-1 and letter from Serbian alphabet: + insert into test_utf8 values( rpad('', 169, 'Á') ); + insert into test_utf8 values( rpad('', 169, 'Á') ); + insert into test_utf8 values( rpad('', 169, 'Њ') ); + insert into test_utf8 values( rpad('', 169, 'Њ') ); + + -- Three bytes per character: 'euro' currency sign and mathematical 'Sigma' sign (SUM): + insert into test_utf8 values( rpad('', 169, '€') ); + insert into test_utf8 values( rpad('', 169, '€') ); + insert into test_utf8 values( rpad('', 169, '∑') ); + insert into test_utf8 values( rpad('', 169, '∑') ); + + -- Two-Three bytes_per-character combinations: + insert into test_utf8 values( rpad('', 169, 'Á∑') ); + insert into test_utf8 values( rpad('', 169, 'ÁÁ∑') ); + insert into test_utf8 values( rpad('', 169, 'ÁÁÁ∑') ); + insert into test_utf8 values( rpad('', 169, 'ÁÁÁ∑∑') ); + insert into test_utf8 values( rpad('', 169, 'ÁÁÁÁ∑') ); + insert into test_utf8 values( rpad('', 169, 'Á∑∑') ); + insert into test_utf8 values( rpad('', 169, 'Á∑∑∑') ); + insert into test_utf8 values( rpad('', 169, 'ÁÁ∑∑∑') ); + insert into test_utf8 values( rpad('', 169, 'Á∑∑∑∑') ); + + insert into test_utf8 values( rpad('', 169, 'Á∑') ); + insert into test_utf8 values( rpad('', 169, 'ÁÁ∑') ); + insert into test_utf8 values( rpad('', 169, 'ÁÁÁ∑') ); + insert into test_utf8 values( rpad('', 169, 'ÁÁÁ∑∑') ); + insert into test_utf8 values( rpad('', 169, 'ÁÁÁÁ∑') ); + insert into test_utf8 values( rpad('', 169, 'Á∑∑') ); + insert into test_utf8 values( rpad('', 169, 'Á∑∑∑') ); + insert into test_utf8 values( rpad('', 169, 'ÁÁ∑∑∑') ); + insert into test_utf8 values( rpad('', 169, 'Á∑∑∑∑') ); + + -- NB: textual key representation has a limit of 249 _bytes_, so full key can be seen only for single-byte characters. + -- Multi-byte values will be printed shorter. + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + 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.version('>=2.5.5') +def test_core_4786_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_4789.py b/tests/bugs/test_core_4789.py new file mode 100644 index 00000000..f9ddb2f7 --- /dev/null +++ b/tests/bugs/test_core_4789.py @@ -0,0 +1,113 @@ +#coding:utf-8 +# +# id: bugs.core_4789 +# title: Prohibit ability to cast timestamps that out of valid range to varchar +# decription: This test is also related to CORE-2174 +# tracker_id: CORE-4789 +# min_versions: ['2.5.5'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + --set echo on; + + -- Initial checks (from tracker stat post): + + select cast(dateadd( 87649415 hour to timestamp '01.01.0001 00:00:00.0000') as varchar(32)) text_dts_1 + from rdb$database; + + select cast(dateadd( 87649415000 hour to timestamp '01.01.0001 00:00:00.0000') as varchar(32)) text_dts_2a + from rdb$database; + + select cast(dateadd( -87649415000 hour to timestamp '31.12.9999 23:59:59.9999') as varchar(32)) text_dts_2b + from rdb$database; + + + select cast(dateadd( 8764941500000 hour to timestamp '01.01.0001 00:00:00.0000') as varchar(32)) text_dts_3a + from rdb$database; + + select cast(dateadd( -8764941500000 hour to timestamp '31.12.9999 23:59:59.9999') as varchar(32)) text_dts_3b + from rdb$database; + + -- Additional checks for boundary values: + set term ^; + execute block as + begin + rdb$set_context('USER_SESSION','MAX_DIFF_IN_MS', datediff(millisecond from timestamp '01.01.0001 00:00:00.000' to timestamp '31.12.9999 23:59:59.999' )); + end + ^ set term ;^ + + + -- Jump forward exactly to 31.12.9999 23:59:59.999 + select cast( dateadd( rdb$get_context('USER_SESSION','MAX_DIFF_IN_MS') millisecond to timestamp '01.01.0001 00:00:00.000') as varchar(32)) text_dts4 + from rdb$database; + + -- Jump forward beyond 31.12.9999 23:59:59.999 (i.e. to 01.01.10000 00:00:00.001): + select cast( dateadd( 1+cast(rdb$get_context('USER_SESSION','MAX_DIFF_IN_MS') as bigint) millisecond to timestamp '01.01.0001 00:00:00.000') as varchar(32)) text_dts5 + from rdb$database; + + -- Jump backward exactly to 01.01.0001 00:00:00.000 + select cast( dateadd( -cast(rdb$get_context('USER_SESSION','MAX_DIFF_IN_MS') as bigint) millisecond to timestamp '31.12.9999 23:59:59.999') as varchar(32)) text_dts6 + from rdb$database; + + -- Jump backward beyond 01.01.0001 00:00:00.000 (i.e. to 01.01.0000 23:59:59.999): + select cast( dateadd( -cast(rdb$get_context('USER_SESSION','MAX_DIFF_IN_MS') as bigint)-1 millisecond to timestamp '31.12.9999 23:59:59.999') as varchar(32)) text_dts7 + from rdb$database; + + + -- Check postfix ( http://sourceforge.net/p/firebird/code/61565 ): + select + cast( dateadd( 1 second to cast('00:00:00' as time) ) as varchar(15)) text_tm1 + ,cast( dateadd( 86400 second to cast('00:00:00' as time) ) as varchar(15)) text_tm2 + ,cast( dateadd(-1 second to cast('00:00:00' as time) ) as varchar(15)) text_tm3 + ,cast( dateadd(-86400 second to cast('00:00:00' as time) ) as varchar(15)) text_tm4 + from rdb$database rows 1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TEXT_DTS_1 9999-12-31 23:00:00.0000 + TEXT_DTS4 9999-12-31 23:59:59.9990 + TEXT_DTS6 0001-01-01 00:00:00.0000 + TEXT_TM1 00:00:01.0000 + TEXT_TM2 00:00:00.0000 + TEXT_TM3 23:59:59.0000 + TEXT_TM4 00:00:00.0000 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22008 + value exceeds the range for valid timestamps + Statement failed, SQLSTATE = 22008 + value exceeds the range for valid timestamps + Statement failed, SQLSTATE = 22008 + value exceeds the range for valid timestamps + Statement failed, SQLSTATE = 22008 + value exceeds the range for valid timestamps + Statement failed, SQLSTATE = 22008 + value exceeds the range for valid timestamps + Statement failed, SQLSTATE = 22008 + value exceeds the range for valid timestamps + """ + +@pytest.mark.version('>=3.0') +def test_core_4789_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4791.py b/tests/bugs/test_core_4791.py new file mode 100644 index 00000000..63706329 --- /dev/null +++ b/tests/bugs/test_core_4791.py @@ -0,0 +1,148 @@ +#coding:utf-8 +# +# id: bugs.core_4791 +# title: Make INSERTING/UPDATING/DELETING reserved words to fix ambiguity with boolean expresions +# decription: +# tracker_id: CORE-4791 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('line [0-9]+, column [0-9]+', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test1(id int, "inserting" boolean); + recreate table test2(id int, "inserting" boolean, "updating" boolean); + recreate table test3(id int, "inserting" boolean, "updating" boolean, "deleting" boolean); + recreate table test4(id int, "inserting" boolean, "updating" boolean, "deleting" boolean); + commit; + + set term ^; + create or alter trigger trg_test1_bi for test1 active before insert as + begin + new."inserting" = true; + end + ^ + + create or alter trigger trg_test2_bu for test2 active before insert or update as + begin + new."inserting" = inserting; + new."updating" = updating; + end + ^ + + create or alter trigger trg_test3_bu for test3 active before insert or update or delete as + begin + if (deleting) then + insert into test4(id, "inserting", "updating", "deleting") + values(old.id, old."inserting", old."updating", deleting); + else + begin + new."inserting" = inserting; + new."updating" = updating; + end + end + ^ + set term ;^ + commit; + + insert into test1(id) values(1); + + insert into test2(id) values(2); + update test2 set id=-id; + + insert into test3(id) values(3); + + delete from test3; + + set count on; + set echo on; + select * from test1; + + select * from test2; + + select * from test3; + + select * from test4; + + commit; + + recreate table testa(inserting int); + recreate table testb(updating int); + recreate table testc(deleting int); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + select * from test1; + + ID inserting + ============ ========= + 1 + + Records affected: 1 + + select * from test2; + + ID inserting updating + ============ ========= ======== + -2 + + Records affected: 1 + + select * from test3; + Records affected: 0 + + select * from test4; + + ID inserting updating deleting + ============ ========= ======== ======== + 3 + + Records affected: 1 + + commit; + + recreate table testa(inserting int); + recreate table testb(updating int); + recreate table testc(deleting int); + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Token unknown - line 1, column 20 + -inserting + + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Token unknown - line 1, column 20 + -updating + + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Token unknown - line 1, column 20 + -deleting + """ + +@pytest.mark.version('>=3.0') +def test_core_4791_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4798.py b/tests/bugs/test_core_4798.py new file mode 100644 index 00000000..1dc10829 --- /dev/null +++ b/tests/bugs/test_core_4798.py @@ -0,0 +1,96 @@ +#coding:utf-8 +# +# id: bugs.core_4798 +# title: Regression: MIN/MAX with a join ignores possible index navigation +# decription: +# tracker_id: CORE-4798 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='mon-stat-gathering-3_0.fbk', init=init_script_1) + +test_script_1 = """ + recreate table test(x int); + commit; + + insert into test select rand()*100 from (select 1 i from rdb$types rows 50) a, (select 1 i from rdb$types rows 50) b; + commit; + create index test_x on test(x); + commit; + set term ^; + execute block as + begin + -- #################################### + -- S E T T I N G T H R E S H O L D S + -- #################################### + rdb$set_context('USER_SESSION','NAT_READS_MAX_THRESHOLD', '0'); + rdb$set_context('USER_SESSION','IDX_READS_MAX_THRESHOLD', '20'); -- increased 27.07.2016 + end + ^ + set term ;^ + + alter sequence g_gather_stat restart with 0; + execute procedure sp_truncate_stat; + commit; + + execute procedure sp_gather_stat; ------- catch statistics BEFORE measured statement(s) + commit; + + set term ^; + execute block as + declare v_dummy int; + begin + select min(a.x) from test a join test b on a.x = b.x join test c on b.x = c.x into v_dummy; + end + ^ + set term ;^ + execute procedure sp_gather_stat; ------- catch statistics AFTER measured statement(s) + commit; + + set list on; + -- 3.0.0.31374 (Beta 1): + -- natural_reads 2500 + -- indexed_reads 1839808 + -- 3.0.0.31852: + -- natural_reads 0 + -- indexed_reads 6 + -- 4.0.0.313: + -- natural_reads 0 + -- indexed_reads 18 + select + iif( natural_reads <= nat_max, 'acceptable, <= ' || nat_max, 'abnormal, ' || natural_reads || ' > ' || nat_max ) as natural_reads + ,iif( indexed_reads <= idx_max, 'acceptable, <= ' || idx_max, 'abnormal, ' || indexed_reads || ' > ' || idx_max ) as indexed_reads + from ( + select + v.natural_reads + ,v.indexed_reads + ,cast(rdb$get_context('USER_SESSION','NAT_READS_MAX_THRESHOLD') as int) nat_max + ,cast(rdb$get_context('USER_SESSION','IDX_READS_MAX_THRESHOLD') as int) idx_max + from v_agg_stat v + ); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + NATURAL_READS acceptable, <= 0 + INDEXED_READS acceptable, <= 20 + """ + +@pytest.mark.version('>=3.0') +def test_core_4798_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4802.py b/tests/bugs/test_core_4802.py new file mode 100644 index 00000000..83b155c7 --- /dev/null +++ b/tests/bugs/test_core_4802.py @@ -0,0 +1,157 @@ +#coding:utf-8 +# +# id: bugs.core_4802 +# title: Regression: GRANT UPDATE() on acts like grant update on ALL columns of +# decription: +# tracker_id: CORE-4802 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('GRANT.*TMP.*', ''), ('-Effective user is.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set wng off; + + recreate table test(fld_for_seniors varchar(70), fld_for_juniors varchar(70)); + commit; + + create or alter user BIG_BROTHER password '123' revoke admin role; + create or alter user SENIOR_MNGR password '456' revoke admin role; + create or alter user JUNIOR_MNGR password '789' revoke admin role; + create role FLD_FOR_SENIORS_UPDATER; + create role FLD_FOR_JUNIORS_UPDATER; + commit; + + revoke all on all from BIG_BROTHER; + revoke all on all from SENIOR_MNGR; + revoke all on all from JUNIOR_MNGR; + + -- Statement failed, SQLSTATE = 28000 + -- unsuccessful metadata update + -- -REVOKE failed + -- -SQL role FLD_FOR_SENIORS_UPDATER does not exist + -- -in security database + -- revoke all on all from role FLD_FOR_SENIORS_UPDATER; + -- revoke all on all from role FLD_FOR_JUNIORS_UPDATER; + 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; + --------------------------------------------------------------- + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + drop role FLD_FOR_SENIORS_UPDATER; + drop role FLD_FOR_JUNIORS_UPDATER; + drop user BIG_BROTHER; + drop user SENIOR_MNGR; + drop user JUNIOR_MNGR; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + /* 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_1 = """ + 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 + """ + +@pytest.mark.version('>=3.0') +def test_core_4802_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4806.py b/tests/bugs/test_core_4806.py new file mode 100644 index 00000000..8065c12c --- /dev/null +++ b/tests/bugs/test_core_4806.py @@ -0,0 +1,185 @@ +#coding:utf-8 +# +# id: bugs.core_4806 +# title: Regression: generators can be seen/modified by unprivileged users +# decription: +# We create sequence ('g') and three users and one role. +# First user ('big_brother') is granted to use generator directly. +# Second user ('bill_junior') is gratned to use generator via ROLE ('stockmgr'). +# Third user ('maverick') has no grants to use neither on role nor on generator. +# Then we try to change value of generator by call gen_id(g,1) by create apropriate +# connections (for each of these users). +# First and second users must have ability both to change generator and to see its +# values using command 'SHOW SEQUENCE'. +# 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). +# +# :::::::::::::::::::::::::::::::::::::::: NB :::::::::::::::::::::::::::::::::::: +# 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. +# +# Checked on: +# 4.0.0.2164 +# 3.0.7.33356 +# +# tracker_id: CORE-4806 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('-Effective user is.*', ''), ('current value.*', 'current value')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set wng off; + recreate sequence g; + commit; + set term ^; + execute block as + begin + execute statement 'drop role stockmgr'; + when any do begin end + end + ^ set term ;^ + commit; + + create or alter user Maverick password '123'; + create or alter user Big_Brother password '456'; + create or alter user Bill_Junior password '789'; + create role stockmgr; + commit; + + revoke all on all from Maverick; + revoke all on all from Big_Brother; + revoke all on all from Bill_Junior; + --revoke all on all from stockmgr; -- COMMENTED TEMPLY, error "Revoke all on all from role -- failed with "SQL role does not exist in security database"", see core-4831 + revoke all on all from public; + commit; + + grant usage on sequence g to big_brother; + grant usage on sequence g to role stockmgr; + grant stockmgr to Bill_Junior; + commit; + show grants; + + set list on; + + connect '$(DSN)' user 'BIG_BROTHER' password '456'; + select current_user, current_role from rdb$database; + show sequ g; + select gen_id(g, -111) as new_gen from rdb$database; + commit; + + connect '$(DSN)' user 'BILL_JUNIOR' password '789' role 'STOCKMGR'; -- !! specify role in UPPER case !! + select current_user, current_role from rdb$database; + show sequ g; + select gen_id(g, -222) as new_gen from rdb$database; + commit; + + connect '$(DSN)' user 'BILL_JUNIOR' password '789'; + select current_user, current_role from rdb$database; + + -- 'show sequ' should produce error: + -- Statement failed, SQLSTATE = 28000 + -- no permission for USAGE access to GENERATOR G + -- There is no generator G in this database + -- (for user 'Bill_Junior' who connects w/o ROLE and thus has NO rights to see that sequence) + show sequ g; + + -- 'select gen_id(...)' should produce error: + -- Statement failed, SQLSTATE = 28000 + -- no permission for USAGE access to GENERATOR G + -- (for user 'Bill_Junior' who connects w/o ROLE and thus has NO rights to see that sequence) + select gen_id(g, -333) as new_gen from rdb$database; + commit; + + connect '$(DSN)' user 'MAVERICK' password '123'; + select current_user, current_role from rdb$database; + + + -- 'show sequ' should produce error: + -- Statement failed, SQLSTATE = 28000 + -- no permission for USAGE access to GENERATOR G + -- There is no generator G in this database + -- (for user 'maverick' who has NO rights at all) + show sequ g; + + -- 'select gen_id(...)' should produce error: + -- Statement failed, SQLSTATE = 28000 + -- no permission for USAGE access to GENERATOR G + -- (for user 'maverick' who has NO rights at all) + select gen_id(g, -444) as new_gen from rdb$database; + + commit; + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + + drop user Maverick; + drop user Big_Brother; + drop user Bill_Junior; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + /* 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_1 = """ + 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 + + 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 + """ + +@pytest.mark.version('>=3.0') +def test_core_4806_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4807.py b/tests/bugs/test_core_4807.py new file mode 100644 index 00000000..311a7f83 --- /dev/null +++ b/tests/bugs/test_core_4807.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_4807 +# title: Regression: List of aggregation is not checked properly +# decription: 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). +# tracker_id: CORE-4807 +# min_versions: ['2.5.5'] +# versions: 2.5.5 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.5 +# resources: None + +substitutions_1 = [('SORT \\(\\(T NATURAL\\)\\)', 'SORT (T NATURAL)')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set planonly; + select t.rdb$field_name, (select 1 from rdb$database), count(*) + from rdb$types t + group by t.rdb$field_name; + + select t.rdb$field_name, (select 1 from rdb$database where t.rdb$system_flag=1), count(*) + from rdb$types t + group by t.rdb$field_name; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (RDB$DATABASE NATURAL) + PLAN SORT ((T NATURAL)) + """ +expected_stderr_1 = """ + 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) + """ + +@pytest.mark.version('>=2.5.5') +def test_core_4807_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4809.py b/tests/bugs/test_core_4809.py new file mode 100644 index 00000000..f8835873 --- /dev/null +++ b/tests/bugs/test_core_4809.py @@ -0,0 +1,187 @@ +#coding:utf-8 +# +# id: bugs.core_4809 +# title: HASH/MERGE JOIN is not used for more than two streams if they are joined via USING/NATURAL clauses and join is based on DBKEY concatenations +# decription: Test verifies only 3.0. For 2.5.x see CORE-4822. +# tracker_id: CORE-4809 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table tk(x int primary key using index tk_x); + commit; + insert into tk(x) + with recursive r as (select 0 i from rdb$database union all select r.i+1 from r where r.i<99) + select r1.i*100+r0.i from r r1, r r0; + commit; + set statistics index tk_x; + commit; + + recreate table tf(id_key int primary key using index tf_id_key); + commit; + insert into tf(id_key) + with recursive r as (select 0 i from rdb$database union all select r.i+1 from r where r.i<99) + select r1.i*100+r0.i from r r1, r r0; + commit; + set statistics index tf_id_key; + commit; + + set planonly; + + -- 1. Join using RDB$DB_KEY based expressions: + + ----------- test `traditional` join form ----------------- + + select count(*) + from (select rdb$db_key||'' a from tk) r + join (select rdb$db_key||'' a from tk) s on r.a = s.a; + + + select count(*) + from (select rdb$db_key||'' a from tk) r + join (select rdb$db_key||'' a from tk) s on r.a = s.a + join (select rdb$db_key||'' a from tk) t on s.a = t.a; + + + select count(*) + from (select rdb$db_key||'' a from tk) r + join (select rdb$db_key||'' a from tk) s on r.a = s.a + join (select rdb$db_key||'' a from tk) t on s.a = t.a + join (select rdb$db_key||'' a from tk) u on t.a = u.a; + + ----------- test join on named columns form ----------------- + + select count(*) + from (select rdb$db_key||'' a from tk) r + join (select rdb$db_key||'' a from tk) s using(a); + + select count(*) + from (select rdb$db_key||'' a from tk) r + join (select rdb$db_key||'' a from tk) s using(a) + join (select rdb$db_key||'' a from tk) t using(a); + + select count(*) + from (select rdb$db_key||'' a from tk) r + join (select rdb$db_key||'' a from tk) s using(a) + join (select rdb$db_key||'' a from tk) t using(a) + join (select rdb$db_key||'' a from tk) u using(a); + + ----------- test natural join form ----------------- + + select count(*) + from (select rdb$db_key||'' a from tk) r + natural join (select rdb$db_key||'' a from tk) s; + + select count(*) + from (select rdb$db_key||'' a from tk) r + natural join (select rdb$db_key||'' a from tk) s + natural join (select rdb$db_key||'' a from tk) t; + + select count(*) + from (select rdb$db_key||'' a from tk) r + natural join (select rdb$db_key||'' a from tk) s + natural join (select rdb$db_key||'' a from tk) t + natural join (select rdb$db_key||'' a from tk) u; + + ------------------------------------------------- + + -- 2. Join using COMMON FIELD based expressions: + -- (all following statements produced 'PLAN HASH' before fix also; + -- here we verify them only for sure that evething remains OK). + + ----------- test `traditional` join form ----------------- + + select count(*) + from (select id_key||'' a from tf) r + join (select id_key||'' a from tf) s on r.a = s.a; + + + select count(*) + from (select id_key||'' a from tf) r + join (select id_key||'' a from tf) s on r.a = s.a + join (select id_key||'' a from tf) t on s.a = t.a; + + + select count(*) + from (select id_key||'' a from tf) r + join (select id_key||'' a from tf) s on r.a = s.a + join (select id_key||'' a from tf) t on s.a = t.a + join (select id_key||'' a from tf) u on t.a = u.a; + + ----------- test join on named columns form ----------------- + + select count(*) + from (select id_key||'' a from tf) r + join (select id_key||'' a from tf) s using(a); + + select count(*) + from (select id_key||'' a from tf) r + join (select id_key||'' a from tf) s using(a) + join (select id_key||'' a from tf) t using(a); + + select count(*) + from (select id_key||'' a from tf) r + join (select id_key||'' a from tf) s using(a) + join (select id_key||'' a from tf) t using(a) + join (select id_key||'' a from tf) u using(a); + + ----------- test natural join form ----------------- + + select count(*) + from (select id_key||'' a from tf) r + natural join (select id_key||'' a from tf) s; + + select count(*) + from (select id_key||'' a from tf) r + natural join (select id_key||'' a from tf) s + natural join (select id_key||'' a from tf) t; + + select count(*) + from (select id_key||'' a from tf) r + natural join (select id_key||'' a from tf) s + natural join (select id_key||'' a from tf) t + natural join (select id_key||'' a from tf) u; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN HASH (S TK NATURAL, R TK NATURAL) + PLAN HASH (HASH (T TK NATURAL, S TK NATURAL), R TK NATURAL) + PLAN HASH (HASH (HASH (U TK NATURAL, T TK NATURAL), S TK NATURAL), R TK NATURAL) + PLAN HASH (S TK NATURAL, R TK NATURAL) + PLAN HASH (T TK NATURAL, HASH (S TK NATURAL, R TK NATURAL)) + PLAN HASH (U TK NATURAL, HASH (T TK NATURAL, HASH (S TK NATURAL, R TK NATURAL))) + PLAN HASH (S TK NATURAL, R TK NATURAL) + PLAN HASH (T TK NATURAL, HASH (S TK NATURAL, R TK NATURAL)) + PLAN HASH (U TK NATURAL, HASH (T TK NATURAL, HASH (S TK NATURAL, R TK NATURAL))) + PLAN HASH (S TF NATURAL, R TF NATURAL) + PLAN HASH (HASH (T TF NATURAL, S TF NATURAL), R TF NATURAL) + PLAN HASH (HASH (HASH (U TF NATURAL, T TF NATURAL), S TF NATURAL), R TF NATURAL) + PLAN HASH (S TF NATURAL, R TF NATURAL) + PLAN HASH (T TF NATURAL, HASH (S TF NATURAL, R TF NATURAL)) + PLAN HASH (U TF NATURAL, HASH (T TF NATURAL, HASH (S TF NATURAL, R TF NATURAL))) + PLAN HASH (S TF NATURAL, R TF NATURAL) + PLAN HASH (T TF NATURAL, HASH (S TF NATURAL, R TF NATURAL)) + PLAN HASH (U TF NATURAL, HASH (T TF NATURAL, HASH (S TF NATURAL, R TF NATURAL))) + """ + +@pytest.mark.version('>=3.0') +def test_core_4809_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4811.py b/tests/bugs/test_core_4811.py new file mode 100644 index 00000000..79abfc31 --- /dev/null +++ b/tests/bugs/test_core_4811.py @@ -0,0 +1,205 @@ +#coding:utf-8 +# +# id: bugs.core_4811 +# title: Make user names behave according to SQL identifiers rules +# decription: +# tracker_id: CORE-4811 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('set echo.*', ''), ('Use CONNECT or CREATE DATABASE.*', ''), ('Your user name and password.*', ''), ('line: [0-9]+, col: [0-9]+', ''), ('exception [0-9]+', 'exception')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set wng off; + set list on; + create or alter procedure sp_check_actual_role as begin end; + set term ^; + execute block as + begin + execute statement 'drop role Boss'; + when any do begin end + end ^ + set term ;^ + 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; + create or alter user Tmp$c4811 password '1'; + revoke all on all from Tmp$c4811; + create role Boss; + 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; + + -- ### CLEANUP ### + -- Do not forget about cleanup (other tests can query sec$users or run `show users`!) + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + drop user Tmp$c4811; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + create or alter user Tmp$c4811 password '1'; + revoke all on all from Tmp$c4811; + create role Boss; + 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 + + 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_1 = """ + 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_core_4811_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4817.py b/tests/bugs/test_core_4817.py new file mode 100644 index 00000000..c1797f45 --- /dev/null +++ b/tests/bugs/test_core_4817.py @@ -0,0 +1,69 @@ +#coding:utf-8 +# +# id: bugs.core_4817 +# title: ISQL doesn`t show number of affected rows for "MERGE ... WHEN MATCHING" in case when this number surely > 0 +# decription: +# tracker_id: CORE-4817 +# min_versions: ['2.5.6'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table src(id int, x int); + commit; + + insert into src + with recursive r as(select 0 i from rdb$database union all select r.i+1 from r where r.i<9) + select r.i, r.i * 2 from r; + commit; + + recreate table tgt(id int primary key, x int); + commit; + + set count on; + merge into tgt t + using (select * from src where id > 1) s on s.id = t.id + when not matched then insert values(s.id, s.x); + commit; + + merge into tgt t + using src s on s.id = t.id + when matched and s.id in (7,8,9) then update set t.x = -2 * s.x; + rollback; + + merge into tgt t + using src s on s.id = t.id + when matched and s.id in (0,1,2) then update set t.x = -2 * s.x + when not matched and s.id = 0 then insert values(s.id, 1111) + when matched and s.id in (3,4,5,6) then update set t.x = - 3 * s.x + when not matched and s.id = 1 then insert values(s.id, 2222) + when matched then delete + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 8 + Records affected: 3 + Records affected: 10 + """ + +@pytest.mark.version('>=3.0') +def test_core_4817_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4819.py b/tests/bugs/test_core_4819.py new file mode 100644 index 00000000..e0147242 --- /dev/null +++ b/tests/bugs/test_core_4819.py @@ -0,0 +1,479 @@ +#coding:utf-8 +# +# id: bugs.core_4819 +# title: EXECUTE PROCEDURE's RETURNING_VALUES and EXECUTE STATEMENT's INTO does not check validity of assignments targets leading to bugcheck +# decription: +# tracker_id: CORE-4819 +# min_versions: ['3.0'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter procedure sp_test(a_x int) as begin end; + recreate table test(id int primary key, x bigint, y bigint); + + insert into test values(1, 3, 7); + + set list on; + + --------------------- + select 'initial state' msg, t.* from test t; + --------------------- + commit; + + set term ^; + create or alter procedure sp_test(a_x int) returns(o_y int) as + begin + o_y = 7 * a_x; + suspend; + end + ^ + commit + ^ + create or alter trigger test_aud1 for test active after insert or update or delete as + begin + -- Since WI-T3.0.0.31846 following must produce: + -- Statement failed, SQLSTATE = 42000 + -- attempted update of read-only column + + if (not inserting) then + begin + execute procedure sp_test(old.x) returning_values(old.x); + execute procedure sp_test(old.x) returning_values(old.y); + end + else + begin + execute procedure sp_test(new.x) returning_values(new.x); + execute procedure sp_test(new.x) returning_values(new.y); + end + + rdb$set_context( 'USER_SESSION', 'X_TRG_AIUD1', iif( inserting, new.x, old.x ) ); + rdb$set_context( 'USER_SESSION', 'Y_TRG_AIUD1', iif( inserting, new.y, old.y ) ); + + end + ^ + + create or alter trigger test_aud2 for test active after insert or update or delete as + begin + -- Since WI-T3.0.0.31846 following must produce: + -- Statement failed, SQLSTATE = 42000 + -- attempted update of read-only column + if (not inserting) then + begin + execute statement ('execute procedure sp_test( ? )') ( 2 * old.x ) into old.x; + execute statement ('execute procedure sp_test( ? )') ( 2 * old.x ) into old.y; + end + else + begin + execute statement ('execute procedure sp_test( ? )') ( 2 * new.x ) into new.x; + execute statement ('execute procedure sp_test( ? )') ( 2 * new.x ) into new.y; + end + + rdb$set_context( 'USER_SESSION', 'X_TRG_AIUD2', iif( inserting, new.x, old.x ) ); + rdb$set_context( 'USER_SESSION', 'Y_TRG_AIUD2', iif( inserting, new.y, old.y ) ); + end + ^ + set term ;^ + commit; + + -- ###################################################################### + -- 1. Check when 'execute proc returning_values' is called from trigger, + -- making invalid update of old. & new. variables: + + delete from test where id = 1 + returning 'delete-returning:' as msg, + x as old_x, + y as old_y; + select + 'after delete' 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, + cast(rdb$get_context('USER_SESSION', 'Y_TRG_AIUD2') as int) as Y_TRG_AIUD2 + from rdb$database; + rollback; + + update test set x = 17 where id = 1 + returning 'update-returning:' as msg, + old.x as old_x, + new.x as new_x, + old.y as old_y, + new.y as new_y; + + select + '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, + cast(rdb$get_context('USER_SESSION', 'Y_TRG_AIUD2') as int) as Y_TRG_AIUD2, + t.* + from test t; + rollback; + + --------------------- + + insert into test(id, x) values(2, 19) + returning 'insert-returning:' as msg, x as new_x, y as new_y; + + select + 'after insert' 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, + cast(rdb$get_context('USER_SESSION', 'Y_TRG_AIUD2') as int) as Y_TRG_AIUD2, + t.* + from test t where id=2; + rollback; + + -- ###################################################################### + -- 2. Check when call 'execute proc returning_values' inside implicit cursor: + set term ^; + execute block returns(msg varchar(20), old_y int, new_y int) as + begin + msg='within cursor-1:'; + for + select x, y from test + as cursor ce + do begin + old_y = ce.y; + + -- WI-T3.0.0.31845. Following leads to: + -- Statement failed, SQLSTATE = XX000 + -- internal Firebird consistency check (EVL_assign_to: invalid operation (229), file: evl.cpp line: 205) + -- Since WI-T3.0.0.31846 must produce: + -- Statement failed, SQLSTATE = 42000 + -- attempted update of read-only column + + execute procedure sp_test(ce.x) returning_values(ce.y); + new_y = ce.y; + suspend; + end + end + ^ + set term ;^ + rollback; + + -- ###################################################################### + -- 3. Check when call 'execute statement' inside implicit cursor: + set term ^; + execute block returns(msg varchar(20), old_y int, new_y int) as + begin + msg='within cursor-2:'; + for + select x, y from test + as cursor ce + do begin + old_y = ce.y; + + -- Since WI-T3.0.0.31846 following must produce: + -- Statement failed, SQLSTATE = 42000 + -- attempted update of read-only column + execute statement ('execute procedure sp_test( ? )') ( ce.x ) into ce.y; + new_y = ce.y; + suspend; + end + end + ^ + set term ;^ + rollback; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG initial state + ID 1 + X 3 + Y 7 + + MSG after delete + X_TRG_AIUD1 + Y_TRG_AIUD1 + X_TRG_AIUD2 + Y_TRG_AIUD2 + + MSG after update + X_TRG_AIUD1 + Y_TRG_AIUD1 + X_TRG_AIUD2 + Y_TRG_AIUD2 + ID 1 + X 3 + Y 7 + """ +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_core_4819_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + create or alter procedure sp_test(a_x int) as begin end; + recreate table test(id int primary key, x bigint, y bigint); + + insert into test values(1, 3, 7); + + set list on; + + --------------------- + select 'initial state' msg, t.* from test t; + --------------------- + commit; + + set term ^; + create or alter procedure sp_test(a_x int) returns(o_y int) as + begin + o_y = 7 * a_x; + suspend; + end + ^ + commit + ^ + create or alter trigger test_aud1 for test active after insert or update or delete as + begin + -- Since WI-T3.0.0.31846 following must produce: + -- Statement failed, SQLSTATE = 42000 + -- attempted update of read-only column + + if (not inserting) then + begin + execute procedure sp_test(old.x) returning_values(old.x); + execute procedure sp_test(old.x) returning_values(old.y); + end + else + begin + execute procedure sp_test(new.x) returning_values(new.x); + execute procedure sp_test(new.x) returning_values(new.y); + end + + rdb$set_context( 'USER_SESSION', 'X_TRG_AIUD1', iif( inserting, new.x, old.x ) ); + rdb$set_context( 'USER_SESSION', 'Y_TRG_AIUD1', iif( inserting, new.y, old.y ) ); + + end + ^ + + create or alter trigger test_aud2 for test active after insert or update or delete as + begin + -- Since WI-T3.0.0.31846 following must produce: + -- Statement failed, SQLSTATE = 42000 + -- attempted update of read-only column + if (not inserting) then + begin + execute statement ('execute procedure sp_test( ? )') ( 2 * old.x ) into old.x; + execute statement ('execute procedure sp_test( ? )') ( 2 * old.x ) into old.y; + end + else + begin + execute statement ('execute procedure sp_test( ? )') ( 2 * new.x ) into new.x; + execute statement ('execute procedure sp_test( ? )') ( 2 * new.x ) into new.y; + end + + rdb$set_context( 'USER_SESSION', 'X_TRG_AIUD2', iif( inserting, new.x, old.x ) ); + rdb$set_context( 'USER_SESSION', 'Y_TRG_AIUD2', iif( inserting, new.y, old.y ) ); + end + ^ + set term ;^ + commit; + + -- ###################################################################### + -- 1. Check when 'execute proc returning_values' is called from trigger, + -- making invalid update of old. & new. variables: + + delete from test where id = 1 + returning 'delete-returning:' as msg, + x as old_x, + y as old_y; + select + 'after delete' 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, + cast(rdb$get_context('USER_SESSION', 'Y_TRG_AIUD2') as int) as Y_TRG_AIUD2 + from rdb$database; + rollback; + + update test set x = 17 where id = 1 + returning 'update-returning:' as msg, + old.x as old_x, + new.x as new_x, + old.y as old_y, + new.y as new_y; + + select + '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, + cast(rdb$get_context('USER_SESSION', 'Y_TRG_AIUD2') as int) as Y_TRG_AIUD2, + t.* + from test t; + rollback; + + --------------------- + + insert into test(id, x) values(2, 19) + returning 'insert-returning:' as msg, x as new_x, y as new_y; + + select + 'after insert' 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, + cast(rdb$get_context('USER_SESSION', 'Y_TRG_AIUD2') as int) as Y_TRG_AIUD2, + t.* + from test t where id=2; + rollback; + + -- ###################################################################### + -- 2. Check when call 'execute proc returning_values' inside implicit cursor: + set term ^; + execute block returns(msg varchar(20), old_y int, new_y int) as + begin + msg='within cursor-1:'; + for + select x, y from test + as cursor ce + do begin + old_y = ce.y; + + -- WI-T3.0.0.31845. Following leads to: + -- Statement failed, SQLSTATE = XX000 + -- internal Firebird consistency check (EVL_assign_to: invalid operation (229), file: evl.cpp line: 205) + -- Since WI-T3.0.0.31846 must produce: + -- Statement failed, SQLSTATE = 42000 + -- attempted update of read-only column + + execute procedure sp_test(ce.x) returning_values(ce.y); + new_y = ce.y; + suspend; + end + end + ^ + set term ;^ + rollback; + + -- ###################################################################### + -- 3. Check when call 'execute statement' inside implicit cursor: + set term ^; + execute block returns(msg varchar(20), old_y int, new_y int) as + begin + msg='within cursor-2:'; + for + select x, y from test + as cursor ce + do begin + old_y = ce.y; + + -- Since WI-T3.0.0.31846 following must produce: + -- Statement failed, SQLSTATE = 42000 + -- attempted update of read-only column + execute statement ('execute procedure sp_test( ? )') ( ce.x ) into ce.y; + new_y = ce.y; + suspend; + end + end + ^ + set term ;^ + rollback; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + MSG initial state + ID 1 + X 3 + Y 7 + + MSG after delete + X_TRG_AIUD1 + Y_TRG_AIUD1 + X_TRG_AIUD2 + Y_TRG_AIUD2 + + MSG after update + X_TRG_AIUD1 + Y_TRG_AIUD1 + X_TRG_AIUD2 + Y_TRG_AIUD2 + ID 1 + X 3 + Y 7 + """ +expected_stderr_2 = """ + 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 + + 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 CE.Y + + Statement failed, SQLSTATE = 42000 + attempted update of read-only column CE.Y + """ + +@pytest.mark.version('>=4.0') +def test_core_4819_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_expected_stderr == act_2.clean_stderr + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/bugs/test_core_4821.py b/tests/bugs/test_core_4821.py new file mode 100644 index 00000000..e3335b9b --- /dev/null +++ b/tests/bugs/test_core_4821.py @@ -0,0 +1,216 @@ +#coding:utf-8 +# +# id: bugs.core_4821 +# title: grant create database to ROLE does not work: "no permission for CREATE access to DATABASE ..." +# decription: +# ::: NOTE ::: Test requires that databases.conf contains 'RemoteAccess = true' for security.db +# This line is added there by scenario ' +# undaily.bat' every time when check new FB snapshot. +# +# We make connection to security.db and create there user and role, with granting this role to user. +# (so, ROLE also is stored in the security.db). +# Then we grant privilege to create DB to just created role. +# After this we check that: +# * user can NOT create database if 'ROLE ' missed in the 'create database' statement; +# * user _CAN_ create database when issues: create database ... user ... password ... ROLE +# +# Then we create backup of just created database and check that: +# * user can NOT restore it until specifying '-ROLE ' in gbak command line; +# * user _CAN_ restore database when issues: gbak -rep ... -user ... -pas ... -ROLE ; +# * the same pair of checks is performed for fbsvcmgr invocation; +# +# Finally, we connect again to security.db and drop . After this restore must not be allowed +# even when "ROLE " is specified in commands gbak or fbsvcmgr. +# +# Checked on: +# 4.0.0.1713 SS: 5.250s. +# 4.0.0.1346 SC: 5.734s. +# 4.0.0.1691 CS: 9.875s. +# 3.0.5.33218 SS: 4.313s. +# 3.0.5.33084 SC: 4.031s. +# 3.0.5.33212 CS: 7.672s. +# +# 13.04.2021. Adapted for run both on Windows and Linux. Checked on: +# Windows: 3.0.8.33445, 4.0.0.2416 +# Linux: 3.0.8.33426, 4.0.0.2416 +# +# tracker_id: CORE-4821 +# min_versions: ['3.0.5'] +# versions: 3.0.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [('no permission for CREATE access to DATABASE .*', 'no permission for CREATE access to DATABASE'), ('gbak: ERROR:failed to create database .*', 'gbak: ERROR:failed to create database'), ('-failed to create database .*', '-failed to create database'), ('CREATED_DB_NAME .*', 'CREATED_DB_NAME'), ('FDB_RESTORED_USING_GBAK .*', 'FDB_RESTORED_USING_GBAK'), ('FDB_RESTORED_USING_SMGR .*', 'FDB_RESTORED_USING_SMGR')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# this_db = db_conn.database_name +# db_conn.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 ) +# +# #-------------------------------------------- +# +# fdb_test1 = os.path.join(context['temp_directory'],'tmp_4821_test1.fdb') +# fdb_test2 = os.path.join(context['temp_directory'],'tmp_4821_test2.fdb') +# fbk_name = os.path.join(context['temp_directory'],'tmp_4821_test2.fbk') +# fdb_restored_using_gbak = os.path.join(context['temp_directory'],'tmp_4821_restored.gbak.fdb') +# fdb_restored_using_smgr = os.path.join(context['temp_directory'],'tmp_4821_restored.smgr.fdb') +# fdb_restored_unexpected = os.path.join(context['temp_directory'],'tmp_4821_restored.wo_grant.fdb') +# +# f_list = [fdb_test1, fdb_test2, fbk_name, fdb_restored_using_gbak, fdb_restored_using_smgr, fdb_restored_unexpected] +# cleanup( f_list ) +# +# sql_init=''' +# set wng off; +# set bail on; +# set term ^; +# execute block as +# begin +# execute statement 'drop role tmp$db_creator'; +# when any do begin end +# end^ +# set term ;^ +# commit; +# create role tmp$db_creator; +# commit; +# create or alter user tmp$c4821_boss password '123' using plugin Srp; +# revoke all on all from tmp$c4821_boss; +# grant create database to role tmp$db_creator; +# grant tmp$db_creator to tmp$c4821_boss; +# commit; +# --show grants; +# ''' +# +# runProgram('isql', [ 'localhost:security.db' ], sql_init) +# +# sql_test=''' +# create database 'localhost:%(fdb_test1)s' user tmp$c4821_boss password '123'; +# select mon$database_name as created_db_name from mon$database; +# rollback; +# create database 'localhost:%(fdb_test2)s' user tmp$c4821_boss password '123' role tmp$db_creator; +# set list on; +# select mon$database_name as created_db_name from mon$database; +# ''' % locals() +# +# runProgram('isql', [ '-q' ], sql_test) +# +# # Must PASS because user tmp$c4821_boss is the owner of this DB: +# runProgram('gbak', [ '-b', 'localhost:' + fdb_test2, fbk_name, '-user', 'tmp$c4821_boss', '-pas', '123'] ) +# +# # Must FAIL because we do not specify role, with text: +# # "gbak: ERROR:no permission for CREATE access to DATABASE ... / gbak: ERROR:failed to create database localhost:tmp_4821_restored.gbak.fdb" +# runProgram('gbak', [ '-rep', fbk_name, 'localhost:'+fdb_restored_using_gbak, '-user', 'tmp$c4821_boss', '-pas', '123'] ) +# +# # Must PASS because we DO specify role: +# runProgram('gbak', [ '-rep', fbk_name, 'localhost:'+fdb_restored_using_gbak, '-user', 'tmp$c4821_boss', '-pas', '123', '-role', 'tmp$db_creator'] ) +# +# runProgram('isql', [ 'localhost:'+fdb_restored_using_gbak ], 'set list on; select mon$database_name as fdb_restored_using_gbak from mon$database;') +# +# # Must FAIL because we do not specify role, with text: "no permission for CREATE access to DATABASE ... / failed to create database tmp_4821_restored.smgr.fdb" +# runProgram('fbsvcmgr', [ 'localhost:service_mgr', 'user', 'tmp$c4821_boss', 'password', '123', 'action_restore', 'res_replace', 'bkp_file', fbk_name, 'dbname', fdb_restored_using_smgr ] ) +# +# # Must PASS because we DO specify role: +# runProgram('fbsvcmgr', [ 'localhost:service_mgr', 'user', 'tmp$c4821_boss', 'password', '123', 'role', 'tmp$db_creator', 'action_restore', 'res_replace', 'bkp_file', fbk_name, 'dbname', fdb_restored_using_smgr ] ) +# +# runProgram('isql', [ 'localhost:'+fdb_restored_using_smgr ], 'set list on; select mon$database_name as fdb_restored_using_smgr from mon$database;') +# +# +# # ATTENTION: now we DROP role and check that after this action user tmp$c4821_boss will not be allowed to restore DB +# ############################# +# runProgram('isql', [ 'localhost:security.db' ], 'drop role tmp$db_creator; commit;') +# +# # Must FAIL because there is no more role which was allowed to create DB +# # Error text: "gbak: ERROR:no permission for CREATE ... TMP_4821_RESTORED.WO_GRANT.FDB" +# runProgram('gbak', [ '-rep', fbk_name, 'localhost:'+fdb_restored_unexpected, '-user', 'tmp$c4821_boss', '-pas', '123', '-role', 'tmp$db_creator'] ) +# +# # Must FAIL (because of the same reason), with text: "no permission for CREATE access to DATABASE TMP_4821_RESTORED.WO_GRANT.FDB" +# runProgram('fbsvcmgr', [ 'localhost:service_mgr', 'user', 'tmp$c4821_boss', 'password', '123', 'role', 'tmp$db_creator', 'action_restore', 'res_replace', 'bkp_file', fbk_name, 'dbname', fdb_restored_unexpected ] ) +# +# # CLEANUP: +# ########## +# +# sql_fini=''' +# drop user tmp$c4821_boss using plugin Srp; +# commit; +# ''' +# runProgram('isql', [ 'localhost:security.db' ], sql_fini) +# +# cleanup( f_list ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CREATED_DB_NAME /opt/scripts/qa-rundaily/dbg-repo/tmp/tmp_4821_test2.fdb + FDB_RESTORED_USING_GBAK /opt/scripts/qa-rundaily/dbg-repo/tmp/tmp_4821_restored.gbak.fdb + FDB_RESTORED_USING_SMGR /opt/scripts/qa-rundaily/dbg-repo/tmp/tmp_4821_restored.smgr.fdb + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 28000 + no permission for CREATE access to DATABASE + gbak: ERROR:no permission for CREATE access to DATABASE + gbak: ERROR:failed to create database + gbak:Exiting before completion due to errors + no permission for CREATE access to DATABASE + -failed to create database + -Exiting before completion due to errors + gbak: ERROR:no permission for CREATE access to DATABASE + gbak: ERROR:failed to create database + gbak:Exiting before completion due to errors + no permission for CREATE access to DATABASE + -failed to create database + -Exiting before completion due to errors + """ + +@pytest.mark.version('>=3.0.5') +@pytest.mark.xfail +def test_core_4821_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4822.py b/tests/bugs/test_core_4822.py new file mode 100644 index 00000000..31dfa0a8 --- /dev/null +++ b/tests/bugs/test_core_4822.py @@ -0,0 +1,33 @@ +#coding:utf-8 +# +# id: bugs.core_4822 +# title: MERGE JOIN cannot be used for DBKEY based expressions +# decription: Test is related ONLY to versions 2.x. Block for 3.0 intentionally left EMPTY. +# tracker_id: CORE-4822 +# min_versions: ['2.5.5'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + --- SKIP any test for 3.0 for this ticket --- + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +def test_core_4822_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_4826.py b/tests/bugs/test_core_4826.py new file mode 100644 index 00000000..5b796d1c --- /dev/null +++ b/tests/bugs/test_core_4826.py @@ -0,0 +1,77 @@ +#coding:utf-8 +# +# id: bugs.core_4826 +# title: Make ISQL display character set when sqlda_display is on +# decription: +# tracker_id: CORE-4826 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!sqltype).)*$', ''), ('[ ]+', ' '), ('[\t]*', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Before WI-T3.0.0.31876 charsets were displeyd for field of ANY type, not only for text. + recreate table test1( + id1 smallint, + id2 int, + id3 bigint, + nf1 numeric(12,4), + nf2 double precision, + nf3 float, + tf1 date, + tf2 time, + tf3 timestamp, + boo boolean, + tx1 char character set utf8, + tx2 varchar(10) character set iso8859_1, + tx3 nchar, + -- doesn`t compile: tx4 nvarchar(10), + tx4 national character varying(32760), + tb1 blob sub_type 1 character set win1251, + tb2 blob sub_type 0 + ); + commit; + + set sqlda_display on; + select * from test1; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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_core_4826_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4831.py b/tests/bugs/test_core_4831.py new file mode 100644 index 00000000..f1a0949b --- /dev/null +++ b/tests/bugs/test_core_4831.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_4831 +# title: Revoke all on all from role -- failed with "SQL role does not exist in security database" +# decription: +# tracker_id: CORE-4831 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + There is no privilege granted in this database + """ + +@pytest.mark.version('>=3.0') +def test_core_4831_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_4836.py b/tests/bugs/test_core_4836.py new file mode 100644 index 00000000..7ec7d2fe --- /dev/null +++ b/tests/bugs/test_core_4836.py @@ -0,0 +1,69 @@ +#coding:utf-8 +# +# id: bugs.core_4836 +# title: Grant update(c) on t to U01 with grant option: user U01 will not be able to `revoke update(c) on t from ` if this `U01` do some DML before revoke +# decription: +# tracker_id: CORE-4836 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!C4836|R4836).)*$', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter user tmp$c4836 password '123' grant admin role; + create role tmp$r4836; + recreate table test(id int, text varchar(30)); + + grant select on test to public; + grant update(text) on test to tmp$c4836 with grant option; + commit; + + connect '$(DSN)' user tmp$c4836 password '123'; + + grant update (text) on test to tmp$r4836; + commit; + show grants; + commit; + + select * from test; -- this DML prevented to do subsequent `revoke update(text) on test from role` on build 3.0.0.31873 + + commit; + + revoke update(text) on test from role tmp$r4836; + commit; + + show grants; + commit; + + connect '$(DSN)' user sysdba password 'masterkey'; + drop role tmp$r4836; + drop user tmp$c4836; + drop table test; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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.version('>=3.0') +def test_core_4836_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4839.py b/tests/bugs/test_core_4839.py new file mode 100644 index 00000000..69ce0a9f --- /dev/null +++ b/tests/bugs/test_core_4839.py @@ -0,0 +1,51 @@ +#coding:utf-8 +# +# id: bugs.core_4839 +# title: SHOW GRANTS does not display info about exceptions which were granted to user +# decription: +# tracker_id: CORE-4839 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter user tmp$c4839 password '123'; + recreate exception exc_foo 'Houston we have a problem: next sequence value is @1'; + recreate sequence gen_bar start with 9223372036854775807 increment by 2147483647; + commit; + + grant usage on exception exc_foo to tmp$c4839; -- this wasn`t shown before rev. 61822 (build 3.0.0.31881), 2015-06-14 11:35 + grant usage on sequence gen_bar to tmp$c4839; + commit; + show grants; + commit; + drop user tmp$c4839; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + /* 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 + """ + +@pytest.mark.version('>=3.0') +def test_core_4839_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4840.py b/tests/bugs/test_core_4840.py new file mode 100644 index 00000000..208c0ec1 --- /dev/null +++ b/tests/bugs/test_core_4840.py @@ -0,0 +1,91 @@ +#coding:utf-8 +# +# id: bugs.core_4840 +# title: Transactions with isc_tpb_autocommit can hang the server +# decription: +# Test creates trivial SP and comment for it (in UTF8 with multi-byte characters) in single Tx with autocommit = true. +# Confirmed: +# 1. Crash on LI-V3.0.0.32173, WI-V3.0.0.32239 +# Crash on WI-V3.0.0.32134 Firebird 3.0 Release Candidate 1 with issuing in firebird.log: +# === +# internal Firebird consistency check (Too many savepoints (287), file: tra.cpp line: 2486) +# internal Firebird consistency check (wrong record version (185), file: vio.cpp line: 3823) +# === +# (after this FB instance is unavaliable; no any *other* database can be attached). +# +# 2. Normal work on LI-V3.0.0.32239 Rev: 62705 +# Example of TPB creation can be found here: +# http://www.firebirdsql.org/file/documentation/drivers_documentation/python/3.3.0/beyond-python-db-api.html +# List of allowed TPB parameters: C:\\Python27\\Lib\\site-packages +# db\\ibase.py +# +# tracker_id: CORE-4840 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import fdb +# +# db_conn.close() +# conn = kdb.connect(dsn=dsn.encode(),user='SYSDBA',password='masterkey') +# +# customTPB = ( [ fdb.isc_tpb_read_committed, fdb.isc_tpb_rec_version, fdb.isc_tpb_autocommit ] ) +# +# conn.begin( tpb=customTPB ) +# xcur=conn.cursor() +# +# sp_ddl="create or alter procedure sp_test (in1 integer, in2 float)" + "returns (" + " out1 varchar(20)," + " out2 double precision, " + " out3 integer" + ") as " + " declare x integer;" + "begin" + " out1 = 'out string';" + " out2 = 2 * in2;" + " out3 = 3 * in1;" + " suspend; " + "end" +# +# sp_rem="comment on procedure sp_test is 'Det är inte alla präster, som göra prästgården eller dess torp till änkesäte åt orkeslösa trotjänarinnor, hade biskopen en gång sagt om Helenas prost.'" +# +# ### 27.01.2016: fdb 1.5 will produce +# ### === +# ### ReferenceError: +# ### weakly-referenced object no longer exists +# ### === +# ### - for these statements: +# ###xcmd=xcur.prep( sp_ddl ) +# ###xcur.execute(xcmd) +# ###xcmd=xcur.prep( sp_rem ) +# ###xcur.execute(xcmd) +# +# # For confirmation of ticket issues it is enough to do just this: +# +# xcur.execute(sp_ddl) +# xcur.execute(sp_rem) +# +# conn.commit() +# conn.close() +# +# sqltxt="set list on; select * from sp_test(12345, 3.1415926);" +# runProgram('isql',[dsn,'-user',user_name,'-pas',user_password,'-q'],sqltxt) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + OUT1 out string + OUT2 6.283185005187988 + OUT3 37035 + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_4840_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4841.py b/tests/bugs/test_core_4841.py new file mode 100644 index 00000000..859b35af --- /dev/null +++ b/tests/bugs/test_core_4841.py @@ -0,0 +1,81 @@ +#coding:utf-8 +# +# id: bugs.core_4841 +# title: Make message about missing password being always displayed as reply on attempt to issue CREATE new login without PASSWORD clause +# decription: +# Checked on +# 4.0.0.2271 SS; 4.0.0.2265 SS; 4.0.0.2267 CS. +# 3.0.8.33392 SS; 3.0.8.33390 SC; 3.0.7.33388 CS. +# +# tracker_id: CORE-4841 +# min_versions: ['3.0.7'] +# versions: 3.0.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.7 +# resources: None + +substitutions_1 = [('[-]?Password', 'Password')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- All following statements must fail with message that contains phrase: + -- "Password must be specified when creating user" + create user u01; + create user u01 using plugin Srp; + create user u01 firstname 'john'; + create user u01 grant admin role; + create user u01 inactive; + create or alter user u01 tags (password = 'foo'); + create user password; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE USER U01 failed + -Password must be specified when creating user + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE USER U01 failed + -Password must be specified when creating user + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE USER U01 failed + -Password must be specified when creating user + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE USER U01 failed + -Password must be specified when creating user + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE USER U01 failed + -Password must be specified when creating user + + Statement failed, SQLSTATE = HY000 + Password must be specified when creating user + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE USER PASSWORD failed + -Password must be specified when creating user + """ + +@pytest.mark.version('>=3.0.7') +def test_core_4841_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_4846.py b/tests/bugs/test_core_4846.py new file mode 100644 index 00000000..e3234ef0 --- /dev/null +++ b/tests/bugs/test_core_4846.py @@ -0,0 +1,128 @@ +#coding:utf-8 +# +# id: bugs.core_4846 +# title: Altering a trigger indicating other table than the original does not reflect the change +# decription: +# tracker_id: CORE-4846 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('\\+.*', ''), ('\\=.*', ''), ('Trigger text.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + execute block as + begin + execute statement 'drop trigger muddy_trg'; + when any do begin end + end + ^ + set term ;^ + commit; + + recreate table test1( id1 int primary key, x1 int); + recreate table test2( id2 int primary key, x2 int); + recreate sequence g; + commit; + + 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 + ^ + set term ;^ + commit; + show trigger muddy_trg; + + + -- Following statements failed on 3.0.0.31907 with: + -- Statement failed, SQLSTATE = 42S22 + -- invalid request BLR at offset 17 + -- -column ID1 is not defined in table TEST2 + -- Passes OK on LI-V3.0.0.31916 Firebird 3.0 Release Candidate 1. + + 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 + ^ + set term ;^ + commit; + show trigger muddy_trg; + + 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 + ^ + set term ;^ + commit; + show trigger muddy_trg; + + + 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 + ^ + set term ;^ + commit; + show trigger muddy_trg; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Triggers on Table TEST2: + MUDDY_TRG, Sequence: 23184, Type: BEFORE INSERT, Active + as + begin + new.id2 = coalesce( new.id2, gen_id(g, 1) ); + end + + + 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 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 + """ + +@pytest.mark.version('>=3.0') +def test_core_4846_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4848.py b/tests/bugs/test_core_4848.py new file mode 100644 index 00000000..d6f6a04a --- /dev/null +++ b/tests/bugs/test_core_4848.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: bugs.core_4848 +# title: MERGE ... WHEN NOT MATCHED ... RETURNING returns wrong (non-null) values when no insert is performed +# decription: +# tracker_id: CORE-4848 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=1, init=init_script_1) + +test_script_1 = """ + set list on; + recreate table t1 (n1 integer, n2 integer); + + -- Case 1: + merge into t1 + using ( + select 1 x + from rdb$database + where 1 = 0 + ) on 1 = 1 + when not matched then + insert values (1, 11) + returning n1, n2; + + -- Case 2: + merge into t1 + using ( + select 1 x + from rdb$database + where 1 = 1 + ) on 1 = 0 + when not matched and 1 = 0 then + insert values (1, 11) + returning n1, n2; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + N1 + N2 + + N1 + N2 + """ + +@pytest.mark.version('>=3.0') +def test_core_4848_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4855.py b/tests/bugs/test_core_4855.py new file mode 100644 index 00000000..44ff4762 --- /dev/null +++ b/tests/bugs/test_core_4855.py @@ -0,0 +1,248 @@ +#coding:utf-8 +# +# id: bugs.core_4855 +# 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" +# decription: +# In order to check ticket issues this test does following: +# 1. Change on test database FW to OFF - this will increase DML performance. +# 2. Create two tables: one for inserting rows ('test') and second to serve as 'signal' to stop DML: +# inserts will be done until 2nd table (with name = 'stop') is empty. +# 3. Adds to SQL script DML (execute block) that will be used in ISQL session #1: it inserts rows +# into 'test' and checks after each inserting table 'stop' on presence there at least one row. +# This 'stop-row' will be inserted into 'stop' table in another ISQL session. +# 4. Launches ISQL connection #1 in separate (child) process. This ISQL will start 'heavy DML'. +# 5. Proceeds several online-validation actions by using synchronous call of 'FBSVCMGR action_validate'. +# Adds result of each validation to log. +# 6. Launches ISQL connection #2 in separate (child) process and give to this session trivial job: +# 'insert into stop(id) values(1); commit;'. This will cause ISQL session #1 to stop its activity +# because it runs in transaction with TIL = RC. +# 7. Outputs log of ISQL-1 and online validation results. +# +# Tested on WI-V3.0.0.32008, SS, SC and CS. Result: OK. +# Updated since WI-V3.0.0.32064: reduced key-length from extremely huge (1000) to "normal" value 36, +# otherwise get 'Statement failed, SQLSTATE = 54000 / Implementation limit exceeded / -Maximum index level reached'. +# (since CORE-4914 was fixed, see: http://sourceforge.net/p/firebird/code/62266 ) +# +# tracker_id: CORE-4855 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9]', ''), ('Relation [0-9]{3,4}', 'Relation'), ('Statement failed, SQLSTATE = HY008', ''), ('operation was cancelled', ''), ('After line .*', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# +# import os +# import subprocess +# from subprocess import Popen +# #import signal +# import time +# from fdb import services +# +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # Obtain engine version: +# engine = str(db_conn.engine_version) # convert to text because 'float' object has no attribute 'startswith' +# dbname=db_conn.database_name +# db_conn.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'): +# # 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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# ##################################################################### +# # Change database FW to OFF in order to increase speed of insertions and output its header info: +# +# fwoff_log=open( os.path.join(context['temp_directory'],'tmp_fw_off_4855.log'), 'w') +# subprocess.call([ context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", +# "prp_write_mode", "prp_wm_async", +# "dbname", dbname ], +# stdout=fwoff_log, stderr=subprocess.STDOUT) +# +# fwoff_log.seek(0,2) +# subprocess.call([ context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_db_stats", +# "dbname", dbname, "sts_hdr_pages"], +# stdout=fwoff_log, stderr=subprocess.STDOUT) +# flush_and_close( fwoff_log ) +# +# ##################################################################### +# # Preparing script for ISQL that will do 'heavy DML': +# +# sql_cmd=''' +# 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; +# ''' +# +# f_heavy_dml_cmd=open( os.path.join(context['temp_directory'],'tmp_isql_4855.sql'), 'w') +# f_heavy_dml_cmd.write(sql_cmd) +# flush_and_close( f_heavy_dml_cmd ) +# +# ##################################################################### +# # Starting ISQL in separate process with doing 'heavy DML' (bulk-inserts) until table 'stop' +# # remains empty (this table will get one row in separate ISQL session, see below p_stopper): +# +# f_heavy_dml_log=open( os.path.join(context['temp_directory'],'tmp_isql_4855.log'), 'w') +# p_heavy_dml = Popen([ context['isql_path'] , dsn, "-i", f_heavy_dml_cmd.name ], stdout=f_heavy_dml_log, stderr=subprocess.STDOUT) +# +# # Here we have to wait for sure that ISQL could establish its connect and starts DML +# # before we will run online-validation: +# +# # 16.03.2016: increased time delay because under some circumstances ISQL could not establish connect +# # and this lead validation to start verify table TEST (which was not expected). +# # Detected many times on CS/SC. +# +# time.sleep(4) +# +# +# ##################################################################### +# # Doing online-validation. +# # Use subprocess.call() with waiting in main thread for it will finish. +# +# val_log=open( os.path.join(context['temp_directory'],'tmp_onval_4855.log'), 'w') +# +# val_log.write('Iteration #1:\\n') +# val_log.seek(0,2) +# subprocess.call( [ context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_validate","val_lock_timeout","1", +# "dbname",dbname +# ], +# stdout=val_log, stderr=subprocess.STDOUT +# ) +# +# time.sleep(2) +# +# # Iteration #2: +# +# val_log.seek(0,2) +# val_log.write('\\n\\nIteration #2:\\n') +# val_log.seek(0,2) +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_validate","val_lock_timeout","1", +# "dbname",dbname], +# stdout=val_log, stderr=subprocess.STDOUT) +# flush_and_close( val_log ) +# +# ##################################################################### +# +# # Stopping ISQL that is doing now 'heavy DML' (bulk-inserts): +# +# f_stopper_cmd=open( os.path.join(context['temp_directory'],'tmp_stop_4855.sql'), 'w') +# f_stopper_cmd.write('insert into stop(id) values(1); commit;') +# flush_and_close( f_stopper_cmd ) +# p_stopper = subprocess.call([ context['isql_path'], dsn, "-i", f_stopper_cmd.name]) +# +# # Stop working ISQL. NB: in rare cases this can lead to: +# # + Statement failed, SQLSTATE = HY008 +# # + operation was cancelled +# # + After line ... in file .../tmp_isql_4855.sql +# +# p_heavy_dml.terminate() +# flush_and_close( f_heavy_dml_log ) +# +# with open( f_heavy_dml_log.name,'r') as f: +# print(f.read()) +# +# with open( val_log.name,'r') as f: +# print(f.read()) +# +# +# ##################################################################### +# # Cleanup: +# time.sleep(1) +# cleanup( (fwoff_log, val_log, f_heavy_dml_cmd, f_heavy_dml_log, f_stopper_cmd) ) +# +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +INSERTED_ROWS OK, LOT OF. +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 + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4855_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4864.py b/tests/bugs/test_core_4864.py new file mode 100644 index 00000000..b7b5affe --- /dev/null +++ b/tests/bugs/test_core_4864.py @@ -0,0 +1,169 @@ +#coding:utf-8 +# +# id: bugs.core_4864 +# title: CREATE DATABASE fail with ISQL +# decription: +# Test obtains full path to $fb_home via FBSVCMGR info_get_env. +# Then it makes copy of file 'databases.conf' that is in $fb_home directory because +# following lines will be added to that 'databases.conf': +# === +# tmp_alias_4864 = ... +# { +# SecurityDatabase = tmp_alias_4864 +# } +# === +# Then we run ISQL and give to it command to create database which definition +# should be taken from 'databases.conf', as it was explained in the ticket by Alex: +# === +# create database 'tmp_alias_4864' user 'SYSDBA'; +# === +# Finally, mon$attachment is queried and some info is extracted from it in order +# to be sure that we really got proper result. +# ............................................. +# ::: NB ::: +# It is impossible to check ability to create new user in new database that was made by such way: +# plugin 'Srp' is required that currently is replaced before any test with 'Legacy' one. +# +# tracker_id: CORE-4864 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import time +# import shutil +# import subprocess +# from subprocess import Popen +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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'): +# # 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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# svc = services.connect(host='localhost') +# fb_home=svc.get_home_directory() +# svc.close() +# +# dbconf = os.path.join(fb_home,'databases.conf') +# dbcbak = os.path.join(fb_home,'databases.bak') +# shutil.copy2( dbconf, dbcbak ) +# +# tmp_fdb = os.path.join(context['temp_directory'],'tmp_4864.fdb') +# +# cleanup( (tmp_fdb,) ) +# +# f_dbconf=open(dbconf,'a') +# f_dbconf.seek(0, 2) +# f_dbconf.write("\\n\\n# Created temply by fbtest, CORE-4864. Should be removed auto.") +# f_dbconf.write("\\n\\ntmp_alias_4864 = " + tmp_fdb ) +# f_dbconf.write("\\n{\\n SecurityDatabase = tmp_alias_4864 \\n}\\n") +# f_dbconf.close() +# +# isql_script=''' +# create database 'tmp_alias_4864' user 'SYSDBA'; +# set list on; +# select +# d.mon$sec_database +# ,a.mon$attachment_name +# ,a.mon$user +# ,a.mon$remote_protocol +# ,a.mon$remote_address +# ,a.mon$remote_process +# ,a.mon$auth_method +# from mon$database d cross join mon$attachments a +# where a.mon$attachment_id = current_connection; +# commit; +# drop database; +# quit; +# ''' +# +# f_isql_cmd=open( os.path.join(context['temp_directory'],'tmp_create_4864.sql'), 'w') +# f_isql_cmd.write( isql_script ) +# flush_and_close( f_isql_cmd ) +# +# f_isql_log=open( os.path.join(context['temp_directory'],'tmp_create_4864.log'), 'w') +# subprocess.call([context['isql_path'],"-q","-i",f_isql_cmd.name], stdout=f_isql_log, stderr=subprocess.STDOUT) +# flush_and_close( f_isql_log ) +# +# shutil.move(dbcbak, dbconf) +# +# with open( f_isql_log.name,'r') as f: +# print(f.read()) +# +# ##################################################################### +# # Cleanup: +# +# # do NOT remove this pause otherwise some of logs will not be enable for deletion and test will finish with +# # Exception raised while executing Python test script. exception: WindowsError: 32 +# time.sleep(1) +# cleanup( (f_isql_log, f_isql_cmd, tmp_fdb) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MON$SEC_DATABASE Self + MON$ATTACHMENT_NAME tmp_alias_4864 + MON$USER SYSDBA + MON$REMOTE_PROTOCOL + MON$REMOTE_ADDRESS + MON$REMOTE_PROCESS + MON$AUTH_METHOD User name in DPB + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4864_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4867.py b/tests/bugs/test_core_4867.py new file mode 100644 index 00000000..68f1f08e --- /dev/null +++ b/tests/bugs/test_core_4867.py @@ -0,0 +1,84 @@ +#coding:utf-8 +# +# id: bugs.core_4867 +# title: Server crash when preparing a query with PLAN clause at some CTE +# decription: +# tracker_id: CORE-4867 +# min_versions: ['2.5.5'] +# versions: 2.5.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Tested on: + -- LI-V2.5.5.26910 after commit http://sourceforge.net/p/firebird/code/61955 + -- LI-V3.0.0.31924 + + recreate table table1 ( + field1 integer not null + ); + + recreate table table2 ( + field1 integer not null, + date1 date not null + ); + + insert into table1 values(1); + insert into table2 values(1, date '30.06.2015'); + insert into table2 values(1, date '31.05.2015'); + insert into table2 values(1, date '31.07.2015'); + + insert into table1 values(2); + insert into table2 values(2, date '31.03.2012'); + insert into table2 values(2, date '29.05.2012'); + insert into table2 values(2, date '31.01.2012'); + commit; + + alter table table1 add constraint pk_table1 primary key (field1); + alter table table2 add constraint pk_table2 primary key (field1, date1) + using descending index pk_table2; + create index idx_table2 on table2 (field1, date1); + commit; + + set list on; + with aa + as (select t1.field1, + (select first 1 t2.date1 + from table2 t2 + where t2.field1 = t1.field1 + plan(t2 index(idx_table2)) + order by t2.field1 asc, t2.date1 asc) as date1 + from table1 t1) + + select date1, count('x') + from aa + group by 1; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DATE1 2012-01-31 + COUNT 1 + + DATE1 2015-05-31 + COUNT 1 +""" + +@pytest.mark.version('>=2.5.5') +def test_core_4867_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4870.py b/tests/bugs/test_core_4870.py new file mode 100644 index 00000000..34aa0fcf --- /dev/null +++ b/tests/bugs/test_core_4870.py @@ -0,0 +1,106 @@ +#coding:utf-8 +# +# id: bugs.core_4870 +# title: Incorrect number of affected rows for UPDATE against VIEW created WITH CHECK OPTION +# decription: +# Issue about 2.5.x: added artificial sort inside MERGE source: "using( select ... from test ORDER BY X ) s" +# - for suppressing undesirable effect of unstable cursor. +# Until 21-may-2016 ISQL 2.5 did not contain portion that fixed CORE-4817 +# (see: https://github.com/FirebirdSQL/firebird/commit/845120fdb9b5934e3af32b5404ffde7ed363724d ) +# - letter from dimitr, 21-may-2016 14:51. +# +# tracker_id: CORE-4870 +# min_versions: ['2.5.6'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Checked on LI-V3.0.0.32008, build after commiting rev. http://sourceforge.net/p/firebird/code/62140 + create or alter view v_test3 as select 1 id from rdb$database; + create or alter view v_test2 as select 1 id from rdb$database; + create or alter view v_test1 as select 1 id from rdb$database; + commit; + + recreate table test(id int primary key, x int); + commit; + insert into test values(1, 100); + insert into test values(2, 200); + insert into test values(3, 300); + insert into test values(4, 400); + insert into test values(5, 500); + insert into test values(6, 600); + commit; + + recreate view v_test1 as select * from test where mod(id, 3)=0; + recreate view v_test2 as select * from test where mod(id, 3)=0 with check option; + recreate view v_test3 as select * from v_test2 where mod(id, 3)=0 with check option; + commit; + + set count on; + update v_test1 set x = -x where mod(id,3) = 0; + rollback; + + update v_test2 set x = -x where mod(id,3) = 0; + rollback; + + update v_test3 set x = -x where mod(id,3) = 0; + rollback; + + merge into v_test1 t using( select id, x from test ) s on t.id = s.id + when matched then update set x = -s.x + when not matched then insert(id, x) values( -3 * s.id, -s.x ) + ; + rollback; + + merge into v_test2 t using( select id, x from test ) s on t.id = s.id + when matched then update set x = -s.x + when not matched then insert(id, x) values( -3 * s.id, -s.x ) + ; + rollback; + + merge into v_test3 t using( select id, x from test ) s on t.id = s.id + when matched then update set x = -s.x + when not matched then insert(id, x) values( -3 * s.id, -s.x ) + ; + rollback; + + insert into v_test1(id, x) values( 9, 900); + insert into v_test2(id, x) values(12, 1200); + insert into v_test3(id, x) values(15, 1500); + rollback; + + set count off; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 2 + Records affected: 2 + Records affected: 2 + Records affected: 6 + Records affected: 6 + Records affected: 6 + Records affected: 1 + Records affected: 1 + Records affected: 1 + """ + +@pytest.mark.version('>=3.0') +def test_core_4870_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4874.py b/tests/bugs/test_core_4874.py new file mode 100644 index 00000000..f6030d4a --- /dev/null +++ b/tests/bugs/test_core_4874.py @@ -0,0 +1,79 @@ +#coding:utf-8 +# +# id: bugs.core_4874 +# title: Infinite "similar to" matching +# decription: +# Confirmed normal work (evaluation for less than 2 ms) on WI-T4.0.0.1598 +# +# tracker_id: CORE-4874 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + + set term ^; + execute block as + begin + rdb$set_context( 'USER_SESSION','DTS_START', cast('now' as timestamp) ); + rdb$set_context( 'USER_SESSION','MAX_THRESHOLD_MS', 500 ); + -- ^ + -- | + -- ############################# + -- MAX ALLOWED EXECUTION TIME,MS + -- ############################# + end + ^ + set term ;^ + + select 1 from rdb$database + where + '' + similar to '%>(_%_){0,6}' escape '\\' + -- ^ + -- | + -- ATTENTION: TWO BACKSLASHES MUST BE HERE WHEN USE FBT_RUN TO CHECK + -- ############### + ; + + set count off; + select + iif( evaluated_ms <= max_allowed_ms + ,'acceptable' + ,'TOO LONG: ' || evaluated_ms || ' ms - this is more then threshold = ' || max_allowed_ms || ' ms' + ) as duration + from ( + select + datediff( millisecond from cast(rdb$get_context( 'USER_SESSION','DTS_START') as timestamp) to current_timestamp ) evaluated_ms + ,cast( rdb$get_context( 'USER_SESSION','MAX_THRESHOLD_MS' ) as int ) as max_allowed_ms + from rdb$database + ); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + DURATION acceptable + """ + +@pytest.mark.version('>=4.0') +def test_core_4874_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4879.py b/tests/bugs/test_core_4879.py new file mode 100644 index 00000000..7d63c29d --- /dev/null +++ b/tests/bugs/test_core_4879.py @@ -0,0 +1,106 @@ +#coding:utf-8 +# +# id: bugs.core_4879 +# title: Minor inconvenience in user management via services API +# decription: +# Confirmed weird error message on 3.0.0.31374. +# Command: +# fbsvcmgr.exe localhost:service_mgr user sysdba password masterkey action_add_user dbname employee sec_username foo sec_password 123 +# - failed with: +# unexpected item in service parameter block, expected isc_spb_sec_username +# Checked on 4.0.0.2307; 3.0.8.33393. +# +# tracker_id: CORE-4879 +# min_versions: ['3.0.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import subprocess +# from subprocess import Popen +# import time +# +# #-------------------------------------------- +# +# 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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# this_fdb=db_conn.database_name +# db_conn.close() +# +# f_svc_log=open( os.path.join(context['temp_directory'],'tmp_4879_fbsvc.log'), "w", buffering = 0) +# # C:\\FB\\old.3b1 +# bsvcmgr.exe localhost:service_mgr user sysdba password masterkey action_add_user dbname employee sec_username foo sec_password 123 +# subprocess.call( [context['fbsvcmgr_path'], "localhost:service_mgr", "action_add_user", "dbname", this_fdb, "sec_username", "TMP$C4879", "sec_password", "123" ], +# stdout=f_svc_log, +# stderr=subprocess.STDOUT +# ) +# +# subprocess.call( [context['fbsvcmgr_path'], "localhost:service_mgr", "action_delete_user", "dbname", this_fdb, "sec_username", "TMP$C4879" ], +# stdout=f_svc_log, +# stderr=subprocess.STDOUT +# ) +# +# flush_and_close(f_svc_log) +# +# with open( f_svc_log.name,'r') as f: +# for line in f: +# if line.split(): +# print('UNEXPECTED OUTPUT in '+f_svc_log.name+': '+line) +# +# +# # CLEANUP +# ######### +# time.sleep(1) +# cleanup( (f_svc_log.name,) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4879_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4880.py b/tests/bugs/test_core_4880.py new file mode 100644 index 00000000..6152134e --- /dev/null +++ b/tests/bugs/test_core_4880.py @@ -0,0 +1,122 @@ +#coding:utf-8 +# +# id: bugs.core_4880 +# title: Increase speed of creating package when number of its functions more than several hundreds +# decription: +# This test uses TWO auto-generated scripts, both of them have been packed due to their size in files/core_4880.zip +# and are unpacked at runtime here. +# First script, 'core_4880_fnc.tmp', creates 5'000 STANDALONE functions and adds into log timestamps of start and finish. +# Second script, 'core_4880_pkg.tmp', creates PACKAGE with head and body also of 5'000 functions and also adds into log +# timestamps for start of 'create package' and finish of 'create package BODY' statements. +# Both scripts use simplest body of functions. +# +# After both scripts will be finishec, number of seconds is compared for creation: +# 1) standalone functions and 2) package header and body with the same number of functions. +# Then, we evaluate maxValue and minValue in this pair and result of division: maxValue / minValue, casted to num(12,2). +# +# Numerous runs showed that this ratio (N) is about 1.2 ... 1.5, and it never was more than 1.8. +# It was decided to use N = 2 as max acceptable ratio between time for creation of package and for standalone funcions. +# If any kind of objects (package or s/alone funcs) will be created more than N times than another, expected_stdout +# will contain phrase about regression. +# +# Checked on WI-V3.0.0.32008, machine: P-IV 3.0 Ghz RAM 2Gb, OS = Win XP. +# Duration of test on that machine is about 45-55 seconds. +# +# 13.04.2021. Adapted for run both on Windows and Linux. Checked on: +# Windows: 3.0.8.33445, 4.0.0.2416 +# Linux: 3.0.8.33426, 4.0.0.2416 +# +# tracker_id: CORE-4880 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table log( + standalone_func_beg timestamp default null + ,standalone_func_end timestamp default null + ,pkg_head_n_body_beg timestamp default null + ,pkg_head_n_body_end timestamp default null + ); + commit; + insert into log default values; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import zipfile +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# runProgram('gfix',['-w','async',dsn]) +# +# zf = zipfile.ZipFile( os.path.join(context['files_location'],'core_4880.zip') ) +# zf.extractall( context['temp_directory'] ) +# zf.close() +# runProgram('isql',[dsn,'-q','-i', os.path.join(context['temp_directory'],'core_4880_fnc.tmp') ]) +# runProgram('isql',[dsn,'-q','-i', os.path.join(context['temp_directory'],'core_4880_pkg.tmp') ]) +# +# os.remove( os.path.join(context['temp_directory'],'core_4880_fnc.tmp') ) +# os.remove( os.path.join(context['temp_directory'],'core_4880_pkg.tmp') ) +# +# script="""set list on; +# set term ^; +# execute block as +# begin +# rdb$set_context('USER_SESSION', 'MAX_ACCEPTABLE_RATIO', '2'); +# -- ^ +# -- ################# +# -- T H R E S H O L D +# -- ################# +# end +# ^ +# set term ;^ +# +# select iif( x.ratio < cast( rdb$get_context('USER_SESSION', 'MAX_ACCEPTABLE_RATIO') as int ), +# 'Ratio is acceptable', +# 'Regression, ratio >= ' || rdb$get_context('USER_SESSION', 'MAX_ACCEPTABLE_RATIO') || 'x' +# ) as result_msg +# --, x.* +# from ( +# select +# standalone_func_sec +# ,pkg_head_n_body_sec +# ,cast( iif( pkg_head_n_body_sec > standalone_func_sec, 1.00 * pkg_head_n_body_sec / standalone_func_sec, 1.00 * standalone_func_sec / pkg_head_n_body_sec ) as numeric(12,2) ) as ratio +# ,cast( 1.00 * pkg_head_n_body_sec / standalone_func_sec as numeric(12,2) ) package_vs_standalone +# ,cast( 1.00 * standalone_func_sec / pkg_head_n_body_sec as numeric(12,2) ) standalone_vs_package +# from ( +# select +# nullif( datediff(second from standalone_func_beg to standalone_func_end), 0) standalone_func_sec +# ,nullif( datediff(second from pkg_head_n_body_beg to pkg_head_n_body_end), 0) pkg_head_n_body_sec +# from log +# ) +# ) x; +# """ +# runProgram('isql',[dsn,'-q'],script) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT_MSG Ratio is acceptable + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4880_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4881.py b/tests/bugs/test_core_4881.py new file mode 100644 index 00000000..a0cf8005 --- /dev/null +++ b/tests/bugs/test_core_4881.py @@ -0,0 +1,82 @@ +#coding:utf-8 +# +# id: bugs.core_4881 +# title: Increase maximum string literal length to 64K (bytes) while setting a lower limit (of characters) for multibyte charsets based on their max char. length (UTF-8 literals will be limited to 16383 characters) +# decription: +# Test verifies that one may to operate with string literals: +# 1) containing only ascii characters (and limit for this case should be 65535 bytes (=chars)) +# 2) containing unicode characters but all of them requires 3 bytes for encoding (and limit for this should be 16383 character) +# 3) containing literals with mixed byte-per-character encoding requirement (limit should be also 16383 character). +# Before 3.0.0.31981 following statement raises: +# String literal with 65536 bytes exceeds the maximum length of 32767 bytes +# tracker_id: CORE-4881 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set term ^; + execute block returns( + o_len_ascii_only int, c_len_ascii_only int, + o_len_utf8_3bpc int, c_len_utf8_3bpc int, + o_len_utf8_mixed int, c_len_utf8_mixed int + ) as + begin + o_len_ascii_only = octet_length( + _octets '0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfds0123456789qwertyuioplkjhgfdsazxcvbn' + ); + c_len_ascii_only = char_length( + _octets '0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfdsazxcvbnm,./;:''"[]{}=-_+|\\!@#$%^&*()`0123456789qwertyuioplkjhgfds0123456789qwertyuioplkjhgfdsazxcvbn' + ); + + o_len_utf8_3bpc = octet_length( + _utf8 '∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑€' + ); + c_len_utf8_3bpc = char_length( + _utf8 '∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑∏Ω∑€' + ); + + o_len_utf8_mixed = octet_length( + _utf8 'ååååDer Reichthum an Volksliedern in den Niederlanden war einst sehr groß; der Nachwelt sollte es nicht vergönnt sein, die volle Erbschaft anzutreten, wir müssen uns mit dem was uns blieb begnügen und wollen uns sein erfreuen. So dürftig jedoch ist der übrig gebliebene Theil nicht, wie ihn meine erste Sammlung [4] darbot: Zufall, Glück, emsiges Forschen, und die auch in den Niederlanden dem Volksliede gewidmete Theilnahme haben den Stoff vervielfältigt, und so ist es mir denn jetzt gelungen, obschon ich mich nur auf eigentliche Volkslieder und die volksthümlichen Lieder beschränkte und die älteren geistlichen ausschied (s. Hor. belg. P. X.), eine reichere Sammlung zu Stande zu bringen. Domin: Tak tedy. (sedne si na psací stůl, pozoruje Helenu uchvácen a odříkává rychle) Bylo to roku 1920 kdy se starý Rossum veliký filozof ale tehdy ještě mladý učenec odebral na tento daleký ostrov aby studoval mořské živočišstvo tečka. Přitom se pokoušel napodobit chemickou syntézou živou hmotu řečenou protoplazma až najednou objevil látku která se chovala naprosto jako živá hmota ač byla jiného chemického složení to bylo roku 1932, právě čtyři sta čtyřicet let po objevení Ameriky, uf. Helena: To umíte zpaměti? Domin: Ano; fyziologie, slečno Gloryová, není mým řemeslem. Tak dál? Helena: Třeba. Domin: (slavnostně) A tehdy, slečno, starý Rossum napsal mezi své chemické vzorce tohleto: "Příroda našla jeden způsob, jak organizovat živou hmotu. Je však jiný způsob, jednodušší, tvárnější a rychlejší, na nějž příroda vůbec nenarazila. Tuto druhou cestu, po které se mohl brát vývoj života, jsem dnešního dne objevil." Představte si, slečno, že tahle veliká slova psal nad chrchlem jakéhosi koloidálního rosolu, který by ani pes nesežral. Představte si ho, že sedí nad zkumavkou a myslí na to, jak z ní vyroste celý strom života, jak z ní budou vycházet všechna zvířata, počínajíc vířníkem a končíc--končíc samotným člověkem. Člověk z jiné látky, než jsme my. Slečno Gloryová, to byl ohromný okamžik. Sur le boulevard Montmorency, au n° 53, s''élève une maison portant, encastré dans son balcon, un profil lauré de Louis XV, en bronze doré, qui a tout l''air d''être le médaillon, dont était décorée la tribune de musique de la salle à manger de Luciennes, représenté dans l''aquarelle de Moreau que l''on voit au Louvre. Cette tête, que quelques promeneurs regardent d''un œil farouche, n''est point,--ai-je besoin de le dire?--une affiche des opinions politiques du propriétaire, elle est tout bonnement l''enseigne d''un des nids les plus pleins de choses du XVIIIe siècle qui existent à Paris. La porte noire, que surmonte un élégant dessus de grille de chapelle jésuite en fer forgé, la porte ouverte, du bas de l''escalier, de l''entrée du vestibule, du seuil de la maison, le visiteur est accueilli par des terres cuites, des bronzes, des dessins, des porcelaines du siècle aimable par excellence, mêlés à des objets de l''Extrême-Orient, qui se trouvaient faire si bon ménage dans les collections de Madame de Pompadour et de tous les _curieux_ et les _curiolets_ du temps. Σημείωση: Ο τονισμός έχει αλλάξει από πολυτονικό σε μονοτονικό, κατά τα άλλα έχει διατηρηθεί η ορθογραφία του βιβλίου. Λέξεις με πλαγίους χαρακτήρες έχουν σημειωθεί με _. Οι υποσημειώσεις έχουν μεταφερθεί στο τέλος του βιβλίου και οι αριθμοί τους περικλείονται σε (). Ο Μεταφραστής έχει προσθέσει πολλές υποσημειώσεις που δεν είναι μέρος του αρχικού βιβλίου. Το κείμενό τους τις περισσότερες φορές περικλείεται σε []. Επίσης, επέλεξε να βρει και να παραθέσει στην αρχαία γλώσσα όλα τα αρχαία κείμενα που παραθέτει στα αγγλικά ο Murray. Επειδή πολλοί έλληνες έχουν καλλίτερη γνώση των αγγλικών από τα αρχαία ελληνικά, παραθέτω προς διευκόλυνσή τους το αγγλικό κείμενο, εντός {}. Σπάνια, υπάρχουν διαφορές εντός των δυο επιλεγμένων κειμένων (μήκος ή ακόμα και κείμενο) ή το αρχαίο κείμενο δεν υπάρχει στα αγγλικά στο βιβλίο. Έχω λάβει επίσης υπόψη τον Przyjaciel Dziatek" leci: Z książeczką leci nową, Pozdrowień niesie słowo, Do domków, do szkół spieszy, Toż dziatwa się ucieszy!... A jest się cieszyć z czego, Bo dużo tu nowego: Są bajki i bajeczki, Są wiersze i piosneczki, Są żarty i figielki, Obrazków zapas wielki, Zwierzątka też znajdziecie Więc czegóż więcej chcecie?!... Pójdźcieże więc dziateczki, Chłopaczki i dzieweczki: Niech każde pilnie czyta, "PRZYJACIEL DZIATEK" wita I prosi Was serdecznie: Usiądźcie sobie grzecznie, Książeczkę tę czytajcie, Nauczki spamiętajcie. Gdy słuchać ich zechcecie, Miłemi się staniecie Już teraz, już od młodu, Dla Boga i narodu. Więc: Baczność! Baczność Dzieci! "PRZYJACIEL DZIATEK" leci: Z książeczką bieży nową, Pozdrowień niesie słowo Este dialecto é fallado principalmente pela população de côr e pelas creanças que o aprendem com as creadas e amas negras. Distinguem-se duas fórmas: o creolo _rachado_, creolo _fundo_, creolo _vejo_, fallado principalmente no interior da ilha e de que as noticias e documentos que publicâmos dão conhecimento, e o creolo em que a grammatica portugueza é menos ignorada, distinguindo-se quasi unicamente pela pronuncia de algumas palavras ou sons e pelo accento geral. Все члены семьи и домочадцы чувствовали, что нет смысла в их сожительстве и что на каждом постоялом дворе случайно сошедшиеся люди более связаны между собой, чем они, члены семьи и домочадцы Облонских. Жена не выходила из своих комнат, мужа третий день не было дома. Дети бегали по всему дому, как потерянные; англичанка поссорилась с экономкой и написала записку приятельнице, прося приискать ей новое место; повар ушел еще вчера со двора, во время обеда; черная кухарка и кучер просили расчета. На третий день после ссоры князь Степан Аркадьич Облонский -- Стива, как его звали в свете, -- в обычный час, то есть в восемь часов утра, проснулся не в спальне жены, а в своем кабинете, на сафьянном диване... Он повернул свое полное, выхоленное тело на пружинах дивана, как бы желая опять заснуть надолго, с другой стороны крепко обнял подушку и прижался к ней щекой; но вдруг вскочил, сел на диван и открыл глаза. Kun oleskelin Jerusalemissa vuonna 1831 ja kävin Israelin kuninkaitten tarun-omaisissa hautakammioissa, ajatukseni palasivat erääsen henkilöön, jonka ihmeellinen elämän-juoksu oli jo nuoruudessani kiinnittänyt huomiotani, koska se oli täynnä mitä runsaimpia aiheita runolliseen teokseen. Silloin minä aloitin tätä kertomusta, jonka oli määrä säilyttää _Alroy''n_ muistoa. Kahdennellatoista vuosisadalla, jolloin Alroy astui esiin, oli Idän valtiollinen asema tämmöinen. Kalifatia uhkasi pikaisesti lähestyvä häviö. Seldshukien sultanit, joita oikea-uokoisten hallitsiat olivat kutsuneet avuksensa, olivat, niinkuin Ranskan majordomit, kohonneet valtakunnan varsinaisiksi isänniksi. He olivat Profeetan jälkeläisten maista lohkoneet itselleen neljä kuningaskuntaa, jotka tuottivat sultanin nimen neljälle seldshukilaiselle ruhtinaalle, nimittäin Bagdadin, Persian, Syrian ja Rumin eri Vähän Aasian sultanille. Inte var det just mycket med Helenas humör heller, sedan hon och Jesper hade skilts åt. Hon kom å ena sidan ihåg sin moders pinos historia och gummans många förmaningar, att dottern aldrig skulle göra sig till skotrasa för en karl. Hennes sista ord hade ju varit: »Om du är så enfaldig och tror på någon och tar honom och han gör dig olycklig -- och det gör han -- så vänder jag mig i grafven!» Inte skulle gamla mor behöfva störas i sin griftero för den sakens skull! Men å andra sidan hade det sina sidor att tjäna. Så länge hon ännu var ung och kunde ta i med bägge näfvarna, kunde det nog gå; men när åldern toge till och krafterna toge af -- ja, hvad skulle då bli hennes lott? Fattighuset, förstås. Nog skulle väl alltid prosten ha en vrå och en beta bröd åt henne, om han lefde. Men han hade ju hunnit ut på ålderdomen och kunde falla ifrån när som helst, och man vet, hur det går, när »det kommer en ny konung, som ingenting vet om Josef». Det är inte alla präster, som göra prästgården eller dess torp till änkesäte åt orkeslösa trotjänarinnor, hade biskopen en gång sagt om Helenas prost. ååååååDer Reichthum an Volksliedern in den Niederlanden war einst sehr groß; der Nachwelt sollte es nicht vergönnt sein, die volle Erbschaft anzutreten, wir müssen uns mit dem was uns blieb begnügen und wollen uns sein erfreuen. So dürftig jedoch ist der übrig gebliebene Theil nicht, wie ihn meine erste Sammlung [4] darbot: Zufall, Glück, emsiges Forschen, und die auch in den Niederlanden dem Volksliede gewidmete Theilnahme haben den Stoff vervielfältigt, und so ist es mir denn jetzt gelungen, obschon ich mich nur auf eigentliche Volkslieder und die volksthümlichen Lieder beschränkte und die älteren geistlichen ausschied (s. Hor. belg. P. X.), eine reichere Sammlung zu Stande zu bringen. Domin: Tak tedy. (sedne si na psací stůl, pozoruje Helenu uchvácen a odříkává rychle) Bylo to roku 1920 kdy se starý Rossum veliký filozof ale tehdy ještě mladý učenec odebral na tento daleký ostrov aby studoval mořské živočišstvo tečka. Přitom se pokoušel napodobit chemickou syntézou živou hmotu řečenou protoplazma až najednou objevil látku která se chovala naprosto jako živá hmota ač byla jiného chemického složení to bylo roku 1932, právě čtyři sta čtyřicet let po objevení Ameriky, uf. Helena: To umíte zpaměti? Domin: Ano; fyziologie, slečno Gloryová, není mým řemeslem. Tak dál? Helena: Třeba. Domin: (slavnostně) A tehdy, slečno, starý Rossum napsal mezi své chemické vzorce tohleto: "Příroda našla jeden způsob, jak organizovat živou hmotu. Je však jiný způsob, jednodušší, tvárnější a rychlejší, na nějž příroda vůbec nenarazila. Tuto druhou cestu, po které se mohl brát vývoj života, jsem dnešního dne objevil." Představte si, slečno, že tahle veliká slova psal nad chrchlem jakéhosi koloidálního rosolu, který by ani pes nesežral. Představte si ho, že sedí nad zkumavkou a myslí na to, jak z ní vyroste celý strom života, jak z ní budou vycházet všechna zvířata, počínajíc vířníkem a končíc--končíc samotným člověkem. Člověk z jiné látky, než jsme my. Slečno Gloryová, to byl ohromný okamžik. Sur le boulevard Montmorency, au n° 53, s''élève une maison portant, encastré dans son balcon, un profil lauré de Louis XV, en bronze doré, qui a tout l''air d''être le médaillon, dont était décorée la tribune de musique de la salle à manger de Luciennes, représenté dans l''aquarelle de Moreau que l''on voit au Louvre. Cette tête, que quelques promeneurs regardent d''un œil farouche, n''est point,--ai-je besoin de le dire?--une affiche des opinions politiques du propriétaire, elle est tout bonnement l''enseigne d''un des nids les plus pleins de choses du XVIIIe siècle qui existent à Paris. La porte noire, que surmonte un élégant dessus de grille de chapelle jésuite en fer forgé, la porte ouverte, du bas de l''escalier, de l''entrée du vestibule, du seuil de la maison, le visiteur est accueilli par des terres cuites, des bronzes, des dessins, des porcelaines du siècle aimable par excellence, mêlés à des objets de l''Extrême-Orient, qui se trouvaient faire si bon ménage dans les collections de Madame de Pompadour et de tous les _curieux_ et les _curiolets_ du temps. Σημείωση: Ο τονισμός έχει αλλάξει από πολυτονικό σε μονοτονικό, κατά τα άλλα έχει διατηρηθεί η ορθογραφία του βιβλίου. Λέξεις με πλαγίους χαρακτήρες έχουν σημειωθεί με _. Οι υποσημειώσεις έχουν μεταφερθεί στο τέλος του βιβλίου και οι αριθμοί τους περικλείονται σε (). Ο Μεταφραστής έχει προσθέσει πολλές υποσημειώσεις που δεν είναι μέρος του αρχικού βιβλίου. Το κείμενό τους τις περισσότερες φορές περικλείεται σε []. Επίσης, επέλεξε να βρει και να παραθέσει στην αρχαία γλώσσα όλα τα αρχαία κείμενα που παραθέτει στα αγγλικά ο Murray. Επειδή πολλοί έλληνες έχουν καλλίτερη γνώση των αγγλικών από τα αρχαία ελληνικά, παραθέτω προς διευκόλυνσή τους το αγγλικό κείμενο, εντός {}. Σπάνια, υπάρχουν διαφορές εντός των δυο επιλεγμένων κειμένων (μήκος ή ακόμα και κείμενο) ή το αρχαίο κείμενο δεν υπάρχει στα αγγλικά στο βιβλίο. Έχω λάβει επίσης υπόψη τον Przyjaciel Dziatek" leci: Z książeczką leci nową, Pozdrowień niesie słowo, Do domków, do szkół spieszy, Toż dziatwa się ucieszy!... A jest się cieszyć z czego, Bo dużo tu nowego: Są bajki i bajeczki, Są wiersze i piosneczki, Są żarty i figielki, Obrazków zapas wielki, Zwierzątka też znajdziecie Więc czegóż więcej chcecie?!... Pójdźcieże więc dziateczki, Chłopaczki i dzieweczki: Niech każde pilnie czyta, "PRZYJACIEL DZIATEK" wita I prosi Was serdecznie: Usiądźcie sobie grzecznie, Książeczkę tę czytajcie, Nauczki spamiętajcie. Gdy słuchać ich zechcecie, Miłemi się staniecie Już teraz, już od młodu, Dla Boga i narodu. Więc: Baczność! Baczność Dzieci! "PRZYJACIEL DZIATEK" leci: Z książeczką bieży nową, Pozdrowień niesie słowo Este dialecto é fallado principalmente pela população de côr e pelas creanças que o aprendem com as creadas e amas negras. Distinguem-se duas fórmas: o creolo _rachado_, creolo _fundo_, creolo _vejo_, fallado principalmente no interior da ilha e de que as noticias e documentos que publicâmos dão conhecimento, e o creolo em que a grammatica portugueza é menos ignorada, distinguindo-se quasi unicamente pela pronuncia de algumas palavras ou sons e pelo accento geral. Все члены семьи и домочадцы чувствовали, что нет смысла в их сожительстве и что на каждом постоялом дворе случайно сошедшиеся люди более связаны между собой, чем они, члены семьи и домочадцы Облонских. Жена не выходила из своих комнат, мужа третий день не было дома. Дети бегали по всему дому, как потерянные; англичанка поссорилась с экономкой и написала записку приятельнице, прося приискать ей новое место; повар ушел еще вчера со двора, во время обеда; черная кухарка и кучер просили расчета. На третий день после ссоры князь Степан Аркадьич Облонский -- Стива, как его звали в свете, -- в обычный час, то есть в восемь часов утра, проснулся не в спальне жены, а в своем кабинете, на сафьянном диване... Он повернул свое полное, выхоленное тело на пружинах дивана, как бы желая опять заснуть надолго, с другой стороны крепко обнял подушку и прижался к ней щекой; но вдруг вскочил, сел на диван и открыл глаза. Kun oleskelin Jerusalemissa vuonna 1831 ja kävin Israelin kuninkaitten tarun-omaisissa hautakammioissa, ajatukseni palasivat erääsen henkilöön, jonka ihmeellinen elämän-juoksu oli jo nuoruudessani kiinnittänyt huomiotani, koska se oli täynnä mitä runsaimpia aiheita runolliseen teokseen. Silloin minä aloitin tätä kertomusta, jonka oli määrä säilyttää _Alroy''n_ muistoa. Kahdennellatoista vuosisadalla, jolloin Alroy astui esiin, oli Idän valtiollinen asema tämmöinen. Kalifatia uhkasi pikaisesti lähestyvä häviö. Seldshukien sultanit, joita oikea-uokoisten hallitsiat olivat kutsuneet avuksensa, olivat, niinkuin Ranskan majordomit, kohonneet valtakunnan varsinaisiksi isänniksi. He olivat Profeetan jälkeläisten maista lohkoneet itselleen neljä kuningaskuntaa, jotka tuottivat sultanin nimen neljälle seldshukilaiselle ruhtinaalle, nimittäin Bagdadin, Persian, Syrian ja Rumin eri Vähän Aasian sultanille. Inte var det just mycket med Helenas humör heller, sedan hon och Jesper hade skilts åt. Hon kom å ena sidan ihåg sin moders pinos historia och gummans många förmaningar, att dottern aldrig skulle göra sig till skotrasa för en karl. Hennes sista ord hade ju varit: »Om du är så enfaldig och tror på någon och tar honom och han gör dig olycklig -- och det gör han -- så vänder jag mig i grafven!» Inte skulle gamla mor behöfva störas i sin griftero för den sakens skull! Men å andra sidan hade det sina sidor att tjäna. Så länge hon ännu var ung och kunde ta i med bägge näfvarna, kunde det nog gå; men när åldern toge till och krafterna toge af -- ja, hvad skulle då bli hennes lott? Fattighuset, förstås. Nog skulle väl alltid prosten ha en vrå och en beta bröd åt henne, om han lefde. Men han hade ju hunnit ut på ålderdomen och kunde falla ifrån när som helst, och man vet, hur det går, när »det kommer en ny konung, som ingenting vet om Josef». Det är inte alla präster, som göra prästgården eller dess torp till änkesäte åt orkeslösa trotjänarinnor, hade biskopen en gång sagt om Helenas prost.åååå' + ); + + c_len_utf8_mixed = char_length( + _utf8 'ååååDer Reichthum an Volksliedern in den Niederlanden war einst sehr groß; der Nachwelt sollte es nicht vergönnt sein, die volle Erbschaft anzutreten, wir müssen uns mit dem was uns blieb begnügen und wollen uns sein erfreuen. So dürftig jedoch ist der übrig gebliebene Theil nicht, wie ihn meine erste Sammlung [4] darbot: Zufall, Glück, emsiges Forschen, und die auch in den Niederlanden dem Volksliede gewidmete Theilnahme haben den Stoff vervielfältigt, und so ist es mir denn jetzt gelungen, obschon ich mich nur auf eigentliche Volkslieder und die volksthümlichen Lieder beschränkte und die älteren geistlichen ausschied (s. Hor. belg. P. X.), eine reichere Sammlung zu Stande zu bringen. Domin: Tak tedy. (sedne si na psací stůl, pozoruje Helenu uchvácen a odříkává rychle) Bylo to roku 1920 kdy se starý Rossum veliký filozof ale tehdy ještě mladý učenec odebral na tento daleký ostrov aby studoval mořské živočišstvo tečka. Přitom se pokoušel napodobit chemickou syntézou živou hmotu řečenou protoplazma až najednou objevil látku která se chovala naprosto jako živá hmota ač byla jiného chemického složení to bylo roku 1932, právě čtyři sta čtyřicet let po objevení Ameriky, uf. Helena: To umíte zpaměti? Domin: Ano; fyziologie, slečno Gloryová, není mým řemeslem. Tak dál? Helena: Třeba. Domin: (slavnostně) A tehdy, slečno, starý Rossum napsal mezi své chemické vzorce tohleto: "Příroda našla jeden způsob, jak organizovat živou hmotu. Je však jiný způsob, jednodušší, tvárnější a rychlejší, na nějž příroda vůbec nenarazila. Tuto druhou cestu, po které se mohl brát vývoj života, jsem dnešního dne objevil." Představte si, slečno, že tahle veliká slova psal nad chrchlem jakéhosi koloidálního rosolu, který by ani pes nesežral. Představte si ho, že sedí nad zkumavkou a myslí na to, jak z ní vyroste celý strom života, jak z ní budou vycházet všechna zvířata, počínajíc vířníkem a končíc--končíc samotným člověkem. Člověk z jiné látky, než jsme my. Slečno Gloryová, to byl ohromný okamžik. Sur le boulevard Montmorency, au n° 53, s''élève une maison portant, encastré dans son balcon, un profil lauré de Louis XV, en bronze doré, qui a tout l''air d''être le médaillon, dont était décorée la tribune de musique de la salle à manger de Luciennes, représenté dans l''aquarelle de Moreau que l''on voit au Louvre. Cette tête, que quelques promeneurs regardent d''un œil farouche, n''est point,--ai-je besoin de le dire?--une affiche des opinions politiques du propriétaire, elle est tout bonnement l''enseigne d''un des nids les plus pleins de choses du XVIIIe siècle qui existent à Paris. La porte noire, que surmonte un élégant dessus de grille de chapelle jésuite en fer forgé, la porte ouverte, du bas de l''escalier, de l''entrée du vestibule, du seuil de la maison, le visiteur est accueilli par des terres cuites, des bronzes, des dessins, des porcelaines du siècle aimable par excellence, mêlés à des objets de l''Extrême-Orient, qui se trouvaient faire si bon ménage dans les collections de Madame de Pompadour et de tous les _curieux_ et les _curiolets_ du temps. Σημείωση: Ο τονισμός έχει αλλάξει από πολυτονικό σε μονοτονικό, κατά τα άλλα έχει διατηρηθεί η ορθογραφία του βιβλίου. Λέξεις με πλαγίους χαρακτήρες έχουν σημειωθεί με _. Οι υποσημειώσεις έχουν μεταφερθεί στο τέλος του βιβλίου και οι αριθμοί τους περικλείονται σε (). Ο Μεταφραστής έχει προσθέσει πολλές υποσημειώσεις που δεν είναι μέρος του αρχικού βιβλίου. Το κείμενό τους τις περισσότερες φορές περικλείεται σε []. Επίσης, επέλεξε να βρει και να παραθέσει στην αρχαία γλώσσα όλα τα αρχαία κείμενα που παραθέτει στα αγγλικά ο Murray. Επειδή πολλοί έλληνες έχουν καλλίτερη γνώση των αγγλικών από τα αρχαία ελληνικά, παραθέτω προς διευκόλυνσή τους το αγγλικό κείμενο, εντός {}. Σπάνια, υπάρχουν διαφορές εντός των δυο επιλεγμένων κειμένων (μήκος ή ακόμα και κείμενο) ή το αρχαίο κείμενο δεν υπάρχει στα αγγλικά στο βιβλίο. Έχω λάβει επίσης υπόψη τον Przyjaciel Dziatek" leci: Z książeczką leci nową, Pozdrowień niesie słowo, Do domków, do szkół spieszy, Toż dziatwa się ucieszy!... A jest się cieszyć z czego, Bo dużo tu nowego: Są bajki i bajeczki, Są wiersze i piosneczki, Są żarty i figielki, Obrazków zapas wielki, Zwierzątka też znajdziecie Więc czegóż więcej chcecie?!... Pójdźcieże więc dziateczki, Chłopaczki i dzieweczki: Niech każde pilnie czyta, "PRZYJACIEL DZIATEK" wita I prosi Was serdecznie: Usiądźcie sobie grzecznie, Książeczkę tę czytajcie, Nauczki spamiętajcie. Gdy słuchać ich zechcecie, Miłemi się staniecie Już teraz, już od młodu, Dla Boga i narodu. Więc: Baczność! Baczność Dzieci! "PRZYJACIEL DZIATEK" leci: Z książeczką bieży nową, Pozdrowień niesie słowo Este dialecto é fallado principalmente pela população de côr e pelas creanças que o aprendem com as creadas e amas negras. Distinguem-se duas fórmas: o creolo _rachado_, creolo _fundo_, creolo _vejo_, fallado principalmente no interior da ilha e de que as noticias e documentos que publicâmos dão conhecimento, e o creolo em que a grammatica portugueza é menos ignorada, distinguindo-se quasi unicamente pela pronuncia de algumas palavras ou sons e pelo accento geral. Все члены семьи и домочадцы чувствовали, что нет смысла в их сожительстве и что на каждом постоялом дворе случайно сошедшиеся люди более связаны между собой, чем они, члены семьи и домочадцы Облонских. Жена не выходила из своих комнат, мужа третий день не было дома. Дети бегали по всему дому, как потерянные; англичанка поссорилась с экономкой и написала записку приятельнице, прося приискать ей новое место; повар ушел еще вчера со двора, во время обеда; черная кухарка и кучер просили расчета. На третий день после ссоры князь Степан Аркадьич Облонский -- Стива, как его звали в свете, -- в обычный час, то есть в восемь часов утра, проснулся не в спальне жены, а в своем кабинете, на сафьянном диване... Он повернул свое полное, выхоленное тело на пружинах дивана, как бы желая опять заснуть надолго, с другой стороны крепко обнял подушку и прижался к ней щекой; но вдруг вскочил, сел на диван и открыл глаза. Kun oleskelin Jerusalemissa vuonna 1831 ja kävin Israelin kuninkaitten tarun-omaisissa hautakammioissa, ajatukseni palasivat erääsen henkilöön, jonka ihmeellinen elämän-juoksu oli jo nuoruudessani kiinnittänyt huomiotani, koska se oli täynnä mitä runsaimpia aiheita runolliseen teokseen. Silloin minä aloitin tätä kertomusta, jonka oli määrä säilyttää _Alroy''n_ muistoa. Kahdennellatoista vuosisadalla, jolloin Alroy astui esiin, oli Idän valtiollinen asema tämmöinen. Kalifatia uhkasi pikaisesti lähestyvä häviö. Seldshukien sultanit, joita oikea-uokoisten hallitsiat olivat kutsuneet avuksensa, olivat, niinkuin Ranskan majordomit, kohonneet valtakunnan varsinaisiksi isänniksi. He olivat Profeetan jälkeläisten maista lohkoneet itselleen neljä kuningaskuntaa, jotka tuottivat sultanin nimen neljälle seldshukilaiselle ruhtinaalle, nimittäin Bagdadin, Persian, Syrian ja Rumin eri Vähän Aasian sultanille. Inte var det just mycket med Helenas humör heller, sedan hon och Jesper hade skilts åt. Hon kom å ena sidan ihåg sin moders pinos historia och gummans många förmaningar, att dottern aldrig skulle göra sig till skotrasa för en karl. Hennes sista ord hade ju varit: »Om du är så enfaldig och tror på någon och tar honom och han gör dig olycklig -- och det gör han -- så vänder jag mig i grafven!» Inte skulle gamla mor behöfva störas i sin griftero för den sakens skull! Men å andra sidan hade det sina sidor att tjäna. Så länge hon ännu var ung och kunde ta i med bägge näfvarna, kunde det nog gå; men när åldern toge till och krafterna toge af -- ja, hvad skulle då bli hennes lott? Fattighuset, förstås. Nog skulle väl alltid prosten ha en vrå och en beta bröd åt henne, om han lefde. Men han hade ju hunnit ut på ålderdomen och kunde falla ifrån när som helst, och man vet, hur det går, när »det kommer en ny konung, som ingenting vet om Josef». Det är inte alla präster, som göra prästgården eller dess torp till änkesäte åt orkeslösa trotjänarinnor, hade biskopen en gång sagt om Helenas prost. ååååååDer Reichthum an Volksliedern in den Niederlanden war einst sehr groß; der Nachwelt sollte es nicht vergönnt sein, die volle Erbschaft anzutreten, wir müssen uns mit dem was uns blieb begnügen und wollen uns sein erfreuen. So dürftig jedoch ist der übrig gebliebene Theil nicht, wie ihn meine erste Sammlung [4] darbot: Zufall, Glück, emsiges Forschen, und die auch in den Niederlanden dem Volksliede gewidmete Theilnahme haben den Stoff vervielfältigt, und so ist es mir denn jetzt gelungen, obschon ich mich nur auf eigentliche Volkslieder und die volksthümlichen Lieder beschränkte und die älteren geistlichen ausschied (s. Hor. belg. P. X.), eine reichere Sammlung zu Stande zu bringen. Domin: Tak tedy. (sedne si na psací stůl, pozoruje Helenu uchvácen a odříkává rychle) Bylo to roku 1920 kdy se starý Rossum veliký filozof ale tehdy ještě mladý učenec odebral na tento daleký ostrov aby studoval mořské živočišstvo tečka. Přitom se pokoušel napodobit chemickou syntézou živou hmotu řečenou protoplazma až najednou objevil látku která se chovala naprosto jako živá hmota ač byla jiného chemického složení to bylo roku 1932, právě čtyři sta čtyřicet let po objevení Ameriky, uf. Helena: To umíte zpaměti? Domin: Ano; fyziologie, slečno Gloryová, není mým řemeslem. Tak dál? Helena: Třeba. Domin: (slavnostně) A tehdy, slečno, starý Rossum napsal mezi své chemické vzorce tohleto: "Příroda našla jeden způsob, jak organizovat živou hmotu. Je však jiný způsob, jednodušší, tvárnější a rychlejší, na nějž příroda vůbec nenarazila. Tuto druhou cestu, po které se mohl brát vývoj života, jsem dnešního dne objevil." Představte si, slečno, že tahle veliká slova psal nad chrchlem jakéhosi koloidálního rosolu, který by ani pes nesežral. Představte si ho, že sedí nad zkumavkou a myslí na to, jak z ní vyroste celý strom života, jak z ní budou vycházet všechna zvířata, počínajíc vířníkem a končíc--končíc samotným člověkem. Člověk z jiné látky, než jsme my. Slečno Gloryová, to byl ohromný okamžik. Sur le boulevard Montmorency, au n° 53, s''élève une maison portant, encastré dans son balcon, un profil lauré de Louis XV, en bronze doré, qui a tout l''air d''être le médaillon, dont était décorée la tribune de musique de la salle à manger de Luciennes, représenté dans l''aquarelle de Moreau que l''on voit au Louvre. Cette tête, que quelques promeneurs regardent d''un œil farouche, n''est point,--ai-je besoin de le dire?--une affiche des opinions politiques du propriétaire, elle est tout bonnement l''enseigne d''un des nids les plus pleins de choses du XVIIIe siècle qui existent à Paris. La porte noire, que surmonte un élégant dessus de grille de chapelle jésuite en fer forgé, la porte ouverte, du bas de l''escalier, de l''entrée du vestibule, du seuil de la maison, le visiteur est accueilli par des terres cuites, des bronzes, des dessins, des porcelaines du siècle aimable par excellence, mêlés à des objets de l''Extrême-Orient, qui se trouvaient faire si bon ménage dans les collections de Madame de Pompadour et de tous les _curieux_ et les _curiolets_ du temps. Σημείωση: Ο τονισμός έχει αλλάξει από πολυτονικό σε μονοτονικό, κατά τα άλλα έχει διατηρηθεί η ορθογραφία του βιβλίου. Λέξεις με πλαγίους χαρακτήρες έχουν σημειωθεί με _. Οι υποσημειώσεις έχουν μεταφερθεί στο τέλος του βιβλίου και οι αριθμοί τους περικλείονται σε (). Ο Μεταφραστής έχει προσθέσει πολλές υποσημειώσεις που δεν είναι μέρος του αρχικού βιβλίου. Το κείμενό τους τις περισσότερες φορές περικλείεται σε []. Επίσης, επέλεξε να βρει και να παραθέσει στην αρχαία γλώσσα όλα τα αρχαία κείμενα που παραθέτει στα αγγλικά ο Murray. Επειδή πολλοί έλληνες έχουν καλλίτερη γνώση των αγγλικών από τα αρχαία ελληνικά, παραθέτω προς διευκόλυνσή τους το αγγλικό κείμενο, εντός {}. Σπάνια, υπάρχουν διαφορές εντός των δυο επιλεγμένων κειμένων (μήκος ή ακόμα και κείμενο) ή το αρχαίο κείμενο δεν υπάρχει στα αγγλικά στο βιβλίο. Έχω λάβει επίσης υπόψη τον Przyjaciel Dziatek" leci: Z książeczką leci nową, Pozdrowień niesie słowo, Do domków, do szkół spieszy, Toż dziatwa się ucieszy!... A jest się cieszyć z czego, Bo dużo tu nowego: Są bajki i bajeczki, Są wiersze i piosneczki, Są żarty i figielki, Obrazków zapas wielki, Zwierzątka też znajdziecie Więc czegóż więcej chcecie?!... Pójdźcieże więc dziateczki, Chłopaczki i dzieweczki: Niech każde pilnie czyta, "PRZYJACIEL DZIATEK" wita I prosi Was serdecznie: Usiądźcie sobie grzecznie, Książeczkę tę czytajcie, Nauczki spamiętajcie. Gdy słuchać ich zechcecie, Miłemi się staniecie Już teraz, już od młodu, Dla Boga i narodu. Więc: Baczność! Baczność Dzieci! "PRZYJACIEL DZIATEK" leci: Z książeczką bieży nową, Pozdrowień niesie słowo Este dialecto é fallado principalmente pela população de côr e pelas creanças que o aprendem com as creadas e amas negras. Distinguem-se duas fórmas: o creolo _rachado_, creolo _fundo_, creolo _vejo_, fallado principalmente no interior da ilha e de que as noticias e documentos que publicâmos dão conhecimento, e o creolo em que a grammatica portugueza é menos ignorada, distinguindo-se quasi unicamente pela pronuncia de algumas palavras ou sons e pelo accento geral. Все члены семьи и домочадцы чувствовали, что нет смысла в их сожительстве и что на каждом постоялом дворе случайно сошедшиеся люди более связаны между собой, чем они, члены семьи и домочадцы Облонских. Жена не выходила из своих комнат, мужа третий день не было дома. Дети бегали по всему дому, как потерянные; англичанка поссорилась с экономкой и написала записку приятельнице, прося приискать ей новое место; повар ушел еще вчера со двора, во время обеда; черная кухарка и кучер просили расчета. На третий день после ссоры князь Степан Аркадьич Облонский -- Стива, как его звали в свете, -- в обычный час, то есть в восемь часов утра, проснулся не в спальне жены, а в своем кабинете, на сафьянном диване... Он повернул свое полное, выхоленное тело на пружинах дивана, как бы желая опять заснуть надолго, с другой стороны крепко обнял подушку и прижался к ней щекой; но вдруг вскочил, сел на диван и открыл глаза. Kun oleskelin Jerusalemissa vuonna 1831 ja kävin Israelin kuninkaitten tarun-omaisissa hautakammioissa, ajatukseni palasivat erääsen henkilöön, jonka ihmeellinen elämän-juoksu oli jo nuoruudessani kiinnittänyt huomiotani, koska se oli täynnä mitä runsaimpia aiheita runolliseen teokseen. Silloin minä aloitin tätä kertomusta, jonka oli määrä säilyttää _Alroy''n_ muistoa. Kahdennellatoista vuosisadalla, jolloin Alroy astui esiin, oli Idän valtiollinen asema tämmöinen. Kalifatia uhkasi pikaisesti lähestyvä häviö. Seldshukien sultanit, joita oikea-uokoisten hallitsiat olivat kutsuneet avuksensa, olivat, niinkuin Ranskan majordomit, kohonneet valtakunnan varsinaisiksi isänniksi. He olivat Profeetan jälkeläisten maista lohkoneet itselleen neljä kuningaskuntaa, jotka tuottivat sultanin nimen neljälle seldshukilaiselle ruhtinaalle, nimittäin Bagdadin, Persian, Syrian ja Rumin eri Vähän Aasian sultanille. Inte var det just mycket med Helenas humör heller, sedan hon och Jesper hade skilts åt. Hon kom å ena sidan ihåg sin moders pinos historia och gummans många förmaningar, att dottern aldrig skulle göra sig till skotrasa för en karl. Hennes sista ord hade ju varit: »Om du är så enfaldig och tror på någon och tar honom och han gör dig olycklig -- och det gör han -- så vänder jag mig i grafven!» Inte skulle gamla mor behöfva störas i sin griftero för den sakens skull! Men å andra sidan hade det sina sidor att tjäna. Så länge hon ännu var ung och kunde ta i med bägge näfvarna, kunde det nog gå; men när åldern toge till och krafterna toge af -- ja, hvad skulle då bli hennes lott? Fattighuset, förstås. Nog skulle väl alltid prosten ha en vrå och en beta bröd åt henne, om han lefde. Men han hade ju hunnit ut på ålderdomen och kunde falla ifrån när som helst, och man vet, hur det går, när »det kommer en ny konung, som ingenting vet om Josef». Det är inte alla präster, som göra prästgården eller dess torp till änkesäte åt orkeslösa trotjänarinnor, hade biskopen en gång sagt om Helenas prost.åååå' + ); + suspend; + end + ^ + + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + O_LEN_ASCII_ONLY 65535 + C_LEN_ASCII_ONLY 65535 + O_LEN_UTF8_3BPC 49149 + C_LEN_UTF8_3BPC 16383 + O_LEN_UTF8_MIXED 19889 + C_LEN_UTF8_MIXED 16383 + """ + +@pytest.mark.version('>=3.0') +def test_core_4881_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4882.py b/tests/bugs/test_core_4882.py new file mode 100644 index 00000000..f09e81ca --- /dev/null +++ b/tests/bugs/test_core_4882.py @@ -0,0 +1,61 @@ +#coding:utf-8 +# +# id: bugs.core_4882 +# title: ISQL input command (or -i option) reads large (> 64K) lines incorrectly +# decription: +# This test verifies ability of parsing multiple statements that are going as `single-lined stream`. +# Source for this test is file `fbt-repo +# iles\\core_4882.sql`. +# It contains almost all source code of test that emulates OLTP workload - without initial script for data filling. +# This test can be found here: svn://svn.code.sf.net/p/firebird/code/qa/oltp-emul/ +# Three files were taken from it: oltp30_DDL.sql, oltp30_sp.sql and oltp_main_filling.sql - with total size ~600 Kb. +# Then all single-lined comments ("-- blah blah ...") were removed and remained source code was pulled out in single-line. +# This single-line also could not be compiled up to WI-V3.0.0.31948, raising 'token unknown'. +# No error on compiling should occur since buiild WI-V3.0.0.31981. +# NOTE: before this file also contained lines with bulk of begin..end blocks but since CORE-4884 was fixed that number +# is limited to 512. With this limit single-line statement of begin-end blocks will have length less than 64K. For that +# reason these lines were removed from here to the test for CORE-4884. +# +# tracker_id: CORE-4882 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('exception [0-9]+', 'exception'), ('After line [0-9]+ in file.*', ''), ('CURRENT_TIMESTAMP.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# +# db_conn.close() +# scriptfile=open(os.path.join(context['files_location'],'core_4882.sql'),'r') +# scriptfile.close() +# runProgram('isql',[dsn,'-user',user_name,'-pas',user_password,'-i',scriptfile.name]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG oltp30_DDL.sql start + MSG oltp30_DDL.sql finish + MSG oltp30_sp.sql start + MSG oltp30_sp.sql finish + MSG oltp_main_filling.sql start + MSG oltp_main_filling.sql finish + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4882_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4884.py b/tests/bugs/test_core_4884.py new file mode 100644 index 00000000..b020ff39 --- /dev/null +++ b/tests/bugs/test_core_4884.py @@ -0,0 +1,1586 @@ +#coding:utf-8 +# +# id: bugs.core_4884 +# title: Crash on pasring of script containing `execute block` with lot of nested begin..end statements +# decription: Batch file that generates .sql with arbitrary level of begin..end statements can be seen in the traker. +# tracker_id: CORE-4884 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('exception [0-9]+', 'exception'), ('time=.*', ''), ('-At block line: [\\d]+, col: [\\d]+', '-At block line')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate exception ex_test 'Hi from Mariana Trench, depth=@1, time=@2'; + recreate sequence g; + commit; + set list on; + set term ^; + execute block as + declare n int = 0; + begin + begin -- level = 1 + n = gen_id(g, 1); + begin -- level = 2 + n = gen_id(g, 1); + begin -- level = 3 + n = gen_id(g, 1); + begin -- level = 4 + n = gen_id(g, 1); + begin -- level = 5 + n = gen_id(g, 1); + begin -- level = 6 + n = gen_id(g, 1); + begin -- level = 7 + n = gen_id(g, 1); + begin -- level = 8 + n = gen_id(g, 1); + begin -- level = 9 + n = gen_id(g, 1); + begin -- level = 10 + n = gen_id(g, 1); + begin -- level = 11 + n = gen_id(g, 1); + begin -- level = 12 + n = gen_id(g, 1); + begin -- level = 13 + n = gen_id(g, 1); + begin -- level = 14 + n = gen_id(g, 1); + begin -- level = 15 + n = gen_id(g, 1); + begin -- level = 16 + n = gen_id(g, 1); + begin -- level = 17 + n = gen_id(g, 1); + begin -- level = 18 + n = gen_id(g, 1); + begin -- level = 19 + n = gen_id(g, 1); + begin -- level = 20 + n = gen_id(g, 1); + begin -- level = 21 + n = gen_id(g, 1); + begin -- level = 22 + n = gen_id(g, 1); + begin -- level = 23 + n = gen_id(g, 1); + begin -- level = 24 + n = gen_id(g, 1); + begin -- level = 25 + n = gen_id(g, 1); + begin -- level = 26 + n = gen_id(g, 1); + begin -- level = 27 + n = gen_id(g, 1); + begin -- level = 28 + n = gen_id(g, 1); + begin -- level = 29 + n = gen_id(g, 1); + begin -- level = 30 + n = gen_id(g, 1); + begin -- level = 31 + n = gen_id(g, 1); + begin -- level = 32 + n = gen_id(g, 1); + begin -- level = 33 + n = gen_id(g, 1); + begin -- level = 34 + n = gen_id(g, 1); + begin -- level = 35 + n = gen_id(g, 1); + begin -- level = 36 + n = gen_id(g, 1); + begin -- level = 37 + n = gen_id(g, 1); + begin -- level = 38 + n = gen_id(g, 1); + begin -- level = 39 + n = gen_id(g, 1); + begin -- level = 40 + n = gen_id(g, 1); + begin -- level = 41 + n = gen_id(g, 1); + begin -- level = 42 + n = gen_id(g, 1); + begin -- level = 43 + n = gen_id(g, 1); + begin -- level = 44 + n = gen_id(g, 1); + begin -- level = 45 + n = gen_id(g, 1); + begin -- level = 46 + n = gen_id(g, 1); + begin -- level = 47 + n = gen_id(g, 1); + begin -- level = 48 + n = gen_id(g, 1); + begin -- level = 49 + n = gen_id(g, 1); + begin -- level = 50 + n = gen_id(g, 1); + begin -- level = 51 + n = gen_id(g, 1); + begin -- level = 52 + n = gen_id(g, 1); + begin -- level = 53 + n = gen_id(g, 1); + begin -- level = 54 + n = gen_id(g, 1); + begin -- level = 55 + n = gen_id(g, 1); + begin -- level = 56 + n = gen_id(g, 1); + begin -- level = 57 + n = gen_id(g, 1); + begin -- level = 58 + n = gen_id(g, 1); + begin -- level = 59 + n = gen_id(g, 1); + begin -- level = 60 + n = gen_id(g, 1); + begin -- level = 61 + n = gen_id(g, 1); + begin -- level = 62 + n = gen_id(g, 1); + begin -- level = 63 + n = gen_id(g, 1); + begin -- level = 64 + n = gen_id(g, 1); + begin -- level = 65 + n = gen_id(g, 1); + begin -- level = 66 + n = gen_id(g, 1); + begin -- level = 67 + n = gen_id(g, 1); + begin -- level = 68 + n = gen_id(g, 1); + begin -- level = 69 + n = gen_id(g, 1); + begin -- level = 70 + n = gen_id(g, 1); + begin -- level = 71 + n = gen_id(g, 1); + begin -- level = 72 + n = gen_id(g, 1); + begin -- level = 73 + n = gen_id(g, 1); + begin -- level = 74 + n = gen_id(g, 1); + begin -- level = 75 + n = gen_id(g, 1); + begin -- level = 76 + n = gen_id(g, 1); + begin -- level = 77 + n = gen_id(g, 1); + begin -- level = 78 + n = gen_id(g, 1); + begin -- level = 79 + n = gen_id(g, 1); + begin -- level = 80 + n = gen_id(g, 1); + begin -- level = 81 + n = gen_id(g, 1); + begin -- level = 82 + n = gen_id(g, 1); + begin -- level = 83 + n = gen_id(g, 1); + begin -- level = 84 + n = gen_id(g, 1); + begin -- level = 85 + n = gen_id(g, 1); + begin -- level = 86 + n = gen_id(g, 1); + begin -- level = 87 + n = gen_id(g, 1); + begin -- level = 88 + n = gen_id(g, 1); + begin -- level = 89 + n = gen_id(g, 1); + begin -- level = 90 + n = gen_id(g, 1); + begin -- level = 91 + n = gen_id(g, 1); + begin -- level = 92 + n = gen_id(g, 1); + begin -- level = 93 + n = gen_id(g, 1); + begin -- level = 94 + n = gen_id(g, 1); + begin -- level = 95 + n = gen_id(g, 1); + begin -- level = 96 + n = gen_id(g, 1); + begin -- level = 97 + n = gen_id(g, 1); + begin -- level = 98 + n = gen_id(g, 1); + begin -- level = 99 + n = gen_id(g, 1); + begin -- level = 100 + n = gen_id(g, 1); + begin -- level = 101 + n = gen_id(g, 1); + begin -- level = 102 + n = gen_id(g, 1); + begin -- level = 103 + n = gen_id(g, 1); + begin -- level = 104 + n = gen_id(g, 1); + begin -- level = 105 + n = gen_id(g, 1); + begin -- level = 106 + n = gen_id(g, 1); + begin -- level = 107 + n = gen_id(g, 1); + begin -- level = 108 + n = gen_id(g, 1); + begin -- level = 109 + n = gen_id(g, 1); + begin -- level = 110 + n = gen_id(g, 1); + begin -- level = 111 + n = gen_id(g, 1); + begin -- level = 112 + n = gen_id(g, 1); + begin -- level = 113 + n = gen_id(g, 1); + begin -- level = 114 + n = gen_id(g, 1); + begin -- level = 115 + n = gen_id(g, 1); + begin -- level = 116 + n = gen_id(g, 1); + begin -- level = 117 + n = gen_id(g, 1); + begin -- level = 118 + n = gen_id(g, 1); + begin -- level = 119 + n = gen_id(g, 1); + begin -- level = 120 + n = gen_id(g, 1); + begin -- level = 121 + n = gen_id(g, 1); + begin -- level = 122 + n = gen_id(g, 1); + begin -- level = 123 + n = gen_id(g, 1); + begin -- level = 124 + n = gen_id(g, 1); + begin -- level = 125 + n = gen_id(g, 1); + begin -- level = 126 + n = gen_id(g, 1); + begin -- level = 127 + n = gen_id(g, 1); + begin -- level = 128 + n = gen_id(g, 1); + begin -- level = 129 + n = gen_id(g, 1); + begin -- level = 130 + n = gen_id(g, 1); + begin -- level = 131 + n = gen_id(g, 1); + begin -- level = 132 + n = gen_id(g, 1); + begin -- level = 133 + n = gen_id(g, 1); + begin -- level = 134 + n = gen_id(g, 1); + begin -- level = 135 + n = gen_id(g, 1); + begin -- level = 136 + n = gen_id(g, 1); + begin -- level = 137 + n = gen_id(g, 1); + begin -- level = 138 + n = gen_id(g, 1); + begin -- level = 139 + n = gen_id(g, 1); + begin -- level = 140 + n = gen_id(g, 1); + begin -- level = 141 + n = gen_id(g, 1); + begin -- level = 142 + n = gen_id(g, 1); + begin -- level = 143 + n = gen_id(g, 1); + begin -- level = 144 + n = gen_id(g, 1); + begin -- level = 145 + n = gen_id(g, 1); + begin -- level = 146 + n = gen_id(g, 1); + begin -- level = 147 + n = gen_id(g, 1); + begin -- level = 148 + n = gen_id(g, 1); + begin -- level = 149 + n = gen_id(g, 1); + begin -- level = 150 + n = gen_id(g, 1); + begin -- level = 151 + n = gen_id(g, 1); + begin -- level = 152 + n = gen_id(g, 1); + begin -- level = 153 + n = gen_id(g, 1); + begin -- level = 154 + n = gen_id(g, 1); + begin -- level = 155 + n = gen_id(g, 1); + begin -- level = 156 + n = gen_id(g, 1); + begin -- level = 157 + n = gen_id(g, 1); + begin -- level = 158 + n = gen_id(g, 1); + begin -- level = 159 + n = gen_id(g, 1); + begin -- level = 160 + n = gen_id(g, 1); + begin -- level = 161 + n = gen_id(g, 1); + begin -- level = 162 + n = gen_id(g, 1); + begin -- level = 163 + n = gen_id(g, 1); + begin -- level = 164 + n = gen_id(g, 1); + begin -- level = 165 + n = gen_id(g, 1); + begin -- level = 166 + n = gen_id(g, 1); + begin -- level = 167 + n = gen_id(g, 1); + begin -- level = 168 + n = gen_id(g, 1); + begin -- level = 169 + n = gen_id(g, 1); + begin -- level = 170 + n = gen_id(g, 1); + begin -- level = 171 + n = gen_id(g, 1); + begin -- level = 172 + n = gen_id(g, 1); + begin -- level = 173 + n = gen_id(g, 1); + begin -- level = 174 + n = gen_id(g, 1); + begin -- level = 175 + n = gen_id(g, 1); + begin -- level = 176 + n = gen_id(g, 1); + begin -- level = 177 + n = gen_id(g, 1); + begin -- level = 178 + n = gen_id(g, 1); + begin -- level = 179 + n = gen_id(g, 1); + begin -- level = 180 + n = gen_id(g, 1); + begin -- level = 181 + n = gen_id(g, 1); + begin -- level = 182 + n = gen_id(g, 1); + begin -- level = 183 + n = gen_id(g, 1); + begin -- level = 184 + n = gen_id(g, 1); + begin -- level = 185 + n = gen_id(g, 1); + begin -- level = 186 + n = gen_id(g, 1); + begin -- level = 187 + n = gen_id(g, 1); + begin -- level = 188 + n = gen_id(g, 1); + begin -- level = 189 + n = gen_id(g, 1); + begin -- level = 190 + n = gen_id(g, 1); + begin -- level = 191 + n = gen_id(g, 1); + begin -- level = 192 + n = gen_id(g, 1); + begin -- level = 193 + n = gen_id(g, 1); + begin -- level = 194 + n = gen_id(g, 1); + begin -- level = 195 + n = gen_id(g, 1); + begin -- level = 196 + n = gen_id(g, 1); + begin -- level = 197 + n = gen_id(g, 1); + begin -- level = 198 + n = gen_id(g, 1); + begin -- level = 199 + n = gen_id(g, 1); + begin -- level = 200 + n = gen_id(g, 1); + begin -- level = 201 + n = gen_id(g, 1); + begin -- level = 202 + n = gen_id(g, 1); + begin -- level = 203 + n = gen_id(g, 1); + begin -- level = 204 + n = gen_id(g, 1); + begin -- level = 205 + n = gen_id(g, 1); + begin -- level = 206 + n = gen_id(g, 1); + begin -- level = 207 + n = gen_id(g, 1); + begin -- level = 208 + n = gen_id(g, 1); + begin -- level = 209 + n = gen_id(g, 1); + begin -- level = 210 + n = gen_id(g, 1); + begin -- level = 211 + n = gen_id(g, 1); + begin -- level = 212 + n = gen_id(g, 1); + begin -- level = 213 + n = gen_id(g, 1); + begin -- level = 214 + n = gen_id(g, 1); + begin -- level = 215 + n = gen_id(g, 1); + begin -- level = 216 + n = gen_id(g, 1); + begin -- level = 217 + n = gen_id(g, 1); + begin -- level = 218 + n = gen_id(g, 1); + begin -- level = 219 + n = gen_id(g, 1); + begin -- level = 220 + n = gen_id(g, 1); + begin -- level = 221 + n = gen_id(g, 1); + begin -- level = 222 + n = gen_id(g, 1); + begin -- level = 223 + n = gen_id(g, 1); + begin -- level = 224 + n = gen_id(g, 1); + begin -- level = 225 + n = gen_id(g, 1); + begin -- level = 226 + n = gen_id(g, 1); + begin -- level = 227 + n = gen_id(g, 1); + begin -- level = 228 + n = gen_id(g, 1); + begin -- level = 229 + n = gen_id(g, 1); + begin -- level = 230 + n = gen_id(g, 1); + begin -- level = 231 + n = gen_id(g, 1); + begin -- level = 232 + n = gen_id(g, 1); + begin -- level = 233 + n = gen_id(g, 1); + begin -- level = 234 + n = gen_id(g, 1); + begin -- level = 235 + n = gen_id(g, 1); + begin -- level = 236 + n = gen_id(g, 1); + begin -- level = 237 + n = gen_id(g, 1); + begin -- level = 238 + n = gen_id(g, 1); + begin -- level = 239 + n = gen_id(g, 1); + begin -- level = 240 + n = gen_id(g, 1); + begin -- level = 241 + n = gen_id(g, 1); + begin -- level = 242 + n = gen_id(g, 1); + begin -- level = 243 + n = gen_id(g, 1); + begin -- level = 244 + n = gen_id(g, 1); + begin -- level = 245 + n = gen_id(g, 1); + begin -- level = 246 + n = gen_id(g, 1); + begin -- level = 247 + n = gen_id(g, 1); + begin -- level = 248 + n = gen_id(g, 1); + begin -- level = 249 + n = gen_id(g, 1); + begin -- level = 250 + n = gen_id(g, 1); + begin -- level = 251 + n = gen_id(g, 1); + begin -- level = 252 + n = gen_id(g, 1); + begin -- level = 253 + n = gen_id(g, 1); + begin -- level = 254 + n = gen_id(g, 1); + begin -- level = 255 + n = gen_id(g, 1); + begin -- level = 256 + n = gen_id(g, 1); + begin -- level = 257 + n = gen_id(g, 1); + begin -- level = 258 + n = gen_id(g, 1); + begin -- level = 259 + n = gen_id(g, 1); + begin -- level = 260 + n = gen_id(g, 1); + begin -- level = 261 + n = gen_id(g, 1); + begin -- level = 262 + n = gen_id(g, 1); + begin -- level = 263 + n = gen_id(g, 1); + begin -- level = 264 + n = gen_id(g, 1); + begin -- level = 265 + n = gen_id(g, 1); + begin -- level = 266 + n = gen_id(g, 1); + begin -- level = 267 + n = gen_id(g, 1); + begin -- level = 268 + n = gen_id(g, 1); + begin -- level = 269 + n = gen_id(g, 1); + begin -- level = 270 + n = gen_id(g, 1); + begin -- level = 271 + n = gen_id(g, 1); + begin -- level = 272 + n = gen_id(g, 1); + begin -- level = 273 + n = gen_id(g, 1); + begin -- level = 274 + n = gen_id(g, 1); + begin -- level = 275 + n = gen_id(g, 1); + begin -- level = 276 + n = gen_id(g, 1); + begin -- level = 277 + n = gen_id(g, 1); + begin -- level = 278 + n = gen_id(g, 1); + begin -- level = 279 + n = gen_id(g, 1); + begin -- level = 280 + n = gen_id(g, 1); + begin -- level = 281 + n = gen_id(g, 1); + begin -- level = 282 + n = gen_id(g, 1); + begin -- level = 283 + n = gen_id(g, 1); + begin -- level = 284 + n = gen_id(g, 1); + begin -- level = 285 + n = gen_id(g, 1); + begin -- level = 286 + n = gen_id(g, 1); + begin -- level = 287 + n = gen_id(g, 1); + begin -- level = 288 + n = gen_id(g, 1); + begin -- level = 289 + n = gen_id(g, 1); + begin -- level = 290 + n = gen_id(g, 1); + begin -- level = 291 + n = gen_id(g, 1); + begin -- level = 292 + n = gen_id(g, 1); + begin -- level = 293 + n = gen_id(g, 1); + begin -- level = 294 + n = gen_id(g, 1); + begin -- level = 295 + n = gen_id(g, 1); + begin -- level = 296 + n = gen_id(g, 1); + begin -- level = 297 + n = gen_id(g, 1); + begin -- level = 298 + n = gen_id(g, 1); + begin -- level = 299 + n = gen_id(g, 1); + begin -- level = 300 + n = gen_id(g, 1); + begin -- level = 301 + n = gen_id(g, 1); + begin -- level = 302 + n = gen_id(g, 1); + begin -- level = 303 + n = gen_id(g, 1); + begin -- level = 304 + n = gen_id(g, 1); + begin -- level = 305 + n = gen_id(g, 1); + begin -- level = 306 + n = gen_id(g, 1); + begin -- level = 307 + n = gen_id(g, 1); + begin -- level = 308 + n = gen_id(g, 1); + begin -- level = 309 + n = gen_id(g, 1); + begin -- level = 310 + n = gen_id(g, 1); + begin -- level = 311 + n = gen_id(g, 1); + begin -- level = 312 + n = gen_id(g, 1); + begin -- level = 313 + n = gen_id(g, 1); + begin -- level = 314 + n = gen_id(g, 1); + begin -- level = 315 + n = gen_id(g, 1); + begin -- level = 316 + n = gen_id(g, 1); + begin -- level = 317 + n = gen_id(g, 1); + begin -- level = 318 + n = gen_id(g, 1); + begin -- level = 319 + n = gen_id(g, 1); + begin -- level = 320 + n = gen_id(g, 1); + begin -- level = 321 + n = gen_id(g, 1); + begin -- level = 322 + n = gen_id(g, 1); + begin -- level = 323 + n = gen_id(g, 1); + begin -- level = 324 + n = gen_id(g, 1); + begin -- level = 325 + n = gen_id(g, 1); + begin -- level = 326 + n = gen_id(g, 1); + begin -- level = 327 + n = gen_id(g, 1); + begin -- level = 328 + n = gen_id(g, 1); + begin -- level = 329 + n = gen_id(g, 1); + begin -- level = 330 + n = gen_id(g, 1); + begin -- level = 331 + n = gen_id(g, 1); + begin -- level = 332 + n = gen_id(g, 1); + begin -- level = 333 + n = gen_id(g, 1); + begin -- level = 334 + n = gen_id(g, 1); + begin -- level = 335 + n = gen_id(g, 1); + begin -- level = 336 + n = gen_id(g, 1); + begin -- level = 337 + n = gen_id(g, 1); + begin -- level = 338 + n = gen_id(g, 1); + begin -- level = 339 + n = gen_id(g, 1); + begin -- level = 340 + n = gen_id(g, 1); + begin -- level = 341 + n = gen_id(g, 1); + begin -- level = 342 + n = gen_id(g, 1); + begin -- level = 343 + n = gen_id(g, 1); + begin -- level = 344 + n = gen_id(g, 1); + begin -- level = 345 + n = gen_id(g, 1); + begin -- level = 346 + n = gen_id(g, 1); + begin -- level = 347 + n = gen_id(g, 1); + begin -- level = 348 + n = gen_id(g, 1); + begin -- level = 349 + n = gen_id(g, 1); + begin -- level = 350 + n = gen_id(g, 1); + begin -- level = 351 + n = gen_id(g, 1); + begin -- level = 352 + n = gen_id(g, 1); + begin -- level = 353 + n = gen_id(g, 1); + begin -- level = 354 + n = gen_id(g, 1); + begin -- level = 355 + n = gen_id(g, 1); + begin -- level = 356 + n = gen_id(g, 1); + begin -- level = 357 + n = gen_id(g, 1); + begin -- level = 358 + n = gen_id(g, 1); + begin -- level = 359 + n = gen_id(g, 1); + begin -- level = 360 + n = gen_id(g, 1); + begin -- level = 361 + n = gen_id(g, 1); + begin -- level = 362 + n = gen_id(g, 1); + begin -- level = 363 + n = gen_id(g, 1); + begin -- level = 364 + n = gen_id(g, 1); + begin -- level = 365 + n = gen_id(g, 1); + begin -- level = 366 + n = gen_id(g, 1); + begin -- level = 367 + n = gen_id(g, 1); + begin -- level = 368 + n = gen_id(g, 1); + begin -- level = 369 + n = gen_id(g, 1); + begin -- level = 370 + n = gen_id(g, 1); + begin -- level = 371 + n = gen_id(g, 1); + begin -- level = 372 + n = gen_id(g, 1); + begin -- level = 373 + n = gen_id(g, 1); + begin -- level = 374 + n = gen_id(g, 1); + begin -- level = 375 + n = gen_id(g, 1); + begin -- level = 376 + n = gen_id(g, 1); + begin -- level = 377 + n = gen_id(g, 1); + begin -- level = 378 + n = gen_id(g, 1); + begin -- level = 379 + n = gen_id(g, 1); + begin -- level = 380 + n = gen_id(g, 1); + begin -- level = 381 + n = gen_id(g, 1); + begin -- level = 382 + n = gen_id(g, 1); + begin -- level = 383 + n = gen_id(g, 1); + begin -- level = 384 + n = gen_id(g, 1); + begin -- level = 385 + n = gen_id(g, 1); + begin -- level = 386 + n = gen_id(g, 1); + begin -- level = 387 + n = gen_id(g, 1); + begin -- level = 388 + n = gen_id(g, 1); + begin -- level = 389 + n = gen_id(g, 1); + begin -- level = 390 + n = gen_id(g, 1); + begin -- level = 391 + n = gen_id(g, 1); + begin -- level = 392 + n = gen_id(g, 1); + begin -- level = 393 + n = gen_id(g, 1); + begin -- level = 394 + n = gen_id(g, 1); + begin -- level = 395 + n = gen_id(g, 1); + begin -- level = 396 + n = gen_id(g, 1); + begin -- level = 397 + n = gen_id(g, 1); + begin -- level = 398 + n = gen_id(g, 1); + begin -- level = 399 + n = gen_id(g, 1); + begin -- level = 400 + n = gen_id(g, 1); + begin -- level = 401 + n = gen_id(g, 1); + begin -- level = 402 + n = gen_id(g, 1); + begin -- level = 403 + n = gen_id(g, 1); + begin -- level = 404 + n = gen_id(g, 1); + begin -- level = 405 + n = gen_id(g, 1); + begin -- level = 406 + n = gen_id(g, 1); + begin -- level = 407 + n = gen_id(g, 1); + begin -- level = 408 + n = gen_id(g, 1); + begin -- level = 409 + n = gen_id(g, 1); + begin -- level = 410 + n = gen_id(g, 1); + begin -- level = 411 + n = gen_id(g, 1); + begin -- level = 412 + n = gen_id(g, 1); + begin -- level = 413 + n = gen_id(g, 1); + begin -- level = 414 + n = gen_id(g, 1); + begin -- level = 415 + n = gen_id(g, 1); + begin -- level = 416 + n = gen_id(g, 1); + begin -- level = 417 + n = gen_id(g, 1); + begin -- level = 418 + n = gen_id(g, 1); + begin -- level = 419 + n = gen_id(g, 1); + begin -- level = 420 + n = gen_id(g, 1); + begin -- level = 421 + n = gen_id(g, 1); + begin -- level = 422 + n = gen_id(g, 1); + begin -- level = 423 + n = gen_id(g, 1); + begin -- level = 424 + n = gen_id(g, 1); + begin -- level = 425 + n = gen_id(g, 1); + begin -- level = 426 + n = gen_id(g, 1); + begin -- level = 427 + n = gen_id(g, 1); + begin -- level = 428 + n = gen_id(g, 1); + begin -- level = 429 + n = gen_id(g, 1); + begin -- level = 430 + n = gen_id(g, 1); + begin -- level = 431 + n = gen_id(g, 1); + begin -- level = 432 + n = gen_id(g, 1); + begin -- level = 433 + n = gen_id(g, 1); + begin -- level = 434 + n = gen_id(g, 1); + begin -- level = 435 + n = gen_id(g, 1); + begin -- level = 436 + n = gen_id(g, 1); + begin -- level = 437 + n = gen_id(g, 1); + begin -- level = 438 + n = gen_id(g, 1); + begin -- level = 439 + n = gen_id(g, 1); + begin -- level = 440 + n = gen_id(g, 1); + begin -- level = 441 + n = gen_id(g, 1); + begin -- level = 442 + n = gen_id(g, 1); + begin -- level = 443 + n = gen_id(g, 1); + begin -- level = 444 + n = gen_id(g, 1); + begin -- level = 445 + n = gen_id(g, 1); + begin -- level = 446 + n = gen_id(g, 1); + begin -- level = 447 + n = gen_id(g, 1); + begin -- level = 448 + n = gen_id(g, 1); + begin -- level = 449 + n = gen_id(g, 1); + begin -- level = 450 + n = gen_id(g, 1); + begin -- level = 451 + n = gen_id(g, 1); + begin -- level = 452 + n = gen_id(g, 1); + begin -- level = 453 + n = gen_id(g, 1); + begin -- level = 454 + n = gen_id(g, 1); + begin -- level = 455 + n = gen_id(g, 1); + begin -- level = 456 + n = gen_id(g, 1); + begin -- level = 457 + n = gen_id(g, 1); + begin -- level = 458 + n = gen_id(g, 1); + begin -- level = 459 + n = gen_id(g, 1); + begin -- level = 460 + n = gen_id(g, 1); + begin -- level = 461 + n = gen_id(g, 1); + begin -- level = 462 + n = gen_id(g, 1); + begin -- level = 463 + n = gen_id(g, 1); + begin -- level = 464 + n = gen_id(g, 1); + begin -- level = 465 + n = gen_id(g, 1); + begin -- level = 466 + n = gen_id(g, 1); + begin -- level = 467 + n = gen_id(g, 1); + begin -- level = 468 + n = gen_id(g, 1); + begin -- level = 469 + n = gen_id(g, 1); + begin -- level = 470 + n = gen_id(g, 1); + begin -- level = 471 + n = gen_id(g, 1); + begin -- level = 472 + n = gen_id(g, 1); + begin -- level = 473 + n = gen_id(g, 1); + begin -- level = 474 + n = gen_id(g, 1); + begin -- level = 475 + n = gen_id(g, 1); + begin -- level = 476 + n = gen_id(g, 1); + begin -- level = 477 + n = gen_id(g, 1); + begin -- level = 478 + n = gen_id(g, 1); + begin -- level = 479 + n = gen_id(g, 1); + begin -- level = 480 + n = gen_id(g, 1); + begin -- level = 481 + n = gen_id(g, 1); + begin -- level = 482 + n = gen_id(g, 1); + begin -- level = 483 + n = gen_id(g, 1); + begin -- level = 484 + n = gen_id(g, 1); + begin -- level = 485 + n = gen_id(g, 1); + begin -- level = 486 + n = gen_id(g, 1); + begin -- level = 487 + n = gen_id(g, 1); + begin -- level = 488 + n = gen_id(g, 1); + begin -- level = 489 + n = gen_id(g, 1); + begin -- level = 490 + n = gen_id(g, 1); + begin -- level = 491 + n = gen_id(g, 1); + begin -- level = 492 + n = gen_id(g, 1); + begin -- level = 493 + n = gen_id(g, 1); + begin -- level = 494 + n = gen_id(g, 1); + begin -- level = 495 + n = gen_id(g, 1); + begin -- level = 496 + n = gen_id(g, 1); + begin -- level = 497 + n = gen_id(g, 1); + begin -- level = 498 + n = gen_id(g, 1); + begin -- level = 499 + n = gen_id(g, 1); + begin -- level = 500 + n = gen_id(g, 1); + begin -- level = 501 + n = gen_id(g, 1); + begin -- level = 502 + n = gen_id(g, 1); + begin -- level = 503 + n = gen_id(g, 1); + begin -- level = 504 + n = gen_id(g, 1); + begin -- level = 505 + n = gen_id(g, 1); + begin -- level = 506 + n = gen_id(g, 1); + begin -- level = 507 + n = gen_id(g, 1); + begin -- level = 508 + n = gen_id(g, 1); + begin -- level = 509 + n = gen_id(g, 1); + begin -- level = 510 + n = gen_id(g, 1); + begin -- level = 511 + n = gen_id(g, 1); + exception ex_test using( n, cast('now' as timestamp) ); + end -- level = 511 + end -- level = 510 + end -- level = 509 + end -- level = 508 + end -- level = 507 + end -- level = 506 + end -- level = 505 + end -- level = 504 + end -- level = 503 + end -- level = 502 + end -- level = 501 + end -- level = 500 + end -- level = 499 + end -- level = 498 + end -- level = 497 + end -- level = 496 + end -- level = 495 + end -- level = 494 + end -- level = 493 + end -- level = 492 + end -- level = 491 + end -- level = 490 + end -- level = 489 + end -- level = 488 + end -- level = 487 + end -- level = 486 + end -- level = 485 + end -- level = 484 + end -- level = 483 + end -- level = 482 + end -- level = 481 + end -- level = 480 + end -- level = 479 + end -- level = 478 + end -- level = 477 + end -- level = 476 + end -- level = 475 + end -- level = 474 + end -- level = 473 + end -- level = 472 + end -- level = 471 + end -- level = 470 + end -- level = 469 + end -- level = 468 + end -- level = 467 + end -- level = 466 + end -- level = 465 + end -- level = 464 + end -- level = 463 + end -- level = 462 + end -- level = 461 + end -- level = 460 + end -- level = 459 + end -- level = 458 + end -- level = 457 + end -- level = 456 + end -- level = 455 + end -- level = 454 + end -- level = 453 + end -- level = 452 + end -- level = 451 + end -- level = 450 + end -- level = 449 + end -- level = 448 + end -- level = 447 + end -- level = 446 + end -- level = 445 + end -- level = 444 + end -- level = 443 + end -- level = 442 + end -- level = 441 + end -- level = 440 + end -- level = 439 + end -- level = 438 + end -- level = 437 + end -- level = 436 + end -- level = 435 + end -- level = 434 + end -- level = 433 + end -- level = 432 + end -- level = 431 + end -- level = 430 + end -- level = 429 + end -- level = 428 + end -- level = 427 + end -- level = 426 + end -- level = 425 + end -- level = 424 + end -- level = 423 + end -- level = 422 + end -- level = 421 + end -- level = 420 + end -- level = 419 + end -- level = 418 + end -- level = 417 + end -- level = 416 + end -- level = 415 + end -- level = 414 + end -- level = 413 + end -- level = 412 + end -- level = 411 + end -- level = 410 + end -- level = 409 + end -- level = 408 + end -- level = 407 + end -- level = 406 + end -- level = 405 + end -- level = 404 + end -- level = 403 + end -- level = 402 + end -- level = 401 + end -- level = 400 + end -- level = 399 + end -- level = 398 + end -- level = 397 + end -- level = 396 + end -- level = 395 + end -- level = 394 + end -- level = 393 + end -- level = 392 + end -- level = 391 + end -- level = 390 + end -- level = 389 + end -- level = 388 + end -- level = 387 + end -- level = 386 + end -- level = 385 + end -- level = 384 + end -- level = 383 + end -- level = 382 + end -- level = 381 + end -- level = 380 + end -- level = 379 + end -- level = 378 + end -- level = 377 + end -- level = 376 + end -- level = 375 + end -- level = 374 + end -- level = 373 + end -- level = 372 + end -- level = 371 + end -- level = 370 + end -- level = 369 + end -- level = 368 + end -- level = 367 + end -- level = 366 + end -- level = 365 + end -- level = 364 + end -- level = 363 + end -- level = 362 + end -- level = 361 + end -- level = 360 + end -- level = 359 + end -- level = 358 + end -- level = 357 + end -- level = 356 + end -- level = 355 + end -- level = 354 + end -- level = 353 + end -- level = 352 + end -- level = 351 + end -- level = 350 + end -- level = 349 + end -- level = 348 + end -- level = 347 + end -- level = 346 + end -- level = 345 + end -- level = 344 + end -- level = 343 + end -- level = 342 + end -- level = 341 + end -- level = 340 + end -- level = 339 + end -- level = 338 + end -- level = 337 + end -- level = 336 + end -- level = 335 + end -- level = 334 + end -- level = 333 + end -- level = 332 + end -- level = 331 + end -- level = 330 + end -- level = 329 + end -- level = 328 + end -- level = 327 + end -- level = 326 + end -- level = 325 + end -- level = 324 + end -- level = 323 + end -- level = 322 + end -- level = 321 + end -- level = 320 + end -- level = 319 + end -- level = 318 + end -- level = 317 + end -- level = 316 + end -- level = 315 + end -- level = 314 + end -- level = 313 + end -- level = 312 + end -- level = 311 + end -- level = 310 + end -- level = 309 + end -- level = 308 + end -- level = 307 + end -- level = 306 + end -- level = 305 + end -- level = 304 + end -- level = 303 + end -- level = 302 + end -- level = 301 + end -- level = 300 + end -- level = 299 + end -- level = 298 + end -- level = 297 + end -- level = 296 + end -- level = 295 + end -- level = 294 + end -- level = 293 + end -- level = 292 + end -- level = 291 + end -- level = 290 + end -- level = 289 + end -- level = 288 + end -- level = 287 + end -- level = 286 + end -- level = 285 + end -- level = 284 + end -- level = 283 + end -- level = 282 + end -- level = 281 + end -- level = 280 + end -- level = 279 + end -- level = 278 + end -- level = 277 + end -- level = 276 + end -- level = 275 + end -- level = 274 + end -- level = 273 + end -- level = 272 + end -- level = 271 + end -- level = 270 + end -- level = 269 + end -- level = 268 + end -- level = 267 + end -- level = 266 + end -- level = 265 + end -- level = 264 + end -- level = 263 + end -- level = 262 + end -- level = 261 + end -- level = 260 + end -- level = 259 + end -- level = 258 + end -- level = 257 + end -- level = 256 + end -- level = 255 + end -- level = 254 + end -- level = 253 + end -- level = 252 + end -- level = 251 + end -- level = 250 + end -- level = 249 + end -- level = 248 + end -- level = 247 + end -- level = 246 + end -- level = 245 + end -- level = 244 + end -- level = 243 + end -- level = 242 + end -- level = 241 + end -- level = 240 + end -- level = 239 + end -- level = 238 + end -- level = 237 + end -- level = 236 + end -- level = 235 + end -- level = 234 + end -- level = 233 + end -- level = 232 + end -- level = 231 + end -- level = 230 + end -- level = 229 + end -- level = 228 + end -- level = 227 + end -- level = 226 + end -- level = 225 + end -- level = 224 + end -- level = 223 + end -- level = 222 + end -- level = 221 + end -- level = 220 + end -- level = 219 + end -- level = 218 + end -- level = 217 + end -- level = 216 + end -- level = 215 + end -- level = 214 + end -- level = 213 + end -- level = 212 + end -- level = 211 + end -- level = 210 + end -- level = 209 + end -- level = 208 + end -- level = 207 + end -- level = 206 + end -- level = 205 + end -- level = 204 + end -- level = 203 + end -- level = 202 + end -- level = 201 + end -- level = 200 + end -- level = 199 + end -- level = 198 + end -- level = 197 + end -- level = 196 + end -- level = 195 + end -- level = 194 + end -- level = 193 + end -- level = 192 + end -- level = 191 + end -- level = 190 + end -- level = 189 + end -- level = 188 + end -- level = 187 + end -- level = 186 + end -- level = 185 + end -- level = 184 + end -- level = 183 + end -- level = 182 + end -- level = 181 + end -- level = 180 + end -- level = 179 + end -- level = 178 + end -- level = 177 + end -- level = 176 + end -- level = 175 + end -- level = 174 + end -- level = 173 + end -- level = 172 + end -- level = 171 + end -- level = 170 + end -- level = 169 + end -- level = 168 + end -- level = 167 + end -- level = 166 + end -- level = 165 + end -- level = 164 + end -- level = 163 + end -- level = 162 + end -- level = 161 + end -- level = 160 + end -- level = 159 + end -- level = 158 + end -- level = 157 + end -- level = 156 + end -- level = 155 + end -- level = 154 + end -- level = 153 + end -- level = 152 + end -- level = 151 + end -- level = 150 + end -- level = 149 + end -- level = 148 + end -- level = 147 + end -- level = 146 + end -- level = 145 + end -- level = 144 + end -- level = 143 + end -- level = 142 + end -- level = 141 + end -- level = 140 + end -- level = 139 + end -- level = 138 + end -- level = 137 + end -- level = 136 + end -- level = 135 + end -- level = 134 + end -- level = 133 + end -- level = 132 + end -- level = 131 + end -- level = 130 + end -- level = 129 + end -- level = 128 + end -- level = 127 + end -- level = 126 + end -- level = 125 + end -- level = 124 + end -- level = 123 + end -- level = 122 + end -- level = 121 + end -- level = 120 + end -- level = 119 + end -- level = 118 + end -- level = 117 + end -- level = 116 + end -- level = 115 + end -- level = 114 + end -- level = 113 + end -- level = 112 + end -- level = 111 + end -- level = 110 + end -- level = 109 + end -- level = 108 + end -- level = 107 + end -- level = 106 + end -- level = 105 + end -- level = 104 + end -- level = 103 + end -- level = 102 + end -- level = 101 + end -- level = 100 + end -- level = 99 + end -- level = 98 + end -- level = 97 + end -- level = 96 + end -- level = 95 + end -- level = 94 + end -- level = 93 + end -- level = 92 + end -- level = 91 + end -- level = 90 + end -- level = 89 + end -- level = 88 + end -- level = 87 + end -- level = 86 + end -- level = 85 + end -- level = 84 + end -- level = 83 + end -- level = 82 + end -- level = 81 + end -- level = 80 + end -- level = 79 + end -- level = 78 + end -- level = 77 + end -- level = 76 + end -- level = 75 + end -- level = 74 + end -- level = 73 + end -- level = 72 + end -- level = 71 + end -- level = 70 + end -- level = 69 + end -- level = 68 + end -- level = 67 + end -- level = 66 + end -- level = 65 + end -- level = 64 + end -- level = 63 + end -- level = 62 + end -- level = 61 + end -- level = 60 + end -- level = 59 + end -- level = 58 + end -- level = 57 + end -- level = 56 + end -- level = 55 + end -- level = 54 + end -- level = 53 + end -- level = 52 + end -- level = 51 + end -- level = 50 + end -- level = 49 + end -- level = 48 + end -- level = 47 + end -- level = 46 + end -- level = 45 + end -- level = 44 + end -- level = 43 + end -- level = 42 + end -- level = 41 + end -- level = 40 + end -- level = 39 + end -- level = 38 + end -- level = 37 + end -- level = 36 + end -- level = 35 + end -- level = 34 + end -- level = 33 + end -- level = 32 + end -- level = 31 + end -- level = 30 + end -- level = 29 + end -- level = 28 + end -- level = 27 + end -- level = 26 + end -- level = 25 + end -- level = 24 + end -- level = 23 + end -- level = 22 + end -- level = 21 + end -- level = 20 + end -- level = 19 + end -- level = 18 + end -- level = 17 + end -- level = 16 + end -- level = 15 + end -- level = 14 + end -- level = 13 + end -- level = 12 + end -- level = 11 + end -- level = 10 + end -- level = 9 + end -- level = 8 + end -- level = 7 + end -- level = 6 + end -- level = 5 + end -- level = 4 + end -- level = 3 + end -- level = 2 + end -- level = 1 + end^ + set term ;^ + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + 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_core_4884_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_4887.py b/tests/bugs/test_core_4887.py new file mode 100644 index 00000000..00dedba6 --- /dev/null +++ b/tests/bugs/test_core_4887.py @@ -0,0 +1,147 @@ +#coding:utf-8 +# +# id: bugs.core_4887 +# title: AFTER CREATE/ALTER PACKAGE DDL triggers runs in incorrectly moment +# decription: Since WI-V3.0.0.31981 this code should produce only STDOUT and no STDERR. +# tracker_id: CORE-4887 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set list on; + create exception exc_empty_pkg 'Empty package'; + create sequence g; + commit; + + set term ^; + create or alter trigger t_trig_pkg_head after create package as + begin + rdb$set_context('USER_SESSION','DDL_TRIGGER_ON_PKG_HEAD_FIRING', gen_id(g,1)); + if ( not exists(select * from rdb$functions where rdb$package_name = rdb$get_context('DDL_TRIGGER', 'OBJECT_NAME') ) ) then + exception exc_empty_pkg; + end + ^ + create or alter trigger t_trig_pkg_body after create package body as + begin + rdb$set_context('USER_SESSION','DDL_TRIGGER_ON_PKG_BODY_FIRING', gen_id(g,1)); + end + ^ + set term ;^ + commit; + + set term ^; + execute block as + begin + rdb$set_context('USER_SESSION','PACKAGE_HEADER_CREATION_START', gen_id(g,1)); + end + ^ + create package xpk1 as + begin + function f1 returns integer; + end + ^ + execute block as + begin + rdb$set_context('USER_SESSION','PACKAGE_HEADER_CREATION_FINISH', gen_id(g,1)); + end + ^ + commit + ^ + + execute block as + begin + rdb$set_context('USER_SESSION','PACKAGE_BODY_CREATION_START', gen_id(g,1)); + end + ^ + create package body xpk1 as + begin + function f1 returns integer as + begin + return 12345; + end + end + ^ + execute block as + begin + rdb$set_context('USER_SESSION','PACKAGE_BODY_CREATION_FINISH', gen_id(g,1)); + end + ^ + set term ;^ + + select event_seq, event_name + from( + select + cast( rdb$get_context('USER_SESSION','PACKAGE_HEADER_CREATION_START') as int) event_seq + ,'pkg_header_start' event_name + from rdb$database + union all + select + cast( rdb$get_context('USER_SESSION','PACKAGE_HEADER_CREATION_FINISH') as int) + ,'pkg_header_finish' + from rdb$database + union all + select + cast( rdb$get_context('USER_SESSION','PACKAGE_BODY_CREATION_START') as int) + ,'pkg_body_start' + from rdb$database + union all + select + cast( rdb$get_context('USER_SESSION','PACKAGE_BODY_CREATION_FINISH') as int) + ,'pkg_body_finish' + from rdb$database + union all + select + cast( rdb$get_context('USER_SESSION','DDL_TRIGGER_ON_PKG_HEAD_FIRING') as int) + ,'trg_pkg_head_firing' + from rdb$database + union all + select + cast( rdb$get_context('USER_SESSION','DDL_TRIGGER_ON_PKG_BODY_FIRING') as int) + ,'trg_pkg_body_firing' + from rdb$database + ) + order by event_seq; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + EVENT_SEQ 1 + EVENT_NAME pkg_header_start + + EVENT_SEQ 2 + EVENT_NAME trg_pkg_head_firing + + EVENT_SEQ 3 + EVENT_NAME pkg_header_finish + + EVENT_SEQ 4 + EVENT_NAME pkg_body_start + + EVENT_SEQ 5 + EVENT_NAME trg_pkg_body_firing + + EVENT_SEQ 6 + EVENT_NAME pkg_body_finish + """ + +@pytest.mark.version('>=3.0') +def test_core_4887_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4889.py b/tests/bugs/test_core_4889.py new file mode 100644 index 00000000..de9cd436 --- /dev/null +++ b/tests/bugs/test_core_4889.py @@ -0,0 +1,221 @@ +#coding:utf-8 +# +# id: bugs.core_4889 +# title: FBSVCMGR with `action_trace_start` prevents in 3.0 SuperServer from connecting using local protocol +# decription: +# Confirmed failing to create embedded attach on build 31948. +# Confirmed successful work on build 32268, architectures: SS, SC and CS. +# 10.12.2019. Additional check: +# 4.0.0.1685 SS: 11.439s. +# 4.0.0.1685 CS: 12.078s. +# 3.0.5.33206 SS: 10.827s. +# 3.0.5.33206 CS: 11.793s. +# +# tracker_id: CORE-4889 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# from subprocess import Popen +# import time +# +# fdb_file='$(DATABASE_LOCATION)bugs.core_4889.fdb' +# +# db_conn.close() +# +# ##################################################################### +# # Prepare config for trace session that will be launched by call of FBSVCMGR: +# +# txt = '''database= %[\\\\\\\\/]bugs.core_4889.fdb +# { +# enabled = true +# time_threshold = 0 +# log_errors = true +# log_statement_finish = true +# } +# ''' +# trc_cfg=open( os.path.join(context['temp_directory'],'tmp_trace_4889.cfg'), 'w') +# trc_cfg.write(txt) +# trc_cfg.close() +# trc_log=open( os.path.join(context['temp_directory'],'tmp_trace_4889.log'), 'w') +# trc_log.close() +# trc_lst=open( os.path.join(context['temp_directory'],'tmp_trace_4889.lst'), 'w') +# trc_lst.close() +# +# +# ##################################################################### +# # Async. launch of trace session using FBSVCMGR action_trace_start: +# +# trc_log=open(trc_log.name, "w") +# # Execute a child program in a new process, redirecting STDERR to the same target as of STDOUT: +# p_svcmgr = Popen( ["fbsvcmgr", "localhost:service_mgr", "user" , "SYSDBA" , "password" , "masterkey", "action_trace_start","trc_cfg", trc_cfg.name], stdout=trc_log, stderr=subprocess.STDOUT) +# +# # Wait! Trace session is initialized not instantly! +# time.sleep(2) +# +# ##################################################################### +# +# # Determine active trace session ID (for further stop): +# +# trc_lst=open(trc_lst.name, "w") +# subprocess.call(["fbsvcmgr", "localhost:service_mgr", "user" , "SYSDBA" , "password" , "masterkey", "action_trace_list"], stdout=trc_lst, stderr=subprocess.STDOUT ) +# trc_lst.close() +# +# # Session ID: 5 +# # user: +# # date: 2015-08-27 15:24:14 +# # flags: active, trace +# +# trcssn=0 +# with open( trc_lst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# +# # Result: `trcssn` is ID of active trace session. +# # We have to terminate trace session that is running on server BEFORE we termitane process `p_svcmgr` +# if trcssn==0: +# print("Error parsing trace session ID.") +# trc_log.close() +# +# else: +# ##################################################################### +# +# # Preparing script for ISQL: +# +# sql_cmd=''' +# set list on; +# set count on; +# select +# iif(a.mon$remote_protocol is null, 'internal', 'remote') as connection_protocol, +# iif(a.mon$remote_process is null, 'internal', 'remote') as connection_process, +# iif(a.mon$remote_pid is null, 'internal', 'remote') as connection_remote_pid, +# a.mon$auth_method as auth_method -- should be: 'User name in DPB' +# from rdb$database r +# left join mon$attachments a on a.mon$attachment_id = current_connection and a.mon$system_flag = 0; +# commit; +# ''' +# +# isql_cmd=open( os.path.join(context['temp_directory'],'tmp_isql_4889.sql'), 'w') +# isql_cmd.write(sql_cmd) +# isql_cmd.close() +# +# ####################################################################### +# +# # Async. launch ISQL process with EMBEDDED connect. +# # ::::: NB ::::: +# # Confirmed that this action: +# # works fine on WI-V3.0.0.31940, build 14-jul-2015 +# # **HANGS** on WI-V3.0.0.31948, build 16-jul-2015 +# +# isql_log=open( os.path.join(context['temp_directory'],'tmp_isql_4889.log'), 'w') +# p_isql = Popen( [ "isql" , fdb_file, "-user", "tmp$no$such$user$4889", "-n", "-i", isql_cmd.name ], stdout=isql_log, stderr=subprocess.STDOUT ) +# +# # do NOT remove this delay: +# time.sleep(5) +# +# p_isql.terminate() +# isql_log.close() +# +# ##################################################################### +# +# # Stop trace session: +# +# trc_lst=open(trc_lst.name, "a") +# trc_lst.seek(0,2) +# subprocess.call([ "fbsvcmgr", "localhost:service_mgr", "user" , "SYSDBA" , "password" , "masterkey", "action_trace_stop","trc_id",trcssn], stdout=trc_lst, stderr=subprocess.STDOUT ) +# trc_lst.close() +# +# p_svcmgr.terminate() +# trc_log.close() +# +# # do NOT remove this delay: +# time.sleep(2) +# +# ##################################################################### +# +# # Output logs: +# +# i=0 +# with open( trc_log.name,'r') as f: +# for line in f: +# if ') EXECUTE_STATEMENT_FINISH' in line: +# i=1 +# if i==1 and '1 records fetched' in line: +# i=2 +# print("OK: found text in trace related to EMBEDDED connect.") +# break +# +# if not i==2: +# print("FAILED to found text in trace related to EMBEDDED connect.") +# +# if os.path.getsize(isql_log.name) == 0: +# print("FAILED to print log from EMBEDDED connect: log is EMPTY.") +# else: +# with open( isql_log.name,'r') as f: +# print(f.read()) +# f.close() +# +# +# # do NOT remove this pause otherwise log of trace will not be enable for deletion and test will finish with +# # Exception raised while executing Python test script. exception: WindowsError: 32 +# +# time.sleep(1) +# +# # On WI-V3.0.0.31948 final output was: +# # FAILED to found text in trace related to EMBEDDED connect. +# # FAILED to print log from EMBEDDED connect: log is EMPTY. +# +# ##################################################################### +# +# # Cleanup: +# +# f_list = [ trc_lst, trc_cfg, trc_log ] +# if trcssn > 0: +# f_list += [isql_cmd, isql_log, ] +# +# for f in f_list: +# os.remove(f.name) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + OK: found text in trace related to EMBEDDED connect. + CONNECTION_PROTOCOL internal + CONNECTION_PROCESS internal + CONNECTION_REMOTE_PID internal + AUTH_METHOD User name in DPB + Records affected: 1 + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_4889_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4898.py b/tests/bugs/test_core_4898.py new file mode 100644 index 00000000..9de6b1f3 --- /dev/null +++ b/tests/bugs/test_core_4898.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: bugs.core_4898 +# title: Speed up function creation and loading when there are many functions in the database +# decription: +# tracker_id: CORE-4898 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- See: http://sourceforge.net/p/firebird/code/62075 + set list on; + select ri.rdb$relation_name,rs.rdb$field_name,rs.rdb$field_position + from rdb$indices ri join rdb$index_segments rs + using (rdb$index_name) + where ri.rdb$relation_name='RDB$FUNCTIONS' and rdb$field_name='RDB$FUNCTION_ID'; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_NAME RDB$FUNCTION_ID + RDB$FIELD_POSITION 0 + """ + +@pytest.mark.version('>=3.0') +def test_core_4898_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4899.py b/tests/bugs/test_core_4899.py new file mode 100644 index 00000000..0468d667 --- /dev/null +++ b/tests/bugs/test_core_4899.py @@ -0,0 +1,105 @@ +#coding:utf-8 +# +# id: bugs.core_4899 +# title: GFIX -online: message "IProvider::attachDatabase failed when loading mapping cache" appears in Classic (only) if access uses remote protocol +# decription: +# +# tracker_id: CORE-4899 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!Attributes).)*$', ''), ('[\t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# fdb='$(DATABASE_LOCATION)bugs.core_4899.fdb' +# fdx=os.path.join(context['temp_directory'],'tmp_copy_4899.fdb') +# +# if os.path.isfile(fdx): +# os.remove(fdx) +# +# script="create database 'localhost:%s';" % fdx +# runProgram('isql',['-q'],script) +# # --------------------- I ---------------- +# +# #shutil.copy2( fdb, fdx ) +# +# # Trying to move database to OFFLINE: +# +# runProgram('gfix',['-shut', 'full', '-force', '0', fdx]) +# +# runProgram('gstat',['-h',fdx]) +# +# # Trying to move database online using LOCAL protocol: +# runProgram('gfix',['-online',fdx]) +# +# # gfix attachment via local protocol reflects with following lines in trace: +# # 2015-08-24T18:30:03.2580 (2516:012417E0) ATTACH_DATABASE +# # C:\\MIX\\FIREBIRD\\QA\\FBT-REPO\\TMP\\CORE4899-TMP.FDB (ATT_9, SYSDBA:NONE, NONE, ) +# +# runProgram('gstat',['-h',fdx]) +# +# if os.path.isfile(fdx): +# os.remove(fdx) +# +# # --------------------- II --------------- +# +# #shutil.copy2( fdb, fdx ) +# runProgram('isql',['-q'],script) +# +# runProgram('gfix',['-shut', 'full', '-force', '0', fdx]) +# runProgram('gstat',['-h',fdx]) +# +# # Trying to move database online using REMOTE protocol: +# runProgram('gfix',['-online','localhost:'+fdx]) +# +# # Note: gfix attachment via remote protocol refects with following lines in trace: +# # 2015-08-24T18:30:03.8520 (3256:01B526A8) ATTACH_DATABASE +# # C:\\MIX\\FIREBIRD\\QA\\FBT-REPO\\TMP\\CORE4899-TMP.FDB (ATT_9, SYSDBA:NONE, NONE, TCPv4:127.0.0.1) +# # C:\\MIX +# irebird +# b30\\gfix.exe:1448 +# +# runProgram('gstat',['-h',fdx]) +# +# if os.path.isfile(fdx): +# os.remove(fdx) +# +# #, 'substitutions':[('^((?!Attributes).)*$',''),('[\\s]+',' ')] +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +Attributes force write, full shutdown +Attributes force write +Attributes force write, full shutdown +Attributes force write + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4899_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4904.py b/tests/bugs/test_core_4904.py new file mode 100644 index 00000000..faf9e746 --- /dev/null +++ b/tests/bugs/test_core_4904.py @@ -0,0 +1,173 @@ +#coding:utf-8 +# +# id: bugs.core_4904 +# title: Index corruption when add data in long-key-indexed field +# decription: +# In order to check ticket issues this test does following: +# 1. Change on test database FW to OFF - this will increase DML performance. +# 2. Create table with indexed field of length = maximum that is allowed by +# current FB implementation (page_size / 4 - 9 bytes). +# 3. Try to insert enough number of records in this table - this should cause +# runtime exception SQLSTATE = 54000, "Maximum index level reached" +# 4. Start validation of database: index should NOT be corrupted in its report. +# +# Checked on WI-V3.0.0.32140 (CS, SC); WI-V3.0.0.32157 - official RC1 (SS) +# +# tracker_id: CORE-4904 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9]', ''), ('Maximum index .* reached', 'Maximum index reached'), ('Relation [0-9]{3,4}', 'Relation'), ('After line .*', ''), ('-At block line: [\\d]+, col: [\\d]+', '-At block line')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_name = db_conn.database_name +# db_conn.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'): +# # 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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# # Move database to FW = OFF in order to increase speed of insertions and output its header info: +# ##################################################################### +# +# f_change_fw_log=open( os.path.join(context['temp_directory'],'tmp_fw_off_4904.log'), 'w') +# subprocess.call([ context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", +# "prp_write_mode", "prp_wm_async", +# "dbname", db_name ], +# stdout=f_change_fw_log, stderr=subprocess.STDOUT) +# flush_and_close( f_change_fw_log ) +# +# ##################################################################### +# # Preparing script for ISQL that will do inserts with long keys: +# +# sql_cmd=''' recreate table test(s varchar(1015)); -- with THIS length of field following EB will get exception very fast. +# create index test_s on test(s); +# commit; +# set term ^; +# execute block as +# begin +# insert into test(s) +# select rpad('', 1015, uuid_to_char(gen_uuid()) ) +# from rdb$types, rdb$types +# rows 50000; -- this is extra-huge reserve; exception should raise when about 120-130 rows will be inserted. +# end +# ^ +# set term ;^ +# commit; +# ''' +# +# f_long_keys_cmd=open( os.path.join(context['temp_directory'],'tmp_isql_4904.sql'), 'w') +# f_long_keys_cmd.write(sql_cmd) +# flush_and_close( f_long_keys_cmd ) +# +# ##################################################################### +# # Starting ISQL +# +# f_long_keys_log=open( os.path.join(context['temp_directory'],'tmp_isql_4904.log'), 'w') +# subprocess.call([ context['isql_path'] , dsn, "-i", f_long_keys_cmd.name], +# stdout=f_long_keys_log, stderr=subprocess.STDOUT) +# flush_and_close( f_long_keys_log ) +# +# ##################################################################### +# # Run validation after ISQL will finish (with runtime exception due to implementation limit exceeding): +# +# f_validation_log=open( os.path.join(context['temp_directory'],'tmp_onval_4904.log'), 'w') +# +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_validate","val_lock_timeout","1", +# "dbname","$(DATABASE_LOCATION)bugs.core_4904.fdb"], +# stdout=f_validation_log, stderr=subprocess.STDOUT) +# +# flush_and_close( f_validation_log ) +# +# ##################################################################### +# # Output result of ISQL and online validation: +# with open( f_long_keys_log.name,'r') as f: +# print(f.read()) +# +# +# with open( f_validation_log.name,'r') as f: +# print(f.read()) +# +# +# +# # Cleanup: +# ########## +# time.sleep(1) +# cleanup( (f_change_fw_log, f_validation_log, f_long_keys_cmd, f_long_keys_log) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Statement failed, SQLSTATE = 54000 + Implementation limit exceeded + -Maximum index level reached + -At block line: 3, col: 7 + + Validation started + Relation (TEST) + process pointer page 0 of 1 + Index 1 (TEST_S) + Relation (TEST) is ok + Validation finished + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4904_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4905.py b/tests/bugs/test_core_4905.py new file mode 100644 index 00000000..7ab03e97 --- /dev/null +++ b/tests/bugs/test_core_4905.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: bugs.core_4905 +# title: Invalid internal BLR filter conversion +# decription: +# tracker_id: CORE-4905 +# min_versions: ['2.5.5'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('SP_BLR_BLOB.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create or alter procedure sp_test(field_name type of column rdb$types.rdb$field_name) as + begin + end + ^ + set term ;^ + commit; + set list on; + set blob all; + select cast(p.rdb$procedure_blr as blob sub_type text) sp_blr_blob + from rdb$procedures p + where p.rdb$procedure_name = upper('SP_TEST'); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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 + """ + +@pytest.mark.version('>=3.0') +def test_core_4905_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4909.py b/tests/bugs/test_core_4909.py new file mode 100644 index 00000000..6f438e4c --- /dev/null +++ b/tests/bugs/test_core_4909.py @@ -0,0 +1,143 @@ +#coding:utf-8 +# +# id: bugs.core_4909 +# title: MERGE / HASH JOINs produce incorrect results when VARCHAR join keys differ only by trailing spaces +# decription: +# tracker_id: CORE-4909 +# min_versions: ['2.5.5'] +# versions: 2.5.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter view v_test as select 1 id from rdb$database; + commit; + recreate table test ( + v varchar(10), + x integer + ); + recreate table show ( + t1_v_repl varchar(10), + t1_x integer, + t2_v_repl varchar(10), + t2_x integer + ); + commit; + + create or alter view v_test as + select + replace(t1.v, ' ', '0') as t1_v_repl + ,t1.x as t1_x + ,replace(t2.v, ' ', '0') as t2_v_repl + ,t2.x as t2_x + from test t1 + join test t2 on t1.v = t2.v; + commit; + + insert into test (v, x) values ('ww', 1); + insert into test (v, x) values ('ww ', 2); + commit; + + create index test_v on test(v); + commit; + + alter index test_v inactive; + commit; + + set list on; + + delete from show; + + --set plan on; + insert into show + select * from v_test; + set plan off; + commit; + + select 'index_inactive' as msg, s.* from show s order by t1_v_repl, t2_v_repl; + commit; + + alter index test_v active; + commit; + + delete from show; + + --set plan on; + insert into show + select * from v_test; + set plan off; + commit; + + select 'index_active' as msg, s.* from show s order by t1_v_repl, t2_v_repl; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG index_inactive + T1_V_REPL ww + T1_X 1 + T2_V_REPL ww + T2_X 1 + + MSG index_inactive + T1_V_REPL ww + T1_X 1 + T2_V_REPL ww0 + T2_X 2 + + MSG index_inactive + T1_V_REPL ww0 + T1_X 2 + T2_V_REPL ww + T2_X 1 + + MSG index_inactive + T1_V_REPL ww0 + T1_X 2 + T2_V_REPL ww0 + T2_X 2 + + MSG index_active + T1_V_REPL ww + T1_X 1 + T2_V_REPL ww + T2_X 1 + + MSG index_active + T1_V_REPL ww + T1_X 1 + T2_V_REPL ww0 + T2_X 2 + + MSG index_active + T1_V_REPL ww0 + T1_X 2 + T2_V_REPL ww + T2_X 1 + + MSG index_active + T1_V_REPL ww0 + T1_X 2 + T2_V_REPL ww0 + T2_X 2 + """ + +@pytest.mark.version('>=2.5.5') +def test_core_4909_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4917.py b/tests/bugs/test_core_4917.py new file mode 100644 index 00000000..f4248baa --- /dev/null +++ b/tests/bugs/test_core_4917.py @@ -0,0 +1,96 @@ +#coding:utf-8 +# +# id: bugs.core_4917 +# title: ALTER DOMAIN ... TO allows to specify matching to 'RDB$[[:DIGIT:]]*' +# decription: +# tracker_id: CORE-4917 +# min_versions: ['2.5.5'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- CREATION: + -- ######### + + -- First, check that direct creation of domain with 'RDB$' prefix is disabled: + create domain rdb$1 int; + + -- This also should FAIL becase new domain name is written in UPPER case (despite quotes): + create domain "RDB$2" int; + + -- This should pass because new though name starts with 'rdb$' it + -- is written in quotes and not in upper case: + create domain "rdb$1" int; + + -- ALTERING: + -- ######### + + alter domain "rdb$1" to foo; + + alter domain foo to "rdb$1"; + + -- This should pass because new though name starts with 'rdb$' it + -- is written in quotes and not in upper case: + alter domain "rdb$1" to "rdb$2"; + + -- this should FAIL: + alter domain "rdb$2" to RDB$3; + + -- 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + rdb$2 + """ +expected_stderr_1 = """ + 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_core_4917_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4921.py b/tests/bugs/test_core_4921.py new file mode 100644 index 00000000..15fa269e --- /dev/null +++ b/tests/bugs/test_core_4921.py @@ -0,0 +1,72 @@ +#coding:utf-8 +# +# id: bugs.core_4921 +# title: Predicate IS [NOT] DISTINCT FROM is not pushed into unions/aggregates thus causing sub-optimal plans +# decription: +# 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. +# Checked on: 3.0.0.32020 and 2.5.5.26926 - all versions before those produced suboptimal of inefficient plan. +# +# tracker_id: CORE-4921 +# min_versions: ['2.5.5'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create or alter view v_test as select 1 id from rdb$database; + commit; + + recreate table t1(x int, y int); + create index t1_single_x on t1(x); + create index t1_compound_x_y on t1(x, y); + + recreate table t2(x int, y int); + create index t2_single_x on t2(x); + create index t2_compound_x_y on t2(x, y); + + recreate table t3(x int, y int); + create index t3_single_x on t3(x); + create index t3_compound_x_y on t3(x, y); + commit; + + create or alter view v_test as + select * from t1 + union all + select * from t2 + union all + select * from t3; + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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)) + """ + +@pytest.mark.version('>=3.0') +def test_core_4921_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4923.py b/tests/bugs/test_core_4923.py new file mode 100644 index 00000000..dd348272 --- /dev/null +++ b/tests/bugs/test_core_4923.py @@ -0,0 +1,257 @@ +#coding:utf-8 +# +# id: bugs.core_4923 +# title: Add ability to track domains rename in DDL triggers +# decription: +# tracker_id: CORE-4923 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('SQL_TEXT.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table ddl_log ( + id integer generated by default as identity constraint pk_ddl_log primary key using index pk_ddl_log + ,who_logs varchar(50) + ,evn_type varchar(50) + ,obj_type varchar(50) + ,obj_name varchar(50) + ,old_name varchar(50) + ,new_name varchar(50) + ,sql_text blob sub_type text + ); + commit; + + + set term ^; + + -- active before create domain or alter domain or drop domain + create trigger ddl_log_befo active before any ddl statement + as + begin + insert into ddl_log( + who_logs + ,evn_type + ,obj_type + ,obj_name + ,old_name + ,new_name + ,sql_text + ) values ( + 'DDL trigger BEFORE ddl statement' + ,rdb$get_context('DDL_TRIGGER', 'EVENT_TYPE') + ,rdb$get_context('DDL_TRIGGER', 'OBJECT_TYPE') + ,rdb$get_context('DDL_TRIGGER', 'OBJECT_NAME') + ,rdb$get_context('DDL_TRIGGER', 'OLD_OBJECT_NAME') + ,rdb$get_context('DDL_TRIGGER', 'NEW_OBJECT_NAME') + ,rdb$get_context('DDL_TRIGGER', 'SQL_TEXT') + ); + end + ^ + + -- active before create domain or alter domain or drop domain + create trigger ddl_log_afte active after any ddl statement + as + begin + in autonomous transaction do + insert into ddl_log( + who_logs + ,evn_type + ,obj_type + ,obj_name + ,old_name + ,new_name + ,sql_text + ) values ( + 'DDL trigger AFTER ddl statement' + ,rdb$get_context('DDL_TRIGGER', 'EVENT_TYPE') + ,rdb$get_context('DDL_TRIGGER', 'OBJECT_TYPE') + ,rdb$get_context('DDL_TRIGGER', 'OBJECT_NAME') + ,rdb$get_context('DDL_TRIGGER', 'OLD_OBJECT_NAME') + ,rdb$get_context('DDL_TRIGGER', 'NEW_OBJECT_NAME') + ,rdb$get_context('DDL_TRIGGER', 'SQL_TEXT') + ); + end + ^ + + set term ;^ + commit; + + + create domain dm_foo smallint not null; -- here TWO transactions will start: DML and DDL. Only Tx for DDL will be auto-committed. + + -- For each of following DDL statements (which are executed with AUTOCOMMIT mode) two triggers fire: + -- "ddl_log_befo" and "ddl_log_afte". Each trigger DOES write info about DDL changing to the log table + -- ("ddl_log") but it does this work in the same Tx as DDL. So, new content of DDL_LOG table can not + -- be seen by starting DML transaction and we should do one more COMMIT before querying it (see below). + alter domain dm_foo type int; + alter domain dm_foo to dm_bar; + alter domain dm_bar type bigint; + alter domain dm_bar drop not null; + drop domain dm_bar; + + -- NB: 1st DML transaction was started in TIL = SNAPSHOT when we did "create domain dm_foo smallint not null;", + -- so it does not yet see data in ddl_log and we have to COMMIT this DML transaction: + commit; + + + set list on; + set count on; + select + id + ,who_logs + ,evn_type + ,obj_type + ,obj_name + ,old_name + ,new_name + ,sql_text + from ddl_log + where obj_type<>'TRIGGER' + order by id; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 2 + WHO_LOGS DDL trigger BEFORE ddl statement + EVN_TYPE CREATE + OBJ_TYPE DOMAIN + OBJ_NAME DM_FOO + OLD_NAME + NEW_NAME + SQL_TEXT 80:1 + create domain dm_foo smallint not null + + ID 3 + WHO_LOGS DDL trigger AFTER ddl statement + EVN_TYPE CREATE + OBJ_TYPE DOMAIN + OBJ_NAME DM_FOO + OLD_NAME + NEW_NAME + SQL_TEXT 80:2 + create domain dm_foo smallint not null + + ID 4 + WHO_LOGS DDL trigger BEFORE ddl statement + EVN_TYPE ALTER + OBJ_TYPE DOMAIN + OBJ_NAME DM_FOO + OLD_NAME + NEW_NAME + SQL_TEXT 80:3 + alter domain dm_foo type int + + ID 5 + WHO_LOGS DDL trigger AFTER ddl statement + EVN_TYPE ALTER + OBJ_TYPE DOMAIN + OBJ_NAME DM_FOO + OLD_NAME + NEW_NAME + SQL_TEXT 80:4 + alter domain dm_foo type int + + ID 6 + WHO_LOGS DDL trigger BEFORE ddl statement + EVN_TYPE ALTER + OBJ_TYPE DOMAIN + OBJ_NAME DM_FOO + OLD_NAME DM_FOO + NEW_NAME DM_BAR + SQL_TEXT 80:5 + alter domain dm_foo to dm_bar + + ID 7 + WHO_LOGS DDL trigger AFTER ddl statement + EVN_TYPE ALTER + OBJ_TYPE DOMAIN + OBJ_NAME DM_BAR + OLD_NAME DM_FOO + NEW_NAME DM_BAR + SQL_TEXT 80:6 + alter domain dm_foo to dm_bar + + ID 8 + WHO_LOGS DDL trigger BEFORE ddl statement + EVN_TYPE ALTER + OBJ_TYPE DOMAIN + OBJ_NAME DM_BAR + OLD_NAME + NEW_NAME + SQL_TEXT 80:7 + alter domain dm_bar type bigint + + ID 9 + WHO_LOGS DDL trigger AFTER ddl statement + EVN_TYPE ALTER + OBJ_TYPE DOMAIN + OBJ_NAME DM_BAR + OLD_NAME + NEW_NAME + SQL_TEXT 80:8 + alter domain dm_bar type bigint + + ID 10 + WHO_LOGS DDL trigger BEFORE ddl statement + EVN_TYPE ALTER + OBJ_TYPE DOMAIN + OBJ_NAME DM_BAR + OLD_NAME + NEW_NAME + SQL_TEXT 80:9 + alter domain dm_bar drop not null + + ID 11 + WHO_LOGS DDL trigger AFTER ddl statement + EVN_TYPE ALTER + OBJ_TYPE DOMAIN + OBJ_NAME DM_BAR + OLD_NAME + NEW_NAME + SQL_TEXT 80:a + alter domain dm_bar drop not null + + ID 12 + WHO_LOGS DDL trigger BEFORE ddl statement + EVN_TYPE DROP + OBJ_TYPE DOMAIN + OBJ_NAME DM_BAR + OLD_NAME + NEW_NAME + SQL_TEXT 80:b + drop domain dm_bar + + ID 13 + WHO_LOGS DDL trigger AFTER ddl statement + EVN_TYPE DROP + OBJ_TYPE DOMAIN + OBJ_NAME DM_BAR + OLD_NAME + NEW_NAME + SQL_TEXT 80:c + drop domain dm_bar + + + Records affected: 12 + """ + +@pytest.mark.version('>=3.0') +def test_core_4923_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4927.py b/tests/bugs/test_core_4927.py new file mode 100644 index 00000000..9bafb017 --- /dev/null +++ b/tests/bugs/test_core_4927.py @@ -0,0 +1,283 @@ +#coding:utf-8 +# +# id: bugs.core_4927 +# title: IIF function prevents the condition from being pushed into the union for better optimization +# decription: +# 1. Obtain engine_version from built-in context variable. +# 2. Make config for trace in proper format according to FB engine version, +# with adding invalid element 'foo' instead on boolean ('true' or 'false') +# 3. Launch trace session in separate child process using 'FBSVCMGR action_trace_start' +# 4. Run ISQL with calling test SP. +# 5. Stop trace session. Output its log with filtering only messages related to ticket notes. +# +# Trace log for FB 2.5 builds before rev. 62200 ( http://sourceforge.net/p/firebird/code/62200 ) +# contained tables which does NOT contain data which we are looked for (marked as "<<<"): +# +# Table Natural Index +# **************************************************** +# HEADER_2100 1 +# DETAIL_1000 1 <<< +# DETAIL_1200 1 +# DETAIL_2000 1 <<< +# DETAIL_2100 1 +# DETAIL_3300 1 <<< +# +# Here we check that trace log will contain only TWO tables: HEADER_2100 and DETAIL_2100. +# Bug affected only 2.5.x. Test checked on: WI-V2.5.5.26928, built at: 2015-09-08 00:13:06 UTC (rev 62201) +# +# ::: NB ::: +# Several delays (time.sleep) added in main thread because of OS buffering. Couldn't switch this buffering off. +# +# tracker_id: CORE-4927 +# min_versions: ['2.5.5'] +# versions: 2.5.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.5 +# resources: None + +substitutions_1 = [('^((?!HEADER_|DETAIL_).)*$', ''), ('HEADER_2100.*', 'HEADER_2100'), ('DETAIL_2100.*', 'DETAIL_2100')] + +init_script_1 = """ + create or alter procedure sp_test as begin end; + recreate view vd_union as select 1 id from rdb$database; + recreate table header_2100(dd_id int, ware_id int, snd_optype_id int); + recreate table detail_1000 (ware_id int,snd_optype_id int,rcv_optype_id int,snd_id int); + recreate table detail_1200 (ware_id int,snd_optype_id int,rcv_optype_id int,snd_id int); + recreate table detail_2000 (ware_id int,snd_optype_id int,rcv_optype_id int,snd_id int); + recreate table detail_2100 (ware_id int,snd_optype_id int,rcv_optype_id int,snd_id int); + recreate table detail_3300 (ware_id int,snd_optype_id int,rcv_optype_id int,snd_id int); + recreate view vd_union as + select 'd1000' src,q.* + from detail_1000 q + union all + select 'd1200', q.* + from detail_1200 q + union all + select 'd2000', q.* + from detail_2000 q + union all + select 'd2100', q.* + from detail_2100 q + union all + select 'd3300', q.* + from detail_3300 q + ; + commit; + + set term ^; + create or alter procedure sp_test returns(result int) as + begin + for + select count(*) + from ( + select + d.dd_id, + d.ware_id, + iif(1 = 0, 3300, 2100) as snd_optype_id -- this caused engine to unnecessary scans of tables which did not contain data searched for + from header_2100 d + ) d + left join vd_union qd on + qd.ware_id = d.ware_id + and qd.snd_optype_id = d.snd_optype_id + and qd.rcv_optype_id is not distinct from 3300 + and qd.snd_id = d.dd_id + into result + do + suspend; + end + ^ + set term ;^ + commit; + + insert into header_2100(dd_id, ware_id, snd_optype_id) values(1, 11, 2100); + commit; + + insert into detail_1000 (ware_id,snd_optype_id,rcv_optype_id,snd_id) values( 11, 1000, 1200, 1); + insert into detail_1200 (ware_id,snd_optype_id,rcv_optype_id,snd_id) values( 11, 1200, 2000, 1); + insert into detail_2000 (ware_id,snd_optype_id,rcv_optype_id,snd_id) values( 11, 2000, 2100, 1); + insert into detail_2100 (ware_id,snd_optype_id,rcv_optype_id,snd_id) values( 11, 2100, 3300, 1); + insert into detail_3300 (ware_id,snd_optype_id,rcv_optype_id,snd_id) values( 11, 3300, null, 1); + commit; + + create index d1000_wsrs on detail_1000 (ware_id,snd_optype_id,rcv_optype_id,snd_id); + create index d1200_wsrs on detail_1200 (ware_id,snd_optype_id,rcv_optype_id,snd_id); + create index d2000_wsrs on detail_2000 (ware_id,snd_optype_id,rcv_optype_id,snd_id); + create index d2100_wsrs on detail_2100 (ware_id,snd_optype_id,rcv_optype_id,snd_id); + create index d3300_wsrs on detail_3300 (ware_id,snd_optype_id,rcv_optype_id,snd_id); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import subprocess +# from subprocess import Popen +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # Obtain engine version: +# engine = str(db_conn.engine_version) # convert to text because 'float' object has no attribute 'startswith' +# db_conn.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'): +# # 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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# ##################################################### +# +# txt25 = '''# Trace config, format for 2.5. Generated auto, do not edit! +# +# enabled true +# time_threshold 0 +# log_statement_finish true +# print_perf true +# +# ''' +# +# # NOTES ABOUT TRACE CONFIG FOR 3.0: +# # 1) Header contains `database` clause in different format vs FB 2.5: its data must be enclosed with '{' '}' +# # 2) Name and value must be separated by EQUALITY sign ('=') in FB-3 trace.conf, otherwise we get runtime error: +# # element "<. . .>" have no attribute value set +# +# txt30 = '''# Trace config, format for 3.0. Generated auto, do not edit! +# database=%[\\\\\\\\/]bugs.core_4927.fdb +# { +# enabled = true +# time_threshold = 0 +# log_statement_finish = true +# print_perf = true +# } +# ''' +# +# f_trccfg=open( os.path.join(context['temp_directory'],'tmp_trace_4927.cfg'), 'w') +# if engine.startswith('2.5'): +# f_trccfg.write(txt25) +# else: +# f_trccfg.write(txt30) +# +# flush_and_close( f_trccfg ) +# +# ##################################################### +# # Starting trace session in new child process (async.): +# +# f_trclog=open( os.path.join(context['temp_directory'],'tmp_trace_4927.log'), 'w') +# # Execute a child program in a new process, redirecting STDERR to the same target as of STDOUT: +# p_trace=Popen([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_start", +# "trc_cfg", f_trccfg.name], +# stdout=f_trclog, stderr=subprocess.STDOUT) +# +# # Wait! Trace session is initialized not instantly! +# time.sleep(1) +# +# sqltxt=''' +# set list on; +# select result from sp_test; +# ''' +# +# runProgram('isql',[dsn],sqltxt) +# +# # do NOT remove this otherwise trace log can contain only message about its start before being closed! +# time.sleep(3) +# +# # Getting ID of launched trace session and STOP it: +# ################################################### +# +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# f_trclst=open( os.path.join(context['temp_directory'],'tmp_trace_4927.lst'), 'w') +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_list"], +# stdout=f_trclst, stderr=subprocess.STDOUT +# ) +# flush_and_close( f_trclst ) +# +# trcssn=0 +# with open( f_trclst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# f_trclst=open(f_trclst.name,'a') +# f_trclst.seek(0,2) +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_stop", +# "trc_id",trcssn], +# stdout=f_trclst, stderr=subprocess.STDOUT +# ) +# flush_and_close( f_trclst ) +# +# # Terminate child process of launched trace session (though it should already be killed): +# p_trace.terminate() +# flush_and_close( f_trclog ) +# +# with open( f_trclog.name,'r') as f: +# for line in f: +# print(line) +# +# # do NOT remove this delay otherwise get access error 'Windows 32' +# # (The process cannot access the file because it is being used by another process): +# time.sleep(1) +# +# # CLEANUP +# ######### +# cleanup( (f_trccfg, f_trclst, f_trclog) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + HEADER_2100 + DETAIL_2100 + """ + +@pytest.mark.version('>=2.5.5') +@pytest.mark.xfail +def test_core_4927_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4928.py b/tests/bugs/test_core_4928.py new file mode 100644 index 00000000..b7e12a67 --- /dev/null +++ b/tests/bugs/test_core_4928.py @@ -0,0 +1,99 @@ +#coding:utf-8 +# +# id: bugs.core_4928 +# title: It is not possible to save the connection information in the ON CONNECT trigger, if the connection is created by the gbak +# decription: +# tracker_id: CORE-4928 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table att_log ( + att_id int, + att_name varchar(255), + att_user varchar(255), + att_addr varchar(255), + att_prot varchar(255), + att_auth varchar(255), + att_dts timestamp default 'now' + ); + + commit; + + set term ^; + create or alter trigger trg_connect active on connect as + begin + in autonomous transaction do + insert into att_log(att_id, att_name, att_user, att_addr, att_prot, att_auth) + select + mon$attachment_id + ,mon$attachment_name + ,mon$user + ,mon$remote_address + ,mon$remote_protocol + ,mon$auth_method + from mon$attachments + where mon$remote_protocol starting with upper('TCP') and mon$user = upper('SYSDBA') + ; + end + ^ + set term ;^ + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# db_conn.close() +# fbk = os.path.join(context['temp_directory'],'tmp.core_4928.fbk') +# runProgram('gbak',['-b','-user',user_name,'-password',user_password,dsn,fbk]) +# runProgram('gbak',['-rep','-user',user_name,'-password',user_password,fbk,dsn]) +# +# sql=''' +# set list on; +# select +# iif( att_id > 0, 1, 0) is_att_id_ok +# ,iif( att_name containing 'core_4928.fdb', 1, 0) is_att_name_ok +# ,iif( att_user = upper('SYSDBA'), 1, 0) is_att_user_ok +# ,iif( att_addr is not null, 1, 0) is_att_addr_ok +# ,iif( upper(att_prot) starting with upper('TCP'), 1, 0) is_att_prot_ok +# ,iif( att_auth is not null, 1, 0) is_att_auth_ok +# ,iif( att_dts is not null, 1, 0) is_att_dts_ok +# from att_log +# where att_id <> current_connection; +# ''' +# runProgram('isql',[dsn,'-user',user_name,'-pas',user_password],sql) +# +# if os.path.isfile(fbk): +# os.remove(fbk) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + IS_ATT_ID_OK 1 + IS_ATT_NAME_OK 1 + IS_ATT_USER_OK 1 + IS_ATT_ADDR_OK 1 + IS_ATT_PROT_OK 1 + IS_ATT_AUTH_OK 1 + IS_ATT_DTS_OK 1 + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4928_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4929.py b/tests/bugs/test_core_4929.py new file mode 100644 index 00000000..ccf79850 --- /dev/null +++ b/tests/bugs/test_core_4929.py @@ -0,0 +1,94 @@ +#coding:utf-8 +# +# id: bugs.core_4929 +# title: Cannot compile source with "ELSE IF ( ) THEN" statement and commands to manupulate explicit cursor inside +# decription: +# tracker_id: CORE-4929 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create or alter procedure sp_test(v smallint) returns(result int) as + begin + result = null; + suspend; + end + ^ + set term ;^ + + commit; + + set term ^; + alter procedure sp_test(v smallint) returns(result int) as + + declare c1 cursor for ( + select 1 id from rdb$database + ); + + declare c2 cursor for ( + select 2 id from rdb$database + ); + + begin + + if ( v = 1 ) then open c1; + else + if ( :v = 2 ) then + open c2; + + while (1=1) do + begin + if ( v = 1 ) then fetch c1 into result; + else + if ( :v = 2 ) then + fetch c2 into result; + + if (row_count = 0) then leave; + + suspend; + + end + + if ( v = 1 ) then close c1; + else + if ( :v = 2 ) then + close c2; + + end + ^ + set term ;^ + commit; + + set list on; + select * from sp_test(1); + select * from sp_test(2); + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT 1 + RESULT 2 + """ + +@pytest.mark.version('>=3.0') +def test_core_4929_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4933.py b/tests/bugs/test_core_4933.py new file mode 100644 index 00000000..17f4814b --- /dev/null +++ b/tests/bugs/test_core_4933.py @@ -0,0 +1,256 @@ +#coding:utf-8 +# +# id: bugs.core_4933 +# title: Add better transaction control to isql +# decription: +# Test creates two .sql script and run them using ISQL utility. +# In the 1st script we create view for check current transaction parameters. +# View output following values for transaction: +# TIL, lock resolution (wait/no_wait/lock_timeout), read_only/read_write and [no]auto_undo +# +# Then we TURN ON keeping of Tx parameters (SET KEEP_TRAN ON) and do some manipulations in this +# ('main') script, including invocation of auxiliary ('addi') script using IN <...> command. +# +# Second script creates another database and the same view in it, then does soma actions there +# and also check output of this view. +# After this (second) script finish, we return to 1st one and resume there final actions. +# +# IN ALL STEPS WE HAVE TO SEE THE SAME PARAMS - NO MATTER HOW MUCH TIMES +# WE DID COMMIT/ROLLBACK/RECONNECT AND EVEN WORK IN OTHER DB. +# +# Checked on: 3.0.6.33249; 4.0.0.1777 +# +# tracker_id: CORE-4933 +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import sys +# import os +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.close() +# +# tmp_addi_fdb = os.path.join(context['temp_directory'],'tmp_addi_4933.fdb') +# +# if os.path.isfile(tmp_addi_fdb): +# os.remove( tmp_addi_fdb ) +# +# #------------------------------------------- +# +# sql_addi_script=''' +# create database 'localhost:%(tmp_addi_fdb)s' user %(user_name)s password '%(user_password)s'; +# +# 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_addi_fdb)s' user %(user_name)s password '%(user_password)s'; +# select 'addi_script: reconnect' as msg, v.* from v_check v; +# rollback; +# +# drop database; +# ''' +# +# f_addi_sql = open( os.path.join(context['temp_directory'],'tmp_core_4731_addi.sql'), 'w', buffering = 0) +# f_addi_sql.write( sql_addi_script % dict(globals(), **locals()) ) +# f_addi_sql.close() +# f_addi_sql_name = f_addi_sql.name +# #------------------------------------------- +# +# sql_main_script=''' +# set list on; +# connect '%(dsn)s' user %(user_name)s password '%(user_password)s'; +# 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 '%(dsn)s' user %(user_name)s password '%(user_password)s'; --------------------------- [ 3 ] +# +# select 'main_script: after_reconnect' as msg, v.* from v_check v; +# rollback; +# +# --################### +# in %(f_addi_sql_name)s; +# --################### +# +# connect '%(dsn)s' user %(user_name)s password '%(user_password)s'; --------------------------- [ 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; +# ''' +# +# f_main_sql = open( os.path.join(context['temp_directory'],'tmp_core_4731_main.sql'), 'w', buffering = 0) +# f_main_sql.write( sql_main_script % dict(globals(), **locals()) ) +# f_main_sql.close() +# +# runProgram( 'isql',['-q', '-i', f_main_sql.name] ) +# +# os.remove( f_main_sql.name ) +# os.remove( f_addi_sql.name ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG main_script: initial + TX_TIL_MON_TRANS snapshot + TX_TIL_RDB_GET_CONTEXT SNAPSHOT + TX_LOCK_TIMEOUT_MON_TRANS wait + TX_LOCK_TIMEOUT_RDB_GET_CONTEXT -1 + TX_READ_ONLY_MON_TRANS read_write + TX_READ_ONLY_RDB_GET_CONTEXT FALSE + TX_AUTOUNDO_MON_TRANS 1 + + + MSG main_script: started Tx + TX_TIL_MON_TRANS rc rec_vers + TX_TIL_RDB_GET_CONTEXT READ COMMITTED + TX_LOCK_TIMEOUT_MON_TRANS timeout 5 + TX_LOCK_TIMEOUT_RDB_GET_CONTEXT 5 + TX_READ_ONLY_MON_TRANS read_only + TX_READ_ONLY_RDB_GET_CONTEXT TRUE + TX_AUTOUNDO_MON_TRANS 0 + + + MSG main_script: after_commit + TX_TIL_MON_TRANS rc rec_vers + TX_TIL_RDB_GET_CONTEXT READ COMMITTED + TX_LOCK_TIMEOUT_MON_TRANS timeout 5 + TX_LOCK_TIMEOUT_RDB_GET_CONTEXT 5 + TX_READ_ONLY_MON_TRANS read_only + TX_READ_ONLY_RDB_GET_CONTEXT TRUE + TX_AUTOUNDO_MON_TRANS 0 + + + MSG main_script: after_rollback + TX_TIL_MON_TRANS rc rec_vers + TX_TIL_RDB_GET_CONTEXT READ COMMITTED + TX_LOCK_TIMEOUT_MON_TRANS timeout 5 + TX_LOCK_TIMEOUT_RDB_GET_CONTEXT 5 + TX_READ_ONLY_MON_TRANS read_only + TX_READ_ONLY_RDB_GET_CONTEXT TRUE + TX_AUTOUNDO_MON_TRANS 0 + + + MSG main_script: after_reconnect + TX_TIL_MON_TRANS rc rec_vers + TX_TIL_RDB_GET_CONTEXT READ COMMITTED + TX_LOCK_TIMEOUT_MON_TRANS timeout 5 + TX_LOCK_TIMEOUT_RDB_GET_CONTEXT 5 + TX_READ_ONLY_MON_TRANS read_only + TX_READ_ONLY_RDB_GET_CONTEXT TRUE + TX_AUTOUNDO_MON_TRANS 0 + + + MSG addi_script: create_new_db + TX_TIL_MON_TRANS rc rec_vers + TX_TIL_RDB_GET_CONTEXT READ COMMITTED + TX_LOCK_TIMEOUT_MON_TRANS timeout 5 + TX_LOCK_TIMEOUT_RDB_GET_CONTEXT 5 + TX_READ_ONLY_MON_TRANS read_only + TX_READ_ONLY_RDB_GET_CONTEXT TRUE + TX_AUTOUNDO_MON_TRANS 0 + + + MSG addi_script: reconnect + TX_TIL_MON_TRANS rc rec_vers + TX_TIL_RDB_GET_CONTEXT READ COMMITTED + TX_LOCK_TIMEOUT_MON_TRANS timeout 5 + TX_LOCK_TIMEOUT_RDB_GET_CONTEXT 5 + TX_READ_ONLY_MON_TRANS read_only + TX_READ_ONLY_RDB_GET_CONTEXT TRUE + TX_AUTOUNDO_MON_TRANS 0 + + + MSG main_script: resume + TX_TIL_MON_TRANS rc rec_vers + TX_TIL_RDB_GET_CONTEXT READ COMMITTED + TX_LOCK_TIMEOUT_MON_TRANS timeout 5 + TX_LOCK_TIMEOUT_RDB_GET_CONTEXT 5 + TX_READ_ONLY_MON_TRANS read_only + TX_READ_ONLY_RDB_GET_CONTEXT TRUE + TX_AUTOUNDO_MON_TRANS 0 + + + MSG keep_tran: turned_off + TX_TIL_MON_TRANS snapshot + TX_TIL_RDB_GET_CONTEXT SNAPSHOT + TX_LOCK_TIMEOUT_MON_TRANS wait + TX_LOCK_TIMEOUT_RDB_GET_CONTEXT -1 + TX_READ_ONLY_MON_TRANS read_write + TX_READ_ONLY_RDB_GET_CONTEXT FALSE + TX_AUTOUNDO_MON_TRANS 1 + """ + +@pytest.mark.version('>=3.0.6') +@pytest.mark.xfail +def test_core_4933_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4934.py b/tests/bugs/test_core_4934.py new file mode 100644 index 00000000..36d9368b --- /dev/null +++ b/tests/bugs/test_core_4934.py @@ -0,0 +1,159 @@ +#coding:utf-8 +# +# id: bugs.core_4934 +# title: Different collation ID for altered computed column +# decription: +# tracker_id: CORE-4934 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table t_country(id int); + commit; + + create or alter view v_test as + select + rf.rdb$relation_name rel_name + ,rf.rdb$field_name fld_name + --,rf.rdb$field_source fld_source + ,f.rdb$character_set_id cset_id + ,f.rdb$collation_id coll_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 in( upper('t_country'), upper('t_translation_meta')) + order by 1,2; + + commit; + + recreate table t_translation_meta ( + f_trm_id bigint not null, + f_trm_code varchar(512) character set utf8 not null collate + unicode_ci + ); + commit; + + recreate table t_country ( + f_cnr_id bigint not null, + f_trm_name_id bigint default -1 not null, + cf_cnr_name computed by ( + ( + ( + select f_trm_code + from t_translation_meta + where f_trm_id = f_trm_name_id + ) + ) + ) + ); + commit; + + set width rel_name 20; + set width fld_name 20; + set width fld_source 20; + + set list on; + + select 'before' msg, v.* from v_test v; + + + alter table t_country alter cf_cnr_name computed by + ( + ( + ( + select + f_trm_code + from t_translation_meta + where f_trm_id = f_trm_name_id + ) + ) + ); + commit; + + select 'after' msg, v.* from v_test v; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG before + REL_NAME T_COUNTRY + FLD_NAME CF_CNR_NAME + CSET_ID 4 + COLL_ID 3 + + MSG before + REL_NAME T_COUNTRY + FLD_NAME F_CNR_ID + CSET_ID + COLL_ID + + MSG before + REL_NAME T_COUNTRY + FLD_NAME F_TRM_NAME_ID + CSET_ID + COLL_ID + + MSG before + REL_NAME T_TRANSLATION_META + FLD_NAME F_TRM_CODE + CSET_ID 4 + COLL_ID 3 + + MSG before + REL_NAME T_TRANSLATION_META + FLD_NAME F_TRM_ID + CSET_ID + COLL_ID + + + + MSG after + REL_NAME T_COUNTRY + FLD_NAME CF_CNR_NAME + CSET_ID 4 + COLL_ID 3 + + MSG after + REL_NAME T_COUNTRY + FLD_NAME F_CNR_ID + CSET_ID + COLL_ID + + MSG after + REL_NAME T_COUNTRY + FLD_NAME F_TRM_NAME_ID + CSET_ID + COLL_ID + + MSG after + REL_NAME T_TRANSLATION_META + FLD_NAME F_TRM_CODE + CSET_ID 4 + COLL_ID 3 + + MSG after + REL_NAME T_TRANSLATION_META + FLD_NAME F_TRM_ID + CSET_ID + COLL_ID + """ + +@pytest.mark.version('>=3.0') +def test_core_4934_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4937.py b/tests/bugs/test_core_4937.py new file mode 100644 index 00000000..8772fe18 --- /dev/null +++ b/tests/bugs/test_core_4937.py @@ -0,0 +1,161 @@ +#coding:utf-8 +# +# id: bugs.core_4937 +# title: View/subselect with "union" does not use computed index +# decription: +# tracker_id: CORE-4937 +# min_versions: ['2.5.5'] +# versions: 2.5.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='mon-stat-gathering-2_5.fbk', init=init_script_1) + +test_script_1 = """ + -- ::: NB ::: Plans in 2.5 and 3.0 differ (see below). + -- It was decided to check number of natural reads gathered + -- from mon$ statistics rather than filter plan text with + -- finding word 'NATURAL'. + + -- Checked on: + -- 2.5.5.26916 - had non-zero natural reads in statistics + -- 2.5.5.26933, 3.0.0.32052 - all Ok. + set term ^; + execute block as begin execute statement 'drop sequence g'; when any do begin end end + ^ + set term ;^ + commit; + create sequence g; + + recreate view test_view as select 1 id from rdb$database; + recreate table test1 (id int not null primary key, tms timestamp default current_timestamp); + recreate table test2 (id int not null primary key, tms timestamp default current_timestamp); + + alter table test1 add occurred int computed by (case when tms < current_timestamp then 1 else 0 end); + + alter table test2 add occurred int; + + recreate view test_view as select * from test1 union select * from test2; + commit; + + insert into test1(id, tms) + select gen_id(g,1), dateadd( -gen_id(g,1) minute to cast('now' as timestamp) ) + from rdb$types + rows 200; + + insert into test1(id, tms) + select gen_id(g,1), dateadd( gen_id(g,1) minute to cast('now' as timestamp) ) + from rdb$types + rows 200; + + + insert into test2(id, tms) + select gen_id(g,1), dateadd( -gen_id(g,1) minute to cast('now' as timestamp) ) + from rdb$types + rows 200; + + insert into test2(id, tms) + select gen_id(g,1), dateadd( gen_id(g,1) minute to cast('now' as timestamp) ) + from rdb$types + rows 200; + + update test2 set occurred = case when tms < current_timestamp then 1 else 0 end; + + commit; + + create index test1_occ on test1 computed by (case when tms < current_timestamp then 1 else 0 end); + create index test2_occ on test2(occurred); + commit; + + execute procedure sp_truncate_stat; + commit; + + set list on; + + --------------------- run-1 ------------------- + execute procedure sp_gather_stat; -- catch statistics BEFORE measured statement(s) + commit; + + select count(*) cnt_1 from test1 where occurred = 1; + + execute procedure sp_gather_stat; -- catch statistics AFTER measured statement(s) + commit; + + --------------------- run-2 ------------------- + execute procedure sp_gather_stat; -- catch statistics BEFORE measured statement(s) + commit; + + select count(*) cnt_2 from test2 where occurred = 1; + + execute procedure sp_gather_stat; -- catch statistics AFTER measured statement(s) + commit; + + --------------------- run-3 ------------------- + execute procedure sp_gather_stat; -- catch statistics BEFORE measured statement(s) + commit; + + -- in 2.5: + -- PLAN (TEST1 INDEX (TEST1_OCC)) + -- PLAN (TEST2 INDEX (TEST2_OCC)) + -- in 3.0: + -- PLAN SORT (TEST1 INDEX (TEST1_OCC), TEST2 INDEX (TEST2_OCC)) + + select count(*) cnt_3 from (select * from test1 union select * from test2) where occurred = 1; + + execute procedure sp_gather_stat; -- catch statistics AFTER measured statement(s) + commit; + + --------------------- run-4 ------------------- + execute procedure sp_gather_stat; -- catch statistics BEFORE measured statement(s) + commit; + + -- in 2.5: + -- PLAN (TEST_VIEW TEST1 INDEX (TEST1_OCC)) + -- PLAN (TEST_VIEW TEST2 INDEX (TEST2_OCC)) + -- in 3.0: + -- PLAN SORT (TEST_VIEW TEST1 INDEX (TEST1_OCC), TEST_VIEW TEST2 INDEX (TEST2_OCC)) + + select count(*) cnt_4 from test_view where occurred = 1; + + execute procedure sp_gather_stat; -- catch statistics AFTER measured statement(s) + commit; + + ------------------------------------------------- + + -- Output statistics. Natural reads in all cases should be 0 (zero): + select 'run_' || a.rowset as run_no, a.natural_reads from v_agg_stat a; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CNT_1 200 + CNT_2 200 + CNT_3 400 + CNT_4 400 + + RUN_NO run_1 + NATURAL_READS 0 + RUN_NO run_2 + NATURAL_READS 0 + RUN_NO run_3 + NATURAL_READS 0 + RUN_NO run_4 + NATURAL_READS 0 + """ + +@pytest.mark.version('>=2.5.5') +def test_core_4937_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4940.py b/tests/bugs/test_core_4940.py new file mode 100644 index 00000000..bcbebef1 --- /dev/null +++ b/tests/bugs/test_core_4940.py @@ -0,0 +1,60 @@ +#coding:utf-8 +# +# id: bugs.core_4940 +# title: Add label about deterministic flag for stored function in SHOW and extract commands +# decription: +# tracker_id: CORE-4940 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!Deterministic|deterministic).)*$', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- 1. Specify 'deterministic' flag - it should be reflected in SHOW command: + set term ^; + create or alter function fn_infinity returns bigint deterministic as + begin + return 9223372036854775807; + end + ^ + set term ;^ + commit; + + show function fn_infinity; + + -- 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 + ^ + set term ;^ + commit; + + show function fn_infinity; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Deterministic function + """ + +@pytest.mark.version('>=3.0') +def test_core_4940_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4943.py b/tests/bugs/test_core_4943.py new file mode 100644 index 00000000..a104d8fc --- /dev/null +++ b/tests/bugs/test_core_4943.py @@ -0,0 +1,90 @@ +#coding:utf-8 +# +# id: bugs.core_4943 +# title: Dialect 1 casting date to string breaks when in the presence a domain with a check constraint +# decription: +# tracker_id: CORE-4943 +# min_versions: ['2.5.5'] +# versions: 2.5.5 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=1, init=init_script_1) + +test_script_1 = """ + -- Confirmed fail on build 2.5.5.26916. + -- Works fine on: 2.5.5.26933, 3.0.0.32052 + + set wng off; + set term ^; + create domain dm_without_chk as varchar(5); + ^ + + create or alter procedure sp_test1 + returns ( + retDate varchar(25) + ,out_without_chk dm_without_chk + ) as + + begin + + out_without_chk = 'qwe'; + + retDate = cast('today' as date); + + suspend; + end + ^ + + create domain dm_with_check as varchar(5) + check (value is null or value in ('qwe', 'rty')) + ^ + + create or alter procedure sp_test2 + returns ( + retDate varchar(25) + ,out_with_check dm_with_check + ) as + begin + out_with_check = 'rty'; + + retDate = cast('today' as date); + + suspend; + end + ^ + set term ;^ + commit; + + set list on; + + select iif(char_length(retDate)<=11, 1, 0) as sp_test1_format_ok + from sp_test1; + + select iif(char_length(retDate)<=11, 1, 0) as sp_test2_format_ok + from sp_test2; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + + SP_TEST1_FORMAT_OK 1 + SP_TEST2_FORMAT_OK 1 + """ + +@pytest.mark.version('>=2.5.5') +def test_core_4943_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4947.py b/tests/bugs/test_core_4947.py new file mode 100644 index 00000000..ed1ed8cd --- /dev/null +++ b/tests/bugs/test_core_4947.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: bugs.core_4947 +# title: Compound ALTER TABLE statement with ADD and DROP the same check constraint fails +# decription: +# tracker_id: CORE-4947 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table t(x int not null); + alter table t + add constraint cx check(x > 0), + drop constraint cx; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +def test_core_4947_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_4950.py b/tests/bugs/test_core_4950.py new file mode 100644 index 00000000..bdf57aeb --- /dev/null +++ b/tests/bugs/test_core_4950.py @@ -0,0 +1,108 @@ +#coding:utf-8 +# +# id: bugs.core_4950 +# title: Statistics for any system index can not be updated/recalculated +# decription: +# tracker_id: CORE-4950 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table stat(idx_name varchar(31), stat_init double precision, stat_curr double precision); + recreate table test(id int primary key, pid int references test(id), x int, y int, unique(x,y)); + create or alter view v_stat as + select + iif( ri.rdb$index_name starting with 'RDB$PRIMARY', + 'RDB$PRIMARY', + iif( ri.rdb$index_name starting with 'RDB$FOREIGN', + 'RDB$FOREIGN', + 'RDB$UNIQUE' + ) + ) as idx_name + ,ri.rdb$statistics idx_stat + from rdb$indices ri + where ri.rdb$relation_name = upper('test'); + commit; + + insert into test(id, pid, x, y) values( 0, null, null, null); + + set term ^; + execute block as + declare i int = 1; + declare n int = 999; + begin + while (i < n) do + begin + insert into test(id, pid, x, y) values( :i, :i / 2, iif( mod(:i,2)=0, :i/2, null ), iif( mod(:i,2)=0, null, :i/2 )); + i = i + 1; + end + end + ^ + set term ;^ + commit; + + insert into stat(idx_name, stat_init) select idx_name, idx_stat from v_stat; + commit; + + set list on; + + set term ^; + execute block as + begin + for + select trim(ri.rdb$index_name) idx_name + from rdb$indices ri + where ri.rdb$relation_name = upper('test') + as cursor c + do + execute statement 'set statistics index ' || c.idx_name; + end + ^ + set term ;^ + commit; + + merge into stat t + using(select idx_name, idx_stat from v_stat) s + on t.idx_name = s.idx_name + when matched then update set t.stat_curr = s.idx_stat + when not matched then insert(idx_name, stat_curr) values( s.idx_name, s.idx_stat); + + commit; + + select idx_name, abs( sign( stat_curr - stat_init ) ) stat_diff + from stat + stat order by idx_name; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + IDX_NAME RDB$FOREIGN + STAT_DIFF 1 + + IDX_NAME RDB$PRIMARY + STAT_DIFF 1 + + IDX_NAME RDB$UNIQUE + STAT_DIFF 1 + """ + +@pytest.mark.version('>=3.0') +def test_core_4950_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4954.py b/tests/bugs/test_core_4954.py new file mode 100644 index 00000000..4cc5dc1d --- /dev/null +++ b/tests/bugs/test_core_4954.py @@ -0,0 +1,88 @@ +#coding:utf-8 +# +# id: bugs.core_4954 +# title: The package procedure with value by default isn't called if this parameter isn't specified. +# decription: +# tracker_id: CORE-4954 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create or alter package pkg_test + as + begin + procedure p1(a int, b int = 1) returns(x int); + function f1(a int, b int = 1) returns int; + procedure sp_test returns(x int); + end + ^ + + recreate package body pkg_test + as + begin + procedure p1(a int, b int) returns(x int) as + begin + x = a + b; + suspend; + end + + function f1(a int, b int) returns int as + begin + return a + b; + end + + procedure sp_test returns(x int) as + begin + + execute procedure p1( 12 ) returning_values :x; suspend; + + execute procedure p1( 12, 13 ) returning_values :x; suspend; + + select x from p1( 12 ) into x; suspend; + select x from p1( 12, 13 ) into x; suspend; + + x = f1( 21 ); suspend; + x = f1( 22, 23 ); suspend; + + end + end + ^ + set term ;^ + commit; + + + set list on; + select * from pkg_test.sp_test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + X 13 + X 25 + X 13 + X 25 + X 22 + X 45 + """ + +@pytest.mark.version('>=3.0') +def test_core_4954_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4964.py b/tests/bugs/test_core_4964.py new file mode 100644 index 00000000..cba1d6a5 --- /dev/null +++ b/tests/bugs/test_core_4964.py @@ -0,0 +1,265 @@ +#coding:utf-8 +# +# id: 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. +# decription: +# Test obtains full path to $fb_home via FBSVCMGR info_get_env. +# Then it makes copy of file 'databases.conf' that is in $fb_home directory because +# following lines will be added to that 'databases.conf': +# === +# tmp_alias_4964 = ... +# { +# SecurityDatabase = $(dir_conf)/firebird.msg +# } +# === +# NB: we intentionally put reference to file that for sure does exist but is INVALID for usage as fdb: 'firebird.msg' +# +# Then we: +# 1) obtain content of server firebird.log +# 2) try to make connect to alias 'tmp_alias_4964' and (as expected) get error. +# 3) wait a little and obtain again content of server firebird.log +# +# Finally we restore original databases.conf and check that: +# 1) Client error message contains phrase about need to check server firebird.log for details. +# 2) Difference of firebird.log contains messages that engine could not attach to password database +# because it is invalid (we specify 'firebird.msg' as security_db in databases.conf for test database, +# and of course this is not valid database) +# +# Client always get message with gdscode = 335545106 and sqlcode=-902. +# Error text in firebird.log depends on what plugin is used for authentification: +# 1) Legacy: +# Authentication error +# cannot attach to password database +# Error in isc_attach_database() API call when working with legacy security database +# file <...> is not a valid database +# 2) Srp: +# Authentication error +# file C:\\FBSS\\FIREBIRD.MSG is not a valid database +# +# Checked for: +# FB30SS, build 3.0.4.32972: OK, 3.360s. +# FB40SS, build 4.0.0.977: OK, 3.485s. +# +# Refactored 05.01.2020 (firebird.conf now contains Srp as first plugin in UserManager parameter): +# 4.0.0.1714 SS: 2.922s; 4.0.0.1714 SC: 5.563s; 4.0.0.1714 CS: 9.172s. +# 3.0.5.33221 SS: 2.015s; 3.0.5.33221 SC: 3.469s; 3.0.5.33221 CS: 6.173s. +# +# tracker_id: CORE-4964 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('FILE.*FIREBIRD.MSG', 'FILE FIREBIRD.MSG'), ('CLIENT_MSG: 335545106L', 'CLIENT_MSG: 335545106')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# from subprocess import Popen +# import difflib +# import datetime +# import time +# import shutil +# import re +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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'): +# # 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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# def svc_get_fb_log( f_fb_log ): +# +# global subprocess +# +# subprocess.call( [ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# "action_get_fb_log" +# ], +# stdout=f_fb_log, stderr=subprocess.STDOUT +# ) +# return +# +# #-------------------------------------------- +# +# svc = services.connect(host='localhost') +# fb_home=svc.get_home_directory() +# svc.close() +# +# dts = datetime.datetime.now().strftime("%y%m%d_%H%M%S") +# +# dbconf = os.path.join(fb_home, 'databases.conf') +# fbconf = os.path.join(fb_home, 'firebird.conf') +# +# dbcbak = os.path.join(fb_home, 'databases_'+dts+'.bak') +# fbcbak = os.path.join(fb_home, 'firebird_'+dts+'.bak') +# +# shutil.copy2( dbconf, dbcbak ) +# shutil.copy2( fbconf, fbcbak ) +# +# tmp_fdb=os.path.join(context['temp_directory'],'tmp_4964.fdb') +# +# f_dbconf=open(dbconf,'a') +# f_dbconf.seek(0, 2) +# f_dbconf.write("\\n\\n# Temporarily added by fbtest, CORE-4964. Should be removed auto:") +# f_dbconf.write("\\n#" + '='*60 ) +# f_dbconf.write("\\ntmp_alias_4964_"+dts+" = " + tmp_fdb ) +# f_dbconf.write("\\n{\\n SecurityDatabase = $(dir_conf)/firebird.msg\\n}") +# f_dbconf.write("\\n#" + '='*60 ) +# f_dbconf.close() +# +# f_fbconf=open(fbconf,'r') +# fbconf_content=f_fbconf.readlines() +# f_fbconf.close() +# for i,s in enumerate( fbconf_content ): +# if s.lower().lstrip().startswith( 'wirecrypt'.lower() ): +# fbconf_content[i] = '# ' + s +# +# fbconf_content.append('\\n# Temporarily added by fbtest, CORE-4964. Should be removed auto:') +# fbconf_content.append("\\n#" + '='*30 ) +# fbconf_content.append('\\nWireCrypt = Disabled') +# fbconf_content.append("\\n#" + '='*30 ) +# +# f_fbconf=open(fbconf,'w') +# f_fbconf.writelines( fbconf_content ) +# flush_and_close( f_fbconf ) +# +# f_fblog_before=open( os.path.join(context['temp_directory'],'tmp_4964_fblog_before.txt'), 'w') +# svc_get_fb_log( f_fblog_before ) +# flush_and_close( f_fblog_before ) +# +# f_connect_log=open( os.path.join(context['temp_directory'],'tmp_connect_4964.log'), 'w') +# +# try: +# # Try to connect to 'firebird.msg' which is obviously not a database file: +# ################################### +# con1=fdb.connect( dsn = 'localhost:tmp_alias_4964_'+dts ) +# f_connect_log.write( con1.firebird_version ) +# con1.close() +# except Exception,e: +# for x in e: +# f_connect_log.write( repr(x)+'\\n' ) +# +# flush_and_close( f_connect_log ) +# +# f_fblog_after=open( os.path.join(context['temp_directory'],'tmp_4964_fblog_after.txt'), 'w') +# svc_get_fb_log( f_fblog_after ) +# flush_and_close( f_fblog_after ) +# +# +# # RESTORE original config: +# ########################## +# shutil.move( dbcbak, dbconf ) +# shutil.move( fbcbak, fbconf ) +# +# # Compare firebird.log versions BEFORE and AFTER this test: +# ###################### +# +# oldfb=open(f_fblog_before.name, 'r') +# newfb=open(f_fblog_after.name, 'r') +# +# difftext = ''.join(difflib.unified_diff( +# oldfb.readlines(), +# newfb.readlines() +# )) +# oldfb.close() +# newfb.close() +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_4964_diff.txt'), 'w') +# f_diff_txt.write(difftext) +# flush_and_close( f_diff_txt ) +# +# +# allowed_patterns = ( +# re.compile('cannot\\s+attach\\s+to\\s+password+\\s+database\\.*', re.IGNORECASE) +# ,re.compile('error\\s+in\\s+isc_attach_database\\(\\)\\s+API\\.*', re.IGNORECASE) +# ,re.compile('file\\s+.*\\s+is\\s+not\\s+a\\s+valid\\s+database\\.*', re.IGNORECASE) +# ,re.compile('authentication\\s+error.*', re.IGNORECASE) +# ,re.compile('335545106') +# ,re.compile('-902') +# ) +# +# with open( f_connect_log.name,'r') as f: +# for line in f: +# match2some = filter( None, [ p.search(line) for p in allowed_patterns ] ) +# if match2some: +# print( 'CLIENT_MSG: ' + line.upper() ) +# +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# if line.startswith('+'): +# match2some = filter( None, [ p.search(line) for p in allowed_patterns ] ) +# if match2some: +# print( 'FIREBIRD.LOG: ' + (' '.join(line.split()).upper()) ) +# +# +# +# # Cleanup: +# ########## +# # do NOT remove this pause otherwise some of logs will not be enable for deletion and test will finish with +# # Exception raised while executing Python test script. exception: WindowsError: 32 +# time.sleep(1) +# cleanup( (f_connect_log, f_diff_txt, f_fblog_before, f_fblog_after) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CLIENT_MSG: 'ERROR WHILE CONNECTING TO DATABASE:\\N- SQLCODE: -902\\N- ERROR OCCURRED DURING LOGIN, PLEASE CHECK SERVER FIREBIRD.LOG FOR DETAILS' + CLIENT_MSG: -902 + CLIENT_MSG: 335545106L + FIREBIRD.LOG: + AUTHENTICATION ERROR + FIREBIRD.LOG: + FILE FIREBIRD.MSG IS NOT A VALID DATABASE + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4964_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4970.py b/tests/bugs/test_core_4970.py new file mode 100644 index 00000000..13569512 --- /dev/null +++ b/tests/bugs/test_core_4970.py @@ -0,0 +1,110 @@ +#coding:utf-8 +# +# id: bugs.core_4970 +# title: Table trigger does not see its mode: inserting or updating or deleting +# decription: +# tracker_id: CORE-4970 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + create or alter view v_chk as select 1 id from rdb$database; + recreate sequence g; + + recreate table test( id int, x int ); + recreate table tlog( + id int generated by default as identity + ,expected_mode_in_before_trg varchar(20) + ,expected_mode_in_after_trg varchar(20) + ,actual_mode_in_before_trg varchar(20) + ,actual_mode_in_after_trg varchar(20) + ); + commit; + + create or alter view v_chk as + select * from tlog + order by id; + commit; + + set term ^; + create or alter trigger test_biud for test active before insert or update or delete + as + begin + update tlog set actual_mode_in_before_trg = trim( iif(inserting,'INSERTING', iif(updating,'UPDATING', iif(deleting, 'DELETING', '??? NULL ???'))) ) + where actual_mode_in_before_trg is null + rows 1; + end + ^ + + create or alter trigger test_aiud for test active after insert or update or delete + as + begin + update tlog set actual_mode_in_after_trg = trim( iif(inserting,'INSERTING', iif(updating,'UPDATING', iif(deleting, 'DELETING', '??? NULL ???'))) ) + where actual_mode_in_after_trg is null + rows 1; + end + ^ + set term ;^ + commit; + + insert into tlog(expected_mode_in_before_trg, expected_mode_in_after_trg) values ('INSERTING', 'INSERTING'); + insert into test default values; + + insert into tlog(expected_mode_in_before_trg, expected_mode_in_after_trg) values ('UPDATING', 'UPDATING'); + update test set id = -id; + + insert into tlog(expected_mode_in_before_trg, expected_mode_in_after_trg) values ('DELETING', 'DELETING'); + delete from test; + + select * from v_chk; + + rollback; + + drop table test; + drop view v_chk; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + EXPECTED_MODE_IN_BEFORE_TRG INSERTING + EXPECTED_MODE_IN_AFTER_TRG INSERTING + ACTUAL_MODE_IN_BEFORE_TRG INSERTING + ACTUAL_MODE_IN_AFTER_TRG INSERTING + + ID 2 + EXPECTED_MODE_IN_BEFORE_TRG UPDATING + EXPECTED_MODE_IN_AFTER_TRG UPDATING + ACTUAL_MODE_IN_BEFORE_TRG UPDATING + ACTUAL_MODE_IN_AFTER_TRG UPDATING + + ID 3 + EXPECTED_MODE_IN_BEFORE_TRG DELETING + EXPECTED_MODE_IN_AFTER_TRG DELETING + ACTUAL_MODE_IN_BEFORE_TRG DELETING + ACTUAL_MODE_IN_AFTER_TRG DELETING + """ + +@pytest.mark.version('>=3.0') +def test_core_4970_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4977.py b/tests/bugs/test_core_4977.py new file mode 100644 index 00000000..36637a75 --- /dev/null +++ b/tests/bugs/test_core_4977.py @@ -0,0 +1,115 @@ +#coding:utf-8 +# +# id: bugs.core_4977 +# title: Detach using Linux client takes much longer than from Windows +# decription: +# # *** NOTE *** +# # We measure APPROXIMATE time that is required for detaching from database by evaluating number of seconds that passed +# # from UNIX standard epoch time inside ISQL and writing it to log. After returning control from ISQL we evaluate again +# # that number by calling Python 'time.time()' - and it will return value upto current UTC time, i.e. it WILL take in +# # account local timezone from OS settings (this is so at least on Windows). Thus we have to add/substract time shift +# # between UTC and local time - this is done by 'time.timezone' summand. +# # On PC-host with CPU 3.0 GHz and 2Gb RAM) in almost all cases difference was less than 1000 ms, so it was decided +# # to set threshold = 1200 ms. +# # Tested on WI-V3.0.0.32140 (SS/SC/CC). +# ########################################################################## +# # Test on LINUX was not done yet, so I've assign platform = 'Windows' yet. +# ########################################################################## +# Results for 22.05.2017: +# fb30Cs, build 3.0.3.32725: OK, 1.796ss. +# fb30SC, build 3.0.3.32725: OK, 1.047ss. +# FB30SS, build 3.0.3.32725: OK, 0.937ss. +# FB40CS, build 4.0.0.645: OK, 2.032ss. +# FB40SC, build 4.0.0.645: OK, 1.188ss. +# FB40SS, build 4.0.0.645: OK, 1.157ss. +# +# +# tracker_id: CORE-4977 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import time +# db_conn.close() +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# sqltxt=''' +# set list on; +# select datediff(second from timestamp '01.01.1970 00:00:00.000' to current_timestamp) as " " +# from rdb$types rows 1; +# ''' +# +# f_isql_cmd=open( os.path.join(context['temp_directory'],'tmp_4977.sql'), 'w') +# f_isql_cmd.write(sqltxt) +# f_isql_cmd.close() +# +# ms_before_detach=0 +# +# f_isql_log = open( os.path.join(context['temp_directory'],'tmp_4977.log'), 'w') +# f_isql_err = open( os.path.join(context['temp_directory'],'tmp_4977.err'), 'w') +# +# subprocess.call( ["isql", dsn, "-i", f_isql_cmd.name ], +# stdout = f_isql_log, +# stderr = f_isql_err +# ) +# f_isql_log.close() +# f_isql_err.close() +# +# with open( f_isql_log.name,'r') as f: +# for line in f: +# # ::: NB ::: do NOT remove "and line.split()[0].isdigit()" if decide to replace subprocess.call() +# # with pipe-way like: runProgram('isql',[dsn,'-q','-o',sqllog.name], sqltxt) !! +# # String like: 'Database ....' does appear first in log instead of result! +# if line.split() and line.split()[0].isdigit(): +# ms_before_detach=int( line.split()[0] ) +# +# detach_during_ms = int( (time.time() - ms_before_detach - time.timezone) * 1000 ) +# +# ############################################ +# ### d e f i n e t h r e s h o l d ### +# ############################################ +# threshold=1200 +# +# if detach_during_ms < threshold: +# print('Detach performed fast enough: less than threshold.') +# else: +# print('Detach lasted too long time: %s ms, threshold is %s ms' % (detach_during_ms, threshold) ) +# +# f_list=(f_isql_log, f_isql_err, f_isql_cmd) +# for i in range(len(f_list)): +# if os.path.isfile(f_list[i].name): +# os.remove(f_list[i].name) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Detach performed fast enough: less than threshold. + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_4977_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_4980.py b/tests/bugs/test_core_4980.py new file mode 100644 index 00000000..7ae5a490 --- /dev/null +++ b/tests/bugs/test_core_4980.py @@ -0,0 +1,136 @@ +#coding:utf-8 +# +# id: bugs.core_4980 +# title: Operator REVOKE can modify rights granted to system tables at DB creation time +# decription: +# We create here NON-privileged user and revoke any right from him. Also create trivial table TEST. +# Then try to connect with as user and query non-system table TEST and system tables. +# Query to table TEST should be denied, but queries to RDB-tables should run OK and display their data. +# +# tracker_id: CORE-4980 +# min_versions: ['3.0'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set wng off; + create or alter user tmp_c4980 password '123'; + commit; + + recreate table test(id int); + commit; + insert into test values(1); + commit; + + revoke all on all from tmp_c4980; + revoke all on all from public; + 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; + + 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; + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + drop user tmp_c4980; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE TEST + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_core_4980_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set wng off; + create or alter user tmp_c4980 password '123'; + commit; + + recreate table test(id int); + commit; + insert into test values(1); + commit; + + revoke all on all from tmp_c4980; + revoke all on all from public; + commit; + + connect '$(DSN)' user tmp_c4980 password '123'; + + 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; + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + drop user tmp_c4980; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + 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 + """ +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_core_4980_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_expected_stderr == act_2.clean_stderr + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/bugs/test_core_4984.py b/tests/bugs/test_core_4984.py new file mode 100644 index 00000000..8ce7a5cf --- /dev/null +++ b/tests/bugs/test_core_4984.py @@ -0,0 +1,121 @@ +#coding:utf-8 +# +# id: bugs.core_4984 +# title: Ordering by compound index together with a range condition gives wrong results +# decription: +# tracker_id: CORE-4984 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Confirmed on WI-V3.0.0.32081: wrong output for CHECKED_RESULT_1, CHECKED_RESULT_3 & CHECKED_RESULT_4 + -- (but this was only for ASC index; for DESC index all was fine). + -- Since WI-V3.0.0.32137 result is correct. + + recreate table test_idx( + id integer not null, + val integer, + create_date date, + primary key (id) + ); + commit; + + insert into test_idx values(1,1,'2016-01-01'); + insert into test_idx values(2,1,'2015-01-02'); + insert into test_idx values(3,2,'1999-09-09'); + insert into test_idx values(4,2,'2015-02-02'); + insert into test_idx values(5,3,'2015-03-01'); + insert into test_idx values(6,3,'2015-03-02'); + insert into test_idx values(7,4,'2015-04-01'); + commit; + + set list on; + + select 'natural_scan' as msg, cast(min(create_date) as date) as expected_result from test_idx where val >=1 and val <=3; + commit; + + create index idx_val_create_date_asc on test_idx (val, create_date); + commit; + + select 'index_scan_ascending' as msg, cast(min(create_date) as date) as checked_result_1 + from test_idx where val >=1 and val <=3; + select 'index_scan_ascending' as msg, cast(min(create_date) as date) as checked_result_2 + from (select * from test_idx where val > 0 and val < 4 order by val); + select 'index_scan_ascending' as msg, cast(min(create_date) as date) as checked_result_3 + from test_idx where 4 > val and 0 < val; + select 'index_scan_ascending' as msg, cast(min(create_date) as date) as checked_result_4 + from test_idx where val between 1 and 3; + select 'index_scan_ascending' as msg, cast(min(create_date) as date) as checked_result_5 + from test_idx where val in (1,2,3); + commit; + + drop index idx_val_create_date_asc; + commit; + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + + create descending index idx_val_create_date_desc on test_idx (val, create_date); + commit; + + select 'index_scan_descending' as msg, cast(min(create_date) as date) as checked_result_1 + from test_idx where val >=1 and val <=3; + select 'index_scan_descending' as msg, cast(min(create_date) as date) as checked_result_2 + from (select * from test_idx where val > 0 and val < 4 order by val desc); + select 'index_scan_descending' as msg, cast(min(create_date) as date) as checked_result_3 + from test_idx where 4 > val and 0 < val; + select 'index_scan_descending' as msg, cast(min(create_date) as date) as checked_result_4 + from test_idx where val between 1 and 3; + select 'index_scan_descending' as msg, cast(min(create_date) as date) as checked_result_5 + from test_idx where val in (1,2,3); + + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG natural_scan + EXPECTED_RESULT 1999-09-09 + + MSG index_scan_ascending + CHECKED_RESULT_1 1999-09-09 + MSG index_scan_ascending + CHECKED_RESULT_2 1999-09-09 + MSG index_scan_ascending + CHECKED_RESULT_3 1999-09-09 + MSG index_scan_ascending + CHECKED_RESULT_4 1999-09-09 + MSG index_scan_ascending + CHECKED_RESULT_5 1999-09-09 + + MSG index_scan_descending + CHECKED_RESULT_1 1999-09-09 + MSG index_scan_descending + CHECKED_RESULT_2 1999-09-09 + MSG index_scan_descending + CHECKED_RESULT_3 1999-09-09 + MSG index_scan_descending + CHECKED_RESULT_4 1999-09-09 + MSG index_scan_descending + CHECKED_RESULT_5 1999-09-09 + """ + +@pytest.mark.version('>=3.0') +def test_core_4984_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4985.py b/tests/bugs/test_core_4985.py new file mode 100644 index 00000000..241c33c3 --- /dev/null +++ b/tests/bugs/test_core_4985.py @@ -0,0 +1,74 @@ +#coding:utf-8 +# +# id: bugs.core_4985 +# title: Non-privileged user can implicitly count records in a restricted table +# decription: +# tracker_id: CORE-4985 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Checked on build of 24.03.2016 4.0 Unstable. + + set wng off; + create or alter user TMP$C4985 password '123'; + create table test(id int); + set count on; + insert into test select 1 from rdb$types rows 7; + commit; + revoke all on all from TMP$C4985; + commit; + + connect '$(DSN)' user 'TMP$C4985' password '123'; + + set list on; + select current_user as who_am_i from rdb$database; + select count(*) from test; + set count on; + select 1 from test; + + commit; + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + + drop user TMP$C4985; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 7 + WHO_AM_I TMP$C4985 + Records affected: 1 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE TEST + -Effective user is TMP$C4985 + + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE TEST + -Effective user is TMP$C4985 + """ + +@pytest.mark.version('>=4.0') +def test_core_4985_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_4998.py b/tests/bugs/test_core_4998.py new file mode 100644 index 00000000..d5bbcd32 --- /dev/null +++ b/tests/bugs/test_core_4998.py @@ -0,0 +1,239 @@ +#coding:utf-8 +# +# id: bugs.core_4998 +# title: Both client and server could not close connection after failed authentification +# decription: +# Reproduced on 3.0.0.32136 RC1 with firebird.conf: +# AuthServer = Legacy_Auth,Srp +# AuthClient = Srp,Legacy_Auth +# ::: NB-1 ::: +# In order to get this environment for client test temp-ly CHANGES firebird.conf +# Test will restore original firebird.conf in the end. +# +# ::: NB-2 ::: +# We have to prepare auxiliary Python script to be executed in SEPARATE (NEW!) execution context, +# otherwise firebird.log is filled with messages "errno = 10054" only after this test completely finished. +# See variable 'f_python_separate_exec_context' - it points to this temp .py file. +# This aux Python script is called like this: +# os.system( f_python_separate_exec_context ) +# +# It contains three attempts to make connection with invalid passwords. +# Exceptions ('Your user/password not defined...') are suppressed, we need only make these attempts to check +# that no new records withh be added to firebird.log (as it is confirmed to be in 3.0.0.32136 RC1). +# +# File firebird.log is compared BEFORE and AFTER os.system( f_python_separate_exec_context ). +# No new messages related to 10054 error should occur during this test in firebird.log. +# +# 3.0.0.32366 RC2 - works OK. +# +# Also checked on: +# 30Cs, build 3.0.4.32972: OK, 6.172s. +# 30SS, build 3.0.4.32972: OK, 4.375s. +# 40CS, build 4.0.0.955: OK, 7.281s. +# 40SS, build 4.0.0.977: OK, 4.704s. +# +# tracker_id: CORE-4998 +# min_versions: ['3.0.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import sys +# import subprocess +# import difflib +# import datetime +# import time +# import re +# import shutil +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# THIS_DSN = dsn +# DBAUSR = user_name +# db_conn.close() +# +# svc = services.connect(host='localhost') +# 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'): +# # 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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# def svc_get_fb_log( f_fb_log ): +# +# global subprocess +# +# subprocess.call( [ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# "action_get_fb_log" +# ], +# stdout=f_fb_log, stderr=subprocess.STDOUT +# ) +# return +# +# ########################################################################################### +# +# dts = datetime.datetime.now().strftime("%y%m%d_%H%M%S") +# +# fbconf = os.path.join( fb_home, 'firebird.conf') +# fbcbak = os.path.join( fb_home, 'firebird_'+dts+'.bak') +# +# shutil.copy2( fbconf, fbcbak ) +# +# f_fbconf = open(fbconf,'r') +# fbconf_content=f_fbconf.readlines() +# f_fbconf.close() +# +# for i,s in enumerate( fbconf_content ): +# if s.lower().lstrip().startswith( 'wirecrypt'.lower() ): +# fbconf_content[i] = '# ' + s +# if s.lower().lstrip().startswith( 'AuthClient'.lower() ): +# fbconf_content[i] = '# ' + s +# +# fbconf_content.append('\\n# Temporarily added by fbtest, CORE-4998. Should be removed auto:') +# fbconf_content.append("\\n#" + '='*30 ) +# fbconf_content.append('\\nAuthClient = Srp,Legacy_Auth') +# fbconf_content.append("\\n#" + '='*30 ) +# +# f_fbconf=open(fbconf,'w') +# f_fbconf.writelines( fbconf_content ) +# flush_and_close( f_fbconf ) +# +# ########################################################################################### +# +# f_fblog_before=open( os.path.join(context['temp_directory'],'tmp_4998_fblog_before.txt'), 'w') +# svc_get_fb_log( f_fblog_before ) +# flush_and_close( f_fblog_before ) +# +# other_exec_context_python_text = '''import fdb +# +# for i in range(0,3): +# con1 = None +# try: +# con1 = fdb.connect( dsn = '%(THIS_DSN)s', user = '%(DBAUSR)s', password = 'inv@l1d' + str(i) ) +# except Exception, e: +# pass +# finally: +# if con1: +# con1.close() +# exit(0) +# ''' % locals() +# +# f_python_separate_exec_context = os.path.join(context['temp_directory'], 'tmp_core_4998_try_connect_with_invalid_passwords.py') +# +# f = open( f_python_separate_exec_context, 'w') +# f.write( other_exec_context_python_text ) +# flush_and_close( f ) +# +# ######################################################################################################## +# ### l a u n c h P y t h o n i n a n o t h e r e x e c u t i o n c o n t e x t ### +# ######################################################################################################## +# +# # 17.06.2018. We have to add full path and name of interpretep (e.g. 'C:\\Python27\\python.exe') +# # because it can appear that OS will not be able to recognize how to handle .py files! +# # sys.executable - returns full path to Python exe, +# +# os.system( sys.executable + ' ' + f_python_separate_exec_context ) +# +# time.sleep(1) +# +# f_fblog_after=open( os.path.join(context['temp_directory'],'tmp_4998_fblog_after.txt'), 'w') +# svc_get_fb_log( f_fblog_after ) +# flush_and_close( f_fblog_after ) +# +# # RESTORE original config: +# ########################## +# shutil.move( fbcbak, fbconf) +# +# # Compare firebird.log versions BEFORE and AFTER this test: +# ###################### +# +# oldfb=open(f_fblog_before.name, 'r') +# newfb=open(f_fblog_after.name, 'r') +# +# difftext = ''.join(difflib.unified_diff( +# oldfb.readlines(), +# newfb.readlines() +# )) +# oldfb.close() +# newfb.close() +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_4998_diff.txt'), 'w') +# f_diff_txt.write(difftext) +# flush_and_close( f_diff_txt ) +# +# # INET/inet_error: read errno = 10054 +# +# allowed_patterns = ( +# re.compile('\\.*inet_error\\:{0,1}\\s{0,}read\\s+errno\\s{0,}\\={0,}\\s{0,}10054\\.*', re.IGNORECASE), +# ) +# +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# if line.startswith('+'): +# match2some = filter( None, [ p.search(line) for p in allowed_patterns ] ) +# if match2some: +# print( 'UNEXPECTED TEXT IN FIREBIRD.LOG: ' + (' '.join(line.split()).upper()) ) +# +# ##################################################################### +# # Cleanup: +# time.sleep(1) +# cleanup( (f_diff_txt,f_fblog_before,f_fblog_after, f_python_separate_exec_context) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_4998_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5016.py b/tests/bugs/test_core_5016.py new file mode 100644 index 00000000..92af6ee0 --- /dev/null +++ b/tests/bugs/test_core_5016.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: bugs.core_5016 +# title: Server crashes during GC when DELETE is executed after adding new referencing column +# decription: +# tracker_id: CORE-5016 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table a (x integer primary key); + create table b (x integer primary key); + insert into b values (1); + commit; + alter table b add y integer references a(x); + commit; + delete from b; + commit; + set list on; + select count(*) as k from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + K 1 + """ + +@pytest.mark.version('>=2.5') +def test_core_5016_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5018.py b/tests/bugs/test_core_5018.py new file mode 100644 index 00000000..1bb57cf4 --- /dev/null +++ b/tests/bugs/test_core_5018.py @@ -0,0 +1,134 @@ +#coding:utf-8 +# +# id: bugs.core_5018 +# title: Regression: Non-indexed predicates may not be applied immediately after retrieval when tables are being joined +# decription: +# tracker_id: CORE-5018 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='mon-stat-gathering-3_0.fbk', init=init_script_1) + +test_script_1 = """ + recreate table zf ( + id int primary key, + kont_id int not null + ); + + recreate table u ( + id int primary key, + kont_id int not null + ); + + recreate table k ( + id int primary key + ); + + commit; + + insert into zf (id, kont_id) values ('1', '1'); + insert into zf (id, kont_id) values ('2', '7'); + insert into zf (id, kont_id) values ('3', '3'); + insert into zf (id, kont_id) values ('4', '5'); + insert into zf (id, kont_id) values ('5', '5'); + insert into zf (id, kont_id) values ('6', '1'); + insert into zf (id, kont_id) values ('7', '4'); + insert into zf (id, kont_id) values ('8', '2'); + insert into zf (id, kont_id) values ('9', '9'); + insert into zf (id, kont_id) values ('10', '1'); + + + insert into k (id) values ('1'); + insert into k (id) values ('2'); + insert into k (id) values ('3'); + insert into k (id) values ('4'); + insert into k (id) values ('5'); + insert into k (id) values ('6'); + insert into k (id) values ('7'); + insert into k (id) values ('8'); + insert into k (id) values ('9'); + insert into k (id) values ('10'); + + insert into u (id, kont_id) values ('1', '4'); + insert into u (id, kont_id) values ('2', '6'); + insert into u (id, kont_id) values ('3', '3'); + insert into u (id, kont_id) values ('4', '2'); + insert into u (id, kont_id) values ('5', '5'); + insert into u (id, kont_id) values ('6', '2'); + insert into u (id, kont_id) values ('7', '9'); + insert into u (id, kont_id) values ('8', '2'); + insert into u (id, kont_id) values ('9', '10'); + insert into u (id, kont_id) values ('10', '1'); + + commit; + + execute procedure sp_truncate_stat; + commit; + execute procedure sp_gather_stat; + commit; + + set term ^; + execute block as + declare c int; + begin + select count(*) + from zf + inner join u on zf.id=u.id + left join k kzf on zf.kont_id=kzf.id + left join k kum on u.kont_id=kum.id + where zf.kont_id<>u.kont_id + into c; + + if ( rdb$get_context('SYSTEM','ENGINE_VERSION') starting with '4.0' ) then + rdb$set_context('USER_SESSION', 'MAX_IDX_READS', '45'); -- 27.07.2016 + else + rdb$set_context('USER_SESSION', 'MAX_IDX_READS', '30'); + -- ^ + -- | + -- ### T H R E S H O L D ###-------+ + end + ^ + set term ;^ + + execute procedure sp_gather_stat; + commit; + + set list on; + select iif( indexed_reads <= c_max_idx_reads, + 'ACCEPTABLE', + 'FAILED, TOO BIG: ' || indexed_reads || ' > ' || c_max_idx_reads + ) as idx_reads_estimation + from ( + select indexed_reads, cast(rdb$get_context('USER_SESSION', 'MAX_IDX_READS') as int) as c_max_idx_reads + from v_agg_stat_main + ); + -- WI-V2.5.5.26952 IR=22 + -- WI-V3.0.0.32140 IR=33 + -- WI-V3.0.0.32179 IR=25 + -- WI-T4.0.0.313: IR=39 + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + IDX_READS_ESTIMATION ACCEPTABLE + """ + +@pytest.mark.version('>=3.0') +def test_core_5018_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5020.py b/tests/bugs/test_core_5020.py new file mode 100644 index 00000000..7684023c --- /dev/null +++ b/tests/bugs/test_core_5020.py @@ -0,0 +1,109 @@ +#coding:utf-8 +# +# id: bugs.core_5020 +# title: Regression: ORDER BY clause on compound index may disable usage of other indices +# decription: +# tracker_id: CORE-5020 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table zf( + id integer not null primary key, + kont_id integer not null + ); + + recreate table u( + id integer not null primary key, + kont_id integer not null + ); + + recreate table k( + id integer not null primary key + ); + + commit; + + insert into zf (id, kont_id) values ('1', '1'); + insert into zf (id, kont_id) values ('2', '7'); + insert into zf (id, kont_id) values ('3', '3'); + insert into zf (id, kont_id) values ('4', '5'); + insert into zf (id, kont_id) values ('5', '5'); + insert into zf (id, kont_id) values ('6', '1'); + insert into zf (id, kont_id) values ('7', '4'); + insert into zf (id, kont_id) values ('8', '2'); + insert into zf (id, kont_id) values ('9', '9'); + insert into zf (id, kont_id) values ('10', '1'); + + + insert into k (id) values ('1'); + insert into k (id) values ('2'); + insert into k (id) values ('3'); + insert into k (id) values ('4'); + insert into k (id) values ('5'); + insert into k (id) values ('6'); + insert into k (id) values ('7'); + insert into k (id) values ('8'); + insert into k (id) values ('9'); + insert into k (id) values ('10'); + + insert into u (id, kont_id) values ('1', '4'); + insert into u (id, kont_id) values ('2', '6'); + insert into u (id, kont_id) values ('3', '3'); + insert into u (id, kont_id) values ('4', '2'); + insert into u (id, kont_id) values ('5', '5'); + insert into u (id, kont_id) values ('6', '2'); + insert into u (id, kont_id) values ('7', '9'); + insert into u (id, kont_id) values ('8', '2'); + insert into u (id, kont_id) values ('9', '10'); + insert into u (id, kont_id) values ('10', '1'); + + commit; + + alter table zf add constraint fk_zf__k + foreign key(kont_id) + references k(id) + using index fk_zf__k + ; + set statistics index fk_zf__k; + + 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. + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (ZF ORDER IXA_FK__ID__KONT_ID INDEX (FK_ZF__K)) + """ + +@pytest.mark.version('>=2.5') +def test_core_5020_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5028.py b/tests/bugs/test_core_5028.py new file mode 100644 index 00000000..f4acf4fb --- /dev/null +++ b/tests/bugs/test_core_5028.py @@ -0,0 +1,58 @@ +#coding:utf-8 +# +# id: bugs.core_5028 +# title: Report the remote port number in MON$ATTACHMENTS +# decription: +# +# tracker_id: CORE-5028 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# cur=db_conn.cursor() +# sqlcmd=''' +# select iif(port > 0, 'OK', 'BAD') as port_value +# from ( +# select cast(substring(mon$remote_address from 1 + position('/' in mon$remote_address)) as int) as port +# from mon$attachments +# where mon$attachment_id = current_connection +# ) +# ''' +# +# # On previous FB versions will raise exception: +# # Statement failed, SQLSTATE = 22018 +# # conversion error from string "192.168.43.154" +# +# cur.execute(sqlcmd) +# for r in cur: +# print(r[0]) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + OK + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_5028_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5034.py b/tests/bugs/test_core_5034.py new file mode 100644 index 00000000..db95e58d --- /dev/null +++ b/tests/bugs/test_core_5034.py @@ -0,0 +1,466 @@ +#coding:utf-8 +# +# id: bugs.core_5034 +# title: At least 5 seconds delay on disconnect could happen if disconnect happens close after Event Manager initialization +# decription: +# This test uses Python multiprocessing package in order to spawn multiple processes with trivial job: attach/detach from DB. +# Number processes ('planned_attachments') and of iterations for each of them ('reconnect_count') depends on FB architecture +# which is obtained by call of SP sys_get_fb_arch. +# For ClassicServer weird effect was detected: when number of processes is more then ~34-35 some of Python processes may not +# finish (but CS processes are gone and thus database has no attachments). +# Database is created with DB_level trigger 'on disconnect' which issues post_event and writes 'now'-timestamp to the table. +# Because we have dozen of different running processes, one need to distinguish records in the table for every of attachments. +# But values of current_connection are not suitable: they are unknown outside of DB connection, i.e. at the moment when we +# just return from DB attachment we still need to know some number that was 'linked' to just finished connection process. +# For this purpose ROLES are used in this test: we generate them beforehand (see 'init_test' section) and when create new +# attachment then specify ROLE in its arguments: 'R_000' for 1st spawned python process, 'R_001' for 2nd etc. +# Value of current_role will be written by DB-trigger in the table LOG4DETACH. +# When attachment finishes and control is returned to Python child process, we catch current timestamp again and save it +# value inside Python data structure 'sqllst' - common list. +# After some process will finish iterations, it will build SQL script for further applying to database and save it to the file +# with name that reflects to this process: 'tmp_5034_after_detach_NNN.log' whene NNN = '000', '001' etc. +# This file will contain INSERT command with values of timestamp that were on every iteration just after disconnect. +# After all processes will finish, we'll have completed set of such files and they will be "concatenated" together for applying +# at once by single call of ISQL. +# Finally, we can analyze values of datediff() between moments of 'just before' and 'just after' disconnects. +# In order to properly detect records that correspond to post-apply scripts (with INSERT statements) special integer field 'SEQ' +# is used: it will have even values for event when we are 'just before detach' (i.e. "inside" database connection) and odd values +# when we are 'just after' (i.e. when connection has been just closed). The view 'v_top10_slow' is used to display connects which +# were closed too slow. +# Normally, this view should return ONE record with text 'Detaches were fast'. +# Otherwise it will return concrete values of time that was spent on detach process, in milliseconds. +# ####################### +# ### A C H T U N G ### +# ####################### +# Following parameters: 'planned_attachments' and 'reconnect_count' affects on test result **VERY** strong, especially on Classic. +# You may need to change them if test results are unstable. Do NOT make value of 'planned_attachments' more than 33-34 on Classic! +# +# Successfully checked on build 32276, SS/SC/CS. +# Confirmed error on WI-V3.0.0.32134, Cs: "MonitoringData: Cannot initialize the shared memory region / sh_mem_length_mapped is 0" +# +# 23.11.2016 +# Increased threshold to 6000 ms instead of old 5000 ms -- see +# http://web.firebirdsql.org/download/prerelease/results/archive/3.0.2.32630/bugs.core_5034.html +# +# tracker_id: CORE-5034 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + set bail on; + + create or alter user tmp$c5034 password '123'; + commit; + create or alter view v_top10_slow as select 1 x from rdb$database; + commit; + + + set term ^; + create or alter trigger trg_disc active on disconnect position 0 as + begin + end + ^ + + create or alter procedure sys_get_fb_arch ( + a_connect_with_usr varchar(31) default 'SYSDBA' + ,a_connect_with_pwd varchar(31) default 'masterkey' + ) returns( + fb_arch varchar(50) + ) as + declare cur_server_pid int; + declare ext_server_pid int; + declare att_protocol varchar(255); + declare v_test_sttm varchar(255); + declare v_fetches_beg bigint; + declare v_fetches_end bigint; + begin + + -- Aux SP for detect FB architecture. + + select a.mon$server_pid, a.mon$remote_protocol + from mon$attachments a + where a.mon$attachment_id = current_connection + into cur_server_pid, att_protocol; + + if ( att_protocol is null ) then + fb_arch = 'Embedded'; + else if ( upper(current_user) = upper('SYSDBA') + and rdb$get_context('SYSTEM','ENGINE_VERSION') NOT starting with '2.5' + and exists(select * from mon$attachments a + where a.mon$remote_protocol is null + and upper(a.mon$user) in ( upper('Cache Writer'), upper('Garbage Collector')) + ) + ) then + fb_arch = 'SuperServer'; + else + begin + v_test_sttm = + 'select a.mon$server_pid + 0*(select 1 from rdb$database)' + ||' from mon$attachments a ' + ||' where a.mon$attachment_id = current_connection'; + + select i.mon$page_fetches + from mon$io_stats i + where i.mon$stat_group = 0 -- db_level + into v_fetches_beg; + + execute statement v_test_sttm + on external + 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME') + as + user a_connect_with_usr + password a_connect_with_pwd + role left('R' || replace(uuid_to_char(gen_uuid()),'-',''),31) + into ext_server_pid; + + in autonomous transaction do + select i.mon$page_fetches + from mon$io_stats i + where i.mon$stat_group = 0 -- db_level + into v_fetches_end; + + fb_arch = iif( cur_server_pid is distinct from ext_server_pid, + 'Classic', + iif( v_fetches_beg is not distinct from v_fetches_end, + 'SuperClassic', + 'SuperServer' + ) + ); + end + + fb_arch = fb_arch || ' ' || rdb$get_context('SYSTEM','ENGINE_VERSION'); + + suspend; + + end + + ^ -- sys_get_fb_arch + set term ;^ + commit; + + recreate table log4detach( + id int generated by default as identity constraint pk_log4detach primary key using index pk_log4detach + ,rno varchar(31) default current_role -- for worker #0 --> 'R_000', #1 --> 'R_001' etc + ,dts timestamp default 'now' + ,seq int + ,who varchar(31) default current_user + ); + commit; + + set term ^; + execute block as + declare v_stt varchar(128); + declare i smallint; + declare n smallint = 500; + begin + + rdb$set_context('USER_SESSION','INITIAL_DDL','1'); + i=0; + while ( i < n) do + begin + v_stt = 'drop role R_' || lpad(i, 3, '0'); + begin + execute statement v_stt; + when any do begin end + end + + v_stt = 'create role R_' || lpad(i, 3, '0'); + execute statement v_stt; + + v_stt = 'grant R_' || lpad(i, 3, '0') || ' to tmp$c5034'; + execute statement v_stt; + + i = i + 1; + end + + end + ^ + + create or alter trigger trg_disc active on disconnect position 0 as + begin + + POST_EVENT 'FOO'; + + if ( current_user = 'TMP$C5034' and rdb$get_context('USER_SESSION','INITIAL_DDL') is null ) + then + in autonomous transaction do + insert into log4detach default values; + end + ^ + set term ;^ + commit; + + create or alter view v_top10_slow as + select distinct msg + from + ( + select iif( detach_ms > max_detach_ms, + 'Slow detaches > '|| max_detach_ms ||' ms detected: ' || detach_ms || ' ms, from ' || dts_before_detach || ' to '||dts_after_detach, + 'All detaches not exceeded threshold' + ) as msg + from ( + select + rno + ,datediff(millisecond from min(t0) to min(t1)) as detach_ms + ,min(t0) as dts_before_detach + ,min(t1) as dts_after_detach + ,6000 as max_detach_ms -- changed 23.11.2016; was: 5000 + -- ^ + -- | + -- ############################## + -- # t h r e s h o l d, ms # + -- ############################## + from ( + select + rno,dts + ,iif(mod(seq,2)=0, seq, seq-1) seq2 + ,iif( mod(seq,2)=0, dts, null) t0 + ,iif( mod(seq,2)=1, dts, null) t1 + from ( + select rno, dts + ,seq + from log4detach d + where rno starting with 'R_' + order by rno,seq + ) + ) + group by rno, seq2 + ) + where detach_ms >= 0 + order by detach_ms desc + rows 10 + ); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import fdb +# import time +# import subprocess +# from multiprocessing import Process +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # Get FB architecture: +# xcur=db_conn.cursor() +# xcur.execute("select fb_arch from sys_get_fb_arch;") +# +# for r in xcur: +# fb_arch = r[0].split()[0] +# +# dbfile=db_conn.database_name +# db_conn.close() +# +# ISQL_BINARY = context['isql_path'] +# svc = services.connect(host='localhost') +# FB_HOME = os.path.normpath( svc.get_home_directory() ) # 'c: +# irebird' --> 'c: +# irebird' (i.e. remove trailing backslash if needed) +# svc.close() +# +# if os.name == 'nt': +# # For Windows we assume that client library is always in FB_HOME dir: +# FB_CLNT=os.path.join(FB_HOME, 'fbclient.dll') +# else: +# # For Linux client library will be searched in 'lib' subdirectory of FB_HOME: +# # con=fdb.connect( dsn='localhost:employee', user='SYSDBA', password='masterkey', fb_library_name='/var/tmp/fb40tmp/lib/libfbclient.so') +# FB_CLNT=os.path.join(FB_HOME, 'lib', 'libfbclient.so' ) +# +# FBT_TEMP_DIR = os.path.normpath(context['temp_directory']) +# +# #-------------------------------------------- +# +# 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'): +# # 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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# if fb_arch=='Classic': +# # {20,20}=72"; {32,10}=52" - but can hang!; {30,8)=46"; {30,15}=93"; {33,10}=91"; {35,5}=no-return-from-python! +# planned_attachments=30 +# reconnect_count=8 +# elif fb_arch=='SuperClassic': +# # {20,5}=21"; {30,20}=45"; {50,20}=70" +# planned_attachments=40 +# reconnect_count=20 +# else: +# # SS: {30,10}=35"; {50,20}=54"; {40,30}=57"; {75,30}=70"; {80,10}=42" +# planned_attachments=80 +# reconnect_count=10 +# +# +# subprocess.check_output([ context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", +# "prp_write_mode", "prp_wm_async", +# "dbname", dbfile ], stderr=subprocess.STDOUT) +# +# # GENERATE CODE FOR EXECUTING IN SEPARATE EXECUTABLE PYTHON CONTEXT +# ################################################################### +# +# f_parallel_txt='''import os +# import fdb +# import time +# import datetime +# from datetime import datetime +# import subprocess +# from subprocess import Popen +# from multiprocessing import Process +# +# def attach_detach(a_dsn, a_fb_client, v_temp_dir, reconnect_count, process_seq): +# f_detach_info_sql = open( os.path.join(v_temp_dir, 'tmp_5034_after_detach_' + str(process_seq).zfill(3) + '.log'), 'w') +# v_role = 'R_'+str(process_seq).zfill(3) +# v_sqllst = [] +# +# for i in range(0,reconnect_count): +# v_seq = 100000 + (1+process_seq) * 1000 + 2*i +# +# att = fdb.connect( dsn = a_dsn, fb_library_name = a_fb_client, user='TMP$C5034', password='123',role = v_role ) +# +# # Trigger 'trg_disc' will add row to LOG4DETACH table. +# # Column RNO will have value = 'R_nnnn' (for worker #0 --> 'R_000', #1 --> 'R_001' etc), +# # i.e. it will be NOT null for the timestamp when we are DISCONNECTED to database: +# att.close() +# +# v_seq = v_seq + 1 +# +# # Catch current timestamp (we just retuirned from DB connect) and store it in the list: +# v_sqllst.append( "insert into log4detach(dts, rno, seq) values( '%%s', '%%s', %%s ); " %% ( datetime.strftime(datetime.now(), '%%Y-%%m-%%d %%H:%%M:%%S.%%f')[:23], v_role, v_seq ) ) +# +# # Current worker COMPLETED iterations of connect/disconnect, +# # now we can save timestamps that was stores in the list just after each detach +# # to the text file for further executing it by ISQL: +# f_detach_info_sql.write("\\\\n".join(v_sqllst)) +# f_detach_info_sql.write( '\\\\n' ) +# +# merge_sql="merge into log4detach t using ( select id, %%s + 2 * (row_number()over(order by id)-1) seq from log4detach d where rno='%%s' and seq is null ) s on (s.id = t.id) when matched then update set t.seq = s.seq;" %% ( 100000 + (1+process_seq) * 1000, v_role ) +# +# f_detach_info_sql.write( ' '.join(merge_sql.split()).lstrip() ) +# f_detach_info_sql.write( '\\\\n' ) +# f_detach_info_sql.write( 'commit;' ) +# f_detach_info_sql.close() +# +# planned_attachments = %(planned_attachments)s +# +# if __name__ == '__main__': +# p_list=[] +# v_fb_home = r'%(FB_HOME)s' +# v_temp_dir = r'%(FBT_TEMP_DIR)s' +# v_dsn = r'%(dsn)s' +# v_fb_client = r'%(FB_CLNT)s' +# +# for i in range(0, planned_attachments): +# # Python multi-processing feature: +# ################################## +# p_i = Process(target=attach_detach, args=( v_dsn, v_fb_client, v_temp_dir, %(reconnect_count)s, i, )) +# p_i.start() +# p_list.append(p_i) +# +# for i in range(len(p_list)): +# p_list[i].join() +# +# # All completed +# +# f_detach_info_sql = open( os.path.join(v_temp_dir, 'tmp_5034_after_detach_all.sql'), 'w') +# for i in range(len(p_list)): +# f_detach_log_i = os.path.join(v_temp_dir, 'tmp_5034_after_detach_' + str(i).zfill(3) + '.log') +# with open(f_detach_log_i, 'r') as s: +# f_detach_info_sql.write(s.read()+'\\\\n\\\\n\\\\n') +# os.remove(f_detach_log_i) +# +# f_detach_info_sql.flush() +# os.fsync(f_detach_info_sql.fileno()) +# f_detach_info_sql.close() +# +# # subprocess.call( [ os.path.join( v_fb_home, 'isql'), v_dsn, '-user', '%(user_name)s', '-password', '%(user_password)s', '-nod', '-n', '-i', f_detach_info_sql.name] ) +# subprocess.call( [ r'%(ISQL_BINARY)s', v_dsn, '-user', '%(user_name)s', '-password', '%(user_password)s', '-nod', '-n', '-i', f_detach_info_sql.name] ) +# +# os.remove(f_detach_info_sql.name) +# ''' % dict(globals(), **locals()) +# # (context['temp_directory'].replace('\\\\','\\\\\\\\'), planned_attachments, dsn, reconnect_count, dsn) +# +# f_parallel_py=open( os.path.join(context['temp_directory'],'tmp_5034_after_detach.py'), 'w') +# f_parallel_py.write(f_parallel_txt) +# flush_and_close( f_parallel_py ) +# +# ######################################################################################################## +# ### l a u n c h P y t h o n i n a n o t h e r e x e c u t i o n c o n t e x t ### +# ######################################################################################################## +# runProgram( sys.executable, [f_parallel_py.name] ) +# +# time.sleep(2) +# +# f_top_slow_sql=open( os.path.join(context['temp_directory'], 'tmp_5034_slowest_detaches.sql'), 'w') +# f_top_slow_sql.write('drop user tmp$c5034; commit; set count on; set heading off; select * from v_top10_slow; commit;') +# flush_and_close( f_top_slow_sql ) +# +# f_top_slow_log=open( os.path.join(context['temp_directory'], 'tmp_5034_slowest_detaches.log'), 'w') +# subprocess.call( [ context['isql_path'], dsn, "-nod", "-n", "-i", f_top_slow_sql.name], stdout=f_top_slow_log, stderr=subprocess.STDOUT) +# flush_and_close( f_top_slow_log ) +# +# time.sleep(1) +# +# with open(f_top_slow_log.name) as f: +# print(f.read()) +# +# # Cleanup. +# ######### +# time.sleep(1) +# cleanup( (f_top_slow_sql,f_top_slow_log,f_parallel_py,f_parallel_py.name+'c') ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + All detaches not exceeded threshold + Records affected: 1 + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_5034_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5039.py b/tests/bugs/test_core_5039.py new file mode 100644 index 00000000..bb0ed93c --- /dev/null +++ b/tests/bugs/test_core_5039.py @@ -0,0 +1,72 @@ +#coding:utf-8 +# +# id: bugs.core_5039 +# title: Connecting to service with invalid servicename yields incorrect error message +# decription: +# 28.01.2019. +# Name of service manager is ignored in FB 4.0, see http://tracker.firebirdsql.org/browse/CORE-5883 +# ("service_mgr" to be cleaned out from connection string completely...") +# Disabled this test to be run on FB 4.0: added record to '%FBT_REPO% ests\\qa4x-exclude-list.txt'. +# Added EMPTY section for FB version 4.0 in this .fbt as one more way to protect from running. +# +# tracker_id: CORE-5039 +# min_versions: ['3.0'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# db_conn.close() +# runProgram('fbsvcmgr',['localhost:qwe_mnb_zxc_9','user','SYSDBA','password','masterkey','info_server_version']) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Cannot attach to services manager + -service qwe_mnb_zxc_9 is not defined + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_5039_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + -- This section was intentionally left empty. + -- No message should be in expected_* sections. + -- It is STRONGLY RECOMMENDED to add this ticket + -- in the 'excluded-list file: + -- %FBT_REPO% ests\\qa4x-exclude-list.txt + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + + +@pytest.mark.version('>=4.0') +def test_core_5039_2(act_2: Action): + act_2.execute() + diff --git a/tests/bugs/test_core_5049.py b/tests/bugs/test_core_5049.py new file mode 100644 index 00000000..8e1b3ac0 --- /dev/null +++ b/tests/bugs/test_core_5049.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_5049 +# title: Regression: incorrect calculation of byte-length for view columns +# decription: +# tracker_id: CORE-5049 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!sqltype).)*$', ''), ('[ ]+', ' '), ('[\t]*', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Confirmed: + -- 1) FAULT on WI-V3.0.0.32208. + -- 2) SUCCESS on LI-V3.0.0.32233, Rev: 62699. + create or alter view v_test as + select + cast(rdb$character_set_name as varchar(2000)) as test_f01 + ,cast(rdb$character_set_name as varchar(2000)) as test_f02 + ,cast(rdb$character_set_name as varchar(2000)) as test_f03 + from + rdb$database + rows 1; + + set sqlda_display on; + set list on; + select * from v_test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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_core_5049_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5060.py b/tests/bugs/test_core_5060.py new file mode 100644 index 00000000..0c8d2f94 --- /dev/null +++ b/tests/bugs/test_core_5060.py @@ -0,0 +1,121 @@ +#coding:utf-8 +# +# id: bugs.core_5060 +# title: Cannot CREATE VIEW that selects from a system table, despite having all grants +# decription: : +# Confirmed fail on WI-V3.0.0.32253: got +# create or alter view v_tmp$5060_u1 as select 1 i from rdb$database; +# Statement failed, SQLSTATE = 28000 +# unsuccessful metadata update +# -CREATE OR ALTER VIEW V_JOHN1 failed +# -no permission for SELECT access to TABLE/VIEW RDB$DATABASE +# Checked on WI-V3.0.0.32272 (SS/SC/CS). +# +# tracker_id: CORE-5060 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set wng off; + set count on; + set list on; + + create or alter user tmp$5060_u1 password '123' revoke admin role; + create or alter user tmp$5060_u2 password '456' revoke admin role; + + revoke all on all from tmp$5060_u1; + revoke all on all from tmp$5060_u2; + commit; + + set term ^; + execute block as + begin + execute statement 'drop role dba_assistant'; + when any do begin end + end + ^ + set term ;^ + commit; + + create role dba_assistant; + commit; + + grant create view to user tmp$5060_u1; + grant alter any view to user tmp$5060_u1; + grant drop any view to user tmp$5060_u1; + + grant create view to role dba_assistant; + grant alter any view to role dba_assistant; + grant drop any view to role dba_assistant; + grant dba_assistant to tmp$5060_u2; + commit; + + connect '$(DSN)' user tmp$5060_u1 password '123'; + + create or alter view v_tmp$5060_u1 as select 1 i from rdb$database; + create or alter view v_tmp$5060_u2 as select v.i as u1, r.i as u2 from v_tmp$5060_u1 v join (select 1 i from rdb$database) r using (i); + + select current_user, current_role, v.* from v_tmp$5060_u1 v; + select current_user, current_role, v.* from v_tmp$5060_u2 v; + + commit; + + connect '$(DSN)' user tmp$5060_u2 password '456' role 'DBA_ASSISTANT'; + + create or alter view v_tmp$5060_r1 as select 1 i from rdb$database; + create or alter view v_tmp$5060_r2 as select v.i as r1, r.i as r2 from v_tmp$5060_r1 v join (select 1 i from rdb$database) r using (i); + + select current_user, current_role, v.* from v_tmp$5060_r1 v; + select current_user, current_role, v.* from v_tmp$5060_r2 v; + + commit; + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + drop user tmp$5060_u1; + drop user tmp$5060_u2; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + USER TMP$5060_U1 + ROLE NONE + I 1 + Records affected: 1 + USER TMP$5060_U1 + ROLE NONE + U1 1 + U2 1 + Records affected: 1 + USER TMP$5060_U2 + ROLE DBA_ASSISTANT + I 1 + Records affected: 1 + USER TMP$5060_U2 + ROLE DBA_ASSISTANT + R1 1 + R2 1 + Records affected: 1 + """ + +@pytest.mark.version('>=3.0') +def test_core_5060_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5061.py b/tests/bugs/test_core_5061.py new file mode 100644 index 00000000..dc47c014 --- /dev/null +++ b/tests/bugs/test_core_5061.py @@ -0,0 +1,143 @@ +#coding:utf-8 +# +# id: bugs.core_5061 +# title: ISQL plan output is unexpectedly truncated after a query is simplified to become shorter +# decription: +# Start of discussion: letter to dimitr, 30-dec-2015 13:57; its subject refers to core-4708. +# It was found that explained plan produced by ISQL is unexpectedly ends on WI-V3.0.0.32256. +# This testuses that query, but instead of verifying plan text itself (which can be changed in the future) +# it is sufficient to check only that plan does NOT contain lines with ellipsis or 'truncated' or 'error'. +# This mean that 'expected_stdout' section must be EMPTY. Otherwise expected_stdout will contain info +# about error or invalid plan. +# +# tracker_id: CORE-5061 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import time +# +# sql_text=''' set list on; +# set explain on; +# set planonly; +# set blob all; +# with recursive +# r1 as ( +# select 1 as i from rdb$database +# union all +# select r.i+1 from r1 r where r.i < 2 +# ) +# --select count(*) from r1; +# +# ,r2 as ( +# select first 1 row_number() over() i +# from r1 ra +# full join r1 rb on rb.i=ra.i +# group by ra.i +# having count(*)>0 +# +# union all +# +# select rx.i+1 from r2 rx +# where rx.i+1 <= 2 +# ) +# --select count(*) from r2 +# ,r3 as ( +# select first 1 row_number() over() i +# from r2 ra +# full join r2 rb on rb.i=ra.i +# group by ra.i +# having count(*)>0 +# +# union all +# +# select rx.i+1 from r3 rx +# where rx.i+1 <= 2 +# ) +# --select count(*) from r3 +# ,r4 as ( +# select first 1 row_number() over() i +# from r3 ra +# full join r3 rb on rb.i=ra.i +# group by ra.i +# having count(*)>0 +# +# union all +# +# select rx.i+1 from r4 rx +# where rx.i+1 <= 2 +# ) +# ,rn as ( +# select row_number() over() i +# from rdb$database r full join rdb$database r2 on r2.rdb$relation_id=r.rdb$relation_id +# group by r.rdb$relation_id +# having count(*)>0 +# order by r.rdb$relation_id +# rows 1 to 1 +# ) +# select +# char_length(mon$explained_plan) +# ,(select count(*) from r4) +# ,(select count(*) from rn) +# --,(select count(*) from rn) +# from mon$statements +# ; +# ''' +# +# sqltxt=open( os.path.join(context['temp_directory'],'tmp_sql_5061.sql'), 'w') +# sqltxt.write(sql_text) +# sqltxt.close() +# +# sqllog=open( os.path.join(context['temp_directory'],'tmp_sql_5061.log'), 'w') +# subprocess.call( [ context['isql_path'], dsn,'-user',user_name,'-pas',user_password,'-q', '-i', sqltxt.name], +# stdout=sqllog, +# stderr=subprocess.STDOUT +# ) +# sqllog.close() +# +# # Check content of files: 1st shuld contain name of temply created user, 2nd should be with error during get FB log: +# +# i=0 +# with open( sqllog.name,'r') as f: +# for line in f: +# i+=1 +# if '...' in line or 'truncated' in line or 'error' in line: +# print("Plan is truncated or empty. Found at line "+str(i)) +# break +# +# # Do not remove this pause: on Windows closing of handles can take some (small) time. +# # Otherwise Windows(32) access error can raise here. +# time.sleep(1) +# +# if os.path.isfile(sqltxt.name): +# os.remove(sqltxt.name) +# if os.path.isfile(sqllog.name): +# os.remove(sqllog.name) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_5061_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5062.py b/tests/bugs/test_core_5062.py new file mode 100644 index 00000000..9d0d7277 --- /dev/null +++ b/tests/bugs/test_core_5062.py @@ -0,0 +1,70 @@ +#coding:utf-8 +# +# id: bugs.core_5062 +# 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 +# decription: +# tracker_id: CORE-5062 +# min_versions: ['2.5.6'] +# versions: 2.5.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# # ::: NB ::: Could not reproduce ticket issue on x86. +# # Checked on: WI-V2.5.4.26856, WI-V3.0.0.31948 (Python = 2.7 x86, fdb = 1.5). +# +# import fdb +# db_conn.close() +# +# sql_ddl='''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; +# ''' +# +# runProgram('isql',['-user',user_name, '-pas',user_password, dsn],sql_ddl) +# +# con2 = fdb.connect(dsn=dsn, user=user_name, password=user_password, charset='utf8') +# +# xcur2 = con2.cursor() +# psSel = xcur2.prep("select datavalue from test_uuid where uuid = char_to_uuid(?)") +# +# print ( psSel.plan ) +# xcur2.execute(psSel, [('57F2B8C7-E1D8-4B61-9086-C66D1794F2D9')]) +# for row in xcur2: +# print( row[0] ) +# +# con2.close() +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (TEST_UUID INDEX (TEST_UUID_UNQ)) + 1 + """ + +@pytest.mark.version('>=2.5.6') +@pytest.mark.xfail +def test_core_5062_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5064.py b/tests/bugs/test_core_5064.py new file mode 100644 index 00000000..e45fe04f --- /dev/null +++ b/tests/bugs/test_core_5064.py @@ -0,0 +1,80 @@ +#coding:utf-8 +# +# id: bugs.core_5064 +# title: Add datatypes (VAR)BINARY(n) and BINARY VARYING(n) as alias for (VAR)CHAR(n) CHARACTER SET OCTETS +# decription: +# +# tracker_id: CORE-5064 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test(x binary(8), y varbinary(8)); + set list on; + set sqlda_display on; + + -- Check that new datatypes can be used in SQL: + select rdb$db_key,t.* from test t; + + -- Check that new datatypes can be used in PSQL: + set term ^; + execute block returns(x binary(8), y varbinary(8)) as + begin + select rdb$db_key,rdb$db_key + from rdb$database where 1=0 + into x,y; + suspend; + end^ + set term ;^ + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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 + """ + +@pytest.mark.version('>=4.0') +def test_core_5064_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5068.py b/tests/bugs/test_core_5068.py new file mode 100644 index 00000000..fed267c8 --- /dev/null +++ b/tests/bugs/test_core_5068.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: bugs.core_5068 +# title: gbak with invalid parameter crashes FB +# decription: +# Confirmed crash on 2.5.5.26952, but only when use 'gbak' utility (with services call). +# As of fbsvcmgr, it works correct and reports error: Unknown switch "res_user_all_space". +# Output when use gbak is: +# gbak:unknown switch "USER_ALL_SPACE" +# gbak: ERROR:Unable to complete network request to host "localhost". +# gbak: ERROR: Error reading data from the connection. +# gbak:Exiting before completion due to errors +# +# Checked on WI-V2.5.6.26962 - works OK. +# No test needed for 3.0 thus only stub code present here in 'firebird_version': '3.0' section. +# +# tracker_id: CORE-5068 +# min_versions: ['2.5.5'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_5068_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5070.py b/tests/bugs/test_core_5070.py new file mode 100644 index 00000000..24af52ff --- /dev/null +++ b/tests/bugs/test_core_5070.py @@ -0,0 +1,82 @@ +#coding:utf-8 +# +# id: bugs.core_5070 +# title: Compound index cannot be used for filtering in some ORDER/GROUP BY queries +# decription: +# Execution plan is the same for all avaliable FB 3.0+ builds, since Beta1. +# For this reason min_version = 3.0.0 rather than 3.0.5 +# Checked on: +# 3.0.4.33034: OK, 2.375s. +# 3.0.5.33084: OK, 1.422s. +# 3.0.4.33053: OK, 2.469s. +# 4.0.0.1172: OK, 5.344s. +# 4.0.0.1340: OK, 2.531s. +# 4.0.0.1249: OK, 2.594s. +# +# tracker_id: CORE-5070 +# min_versions: ['3.0.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test1 ( + ia integer not null, + id integer not null, + it integer not null, + dt date not null, + constraint test1_pk_ia_id primary key (ia,id) + ); + + set plan on; + set explain on; + + select * + from test1 + where + ia=1 and dt='01/01/2015' and it=1 + order by id + ; + + + select id + from test1 + where + ia=1 and dt='01/01/2015' and it=1 + group by id + ; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Select Expression + -> Filter + -> Table "TEST1" Access By ID + -> Index "TEST1_PK_IA_ID" Range Scan (partial match: 1/2) + + Select Expression + -> Aggregate + -> Filter + -> Table "TEST1" Access By ID + -> Index "TEST1_PK_IA_ID" Range Scan (partial match: 1/2) + """ + +@pytest.mark.version('>=3.0') +def test_core_5070_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5074.py b/tests/bugs/test_core_5074.py new file mode 100644 index 00000000..73f36681 --- /dev/null +++ b/tests/bugs/test_core_5074.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_5074 +# title: Lost the charset ID in selection of array element +# decription: +# Confirmed missed charset in SQLDA output (remained "... charset: 0 NONE" in FB 3.0 and 4.0). +# As of FB 2.5 there we can check only one difference: "sqlsubtype: 1" instead of old "sqlsubtype: 0". +# Checked on: +# build 4.0.0.1524: OK, 1.478s. +# build 3.0.5.33139: OK, 0.913s. +# build 2.5.9.27139: OK, 0.618s. +# +# tracker_id: CORE-5074 +# min_versions: ['2.5.9'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test( + a char(10)[0:3] character set octets + ); + set sqlda_display on; + select a[0] from test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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_core_5074_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5075.py b/tests/bugs/test_core_5075.py new file mode 100644 index 00000000..30cb1678 --- /dev/null +++ b/tests/bugs/test_core_5075.py @@ -0,0 +1,246 @@ +#coding:utf-8 +# +# id: bugs.core_5075 +# title: Regression. Triger on DISCONNECT with dynamic SQL (ES 'insert into ...'): 1) does not work in 3.0; 2) leads FB to crash when it is recreated +# decription: +# Test does following: +# * obtains firebird.log as it was _before_ actions; +# * stores initial script for creation DB objects in file for futher applying it twice (see ticket); +# * open PIPE object and communicates with ISQL issuing commands into STDIN, three times; result is stored in var.'sqlres' +# * print variable 'sqlres'; it content must be equal to that we get in FB 2.5; +# * again apply initial DDL and then - one again launch ISQL with passing to it commands via STDIN and saving result in 'sqlres' +# * print variable 'sqlres'; +# * obtains firebird.log as it is _after_ actions; +# * compare two firebird.log versions - diff must be empty. +# +# Checked on 3.0.0.32281, SS/SC/CS. +# +# +# tracker_id: CORE-5075 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import subprocess +# from subprocess import Popen, PIPE, STDOUT +# import time +# import difflib +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.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'): +# # 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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# def svc_get_fb_log( f_fb_log ): +# +# import subprocess +# +# subprocess.call([ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# "action_get_fb_log" +# ], +# stdout=f_fb_log, stderr=subprocess.STDOUT +# ) +# return +# +# #-------------------------------------------- +# +# f_fblog_before=open( os.path.join(context['temp_directory'],'tmp_5075_fblog_before.txt'), 'w') +# svc_get_fb_log( f_fblog_before ) +# flush_and_close( f_fblog_before ) +# +# sqltxt='''set term ^; +# create or alter trigger trg_connect active on connect position 0 as +# begin +# end +# ^ +# +# create or alter trigger trg_disc active on disconnect position 0 as +# begin +# end +# ^ +# set term ;^ +# commit; +# +# recreate sequence g; +# recreate table log( +# event_id int generated by default as identity constraint pk_log primary key, +# event_name varchar(20), +# when_it_was timestamp default 'now' +# ); +# commit; +# +# set term ^; +# execute block as +# begin +# rdb$set_context('USER_SESSION','INITIAL_DDL','1'); +# end +# ^ +# +# create or alter trigger trg_connect active on connect position 0 as +# begin +# execute statement 'insert into log(event_name) values(''connect'')' +# with autonomous transaction; +# end +# ^ +# +# create or alter trigger trg_disc active on disconnect position 0 as +# begin +# if ( rdb$get_context('USER_SESSION','INITIAL_DDL') is null ) then +# execute statement 'insert into log(event_name) values(''disconnect'')' +# with autonomous transaction; +# end +# ^ +# set term ;^ +# commit; +# ''' +# +# f_sql_init=open( os.path.join(context['temp_directory'],'tmp_5075_init.sql'), 'w') +# f_sql_init.write(sqltxt) +# flush_and_close( f_sql_init ) +# +# sqlres=subprocess.check_output([context['isql_path'], dsn, "-nod", "-i", f_sql_init.name], stderr=subprocess.STDOUT) +# print(sqlres) # Must be empty (no errors) +# +# sqltxt='''set list on;set count on; select event_id, event_name from log; +# ''' +# +# # http://stackoverflow.com/questions/8475290/how-do-i-write-to-a-python-subprocess-stdin +# +# sqlres='' +# +# p = Popen([context['isql_path'], dsn], stdout=PIPE, stdin=PIPE, stderr=subprocess.STDOUT ) +# sqlres += p.communicate(input=sqltxt)[0] +# +# +# p = Popen([context['isql_path'], dsn], stdout=PIPE, stdin=PIPE, stderr=subprocess.STDOUT ) +# sqlres += p.communicate(input=sqltxt)[0] +# +# p = Popen([context['isql_path'], dsn], stdout=PIPE, stdin=PIPE, stderr=subprocess.STDOUT ) +# sqlres += p.communicate(input=sqltxt)[0] +# +# print(sqlres) +# +# sqlres=subprocess.check_output([context['isql_path'], dsn, "-nod", "-i", f_sql_init.name], stderr=subprocess.STDOUT) +# print(sqlres) # Must be empty (no errors) +# +# p = Popen([context['isql_path'], dsn], stdout=PIPE, stdin=PIPE, stderr=subprocess.STDOUT ) +# sqlres = p.communicate(input=sqltxt)[0] +# print(sqlres) +# +# +# f_fblog_after=open( os.path.join(context['temp_directory'],'tmp_5075_fblog_after.txt'), 'w') +# svc_get_fb_log( f_fblog_after ) +# flush_and_close( f_fblog_after ) +# +# time.sleep(1) +# +# oldfb=open(f_fblog_before.name, 'r') +# newfb=open(f_fblog_after.name, 'r') +# +# difftext = ''.join(difflib.unified_diff( +# oldfb.readlines(), +# newfb.readlines() +# )) +# oldfb.close() +# newfb.close() +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_5075_diff.txt'), 'w') +# f_diff_txt.write(difftext) +# flush_and_close( f_diff_txt ) +# +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# print('new messages in firebird.log: '+line) +# +# # Cleanup. +# ########## +# # do NOT remove this pause otherwise some of logs will not be enable for deletion and test will finish with +# # Exception raised while executing Python test script. exception: WindowsError: 32 +# time.sleep(1) +# cleanup((f_sql_init,f_fblog_before,f_fblog_after,f_diff_txt)) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + EVENT_ID 1 + EVENT_NAME connect + Records affected: 1 + EVENT_ID 1 + EVENT_NAME connect + EVENT_ID 2 + EVENT_NAME disconnect + EVENT_ID 3 + EVENT_NAME connect + Records affected: 3 + EVENT_ID 1 + EVENT_NAME connect + EVENT_ID 2 + EVENT_NAME disconnect + EVENT_ID 3 + EVENT_NAME connect + EVENT_ID 4 + EVENT_NAME disconnect + EVENT_ID 5 + EVENT_NAME connect + Records affected: 5 + EVENT_ID 1 + EVENT_NAME connect + Records affected: 1 + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_5075_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5077.py b/tests/bugs/test_core_5077.py new file mode 100644 index 00000000..d0f73e7b --- /dev/null +++ b/tests/bugs/test_core_5077.py @@ -0,0 +1,174 @@ +#coding:utf-8 +# +# id: bugs.core_5077 +# title: ISQL does not show encryption status of database +# decription: +# We create new database ('tmp_core_5077.fdb') and try to encrypt it usng IBSurgeon Demo Encryption package +# ( https://ib-aid.com/download-demo-firebird-encryption-plugin/ ; https://ib-aid.com/download/crypt/CryptTest.zip ) +# License file plugins\\dbcrypt.conf with unlimited expiration was provided by IBSurgeon to Firebird Foundation (FF). +# This file was preliminary stored in FF Test machine. +# Test assumes that this file and all neccessary libraries already were stored into FB_HOME and %FB_HOME%\\plugins. +# +# Anyone who wants to run this test on his own machine must +# 1) download https://ib-aid.com/download/crypt/CryptTest.zip AND +# 2) PURCHASE LICENSE and get from IBSurgeon file plugins\\dbcrypt.conf with apropriate expiration date and other info. +# +# ################################################ ! ! ! N O T E ! ! ! ############################################## +# FF tests storage (aka "fbt-repo") does not (and will not) contain any license file for IBSurgeon Demo Encryption package! +# ######################################################################################################################### +# +# After test database will be created, we try to encrypt it using 'alter database encrypt with ...' command +# (where = dbcrypt - name of .dll in FB_HOME\\plugins\\ folder that implements encryption). +# Then we allow engine to complete this job - take delay about 1..2 seconds BEFORE detach from database. +# +# After this we run ISQL with 'SHOW DATABASE' command. Its output has to contain string 'Database encrypted'. +# +# Finally, we change this temp DB state to full shutdown in order to have 100% ability to drop this file. +# +# Checked on: 4.0.0.1629: OK, 6.264s; 3.0.5.33179: OK, 4.586s. +# +# === NOTE-1 === +# In case of "Crypt plugin DBCRYPT failed to load/607/335544351" check that all +# needed files from IBSurgeon Demo Encryption package exist in %FB_HOME% and %FB_HOME%\\plugins +# %FB_HOME%: +# 283136 fbcrypt.dll +# 2905600 libcrypto-1_1-x64.dll +# 481792 libssl-1_1-x64.dll +# +# %FB_HOME%\\plugins: +# 297984 dbcrypt.dll +# 306176 keyholder.dll +# 108 DbCrypt.conf +# 856 keyholder.conf +# +# === NOTE-2 === +# Version of DbCrypt.dll of october-2018 must be replaced because it has hard-coded +# date of expiration rather than reading it from DbCrypt.conf !! +# +# === NOTE-3 === +# firebird.conf must contain following line: +# KeyHolderPlugin = KeyHolder +# +# +# tracker_id: CORE-5077 +# min_versions: ['3.0.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import time +# import subprocess +# import re +# import fdb +# from fdb import services +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# +# #-------------------------------------------- +# +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# fb_home = services.connect(host='localhost', user= user_name, password= user_password).get_home_directory() +# +# db_conn.close() +# +# tmpfdb='$(DATABASE_LOCATION)'+'tmp_core_5077.fdb' +# +# if os.path.isfile( tmpfdb ): +# os.remove( tmpfdb ) +# +# con = fdb.create_database( dsn = 'localhost:'+tmpfdb ) +# con.close() +# con=fdb.connect( dsn = 'localhost:'+tmpfdb ) +# cur = con.cursor() +# cur.execute('alter database encrypt with dbcrypt key Red') +# con.commit() +# time.sleep(2) +# # ^ +# # +-------- !! ALLOW BACKGROUND ENCRYPTION PROCESS TO COMPLETE ITS JOB !! +# +# con.close() +# +# #--------------------------------- run ISQL -------------------- +# f_isql_cmd=open( os.path.join(context['temp_directory'],'tmp_5077.sql'), 'w') +# f_isql_cmd.write('show database;') +# f_isql_cmd.close() +# +# f_isql_log=open( os.path.join(context['temp_directory'], 'tmp_5077.log'), 'w') +# f_isql_err=open( os.path.join(context['temp_directory'], 'tmp_5077.err'), 'w') +# subprocess.call( [fb_home+'isql', 'localhost:' + tmpfdb, '-q', '-n', '-i', f_isql_cmd.name ], stdout=f_isql_log, stderr = f_isql_err) +# f_isql_log.close() +# f_isql_err.close() +# +# #---------------------------- shutdown temp DB -------------------- +# +# f_dbshut_log = open( os.path.join(context['temp_directory'],'tmp_dbshut_5077.log'), 'w') +# subprocess.call( [ "gfix", 'localhost:'+tmpfdb, "-shut", "full", "-force", "0" ], +# stdout = f_dbshut_log, +# stderr = subprocess.STDOUT +# ) +# f_dbshut_log.close() +# +# allowed_patterns = ( +# re.compile( 'Database(\\s+not){0,1}\\s+encrypted\\.*', re.IGNORECASE), +# ) +# +# with open( f_isql_log.name,'r') as f: +# for line in f: +# match2some = filter( None, [ p.search(line) for p in allowed_patterns ] ) +# if match2some: +# print( (' '.join( line.split()).upper() ) ) +# +# with open( f_isql_err.name,'r') as f: +# for line in f: +# print("Unexpected error when doing 'SHOW DATABASE': "+line) +# +# with open( f_dbshut_log.name,'r') as f: +# for line in f: +# print("Unexpected error on SHUTDOWN temp database: "+line) +# +# time.sleep(1) +# +# # CLEANUP +# ######### +# +# f_list = [ i.name for i in ( f_isql_log, f_isql_err, f_isql_cmd, f_dbshut_log ) ] +# f_list += [ tmpfdb ] +# cleanup( f_list ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DATABASE ENCRYPTED + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_5077_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5078.py b/tests/bugs/test_core_5078.py new file mode 100644 index 00000000..1197108c --- /dev/null +++ b/tests/bugs/test_core_5078.py @@ -0,0 +1,132 @@ +#coding:utf-8 +# +# id: bugs.core_5078 +# title: "Invalid BLOB ID" error +# decription: +# Confirmed, got exception during selecting data on Classic WI-V2.5.5.26952, x64. +# STDERR: +# Statement failed, SQLSTATE = 42000 +# invalid BLOB ID +# -At procedure 'DO_CHANGETXSTATUS' line: 31, col: 21 +# Last record in STDOUT: +# INFO inserting blob +# UPDCNT 51 +# TRANS 1361600 +# SUBS 2806 +# MSGTYPE 2524 +# NOTIFYPARAMS 1482 +# +# tracker_id: CORE-5078 +# min_versions: ['2.5.6'] +# versions: 2.5.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# from subprocess import Popen +# import zipfile +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# zf = zipfile.ZipFile( os.path.join(context['files_location'],'core_5078.zip') ) +# zf.extractall( context['temp_directory'] ) +# zf.close() +# +# # Result: file tmp_core_5078.fbk is extracted into context['temp_directory'] +# +# tmp_fbk=os.path.join(context['temp_directory'],'tmp_core_5078.fbk') +# tmp_fdb=os.path.join(context['temp_directory'],'tmp_core_5078.fdb') +# +# cleanup( (tmp_fdb,) ) +# +# # Restoring from .fbk: +# runProgram( context['fbsvcmgr_path'],['localhost:service_mgr','action_restore','dbname',tmp_fdb,'bkp_file',tmp_fbk]) +# +# f_sql=open( os.path.join(context['temp_directory'],'tmp_isql_5078.sql'), 'w') +# f_sql.write('set list on; select * from do_changeTxStatus;') +# flush_and_close( f_sql ) +# +# f_log = open(os.devnull, 'w') +# f_err = open( os.path.join(context['temp_directory'],'tmp_isql_5078.err'), 'w') +# +# subprocess.call( [context['isql_path'], 'localhost:'+tmp_fdb, "-i", f_sql.name],stdout=f_log,stderr=f_err) +# +# flush_and_close( f_log ) +# flush_and_close( f_err ) +# +# time.sleep(1) +# +# # This file should be EMPTY: +# ########################### +# with open(f_err.name) as f: +# print( f.read() ) +# +# # CLEANUP +# ########## +# time.sleep(1) +# cleanup( (tmp_fbk, tmp_fdb, f_err, f_sql) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.6') +@pytest.mark.xfail +def test_core_5078_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5082.py b/tests/bugs/test_core_5082.py new file mode 100644 index 00000000..ff38ee31 --- /dev/null +++ b/tests/bugs/test_core_5082.py @@ -0,0 +1,216 @@ +#coding:utf-8 +# +# id: bugs.core_5082 +# title: Server does not validate correctness of user/password pair provided in EXECUTE STATEMENT operator +# decription: +# Confirmed on build 32136 (RC1), build 32181: wrongly displayed names of non-existent user 'TMP$C5082' +# and user SYDSDBA that login was provided with wrong (but NOT empty) password. +# NOTE: check does NOT perform inside ES when password is empty string or any number of ascii_char(32) +# and 'new' user specified is equal to user name that was used to login - see examples here when password +# for SYSDBA is '' or ascii_char(32). +# +# 06.02.2019: added separate code for 4.0 because of new error message ("Missing security context for ...") +# Checked on: 4.0.0.1421 SS, CS. +# +# +# 30.12.2019: removed check for all detailed messages about error except SQLSTATE: +# it is enough to check that server does not allow to perform such logins. +# Checked on: +# 4.0.0.1712 SS: 1.134s. +# 4.0.0.1346 SC: 1.563s. +# 4.0.0.1691 CS: 1.878s. +# 3.0.5.33218 SS: 0.637s. +# 3.0.5.33084 SC: 1.058s. +# 3.0.5.33212 CS: 1.613s. +# +# +# tracker_id: CORE-5082 +# min_versions: ['3.0'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('-At block line: [\\d]+, col: [\\d]+', '-At block line')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Make sure that user 'TMP$C5082' does NOT exist at the point just before this test start: + create or alter user tmp$c5082 password '123'; + commit; + drop user tmp$c5082; + commit; + + set list on; + set term ^; + execute block returns (whoami varchar(32)) as + begin + execute statement 'select current_user from rdb$database' as user 'TMP$C5082' password 'qwecXzasd' into whoami; + suspend; + end + ^ + + execute block returns (whoami varchar(32)) as + begin + execute statement 'select current_user from rdb$database' as user 'TMP$C5082' password '' into whoami; + suspend; + end + ^ + + execute block returns (whoami varchar(32)) as + begin + execute statement 'select current_user from rdb$database' as user 'SYSDBA' password 'fullyWrong' into whoami; + suspend; + end + ^ + + execute block returns (whoami varchar(32)) as + begin + execute statement 'select current_user from rdb$database' as user 'SYSDBA' password '' into whoami; + suspend; + end + ^ + + execute block returns (whoami varchar(32)) as + begin + execute statement 'select current_user from rdb$database' as user 'SYSDBA' password ' ' into whoami; + suspend; + end + ^ + + execute block returns (whoami varchar(32)) as + begin + execute statement 'select current_user from rdb$database' as user 'SYSDBA' password ' ' into whoami; + -- ^- Tab character here! + suspend; + end + ^ + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHOAMI SYSDBA + WHOAMI SYSDBA + """ +expected_stderr_1 = """ + 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 + + 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 + + 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 + + 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 + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_core_5082_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [('-At block line: [\\d]+, col: [\\d]+', ''), ('Missing security context.*', ''), ('Your user name and password are not defined.*', '')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + -- Make sure that user 'TMP$C5082' does NOT exist at the point just before this test start: + create or alter user tmp$c5082 password '123'; + commit; + drop user tmp$c5082; + commit; + + set list on; + set term ^; + execute block returns (whoami varchar(32)) as + begin + execute statement 'select current_user from rdb$database' as user 'TMP$C5082' password 'qwecXzasd' into whoami; + suspend; + end + ^ + + execute block returns (whoami varchar(32)) as + begin + execute statement 'select current_user from rdb$database' as user 'TMP$C5082' password '' into whoami; + suspend; + end + ^ + + execute block returns (whoami varchar(32)) as + begin + execute statement 'select current_user from rdb$database' as user 'SYSDBA' password 'fullyWrong' into whoami; + suspend; + end + ^ + + execute block returns (whoami varchar(32)) as + begin + execute statement 'select current_user from rdb$database' as user 'SYSDBA' password '' into whoami; + suspend; + end + ^ + + execute block returns (whoami varchar(32)) as + begin + execute statement 'select current_user from rdb$database' as user 'SYSDBA' password ' ' into whoami; + suspend; + end + ^ + + execute block returns (whoami varchar(32)) as + begin + execute statement 'select current_user from rdb$database' as user 'SYSDBA' password ' ' into whoami; + -- ^- Tab character here! + suspend; + end + ^ + + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + WHOAMI SYSDBA + WHOAMI SYSDBA + """ +expected_stderr_2 = """ + Statement failed, SQLSTATE = 28000 + + Statement failed, SQLSTATE = 28000 + + Statement failed, SQLSTATE = 28000 + + Statement failed, SQLSTATE = 28000 + """ + +@pytest.mark.version('>=4.0') +def test_core_5082_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_expected_stderr == act_2.clean_stderr + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/bugs/test_core_5085.py b/tests/bugs/test_core_5085.py new file mode 100644 index 00000000..6c3a2e68 --- /dev/null +++ b/tests/bugs/test_core_5085.py @@ -0,0 +1,125 @@ +#coding:utf-8 +# +# id: bugs.core_5085 +# title: Allow to fixup (nbackup) database via Services API +# decription: +# Checked on 4.0.0.2119: OK. +# +# tracker_id: CORE-5085 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import time +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_source = db_conn.database_name +# db_delta = db_source +'.delta' +# nbk_level_0 = os.path.splitext(db_source)[0] + '.nbk00' +# #'$(DATABASE_LOCATION)tmp_core_5085.nbk_00' +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# cleanup( ( db_delta, nbk_level_0, ) ) +# +# # 1. Create standby copy: make clone of source DB using nbackup -b 0: +# ######################## +# f_nbk0_log=open( os.path.join(context['temp_directory'],'tmp_nbk0_5085.log'), 'w') +# f_nbk0_err=open( os.path.join(context['temp_directory'],'tmp_nbk0_5085.err'), 'w') +# +# subprocess.call( [context['nbackup_path'], '-L', db_source], stdout=f_nbk0_log, stderr=f_nbk0_err ) +# subprocess.call( [context['fbsvcmgr_path'], 'service_mgr', 'action_nfix', 'dbname', db_source], stdout=f_nbk0_log, stderr=f_nbk0_err ) +# +# flush_and_close( f_nbk0_log ) +# flush_and_close( f_nbk0_err ) +# +# # test connect to ensure that all OK after fixup: +# ############## +# con=fdb.connect(dsn = dsn) +# cur=con.cursor() +# cur.execute('select mon$backup_state from mon$database') +# for r in cur: +# print(r[0]) +# cur.close() +# con.close() +# +# # Check. All of these files must be empty: +# ################################### +# f_list=(f_nbk0_log, f_nbk0_err) +# for i in range(len(f_list)): +# with open( f_list[i].name,'r') as f: +# for line in f: +# if line.split(): +# print( 'UNEXPECTED output in file '+f_list[i].name+': '+line.upper() ) +# +# # Cleanup. +# ########## +# time.sleep(1) +# cleanup( (f_nbk0_log,f_nbk0_err,db_delta, nbk_level_0) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 0 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_5085_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5087.py b/tests/bugs/test_core_5087.py new file mode 100644 index 00000000..8130a0e7 --- /dev/null +++ b/tests/bugs/test_core_5087.py @@ -0,0 +1,518 @@ +#coding:utf-8 +# +# id: bugs.core_5087 +# title: Database shutdown can cause server crash if multiple attachments run EXECUTE STATEMENT +# decription: +# Test makes two copies of current DB file (and closes db_conn after this): +# 1) to - for use by launching ISQL sessions which will perform "heavy DML" (insert rows in the table with wide-key index); +# 2) to - for use to verify that FB is alive after we change state of while ISQL sessions running. +# +# Then we establish connect to database (see 'att_chk'). +# If FB is alive after DML and shutdown then we have to see alive connection to . +# If FB works as SuperServer/SuperClassic and crashed then this connect will be lost and test fails with Python exception. +# If FB works as Classic then this connect will alive but we can check firebird.log for presense of phrases which testify about crash: +# "code attempted to access" and/or "terminate(d) abnormally". We analyze the DIFFERENCE file between old and new firebird.log for this. +# +# After this, we establish connection to (see 'att1') and make INSERT statement to special table 't_lock' which has PK-field. +# Futher, we launch ISQL sessions which also must insert the same (duplicated) key into this table - and they hang. +# Table 't_lock' serves as "semaphore": when we close attachment 'att1' then all running ISQL sessions will immediately do their DML job. +# +# We check that all required number connections of ISQLs present by loop in which we query mon$attachments table and count records from it. +# When result of this count will be equal to then we release lock from T_LOCK table by closing 'att1'. +# +# Futher, we allow ISQL sessions to perform their job by waiting for several seconds and then run command to change DB state to full shutdown. +# This command works without returning to caller until all activity in the DB will stop. +# +# When control will return here, we check that attachment 'att_chk' is alive. Also, we get difference of FB log content and parse by searching +# phrases which can relate to FB crash. +# +# We also do additional check: all ISQL sessions should be disconnected with writing to logs appropriate messages about shutdown. +# +# Confirmed crash on 3.0.0.31374 Beta1 (Classic). +# Hanged on 3.0.0.31896 Beta2 and 3.0.0.32136 RC-1 (no return from SHUTDOWN process). +# Parameter 'min_version' was changed to 2.5.9: now is PASSES for normal time (it seems that issues described in CORE-5106 was actually fixed). +# Checked 20.08.2020 on: +# 4.0.0.2170 SS: 13.911s. +# 4.0.0.2170 CS: 15.915s. +# 3.0.7.33356 SS: 12.210s. +# 3.0.7.33356 CS: 15.004s. +# 2.5.9.27152 SS: 12.690s. +# 2.5.9.27152 CS: 11.550s. +# +# OLD COMMENT ABOUT 2.5: +# On 2.5 no crash but works VERY slow, even for 5 attachments (checked on WI-V2.5.6.26970, 255 seconds!). +# Setting min_version = 2.6.6 is deferred again until CORE-5106 will not be fixed. +# +# tracker_id: CORE-5087 +# min_versions: ['2.5.9'] +# versions: 2.5.9 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.9 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create sequence g; + recreate table test( + id int, + s varchar(500) unique, + att bigint default current_connection + ); + recreate table log4attach( + att bigint default current_connection + ,dts timestamp default 'now' + ,process varchar(255) + ,protocol varchar(255) + ,address varchar(255) + ); + commit; + + set term ^; + execute block as + begin + rdb$set_context('USER_SESSION','INITIAL_DDL','1'); + end + ^ + + create or alter trigger trg_attach active on connect position 0 as + begin + if ( rdb$get_context('USER_SESSION','INITIAL_DDL') is null ) + then + in autonomous transaction do + insert into log4attach(process,protocol, address) + values( rdb$get_context('SYSTEM', 'CLIENT_PROCESS') + ,rdb$get_context('SYSTEM', 'NETWORK_PROTOCOL') + ,rdb$get_context('SYSTEM', 'CLIENT_ADDRESS') + ); + end + ^ -- trg_attach + set term ;^ + commit; + + create index test_att on test(att); + create index test_id on test(id); + create index log4attach_att on log4attach(att); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import sys +# import subprocess +# from subprocess import Popen +# import time +# import datetime +# import shutil +# import difflib +# import re +# import fdb +# +# PLANNED_DML_ATTACHMENTS = 30 +# +# #----------------------------------- +# +# 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() +# os.fsync(file_handle.fileno()) +# +# file_handle.close() +# +# #-------------------------------------------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #--------------------------------------------- +# +# def svc_get_fb_log( engine, f_fb_log ): +# +# global subprocess +# +# if engine.startswith('2.5'): +# get_firebird_log_key='action_get_ib_log' +# else: +# get_firebird_log_key='action_get_fb_log' +# +# subprocess.call([ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# get_firebird_log_key +# ], +# stdout=f_fb_log, stderr=subprocess.STDOUT +# ) +# +# return +# +# #-------------------------------------------- +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_file=db_conn.database_name +# engine = str(db_conn.engine_version) +# +# db_conn.close() +# +# db_verify_alive="$(DATABASE_LOCATION)tmp_5087_chk4alive.fdb" +# db_dml_sessions="$(DATABASE_LOCATION)tmp_5087_dml_heavy.fdb" +# +# +# # Copy database to another file in order to make connect to this copy +# # and check that this connection is alive after we'll do DML and shutdown +# # with source database (i.e. with "bugs.core_5087.fdb"): +# shutil.copy2( db_file, db_verify_alive ) +# shutil.copy2( db_file, db_dml_sessions ) +# +# +# f_chk_log = open( os.path.join(context['temp_directory'],'tmp_chk_5087.log'), 'w', buffering=0) +# +# att_chk = fdb.connect(dsn='localhost:'+db_verify_alive) # This leads to adding 1 row into table 'log4attach' +# att_chk.execute_immediate('delete from log4attach where att<>current_connection') +# att_chk.commit() +# +# att_chk.begin() +# cur_chk = att_chk.cursor() +# +# cur_chk.execute("select 'check_point_1: established connection to ' as msg from rdb$database") +# f_chk_log.seek(0,os.SEEK_END) +# for row in cur_chk: +# f_chk_log.write(row[0]) +# +# att_chk.commit() +# +# att1 = fdb.connect(dsn='localhost:' + db_dml_sessions) +# att2 = fdb.connect(dsn='localhost:' + db_dml_sessions) +# +# att1.execute_immediate('recreate table t_lock(id int primary key)') +# att1.commit() +# att1.execute_immediate('insert into t_lock(id) values(1)') +# +# # do NOT: att1.close() -- it will be done only after all ISQL sessions will establish their attachments. +# +# f_fblog_before=open( os.path.join(context['temp_directory'],'tmp_5087_fblog_before.txt'), 'w', buffering=0) +# svc_get_fb_log( engine, f_fblog_before ) +# f_fblog_before.close() +# +# sql_dml=''' +# commit; +# set transaction wait; +# set term ^; +# execute block as +# begin +# insert into t_lock(id) values(1); +# when any do +# begin +# -- nop -- +# end +# end +# ^ +# set term ;^ +# commit; +# +# set bail on; +# +# set transaction read committed; +# set term ^; +# execute block as +# declare n_limit int = 100000; +# declare s_length smallint; +# begin +# select ff.rdb$field_length +# from rdb$fields ff +# join rdb$relation_fields rf on ff.rdb$field_name = rf.rdb$field_source +# where rf.rdb$relation_name=upper('test') and rf.rdb$field_name=upper('s') +# into s_length; +# +# while (n_limit > 0) do +# begin +# execute statement ('insert into test(id, s) values( ?, ?)') +# ( gen_id(g,1), rpad('', :s_length, uuid_to_char(gen_uuid())) ) +# with autonomous transaction +# ; +# +# n_limit = n_limit - 1; +# end +# insert into test( id ) values( -current_connection ); +# end +# ^ +# set term ;^ +# commit; +# ''' +# +# f_dml_sql = open( os.path.join(context['temp_directory'],'tmp_dml_5087.sql'), 'w') +# f_dml_sql.write(sql_dml) +# flush_and_close( f_dml_sql ) +# +# f_list = [] +# p_list = [] +# +# ######################################################## +# # Launching dozen of child ISQL processes with doing ES +# ######################################################## +# +# for i in range(0, PLANNED_DML_ATTACHMENTS): +# sqllog=open( os.path.join(context['temp_directory'],'tmp_dml_5087_'+str(i)+'.log'), 'w') +# f_list.append(sqllog) +# +# for i in range(len(f_list)): +# ########################################### +# # a s y n c h r o n o u s l a u n c h +# ########################################### +# p_isql=Popen( [ context['isql_path'], 'localhost:' + db_dml_sessions, "-i", f_dml_sql.name ], +# stdout=f_list[i], +# stderr=subprocess.STDOUT +# ) +# p_list.append(p_isql) +# +# cur2 = att2.cursor() +# while True: +# att2.begin() +# cur2.execute("select count(*) from mon$attachments a where a.mon$attachment_id<>current_connection and a.mon$remote_process containing 'isql'") +# for r in cur2: +# established_dml_attachments = r[0] +# att2.commit() +# +# if established_dml_attachments < PLANNED_DML_ATTACHMENTS: +# # do not delete, leave it for debug: +# #################################### +# #msg = datetime.datetime.now().strftime("%H:%M:%S.%f") + ' LOOP: only %(established_dml_attachments)s attachments exist of planned %(PLANNED_DML_ATTACHMENTS)s' % locals() +# #print( msg ) +# #f_chk_log.write('\\n') +# #f_chk_log.write(msg) +# time.sleep(0.2) +# continue +# else: +# # do not delete, leave it for debug: +# #################################### +# #msg = datetime.datetime.now().strftime("%H:%M:%S.%f") + ' Found all planned %(PLANNED_DML_ATTACHMENTS)s attachments. Can release lock.' % locals() +# msg = 'Found all attachments of planned number to . No we can release lock for allow them to start DML.' +# #print( msg ) +# f_chk_log.write('\\n\\n') +# f_chk_log.write(msg) +# break +# +# cur2.close() +# att2.close() +# +# #----------------------------------- +# +# # release t_lock record. +# # All launched ISQL sessions can do useful job (INSERT statements) since this point. +# att1.close() +# +# # Let ISQL sessions do some work: +# time.sleep( 3 ) +# +# cur_chk.execute("select 'check_point_2: before shutdown ' as msg from rdb$database") +# f_chk_log.seek(0,os.SEEK_END) +# for row in cur_chk: +# f_chk_log.write('\\n') +# f_chk_log.write(row[0]) +# +# f_shutdown_log = open( os.path.join(context['temp_directory'],'tmp_shutdown_5087.log'), 'w', buffering=0) +# +# #################################### +# # S H U T D O W N D A T A B A S E +# #################################### +# +# subprocess.call( [context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_properties", +# "dbname", db_dml_sessions, +# "prp_shutdown_mode", "prp_sm_full", "prp_force_shutdown", "0" +# ], +# stdout=f_shutdown_log, +# stderr=subprocess.STDOUT +# ) +# flush_and_close( f_shutdown_log ) +# +# cur_chk.execute("select 'check_point_3: after shutdown ' as msg from rdb$database") +# f_chk_log.seek(0,os.SEEK_END) +# for row in cur_chk: +# f_chk_log.write('\\n') +# f_chk_log.write(row[0]) +# +# #------------------------------------------ +# for i in range(len(f_list)): +# flush_and_close( f_list[i] ) +# +# for i in range(len(p_list)): +# p_list[i].terminate() +# +# #------------------------------------------ +# +# cur_chk.execute("select 'check_point_4: killed all DML sessions.' as msg from rdb$database") +# f_chk_log.seek(0,os.SEEK_END) +# for row in cur_chk: +# f_chk_log.write('\\n') +# f_chk_log.write(row[0]) +# +# # Here we must wait a little because firebird.log will get new messages NOT instantly. +# time.sleep(3) +# +# crashes_in_worker_logs = 0 +# for i in range(len(f_list)): +# dml_worker_log=open(f_list[i].name).read() +# if 'SQLSTATE = 08004' in dml_worker_log: #### do NOT add >>> or 'SQLSTATE = 08006' in dml_worker_log: +# crashes_in_worker_logs += 1 +# +# f_fblog_after=open( os.path.join(context['temp_directory'],'tmp_5087_fblog_after.txt'), 'w', buffering=0) +# svc_get_fb_log( engine, f_fblog_after ) +# flush_and_close( f_fblog_after ) +# +# att_chk.begin() +# cur_chk.execute("select 'check_point_5: get firebird.log' as msg from rdb$database") +# f_chk_log.seek(0,os.SEEK_END) +# for row in cur_chk: +# f_chk_log.write('\\n') +# f_chk_log.write(row[0]) +# +# cur_chk.execute('select count(distinct att) from log4attach;') +# for row in cur_chk: +# f_chk_log.write('\\n') +# f_chk_log.write('distinct attachments to : '+str(row[0])) # must be 1 +# +# cur_chk.close() +# att_chk.close() +# +# #os.remove(db_verify_alive) +# +# #------------------------------------------ +# +# f_chk_log.seek(0,os.SEEK_END) +# f_chk_log.write('\\n') +# f_chk_log.write('Found crash messages in DML worker logs: %(crashes_in_worker_logs)s' % locals() ) # must be 0. +# +# sql_chk=''' +# set list on; +# select +# iif( count(distinct t.att) = %(PLANNED_DML_ATTACHMENTS)s +# ,'YES' +# ,'NO. Only ' || count(distinct t.att) || ' attachments of planned %(PLANNED_DML_ATTACHMENTS)s established.' ) +# as "All DML sessions found in DB ?" +# from rdb$database r +# left join ( +# select +# att +# ,count( iif(id >=0, id, null) ) as cnt_in_autonom_tx +# ,count( iif(id < 0, id, null) ) as cnt_in_common_tx +# from test +# group by att +# ) t on t.cnt_in_common_tx = 0 and t.cnt_in_autonom_tx > 0 +# ; +# ''' % locals() +# +# f_chk_sql = open( os.path.join(context['temp_directory'],'tmp_chk_5087.sql'), 'w', buffering=0) +# f_chk_sql.write(sql_chk) +# f_chk_sql.close() +# +# f_chk_log.seek(0,os.SEEK_END) +# +# f_chk_log.write('\\n') +# f_chk_log.write('Point before bring DML database online.' ) +# +# subprocess.call( [context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "prp_db_online", +# "dbname", db_dml_sessions, +# ] +# ) +# +# f_chk_log.write('\\n') +# f_chk_log.write('Point after bring DML database online.' ) +# +# subprocess.call( [ context['isql_path'], "localhost:"+db_dml_sessions, "-nod", "-i", f_chk_sql.name ], +# stdout=f_chk_log, +# stderr=subprocess.STDOUT +# ) +# flush_and_close( f_chk_log ) +# +# #------------------------------------------- +# +# # Now we can compare two versions of firebird.log and check their difference. +# +# oldfb=open(f_fblog_before.name, 'r') +# newfb=open(f_fblog_after.name, 'r') +# +# difftext = ''.join(difflib.unified_diff( +# oldfb.readlines(), +# newfb.readlines() +# )) +# oldfb.close() +# newfb.close() +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_5087_diff.txt'), 'w') +# f_diff_txt.write(difftext) +# flush_and_close( f_diff_txt ) +# +# allowed_patterns = ( +# re.compile('code attempt\\S+.*\\s+access',re.IGNORECASE), +# re.compile('terminate\\S+ abnormally',re.IGNORECASE), +# re.compile('Error writing data',re.IGNORECASE) +# ) +# +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# if line.startswith('+'): +# match2some = filter( None, [ p.search(line) for p in allowed_patterns ] ) +# if match2some: +# print('Crash message in firebird.log detected: '+line.upper()) +# +# # This should be empty: +# ####################### +# with open( f_shutdown_log.name,'r') as f: +# for line in f: +# print(line.upper()) +# +# +# # Print check info: +# with open( f_chk_log.name,'r') as f: +# print( f.read() ) +# +# +# ############################### +# # Cleanup. +# k_list = [ x.name for x in [ f_shutdown_log, f_dml_sql, f_chk_sql, f_fblog_before, f_fblog_after, f_diff_txt, f_chk_log] + f_list ] +# k_list += [db_verify_alive, db_dml_sessions] +# cleanup(k_list) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + check_point_1: established connection to + Found all attachments of planned number to . No we can release lock for allow them to start DML. + check_point_2: before shutdown + check_point_3: after shutdown + check_point_4: killed all DML sessions. + check_point_5: get firebird.log + distinct attachments to : 1 + Found crash messages in DML worker logs: 0 + Point before bring DML database online. + Point after bring DML database online. + All DML sessions found in DB ? YES + """ + +@pytest.mark.version('>=2.5.9') +@pytest.mark.xfail +def test_core_5087_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5089.py b/tests/bugs/test_core_5089.py new file mode 100644 index 00000000..b005c6f6 --- /dev/null +++ b/tests/bugs/test_core_5089.py @@ -0,0 +1,312 @@ +#coding:utf-8 +# +# id: bugs.core_5089 +# title: Metadata extration (ISQL -X): "CREATE PROCEDURE/FUNCTION" statement contains reference to column of table(s) that not yet exists if this procedure had parameter of such type when it was created +# decription: +# Test creates database with table 'TEST' and standalone and packaged procedures and functions which have parameters or variables +# with referencing to the table 'TEST' column. Also, there are DB-level and DDL-level triggers with similar references. +# Then we extract metadata and save it into file as 'initial' text. +# After this we drop all objects and make attempt to APPLY just extracted metadata script. It should perform without errors. +# Finally, we extract metadata again and do COMPARISON of their current content and those which are stored 'initial' file. +# +# Checked on: WI-V3.0.0.32313 (SS/CS/SC). See also: test for CORE-2408. +# +# tracker_id: CORE-5089 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create domain dm_test int not null check ( value >=-1 ); + + create table test(mode varchar(30), result dm_test); + commit; + + set term ^; + create procedure sp_test( + i1 dm_test + ,i2 type of dm_test + ,i3 type of column test.result + ) returns ( + o1 dm_test + ,o2 type of dm_test + ,o3 type of column test.result + ) + as + declare v1 dm_test = 3; + declare v2 type of dm_test = 7; + declare v3 type of column test.result = 9; + begin + o1 = v1 * i1; + o2 = v2 * i2; + o3 = v3 * i3; + + suspend; + + end + ^ + + create function fn_test( + i1 dm_test + ,i2 type of dm_test + ,i3 type of column test.result + ) returns type of column test.result + as + declare v1 dm_test = 11; + declare v2 type of dm_test = 13; + declare v3 type of column test.result = 17; + begin + return v1 * i1 + v2 * i2 + v3 * i3; + end + ^ + + create package pg_test as + begin + procedure pg_proc( + i1 dm_test + ,i2 type of dm_test + ,i3 type of column test.result + ) returns ( + o1 dm_test + ,o2 type of dm_test + ,o3 type of column test.result + ); + + function pg_func( + i1 dm_test + ,i2 type of dm_test + ,i3 type of column test.result + ) returns type of column test.result; + end + ^ + + create package body pg_test as + begin + procedure pg_proc( + i1 dm_test + ,i2 type of dm_test + ,i3 type of column test.result + ) returns ( + o1 dm_test + ,o2 type of dm_test + ,o3 type of column test.result + ) as + declare v1 dm_test = 19; + declare v2 type of dm_test = 23; + declare v3 type of column test.result = 29; + begin + + o1 = v1 * i1; + o2 = v2 * i2; + o3 = v3 * i3; + + suspend; + + end + + function pg_func( + i1 dm_test + ,i2 type of dm_test + ,i3 type of column test.result + ) returns type of column test.result as + declare v1 dm_test = 13; + declare v2 type of dm_test = 17; + declare v3 type of column test.result = 19; + begin + return v1 * i1 + v2 * i2 + v3 * i3; + end + + end + ^ + create or alter trigger trg_connect on connect as + declare v1 dm_test = 19; + declare v2 type of dm_test = 23; + declare v3 type of column test.result = 29; + begin + /* 1st db-level trigger, on CONNECT event */ + end + ^ + + create or alter trigger trg_commit on transaction commit as + declare v1 dm_test = 19; + declare v2 type of dm_test = 23; + declare v3 type of column test.result = 29; + begin + /* 2nd db-level trigger, on transaction COMMIT event */ + end + ^ + + create or alter trigger trg_ddl_before before any ddl statement + as + declare v1 dm_test = 19; + declare v2 type of dm_test = 23; + declare v3 type of column test.result = 29; + begin + /* DDL-level trigger before any ddl statement */ + end + ^ + + set term ^; + commit; + """ + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# import difflib +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_file = db_conn.database_name +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# f_extract_initial_meta_sql = open( os.path.join(context['temp_directory'],'tmp_meta_5089_init.sql'), 'w') +# subprocess.call( [context['isql_path'], dsn, "-x", "-ch", "utf8"], +# stdout = f_extract_initial_meta_sql, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_extract_initial_meta_sql ) +# +# ddl_clear_all=''' +# drop trigger trg_ddl_before; +# drop trigger trg_commit; +# drop trigger trg_connect; +# drop package pg_test; +# drop function fn_test; +# drop procedure sp_test; +# drop table test; +# drop domain dm_test; +# commit; +# ''' +# +# f_meta_drop_all_sql = open( os.path.join(context['temp_directory'],'tmp_meta_5089_drop_all.sql'), 'w') +# f_meta_drop_all_sql.write(ddl_clear_all) +# flush_and_close( f_meta_drop_all_sql ) +# +# f_meta_drop_all_log = open( os.path.join(context['temp_directory'],'tmp_meta_5089_drop_all.log'), 'w') +# subprocess.call( [context['isql_path'], dsn, "-i", f_meta_drop_all_sql.name, "-ch", "utf8" ], +# stdout = f_meta_drop_all_log, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_meta_drop_all_log ) +# +# +# f_apply_extracted_meta_log = open( os.path.join(context['temp_directory'],'tmp_meta_5089_apply.log'), 'w') +# subprocess.call( [context['isql_path'], dsn, "-i", f_extract_initial_meta_sql.name, "-ch", "utf8" ], +# stdout = f_apply_extracted_meta_log, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_apply_extracted_meta_log ) +# +# f_extract_current_meta_sql = open( os.path.join(context['temp_directory'],'tmp_meta_5089_last.sql'), 'w') +# subprocess.call( [context['isql_path'], dsn, "-x", "-ch", "utf8"], +# stdout = f_extract_current_meta_sql, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_extract_current_meta_sql ) +# +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_5089_meta_diff.txt'), 'w') +# +# f_old=[] +# f_new=[] +# +# f_old.append(f_extract_initial_meta_sql) # tmp_meta_5089_init.sql -- extracted metadata just after 'init_script' was done +# f_new.append(f_extract_current_meta_sql) # tmp_meta_5089_last.sql -- extracted metadata after drop all object and applying 'tmp_meta_5089_init.sql' +# +# for i in range(len(f_old)): +# old_file=open(f_old[i].name,'r') +# new_file=open(f_new[i].name,'r') +# +# f_diff_txt.write( ''.join( difflib.unified_diff( old_file.readlines(), new_file.readlines() ) ) ) +# +# old_file.close() +# new_file.close() +# +# flush_and_close( f_diff_txt ) +# +# +# # Should be EMPTY: +# ################## +# with open( f_meta_drop_all_log.name, 'r') as f: +# for line in f: +# print( 'Error log of dropping existing objects: ' + f.line() ) +# +# +# # Should be EMPTY: +# ################## +# with open( f_apply_extracted_meta_log.name, 'r') as f: +# for line in f: +# print( 'Error log of applying extracted metadata: ' + f.line() ) +# +# +# # Should be EMPTY: +# ################## +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# print( ' '.join(line.split()).upper() ) +# +# +# +# # CLEANUP. +# ########## +# time.sleep(1) +# cleanup( (f_extract_initial_meta_sql,f_extract_current_meta_sql,f_meta_drop_all_sql,f_meta_drop_all_log,f_apply_extracted_meta_log,f_diff_txt) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_5089_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5092.py b/tests/bugs/test_core_5092.py new file mode 100644 index 00000000..67f60d8a --- /dev/null +++ b/tests/bugs/test_core_5092.py @@ -0,0 +1,204 @@ +#coding:utf-8 +# +# id: bugs.core_5092 +# title: ISQL extract command looses COMPUTED BY field types +# decription: +# Test creates database with empty table T1 that has computed by fileds with DDL appopriate to the ticket issues. +# Then we: +# 1) extract metadata from database and store it to ; +# 2) run query to the table T1 with setting sqlda_display = ON, and store output to ; +# 3) DROP table T1; +# 4) try to apply script with extracted metadata (see step "1") - it should pass without errors; +# 5) AGAIN extract metadata and store it to ; +# 6) AGAIN run query to T1 with set sqlda_display = on, and store output to ; +# 7) compare text files: +# vs +# vs +# 8) Check that result of comparison is EMPTY (no rows). +# +# Confirmed bug on 3.0.0.32300, fixed on 3.0.0.32306. +# +# tracker_id: CORE-5092 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table t1 ( + n0 int + + ,si smallint computed by( 32767 ) + ,bi bigint computed by ( 2147483647 ) + ,s2 smallint computed by ( mod(bi, nullif(si,0)) ) + + ,dv double precision computed by (pi()) + ,fv float computed by (dv*dv) + ,nv numeric(3,1) computed by (sqrt(fv)) + + ,dt date computed by ('now') + ,tm time computed by ('now') + ,dx timestamp computed by ( dt ) + ,tx timestamp computed by ( tm ) + + ,c1 char character set win1251 computed by ('ы') + ,c2 char character set win1252 computed by ('å') + ,cu char character set utf8 computed by ('∑') + + ,c1x char computed by(c1) + ,c2x char computed by(c2) + ,cux char computed by(cu) + + ,b1 blob character set win1251 computed by ('ы') + ,b2 blob character set win1252 computed by ('ä') + ,bu blob character set utf8 computed by ('∑') + ,bb blob computed by ('∞') + + ,b1x blob computed by (b1) + ,b2x blob computed by (b2) + ,bux blob computed by (bu) + ,bbx blob computed by (bb) + ); + --insert into t1 values(null); + commit; + """ + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# import difflib +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_file = db_conn.database_name +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# f_meta_init_sql = open( os.path.join(context['temp_directory'],'tmp_meta_5092_init.sql'), 'w') +# subprocess.call( [context['isql_path'], dsn, "-x", "-ch", "utf8"], +# stdout = f_meta_init_sql, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_meta_init_sql ) +# +# sqlda_check='set list on; set sqlda_display on; select * from t1; commit; drop table t1; exit;' +# +# f_sqlda_init = open( os.path.join(context['temp_directory'],'tmp_sqlda_5092_init.log'), 'w') +# f_sqlda_init.close() +# runProgram( 'isql',[dsn, '-q', '-m', '-o', f_sqlda_init.name], sqlda_check) +# +# f_apply_meta_log = open( os.path.join(context['temp_directory'],'tmp_meta_5092_apply.log'), 'w') +# subprocess.call( [context['isql_path'], dsn, "-i", f_meta_init_sql.name, "-ch", "utf8" ], +# stdout = f_apply_meta_log, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_apply_meta_log ) +# +# f_meta_last_sql = open( os.path.join(context['temp_directory'],'tmp_meta_5092_last.sql'), 'w') +# subprocess.call( [context['isql_path'], dsn, "-x", "-ch", "utf8"], +# stdout = f_meta_last_sql, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_meta_last_sql ) +# +# f_sqlda_last = open( os.path.join(context['temp_directory'],'tmp_sqlda_5092_last.log') , 'w') +# f_sqlda_last.close() +# +# runProgram( 'isql',[dsn, '-q', '-m', '-o', f_sqlda_last.name], sqlda_check) +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_5092_meta_diff.txt'), 'w') +# +# f_old=[] +# f_new=[] +# +# f_old.append(f_meta_init_sql) +# f_old.append(f_sqlda_init) +# +# f_new.append(f_meta_last_sql) +# f_new.append(f_sqlda_last) +# +# for i in range(len(f_old)): +# old_file=open(f_old[i].name,'r') +# new_file=open(f_new[i].name,'r') +# +# f_diff_txt.write( ''.join( difflib.unified_diff( old_file.readlines(), new_file.readlines() ) ) ) +# +# old_file.close() +# new_file.close() +# +# flush_and_close( f_diff_txt ) +# +# # Should be EMPTY: +# ################## +# with open( f_apply_meta_log.name, 'r') as f: +# for line in f: +# print( 'Error log of applying extracted metadata: ' + f.line() ) +# +# +# # Should be EMPTY: +# ################## +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# print( ' '.join(line.split()).upper() ) +# +# +# +# # Cleanup. +# ########## +# time.sleep(1) +# +# cleanup( (f_meta_init_sql,f_meta_last_sql,f_sqlda_init,f_sqlda_last,f_apply_meta_log,f_diff_txt) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_5092_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5093.py b/tests/bugs/test_core_5093.py new file mode 100644 index 00000000..9d4729d4 --- /dev/null +++ b/tests/bugs/test_core_5093.py @@ -0,0 +1,208 @@ +#coding:utf-8 +# +# id: bugs.core_5093 +# title: ISQL extract command lose COMPUTED BY field types +# decription: +# Test creates table with fields of (almost) all possible datatypes. +# Then we apply "ALTER TABLE ALTER FIELD ..., ALTER FIELD ..." so that every field is changed, +# either by updating its computed-by value or type (for text fields - also add/remove charset). +# Expression for ALTER TABLE - see literal "alter_table_ddl", encoded in UTF8. +# NB: changing character set should NOT be reflected on SQLDA output (at least for current FB builds). +# Confirmed bug on WI-V3.0.0.32134 (RC1), fixed on: WI-V3.0.0.32311. +# ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +# ::: NB ::: +# It is possible that this test need to be adjusted soon for FB 3.0, because current SQLDA +# output is not affected by changing of field character set (adding or removing or updating). +# Sent letter to Adriano, 02-feb-2015 15:25, waiting for reply. +# +# tracker_id: CORE-5093 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('DATABASE: LOCALHOST.*BUGS.CORE_5093.FDB.*', ''), ('.*TABLE: T1.*', ''), ('.*MESSAGE FIELD COUNT.*', '')] + +init_script_1 = """ + recreate table t1 ( + n0 int + + ,si smallint computed by(32767) + ,bi bigint computed by (2147483647) + ,s2 smallint computed by ( mod(bi, nullif(si,0)) ) + + ,dx double precision computed by (pi()) + ,fx float computed by (dx*dx) + ,nf numeric(3,1) computed by (fx) + + ,dt date computed by ('now') + ,tm time computed by ('now') + + ,c_change_cb_value char character set win1251 computed by ('ы') -- for this field we only will change value inside its COMPUTED_BY clause; this should NOT bring any affect on SQLDA output. + ,c_change_charset char character set win1252 computed by ('å') -- for this field we'll only change CHARACTER SET, but this will not has effect (at least on current FB builds) + ,c_change_length char character set utf8 computed by ('∑') -- for this field we'll only increase its length + + ,b_change_cb_value blob character set win1251 computed by ('ы') -- for this field we only will change value inside its COMPUTED_BY clause; this should NOT bring any affect on SQLDA output. + ,b_change_charset blob character set win1252 computed by ('å') -- for this field we'll only change CHARACTER SET, but this will not has effect (at least on current FB builds) + ,b_remove_charset blob character set win1252 computed by ('ä') -- for this field we'll only REMOVE its CHARACTER SET; this should change this blob subtype from 1 to 0 + ,b_added_charset blob computed by ('∑') -- for this field we'll only ADD definition of CHARACTER SET; this should change this blob subtype from 0 to 1 + ); + commit; + """ + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# +# db_conn.close() +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_file="$(DATABASE_LOCATION)bugs.core_5093.fdb" +# +# f_sqlda_init = open( os.path.join(context['temp_directory'],'tmp_sqlda_5093_init.log') , 'w') +# f_sqlda_init.close() +# +# runProgram( 'isql',[dsn, '-q', '-m', '-o', f_sqlda_init.name], 'set sqlda_display on; select * from t1;') +# +# alter_table_ddl=u''' +# alter table t1 +# alter si type int computed by (32767) -- LONG +# ,alter bi type int computed by (2147483647) -- LONG +# ,alter s2 type smallint computed by ( 1 + mod(bi, nullif(si,0)) ) -- SHORT +# +# ,alter dx type float computed by( pi()/2 ) -- FLOAT +# ,alter fx type float computed by (dx*dx*dx) -- FLOAT +# ,alter nf type bigint computed by (fx * fx) -- INT64 +# +# ,alter dt type date computed by ('today') -- DATE +# ,alter tm type timestamp computed by ('now') -- TIMESTAMP +# +# ,alter c_change_cb_value type char character set win1251 computed by ('Ё') -- TEXT +# ,alter c_change_charset type char character set utf8 computed by ('Æ') -- TEXT +# ,alter c_change_length type char(2) computed by ('∑∞') -- TEXT +# +# -- All these fields, of course, should remain in type = BLOB, +# -- but when charset is removed (field "b_remove_charset") then blob subtype has to be changed to 0, +# -- and when we ADD charset (field "b_added_charset") then blob subtype has to be changed to 1. +# ,alter b_change_cb_value type blob character set win1251 computed by ('Ё') -- BLOB +# ,alter b_change_charset type blob character set iso8859_1 computed by ('å') -- BLOB +# ,alter b_remove_charset type blob /*character set win1252 */ computed by ('Æ') -- BLOB +# ,alter b_added_charset type blob character set utf8 computed by ('∞') -- BLOB +# ; +# commit; +# set sqlda_display on; +# select * from t1; +# exit; +# ''' +# +# f_sqlda_last = open( os.path.join(context['temp_directory'],'tmp_sqlda_5093_last.log') , 'w') +# f_sqlda_last.close() +# +# runProgram( 'isql',[dsn, '-q', '-m', '-o', f_sqlda_last.name], alter_table_ddl) +# +# with open( f_sqlda_init.name,'r') as f: +# for line in f: +# print( ' '.join(line.split()).upper() ) +# +# with open( f_sqlda_last.name,'r') as f: +# for line in f: +# print( ' '.join(line.split()).upper() ) +# f.close() +# +# ############################### +# # Cleanup. +# +# f_list=[] +# f_list.append(f_sqlda_init) +# f_list.append(f_sqlda_last) +# +# for i in range(len(f_list)): +# if os.path.isfile(f_list[i].name): +# os.remove(f_list[i].name) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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 + + + 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 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: 8 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: 0 LEN: 8 + : NAME: B_REMOVE_CHARSET ALIAS: B_REMOVE_CHARSET + 16: SQLTYPE: 520 BLOB NULLABLE SCALE: 0 SUBTYPE: 1 LEN: 8 CHARSET: 0 NONE + : NAME: B_ADDED_CHARSET ALIAS: B_ADDED_CHARSET + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_5093_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5097.py b/tests/bugs/test_core_5097.py new file mode 100644 index 00000000..510d7d0c --- /dev/null +++ b/tests/bugs/test_core_5097.py @@ -0,0 +1,66 @@ +#coding:utf-8 +# +# id: bugs.core_5097 +# title: COMPUTED-BY expressions are not converted to their field type inside the engine +# decription: +# +# tracker_id: CORE-5097 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!sqltype|T2_CHECK|C1_CHECK).)*$', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test1( + t0 timestamp default 'now' + ,t1 timestamp computed by( 'now' ) + ,t2 computed by( extract(weekday from t1) ) + ); + recreate table test2 (n1 integer, c1 integer computed by (1.2)); + commit; + + insert into test1 default values; + insert into test2 values (0); + commit; + + set list on; + set sqlda_display on; + + select * from test1 rows 0; + select * from test2 rows 0; + + set sqlda_display off; + + select iif( t2 between 0 and 6, 1, 0 ) t2_check from test1; + select c1 || '' as c1_check from test2; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 01: sqltype: 510 TIMESTAMP Nullable scale: 0 subtype: 0 len: 8 + 02: sqltype: 510 TIMESTAMP Nullable scale: 0 subtype: 0 len: 8 + 03: sqltype: 500 SHORT Nullable scale: 0 subtype: 0 len: 2 + 01: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + 02: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + T2_CHECK 1 + C1_CHECK 1 + """ + +@pytest.mark.version('>=3.0') +def test_core_5097_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5107.py b/tests/bugs/test_core_5107.py new file mode 100644 index 00000000..261cd04f --- /dev/null +++ b/tests/bugs/test_core_5107.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: bugs.core_5107 +# title: set autoddl off and sequence of: ( create view V as select * from T; alter view V as select 1 x from rdb$database; drop view V; ) leads to server crash +# decription: +# +# tracker_id: CORE-5107 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set autoddl off; + commit; + recreate table test(id int, x int); + create view v_test as select * from test; + alter view v_test as select 1 id from rdb$database; + drop view v_test; + commit; + set list on; + select 'Done' as msg from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG Done + """ + +@pytest.mark.version('>=3.0') +def test_core_5107_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5110.py b/tests/bugs/test_core_5110.py new file mode 100644 index 00000000..0aac82c0 --- /dev/null +++ b/tests/bugs/test_core_5110.py @@ -0,0 +1,89 @@ +#coding:utf-8 +# +# id: bugs.core_5110 +# title: False PK\\FK violation could be reported when attachment used isc_dpb_no_garbage_collect flag +# decription: +# Fix relates only such transactions that are in the state 'dead', see: https://sourceforge.net/p/firebird/code/62965 +# This mean that such Tx should did sufficiently big changes _before_ inserting key into table with PK/UK. +# Number of these changes should force Tx-1 be rolled back via TIP rather than undo+commit. +# Simple experiment shows that threshold is near 80'000 rows being inserted into the table with single +# text field of length = 50 characters. This test inserts 120'000 rows for ensuring that rollback will be +# done via TIP. +# === +# ::: NB ::: +# Minimal version of 'fdb' driver should be 1.5.1 for this test can be run. +# :::::::::: +# Confirmed exception with PK/UK violation on WI-V3.0.0.32332 (11-feb-2016), 2.5.6.26970 (05-feb-2016): +# - SQLCODE: -803 ; - violation of PRIMARY or UNIQUE KEY constraint "TEST_ID_UNQ" on table "TEST" +# - Problematic key value is ("ID" = 1) ; -803 ; 335544665 +# +# No such error on WI-T4.0.0.32371, WI-V2.5.6.26979. +# +# tracker_id: CORE-5110 +# min_versions: ['2.5.6'] +# versions: 2.5.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table test( id int, who varchar(5), constraint test_id_unq unique(id) using index test_id_unq ); + recreate table tbig( s varchar(50) ); + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import fdb +# +# db_conn.close() +# +# # This reduces test running time from ~5" to ~4": +# runProgram('gfix',[dsn,'-user',user_name,'-pas',user_password,'-w','async']) +# +# # Specifying 'no_gc=1' requires fdb version >= 1.5.1, issued 19-feb-2016, see: +# # http://sourceforge.net/p/firebird/code/62989 +# conn = fdb.connect(dsn=dsn, user=user_name, password=user_password, no_gc=1) +# +# customTPB = ( [ fdb.isc_tpb_concurrency ] ) +# tx1=conn.trans() +# tx2=conn.trans() +# +# tx1.begin( tpb=customTPB ) +# tx2.begin( tpb=customTPB ) +# +# cur1=tx1.cursor() +# cur2=tx2.cursor() +# +# print('Tx-1: insert big number of rows.') +# cur1.execute("insert into tbig(s) select rpad('', 50, uuid_to_char(gen_uuid())) from rdb$types,rdb$types,(select 1 k from rdb$types rows 2) rows 120000") +# cur1.execute("insert into test(id, who) values(1, 'Tx-1')") +# tx1.rollback() +# print('Tx-1: rollback via TIP.') +# cur2.execute("insert into test(id, who) values(1, 'Tx-2')") +# print('Tx-2: insert single test record.') +# tx2.rollback() +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Tx-1: insert big number of rows. + Tx-1: rollback via TIP. + Tx-2: insert single test record. + """ + +@pytest.mark.version('>=2.5.6') +@pytest.mark.xfail +def test_core_5110_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5118.py b/tests/bugs/test_core_5118.py new file mode 100644 index 00000000..32cf0127 --- /dev/null +++ b/tests/bugs/test_core_5118.py @@ -0,0 +1,184 @@ +#coding:utf-8 +# +# id: bugs.core_5118 +# title: Indices on computed fields are broken after restore (all keys are NULL) +# decription: +# Confirmed wrong result on: 2.5.9.27117, 3.0.4.33054 +# Works fine on: +# 4.0.0.1455: OK, 3.656s. +# 3.0.5.33109: OK, 2.641s. +# 2.5.9.27129: OK, 1.569s. +# +# tracker_id: CORE-5118 +# min_versions: ['2.5.9'] +# versions: 2.5.9 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.9 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table test ( + id int, + x varchar(10), + y varchar(10) , + concat_text computed by (x || ' ' || y) + ); + commit; + + insert into test(id, x, y) values (1, 'nom1', 'prenom1'); + insert into test(id, x, y) values (2, 'nom2', 'prenom2'); + insert into test(id, x, y) values (3, 'nom3', 'prenom3'); + commit; + + create index test_concat_text on test computed by ( concat_text ); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import time +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# tmpsrc = db_conn.database_name +# tmpbkp = os.path.splitext(tmpsrc)[0] + '.fbk' +# tmpres = os.path.splitext(tmpsrc)[0] + '.tmp' +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# # NB: we have ALWAYS to drop file that is to be target for restoring process, +# # otherwise one can get: +# # Statement failed, SQLSTATE = HY000 +# # unsupported on-disk structure for file ...; found 12.0, support 13.0 +# # (it will occur if THIS test was already run for older FB major version) +# +# cleanup( (tmpres,) ) +# +# f_backup_log=open(os.devnull, 'w') +# f_backup_err=open( os.path.join(context['temp_directory'],'tmp_backup_5118.err'), 'w') +# +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_backup", +# "dbname", tmpsrc, +# "bkp_file", tmpbkp, +# "verbose" +# ], +# stdout=f_backup_log, +# stderr=f_backup_err +# ) +# flush_and_close( f_backup_log ) +# flush_and_close( f_backup_err ) +# +# f_restore_log = open( os.path.join(context['temp_directory'],'tmp_restore_5118.log'), 'w') +# f_restore_err = open( os.path.join(context['temp_directory'],'tmp_restore_5118.err'), 'w') +# +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_restore", +# "bkp_file", tmpbkp, +# "dbname", tmpres, +# "res_replace", +# "verbose" +# ], +# stdout=f_restore_log, +# stderr=f_restore_err +# ) +# +# flush_and_close( f_restore_log ) +# flush_and_close( f_restore_err ) +# +# with open(f_backup_err.name, 'r') as f: +# for line in f: +# print( "BACKUP STDERR: "+line ) +# +# +# # Result of this filtering should be EMPTY: +# with open( f_restore_err.name,'r') as f: +# for line in f: +# print( "RESTORE STDERR: "+line ) +# +# +# runProgram( 'isql', [ 'localhost:' + tmpres, '-q' ], 'set list on; set plan on; set count on; select * from test order by concat_text;' ) +# +# ##################################################################### +# # Cleanup: +# # do NOT remove this pause otherwise some of logs will not be enable for deletion and test will finish with +# # Exception raised while executing Python test script. exception: WindowsError: 32 +# time.sleep(1) +# cleanup( (f_backup_log, f_backup_err, f_restore_log, f_restore_err, tmpbkp, tmpres) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (TEST ORDER TEST_CONCAT_TEXT) + + ID 1 + X nom1 + Y prenom1 + CONCAT_TEXT nom1 prenom1 + + ID 2 + X nom2 + Y prenom2 + CONCAT_TEXT nom2 prenom2 + + ID 3 + X nom3 + Y prenom3 + CONCAT_TEXT nom3 prenom3 + + Records affected: 3 + """ + +@pytest.mark.version('>=2.5.9') +@pytest.mark.xfail +def test_core_5118_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5119.py b/tests/bugs/test_core_5119.py new file mode 100644 index 00000000..f0c6e008 --- /dev/null +++ b/tests/bugs/test_core_5119.py @@ -0,0 +1,57 @@ +#coding:utf-8 +# +# id: bugs.core_5119 +# title: Support autocommit mode in SET TRANSACTION statement +# decription: +# Test starts transaction by issuing ISQL command with 'auto commit' clause and check then +# whether transaction data are written in the table, despite of final rollback. +# +# tracker_id: CORE-5119 +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Checked on: 4.0.0.32371 + recreate table test(id int generated by default as identity, tx int default current_transaction); + commit; + set transaction auto commit; + insert into test default values; + insert into test default values; + insert into test default values; + rollback; + set count on; + set list on; + select id, rank()over(order by tx) tx from test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + TX 1 + ID 2 + TX 2 + ID 3 + TX 3 + Records affected: 3 + """ + +@pytest.mark.version('>=4.0') +def test_core_5119_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5122.py b/tests/bugs/test_core_5122.py new file mode 100644 index 00000000..e37643e6 --- /dev/null +++ b/tests/bugs/test_core_5122.py @@ -0,0 +1,109 @@ +#coding:utf-8 +# +# id: bugs.core_5122 +# title: Expression index may not be used by the optimizer if created and used in different connection charsets +# decription: +# Confirmed: +# wrong plan (natural scan) on: WI-V3.0.0.32358. +# plan with index usage on: WI-T4.0.0.32371, WI-V2.5.6.26979. +# +# tracker_id: CORE-5122 +# min_versions: ['2.5.6'] +# versions: 2.5.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import time +# import fdb +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# con1 = fdb.connect(dsn=dsn, charset='iso8859_1') +# +# cur1=con1.cursor() +# cur1.execute("recreate table test(s varchar(10))") +# cur1.execute("create index test_calc_s on test computed by ( 'zxc' || s )") +# con1.commit() +# con1.close() +# +# sql_data_cmd=open( os.path.join(context['temp_directory'],'tmp_data_5122.sql'), 'w') +# sql_data_cmd.write("set planonly; select * from test where 'zxc' || s starting with 'qwe';") +# sql_data_cmd.close() +# +# sql_data_log=open( os.path.join(context['temp_directory'],'tmp_data_5122.log'), 'w') +# +# subprocess.call([context['isql_path'], dsn, "-n", "-ch", "utf8", "-i", sql_data_cmd.name], stdout = sql_data_log, stderr=subprocess.STDOUT) +# flush_and_close( sql_data_log ) +# +# with open(sql_data_log.name) as f: +# print(f.read()) +# +# # Cleanup. +# ########## +# time.sleep(1) +# cleanup( (sql_data_log, sql_data_cmd) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (TEST INDEX (TEST_CALC_S)) + """ + +@pytest.mark.version('>=2.5.6') +@pytest.mark.xfail +def test_core_5122_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5130.py b/tests/bugs/test_core_5130.py new file mode 100644 index 00000000..604e8cad --- /dev/null +++ b/tests/bugs/test_core_5130.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: bugs.core_5130 +# title: Compiler issues message about "invalid request BLR" when attempt to compile wrong DDL of view with both subquery and "WITH CHECK OPTION" in its DDL +# decription: +# tracker_id: CORE-5130 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Confirmed proper result on: WI-V3.0.0.32380 + create or alter view v1 as select 1 id from rdb$database; + recreate table t1(id int, x int, y int); + commit; + + alter view v1 as + select * from t1 a + where + not exists(select * from t1 r where r.x > a.x) + with check option + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + 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_core_5130_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_5133.py b/tests/bugs/test_core_5133.py new file mode 100644 index 00000000..3af60b71 --- /dev/null +++ b/tests/bugs/test_core_5133.py @@ -0,0 +1,137 @@ +#coding:utf-8 +# +# id: bugs.core_5133 +# title: ALTER SEQUENCE RESTART WITH does not change the initial value +# decription: +# :::::::::::::::::::::::::::::::::::::::: NB :::::::::::::::::::::::::::::::::::: +# 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 create separate section for FB 4.x. +# +# Checked on: +# 4.0.0.2164 +# 3.0.7.33356 +# +# +# tracker_id: CORE-5133 +# min_versions: ['3.0'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Confirmed: + -- initial value did not change on WI-V3.0.0.32376, ok since 32378. + + create or alter view v_gen as select 1 id from rdb$database; + commit; + + recreate sequence s1 start with 100 increment 2; + create or alter view v_gen as + select + trim(rdb$generator_name) gen_name + ,gen_id(s1, 0) as generator_current_value + ,rdb$initial_value gen_init + ,rdb$generator_increment gen_incr + from rdb$generators + where rdb$system_flag<>1; + commit; + + + set list on; + select * from v_gen; + + alter sequence s1 restart with -1 increment -3; + commit; + + select * from v_gen; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + GEN_NAME S1 + GENERATOR_CURRENT_VALUE 100 + GEN_INIT 100 + GEN_INCR 2 + GEN_NAME S1 + GENERATOR_CURRENT_VALUE -1 + GEN_INIT -1 + GEN_INCR -3 + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_core_5133_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + create or alter view v_gen as select 1 id from rdb$database; + commit; + + recreate sequence s1 start with 100 increment 2; + create or alter view v_gen as + select + trim(rdb$generator_name) gen_name + ,gen_id(s1, 0) as generator_current_value + ,rdb$initial_value gen_init + ,rdb$generator_increment gen_incr + from rdb$generators + where rdb$system_flag<>1; + commit; + + + set list on; + select * from v_gen; + + alter sequence s1 restart with -1 increment -3; + commit; + + select * from v_gen; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + GEN_NAME S1 + GENERATOR_CURRENT_VALUE 98 + GEN_INIT 100 + GEN_INCR 2 + GEN_NAME S1 + GENERATOR_CURRENT_VALUE 2 + GEN_INIT 100 + GEN_INCR -3 + """ + +@pytest.mark.version('>=4.0') +def test_core_5133_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/bugs/test_core_5140.py b/tests/bugs/test_core_5140.py new file mode 100644 index 00000000..10cf740e --- /dev/null +++ b/tests/bugs/test_core_5140.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: bugs.core_5140 +# title: Wrong error message when user tries to set number of page buffers into not supported value +# decription: +# +# tracker_id: CORE-5140 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('range.*', 'range')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# runProgram('gfix',['-user',user_name,'-pas',user_password,'-b','1',dsn]) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + bad parameters on attach or create database + -Attempt to set in database number of buffers which is out of acceptable range [50:131072] + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_5140_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5141.py b/tests/bugs/test_core_5141.py new file mode 100644 index 00000000..189baeac --- /dev/null +++ b/tests/bugs/test_core_5141.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: bugs.core_5141 +# title: Field definition allows several NOT NULL clauses +# decription: +# tracker_id: CORE-5141 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Confirmed: + -- * wrong behavour: WI-V3.0.0.32378 Firebird 3.0 + -- * proper result (compiler errror): WI-T4.0.0.32390 Firebird 4.0. + recreate table t1 (a integer not null not null not null); + recreate table t2 (a integer unique not null not null references t2(a)); + recreate table t3 (a integer unique not null references t2(a) not null); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + SQL error code = -637 + -duplicate specification of NOT NULL - not supported + + Statement failed, SQLSTATE = 42000 + SQL error code = -637 + -duplicate specification of NOT NULL - not supported + + Statement failed, SQLSTATE = 42000 + SQL error code = -637 + -duplicate specification of NOT NULL - not supported + """ + +@pytest.mark.version('>=4.0') +def test_core_5141_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_5142.py b/tests/bugs/test_core_5142.py new file mode 100644 index 00000000..d2c54a03 --- /dev/null +++ b/tests/bugs/test_core_5142.py @@ -0,0 +1,143 @@ +#coding:utf-8 +# +# id: bugs.core_5142 +# title: Error "no current record to fetch" if some record is to be deleted both by the statement itself and by some trigger fired during statement execution +# decription: +# Reproduced bug on WI-V3.0.0.32483. +# All fine on WI-V3.0.1.32596, WI-T4.0.0.366. +# After this test commit it is possible to remove test for CORE-5182 because the latter does the same. +# +# tracker_id: CORE-5142 +# min_versions: ['3.0.1'] +# versions: 3.0.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table test(id int); + commit; + + recreate sequence test_id_gen; + commit; + + recreate table test ( + id integer not null, + ltjahr integer, + ltkw integer, + auftragsjahr integer, + auftragsnr integer, + kwtag integer, + stck_je_std double precision, + stck_je_tag integer, + stck_je_lkw integer, + palette_je_lkw integer, + erg_std_tag double precision, + status integer, + teilenr varchar(16) character set iso8859_1 collate de_de, + erg_std_datensatz double precision, + ap integer, + arbgang integer, + prio integer, + bemerkung varchar(200) character set iso8859_1 collate de_de, + abgearbeitet integer, + menge_ist double precision, + ps2 integer, + id_autoins integer, + schistaerke varchar(6) character set iso8859_1 collate de_de + ); + commit; + + alter table test add constraint pk_test primary key (id); + create index idx_test on test(kwtag); + create index idx_test1 on test(erg_std_datensatz); + + set term ^ ; + create or alter trigger ai_test_id for test + active before insert position 0 + as + begin + if (new.id is null) then + new.id = gen_id(test_id_gen, 1); + end + ^ + + create or alter trigger test_ad for test + active after delete position 0 + as + begin + if(old.ap = 69) then + begin + delete from test where id_autoins = old.id; + end + end + ^ + set term ;^ + commit; + """ + +db_1 = db_factory(charset='ISO8859_1', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + + + insert into test (id, ltjahr, ltkw, auftragsjahr, auftragsnr, kwtag, stck_je_std, stck_je_tag, stck_je_lkw, palette_je_lkw, erg_std_tag, status, teilenr, erg_std_datensatz, ap, arbgang, prio, bemerkung, abgearbeitet, menge_ist, ps2, id_autoins, schistaerke) + values(1, 2016, 11, 2016, 2953, 7, 15, 2, null, null, null, null, 'must-aip-revi/1', 0.133333333333333, 15, 4, null, null, 0, null, 0, null, null); + insert into test (id, ltjahr, ltkw, auftragsjahr, auftragsnr, kwtag, stck_je_std, stck_je_tag, stck_je_lkw, palette_je_lkw, erg_std_tag, status, teilenr, erg_std_datensatz, ap, arbgang, prio, bemerkung, abgearbeitet, menge_ist, ps2, id_autoins, schistaerke) + values(2, 2016, 11, 2016, 2953, 7, 15, 2, null, null, null, null, 'must-aip-revi/1', 0.133333333333333, 15, 5, null, null, 0, null, 0, null, null); + insert into test (id, ltjahr, ltkw, auftragsjahr, auftragsnr, kwtag, stck_je_std, stck_je_tag, stck_je_lkw, palette_je_lkw, erg_std_tag, status, teilenr, erg_std_datensatz, ap, arbgang, prio, bemerkung, abgearbeitet, menge_ist, ps2, id_autoins, schistaerke) + values(3, 2016, 11, 2016, 2953, 7, 15, 2, null, null, null, null, 'must-aip-revit', 0.133333333333333, 15, 2, null, null, 0, null, 0, null, null); + insert into test (id, ltjahr, ltkw, auftragsjahr, auftragsnr, kwtag, stck_je_std, stck_je_tag, stck_je_lkw, palette_je_lkw, erg_std_tag, status, teilenr, erg_std_datensatz, ap, arbgang, prio, bemerkung, abgearbeitet, menge_ist, ps2, id_autoins, schistaerke) + values(4, 2016, 11, 2016, 2953, 7, 40, 2, null, null, null, null, 'must-aip-revit', 0.05, 21, 3, null, null, 0, null, 0, null, null); + insert into test (id, ltjahr, ltkw, auftragsjahr, auftragsnr, kwtag, stck_je_std, stck_je_tag, stck_je_lkw, palette_je_lkw, erg_std_tag, status, teilenr, erg_std_datensatz, ap, arbgang, prio, bemerkung, abgearbeitet, menge_ist, ps2, id_autoins, schistaerke) + values(5, 2016, 11, 2016, 2953, 7, 15, 2, null, null, null, null, 'must-aip-revi/1', 0.133333333333333, 23, 3, null, null, 0, null, 0, null, null); + insert into test (id, ltjahr, ltkw, auftragsjahr, auftragsnr, kwtag, stck_je_std, stck_je_tag, stck_je_lkw, palette_je_lkw, erg_std_tag, status, teilenr, erg_std_datensatz, ap, arbgang, prio, bemerkung, abgearbeitet, menge_ist, ps2, id_autoins, schistaerke) + values(6, 2016, 11, 2016, 2953, 7, 60, 2, null, null, null, null, 'must-aip-revi/2', 0.0333333333333333, 23, 2, null, null, 0, null, 0, null, null); + insert into test (id, ltjahr, ltkw, auftragsjahr, auftragsnr, kwtag, stck_je_std, stck_je_tag, stck_je_lkw, palette_je_lkw, erg_std_tag, status, teilenr, erg_std_datensatz, ap, arbgang, prio, bemerkung, abgearbeitet, menge_ist, ps2, id_autoins, schistaerke) + values(7, 2016, 11, 2016, 2953, 7, 60, 4, null, null, null, null, 'must-aip-revi/3', 0.0666666666666667, 23, 2, null, null, 0, null, 0, null, null); + insert into test (id, ltjahr, ltkw, auftragsjahr, auftragsnr, kwtag, stck_je_std, stck_je_tag, stck_je_lkw, palette_je_lkw, erg_std_tag, status, teilenr, erg_std_datensatz, ap, arbgang, prio, bemerkung, abgearbeitet, menge_ist, ps2, id_autoins, schistaerke) + values(8, 2016, 11, 2016, 2953, 7, 60, 4, null, null, null, null, 'must-aip-revi/4', 0.0666666666666667, 23, 2, null, null, 0, null, 0, null, null); + insert into test (id, ltjahr, ltkw, auftragsjahr, auftragsnr, kwtag, stck_je_std, stck_je_tag, stck_je_lkw, palette_je_lkw, erg_std_tag, status, teilenr, erg_std_datensatz, ap, arbgang, prio, bemerkung, abgearbeitet, menge_ist, ps2, id_autoins, schistaerke) + values(9, 2016, 11, 2016, 2953, 7, 60, 4, null, null, null, null, 'must-aip-revi/5', 0.0666666666666667, 23, 2, null, null, 0, null, 0, null, null); + insert into test (id, ltjahr, ltkw, auftragsjahr, auftragsnr, kwtag, stck_je_std, stck_je_tag, stck_je_lkw, palette_je_lkw, erg_std_tag, status, teilenr, erg_std_datensatz, ap, arbgang, prio, bemerkung, abgearbeitet, menge_ist, ps2, id_autoins, schistaerke) + values(10, 2016, 11, 2016, 2953, 7, 60, 2, null, null, null, null, 'must-aip-revi/6', 0.0333333333333333, 23, 2, null, null, 0, null, 0, null, null); + insert into test (id, ltjahr, ltkw, auftragsjahr, auftragsnr, kwtag, stck_je_std, stck_je_tag, stck_je_lkw, palette_je_lkw, erg_std_tag, status, teilenr, erg_std_datensatz, ap, arbgang, prio, bemerkung, abgearbeitet, menge_ist, ps2, id_autoins, schistaerke) + values(11, 2016, 11, 2016, 2953, 7, 4, 2, null, null, 35.6060832890307, null, 'must-aip-revit-p', 0.5, 69, 1, null, null, 0, null, 0, null, null); + insert into test (id, ltjahr, ltkw, auftragsjahr, auftragsnr, kwtag, stck_je_std, stck_je_tag, stck_je_lkw, palette_je_lkw, erg_std_tag, status, teilenr, erg_std_datensatz, ap, arbgang, prio, bemerkung, abgearbeitet, menge_ist, ps2, id_autoins, schistaerke) + values(12, 2016, 11, 2016, 2953, 7, 13.5, 2, null, null, 35.6060832890307, null, 'must-aip-revit-p', 0.148148148148148, 69, 2, null, null, 0, null, 0, null, null); + insert into test (id, ltjahr, ltkw, auftragsjahr, auftragsnr, kwtag, stck_je_std, stck_je_tag, stck_je_lkw, palette_je_lkw, erg_std_tag, status, teilenr, erg_std_datensatz, ap, arbgang, prio, bemerkung, abgearbeitet, menge_ist, ps2, id_autoins, schistaerke) + values(13, 2016, 11, 2016, 2953, 7, 13.5, 2, null, null, null, null, 'must-aip-revit-p', 0.148148148148148, 67, 3, null, null, 0, null, 0, 12, null); + insert into test (id, ltjahr, ltkw, auftragsjahr, auftragsnr, kwtag, stck_je_std, stck_je_tag, stck_je_lkw, palette_je_lkw, erg_std_tag, status, teilenr, erg_std_datensatz, ap, arbgang, prio, bemerkung, abgearbeitet, menge_ist, ps2, id_autoins, schistaerke) + values(14, 2016, 11, 2016, 2953, 7, 3, 1, null, null, null, null, 'must-aip-revi/1', 0.333333333333333, 87, 1, null, null, 0, null, 0, null, null); + insert into test (id, ltjahr, ltkw, auftragsjahr, auftragsnr, kwtag, stck_je_std, stck_je_tag, stck_je_lkw, palette_je_lkw, erg_std_tag, status, teilenr, erg_std_datensatz, ap, arbgang, prio, bemerkung, abgearbeitet, menge_ist, ps2, id_autoins, schistaerke) + values(15, 2016, 11, 2016, 2953, 7, 2.4, 2, null, null, null, null, 'must-aip-revi/1', 0.833333333333333, 87, 2, null, null, 0, null, 0, null, null); + insert into test (id, ltjahr, ltkw, auftragsjahr, auftragsnr, kwtag, stck_je_std, stck_je_tag, stck_je_lkw, palette_je_lkw, erg_std_tag, status, teilenr, erg_std_datensatz, ap, arbgang, prio, bemerkung, abgearbeitet, menge_ist, ps2, id_autoins, schistaerke) + values(16, 2016, 11, 2016, 2953, 7, 15, 2, null, null, null, null, 'must-aip-revi/2', 0.133333333333333, 87, 1, null, null, 0, null, 0, null, null); + insert into test (id, ltjahr, ltkw, auftragsjahr, auftragsnr, kwtag, stck_je_std, stck_je_tag, stck_je_lkw, palette_je_lkw, erg_std_tag, status, teilenr, erg_std_datensatz, ap, arbgang, prio, bemerkung, abgearbeitet, menge_ist, ps2, id_autoins, schistaerke) + values(17, 2016, 11, 2016, 2953, 7, 24, 4, null, null, null, null, 'must-aip-revi/3', 0.166666666666667, 87, 1, null, null, 0, null, 0, null, null); + insert into test (id, ltjahr, ltkw, auftragsjahr, auftragsnr, kwtag, stck_je_std, stck_je_tag, stck_je_lkw, palette_je_lkw, erg_std_tag, status, teilenr, erg_std_datensatz, ap, arbgang, prio, bemerkung, abgearbeitet, menge_ist, ps2, id_autoins, schistaerke) + values(18, 2016, 11, 2016, 2953, 7, 30, 4, null, null, null, null, 'must-aip-revi/4', 0.133333333333333, 87, 1, null, null, 0, null, 0, null, null); + insert into test (id, ltjahr, ltkw, auftragsjahr, auftragsnr, kwtag, stck_je_std, stck_je_tag, stck_je_lkw, palette_je_lkw, erg_std_tag, status, teilenr, erg_std_datensatz, ap, arbgang, prio, bemerkung, abgearbeitet, menge_ist, ps2, id_autoins, schistaerke) + values(19, 2016, 11, 2016, 2953, 7, 60, 4, null, null, null, null, 'must-aip-revi/5', 0.0666666666666667, 87, 1, null, null, 0, null, 0, null, null); + insert into test (id, ltjahr, ltkw, auftragsjahr, auftragsnr, kwtag, stck_je_std, stck_je_tag, stck_je_lkw, palette_je_lkw, erg_std_tag, status, teilenr, erg_std_datensatz, ap, arbgang, prio, bemerkung, abgearbeitet, menge_ist, ps2, id_autoins, schistaerke) + values(20, 2016, 11, 2016, 2953, 7, 15, 2, null, null, null, null, 'must-aip-revi/6', 0.133333333333333, 87, 1, null, null, 0, null, 0, null, null); + insert into test (id, ltjahr, ltkw, auftragsjahr, auftragsnr, kwtag, stck_je_std, stck_je_tag, stck_je_lkw, palette_je_lkw, erg_std_tag, status, teilenr, erg_std_datensatz, ap, arbgang, prio, bemerkung, abgearbeitet, menge_ist, ps2, id_autoins, schistaerke) + values(21, 2016, 11, 2016, 2953, 7, 4, 2, null, null, null, null, 'must-aip-revit', 0.5, 126, 1, null, null, 0, null, 0, null, null); + commit; + + delete from test where auftragsjahr = 2016 and auftragsnr = 2953; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0.1') +def test_core_5142_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_5143.py b/tests/bugs/test_core_5143.py new file mode 100644 index 00000000..1aa20c4b --- /dev/null +++ b/tests/bugs/test_core_5143.py @@ -0,0 +1,169 @@ +#coding:utf-8 +# +# id: bugs.core_5143 +# title: internal Firebird consistency check (cannot find tip page (165), file: tra.cpp line: 2375) +# decription: +# This .fbt does exactly what's specified in the ticket: creates database, adds objects and makes b/r. +# Restoring process is logged; STDOUT should not contain word 'ERROR:'; STDERR should be empty at all. +# +# Confirmed: +# 1) error on 3.0.0.32378: +# STDLOG: gbak: ERROR:table T2 is not defined +# STDLOG: gbak: ERROR:unsuccessful metadata update +# STDLOG: gbak: ERROR: TABLE T2 +# STDLOG: gbak: ERROR: Can't have relation with only computed fields or constraints +# STDERR: action cancelled by trigger (0) to preserve data integrity +# STDERR: -could not find object for GRANT +# STDERR: -Exiting before completion due to errors +# 2) OK on 3.0.0.32471, 4.0.0.127 +# +# tracker_id: CORE-5143 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + set term ^; + create or alter function f1 returns int as begin return 1; end + ^ + set term ;^ + commit; + + recreate table t1 (id int); + recreate table t2 (id int); + + set term ^; + create or alter function f1 returns int + as + begin + return (select count(*) from t1) + (select count(*) from t2); + end^ + set term ;^ + commit; + + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import time +# import subprocess +# +# tmpsrc = db_conn.database_name +# tmpbkp = os.path.splitext(tmpsrc)[0] + '.fbk' +# tmpres = os.path.splitext(tmpsrc)[0] + '.tmp' +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# f_backup_log=open(os.devnull, 'w') +# f_backup_err=open( os.path.join(context['temp_directory'],'tmp_backup_5143.err'), 'w') +# +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_backup", +# "dbname", tmpsrc, +# "bkp_file", tmpbkp, +# "verbose" +# ], +# stdout=f_backup_log, +# stderr=f_backup_err +# ) +# flush_and_close( f_backup_log ) +# flush_and_close( f_backup_err ) +# +# f_restore_log = open( os.path.join(context['temp_directory'],'tmp_restore_5143.log'), 'w') +# f_restore_err = open( os.path.join(context['temp_directory'],'tmp_restore_5143.err'), 'w') +# +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_restore", +# "bkp_file", tmpbkp, +# "dbname", tmpres, +# "res_replace", +# "res_one_at_a_time", +# "verbose" +# ], +# stdout=f_restore_log, +# stderr=f_restore_err +# ) +# +# flush_and_close( f_restore_log ) +# flush_and_close( f_restore_err ) +# +# with open(f_backup_err.name, 'r') as f: +# for line in f: +# print( "STDOUT: "+line ) +# +# # Result of this filtering should be EMPTY: +# with open( f_restore_log.name,'r') as f: +# for line in f: +# if 'ERROR:' in line.upper(): +# print( "STDLOG: "+line ) +# +# # This file should be EMPTY: +# with open(f_restore_err.name, 'r') as f: +# for line in f: +# print( "STDERR: "+line ) +# +# # Cleanup: +# ########## +# +# # do NOT remove this pause otherwise some of logs will not be enable for deletion and test will finish with +# # Exception raised while executing Python test script. exception: WindowsError: 32 +# time.sleep(1) +# +# cleanup( (f_backup_log,f_backup_err,f_restore_log,f_restore_err,tmpbkp,tmpres) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_5143_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5146.py b/tests/bugs/test_core_5146.py new file mode 100644 index 00000000..0b3be783 --- /dev/null +++ b/tests/bugs/test_core_5146.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_5146 +# title: Suboptimal join order if one table has a selective predicate and MIN is calculated for the other one +# decription: +# tracker_id: CORE-5146 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Confirmed: + -- effective plan on: V3.0.0.32435, T4.0.0.113 + -- ineffect. plan on: V3.0.0.32378, T4.0.0.98 + + recreate table houritems(houritemid int, projectid int); -- hi + recreate table dihourentries(houritemid int, datevalue int); -- he + + create index hi_itemid on houritems(houritemid); + create index hi_projid on houritems(projectid); + create index he_itemid on dihourentries(houritemid); + create index he_datevl on dihourentries(datevalue); + + set planonly; + + select min(he.datevalue) + from houritems hi inner join dihourentries he on hi.houritemid = he.houritemid + where hi.projectid = ?; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN JOIN (HI INDEX (HI_PROJID), HE INDEX (HE_ITEMID)) + """ + +@pytest.mark.version('>=3.0') +def test_core_5146_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5147.py b/tests/bugs/test_core_5147.py new file mode 100644 index 00000000..21c99ef6 --- /dev/null +++ b/tests/bugs/test_core_5147.py @@ -0,0 +1,80 @@ +#coding:utf-8 +# +# id: bugs.core_5147 +# title: create trigger fails with ambiguous field name between table B and table A error +# decription: +# tracker_id: CORE-5147 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Result: OK on build based on sources 18-03-2016 14:40 + -- (take sources from github, build No. was wrong - 32400). + + recreate table test_b ( + id integer not null, + qty float, + constraint pk_b primary key (id) + ); + recreate table test_a ( + id integer not null, + qty float, + constraint pk_a primary key (id) + ); + + set term ^; + create or alter trigger test_b_bi for test_b active before insert position 0 as + declare oldqty float; + declare newqty float; + begin + update test_a + set qty = new.qty + where + id=new.id + returning new.qty, old.qty + into newqty, oldqty; + + rdb$set_context('USER_SESSION' ,'TRG_OLD_QTY', oldQty); + rdb$set_context('USER_SESSION' ,'TRG_NEW_QTY', newQty); + end + ^ + set term ;^ + commit; + + insert into test_a values( 1, 3.1415926); + insert into test_b(id, qty) values( 1, 2.718281828 ); + + set list on; + + select + rdb$get_context('USER_SESSION' ,'TRG_OLD_QTY') as trg_old_qty + ,rdb$get_context('USER_SESSION' ,'TRG_NEW_QTY') as trg_new_qty + from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TRG_OLD_QTY 3.1415925 + TRG_NEW_QTY 2.7182817 + """ + +@pytest.mark.version('>=3.0') +def test_core_5147_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5149.py b/tests/bugs/test_core_5149.py new file mode 100644 index 00000000..93b9b3f4 --- /dev/null +++ b/tests/bugs/test_core_5149.py @@ -0,0 +1,86 @@ +#coding:utf-8 +# +# id: bugs.core_5149 +# title: Regression: LEFT JOIN incorrectly pushes COALESCE into the inner stream causing wrong results +# decription: +# tracker_id: CORE-5149 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Confirmed: wrong result on WI-V3.0.0.32380; works fine on LI-V3.0.0.32381. + recreate table t_stock ( + tnr varchar(16), + amount integer + ); + + recreate table t_main ( + tnr varchar(16) primary key using index t_main_tnr, + minb integer + ); + + alter table t_stock + add constraint fk_t_stock_1 + foreign key (tnr) references t_main (tnr) + on delete cascade on update cascade + using index t_stock_tnr + ; + commit; + + insert into t_main (tnr, minb) values ('aaa', 0); + insert into t_main (tnr, minb) values ('bbb', 10); + insert into t_main (tnr, minb) values ('ccc', 10); + insert into t_main (tnr, minb) values ('ddd', 10); + + insert into t_stock (tnr, amount) values ('aaa', 100); + insert into t_stock (tnr, amount) values ('bbb', 5); + insert into t_stock (tnr, amount) values ('ccc', 15); + commit; + + set list on; + + select + a.tnr + ,a.minb + ,b.amount as b_amount + ,coalesce(b.amount,0) as coalesce_b_amt + from t_main a + left join t_stock b on a.tnr = b.tnr + where a.minb > coalesce(b.amount,0) + order by a.tnr + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TNR bbb + MINB 10 + B_AMOUNT 5 + COALESCE_B_AMT 5 + + TNR ddd + MINB 10 + B_AMOUNT + COALESCE_B_AMT 0 + """ + +@pytest.mark.version('>=3.0') +def test_core_5149_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5153.py b/tests/bugs/test_core_5153.py new file mode 100644 index 00000000..6e30e7b8 --- /dev/null +++ b/tests/bugs/test_core_5153.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: bugs.core_5153 +# title: Regression: Server crashes when aggregate functions are used together with NOT IN predicate +# decription: +# ::: NB ::: +# Here we only check that server is alive after running query but WITHOUT checking its data +# (see: "and 1=0" below in HAVING section). +# We do NOT check correctness of query results - this will be done by another ticket, CORE-5165: +# wrong result in 3.0 RC2 and 4.0 comparing 2.5. It's NOT related to this ticket. +# +# Confirmed success (no crash) on snapshots 3.0 RC2 and 4.0 with timestamp 23-mar-2016. +# Crash was detected on WI-V3.0.0.32378. +# +# tracker_id: CORE-5153 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + select r.rdb$relation_id as id, count(*) as cnt + from rdb$database r + group by r.rdb$relation_id + having count(*) not in (select r2.rdb$relation_id from rdb$database r2) + and 1=0 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +def test_core_5153_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_5155.py b/tests/bugs/test_core_5155.py new file mode 100644 index 00000000..513f4a84 --- /dev/null +++ b/tests/bugs/test_core_5155.py @@ -0,0 +1,38 @@ +#coding:utf-8 +# +# id: bugs.core_5155 +# title: [CREATE OR] ALTER USER statement: clause PASSWORD (if present) must be always specified just after USER +# decription: +# tracker_id: CORE-5155 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter user tmp$c5155 password '123' firstname 'john' revoke admin role; + create or alter user tmp$c5155 revoke admin role firstname 'john' password '123'; + create or alter user tmp$c5155 firstname 'john' revoke admin role password '123' lastname 'smith'; + create or alter user tmp$c5155 lastname 'adams' grant admin role firstname 'mick' password '123'; + create or alter user tmp$c5155 revoke admin role lastname 'adams' firstname 'mick' password '123'; + drop user tmp$c5155; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +def test_core_5155_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_5161.py b/tests/bugs/test_core_5161.py new file mode 100644 index 00000000..8de13241 --- /dev/null +++ b/tests/bugs/test_core_5161.py @@ -0,0 +1,85 @@ +#coding:utf-8 +# +# id: bugs.core_5161 +# title: Unique index could be created on non-unique data +# decription: +# tracker_id: CORE-5161 +# min_versions: ['2.5.6'] +# versions: 2.5.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- 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. + + recreate table t (id int, x int); + set term ^; + execute block as + declare i int = 0; + begin + --while (i < 100000) do + while (i < 50000) do -- minimal number for reproduce: 3276 + begin + insert into t values ( :i, iif(:i=1, -888888888, -:i) ); + i = i + 1; + end + 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; + + create unique index t_id_unique on t(id); + + set plan on; + select id, x from t where id = 1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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; + PLAN (T NATURAL) + ID 1 + X -888888888 + ID 1 + X -999999999 + """ +expected_stderr_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) + """ + +@pytest.mark.version('>=2.5.6') +def test_core_5161_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5162.py b/tests/bugs/test_core_5162.py new file mode 100644 index 00000000..f63af5b2 --- /dev/null +++ b/tests/bugs/test_core_5162.py @@ -0,0 +1,117 @@ +#coding:utf-8 +# +# id: bugs.core_5162 +# title: SEC$ tables and tag/attributes +# decription: +# FB30SS, build 3.0.4.32972: OK, 1.047s. +# FB40SS, build 4.0.0.977: OK, 1.266s. +# +# tracker_id: CORE-5162 +# min_versions: ['3.0.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=+', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set term ^; + execute block as + begin + begin + execute statement 'drop user tmp$c5162 using plugin Legacy_UserManager' with autonomous transaction; + when any do begin end + end + + begin + execute statement 'drop user tmp$c5162 using plugin Srp' with autonomous transaction; + when any do begin end + end + end^ + set term ;^ + commit; + + create user tmp$c5162 password '123' firstname 'John' using plugin Legacy_UserManager; + + alter user tmp$c5162 using plugin Legacy_UserManager tags ( + key1 = '1val11' + ,key2 = '2val22' + ,key3 = '3val33' + ); + + create user tmp$c5162 password '123' firstname 'Mary' using plugin Srp tags ( + key1 = 'val111' + ,key2 = 'val222' + ,key3 = 'val333' + ); + commit; + + --set list on; + set width usrname 10; + set width firstnm 10; + set width su_plg 20; + set width sa_key 6; + set width sa_val 6; + set width sa_plg 20; + + select + sa.sec$user_name as usrname + ,sa.sec$key as sa_key + ,sa.sec$value as sa_val + ,sa.sec$plugin as sa_plg + from sec$user_attributes sa + where sa.sec$user_name ='TMP$C5162' + order by usrname, sa_plg; + + select + su.sec$user_name as usrname + ,su.sec$first_name as firstnm + ,su.sec$plugin as su_plg + ,sa.sec$key as sa_key + ,sa.sec$value as sa_val + ,sa.sec$plugin as sa_plg + from sec$users su left join sec$user_attributes sa using(sec$user_name, sec$plugin) + where su.sec$user_name ='TMP$C5162' + order by usrname, sa_plg; + + commit; + + -- cleanup: + drop user tmp$c5162 using plugin Legacy_UserManager; + drop user tmp$c5162 using plugin Srp; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + USRNAME SA_KEY SA_VAL SA_PLG + ========== ====== ====== ==================== + TMP$C5162 KEY1 val111 Srp + TMP$C5162 KEY2 val222 Srp + TMP$C5162 KEY3 val333 Srp + + + USRNAME FIRSTNM SU_PLG SA_KEY SA_VAL SA_PLG + ========== ========== ==================== ====== ====== ======== + TMP$C5162 John Legacy_UserManager + TMP$C5162 Mary Srp KEY1 val111 Srp + TMP$C5162 Mary Srp KEY2 val222 Srp + TMP$C5162 Mary Srp KEY3 val333 Srp + """ + +@pytest.mark.version('>=3.0') +def test_core_5162_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5165.py b/tests/bugs/test_core_5165.py new file mode 100644 index 00000000..8141cb9a --- /dev/null +++ b/tests/bugs/test_core_5165.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: bugs.core_5165 +# title: HAVING COUNT(*) NOT IN ( ) prevent record from appearing in outer resultset when it should be there ( = resultset without nulls) +# decription: +# tracker_id: CORE-5165 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Confirmed proper result on: WI-V3.0.0.32418, WI-T4.0.0.98 + set list on; + set count on; + select 1 as check_ok + from rdb$database r + group by r.rdb$relation_id + having count(*) not in (select -1 from rdb$database r2); + + select 2 as check_ok + from rdb$database r + group by r.rdb$relation_id + having count(1) not in (select -1 from rdb$database r2); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CHECK_OK 1 + Records affected: 1 + + CHECK_OK 2 + Records affected: 1 + """ + +@pytest.mark.version('>=3.0') +def test_core_5165_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5166.py b/tests/bugs/test_core_5166.py new file mode 100644 index 00000000..bede4e57 --- /dev/null +++ b/tests/bugs/test_core_5166.py @@ -0,0 +1,95 @@ +#coding:utf-8 +# +# id: bugs.core_5166 +# title: Wrong error message with UNIQUE BOOLEAN field +# decription: +# tracker_id: CORE-5166 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Confirmed: result is OK, builds: 3.0.0.32418, WI-T4.0.0.98 + set list on; + recreate table test1 ( + x boolean, + constraint test1_x_unq unique (x) + using index test1_x_unq + ); + commit; + insert into test1(x) values (true); + select * from test1; + + set count on; + insert into test1(x) values (true); + commit; + set count off; + + recreate table test2 ( + u boolean, + v boolean, + w boolean, + constraint test2_uvw_unq unique (u,v,w) + using index test2_uvw_unq + ); + commit; + + set count on; + insert into test2 values( null, null, null); + insert into test2 values( true, true, true); + insert into test2 values( true, null, true); + insert into test2 values( true, null, null); + insert into test2 values( null, true, null); + insert into test2 values( null, null, null); + insert into test2 values( true, true, true); + update test2 set u=true, v=null, w=true where coalesce(u,v,w) is null rows 1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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_1 = """ + 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) + """ + +@pytest.mark.version('>=3.0') +def test_core_5166_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5167.py b/tests/bugs/test_core_5167.py new file mode 100644 index 00000000..2131e172 --- /dev/null +++ b/tests/bugs/test_core_5167.py @@ -0,0 +1,372 @@ +#coding:utf-8 +# +# id: bugs.core_5167 +# title: Allow implicit conversion between boolean and string +# decription: +# Test contains of TWO set of expressions: those which should finish OK and which should FAIL. +# Expressions that should work fine are called directly with checking only their result. +# Expressions that should fail are inserted into table and are called via ES from cursor on that table. +# Inside this cursor we register values of gdscode and sqlstate that raise, and issue via output args +# three columns: statement, gdscode, sqlstate. This output is then checked for matching with expected. +# Checked on WI-T4.0.0.141; WI-V3.0.0.32490 +# +# tracker_id: CORE-5167 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + recreate sequence g; + recreate table test( + id int, -- generated by default as identity constraint pk_test primary key using index pk_test, + expr varchar(128) + ); + commit; + + + -- ########################################################### + -- ### FOLLOWING STATEMENTS SHOULD FINISH __SUCCESSFULLY__ ### + -- ########################################################### + + -- check trivial ability to convert string to boolean + select gen_id(g,1) as expr_no, true > 'false' as result from rdb$database; + + select gen_id(g,1) as expr_no, 'false' ~= true and true != 'false' and false ^= 'true' as result from rdb$database; + + -- following should work as: 1) (true > 'false)==> ; 2) true > 'false' ==> + select gen_id(g,1) as expr_no, true > 'false' > 'false' as result from rdb$database; + + + -- 1) 'true' > false ==> TRUE > false ==> ; 2) TRUE > 'true' ==> > TRUE ==> + select gen_id(g,1) as expr_no, 'true' > false > 'true' as result from rdb$database; + + select gen_id(g,1) as expr_no, 'true' in (false, false, null, true) as result from rdb$database; -- + select gen_id(g,1) as expr_no, 'true' not in (false, null, true) as result from rdb$database; -- + + select gen_id(g,1) as expr_no, 'true' between false and 'true' as result from rdb$database; -- + + -- works as: NOT ('true' between false and 'true'): + select gen_id(g,1) as expr_no, not 'true' between false and 'true' as result from rdb$database; -- + + select gen_id(g,1) as expr_no, unknown = 'unknown' as result from rdb$database; -- null + select gen_id(g,1) as expr_no, unknown in ('false', 'true','unknown') as result from rdb$database; -- null + select gen_id(g,1) as expr_no, unknown = 'false' as result from rdb$database; -- null + select gen_id(g,1) as expr_no, unknown > 'true' as result from rdb$database; -- null + select gen_id(g,1) as expr_no, unknown between 'false' and 'true' as result from rdb$database; -- null + select gen_id(g,1) as expr_no, unknown = 'false' or 'true' = unknown as result from rdb$database; -- null + + -- check how 'NOT' works (operator precedence) + -- Also check 'IS', 'IS DISTINCT FROM' and CaSe InsensItivity of strings: + -- ASF, 06/Apr/16 01:37 PM: is 'true' is invalid. + -- The operator is: + -- IS [NOT] {TRUE | FALSE} + -- + -- but not like: + -- IS [NOT] + -- + -- not 'false' together with AND/OR, does not allow non boolean argument. + + select gen_id(g,1) as expr_no, not 'false' = true as result from rdb$database; -- works as: not ( 'false' = true ); result: + select gen_id(g,1) as expr_no, not 'faLSe' is distinct from true as result from rdb$database; -- works as: not ( 'false is ... ); result: + + select gen_id(g,1) as expr_no, not true = 'false' as result from rdb$database; + select gen_id(g,1) as expr_no, not true is not distinct from 'false' as result from rdb$database; + select gen_id(g,1) as expr_no, 'false' <> not false as result from rdb$database; -- true + + select gen_id(g,1) as expr_no, 'true' between (not true) and (not false) as result from rdb$database; -- true + commit; + + -- ######################################################### + -- ### FOLLOWING STATEMENTS SHOULD FINISH __ABNORMALLY__ ### + -- ######################################################### + + delete from test; + + -- ASF 11/Apr/16 12:59 AM + -- About BETWEEN, if we allow every crazy construct there, parser conflicts explodes. + insert into test(id, expr) values(gen_id(g,1), 'select true between not true and not false as result from rdb$database'); -- token unknown ''not'' + insert into test(id, expr) values(gen_id(g,1), 'select true between not false and true as result from rdb$database'); -- token unknown ''not'' + + insert into test(id, expr) values(gen_id(g,1), 'select (not ''true'') as result from rdb$database'); -- invalid usage of bool expr + insert into test(id, expr) values(gen_id(g,1), 'select not ''faLSe'' is true as result from rdb$database'); -- works as: not ( ''false'' is true ) -- invalid usage of bool + insert into test(id, expr) values(gen_id(g,1), 'select ''true'' is not false as result from rdb$database'); -- invalid usage of bool expr + insert into test(id, expr) values(gen_id(g,1), 'select ''true'' is distinct from not ''unknown'' as result from rdb$database'); -- invalid usage of bool expr + insert into test(id, expr) values(gen_id(g,1), 'select ''true'' is distinct from (not false and ''false'') as result from rdb$database'); -- -Invalid usage of boolean expression + insert into test(id, expr) values(gen_id(g,1), 'select ''true'' is not false as result from rdb$database'); -- invalid usage of bool + insert into test(id, expr) values(gen_id(g,1), 'select true = not ''false'' as result from rdb$database'); -- invalid usage of bool + insert into test(id, expr) values(gen_id(g,1), 'select ''false'' is not distinct from not true or ''unknown'' as result from rdb$database'); -- invalid usage of bool + insert into test(id, expr) values(gen_id(g,1), 'select true = not not ''true'' as result from rdb$database'); -- invalid usage of bool + insert into test(id, expr) values(gen_id(g,1), 'select ''true'' is unknown as result from rdb$database'); -- invalid usage of bool + + insert into test(id, expr) values(gen_id(g,1), 'select ''true'' is unknown as result from rdb$database'); -- invalid usage of bool + insert into test(id, expr) values(gen_id(g,1), 'select ''true'' is true as result from rdb$database'); -- invalid usage of bool + insert into test(id, expr) values(gen_id(g,1), 'select true and ''false'' as result from rdb$database'); -- -Invalid usage of boolean expression + insert into test(id, expr) values(gen_id(g,1), 'select ''true'' and false as result from rdb$database'); -- -Invalid usage of boolean expression + + + -- convers error: + insert into test(id, expr) values(gen_id(g,1), 'select true = ''unknown'' as result from rdb$database'); -- convers error + insert into test(id, expr) values(gen_id(g,1), 'select true in (''unknown'', ''false'', ''true'') as result from rdb$database'); -- convers error + insert into test(id, expr) values(gen_id(g,1), 'select cast(''true'' as blob) > false as result from rdb$database'); + insert into test(id, expr) values(gen_id(g,1), 'select list(b, '''') > false as result from (select ''true'' as b from rdb$database)'); + commit; + + set list on; + set term ^; + execute block returns( + expr_no int, + run_expr type of column test.expr, + raised_gds int, + raised_sql char(6) + ) as + declare bool_result boolean; + begin + for + select id, expr + from test + order by id + into expr_no, run_expr + do begin + raised_gds=null; + raised_sql=null; + begin + execute statement run_expr into bool_result; + when any do + begin + raised_gds=gdscode; + raised_sql=sqlstate; + end + end + suspend; + end + end + ^ + set term ;^ + commit; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + EXPR_NO 1 + RESULT + + + + EXPR_NO 2 + RESULT + + + + EXPR_NO 3 + RESULT + + + + EXPR_NO 4 + RESULT + + + + EXPR_NO 5 + RESULT + + + + EXPR_NO 6 + RESULT + + + + EXPR_NO 7 + RESULT + + + + EXPR_NO 8 + RESULT + + + + EXPR_NO 9 + RESULT + + + + EXPR_NO 10 + RESULT + + + + EXPR_NO 11 + RESULT + + + + EXPR_NO 12 + RESULT + + + + EXPR_NO 13 + RESULT + + + + EXPR_NO 14 + RESULT + + + + EXPR_NO 15 + RESULT + + + + EXPR_NO 16 + RESULT + + + + EXPR_NO 17 + RESULT + + + + EXPR_NO 18 + RESULT + + + + EXPR_NO 19 + RESULT + + + + EXPR_NO 20 + RESULT + + + + EXPR_NO 21 + RUN_EXPR select true between not true and not false as result from rdb$database + RAISED_GDS 335544569 + RAISED_SQL 42000 + + EXPR_NO 22 + RUN_EXPR select true between not false and true as result from rdb$database + RAISED_GDS 335544569 + RAISED_SQL 42000 + + EXPR_NO 23 + RUN_EXPR select (not 'true') as result from rdb$database + RAISED_GDS 335544569 + RAISED_SQL 22000 + + EXPR_NO 24 + RUN_EXPR select not 'faLSe' is true as result from rdb$database + RAISED_GDS 335544569 + RAISED_SQL 22000 + + EXPR_NO 25 + RUN_EXPR select 'true' is not false as result from rdb$database + RAISED_GDS 335544569 + RAISED_SQL 22000 + + EXPR_NO 26 + RUN_EXPR select 'true' is distinct from not 'unknown' as result from rdb$database + RAISED_GDS 335544569 + RAISED_SQL 22000 + + EXPR_NO 27 + RUN_EXPR select 'true' is distinct from (not false and 'false') as result from rdb$database + RAISED_GDS 335544569 + RAISED_SQL 22000 + + EXPR_NO 28 + RUN_EXPR select 'true' is not false as result from rdb$database + RAISED_GDS 335544569 + RAISED_SQL 22000 + + EXPR_NO 29 + RUN_EXPR select true = not 'false' as result from rdb$database + RAISED_GDS 335544569 + RAISED_SQL 22000 + + EXPR_NO 30 + RUN_EXPR select 'false' is not distinct from not true or 'unknown' as result from rdb$database + RAISED_GDS 335544569 + RAISED_SQL 22000 + + EXPR_NO 31 + RUN_EXPR select true = not not 'true' as result from rdb$database + RAISED_GDS 335544569 + RAISED_SQL 22000 + + EXPR_NO 32 + RUN_EXPR select 'true' is unknown as result from rdb$database + RAISED_GDS 335544569 + RAISED_SQL 22000 + + EXPR_NO 33 + RUN_EXPR select 'true' is unknown as result from rdb$database + RAISED_GDS 335544569 + RAISED_SQL 22000 + + EXPR_NO 34 + RUN_EXPR select 'true' is true as result from rdb$database + RAISED_GDS 335544569 + RAISED_SQL 22000 + + EXPR_NO 35 + RUN_EXPR select true and 'false' as result from rdb$database + RAISED_GDS 335544569 + RAISED_SQL 22000 + + EXPR_NO 36 + RUN_EXPR select 'true' and false as result from rdb$database + RAISED_GDS 335544569 + RAISED_SQL 22000 + + EXPR_NO 37 + RUN_EXPR select true = 'unknown' as result from rdb$database + RAISED_GDS 335544334 + RAISED_SQL 22018 + + EXPR_NO 38 + RUN_EXPR select true in ('unknown', 'false', 'true') as result from rdb$database + RAISED_GDS 335544334 + RAISED_SQL 22018 + + EXPR_NO 39 + RUN_EXPR select cast('true' as blob) > false as result from rdb$database + RAISED_GDS 335544334 + RAISED_SQL 22018 + + EXPR_NO 40 + RUN_EXPR select list(b, '') > false as result from (select 'true' as b from rdb$database) + RAISED_GDS 335544334 + RAISED_SQL 22018 + """ + +@pytest.mark.version('>=3.0') +def test_core_5167_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5174.py b/tests/bugs/test_core_5174.py new file mode 100644 index 00000000..532b2c35 --- /dev/null +++ b/tests/bugs/test_core_5174.py @@ -0,0 +1,120 @@ +#coding:utf-8 +# +# id: bugs.core_5174 +# title: Wrong sequence of savepoints may be produced by selectable procedure +# decription: +# tracker_id: CORE-5174 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + create or alter procedure ins_t1 as begin end; + create or alter procedure ins_t2 as begin end; + commit; + + recreate table t (f varchar(20)); + recreate exception Boom 'Boom'; + + set term ^; + create or alter procedure ins_t2 returns (a integer) as + begin + a = coalesce(rdb$get_context('USER_TRANSACTION', 'a'),0); + rdb$set_context('USER_TRANSACTION', 'a', a+1); + insert into t values (:a); + if (a = 2) then + exception Boom; + end + ^ + create or alter procedure ins_t1 returns (a integer) as + begin + a = 100; + while (1=1) do + begin + begin + insert into t values (:a||'_point_a'); + execute procedure ins_t2 returning_values a; + if (a > 4) then + leave; + suspend; + insert into t values (:a||'_point_b'); + when any do begin insert into t values (-1); end + end + end + end^ + commit^ + + execute block returns (a integer) as + begin + for select a from ins_t1 into :a do + begin + insert into t values (:a||'_point_c'); + suspend; + insert into t values (:a||'_point_d'); + end + end^ + set term ;^ + + select * from t; + -- ... + -- 1_point_d + -- 1_point_b + -- 1_point_a <<< this record was absent before 2016-03-28 in 4.0, see: https://github.com/FirebirdSQL/firebird/commit/6ae11453944c1d37789dd1c11913cd31829de341 + -- -1 + -- 1_point_a + -- ... + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 0 + 1 + 3 + 4 + + 100_point_a + 0 + 0_point_c + 0_point_d + 0_point_b + 0_point_a + 1 + 1_point_c + 1_point_d + 1_point_b + 1_point_a + -1 + 1_point_a + 3 + 3_point_c + 3_point_d + 3_point_b + 3_point_a + 4 + 4_point_c + 4_point_d + 4_point_b + 4_point_a + 5 + """ + +@pytest.mark.version('>=4.0') +def test_core_5174_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5183.py b/tests/bugs/test_core_5183.py new file mode 100644 index 00000000..406c6e55 --- /dev/null +++ b/tests/bugs/test_core_5183.py @@ -0,0 +1,157 @@ +#coding:utf-8 +# +# id: bugs.core_5183 +# title: Regression: line/column numbering may be twisted if alias.name syntax is used +# decription: +# NB: it's very _poor_ idea to compare line and column values from text of failed statement +# and some concrete values because they depend on position of statement whithin text ('sqltxt') +# which we going to execute by ISQL. +# Thus it was decided to check only that at final point we will have error log with only ONE +# unique pair of values {line, column} - no matter which exactly values are stored there. +# For this purpose we run script, filter its log (which contains text like: -At line NN, column MM) +# and parse (split) these lines on tokens. We extract tokens with number line and column and add +# each pair to the dictionary (Python; Map in java). Name of variable for this dict. = 'pairs'. +# +# Key point: length of this dictionary should be 1. +# +# Confirmed on 3.0.0.32493 - line and column numbers differed: +# -At line 6, column 35 +# -At line 9, column 5 +# (thus length of 'pairs' is 2). +# +# On 2.5.6.27001, 4.0.0.145 -- all fine, numbers of line and column is the same, length of 'pairs' = 1. +# +# tracker_id: CORE-5183 +# min_versions: ['2.5.6'] +# versions: 2.5.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# import re +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# sqltxt=''' +# set term ^; +# execute block +# returns (id int) +# as +# begin +# select y +# from rdb$database x where z = 0 +# into id; +# suspend; +# end^ +# +# execute block +# returns (id int) +# as +# begin +# select x.y +# from rdb$database x where z = 0 +# into id; +# suspend; +# end^ +# ''' +# +# f_checksql=open( os.path.join(context['temp_directory'],'tmp_5183.sql'), 'w') +# f_checksql.write(sqltxt) +# flush_and_close( f_checksql ) +# +# f_isqllog=open( os.path.join(context['temp_directory'],'tmp_5183.log'), 'w') +# subprocess.call([context['isql_path'], dsn, "-i", f_checksql.name], stdout=f_isqllog, stderr=subprocess.STDOUT) +# flush_and_close( f_isqllog ) +# +# # Output +# # -At line 6, column 35 +# # -At line 9, column 5 +# # ^ ^ ^ ^ ^ +# # | | | | | +# # 1 2 3 4 5 <<< indices for tokens +# +# pattern = re.compile("-At line[\\s]+[0-9]+[\\s]*,[\\s]*column[\\s]+[0-9]+") +# pairs={} +# with open( f_isqllog.name,'r') as f: +# for line in f: +# if pattern.match(line): +# tokens=re.split('\\W+', line) +# pairs[ tokens[3] ] = tokens[5] +# +# print( 'Number of distinct pairs {line,column}: %d ' % len(pairs) ) +# +# # This is sample of WRONG content of dictionary (it was so till 3.0.0.32493): +# # {'9': '5', '6': '35'} +# # Number of distinct pairs {line,column}: 2 +# +# +# # Cleanup: +# ########## +# time.sleep(1) +# cleanup( (f_isqllog,f_checksql) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Number of distinct pairs {line,column}: 1 + """ + +@pytest.mark.version('>=2.5.6') +@pytest.mark.xfail +def test_core_5183_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5193.py b/tests/bugs/test_core_5193.py new file mode 100644 index 00000000..47dcd4b5 --- /dev/null +++ b/tests/bugs/test_core_5193.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: bugs.core_5193 +# title: Precedence problem with operator IS +# decription: +# Checked on WI-V3.0.1.32518, WI-T4.0.0.184 +# +# tracker_id: CORE-5193 +# min_versions: ['3.0.1'] +# versions: 3.0.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select not false is true is unknown as boo1 from rdb$database; + select not false = true is not unknown as boo2 from rdb$database; + select not unknown and not unknown is not unknown as boo3 from rdb$database; + select not not unknown is not unknown as boo4 from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + BOO1 + BOO2 + BOO3 + BOO4 + """ + +@pytest.mark.version('>=3.0.1') +def test_core_5193_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5194.py b/tests/bugs/test_core_5194.py new file mode 100644 index 00000000..2f5c1b37 --- /dev/null +++ b/tests/bugs/test_core_5194.py @@ -0,0 +1,184 @@ +#coding:utf-8 +# +# id: bugs.core_5194 +# title: Invalid computed by definition generated by isql -x +# decription: +# 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. +# Test checks that: +# 1) table is recreated successfully and consists of the same fields as before; +# 2) compiler STDERR (see var. 'f_apply_err') is empty. +# Confirmed: +# 1) wrong metadata generation on 4.0.0.130 +# 2) works fine on 4.0.0.132, 3.0.0.32474 +# +# tracker_id: CORE-5194 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('.* line \\d+ .*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# from subprocess import Popen +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# sql_ddl='''recreate table test( a timestamp, b computed by (current_timestamp - a) );''' +# +# f_init_sql = open( os.path.join(context['temp_directory'],'tmp_init_5194.sql'), 'w') +# f_init_sql.write(sql_ddl) +# flush_and_close( f_init_sql ) +# +# f_init_log = open( os.path.join(context['temp_directory'],'tmp_init_5194.log'), 'w') +# +# subprocess.call( [context['isql_path'], dsn, "-i", f_init_sql.name], +# stdout = f_init_log, +# stderr = subprocess.STDOUT +# ) +# # This file should be empty: +# flush_and_close( f_init_log ) +# +# f_xmeta_log = open( os.path.join(context['temp_directory'],'tmp_xmeta_5194.log'), 'w') +# f_xmeta_err = open( os.path.join(context['temp_directory'],'tmp_xmeta_5194.err'), 'w') +# +# subprocess.call( [context['isql_path'], dsn, "-x"], +# stdout = f_xmeta_log, +# stderr = f_xmeta_err +# ) +# +# # This file should contain metadata - table TEST definition with its COMPUTED BY column 'B': +# flush_and_close( f_xmeta_log ) +# +# # This file should be empty: +# flush_and_close( f_xmeta_err ) +# +# att1 = fdb.connect(dsn=dsn.encode()) +# cur1=att1.cursor() +# cur1.execute("drop table test") +# att1.commit() +# att1.close() +# +# # This should issue "There is no table TEST in this database": +# #runProgram('isql',[dsn, '-q','-user',user_name,'-pas',user_password],'show table test;') +# +# f_apply_log = open( os.path.join(context['temp_directory'],'tmp_apply_5194.log'), 'w') +# f_apply_err = open( os.path.join(context['temp_directory'],'tmp_apply_5194.err'), 'w') +# subprocess.call( [context['isql_path'], dsn, "-i", f_xmeta_log.name], +# stdout = f_apply_log, +# stderr = f_apply_err +# ) +# # Both of these files should be empty: +# flush_and_close( f_apply_log ) +# flush_and_close( f_apply_err ) +# +# # This should issue DDL of table TEST which was just created by extracted metadata: +# table_ddl=''' +# set list on; +# select +# rf.rdb$field_name +# ,ff.rdb$field_length +# ,ff.rdb$field_scale +# ,ff.rdb$field_type +# ,cast(ff.rdb$computed_source as varchar(100)) as rdb$computed_source +# from rdb$relation_fields rf +# join rdb$fields ff on rf.rdb$field_source = ff.rdb$field_name +# where rf.rdb$relation_name='TEST' +# order by rdb$field_name; +# ''' +# runProgram('isql',[dsn, '-q'],table_ddl) +# +# # No output should be here: +# with open( f_xmeta_err.name,'r') as f: +# print(f.read()) +# +# # No output should be here: +# with open( f_apply_log.name,'r') as f: +# print(f.read()) +# +# # No output should be here: +# with open( f_apply_err.name,'r') as f: +# for line in f: +# print( "APPLY_METADATA_STDERR: "+line ) +# +# +# # Cleanup +# ######### +# time.sleep(1) +# cleanup( (f_init_sql,f_init_log,f_xmeta_log,f_xmeta_err,f_apply_log,f_apply_err) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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') +@pytest.mark.xfail +def test_core_5194_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5201.py b/tests/bugs/test_core_5201.py new file mode 100644 index 00000000..15cb9e57 --- /dev/null +++ b/tests/bugs/test_core_5201.py @@ -0,0 +1,158 @@ +#coding:utf-8 +# +# id: bugs.core_5201 +# title: Return nonzero result code when restore fails on activating and creating deferred user index +# decription: +# ### NB ### +# According to Alex responce on letter 25-apr-2016 19:15, zero retcode returned ONLY when restore +# was done WITH '-verbose' switch, and this was fixed. When restoring wasdone without additional +# switches, retcode was NON zero and its value was 1. +# +# Test description. +# 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. +# +# Confirmed on: 3.0.0.32484, 4.0.0.142 - retcode was ZERO (and this was wrong); since 4.0.0.145 - all fine, retcode=2. +# +# tracker_id: CORE-5201 +# min_versions: ['2.5.6'] +# versions: 2.5.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + 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_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# thisdb = db_conn.database_name +# tmpbkp = os.path.splitext(thisdb)[0] + '.fbk' +# tmpres = os.path.splitext(thisdb)[0] + '.tmp' +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# f_backup=open( os.path.join(context['temp_directory'],'tmp_backup_5201.log'), 'w') +# subprocess.check_call([context['fbsvcmgr_path'], +# "localhost:service_mgr", +# "action_backup", +# "dbname", thisdb, +# "bkp_file", tmpbkp +# ], +# stdout=f_backup, stderr=subprocess.STDOUT) +# flush_and_close( f_backup ) +# +# f_restore=open( os.path.join(context['temp_directory'],'tmp_restore_5201.log'), 'w') +# try: +# # This is key point: before 4.0.0.145 restoring with '-v' key did assign retcode to zero +# # even in case when index could not be created because of errors. +# # Since 4.0.0.145 this call should assign retcode = 2: +# restore_out=subprocess.check_call([ context['gbak_path'], +# "-rep", +# "-v", +# tmpbkp, +# tmpres +# ], +# stdout=f_restore, stderr=subprocess.STDOUT) +# +# except subprocess.CalledProcessError as cpexc: +# # Final output of this test MUST have following line (confirmed on 3.0.0.32484: did not has this). +# print ('Restore finished with error code: '+str(cpexc.returncode)) +# +# flush_and_close( f_restore ) +# +# +# # Output STDOUT+STDERR of backup: they both should be EMPTY because we did not specify '-v' key: +# with open( f_backup.name,'r') as f: +# for line in f: +# print( "BACKUP LOG: "+line ) +# +# # Output STDOUT+STDERR of restoring with filtering text related to ERRORs: +# with open( f_restore.name,'r') as f: +# for line in f: +# if ' ERROR:' in line: +# print( "RESTORE LOG: "+line ) +# +# +# # Cleanup: +# ########## +# time.sleep(1) +# cleanup( (f_backup, f_restore, tmpbkp, tmpres) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Restore finished with error code: 2 + RESTORE LOG: gbak: ERROR:attempt to store duplicate value (visible to active transactions) in unique index "TEST_1_UNQ" + RESTORE LOG: gbak: ERROR: Problematic key value is ( = 1) + """ + +@pytest.mark.version('>=2.5.6') +@pytest.mark.xfail +def test_core_5201_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5207.py b/tests/bugs/test_core_5207.py new file mode 100644 index 00000000..e0d0b702 --- /dev/null +++ b/tests/bugs/test_core_5207.py @@ -0,0 +1,178 @@ +#coding:utf-8 +# +# id: bugs.core_5207 +# title: ISQL -X may generate invalid GRANT USAGE statements for domains +# decription: +# Test uses .fbk which was prepared on FB 2.5 (source .fdb contains single domain). +# After .fbk extration we start restore from it and extract metadata to log. +# Then we search metadata log for phrase 'GRANT USAGE ON DOMAIN' - it should NOT present there. +# Afterall, we try to apply extracted metadata to temp database (that was created auto by fbtest). +# If something will be broken we'll get: +# === +# APPLY STDERR: Statement failed, SQLSTATE = 42000 +# APPLY STDERR: Dynamic SQL Error +# APPLY STDERR: -SQL error code = -104 +# APPLY STDERR: -Token unknown - line 1, column 16 +# APPLY STDERR: -DOMAIN +# APPLY STDERR: At line in file /tmp_xmeta_5207.log +# WRONG GRANT: GRANT USAGE ON DOMAIN DM_INT TO PUBLIC; +# === +# Checked on: LI-T4.0.0.142 - works fine. +# +# tracker_id: CORE-5207 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import zipfile +# import subprocess +# import re +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# tmpbkp = os.path.join( context['temp_directory'], 'core_5207.fbk' ) +# tmpres = os.path.join( context['temp_directory'], 'tmp_core_5207.fdb' ) +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# zf = zipfile.ZipFile( os.path.join(context['files_location'],'core_5207.zip') ) +# zf.extractall( context['temp_directory'] ) +# zf.close() +# +# # Result: core_5207.fbk is extracted into context['temp_directory'] +# +# f_restore=open( os.path.join(context['temp_directory'],'tmp_restore_5207.log'), 'w') +# subprocess.check_call([context['fbsvcmgr_path'], +# "localhost:service_mgr", +# "action_restore", +# "bkp_file", tmpbkp, +# "dbname", tmpres, +# "res_replace" +# ], +# stdout=f_restore, stderr=subprocess.STDOUT) +# flush_and_close( f_restore ) +# +# # Result: database file 'tmp_core_5207.fdb' should be created after this restoring, +# # log ('tmp_restore_5207.log') must be EMPTY. +# +# f_xmeta_log = open( os.path.join(context['temp_directory'],'tmp_xmeta_5207.log'), 'w') +# f_xmeta_err = open( os.path.join(context['temp_directory'],'tmp_xmeta_5207.err'), 'w') +# +# subprocess.call( [context['isql_path'], "localhost:"+tmpres, "-x"], +# stdout = f_xmeta_log, +# stderr = f_xmeta_err +# ) +# +# # This file should contain metadata: +# flush_and_close( f_xmeta_log ) +# +# # This file should be empty: +# flush_and_close( f_xmeta_err ) +# +# f_apply_log = open( os.path.join(context['temp_directory'],'tmp_apply_5207.log'), 'w') +# f_apply_err = open( os.path.join(context['temp_directory'],'tmp_apply_5207.err'), 'w') +# +# subprocess.call( [context['isql_path'], dsn, "-i", f_xmeta_log.name], +# stdout = f_apply_log, +# stderr = f_apply_err +# ) +# +# # Both of these files should be empty: +# flush_and_close( f_apply_log ) +# flush_and_close( f_apply_err ) +# +# # Output STDOUT+STDERR of restoring and STDERR of metadata extraction: they both should be EMPTY: +# with open( f_restore.name,'r') as f: +# for line in f: +# print( "RESTORE LOG: "+line ) +# +# with open( f_xmeta_err.name,'r') as f: +# for line in f: +# print( "EXTRACT ERR: "+line ) +# +# with open( f_apply_log.name,'r') as f: +# for line in f: +# print( "APPLY STDOUT: "+line ) +# +# with open( f_apply_err.name,'r') as f: +# for line in f: +# print( "APPLY STDERR: "+line ) +# +# # Check that STDOUT of metadata extration (f_xmeta_log) does __not__ contain +# # statement like 'GRANT USAGE ON DOMAIN'. +# # Output must be empty here: +# # +# with open( f_xmeta_log.name,'r') as f: +# for line in f: +# if 'GRANT USAGE ON DOMAIN' in line: +# print( "WRONG GRANT: "+line ) +# +# +# # Cleanup: +# ########## +# +# # do NOT remove this pause otherwise some of logs will not be enable for deletion and test will finish with +# # Exception raised while executing Python test script. exception: WindowsError: 32 +# time.sleep(1) +# cleanup( (f_restore,f_xmeta_log,f_xmeta_err,f_apply_log,f_apply_err,tmpbkp,tmpres) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_5207_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5210.py b/tests/bugs/test_core_5210.py new file mode 100644 index 00000000..5b3edb63 --- /dev/null +++ b/tests/bugs/test_core_5210.py @@ -0,0 +1,138 @@ +#coding:utf-8 +# +# id: bugs.core_5210 +# title: Firebird 3.0 + fbclient 3.0 - POST_EVENT won't work +# decription: +# We create database-level trigger which sends event with name 'dml_event' on COMMIT. +# Then we do new connect and run thread with INSERT statement (with delay = 1.0 second), and wait +# NO MORE than sec. +# We should receive event during ~ 1.0 second. +# We have to consider result as FAIL if we do not receive event in seconds. +# Result of "events.wait(max4delivering)" will be non-empty dictionary with following key-value: +# {'dml_event': 1} - when all fine and client got event; +# {'dml_event': 0} - when NO event was delivered +# All such actions are repeated several times in order to increase probability of failure if something +# in FB will be broken. +# +# Confirmed wrong result on: 4.0.0.145, V3.0.0.32493 - with probability approx 60%. +# All fine on: T4.0.0.150, WI-V3.0.0.32496 (SS/SC/CS). +# +# PS. Event handling code in this text was adapted from fdb manual: +# http://pythonhosted.org/fdb/usage-guide.html#database-events +# +# tracker_id: CORE-5210 +# min_versions: ['2.5.6'] +# versions: 2.5.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + set term ^; + create or alter trigger trg_commit on transaction commit as + begin + post_event 'dml_event'; + end ^ + set term ;^ + commit; + + recreate table test(id int); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# def check_events(seqno): +# import fdb +# import threading +# import datetime +# import time +# from time import time +# import os +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # Utility function +# def send_events(command_list): +# cur=db_conn.cursor() +# for cmd in command_list: +# cur.execute(cmd) +# db_conn.commit() +# +# timed_event = threading.Timer(1.0, send_events, args=[["insert into test(id) values ( rand()*1000 )",]]) +# +# # Connection.event_conduit() takes a sequence of string event names as parameter, and returns +# # EventConduit instance. +# events = db_conn.event_conduit(['dml_event']) +# +# # To start listening for events it's necessary (starting from FDB version 1.4.2) +# # to call EventConduit.begin() method or use EventConduit's context manager interface +# # Immediately when begin() method is called, EventConduit starts to accumulate notifications +# # of any events that occur within the conduit's internal queue until the conduit is closed +# # (via the close() method) +# +# #print("Start listening for event") +# +# events.begin() +# +# timed_event.start() +# +# +# # Notifications about events are aquired through call to wait() method, that blocks the calling +# # thread until at least one of the events occurs, or the specified timeout (if any) expires, +# # and returns None if the wait timed out, or a dictionary that maps event_name -> event_occurrence_count. +# #t1 = datetime.datetime.now() +# t1 = time() +# max4delivering = 3 +# e = events.wait(max4delivering) +# t2 = time() +# #t2 = datetime.datetime.now() +# +# +# events.close() +# +# print(e) +# print( str(seqno)+': event was SUCCESSFULLY delivered.' if t2-t1 < max4delivering else str(seqno)+': event was NOT delivered for %.2f s (threshold is %.2f s)' % ( (t2-t1), max4delivering ) ) +# +# check_events(1) +# check_events(2) +# check_events(3) +# check_events(4) +# check_events(5) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + {'dml_event': 1} + 1: event was SUCCESSFULLY delivered. + + {'dml_event': 1} + 2: event was SUCCESSFULLY delivered. + + {'dml_event': 1} + 3: event was SUCCESSFULLY delivered. + + {'dml_event': 1} + 4: event was SUCCESSFULLY delivered. + + {'dml_event': 1} + 5: event was SUCCESSFULLY delivered. + """ + +@pytest.mark.version('>=2.5.6') +@pytest.mark.xfail +def test_core_5210_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5216.py b/tests/bugs/test_core_5216.py new file mode 100644 index 00000000..2909bb95 --- /dev/null +++ b/tests/bugs/test_core_5216.py @@ -0,0 +1,287 @@ +#coding:utf-8 +# +# id: bugs.core_5216 +# title: Provide location context (line/column numbers) for runtime errors raised inside EXECUTE BLOCK +# decription: +# Checked on 4.0.0.372, 3.0.1.32598 - works fine. +# NOTE: 2.5.x does not work as expected: some of 'line: ..., col: ...' messages are not displayed. +# +# tracker_id: CORE-5216 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('exception [\\d]+', 'exception K'), ('At line [\\d]+, column [\\d]+', 'At line N, column M'), ('-At block line: [\\d]+, col: [\\d]+', 'At block line: N, col: M')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate exception rio 'Exception w/o parameter test. Invalid value detected'; + recreate exception foo 'Exception with parameter test. Invalid value of BAR = @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); + commit; + + set term ^; + + + -- -Column unknown + -- -NON_EXISTING_COLUMN + execute block as + begin + execute statement 'select non_existing_column from rdb$database'; + end + ^ + + + -- 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. + execute block as + begin + execute statement ( + 'execute block(a int = ?) as ' + || 'begin ' + || ' update test set x = x/:a; ' + || 'end') (0); + end + ^ + + -- Statement failed, SQLSTATE = 42000 + -- validation error for variable R, value "*** null ***" + execute block as + begin + execute statement + ' + execute block as + declare r smallint not null; + begin + execute statement ''select null from rdb$database'' into r; + end + ' + ; + end + ^ + + -- Statement failed, SQLSTATE = 23000 + -- validation error for column "TEST"."X", value "*** null ***" + execute block as + begin + execute statement + ' + execute block as + declare x smallint; + begin + execute statement + '' + execute block as + begin + update test set x=null; + end + ''; + end + ' + ; + end + ^ + + + -- Statement failed, SQLSTATE = 23000 + -- validation error for column "TEST"."Y", value "*** null ***" + execute block as + begin + execute statement + ' + execute block as + declare x smallint; + begin + execute statement + '' + execute block as + declare x smallint; + begin + insert into test(id, x) values(2, 222); + end + ''; + end + ' + ; + end + ^ + + + -- Statement failed, SQLSTATE = 23000 + -- violation of PRIMARY or UNIQUE KEY constraint "TEST_PK" on table "TEST" + -- -Problematic key value is ("ID" = 1) + execute block as + begin + execute statement + ' + execute block as + declare x smallint; + begin + execute statement + '' + execute block as + declare x smallint; + begin + execute statement + '''' + execute block returns(x smallint) as + begin + insert into test(id, x, y) values(1, 200, 400) returning x into x; + suspend; + end + '''' into x; + end + ''; + end + ' + ; + end + ^ + + -- -RIO + -- -Exception w/o parameter test. Invalid value detected + execute block as + begin + execute statement + ' + execute block as + declare x smallint; + begin + execute statement + '' + execute block as + declare x smallint; + begin execute statement + '''' + execute block as + declare x smallint = 789; + begin + x = x * 100; + when any do + begin + exception rio; + end + end + '''' into x; end + ''; + end + ' + ; + end + ^ + + -- -FOO + -- -Exception with parameter test. Invalid value of BAR = *** null *** + execute block as + begin + execute statement + ' + execute block as + declare x smallint; + begin + execute statement + '' + execute block as + declare x smallint; + begin + execute statement + '''' + execute block as + declare x smallint; + begin + x = 99999; + when any do + begin + exception foo using(:x); + end + end + '''' + into x; + end + ''; + end + ' + ; + end + ^ + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + 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_core_5216_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_5217.py b/tests/bugs/test_core_5217.py new file mode 100644 index 00000000..3f574e6b --- /dev/null +++ b/tests/bugs/test_core_5217.py @@ -0,0 +1,63 @@ +#coding:utf-8 +# +# id: bugs.core_5217 +# title: ISQL -x may crash while exporting an exception with message text length > 127 bytes +# decription: +# +# tracker_id: CORE-5217 +# min_versions: ['2.5.6'] +# versions: 2.5.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate exception exc_test_a + '1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123'; + + recreate exception exc_test_b + '12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234'; + + recreate exception exc_test_c + '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345'; + + commit; + + set list on; + set count on; + select rdb$exception_name, rdb$message + from rdb$exceptions + order by rdb$exception_name; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$EXCEPTION_NAME EXC_TEST_A + RDB$MESSAGE 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123 + + RDB$EXCEPTION_NAME EXC_TEST_B + RDB$MESSAGE 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234 + + RDB$EXCEPTION_NAME EXC_TEST_C + RDB$MESSAGE 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345 + + Records affected: 3 + """ + +@pytest.mark.version('>=2.5.6') +def test_core_5217_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5218.py b/tests/bugs/test_core_5218.py new file mode 100644 index 00000000..e40bbc82 --- /dev/null +++ b/tests/bugs/test_core_5218.py @@ -0,0 +1,134 @@ +#coding:utf-8 +# +# id: bugs.core_5218 +# title: Explicitly defined names for NOT NULL constraints are not exported into script by ISQL -x +# decription: +# Checked on WI-V3.0.0.32501, WI-T4.0.0.155. +# +# tracker_id: CORE-5218 +# min_versions: ['2.5.6'] +# versions: 2.5.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table test( + f01 int constraint f01_nn not null constraint f01_pk primary key + ,f02 int constraint f02_nn not null constraint f02_uk unique + -- NB: 3.0 allows to skip reference of PK column from table that + --- is created now, i.e. one may to declare FK-field like this: + -- ... f03 references test + -- That's not so for 2.5.x: + ,f03 int constraint f03_nn not null + constraint f03_fk + references test( f01 ) + -- ^-- this must be specified in 2.5.x + ); + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# f_extract_meta_sql = open( os.path.join(context['temp_directory'],'tmp_5218_meta.log'), 'w') +# f_extract_meta_err = open( os.path.join(context['temp_directory'],'tmp_5218_meta.err'), 'w') +# subprocess.call( [context['isql_path'], dsn, "-x"], +# stdout = f_extract_meta_sql, +# stderr = f_extract_meta_err +# ) +# flush_and_close( f_extract_meta_sql ) +# flush_and_close( f_extract_meta_err ) +# +# ############### +# # CHECK RESULTS +# ############### +# +# # 1. STDERR for extracted metadata must be EMPTY. +# with open( f_extract_meta_err.name, 'r') as f: +# for line in f: +# if line.strip(): +# print('EXTRACTED METADATA ERR: '+line) +# +# # 2. STDLOG for extracted metadata: we must ouput all +# # lines with phrase 'CONSTRAINT' in order to check that this +# # keyword actually present for each initial declaration: +# +# with open( f_extract_meta_sql.name, 'r') as f: +# for line in f: +# if 'CONSTRAINT' in line: +# print( 'EXTRACTED METADATA LOG: '+line ) +# +# +# # Cleanup: +# ########## +# time.sleep(1) +# cleanup( (f_extract_meta_sql, f_extract_meta_err) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + EXTRACTED METADATA LOG: CREATE TABLE TEST (F01 INTEGER CONSTRAINT F01_NN NOT NULL, + EXTRACTED METADATA LOG: F02 INTEGER CONSTRAINT F02_NN NOT NULL, + EXTRACTED METADATA LOG: F03 INTEGER CONSTRAINT F03_NN NOT NULL, + EXTRACTED METADATA LOG: CONSTRAINT F01_PK PRIMARY KEY (F01), + EXTRACTED METADATA LOG: CONSTRAINT F02_UK UNIQUE (F02)); + EXTRACTED METADATA LOG: ALTER TABLE TEST ADD CONSTRAINT F03_FK FOREIGN KEY (F03) REFERENCES TEST (F01); + """ + +@pytest.mark.version('>=2.5.6') +@pytest.mark.xfail +def test_core_5218_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5220.py b/tests/bugs/test_core_5220.py new file mode 100644 index 00000000..e10d8a5c --- /dev/null +++ b/tests/bugs/test_core_5220.py @@ -0,0 +1,164 @@ +#coding:utf-8 +# +# id: bugs.core_5220 +# title: ISQL -X: double quotes are missed for COLLATE of CREATE DOMAIN statement when is from any non-ascii charset +# decription: +# We create in init_script two collations with non-ascii names and two varchar domains which use these collations. +# Then we extract metadata and save it to file as .sql script to be applied further. +# This script should contain CORRECT domains definition, i.e. collations should be enclosed in double quotes. +# We check correctness by removing from database all objects and applying this script: no errors should occur at that point. +# Then we extract metadata second time, store it to second .sql and COMPARE this file with result of first metadata extraction. +# These files should be equal, i.e. difference should be empty. +# +# Checked on WI-V3.0.0.32501, WI-T4.0.0.155. +# +# tracker_id: CORE-5220 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create collation "Циферки" for utf8 from unicode case insensitive 'NUMERIC-SORT=1'; + create collation "Испания" for iso8859_1 from es_es_ci_ai 'SPECIALS-FIRST=1';; + commit; + create domain "Артикулы" varchar(12) character set utf8 collate "Циферки"; + create domain "Комрады" varchar(40) character set iso8859_1 collate "Испания"; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# import difflib +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# f_extract_meta1_sql = open( os.path.join(context['temp_directory'],'tmp_5220_meta1.sql'), 'w') +# subprocess.call( ["isql", dsn, "-x"], +# stdout = f_extract_meta1_sql, +# stderr = subprocess.STDOUT +# ) +# f_extract_meta1_sql.close() +# +# f_remove_meta_sql = open( os.path.join(context['temp_directory'],'tmp_5220_kill.sql'), 'w') +# f_remove_meta_sql.write('drop domain "Комрады"; drop domain "Артикулы"; drop collation "Испания"; drop collation "Циферки"; commit; show domain; show collation;') +# f_remove_meta_sql.close() +# +# f_remove_meta_log = open( os.path.join(context['temp_directory'],'tmp_5220_kill.log'), 'w') +# subprocess.call( ["isql", dsn, "-ch", "utf8", "-i", f_remove_meta_sql.name], +# stdout = f_remove_meta_log, +# stderr = subprocess.STDOUT +# ) +# f_remove_meta_log.close() +# +# f_apply_meta_log = open( os.path.join(context['temp_directory'],'tmp_5220_apply.log'), 'w') +# subprocess.call( ["isql", dsn, "-ch", "utf8", "-i", f_extract_meta1_sql.name], +# stdout = f_apply_meta_log, +# stderr = subprocess.STDOUT +# ) +# f_apply_meta_log.close() +# +# +# f_extract_meta2_sql = open( os.path.join(context['temp_directory'],'tmp_5220_meta2.sql'), 'w') +# subprocess.call( ["isql", dsn, "-x"], +# stdout = f_extract_meta2_sql, +# stderr = subprocess.STDOUT +# ) +# f_extract_meta2_sql.close() +# +# time.sleep(1) +# +# ############### +# # CHECK RESULTS +# ############### +# +# # 1. Log f_remove_meta_log (REMOVING metadata) should contain only phrases about absence of domains and collations +# with open( f_remove_meta_log.name, 'r') as f: +# for line in f: +# if line.strip(): +# print('REMOVE METADATA LOG: '+line) +# f.close() +# +# # 2. Log f_apply_meta_log (result of APPLYING extracted metadata, file: f_extract_meta1_sql) should be EMPTY +# # (because collation names now should be enclosed in double quotes) +# with open( f_apply_meta_log.name, 'r') as f: +# for line in f: +# if line.strip(): +# print('APPLY EXTRACTED METADATA LOG: '+line) +# f.close() +# +# # 3. Log f_extract_meta2_sql should EXACTLY match to first extracted metadata log (f_extract_meta1_sql). +# # We compare these files using Python 'diff' package. +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_5220_meta_diff.txt'), 'w') +# +# f_old=[] +# f_new=[] +# +# f_old.append(f_extract_meta1_sql) # tmp_5220_meta1.sql -- extracted metadata just after 'init_script' was done +# f_new.append(f_extract_meta2_sql) # tmp_5220_meta2.sql -- extracted metadata after drop all object and applying 'f_extract_meta1_sql' +# +# for i in range(len(f_old)): +# old_file=open(f_old[i].name,'r') +# new_file=open(f_new[i].name,'r') +# +# f_diff_txt.write( ''.join( difflib.unified_diff( old_file.readlines(), new_file.readlines() ) ) ) +# +# old_file.close() +# new_file.close() +# +# f_diff_txt.close() +# +# # Should be EMPTY: +# ################## +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# print( 'METADATA DIFF:' + ' '.join(line.split()).upper() ) +# f.close() +# +# ##################################################################### +# # Cleanup: +# +# f_list=[] +# f_list.append(f_extract_meta1_sql) +# f_list.append(f_extract_meta2_sql) +# f_list.append(f_apply_meta_log) +# f_list.append(f_remove_meta_log) +# f_list.append(f_remove_meta_sql) +# f_list.append(f_diff_txt) +# +# for i in range(len(f_list)): +# if os.path.isfile(f_list[i].name): +# os.remove(f_list[i].name) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + REMOVE METADATA LOG: There are no domains in this database + REMOVE METADATA LOG: There are no user-defined collations in this database + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_5220_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5222.py b/tests/bugs/test_core_5222.py new file mode 100644 index 00000000..df8d6ab8 --- /dev/null +++ b/tests/bugs/test_core_5222.py @@ -0,0 +1,272 @@ +#coding:utf-8 +# +# id: bugs.core_5222 +# title: SELECT WITH LOCK may raise unexpected update conflict errors under concurrent load +# decription: +# Prototype: https://groups.yahoo.com/neo/groups/firebird-support/conversations/messages/128920 +# Done with suggestions from dimitr, see letter 01-may-2016 09:15. +# Confirmed on WI-V3.0.0.32366, WI-V3.0.0.32483, 3.0.0.32501 (SS,SC,CS) - it was enough to +# async. start THREE child ISQLs sessions, one or two of them always raise exception after +# few seconds with text: 'deadlock / update conflicts' and could not finish its job. +# +# Checked on: WI-V3.0.0.32503, 3.0.1.32570, WI-T4.0.0.157 - works fine. +# Checked on 4.0.0.322 (Classic, SuperClassic, SuperServer) - works OK. +# +# 12.08.2018 ::: NB ::: +# It is unclear now how this test can be implemented on 4.0 after introduction of READ CONSISTENCY +# with default value ReadConsistency = 1. According to doc: +# === +# If ReadConsistency set to 1 (by default) engine ignores +# [NO] RECORD VERSION flags and makes all read-committed +# transactions READ COMMITTED READ CONSISTENCY. +# === +# +# Also, doc\\README.read_consistency.md says that: +# "Old read-committed isolation modes (**RECORD VERSION** and **NO RECORD VERSION**) are still +# allowed but considered as legacy and not recommended to use." +# +# This mean that one can NOT to check issues of this ticket under 4.0 using default (and recommended) +# value of config parameter 'ReadConsistency'. +# For that reason it was decided to make new EMPTY section of test for 4.0. +# +# tracker_id: CORE-5222 +# min_versions: ['3.0.0'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create or alter procedure p_increment as begin end; + commit; + recreate table gen_tab( + id bigint primary key + ); + recreate table gen_log ( + id bigint primary key, + id_new bigint not null, + id_diff bigint not null + ); + + set term ^; + alter procedure p_increment (a_iter_cnt int default 1000) + returns ( + proc_start timestamp, + selected_id bigint, + proc_finish timestamp + ) as + declare i bigint; + declare id_new bigint; + begin + i = 1; + proc_start = 'now'; + while (i <= a_iter_cnt ) do + begin + in autonomous transaction do + begin + + select id + from gen_tab with lock -- this raised SQLSTATE = 40001 / -update conflicts with concurrent update + into selected_id; + i = i + 1; + + id_new = selected_id + 1; + insert into gen_log(id, id_new, id_diff) + values( :selected_id, :id_new, :id_new - :selected_id); + + update gen_tab set id = :id_new + where id = :selected_id; + + end + end + proc_finish = 'now'; + + suspend; -- outputs row with three fields: 'PROC_START ', 'SELECTED_ID ', 'PROC_FINISH ' + end ^ + set term ;^ + commit; + + insert into gen_tab (id) values (0); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# from subprocess import Popen +# import re +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# +# f_run_sql=open( os.path.join(context['temp_directory'],'tmp_5222_run.sql'), 'w') +# f_run_sql.write(''' --show version; +# commit; +# set list on; +# set transaction read committed no record_version lock timeout 3; +# select current_timestamp as before_proc +# from rdb$database; +# +# select * from p_increment(10); +# +# select current_timestamp as after_proc +# from rdb$database; +# ''') +# f_run_sql.close() +# +# ########################################################################################## +# # Launching several concurrent child ISQL processes which perform script from `f_run_sql` +# ########################################################################################## +# planned_dml_attachments = 3 +# +# f_list = [] +# p_list = [] +# +# +# for i in range(0, planned_dml_attachments): +# sqllog=open( os.path.join(context['temp_directory'],'tmp_dml_5222_'+str(i)+'.log'), 'w') +# f_list.append(sqllog) +# +# for i in range(len(f_list)): +# p_isql=Popen( [ context['isql_path'] , dsn, "-i", f_run_sql.name ], +# stdout=f_list[i], +# stderr=subprocess.STDOUT +# ) +# p_list.append(p_isql) +# +# time.sleep(7) +# +# for i in range(len(f_list)): +# f_list[i].close() +# +# for i in range(len(p_list)): +# p_list[i].terminate() +# +# # 12.08.2016: added small delay because it's possible to get: +# # WindowsError: +# # 32 +# # The process cannot access the file because it is being used by another process +# +# time.sleep(2) +# +# ########################### +# # CHECK RESULTS and CLEANUP +# ########################### +# +# # 1. Each log _should_ contain ONLY following lines: +# # BEFORE_PROC 2016-05-03 09:27:57.6210 +# # PROC_START 2016-05-03 09:27:57.6210 +# # SELECTED_ID 1569 +# # PROC_FINISH 2016-05-03 09:28:04.0740 +# # AFTER_PROC 2016-05-03 09:28:04.0740 +# # 2. _NO_ log should contain 'SQLSTATE = 40001' +# +# # Open every log and print 1st word from each line, ignoring values of timestamp and ID. +# # Then close log and remove it: +# +# pattern = re.compile("BEFORE_PROC*|PROC_START*|SELECTED_ID*|PROC_FINISH*|AFTER_PROC*") +# for i in range(len(f_list)): +# with open( f_list[i].name, 'r') as f: +# for line in f: +# if line.split(): +# if pattern.match(line): +# print( 'EXPECTED, LOG #'+str(i)+': '+line.split()[0] ) +# else: +# print( 'UNEXPECTED, LOG #'+str(i)+': '+ line ) +# f.close() +# os.remove(f_list[i].name) +# +# os.remove(f_run_sql.name) +# +# # Sample of WRONG result (got on 3.0.0.32483): +# # =============== +# # EXPECTED, LOG #0: BEFORE_PROC +# # EXPECTED, LOG #0: PROC_START +# # EXPECTED, LOG #0: SELECTED_ID +# # EXPECTED, LOG #0: PROC_FINISH +# # EXPECTED, LOG #0: AFTER_PROC +# # EXPECTED, LOG #1: BEFORE_PROC +# # EXPECTED, LOG #1: PROC_START +# # EXPECTED, LOG #1: SELECTED_ID +# # EXPECTED, LOG #1: PROC_FINISH +# # EXPECTED, LOG #1: AFTER_PROC +# # EXPECTED, LOG #2: BEFORE_PROC +# # - EXPECTED, LOG #2: PROC_START +# # - EXPECTED, LOG #2: SELECTED_ID +# # - EXPECTED, LOG #2: PROC_FINISH +# # + UNEXPECTED, LOG #2: Statement failed, SQLSTATE = 40001 +# # + UNEXPECTED, LOG #2: deadlock +# # + UNEXPECTED, LOG #2: -update conflicts with concurrent update +# # + UNEXPECTED, LOG #2: -concurrent transaction number is 32 +# # + UNEXPECTED, LOG #2: -At procedure 'P_INCREMENT' line: 17, col: 17 +# # + UNEXPECTED, LOG #2: After line 6 in file C:\\MIX +# irebird\\QA +# bt-repo mp mp_5222_run.sql +# # EXPECTED, LOG #2: AFTER_PROC +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + EXPECTED, LOG #0: BEFORE_PROC + EXPECTED, LOG #0: PROC_START + EXPECTED, LOG #0: SELECTED_ID + EXPECTED, LOG #0: PROC_FINISH + EXPECTED, LOG #0: AFTER_PROC + + EXPECTED, LOG #1: BEFORE_PROC + EXPECTED, LOG #1: PROC_START + EXPECTED, LOG #1: SELECTED_ID + EXPECTED, LOG #1: PROC_FINISH + EXPECTED, LOG #1: AFTER_PROC + + EXPECTED, LOG #2: BEFORE_PROC + EXPECTED, LOG #2: PROC_START + EXPECTED, LOG #2: SELECTED_ID + EXPECTED, LOG #2: PROC_FINISH + EXPECTED, LOG #2: AFTER_PROC + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_5222_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +# test_script_2 +#--- +# +# +#--- +#act_2 = python_act('db_2', test_script_2, substitutions=substitutions_2) + + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_5222_2(db_2): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5225.py b/tests/bugs/test_core_5225.py new file mode 100644 index 00000000..467800aa --- /dev/null +++ b/tests/bugs/test_core_5225.py @@ -0,0 +1,105 @@ +#coding:utf-8 +# +# id: bugs.core_5225 +# title: Authentication end with first plugin that has the user but auth fails; should continue with next plugin +# decription: +# We create two users with the same name, 1st using plugin Srp, 2nd - via Legacy. +# Then we try to establish subsequent attachments via ES/EDS for each of them. +# No error should occur. +# +# Confirmed exception on 3.0.0 for plugin that was specified as SECOND in firebird.conf, got: +# Statement failed, SQLSTATE = 42000 +# Execute statement error at attach : +# 335544472 : Your user name and password are not defined <...> +# +# Works fine on: +# fb30Cs, build 3.0.4.32947: OK, 2.907s. +# FB30SS, build 3.0.4.32963: OK, 1.140s. +# FB40CS, build 4.0.0.955: OK, 3.531s. +# FB40SS, build 4.0.0.967: OK, 1.312s. +# +# tracker_id: CORE-5225 +# min_versions: ['3.0.1'] +# versions: 3.0.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + create or alter user tmp$c5225 password 'srp' using plugin Srp; + create or alter user tmp$c5225 password 'leg' using plugin Legacy_UserManager; + commit; + + set term ^; + execute block returns(whoami_leg varchar(31)) as + begin + execute statement 'select current_user from rdb$database' + on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') + as user 'tmp$c5225' password 'leg' + into whoami_leg; + suspend; + end + ^ + set term ;^ + commit; + + set term ^; + execute block returns(whoami_srp varchar(31)) as + begin + execute statement 'select current_user from rdb$database' + on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') + as user 'tmp$c5225' password 'srp' + into whoami_srp; + 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; + + drop user tmp$c5225 using plugin Srp; + drop user tmp$c5225 using plugin Legacy_UserManager; + commit; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHOAMI_LEG TMP$C5225 + WHOAMI_SRP TMP$C5225 + """ + +@pytest.mark.version('>=3.0.1') +def test_core_5225_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5229.py b/tests/bugs/test_core_5229.py new file mode 100644 index 00000000..b7992dc3 --- /dev/null +++ b/tests/bugs/test_core_5229.py @@ -0,0 +1,126 @@ +#coding:utf-8 +# +# id: bugs.core_5229 +# title: Allow to enforce IPv4 or IPv6 in URL-like connection strings +# decription: +# Checked on 4.0.0.256 (SS, SC), 3.0.1.32531 (SS,SC,CS) - all on Windows XP (inet4 only was avaliable). +# Additional check: +# 4.0.0.1635: OK, 1.635s. +# 4.0.0.1633: OK, 2.541s. +# 3.0.5.33180: OK, 1.311s. +# 3.0.5.33178: OK, 1.836s. +# - with both inet4 and inet6 +# +# tracker_id: CORE-5229 +# min_versions: ['3.0.1'] +# versions: 3.0.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# this_fdb=os.path.join(context['temp_directory'],'bugs.core_5229.fdb') +# who = user_name +# pwd = user_password +# +# sql_chk=''' +# 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://%(this_fdb)s'; +# +# select mon$remote_protocol as procotol_when_connect_from_isql +# from mon$attachments where mon$attachment_id = current_connection; +# +# set term ^; +# execute block returns(protocol_when_connect_by_es_eds varchar(20) ) as +# declare stt varchar(255) = 'select mon$remote_protocol from mon$attachments where mon$attachment_id = current_connection'; +# begin +# for +# execute statement (stt) +# on external 'inet4://%(this_fdb)s' +# as user '%(who)s' password '%(pwd)s' +# into protocol_when_connect_by_es_eds +# do +# suspend; +# end +# ^ +# set term ;^ +# commit; +# +# -- since 27.10.2019: +# connect 'inet6://%(this_fdb)s'; +# +# select mon$remote_protocol as procotol_when_connect_from_isql +# from mon$attachments where mon$attachment_id = current_connection; +# +# set term ^; +# execute block returns(protocol_when_connect_by_es_eds varchar(20) ) as +# declare stt varchar(255) = 'select mon$remote_protocol from mon$attachments where mon$attachment_id = current_connection'; +# begin +# for +# execute statement (stt) +# on external 'inet6://%(this_fdb)s' +# as user '%(who)s' password '%(pwd)s' +# into protocol_when_connect_by_es_eds +# 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; +# ''' +# runProgram('isql',[ 'inet4://'+this_fdb, '-q'], sql_chk % locals() ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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 + """ + +@pytest.mark.version('>=3.0.1') +@pytest.mark.xfail +def test_core_5229_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5231.py b/tests/bugs/test_core_5231.py new file mode 100644 index 00000000..0da286f7 --- /dev/null +++ b/tests/bugs/test_core_5231.py @@ -0,0 +1,164 @@ +#coding:utf-8 +# +# id: bugs.core_5231 +# title: EXECUTE STATEMENT: BLR error if more than 256 output parameters exist +# decription: +# 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). +# +# Confirmed bug on WI-T4.0.0.184 for number of output args >= 256: +# Statement failed, SQLSTATE = HY000 +# invalid request BLR at offset 7157 +# -BLR syntax error: expected statement at offset 7158, encountered 0 +# Checked on WI-V3.0.1.32518, WI-T4.0.0.197 - works fine. +# +# tracker_id: CORE-5231 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# ####################### N U M B E R O F O U T P U T A R G S. ########### +# sp_args_count=5000 +# ################################################################################### +# +# sql_pref='''set term ^; +# execute block as +# begin +# execute statement 'drop procedure sp_test'; +# when any do begin end +# end ^ +# commit ^ +# create or alter procedure sp_test returns ( +# ''' +# +# f_ddl_sql = open( os.path.join(context['temp_directory'],'tmp_5231_ddl.sql'), 'w') +# f_ddl_sql.write(sql_pref) +# +# delimiter='' +# for i in range(sp_args_count): +# f_ddl_sql.write( '%so%s int' % (delimiter, str(i)) ) +# delimiter=',' +# +# f_ddl_sql.write( +# ''') as begin +# for execute statement 'select +# ''' +# ) +# +# delimiter='' +# for i in range(sp_args_count): +# f_ddl_sql.write( '%s%s' % (delimiter, str(i)) ) +# delimiter=',' +# f_ddl_sql.write(" from rdb$database'\\ninto ") +# +# delimiter='' +# for i in range(sp_args_count): +# f_ddl_sql.write( '%so%s' % (delimiter, str(i)) ) +# delimiter=',' +# +# sql_suff=''' +# do suspend; +# end^ +# set term ;^ +# commit; +# set list on; +# select * from sp_test; +# ''' +# f_ddl_sql.write(sql_suff) +# flush_and_close( f_ddl_sql ) +# +# f_run_log=open( os.path.join(context['temp_directory'],'tmp_5231_run.log'), 'w') +# f_run_err=open( os.path.join(context['temp_directory'],'tmp_5231_run.err'), 'w') +# +# subprocess.call([context['isql_path'], dsn, "-i", f_ddl_sql.name], +# stdout=f_run_log, +# stderr=f_run_err) +# flush_and_close( f_run_log ) +# flush_and_close( f_run_err ) +# +# with open( f_run_err.name,'r') as f: +# for line in f: +# if line.split(): +# print('UNEXPECTED STDERR: '+line) +# +# with open( f_run_log.name,'r') as f: +# for line in f: +# if line.split() and not line.startswith('O'): +# print('UNEXPECTED STDLOG: '+line) +# +# # CLEANUP +# ######### +# time.sleep(1) +# cleanup( (f_ddl_sql, f_run_log, f_run_err) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_5231_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5236.py b/tests/bugs/test_core_5236.py new file mode 100644 index 00000000..473bc109 --- /dev/null +++ b/tests/bugs/test_core_5236.py @@ -0,0 +1,112 @@ +#coding:utf-8 +# +# id: bugs.core_5236 +# title: IN/ANY/ALL predicates may cause sub-optimal (late filtering) execution of joins +# decription: +# Plan BEFORE fix was (confirmed on 4.0.0.258): +# ... +# Select Expression +# -> Filter +# -> 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 +# -> Nested Loop Join (inner) +# -> 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) +# +# +# tracker_id: CORE-5236 +# min_versions: ['3.0.1'] +# versions: 3.0.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table dp_registro_oest( + autoinc_registro int primary key using index pk_dp_registro_oest, + registro_pri_roest integer not null, + registro_sec_roest integer not null + ); + + recreate table dp_recibo( + codigo_rec bigint primary key, + registro_rec integer not null, + competencia_rec varchar(6) not null, + unique(registro_rec, competencia_rec) using index unq1_dp_recibo + ); + + recreate table dp_registro( + autoinc_registro integer primary key using index pk_dp_registro + ); + + + alter table dp_registro_oest + add constraint fk_dp_registro_oest_1 foreign key (registro_pri_roest) + references dp_registro (autoinc_registro) on update cascade + ,add constraint fk_dp_registro_oest_2 foreign key (registro_sec_roest) + references dp_registro (autoinc_registro) on update cascade + ,add constraint unq1_dp_registro_oest unique (registro_pri_roest, registro_sec_roest) + ; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set explain on; + select 1 + from dp_recibo + inner join dp_registro on dp_registro.autoinc_registro = dp_recibo.registro_rec + where + dp_registro.autoinc_registro in ( + select registro_sec_roest + from dp_registro_oest + where registro_pri_roest = 1 + ) + ; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Select Expression + -> 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) + """ + +@pytest.mark.version('>=3.0.1') +def test_core_5236_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5241.py b/tests/bugs/test_core_5241.py new file mode 100644 index 00000000..d8ee7600 --- /dev/null +++ b/tests/bugs/test_core_5241.py @@ -0,0 +1,121 @@ +#coding:utf-8 +# +# id: bugs.core_5241 +# title: Affected rows are not counted for some update operations with views +# decription: +# Confirmed big: WI-T4.0.0.184, WI-V2.5.6.27008 +# Works fine on: WI-V3.0.1.32518, WI-T4.0.0.197 +# +# tracker_id: CORE-5241 +# min_versions: ['2.5.6'] +# versions: 2.5.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate view v_test_b as select 1 i from rdb$database; + recreate view v_test_a as select 1 i from rdb$database; + commit; + recreate table test (col int); + recreate view v_test_a as select col from test; + recreate view v_test_b as select col from v_test_a; + commit; + + insert into test values (1); + commit; + + set list on; + + set term ^; + + execute block returns (out_table int, out_view_a int, out_view_b int) + as + begin + update test set col = 2; + out_table = row_count; + + update v_test_a set col = 2; + out_view_a = row_count; + + update v_test_b set col = 2; + out_view_b = row_count; + + suspend; + + end^ + + recreate trigger v_test_a_bu for v_test_a before update as begin end^ + recreate trigger v_test_b_bu for v_test_b before update as begin end^ + commit^ + + execute block returns (out_table int, out_view_a int, out_view_b int) + as + begin + + + update test set col = 2; + out_table = row_count; + + update v_test_a set col = 2; + out_view_a = row_count; + + update v_test_b set col = 2; + out_view_b = row_count; + + suspend; + + end^ + + execute block returns (out_table int, out_view_a int, out_view_b int) + as + begin + + update v_test_a set col = 2; + out_view_a = row_count; + + update v_test_b set col = 2; + out_view_b = row_count; + + + update test set col = 2; + out_table = row_count; + + suspend; + + end^ + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + OUT_TABLE 1 + OUT_VIEW_A 1 + OUT_VIEW_B 1 + + OUT_TABLE 1 + OUT_VIEW_A 1 + OUT_VIEW_B 1 + + OUT_TABLE 1 + OUT_VIEW_A 1 + OUT_VIEW_B 1 + """ + +@pytest.mark.version('>=2.5.6') +def test_core_5241_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5246.py b/tests/bugs/test_core_5246.py new file mode 100644 index 00000000..15885ef3 --- /dev/null +++ b/tests/bugs/test_core_5246.py @@ -0,0 +1,61 @@ +#coding:utf-8 +# +# id: bugs.core_5246 +# title: String truncation error while selecting from MON$ tables if some user-defined context variable exceeds 255 bytes in length +# decription: +# More description see here: +# https://github.com/FirebirdSQL/firebird/commit/373c4599d3f2be06ea9d239a25e18248c8d38a64 +# See also: CORE-6248. +# +# tracker_id: CORE-5246 +# min_versions: ['3.0.1'] +# versions: 3.0.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set term ^; + execute block returns(rdb_get_context_value varchar(32765), RDB_GET_CONTEXT_LENGTH smallint) as + begin + rdb$set_context('USER_SESSION','LONG_TEXT', lpad('', 32765, '6729699E-CCD1-425A-8892-277E6CFEECD3') ); + rdb_get_context_value = rdb$get_context('USER_SESSION','LONG_TEXT'); + rdb_get_context_length = char_length( rdb_get_context_value ); + suspend; + end + ^ + set term ;^ + + select mon$variable_name mon_context_var, mon$variable_value as mon_context_val, char_length(mon$variable_value) as mon_context_len + from rdb$database r + left join mon$context_variables c on mon$attachment_id=current_connection; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB_GET_CONTEXT_VALUE 6729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD367296 + RDB_GET_CONTEXT_LENGTH 32765 + MON_CONTEXT_VAR LONG_TEXT + MON_CONTEXT_VAL 6729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD36729699E-CCD1-425A-8892-277E6CFEECD367296 + MON_CONTEXT_LEN 32765 + """ + +@pytest.mark.version('>=3.0.1') +def test_core_5246_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5248.py b/tests/bugs/test_core_5248.py new file mode 100644 index 00000000..3b8a80a1 --- /dev/null +++ b/tests/bugs/test_core_5248.py @@ -0,0 +1,429 @@ +#coding:utf-8 +# +# id: bugs.core_5248 +# title: Improve consistency in GRANT syntax between roles and privileges according to SQL standard +# decription: +# Checked on 4.0.0.249; 3.0.1.32585 +# +# tracker_id: CORE-5248 +# min_versions: ['3.0.1'] +# versions: 3.0.1, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set autoddl off; + commit; + connect '$(DSN)' user sysdba password 'masterkey'; + create or alter user tmp$c5248_usr0 password 'c5248$u0'; + create or alter user tmp$c5248_usrx password 'c5248$ux'; + commit; + grant create role to user tmp$c5248_usr0; + commit; + + set term ^; + execute block as + begin + execute statement 'drop role test_role1'; + when any do begin end + end^ + set term ;^ + commit; + + connect '$(DSN)' user tmp$c5248_usr0 password 'c5248$u0'; + create role test_role1; -- tmp$c5248_usr0 is owner of role test_role1 + commit; + + -- drop role - should fail + connect '$(DSN)' user tmp$c5248_usrx password 'c5248$ux'; + + -- Statement failed, SQLSTATE = 28000 + -- unsuccessful metadata update + -- -DROP ROLE TEST_ROLE1 failed + -- -no permission for DROP access to ROLE TEST_ROLE1 + + drop role test_role1; -- should fail: this user is not owner of this role and he was not granted to use it with admin option + select count(*) from rdb$roles where rdb$role_name = 'TEST_ROLE1'; + rollback; + + connect '$(DSN)' user sysdba password 'masterkey'; + drop user tmp$c5248_usr0; + drop user tmp$c5248_usrx; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + COUNT 1 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -DROP ROLE TEST_ROLE1 failed + -no permission for DROP access to ROLE TEST_ROLE1 + """ + +@pytest.mark.version('>=3.0.1,<4.0') +def test_core_5248_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [('-TMP\\$C5248_USR1 is not grantor of (role|ROLE|Role) on TEST_ROLE1 to TMP\\$C5248_USR1.', '-TMP$C5248_USR1 is not grantor of ROLE on TEST_ROLE1 to TMP$C5248_USR1.'), ('-Effective user is.*', '')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set list on; + set count on; + set autoddl off; + --set echo on; + commit; + connect '$(DSN)' user sysdba password 'masterkey'; + create or alter user tmp$c5248_usr0 password 'c5248$u0'; + create or alter user tmp$c5248_usr1 password 'c5248$u1'; + create or alter user tmp$c5248_usr2 password 'c5248$u2'; + create or alter user tmp$c5248_usr3 password 'c5248$u3'; + create or alter user tmp$c5248_usrx password 'c5248$ux'; + commit; + grant create role to user tmp$c5248_usr0; + commit; + + set term ^; + execute block as + begin + execute statement 'drop role test_role1'; + when any do begin end + end^ + set term ;^ + commit; + + recreate view v_grants as + select + current_user as who_am_i + ,p.RDB$USER as who_was_granted + ,p.RDB$PRIVILEGE as privilege_type + ,p.RDB$RELATION_NAME as role_name + ,r.RDB$OWNER_NAME as role_owner + ,p.RDB$GRANTOR as granted_by + ,p.RDB$GRANT_OPTION as grant_option + from rdb$user_privileges p + left join rdb$roles r on p.rdb$relation_name = r.rdb$role_name + where p.rdb$object_type=13 + ; + commit; + grant select on v_grants to public; + commit; + + connect '$(DSN)' user tmp$c5248_usr0 password 'c5248$u0'; + create role test_role1; -- tmp$c5248_usr0 is owner of role test_role1 + commit; + + connect '$(DSN)' user sysdba password 'masterkey'; + grant test_role1 to tmp$c5248_usr1 with admin option; + grant test_role1 to tmp$c5248_usr3; + commit; + + connect '$(DSN)' user tmp$c5248_usr1 password 'c5248$u1'; + grant test_role1 to tmp$c5248_usr2; ----------------------- tmp$c5248_usr1 grants role to tmp$c5248_usr2 + commit; + + -- 1. revoke - avoid cascade grants delete + + connect '$(DSN)' user sysdba password 'masterkey'; + + select * from v_grants where upper(who_was_granted) in ( upper('tmp$c5248_usr1'), upper('tmp$c5248_usr2') ); -- must contain 2 records + + revoke test_role1 from tmp$c5248_usr1; -- Q: whether grant on role 'test_role1' remains to user 'tmp$c5248_usr2' after revoking from 'tmp$c5248_usr1' ? + + select * from v_grants where upper(who_was_granted) in ( upper('tmp$c5248_usr1'), upper('tmp$c5248_usr2') ); -- must contain 1 record for tmp$c5248_usr2 + + -- return grant to tmp$c5248_usr1 because it was revoked just now: + rollback; + --grant test_role1 to tmp$c5248_usr1 with admin option; + --commit; + + + + -- 2. revoke: user who has 'admin option' can revoke role from anyone EXCEPT himself + connect '$(DSN)' user tmp$c5248_usr1 password 'c5248$u1'; + + -- Following REVOKE should fail with: + -- Statement failed, SQLSTATE = 42000 + -- unsuccessful metadata update + -- -REVOKE failed + -- -tmp$c5248_usr1 is not grantor of Role on TEST_ROLE1 to tmp$c5248_usr1. + revoke test_role1 from tmp$c5248_usr1; + + select * from v_grants where upper(who_was_granted) = upper('tmp$c5248_usr1'); -- record should remain + rollback; + + + + -- 3. revoke - check role owner rights + connect '$(DSN)' user tmp$c5248_usr0 password 'c5248$u0'; + + select * from v_grants where upper(who_was_granted) = upper('tmp$c5248_usr3'); + + -- current user = tmp$c5248_usr0 - is owner of role test_role1, but this role was granted to tmp$c5248_usr3 by SYSDBA. + -- Q: should user 'c5248$u0' (current) be able to revoke role which he did NOT grant but owns ? + -- A: yes. + + revoke test_role1 from tmp$c5248_usr3; -- NO error/warning should be here + + select * from v_grants where upper(who_was_granted) = upper('tmp$c5248_usr3'); -- record should NOT appear. + rollback; + + + + -- 4. revoke - check admin option + connect '$(DSN)' user tmp$c5248_usr1 password 'c5248$u1'; + + select * from v_grants where upper(who_was_granted) in ( upper('tmp$c5248_usr1'), upper('tmp$c5248_usr3') ); -- two records should be here + + -- current user = tmp$c5248_usr1 - is NOT owner of role TEST_ROLE1 but he was granted to use it WITH ADMIN option + -- (grant test_role1 to tmp$c5248_usr1 with admin option). + -- Q: should user 'tmp$c5248_usr1' (current) be able to revoke role which he neither did grant nor owns but has admin option ? + -- A: yes. + + revoke test_role1 from tmp$c5248_usr3; + + select * from v_grants where upper(who_was_granted) in (upper('tmp$c5248_usr1'), upper('tmp$c5248_usr3')); -- only one record should be here + rollback; + + + -- 5a. drop role - should fail + connect '$(DSN)' user tmp$c5248_usrx password 'c5248$ux'; + + -- Statement failed, SQLSTATE = 28000 + -- unsuccessful metadata update + -- -DROP ROLE TEST_ROLE1 failed + -- -no permission for DROP access to ROLE TEST_ROLE1 + + drop role test_role1; -- should fail: this user is not owner of this role and he was not granted to use it with admin option + + set count off; + select count(*) from rdb$roles where rdb$role_name = 'TEST_ROLE1'; + set count on; + rollback; + + connect '$(DSN)' user tmp$c5248_usr0 password 'c5248$u0'; + + select * from v_grants where upper(role_name) = upper('TEST_ROLE1'); -- should output 3 records + + drop role test_role1; -- current user: 'tmp$c5248_usr0' - is owner of role test_role1 + + select * from rdb$roles where upper(rdb$role_name) = upper('TEST_ROLE1'); -- should output 0 records + select * from v_grants where upper(role_name) = upper('TEST_ROLE1'); -- should output 0 records + rollback; + + + -- 6. drop role - check admin option + connect '$(DSN)' user tmp$c5248_usr1 password 'c5248$u1'; + + -- current user: 'tmp$c5248_usr1' - HAS grant on role TEST_ROLE1 with admin option (but he is NOT owner of this role). + + select * from v_grants where upper(role_name) = upper('TEST_ROLE1'); -- should output 3 records + + drop role test_role1; -- current user: 'tmp$c5248_usr0' - is owner of role test_role1 + + select * from rdb$roles where upper(rdb$role_name) = upper('TEST_ROLE1'); -- should output 0 records + select * from v_grants where upper(role_name) = upper('TEST_ROLE1'); -- should output 0 records + rollback; + + + connect '$(DSN)' user sysdba password 'masterkey'; + drop user tmp$c5248_usr0; + drop user tmp$c5248_usr1; + drop user tmp$c5248_usr2; + drop user tmp$c5248_usr3; + drop user tmp$c5248_usrx; + commit; + + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + WHO_AM_I SYSDBA + WHO_WAS_GRANTED TMP$C5248_USR1 + PRIVILEGE_TYPE M + ROLE_NAME TEST_ROLE1 + ROLE_OWNER TMP$C5248_USR0 + GRANTED_BY SYSDBA + GRANT_OPTION 2 + + WHO_AM_I SYSDBA + WHO_WAS_GRANTED TMP$C5248_USR2 + PRIVILEGE_TYPE M + ROLE_NAME TEST_ROLE1 + ROLE_OWNER TMP$C5248_USR0 + GRANTED_BY TMP$C5248_USR1 + GRANT_OPTION 0 + + + Records affected: 2 + + WHO_AM_I SYSDBA + WHO_WAS_GRANTED TMP$C5248_USR2 + PRIVILEGE_TYPE M + ROLE_NAME TEST_ROLE1 + ROLE_OWNER TMP$C5248_USR0 + GRANTED_BY TMP$C5248_USR1 + GRANT_OPTION 0 + + + Records affected: 1 + + WHO_AM_I TMP$C5248_USR1 + WHO_WAS_GRANTED TMP$C5248_USR1 + PRIVILEGE_TYPE M + ROLE_NAME TEST_ROLE1 + ROLE_OWNER TMP$C5248_USR0 + GRANTED_BY SYSDBA + GRANT_OPTION 2 + + + Records affected: 1 + + WHO_AM_I TMP$C5248_USR0 + WHO_WAS_GRANTED TMP$C5248_USR3 + PRIVILEGE_TYPE M + ROLE_NAME TEST_ROLE1 + ROLE_OWNER TMP$C5248_USR0 + GRANTED_BY SYSDBA + GRANT_OPTION 0 + + + Records affected: 1 + Records affected: 0 + + WHO_AM_I TMP$C5248_USR1 + WHO_WAS_GRANTED TMP$C5248_USR1 + PRIVILEGE_TYPE M + ROLE_NAME TEST_ROLE1 + ROLE_OWNER TMP$C5248_USR0 + GRANTED_BY SYSDBA + GRANT_OPTION 2 + + WHO_AM_I TMP$C5248_USR1 + WHO_WAS_GRANTED TMP$C5248_USR3 + PRIVILEGE_TYPE M + ROLE_NAME TEST_ROLE1 + ROLE_OWNER TMP$C5248_USR0 + GRANTED_BY SYSDBA + GRANT_OPTION 0 + + + Records affected: 2 + + WHO_AM_I TMP$C5248_USR1 + WHO_WAS_GRANTED TMP$C5248_USR1 + PRIVILEGE_TYPE M + ROLE_NAME TEST_ROLE1 + ROLE_OWNER TMP$C5248_USR0 + GRANTED_BY SYSDBA + GRANT_OPTION 2 + + + Records affected: 1 + + COUNT 1 + + WHO_AM_I TMP$C5248_USR0 + WHO_WAS_GRANTED TMP$C5248_USR1 + PRIVILEGE_TYPE M + ROLE_NAME TEST_ROLE1 + ROLE_OWNER TMP$C5248_USR0 + GRANTED_BY SYSDBA + GRANT_OPTION 2 + + WHO_AM_I TMP$C5248_USR0 + WHO_WAS_GRANTED TMP$C5248_USR3 + PRIVILEGE_TYPE M + ROLE_NAME TEST_ROLE1 + ROLE_OWNER TMP$C5248_USR0 + GRANTED_BY SYSDBA + GRANT_OPTION 0 + + WHO_AM_I TMP$C5248_USR0 + WHO_WAS_GRANTED TMP$C5248_USR2 + PRIVILEGE_TYPE M + ROLE_NAME TEST_ROLE1 + ROLE_OWNER TMP$C5248_USR0 + GRANTED_BY TMP$C5248_USR1 + GRANT_OPTION 0 + + + Records affected: 3 + Records affected: 0 + Records affected: 0 + + WHO_AM_I TMP$C5248_USR1 + WHO_WAS_GRANTED TMP$C5248_USR1 + PRIVILEGE_TYPE M + ROLE_NAME TEST_ROLE1 + ROLE_OWNER TMP$C5248_USR0 + GRANTED_BY SYSDBA + GRANT_OPTION 2 + + WHO_AM_I TMP$C5248_USR1 + WHO_WAS_GRANTED TMP$C5248_USR3 + PRIVILEGE_TYPE M + ROLE_NAME TEST_ROLE1 + ROLE_OWNER TMP$C5248_USR0 + GRANTED_BY SYSDBA + GRANT_OPTION 0 + + WHO_AM_I TMP$C5248_USR1 + WHO_WAS_GRANTED TMP$C5248_USR2 + PRIVILEGE_TYPE M + ROLE_NAME TEST_ROLE1 + ROLE_OWNER TMP$C5248_USR0 + GRANTED_BY TMP$C5248_USR1 + GRANT_OPTION 0 + + Records affected: 3 + Records affected: 0 + Records affected: 0 + """ +expected_stderr_2 = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -REVOKE failed + -TMP$C5248_USR1 is not grantor of ROLE on TEST_ROLE1 to TMP$C5248_USR1. + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -DROP ROLE TEST_ROLE1 failed + -no permission for DROP access to ROLE TEST_ROLE1 + """ + +@pytest.mark.version('>=4.0') +def test_core_5248_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_expected_stderr == act_2.clean_stderr + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/bugs/test_core_5268.py b/tests/bugs/test_core_5268.py new file mode 100644 index 00000000..fd4ce395 --- /dev/null +++ b/tests/bugs/test_core_5268.py @@ -0,0 +1,153 @@ +#coding:utf-8 +# +# id: bugs.core_5268 +# title: Nested OR conditions may lead to incorrest results +# decription: +# tracker_id: CORE-5268 +# min_versions: ['3.0.1'] +# versions: 3.0.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Reproduced wrong result on WI-T4.0.0.238. + -- (note on single difference between sp_test and sp_test2: parenthesis that enclose 'OR' expression. + -- Checked on LI-T4.0.0.242 after fix was committed - all works fine. + + create or alter procedure sp_test(a_inp varchar(50)) as begin end; + create or alter procedure sp_test2(a_inp varchar(50)) as begin end; + recreate table testtab ( + feld_a varchar(50), + feld_b varchar(10), + feld_c char(10) + ); + + recreate table result ( + feld_a varchar(50), + feld_b varchar(10), + feld_c char(10) + ); + + create index testtab_idx1 on testtab (feld_b); + create index testtab_idx2 on testtab (feld_a); + commit; + + insert into testtab (feld_a, feld_b, feld_c) values ('aaaa', 'bb', 'cc '); + insert into testtab (feld_a, feld_b, feld_c) values ('aaa', 'aa', 'aaa '); + insert into testtab (feld_a, feld_b, feld_c) values ('uuu', 'uuu', 'uuu '); + insert into testtab (feld_a, feld_b, feld_c) values ('uuu', 'uu', 'uu '); + + + commit; + + + -- test sqls + -- wrong: should get at least 3 records, but gives only 1 + set term ^; + create or alter procedure sp_test(a_inp varchar(50)) as + begin + delete from result; + insert into result + select * + from testtab t + where + :a_inp='123456' -- a_inp = 'blub' for testcase + or + ( + upper(t.feld_b) starting with upper('u') + or + t.feld_a starting with 'a' /* with index */ + ) + ; + end + ^ + + create or alter procedure sp_test2(a_inp varchar(50)) as + begin + delete from result; + insert into result + select * + from testtab t + where + :a_inp='123456' -- a_inp = 'blub' for testcase + or + upper(t.feld_b) starting with upper('u') + or + t.feld_a starting with 'a' /* with index */ + ; + end + ^ + set term ;^ + commit; + + set list on; + + execute procedure sp_test('blub'); + select '1' as result, r.* from result r; + + execute procedure sp_test2('blub'); + select '2' as result, r.* from result r; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT 1 + FELD_A aaaa + FELD_B bb + FELD_C cc + + RESULT 1 + FELD_A aaa + FELD_B aa + FELD_C aaa + + RESULT 1 + FELD_A uuu + FELD_B uuu + FELD_C uuu + + RESULT 1 + FELD_A uuu + FELD_B uu + FELD_C uu + + + RESULT 2 + FELD_A aaaa + FELD_B bb + FELD_C cc + + RESULT 2 + FELD_A aaa + FELD_B aa + FELD_C aaa + + RESULT 2 + FELD_A uuu + FELD_B uuu + FELD_C uuu + + RESULT 2 + FELD_A uuu + FELD_B uu + FELD_C uu + """ + +@pytest.mark.version('>=3.0.1') +def test_core_5268_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5269.py b/tests/bugs/test_core_5269.py new file mode 100644 index 00000000..1d13bf47 --- /dev/null +++ b/tests/bugs/test_core_5269.py @@ -0,0 +1,217 @@ +#coding:utf-8 +# +# id: bugs.core_5269 +# title: FBTRACEMGR should understand 'role ' command switch (needed to explicitly connect with role with 'TRACE_ANY_ATTACHMENT' privilege) +# decription: +# We create two users and one of them is granted with role that allows him to watch other users activity. +# Than we start FBSVCMGR utility with specifying this user and his ROLE so that he can start wathing. +# After this we make trivial query to database from another user. +# Finally, we check trace log that was recived by watching user: this log must contain phrases about +# preprating, starting and executing statements. +# +# Checked on 4.0.0.321 - works fine. +# +# tracker_id: CORE-5269 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('\t+', ' '), ('^((?!ROLE_|PREPARE_STATEMENT|EXECUTE_STATEMENT_START|EXECUTE_STATEMENT_FINISH).)*$', ''), ('.*PREPARE_STATEMENT', 'TRACE_LOG: PREPARE_STATEMENT'), ('.*EXECUTE_STATEMENT_START', 'TRACE_LOG: EXECUTE_STATEMENT_START'), ('.*EXECUTE_STATEMENT_FINISH', 'TRACE_LOG: EXECUTE_STATEMENT_FINISH')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_file = db_conn.database_name +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql_ddl=''' set wng off; +# set bail on; +# set list on; +# +# create or alter user TMP$C5269_1 password '123' revoke admin role; +# create or alter user TMP$C5269_2 password '456' revoke admin role; +# revoke all on all from TMP$C5269_1; +# revoke all on all from TMP$C5269_2; +# commit; +# +# -- Trace other users' attachments +# create role role_for_trace_any_attachment +# set system privileges to TRACE_ANY_ATTACHMENT; +# commit; +# +# grant role_for_trace_any_attachment to user TMP$C5269_2; +# commit; +# +# set list on; +# select p.rdb$user as role_grantee, p.rdb$grantor as role_grantor, r.rdb$role_name as role_name, r.rdb$owner_name as role_owner +# from rdb$user_privileges p +# join rdb$roles r on p.rdb$relation_name = r.rdb$role_name +# where p.rdb$user = upper('TMP$C5269_2'); +# ''' +# runProgram('isql',[dsn],sql_ddl) +# +# att1 = fdb.connect(dsn=dsn,user='TMP$C5269_1',password='123') +# cur1 = att1.cursor() +# +# txt30 = '''# Trace config, format for 3.0. Generated auto, do not edit! +# database=#%[\\\\\\\\/]bugs.core_5269.fdb +# { +# enabled = true +# log_statement_prepare = true +# log_statement_start = true +# log_statement_finish = true +# time_threshold = 0 +# max_sql_length = 5000 +# } +# ''' +# +# f_trccfg=open( os.path.join(context['temp_directory'],'tmp_trace_5269.cfg'), 'w') +# f_trccfg.write(txt30) +# flush_and_close( f_trccfg ) +# +# +# # Now we run TRACE in child process (asynchronous) +# ################## +# +# f_trclog=open( os.path.join(context['temp_directory'],'tmp_trace_5269.log'), 'w') +# f_trcerr=open( os.path.join(context['temp_directory'],'tmp_trace_5269.err'), 'w') +# #''' +# p_trace=subprocess.Popen( [context['fbsvcmgr_path'],"localhost:service_mgr", +# "user", "TMP$C5269_2", +# "password", "456", +# "role", "role_for_trace_any_attachment", +# "action_trace_start", "trc_cfg", f_trccfg.name +# ], +# stdout=f_trclog, stderr=f_trcerr +# ) +# +# time.sleep(1) +# +# cur1.execute("select current_user from rdb$database") +# cur1.close() +# att1.close() +# +# time.sleep(1) +# +# # Getting ID of launched trace session and STOP it: +# ################################################### +# +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# f_trclst=open( os.path.join(context['temp_directory'],'tmp_trace_5269.lst'), 'w') +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_list"], +# stdout=f_trclst, stderr=subprocess.STDOUT +# ) +# flush_and_close( f_trclst ) +# +# trcssn=0 +# with open( f_trclst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# f_trclst=open(f_trclst.name,'a') +# f_trclst.seek(0,2) +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_stop", +# "trc_id",trcssn], +# stdout=f_trclst, stderr=subprocess.STDOUT +# ) +# flush_and_close( f_trclst ) +# +# p_trace.terminate() +# flush_and_close( f_trclog ) +# flush_and_close( f_trcerr ) +# +# runProgram('isql',[dsn],'drop user TMP$C5269_1; drop user TMP$C5269_2; commit;') +# +# with open( f_trclog.name,'r') as f: +# for line in f: +# print('TRACE LOG: '+line) +# +# with open( f_trcerr.name,'r') as f: +# for line in f: +# print('UNEXPECTED TRACE ERR: '+line) +# +# +# # Cleanup. +# ########## +# # Wait! Otherwise get WindowsError 32 on attempt to remove trace log and err files: +# time.sleep(1) +# cleanup( (f_trclog, f_trcerr, f_trccfg,f_trclst) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ROLE_GRANTEE TMP$C5269_2 + ROLE_GRANTOR SYSDBA + ROLE_NAME ROLE_FOR_TRACE_ANY_ATTACHMENT + ROLE_OWNER SYSDBA + TRACE LOG: 2016-08-06T11:51:38.9360 (2536:01FD0CC8) PREPARE_STATEMENT + TRACE LOG: 2016-08-06T11:51:38.9360 (2536:01FD0CC8) EXECUTE_STATEMENT_START + TRACE LOG: 2016-08-06T11:51:38.9360 (2536:01FD0CC8) EXECUTE_STATEMENT_FINISH + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_5269_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5270.py b/tests/bugs/test_core_5270.py new file mode 100644 index 00000000..fb821873 --- /dev/null +++ b/tests/bugs/test_core_5270.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_5270 +# title: FBSVCMGR does not produce error while attempting to shutdown a database without specified timeout (prp_force_shutdown N) +# decription: +# Confirmed bug on 4.0.0.258 (no error message is produced), all fine on 4.0.0.316 and 3.0.1.32570 +# +# tracker_id: CORE-5270 +# min_versions: ['3.0.1'] +# versions: 3.0.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# db_file="$(DATABASE_LOCATION)bugs.core_5270.fdb" +# +# runProgram('fbsvcmgr',['localhost:service_mgr', 'action_properties', 'dbname', db_file, 'prp_shutdown_mode', 'prp_sm_single']) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + must specify type of shutdown + """ + +@pytest.mark.version('>=3.0.1') +@pytest.mark.xfail +def test_core_5270_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5271.py b/tests/bugs/test_core_5271.py new file mode 100644 index 00000000..aa020d2f --- /dev/null +++ b/tests/bugs/test_core_5271.py @@ -0,0 +1,95 @@ +#coding:utf-8 +# +# id: bugs.core_5271 +# title: Regression: Can not create large index +# decription: +# Confirmed bug on WI-T4.0.0.246 (checked SS, SC), get in STDERR: +# === +# Statement failed, SQLSTATE = HY000 +# sort error +# -No free space found in temporary directories +# -operating system directive CreateFile failed +# - , +# === +# TempCacheLimit = default, database grows up to 83M (for SS). +# All works fine on WI-T4.0.0.254. +# +# tracker_id: CORE-5271 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=16384, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# sql_ddl=''' +# recreate table t1( +# s varchar(4000) not null +# ); +# +# commit; +# set term !; +# +# execute block +# as +# declare i int = 0; +# begin +# -- min = 7275 when database page_size=32768 and index key length = 8000 +# -- min= 14750 when database page_size=16384 and index key length = 4000 +# -- min= 29000 when database page_size=16384 and index key length = 2000 +# while (i < 14750) do +# begin +# insert into t1(s) values( rpad('', 4000, uuid_to_char( gen_uuid() ) ) ); +# i = i + 1; +# end +# end! +# +# set term ;! +# +# commit; +# alter table t1 add constraint pk_t1 primary key (s) using index pk_t1_s; +# commit; +# +# set list on; +# set count on; +# select rdb$index_name, rdb$relation_name, rdb$unique_flag,rdb$segment_count +# from rdb$indices +# where rdb$index_name = upper('pk_t1_s'); +# ''' +# runProgram('gfix',[dsn, '-w', 'async']) +# runProgram('isql',[dsn], sql_ddl) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$INDEX_NAME PK_T1_S + RDB$RELATION_NAME T1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + Records affected: 1 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_5271_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5273.py b/tests/bugs/test_core_5273.py new file mode 100644 index 00000000..1832505f --- /dev/null +++ b/tests/bugs/test_core_5273.py @@ -0,0 +1,293 @@ +#coding:utf-8 +# +# id: bugs.core_5273 +# title: Crash when attempt to create database with running trace ( internal Firebird consistency check (cannot find tip page (165), file: tra.cpp line: 2233) ) +# decription: +# 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. +# 3. Make DDLfile and run ISQL, with separate logging of its STDOUT and STDERR. +# 4. Stop trace session +# 5. Get the content of firebird.log after test. +# 6. Ensure that files which should store STDERR results are empty. +# 7. Ensure that there is no difference in the content of firebird.log. +# +# Confirmed on 4.0.0.254 (SS, SC): +# 1) unexpected STDERR logs: +# + Unexpected STDERR, file ... mp_5273_ddl.err: Statement failed, SQLSTATE = 08006 +# + Unexpected STDERR, file ... mp_5273_ddl.err: Error reading data from the connection. +# + Unexpected STDERR, file ... mp_5273_ddl.err: After line 3 in file ... mp_5273_ddl.sql +# + Unexpected STDERR, file ... mp_trace_5273.err: Error reading data from the connection. +# 2) diff in firebird.log: +# +CSPROG Thu Jun 16 14:17:13 2016 +# + Database: C:\\MIX\\FIREBIRD\\QA\\FBT-REPO\\TMP\\TMP_5273.FDB +# + internal Firebird consistency check (cannot find tip page (165), file: tra.cpp line: 2233) +# + +# + +# +CSPROG Thu Jun 16 14:17:13 2016 +# + INET/inet_error: read errno = 10054, server host = localhost, address = 127.0.0.1/3430 +# +# Works fine on 4.0.0.256. +# +# tracker_id: CORE-5273 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# import difflib +# from subprocess import Popen +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# def svc_get_fb_log( f_fb_log ): +# +# global subprocess +# +# subprocess.call([ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# "action_get_fb_log" +# ], +# stdout=f_fb_log, +# stderr=subprocess.STDOUT +# ) +# +# return +# +# +# +# +# tmpfdb1=os.path.join(context['temp_directory'],'tmp_5273.fdb') +# cleanup( tmpfdb1, ) +# +# sql_ddl=''' set list on; +# set bail on; +# create database 'localhost:%(tmpfdb1)s'; +# select mon$database_name from mon$database; +# commit; +# drop database; +# ''' % locals() +# +# trace_options = '''# Trace config, format for 3.0 and above. Generated auto, do not edit! +# database=%[\\\\\\\\/]tmp_5273.fdb +# { +# enabled = true +# log_sweep = true +# log_errors = true +# time_threshold = 0 +# log_connections = true +# log_transactions = true +# log_statement_prepare = true +# log_statement_start = true +# log_statement_finish = true +# log_statement_free = true +# log_trigger_start = true +# log_trigger_finish = true +# print_perf = true +# max_sql_length = 16384 +# max_log_size = 5000000 +# } +# services +# { +# enabled = false +# log_services = true +# log_service_query = true +# log_errors = true +# } +# ''' +# f_trccfg=open( os.path.join(context['temp_directory'],'tmp_trace_5273.cfg'), 'w') +# f_trccfg.write(trace_options) +# flush_and_close( f_trccfg ) +# +# # Get content of firebird.log BEFORE test: +# ########################################## +# f_fblog_before=open( os.path.join(context['temp_directory'],'tmp_5273_fblog_before.txt'), 'w') +# svc_get_fb_log( f_fblog_before ) +# flush_and_close( f_fblog_before ) +# +# +# # Starting trace session in new child process (async.): +# ####################################################### +# +# f_trclog=open( os.path.join(context['temp_directory'],'tmp_trace_5273.log'), 'w') +# f_trcerr=open( os.path.join(context['temp_directory'],'tmp_trace_5273.err'), 'w') +# +# # Execute a child program in a new process, redirecting STDERR to the same target as of STDOUT: +# p_trace=Popen([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_start", +# "trc_cfg", f_trccfg.name], +# stdout=f_trclog, +# stderr=f_trcerr +# ) +# +# # Wait! Trace session is initialized not instantly! +# time.sleep(2) +# +# f_create_db_sql = open( os.path.join(context['temp_directory'],'tmp_5273_ddl.sql'), 'w') +# f_create_db_sql.write(sql_ddl) +# flush_and_close( f_create_db_sql ) +# +# +# # CREATE DATABASE +# ################# +# +# f_create_db_log = open( os.path.join(context['temp_directory'],'tmp_5273_ddl.log'), 'w') +# f_create_db_err = open( os.path.join(context['temp_directory'],'tmp_5273_ddl.err'), 'w') +# subprocess.call( [context['isql_path'], "-q", "-i", f_create_db_sql.name ], +# stdout = f_create_db_log, +# stderr = f_create_db_err +# ) +# flush_and_close( f_create_db_log ) +# flush_and_close( f_create_db_err ) +# +# +# ##################################################### +# # Getting ID of launched trace session and STOP it: +# +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# f_trclst=open( os.path.join(context['temp_directory'],'tmp_trace_5273.lst'), 'w') +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_list"], +# stdout=f_trclst, +# stderr=subprocess.STDOUT +# ) +# flush_and_close( f_trclst ) +# +# trcssn=0 +# with open( f_trclst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# f_trclst=open(f_trclst.name,'a') +# f_trclst.seek(0,2) +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_stop", +# "trc_id",trcssn], +# stdout=f_trclst, stderr=subprocess.STDOUT +# ) +# flush_and_close( f_trclst ) +# +# # 23.02.2021. DELAY FOR AT LEAST 1 SECOND REQUIRED HERE! +# # On windows preliminary termination of running trace before it completes 'stop' request leads to: +# # INET/inet_error: read errno = 10054, client host = ..., address = ::1/62963, user = ... +# time.sleep(1) +# +# # Terminate child process of launched trace session (though it should already be killed): +# p_trace.terminate() +# flush_and_close( f_trclog ) +# flush_and_close( f_trcerr ) +# +# +# # Get content of firebird.log AFTER test: +# ######################################### +# +# f_fblog_after=open( os.path.join(context['temp_directory'],'tmp_5273_fblog_after.txt'), 'w') +# svc_get_fb_log( f_fblog_after ) +# flush_and_close( f_fblog_after ) +# +# # STDERR for ISQL (that created DB) and trace session - they both must be EMPTY: +# ################# +# f_list=[f_create_db_err, f_trcerr] +# for i in range(len(f_list)): +# f_name=f_list[i].name +# if os.path.getsize(f_name) > 0: +# with open( f_name,'r') as f: +# for line in f: +# print("Unexpected STDERR, file "+f_name+": "+line) +# +# # DIFFERENCE in the content of firebird.log should be EMPTY: +# #################### +# +# oldfb=open(f_fblog_before.name, 'r') +# newfb=open(f_fblog_after.name, 'r') +# +# difftext = ''.join(difflib.unified_diff( +# oldfb.readlines(), +# newfb.readlines() +# )) +# oldfb.close() +# newfb.close() +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_5273_diff.txt'), 'w') +# f_diff_txt.write(difftext) +# flush_and_close( f_diff_txt ) +# +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# print("Unexpected DIFF in firebird.log: "+line) +# +# +# # Cleanup: +# ########## +# time.sleep(1) +# cleanup( (f_create_db_sql, f_create_db_log, f_create_db_err, f_trccfg, f_trclst, f_trclog, f_trcerr,f_fblog_before,f_fblog_after,f_diff_txt, tmpfdb1) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_5273_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5275.py b/tests/bugs/test_core_5275.py new file mode 100644 index 00000000..47da5c9c --- /dev/null +++ b/tests/bugs/test_core_5275.py @@ -0,0 +1,443 @@ +#coding:utf-8 +# +# id: bugs.core_5275 +# title: CORE-5275: Expression index may become inconsistent if CREATE INDEX was interrupted after b-tree creation but before commiting +# decription: +# This test (and CORE- ticket) has been created after wrong initial implementation of test for CORE-1746. +# Scenario: +# 1. ISQL_1 is launched as child async. process, inserts 1000 rows and then falls in pause (delay) ~10 seconds; +# 2. ISQL_2 is launched as child async. process in Tx = WAIT, tries to create index on the table which is handled +# by ISQL_1 and immediatelly falls in pause because of waiting for table lock. +# 3. ISQL_3 is launched in SYNC mode and does 'DELETE FROM MON$ATTACHMENTS' thus forcing other attachments to be +# closed with raising 00803/connection shutdown. +# 4. Repeat step 1. On WI-T4.0.0.258 this step lead to: +# "invalid SEND request (167), file: JrdStatement.cpp line: 325", 100% reproducilbe. +# +# Checked on WI-V2.5.6.27017 (SC), WI-V3.0.1.32539 (SS/SC/CS), WI-T4.0.0.262 (SS) - works fine. +# +# Beside above mentioned steps, we also: +# 1) compare content of old/new firebird.log (difference): it should NOT contain line "consistency check"; +# 2) run database online validation: it should NOT report any error in the database. +# +# :::::::::::::::::::::::::::::::::::::::: NB :::::::::::::::::::::::::::::::::::: +# 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 replace 'alter sequence restart...' with subtraction of two gen values: +# c = gen_id(, -gen_id(, 0)) -- see procedure sp_restart_sequences. +# +# Checked on: +# 4.0.0.2164 SS: 15.932s. +# 4.0.0.2119 SS: 16.141s. +# 4.0.0.2164 CS: 17.549s. +# 3.0.7.33356 SS: 17.446s. +# 3.0.7.33356 CS: 18.321s. +# 2.5.9.27150 SC: 13.768s. +# +# tracker_id: CORE-5275 +# min_versions: ['2.5.6'] +# versions: 2.5.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.6 +# resources: None + +substitutions_1 = [('0: CREATE INDEX LOG: RDB_EXPR_BLOB.*', '0: CREATE INDEX LOG: RDB_EXPR_BLOB'), ('BULK_INSERT_START.*', 'BULK_INSERT_START'), ('.*KILLED BY DATABASE ADMINISTRATOR.*', ''), ('BULK_INSERT_FINISH.*', 'BULK_INSERT_FINISH'), ('CREATE_INDX_START.*', 'CREATE_INDX_START'), ('AFTER LINE.*', 'AFTER LINE'), ('RECORDS AFFECTED:.*', 'RECORDS AFFECTED:'), ('[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9]', ''), ('RELATION [0-9]{3,4}', 'RELATION')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import difflib +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_file=db_conn.database_name +# engine =str(db_conn.engine_version) +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# def svc_get_fb_log( engine, f_fb_log ): +# +# import subprocess +# +# if engine.startswith('2.5'): +# get_firebird_log_key='action_get_ib_log' +# else: +# get_firebird_log_key='action_get_fb_log' +# +# # C:\\MIX +# irebird\\oldfb251in +# bsvcmgr localhost:service_mgr -user sysdba -password masterkey action_get_ib_log +# subprocess.call([ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# get_firebird_log_key +# ], +# stdout=f_fb_log, stderr=subprocess.STDOUT +# ) +# +# return +# +# sql_ddl=''' +# create or alter procedure sp_ins(n int) as begin end; +# +# recreate table test(x int unique using index test_x, s varchar(10) default 'qwerty' ); +# +# set term ^; +# execute block as +# begin +# execute statement 'drop sequence g'; +# when any do begin end +# end +# ^ +# set term ;^ +# commit; +# create sequence g; +# commit; +# +# set term ^; +# create or alter procedure sp_ins(n int) as +# begin +# while (n>0) do +# begin +# insert into test( x ) values( gen_id(g,1) ); +# n = n - 1; +# end +# end +# ^ +# set term ;^ +# commit; +# ''' +# runProgram('isql',[dsn],sql_ddl) +# +# f_fblog_before=open( os.path.join(context['temp_directory'],'tmp_5275_fblog_before.txt'), 'w') +# svc_get_fb_log( engine, f_fblog_before ) +# flush_and_close( f_fblog_before ) +# +# ######################################################### +# +# rows_to_add=1000 +# +# sql_bulk_insert=''' set bail on; +# set list on; +# +# -- DISABLED 19.08.2020: alter sequence g restart with 0; +# +# delete from test; +# commit; +# set transaction lock timeout 10; -- THIS LOCK TIMEOUT SERVES ONLY FOR DELAY, see below auton Tx start. +# +# select current_timestamp as bulk_insert_start from rdb$database; +# set term ^; +# execute block as +# declare i int; +# begin +# i = gen_id(g, -gen_id(g, 0)); -- restart sequence, since 19.08.2020 +# execute procedure sp_ins( %(rows_to_add)s ); +# begin +# -- ######################################################### +# -- ####################### D E L A Y ##################### +# -- ######################################################### +# in autonomous transaction do +# insert into test( x ) values( %(rows_to_add)s ); -- this will cause delay because of duplicate in index +# when any do +# begin +# i = gen_id(g,1); +# end +# end +# end +# ^ +# set term ;^ +# commit; +# select current_timestamp as bulk_insert_finish from rdb$database; +# ''' +# +# sql_create_indx=''' set bail on; +# set list on; +# set blob all; +# select +# iif( gen_id(g,0) > 0 and gen_id(g,0) < 1 + %(rows_to_add)s, +# 'OK, IS RUNNING', +# iif( gen_id(g,0) <=0, +# 'WRONG: not yet started, current gen_id='||gen_id(g,0), +# 'WRONG: already finished, rows_to_add='||%(rows_to_add)s ||', current gen_id='||gen_id(g,0) +# ) +# ) as inserts_state, +# current_timestamp as create_indx_start +# from rdb$database; +# set autoddl off; +# commit; +# +# set echo on; +# set transaction %(tx_decl)s; +# +# create index test_%(idx_name)s on test computed by( %(idx_expr)s ); +# set echo off; +# commit; +# +# select +# iif( gen_id(g,0) >= 1 + %(rows_to_add)s, +# 'OK, FINISHED', +# 'SOMETHING WRONG: current gen_id=' || gen_id(g,0)||', rows_to_add='||%(rows_to_add)s +# ) as inserts_state +# from rdb$database; +# +# set count on; +# select +# rdb$index_name +# ,coalesce(rdb$unique_flag,0) as rdb$unique_flag +# ,coalesce(rdb$index_inactive,0) as rdb$index_inactive +# ,rdb$expression_source as rdb_expr_blob +# from rdb$indices ri +# where ri.rdb$index_name = upper( 'test_%(idx_name)s' ) +# ; +# set count off; +# set echo on; +# set plan on; +# select 1 from test where %(idx_expr)s > '' rows 0; +# set plan off; +# set echo off; +# commit; +# drop index test_%(idx_name)s; +# commit; +# ''' +# +# sql_kill_att=''' set count on; +# set list on; +# commit; +# delete from mon$attachments where mon$attachment_id<>current_connection; +# ''' +# +# f_kill_att_sql = open( os.path.join(context['temp_directory'],'tmp_5275_kill_att.sql' ), 'w') +# f_kill_att_sql.write( sql_kill_att ) +# flush_and_close( f_kill_att_sql ) +# +# tx_param=['WAIT','WAIT'] +# +# for i in range(len(tx_param)): +# +# f_bulk_insert_sql = open( os.path.join(context['temp_directory'],'tmp_5275_ins.sql'), 'w') +# f_bulk_insert_sql.write(sql_bulk_insert % locals() ) +# flush_and_close( f_bulk_insert_sql ) +# +# tx_decl=tx_param[i] +# idx_name=tx_decl.replace(' ','_') +# idx_expr="'"+idx_name+"'|| s" +# +# f_create_indx_sql = open( os.path.join(context['temp_directory'],'tmp_5275_idx_%s.sql' % str(i) ), 'w') +# f_create_indx_sql.write( sql_create_indx % locals() ) +# flush_and_close( f_create_indx_sql ) +# +# f_bulk_insert_log = open( os.path.join(context['temp_directory'],'tmp_5275_ins_%s.log' % str(i) ), 'w') +# f_create_indx_log = open( os.path.join(context['temp_directory'],'tmp_5275_idx_%s.log' % str(i) ), 'w') +# +# p_bulk_insert=subprocess.Popen( [context['isql_path'], dsn, "-q", "-i", f_bulk_insert_sql.name ], +# stdout = f_bulk_insert_log, +# stderr = subprocess.STDOUT +# ) +# +# # 3.0 Classic: seems that it requires at least 2 seconds for ISQL be loaded into memory. +# time.sleep(2) +# +# p_create_indx=subprocess.Popen( [context['isql_path'], dsn, "-q", "-i", f_create_indx_sql.name ], +# stdout = f_create_indx_log, +# stderr = subprocess.STDOUT +# ) +# time.sleep(2) +# +# f_kill_att_log = open( os.path.join(context['temp_directory'],'tmp_5275_kill_att.log' ), 'w') +# +# subprocess.call( [context['isql_path'], dsn, "-q", "-i", f_kill_att_sql.name ], +# stdout = f_kill_att_log, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_kill_att_log ) +# +# # 11.05.2017, FB 4.0 only! +# # Following messages can appear after 'connection shutdown' +# # (letter from dimitr, 08-may-2017 20:41): +# # isc_att_shut_killed: Killed by database administrator +# # isc_att_shut_idle: Idle timeout expired +# # isc_att_shut_db_down: Database is shutdown +# # isc_att_shut_engine: Engine is shutdown +# +# # do NOT remove this delay, otherwise ISQL logs in 2.5.x will contain NO text with error message +# # STATEMENT FAILED, SQLSTATE = 08003 / CONNECTION SHUTDOWN: +# time.sleep(1) +# +# p_create_indx.terminate() +# p_bulk_insert.terminate() +# +# flush_and_close( f_bulk_insert_log ) +# flush_and_close( f_create_indx_log ) +# +# with open( f_bulk_insert_log.name,'r') as f: +# for line in f: +# if line.split(): +# print( str(i)+': BULK INSERTS LOG: '+line.strip().upper() ) +# +# with open( f_create_indx_log.name,'r') as f: +# for line in f: +# if line.split(): +# print( str(i)+': CREATE INDEX LOG: '+line.strip().upper() ) +# +# with open( f_kill_att_log.name,'r') as f: +# for line in f: +# if line.split(): +# print( str(i)+': KILL ATTACH LOG: '+line.upper() ) +# +# # cleanup (nitermediate): +# ######### +# time.sleep(1) +# cleanup( (f_bulk_insert_sql, f_create_indx_sql, f_bulk_insert_log, f_create_indx_log, f_kill_att_log) ) +# +# # ------------------------------------------------------------------------------------------ +# +# f_fblog_after=open( os.path.join(context['temp_directory'],'tmp_5275_fblog_after.txt'), 'w') +# svc_get_fb_log( engine, f_fblog_after ) +# flush_and_close( f_fblog_after ) +# +# # Now we can compare two versions of firebird.log and check their difference. +# ################################# +# +# oldfb=open(f_fblog_before.name, 'r') +# newfb=open(f_fblog_after.name, 'r') +# +# difftext = ''.join(difflib.unified_diff( +# oldfb.readlines(), +# newfb.readlines() +# )) +# oldfb.close() +# newfb.close() +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_5275_diff.txt'), 'w') +# f_diff_txt.write(difftext) +# flush_and_close( f_diff_txt ) +# +# # This should be empty: +# ####################### +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# # internal Firebird consistency check (invalid SEND request (167), file: JrdStatement.cpp line: 325) +# if 'consistency check' in line: +# print('NEW IN FIREBIRD.LOG: '+line.upper()) +# +# +# #-------------------------------------------------------------------------------------------- +# +# f_validate_log=open( os.path.join(context['temp_directory'],'tmp_5275_validate.log'), "w") +# f_validate_err=open( os.path.join(context['temp_directory'],'tmp_5275_validate.err'), "w") +# +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_validate", +# "dbname", "$(DATABASE_LOCATION)bugs.core_5275.fdb" +# ], +# stdout=f_validate_log, +# stderr=f_validate_err) +# flush_and_close( f_validate_log ) +# flush_and_close( f_validate_err ) +# +# with open( f_validate_log.name,'r') as f: +# for line in f: +# if line.split(): +# print( 'VALIDATION STDOUT: '+line.upper() ) +# +# with open( f_validate_err.name,'r') as f: +# for line in f: +# if line.split(): +# print( 'VALIDATION STDERR: '+line.upper() ) +# +# # cleanup +# ######### +# time.sleep(1) +# cleanup( (f_validate_log, f_validate_err, f_kill_att_sql, f_fblog_before, f_fblog_after, f_diff_txt) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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 + """ + +@pytest.mark.version('>=2.5.6') +@pytest.mark.xfail +def test_core_5275_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5277.py b/tests/bugs/test_core_5277.py new file mode 100644 index 00000000..476efbab --- /dev/null +++ b/tests/bugs/test_core_5277.py @@ -0,0 +1,109 @@ +#coding:utf-8 +# +# id: bugs.core_5277 +# title: Parameters with multibyte character sets allow to bypass the character limit of varchar fields +# decription: +# Checked on LI-V3.0.1.32533, built it from sources 20160617 19:30 +# +# tracker_id: CORE-5277 +# min_versions: ['3.0.1'] +# versions: 3.0.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.1 +# resources: None + +substitutions_1 = [('BULK>.*', '')] + +init_script_1 = """ + recreate table test ( c varchar(2) character set utf8 ); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# # 'connection_character_set': 'UTF8', +# +# db_conn.close() +# +# sql_chk=''' +# set bulk_insert insert into test values(?); +# ('ab') +# ('qw') +# ('er') +# ('tyu') +# stop +# set list on; -- !! do NOT remove this "duplicate" statement, otherwise data will be shown as when set list OFF !! Incredible... 8-O +# set list on; +# select * from test; +# +# commit; +# ----------------------------------- +# -- Following sample was discussed with dimitr 29.06.2016. +# -- Statement failed, SQLSTATE = 22001 +# -- arithmetic exception, numeric overflow, or string truncation +# -- -string right truncation +# -- -expected length 10, actual 17 +# set term ^; +# create or alter function get_mnemonic ( +# afield_name type of column rdb$types.rdb$field_name, +# atype type of column rdb$types.rdb$type) +# returns type of column rdb$types.rdb$type_name +# as +# begin +# return (select rdb$type_name +# from rdb$types +# where +# rdb$field_name = :afield_name +# and rdb$type = :atype +# order by rdb$type_name +# ); +# end +# ^ +# set term ;^ +# commit; +# +# set list on; +# +# select get_mnemonic('MON$SHUTDOWN_MODE', 1) as mnemonic from rdb$database; +# ''' +# +# runProgram('isql',[dsn, '-ch', 'utf8'],sql_chk) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + C ab + C qw + C er + MNEMONIC MULTI_USER_SHUTDOWN + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22001 + arithmetic exception, numeric overflow, or string truncation + -string right truncation + -expected length 2, actual 3 + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Token unknown - line 1, column 1 + -stop + """ + +@pytest.mark.version('>=3.0.1') +@pytest.mark.xfail +def test_core_5277_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5279.py b/tests/bugs/test_core_5279.py new file mode 100644 index 00000000..168acae6 --- /dev/null +++ b/tests/bugs/test_core_5279.py @@ -0,0 +1,72 @@ +#coding:utf-8 +# +# id: bugs.core_5279 +# title: Granting access rights to view is broken +# decription: +# Confirmed bug on 3.0.0.32483 (official 3.0 release). +# Checked on 3.0.1.32539, 4.0.0.262 - works fine. +# +# tracker_id: CORE-5279 +# min_versions: ['3.0.1'] +# versions: 3.0.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter user tmp$c5279 password '123'; + commit; + recreate table test (id integer); + recreate table test1 (id integer); + commit; + create or alter view v_test as + select * + from test + where id in (select id from test1); + commit; + grant select on v_test to public; + grant select on test1 to view v_test; + commit; + insert into test(id) values(1); + insert into test(id) values(2); + insert into test(id) values(3); + + insert into test1(id) values(3); + insert into test1(id) values(4); + insert into test1(id) values(5); + commit; + + connect '$(DSN)' user tmp$c5279 password '123'; + set count on; + set list on; + select current_user as who_am_i, v.* from v_test v; + commit; + connect '$(DSN)' user sysdba password 'masterkey'; + drop user tmp$c5279; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHO_AM_I TMP$C5279 + ID 3 + Records affected: 1 + """ + +@pytest.mark.version('>=3.0.1') +def test_core_5279_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5291.py b/tests/bugs/test_core_5291.py new file mode 100644 index 00000000..8293f3ac --- /dev/null +++ b/tests/bugs/test_core_5291.py @@ -0,0 +1,94 @@ +#coding:utf-8 +# +# id: bugs.core_5291 +# title: Error messages differ when regular user tries to RESTORE database, depending on his default role and (perhaps) system privilege USE_GBAK_UTILITY +# decription: +# Works fine on 4.0.0.316. +# +# tracker_id: CORE-5291 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('gbak: ERROR:no permission for CREATE access to DATABASE.*', 'gbak: ERROR:no permission for CREATE access to DATABASE'), ('gbak: ERROR: failed to create database.*', 'gbak: ERROR: failed to create database'), ('gbak: ERROR:failed to create database localhost:.*', 'gbak: ERROR:failed to create database localhost')] + +init_script_1 = """ + set wng off; + create or alter user tmp$c5291_1 password '123' revoke admin role; + create or alter user tmp$c5291_2 password '456' revoke admin role; + commit; + revoke all on all from tmp$c5291_1; + revoke all on all from tmp$c5291_2; + commit; + create role role_for_use_gbak_utility set system privileges to USE_GBAK_UTILITY, SELECT_ANY_OBJECT_IN_DATABASE; + commit; + grant default role_for_use_gbak_utility to user tmp$c5291_2; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# tmpfbk=os.path.join(context['temp_directory'],'tmp_core_5291.fbk') +# tmpres1=os.path.join(context['temp_directory'],'tmp_core_5291_1.tmp') +# tmpres2=os.path.join(context['temp_directory'],'tmp_core_5291_2.tmp') +# +# runProgram('gbak',['-b', dsn, tmpfbk]) +# +# runProgram('gbak',['-se', 'localhost:service_mgr', '-rep', tmpfbk, tmpres1, '-user', 'tmp$c5291_1', '-pas', '123']) +# runProgram('gbak',['-rep', tmpfbk, 'localhost:' + tmpres2, '-user', 'tmp$c5291_1', '-pas', '123']) +# +# runProgram('gbak',['-se', 'localhost:service_mgr', '-rep', tmpfbk, tmpres1, '-user', 'tmp$c5291_2', '-pas', '456']) +# runProgram('gbak',['-rep', tmpfbk, 'localhost:' + tmpres2, '-user', 'tmp$c5291_2', '-pas', '456']) +# +# runProgram('isql',[dsn],'drop user tmp$c5291_1; drop user tmp$c5291_2;') +# +# f_list=[tmpfbk, tmpres1, tmpres2] +# +# for i in range(len(f_list)): +# if os.path.isfile(f_list[i]): +# os.remove(f_list[i]) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + gbak: ERROR:no permission for CREATE access to DATABASE + gbak: ERROR: failed to create database + gbak: ERROR: Exiting before completion due to errors + gbak:Exiting before completion due to errors + + gbak: ERROR:no permission for CREATE access to DATABASE + gbak: ERROR:failed to create database localhost + gbak:Exiting before completion due to errors + + gbak: ERROR:no permission for CREATE access to DATABASE + gbak: ERROR: failed to create database + gbak: ERROR: Exiting before completion due to errors + gbak:Exiting before completion due to errors + + gbak: ERROR:no permission for CREATE access to DATABASE + gbak: ERROR:failed to create database localhost + gbak:Exiting before completion due to errors + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_5291_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5295.py b/tests/bugs/test_core_5295.py new file mode 100644 index 00000000..927f4560 --- /dev/null +++ b/tests/bugs/test_core_5295.py @@ -0,0 +1,122 @@ +#coding:utf-8 +# +# id: bugs.core_5295 +# title: Validation could read after the end-of-file when handle multifile database +# decription: +# Reproduced error on WI-V3.0.1.32542 (SS/SC/CS) and WI-T4.0.0.258, WI-T4.0.0.267 (SS). +# Could NOT reproduce on WI-V2.5.6.27017 (SuperClassic). +# +# 07.08.2016: removed dependency on 'employee'- there is some strange reports about missing it. +# Instead of using existing 'employee', its .fbk was created (on 2.5.7), added it to fpt-repo/fbk +# folder and is restored here. +# +# tracker_id: CORE-5295 +# min_versions: ['2.5.6'] +# versions: 2.5.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.6 +# resources: None + +substitutions_1 = [('\t+', ' '), ('^((?!checked_size|Error|error).)*$', '')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core5295.fbk', init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import time +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# fbk_file='$(DATABASE_LOCATION)tmp.core_5295.fbk' +# fdb_tmp1='$(DATABASE_LOCATION)tmp.core_5295.1.tmp' +# fdb_tmp2='$(DATABASE_LOCATION)tmp.core_5295.2.tmp' +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# cleanup( (fbk_file, fdb_tmp1, fdb_tmp2) ) +# +# runProgram('gbak',['-b', dsn, fbk_file]) +# runProgram('gbak',['-rep',fbk_file, 'localhost:'+fdb_tmp1, '100000', fdb_tmp2 ]) +# +# f_val_log=open( os.path.join(context['temp_directory'],'tmp_gfix_v_5295.log'), 'w') +# +# # Only 'gfix -v' raised error. Online validation works fine: +# ################ +# subprocess.call([context['gfix_path'], "-v", 'localhost:'+fdb_tmp1], stdout=f_val_log, stderr=subprocess.STDOUT) +# +# flush_and_close( f_val_log ) +# +# #I/O error during "ReadFile" operation for file " mp.core_5295.fd1" +# #-Error while trying to read from file +# #- +# +# # NB: because of localized text inside f_val_log we have to SKIP scanning this file line-by-line +# # and only check that its size is ZERO. +# # If size of validation is non-zero than it must be considered as error: +# +# print("checked_size of validation log: " + str(os.path.getsize(f_val_log.name)) ) +# with open( f_val_log.name,'r') as f: +# for line in f: +# print('VALIDATION LOG: '+line) +# +# +# # cleanup: +# ########## +# time.sleep(1) +# cleanup( (f_val_log.name, fbk_file, fdb_tmp1, fdb_tmp2) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + checked_size of validation log: 0 + """ + +@pytest.mark.version('>=2.5.6') +@pytest.mark.xfail +def test_core_5295_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5302.py b/tests/bugs/test_core_5302.py new file mode 100644 index 00000000..66bd08e5 --- /dev/null +++ b/tests/bugs/test_core_5302.py @@ -0,0 +1,116 @@ +#coding:utf-8 +# +# id: bugs.core_5302 +# title: Performance regression when bulk inserting into table with indices +# decription: +# Test uses TWO tables, one w/o indices and another with indexes. +# We evaluate RATIO between performance rather than absolute duration values. +# This ratio then is compared with THRESHOLD which was choosen after dozen runs +# of test on FB 3.0 and 4.0. +# +# _BEFORE_ this ticket was fixed ratio was following: +# +# Ratio for 4.0.0.258: ~32...34 -- poor +# Ratio for 3.0.1.32566: ~23...24 -- poor +# +# _AFTER_ ticket was fixed ratio is: +# +# Ratio for 4.0.0.313: ~11...13 -- OK +# Ratio for 3.0.1.32568: ~10...11 -- OK +# +# Fix for 4.0 was 07-jul-2016, see here: +# https://github.com/FirebirdSQL/firebird/commit/a75e0af175ea6e803101b5fd62ec91cdf039b951 +# Fix for 3.0 was 27-jul-2016, see here: +# https://github.com/FirebirdSQL/firebird/commit/96a24228b61003e72c68596faf3c4c4ed0b95ea1 +# +# All measures were done on regular PC, OS = Windows XP, CPU 3.0 Ghz, RAM 2 Gb, HDD IDE. +# 05.01.2020: increased threshold from 15 to 20 (Win 2008 Server R2, ram 8gb) +# Checked on: +# 4.0.0.1714 SS: 5.922s; 4.0.0.1714 SC: 7.891s; 4.0.0.1714 CS: 9.891s. +# 3.0.5.33221 SS: 4.735s; 3.0.5.33221 SC: 5.718s; 3.0.5.33221 CS: 7.126s. +# +# 13.01.2020: checked again (Win 8.1 Pro, ram 12 gb): +# 4.0.0.2325 SS: 5.806s. +# 4.0.0.2324 SC: 5.812s. +# 4.0.0.2324 CS: 6.651s. +# 3.0.8.33401 SS: 5.366s. +# 3.0.8.33401 SC: 4.823s. +# 3.0.8.33401 CS: 6.089s. +# +# tracker_id: CORE-5302 +# min_versions: ['3.0.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table test0(x int, y int, z int); + recreate table test1(x int, y int, z int); + create index test1_x on test1(x); + create index test1_y on test1(y); + create index test1_z on test1(z); + create index test1_xy on test1(x, y); + create index test1_xz on test1(x, z); + create index test1_xyz on test1(x, y, z); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set term ^; + execute block returns(msg varchar(100)) as + declare n int = 50000; + declare m int; + declare t0 timestamp; + declare t1 timestamp; + declare t2 timestamp; + declare max_ratio numeric(12,4) = 20; + -- ^ + -- | + -- +--- ##### T H R E S H O L D ##### + declare cur_ratio numeric(12,4); + begin + t0='now'; + m = n; + while(m>0) do insert into test0(x, y, z) values(:m, :m, :m) returning :m-1 into m; + + t1='now'; + m = n; + while(m>0) do insert into test1(x, y, z) values(:m, :m, :m) returning :m-1 into m; + t2='now'; + + cur_ratio = 1.0000 * datediff(millisecond from t1 to t2) / datediff(millisecond from t0 to t1); + + msg = iif( cur_ratio < max_ratio, + 'OK, ratio is acceptable', + 'POOR: ratio = ' || cur_ratio || ' - exceeds threshold = ' || max_ratio + ); + suspend; + + end + ^ + set term ;^ + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG OK, ratio is acceptable + """ + +@pytest.mark.version('>=3.0') +def test_core_5302_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5304.py b/tests/bugs/test_core_5304.py new file mode 100644 index 00000000..50cc4d2f --- /dev/null +++ b/tests/bugs/test_core_5304.py @@ -0,0 +1,74 @@ +#coding:utf-8 +# +# id: bugs.core_5304 +# title: Regression: Can not restore database with table contains field CHAR(n) and UTF8 character set +# decription: +# We make initial DDL and DML using ISQL with connection charset = UTF8, and then run b/r. +# Ouput of restore is filtered so that only lines with 'ERROR' word can be displayed. +# This output should be EMPTY (i.e. no errors should occur). +# +# Confirmed on WI-T4.0.0.258, got: +# gbak: ERROR:arithmetic exception, numeric overflow, or string truncation +# gbak: ERROR: string right truncation +# gbak: ERROR: expected length 10, actual 40 +# gbak: ERROR: gds_$send failed +# gbak: ERROR: Exiting before completion due to errors +# +# All works fine on WI-T4.0.0.313. +# +# tracker_id: CORE-5304 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('^((?!ERROR).)*$', '')] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# sql=''' +# recreate table test(c char(10)); +# commit; +# insert into test values(null); +# commit; +# ''' +# runProgram('isql',['-ch','UTF8',dsn],sql) +# +# tmpfbk = os.path.join(context['temp_directory'],'tmp_core_5304.fbk') +# tmpres = os.path.join(context['temp_directory'],'tmp_core_5304.fdb') +# +# runProgram('gbak',['-b',dsn,tmpfbk]) +# runProgram('gbak',['-c','-v','-se','localhost:service_mgr',tmpfbk,tmpres]) +# +# f_list=[tmpfbk,tmpres] +# for i in range(len(f_list)): +# if os.path.isfile(f_list[i]): +# os.remove(f_list[i]) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_5304_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5305.py b/tests/bugs/test_core_5305.py new file mode 100644 index 00000000..361e31da --- /dev/null +++ b/tests/bugs/test_core_5305.py @@ -0,0 +1,165 @@ +#coding:utf-8 +# +# id: bugs.core_5305 +# title: CASCADE UPDATE fails for self-referencing FK +# decription: +# Checked on 4.0.0.326, WI-V3.0.1.32573 +# +# tracker_id: CORE-5305 +# min_versions: ['3.0.1'] +# versions: 3.0.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + recreate table test1( + x int, + y int, + constraint test1_pk primary key(x), + constraint test1_fk foreign key(y) references test1(x) on update cascade + ); + commit; + + insert into test1 (x, y) values (1, null); + insert into test1 (x, y) values (2, null); + insert into test1 (x, y) values (3, 1); + commit; + + -- 4.0.0.322 - OK + -- 3.0.0.32483: + -- Statement failed, SQLSTATE = 23000 + -- violation of FOREIGN KEY constraint "test1_FK" on table "test1" + -- -Foreign key reference target does not exist + -- -Problematic key value is ("y" = 1) + + update test1 set x = -x; + select 'test1' as what, a.* from test1 a order by x; + commit; + + -------------------------------------------------------------------------------------- + + -- Sample from core-3362, 03/Jan/14 05:07 PM: + -- ========================================== + recreate table test2( + x int, y int, + constraint t_pk primary key(x), + constraint t_fk foreign key(y) references test2(x) on update cascade -- SELF-REFERENCING + ); + create descending index t_x_desc on test2(x); + commit; + + insert into test2(x, y) values(1, null); + insert into test2(x, y) values(2, 1 ); + insert into test2(x, y) values(3, 2 ); + insert into test2(x, y) values(4, 3 ); + insert into test2(x, y) values(5, 4 ); + update test2 set y=5 where x=1; -- "closure" of chain + commit; + + update test2 set x = y + 1; + + select 'test2' as what, a.* from test2 a order by x; + commit; + + ---------------------------------------------------------------------------- + + -- Sample from core-3362, 14/May/15 06:40 AM + -- ========================================= + + recreate table test3( + id int constraint test_pk_id primary key using index test_pk_id, + pid int constraint test_fk_pid2id references test3(id) + on update SET NULL + ); + commit; + insert into test3 values( 5, null ); + insert into test3 values( 4, 5 ); + insert into test3 values( 3, 4 ); + insert into test3 values( 2, 3 ); + insert into test3 values( 1, 2 ); + update test3 set pid=1 where id=5; --"closure" of chain + commit; + + update test3 set id = id + 1 order by id desc; + select 'test3' as what, a.* from test3 a order by id; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHAT test1 + X -3 + Y -1 + + WHAT test1 + X -2 + Y + + WHAT test1 + X -1 + Y + + + + WHAT test2 + X 2 + Y 6 + + WHAT test2 + X 3 + Y 2 + + WHAT test2 + X 4 + Y 3 + + WHAT test2 + X 5 + Y 4 + + WHAT test2 + X 6 + Y 5 + + + + WHAT test3 + ID 2 + PID + + WHAT test3 + ID 3 + PID + + WHAT test3 + ID 4 + PID + + WHAT test3 + ID 5 + PID + + WHAT test3 + ID 6 + PID + """ + +@pytest.mark.version('>=3.0.1') +def test_core_5305_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5309.py b/tests/bugs/test_core_5309.py new file mode 100644 index 00000000..d6a54c6e --- /dev/null +++ b/tests/bugs/test_core_5309.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: bugs.core_5309 +# title: Backup created under FB2.5 can be restored in FB3.0.0.32419 but not under current snapshot (FB3.0.1.32556) +# decription: +# Test does trivial attempt to restore database which was given by ticket starter as attached file. +# No further actions required. STDOUR and STDERR must be empty. +# +# Confirmed on 4.0.0.258, got: +# GBAK_STDERR: +# gbak: ERROR:arithmetic exception, numeric overflow, or string truncation +# gbak: ERROR: string right truncation +# gbak: ERROR: expected length 67, actual 201 +# gbak: ERROR:gds_$send failed +# gbak:Exiting before completion due to errors +# +# All works fine on 3.0.1.32568 and 4.0.0.313. +# +# tracker_id: CORE-5309 +# min_versions: ['3.0.1'] +# versions: 3.0.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core5309.fbk', init=init_script_1) + +test_script_1 = """ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0.1') +def test_core_5309_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_5313.py b/tests/bugs/test_core_5313.py new file mode 100644 index 00000000..44503126 --- /dev/null +++ b/tests/bugs/test_core_5313.py @@ -0,0 +1,87 @@ +#coding:utf-8 +# +# id: bugs.core_5313 +# title: Data type unknown error with LIST +# decription: +# tracker_id: CORE-5313 +# min_versions: ['3.0.1'] +# versions: 3.0.1, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set planonly; + set sqlda_display on; + select list(trim(rdb$relation_name), ?) from rdb$relations; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + INPUT message field count: 1 + 01: sqltype: 452 TEXT scale: 0 subtype: 0 len: 3 charset: 3 UNICODE_FSS + : 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: 3 UNICODE_FSS + : name: LIST alias: LIST + : table: owner: + """ + +@pytest.mark.version('>=3.0.1,<4.0') +def test_core_5313_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set planonly; + set sqlda_display on; + select list(trim(rdb$relation_name), ?) from rdb$relations; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + 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: + """ + +@pytest.mark.version('>=4.0') +def test_core_5313_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/bugs/test_core_5322.py b/tests/bugs/test_core_5322.py new file mode 100644 index 00000000..3b931f6a --- /dev/null +++ b/tests/bugs/test_core_5322.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: bugs.core_5322 +# title: Error "no current record to fetch" if some record is to be deleted both by the statement itself and by some trigger fired during statement execution +# decription: +# Reproduced bug on WI-V3.0.0.32483, WI-T4.0.0.258 +# All fine on WI-V3.0.1.32596, WI-T4.0.0.366. +# +# tracker_id: CORE-5322 +# min_versions: ['3.0.1'] +# versions: 3.0.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table tdetl(id int); + commit; + + recreate table tmain ( + id integer not null, + some_data integer + ); + + recreate table tdetl ( + id integer not null, + tmain_id integer, + some_data integer, + parent_id integer + ); + commit; + + insert into tmain (id, some_data) values (1, 10); + commit; + + insert into tdetl (id, tmain_id, some_data, parent_id) values (1, 1, 555, null); + insert into tdetl (id, tmain_id, some_data, parent_id) values (2, 1, 222, 1); + commit; + + alter table tmain add constraint pk_tmain primary key (id); + alter table tdetl add constraint pk_tdetl primary key (id); + alter table tdetl add constraint fk_tdetl_1 foreign key (tmain_id) references tmain (id) on delete cascade; + alter table tdetl add constraint fk_tdetl_2 foreign key (parent_id) references tdetl (id) on delete cascade; + commit; + + delete from tmain where (id = 1); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0.1') +def test_core_5322_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_5325.py b/tests/bugs/test_core_5325.py new file mode 100644 index 00000000..5efb1936 --- /dev/null +++ b/tests/bugs/test_core_5325.py @@ -0,0 +1,136 @@ +#coding:utf-8 +# +# id: bugs.core_5325 +# title: Malformed string error when using cyrilic symbols and x'0d0a' in exception +# decription: +# Ticked is marked as Won't fix, but it seems that sample shown by Adriano is useful for testing. +# Checked on old versions: 3.0.0.32483, 3.0.2.32703, 3.0.4.32972 -- works OK. +# +# 05-mar-2021. Re-implemented in order to have ability to run this test on Linux. +# Test encodes to UTF8 all needed statements (SET NAMES; CONNECT; DDL and DML) and stores this text in .sql file. +# NOTE: 'SET NAMES' contain character set that must be used for reproducing problem (WIN1251 in this test). +# Then ISQL is launched in separate (child) process which performs all necessary actions (using required charset). +# Result will be redirected to log(s) which will be opened further via codecs.open(...encoding='cp1251'). +# Finally, its content will be converted to UTF8 for showing in expected_stdout. +# Checked on: +# * Windows: 4.0.0.2377 +# * Linux: 4.0.0.2379, 3.0.8.33415 +# +# tracker_id: CORE-5325 +# min_versions: ['3.0.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('exception [\\d]+', 'exception'), ('-At block line(:)?\\s+[\\d]+.*', ''), ('After line(:)?\\s+[\\d]+.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import codecs +# import subprocess +# import time +# engine = db_conn.engine_version +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql_txt=''' set bail on; +# set names win1251; +# connect '%(dsn)s' user '%(user_name)s' password '%(user_password)s'; +# +# +# create exception error_test 'йцукенг'; +# commit; +# set term ^; +# execute block as +# begin +# exception error_test 'йцу' || _win1251 x'0d0a' || 'кенг'; +# end^ +# set term ;^ +# +# ''' % dict(globals(), **locals()) +# +# f_run_sql = open( os.path.join(context['temp_directory'], 'tmp_5325_win1251.sql'), 'w' ) +# f_run_sql.write( sql_txt.decode('utf8').encode('cp1251') ) +# flush_and_close( f_run_sql ) +# +# # result: file tmp_5325_win1251.sql is encoded in win1251 +# +# f_run_log = open( os.path.splitext(f_run_sql.name)[0]+'.log', 'w') +# subprocess.call( [ context['isql_path'], '-q', '-i', f_run_sql.name ], +# stdout = f_run_log, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_run_log ) # result: output will be encoded in win1251 +# +# with codecs.open(f_run_log.name, 'r', encoding='cp1251' ) as f: +# result_in_win1251 = f.readlines() +# +# for i in result_in_win1251: +# print( i.encode('utf8') ) +# +# # cleanup: +# ########### +# cleanup( (f_run_sql, f_run_log) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Statement failed, SQLSTATE = HY000 + exception 1 + -ERROR_TEST + -йцу + + кенг + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_5325_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5329.py b/tests/bugs/test_core_5329.py new file mode 100644 index 00000000..8557779c --- /dev/null +++ b/tests/bugs/test_core_5329.py @@ -0,0 +1,169 @@ +#coding:utf-8 +# +# id: bugs.core_5329 +# title: Database gets partially corrupted in the "no-reserve" mode +# decription: +# Test uses .fbk which was created on 2.5.7. +# We restore this database and run validation using gfix (NOT fbsvcmgr!). +# Validation should not produce any output and new lines in firebird.log should contain +# only messages about start and finish of validation with zero errors and warnings. +# +# Confirmed bug on 4.0.0.326, 3.0.1.32573. No errors on 4.0.0.328, 3.0.1.32575 +# +# tracker_id: CORE-5329 +# min_versions: ['3.0.1'] +# versions: 3.0.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.1 +# resources: None + +substitutions_1 = [('\t+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core5329.fbk', init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import time +# import subprocess +# import difflib +# import re +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# def svc_get_fb_log( f_fb_log ): +# +# import subprocess +# +# subprocess.call([ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# 'action_get_fb_log' +# ], +# stdout=f_fb_log, stderr=subprocess.STDOUT +# ) +# return +# +# +# # Get firebird.log content BEFORE running validation: +# +# f_fblog_before=open( os.path.join(context['temp_directory'],'tmp_5329_fblog_before.txt'), 'w') +# svc_get_fb_log( f_fblog_before ) +# flush_and_close( f_fblog_before ) +# +# # Only 'gfix -v' did show errors. +# ################################# +# # Online validation ('fbsvcmgr action_validate ...') worked WITHOUT any error/warningin its output. +# +# f_gfix_log=open( os.path.join(context['temp_directory'],'tmp_5329_gfix.txt'), 'w') +# subprocess.call( [ context['gfix_path'], '-v', '-full', dsn], stdout=f_gfix_log, stderr=subprocess.STDOUT) +# flush_and_close( f_gfix_log ) +# +# # Get firebird.log content AFTER running validation: +# +# f_fblog_after=open( os.path.join(context['temp_directory'],'tmp_5329_fblog_after.txt'), 'w') +# svc_get_fb_log( f_fblog_after ) +# flush_and_close( f_fblog_after ) +# +# # Check-1. Log of 'gfix -v -full'should be EMPTY: +# ################################################# +# +# print("Checked_size of gfix stdlog+stderr: " + str(os.path.getsize(f_gfix_log.name)) ) +# +# with open( f_gfix_log.name,'r') as f: +# for line in f: +# print('UNEXPECTED VALIDATION LOG: '+line) +# +# oldfb=open(f_fblog_before.name, 'r') +# newfb=open(f_fblog_after.name, 'r') +# +# difftext = ''.join(difflib.unified_diff( +# oldfb.readlines(), +# newfb.readlines() +# )) +# oldfb.close() +# newfb.close() +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_2668_diff.txt'), 'w') +# f_diff_txt.write(difftext) +# flush_and_close( f_diff_txt ) +# +# pattern = re.compile('.*VALIDATION.*|.*ERROR:.*') +# +# # NB: difflib.unified_diff() can show line(s) that present in both files, without marking that line(s) with "+". +# # Usually these are 1-2 lines that placed just BEFORE difference starts. +# # So we have to check output before display diff content: lines that are really differ must start with "+". +# +# # Check-2. Difference betweenold and new firebird.log should contain +# # only lines about validation start and finish, without errors: +# ############################################################### +# +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# if line.startswith('+'): +# if pattern.match(line.upper()): +# print( ' '.join(line.split()).upper() ) +# +# +# # Cleanup +# ######### +# time.sleep(1) +# cleanup( (f_gfix_log, f_fblog_before, f_fblog_after, f_diff_txt) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Checked_size of gfix stdlog+stderr: 0 + + VALIDATION STARTED + + VALIDATION FINISHED: 0 ERRORS, 0 WARNINGS, 0 FIXED + """ + +@pytest.mark.version('>=3.0.1') +@pytest.mark.xfail +def test_core_5329_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5330.py b/tests/bugs/test_core_5330.py new file mode 100644 index 00000000..705966d1 --- /dev/null +++ b/tests/bugs/test_core_5330.py @@ -0,0 +1,249 @@ +#coding:utf-8 +# +# id: bugs.core_5330 +# 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. +# decription: +# 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. +# Then we stop trace session and open isql log - it should contain three 'packets' of table records. +# If FB becomes unavaliable, this (and all subsequent) test will not finish at all. +# +# Checked on 4.0.0.331 (SS, SC) - works fine. +# +# tracker_id: CORE-5330 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# from subprocess import Popen +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# # Obtain engine version: +# +# txt30 = '''database = +# { +# enabled = true +# } +# ''' +# +# f_trccfg=open( os.path.join(context['temp_directory'],'tmp_trace_5330.cfg'), 'w') +# f_trccfg.write(txt30) +# flush_and_close( f_trccfg ) +# +# # Starting trace session in new child process (async.): +# ####################################################### +# +# f_trclog=open( os.path.join(context['temp_directory'],'tmp_trace_5330.log'), 'w') +# f_trcerr=open( os.path.join(context['temp_directory'],'tmp_trace_5330.err'), 'w') +# +# +# p_trace=Popen([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_start", +# "trc_cfg", f_trccfg.name], +# stdout=f_trclog, +# stderr=f_trcerr +# ) +# +# sql='''recreate table ttt(id int generated by default as identity, x int, y int); +# commit; +# +# set term ^; +# execute block as +# declare s varchar(200) = 'insert into ttt(x, y) values(?, ?)'; +# declare n int = 3; +# begin +# while (n>0) do +# begin +# execute statement (s) (:n, :n * 2); +# n = n - 1; +# end +# end +# ^ +# set term ;^ +# commit; +# set list on; +# select * from ttt; +# ''' +# +# f_isql_cmd=open( os.path.join(context['temp_directory'],'tmp_isql_5330.sql'), 'w') +# f_isql_cmd.write(sql) +# flush_and_close( f_isql_cmd ) +# +# f_isql_log=open( os.path.join(context['temp_directory'],'tmp_isql_5330.log'), 'w') +# f_isql_err=open( os.path.join(context['temp_directory'],'tmp_isql_5330.err'), 'w') +# +# for i in range(3,0,-1): +# subprocess.call([ context['isql_path'], dsn, '-i', f_isql_cmd.name], stdout=f_isql_log, stderr=subprocess.STDOUT) +# if i > 1: +# time.sleep(1) +# flush_and_close( f_isql_log ) +# flush_and_close( f_isql_err ) +# +# +# ##################################################### +# # Getting ID of launched trace session and STOP it: +# +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# f_trclst=open( os.path.join(context['temp_directory'],'tmp_trace_5330.lst'), 'w') +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_list"], +# stdout=f_trclst, +# stderr=subprocess.STDOUT +# ) +# flush_and_close( f_trclst ) +# +# trcssn=0 +# with open( f_trclst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# f.close() +# +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# f_trclst=open(f_trclst.name,'a') +# f_trclst.seek(0,2) +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_stop", +# "trc_id",trcssn], +# stdout=f_trclst, stderr=subprocess.STDOUT +# ) +# flush_and_close( f_trclst ) +# +# # do NOT remove this delay: trase session can not be stopped immediatelly: +# time.sleep(1) +# +# # Terminate child process of launched trace session (though it should already be killed): +# p_trace.terminate() +# flush_and_close( f_trclog ) +# flush_and_close( f_trcerr ) +# +# # STDERR for ISQL (that created DB) and trace session - they both must be EMPTY: +# ################# +# f_list=[f_isql_err, f_trcerr] +# for i in range(len(f_list)): +# f_name=f_list[i].name +# if os.path.getsize(f_name) > 0: +# with open( f_name,'r') as f: +# for line in f: +# print("Unexpected STDERR, file "+f_name+": "+line) +# +# # STDLOG of isql: +# ################# +# with open(f_isql_log.name,'r') as f: +# for line in f: +# if line.split(): +# print(line) +# +# # Cleanup: +# ########## +# time.sleep(1) +# cleanup( (f_isql_cmd, f_isql_log, f_isql_err, f_trccfg, f_trclst, f_trcerr, f_trclog) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + X 3 + Y 6 + + ID 2 + X 2 + Y 4 + + ID 3 + X 1 + Y 2 + + ID 1 + X 3 + Y 6 + + ID 2 + X 2 + Y 4 + + ID 3 + X 1 + Y 2 + + ID 1 + X 3 + Y 6 + + ID 2 + X 2 + Y 4 + + ID 3 + X 1 + Y 2 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_5330_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5337.py b/tests/bugs/test_core_5337.py new file mode 100644 index 00000000..780c907c --- /dev/null +++ b/tests/bugs/test_core_5337.py @@ -0,0 +1,66 @@ +#coding:utf-8 +# +# id: bugs.core_5337 +# title: Regression: The subquery in the insert list expressions ignore the changes made earlier in the same executable block. +# decription: +# Confirmed on WI-T4.0.0.372 (nightly build) +# Works fine on: +# * 4.0.0.372 - after commit 21-sep-2016 12:39 +# https://github.com/FirebirdSQL/firebird/commit/d8f43da00f10181495160d12f17556fe9cc5687b +# * WI-V3.0.1.32609 - after commit 25-sep-2016 23:47 +# https://github.com/FirebirdSQL/firebird/commit/d5ff6d82c2d9edba7b6def2e6a32f753b856227a +# +# tracker_id: CORE-5337 +# min_versions: ['3.0.1'] +# versions: 3.0.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test ( + id integer not null, + val integer not null + ); + + set term ^; + execute block + as + begin + insert into test (id, val) values (1, 100); + insert into test (id, val) values (2, (select val from test where id = 1)); + end + ^ + set term ;^ + + set list on; + select * from test; + rollback; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + VAL 100 + + ID 2 + VAL 100 + """ + +@pytest.mark.version('>=3.0.1') +def test_core_5337_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5341.py b/tests/bugs/test_core_5341.py new file mode 100644 index 00000000..60b959bf --- /dev/null +++ b/tests/bugs/test_core_5341.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: bugs.core_5341 +# title: User collate doesn't work with blobs +# decription: +# Reproduced bug on 3.0.1.32594. +# All fine on WI-V3.0.1.32596, WI-T4.0.0.366. +# +# tracker_id: CORE-5341 +# min_versions: ['3.0.1'] +# versions: 3.0.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.1 +# resources: None + +substitutions_1 = [('BLOB_ID.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + execute block as + begin + execute statement 'drop collation pxw_cyrl_ci_ai'; + when any do begin end + end + ^ + set term ;^ + commit; + + create collation pxw_cyrl_ci_ai for win1251 from pxw_cyrl case insensitive accent insensitive; + commit; + + set list on; + set count on; + + with A as( + select cast('update' as blob sub_type text) as blob_id from rdb$database + union all + select 'UPDATE' from rdb$database + ) + select * from a + where blob_id collate PXW_CYRL_CI_AI like '%update%'; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + update + UPDATE + Records affected: 2 + """ + +@pytest.mark.version('>=3.0.1') +def test_core_5341_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5346.py b/tests/bugs/test_core_5346.py new file mode 100644 index 00000000..59de5f25 --- /dev/null +++ b/tests/bugs/test_core_5346.py @@ -0,0 +1,153 @@ +#coding:utf-8 +# +# id: bugs.core_5346 +# title: Window Function: named window +# decription: +# Simlified test for just check ability to compile and run a query with named window. +# More complex tests (e.g. when result of window functions are involved in JOIN expr.) +# will be implemented later. +# +# NOTE: bug was found on 4.0.0.2298 when using named window. +# Discussed with hvlad and dimitr, letters since 21.12.2020 08:59 +# See CORE-6460 and fix: https://github.com/FirebirdSQL/firebird/commit/964438507cacdfa192b8140ca3f1a2df340d511d +# +# Checked on 4.0.0.2234. +# +# tracker_id: CORE-5346 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table emp_test ( + emp_no smallint, + dept_no char(3), + salary numeric(10,2) + ); + + insert into emp_test (emp_no, dept_no, salary) values (2, '600', 105900); + insert into emp_test (emp_no, dept_no, salary) values (4, '621', 97500); + insert into emp_test (emp_no, dept_no, salary) values (5, '130', 102750); + insert into emp_test (emp_no, dept_no, salary) values (8, '180', 64635); + insert into emp_test (emp_no, dept_no, salary) values (9, '622', 75060); + insert into emp_test (emp_no, dept_no, salary) values (11, '130', 86292.94); + insert into emp_test (emp_no, dept_no, salary) values (12, '000', 53793); + insert into emp_test (emp_no, dept_no, salary) values (14, '900', 69482.63); + insert into emp_test (emp_no, dept_no, salary) values (15, '623', 67241.25); + insert into emp_test (emp_no, dept_no, salary) values (20, '671', 89655); + insert into emp_test (emp_no, dept_no, salary) values (24, '671', 81810.19); + insert into emp_test (emp_no, dept_no, salary) values (28, '120', 22935); + insert into emp_test (emp_no, dept_no, salary) values (29, '623', 69482.63); + insert into emp_test (emp_no, dept_no, salary) values (34, '110', 61637.81); + insert into emp_test (emp_no, dept_no, salary) values (36, '120', 33620.63); + insert into emp_test (emp_no, dept_no, salary) values (37, '120', 39224.06); + insert into emp_test (emp_no, dept_no, salary) values (44, '623', 56034.38); + insert into emp_test (emp_no, dept_no, salary) values (45, '621', 80689.5); + insert into emp_test (emp_no, dept_no, salary) values (46, '900', 116100); + insert into emp_test (emp_no, dept_no, salary) values (52, '180', 42742.5); + insert into emp_test (emp_no, dept_no, salary) values (61, '110', 68805); + insert into emp_test (emp_no, dept_no, salary) values (65, '670', 31275); + insert into emp_test (emp_no, dept_no, salary) values (71, '622', 53167.5); + insert into emp_test (emp_no, dept_no, salary) values (72, '140', 100914); + insert into emp_test (emp_no, dept_no, salary) values (83, '621', 62550); + insert into emp_test (emp_no, dept_no, salary) values (85, '100', 111262.5); + insert into emp_test (emp_no, dept_no, salary) values (94, '672', 56295); + insert into emp_test (emp_no, dept_no, salary) values (105, '000', 212850); + insert into emp_test (emp_no, dept_no, salary) values (107, '670', 111262.5); + insert into emp_test (emp_no, dept_no, salary) values (109, '600', 27000); + insert into emp_test (emp_no, dept_no, salary) values (110, '115', 6000000); + insert into emp_test (emp_no, dept_no, salary) values (113, '671', 48000); + insert into emp_test (emp_no, dept_no, salary) values (114, '623', 35000); + insert into emp_test (emp_no, dept_no, salary) values (118, '115', 7480000); + insert into emp_test (emp_no, dept_no, salary) values (121, '125', 33000); + insert into emp_test (emp_no, dept_no, salary) values (127, '100', 44000); + insert into emp_test (emp_no, dept_no, salary) values (134, '123', 38500); + insert into emp_test (emp_no, dept_no, salary) values (136, '623', 60000); + insert into emp_test (emp_no, dept_no, salary) values (138, '621', 36000); + insert into emp_test (emp_no, dept_no, salary) values (141, '121', 110000); + insert into emp_test (emp_no, dept_no, salary) values (144, '672', 35000); + insert into emp_test (emp_no, dept_no, salary) values (145, '622', 32000); + commit; + + set heading off; + select + e.emp_no, + e.dept_no, + e.salary, + count(*) over w1, + first_value(e.salary) over w2, + last_value(e.salary) over w2 + from emp_test e + window w1 as (partition by e.dept_no), + w2 as (w1 order by e.salary, e.emp_no) + order by + rank() over w2, + e.dept_no, + e.salary; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 12 000 53793.00 2 53793.00 53793.00 + 127 100 44000.00 2 44000.00 44000.00 + 34 110 61637.81 2 61637.81 61637.81 + 110 115 6000000.00 2 6000000.00 6000000.00 + 28 120 22935.00 3 22935.00 22935.00 + 141 121 110000.00 1 110000.00 110000.00 + 134 123 38500.00 1 38500.00 38500.00 + 121 125 33000.00 1 33000.00 33000.00 + 11 130 86292.94 2 86292.94 86292.94 + 72 140 100914.00 1 100914.00 100914.00 + 52 180 42742.50 2 42742.50 42742.50 + 109 600 27000.00 2 27000.00 27000.00 + 138 621 36000.00 4 36000.00 36000.00 + 145 622 32000.00 3 32000.00 32000.00 + 114 623 35000.00 5 35000.00 35000.00 + 65 670 31275.00 2 31275.00 31275.00 + 113 671 48000.00 3 48000.00 48000.00 + 144 672 35000.00 2 35000.00 35000.00 + 14 900 69482.63 2 69482.63 69482.63 + 105 000 212850.00 2 53793.00 212850.00 + 85 100 111262.50 2 44000.00 111262.50 + 61 110 68805.00 2 61637.81 68805.00 + 118 115 7480000.00 2 6000000.00 7480000.00 + 36 120 33620.63 3 22935.00 33620.63 + 5 130 102750.00 2 86292.94 102750.00 + 8 180 64635.00 2 42742.50 64635.00 + 2 600 105900.00 2 27000.00 105900.00 + 83 621 62550.00 4 36000.00 62550.00 + 71 622 53167.50 3 32000.00 53167.50 + 44 623 56034.38 5 35000.00 56034.38 + 107 670 111262.50 2 31275.00 111262.50 + 24 671 81810.19 3 48000.00 81810.19 + 94 672 56295.00 2 35000.00 56295.00 + 46 900 116100.00 2 69482.63 116100.00 + 37 120 39224.06 3 22935.00 39224.06 + 45 621 80689.50 4 36000.00 80689.50 + 9 622 75060.00 3 32000.00 75060.00 + 136 623 60000.00 5 35000.00 60000.00 + 20 671 89655.00 3 48000.00 89655.00 + 4 621 97500.00 4 36000.00 97500.00 + 15 623 67241.25 5 35000.00 67241.25 + 29 623 69482.63 5 35000.00 69482.63 + """ + +@pytest.mark.version('>=4.0') +def test_core_5346_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5351.py b/tests/bugs/test_core_5351.py new file mode 100644 index 00000000..24afed27 --- /dev/null +++ b/tests/bugs/test_core_5351.py @@ -0,0 +1,89 @@ +#coding:utf-8 +# +# id: bugs.core_5351 +# title: LEFT JOIN incorrectly pushes UDF into the inner stream causing wrong results +# decription: +# 25.01.2019: totally changed: use ticket author's sample + dimitr's suggestion +# to operate with usual PSQL fcuntion (rather than UDF). +# Thus test nothing has to do with UDF or UDR. +# Checked on: +# 3.0.5.33086: OK, 1.891s. +# 4.0.0.1172: OK, 6.703s. +# 4.0.0.1340: OK, 2.953s. +# 4.0.0.1378: OK, 3.312s. +# Confirmed wrong result on +# WI-V3.0.0.32136 (Release Candidate 1; 06.11.2015) and 4.0.0.98 (30.03.2016) +# +# Old comment: +# Confirmed on 3.0.1.32597, 4.0.0.371 (wrong result). +# Works fine on 3.0.1.32598, 4.0.0.372, +# +# tracker_id: CORE-5351 +# min_versions: ['3.0.1'] +# versions: 3.0.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set term ^; + create or alter function psql_strlen (val varchar(10)) returns int as + begin + return char_length(coalesce(val, '')); + end + ^ + set term ;^ + commit; + + recreate table test_table1 ( + id integer not null, + testtable2_id integer + ); + + alter table test_table1 add primary key (id); + commit; + + recreate table test_table2 ( + id integer not null, + groupcode varchar(10) + ); + alter table test_table2 add primary key (id); + commit; + + insert into test_table1 (id,testtable2_id) values (1,100); + insert into test_table2 (id,groupcode) values (100,'a'); + commit; + + set count on; + set list on; + + select t1.id + from test_table1 t1 + left join test_table2 t2 on t2.id=t1.testtable2_id + where psql_strlen(t2.groupcode) = 0 ; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ + +@pytest.mark.version('>=3.0.1') +def test_core_5351_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5364.py b/tests/bugs/test_core_5364.py new file mode 100644 index 00000000..a19bf1fa --- /dev/null +++ b/tests/bugs/test_core_5364.py @@ -0,0 +1,130 @@ +#coding:utf-8 +# +# id: bugs.core_5364 +# title: gfix -online normal (being issued in window #1) does not produce error when there is sysdba attachment in window #2 +# decription: +# We create new DB and immediately change its state to single-user maintanance. +# Then we attach to this DB ans run (in separate process) 'gfix -online normal '. +# This command must produce in its STDERR error: "database ... shutdown" - and we check that this actually occurs. +# Also, we check that after reconnect to this DB value of mon$database.mon$shutdown_mode remains the same: 2. +# +# Confirmed bug on: 4.0.0.1850 SS, 3.0.6.33276 SS - no error when doing 'gfix -online normal'. +# Checked on 4.0.0.1881 SS, 3.0.6.33283 SS -- all fine, DB state is not changed to normal. +# +# tracker_id: CORE-5364 +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [('database .* shutdown', 'database shutdown')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import time +# import subprocess +# from subprocess import Popen +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# tmpfdb = os.path.join( context['temp_directory'], 'tmp_5364.fdb') +# cleanup( (tmpfdb,) ) +# +# con1=fdb.create_database(dsn = 'localhost:' + tmpfdb) +# con1.close() +# subprocess.call( [ context['gfix_path'], 'localhost:' + tmpfdb, '-shut', 'single', '-force', '0'] ) +# +# con1=fdb.connect(dsn = 'localhost:' + tmpfdb) +# +# f_gfix_online_log=open( os.path.join(context['temp_directory'],'tmp_5364_online.log'), 'w', buffering = 0) +# f_gfix_online_err=open( os.path.join(context['temp_directory'],'tmp_5364_online.err'), 'w', buffering = 0) +# +# subprocess.call( [ context['gfix_path'], 'localhost:' + tmpfdb, '-online', 'normal'], stdout=f_gfix_online_log, stderr=f_gfix_online_err ) +# +# flush_and_close( f_gfix_online_log ) +# flush_and_close( f_gfix_online_err ) +# +# con1.close() +# +# con1=fdb.connect(dsn = 'localhost:' + tmpfdb) +# cur1=con1.cursor() +# cur1.execute('select d.mon$shutdown_mode from mon$database d') +# for r in cur1: +# print( 'DB shutdown mode:', r[0] ) +# cur1.close() +# con1.close() +# +# with open(f_gfix_online_err.name, 'r') as f: +# for line in f: +# if line.split(): +# print(line) +# +# # cleanup +# ########## +# time.sleep(1) +# cleanup( (f_gfix_online_log, f_gfix_online_err, tmpfdb) ) +# +# # database C:\\FBTESTING\\QA\\FBT-REPO\\TMP\\TMP_5364.FDB shutdown +# # database /opt/scripts/qa-rundaily/fbt-repo/tmp/tmp_5364.fdb shutdown +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DB shutdown mode: 2 + database C:\\FBTESTING\\QA\\FBT-REPO\\TMP\\TMP_5364.FDB shutdown + """ + +@pytest.mark.version('>=3.0.6') +@pytest.mark.xfail +def test_core_5364_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5366.py b/tests/bugs/test_core_5366.py new file mode 100644 index 00000000..5ad45ae9 --- /dev/null +++ b/tests/bugs/test_core_5366.py @@ -0,0 +1,538 @@ +#coding:utf-8 +# +# id: bugs.core_5366 +# title: Regression: could not use CASE expression with more than 255 conditions. +# decription: +# Confirmed on 4.0.0.397: +# Statement failed, SQLSTATE = HY000 +# invalid request BLR at offset 1591 +# -BLR syntax error: expected valid BLR code at offset 1592, encountered 0 +# Works fine since commit: +# https://github.com/FirebirdSQL/firebird/commit/3dcb2c091cfa6981924f5b92d3e42c8783498074 +# (07.10.2016 15:51; checked on LI-T4.0.0.399). +# +# tracker_id: CORE-5366 +# min_versions: ['3.0.2'] +# versions: 3.0.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set TERM ^; + create or alter procedure sp_test ( + "Class" bigint) + returns ( + "Result" varchar(64)) + as + begin + "Result" = trim( + case "Class" + when null then null + when 439 then 'test' + when 63456 then 'test' + when 63479 then 'test' + when 63487 then 'test' + when 63491 then 'test' + when 63499 then 'test' + when 63501 then 'test' + when 63533 then 'test' + when 63569 then 'test' + when 63610 then 'test' + when 63622 then 'test' + when 63639 then 'test' + when 63655 then 'test' + when 63657 then 'test' + when 63659 then 'test' + when 63660 then 'test' + when 63661 then 'test' + when 63662 then 'test' + when 63663 then 'test' + when 63697 then 'test' + when 63702 then 'test' + when 63704 then 'test' + when 63707 then 'test' + when 63778 then 'test' + when 63779 then 'test' + when 63798 then 'test' + when 63878 then 'test' + when 63879 then 'test' + when 63920 then 'test' + when 63942 then 'test' + when 63960 then 'test' + when 63970 then 'test' + when 64042 then 'test' + when 64073 then 'test' + when 64085 then 'test' + when 64086 then 'test' + when 64622 then 'test' + when 64657 then 'test' + when 64697 then 'test' + when 64731 then 'test' + when 64764 then 'test' + when 64785 then 'test' + when 64841 then 'test' + when 64855 then 'test' + when 64856 then 'test' + when 65128 then 'test' + when 65141 then 'test' + when 65185 then 'test' + when 65621 then 'test' + when 65629 then 'test' + when 65659 then 'test' + when 65949 then 'test' + when 66123 then 'test' + when 66142 then 'test' + when 66161 then 'test' + when 66196 then 'test' + when 66206 then 'test' + when 66337 then 'test' + when 66362 then 'test' + when 66383 then 'test' + when 66415 then 'test' + when 66636 then 'test' + when 66661 then 'test' + when 66689 then 'test' + when 66722 then 'test' + when 66781 then 'test' + when 66787 then 'test' + when 66839 then 'test' + when 66850 then 'test' + when 66953 then 'test' + when 66963 then 'test' + when 66964 then 'test' + when 67064 then 'test' + when 67076 then 'test' + when 67206 then 'test' + when 67229 then 'test' + when 67251 then 'test' + when 67306 then 'test' + when 67326 then 'test' + when 70434 then 'test' + when 70474 then 'test' + when 73835 then 'test' + when 150093 then 'test' + when 320101 then 'test' + when 320102 then 'test' + when 320103 then 'test' + when 320543 then 'test' + when 320831 then 'test' + when 320838 then 'test' + when 320982 then 'test' + when 342166 then 'test' + when 343655 then 'test' + when 459484 then 'test' + when 459637 then 'test' + when 460287 then 'test' + when 460288 then 'test' + when 460290 then 'test' + when 460291 then 'test' + when 460292 then 'test' + when 460293 then 'test' + when 460294 then 'test' + when 460296 then 'test' + when 460298 then 'test' + when 640789 then 'test' + when 640903 then 'test' + when 651564 then 'test' + when 678189 then 'test' + when 780399 then 'test' + when 787843 then 'test' + when 787955 then 'test' + when 789099 then 'test' + when 820215 then 'test' + when 827077 then 'test' + when 827352 then 'test' + when 835229 then 'test' + when 837108 then 'test' + when 837718 then 'test' + when 890841 then 'test' + when 890879 then 'test' + when 890885 then 'test' + when 890980 then 'test' + when 891005 then 'test' + when 891007 then 'test' + when 891009 then 'test' + when 891035 then 'test' + when 891093 then 'test' + when 892318 then 'test' + when 905608 then 'test' + when 905627 then 'test' + when 913744 then 'test' + when 913753 then 'test' + when 916244 then 'test' + when 916265 then 'test' + when 916273 then 'test' + when 916334 then 'test' + when 916346 then 'test' + when 916351 then 'test' + when 916360 then 'test' + when 935588 then 'test' + when 935623 then 'test' + when 935648 then 'test' + when 2478129 then 'test' + when 2915244 then 'test' + when 3257588 then 'test' + when 3257761 then 'test' + when 3319392 then 'test' + when 3321575 then 'test' + when 3340716 then 'test' + when 3355291 then 'test' + when 3356388 then 'test' + when 3358162 then 'test' + when 3382051 then 'test' + when 3383662 then 'test' + when 3420043 then 'test' + when 3420159 then 'test' + when 3450179 then 'test' + when 3452688 then 'test' + when 3453211 then 'test' + when 3460436 then 'test' + when 3483933 then 'test' + when 3716039 then 'test' + when 3756014 then 'test' + when 3915294 then 'test' + when 3984675 then 'test' + when 3993573 then 'test' + when 4002668 then 'test' + when 4002670 then 'test' + when 4017059 then 'test' + when 4017121 then 'test' + when 4032403 then 'test' + when 4032603 then 'test' + when 4037129 then 'test' + when 4077764 then 'test' + when 4077782 then 'test' + when 4077947 then 'test' + when 4077955 then 'test' + when 4078411 then 'test' + when 4081351 then 'test' + when 4084613 then 'test' + when 4084832 then 'test' + when 4089569 then 'test' + when 4092258 then 'test' + when 4092406 then 'test' + when 4103178 then 'test' + when 4104045 then 'test' + when 4107074 then 'test' + when 4107278 then 'test' + when 4107482 then 'test' + when 4107630 then 'test' + when 4107924 then 'test' + when 4114129 then 'test' + when 4125291 then 'test' + when 4179806 then 'test' + when 4192560 then 'test' + when 4194013 then 'test' + when 4194703 then 'test' + when 4194704 then 'test' + when 4194706 then 'test' + when 4194707 then 'test' + when 4195442 then 'test' + when 4300071 then 'test' + when 4300073 then 'test' + when 4300075 then 'test' + when 4304215 then 'test' + when 4304673 then 'test' + when 4304752 then 'test' + when 4310521 then 'test' + when 4311220 then 'test' + when 4311222 then 'test' + when 4311224 then 'test' + when 4314331 then 'test' + when 4314447 then 'test' + when 4322367 then 'test' + when 4325243 then 'test' + when 4326759 then 'test' + when 4327323 then 'test' + when 4328037 then 'test' + when 4328303 then 'test' + when 4328305 then 'test' + when 4328307 then 'test' + when 4328309 then 'test' + when 4328318 then 'test' + when 4336060 then 'test' + when 4337487 then 'test' + when 4337516 then 'test' + when 4337626 then 'test' + when 4339439 then 'test' + when 4341099 then 'test' + when 4341196 then 'test' + when 4341425 then 'test' + when 4349966 then 'test' + when 4351930 then 'test' + when 4352853 then 'test' + when 4352969 then 'test' + when 4355074 then 'test' + when 4355114 then 'test' + when 4355858 then 'test' + when 4371296 then 'test' + when 4416501 then 'test' + when 4418300 then 'test' + when 4421281 then 'test' + when 4421840 then 'test' + when 4422068 then 'test' + when 4422677 then 'test' + when 4423043 then 'test' + when 4429998 then 'test' + when 4431236 then 'test' + when 4435348 then 'test' + when 4435676 then 'test' + when 4440546 then 'test' + when 4447884 then 'test' + when 4454022 then 'test' + when 4472466 then 'test' + when 4502449 then 'test' + when 4512948 then 'test' + when 4558442 then 'test' + when 4558448 then 'test' + when 4558450 then 'test' + when 4567499 then 'test' + when 4567501 then 'test' + when 4569241 then 'test' + when 4569243 then 'test' + when 4572117 then 'test' + when 4573591 then 'test' + when 4589022 then 'test' + when 4623252 then 'test' + when 4635919 then 'test' + when 4645888 then 'test' + when 4649966 then 'test' + when 4650088 then 'test' + when 4650173 then 'test' + when 4650401 then 'test' + when 4681332 then 'test' + when 4745895 then 'test' + when 4755573 then 'test' + when 4762122 then 'test' + when 4850659 then 'test' + when 4850660 then 'test' + when 4850661 then 'test' + when 4876232 then 'test' + when 4892331 then 'test' + when 4900586 then 'test' + when 4900591 then 'test' + when 4900593 then 'test' + when 4914540 then 'test' + when 4914542 then 'test' + when 4914587 then 'test' + when 4936301 then 'test' + when 4944698 then 'test' + when 4944988 then 'test' + when 4945334 then 'test' + when 4968126 then 'test' + when 5014366 then 'test' + when 5055181 then 'test' + when 5193460 then 'test' + when 5383087 then 'test' + when 5383089 then 'test' + when 5383091 then 'test' + when 5543680 then 'test' + when 5592996 then 'test' + when 5593256 then 'test' + when 5594327 then 'test' + when 5600265 then 'test' + when 5655816 then 'test' + when 5655818 then 'test' + when 5666867 then 'test' + when 5666869 then 'test' + when 5876954 then 'test' + when 5884798 then 'test' + when 5912516 then 'test' + when 5914761 then 'test' + when 5957197 then 'test' + when 5992166 then 'test' + when 5992167 then 'test' + when 6033375 then 'test' + when 6203209 then 'test' + when 6203636 then 'test' + when 6204269 then 'test' + when 6204271 then 'test' + when 6204273 then 'test' + when 6213155 then 'test' + when 6213323 then 'test' + when 6301141 then 'test' + when 6301964 then 'test' + when 6312533 then 'test' + when 6316960 then 'test' + when 6316965 then 'test' + when 6319351 then 'test' + when 6320539 then 'test' + when 6321288 then 'test' + when 6325447 then 'test' + when 6325470 then 'test' + when 6344050 then 'test' + when 6358457 then 'test' + when 6364261 then 'test' + when 6364600 then 'test' + when 6365524 then 'test' + when 6365682 then 'test' + when 6417870 then 'test' + when 6418013 then 'test' + when 6418015 then 'test' + when 6467138 then 'test' + when 6558972 then 'test' + when 6609950 then 'test' + when 6612377 then 'test' + when 6612379 then 'test' + when 6635581 then 'test' + when 6642875 then 'test' + when 6649739 then 'test' + when 6649742 then 'test' + when 6649747 then 'test' + when 6652184 then 'test' + when 6652567 then 'test' + when 6667495 then 'test' + when 6673208 then 'test' + when 6683547 then 'test' + when 6701017 then 'test' + when 6701022 then 'test' + when 6701654 then 'test' + when 6705470 then 'test' + when 6705924 then 'test' + when 6705926 then 'test' + when 6705928 then 'test' + when 6705930 then 'test' + when 6705947 then 'test' + when 6705949 then 'test' + when 6705951 then 'test' + when 6705953 then 'test' + when 6706392 then 'test' + when 6708534 then 'test' + when 6708681 then 'test' + when 6708846 then 'test' + when 6708998 then 'test' + when 6828688 then 'test' + when 6843679 then 'test' + when 6844530 then 'test' + when 6846408 then 'test' + when 6846816 then 'test' + when 6848563 then 'test' + when 6849455 then 'test' + when 6856175 then 'test' + when 6859372 then 'test' + when 6860314 then 'test' + when 6866537 then 'test' + when 6866957 then 'test' + when 6901444 then 'test' + when 6904268 then 'test' + when 6904952 then 'test' + when 6904954 then 'test' + when 6905712 then 'test' + when 6938436 then 'test' + when 6939545 then 'test' + when 6940014 then 'test' + when 7079756 then 'test' + when 7080194 then 'test' + when 7101872 then 'test' + when 7138242 then 'test' + when 7138450 then 'test' + when 7148537 then 'test' + when 7150271 then 'test' + when 7150273 then 'test' + when 7150513 then 'test' + when 7151690 then 'test' + when 7152043 then 'test' + when 7152866 then 'test' + when 7159124 then 'test' + when 7159482 then 'test' + when 7159670 then 'test' + when 7171290 then 'test' + when 7187300 then 'test' + when 7187979 then 'test' + when 7187988 then 'test' + when 7188039 then 'test' + when 7188073 then 'test' + when 7188190 then 'test' + when 7188192 then 'test' + when 7188200 then 'test' + when 7188226 then 'test' + when 7188228 then 'test' + when 7188291 then 'test' + when 7188351 then 'test' + when 7188462 then 'test' + when 7188699 then 'test' + when 7188746 then 'test' + when 7188748 then 'test' + when 7188888 then 'test' + when 7188889 then 'test' + when 7188890 then 'test' + when 7188891 then 'test' + when 7203393 then 'test' + when 7206715 then 'test' + when 7206717 then 'test' + when 7206719 then 'test' + when 7207844 then 'test' + when 7229114 then 'test' + when 7229319 then 'test' + when 7229474 then 'test' + when 7238128 then 'test' + when 7239486 then 'test' + when 7239666 then 'test' + when 7239931 then 'test' + when 7242657 then 'test' + when 7242659 then 'test' + when 7246983 then 'test' + when 7251258 then 'test' + when 7253427 then 'test' + when 7275788 then 'test' + when 7276015 then 'test' + when 7276164 then 'test' + when 7276637 then 'test' + when 7314109 then 'test' + when 7314881 then 'test' + when 7319806 then 'test' + when 7366851 then 'test' + when 7368696 then 'test' + when 7368703 then 'test' + when 7368760 then 'test' + when 7380288 then 'test' + when 7425756 then 'test' + when 7425972 then 'test' + when 7427947 then 'test' + when 7427949 then 'test' + when 7428010 then 'test' + when 7428012 then 'test' + when 7456599 then 'test' + when 7469922 then 'test' + when 7480114 then 'test' + when 7497387 then 'test' + when 7502178 then 'test' + when 7502180 then 'test' + when 7502182 then 'test' + when 7503001 then 'test' + when 7503003 then 'test' + when 7512844 then 'test' + when 7535816 then 'test' + end); + suspend; + end^ + set term ;^ + commit; + + set list on; + select * from sp_test(7535816); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Result test + """ + +@pytest.mark.version('>=3.0.2') +def test_core_5366_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5367.py b/tests/bugs/test_core_5367.py new file mode 100644 index 00000000..fc9e5389 --- /dev/null +++ b/tests/bugs/test_core_5367.py @@ -0,0 +1,66 @@ +#coding:utf-8 +# +# id: bugs.core_5367 +# title: Regression: (boolean) parameters as search condition no longer allowed +# decription: +# Confirmed on WI-T4.0.0.397 before commit 04-oct-2016 17:52 +# https://github.com/FirebirdSQL/firebird/commit/8a4b7e3b79a31dc7bf6e569e6cf673cf6899a475 +# - got: +# Statement failed, SQLSTATE = 22000 +# Dynamic SQL Error +# -SQL error code = -104 +# -Invalid usage of boolean expression +# +# Works fine since that commit (checked on LI-T4.0.0.397). +# +# tracker_id: CORE-5367 +# min_versions: ['3.0.2'] +# versions: 3.0.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table test(id int,boo boolean); + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set sqlda_display on; + set planonly; + select * from test where ?; + set planonly; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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_core_5367_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5380.py b/tests/bugs/test_core_5380.py new file mode 100644 index 00000000..754fa912 --- /dev/null +++ b/tests/bugs/test_core_5380.py @@ -0,0 +1,86 @@ +#coding:utf-8 +# +# id: bugs.core_5380 +# title: Allow subroutines to call others subroutines and themself recursively +# decription: +# We check not only ability of recursive calls but also max depth of them. It should be equal to 1000. +# FB40SS, build 4.0.0.688: OK, 0.890s. +# +# tracker_id: CORE-5380 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('line:\\s[0-9]+,', 'line: x'), ('col:\\s[0-9]+', 'col: y')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create or alter function get_arithmetic_progression_total(n smallint) returns decfloat(34) as + declare function get_sub_total_recursively(n smallint) returns decfloat(34) as + begin + if (n = 1) then + return 1; + else + return n + get_sub_total_recursively(n - 1); + end + begin + if (n <= 0) then + return 0; + else + return get_sub_total_recursively(n); + end + ^ + set term ;^ + commit; + + set list on; + select get_arithmetic_progression_total(1001) as arithmetic_progression_total from rdb$database; + select get_arithmetic_progression_total(1002) as arithmetic_progression_total from rdb$database; + -- (a1 + an) * n / 2 + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ARITHMETIC_PROGRESSION_TOTAL 501501 + """ +expected_stderr_1 = """ + 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_core_5380_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5381.py b/tests/bugs/test_core_5381.py new file mode 100644 index 00000000..99cc838a --- /dev/null +++ b/tests/bugs/test_core_5381.py @@ -0,0 +1,120 @@ +#coding:utf-8 +# +# id: bugs.core_5381 +# title: Regression: could not execute query (select from view with nested view) +# decription: +# Confirmed trouble on 3.0.1.32609: query PREPARING lasts more than 2 mintes and end up with: +# Statement failed, SQLSTATE = HY000 +# request size limit exceeded +# Works fine on WI-V3.0.2.32703 - query runs less than for 2 ms. +# Decided to compare execution time of this query with threshold 1000 ms. +# Checked on: +# 4.0.0.1629: OK, 1.508s. +# 3.0.5.33179: OK, 0.866s. +# +# tracker_id: CORE-5381 +# min_versions: ['3.0.2'] +# versions: 3.0.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + 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); + + create view inner_view(ID) + 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 + ; + + create view test_view(ID) + 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; + + set list on; + + set term ^; + execute block returns( result varchar(128) ) as + declare dts_beg timestamp; + 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; + end + ^ + set term ;^ + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT Acceptable. + """ + +@pytest.mark.version('>=3.0.2') +def test_core_5381_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5383.py b/tests/bugs/test_core_5383.py new file mode 100644 index 00000000..32f69ff0 --- /dev/null +++ b/tests/bugs/test_core_5383.py @@ -0,0 +1,169 @@ +#coding:utf-8 +# +# id: bugs.core_5383 +# title: Dependencies in Package not recognised +# decription: +# Confirmed bug on: 3.0.2.32620 and 4.0.0.420 +# WOrks fine on 3.0.2.32625 and 4.0.0.440 +# +# tracker_id: CORE-5383 +# min_versions: ['3.0.2'] +# versions: 3.0.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + recreate package pg_03 as begin end; + recreate package pg_02 as begin end; + recreate package pg_01 as begin end; + commit; + + recreate table test01 (id1 int primary key, f01 int); + recreate table test02 (id2 int primary key, f02 int); + recreate table test03 (id3 int primary key, f03 int); + commit; + + insert into test01(id1, f01) values(1, 111); + insert into test02(id2, f02) values(1, 222); + insert into test03(id3, f03) values(1, 333); + commit; + + set term ^; + create package body pg_01 as + begin + procedure p01(i_x int) returns (o_y int) as + begin + -- dependencies is created for test01 + select id1 from test01 into :o_y; + end + end + ^ + + create package body pg_02 as + begin + procedure p01(i_x int) returns (o_y int) as + begin + -- dependencies is created for test01 and test02 and test03 + select id1 from test01 into :o_y; + select id2 from test02 into :o_y; + select id3 from test03 into :o_y; + end + end + ^ + + recreate package pg_03 as + begin + procedure p01(i_x int) returns (o_y int); + procedure p02(i_x int) returns (o_y int); + procedure p03(i_x int) returns (o_y int); + end + ^ + + create package body pg_03 + as + begin + procedure p01(i_x int) returns (o_y int) as + begin + -- no dependencies is created !!! + select f01 from test01 where id1 = :i_x into :o_y; + end + + procedure p02(i_x int) returns (o_y int) as + begin + -- no dependencies is created !!! + select f02 from test02 where id2 = :i_x into :o_y; + end + + procedure p03(i_x int) returns (o_y int) as + begin + -- dependencies is only created for test03 + select f03 from test03 where id3 = :i_x into :o_y; + end + end + ^ + set term ;^ + commit; + + drop package pg_01; + drop package pg_02; + + -- Following two drops PASSED WITHOUT ERROR on WI-V3.0.2.32620 and WI-T4.0.0.420 (BUG!). + -- Expected STDERR: + -- Statement failed, SQLSTATE = 42000 + -- unsuccessful metadata update + -- -cannot delete + -- -COLUMN TEST01.ID1 (TEST02,ID2) + -- -there are 1 dependencies + drop table test01; + drop table test02; + commit; + + set count on; + select distinct rdb$dependent_name, rdb$depended_on_name from rdb$dependencies d; + + -- Following two statements issued on WI-V3.0.2.32620 and WI-T4.0.0.420: + -- Statement failed, SQLSTATE = 2F000 + -- Error while parsing procedure PG_03.P01's (PG_03.P02's) BLR + -- -table TEST01 (TEST02) is not defined + -- Expected STDOUT: + -- O_Y = 111 and O_Y = 222 + execute procedure pg_03.p01(1); + execute procedure pg_03.p02(1); + + execute procedure pg_03.p03(1); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + + 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_1 = """ + 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 + """ + +@pytest.mark.version('>=3.0.2') +def test_core_5383_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5389.py b/tests/bugs/test_core_5389.py new file mode 100644 index 00000000..918891fa --- /dev/null +++ b/tests/bugs/test_core_5389.py @@ -0,0 +1,173 @@ +#coding:utf-8 +# +# id: bugs.core_5389 +# title: Query cannot be executed if win1251 characters used in field aliases +# decription: +# Test prepares file that will serve as input SQL script and will have CYRYLLIC names for field aliases. +# File has name = 'tmp_non_ascii_chk_5389.sql' and is encoded to windows-1251 codepage. +# Checked on 4.0.0.639. +# 30.10.2019 checked on: +# 4.0.0.1635 SS: 2.782s. +# 4.0.0.1633 CS: 3.515s. +# NB: old checked on: 4.0.0.639 - did pass without using codecs! Strange! +# +# tracker_id: CORE-5389 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('.*After line [0-9]+ in file .*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# +# # 30.10.2019. This is needed in Python 2.7 for converting string in UTF8 to cp1251 +# import codecs +# +# #-------------------------------------------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# +# #-------------------------------------------- +# +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# non_ascii_ddl=''' +# set list on; +# select +# '' as "ФИО" +# ,'' as "Д.рождения" +# ,'' as "Город" +# ,'' as "Расшифровка выступлений" +# from rdb$database; +# ''' +# +# f_checksql=os.path.join(context['temp_directory'],'tmp_non_ascii_ddl_5389.sql') +# with codecs.open( f_checksql, 'w', encoding='cp1251') as f: +# f.write( non_ascii_ddl.decode('utf-8') ) +# +# # Result: file 'tmp_non_ascii_chk_5389.sql' is encoded in cp1251 and contains SQL statements to be executed. +# +# ########################################################################################################### +# ### check-1: attempt to apply DDL with non-ascii characters __WITHOUT__ charset specifying (for ISQL) ### +# ########################################################################################################### +# +# f_apply_cset_none_log = open( os.path.join(context['temp_directory'],'tmp_5389_apply_cset_none.log'), 'w') +# f_apply_cset_none_err = open( os.path.join(context['temp_directory'],'tmp_5389_apply_cset_none.err'), 'w') +# +# subprocess.call( ["isql", dsn, "-i", f_checksql ], +# stdout = f_apply_cset_none_log, +# stderr = f_apply_cset_none_err +# ) +# +# f_apply_cset_none_log.close() +# f_apply_cset_none_err.close() +# +# ############################################################################################################# +# ### check-2: attempt to apply DDL with non-ascii characters ___WITH___ specifying: ISQL ... -ch WIN1251 ### +# ############################################################################################################# +# +# f_apply_cset_1251_log = open( os.path.join(context['temp_directory'],'tmp_5389_apply_cset_1251.log'), 'w') +# f_apply_cset_1251_err = open( os.path.join(context['temp_directory'],'tmp_5389_apply_cset_1251.err'), 'w') +# +# subprocess.call( ["isql", dsn, "-i", f_checksql, "-ch", "win1251" ], +# stdout = f_apply_cset_1251_log, +# stderr = f_apply_cset_1251_err +# ) +# +# f_apply_cset_1251_log.close() +# +# # This file should NOT contain any errors: +# f_apply_cset_1251_err.close() +# +# # do NOT remove this pause otherwise some of logs will not be enable for deletion and test will finish with +# # Exception raised while executing Python test script. exception: WindowsError: 32 +# time.sleep(1) +# +# +# # CHECK RESULTS: +# ################ +# +# # This stdout log should contain only ONE statement (create collation ...), +# # this DDL failed and caused ISQL to immediately terminate: +# with open( f_apply_cset_none_log.name, 'r') as f: +# for line in f: +# out_txt='STDLOG WHEN CSET=NONE: '; +# if line.strip(): +# print( out_txt+line.strip().decode("cp1251").encode('utf8') ) +# f.close() +# +# +# with open( f_apply_cset_none_err.name, 'r') as f: +# for line in f: +# out_txt='STDERR WHEN CSET=NONE: '; +# if line.strip(): +# print( out_txt+line.strip().decode("cp1251").encode('utf8') ) +# +# f.close() +# +# +# with open( f_apply_cset_1251_log.name, 'r') as f: +# for line in f: +# out_txt='STDLOG WHEN CSET=WIN1251: '; +# if line.strip(): +# print( out_txt+line.strip().decode("cp1251").encode('utf8') ) +# f.close() +# +# with open( f_apply_cset_1251_err.name, 'r') as f: +# for line in f: +# out_txt='STDERR WHEN CSET=WIN1251: '; +# if line.strip(): +# print( out_txt+line.strip().decode("cp1251").encode('utf8') ) +# f.close() +# +# +# ##################################################################### +# # Cleanup: +# +# f_list = [ i.name for i in ( f_apply_cset_none_log, f_apply_cset_none_err, f_apply_cset_1251_log, f_apply_cset_1251_err ) ] +# f_list += [ f_checksql, ] +# cleanup( f_list ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + STDERR WHEN CSET=NONE: Statement failed, SQLSTATE = 22018 + STDERR WHEN CSET=NONE: arithmetic exception, numeric overflow, or string truncation + STDERR WHEN CSET=NONE: -Cannot transliterate character between character sets + STDLOG WHEN CSET=WIN1251: ФИО + STDLOG WHEN CSET=WIN1251: Д.рождения + STDLOG WHEN CSET=WIN1251: Город + STDLOG WHEN CSET=WIN1251: Расшифровка выступлений + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_5389_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5392.py b/tests/bugs/test_core_5392.py new file mode 100644 index 00000000..826c82cd --- /dev/null +++ b/tests/bugs/test_core_5392.py @@ -0,0 +1,233 @@ +#coding:utf-8 +# +# id: bugs.core_5392 +# title: BUGCHECK 179 (decompression overran buffer) or unexpected lock conflict may happen during record versions backout +# decription: +# NOTE: bug can be reproduced only in SuperServer arch. +# +# We determine FB arch, and if it is SuperServer then change FW to OFF, add rows into table and +# perform statements that should raise internal FB CC. +# If no errors occures then ISQL log should contain number of affected rows. +# If internal FB CC will occur again then control will be returned to fbtest after ~2 minutes. +# +# For SS test lasts about 40 seconds, for SC/CS it should pass instantly because we SKIP entire test +# for both SC and CS architectures and just print 'OK' for matching expected_stdout. +# +# Confirmed bug on WI-T4.0.0.462, minimal number of rows for reproducing is ~98000. +# Checked on WI-V3.0.2.32643, WI-T4.0.0.463 - works fine. +# ------- +# 01-feb-2017: confirmed bugcheck on 2.5.7.27030 (only with WF = OFF), fix on 2.5.7.27038. +# Changed min-version to 2.5.7. +# +# tracker_id: CORE-5392 +# min_versions: ['2.5.7'] +# versions: 2.5.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import time +# import subprocess +# #from subprocess import Popen +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# +# #-------------------------------------------- +# +# 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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# def get_fb_arch(a_dsn): +# try: +# con1 = fdb.connect(dsn = a_dsn) +# con2 = fdb.connect(dsn = a_dsn) +# +# cur1 = con1.cursor() +# +# sql=( +# "select count(distinct a.mon$server_pid), min(a.mon$remote_protocol), max(iif(a.mon$remote_protocol is null,1,0))" +# +" from mon$attachments a" +# +" where a.mon$attachment_id in (%s, %s) or upper(a.mon$user) = upper('%s')" +# % (con1.attachment_id, con2.attachment_id, 'cache writer') +# ) +# +# cur1.execute(sql) +# for r in cur1.fetchall(): +# server_cnt=r[0] +# server_pro=r[1] +# cache_wrtr=r[2] +# +# if server_pro == None: +# fba='Embedded' +# elif cache_wrtr == 1: +# fba='SS' +# elif server_cnt == 2: +# fba='CS' +# else: +# +# f1=con1.db_info(fdb.isc_info_fetches) +# +# cur2=con2.cursor() +# cur2.execute('select 1 from rdb$database') +# for r in cur2.fetchall(): +# pass +# +# f2=con1.db_info(fdb.isc_info_fetches) +# +# fba = 'SC' if f1 ==f2 else 'SS' +# +# return fba +# +# finally: +# con1.close() +# con2.close() +# +# #-------------------------------------------- +# +# fb_arch= get_fb_arch(dsn) +# rows_cnt=100000 +# +# if fb_arch == 'SS': +# +# dbname=db_conn.database_name +# db_conn.close() +# +# # NB: do _not_ remove changing of FW to OFF in 2.5.7 (Ivan said that FW on 2.5.6 was ON, see 15/Dec/16 01:07 PM). +# # Bucgcheck is reproduced on 2.5.7.27030 only when FW = OFF. +# fn_nul = open(os.devnull, 'w') +# subprocess.call( [context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "dbname", dbname, +# "prp_write_mode", "prp_wm_async" ], +# stdout = fn_nul, +# stderr = subprocess.STDOUT +# ) +# fn_nul.close() +# +# sql_chk= ''' +# create domain dm_longutf as varchar(8000) character set utf8; +# recreate table test (id int not null, a int); +# commit; +# +# set term ^; +# execute block as +# declare i int; +# declare n int = %(rows_cnt)s; -- (4.0 SS, page_size 8k: threshold is ~98000 records) +# begin +# while (n>0) do insert into test(id, a) values(:n, :n) returning :n-1 into n; +# end +# ^ +# set term ;^ +# commit; +# alter table test add constraint pk_test primary key (id) using descending index pk_test_desc; +# commit; +# +# alter table test add b dm_longutf default '' not null; +# commit; +# +# update test set a=2; +# rollback; +# +# set count on; +# -- Following UPDATE statement leads to: +# -- 1) on 3.0: decompression overran buffer (179), file: sqz.cpp line: 282 +# -- 2) on 2.5.7.27030: decompression overran buffer (179), file: sqz.cpp line: 228 +# -- Then FB waits (or is doing?) somewhat about 2 minutes abd after this +# -- control is returned to fbtest. +# update test set a=3; +# commit; +# ''' % locals() +# +# f_sql_cmd=open(os.path.join(context['temp_directory'],'tmp_core_5392.sql'), 'w') +# f_sql_cmd.write(sql_chk) +# flush_and_close( f_sql_cmd ) +# +# f_sql_log=open(os.path.join(context['temp_directory'],'tmp_core_5392.log'),'w') +# f_sql_err=open(os.path.join(context['temp_directory'],'tmp_core_5392.err'),'w') +# +# subprocess.call([context['isql_path'], dsn, "-i", f_sql_cmd.name],stdout=f_sql_log, stderr=f_sql_err) +# +# flush_and_close( f_sql_log ) +# flush_and_close( f_sql_err ) +# +# # This should contain message about affected rows: +# ##################### +# with open( f_sql_log.name,'r') as f: +# for line in f: +# if 'affected: '+str(rows_cnt) in line: +# print('OK') +# +# # This should be empty: +# ####################### +# with open( f_sql_err.name,'r') as f: +# for line in f: +# if line.strip(): +# print('UNEXPECTED ERROR: '+line.upper()) +# # Cleanup +# ######### +# time.sleep(1) +# cleanup( (f_sql_cmd, f_sql_log, f_sql_err) ) +# +# else: +# # FB arch is NOT SuperServer: test should not run at all because its subject relates only to SS. +# # (see leter from dimitr, 06-dec-2016 08:37, about races between GC and working DML thread). +# print('OK') +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + OK + """ + +@pytest.mark.version('>=2.5.7') +@pytest.mark.xfail +def test_core_5392_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5393.py b/tests/bugs/test_core_5393.py new file mode 100644 index 00000000..69b4cf26 --- /dev/null +++ b/tests/bugs/test_core_5393.py @@ -0,0 +1,144 @@ +#coding:utf-8 +# +# id: bugs.core_5393 +# title: Bad optimization of some operations with views containing subqueries +# decription: +# Confirmed trouble on WI-V3.0.2.3262, ratio was ~146(!). +# Performance is OK on WI-V3.0.2.32629 and WI-T4.0.0.450 +# ::: NB::: +# Plans differ on 3.0.2 and 4.0 thus they are excluded from the output! +# Performance of 4.0 significantly _WORSE_ than of 3.0.2, sent letter to dimitr, 11.11.2016 13:47. +# +# tracker_id: CORE-5393 +# min_versions: ['3.0.2'] +# versions: 3.0.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate view v_test as select 1 id from rdb$database; + recreate view v_test1 as select 1 id from rdb$database; + recreate view v_test2 as select 1 id from rdb$database; + commit; + + recreate table test (id int primary key using index test_pk, col int); + recreate table tlog(qt int, elap_ms int); + commit; + + insert into test select row_number()over(),row_number()over() from rdb$types,rdb$types rows 1000; + --insert into test (id, col) values (1, 1); + --insert into test (id, col) values (2, 2); + commit; + + -- view must contain a subquery + create or alter view v_test1 (id1, id2, col1, col2, dummy) + as + select t1.id, t2.id, t1.col, t2.col, (select 1 from rdb$database) + from test t1 join test t2 on t1.col = t2.id; + + -- trigger makes the view updatable + create or alter trigger trg_vtest1_bu for v_test1 before update as + begin + end; + + -- view must contain a subquery + create or alter view v_test2 (id1, id2, col1, col2, dummy) + as + select ta.id, tb.id, ta.col, tb.col, (select 1 from rdb$database) + from test ta join test tb on ta.col = tb.id; + + -- trigger makes the view updatable + create or alter trigger trg_vtest2_bu + for v_test2 before update + as + begin + end; + + + -- temply(?) disable ouput of plans: they DIFFER in 3.0.2 vs 4.0! -- set plan; + + set term ^; + + execute block as -- returns(elap_ms1 int) as + declare t0 timestamp; + begin + t0='now'; + for select id1 from v_test1 as cursor c do + begin + update v_test1 x set x.col1 = 1 + where x.id1 = c.id1; + -- where current of c; + + update v_test2 y set y.col1 = 1 + where y.id1 = c.id1; + end + insert into tlog(qt, elap_ms) values(1, datediff(millisecond from :t0 to cast('now' as timestamp)) ); + end + ^ + + execute block as -- returns(elap_ms2 int) as + declare t0 timestamp; + begin + t0='now'; + for select id1 from v_test1 as cursor c do + begin + update v_test1 u set u.col1 = 1 + -- where id1 = c.id1; + where current of c; + + update v_test2 v set v.col1 = 1 + where v.id1 = c.id1; + end + insert into tlog(qt, elap_ms) values(2, datediff(millisecond from :t0 to cast('now' as timestamp)) ); + end^ + set term ;^ + + set list on; + select iif( coalesce(ratio,0) < max_allowed, + 'Acceptable', + 'Poor ratio = ' + || cast(max_elap as varchar(20)) + || '/' || cast(min_elap as varchar(20)) + || ' = ' + || cast(ratio as varchar(20)) + || ' - more than max_allowed = ' || cast(max_allowed as varchar(20)) + ) + as ratio + from ( + select + min(elap_ms) min_elap, + max(elap_ms) max_elap, + 1.00 * max(elap_ms) / nullif(min(elap_ms),0) as ratio, + 2.30 as max_allowed + -- ^ + -- | + -- ################# + -- T H R E S H O L D + -- ################# + from tlog + ); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RATIO Acceptable + """ + +@pytest.mark.version('>=3.0.2') +def test_core_5393_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5395.py b/tests/bugs/test_core_5395.py new file mode 100644 index 00000000..547a8ba2 --- /dev/null +++ b/tests/bugs/test_core_5395.py @@ -0,0 +1,106 @@ +#coding:utf-8 +# +# id: bugs.core_5395 +# title: Invalid data type for negation (minus operator) +# decription: +# Confirmed on: +# WI-V3.0.4.33053, WI-T4.0.0.1249 +# Statement failed, SQLSTATE = 42000 +# +# Checked on: +# 3.0.5.33084: OK, 1.250s. +# 4.0.0.1340: OK, 2.344s. +# -- works fine both when SQL dialect = 1 and 3. +# +# tracker_id: CORE-5395 +# min_versions: ['3.0.5'] +# versions: 3.0.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set term ^; + execute block returns (eval_result int) as + begin + for + execute statement ('select 1 from rdb$database where 1 = - :id') (id := -1) + into :eval_result + do + suspend; + + -- Statement failed, SQLSTATE = 42000 + -- Dynamic SQL Error + -- -expression evaluation not supported + -- -Invalid data type for negation (minus operator) + -- -At block line: 3, col: 5 + + end + ^ + + execute block returns (eval_result int) as + begin + for + execute statement ('select 1 from rdb$database where 1 = (:id) * -1') (id := -1) + into :eval_result + do + suspend; + + -- Statement failed, SQLSTATE = 42000 + -- Dynamic SQL Error + -- -expression evaluation not supported + -- -Invalid data type for multiplication in dialect N, N=1 or 3 + -- -At block line: 13, col: 3 + + end + ^ + + execute block returns (eval_result int) as + declare selected_year int; + declare selected_mont int; + begin + selected_year = extract(year from current_timestamp); + selected_mont = extract(month from current_timestamp); + + for + execute statement ('select 1 from rdb$database where extract(year from current_timestamp)*100 + extract(month from current_timestamp) = ? * 100 + ? ') (selected_year, selected_mont) + into :eval_result + do + suspend; + + -- Statement failed, SQLSTATE = 42000 + -- Dynamic SQL Error + -- -expression evaluation not supported + -- -Invalid data type for multiplication in dialect N, N=1 or 3 + -- -At block line: 8, col: 5 + + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + EVAL_RESULT 1 + EVAL_RESULT 1 + EVAL_RESULT 1 + """ + +@pytest.mark.version('>=3.0.5') +def test_core_5395_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5404.py b/tests/bugs/test_core_5404.py new file mode 100644 index 00000000..892c2676 --- /dev/null +++ b/tests/bugs/test_core_5404.py @@ -0,0 +1,123 @@ +#coding:utf-8 +# +# id: bugs.core_5404 +# title: Inconsistent column/line references when PSQL definitions return errors +# decription: +# ### 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). +# +# tracker_id: CORE-5404 +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('-At line[:]{0,1}[\\s]+[\\d]+,[\\s]+column[:]{0,1}[\\s]+[\\d]+', '-At line: column:')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create or alter procedure dsql_field_err1 as + declare i int; + begin + select "" from rdb$database into i; -- Column unknown. + end + ^ + + create or alter procedure dsql_field_err2 as + declare i int; + begin + select foo from rdb$database into i; + end + ^ + set term ;^ + + quit; --------------------------------------- Q U I T ------------------- (TEMPLY) + + set term ^; + create or alter procedure dsql_count_mismatch as + declare i int; + declare k int; + begin + select 1 from rdb$database into i, k; -- Count of column list and variable list do not match. + end + ^ + + create or alter procedure dsql_invalid_expr as + declare i int; + declare j varchar(64); + declare k int; + begin + select RDB$RELATION_ID,RDB$CHARACTER_SET_NAME, count(*) + from rdb$database + group by 1 + into i, j, k; + end + ^ + + create or alter procedure dsql_agg_where_err as + declare i int; + begin + select count(*) + from rdb$database + group by count(*) -- Cannot use an aggregate function in a GROUP BY clause. + into i; + end + ^ + + create or alter procedure dsql_agg_nested_err as + declare i int; + begin + select count( max(1) ) -- Nested aggregate functions are not allowed. + from rdb$database + into i; + end + ^ + + create or alter procedure dsql_column_pos_err as + declare i int; + begin + select 1 + from rdb$database + order by 1, 2 -- Invalid column position used in the @1 clause + into i; + end + ^ + set term ;^ + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + -At line 4, column 10 + + Statement failed, SQLSTATE = 42S22 + unsuccessful metadata update + -CREATE OR ALTER PROCEDURE DSQL_FIELD_ERR2 failed + -Dynamic SQL Error + -SQL error code = -206 + -Column unknown + -FOO + -At line 4, column 10 + """ + +@pytest.mark.version('>=4.0') +def test_core_5404_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_5408.py b/tests/bugs/test_core_5408.py new file mode 100644 index 00000000..999207d1 --- /dev/null +++ b/tests/bugs/test_core_5408.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: bugs.core_5408 +# title: Result of boolean expression can not be concatenated with string literal +# decription: +# Checked on WI-T4.0.0.466 - works fine. +# +# tracker_id: CORE-5408 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select (true = true)|| 'aaa' as "(true=true) concat 'aaa'" from rdb$database; + select (true is true)|| 'aaa' as "(true is true) concat 'aaa'" from rdb$database; + select 'aaa' || (true = true) as "'aaa' concat (true = true)" from rdb$database; + select 'aaa' || (true is true) as "'aaa' concat (true is true)" from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + (true=true) concat 'aaa' TRUEaaa + (true is true) concat 'aaa' TRUEaaa + 'aaa' concat (true = true) aaaTRUE + 'aaa' concat (true is true) aaaTRUE + """ + +@pytest.mark.version('>=4.0') +def test_core_5408_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5410.py b/tests/bugs/test_core_5410.py new file mode 100644 index 00000000..61eb4325 --- /dev/null +++ b/tests/bugs/test_core_5410.py @@ -0,0 +1,153 @@ +#coding:utf-8 +# +# id: bugs.core_5410 +# title: Dependencies are not stored when using some type of contructions in subroutines +# decription: +# Confirmed: +# 1) bug on WI-V3.0.2.32630, WI-T4.0.0.454 +# 2) fixed on WI-V3.0.2.32642, WI-T4.0.0.460 (does not allow to drop tables). +# +# tracker_id: CORE-5410 +# min_versions: ['3.0.2'] +# versions: 3.0.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + create or alter procedure sp_outer_standalone as begin end; + create or alter package pg_test as begin end; + commit; + + recreate table test_1(f01 integer); + insert into test_1(f01) values(100); + insert into test_1(f01) values(1); + insert into test_1(f01) values(10); + commit; + + recreate table test_2(f02 integer); + commit; + insert into test_2(f02) values(200); + insert into test_2(f02) values(2); + insert into test_2(f02) values(20); + commit; + + recreate table test_3(f02 integer); + commit; + insert into test_3(f02) values(300); + insert into test_3(f02) values(3); + insert into test_3(f02) values(30); + commit; + + set term ^; + create or alter procedure sp_outer_standalone returns(max_f01 int) as + declare procedure sp_inner returns(max_f01 int) as + begin + select max(f01) from test_1 into max_f01; + suspend; + end + begin + select max_f01 from sp_inner into max_f01; + suspend; + end; + ^ + + create or alter function fn_outer_standalone returns int as + declare function fn_inner returns int as + begin + return (select min(f01) from test_1); + end + begin + return fn_inner(); + end; + ^ + + create or alter package pg_test as + begin + procedure sp_outer_packaged returns(max_f02 int); + function fn_outer_packaged returns int; + end + ^ + recreate package body pg_test as + begin + procedure sp_outer_packaged returns(max_f02 int) as + declare procedure sp_inner returns(max_f02 int) as + begin + select max(f02) from test_2 into max_f02; + suspend; + end + begin + select max_f02 from sp_inner into max_f02; + suspend; + end + + function fn_outer_packaged returns int as + declare function fn_inner returns int as + begin + return (select min(f02) from test_2); + end + begin + return fn_inner(); + end + end + ^ + + set term ;^ + commit; + + ----------------------- + + drop table test_1; -- should FAIL! + drop table test_2; -- should FAIL! + commit; + + select max_f01 from sp_outer_standalone; + select fn_outer_standalone() as min_f01 from rdb$database; + + select max_f02 from pg_test.sp_outer_packaged; + select pg_test.fn_outer_packaged() as min_f02 from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MAX_F01 100 + MIN_F01 1 + + MAX_F02 200 + MIN_F02 2 + + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -COLUMN TEST_1.F01 + -there are 2 dependencies + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -COLUMN TEST_2.F02 + -there are 1 dependencies + """ + +@pytest.mark.version('>=3.0.2') +def test_core_5410_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5414.py b/tests/bugs/test_core_5414.py new file mode 100644 index 00000000..8195ac24 --- /dev/null +++ b/tests/bugs/test_core_5414.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_5414 +# title: Error restoring on FB 3.0 from FB 2.5: bugcheck 221 (cannot remap) +# decription: +# Test verifies only issue 08/Dec/16 02:47 PM (pointed out by ASF). +# Confirmed bug on 3.0.1.32539, 3.0.2.32643 got on new database: +# SQL> select 1 from rdb$database a full join rdb$database b on (exists(select 1 from rdb$database)); +# Statement failed, SQLSTATE = XX000 +# internal Firebird consistency check ((CMP) copy: cannot remap (221), file: RecordSourceNodes.cpp line: 594) +# Checked on 3.0.2.32676, 4.0.0.511 -- all fine. +# +# tracker_id: CORE-5414 +# min_versions: ['3.0.2'] +# versions: 3.0.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select 1 x from rdb$database a full join rdb$database b on (exists(select 1 from rdb$database)); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + X 1 + """ + +@pytest.mark.version('>=3.0.2') +def test_core_5414_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5418.py b/tests/bugs/test_core_5418.py new file mode 100644 index 00000000..925c706b --- /dev/null +++ b/tests/bugs/test_core_5418.py @@ -0,0 +1,142 @@ +#coding:utf-8 +# +# id: bugs.core_5418 +# title: Inconsistent output when retrieving the server log via Services API +# decription: +# Test gets FB home directory and copies firebird.log to *.tmp. +# Then it makes firebird.log empty and retrieves it via services API. Output should be empty. +# Finally, it opens firebird.log and adds to it several empty newlines. +# Repeat retrieveing content - it also should not contain any characters except newline. +# Checked on 2.5.7.27030, 4.0.0.465 +# +# tracker_id: CORE-5418 +# min_versions: ['2.5.7'] +# versions: 2.5.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# from fdb import services +# import subprocess +# import time +# import shutil +# import difflib +# import re +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# engine = str(db_conn.engine_version) # convert to text because 'float' object has no attribute 'startswith' +# db_conn.close() +# +# svc = services.connect(host='localhost') +# 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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# if engine.startswith('2.5'): +# get_firebird_log_key='action_get_ib_log' +# else: +# get_firebird_log_key='action_get_fb_log' +# +# fb_log = os.path.join( fb_home, 'firebird.log' ) +# fb_bak = os.path.join( fb_home, 'firebird.tmp' ) +# shutil.copy2( fb_log, fb_bak ) +# open(fb_log, 'w').close() +# +# f_init_log = open( os.path.join(context['temp_directory'],'tmp_5418_old.log'), 'w') +# subprocess.call( [ context['fbsvcmgr_path'],"localhost:service_mgr", get_firebird_log_key ], stdout = f_init_log, stderr = subprocess.STDOUT) +# flush_and_close( f_init_log ) +# +# f = open(fb_log, 'w') +# for i in range(0,10): +# f.write(os.linesep) +# flush_and_close( f ) +# +# f_curr_log = open( os.path.join(context['temp_directory'],'tmp_5418_new.log'), 'w') +# subprocess.call( [ context['fbsvcmgr_path'],"localhost:service_mgr", get_firebird_log_key ], stdout = f_curr_log, stderr = subprocess.STDOUT ) +# flush_and_close( f_curr_log ) +# +# shutil.move( fb_bak, fb_log ) +# +# f_init_log=open(f_init_log.name, 'r') +# f_curr_log=open(f_curr_log.name, 'r') +# difftext = ''.join(difflib.unified_diff( +# f_init_log.readlines(), +# f_curr_log.readlines() +# )) +# f_init_log.close() +# f_curr_log.close() +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_5418_diff.txt'), 'w') +# f_diff_txt.write(difftext) +# flush_and_close( f_diff_txt ) +# +# p = re.compile('\\+\\s?\\S+') +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# if line.startswith('+') and line.strip() != '+++' and p.search(line): +# print( 'UNEXPECTED content in firebird.log: %(line)s' % locals() ) +# +# # Cleanup. +# ########## +# time.sleep(1) +# cleanup( (f_init_log,f_curr_log,f_diff_txt) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.7') +@pytest.mark.xfail +def test_core_5418_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5421.py b/tests/bugs/test_core_5421.py new file mode 100644 index 00000000..25568edf --- /dev/null +++ b/tests/bugs/test_core_5421.py @@ -0,0 +1,89 @@ +#coding:utf-8 +# +# id: bugs.core_5421 +# title: Performance degradation in FB 3.0.2 compared to FB 2.5.7 +# decription: +# Confirmed inefficient plan on 3.0.2.32644, 4.0.0.477: +# PLAN JOIN (D ORDER C5421_TDETL_DTS, C INDEX (C5421_TMAIN_ID, C5421_TMAIN_EKEY)) +# +# All fine on 3.0.2.32658, WI-T4.0.0.483 +# +# tracker_id: CORE-5421 +# min_versions: ['2.5.7'] +# versions: 2.5.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table tmain(id int, ekey int); + recreate table tdetl(doc_id int, dts timestamp); + + set term ^; + execute block as + declare n int = 10000; -- 7600000; + declare d int = 100; -- 5000; + declare i int = 0; + begin + while ( i < n ) do + begin + insert into tdetl(doc_id, dts) values( :i, current_date-rand()*:d ) + returning :i+1 into i; + end + insert into tmain(id, ekey) values(0, 100); + end^ + set term ;^ + commit; + + create index c5421_tmain_id on tmain(id); + create index c5421_tmain_ekey on tmain(ekey); + + create index c5421_tdetl_doc_id on tdetl(doc_id); + create descending index c5421_tdetl_dts on tdetl(dts); + commit; + + --set width rel_name 8; + --set width idx_name 30; + --select ri.rdb$relation_name rel_name, ri.rdb$index_name idx_name, ri.rdb$statistics + --from rdb$indices ri where ri.rdb$index_name starting with 'C5421'; + + set list on; + set plan on; + --set stat on; + set count on; + select first 1 d.doc_id --, d.dts + from tmain c + join tdetl d ON d.doc_id = c.id + where + c.ekey = 100 and + d.dts <= 'tomorrow' + order by + d.dts desc + ; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN SORT (JOIN (C INDEX (C5421_TMAIN_EKEY), D INDEX (C5421_TDETL_DOC_ID))) + DOC_ID 0 + Records affected: 1 + """ + +@pytest.mark.version('>=2.5.7') +def test_core_5421_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5423.py b/tests/bugs/test_core_5423.py new file mode 100644 index 00000000..9ee1552a --- /dev/null +++ b/tests/bugs/test_core_5423.py @@ -0,0 +1,55 @@ +#coding:utf-8 +# +# id: bugs.core_5423 +# title: Regression: "Invalid usage of boolean expression" when use "BETWEEN" and "IS" operators +# decription: +# +# tracker_id: CORE-5423 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('-At line[:]{0,1}[\\s]+[\\d]+,[\\s]+column[:]{0,1}[\\s]+[\\d]+', '-At line: column:')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + select 1 k from rdb$database where 1 between 0 and 2 and null is null; + select 2 k from rdb$database where 1 between 0 and 2 and foo is not null; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + K 1 + + + Records affected: 1 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42S22 + Dynamic SQL Error + -SQL error code = -206 + -Column unknown + -FOO + -At line: column: + """ + +@pytest.mark.version('>=3.0') +def test_core_5423_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5427.py b/tests/bugs/test_core_5427.py new file mode 100644 index 00000000..bcec759f --- /dev/null +++ b/tests/bugs/test_core_5427.py @@ -0,0 +1,51 @@ +#coding:utf-8 +# +# id: bugs.core_5427 +# title: Error on field concatenation of System tables +# decription: +# Confirmed bug on WI-T4.0.0.469, got: +# arithmetic exception, numeric overflow, or string truncation +# -string right truncation +# -expected length 75, actual 264 +# Checked on WI-T4.0.0.470 - works fine. +# +# tracker_id: CORE-5427 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select 0*char_length(txt) x1, 0*octet_length(txt) x2 + from ( + select 'generator '|| r.rdb$generator_name ||' .' as txt from rdb$generators r + order by 1 rows 1 + ) + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + X1 0 + X2 0 + """ + +@pytest.mark.version('>=3.0') +def test_core_5427_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5430.py b/tests/bugs/test_core_5430.py new file mode 100644 index 00000000..873673f2 --- /dev/null +++ b/tests/bugs/test_core_5430.py @@ -0,0 +1,73 @@ +#coding:utf-8 +# +# id: bugs.core_5430 +# title: Support for INCREMENT option in identity columns +# decription: +# Checked on 4.0.0.474 +# 18.08.2020: replaced expected_stdout, checked on 4.0.0.2164. +# +# tracker_id: CORE-5430 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + --set echo on; + recreate table test1( + id int generated by default as identity ( start with 12345 ) + ); + recreate table test2( + id int generated by default as identity ( start with 12345 increment 22222 ) + ); + + recreate table test3( + id int generated by default as identity ( increment 33333 ) + ); + + insert into test1 default values returning id as test1_id; + insert into test2 default values returning id as test2_id; + insert into test3 default values returning id as test3_id; + commit; + + alter table test1 alter column id restart; + alter table test2 alter column id restart with 23456; + + alter table test3 alter column id restart with 0; + alter table test3 alter column id set increment 11111; + commit; + + insert into test1 default values returning id as test1_restarted_id; + insert into test2 default values returning id as test2_restarted_id; + insert into test3 default values returning id as test3_chng_incr_id; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TEST1_ID 12345 + TEST2_ID 12345 + TEST3_ID 1 + TEST1_RESTARTED_ID 12345 + TEST2_RESTARTED_ID 23456 + TEST3_CHNG_INCR_ID -22222 + """ + +@pytest.mark.version('>=4.0') +def test_core_5430_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5431.py b/tests/bugs/test_core_5431.py new file mode 100644 index 00000000..946caf62 --- /dev/null +++ b/tests/bugs/test_core_5431.py @@ -0,0 +1,80 @@ +#coding:utf-8 +# +# id: bugs.core_5431 +# title: Support for DROP IDENTITY clause +# decription: +# Checked on 4.0.0.477 +# 18.08.2020: replaced expected_stdout, checked on 4.0.0.2164. +# +# tracker_id: CORE-5431 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('RDB\\$[\\d]+', 'RDB')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + --set echo on; + + recreate table test1( + id smallint generated by default as identity ( start with 32767 increment -65535 ) + ); + + commit; + + -- Should be 1: + select count(*) as identity_sequences_count_1 + from rdb$generators + where rdb$system_flag = 6; + + insert into test1 default values returning id as test1_id; + commit; + + alter table test1 alter column id drop identity; + commit; + + -- Should be 0: + select count(*) as identity_sequences_count_2 + from rdb$generators + where rdb$system_flag = 6; + + -- Should issue + -- Statement failed, SQLSTATE = 42000 + -- invalid request BLR at offset 47 + -- -generator RDB$nnn is not defined + insert into test1 default values returning id as test1_id; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + IDENTITY_SEQUENCES_COUNT_1 1 + TEST1_ID 32767 + IDENTITY_SEQUENCES_COUNT_2 0 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + invalid request BLR at offset 47 + -generator RDB is not defined + """ + +@pytest.mark.version('>=4.0') +def test_core_5431_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5433.py b/tests/bugs/test_core_5433.py new file mode 100644 index 00000000..0ca6a1f1 --- /dev/null +++ b/tests/bugs/test_core_5433.py @@ -0,0 +1,121 @@ +#coding:utf-8 +# +# id: bugs.core_5433 +# title: Minor performance optimization - avoid additional database attachment from security objects mapping code +# decription: +# After discuss with Alex (letters 08-10 mar 2017) it was decided to estimate effect of optimization +# by evaluating difference of attachment_id between two subsequent connections to DB. +# NB: Alex said that there was no way to see special service attachment because is was made with turned off +# ability to trace it (see letter 09-mar-2017 16:16). +# +# Checked on: +# 4.0.0.477, 29-dec-2016: ClassicServer diff=2 - one of these two attachments should be removed +# 4.0.0.494, 10-jan-2017: ClassicServer diff=1 - Ok, expected. +# ::: NB ::: +# SuperServer will have diff=3 (THREE) attachment_id because of CacheWriter and GarbageCollector. +# For that reason we detect FB architecture here and SKIP checking SS results by substitution of +# dummy "OK" instead. +# +# tracker_id: CORE-5433 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import fdb +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# def get_fb_arch(a_dsn): +# try: +# con1 = fdb.connect(dsn = a_dsn) +# con2 = fdb.connect(dsn = a_dsn) +# +# cur1 = con1.cursor() +# +# sql=( +# "select count(distinct a.mon$server_pid), min(a.mon$remote_protocol), max(iif(a.mon$remote_protocol is null,1,0))" +# +" from mon$attachments a" +# +" where a.mon$attachment_id in (%s, %s) or upper(a.mon$user) = upper('%s')" +# % (con1.attachment_id, con2.attachment_id, 'cache writer') +# ) +# +# cur1.execute(sql) +# for r in cur1.fetchall(): +# server_cnt=r[0] +# server_pro=r[1] +# cache_wrtr=r[2] +# +# if server_pro == None: +# fba='Embedded' +# elif cache_wrtr == 1: +# fba='SS' +# elif server_cnt == 2: +# fba='CS' +# else: +# +# f1=con1.db_info(fdb.isc_info_fetches) +# +# cur2=con2.cursor() +# cur2.execute('select 1 from rdb$database') +# for r in cur2.fetchall(): +# pass +# +# f2=con1.db_info(fdb.isc_info_fetches) +# +# fba = 'SC' if f1 ==f2 else 'SS' +# +# #print(fba, con1.engine_version, con1.version) +# return fba +# +# finally: +# con1.close() +# con2.close() +# +# fb_arch= get_fb_arch(dsn) +# +# if fb_arch=='CS' or fb_arch=='CS': +# con1=fdb.connect(dsn=dsn) +# att1=con1.attachment_id +# con1.close() +# +# con2=fdb.connect(dsn=dsn) +# att2=con2.attachment_id +# con2.close() +# +# print( 'OK' if att2-att1<=1 else ('BAD: attachment_id diff=%d -- too big.' % (att2-att1) ) ) +# +# else: +# print('OK') +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + OK + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_5433_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5434.py b/tests/bugs/test_core_5434.py new file mode 100644 index 00000000..435fe20c --- /dev/null +++ b/tests/bugs/test_core_5434.py @@ -0,0 +1,141 @@ +#coding:utf-8 +# +# id: bugs.core_5434 +# title: Read-only transactions in SuperServer could avoid immediate write of Header and TIP pages after change +# decription: +# If current FB arch is SuperServer then we: +# 1. We make 'snapshot' of mon$io_stats.mon$page_writes value before test and then launch plently transactions (e.g, 50) +# in READ-ONLY mode. All of them then are immediately committed, w/o any actions. +# 2. After this we take 2nd 'snapshot' of mon$io_stats.mon$page_writes and compare it with 1st one. +# 3. Difference of 'mon$page_writes' values should be 1 (One). +# Otherwise (SC/CS) we defer checking because improvement currently not implemented for these modes. +# +# Checked on: +# 1) WI-T4.0.0.463, WI-V3.0.2.32670 - room for improvement DOES exist: page_diff = 102 pages +# 2) WI-T4.0.0.511, WI-V3.0.2.32676 - all OK, page_diff = 1 (One). +# +# tracker_id: CORE-5434 +# min_versions: ['3.0.2'] +# versions: 3.0.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.2 +# resources: None + +substitutions_1 = [('Deferred: fb_arch=.*', 'Acceptable')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# def get_fb_arch(a_dsn): +# try: +# con1 = fdb.connect(dsn = a_dsn) +# con2 = fdb.connect(dsn = a_dsn) +# +# cur1 = con1.cursor() +# +# sql=( +# "select count(distinct a.mon$server_pid), min(a.mon$remote_protocol), max(iif(a.mon$remote_protocol is null,1,0))" +# +" from mon$attachments a" +# +" where a.mon$attachment_id in (%s, %s) or upper(a.mon$user) = upper('%s')" +# % (con1.attachment_id, con2.attachment_id, 'cache writer') +# ) +# +# cur1.execute(sql) +# for r in cur1.fetchall(): +# server_cnt=r[0] +# server_pro=r[1] +# cache_wrtr=r[2] +# +# if server_pro == None: +# fba='Embedded' +# elif cache_wrtr == 1: +# fba='SS' +# elif server_cnt == 2: +# fba='CS' +# else: +# +# f1=con1.db_info(fdb.isc_info_fetches) +# +# cur2=con2.cursor() +# cur2.execute('select 1 from rdb$database') +# for r in cur2.fetchall(): +# pass +# +# f2=con1.db_info(fdb.isc_info_fetches) +# +# fba = 'SC' if f1 ==f2 else 'SS' +# +# #print(fba, con1.engine_version, con1.version) +# return fba +# +# finally: +# con1.close() +# con2.close() +# +# fb_arch=get_fb_arch(dsn) +# +# if fb_arch == 'SS': +# +# txParams = ( [ fdb.isc_tpb_read ] ) +# c2 = fdb.connect(dsn=dsn) +# +# sql='select mon$page_writes from mon$io_stats where mon$stat_group=0' +# cur=db_conn.cursor() +# +# cur.execute(sql) +# for r in cur: +# page_writes_before_test = r[0] +# db_conn.commit() +# +# ta=[] +# for i in range(0, 50): +# ta.append( c2.trans( default_tpb = txParams ) ) +# ta[i].begin() +# +# for i in range(0,len(ta)): +# ta[i].rollback() +# +# +# cur.execute(sql) +# for r in cur: +# page_writes_after_test = r[0] +# +# pw_diff = page_writes_after_test - page_writes_before_test +# +# db_conn.commit() +# c2.close() +# +# msg = 'Acceptable' if pw_diff == 1 else ('Too big value of page_writes diff: %s' % ( pw_diff )) +# else: +# # FB works NOT in SuperServer. This currently must be SKIPPED from checking (see notes in the ticket). +# msg = 'Deferred: fb_arch=%s' % fb_arch +# +# print(msg) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Acceptable + """ + +@pytest.mark.version('>=3.0.2') +@pytest.mark.xfail +def test_core_5434_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5435.py b/tests/bugs/test_core_5435.py new file mode 100644 index 00000000..cfc276a7 --- /dev/null +++ b/tests/bugs/test_core_5435.py @@ -0,0 +1,296 @@ +#coding:utf-8 +# +# id: bugs.core_5435 +# title: Badly selective index could be used for extra filtering even if selective index is used for sorting +# decription: +# Test creates table and fills it with data like it was specified in the source ticket, +# but query has been CHANGED after discuss with dimitr (see letter 19-jan-2017 08:43): +# instead of 'f01 is null' we use 'f01 = 1' because actually problem that was fixed +# is NOT related with NULL handling. +# Usage of NULL will hide effect of improvement in optimizer because there is old bug +# in FB from early years which prevent engine from fast navigate on index (i.e. PLAN ORDER) +# when expression is like 'is NULL'. +# ---------------------------------- +# +# Implementation details: we start trace and run ISQL with query, then stop trace, open its log +# and parse it with seeking lines with 'plan (' and 'fetch(es)'. +# Expected plan: +# PLAN (TEST ORDER TEST_F01_ID) -- confirmed on WI-T4.0.0.503 +# 0 ms, 3 read(s), 44 fetch(es) +# WRONG (ineffective) plan: +# PLAN (TEST ORDER TEST_F01_ID INDEX (TEST_F02_ONLY)) -- detected on WI-T4.0.0.463 +# 21 ms, 115 read(s), 157 fetch(es) +# Value of fetches is compared with threshold (currently = 80) which was received after several runs. +# +# tracker_id: CORE-5435 +# min_versions: ['3.0.2'] +# versions: 3.0.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=8192, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import time +# from fdb import services +# from subprocess import Popen +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_file = db_conn.database_name +# # Obtain engine version: +# engine = str(db_conn.engine_version) +# +# db_conn.close() +# +# FETCHES_THRESHOLD = 80 +# +# #-------------------------------------------- +# +# 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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# # Change FW to OFF in order to speed up initial data filling: +# ################## +# fn_nul = open(os.devnull, 'w') +# +# subprocess.call([ context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "prp_write_mode", "prp_wm_async", +# "dbname", db_file ], +# stdout = fn_nul, +# stderr = subprocess.STDOUT +# ) +# +# fn_nul.close() +# +# ##################### +# # Prepare table: add data. +# +# sql_init=''' +# recreate table test +# ( +# id int not null, +# f01 int, +# f02 int +# ); +# +# set term ^; +# create or alter procedure sp_add_init_data(a_rows_to_add int) +# as +# declare n int; +# declare i int = 0; +# begin +# n = a_rows_to_add; +# while ( i < n ) do +# begin +# insert into test(id, f01, f02) values( :i, nullif(mod(:i, :n/20), 0), iif( mod(:i,3)<2, 0, 1) ) +# returning :i+1 into i; +# end +# end +# ^ +# set term ^; +# commit; +# +# execute procedure sp_add_init_data( 300000 ); +# commit; +# +# create index test_f01_id on test(f01, id); +# create index test_f02_only on test(f02); +# commit; +# ''' +# +# sql_cmd=open(os.path.join(context['temp_directory'],'tmp_core_5435.sql'), 'w') +# sql_cmd.write(sql_init) +# flush_and_close( sql_cmd ) +# +# sql_log=open(os.path.join(context['temp_directory'],'tmp_core_5435.log'),'w') +# sql_err=open(os.path.join(context['temp_directory'],'tmp_core_5435.err'),'w') +# +# subprocess.call([ context['isql_path'], dsn, "-i", sql_cmd.name],stdout=sql_log, stderr=sql_err) +# +# flush_and_close( sql_log ) +# flush_and_close( sql_err ) +# +# ######################### +# +# txt = '''# Generated auto, do not edit! +# database=%[\\\\\\\\/]security?.fdb +# { +# enabled = false +# } +# database=%[\\\\\\\\/]bugs.core_5435.fdb +# { +# enabled = true +# time_threshold = 0 +# log_statement_finish = true +# print_plan = true +# print_perf = true +# } +# ''' +# +# f_trc_cfg=open( os.path.join(context['temp_directory'],'tmp_trace_5435.cfg'), 'w') +# f_trc_cfg.write(txt) +# flush_and_close( f_trc_cfg ) +# +# # ############################################################## +# # S T A R T T R A C E i n S E P A R A T E P R O C E S S +# # ############################################################## +# +# f_trc_log=open( os.path.join(context['temp_directory'],'tmp_trace_5435.log'), "w") +# f_trc_err=open( os.path.join(context['temp_directory'],'tmp_trace_5435.err'), "w") +# +# p_trace = Popen( [ context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_start' , 'trc_cfg', f_trc_cfg.name],stdout=f_trc_log,stderr=f_trc_err) +# +# +# sql_run=''' +# set list on; +# select count(*) cnt_check +# from ( +# select * +# from test -- ############################################################################ +# where f01 = 1 and f02=0 -- <<< ::: NB ::: we check here 'f01 = 1' rather than 'f01 is NULL' <<< !!! <<< +# order by f01, id -- ############################################################################ +# ) +# ; +# ''' +# +# sql_cmd=open(os.path.join(context['temp_directory'],'tmp_core_5435.sql'), 'w') +# +# sql_cmd.write(sql_run) +# flush_and_close( sql_cmd ) +# +# sql_log=open(os.path.join(context['temp_directory'],'tmp_core_5435.log'),'w') +# sql_err=open(os.path.join(context['temp_directory'],'tmp_core_5435.err'),'w') +# +# subprocess.call([ context['isql_path'], dsn, "-i", sql_cmd.name],stdout=sql_log, stderr=sql_err) +# +# flush_and_close( sql_log ) +# flush_and_close( sql_err ) +# +# # 01-mar-2021: do NOT remove delay from here. +# # It must be at least 2 seconds, otherwise trace log will not be fulfilled +# # when run on Linux! +# time.sleep(2) +# +# # #################################################### +# # G E T A C T I V E T R A C E S E S S I O N I D +# # #################################################### +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# +# f_trc_lst = open( os.path.join(context['temp_directory'],'tmp_trace_5435.lst'), 'w') +# subprocess.call([context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_list'], stdout=f_trc_lst) +# flush_and_close( f_trc_lst ) +# +# trcssn=0 +# with open( f_trc_lst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# +# # #################################################### +# # S E N D R E Q U E S T T R A C E T O S T O P +# # #################################################### +# if trcssn>0: +# fn_nul = open(os.devnull, 'w') +# subprocess.call([context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_stop','trc_id', trcssn], stdout=fn_nul) +# fn_nul.close() +# else: +# print('Trace session was finished forcedly: could not find its trc_id.') +# +# p_trace.terminate() +# flush_and_close( f_trc_log ) +# flush_and_close( f_trc_err ) +# +# run_with_plan='' +# num_of_fetches=-1 +# +# with open( f_trc_log.name,'r') as f: +# for line in f: +# if line.lower().startswith('plan ('): +# run_with_plan = line.upper() +# if 'fetch(es)' in line: +# words = line.split() +# for k in range(len(words)): +# if words[k].startswith('fetch'): +# num_of_fetches = int( words[k-1] ) +# +# if run_with_plan and num_of_fetches>0: +# print(run_with_plan) +# print('Number of fetches: acceptable.' if num_of_fetches < FETCHES_THRESHOLD else 'Too much fetches %(num_of_fetches)s: more than threshold = %(FETCHES_THRESHOLD)s' % locals()) +# else: +# print('Trace log was not fulfilled: can not find lines with PLAN and/or STATISTICS. Increase delays in the test code!') +# print('Content of trace log:') +# print('=' * 21) +# f=open( f_trc_log.name,'r') +# for r in f.readlines(): +# print(r) +# f.close() +# print('=' * 21) +# +# # CLEANUP +# ######### +# time.sleep(1) +# cleanup( (f_trc_cfg, f_trc_lst, f_trc_log, f_trc_err, sql_log, sql_err, sql_cmd) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (TEST ORDER TEST_F01_ID) + Number of fetches: acceptable. + """ + +@pytest.mark.version('>=3.0.2') +@pytest.mark.xfail +def test_core_5435_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5441.py b/tests/bugs/test_core_5441.py new file mode 100644 index 00000000..643f6919 --- /dev/null +++ b/tests/bugs/test_core_5441.py @@ -0,0 +1,243 @@ +#coding:utf-8 +# +# id: bugs.core_5441 +# title: Cache physical numbers of often used data pages to reduce number of fetches of pointer pages +# decription: +# We create table with single field, add several rows and create index. +# Number of these rows must be enough to fit all of them in the single data page. +# Than we do loop and query on every iteration one row, using PLAN INDEX. +# Only _first_ iteration should lead to reading PP (and this requires 1 fetch), +# but all subseq. must require to read only DP. This should refect in trace as: +# * 4 fetches for 1st statement; +# * 3 fetches for statements starting with 2nd. +# Distinct number of fetches are accumulated in Python dict, and is displayed finally. +# We should have TWO distinct elements in this dict, and numbers in their values must +# differ at (N-1), where N = number of rows in the table. +# +# Checked on: +# * WI-T4.0.0.454 (22-nov-2016) -- number of fethes on every iteration is the same and equal to 4; +# * WI-T4.0.0.460 (02-dec-2016) -- only at FIRST iter. fetches=4; for all subsequent loops fetches = 3. +# This proves that lot of PP scans are avoided and necessary data are taken from cache. +# +# Also checked on: +# WI-V3.0.2.32677 (SS), WI-V3.0.2.32643 (SC/CS), WI-T4.0.0.519 (SS) -- all fine. +# +# +# tracker_id: CORE-5441 +# min_versions: ['3.0.2'] +# versions: 3.0.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table test(x int primary key); + commit; + insert into test(x) select r from ( + select row_number()over() r + from rdb$types a,rdb$types b + rows 10 + ) + order by rand(); + commit; + + set term ^; + create procedure sp_test as + declare n int; + declare c int; + begin + n = 10; + while( n > 0 ) do + begin + execute statement ( 'select 1 from test where x = ? rows 1' ) ( :n ) into c; + n = n - 1; + end + end^ + set term ;^ + commit; + """ + +db_1 = db_factory(page_size=8192, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import time +# from fdb import services +# from subprocess import Popen +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# txt = '''# Generated auto, do not edit! +# database=%[\\\\\\\\/]security?.fdb +# { +# enabled = false +# } +# database=%[\\\\\\\\/]bugs.core_5441.fdb +# { +# enabled = true +# time_threshold = 0 +# include_filter = "%(select % from test where x = ?)%" +# log_statement_finish = true +# +# } +# ''' +# +# f_trc_cfg=open( os.path.join(context['temp_directory'],'tmp_trace_5441.cfg'), 'w') +# f_trc_cfg.write(txt) +# flush_and_close( f_trc_cfg ) +# +# # ############################################################## +# # S T A R T T R A C E i n S E P A R A T E P R O C E S S +# # ############################################################## +# +# f_trc_log=open( os.path.join(context['temp_directory'],'tmp_trace_5441.log'), "w") +# f_trc_err=open( os.path.join(context['temp_directory'],'tmp_trace_5441.err'), "w") +# +# p_trace = Popen( [ context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_start' , 'trc_cfg', f_trc_cfg.name],stdout=f_trc_log,stderr=f_trc_err) +# +# time.sleep(1) +# +# # #################################################### +# # G E T A C T I V E T R A C E S E S S I O N I D +# # #################################################### +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# +# f_trc_lst = open( os.path.join(context['temp_directory'],'tmp_trace_5441.lst'), 'w') +# subprocess.call([context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_list'], stdout=f_trc_lst) +# flush_and_close( f_trc_lst ) +# +# # !!! DO NOT REMOVE THIS LINE !!! +# # time.sleep(1) +# +# trcssn=0 +# with open( f_trc_lst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# +# con1 = fdb.connect(dsn=dsn) +# cur1=con1.cursor() +# +# ############################# +# # R U N T E S T P R O C +# ############################# +# cur1.callproc('sp_test') +# con1.close() +# +# # Let trace log to be entirely written on disk: +# time.sleep(1) +# +# # #################################################### +# # S E N D R E Q U E S T T R A C E T O S T O P +# # #################################################### +# if trcssn>0: +# fn_nul = open(os.devnull, 'w') +# subprocess.call([context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_stop','trc_id', trcssn], stdout=fn_nul) +# fn_nul.close() +# +# # 23.02.2021. DELAY FOR AT LEAST 1 SECOND REQUIRED HERE! +# # Otherwise trace log can remain empty. +# time.sleep(2) +# +# p_trace.terminate() +# flush_and_close( f_trc_log ) +# flush_and_close( f_trc_err ) +# +# # Following file should be EMPTY: +# ################ +# +# f_list=(f_trc_err,) +# for i in range(len(f_list)): +# f_name=f_list[i].name +# if os.path.getsize(f_name) > 0: +# with open( f_name,'r') as f: +# for line in f: +# print("Unexpected STDERR, file "+f_name+": "+line) +# +# fetches_distinct_amounts={} +# +# with open( f_trc_log.name,'r') as f: +# for line in f: +# if 'fetch(es)' in line: +# words = line.split() +# for k in range(len(words)): +# if words[k].startswith('fetch'): +# if not words[k-1] in fetches_distinct_amounts: +# fetches_distinct_amounts[ words[k-1] ] = 1 +# else: +# fetches_distinct_amounts[ words[k-1] ] += 1 +# +# for k, v in sorted( fetches_distinct_amounts.items() ): +# print( ''.join( ('fetches=',k) ), 'occured', v, 'times' ) +# +# # CLEANUP +# ######### +# time.sleep(1) +# cleanup( (f_trc_cfg, f_trc_lst, f_trc_log, f_trc_err) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + fetches=3 occured 9 times + fetches=4 occured 1 times + """ + +@pytest.mark.version('>=3.0.2') +@pytest.mark.xfail +def test_core_5441_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5447.py b/tests/bugs/test_core_5447.py new file mode 100644 index 00000000..80e4fa03 --- /dev/null +++ b/tests/bugs/test_core_5447.py @@ -0,0 +1,105 @@ +#coding:utf-8 +# +# id: bugs.core_5447 +# title: EXECUTE STATEMENT when starts with '--' issues -Unexpected ... column , value is invalid and can change randomly +# decription: +# We run EB that is show in the ticket three times, with redirection STDOUT and STDERR to separate files. +# Then we open file of STDERR and parse it: search for lines which contain "-Unexpected end of command" text. +# Extract nineth word from this and add it to Python structure of type = SET. +# Finally, we check that this set: +# 1) all columns are positive integers; +# 2) contains only one element (i.e. all columns have the same value). +# +# Checked on 3.0.02.32684, 4.0.0.531 - all fine. +# +# tracker_id: CORE-5447 +# min_versions: ['3.0.2'] +# versions: 3.0.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# so=sys.stdout +# se=sys.stderr +# +# +# f_sql_log=os.path.join(context['temp_directory'],'tmp_c5447.log') +# f_sql_err=os.path.join(context['temp_directory'],'tmp_c5447.err') +# +# sys.stdout = open( f_sql_log, 'w') +# sys.stderr = open( f_sql_err, 'w') +# +# es_sql=''' +# set term ^; +# execute block as +# begin +# execute statement '-- table ''test'' has no trigger, DROP TRIGGER is skipped.'; +# end +# ^ +# execute block as +# begin +# execute statement '-- table ''test'' has no trigger, DROP TRIGGER is skipped.'; +# end +# ^ +# execute block as +# begin +# execute statement '-- table ''test'' has no trigger, DROP TRIGGER is skipped.'; +# end +# ^ +# set term ;^ +# ''' +# runProgram('isql',[dsn], es_sql) +# +# sys.stdout = so +# sys.stderr = se +# +# col_set=set() +# with open( f_sql_err, 'r') as f: +# for line in f: +# if '-Unexpected end of command' in line: +# # -Unexpected end of command - line 0, column -45949567 +# # 0 1 2 3 4 5 6 7 8 +# col_number=line.split()[8] +# print( 'OK: column is integer > 0' if col_number.isdigit() and str(col_number) > 0 else 'FAIL: column is ZERO, NEGATIVE or NaN' ) +# col_set.add( line.split()[8] ) +# +# print( 'OK: all columns are the same' if len(col_set)==1 else 'FAIL: columns differ or empty set()' ) +# +# os.remove(f_sql_log) +# os.remove(f_sql_err) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + OK: column is integer > 0 + OK: column is integer > 0 + OK: column is integer > 0 + OK: all columns are the same + """ + +@pytest.mark.version('>=3.0.2') +@pytest.mark.xfail +def test_core_5447_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5449.py b/tests/bugs/test_core_5449.py new file mode 100644 index 00000000..7a6ac033 --- /dev/null +++ b/tests/bugs/test_core_5449.py @@ -0,0 +1,120 @@ +#coding:utf-8 +# +# id: bugs.core_5449 +# title: Support DEFAULT context value in INSERT, UPDATE, MERGE and UPDATE OR INSERT statements +# decription: +# Checked on WI-T4.0.0.531. +# +# tracker_id: CORE-5449 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + recreate table test1( + id int generated by default as identity constraint test1_pk primary key using index test1_pk + ,x int default 123 + ,y int + ,z computed by(x + coalesce(y, id) ) + ); + + insert into test1(id, x, y, z) values( default, default, 222, default ) + returning 'AFFECTED BY "INSERT"' msg, id, x, y, z + ; + + update or insert into test1(id, x, y, z) values(-1, default, default, default ) + matching(id) + returning 'AFFECTED BY "UPDATE OR INSERT"' msg, id, x, y, z + ; + + + update test1 set y = z, z = default + where y is null + order by id + rows 1 + returning + 'AFFECTED BY "UPDATE"' msg, + id, + old.y as y_before_update, + old.z as z_before_update, + new.y as y_after_update, + new.z as z_after_update + ; + + + merge into test1 t using(select id,x,y from test1 union all select 2*id, 3*x,4*y from test1) s + on s.id = t.id -- and + when matched then update set t.y = s.x, t.x=s.y, t.z = default + when NOT matched then insert(x,y,z) values(default, default, default) + ; + + select 'AFFECTED BY "MERGE"' msg, t.* from test1 t order by id; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG AFFECTED BY "INSERT" + ID 1 + X 123 + Y 222 + Z 345 + + MSG AFFECTED BY "UPDATE OR INSERT" + ID -1 + X 123 + Y + Z 122 + + MSG AFFECTED BY "UPDATE" + ID -1 + Y_BEFORE_UPDATE + Z_BEFORE_UPDATE 122 + Y_AFTER_UPDATE 122 + Z_AFTER_UPDATE 245 + + MSG AFFECTED BY "MERGE" + ID -1 + X 122 + Y 123 + Z 245 + + MSG AFFECTED BY "MERGE" + ID 1 + X 222 + Y 123 + Z 345 + + MSG AFFECTED BY "MERGE" + ID 2 + X 123 + Y + Z 125 + + MSG AFFECTED BY "MERGE" + ID 3 + X 123 + Y + Z 126 + """ + +@pytest.mark.version('>=4.0') +def test_core_5449_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5454.py b/tests/bugs/test_core_5454.py new file mode 100644 index 00000000..9c957d94 --- /dev/null +++ b/tests/bugs/test_core_5454.py @@ -0,0 +1,74 @@ +#coding:utf-8 +# +# id: bugs.core_5454 +# title: INSERT into updatable view without explicit field list failed +# decription: +# Confirmed bug on WI-T4.0.0.463, got: +# Statement failed, SQLSTATE = 21S01 +# Dynamic SQL Error +# -SQL error code = -804 +# -Count of read-write columns does not equal count of values +# Checked on WI-T4.0.0.503 - works fine. +# NB: this bug was NOT (yet ?) fixed for 3.0 ==> min_version = 4.0 +# (checked on WI-V3.0.2.32670, 17-jan-2017). +# +# tracker_id: CORE-5454 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate view v_test as select 1 x from rdb$database; + commit; + + recreate table test1(id int, x int); + recreate table test2(id int, x int); + + recreate view v_test as + select * from test1 + union all + select * from test2; + + set term ^; + create trigger v_test_dml for v_test before insert as + declare i integer; + begin + i = mod(new.id, 2); + if (i = 0) then + insert into test1 values (new.id, new.x); + else if (i = 1) then + insert into test2 values (new.id, new.x); + end + ^ + set term ;^ + commit; + + set count on; + insert into v_test values(123, 321); + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 1 + """ + +@pytest.mark.version('>=4.0') +def test_core_5454_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5457.py b/tests/bugs/test_core_5457.py new file mode 100644 index 00000000..a1d8a3ae --- /dev/null +++ b/tests/bugs/test_core_5457.py @@ -0,0 +1,209 @@ +#coding:utf-8 +# +# id: bugs.core_5457 +# title: Bugcheck 167 (invalid SEND request) +# decription: +# Reproduced on: WI-V3.0.1.32609 - got in firebird.log: +# "internal Firebird consistency check (invalid SEND request (167), file: JrdStatement.cpp line: 325)" +# On client side got: +# DatabaseError: +# Error while rolling back transaction: +# - SQLCODE: -902 +# - internal Firebird consistency check (can't continue after bugcheck) +# -902 +# 335544333 +# +# Test extracts content of firebird.log, then runs scenario which earlier led to "invalid SEND request (167)" +# and then again get firebird.log for comparing with its previous content. +# The only new record in firebird.log must be: +# "Modifying procedure SP_CALC_VAL which is currently in use by active user requests" +# Checked on: +# fb30Cs, build 3.0.4.32972: OK, 2.984s. +# FB30SS, build 3.0.4.32988: OK, 3.047s. +# FB40CS, build 4.0.0.955: OK, 4.531s. +# FB40SS, build 4.0.0.1008: OK, 3.141s. +# +# +# tracker_id: CORE-5457 +# min_versions: ['3.0.2'] +# versions: 3.0.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# import difflib +# import re +# import time +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# def svc_get_fb_log( f_fb_log ): +# +# global subprocess +# +# subprocess.call( [ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# "action_get_fb_log" +# ], +# stdout=f_fb_log, stderr=subprocess.STDOUT +# ) +# return +# +# ########################################################################################### +# +# f_fblog_before=open( os.path.join(context['temp_directory'],'tmp_5457_fblog_before.txt'), 'w') +# svc_get_fb_log( f_fblog_before ) +# flush_and_close( f_fblog_before ) +# +# con1=fdb.connect(dsn = dsn) +# +# sp_test_ddl=''' +# create procedure sp_calc_val(a_id int) returns(val int) as +# begin +# val = a_id * 10; +# suspend; +# end +# ''' +# +# test_table_ddl=''' +# create table test( +# id int primary key, +# txt varchar(80), +# calc_val computed by ( (select val from sp_calc_val(test.id) ) ) +# ) +# ''' +# con1.execute_immediate(sp_test_ddl) +# con1.commit() +# con1.execute_immediate(test_table_ddl) +# con1.commit() +# +# cur1=con1.cursor() +# cur1.execute('insert into test select row_number()over(), ascii_char( 96+row_number()over() ) from rdb$types rows 7') +# con1.commit() +# +# cur1.execute('select count(*), sum(calc_val) from test') +# for r in cur1: +# pass; +# +# +# sp_alter_ddl=''' +# alter procedure sp_calc_val (a_id int) returns (val int) as +# begin +# val = a_id * 7; +# suspend; +# end +# ''' +# +# con1.execute_immediate(sp_alter_ddl) +# +# cur1.execute('select count(*), sum(calc_val) from test') +# for r in cur1: +# pass; +# con1.commit() +# +# cur1.execute('select count(*), sum(calc_val) from test') +# for r in cur1: +# pass; +# +# time.sleep(1) +# +# f_fblog_after=open( os.path.join(context['temp_directory'],'tmp_5457_fblog_after.txt'), 'w') +# svc_get_fb_log( f_fblog_after ) +# flush_and_close( f_fblog_after ) +# +# +# # Compare firebird.log versions BEFORE and AFTER this test: +# ###################### +# +# oldfb=open(f_fblog_before.name, 'r') +# newfb=open(f_fblog_after.name, 'r') +# +# difftext = ''.join(difflib.unified_diff( +# oldfb.readlines(), +# newfb.readlines() +# )) +# oldfb.close() +# newfb.close() +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_5457_diff.txt'), 'w') +# f_diff_txt.write(difftext) +# flush_and_close( f_diff_txt ) +# +# unexpected_patterns =( +# re.compile('\\s+internal\\s+Firebird\\s+consistency\\s+check', re.IGNORECASE), +# ) +# +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# if line.startswith('+'): +# match2some = filter( None, [ p.search(line) for p in unexpected_patterns ] ) +# if match2some: +# print( 'UNEXPECTED TEXT IN FIREBIRD.LOG: ' + (' '.join(line.split()).upper()) ) +# +# # Cleanup: +# ########## +# time.sleep(1) +# cleanup( (f_diff_txt,f_fblog_before,f_fblog_after) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0.2') +@pytest.mark.xfail +def test_core_5457_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5463.py b/tests/bugs/test_core_5463.py new file mode 100644 index 00000000..fd904152 --- /dev/null +++ b/tests/bugs/test_core_5463.py @@ -0,0 +1,119 @@ +#coding:utf-8 +# +# id: bugs.core_5463 +# title: Support GENERATED ALWAYS identity columns and OVERRIDE clause +# decription: +# Checked on WI-T4.0.0.546. Works fine. +# 18.08.2020: replaced expected_stdout, checked on 4.0.0.2164. +# +# tracker_id: CORE-5463 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('OVERRIDING SYSTEM VALUE should be used.*', 'OVERRIDING SYSTEM VALUE should be used')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + recreate table test_always( + id_always int generated ALWAYS as identity (start with 11 increment 22) unique + ); + + recreate table test_default( + id_default int generated BY DEFAULT as identity (start with -11 increment -22) unique + ); + + + insert into test_default default values returning id_default; -- expected: -33 + + insert into test_always default values returning id_always; -- expected: 33 + + -- Comments taken from doc\\sql.extensions\\README.identity_columns.txt + -- ================================================================== + + -- ........................................ + -- Identity columns are implicitly NOT NULL + -- ........................................ + -- Statement failed, SQLSTATE = 42000 + -- OVERRIDING SYSTEM VALUE should be used to override the value of an identity column defined as 'GENERATED ALWAYS' in ta + insert into test_always(id_always) values(null); + + -- Statement failed, SQLSTATE = 23000 + -- validation error for column "TEST"."id_default", value "*** null ***" + insert into test_default(id_default) values(null); + + + -- ........................................................................ + -- BY DEFAULT identity columns can be overriden in INSERT statements + -- just specifying the value in the values list + -- ........................................................................ + insert into test_default(id_default) values(-7654321) returning id_default; + -- insert into test_default default values returning id_default; ==> -99 ! + + + -- ........................................................................ + -- However, for ALWAYS identity columns that is not allowed. + -- To use the value passed in the INSERT statement for an ALWAYS column, you should pass + -- OVERRIDING SYSTEM VALUE: + -- ........................................................................ + + + -- 1) check that OVERRIDING SYSTEM VALUE clause does not affect on NOT_NULL constraint: + -- Statement failed, SQLSTATE = 23000 + -- validation error for column "test_always"."ID_ALWAYS", value "*** null ***" + insert into test_always(id_always) overriding system value values (null) returning id_always; + + -- 2) check ability to override system value by providing our own: + insert into test_always(id_always) overriding system value values (7654321) returning id_always; + + -- ......................................................................... + -- OVERRIDING also supports a subclause to be used with BY DEFAULT columns, + -- to ignore the value passed in INSERT and use the defined sequence: + -- ......................................................................... + + -- 1) check that attempt to pass NULL into VALUES list has no effect: + insert into test_default(id_default) overriding user value values(null) returning id_default; -- expected: -99 + + -- 2) check ability to pass allowed value but it also must be overriden by default one: + insert into test_default(id_default) overriding user value values(-7654322) returning id_default; -- expected: -121 + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID_DEFAULT -11 + ID_ALWAYS 11 + ID_DEFAULT -7654321 + ID_ALWAYS 7654321 + ID_DEFAULT -33 + ID_DEFAULT -55 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + OVERRIDING SYSTEM VALUE should be used + + Statement failed, SQLSTATE = 23000 + validation error for column "TEST_DEFAULT"."ID_DEFAULT", value "*** null ***" + + Statement failed, SQLSTATE = 23000 + validation error for column "TEST_ALWAYS"."ID_ALWAYS", value "*** null ***" + """ + +@pytest.mark.version('>=4.0') +def test_core_5463_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5464.py b/tests/bugs/test_core_5464.py new file mode 100644 index 00000000..592439fa --- /dev/null +++ b/tests/bugs/test_core_5464.py @@ -0,0 +1,109 @@ +#coding:utf-8 +# +# id: bugs.core_5464 +# title: AV in fbclient when reading blob stored in incompatible encoding +# decription: +# Reproduced crash of isql on WI-T4.0.0.463 +# (standard message appeared with text about program that is to be closed). +# Checked on 3.0.2.32677, 4.0.0.519 - works fine. +# +# tracker_id: CORE-5464 +# min_versions: ['3.0.2'] +# versions: 3.0.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create domain d_int int; + comment on domain d_int is + '*Лев Николаевич Толстой * *Анна Каренина * /Мне отмщение, и аз воздам/ *ЧАСТЬ ПЕРВАЯ* *I * + Все счастливые семьи похожи друг на друга, каждая несчастливая + семья несчастлива по-своему. + Все смешалось в доме Облонских. Жена узнала, что муж был в связи + с бывшею в их доме француженкою-гувернанткой, и объявила мужу, что + не может жить с ним в одном доме. Положение это продолжалось уже + третий день и мучительно чувствовалось и самими супругами, и всеми + членами семьи, и домочадцами. Все члены семьи и домочадцы + чувствовали, что нет смысла в их сожительстве и что на каждом + п1 + '; + commit; + """ + +db_1 = db_factory(charset='WIN1251', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.close() +# +# so=sys.stdout +# se=sys.stderr +# +# fn_log = os.path.join(context['temp_directory'],'tmp_c5464.log') +# fn_err = os.path.join(context['temp_directory'],'tmp_c5464.err') +# sys.stdout = open( fn_log, 'w') +# sys.stderr = open( fn_err, 'w') +# sql=''' +# set names win1250; +# connect '%s' user '%s' password '%s'; +# set blob all; +# set list on; +# +# 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; +# +# select rdb$field_name, rdb$system_flag, rdb$description +# from rdb$fields where rdb$description is not null; +# ''' % ( dsn, user_name, user_password ) +# +# runProgram('isql',['-q'],sql) +# +# sys.stdout = so +# sys.stderr = se +# +# with open( fn_log,'r') as f: +# for line in f: +# line=line.replace('SQL> ', '').replace('CON> ', '').rstrip() +# if line.split(): +# print(line) +# +# with open( fn_err,'r') as f: +# for line in f: +# if line.split(): +# print(line) +# +# os.remove(fn_log) +# os.remove(fn_err) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CONNECTION_CSET WIN1250 + DB_DEFAULT_CSET WIN1251 + Statement failed, SQLSTATE = 22018 + Cannot transliterate character between character sets + """ + +@pytest.mark.version('>=3.0.2') +@pytest.mark.xfail +def test_core_5464_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5470.py b/tests/bugs/test_core_5470.py new file mode 100644 index 00000000..8db58352 --- /dev/null +++ b/tests/bugs/test_core_5470.py @@ -0,0 +1,242 @@ +#coding:utf-8 +# +# id: bugs.core_5470 +# title: Trace INCLUDE_FILTER with [[:WHITESPACE:]]+ does not work when statement contains newline is issued +# decription: +# We create a list of several DDLs which all contain NEWLINE character(s) between jeyword 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. +# +# Checked on 2.5.7.27048, 3.0.2.32685, 4.0.0.531 - all fine. +# +# tracker_id: CORE-5470 +# min_versions: ['2.5.7'] +# versions: 2.5.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import time +# from fdb import services +# from subprocess import Popen +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # Obtain engine version: +# engine = str(db_conn.engine_version) # convert to text because 'float' object has no attribute 'startswith' +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# if engine.startswith('2.5'): +# fb_home = fb_home + 'bin'+os.sep +# txt = '''# Generated auto, do not edit! +# +# enabled false +# +# +# +# enabled true +# time_threshold 0 +# log_initfini false +# log_statement_finish = true +# include_filter = "%(recreate|create|alter|drop|comment on)[[:WHITESPACE:]]+(domain|generator|sequence|exception|procedure|table|index|view|trigger|role|filter|external function)%" +# +# ''' +# else: +# txt = '''# Generated auto, do not edit! +# database=%[\\\\\\\\/]security?.fdb +# { +# enabled = false +# } +# database=%[\\\\\\\\/]bugs.core_5470.fdb +# { +# enabled = true +# 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)%" +# } +# ''' +# +# f_trc_cfg=open( os.path.join(context['temp_directory'],'tmp_trc_5470.cfg'), 'w') +# f_trc_cfg.write(txt) +# flush_and_close( f_trc_cfg ) +# +# # ############################################################## +# # S T A R T T R A C E i n S E P A R A T E P R O C E S S +# # ############################################################## +# +# f_trc_log=open( os.path.join(context['temp_directory'],'tmp_trc_5470.log'), "w") +# f_trc_err=open( os.path.join(context['temp_directory'],'tmp_trc_5470.err'), "w") +# +# p_trace = Popen( [ context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_start' , 'trc_cfg', f_trc_cfg.name],stdout=f_trc_log,stderr=f_trc_err) +# +# time.sleep(1) +# +# # #################################################### +# # G E T A C T I V E T R A C E S E S S I O N I D +# # #################################################### +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# +# f_trc_lst = open( os.path.join(context['temp_directory'],'tmp_trace_5470.lst'), 'w') +# subprocess.call([context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_list'], stdout=f_trc_lst) +# flush_and_close( f_trc_lst ) +# +# trcssn=0 +# with open( f_trc_lst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# +# ddl_lst=( +# '''recreate +# +# table +# +# +# +# t_test(x int) +# ''', +# '''comment on +# table +# +# +# t_test is +# 'foo +# bar' +# ''', +# ''' +# +# create +# or +# +# alter +# view +# +# v_rio +# +# as +# select * +# from +# +# rdb$database +# ''' +# ) +# +# con1 = fdb.connect(dsn=dsn) +# for s in ddl_lst: +# con1.execute_immediate(s) +# +# con1.commit() +# con1.close() +# +# # Let trace log to be entirely written on disk: +# time.sleep(2) +# +# # #################################################### +# # S E N D R E Q U E S T T R A C E T O S T O P +# # #################################################### +# if trcssn>0: +# fn_nul = open(os.devnull, 'w') +# subprocess.call([context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_stop','trc_id', trcssn], stdout=fn_nul) +# fn_nul.close() +# # # DO NOT REMOVE THIS LINE: +# # time.sleep(2) +# +# p_trace.terminate() +# flush_and_close( f_trc_log ) +# flush_and_close( f_trc_err ) +# +# # Following file should be EMPTY: +# ################ +# +# f_list=(f_trc_err,) +# for i in range(len(f_list)): +# f_name=f_list[i].name +# if os.path.getsize(f_name) > 0: +# with open( f_name,'r') as f: +# for line in f: +# print("Unexpected STDERR, file "+f_name+": "+line) +# +# with open( f_trc_log.name,'r') as f: +# lines=f.read() +# for s in ddl_lst: +# print( 'FOUND' if lines.find(s) > 0 else 'NOT found' ) +# +# # CLEANUP +# ######### +# time.sleep(1) +# cleanup( (f_trc_cfg, f_trc_lst, f_trc_log, f_trc_err) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + FOUND + FOUND + FOUND + """ + +@pytest.mark.version('>=2.5.7') +@pytest.mark.xfail +def test_core_5470_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5470_addi.py b/tests/bugs/test_core_5470_addi.py new file mode 100644 index 00000000..ec7249bf --- /dev/null +++ b/tests/bugs/test_core_5470_addi.py @@ -0,0 +1,201 @@ +#coding:utf-8 +# +# id: bugs.core_5470_addi +# title: Additional check for trace log when user issues statement with character that can not be transliterated +# decription: +# It was detected that trace can stop any writing to its log if client issues query with character +# that can NOT transliterated between character sets. Such statement and *any* other statements +# that go after will NOT be reflected in the trace if its config contain include_filter with any +# rule (even such trivial as: include_filter = "%"). +# +# Initial discuss: july-2019, subj: "... fbtrace returned error on call trace_dsql_execute" (mailbox: pz@ibase.ru). +# Letter with example how to reproduce: 16.07.19 22:08. +# Finally this bug was fixed 26.03.2020: +# https://github.com/FirebirdSQL/firebird/commit/70ed61cba88ad70bd868079016cde3b338073db8 +# ::: NB ::: +# Problem was found only in FB 3.0; 4.x works OK because of new regexp mechanism in it. +# +# Test uses SQL script with two correct statements ('point-1' and 'point-2') and invalid character literal between them. +# This SQL can not be prepared in fbtest because of strict checks related to characters matching to unicode charsets. +# Then we prepare tempopary BATCH file which does: +# chcp 1251 +# run ISQL with applying this script. +# After this, we launch trace with config that contains trivial include_filter and run this temp batch. +# Expected result: trace must contain lines with ALL THREE executed statements. +# +# Confirmed bug on 3.0.6.33273: only 'point-1' appears in the trace. No further statements at all. +# All fine on 3.0.6.33276: all three statements can be seen in the trace. +# +# tracker_id: CORE-5470 +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import time +# from fdb import services +# from subprocess import Popen +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# #-------------------------------------------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# +# #-------------------------------------------- +# +# # Obtain engine version: +# engine = str(db_conn.engine_version) # convert to text because 'float' object has no attribute 'startswith' +# db_conn.close() +# +# # NB, 06.12.2016: as of fdb 1.6.1 one need to EXPLICITLY specify user+password pair when doing connect +# # via to FB services API by services.connect() - see FB tracker, PYFB-69 +# # ("Can not connect to FB services if set ISC_USER & ISC_PASSWORD by os.environ[ ... ]") +# +# fb_home = services.connect(host='localhost', user= user_name, password= user_password).get_home_directory() +# # fb_home = services.connect(host='localhost').get_home_directory() +# +# fb_isql = fb_home+'isql' +# sql_chk = os.path.join(context['files_location'],'core_5470_addi.sql') +# tmp_log = os.path.join(context['temp_directory'],'core_5470_addi.log') +# +# txt = '''@echo off +# chcp 1251>nul +# %(fb_isql)s %(dsn)s -ch win1251 -user %(user_name)s -pas %(user_password)s -i %(sql_chk)s 1>%(tmp_log)s 2>&1 +# ''' % dict(globals(), **locals()) +# +# f_tmp_bat=open( os.path.join(context['temp_directory'],'tmp_run_5470.bat'), 'w', buffering = 0) +# f_tmp_bat.write(txt) +# f_tmp_bat.close() +# +# #-------------------------------------------------- +# +# txt = '''# Generated auto, do not edit! +# database=%[\\\\\\\\/]security?.fdb +# { +# enabled = false +# } +# database=%[\\\\\\\\/]bugs.core_5470_addi.fdb +# { +# enabled = true +# time_threshold = 0 +# +# log_initfini = false +# log_warnings = false +# log_errors = true +# +# log_statement_finish = true +# +# include_filter = "%" +# +# } +# ''' +# +# f_trc_cfg=open( os.path.join(context['temp_directory'],'tmp_trace_5470.cfg'), 'w', buffering = 0) +# f_trc_cfg.write(txt) +# f_trc_cfg.close() +# +# # ############################################################## +# # S T A R T T R A C E i n S E P A R A T E P R O C E S S +# # ############################################################## +# +# f_trc_log=open( os.path.join(context['temp_directory'],'tmp_trace_5470.log'), "w", buffering = 0) +# f_trc_err=open( os.path.join(context['temp_directory'],'tmp_trace_5470.err'), "w", buffering = 0) +# +# p_trace = Popen( [ fb_home+'fbsvcmgr', 'localhost:service_mgr', 'action_trace_start' , 'trc_cfg', f_trc_cfg.name],stdout=f_trc_log,stderr=f_trc_err) +# +# time.sleep(1) +# +# # #################################################### +# # G E T A C T I V E T R A C E S E S S I O N I D +# # #################################################### +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# +# f_trc_lst = open( os.path.join(context['temp_directory'],'tmp_trace_5470.lst'), 'w', buffering = 0) +# subprocess.call([fb_home+'fbsvcmgr', 'localhost:service_mgr', 'action_trace_list'], stdout=f_trc_lst) +# f_trc_lst.close() +# +# # !!! DO NOT REMOVE THIS LINE !!! +# time.sleep(1) +# +# trcssn=0 +# with open( f_trc_lst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# f.close() +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# +# #------------------------------------------------ +# # Run auxiliary batch: +# subprocess.call( [ f_tmp_bat.name ] ) +# #------------------------------------------------ +# +# # Let trace log to be entirely written on disk: +# time.sleep(1) +# +# # #################################################### +# # S E N D R E Q U E S T T R A C E T O S T O P +# # #################################################### +# if trcssn>0: +# fn_nul = open(os.devnull, 'w') +# subprocess.call([fb_home+'fbsvcmgr', 'localhost:service_mgr', 'action_trace_stop','trc_id', trcssn], stdout=fn_nul) +# fn_nul.close() +# # DO NOT REMOVE THIS LINE: +# time.sleep(2) +# +# p_trace.terminate() +# f_trc_log.close() +# f_trc_err.close() +# +# time.sleep(1) +# +# with open(f_trc_log.name, 'r') as f: +# for line in f: +# if line.startswith( "select 'point-" ): +# print(line) +# +# cleanup( [ i.name for i in ( f_trc_log, f_trc_err, f_trc_cfg, f_trc_lst, f_tmp_bat ) ] + [tmp_log,] ) # DO NOT ADD 'sql_chk' here! +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + select 'point-1' from rdb$database + select 'point-2' from rdb$database + """ + +@pytest.mark.version('>=3.0.6') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_5470_addi_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5475.py b/tests/bugs/test_core_5475.py new file mode 100644 index 00000000..065f38ca --- /dev/null +++ b/tests/bugs/test_core_5475.py @@ -0,0 +1,442 @@ +#coding:utf-8 +# +# id: bugs.core_5475 +# title: Provide ability to filter out info and warnings from trace log +# decription: +# For FB 2.5 we verify that one may to suppress messages like TRACE_INIT/FINI ("log_initfini false") +# Also, by default no more warnings should appear in the trace. +# +# For FB 3.0 and above we check that trace log contains only those gdscodes which we expect. +# Also, trace should NOT contain gdscodes which we explicitly prohibit or which we do not expect +# because not empty list in 'include_gds_codes' parameter. +# Also, we verify that no more TRACE_INIT / TRACE_FINI in trace because log_initfini=false. +# +# Checked on 2.5.7.27048, 3.0.2.32685, 4.0.0.531 -- all fine. +# +# 01.04.2020. Up to 4.0.0.1820 (~29.03.2020, including) cursor.execute() with SELECT +# statement did NOT actually fetch record until we explicitly do futher actions, e.g: +# for r in cur: +# print(r[0]) +# For this reason code which did only cur.execute('SELECT ...' ) +# was useless: it did not lead to any error and trace log did NOT contain any "undesired" gdscodes +# like 335544914 or 335545033. It was exactly because of THIS rather than "good behaviour" of filter +# that we specify in the trace config (i.e. include_gdscodes or exclude_gdscodes). +# It was decided to replace selectable cursor with DML and use value that will violates limits +# of Firebird implementation (timestamp field, assign value = '01.01.0000' - it can not be used in FB). +# +# See letter from Vlad, 31-mar-2020 14:29. +# +# Checked after refactoring (01.04.2020) on: +# 4.0.0.1850 SS: 9.750s. +# 4.0.0.1820 SC: 9.703s. +# 4.0.0.1848 CS: 10.735s. +# 3.0.6.33273 SS: 8.235s. +# 3.0.6.33240 SC: 8.016s. +# 3.0.6.33247 CS: 10.563s. +# +# tracker_id: CORE-5475 +# min_versions: ['2.5.7'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table test( + id int generated by default as identity constraint test_pk primary key using index test_id, + tiny_num smallint, + dts timestamp, + s varchar(4) -- added 01.04.2020 + ); + commit; + insert into test(id, tiny_num, dts) values(1,32767, null); + commit; + """ + +db_1 = db_factory(sql_dialect=1, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import time +# from fdb import services +# from subprocess import Popen +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # Obtain engine version: +# engine = str(db_conn.engine_version) # convert to text because 'float' object has no attribute 'startswith' +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# txt = '''# Generated auto, do not edit! +# database=%[\\\\\\\\/]security?.fdb +# { +# enabled = false +# } +# database=%[\\\\\\\\/]bugs.core_5475.fdb +# { +# enabled = true +# log_connections = true +# time_threshold = 0 +# log_initfini = false +# log_errors = true +# log_warnings = true +# +# log_statement_prepare = true +# log_statement_finish = true +# +# # 1. We EXPLICITLY ALLOW to be logged (and EXPECT because of current test scenario): +# # 1.1) any kind of "arithmetic exc, num ovf, or string trunc" +# # 1.2) PK/UK violation +# # 1.3) (warning) 336068855 : Warning: ALL on ALL is not granted to <...>. +# include_gds_codes = arith_except,unique_key_violation,336068855 +# +# # We EXPLICITLY PREVENT from logging: +# # 2.1 "FP divide by zero", +# # 2.2 "Integer divide by zero" and +# # 2.3 (warning) "DATE data type is now called TIMESTAMP" (warning) +# exclude_gds_codes = 335544772,335544778,335544808 +# +# # We do not prevent (explicitly) but DO NOT expect see in trace following errors: +# # 1) 335544347 : validation error for column ..., value "*** null ***" +# # 2) 335544913 : value exceeds the range for valid timestamps +# +# } +# ''' +# +# f_trc_cfg=open( os.path.join(context['temp_directory'],'tmp_trace_5475.cfg'), 'w') +# f_trc_cfg.write(txt) +# flush_and_close( f_trc_cfg ) +# +# # ############################################################## +# # S T A R T T R A C E i n S E P A R A T E P R O C E S S +# # ############################################################## +# +# f_trc_log=open( os.path.join(context['temp_directory'],'tmp_trace_5475.log'), "w") +# f_trc_err=open( os.path.join(context['temp_directory'],'tmp_trace_5475.err'), "w") +# +# p_trace = Popen( [ context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_start' , 'trc_cfg', f_trc_cfg.name],stdout=f_trc_log,stderr=f_trc_err) +# +# time.sleep(1) +# +# # #################################################### +# # G E T A C T I V E T R A C E S E S S I O N I D +# # #################################################### +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# +# f_trc_lst = open( os.path.join(context['temp_directory'],'tmp_trace_5475.lst'), 'w') +# subprocess.call([context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_list'], stdout=f_trc_lst) +# flush_and_close( f_trc_lst ) +# +# trcssn=0 +# with open( f_trc_lst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# +# +# con1 = fdb.connect(dsn=dsn) +# cur1 = con1.cursor() +# try: +# # 335544321 : arithmetic exception, numeric overflow, or string truncation +# # NOTE. dialect_1: 335544772 : Floating-point divide by zero. The code attempted to divide a floating-point value by zero. +# # NOTE. dialect_3: 335544778 : Integer divide by zero. The code attempted to divide an integer value by an integer divisor of zero. +# cur1.execute('insert into test( tiny_num ) values( 1/0 )' ) # -------- should raise zero divide +# except Exception as e: +# print(e[0]) +# con1.close() +# +# +# con2 = fdb.connect(dsn=dsn) +# cur2 = con2.cursor() +# try: +# # Should raise +# # 335544665 : violation of PRIMARY or UNIQUE KEY constraint "INTEG_10" on table "TEST" +# # 335545072 : Problematic key value is ("ID" = 1) +# cur2.execute('insert into test(id,tiny_num) values(?, ?)', (1, 1) ) +# except Exception as e: +# print(e[0]) +# con2.close() +# +# +# con3 = fdb.connect(dsn=dsn) +# cur3 = con3.cursor() +# try: +# # Should raise +# # 335544321 : arithmetic exception, numeric overflow, or string truncation +# # 335544916 : numeric value is out of range +# # (because we attempt to increase smallint value from 32767 for 1) +# cur3.execute('update test set tiny_num = tiny_num + 1') +# except Exception as e: +# print(e[0]) +# con3.close() +# +# +# con4 = fdb.connect(dsn=dsn) +# cur4 = con4.cursor() +# try: +# ############################################################# +# ### NB ### CHANGED 01.04.2020 BECAUSE OF NEW BEHAVIOUR IN 4.0 +# ############################################################# +# +# # Up to 4.0.0.1820 cursor.execute() with SELECT statement did NOT fetch record until +# # until we explicitly do futher actions, i.e.: for r in cur4: / print(r[0]) etc +# # Trace log did NOT contain any of 335544914 / 335545033 exactly because of ***THIS*** +# # rather than include_gds_codes filter in its config! +# # See letter from Vlad, 31-mar-2020 14:29. +# ########################################## +# # !! USELESS !! DO NOT USE IT >>> cur4.execute( "select cast('qwerty' as varchar(5)) from rdb$database" ) +# +# # Decided to try to append into table value with timestamp that is out of avaliable range: 01.01.0000. +# # This action raises gdscode = 335544913 which does not belong NEITHER to include* not to exclude* lists. +# # For this reason such gdscode should NOT appear in the trace - it will bechecked at the end of this test. +# cur4.execute( "insert into test( dts ) values( '01.01.0000' )" ) +# +# except Exception as e: +# print(e[0]) +# con4.close() +# +# +# con5 = fdb.connect(dsn=dsn, sql_dialect=1) +# cur5 = con5.cursor() +# try: +# # Leads to WARNING in trace: +# # 335544807 : SQL warning code = 301 +# # 335544808 : DATE data type is now called TIMESTAMP +# cur5.execute( "update test set dts = cast('now' as date)" ) +# except Exception as e: +# print(e[0]) +# con5.close() +# +# +# con6 = fdb.connect(dsn=dsn) +# cur6 = con6.cursor() +# try: +# # Should raise +# # 335544347 : validation error for column ..., value "*** null ***" +# # NB: this gdscode was NOT specified neither in include_gds nor in exclude_gds lists. +# # We do attempt to violate not null and check what does appear in the trace log. +# cur6.execute('insert into test(id) values(null)') +# except Exception as e: +# print(e[0]) +# con6.close() +# +# +# con7 = fdb.connect(dsn=dsn) +# # Should raise: +# # (warning) 336068855 : Warning: ALL on ALL is not granted to <...>. +# con7.execute_immediate('revoke all on all from tmp$c5475') +# con7.close() +# +# +# # 1. We ALLOW to be logged: +# # 1.1) any kind of "arithmetic exc, num ovf, or string trunc" +# # 1.2) PK/UK violation +# # 1.3) (warning) 336068855 : Warning: ALL on ALL is not granted to <...>. +# #include_gds_codes = arith_except,no_dup,336068855 +# +# # We PREVENT from logging: +# # 2.1 "FP divide by zero", +# # 2.2 "Integer divide by zero" and +# # 2.3 (warning) "DATE data type is now called TIMESTAMP" (warning) +# #exclude_gds_codes = 335544772,335544778,335544808 +# +# +# # Let trace log to be entirely written on disk: +# time.sleep(1) +# +# +# # #################################################### +# # S E N D R E Q U E S T T R A C E T O S T O P +# # #################################################### +# if trcssn>0: +# fn_nul = open(os.devnull, 'w') +# subprocess.call([context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_stop','trc_id', trcssn], stdout=fn_nul) +# fn_nul.close() +# # DO NOT REMOVE THIS LINE: +# time.sleep(1) +# +# p_trace.terminate() +# flush_and_close( f_trc_log ) +# flush_and_close( f_trc_err ) +# +# # Following file should be EMPTY: +# ################ +# +# f_list=(f_trc_err,) +# for i in range(len(f_list)): +# f_name=f_list[i].name +# with open( f_name,'r') as f: +# for line in f: +# if line.split(): +# print("Unexpected STDERR, file "+f_name+": "+line) +# +# +# # 1. We ALLOW to be logged (and EXPECT because of current test scenario): +# # 1.1) "arithmetic exc" caused by numeric overflow // 335544321, 335544916 +# # 1.2) PK/UK violation // 335544665 +# # 1.3) ALL on ALL is not granted to <...> // 336068855 - warning +# #include_gds_codes = arith_except,unique_key_violation,336068855 +# +# # We PREVENT from logging: +# # 2.1 "FP divide by zero" // 335544772 - occurs when dialect=1 +# # 2.2 "Integer divide by zero" // 335544778 - occurs when dialect=3 +# # 2.3 (warning) "DATE data type is now called TIMESTAMP" // 335544808 - warning +# #exclude_gds_codes = 335544772,335544778,335544808 +# +# # we do not prevent but do not expect to be logged: +# # 335544347 : validation error for column ..., value "*** null ***" +# # 335544914 : string right truncation (plus 335545033 : expected length 5, actual 6) +# +# +# # Following gdscodes MUST BE found in the trace log: +# # ~~~~~~~~~~~~~~~~~~~~~~~~~~ +# missed_expected_token = 'ERROR: missed expected token which MUST be in the trace log' +# expected_set = { +# '335544321' : missed_expected_token +# ,'335544916' : missed_expected_token +# ,'335544665' : missed_expected_token +# ,'336068855' : missed_expected_token +# } +# +# # Following gdscodes must NOT present on trace log because we explicitly PROHIBIT them: +# # ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# not_found_explicitly_prohibited = 'SUCCESS: no tokens which are explicitly prohibited in exclude_gds_codes list' +# prohibit_set = { +# '335544772' : not_found_explicitly_prohibited +# ,'335544778' : not_found_explicitly_prohibited +# ,'335544808' : not_found_explicitly_prohibited +# ,'TRACE_INIT' : not_found_explicitly_prohibited +# ,'TRACE_FINI' : not_found_explicitly_prohibited +# } +# +# # Following gdscodes are UNEXPECTED, i.e. we did not prohibit them explicitly +# # but none of them are in include_gds_codes ==> they should NOT appear in the trace: +# not_found_implicitly_prohibited = 'SUCCESS: no tokens which are not in include_gds_codes list.' +# unexpect_set = { +# '335544347' : not_found_implicitly_prohibited +# ,'335544913' : not_found_implicitly_prohibited +# } +# +# +# with open( f_trc_log.name,'r') as f: +# for line in f: +# if line.split(): +# starting_word=line.split()[0] +# if starting_word in expected_set: +# expected_set[ starting_word ] = 'SUCCESS: found expected token which MUST be in the trace log.' +# elif starting_word in prohibit_set: +# prohibit_set[ starting_word ] = 'ERROR: found token which is EXPLICITLY prohibited in exclude_gds_codes list.' +# elif starting_word in unexpect_set: +# unexpect_set[ starting_word ] = 'ERROR: found token NOT from include_gdscodes list (implicitly prohibited).' +# +# for k,v in sorted(expected_set.items()): +# print('expected_token:', k, '; trace search result:', v) +# +# for k,v in sorted(prohibit_set.items()): +# print('prohibit_token:', k, '; trace search result:', v) +# +# for k,v in sorted(unexpect_set.items()): +# print('unexpect_token:', k, '; trace search result:', v) +# +# +# # CLEANUP +# ######### +# time.sleep(1) +# cleanup( (f_trc_cfg, f_trc_lst, f_trc_log, f_trc_err) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Error while executing SQL statement: + - SQLCODE: -802 + - 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. + + Error while executing SQL statement: + - SQLCODE: -803 + - violation of PRIMARY or UNIQUE KEY constraint "TEST_PK" on table "TEST" + - Problematic key value is ("ID" = 1) + + Error while executing SQL statement: + - SQLCODE: -802 + - arithmetic exception, numeric overflow, or string truncation + - numeric value is out of range + + Error while executing SQL statement: + - SQLCODE: -833 + - value exceeds the range for valid timestamps + + Error while executing SQL statement: + - SQLCODE: -625 + - validation error for column "TEST"."ID", value "*** null ***" + + expected_token: 335544321 ; trace search result: SUCCESS: found expected token which MUST be in the trace log. + expected_token: 335544665 ; trace search result: SUCCESS: found expected token which MUST be in the trace log. + expected_token: 335544916 ; trace search result: SUCCESS: found expected token which MUST be in the trace log. + expected_token: 336068855 ; trace search result: SUCCESS: found expected token which MUST be in the trace log. + prohibit_token: 335544772 ; trace search result: SUCCESS: no tokens which are explicitly prohibited in exclude_gds_codes list + prohibit_token: 335544778 ; trace search result: SUCCESS: no tokens which are explicitly prohibited in exclude_gds_codes list + prohibit_token: 335544808 ; trace search result: SUCCESS: no tokens which are explicitly prohibited in exclude_gds_codes list + prohibit_token: TRACE_FINI ; trace search result: SUCCESS: no tokens which are explicitly prohibited in exclude_gds_codes list + prohibit_token: TRACE_INIT ; trace search result: SUCCESS: no tokens which are explicitly prohibited in exclude_gds_codes list + unexpect_token: 335544347 ; trace search result: SUCCESS: no tokens which are not in include_gds_codes list. + unexpect_token: 335544913 ; trace search result: SUCCESS: no tokens which are not in include_gds_codes list. + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_5475_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5477.py b/tests/bugs/test_core_5477.py new file mode 100644 index 00000000..acdfaa60 --- /dev/null +++ b/tests/bugs/test_core_5477.py @@ -0,0 +1,196 @@ +#coding:utf-8 +# +# id: bugs.core_5477 +# title: Trace duplicates asci_char(13) in its output (Windows only) +# decription: +# We launch trace and create connect to DB with statement line 'select 1 from rdb$database'. +# Trace log should contain several lines related to connection, transaction and statement. +# These lines should be separated by standard Windows PAIR of characters: CR + NL. +# Count of these chars should be equal (ideally; actually 1st line in trace has EOL = single NL +# rather than pair CR+NL). +# We then open trace log as binary file and read all its content into dict of Counter type, +# thus we can get number of occurences for each character, including CR and NL. +# Finally, we compare number of occurences of CR and NL. Difference has to be no more than 1. +# +# Checked on 2.5.7.27048, 3.0.2.32685, 4.0.0.531 - all fine. +# +# tracker_id: CORE-5477 +# min_versions: ['2.5.7'] +# versions: 2.5.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import time +# from fdb import services +# from subprocess import Popen +# from collections import Counter +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # Obtain engine version: +# engine = str(db_conn.engine_version) # convert to text because 'float' object has no attribute 'startswith' +# +# db_conn.close() +# +# # NB, 06.12.2016: as of fdb 1.6.1 one need to EXPLICITLY specify user+password pair when doing connect +# # via to FB services API by services.connect() - see FB tracker, PYFB-69 +# # ("Can not connect to FB services if set ISC_USER & ISC_PASSWORD by os.environ[ ... ]") +# +# fb_home = services.connect(host='localhost', user= user_name, password= user_password).get_home_directory() +# # fb_home = services.connect(host='localhost').get_home_directory() +# +# if engine.startswith('2.5'): +# fb_home = fb_home + 'bin'+os.sep +# txt = '''# Generated auto, do not edit! +# +# enabled false +# +# +# +# enabled true +# time_threshold 0 +# log_initfini false +# log_connections true +# log_transactions true +# log_statement_finish = true +# +# ''' +# else: +# txt = '''# Generated auto, do not edit! +# database=%[\\\\\\\\/]security?.fdb +# { +# enabled = false +# } +# database=%[\\\\\\\\/]bugs.core_5477.fdb +# { +# enabled = true +# time_threshold = 0 +# log_initfini = false +# log_connections = true +# log_transactions = true +# log_statement_finish = true +# } +# ''' +# f_trc_cfg=open( os.path.join(context['temp_directory'],'tmp_trc_5477.cfg'), 'w') +# f_trc_cfg.write(txt) +# f_trc_cfg.close() +# +# # ############################################################## +# # S T A R T T R A C E i n S E P A R A T E P R O C E S S +# # ############################################################## +# +# f_trc_log=open( os.path.join(context['temp_directory'],'tmp_trc_5477.log'), "w") +# f_trc_err=open( os.path.join(context['temp_directory'],'tmp_trc_5477.err'), "w") +# +# p_trace = Popen( [ fb_home+'fbsvcmgr', 'localhost:service_mgr', 'action_trace_start' , 'trc_cfg', f_trc_cfg.name],stdout=f_trc_log,stderr=f_trc_err) +# +# time.sleep(1) +# +# # #################################################### +# # G E T A C T I V E T R A C E S E S S I O N I D +# # #################################################### +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# +# f_trc_lst = open( os.path.join(context['temp_directory'],'tmp_trace_5477.lst'), 'w') +# subprocess.call([fb_home+'fbsvcmgr', 'localhost:service_mgr', 'action_trace_list'], stdout=f_trc_lst) +# f_trc_lst.close() +# +# # !!! DO NOT REMOVE THIS LINE !!! +# time.sleep(1) +# +# trcssn=0 +# with open( f_trc_lst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# f.close() +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# +# con1 = fdb.connect(dsn=dsn) +# cur1=con1.cursor() +# cur1.execute('select 1 from rdb$database') +# for r in cur1: +# pass +# con1.close() +# +# # Let trace log to be entirely written on disk: +# time.sleep(2) +# +# # #################################################### +# # S E N D R E Q U E S T T R A C E T O S T O P +# # #################################################### +# if trcssn>0: +# fn_nul = open(os.devnull, 'w') +# subprocess.call([fb_home+'fbsvcmgr', 'localhost:service_mgr', 'action_trace_stop','trc_id', trcssn], stdout=fn_nul) +# fn_nul.close() +# # DO NOT REMOVE THIS LINE: +# time.sleep(2) +# +# p_trace.terminate() +# f_trc_log.close() +# f_trc_err.close() +# +# # Following file should be EMPTY: +# ################ +# +# f_list=(f_trc_err,) +# for i in range(len(f_list)): +# f_name=f_list[i].name +# if os.path.getsize(f_name) > 0: +# with open( f_name,'r') as f: +# for line in f: +# print("Unexpected STDERR, file "+f_name+": "+line) +# +# letters_dict={} +# with open( f_trc_log.name,'rb') as f: +# letters_dict = Counter(f.read()) +# +# nl_count = letters_dict['\\n'] +# cr_count = letters_dict['\\r'] +# +# print( 'EXPECTED.' if nl_count >= 1 and abs(nl_count - cr_count) <= 1 else 'FAIL: empty log or NL count differ than CR.' ) +# +# # CLEANUP +# ######### +# f_list=(f_trc_cfg, f_trc_lst, f_trc_log, f_trc_err) +# for i in range(len(f_list)): +# if os.path.isfile(f_list[i].name): +# os.remove(f_list[i].name) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + EXPECTED. + """ + +@pytest.mark.version('>=2.5.7') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_5477_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5480.py b/tests/bugs/test_core_5480.py new file mode 100644 index 00000000..106248b1 --- /dev/null +++ b/tests/bugs/test_core_5480.py @@ -0,0 +1,72 @@ +#coding:utf-8 +# +# id: bugs.core_5480 +# title: SUBSTRING startposition smaller than 1 should be allowed +# decription: +# Test is based on ticket samples, plus similar checks for non-ascii strings. +# Checked on WI-T4.0.0.546 with UTF8 charset. Works fine. +# +# tracker_id: CORE-5480 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + -- ASCII string tests: + select '|' || substring('abcdef' from 0) || '|' a01 from rdb$database; -- Expected result: 'abcdef' + select '|' || substring('abcdef' from 0 for 2) || '|' a02 from rdb$database; --Expected result: 'a' (and NOT 'ab') + select '|' || substring('abcdef' from -5 for 2) || '|' a03 from rdb$database; --Expected result: '' + select '|' || substring('abcdef' from -1 for 3) || '|' a04 from rdb$database; --Expected result: 'a' + select '|' || substring('abcdef' from -2 for 5) || '|' a05 from rdb$database; --Expected result: 'ab' + select '|' || substring('abcdef' from -2147483645 for 2147483647) || '|' a06 from rdb$database; -- added case with big values for arguments + + -- multi-byte string tests: + -- Euro sign (requires three bytes for encoding) concatenated + -- with letters from Danish, German & Iceland alphabets: + select '|' || substring('€åßðéæø' from 0) || '|' n01 from rdb$database; + select '|' || substring('€åßðéæø' from 0 for 2) || '|' n02 from rdb$database; + select '|' || substring('€åßðéæø' from -5 for 2) || '|' n03 from rdb$database; + select '|' || substring('€åßðéæø' from -1 for 3) || '|' n04 from rdb$database; + select '|' || substring('€åßðéæø' from -2 for 5) || '|' n05 from rdb$database; + select '|' || substring('€åßðéæø' from -2147483645 for 2147483647) || '|' n06 from rdb$database; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A01 |abcdef| + A02 |a| + A03 || + A04 |a| + A05 |ab| + A06 |a| + + N01 |€åßðéæø| + N02 |€| + N03 || + N04 |€| + N05 |€å| + N06 |€| + """ + +@pytest.mark.version('>=4.0') +def test_core_5480_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5481.py b/tests/bugs/test_core_5481.py new file mode 100644 index 00000000..c6738da0 --- /dev/null +++ b/tests/bugs/test_core_5481.py @@ -0,0 +1,83 @@ +#coding:utf-8 +# +# id: bugs.core_5481 +# title: Available indices are not used in some cases if ORDER BY expression is a filtered one +# decription: +# Confirmed bug on WI-V3.0.1.32609: +# 1. Plan when FK did present was ineffective: PLAN (V_TEST B ORDER BALANCES_BALANCEDATE_DESC) +# 2. Effective plan was in use only after dropping FK. +# Checked on: 3.0.5.33084, 4.0.0.1340 - works fine. +# +# tracker_id: CORE-5481 +# min_versions: ['3.0.4'] +# versions: 3.0.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate view v_test as select 1 x from rdb$database; + commit; + recreate table balances + ( + balanceid bigint not null, + orgaccountid bigint not null, + balancedate date not null + ); + + recreate table org_accounts + ( + orgaccountid bigint not null primary key + ); + + alter table balances add constraint pk_balances primary key (balanceid); + alter table balances add constraint fk_balances_orgaccounts foreign key (orgaccountid) references org_accounts (orgaccountid); + alter table balances add constraint balances_balancedate_orgaccount unique (orgaccountid, balancedate); + + create descending index balances_balancedate_desc on balances (balancedate); + + recreate view v_test as + select b.* + from balances b + where + orgaccountid=18 and + balancedate<='01.01.2017' + order by balancedate desc + rows 1 + ; + commit; + + set plan on; + select * from v_test; + commit; + + ALTER TABLE BALANCES DROP CONSTRAINT BALANCES_BALANCEDATE_ORGACCOUNT; + commit; + + select * from v_test; -- plan here should remains the same! + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (V_TEST B ORDER BALANCES_BALANCEDATE_DESC INDEX (FK_BALANCES_ORGACCOUNTS)) + PLAN (V_TEST B ORDER BALANCES_BALANCEDATE_DESC INDEX (FK_BALANCES_ORGACCOUNTS)) + """ + +@pytest.mark.version('>=3.0.4') +def test_core_5481_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5488.py b/tests/bugs/test_core_5488.py new file mode 100644 index 00000000..2cac405c --- /dev/null +++ b/tests/bugs/test_core_5488.py @@ -0,0 +1,213 @@ +#coding:utf-8 +# +# id: bugs.core_5488 +# title: Timeout for running SQL statement (SET STATEMENT TIMEOUT ) +# decription: +# ::: NB::: +# +# This is _initial_ test with trivial checks: +# 1) it hould be possible to cancel 'heavy query' executed on ; +# 2) the same, but passed via ES/EDS, should also be cancelled; +# Elapsed time should be equal to statement timeout with precise -0.1% / +2% +# (minus 0.1% - because PC clock can be imprecise!) +# +# More complex cases will be implemented later. +# +# Explanations were given by hvlad, see letters from him of 05-mar-2017. +# Checked on WI-T4.0.0.546. +# +# 28.10.2019: increased spread between low and high limit for ratio elapsed_ms / sttm_timeout. +# Checked on: +# 4.0.0.1635 SS: 3.672s. +# 4.0.0.1633 CS: 3.983s. +# +# 01.04.2020: changed logic in execute block (see "--- 2 ===') after letter from Vlad, 31.03.2020 13:15. +# We must NOT suppose that engine could always in time do SUSPEND after ES/EDS will be interrupted. +# For this reason all results that we get inside EB must be stored as context variables, WITHOUT using +# output arguments which are returned by SUSPEND (see variables: 'returned_cnt', 'gds_after_eds'). +# Engine restarts mechanism was changed 30-03-2020, see: +# https://github.com/FirebirdSQL/firebird/commit/059694b0b4f3a6f92f852b0a7be6358d708ee5e0 +# et al. +# +# Checked 01.04.2020 on: +# 4.0.0.1850 SS: 3.686s. +# 4.0.0.1848 CS: 4.070s. +# 4.0.0.1767 SC: 3.821s. +# +# tracker_id: CORE-5488 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + -- #################################### + set statement timeout 1234 millisecond; + -- #################################### + + + ---------------------------------------- 1 ---------------------------------------------- + + set term ^; + execute block as + begin + rdb$set_context('USER_SESSION','EB_FINAL_DTS', null); + rdb$set_context('USER_SESSION','MIN_RATIO', 0.95); -- BEFORE 28.10.2019: 0.999 + rdb$set_context('USER_SESSION','MAX_RATIO', 1.05); -- BEFORE 28.10.2019: 1.02 + rdb$set_context('USER_SESSION','START_DTS', cast('now' as timestamp)); + end^ + set term ;^ + + select count(*) from rdb$types,rdb$types,rdb$types; + + set term ^; + execute block as + begin + rdb$set_context('USER_SESSION','EB_FINAL_DTS', cast('now' as timestamp)); + end^ + set term ;^ + + + select iif( 1.00 * elapsed_ms / sttm_timeout between low_bound and high_bound, + 'Acceptable', + 'WRONG: sttm_timeout = ' || sttm_timeout + || ', elapsed_ms = ' || elapsed_ms + || ', ratio elapsed_ms / sttm_timeout = '|| (1.00 * elapsed_ms / sttm_timeout) + ||' must belong to [' || low_bound || ' ... '|| high_bound || ']' + ) as result_1 + from ( + select + cast(rdb$get_context('SYSTEM','STATEMENT_TIMEOUT') as int) as sttm_timeout + ,datediff( millisecond + from cast( rdb$get_context('USER_SESSION','START_DTS') as timestamp) + to cast(rdb$get_context('USER_SESSION','EB_FINAL_DTS') as timestamp) + ) elapsed_ms + ,cast( rdb$get_context('USER_SESSION','MIN_RATIO') as double precision) as low_bound -- ### THRESHOLD, LOW ### + ,cast( rdb$get_context('USER_SESSION','MAX_RATIO') as double precision) as high_bound -- ### THRESHOLD, HIGH ### + from rdb$database + ); + + ---------------------------------------- 2 ---------------------------------------------- + + set term ^; + execute block as + begin + rdb$set_context('USER_SESSION','EB_FINAL_DTS', null); + rdb$set_context('USER_SESSION','START_DTS', cast('now' as timestamp)); + end + ^ + + execute block as + declare p varchar(20) = 'masterkey'; + declare returned_cnt int = null; + declare gds_after_eds int = null; + begin + + begin + execute statement 'select count(*) from rdb$types,rdb$types,rdb$types' + on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') + as user current_user password :p role right( uuid_to_char(gen_uuid()), 12 ) + into returned_cnt; + when any do + begin + -- Control MUST come here after statement will be interruptec (cancelled) in EDS. + -- gdscode should be = 335544926. + gds_after_eds = gdscode; + rdb$set_context('USER_SESSION','GDS_IN_WHEN_ANY_BLOCK', gds_after_eds); + rdb$set_context('USER_SESSION','TIMESTAMP_IN_WHEN_ANY_BLOCK', cast('now' as timestamp)); + end + end + if (gds_after_eds is null) then + begin + -- Normally we should NOT pass here, thus following context variables must remain NULL: + rdb$set_context('USER_SESSION','EB_FINAL_DTS', timestamp '01.01.2000 00:00:01' ); + rdb$set_context('USER_SESSION','EB_EDS_CNT', -1); + end + + -- control MUST come here, but: 'returned_cnt' will remain undefined, 'gds_after_eds' will be 335544926. + -- disabled 01.04.2020, see letter from hvlad 31.03.2020 -- suspend; + + end + ^ + set term ;^ + + ------------------------------------- verify results ------------------------------------ + + select iif( 1.00 * x.elapsed_ms / x.sttm_timeout between x.low_bound and x.high_bound, + 'Acceptable', + 'WRONG: sttm_timeout = ' || sttm_timeout + || ', elapsed_ms = ' || elapsed_ms + || ', ratio elapsed_ms / sttm_timeout = '|| (1.00 * elapsed_ms / sttm_timeout) + ||' must belong to [' || low_bound || ' ... '|| high_bound || ']' + ) as result_2 + ,x.gds_in_when_any_block -- expected: 335544926, which means that ES/EDS was really interrupted + ,iif( x.end_of_eb_cnt is null, 'EXPECTED, ', 'UNEXPECTED: ' || x.end_of_eb_cnt ) as end_of_eb_cnt -- expected: null which means that GDSCODE in when-any block had not-null value + from ( + select + cast(rdb$get_context('SYSTEM','STATEMENT_TIMEOUT') as int) as sttm_timeout + ,datediff( millisecond + from cast( rdb$get_context('USER_SESSION','START_DTS') as timestamp) + to cast(rdb$get_context('USER_SESSION','TIMESTAMP_IN_WHEN_ANY_BLOCK') as timestamp) + ) elapsed_ms + ,rdb$get_context('USER_SESSION','GDS_IN_WHEN_ANY_BLOCK') as gds_in_when_any_block -- expected: 335544926 + ,rdb$get_context('USER_SESSION','EB_FINAL_DTS') end_of_eb_dts -- expected: NULL + ,rdb$get_context('USER_SESSION','EB_EDS_CNT') as end_of_eb_cnt -- expected: NULL + ,cast( rdb$get_context('USER_SESSION','MIN_RATIO') as double precision) as low_bound -- ### THRESHOLD, LOW ### + ,cast( rdb$get_context('USER_SESSION','MAX_RATIO') as double precision) as high_bound -- ### THRESHOLD, HIGH ### + from rdb$database + ) x; + + 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT_1 Acceptable + + RESULT_2 Acceptable + GDS_IN_WHEN_ANY_BLOCK 335544926 + END_OF_EB_CNT EXPECTED, + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = HY008 + operation was cancelled + -Attachment level timeout expired. + """ + +@pytest.mark.version('>=4.0') +def test_core_5488_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5488_session_idle.py b/tests/bugs/test_core_5488_session_idle.py new file mode 100644 index 00000000..fcd1698c --- /dev/null +++ b/tests/bugs/test_core_5488_session_idle.py @@ -0,0 +1,283 @@ +#coding:utf-8 +# +# id: bugs.core_5488_session_idle +# title: Timeout for IDLE connection (SET SESSION IDLE TIMEOUT ) +# decription: +# We create .sql script with +# 1) SET SESSION IDLE TIMEOUT with small delay N (in seconds); +# 2) two trivial statements that are separated by artificial delay with T > N. +# Both statements are trivial: select from rdb$database. +# +# This delay is done by isql 'SHELL' command and its form depens on OS: +# * shell ping 127.0.0.1 -- for Windows +# * shell sleep -- for Linux. +# +# Before .sql we launch trace with logging events for parsing them at final stage of test. +# +# When this .sql script is launched and falls into delay, session timeout must be triggered +# and second statement should raise exception. +# We redirect ISQL output to separate logs and expect that: +# * log of STDOUT contains all except result of 2nd statement (which must fail); +# * log of STDERR contains exception SQLSTATE = 08003 / connection shutdown / -Idle timeout expired +# +# Trace log should contain only following events: +# attach to DB, start Tx, first statement finish, rollback Tx and detach DB. +# +# ::: NB::: +# No events related to SECOND statement should be in the trace log. +# +# Checked on WI-4.0.0.550 -- works fine. +# +# tracker_id: CORE-5488 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('timeout .* second', 'timeout second'), ('.*After line [\\d]+.*', ''), ('.*shell.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import re +# import subprocess +# import time +# from fdb import services +# from subprocess import Popen +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# fb_home = services.connect(host='localhost', user= user_name, password= user_password).get_home_directory() +# +# fbv=db_conn.firebird_version # 'WI-...' ==> Windows; 'LI-' ==> Linux +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# # 2017-03-08T17:36:33.6870 (3720:00D22BD0) ATTACH_DATABASE | START_TRANSACTION | EXECUTE_STATEMENT_FINISH | ... +# trace_dts_pattern=re.compile('.*(ATTACH_DATABASE|START_TRANSACTION|EXECUTE_STATEMENT_FINISH|ROLLBACK_TRANSACTION|DETACH_DATABASE)') +# +# session_idle_timeout=1 +# shell_sleep_sec=session_idle_timeout + 2 +# if os.name == 'nt': +# shell_sleep_cmd = 'shell ping -n %d 127.0.0.1 > %s' % (shell_sleep_sec, os.devnull) +# else: +# shell_sleep_cmd = 'shell sleep %d > %s' % (shell_sleep_sec, os.devnull) +# +# sql=''' +# set list on; +# set bail on; +# set echo on; +# +# set session idle timeout %(session_idle_timeout)s second; +# +# select 1 as point_1 from rdb$database; +# %(shell_sleep_cmd)s; +# select 2 as point_2 from rdb$database; +# quit; +# ''' % locals() +# +# f_sql_cmd=open( os.path.join(context['temp_directory'],'tmp_c5488_run_session_idle.sql'), 'w') +# f_sql_cmd.write(sql) +# flush_and_close( f_sql_cmd ) +# +# txt = '''# Generated auto, do not edit! +# database=%[\\\\\\\\/]security?.fdb +# { +# enabled = false +# } +# database=%[\\\\\\\\/]bugs.core_5488_session_idle.fdb +# { +# enabled = true +# time_threshold = 0 +# log_initfini = false +# log_warnings = false +# log_errors = true +# log_connections = true +# log_transactions = true +# log_statement_finish = true +# } +# ''' +# +# f_trc_cfg=open( os.path.join(context['temp_directory'],'tmp_c5488_trc_session_idle.cfg'), 'w', buffering = 0) +# f_trc_cfg.write(txt) +# flush_and_close( f_trc_cfg ) +# +# # ############################################################## +# # S T A R T T R A C E i n S E P A R A T E P R O C E S S +# # ############################################################## +# +# f_trc_log=open( os.path.join(context['temp_directory'],'tmp_c5488_trc_session_idle.log'), "w", buffering = 0) +# f_trc_err=open( os.path.join(context['temp_directory'],'tmp_c5488_trc_session_idle.err'), "w", buffering = 0) +# +# p_trace = Popen( [ context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_start' , 'trc_cfg', f_trc_cfg.name], +# stdout=f_trc_log, +# stderr=f_trc_err +# ) +# +# time.sleep(1) +# +# f_isql_log=open( os.path.join(context['temp_directory'],'tmp_c5488_run_session_idle.log'), 'w', buffering = 0) +# f_isql_err=open( os.path.join(context['temp_directory'],'tmp_c5488_run_session_idle.err'), 'w', buffering = 0) +# +# ###################### +# # S T A R T I S Q L +# ###################### +# subprocess.call( [context['isql_path'], dsn, '-q', '-n', '-i', f_sql_cmd.name], +# stdout=f_isql_log, +# stderr=f_isql_err +# ) +# flush_and_close( f_isql_log ) +# flush_and_close( f_isql_err ) +# +# +# # #################################################### +# # G E T A C T I V E T R A C E S E S S I O N I D +# # #################################################### +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# +# f_trc_lst = open( os.path.join(context['temp_directory'],'tmp_c5488_trc_session_idle.lst'), 'w', buffering = 0) +# subprocess.call([context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_list'], stdout=f_trc_lst) +# flush_and_close( f_trc_lst ) +# +# trcssn=0 +# with open( f_trc_lst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# +# +# +# # #################################################### +# # S E N D R E Q U E S T T R A C E T O S T O P +# # #################################################### +# if trcssn>0: +# fn_nul = open(os.devnull, 'w') +# subprocess.call([context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_stop','trc_id', trcssn], stdout=fn_nul) +# fn_nul.close() +# # DO NOT REMOVE THIS LINE: +# time.sleep(1) +# +# p_trace.terminate() +# flush_and_close( f_trc_log ) +# flush_and_close( f_trc_err ) +# +# # Output of TRACE results: +# ########################## +# with open(f_trc_log.name, 'r') as f: +# for line in f: +# if trace_dts_pattern.match(line): +# print( ''.join( ( 'TRCLOG: ', line.strip().split()[-1] ) ) ) +# if 'set session idle' in line: +# # Since fixed CORE-6469 ("Provide ability to see in the trace log actions related to session management"), 20.01.2021: +# # https://github.com/FirebirdSQL/firebird/commit/a65f19f8b36384d59a55fbb6e0a43a6b84cf4978 +# print( ''.join( ( 'TRCLOG: ', line ) ) ) +# +# # Following file should be EMPTY: +# ################ +# f_list=(f_trc_err,) +# for i in range(len(f_list)): +# f_name=f_list[i].name +# if os.path.getsize(f_name) > 0: +# with open( f_name,'r') as f: +# for line in f: +# print("Unexpected TRCERR, file "+f_name+": "+line) +# +# +# # Output of ISQL results +# ################ +# with open(f_isql_log.name, 'r') as f: +# for line in f: +# if line.split(): +# print( ''.join( ( 'SQLLOG: ', line.strip() ) ) ) +# +# with open(f_isql_err.name, 'r') as f: +# for line in f: +# if line.split(): +# print( ''.join( ( 'SQLERR: ', line.strip() ) ) ) +# +# +# # CLEANUP +# ######### +# time.sleep(1) +# cleanup( (f_trc_cfg, f_trc_lst, f_trc_log, f_trc_err, f_sql_cmd, f_isql_log, f_isql_err ) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TRCLOG: ATTACH_DATABASE + TRCLOG: START_TRANSACTION + TRCLOG: EXECUTE_STATEMENT_FINISH + TRCLOG: set session idle timeout second + TRCLOG: EXECUTE_STATEMENT_FINISH + TRCLOG: ROLLBACK_TRANSACTION + TRCLOG: DETACH_DATABASE + + SQLLOG: set session idle timeout second; + SQLLOG: select 1 as point_1 from rdb$database; + SQLLOG: POINT_1 1 + SQLLOG: select 2 as point_2 from rdb$database; + + SQLERR: Statement failed, SQLSTATE = 08003 + SQLERR: connection shutdown + SQLERR: -Idle timeout expired. + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_5488_session_idle_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5489.py b/tests/bugs/test_core_5489.py new file mode 100644 index 00000000..df2187a7 --- /dev/null +++ b/tests/bugs/test_core_5489.py @@ -0,0 +1,319 @@ +#coding:utf-8 +# +# id: bugs.core_5489 +# title: Bad performance for NULLs filtering inside a navigational index scan +# decription: +# See prototype and explanations for this test in CORE_5435.fbt +# Confirmed improvement: +# +# 3.0.2.32643, 4.0.0.563: +# ********** +# PLAN (TEST ORDER TEST_F01_ID) +# 1 records fetched +# 1143 ms, 2375 read(s), 602376 fetch(es) ---------------- poor :( +# Table Natural Index +# **************************************************** +# TEST 300000 +# ********** +# +# +# 3.0.2.32708, 4.0.0.572: +# ********** +# PLAN (TEST ORDER TEST_F01_ID) +# 0 ms, 22 read(s), 63 fetch(es) --------------------------- cool :) +# Table Natural Index +# **************************************************** +# TEST 20 +# ********** +# +# +# tracker_id: CORE-5489 +# min_versions: ['3.0.2'] +# versions: 3.0.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=8192, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import time +# from fdb import services +# from subprocess import Popen +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # Obtain engine version: +# engine = str(db_conn.engine_version) # convert to text because 'float' object has no attribute 'startswith' +# db_file = db_conn.database_name +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# FETCHES_THRESHOLD = 80 +# +# # Change FW to OFF in order to speed up initial data filling: +# ################## +# +# fn_nul = open(os.devnull, 'w') +# +# subprocess.call([ context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "prp_write_mode", "prp_wm_async", +# "dbname", db_file ], +# stdout = fn_nul, +# stderr = subprocess.STDOUT +# ) +# +# fn_nul.close() +# +# ##################### +# # Prepare table: add data. +# +# sql_init=''' +# recreate table test +# ( +# id int not null, +# f01 int, +# f02 int +# ); +# +# set term ^; +# create or alter procedure sp_add_init_data(a_rows_to_add int) +# as +# declare n int; +# declare i int = 0; +# begin +# n = a_rows_to_add; +# while ( i < n ) do +# begin +# insert into test(id, f01, f02) values( :i, nullif(mod(:i, :n/20), 0), iif( mod(:i,3)<2, 0, 1) ) +# returning :i+1 into i; +# end +# end +# ^ +# set term ^; +# commit; +# +# execute procedure sp_add_init_data( 300000 ); +# commit; +# +# create index test_f01_id on test(f01, id); +# create index test_f02_only on test(f02); +# commit; +# ''' +# +# sql_cmd=open(os.path.join(context['temp_directory'],'tmp_core_5489.sql'), 'w') +# sql_cmd.write(sql_init) +# flush_and_close( sql_cmd ) +# +# sql_log=open(os.path.join(context['temp_directory'],'tmp_core_5489.log'),'w') +# sql_err=open(os.path.join(context['temp_directory'],'tmp_core_5489.err'),'w') +# +# subprocess.call([context['isql_path'], dsn, "-i", sql_cmd.name],stdout=sql_log, stderr=sql_err) +# +# flush_and_close( sql_log ) +# flush_and_close( sql_err ) +# +# ######################### +# +# # ::: NB ::: Trace config file format in 3.0 differs from 2.5 one: +# # 1) header section must be enclosed in "[" and "]", +# # 2) parameter-value pairs must be separated with '=' sign: +# # services +# # { +# # parameter = value +# # } +# +# if engine.startswith('2.5'): +# txt = '''# Generated auto, do not edit! +# +# enabled false +# +# +# +# enabled true +# time_threshold 0 +# log_statement_finish true +# print_plan true +# print_perf true +# +# ''' +# else: +# txt = '''# Generated auto, do not edit! +# database=%[\\\\\\\\/]security?.fdb +# { +# enabled = false +# } +# database=%[\\\\\\\\/]bugs.core_5489.fdb +# { +# enabled = true +# time_threshold = 0 +# log_statement_finish = true +# print_plan = true +# print_perf = true +# } +# ''' +# +# f_trc_cfg=open( os.path.join(context['temp_directory'],'tmp_trace_5489.cfg'), 'w') +# f_trc_cfg.write(txt) +# flush_and_close( f_trc_cfg ) +# +# # ############################################################## +# # S T A R T T R A C E i n S E P A R A T E P R O C E S S +# # ############################################################## +# +# f_trc_log=open( os.path.join(context['temp_directory'],'tmp_trace_5489.log'), "w") +# f_trc_err=open( os.path.join(context['temp_directory'],'tmp_trace_5489.err'), "w") +# +# p_trace = Popen( [ context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_start' , 'trc_cfg', f_trc_cfg.name],stdout=f_trc_log,stderr=f_trc_err) +# +# time.sleep(1) +# +# sql_run=''' +# set list on; +# --show version; +# select count(*) cnt_check +# from ( +# select * +# from test +# where f01 -- ################################################################### +# IS NULL -- <<< ::: NB ::: we check here 'f01 is NULL', exactly as ticket says. +# and f02=0 -- ################################################################### +# order by f01, id +# ) +# ; +# ''' +# +# sql_cmd=open(os.path.join(context['temp_directory'],'tmp_core_5489.sql'), 'w') +# sql_cmd.write(sql_run) +# flush_and_close( sql_cmd ) +# +# sql_log=open(os.path.join(context['temp_directory'],'tmp_core_5489.log'),'w') +# sql_err=open(os.path.join(context['temp_directory'],'tmp_core_5489.err'),'w') +# +# subprocess.call([context['isql_path'], dsn, "-i", sql_cmd.name],stdout=sql_log, stderr=sql_err) +# +# flush_and_close( sql_log ) +# flush_and_close( sql_err ) +# +# # #################################################### +# # G E T A C T I V E T R A C E S E S S I O N I D +# # #################################################### +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# +# f_trc_lst = open( os.path.join(context['temp_directory'],'tmp_trace_5489.lst'), 'w') +# subprocess.call([context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_list'], stdout=f_trc_lst) +# flush_and_close( f_trc_lst ) +# +# # !!! DO NOT REMOVE THIS LINE !!! +# time.sleep(1) +# +# trcssn=0 +# with open( f_trc_lst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# +# # #################################################### +# # S E N D R E Q U E S T T R A C E T O S T O P +# # #################################################### +# if trcssn>0: +# fn_nul = open(os.devnull, 'w') +# subprocess.call([context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_stop','trc_id', trcssn], stdout=fn_nul) +# fn_nul.close() +# # DO NOT REMOVE THIS LINE: +# time.sleep(1) +# +# p_trace.terminate() +# flush_and_close( f_trc_log ) +# flush_and_close( f_trc_err ) +# +# +# run_with_plan='' +# num_of_fetches=99999999 +# +# with open( f_trc_log.name,'r') as f: +# for line in f: +# if line.lower().startswith('plan ('): +# run_with_plan = line.upper() +# if 'fetch(es)' in line: +# words = line.split() +# for k in range(len(words)): +# if words[k].startswith('fetch'): +# num_of_fetches = int( words[k-1] ) +# +# print(run_with_plan) +# print( 'Number of fetches: acceptable.' +# if num_of_fetches < FETCHES_THRESHOLD else +# 'Too much fetches %(num_of_fetches)s -- more than threshold = %(FETCHES_THRESHOLD)s' % locals() +# ) +# +# # CLEANUP +# ######### +# time.sleep(1) +# cleanup( (f_trc_cfg, f_trc_lst, f_trc_log, f_trc_err, sql_log, sql_err, sql_cmd) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (TEST ORDER TEST_F01_ID) + Number of fetches: acceptable. + """ + +@pytest.mark.version('>=3.0.2') +@pytest.mark.xfail +def test_core_5489_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5494.py b/tests/bugs/test_core_5494.py new file mode 100644 index 00000000..54a57689 --- /dev/null +++ b/tests/bugs/test_core_5494.py @@ -0,0 +1,66 @@ +#coding:utf-8 +# +# id: bugs.core_5494 +# title: Creating a column of type BLOB SUB_TYPE BINARY fails with a Token unknown +# decription: +# Confirmed compilation problem on WI-T4.0.0.546. +# Checked on WI-T4.0.0.549 -- all OK. +# +# tracker_id: CORE-5494 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + recreate table test ( + c1 binary(8), + v1 varbinary(8), + b1 blob sub_type binary + ); + + insert into test(c1, b1) values('', ''); + update test set c1 = rdb$db_key, v1 = rdb$db_key, b1 = rpad('',32765,gen_uuid()); + + set sqlda_display on; + set planonly; + select * from test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + INPUT message field count: 0 + + PLAN (TEST NATURAL) + + OUTPUT message field count: 3 + 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 + """ + +@pytest.mark.version('>=4.0') +def test_core_5494_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5495.py b/tests/bugs/test_core_5495.py new file mode 100644 index 00000000..cf4a209a --- /dev/null +++ b/tests/bugs/test_core_5495.py @@ -0,0 +1,62 @@ +#coding:utf-8 +# +# id: bugs.core_5495 +# title: New users or changed passwords in legacy authentication do not work in Firebird 4 +# decription: +# Confirmed bug on WI-T4.0.0.546, got: +# Statement failed, SQLSTATE = 28000 +# Your user name and password are not defined. Ask your database administrator <...> +# Used config: +# AuthServer = Legacy_Auth,Srp +# AuthClient = Legacy_Auth,Srp,Win_Sspi +# WireCrypt = Disabled +# UserManager = Srp, Legacy_UserManager +# Checked on WI-T4.0.0.549 - works fine. +# +# tracker_id: CORE-5495 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('TCPv.*', 'TCP')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set bail on; + create user tmp$c5495 password '123' using plugin Legacy_UserManager; + commit; + 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; + drop user tmp$c5495 using plugin Legacy_UserManager; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MON$USER TMP$C5495 + MON$REMOTE_PROTOCOL TCP + MON$AUTH_METHOD Legacy_Auth + """ + +@pytest.mark.version('>=4.0') +def test_core_5495_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5496.py b/tests/bugs/test_core_5496.py new file mode 100644 index 00000000..cece3a58 --- /dev/null +++ b/tests/bugs/test_core_5496.py @@ -0,0 +1,84 @@ +#coding:utf-8 +# +# id: bugs.core_5496 +# title: Creating SRP SYSDBA with explicit admin (-admin yes in gsec or grant admin role in create user) creates two SYSDBA accounts +# decription: +# Test script should display only ONE record. +# Confirmed problem on: +# 3.0.0.32483: three(!) records are displayed instead of one. +# 3.0.1.32609: no records displayed with 'sysdba' account. +# Confirmed bug on 3.0.2.32658, WI-V3.0.2.32691. +# +# Checked on 3.0.2.32703: all OK. +# Checked on 4.0.0.1479, 3.0.5.33115 - all fine. +# +# 03-mar-2021: replaced 'xnet' with 'localhost' in order have ability to run this test on Linux. +# +# tracker_id: CORE-5496 +# min_versions: ['3.0.2'] +# versions: 3.0.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# check_sql=''' +# -- connect 'xnet://security.db'; +# connect 'localhost:security.db'; +# create or alter user foo password '123' grant admin role using plugin Srp; +# create or alter user rio password '123' grant admin role using plugin Srp; +# create or alter user bar password '123' grant admin role using plugin Srp; +# commit; +# grant rdb$admin to sysdba granted by foo; +# grant rdb$admin to sysdba granted by rio; +# grant rdb$admin to sysdba granted by bar; +# commit; +# set list on; +# set count on; +# select sec$user_name, sec$plugin from sec$users where upper(sec$user_name) = upper('sysdba') and upper(sec$plugin) = upper('srp'); +# commit; +# +# drop user foo using plugin Srp; +# drop user rio using plugin Srp; +# drop user bar using plugin Srp; +# commit; +# quit; +# ''' +# +# runProgram('isql', ['-q'], check_sql) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + SEC$USER_NAME SYSDBA + SEC$PLUGIN Srp + Records affected: 1 + """ + +@pytest.mark.version('>=3.0.2') +@pytest.mark.xfail +def test_core_5496_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5501.py b/tests/bugs/test_core_5501.py new file mode 100644 index 00000000..bb9e64a4 --- /dev/null +++ b/tests/bugs/test_core_5501.py @@ -0,0 +1,472 @@ +#coding:utf-8 +# +# id: bugs.core_5501 +# title: Unclear gstat's diagnostic when damaged page in DB file appears encrypted +# decription: +# Test creates table 'TEST' with varchar and blob fields, + index on varchar, and add some data to it. +# Blob field is filled by long values in order to prevent acomodation of its content within data pages. +# As result, this table should have pages of three different types: DataPage, BTreePage and BlobPage. +# +# Then we find number of first PP of this table by scrolling RDB$PAGES join RDB$RELATIONS result set. +# After this we: +# * define type of every page starting from first PP for 'TEST' table and up to total pages of DB, +# and doing this for each subsequent page, until ALL THREE different page types will be detected: +# 1) data page, 2) index B-Tree and 3) blob page. +# These page numbers are stored in variables: (brk_datapage, brk_indxpage, brk_blobpage). +# When all three page numbers are found, loop is terminated; +# * close connection and open dB as binary file for reading and writing; +# * store previous content of .fdb in variable 'raw_db_content' (for further restore); +# * move file seek pointer at the beginning of every page from list: (brk_datapage, brk_indxpage, brk_blobpage); +# * BREAK page content by writing invalid binary data in the header of page; +# This invalid data are: bytes 0...7 ==> 0xFFAACCEEBB0000CC; bytes 8...15 ==> 0xDDEEAADDCC00DDEE; +# * Close DB file handle and: +# ** 1) run 'gstat -e'; +# ** 2) run online validation; +# * open DB file again as binary and restore its content from var. 'raw_db_content' in order +# fbtest framework could finish this test (by making connect and drop this database); +# +# KEY POINTS: +# * report of 'gstat -e' should contain line with text 'ENCRYPTED 3 (DB problem!)' +# (number '3' should present becase we damaged pages of THREE diff. types: DP, BTree and Blob). +# * report of online validation should contain lines with info about three diff. page types which have problems. +# +# Checked on 3.0.2.32702 (CS/SC/SS), 4.0.0.563 (CS/SC/SS) +# +# tracker_id: CORE-5501 +# min_versions: ['3.0.2'] +# versions: 3.0.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.2 +# resources: None + +substitutions_1 = [('total \\d+,', 'total'), ('non-crypted \\d+', 'non-crypted'), ('crypted \\d+', 'crypted')] + +init_script_1 = """ + alter database drop linger; + commit; + + create table test(s varchar(1000) unique using index test_s_unq, b blob); + commit; + + set count on; + insert into test(s, b) + select + rpad( '',1000, uuid_to_char(gen_uuid()) ), + rpad( '', + 10000, -- NB: blob should have a big size! It should NOT be stored withih a data page. + 'qwertyuioplkjhgfdsazxcvbnm0987654321') + from rdb$types + rows 100; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import fdb +# import re +# import subprocess +# import time +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# dbnm = db_conn.database_name +# +# so=sys.stdout +# se=sys.stderr +# +# map_dbo={} +# +# #-------------------------------------------- +# +# 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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# def fill_dbo(con, map_dbo): +# cur=con.cursor() +# sql=''' +# select rel_id, rel_name, idx_id, idx_name +# from ( +# select +# rr.rdb$relation_id rel_id, -- 0 +# rr.rdb$relation_name rel_name, -- 1 +# -1 idx_id, -- 2 +# '' idx_name, -- 3 +# rr.rdb$relation_type rel_type, +# rr.rdb$system_flag sys_flag +# from rdb$relations rr +# +# union all +# +# select +# rr.rdb$relation_id rel_id, -- 0 +# rr.rdb$relation_name rel_name, -- 1 +# coalesce(ri.rdb$index_id-1,-1) idx_id, -- 2 +# coalesce(ri.rdb$index_name,'') idx_name, -- 3 +# rr.rdb$relation_type rel_type, +# rr.rdb$system_flag sys_flag +# from rdb$relations rr +# join rdb$indices ri on +# rr.rdb$relation_name = ri.rdb$relation_name +# ) r +# where +# coalesce(r.rel_type,0) = 0 -- exclude views, GTT and external tables +# and r.sys_flag is distinct from 1 +# ''' +# cur.execute(sql) +# for r in cur: +# map_dbo[ r[0], r[2] ] = ( r[1].strip(), r[3].strip() ) +# +# #-------------------------------------------- +# +# def parse_page_header(con, page_number, map_dbo): +# +# from struct import unpack_from +# +# global PAGE_TYPES +# +# page_buffer = con.get_page_contents( page_number ) +# +# # dimitr, 20.01.2017 ~13:00 +# # all *CHAR = 1 byte, *SHORT = 2 bytes, *LONG = 4 bytes. +# +# # https://docs.python.org/2/library/struct.html +# # struct.unpack_from(fmt, buffer[, offset=0]) +# # Unpack the buffer according to the given format. +# # The result is a tuple even if it contains exactly one item. +# # The buffer must contain at least the amount of data required by the format +# # len(buffer[offset:]) must be at least calcsize(fmt). +# # First character of the format string can be used to indicate the byte order, +# # size and alignment of the packed data +# # Native byte order is big-endian or little-endian: +# # < little-endian +# # > big-endian +# # Intel x86 and AMD64 (x86-64) are little-endian +# # Use sys.byteorder to check the endianness of your system: +# # https://docs.python.org/2/library/struct.html#format-characters +# # c char string of length 1 +# # b signed char +# # B unsigned char +# # h short +# # H unsigned short integer +# # i int integer 4 +# # I unsigned int integer 4 +# # l long (4) +# # L unsigned long (4) +# # q long long (8) +# # Q unsigned long long +# +# (page_type,) = unpack_from(' 16+4+4+2=26 +# # struct pointer_page +# # { +# # pag ppg_header; +# # SLONG ppg_sequence; // Sequence number in relation +# # SLONG ppg_next; // Next pointer page in relation +# # USHORT ppg_count; // Number of slots active +# # USHORT ppg_relation; // Relation id +# # USHORT ppg_min_space; // Lowest slot with space available +# # USHORT ppg_max_space; // Highest slot with space available +# # SLONG ppg_page[1]; // Data page vector +# # }; +# (relation_id,) = unpack_from(' USHORT +# +# # ------------------------------------------------------------------------------------------------------ +# +# +# if page_type == 5: +# # DATA page: +# # *pag* dpg_header=16, SLONG dpg_sequence=4 ==> 16+4 = 20: +# # struct data_page +# # { +# # 16 pag dpg_header; +# # 4 SLONG dpg_sequence; // Sequence number in relation +# # 2 USHORT dpg_relation; // Relation id +# # 2 USHORT dpg_count; // Number of record segments on page +# # struct dpg_repeat +# # { +# # USHORT dpg_offset; // Offset of record fragment +# # USHORT dpg_length; // Length of record fragment +# # } dpg_rpt[1]; +# # }; +# (relation_id,) = unpack_from(' USHORT +# (segment_cnt,) = unpack_from(' USHORT +# +# +# # ------------------------------------------------------------------------------------------------------ +# +# index_id=-1 +# ix_level=-1 +# btr_len=-1 +# +# if page_type == 7: +# # B-tree page ("bucket"): +# # struct btree_page +# # { +# # 16 pag btr_header; +# # 4 SLONG btr_sibling; // right sibling page +# # 4 SLONG btr_left_sibling; // left sibling page +# # 4 SLONG btr_prefix_total; // sum of all prefixes on page +# # 2 USHORT btr_relation; // relation id for consistency +# # 2 USHORT btr_length; // length of data in bucket +# # 1 UCHAR btr_id; // index id for consistency +# # 1 UCHAR btr_level; // index level (0 = leaf) +# # btree_nod btr_nodes[1]; +# # }; +# (relation_id,) = unpack_from(' USHORT +# (btr_len,) = unpack_from(' USHORT // length of data in bucket +# (index_id,) = unpack_from(' UCHAR +# (ix_level,) = unpack_from('=0 and (relation_id, index_id) in map_dbo: +# u = map_dbo[ relation_id, index_id ] +# page_info = ''.join( ( PAGE_TYPES[page_type].ljust(9), ', ', u[1].strip(),', data_len=',str(btr_len),', lev=',str(ix_level) ) ) # 'Indx Page, , ' +# elif (relation_id, -1) in map_dbo: +# u = map_dbo[ relation_id, -1 ] +# if page_type == 5: +# page_info = ''.join( ( PAGE_TYPES[page_type].ljust(9),', ',u[0].strip(),', segments on page: ',str(segment_cnt) ) ) # ', segments on page: NNN' - for Data page +# else: +# page_info = ''.join( ( PAGE_TYPES[page_type].ljust(9),', ',u[0].strip() ) ) # '' - for Pointer page +# +# elif relation_id == -1: +# page_info = PAGE_TYPES[page_type].ljust(9) +# else: +# page_info = ''.join( ('UNKNOWN; ',PAGE_TYPES[page_type].ljust(9),'; relation_id ', str(relation_id), '; index_id ', str(index_id)) ) +# +# return (page_type, relation_id, page_info) +# +# # end of func parse_page_header +# +# +# fill_dbo(db_conn, map_dbo) +# # ('map_dbo:', {(128, -1): ('TEST', ''), (128, 0): ('TEST', 'TEST_S')}) +# +# sql=''' +# select p.rdb$relation_id, p.rdb$page_number +# 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 +# order by p.rdb$page_number +# rows 1 +# ''' +# cur=db_conn.cursor() +# cur.execute(sql) +# (rel_id, pp1st) = (-1, -1) +# for r in cur: +# (rel_id, pp1st) = ( r[0], r[1] ) # (128, 192) +# +# PAGE_TYPES = { 0 : "undef/free", +# 1 : "DB header", +# 2 : "PIP", +# 3 : "TIP", +# 4 : "Pntr Page", +# 5 : "Data Page", +# 6 : "Indx Root", +# 7 : "Indx Data", +# 8 : "Blob Page", +# 9 : "Gens Page", +# 10 : "SCN" # only for ODS>=12 +# } +# +# +# res = db_conn.db_info([fdb.isc_info_page_size, fdb.isc_info_allocation]) +# pagesAllocated = res[fdb.isc_info_allocation] +# pgsize = res[fdb.isc_info_page_size] +# +# ################## +# # Found first page for each of three types: Data, Index and Blob +# # (loop starts from first PointerPage of table 'TEST') +# ################## +# +# (brk_datapage, brk_indxpage, brk_blobpage) = (-1, -1, -1) +# for i in range(pp1st,pagesAllocated): +# (page_type, relation_id, page_info) = parse_page_header(db_conn, i, map_dbo) +# #print('page:',i, '; page_type:',page_type, '; rel_id:',relation_id,';', page_info) +# if relation_id==128 and page_type == 5: +# brk_datapage = i +# if relation_id==128 and page_type == 7: +# brk_indxpage = i +# if page_type == 8: +# brk_blobpage = i +# if brk_datapage > 0 and brk_indxpage > 0 and brk_blobpage > 0: +# break +# +# db_conn.close() +# +# +# # Store binary content of .fdb for futher restore: +# ###################### +# with open(dbnm, 'rb') as f: +# raw_db_content=f.read() +# +# #################### +# # Make pages damaged +# #################### +# +# # 0xFFAACCEEBB0000CC 0xDDEEAADDCC00DDEE +# bw=bytearray(b'\\xff\\xaa\\xcc\\xee\\xbb\\x00\\x00\\xcc\\xdd\\xee\\xaa\\xdd\\xcc\\x00\\xdd\\xee') +# +# with open(dbnm, 'r+b') as w: +# for brk_page in (brk_datapage, brk_indxpage, brk_blobpage): +# w.seek( brk_page * pgsize) +# w.write(bw) +# +# #--------------------------------------------------------------------------- +# +# ###################### +# # Validate DB - ensure that there are errors in pages: +# ###################### +# f_onval_log=open( os.path.join(context['temp_directory'],'tmp_onval_c5501.log'), 'w') +# subprocess.call([context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_validate', 'dbname', dbnm, 'val_lock_timeout','1'],stdout=f_onval_log, stderr=subprocess.STDOUT) +# flush_and_close( f_onval_log ) +# +# # RESULT: validation log should contain lines with problems about three diff. page types: +# # expected data encountered unknown +# # expected index B-tree encountered unknown +# # expected blob encountered unknown +# +# #--------------------------------------------------------------------------- +# +# f_gstat_log=os.path.join(context['temp_directory'],'tmp_gstat_c5501.log') +# f_gstat_err=os.path.join(context['temp_directory'],'tmp_gstat_c5501.err') +# +# sys.stdout = open( f_gstat_log, 'w') +# sys.stderr = open( f_gstat_err, 'w') +# +# runProgram('gstat',['-e',dsn]) +# +# sys.stdout = so +# sys.stderr = se +# +# +# # ------------------ +# # restore DB content +# # ------------------ +# with open(dbnm,'wb') as f: +# f.write(raw_db_content) +# +# +# with open( f_gstat_err, 'r') as f: +# for line in f: +# print('UNEXPECTED STDERR', line) +# +# +# # Data pages: total 63, encrypted 0, non-crypted 63 +# # Index pages: total 86, encrypted 0, non-crypted 86 +# # Blob pages: total 199, encrypted 0, non-crypted 199 +# # Other pages: total 117, ENCRYPTED 3 (DB problem!), non-crypted 114 <<< __THIS__ should appear after CORE-5501 was fixed. +# +# pages_info_overall_pattern=re.compile('(data|index|blob|other)\\s+pages[:]{0,1}\\s+total[:]{0,1}\\s+\\d+[,]{0,1}\\s+encrypted[:]{0,1}\\s+\\d+.*[,]{0,1}non-crypted[:]{0,1}\\s+\\d+.*', re.IGNORECASE) +# +# with open( f_gstat_log, 'r') as f: +# for line in f: +# if pages_info_overall_pattern.match(line.strip()): +# print(line.strip()) +# +# +# ######################################################################## +# +# # Validation log should contain following lines: +# # -------------- +# # Error: Page 187 wrong type (expected data encountered unknown (255)) +# # Error: Page 186 wrong type (expected blob encountered unknown (255)) +# # Warning: Pointer page 180 {sequence 0} bits {0x0A large, secondary} are not consistent with data page 187 {sequence 0} state {0x05 full, swept} +# # Index 1 (TEST_S_UNQ) +# # Error: Page 184 wrong type (expected index B-tree encountered unknown (255)) +# # Error: Page 184 wrong type (expected index B-tree encountered unknown (255)) +# # Relation 128 (TEST) : 4 ERRORS found +# +# # We have to ensure that validation informs about ALL __THREE__ types of problem: +# # with DataPage, Index B-Tree and BlobPage: +# ########################################### +# (data_page_problem, indx_page_problem, blob_page_problem) = (-1, -1, -1) +# with open( f_onval_log.name, 'r') as f: +# for line in f: +# if 'expected data' in line: +# data_page_problem = 1 +# if 'expected index B-tree' in line: +# indx_page_problem = 1 +# if 'expected blob' in line: +# blob_page_problem = 1 +# +# print( 'Detect all THREE page types with problem ? => %s' % ('YES' if (data_page_problem, indx_page_problem, blob_page_problem) == (1,1,1) else 'NO.') ) +# +# # Cleanup: +# ########## +# cleanup( (f_gstat_log, f_gstat_err, f_onval_log) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Data pages: total 63, encrypted 0, non-crypted 63 + Index pages: total 88, encrypted 0, non-crypted 88 + Blob pages: total 199, encrypted 0, non-crypted 199 + Other pages: total 115, ENCRYPTED 3 (DB problem!), non-crypted 112 + Detect all THREE page types with problem ? => YES + """ + +@pytest.mark.version('>=3.0.2') +@pytest.mark.xfail +def test_core_5501_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5533.py b/tests/bugs/test_core_5533.py new file mode 100644 index 00000000..5a324df7 --- /dev/null +++ b/tests/bugs/test_core_5533.py @@ -0,0 +1,91 @@ +#coding:utf-8 +# +# id: bugs.core_5533 +# title: Crash on 3.0 and 4.0 when DB contains database-level trigger +# decription: +# Confirmed bug on WI-T4.0.0.633. +# Checked on WI-T4.0.0.638, WI-V3.0.3.32721 -- both on SS and CS. +# +# tracker_id: CORE-5533 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set list on; + set term ^; + execute block as + begin + begin + execute statement 'drop trigger trg_tx_start'; + when any do begin end + end + end + ^ + set term ;^ + commit; + + recreate table tlog (ID integer default current_transaction, msg varchar(20)); + + set term ^; + create trigger trg_tx_start inactive on transaction start position 0 + as + begin + execute statement ('insert into tlog(msg) values(?)') ('Tx start'); + end + ^ + set term ;^ + commit; + + set autoddl off; + select count(distinct id) id_distinct_count_0 from tlog; + alter trigger trg_tx_start active; + commit; + + set term ^; + execute block as + declare c int; + begin + begin + execute statement 'drop trigger trg_tx_start'; + when any do begin end + end + end + ^ + set term ;^ + commit; + + select count(distinct id) id_distinct_count_1 from tlog; + commit; + select count(distinct id) id_distinct_count_2 from tlog; + quit; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID_DISTINCT_COUNT_0 0 + ID_DISTINCT_COUNT_1 1 + ID_DISTINCT_COUNT_2 1 + """ + +@pytest.mark.version('>=3.0') +def test_core_5533_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5535.py b/tests/bugs/test_core_5535.py new file mode 100644 index 00000000..4659a4c4 --- /dev/null +++ b/tests/bugs/test_core_5535.py @@ -0,0 +1,61 @@ +#coding:utf-8 +# +# id: bugs.core_5535 +# title: Garbage value in RDB$FIELD_SUB_TYPE in RDB$FUNCTION_ARGUMENTS after altering function +# decription: +# tracker_id: CORE-5535 +# min_versions: ['3.0.2'] +# versions: 3.0.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter view v_check as + select rdb$field_sub_type from rdb$function_arguments where rdb$function_name=upper('test') + ; + commit; + + set list on; + set count on; + + select * from v_check; + + create function test(i int) returns int as begin end; + commit; + select * from v_check; + + create or alter function test(i int) returns int as begin end; + commit; + select * from v_check; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + RDB$FIELD_SUB_TYPE + RDB$FIELD_SUB_TYPE + Records affected: 2 + RDB$FIELD_SUB_TYPE + RDB$FIELD_SUB_TYPE + Records affected: 2 + """ + +@pytest.mark.version('>=3.0.2') +def test_core_5535_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5536.py b/tests/bugs/test_core_5536.py new file mode 100644 index 00000000..aad62abd --- /dev/null +++ b/tests/bugs/test_core_5536.py @@ -0,0 +1,63 @@ +#coding:utf-8 +# +# id: bugs.core_5536 +# title: Connections compressed and encrypted in MON$ATTACHMENTS table +# decription: +# 26.01.2019. Replaced old field names (MON$CONNECTION_COMPRESSED, MON$CONNECTION_ENCRYPTED) with new ones. +# Removed trivial 'select 1', use SQLDA_DISPLAY to have explicit output columns type (boolean). +# Checked on: +# 4.0.0.1340: OK, 1.828s. +# 4.0.0.1410: OK, 1.969s. +# Previous check: 4.0.0.728: OK, 0.797s. +# +# tracker_id: CORE-5536 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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_core_5536_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5538.py b/tests/bugs/test_core_5538.py new file mode 100644 index 00000000..3ff6f775 --- /dev/null +++ b/tests/bugs/test_core_5538.py @@ -0,0 +1,189 @@ +#coding:utf-8 +# +# id: bugs.core_5538 +# title: DELETE FROM MON$STATEMENTS does not interrupt a longish fetch +# decription: +# We create several tables and add single row to each of them. Row contains name of corresponding table. +# Then we create view that based on UNIONED-query to all of these tables. +# After this, we handle list of PATTERNS and pass each of its elements (herteafter its name is:

) to +# '-include_data' gbak command switch. +# Further we RESTORE from this .fbk to temporary DB. This new database which contain only those tables +# which names matched to '-include_data

' pattern on previous step. +# We also must check joint usage of '-include_data' and (old) '-skip_data' command switches. +# For this purpose we create single pattern for EXCLUDING some tables (see 'skip_ptn' variable) and use +# this pattern together with elements from patterns list for tables which data must be included in .fbk. +# +# Checked on: 4.0.0.1639 SS: 13.978s. +# +# +# tracker_id: CORE-5538 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """ + recreate view v_test as select 1 x from rdb$database; + commit; + recreate table test_anna( s varchar(20) default 'anna' ); + recreate table test_beta( s varchar(20) default 'beta' ); + recreate table test_ciao( s varchar(20) default 'ciao' ); + recreate table test_cola( s varchar(20) default 'cola' ); + recreate table test_dina( s varchar(20) default 'dina' ); + recreate table test_doca( s varchar(20) default 'doca' ); + recreate table test_docb( s varchar(20) default 'docb' ); + recreate table test_docc( s varchar(20) default 'docc' ); + recreate table test_dora( s varchar(20) default 'dora' ); + recreate table test_dura( s varchar(20) default 'dura' ); + recreate table test_mail( s varchar(20) default 'mail' ); + recreate table test_omen( s varchar(20) default 'omen' ); + recreate table test_opel( s varchar(20) default 'opel' ); + recreate table test_rose( s varchar(20) default 'rose' ); + recreate table test_win1( s varchar(20) default 'win1' ); + recreate table test_won2( s varchar(20) default 'won2' ); + recreate table test_w_n3( s varchar(20) default 'w_n3' ); + commit; + + recreate view v_test as + select v.s + from rdb$database r + left join ( + select s from test_anna union all + select s from test_beta union all + select s from test_ciao union all + select s from test_cola union all + select s from test_dina union all + select s from test_doca union all + select s from test_docb union all + select s from test_docc union all + select s from test_dora union all + select s from test_dura union all + select s from test_mail union all + select s from test_omen union all + select s from test_opel union all + select s from test_rose union all + select s from test_win1 union all + select s from test_won2 union all + select s from test_w_n3 + ) v on 1=1 + ; + commit; + + + insert into test_anna default values; + insert into test_beta default values; + insert into test_ciao default values; + insert into test_cola default values; + insert into test_dina default values; + insert into test_doca default values; + insert into test_docb default values; + insert into test_docc default values; + insert into test_dora default values; + insert into test_dura default values; + insert into test_mail default values; + insert into test_omen default values; + insert into test_opel default values; + insert into test_rose default values; + insert into test_win1 default values; + insert into test_won2 default values; + insert into test_w_n3 default values; + commit; + + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # dsn localhost/3400:C:\\FBTESTING\\qa +# bt-repo mpugs.core_NNNN.fdb +# # db_conn.database_name C:\\FBTESTING\\QA\\FBT-REPO\\TMP\\BUGS.CORE_NNNN.FDB +# # $(DATABASE_LOCATION)... C:/FBTESTING/qa/fbt-repo/tmp/bugs.core_NNN.fdb +# +# this_fdb=db_conn.database_name +# this_fbk=os.path.join(context['temp_directory'],'tmp_5538.fbk') +# test_res=os.path.join(context['temp_directory'],'tmp_5538.tmp') +# +# db_conn.close() +# +# ############################################## +# # Script for ISQL that will do 'heavy select': +# +# usr=user_name +# pwd=user_password +# +# # 1. Check that we can use patterns for include data only from several selected tables: +# incl_ptn_list = ('test_doc%', 'test_d(o|u)ra', '%_w(i|o|_)n[[:DIGIT:]]', 'test_a[[:ALPHA:]]{1,}a' ) +# +# for i, p in enumerate(incl_ptn_list): +# runProgram('gbak',['-b', dsn, this_fbk, '-include', p ]) +# runProgram('gbak',['-rep', this_fbk, 'localhost:'+test_res]) +# sql_check = "set heading off; select %(i)s ptn_indx, q'{%(p)s}' as ptn_text, v.* from v_test v;" % locals() +# runProgram('isql',['localhost:'+test_res], sql_check ) +# +# # 2. Check interaction between -INCLUDE_DATA and -SKIP_DATA switches for a table: +# # We must check only conditions marked by '**': +# # +--------------------------------------------------+ +# # | | INCLUDE_DATA | +# # | |--------------------------------------| +# # | SKIP_DATA | NOT SET | MATCH | NOT MATCH | +# # +-----------+------------+------------+------------+ +# # | NOT SET | included | included | excluded | <<< these rules can be skipped in this test +# # | MATCH | excluded |**excluded**|**excluded**| +# # | NOT MATCH | included |**included**|**excluded**| +# # +-----------+------------+------------+------------+ +# +# skip_ptn = 'test_d(o|u)%' +# incl_ptn_list = ('test_d%', 'test_(a|b)[[:ALPHA:]]+a', ) +# +# for i, p in enumerate(incl_ptn_list): +# runProgram('gbak',['-b', dsn, this_fbk, '-include_data', p, '-skip_data', skip_ptn ]) +# runProgram('gbak',['-rep', this_fbk, 'localhost:'+test_res]) +# sql_check = "set heading off; select %(i)s ptn_indx, q'{%(p)s}' as include_ptn, q'{%(skip_ptn)s}' as exclude_ptn, v.* from v_test v;" % locals() +# runProgram('isql',['localhost:'+test_res], sql_check ) +# +# time.sleep(1) +# os.remove( this_fbk ) +# os.remove( test_res ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 0 test_doc% doca + 0 test_doc% docb + 0 test_doc% docc + 1 test_d(o|u)ra dora + 1 test_d(o|u)ra dura + 2 %_w(i|o|_)n[[:DIGIT:]] win1 + 2 %_w(i|o|_)n[[:DIGIT:]] won2 + 2 %_w(i|o|_)n[[:DIGIT:]] w_n3 + 3 test_a[[:ALPHA:]]{1,}a anna + + 0 test_d% test_d(o|u)% dina + 1 test_(a|b)[[:ALPHA:]]+a test_d(o|u)% anna + 1 test_(a|b)[[:ALPHA:]]+a test_d(o|u)% beta + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_5538_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5542_db_attach.py b/tests/bugs/test_core_5542_db_attach.py new file mode 100644 index 00000000..53050b7c --- /dev/null +++ b/tests/bugs/test_core_5542_db_attach.py @@ -0,0 +1,151 @@ +#coding:utf-8 +# +# id: bugs.core_5542_db_attach +# title: Database-level triggers related to TRANSACTION events (i.e. start, commit and rollback) do not take in account their POSITION index (when more than one trigger for the same event type is defined) +# decription: +# Note. This test does check only for 'DATABASE CONNECT' case (though it worked Ok before this bug was found). +# Resuls for 22.05.2017: +# fb30Cs, build 3.0.3.32725: OK, 2.203ss. +# fb30SC, build 3.0.3.32725: OK, 1.375ss. +# FB30SS, build 3.0.3.32725: OK, 1.328ss. +# FB40CS, build 4.0.0.645: OK, 2.391ss. +# FB40SC, build 4.0.0.645: OK, 1.422ss. +# FB40SS, build 4.0.0.645: OK, 2.375ss. +# +# tracker_id: CORE-5542 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + set term ^; + create or alter trigger trg_db_attach_beta inactive on connect position 0 as begin end + ^ + create or alter trigger trg_db_attach_anna inactive on connect position 0 as begin end + ^ + create or alter trigger trg_db_attach_ciao inactive on connect position 0 as begin end + ^ + commit + ^ + drop trigger trg_db_attach_beta + ^ + drop trigger trg_db_attach_anna + ^ + drop trigger trg_db_attach_ciao + ^ + + recreate table tsignal( id integer ) + ^ + recreate table trg_log( id integer, msg varchar(20) ); + ^ + + execute block as + begin + execute statement 'drop sequence g'; + when any do begin end + end + ^ + set term ;^ + commit; + + set autoddl off; + set bail on; + + create sequence g; + commit; + + set term ^; + create trigger trg_log_bi for trg_log active before insert position 0 as + begin + new.id = coalesce( new.id, gen_id(g,1) ); + end + ^ + set term ;^ + commit; + + ------------------------------------------------------------------------ + + set term ^; + create or alter trigger trg_db_attach_ciao active on connect position 111 as + begin + if ( exists(select * from tsignal) ) then + insert into trg_log(msg) values('trigger tx_ciao'); + end + ^ + + create or alter trigger trg_db_attach_anna active on connect position 22 as + begin + if ( exists(select * from tsignal) ) then + insert into trg_log(msg) values('trigger tx_anna'); + end + ^ + + create or alter trigger trg_db_attach_beta active on connect position 3 as + begin + if ( exists(select * from tsignal) ) then + insert into trg_log(msg) values('trigger tx_beta'); + end + ^ + + set term ;^ + commit; + + insert into tsignal(id) values(1); + commit; + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + + select + r.rdb$trigger_name + ,r.rdb$trigger_sequence + ,r.rdb$trigger_type + from rdb$triggers r + where r.rdb$trigger_name starting with upper('TRG_DB_ATTACH') + order by r.rdb$trigger_sequence + ; + + set count on; + select * from trg_log; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$TRIGGER_NAME TRG_DB_ATTACH_BETA + RDB$TRIGGER_SEQUENCE 3 + RDB$TRIGGER_TYPE 8192 + RDB$TRIGGER_NAME TRG_DB_ATTACH_ANNA + RDB$TRIGGER_SEQUENCE 22 + RDB$TRIGGER_TYPE 8192 + RDB$TRIGGER_NAME TRG_DB_ATTACH_CIAO + RDB$TRIGGER_SEQUENCE 111 + RDB$TRIGGER_TYPE 8192 + ID 1 + MSG trigger tx_beta + ID 2 + MSG trigger tx_anna + ID 3 + MSG trigger tx_ciao + Records affected: 3 + """ + +@pytest.mark.version('>=3.0') +def test_core_5542_db_attach_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5542_db_detach.py b/tests/bugs/test_core_5542_db_detach.py new file mode 100644 index 00000000..97d40de5 --- /dev/null +++ b/tests/bugs/test_core_5542_db_detach.py @@ -0,0 +1,153 @@ +#coding:utf-8 +# +# id: bugs.core_5542_db_detach +# title: Database-level triggers related to TRANSACTION events (i.e. start, commit and rollback) do not take in account their POSITION index (when more than one trigger for the same event type is defined) +# decription: +# Note. This test does check only for 'DATABASE DISCONNECT' case (though it worked Ok before this bug was found). +# Resuls for 22.05.2017: +# fb30Cs, build 3.0.3.32725: OK, 2.172ss. +# fb30SC, build 3.0.3.32725: OK, 1.406ss. +# FB30SS, build 3.0.3.32725: OK, 1.250ss. +# FB40CS, build 4.0.0.645: OK, 2.313ss. +# FB40SC, build 4.0.0.645: OK, 1.485ss. +# FB40SS, build 4.0.0.645: OK, 1.500ss. +# +# tracker_id: CORE-5542 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + set term ^; + create or alter trigger trg_db_deattach_beta inactive on disconnect position 0 as begin end + ^ + create or alter trigger trg_db_deattach_anna inactive on disconnect position 0 as begin end + ^ + create or alter trigger trg_db_deattach_ciao inactive on disconnect position 0 as begin end + ^ + commit + ^ + drop trigger trg_db_deattach_beta + ^ + drop trigger trg_db_deattach_anna + ^ + drop trigger trg_db_deattach_ciao + ^ + + recreate table tsignal( id integer ) + ^ + recreate table trg_log( id integer, msg varchar(20) ); + ^ + + execute block as + begin + execute statement 'drop sequence g'; + when any do begin end + end + ^ + set term ;^ + commit; + + set autoddl off; + set bail on; + + create sequence g; + commit; + + set term ^; + create trigger trg_log_bi for trg_log active before insert position 0 as + begin + new.id = coalesce( new.id, gen_id(g,1) ); + end + ^ + set term ;^ + commit; + + ------------------------------------------------------------------------ + + set term ^; + create or alter trigger trg_db_deattach_ciao active on disconnect position 111 as + begin + if ( exists(select * from tsignal) ) then + insert into trg_log(msg) values('trigger tx_ciao'); + end + ^ + + create or alter trigger trg_db_deattach_anna active on disconnect position 22 as + begin + if ( exists(select * from tsignal) ) then + insert into trg_log(msg) values('trigger tx_anna'); + end + ^ + + create or alter trigger trg_db_deattach_beta active on disconnect position 3 as + begin + if ( exists(select * from tsignal) ) then + insert into trg_log(msg) values('trigger tx_beta'); + end + ^ + + set term ;^ + commit; + + insert into tsignal(id) values(1); -- this will allow triggers to INSERT rows into TRG_LOG table. + commit; + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + + + select + r.rdb$trigger_name + ,r.rdb$trigger_sequence + ,r.rdb$trigger_type + from rdb$triggers r + where r.rdb$trigger_name starting with upper('trg_db_deattach') + order by r.rdb$trigger_sequence + ; + + set count on; + select * from trg_log; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$TRIGGER_NAME TRG_DB_DEATTACH_BETA + RDB$TRIGGER_SEQUENCE 3 + RDB$TRIGGER_TYPE 8193 + RDB$TRIGGER_NAME TRG_DB_DEATTACH_ANNA + RDB$TRIGGER_SEQUENCE 22 + RDB$TRIGGER_TYPE 8193 + RDB$TRIGGER_NAME TRG_DB_DEATTACH_CIAO + RDB$TRIGGER_SEQUENCE 111 + RDB$TRIGGER_TYPE 8193 + ID 1 + MSG trigger tx_beta + ID 2 + MSG trigger tx_anna + ID 3 + MSG trigger tx_ciao + Records affected: 3 + """ + +@pytest.mark.version('>=3.0') +def test_core_5542_db_detach_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5542_tx_commit.py b/tests/bugs/test_core_5542_tx_commit.py new file mode 100644 index 00000000..5f993855 --- /dev/null +++ b/tests/bugs/test_core_5542_tx_commit.py @@ -0,0 +1,165 @@ +#coding:utf-8 +# +# id: bugs.core_5542_tx_commit +# title: Database-level triggers related to TRANSACTION events (i.e. start, commit and rollback) do not take in account their POSITION index (when more than one trigger for the same event type is defined) +# decription: +# Note. This test does check only for 'TRANSACTION COMMIT' case. +# Resuls for 22.05.2017: +# fb30Cs, build 3.0.3.32725: OK, 2.281ss. +# fb30SC, build 3.0.3.32725: OK, 1.265ss. +# FB30SS, build 3.0.3.32725: OK, 1.172ss. +# FB40CS, build 4.0.0.645: OK, 2.187ss. +# FB40SC, build 4.0.0.645: OK, 1.297ss. +# FB40SS, build 4.0.0.645: OK, 1.390ss. +# +# tracker_id: CORE-5542 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + set term ^; + create or alter trigger trg_tx_commit_beta inactive on transaction commit position 0 as begin end + ^ + create or alter trigger trg_tx_commit_anna inactive on transaction commit position 0 as begin end + ^ + create or alter trigger trg_tx_commit_ciao inactive on transaction commit position 0 as begin end + ^ + commit + ^ + drop trigger trg_tx_commit_beta + ^ + drop trigger trg_tx_commit_anna + ^ + drop trigger trg_tx_commit_ciao + ^ + + execute block as + begin + execute statement 'drop sequence g'; + when any do begin end + end + ^ + set term ;^ + commit; + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + + set autoddl off; + set bail on; + + create sequence g; + commit; + + + set term ^; + create or alter trigger trg_tx_commit_ciao active on transaction commit position 111 as + declare c int; + begin + if ( rdb$get_context('USER_SESSION','RUN_DB_LEVEL_TRG') is not null ) then + begin + --select count(*) from rdb$types,rdb$types,(select 1 i from rdb$types rows 3) into c; + rdb$set_context('USER_SESSION','RUN_DB_LEVEL_TRG_CIAO', gen_id(g,1) || ': TRG_TX_COMMIT_CIAO '); + end + end + ^ + + create or alter trigger trg_tx_commit_anna active on transaction commit position 3 as + declare c int; + begin + if ( rdb$get_context('USER_SESSION','RUN_DB_LEVEL_TRG') is not null ) then + begin + --select count(*) from rdb$types,rdb$types,(select 1 i from rdb$types rows 3) into c; + rdb$set_context('USER_SESSION','RUN_DB_LEVEL_TRG_ANNA', gen_id(g,1) || ': TRG_TX_COMMIT_ANNA '); + end + end + ^ + + create or alter trigger trg_tx_commit_beta active on transaction commit position 22 as + declare c int; + begin + if ( rdb$get_context('USER_SESSION','RUN_DB_LEVEL_TRG') is not null ) then + begin + --select count(*) from rdb$types,rdb$types,(select 1 i from rdb$types rows 3) into c; + rdb$set_context('USER_SESSION','RUN_DB_LEVEL_TRG_BETA', gen_id(g,1) || ': TRG_TX_COMMIT_BETA '); + end + end + ^ + + set term ;^ + commit; + + -- Check (preview): + select + r.rdb$trigger_name + ,r.rdb$trigger_sequence + ,r.rdb$trigger_type + from rdb$triggers r + where r.rdb$trigger_name starting with upper('trg_tx_commit') + order by r.rdb$trigger_sequence + ; + + + set term ^; + execute block as + begin + rdb$set_context('USER_SESSION','RUN_DB_LEVEL_TRG', 1); -- Allow triggers to assign values to corresp. context variables 'RUN_DB_LEVEL_TRG_*' + end + ^ + set term ;^ + + + set count on; + commit; + + select + c.MON$VARIABLE_NAME + ,c.MON$VARIABLE_VALUE + from mon$context_variables c + where c.mon$attachment_id = current_connection and c.mon$variable_name similar to '%(ANNA|BETA|CIAO)' + order by c.mon$variable_VALUE + ; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$TRIGGER_NAME TRG_TX_COMMIT_ANNA + RDB$TRIGGER_SEQUENCE 3 + RDB$TRIGGER_TYPE 8195 + RDB$TRIGGER_NAME TRG_TX_COMMIT_BETA + RDB$TRIGGER_SEQUENCE 22 + RDB$TRIGGER_TYPE 8195 + RDB$TRIGGER_NAME TRG_TX_COMMIT_CIAO + RDB$TRIGGER_SEQUENCE 111 + RDB$TRIGGER_TYPE 8195 + MON$VARIABLE_NAME RUN_DB_LEVEL_TRG_ANNA + MON$VARIABLE_VALUE 1: TRG_TX_COMMIT_ANNA + MON$VARIABLE_NAME RUN_DB_LEVEL_TRG_BETA + MON$VARIABLE_VALUE 2: TRG_TX_COMMIT_BETA + MON$VARIABLE_NAME RUN_DB_LEVEL_TRG_CIAO + MON$VARIABLE_VALUE 3: TRG_TX_COMMIT_CIAO + Records affected: 3 + """ + +@pytest.mark.version('>=3.0') +def test_core_5542_tx_commit_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5542_tx_rollback.py b/tests/bugs/test_core_5542_tx_rollback.py new file mode 100644 index 00000000..b8787430 --- /dev/null +++ b/tests/bugs/test_core_5542_tx_rollback.py @@ -0,0 +1,159 @@ +#coding:utf-8 +# +# id: bugs.core_5542_tx_rollback +# title: Database-level triggers related to TRANSACTION events (i.e. start, commit and rollback) do not take in account their POSITION index (when more than one trigger for the same event type is defined) +# decription: +# Note. This test does check only for 'TRANSACTION ROLLBACK' case. +# Resuls for 22.05.2017: +# fb30Cs, build 3.0.3.32725: OK, 2.219ss. +# fb30SC, build 3.0.3.32725: OK, 1.359ss. +# FB30SS, build 3.0.3.32725: OK, 1.265ss. +# FB40CS, build 4.0.0.645: OK, 2.516ss. +# FB40SC, build 4.0.0.645: OK, 1.453ss. +# FB40SS, build 4.0.0.645: OK, 1.453ss. +# +# tracker_id: CORE-5542 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + + set list on; + + set term ^; + create or alter trigger trg_tx_cancel_beta inactive on transaction rollback position 0 as begin end + ^ + create or alter trigger trg_tx_cancel_anna inactive on transaction rollback position 0 as begin end + ^ + create or alter trigger trg_tx_cancel_ciao inactive on transaction rollback position 0 as begin end + ^ + commit + ^ + drop trigger trg_tx_cancel_beta + ^ + drop trigger trg_tx_cancel_anna + ^ + drop trigger trg_tx_cancel_ciao + ^ + + recreate table trg_log( id integer, msg varchar(20) ); + ^ + + execute block as + begin + execute statement 'drop sequence g'; + when any do begin end + end + ^ + set term ;^ + commit; + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + + set autoddl off; + set bail on; + + create sequence g; + commit; + + set term ^; + create trigger trg_log_bi for trg_log active before insert position 0 as + begin + new.id = coalesce( new.id, gen_id(g,1) ); + end + ^ + set term ;^ + commit; + + + set term ^; + create or alter trigger trg_tx_cancel_ciao active on transaction rollback position 111 as + begin + if ( rdb$get_context('USER_SESSION','RUN_DB_LEVEL_TRG') is not null ) then + in autonomous transaction do + insert into trg_log(msg) values('trigger tx_ciao'); + end + ^ + + create or alter trigger trg_tx_cancel_anna active on transaction rollback position 3 as + begin + if ( rdb$get_context('USER_SESSION','RUN_DB_LEVEL_TRG') is not null ) then + in autonomous transaction do + insert into trg_log(msg) values('trigger tx_anna'); + end + ^ + + create or alter trigger trg_tx_cancel_beta active on transaction rollback position 22 as + begin + if ( rdb$get_context('USER_SESSION','RUN_DB_LEVEL_TRG') is not null ) then + in autonomous transaction do + insert into trg_log(msg) values('trigger tx_beta'); + end + ^ + + set term ;^ + commit; + + select + r.rdb$trigger_name + ,r.rdb$trigger_sequence + ,r.rdb$trigger_type + from rdb$triggers r + where r.rdb$trigger_name starting with upper('trg_tx_cancel') + order by r.rdb$trigger_sequence + ; + + + set term ^; + execute block as + begin + rdb$set_context('USER_SESSION','RUN_DB_LEVEL_TRG', 1); + end + ^ + set term ;^ + + set count on; + rollback; + select * from trg_log; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$TRIGGER_NAME TRG_TX_CANCEL_ANNA + RDB$TRIGGER_SEQUENCE 3 + RDB$TRIGGER_TYPE 8196 + RDB$TRIGGER_NAME TRG_TX_CANCEL_BETA + RDB$TRIGGER_SEQUENCE 22 + RDB$TRIGGER_TYPE 8196 + RDB$TRIGGER_NAME TRG_TX_CANCEL_CIAO + RDB$TRIGGER_SEQUENCE 111 + RDB$TRIGGER_TYPE 8196 + ID 1 + MSG trigger tx_anna + ID 2 + MSG trigger tx_beta + ID 3 + MSG trigger tx_ciao + Records affected: 3 + """ + +@pytest.mark.version('>=3.0') +def test_core_5542_tx_rollback_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5542_tx_start.py b/tests/bugs/test_core_5542_tx_start.py new file mode 100644 index 00000000..7fef0387 --- /dev/null +++ b/tests/bugs/test_core_5542_tx_start.py @@ -0,0 +1,159 @@ +#coding:utf-8 +# +# id: bugs.core_5542_tx_start +# title: Database-level triggers related to TRANSACTION events (i.e. start, commit and rollback) do not take in account their POSITION index (when more than one trigger for the same event type is defined) +# decription: +# Note. This test does check only for 'TRANSACTION START' case. +# Resuls for 22.05.2017: +# fb30Cs, build 3.0.3.32725: OK, 1.969ss. +# fb30SC, build 3.0.3.32725: OK, 1.422ss. +# FB30SS, build 3.0.3.32725: OK, 1.453ss. +# FB40CS, build 4.0.0.645: OK, 2.313ss. +# FB40SC, build 4.0.0.645: OK, 1.593ss. +# FB40SS, build 4.0.0.645: OK, 1.578ss. +# +# tracker_id: CORE-5542 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + set term ^; + create or alter trigger trg_tx_start_beta inactive on transaction start position 0 as begin end + ^ + create or alter trigger trg_tx_start_anna inactive on transaction start position 0 as begin end + ^ + create or alter trigger trg_tx_start_ciao inactive on transaction start position 0 as begin end + ^ + commit + ^ + drop trigger trg_tx_start_beta + ^ + drop trigger trg_tx_start_anna + ^ + drop trigger trg_tx_start_ciao + ^ + + recreate table trg_log( id integer, msg varchar(20) ); + ^ + + execute block as + begin + execute statement 'drop sequence g'; + when any do begin end + end + ^ + set term ;^ + commit; + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + + set autoddl off; + set bail on; + + create sequence g; + commit; + + set term ^; + create trigger trg_log_bi for trg_log active before insert position 0 as + begin + new.id = coalesce( new.id, gen_id(g,1) ); + end + ^ + set term ;^ + commit; + + + set term ^; + create or alter trigger trg_tx_start_ciao active on transaction start position 111 as + begin + if ( rdb$get_context('USER_SESSION','RUN_DB_LEVEL_TRG') is not null ) then + insert into trg_log(msg) values('trigger tx_ciao'); + end + ^ + + create or alter trigger trg_tx_start_anna active on transaction start position 3 as + begin + if ( rdb$get_context('USER_SESSION','RUN_DB_LEVEL_TRG') is not null ) then + insert into trg_log(msg) values('trigger tx_anna'); + end + ^ + + create or alter trigger trg_tx_start_beta active on transaction start position 22 as + begin + if ( rdb$get_context('USER_SESSION','RUN_DB_LEVEL_TRG') is not null ) then + insert into trg_log(msg) values('trigger tx_beta'); + end + ^ + + set term ;^ + commit; + + -- Check (preview): + select + r.rdb$trigger_name + ,r.rdb$trigger_sequence + ,r.rdb$trigger_type + from rdb$triggers r + where r.rdb$trigger_name starting with upper('TRG_TX_START') + order by r.rdb$trigger_sequence + ; + + + set term ^; + execute block as + begin + rdb$set_context('USER_SESSION','RUN_DB_LEVEL_TRG', 1); -- this allows triggers to do INSERTs in the TRG_LOG table. + end + ^ + set term ;^ + + commit; + + -- Following 'select' statement causes IMPLICIT start of transaction. It means that all triggers with names "trg_tx_start_nnnn" + -- will fire. They all should run within current Tx, so we could see results of their activity in the table 'trg_log': + set count on; + select * from trg_log; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$TRIGGER_NAME TRG_TX_START_ANNA + RDB$TRIGGER_SEQUENCE 3 + RDB$TRIGGER_TYPE 8194 + RDB$TRIGGER_NAME TRG_TX_START_BETA + RDB$TRIGGER_SEQUENCE 22 + RDB$TRIGGER_TYPE 8194 + RDB$TRIGGER_NAME TRG_TX_START_CIAO + RDB$TRIGGER_SEQUENCE 111 + RDB$TRIGGER_TYPE 8194 + ID 1 + MSG trigger tx_anna + ID 2 + MSG trigger tx_beta + ID 3 + MSG trigger tx_ciao + Records affected: 3 + """ + +@pytest.mark.version('>=3.0') +def test_core_5542_tx_start_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5545.py b/tests/bugs/test_core_5545.py new file mode 100644 index 00000000..d92e3572 --- /dev/null +++ b/tests/bugs/test_core_5545.py @@ -0,0 +1,385 @@ +#coding:utf-8 +# +# id: bugs.core_5545 +# title: Wrong syntax with CREATE TRIGGER ... ON

used with POSITION +# decription: +# Test checks that: +# 1. Triggers with POSITION can be accepted only when this clause is at the END of declaration +# (but before SQL SECURITY clause because it belongs to '' rather than to the trigger header. +# 2. Any kind of trigger which has POSITION not in the end of header section will not compile. +# Failed DDL statement, gdscode and SQLSTATE are written into special table, DDL_AUDIT (in autonomous Tx, of course). +# +# Finally, we make output of triggers list which present in the database (i.e. which passed) and list of failed DDLs +# from the table DDL_AUDIT, with filtering out any details of their declarations (we need only trigger names from failed DDL). +# +# Checked on 4.0.0.1763 +# See also: http://tracker.firebirdsql.org/browse/CORE-6243 +# +# ::: NB ::: Section 'expected_stdout' was changed. +# Trigger 'trg_test_bi_sql2003_02' violates SQL:2003 but such form is maintained for backward compatibility. +# This trigger is compiled successfully since build 4.0.0.1767. +# +# tracker_id: CORE-5545 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('^((?!(ACCEPTED_DDL|Records affected|FAILED_DDL|GDS_CODE|SQL_STATE)).)*$', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter procedure sp_try2run as begin end; + recreate table ddl_audit( + id int generated by default as identity constraint pk_ddl primary key + ,failed_ddl varchar(1024) + ,gds_code bigint + ,sql_state char(5) + ); + + set term ^; + create or alter procedure sp_try2run(ddl_sttm type of column ddl_audit.failed_ddl) as + begin + execute statement (ddl_sttm); + when any do + begin + in autonomous transaction do + insert into ddl_audit(failed_ddl, gds_code, sql_state) values(:ddl_sttm, gdscode, sqlstate); + end + end + ^ + set term ;^ + commit; + + + recreate table test(id int); + commit; + + set term ^; + -- must be accepted because POSITION is at the end of decl. + create or alter trigger trg_test_bi_legacy_01 + for test + inactive + before insert + position 1 + sql security definer + as begin + end + ^ + + -- must be accepted because POSITION is at the end of decl. + create or alter trigger trg_test_bi_sql2003_01 + inactive + before insert + on test + position 1 + sql security definer + as begin + end + ^ + + + -- must be accepted because POSITION is at the end of decl. + create or alter trigger trg_dbevent_01 + inactive + on disconnect + position 1 + sql security definer + as begin + end + ^ + + + -- must be accepted because POSITION is at the end of decl. + create or alter trigger trg_ddl_01 + inactive + before any ddl statement + position 1 + sql security definer + as begin + end + ^ + commit -- otherwise concurrent update raises... why ?.. + ^ + -- ##################################################### + -- ### All following DDL statements must FAILED with ### + -- ### SQLSTATE = 42000 / -Token unknown / -position ### + -- ##################################################### + + execute block as + declare ddl_sttm type of column ddl_audit.failed_ddl; + begin + + -- =========================== + -- 1. LEGACY-STYLE DECLARATION + -- =========================== + ddl_sttm = + 'create or alter trigger trg_test_bi_legacy_02 + for test + inactive + position 2 + before insert + as begin + end' + ; + execute procedure sp_try2run(ddl_sttm); + + + ddl_sttm = + 'create or alter trigger trg_test_bi_legacy_03 + for test + position 3 + inactive + before insert + as begin + end' + ; + execute procedure sp_try2run(ddl_sttm); + + ddl_sttm = + 'create or alter trigger trg_test_bi_legacy_04 + position 4 + for test + inactive + before insert + as begin + end' + ; + execute procedure sp_try2run(ddl_sttm); + + + -- ============================= + -- 2. SQL-2003 STYLE DECLARATION + -- ============================= + + -- 24.04.2020: this form must PASS though it is violates requirements of SQL:2003. + -- This behaviour is kept for backward compatibility - see explanation by Adriano, + -- letter 24.04.2020 17:20. + -- ::: NB ::: documentation for FB 4.x need to be changed because of this. + ddl_sttm = + 'create or alter trigger trg_test_bi_sql2003_02 + inactive + before insert + position 2 + on test + as begin + end' + ; + execute procedure sp_try2run(ddl_sttm); + + + ddl_sttm = + 'create or alter trigger trg_test_bi_sql2003_03 + inactive + position 3 + before insert + on test + as begin + end' + ; + execute procedure sp_try2run(ddl_sttm); + + + ddl_sttm = + 'create or alter trigger trg_test_bi_sql2003_04 + position 4 + inactive + before insert + on test + as begin + end' + ; + execute procedure sp_try2run(ddl_sttm); + + + -- ======================= + -- 3. DB-LEVEL DECLARATION + -- ======================= + + ddl_sttm = + 'create or alter trigger trg_dbevent_02 + position 2 + inactive + on disconnect + as begin + end' + ; + execute procedure sp_try2run(ddl_sttm); + + + ddl_sttm = + 'create or alter trigger trg_dbevent_03 + inactive + position 3 + on disconnect + as begin + end' + ; + execute procedure sp_try2run(ddl_sttm); + + + -- ======================== + -- 4. DDL-LEVEL DECLARATION + -- ======================== + + ddl_sttm = + 'create or alter trigger trg_ddl_02 + inactive + position 2 + before any ddl statement + as begin + end' + ; + execute procedure sp_try2run(ddl_sttm); + + + ddl_sttm = + 'create or alter trigger trg_ddl_03 + position 3 + inactive + before any ddl statement + as begin + end' + ; + execute procedure sp_try2run(ddl_sttm); + + + end + ^ + set term ;^ + commit; + set list on; + set count on; + select rdb$trigger_name as accepted_ddl from rdb$triggers where rdb$system_flag is distinct from 1; + select * from ddl_audit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ACCEPTED_DDL TRG_TEST_BI_LEGACY_01 + + ACCEPTED_DDL TRG_TEST_BI_SQL2003_01 + + ACCEPTED_DDL TRG_DBEVENT_01 + + ACCEPTED_DDL TRG_DDL_01 + + ACCEPTED_DDL TRG_TEST_BI_SQL2003_02 + + + Records affected: 5 + + ID 1 + FAILED_DDL create or alter trigger trg_test_bi_legacy_02 + for test + inactive + position 2 + before insert + as begin + end + GDS_CODE 335544569 + SQL_STATE 42000 + + ID 2 + FAILED_DDL create or alter trigger trg_test_bi_legacy_03 + for test + position 3 + inactive + before insert + as begin + end + GDS_CODE 335544569 + SQL_STATE 42000 + + ID 3 + FAILED_DDL create or alter trigger trg_test_bi_legacy_04 + position 4 + for test + inactive + before insert + as begin + end + GDS_CODE 335544569 + SQL_STATE 42000 + + ID 4 + FAILED_DDL create or alter trigger trg_test_bi_sql2003_03 + inactive + position 3 + before insert + on test + as begin + end + GDS_CODE 335544569 + SQL_STATE 42000 + + ID 5 + FAILED_DDL create or alter trigger trg_test_bi_sql2003_04 + position 4 + inactive + before insert + on test + as begin + end + GDS_CODE 335544569 + SQL_STATE 42000 + + ID 6 + FAILED_DDL create or alter trigger trg_dbevent_02 + position 2 + inactive + on disconnect + as begin + end + GDS_CODE 335544569 + SQL_STATE 42000 + + ID 7 + FAILED_DDL create or alter trigger trg_dbevent_03 + inactive + position 3 + on disconnect + as begin + end + GDS_CODE 335544569 + SQL_STATE 42000 + + ID 8 + FAILED_DDL create or alter trigger trg_ddl_02 + inactive + position 2 + before any ddl statement + as begin + end + GDS_CODE 335544569 + SQL_STATE 42000 + + ID 9 + FAILED_DDL create or alter trigger trg_ddl_03 + position 3 + inactive + before any ddl statement + as begin + end + GDS_CODE 335544569 + SQL_STATE 42000 + + + Records affected: 9 + """ + +@pytest.mark.version('>=4.0') +def test_core_5545_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_555.py b/tests/bugs/test_core_555.py new file mode 100644 index 00000000..5920468d --- /dev/null +++ b/tests/bugs/test_core_555.py @@ -0,0 +1,171 @@ +#coding:utf-8 +# +# id: bugs.core_555 +# title: Inconsistent results using STARTING WITH and COALESCE +# decription: +# tracker_id: CORE-555 +# min_versions: [] +# versions: 2.0 +# qmid: bugs.core_555 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test(name char(31) character set unicode_fss); + commit; + insert into test (name) values ('RDB$TRIGGER_1'); + insert into test (name) values ('RDB$TRIGGER_8'); + insert into test (name) values ('RDB$TRIGGER_9'); + insert into test (name) values ('RDB$TRIGGER_2'); + insert into test (name) values ('RDB$TRIGGER_3'); + insert into test (name) values ('RDB$TRIGGER_26'); + insert into test (name) values ('RDB$TRIGGER_25'); + insert into test (name) values ('RDB$TRIGGER_10'); + insert into test (name) values ('RDB$TRIGGER_11'); + insert into test (name) values ('RDB$TRIGGER_12'); + insert into test (name) values ('RDB$TRIGGER_13'); + insert into test (name) values ('RDB$TRIGGER_14'); + insert into test (name) values ('RDB$TRIGGER_15'); + insert into test (name) values ('RDB$TRIGGER_16'); + insert into test (name) values ('RDB$TRIGGER_17'); + insert into test (name) values ('RDB$TRIGGER_18'); + insert into test (name) values ('RDB$TRIGGER_19'); + insert into test (name) values ('RDB$TRIGGER_20'); + insert into test (name) values ('RDB$TRIGGER_21'); + insert into test (name) values ('RDB$TRIGGER_22'); + insert into test (name) values ('RDB$TRIGGER_23'); + insert into test (name) values ('RDB$TRIGGER_24'); + insert into test (name) values ('RDB$TRIGGER_27'); + insert into test (name) values ('RDB$TRIGGER_31'); + insert into test (name) values ('RDB$TRIGGER_32'); + insert into test (name) values ('RDB$TRIGGER_33'); + insert into test (name) values ('RDB$TRIGGER_34'); + insert into test (name) values ('RDB$TRIGGER_35'); + insert into test (name) values ('RDB$TRIGGER_36'); + commit; + + set list on; + + select name "test-1" + from test a + where a.name starting with ''; + + select name "test-2" + from test a + where a.name starting with coalesce(null, ''); + + select name "test-3" + from test a + where cast(a.name as char(31)) starting with coalesce(null, ''); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + test-1 RDB$TRIGGER_1 + test-1 RDB$TRIGGER_8 + test-1 RDB$TRIGGER_9 + test-1 RDB$TRIGGER_2 + test-1 RDB$TRIGGER_3 + test-1 RDB$TRIGGER_26 + test-1 RDB$TRIGGER_25 + test-1 RDB$TRIGGER_10 + test-1 RDB$TRIGGER_11 + test-1 RDB$TRIGGER_12 + test-1 RDB$TRIGGER_13 + test-1 RDB$TRIGGER_14 + test-1 RDB$TRIGGER_15 + test-1 RDB$TRIGGER_16 + test-1 RDB$TRIGGER_17 + test-1 RDB$TRIGGER_18 + test-1 RDB$TRIGGER_19 + test-1 RDB$TRIGGER_20 + test-1 RDB$TRIGGER_21 + test-1 RDB$TRIGGER_22 + test-1 RDB$TRIGGER_23 + test-1 RDB$TRIGGER_24 + test-1 RDB$TRIGGER_27 + test-1 RDB$TRIGGER_31 + test-1 RDB$TRIGGER_32 + test-1 RDB$TRIGGER_33 + test-1 RDB$TRIGGER_34 + test-1 RDB$TRIGGER_35 + test-1 RDB$TRIGGER_36 + + test-2 RDB$TRIGGER_1 + test-2 RDB$TRIGGER_8 + test-2 RDB$TRIGGER_9 + test-2 RDB$TRIGGER_2 + test-2 RDB$TRIGGER_3 + test-2 RDB$TRIGGER_26 + test-2 RDB$TRIGGER_25 + test-2 RDB$TRIGGER_10 + test-2 RDB$TRIGGER_11 + test-2 RDB$TRIGGER_12 + test-2 RDB$TRIGGER_13 + test-2 RDB$TRIGGER_14 + test-2 RDB$TRIGGER_15 + test-2 RDB$TRIGGER_16 + test-2 RDB$TRIGGER_17 + test-2 RDB$TRIGGER_18 + test-2 RDB$TRIGGER_19 + test-2 RDB$TRIGGER_20 + test-2 RDB$TRIGGER_21 + test-2 RDB$TRIGGER_22 + test-2 RDB$TRIGGER_23 + test-2 RDB$TRIGGER_24 + test-2 RDB$TRIGGER_27 + test-2 RDB$TRIGGER_31 + test-2 RDB$TRIGGER_32 + test-2 RDB$TRIGGER_33 + test-2 RDB$TRIGGER_34 + test-2 RDB$TRIGGER_35 + test-2 RDB$TRIGGER_36 + + test-3 RDB$TRIGGER_1 + test-3 RDB$TRIGGER_8 + test-3 RDB$TRIGGER_9 + test-3 RDB$TRIGGER_2 + test-3 RDB$TRIGGER_3 + test-3 RDB$TRIGGER_26 + test-3 RDB$TRIGGER_25 + test-3 RDB$TRIGGER_10 + test-3 RDB$TRIGGER_11 + test-3 RDB$TRIGGER_12 + test-3 RDB$TRIGGER_13 + test-3 RDB$TRIGGER_14 + test-3 RDB$TRIGGER_15 + test-3 RDB$TRIGGER_16 + test-3 RDB$TRIGGER_17 + test-3 RDB$TRIGGER_18 + test-3 RDB$TRIGGER_19 + test-3 RDB$TRIGGER_20 + test-3 RDB$TRIGGER_21 + test-3 RDB$TRIGGER_22 + test-3 RDB$TRIGGER_23 + test-3 RDB$TRIGGER_24 + test-3 RDB$TRIGGER_27 + test-3 RDB$TRIGGER_31 + test-3 RDB$TRIGGER_32 + test-3 RDB$TRIGGER_33 + test-3 RDB$TRIGGER_34 + test-3 RDB$TRIGGER_35 + test-3 RDB$TRIGGER_36 + """ + +@pytest.mark.version('>=2.0') +def test_core_555_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5550.py b/tests/bugs/test_core_5550.py new file mode 100644 index 00000000..436a947d --- /dev/null +++ b/tests/bugs/test_core_5550.py @@ -0,0 +1,59 @@ +#coding:utf-8 +# +# id: bugs.core_5550 +# title: Computed decimal field in a view has wrong RDB$FIELD_PRECISION +# decription: +# 30SS, build 3.0.3.32738: OK, 0.828s. +# 40SS, build 4.0.0.680: OK, 1.062s. +# +# tracker_id: CORE-5550 +# min_versions: ['3.0.3'] +# versions: 3.0.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate view v_test(f) as + select cast(null as decimal(10,2)) + from rdb$database; + commit; + + set list on; + set count on; + + select + cast(rf.rdb$field_name as varchar(80)) rf_field_name, + ff.rdb$field_precision ff_field_prec, + ff.rdb$field_scale ff_field_scale + from rdb$relation_fields rf + join rdb$fields ff on rf.rdb$field_source = ff.rdb$field_name + where rf.rdb$relation_name = upper('v_test'); + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RF_FIELD_NAME F + FF_FIELD_PREC 18 + FF_FIELD_SCALE -2 + Records affected: 1 + """ + +@pytest.mark.version('>=3.0.3') +def test_core_5550_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5555.py b/tests/bugs/test_core_5555.py new file mode 100644 index 00000000..a7c06109 --- /dev/null +++ b/tests/bugs/test_core_5555.py @@ -0,0 +1,108 @@ +#coding:utf-8 +# +# id: bugs.core_5555 +# title: 3.0 error handling for SELECT WITH LOCK breaks compatibility with 2.5 +# decription: +# Checked on: +# 4.0.0.1635 SS: OK, 1.053s. +# 4.0.0.1633 CS: OK, 1.309s. +# 3.0.5.33180 SS: OK, 0.823s. +# 3.0.5.33178 CS: OK, 1.181s. +# See also http://tracker.firebirdsql.org/browse/CORE-4473 +# +# tracker_id: CORE-5555 +# min_versions: ['3.0.3'] +# versions: 3.0.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + recreate table test(x int, y int); + insert into test(x, y) values(1, 2); + commit; + + set transaction no wait; + + set term ^; + execute block as + declare c int; + begin + execute statement ('select current_transaction from test where x = ? and 1=1 with lock') (1) + on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') + as user 'sysdba' password 'masterkey' + into c; + end + ^ + + execute block returns(gds_on_update int) as + begin + begin + update test set y = -y where x = 1 and 2=2; + when any do + begin + gds_on_update = gdscode; + end + end + suspend; + end + ^ + + execute block returns(gds_on_select_with_lock int) as + declare c int; + begin + begin + select y from test where x = 1 and 3=3 with lock into c; + when any do + begin + gds_on_select_with_lock = gdscode; + end + end + suspend; + end + ^ + 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + GDS_ON_UPDATE 335544336 + GDS_ON_SELECT_WITH_LOCK 335544336 + """ + +@pytest.mark.version('>=3.0.3') +def test_core_5555_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5563.py b/tests/bugs/test_core_5563.py new file mode 100644 index 00000000..d86fbdb1 --- /dev/null +++ b/tests/bugs/test_core_5563.py @@ -0,0 +1,58 @@ +#coding:utf-8 +# +# id: bugs.core_5563 +# title: Use exception instead bugcheck for EVL_expr +# decription: +# Checked on: +# fb30Cs, build 3.0.4.32972: OK, 0.687s. +# FB30SS, build 3.0.4.32988: OK, 0.672s. +# FB40CS, build 4.0.0.955: OK, 1.656s. +# FB40SS, build 4.0.0.1008: OK, 0.891s. +# +# NOTE. +# Ability to use nested aggregate looks strange. +# Query like here can not be run in MS SQL or Postgress. +# Sent letters to dimitr, 19.06.2018. +# +# tracker_id: CORE-5563 +# min_versions: ['3.0.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select + sum( + sum( + (select sum(rf.rdb$field_position) from rdb$relation_fields rf) + ) + ) + from + rdb$database + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + SUM + """ + +@pytest.mark.version('>=3.0') +def test_core_5563_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5565.py b/tests/bugs/test_core_5565.py new file mode 100644 index 00000000..0665d781 --- /dev/null +++ b/tests/bugs/test_core_5565.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: bugs.core_5565 +# title: No integer division possible in dialect 1 +# decription: +# Reproduced fail on build 4.0.0.651. +# Build 4.0.0.680: OK, 1.046s +# +# tracker_id: CORE-5565 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set wng off; + set sql dialect 1; + commit; + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + set term ^; + execute block as + declare c int; + begin + select 1/1 as x from rdb$database into c; + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=4.0') +def test_core_5565_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_5567.py b/tests/bugs/test_core_5567.py new file mode 100644 index 00000000..5ef45337 --- /dev/null +++ b/tests/bugs/test_core_5567.py @@ -0,0 +1,79 @@ +#coding:utf-8 +# +# id: bugs.core_5567 +# title: Direct system table modifications are not completely prohibited +# decription: +# 30SS, build 3.0.3.32738: OK, 0.828s. +# 40SS, build 4.0.0.680: OK, 0.938s. +# +# tracker_id: CORE-5567 +# min_versions: ['3.0.3'] +# versions: 3.0.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.3 +# resources: None + +substitutions_1 = [('line: [\\d]+, col: [\\d]+', ''), ('.*At block.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + execute block as + begin + execute statement 'drop domain dm_test'; + when any do begin end + end + ^ + set term ;^ + commit; + + create domain dm_test numeric(18, 2); + commit; + + set term ^; + execute block as + declare procedure hack as + begin + update rdb$fields set rdb$field_scale = -3 where rdb$field_name = upper('dm_test'); + end + begin + execute procedure hack; + end + ^ + set term ;^ + commit; + + set list on; + select ff.rdb$field_scale domain_precision + from rdb$fields ff + where ff.rdb$field_name = upper('dm_test') + ; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DOMAIN_PRECISION -2 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + UPDATE operation is not allowed for system table RDB$FIELDS + -At sub procedure 'HACK' + """ + +@pytest.mark.version('>=3.0.3') +def test_core_5567_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5569.py b/tests/bugs/test_core_5569.py new file mode 100644 index 00000000..a69f9474 --- /dev/null +++ b/tests/bugs/test_core_5569.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: bugs.core_5569 +# title: ISQL incorrectly pads UNICODE_FSS/UTF8 columns when they use a collation +# decription: +# 30SS, build 3.0.3.32738: OK, 0.766s. +# 40SS, build 4.0.0.680: OK, 0.859s. +# +# tracker_id: CORE-5569 +# min_versions: ['3.0.3'] +# versions: 3.0.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list OFF; -- for this test we have to check table-wise view rather than list + select + _utf8 '1234567890' collate unicode as f_with_collate, + _utf8 '1234567890' as f_without_collate, + '|' as d + from rdb$database; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F_WITH_COLLATE F_WITHOUT_COLLATE D + ============== ================= ====== + 1234567890 1234567890 | + """ + +@pytest.mark.version('>=3.0.3') +def test_core_5569_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5570.py b/tests/bugs/test_core_5570.py new file mode 100644 index 00000000..cc509838 --- /dev/null +++ b/tests/bugs/test_core_5570.py @@ -0,0 +1,78 @@ +#coding:utf-8 +# +# id: bugs.core_5570 +# title: Negative infinity (double) shown incorrectly without sign in isql +# decription: +# Bug was in ISQL. We do insert in the table with two DP fields special values which +# are "-1.#INF" and "1.#INF" (at least in such view they are represented in the trace). +# These values are defined in Python class Decimal as literals '-Infinity' and 'Infinity'. +# After this we try to query this table. Expected result: "minus" sign should be shown +# leftside of negative infinity. +# +# Confirmed WRONG output (w/o sign with negative infinity) on 3.0.3.32756, 4.0.0.690. +# All fine on: +# 3.0.3.32794: OK, 1.235s. +# 4.0.0.713: OK, 1.203s. +# +# tracker_id: CORE-5570 +# min_versions: ['3.0.3'] +# versions: 3.0.3 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table test(x double precision, y double precision); + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# from decimal import * +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# +# x1=Decimal('-Infinity') +# y1=Decimal('Infinity') +# +# cur1=db_conn.cursor() +# sql='insert into test(x, y) values(?, ?)' +# +# try: +# cur1.execute( sql, (x1, y1, ) ) +# except Exception, e: +# print(e[0]) +# +# cur1.close() +# db_conn.commit() +# db_conn.close() +# +# runProgram('isql',[dsn], "set list on; set count on; select * from test;") +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + X -Infinity + Y Infinity + Records affected: 1 + """ + +@pytest.mark.version('>=3.0.3') +@pytest.mark.xfail +def test_core_5570_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5576.py b/tests/bugs/test_core_5576.py new file mode 100644 index 00000000..07cedee1 --- /dev/null +++ b/tests/bugs/test_core_5576.py @@ -0,0 +1,178 @@ +#coding:utf-8 +# +# id: bugs.core_5576 +# title: Bugcheck on queries containing WITH LOCK clause +# decription: +# We create database as it was show in the ticket and do backup and restore of it. +# Then we run checking query - launch isql two times and check that 2nd call of ISQL +# does not raise bugcheck. Finally we run online validation against this DB. +# +# Neither test query nor validation should raise any output in the STDERR. +# +# Confirmed bug on 4.0.0.684 and 3.0.3.32743, got: +# === +# Statement failed, SQLSTATE = XX000 +# internal Firebird consistency check (decompression overran buffer (179), file: sqz.cpp line: 282) +# Statement failed, SQLSTATE = XX000 +# internal Firebird consistency check (can't continue after bugcheck) +# === +# Results after fix: +# fb30Cs, build 3.0.3.32746: OK, 6.328s. +# fb30SC, build 3.0.3.32746: OK, 3.469s. +# FB30SS, build 3.0.3.32746: OK, 3.172s. +# FB40CS, build 4.0.0.685: OK, 5.954s. +# FB40SC, build 4.0.0.685: OK, 3.781s. +# FB40SS, build 4.0.0.685: OK, 2.828s. +# +# tracker_id: CORE-5576 +# min_versions: ['3.0.3'] +# versions: 3.0.3 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.3 +# resources: None + +substitutions_1 = [('[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9]', ''), ('Relation [0-9]{3,4}', 'Relation')] + +init_script_1 = """ + recreate table test ( + i integer not null primary key, + d char(1024) computed by ('qwert'), + s varchar(8192) + ); + insert into test values (1, 'format1opqwertyuiopqwertyuiop'); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# +# import os +# import subprocess +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # Obtain engine version: +# engine = str(db_conn.engine_version) # convert to text because 'float' object has no attribute 'startswith' +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# f_bkrs_err = open( os.path.join(context['temp_directory'],'tmp_backup_restore_5576.err'), 'w') +# f_bkup_tmp = os.path.join(context['temp_directory'],'tmp_5576.fbk') +# f_rest_tmp = os.path.join(context['temp_directory'],'tmp_5576.fdb') +# +# cleanup( (f_bkup_tmp,f_rest_tmp) ) +# +# fn_nul = open(os.devnull, 'w') +# subprocess.call( [context['gbak_path'], "-b", dsn, f_bkup_tmp ], +# stdout = fn_nul, +# stderr = f_bkrs_err +# ) +# +# subprocess.call( [context['gbak_path'], "-rep", f_bkup_tmp, 'localhost:'+f_rest_tmp ], +# stdout = fn_nul, +# stderr = f_bkrs_err +# ) +# +# flush_and_close( f_bkrs_err ) +# fn_nul.close() +# +# +# script='set list on;select 1 x1 from test where i=1 with lock;' +# +# # Checking query (it did produce bugcheck before fix): +# ################ +# runProgram('isql',['localhost:'+f_rest_tmp],script) +# runProgram('isql',['localhost:'+f_rest_tmp],script) # ---------- launch isql SECOND time! +# +# +# f_val_log=open( os.path.join(context['temp_directory'],'tmp_val_5576.log'), "w") +# f_val_err=open( os.path.join(context['temp_directory'],'tmp_val_5576.err'), "w") +# +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_validate", +# "dbname", f_rest_tmp +# ], +# stdout=f_val_log, +# stderr=f_val_err) +# flush_and_close( f_val_log ) +# flush_and_close( f_val_err ) +# +# with open( f_val_log.name,'r') as f: +# print(f.read()) +# +# # Check that neither restore nor validation raised errors: +# ################### +# f_list=(f_bkrs_err, f_val_err) +# for i in range(len(f_list)): +# with open( f_list[i].name,'r') as f: +# for line in f: +# if line.split(): +# print( 'UNEXPECTED STDERR in file '+f_list[i].name+': '+line.upper() ) +# +# +# # Cleanup +# ######### +# cleanup( (f_bkrs_err, f_val_log, f_val_err, f_bkup_tmp, f_rest_tmp) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + X1 1 + X1 1 + Validation started + Relation 128 (TEST) + process pointer page 0 of 1 + Index 1 (RDB$PRIMARY1) + Relation 128 (TEST) is ok + Validation finished + """ + +@pytest.mark.version('>=3.0.3') +@pytest.mark.xfail +def test_core_5576_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5579.py b/tests/bugs/test_core_5579.py new file mode 100644 index 00000000..ff024348 --- /dev/null +++ b/tests/bugs/test_core_5579.py @@ -0,0 +1,154 @@ +#coding:utf-8 +# +# id: bugs.core_5579 +# title: request synchronization error in the GBAK utility (restore) +# decription: +# Database for this test was created beforehand on 2.5.7 with intentionally broken not null constraint. +# It was done using direct RDB$ table modification: +# --- +# recreate table test(id int not null,fn int); +# insert into test(id, fn) values(1, null); +# insert into test(id, fn) values(2, null); -- 2nd record must also present! +# commit; +# -- add NOT NULL, direct modify rdb$ tables (it is allowed before 3.0): +# update rdb$relation_fields set rdb$null_flag = 1 +# where rdb$field_name = upper('fn') and rdb$relation_name = upper('test'); +# commit; +# --- +# We try to restore .fbk which was created from that DB on current FB snapshot and check that restore log +# does NOT contain phrase 'request synchronization' in any line. +# +# Bug was reproduced on 2.5.7.27062, 3.0.3.32746, 4.0.0.684 +# All fine on: +# FB25Cs, build 2.5.8.27067: OK, 2.125s. +# FB25SC, build 2.5.8.27067: OK, 1.641s. +# fb30Cs, build 3.0.3.32756: OK, 3.891s. +# fb30SC, build 3.0.3.32756: OK, 2.500s. +# FB30SS, build 3.0.3.32756: OK, 2.422s. +# FB40CS, build 4.0.0.690: OK, 3.891s. +# FB40SC, build 4.0.0.690: OK, 2.750s. +# FB40SS, build 4.0.0.690: OK, 2.828s. +# +# tracker_id: CORE-5579 +# min_versions: ['2.5.8'] +# versions: 2.5.8 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.8 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import time +# import zipfile +# import subprocess +# import re +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# zf = zipfile.ZipFile( os.path.join(context['files_location'],'core_5579_broken_nn.zip') ) +# +# # Name of .fbk inside .zip: +# zipfbk='core_5579_broken_nn.fbk' +# +# zf.extract( zipfbk, context['temp_directory'] ) +# zf.close() +# +# tmpfbk=''.join( ( context['temp_directory'], zipfbk ) ) +# tmpfdb=''.join( ( context['temp_directory'], 'core_5579_broken_nn.fdb') ) +# +# # C:\\MIX +# irebird\\QA +# bt-repo mp\\core_5579_broken_nn.fbk +# # C:\\MIX +# irebird\\QA +# bt-repo mp\\core_5579_broken_nn.fdb +# +# f_restore_log=open( os.path.join(context['temp_directory'],'tmp_restore_5579.log'), 'w') +# f_restore_err=open( os.path.join(context['temp_directory'],'tmp_restore_5579.err'), 'w') +# +# if os.path.isfile(tmpfdb): +# os.remove(tmpfdb) +# +# # C:\\MIX +# irebird +# b25Csin\\gbak -rep C:\\MIX +# irebird\\QA +# bt-repo mp\\c5579.fbk\\core_5579_broken_nn.fbk -v -o /:C:\\MIX +# irebird\\QA +# bt-repo mp\\c5579.fbk\\CORE_5579_BROKEN_NN.FDB +# +# subprocess.call([ "fbsvcmgr", +# "localhost:service_mgr", +# "action_restore", +# "bkp_file", tmpfbk, +# "dbname", tmpfdb, +# "res_one_at_a_time" +# ], +# stdout=f_restore_log, +# stderr=f_restore_err +# ) +# # before this ticket was fixed restore log did contain following line: +# # gbak: ERROR:request synchronization error +# +# f_restore_log.close() +# f_restore_err.close() +# +# # Check: +# ######## +# # 1. fbsvcmgr itself must finish without errors: +# with open( f_restore_err.name,'r') as f: +# for line in f: +# if line.split(): +# print( 'UNEXPECTED STDERR in file '+f_restore_err.name+': '+line.upper() ) +# +# # 2. Log of restoring process must NOT contain line with phrase 'request synchronization': +# +# req_sync_pattern=re.compile('[.*]*request\\s+synchronization\\s+error\\.*', re.IGNORECASE) +# +# with open( f_restore_log.name,'r') as f: +# for line in f: +# if req_sync_pattern.search(line): +# print( 'UNEXPECTED STDLOG: '+line.upper() ) +# +# ##################################################################### +# # Cleanup: +# +# # do NOT remove this pause otherwise some of logs will not be enable for deletion and test will finish with +# # Exception raised while executing Python test script. exception: WindowsError: 32 +# time.sleep(1) +# +# f_list=(f_restore_log, f_restore_err) +# for i in range(len(f_list)): +# if os.path.isfile(f_list[i].name): +# os.remove(f_list[i].name) +# os.remove(tmpfdb) +# os.remove(tmpfbk) +# +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.8') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_5579_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5580.py b/tests/bugs/test_core_5580.py new file mode 100644 index 00000000..1a53dbad --- /dev/null +++ b/tests/bugs/test_core_5580.py @@ -0,0 +1,77 @@ +#coding:utf-8 +# +# id: bugs.core_5580 +# title: Signature of packaged functions is not checked for mismatch with [NOT] DETERMINISTIC attribute +# decription: +# Confirmed bug on builds: 3.0.3.32756, 4.0.0.690. +# Works fine on: +# 3.0.3.32757: OK, 0.812s. +# 4.0.0.693: OK, 1.047s. +# +# tracker_id: CORE-5580 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + recreate package pk1 as + begin + function f1() returns int deterministic; + function f2() returns int not deterministic; + end + ^ + recreate package body pk1 as + begin + function f1() returns int not deterministic as + begin + return 123; + end + + function f2() returns int not deterministic as + begin + return 123 * rand(); + end + + end + ^ + set term ;^ + commit; + + set list on; + + select pk1.f1() as f1_result from rdb$database; + select pk1.f2() as f2_result from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + 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 + """ + +@pytest.mark.version('>=3.0') +def test_core_5580_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_5593.py b/tests/bugs/test_core_5593.py new file mode 100644 index 00000000..334368a0 --- /dev/null +++ b/tests/bugs/test_core_5593.py @@ -0,0 +1,151 @@ +#coding:utf-8 +# +# id: bugs.core_5593 +# title: System function RDB$ROLE_IN_USE cannot take long role names +# decription: +# Test creates several roles and grants them to user. +# Role #1 is common ascii string without spaces. +# Role #2 is ascii string with spaces, all character are written in UPPERCASE. +# Role #3 is ascii string with spaces, all character are written in lowercase. +# +# After make connection to database using role #3 we have to check that this role +# indeed was applied to connection and that rdb$role_in_use *does* return this role name also. +# See also: github.com/FirebirdSQL/firebird/commit/61b4bf0d276884a0ba0f2edef3b41fa2c58c87ee +# Comments there: +# - roleStr.upper(); +# + //roleStr.upper(); // sorry - but this breaks role names containing lower case letters +# +# +# ::: NB CAUTION ::: TEMPLY DEFERRED ::: +# We also have to check cases when role contains NON-ASCII characters but currently this is impossible. +# Exception like: +# === +# Statement failed, SQLSTATE = 22001 +# arithmetic exception, numeric overflow, or string truncation +# -string right truncation +# -expected length 63, actual 79 +# === +# - is raised when non-ascii role contains only ~40 *characters* and connection charset = UTF8. +# Sent letter to Alex, 23.06.2018 09:21, waiting for reply. +# +# +# tracker_id: CORE-5593 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set names utf8; + set wng off; + set list on; + set bail on; + + create or alter user tmp$c5593 password '123' revoke admin role; + commit; + + --revoke all on all from tmp$c5593; --> led to crash on 4.0.0.1036 + --commit; + + create or alter view v_role_info as + select + current_user as who_am_i, + current_role as my_current_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 chief; + create role "CHIEF OF TRANSPORT AND LOGISTICS DEPARTMENT"; + create role "chief of financial and accounting department"; + commit; + + grant chief to user tmp$c5593; + grant "CHIEF OF TRANSPORT AND LOGISTICS DEPARTMENT" to user tmp$c5593; + grant "chief of financial and accounting department" to user tmp$c5593; + commit; + --show grants; + grant select on v_role_info to user tmp$c5593; + commit; + + --set echo on; + + connect '$(DSN)' + user tmp$c5593 + password '123' + role chief + ; + select * from v_role_info where my_current_role = r_name; + commit; + + connect '$(DSN)' + user tmp$c5593 + password '123' + role "CHIEF OF TRANSPORT AND LOGISTICS DEPARTMENT" + ; + select * from v_role_info where my_current_role = r_name; + commit; + + connect '$(DSN)' + user tmp$c5593 + password '123' + role "chief of financial and accounting department" + ; + + -- ########################################### + -- Before fix this statement returned FALSE as + -- result of rdb$role_in_use(rdb$role_name) + -- ########################################### + select * from v_role_info where my_current_role = r_name; + commit; + + -- cleanup + connect '$(DSN)' user sysdba password 'masterkey'; + drop user tmp$c5593; + commit; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHO_AM_I TMP$C5593 + MY_CURRENT_ROLE CHIEF + R_NAME CHIEF + R_OWNER SYSDBA + R_IN_USE + + WHO_AM_I TMP$C5593 + MY_CURRENT_ROLE CHIEF OF TRANSPORT AND LOGISTICS DEPARTMENT + R_NAME CHIEF OF TRANSPORT AND LOGISTICS DEPARTMENT + R_OWNER SYSDBA + R_IN_USE + + WHO_AM_I TMP$C5593 + MY_CURRENT_ROLE chief of financial and accounting department + R_NAME chief of financial and accounting department + R_OWNER SYSDBA + R_IN_USE + """ + +@pytest.mark.version('>=4.0') +def test_core_5593_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5598.py b/tests/bugs/test_core_5598.py new file mode 100644 index 00000000..f0d4e9c3 --- /dev/null +++ b/tests/bugs/test_core_5598.py @@ -0,0 +1,184 @@ +#coding:utf-8 +# +# id: bugs.core_5598 +# title: Error "block size exceeds implementation restriction" while inner joining large datasets with a long key using the HASH JOIN plan +# decription: +# 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" +# If test table that serves as the source for HJ has record length about 65 Kb than not less than 16K records must be added there. +# If we use charset UTF8 than record length in bytes will be 8 times of declared field_len, so we declare field with len = 8191 charactyer +# (and this is current implementation limit). +# Than we add into this table >= 16Kb rows of unicode (NON-ascii!) characters. +# Finally, we launch query against this table and this query will use hash join because of missed indices. +# We have to check that NO errors occured during this query. +# +# Discuss with dimitr: letters 08-jan-2018 .. 06-feb-2018. +# Confirmed bug on: +# 3.0.3.32838 +# 4.0.0.838 +# Works fine on: +# 3.0.4.32939 (SS, CS) - time ~ 29-32" +# 4.0.0.945 (SS, CS) - time ~ 29-32" +# +# tracker_id: CORE-5598 +# min_versions: ['3.0.3'] +# versions: 3.0.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.3 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('.*RECORD LENGTH:[ \t]+[\\d]+[ \t]*\\)', ''), ('.*COUNT[ \t]+[\\d]+', '')] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import sys +# import os +# import subprocess +# from subprocess import Popen +# from fdb import services +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# fdb_file=db_conn.database_name +# db_conn.close() +# +# # Threshold: minimal records that is to be inserted in order to reproduce runtime exception +# # 'unable to allocate memory from OS': +# MIN_RECS_TO_ADD = 17000 +# +# fbs = fdb.services.connect( host = 'localhost:service_mgr' ) +# fbs.set_write_mode( database = fdb_file, mode = fdb.services.WRITE_BUFFERED ) +# fbs.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# db_conn=fdb.connect(dsn = dsn, charset = 'utf8') +# db_conn.execute_immediate( 'create table test(id int, s varchar(8191))' ) +# db_conn.commit() +# cur=db_conn.cursor() +# cur.execute( "insert into test( id, s ) select row_number()over(), lpad('', 8191, 'Алексей, Łukasz, Máté, François, Jørgen, Νικόλαος') from rdb$types,rdb$types rows %d" % MIN_RECS_TO_ADD) +# db_conn.commit() +# db_conn.close() +# +# isql_cmd=''' +# set list on; +# --show version; +# set explain on; +# select count(*) from test a join test b using(id, s); +# set explain off; +# quit; +# select +# m.MON$STAT_ID +# ,m.MON$STAT_GROUP +# ,m.MON$MEMORY_USED +# ,m.MON$MEMORY_ALLOCATED +# ,m.MON$MAX_MEMORY_USED +# ,m.MON$MAX_MEMORY_ALLOCATED +# from mon$database d join mon$memory_usage m using (MON$STAT_ID) +# ; +# ''' +# +# isql_run=open( os.path.join(context['temp_directory'],'tmp_isql_5596.sql'), 'w') +# isql_run.write( isql_cmd ) +# isql_run.close() +# +# #----------------------------------- +# isql_log=open( os.path.join(context['temp_directory'],'tmp_isql_5596.log'), 'w') +# isql_err=open( os.path.join(context['temp_directory'],'tmp_isql_5596.err'), 'w') +# +# p_isql = subprocess.call( [context['isql_path'], dsn, '-i', isql_run.name ], stdout=isql_log, stderr=isql_err ) +# +# flush_and_close( isql_log ) +# flush_and_close( isql_err ) +# +# +# # do NOT remove this delay: +# time.sleep(1) +# +# # STDOUT must contain: +# # Select Expression +# # -> Aggregate +# # -> Filter +# # -> Hash Join (inner) +# # -> Table "TEST" as "B" Full Scan +# # -> Record Buffer (record length: 32793) +# # -> Table "TEST" as "A" Full Scan +# # +# # COUNT 17000 +# +# with open(isql_log.name,'r') as f: +# for line in f: +# if line.rstrip(): +# print('STDOUT:' + line.upper() ) +# +# with open(isql_err.name,'r') as f: +# for line in f: +# if line.rstrip(): +# print('UNEXPECTED STDERR:' + line.upper() ) +# +# +# # cleanup: +# ########## +# time.sleep(1) +# cleanup( ( isql_run, isql_log, isql_err ) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + STDOUT:SELECT EXPRESSION + STDOUT: -> AGGREGATE + STDOUT: -> FILTER + STDOUT: -> HASH JOIN (INNER) + STDOUT: -> TABLE "TEST" AS "B" FULL SCAN + STDOUT: -> RECORD BUFFER (RECORD LENGTH: 32793) + STDOUT: -> TABLE "TEST" AS "A" FULL SCAN + STDOUT:COUNT 17000 + """ + +@pytest.mark.version('>=3.0.3') +@pytest.mark.xfail +def test_core_5598_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5600.py b/tests/bugs/test_core_5600.py new file mode 100644 index 00000000..e176d505 --- /dev/null +++ b/tests/bugs/test_core_5600.py @@ -0,0 +1,79 @@ +#coding:utf-8 +# +# id: bugs.core_5600 +# title: Invalid blob id when add a new blob column of type text and update another field +# decription: +# Reproduced bug on WI-V3.0.3.32813, WI-T4.0.0.767. +# All fine on WI-T4.0.0.778. +# +# tracker_id: CORE-5600 +# min_versions: ['3.0.3'] +# versions: 3.0.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.3 +# resources: None + +substitutions_1 = [('BLOB_ID_.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + recreate table operation ( + id bigint not null, + name blob sub_type text character set utf8 default '' not null, + d_value double precision default 0 not null + ); + + alter table operation add constraint operation_pk_1 primary key ( id ); + + insert into operation(id, name, d_value ) + select row_number()over() , 'foo', 1 + from rdb$types + rows 3 + ; + commit; + + alter table operation add surname blob sub_type text character set utf8 default 'bar' not null; + + update operation set id=-id where id=2; + + -- NB: do _not_ put "COMMIT;" here! + + set blob all; + set list on; + select + id + ,name as blob_id_1 + ,surname as blob_id_2 + from operation where abs(id) in (1,2,3); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + foo + bar + + ID -2 + foo + bar + + ID 3 + foo + bar + """ + +@pytest.mark.version('>=3.0.3') +def test_core_5600_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5606.py b/tests/bugs/test_core_5606.py new file mode 100644 index 00000000..d4adb6cf --- /dev/null +++ b/tests/bugs/test_core_5606.py @@ -0,0 +1,106 @@ +#coding:utf-8 +# +# id: bugs.core_5606 +# title: Add expression index name to exception message if computation failed +# decription: +# 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. +# +# Checked on 4.0.0.2173. +# +# tracker_id: CORE-5606 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test( + id int + ,x int + ,y int + ,r double precision + ,s varchar(12) default 'DB_NAME' + ); + create index test_eval1 on test computed by ( x/id ); + insert into test(id, x) values(0, 1); + rollback; + drop index test_eval1; + + create index test_eval2 on test computed by ( log10(r-15) ); + insert into test(id, r) values(1, 12); + rollback; + drop index test_eval2; + + create index test_eval3 on test computed by ( rdb$get_context('SYSTEM', s ) ); + insert into test(id, s) values(2, 'FOO_&_BAR'); + rollback; + drop index test_eval3; + + create index test_eval4 on test computed by ( mod(x , (y-x) ) ); + insert into test(id, x, y) values(3, 10, 10); + rollback; + drop index test_eval4; + + create index test_eval5 on test computed by ( substring(s from x for id+y) ); + insert into test(id, x, y, s) values( 4, 3, -7, 'qwerty' ); + drop index test_eval5; + + set count on; + set list on; + select id, s from test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ +expected_stderr_1 = """ + 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. + """ + +@pytest.mark.version('>=4.0') +def test_core_5606_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5612.py b/tests/bugs/test_core_5612.py new file mode 100644 index 00000000..166badc0 --- /dev/null +++ b/tests/bugs/test_core_5612.py @@ -0,0 +1,63 @@ +#coding:utf-8 +# +# id: bugs.core_5612 +# title: Gradual slowdown compilation (create, recreate or drop) of views +# decription: +# Checked on 4.0.0.1479: OK, 1.336s. +# +# tracker_id: CORE-5612 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + select ri.rdb$index_id idx_id,rs.rdb$field_position pos, rs.rdb$field_name key + from rdb$indices ri + left join rdb$index_segments rs on ri.rdb$index_name = rs.rdb$index_name + where ri.rdb$relation_name = upper('rdb$dependencies') + order by 1,2; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + IDX_ID 1 + POS 0 + KEY RDB$DEPENDENT_NAME + IDX_ID 1 + POS 1 + KEY RDB$DEPENDENT_TYPE + IDX_ID 2 + POS 0 + KEY RDB$DEPENDED_ON_NAME + + IDX_ID 2 + POS 1 + KEY RDB$DEPENDED_ON_TYPE + IDX_ID 2 + POS 2 + KEY RDB$FIELD_NAME + + Records affected: 5 + """ + +@pytest.mark.version('>=4.0') +def test_core_5612_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5618.py b/tests/bugs/test_core_5618.py new file mode 100644 index 00000000..b44bfe3f --- /dev/null +++ b/tests/bugs/test_core_5618.py @@ -0,0 +1,213 @@ +#coding:utf-8 +# +# id: bugs.core_5618 +# title: Part of the pages of the second level blobs is not released when deleting relations. +# decription: +# We create table with blob field and write into it binary data with length that +# is too big to store such blob as level-0 and level-1. Filling is implemented as +# specified in: +# http://pythonhosted.org/fdb/differences-from-kdb.html#stream-blobs +# Then we drop table and close connection. +# Finally, we obtain firebird.log, run full validation (like 'gfix -v -full' does) and get firebird.log again. +# Comparison of two firebird.log versions should give only one difference related to warnings, and they count +# must be equal to 0. +# +# Reproduced on 3.0.3.32837, got lot of warnings in firebird.log when did usual validation ('gfix -v -full ...') +# Checked on: +# 30SS, build 3.0.3.32856: OK, 4.047s. +# 40SS, build 4.0.0.834: OK, 8.266s. +# +# tracker_id: CORE-5618 +# min_versions: ['3.0.3'] +# versions: 3.0.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table test(b blob sub_type 0); + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import zipfile +# import difflib +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# this_fdb = db_conn.database_name +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# def svc_get_fb_log( f_fb_log ): +# +# import subprocess +# +# subprocess.call([ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# "action_get_fb_log" +# ], +# stdout=f_fb_log, stderr=subprocess.STDOUT +# ) +# return +# +# +# ##################################################################### +# # Move database to FW = OFF in order to increase speed of insertions and output its header info: +# +# fwoff_log=open( os.path.join(context['temp_directory'],'tmp_fw_off_5618.log'), 'w') +# subprocess.call( [ context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", +# "prp_write_mode", "prp_wm_async", +# "dbname", this_fdb +# ], +# stdout=fwoff_log, +# stderr=subprocess.STDOUT +# ) +# flush_and_close( fwoff_log ) +# +# zf = zipfile.ZipFile( os.path.join(context['files_location'],'core_5618.zip') ) +# blob_src = 'core_5618.bin' +# zf.extract( blob_src, '$(DATABASE_LOCATION)') +# zf.close() +# +# con1 = fdb.connect(dsn = dsn) +# +# cur1=con1.cursor() +# blob_src = ''.join( ('$(DATABASE_LOCATION)', blob_src) ) +# +# blob_handle = open( blob_src, 'rb') +# cur1.execute('insert into test(b) values(?)',[blob_handle]) +# blob_handle.close() +# +# cur1.close() +# con1.execute_immediate('drop table test'); +# con1.commit() +# con1.close() +# +# +# f_fblog_before=open( os.path.join(context['temp_directory'],'tmp_4337_fblog_before.txt'), 'w') +# svc_get_fb_log( f_fblog_before ) +# flush_and_close( f_fblog_before ) +# +# +# ########################################################## +# # Run full validation (this is what 'gfix -v -full' does): +# +# val_log=open( os.path.join(context['temp_directory'],'tmp_onval_5618.log'), 'w') +# +# subprocess.call( [context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_repair", +# "rpr_validate_db", +# "rpr_full", +# "dbname", this_fdb +# ], +# stdout=val_log, +# stderr=subprocess.STDOUT +# ) +# +# flush_and_close( val_log ) +# +# +# # Get content of firebird.log AFTER test finish. +# ############################# +# +# f_fblog_after=open( os.path.join(context['temp_directory'],'tmp_4337_fblog_after.txt'), 'w') +# svc_get_fb_log( f_fblog_after ) +# flush_and_close( f_fblog_after ) +# +# +# # Compare firebird.log versions BEFORE and AFTER this test: +# ###################### +# +# oldfb=open(f_fblog_before.name, 'r') +# newfb=open(f_fblog_after.name, 'r') +# +# difftext = ''.join(difflib.unified_diff( +# oldfb.readlines(), +# newfb.readlines() +# )) +# oldfb.close() +# newfb.close() +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_4337_diff.txt'), 'w') +# f_diff_txt.write(difftext) +# flush_and_close( f_diff_txt ) +# +# +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# if line.startswith('+') and 'warning'.upper() in line.upper(): +# print( 'DIFF IN FIREBIRD.LOG: ' + (' '.join(line.split()).upper()) ) +# +# with open( fwoff_log.name,'r') as f: +# for line in f: +# print( ''.join( ('Unexpected line in ', fwoff_log.name, ':', line ) ) ) +# +# with open( val_log.name,'r') as f: +# for line in f: +# print( ''.join( ('Unexpected line in ', val_log.name, ':', line ) ) ) +# +# +# # Cleanup: +# ########## +# time.sleep(1) +# cleanup( (f_fblog_before, f_fblog_after, f_diff_txt, val_log, blob_handle, fwoff_log) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DIFF IN FIREBIRD.LOG: + VALIDATION FINISHED: 0 ERRORS, 0 WARNINGS, 0 FIXED + """ + +@pytest.mark.version('>=3.0.3') +@pytest.mark.xfail +def test_core_5618_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5620.py b/tests/bugs/test_core_5620.py new file mode 100644 index 00000000..521b6f31 --- /dev/null +++ b/tests/bugs/test_core_5620.py @@ -0,0 +1,72 @@ +#coding:utf-8 +# +# id: bugs.core_5620 +# title: Add builtin functions FIRST_DAY and LAST_DAY +# decription: +# Checked on: 4.0.0.783: OK, 0.781s. +# +# tracker_id: CORE-5620 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select + first_day(of month from date '2017-09-15') -- 2017-09-01 + ,first_day(of year from date '2017-09-15') -- 2017-01-01 + ,first_day(of week from timestamp '2017-11-01 12:13:14.5678') -- 2017-10-29 12:13:14.5678 + ,last_day(of month from date '2017-09-15') -- 2017-09-30 + ,last_day(of year from date '2017-09-15') -- 2017-12-31 + ,last_day(of week from timestamp '2017-11-01 12:13:14.5678') -- 2017-11-04 12:13:14.5678 + from rdb$database; + + select + last_day(of month from date '2000-02-05') -- 2000.02.29 + ,last_day(of month from date '2001-02-05') -- 2001.02.28 + ,last_day(of month from date '2004-02-05') -- 2004.02.29 + ,last_day(of month from date '2100-02-05') -- 2100.02.28 + from rdb$database; + + + select + last_day(of week from date '2008-12-28') -- 2009.01.03 + ,first_day(of week from date '2009-01-03') -- 2008.12.28 + from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + FIRST_DAY 2017-09-01 + FIRST_DAY 2017-01-01 + FIRST_DAY 2017-10-29 12:13:14.5678 + LAST_DAY 2017-09-30 + LAST_DAY 2017-12-31 + LAST_DAY 2017-11-04 12:13:14.5678 + LAST_DAY 2000-02-29 + LAST_DAY 2001-02-28 + LAST_DAY 2004-02-29 + LAST_DAY 2100-02-28 + LAST_DAY 2009-01-03 + FIRST_DAY 2008-12-28 + """ + +@pytest.mark.version('>=4.0') +def test_core_5620_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5630.py b/tests/bugs/test_core_5630.py new file mode 100644 index 00000000..35f2a07d --- /dev/null +++ b/tests/bugs/test_core_5630.py @@ -0,0 +1,147 @@ +#coding:utf-8 +# +# id: bugs.core_5630 +# title: Shadow file is can not be created during restore when -use_all_space option is used +# decription: +# Confirmed bug on WI-V3.0.3.32805, WI-T4.0.0.789. +# Restore process failed with messages: +# === +# gbak: ERROR:I/O error during "ReadFile" operation for file +# gbak: ERROR: Error while trying to read from file +# gbak: ERROR: // localized message +# gbak:Exiting before completion due to errors +# === +# Works OK on: +# fb30Cs, build 3.0.3.32832: OK, 14.766s. +# FB30SS, build 3.0.3.32832: OK, 5.875s. +# FB40CS, build 4.0.0.796: OK, 7.344s. +# FB40SS, build 4.0.0.796: OK, 4.531s. +# +# tracker_id: CORE-5630 +# min_versions: ['3.0.3'] +# versions: 3.0.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# #------------------------------------------- +# def del_tmp_files(f_list): +# import os +# for i in range(len(f_list)): +# if os.path.isfile(f_list[i]): +# os.remove(f_list[i]) +# #------------------------------------------- +# +# n_prefix="$(DATABASE_LOCATION)bugs.tmp.core.5630" +# fdb_file=n_prefix + ".fdb" +# shd_file=n_prefix + ".shd" +# fbk_file=n_prefix + ".fbk" +# +# del_tmp_files( (fdb_file, shd_file, fbk_file) ) +# +# usr=user_name +# pwd=user_password +# +# sql_text=''' +# set bail on; +# set list on; +# +# create database 'localhost:%(fdb_file)s' user '%(usr)s' password '%(pwd)s'; +# +# 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('bugs.tmp.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)s'; +# commit; +# set list on; +# select * from v_shadow_info; +# select hash( list(s) ) as s_hash_before from test; +# quit; +# ''' +# +# f_init_ddl = open( os.path.join(context['temp_directory'],'tmp_5630_ddl.sql'), 'w') +# f_init_ddl.write( sql_text % locals() ) +# f_init_ddl.close() +# +# runProgram( 'isql',[ '-q', '-i', f_init_ddl.name ] ) +# runProgram( 'gbak',['-b', 'localhost:%s' % fdb_file, fbk_file ] ) +# +# del_tmp_files( (fdb_file, shd_file) ) +# +# # -------------------------------------- +# # restore using "-use_all_space" switch: +# # -------------------------------------- +# runProgram( 'gbak',['-c', '-use_all_space', fbk_file, 'localhost:%s' % fdb_file ] ) +# +# # Check that we have the same data in DB tables: +# sql_text=''' +# set list on; +# select * from v_shadow_info; +# select hash( list(s) ) as s_hash_after from test; +# ''' +# runProgram( 'isql',[ '-q', 'localhost:%s' % fdb_file ], sql_text ) +# +# +# ############################### +# # Cleanup. +# del_tmp_files( (fdb_file, shd_file, fbk_file, f_init_ddl.name) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$FILE_SEQUENCE 0 + RDB$FILE_START 0 + RDB$FILE_LENGTH 0 + RDB$FILE_FLAGS 1 + RDB$SHADOW_NUMBER 1 + S_HASH_BEFORE 1499836372373901520 + + RDB$FILE_SEQUENCE 0 + RDB$FILE_START 0 + RDB$FILE_LENGTH 0 + RDB$FILE_FLAGS 1 + RDB$SHADOW_NUMBER 1 + S_HASH_AFTER 1499836372373901520 + """ + +@pytest.mark.version('>=3.0.3') +@pytest.mark.xfail +def test_core_5630_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5637.py b/tests/bugs/test_core_5637.py new file mode 100644 index 00000000..aa05fd67 --- /dev/null +++ b/tests/bugs/test_core_5637.py @@ -0,0 +1,218 @@ +#coding:utf-8 +# +# id: bugs.core_5637 +# title: string right truncation on restore of security db +# decription: +# Confirmed bug on 4.0.0.838, got: +# gbak: ERROR:arithmetic exception, numeric overflow, or string truncation +# gbak: ERROR: string right truncation +# gbak: ERROR: expected length 10, actual 13 +# gbak: ERROR:gds_$send failed +# ... +# Checked on: +# 4.0.0.918: OK, 6.516s. +# +# Refactored 25.10.2019: restored DB state must be changed to full shutdown in order to make sure tha all attachments are gone. +# Otherwise got on CS: "WindowsError: 32 The process cannot access the file because it is being used by another process". +# Checked on 4.0.0.1633 SS, CS. +# +# tracker_id: CORE-5637 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import time +# import zipfile +# import difflib +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# def svc_get_fb_log( f_fb_log ): +# +# global subprocess +# +# subprocess.call( [ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# "action_get_fb_log" +# ], +# stdout=f_fb_log, stderr=subprocess.STDOUT +# ) +# return +# +# +# +# zf = zipfile.ZipFile( os.path.join(context['files_location'],'core5637.zip') ) +# tmpfbk = 'core5637-security3.fbk' +# zf.extract( tmpfbk, '$(DATABASE_LOCATION)') +# zf.close() +# +# tmpfbk='$(DATABASE_LOCATION)'+tmpfbk +# tmpfdb='$(DATABASE_LOCATION)'+'tmp_5637_check_restored.fdb' +# +# f_fblog_before=open( os.path.join(context['temp_directory'],'tmp_5637_fblog_before.txt'), 'w') +# svc_get_fb_log( f_fblog_before ) +# flush_and_close( f_fblog_before ) +# +# +# f_restore_log=open( os.path.join(context['temp_directory'],'tmp_5637_check_restored.log'), 'w') +# subprocess.check_call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_restore", +# "bkp_file", tmpfbk, +# "dbname", tmpfdb, +# "res_replace", +# "verbose" +# ], +# stdout=f_restore_log, +# stderr=subprocess.STDOUT) +# flush_and_close( f_restore_log ) +# +# f_fblog_after=open( os.path.join(context['temp_directory'],'tmp_5637_fblog_after.txt'), 'w') +# svc_get_fb_log( f_fblog_after ) +# flush_and_close( f_fblog_after ) +# +# +# f_validation_log=open( os.path.join(context['temp_directory'],'tmp_5637_validation.log'), 'w') +# subprocess.check_call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_validate", +# "dbname", tmpfdb, +# ], +# stdout=f_validation_log, +# stderr=subprocess.STDOUT) +# flush_and_close( f_validation_log ) +# +# #time.sleep(1) +# +# # 25.10.2019: add full shutdown to forcedly drop all attachments. +# ## |||||||||||||||||||||||||||| +# ## ###################################||| 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 +# ## ############################################################################################# +# +# f_shutdown_log=open( os.path.join(context['temp_directory'],'tmp_5637_shutdown.log'), 'w') +# +# subprocess.call( [context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "prp_shutdown_mode", "prp_sm_full", "prp_shutdown_db", "0", "dbname", tmpfdb, +# ], +# stdout = f_shutdown_log, +# stderr = subprocess.STDOUT +# ) +# +# flush_and_close( f_shutdown_log ) +# +# +# # Compare firebird.log versions BEFORE and AFTER this test: +# ###################### +# +# oldfb=open(f_fblog_before.name, 'r') +# newfb=open(f_fblog_after.name, 'r') +# +# difftext = ''.join(difflib.unified_diff( +# oldfb.readlines(), +# newfb.readlines() +# )) +# oldfb.close() +# newfb.close() +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_5637_diff.txt'), 'w') +# f_diff_txt.write(difftext) +# flush_and_close( f_diff_txt ) +# +# # Check logs: +# ############# +# with open( f_restore_log.name,'r') as f: +# for line in f: +# if 'Error'.upper() in line.upper(): +# print( 'UNEXPECTED ERROR IN RESTORE LOG: ' + (' '.join(line.split()).upper()) ) +# +# with open( f_validation_log.name,'r') as f: +# for line in f: +# if 'Error'.upper() in line.upper(): +# print( 'UNEXPECTED ERROR IN VALIDATION LOG: ' + (' '.join(line.split()).upper()) ) +# +# with open( f_shutdown_log.name,'r') as f: +# for line in f: +# if line.split(): +# print( 'UNEXPECTED OUTPUT IN DB SHUTDOWN LOG: ' + (' '.join(line.split()).upper()) ) +# +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# if line.startswith('+'): +# print( 'UNEXPECTED DIFF IN FIREBIRD.LOG: ' + (' '.join(line.split()).upper()) ) +# +# +# # Cleanup: +# ########## +# time.sleep(1) +# cleanup( (f_restore_log,f_validation_log,f_shutdown_log,f_fblog_before,f_fblog_after,f_diff_txt, tmpfbk,tmpfdb) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_5637_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5638.py b/tests/bugs/test_core_5638.py new file mode 100644 index 00000000..eb9a0996 --- /dev/null +++ b/tests/bugs/test_core_5638.py @@ -0,0 +1,162 @@ +#coding:utf-8 +# +# id: bugs.core_5638 +# title: Wrong result with index on case-insensitive collation using NUMERIC-SORT +# decription: +# Changed collation to nn_NO (Norwegian) because there are two letters +# which did produce some problems in the past builds (in ~2015): +# 'ø', 'Ø' -- U+C3B8 LATIN SMALL LETTER O WITH STROKE; U+C398 LATIN CAPITAL LETTER O WITH STROKE +# 'æ', 'Æ' -- U+00E6 LATIN SMALL LETTER AE; U+00C6 LATIN CAPITAL LETTER AE +# ################### +# See also: CORE-1945 +# ################### +# +# Checked on Win XP, builds: +# 3.0.3.32813: OK, 2.000s. +# 4.0.0.767: OK, 1.187s. +# NB: I intentionally excluded 'similar to' from "OR"-list of predicates because it changes plan of execution. +# This will be investigated later. +# +# tracker_id: CORE-5638 +# min_versions: ['3.0.3'] +# versions: 3.0.3 +# qmid: bugs.core_5638 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create collation utf_sv_ci + for utf8 + from unicode + case insensitive + --'locale=sv_SE' + 'locale=nn_NO' + ; + + create collation utf_sv_ci_ns + for utf8 + from unicode + case insensitive + --'locale=sv_SE;NUMERIC-SORT=1' + 'locale=nn_NO;NUMERIC-SORT=1' + ; + -- nn_NO + -- da_DK + + set echo off; + + commit; + + create table test ( + f01_case_insens varchar(5) character set utf8 collate utf_sv_ci, + f01_ci_numsort varchar(5) character set utf8 collate utf_sv_ci_ns); + + commit; + + insert into test(f01_case_insens, f01_ci_numsort) values('20', '20'); + insert into test(f01_case_insens, f01_ci_numsort) values('1', '1' ); + insert into test(f01_case_insens, f01_ci_numsort) values('2', '2' ); + insert into test(f01_case_insens, f01_ci_numsort) values('10', '10'); + insert into test(f01_case_insens, f01_ci_numsort) values('a', 'a' ); + insert into test(f01_case_insens, f01_ci_numsort) values('A', 'A' ); + insert into test(f01_case_insens, f01_ci_numsort) values('aa', 'aa'); + insert into test(f01_case_insens, f01_ci_numsort) values('Aa', 'Aa'); + insert into test(f01_case_insens, f01_ci_numsort) values('AA', 'AA'); + insert into test(f01_case_insens, f01_ci_numsort) values('b', 'b' ); + insert into test(f01_case_insens, f01_ci_numsort) values('B', 'B' ); + insert into test(f01_case_insens, f01_ci_numsort) values('o', 'o' ); + insert into test(f01_case_insens, f01_ci_numsort) values('O', 'O' ); + insert into test(f01_case_insens, f01_ci_numsort) values('z', 'z' ); + insert into test(f01_case_insens, f01_ci_numsort) values('Z', 'Z' ); + insert into test(f01_case_insens, f01_ci_numsort) values('å', 'å' ); + insert into test(f01_case_insens, f01_ci_numsort) values('Å', 'Å' ); + insert into test(f01_case_insens, f01_ci_numsort) values('ä', 'ä' ); + insert into test(f01_case_insens, f01_ci_numsort) values('Ä', 'Ä' ); + insert into test(f01_case_insens, f01_ci_numsort) values('ö', 'ö' ); + insert into test(f01_case_insens, f01_ci_numsort) values('Ö', 'Ö' ); + -- from Danish and Norwegian alphabet: + insert into test(f01_case_insens, f01_ci_numsort) values('ø', 'Ø' ); + insert into test(f01_case_insens, f01_ci_numsort) values('æ', 'Æ' ); + commit; + + create index idx_ci on test(f01_case_insens); + create index idx_ci_ns on test(f01_ci_numsort); + commit; + + set list on; + --set plan on; + set count on; + + select f01_case_insens + from test + where + f01_case_insens in('b','å') + or + f01_case_insens >= 'a' and f01_case_insens <= 'a' + or + f01_case_insens between 'ö' and 'ö' + or + f01_case_insens in ( 'ø', 'æ' ) + --or f01_case_insens similar to 'ä' + order by f01_case_insens asc; + + select f01_ci_numsort + from test + where + f01_ci_numsort in('b','å') + or + f01_ci_numsort >= 'a' and f01_ci_numsort <= 'a' + or + f01_ci_numsort between 'ö' and 'ö' + or + f01_ci_numsort in ( 'ø', 'æ' ) + -- !! "similar to" changes HERE plan to: PLAN (TEST ORDER IDX_CI_NS) -- + --or f01_ci_numsort similar to 'ä' + order by f01_ci_numsort asc + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F01_CASE_INSENS a + F01_CASE_INSENS A + F01_CASE_INSENS å + F01_CASE_INSENS Å + F01_CASE_INSENS æ + F01_CASE_INSENS b + F01_CASE_INSENS B + F01_CASE_INSENS ö + F01_CASE_INSENS Ö + F01_CASE_INSENS ø + Records affected: 10 + + F01_CI_NUMSORT a + F01_CI_NUMSORT A + F01_CI_NUMSORT å + F01_CI_NUMSORT Å + F01_CI_NUMSORT Æ + F01_CI_NUMSORT b + F01_CI_NUMSORT B + F01_CI_NUMSORT ö + F01_CI_NUMSORT Ö + F01_CI_NUMSORT Ø + Records affected: 10 + """ + +@pytest.mark.version('>=3.0.3') +def test_core_5638_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5645.py b/tests/bugs/test_core_5645.py new file mode 100644 index 00000000..a2d28535 --- /dev/null +++ b/tests/bugs/test_core_5645.py @@ -0,0 +1,167 @@ +#coding:utf-8 +# +# id: bugs.core_5645 +# title: Wrong transaction can be passed to external engine +# decription: +# Implemented according to notes given by Adriano in the ticket 27-oct-2017 02:41. +# Checked on: +# 4.0.0.1743 SS: 2.719s. +# 4.0.0.1740 SC: 2.531s. +# 4.0.0.1714 CS: 11.750s. +# 3.0.6.33236 SS: 1.141s. +# 3.0.6.33236 CS: 2.563s. +# 3.0.5.33221 SC: 3.812s. +# tracker_id: CORE-5645 +# min_versions: ['3.0.3'] +# versions: 3.0.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.3 +# resources: None + +substitutions_1 = [('INFO_BLOB_ID.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# this_db = db_conn.database_name +# fb_major=db_conn.engine_version +# +# #-------------------------------------------- +# +# 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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# table_ddl=''' +# create table persons ( +# id integer not null, +# name varchar(60) not null, +# address varchar(60), +# info blob sub_type text +# ); +# ''' +# +# +# fdb_repl = os.path.join(context['temp_directory'],'tmp_5645_repl.fdb') +# cleanup( (fdb_repl,) ) +# +# con_repl = fdb.create_database( dsn = 'localhost:%(fdb_repl)s' % locals() ) +# con_repl.execute_immediate( table_ddl ) +# con_repl.commit() +# con_repl.close() +# +# db_conn.execute_immediate( table_ddl ) +# db_conn.commit() +# +# ddl_for_replication=''' +# create table replicate_config ( +# name varchar(31) not null, +# data_source varchar(255) not null +# ); +# +# insert into replicate_config (name, data_source) +# values ('ds1', '%(fdb_repl)s'); +# +# create trigger persons_replicate +# after insert on persons +# external name 'udrcpp_example!replicate!ds1' +# engine udr; +# +# create trigger persons_replicate2 +# after insert on persons +# external name 'udrcpp_example!replicate_persons!ds1' +# engine udr; +# commit; +# +# ''' % locals() +# +# f_apply_ddl_sql = open( os.path.join(context['temp_directory'],'tmp_5645.sql'), 'w', buffering = 0) +# f_apply_ddl_sql.write( ddl_for_replication ) +# flush_and_close( f_apply_ddl_sql ) +# +# f_apply_ddl_log = open( '.'.join( (os.path.splitext( f_apply_ddl_sql.name )[0], 'log') ), 'w', buffering = 0) +# subprocess.call( [ context['isql_path'], dsn, '-q', '-i', f_apply_ddl_sql.name ], stdout = f_apply_ddl_log, stderr = subprocess.STDOUT) +# flush_and_close( f_apply_ddl_log ) +# +# #-------------------------------- +# +# cur = db_conn.cursor() +# cur.execute( "insert into persons values (1, 'One', 'some_address', 'some_blob_info')" ) +# db_conn.commit() +# db_conn.close() +# +# if fb_major >= 4.0: +# runProgram( 'isql', ['-q', dsn], 'ALTER EXTERNAL CONNECTIONS POOL CLEAR ALL;' ) +# +# runProgram( 'isql', ['-q', 'localhost:%(fdb_repl)s' % locals()], 'set list on; set count on; select id,name,address,info as info_blob_id from persons;rollback; drop database;' ) +# +# cleanup( (f_apply_ddl_sql,f_apply_ddl_log) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + NAME One + ADDRESS some_address + INFO_BLOB_ID 80:0 + some_blob_info + + ID 1 + NAME One + ADDRESS + INFO_BLOB_ID 80:1 + some_blob_info + Records affected: 2 + """ + +@pytest.mark.version('>=3.0.3') +@pytest.mark.xfail +def test_core_5645_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5646.py b/tests/bugs/test_core_5646.py new file mode 100644 index 00000000..9f4ccd96 --- /dev/null +++ b/tests/bugs/test_core_5646.py @@ -0,0 +1,878 @@ +#coding:utf-8 +# +# id: bugs.core_5646 +# title: Parse error when compiling a statement causes memory leak until attachment is disconnected +# decription: +# Test uses DDL and query for well known Einstein task. +# Code of SQL was included inside SP and will be compiled on dynamic basis (using ES mechanism). +# Syntax error was intentionally added into this code, so actually it will not ever run. +# After each call of this SP we have to query mon$ tables in order to detect memory leak, but we have to do this +# TWO times together (and i don't know why it is so). +# Every even run (2nd, 4th,6 th etc) of this query gave memory leak about ~7...9% in previous version. +# +# We repeat in loop of 60 iterations attempt to run SP and then twice query mon$ tables and add results into log. +# Finally, we check that difference in max_memory* fields is ZERO, or (at least) there can be only one difference more +# than threshold. After lot of runs this threshold was set to 1.00 (percent) -- see query below. +# +# Reproduced bug on 4.0.0.800: found memory leak. +# Checked on 4.0.0.834 -- all OK, 2.875s. +# Small memory leak (~1.67...2.5%) still _can_ occur, but only in ONE and ONLY ONE of starting measures. +# +# tracker_id: CORE-5646 +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter view v_memo as select 1 x from rdb$database; + recreate sequence g; + commit; + + recreate table memory_usage_log ( + seq_no int + ,cur_used int + ,cur_alloc int + ,max_used int + ,max_alloc int + ); + + recreate table animal (animal varchar(10) primary key using index pk_animal); + recreate table color (color varchar(10) primary key using index pk_color); + recreate table drink (drink varchar(10) primary key using index pk_drink); + recreate table nation (nation varchar(10) primary key using index pk_nation); + recreate table smoke (smoke varchar(10) primary key using index pk_smoke); + + insert into animal (animal) values ('cat'); + insert into animal (animal) values ('fish'); + insert into animal (animal) values ('dog'); + insert into animal (animal) values ('horse'); + insert into animal (animal) values ('bird'); + + insert into color (color) values ('white'); + insert into color (color) values ('yellow'); + insert into color (color) values ('red'); + insert into color (color) values ('blue'); + insert into color (color) values ('green'); + + insert into drink (drink) values ('cofee'); + insert into drink (drink) values ('milk'); + insert into drink (drink) values ('water'); + insert into drink (drink) values ('beer'); + insert into drink (drink) values ('tee'); + + insert into nation (nation) values ('eng'); + insert into nation (nation) values ('swe'); + insert into nation (nation) values ('deu'); + insert into nation (nation) values ('den'); + insert into nation (nation) values ('nor'); + + insert into smoke (smoke) values ('pall mall'); + insert into smoke (smoke) values ('marlboro'); + insert into smoke (smoke) values ('rothmans'); + insert into smoke (smoke) values ('winfield'); + insert into smoke (smoke) values ('dunhill'); + commit; + + + set term ^; + create or alter procedure sp_invalid_es as + declare bad_sql varchar(12000); + declare c int; + begin + bad_sql = + 'select count(*) from ( + select + a1.animal as h1animal, + d1.drink as h1drink, + n1.nation as h1nation, + s1.smoke as h1smoke, + c1.color as h1color, + + a2.animal as h2animal, + d2.drink as h2drink, + n2.nation as h2nation, + s2.smoke as h2smoke, + c2.color as h2color, + + a3.animal as h3animal, + d3.drink as h3drink, + n3.nation as h3nation, + s3.smoke as h3smoke, + c3.color as h3color, + + a4.animal as h4animal, + d4.drink as h4drink, + n4.nation as h4nation, + s4.smoke as h4smoke, + c4.color as h4color, + + a5.animal as h5animal, + d5.drink as h5drink, + n5.nation as h5nation, + s5.smoke as h5smoke, + c5.color as h5color + from + animal a1, + drink d1, + nation n1, + smoke s1, + color c1, + + animal a2, + drink d2, + nation n2, + smoke s2, + color c2, + + animal a3, + drink d3, + nation n3, + smoke s3, + color c3, + + animal a4, + drink d4, + nation n4, + smoke s4, + color c4, + + animal a5, + drink d5, + nation n5, + smoke s5, + color c5 + where + a1.animal <> a2.animal and + a1.animal <> a3.animal and + a1.animal <> a4.animal and + a1.animal <> a5.animal and + a2.animal <> a3.animal and + a2.animal <> a4.animal and + a2.animal <> a5.animal and + a3.animal <> a4.animal and + a3.animal <> a5.animal and + a4.animal <> a5.animal --and + and + c1.color <> c2.color and + c1.color <> c3.color and + c1.color <> c4.color and + c1.color <> c5.color and + c2.color <> c3.color and + c2.color <> c4.color and + c2.color <> c5.color and + c3.color <> c4.color and + c3.color <> c5.color and + c4.color <> c5.color + and + d1.drink <> d2.drink and + d1.drink <> d3.drink and + d1.drink <> d4.drink and + d1.drink <> d5.drink and + d2.drink <> d3.drink and + d2.drink <> d4.drink and + d2.drink <> d5.drink and + d3.drink <> d4.drink and + d3.drink <> d5.drink and + d4.drink <> d5.drink + and + n1.nation <> n2.nation and + n1.nation <> n3.nation and + n1.nation <> n4.nation and + n1.nation <> n5.nation and + n2.nation <> n3.nation and + n2.nation <> n4.nation and + n2.nation <> n5.nation and + n3.nation <> n4.nation and + n3.nation <> n5.nation and + n4.nation <> n5.nation + and + s1.smoke <> s2.smoke and + s1.smoke <> s3.smoke and + s1.smoke <> s4.smoke and + s1.smoke <> s5.smoke and + s2.smoke <> s3.smoke and + s2.smoke <> s4.smoke and + s2.smoke <> s5.smoke and + s3.smoke <> s4.smoke and + s3.smoke <> s5.smoke and + s4.smoke <> s5.smoke + and + -- 1 + ( + (n1.nation = ''eng'' and c1.color = ''red'') or + (n2.nation = ''eng'' and c2.color = ''red'') or + (n3.nation = ''eng'' and c3.color = ''red'') or + (n4.nation = ''eng'' and c4.color = ''red'') or + (n5.nation = ''eng'' and c5.color = ''red'') + ) + and + -- 2 + ( + (n1.nation = ''swe'' and a1.animal = ''dog'') or + (n2.nation = ''swe'' and a2.animal = ''dog'') or + (n3.nation = ''swe'' and a3.animal = ''dog'') or + (n4.nation = ''swe'' and a4.animal = ''dog'') or + (n5.nation = ''swe'' and a5.animal = ''dog'') + ) + and + -- 3 + ( + (n1.nation = ''den'' and d1.drink = ''tee'') or + (n2.nation = ''den'' and d2.drink = ''tee'') or + (n3.nation = ''den'' and d3.drink = ''tee'') or + (n4.nation = ''den'' and d4.drink = ''tee'') or + (n5.nation = ''den'' and d5.drink = ''tee'') + ) + and + -- 4 + ( + (c1.color = ''green'' and c2.color = ''white'') or + (c2.color = ''green'' and c3.color = ''white'') or + (c3.color = ''green'' and c4.color = ''white'') or + (c4.color = ''green'' and c5.color = ''white'') + ) + and + -- 5 + ( + (c1.color = ''green'' and d1.drink = ''coffee'') or + (c2.color = ''green'' and d2.drink = ''coffee'') or + (c3.color = ''green'' and d3.drink = ''coffee'') or + (c4.color = ''green'' and d4.drink = ''coffee'') or + (c5.color = ''green'' and d5.drink = ''coffee'') + ) + and + -- 6 + ( + (s1.smoke = ''pall mall'' and a1.animal = ''bird'') or + (s2.smoke = ''pall mall'' and a2.animal = ''bird'') or + (s3.smoke = ''pall mall'' and a3.animal = ''bird'') or + (s4.smoke = ''pall mall'' and a4.animal = ''bird'') or + (s5.smoke = ''pall mall'' and a5.animal = ''bird'') + ) + and + -- 7 + (d3.drink = ''milk'') + and + -- 8 + ( + (s1.smoke = ''dunhill'' and c1.color = ''yellow'') or + (s2.smoke = ''dunhill'' and c2.color = ''yellow'') or + (s3.smoke = ''dunhill'' and c3.color = ''yellow'') or + (s4.smoke = ''dunhill'' and c4.color = ''yellow'') or + (s5.smoke = ''dunhill'' and c5.color = ''yellow'') + ) + and + -- 9 + (n1.nation = ''nor'') + and + -- 10 + ( + (s1.smoke = ''marlboro'' and a2.animal = ''cat'') or + (s2.smoke = ''marlboro'' and ''cat'' in (a1.animal, a3.animal)) or + (s3.smoke = ''marlboro'' and ''cat'' in (a2.animal, a4.animal)) or + (s4.smoke = ''marlboro'' and ''cat'' in (a3.animal, a5.animal)) or + (s5.smoke = ''marlboro'' and a4.animal = ''cat'') + ) + and + -- 11 + ( + (s1.smoke = ''dunhill'' and a2.animal = ''horse'') or + (s2.smoke = ''dunhill'' and ''cat'' in (a1.animal, a3.animal)) or + (s3.smoke = ''dunhill'' and ''cat'' in (a2.animal, a4.animal)) or + (s4.smoke = ''dunhill'' and ''cat'' in (a3.animal, a5.animal)) or + (s5.smoke = ''dunhill'' and a4.animal = ''horse'') + ) + and + -- 12 + ( + (s1.smoke = ''winfield'' and d1.drink = ''beer'') or + (s2.smoke = ''winfield'' and d2.drink = ''beer'') or + (s3.smoke = ''winfield'' and d3.drink = ''beer'') or + (s4.smoke = ''winfield'' and d4.drink = ''beer'') or + (s5.smoke = ''winfield'' and d5.drink = ''beer'') + ) + and + -- 13 + ( + (n1.nation = ''nor'' and c2.color = ''blue'') or + (n2.nation = ''nor'' and ''blue'' in (c1.color, c3.color)) or + (n3.nation = ''nor'' and ''blue'' in (c2.color, c4.color)) or + (n4.nation = ''nor'' and ''blue'' in (c3.color, c5.color)) or + (n5.nation = ''nor'' and c4.color = ''blue'') + ) + and + -- 14 + ( + (s1.smoke = ''rothmans'' and n1.nation = ''deu'') or + (s2.smoke = ''rothmans'' and n2.nation = ''deu'') or + (s3.smoke = ''rothmans'' and n3.nation = ''deu'') or + (s4.smoke = ''rothmans'' and n4.nation = ''deu'') or + (s5.smoke = ''rothmans'' and n5.nation = ''deu'') + ) + and + -- 15 + ( + (s1.smoke = ''marlboro'' and d2.drink = ''water'') or + (s2.smoke = ''marlboro'' and ''water'' in (d1.drink, d3.drink)) or + (s3.smoke = ''marlboro'' and ''water'' in (d2.drink, d4.drink)) or + (s4.smoke = ''marlboro'' and ''water'' in (d3.drink, d5.drink)) or + (s5.smoke = ''marlboro'' and d4.drink = ''water'') + ) + and and + ) + '; + execute statement ( bad_sql ) into c; + when any do begin end + end + ^ + set term ;^ + commit; + + create or alter view v_memo as + select + gen_id(g,1) as seq_no + ,m.mon$memory_used as cur_used + ,m.mon$memory_allocated as cur_alloc + ,m.mon$max_memory_used as max_used + ,m.mon$max_memory_allocated as max_alloc + 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 + ; + commit; + + --set list on; + + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + + --------------------------------------------------------- + + commit; + execute procedure sp_invalid_es; + + commit; + insert into memory_usage_log select * from v_memo; + commit; + insert into memory_usage_log select * from v_memo; + + + --####################################################### + + set list on; + + set width threshold_violations_count 30; + set width diff_percent_in_max_used_memory 50; + set width diff_percent_in_max_alloc_memory 50; + select + seq_no + ,iif( violations_cnt > 1, 'POOR: ' || violations_cnt || ' times', 'OK') as threshold_violations_count + ,iif( violations_cnt > 1 and diff_used_prc > max_allowed_diff_prc, 'POOR: '|| diff_used_prc ||' - exeeds max allowed percent = ' || max_allowed_diff_prc, 'OK') as diff_percent_in_max_used_memory + ,iif( violations_cnt > 1 and diff_alloc_prc > max_allowed_diff_prc, 'POOR: '|| diff_alloc_prc || ' - exeeds max allowed percent = ' || max_allowed_diff_prc , 'OK') as diff_percent_in_max_alloc_memory + from ( + select a.*, sum( iif(a.diff_used_prc > a.max_allowed_diff_prc or a.diff_alloc_prc > a.max_allowed_diff_prc, 1, 0) )over() as violations_cnt + from ( + select + m.seq_no + ,m.max_used + ,100.00 * m.max_used / nullif( lag(max_used)over(order by seq_no), 0) - 100 diff_used_prc + ,m.max_alloc + ,100.00 * m.max_alloc / nullif( lag(max_alloc)over(order by seq_no), 0) - 100 diff_alloc_prc + ,1.00 as max_allowed_diff_prc + -- ^ + -- | ############################## + -- +------------------------------------- MAX ALLOWED THRESHOLD, PERCENT + -- ############################## + from memory_usage_log m + ) a + --where mod(seq_no,2)=1 and seq_no >= 1 + ) + where mod(seq_no,2)=1 and seq_no >= 1 + order by seq_no + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + SEQ_NO 1 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 3 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 5 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 7 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 9 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 11 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 13 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 15 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 17 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 19 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 21 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 23 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 25 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 27 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 29 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 31 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 33 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 35 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 37 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 39 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 41 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 43 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 45 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 47 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 49 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 51 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 53 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 55 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 57 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + + SEQ_NO 59 + THRESHOLD_VIOLATIONS_COUNT OK + DIFF_PERCENT_IN_MAX_USED_MEMORY OK + DIFF_PERCENT_IN_MAX_ALLOC_MEMORY OK + """ + +@pytest.mark.version('>=4.0') +def test_core_5646_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5647.py b/tests/bugs/test_core_5647.py new file mode 100644 index 00000000..4b925b99 --- /dev/null +++ b/tests/bugs/test_core_5647.py @@ -0,0 +1,85 @@ +#coding:utf-8 +# +# id: bugs.core_5647 +# title: Increase number of formats/versions of views from 255 to 32K +# decription: +# FB40SS, build 4.0.0.789: OK, 3.828s (SS, CS). +# Older version issued: +# Statement failed, SQLSTATE = 54000 +# unsuccessful metadata update +# -TABLE VW1 +# -too many versions +# NB: we have to change FW to OFF in order to increase speed of this test run thus use test_type = Python. +# +# tracker_id: CORE-5647 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.close() +# runProgram('gfix',[dsn,'-w','async']) +# +# script=''' +# set bail on; +# set list on; +# set term ^; +# execute block returns(ret_code smallint) as +# declare n int = 300; +# begin +# while (n > 0) do +# begin +# if (mod(n, 2) = 0) then +# begin +# in autonomous transaction do +# begin +# execute statement 'create or alter view vw1 (dump1) as select 1 from rdb$database'; +# end +# end +# else +# begin +# in autonomous transaction do +# begin +# execute statement 'create or alter view vw1 (dump1, dump2) as select 1, 2 from rdb$database'; +# end +# end +# n = n - 1; +# end +# ret_code = -abs(n); +# suspend; +# end ^ +# set term ;^ +# quit; +# ''' +# runProgram('isql',[dsn],script) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RET_CODE 0 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_5647_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5648.py b/tests/bugs/test_core_5648.py new file mode 100644 index 00000000..ea93e673 --- /dev/null +++ b/tests/bugs/test_core_5648.py @@ -0,0 +1,255 @@ +#coding:utf-8 +# +# id: bugs.core_5648 +# title: Avoid serialization of isc_attach_database calls issued by EXECUTE STATEMENT implementation +# decription: +# We use special IP = 192.0.2.2 as never reachable address thus any attempt to connect it will fail. +# Currently FB tries to establish connect to this host about 20-22 seconds. +# We launch 1st ISQL in Async mode (using subprocess.Popen) with task to establish connect to this host. +# At the same time we launch 2nd ISQL with EDS to localhost and the same DB as test uses. +# Second ISQL must do its job instantly, despite of hanging 1st ISQl, and time for this is about 50 ms. +# We use threshold and compare time for which 2nd ISQL did its job. Finally, we ouptput result of this comparison. +# +# ::::::::::::: NOTE ::::::::::::::::::: +# As of current FB snapshots, there is NOT ability to interrupt ISQL which tries to make connect to 192.0.2.2, +# until this ISQL __itself__ make decision that host is unreachable. This takes about 20-22 seconds. +# Also, if we kill this (hanging) ISQL process, than we will not be able to drop database until this time exceed. +# For this reason, it was decided not only to kill ISQL but also run fbsvcmgr with DB full-shutdown command - this +# will ensure that database is really free from any attachments and can be dropped. +# +# ::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +# See also http://tracker.firebirdsql.org/browse/CORE-5609 +# ::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +# +# +# Reproduced bug on 3.0.3.32756 (SC, 15-jul-2017), 4.0.0.690 (SC, 15-jul-2017) +# Passed on: +# 3.0.3.32805: OK, 24.797s (Classic, 21-sep-2017) +# 3.0.3.32828: OK, 25.328s (SuperServer, 08-nov-2017) +# 4.0.0.748: OK, 25.984s (Classic) +# 4.0.0.789: OK, 24.406s (SuperClassic and SuperServer, 08-nov-2017). +# +# tracker_id: CORE-5648 +# min_versions: ['3.0.3'] +# versions: 3.0.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import subprocess +# from subprocess import Popen +# import time +# import difflib +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_file = db_conn.database_name +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# usr=user_name +# pwd=user_password +# remote_host = '192.0.2.2' +# +# eds_query=''' +# set bail on; +# set list on; +# --select current_timestamp as " " from rdb$database; +# set term ^; +# execute block as +# declare c smallint; +# declare remote_host varchar(50) = '%(remote_host)s'; -- never unreachable: 192.0.2.2 +# begin +# rdb$set_context('USER_SESSION','DTS_BEG', cast('now' as timestamp) ); +# execute statement 'select 1 from rdb$database' +# on external remote_host || ':' || rdb$get_context('SYSTEM', 'DB_NAME') +# as user '%(usr)s' password '%(pwd)s' +# into c; +# end +# ^ +# set term ;^ +# --select current_timestamp as " " from rdb$database; +# select iif( waited_ms < max_wait_ms, +# 'OK: second EDS was fast', +# 'FAILED: second EDS waited too long, ' || waited_ms || ' ms - more than max_wait_ms='||max_wait_ms +# ) as result_msg +# from ( +# select +# datediff( millisecond from cast( rdb$get_context('USER_SESSION','DTS_BEG') as timestamp) to current_timestamp ) as waited_ms +# ,500 as max_wait_ms +# -- ^ +# -- | ################# +# -- +-------------------------------- T H R E S H O L D +# -- ################# +# from rdb$database +# ); +# ''' +# +# f_eds_to_unavail_host_sql = open( os.path.join(context['temp_directory'],'tmp_unavail_host_5648.sql'), 'w') +# f_eds_to_unavail_host_sql.write( eds_query % locals() ) +# flush_and_close( f_eds_to_unavail_host_sql ) +# +# remote_host = 'localhost' +# f_eds_to_local_host_sql = open( os.path.join(context['temp_directory'],'tmp_local_host_5648.sql'), 'w') +# f_eds_to_local_host_sql.write( eds_query % locals() ) +# flush_and_close( f_eds_to_local_host_sql ) +# +# +# +# f_eds_to_unavail_host_log = open( os.path.join(context['temp_directory'],'tmp_unavail_host_5648.log'), 'w') +# f_eds_to_unavail_host_err = open( os.path.join(context['temp_directory'],'tmp_unavail_host_5648.err'), 'w') +# p_isql_to_unavail_host=subprocess.Popen( [context['isql_path'], dsn, "-n", "-i", f_eds_to_unavail_host_sql.name ], +# stdout = f_eds_to_unavail_host_log, +# stderr = f_eds_to_unavail_host_err +# ) +# +# # Let ISQL be loaded: +# time.sleep(1) +# +# f_eds_to_local_host_log = open( os.path.join(context['temp_directory'],'tmp_local_host_5648.log'), 'w') +# f_eds_to_local_host_err = open( os.path.join(context['temp_directory'],'tmp_local_host_5648.err'), 'w') +# subprocess.call( [context['isql_path'], dsn, "-n", "-i", f_eds_to_local_host_sql.name ], +# stdout = f_eds_to_local_host_log, +# stderr = f_eds_to_local_host_err +# ) +# +# #............ kill ISQL that is attampting to found 192.0.2.2 host and thus will hang for about 45 seconds ....... +# +# p_isql_to_unavail_host.terminate() +# flush_and_close( f_eds_to_unavail_host_log ) +# flush_and_close( f_eds_to_unavail_host_err ) +# +# flush_and_close( f_eds_to_local_host_log ) +# flush_and_close( f_eds_to_local_host_err ) +# +# # Make DB shutdown and bring online because some internal server process still can be active! +# # If we skip this step than runtime error related to dropping test DB can occur! +# ######################################### +# +# f_db_reset_log=open( os.path.join(context['temp_directory'],'tmp_reset_5648.log'), 'w') +# f_db_reset_err=open( os.path.join(context['temp_directory'],'tmp_reset_5648.err'), 'w') +# +# f_db_reset_log.write('Point before DB shutdown.'+os.linesep) +# f_db_reset_log.seek(0,2) +# subprocess.call( [context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "prp_shutdown_mode", "prp_sm_full", "prp_shutdown_db", "0", +# "dbname", db_file, +# ], +# stdout = f_db_reset_log, +# stderr = f_db_reset_err +# ) +# f_db_reset_log.write(os.linesep+'Point after DB shutdown.'+os.linesep) +# +# subprocess.call( [context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "prp_db_online", +# "dbname", db_file, +# ], +# stdout = f_db_reset_log, +# stderr = f_db_reset_err +# ) +# +# f_db_reset_log.write(os.linesep+'Point after DB online.'+os.linesep) +# flush_and_close( f_db_reset_log ) +# flush_and_close( f_db_reset_err ) +# +# with open( f_eds_to_local_host_log.name,'r') as f: +# for line in f: +# if line.split(): +# print('STDLOG of 2nd EDS: ', ' '.join(line.split()) ) +# +# +# with open( f_eds_to_local_host_err.name,'r') as f: +# for line in f: +# if line.split(): +# print('UNEXPECTED STDERR in '+f_eds_to_local_host_err.name+': '+line) +# +# with open( f_db_reset_log.name,'r') as f: +# for line in f: +# if line.split(): +# print('STDLOG of DB reset: ', ' '.join(line.split()) ) +# +# with open( f_db_reset_err.name,'r') as f: +# for line in f: +# if line.split(): +# print('UNEXPECTED STDERR in '+f_db_reset_log.name+': '+line) +# +# ############################### +# # Cleanup. +# time.sleep(1) +# +# f_list=( +# f_eds_to_local_host_sql +# ,f_eds_to_local_host_log +# ,f_eds_to_local_host_err +# ,f_eds_to_unavail_host_sql +# ,f_eds_to_unavail_host_log +# ,f_eds_to_unavail_host_err +# ,f_db_reset_log +# ,f_db_reset_err +# ) +# cleanup( f_list ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + STDLOG of 2nd EDS: RESULT_MSG OK: second EDS was fast + STDLOG of DB reset: Point before DB shutdown. + STDLOG of DB reset: Point after DB shutdown. + STDLOG of DB reset: Point after DB online. + """ + +@pytest.mark.version('>=3.0.3') +@pytest.mark.xfail +def test_core_5648_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5658.py b/tests/bugs/test_core_5658.py new file mode 100644 index 00000000..ada8269d --- /dev/null +++ b/tests/bugs/test_core_5658.py @@ -0,0 +1,128 @@ +#coding:utf-8 +# +# id: bugs.core_5658 +# title: Execute statement with excess parameters +# decription: +# Checked on 4.0.0.1479: OK, 1.608s. +# +# tracker_id: CORE-5658 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter procedure sp_test as begin end; + commit; + + recreate table test( + id int generated by default as identity constraint pk_test primary key + ,n int + ,t timestamp + ,b boolean + ,s varchar(1) + ); + commit; + + insert into test(id, n ,t, b, s) values( 1, 11, '01.01.2019 01:01:01', false, 'q'); + insert into test(id, n ,t, b, s) values( 2, 11, '01.01.2019 01:01:01', true, 'a'); + insert into test(id, n ,t, b, s) values( 3, 22, '02.02.2019 03:03:03', true, 'z'); + insert into test(id, n ,t, b, s) values( 4, 22, '04.04.2019 04:04:04', false, 'q'); + insert into test(id, n ,t, b, s) values( 5, 22, '05.03.2019 05:05:05', null, 'q'); + insert into test(id, n ,t, b, s) values( 6, 33, '03.03.2019 03:03:03', true, 'q'); + insert into test(id, n ,t, b, s) values( 7, 33, '03.03.2019 03:03:03', true, 'q'); + commit; + + set term ^; + create or alter procedure sp_test( + a_n int = null + ,a_t timestamp = null + ,a_b boolean = null + ,a_s varchar(1) = null + ,a_u varchar(9) = null + ) returns( + id int + --,sttm varchar(255) + ) as + declare sttm varchar(255); + begin + sttm = 'select t.id from rdb$database r left join test t on'; + if ( a_n is not null ) then + sttm = sttm || ' t.n = :param_n and'; + + if ( a_t is not null ) then + sttm = sttm || ' extract(month from t.t) = :param_t and'; + + if ( a_b is not null ) then + sttm = sttm || ' t.b = :param_b and'; + + if ( a_s is not null ) then + sttm = sttm || ' t.s = :param_s and'; + + + sttm = sttm || ' 1=1'; + --suspend; + + for execute statement ( sttm ) ( excess param_n := :a_n, excess param_t := extract(month from :a_t), excess param_b := :a_b, excess param_s := :a_s ) into id + do + suspend; + end + ^ + set term ;^ + commit; + + ------------------------------------------- + --select * from sp_test; + + set list on; + select 'case-1' as msg, p.* from sp_test(22) as p; + select 'case-2' as msg, p.* from sp_test(22, timestamp '19.04.2011 11:12:13') as p; + select 'case-3' as msg, p.* from sp_test(11, timestamp '11.01.2011 11:12:13', true) as p; + select 'case-4' as msg, p.* from sp_test(null, timestamp '03.03.2003 03:13:23', null, 'q') as p; + select 'case-5' as msg, p.* from sp_test(null, null, null, 'z') as p; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG case-1 + ID 3 + MSG case-1 + ID 4 + MSG case-1 + ID 5 + + MSG case-2 + ID 4 + + MSG case-3 + ID 2 + + MSG case-4 + ID 5 + MSG case-4 + ID 6 + MSG case-4 + ID 7 + + MSG case-5 + ID 3 + """ + +@pytest.mark.version('>=4.0') +def test_core_5658_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5659.py b/tests/bugs/test_core_5659.py new file mode 100644 index 00000000..a04836b3 --- /dev/null +++ b/tests/bugs/test_core_5659.py @@ -0,0 +1,143 @@ +#coding:utf-8 +# +# id: bugs.core_5659 +# title: Bad PLAN generated for query on Firebird v3.0 +# decription: +# 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. +# Reproduced bug on 3.0.2.32708, 4.0.0.800 +# Wrong plan was: +# PLAN JOIN (A NATURAL, C INDEX (PK_EST_PRODUTO), B INDEX (PK_COM_PEDIDO)) +# Elapsed time was more than 1.2 second. +# +# All fine on: +# 3.0.3.32838: OK, 5.922s. +# 4.0.0.801: OK, 6.547s. +# +# tracker_id: CORE-5659 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import time +# import zipfile +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# zf = zipfile.ZipFile( os.path.join(context['files_location'],'core_5659.zip') ) +# tmpfbk = 'core_5659.fbk' +# zf.extract( tmpfbk, '$(DATABASE_LOCATION)') +# zf.close() +# +# tmpfbk='$(DATABASE_LOCATION)'+tmpfbk +# tmpfdb='$(DATABASE_LOCATION)'+'tmp_bad_plan_5659.fdb' +# +# f_restore_log=open( os.path.join(context['temp_directory'],'tmp_bad_plan_5659.log'), 'w') +# subprocess.check_call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_restore", +# "bkp_file", tmpfbk, +# "dbname", tmpfdb, +# "res_replace" +# ], +# stdout=f_restore_log, +# stderr=subprocess.STDOUT) +# flush_and_close( f_restore_log ) +# +# # should be empty: +# ################## +# with open( f_restore_log.name,'r') as f: +# for line in f: +# if line.split(): +# print('UNEXPECTED STDERR in '+f_restore_log.name+': '+line) +# +# +# sqltxt=''' +# set planonly; +# select +# a.id_pedido_item, +# c.descricao +# from com_pedido b +# join com_pedido_item a on a.id_pedido = b.id_pedido +# and ( not(a.id_produto =1 and a.id_pedido_item_pai is not null)) +# join est_produto c on c.id_produto = a.id_produto +# where +# -- b.dth_pedido between cast('10.12.16 05:00:00' as timestamp) and cast('10.12.16 20:00:00' as timestamp) +# b.dth_pedido between ? and ? +# ; +# ''' +# +# runProgram('isql', [ 'localhost:'+tmpfdb,'-q' ], sqltxt) +# +# +# # Cleanup: +# ########## +# time.sleep(1) +# cleanup( (f_restore_log, tmpfdb, tmpfbk) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN JOIN (B INDEX (COM_PEDIDO_IDX1), A INDEX (FK_COM_PEDIDO_ITEM_PEDIDO), C INDEX (PK_EST_PRODUTO)) + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_5659_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5664.py b/tests/bugs/test_core_5664.py new file mode 100644 index 00000000..118ecc69 --- /dev/null +++ b/tests/bugs/test_core_5664.py @@ -0,0 +1,144 @@ +#coding:utf-8 +# +# id: bugs.core_5664 +# title: SIMILAR TO is substantially (500-700x) slower than LIKE on trivial pattern matches with VARCHAR data. +# decription: +# Confirmed normal work (ratio is about 1) on WI-T4.0.0.1598 +# +# tracker_id: CORE-5664 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set bail on; + set term ^; + + + -- test#1: SIMILAR TO '%QWERTY' + -- ################################## + + execute block returns( + ratio_in_test_1 varchar(255) + ) as + declare i int = 0; + declare t0 timestamp; + declare t1 timestamp; + declare elap_ms_using_like int; + declare elap_ms_using_similar_to int; + declare s varchar(32761); + declare ratio_similar_vs_like numeric(15,4); + declare MAX_RATIO numeric(15,4) = 2; + -- ^ + -- ############# + -- MAX THRESHOLD + -- ############# + declare n_count int = 5000; -- do not set it to values less than 500: duration should not be zero! + begin + s = lpad('', 32755, uuid_to_char(gen_uuid())) || 'QWERTY'; + + t0 = cast('now' as timestamp); + while (i < n_count) do + begin + i = i + iif( s like '%QWERTY', 1, 1); + end + t1 = cast('now' as timestamp); + elap_ms_using_like = datediff(millisecond from t0 to t1); + + i = 0; + while (i < n_count) do + begin + i = i + iif( s similar to '%QWERTY', 1, 1); + end + elap_ms_using_similar_to = datediff(millisecond from t1 to cast('now' as timestamp)); + + ratio_similar_vs_like = 1.0000 * elap_ms_using_similar_to / elap_ms_using_like; + + ratio_in_test_1 = iif( ratio_similar_vs_like < MAX_RATIO + ,'acceptable' + ,'TOO LOG: '|| ratio_similar_vs_like ||' times. This is more than max threshold = ' || MAX_RATIO || ' times' + ) + ; + suspend; + end + ^ + + + -- test#2: SIMILAR TO 'QWERTY%' + -- ################################## + + execute block returns( + ratio_in_test_2 varchar(255) + ) as + declare i int = 0; + declare t0 timestamp; + declare t1 timestamp; + declare elap_ms_using_like int; + declare elap_ms_using_similar_to int; + declare s varchar(32761); + declare ratio_similar_vs_like numeric(15,4); + declare MAX_RATIO numeric(15,4) = 2; + -- ^ + -- ############# + -- MAX THRESHOLD + -- ############# + declare n_count int = 5000; -- do not set it to values less than 500: duration should not be zero! + begin + + s = 'QWERTY' || lpad('', 32755, uuid_to_char(gen_uuid())) ; + + t0 = cast('now' as timestamp); + while (i < n_count) do + begin + i = i + iif( s similar to 'QWERTY%', 1, 1); + end + t1 = cast('now' as timestamp); + elap_ms_using_like = datediff(millisecond from t0 to t1); + + i = 0; + while (i < n_count) do + begin + i = i + iif( s similar to 'QWERTY%', 1, 1); + end + elap_ms_using_similar_to = datediff(millisecond from t1 to cast('now' as timestamp)); + + ratio_similar_vs_like = 1.0000 * elap_ms_using_similar_to / elap_ms_using_like; + + ratio_in_test_2 = iif( ratio_similar_vs_like < MAX_RATIO + ,'acceptable' + ,'TOO LONG: '|| ratio_similar_vs_like ||' times. This is more than max threshold = ' || MAX_RATIO || ' times' + ) + ; + suspend; + end + ^ + set term ;^ + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RATIO_IN_TEST_1 acceptable + RATIO_IN_TEST_2 acceptable + """ + +@pytest.mark.version('>=4.0') +def test_core_5664_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5667.py b/tests/bugs/test_core_5667.py new file mode 100644 index 00000000..d80b76dd --- /dev/null +++ b/tests/bugs/test_core_5667.py @@ -0,0 +1,80 @@ +#coding:utf-8 +# +# id: bugs.core_5667 +# title: Regression in 3.0+: message CTE 'X' has cyclic dependencies appear when 'X' is alias for resultset and there is previous CTE part with the same name 'X' in the query +# decription: +# Checked on: +# 25SC, build 2.5.8.27088: OK, 0.344s. +# 30SS, build 3.0.3.32856: OK, 0.968s. +# 40SS, build 4.0.0.834: OK, 1.875s. +# +# tracker_id: CORE-5667 +# min_versions: ['2.5.8'] +# versions: 2.5.8 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.8 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + with + x as( + select 1 i from rdb$database + ) + ,y as( + select i from x + ) + select * from y as x ------------------ NOTE: "as X", i.e. alias for final CTE part ( "y" ) matches to 1st CTE ( "x" ) + ; + + -- Additional sample: + with recursive + a as( + select 0 a from rdb$database + union all + select a+1 from a where a.a < 1 + ) + ,b as( + select a b from a b + ) + ,c as( + select b c from b c + ) + select c a from c a + ; + + -- Two samples from CORE-5655: + with cte as (select sign(t.rdb$relation_id) ct from rdb$database t) select ct.ct from cte ct; + select e.ct from (select d.ct from (select sign(t.rdb$relation_id) ct from rdb$database t) d) e; + + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + I 1 + + A 0 + A 1 + + CT 1 + CT 1 + """ + +@pytest.mark.version('>=2.5.8') +def test_core_5667_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5673.py b/tests/bugs/test_core_5673.py new file mode 100644 index 00000000..76dc11a7 --- /dev/null +++ b/tests/bugs/test_core_5673.py @@ -0,0 +1,157 @@ +#coding:utf-8 +# +# id: bugs.core_5673 +# title: Unique constraint not working in encrypted database on first command +# decription: +# +# We create new database ('tmp_core_5673.fdb') and try to encrypt it using IBSurgeon Demo Encryption package +# ( https://ib-aid.com/download-demo-firebird-encryption-plugin/ ; https://ib-aid.com/download/crypt/CryptTest.zip ) +# License file plugins\\dbcrypt.conf with unlimited expiration was provided by IBSurgeon to Firebird Foundation (FF). +# This file was preliminary stored in FF Test machine. +# Test assumes that this file and all neccessary libraries already were stored into FB_HOME and %FB_HOME%\\plugins. +# +# Anyone who wants to run this test on his own machine must +# 1) download https://ib-aid.com/download/crypt/CryptTest.zip AND +# 2) PURCHASE LICENSE and get from IBSurgeon file plugins\\dbcrypt.conf with apropriate expiration date and other info. +# +# ################################################ ! ! ! N O T E ! ! ! ############################################## +# FF tests storage (aka "fbt-repo") does not (and will not) contain any license file for IBSurgeon Demo Encryption package! +# ######################################################################################################################### +# +# We create table with UNIQUE constraint, add some data to it and try to encrypt database using 'alter database encrypt with ...' +# command (where = dbcrypt - name of .dll in FB_HOME\\plugins\\ folder that implements encryption). +# Then we allow engine to complete this job - take delay about 1..2 seconds BEFORE detach from database. +# +# 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. +# +# ::: NB :::: +# Could not check reproducing of bug on FB 3.0.2 because there is no encryption plugin for this (too old) version. +# Decided only to ensure that exception will be catched on recent FB version for each attempt to insert duplicate. +# Checked on: +# 4.0.0.1524: OK, 4.056s ; 4.0.0.1421: OK, 6.160s. +# 3.0.5.33139: OK, 2.895s ; 3.0.5.33118: OK, 2.837s. +# +# === NOTE-1 === +# In case of "Crypt plugin DBCRYPT failed to load/607/335544351" check that all +# needed files from IBSurgeon Demo Encryption package exist in %FB_HOME% and %FB_HOME%\\plugins +# %FB_HOME%: +# 283136 fbcrypt.dll +# 2905600 libcrypto-1_1-x64.dll +# 481792 libssl-1_1-x64.dll +# +# %FB_HOME%\\plugins: +# 297984 dbcrypt.dll +# 306176 keyholder.dll +# 108 DbCrypt.conf +# 856 keyholder.conf +# +# === NOTE-2 === +# Version of DbCrypt.dll of october-2018 must be replaced because it has hard-coded +# date of expiration rather than reading it from DbCrypt.conf !! +# +# === NOTE-3 === +# firebird.conf must contain following line: +# KeyHolderPlugin = KeyHolder +# +# +# tracker_id: CORE-5673 +# min_versions: ['3.0.3'] +# versions: 3.0.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import time +# import subprocess +# import re +# import fdb +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# #---------- aux func for cleanup: --------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# +# #------------------------------------------ +# +# +# con = fdb.connect( dsn = dsn ) +# con.execute_immediate( 'recreate table test(x int, constraint test_x_unq unique(x))' ) +# con.commit() +# +# cur = con.cursor() +# cur.execute( 'insert into test(x) select row_number()over() from rdb$types rows 10' ) +# con.commit() +# +# cur.execute('alter database encrypt with dbcrypt key Red') +# con.commit() +# +# time.sleep(2) +# # ^ +# # +-------- !! ALLOW BACKGROUND ENCRYPTION PROCESS TO COMPLETE ITS JOB !! +# +# try: +# cur.execute( 'insert into test(x) values(1)' ) +# except Exception as e: +# for x in e.args: +# print( x ) +# +# try: +# cur.execute( 'insert into test(x) values(2)' ) +# except Exception as e: +# for x in e.args: +# #print( x.replace(chr(92),"/") if type(x)=='str' else x ) +# print( x ) +# +# +# cur.close() +# con.close() +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Error while executing SQL statement: + - SQLCODE: -803 + - violation of PRIMARY or UNIQUE KEY constraint "TEST_X_UNQ" on table "TEST" + - Problematic key value is ("X" = 1) + -803 + 335544665 + + Error while executing SQL statement: + - SQLCODE: -803 + - violation of PRIMARY or UNIQUE KEY constraint "TEST_X_UNQ" on table "TEST" + - Problematic key value is ("X" = 2) + -803 + 335544665 + """ + +@pytest.mark.version('>=3.0.3') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_5673_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5674.py b/tests/bugs/test_core_5674.py new file mode 100644 index 00000000..62618e9b --- /dev/null +++ b/tests/bugs/test_core_5674.py @@ -0,0 +1,152 @@ +#coding:utf-8 +# +# id: bugs.core_5674 +# title: Allow unused Common Table Expressions +# decription: +# Checked on: +# 3.0.3.32852: OK, 0.875s. +# 4.0.0.830: OK, 1.062s. +# +# tracker_id: CORE-5674 +# min_versions: ['3.0.3'] +# versions: 3.0.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.3 +# resources: None + +substitutions_1 = [('-At line[:]{0,1}[\\s]+[\\d]+,[\\s]+column[:]{0,1}[\\s]+[\\d]+', '-At line: column:')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + -- Should PASS but two warnings will be issued: + -- SQL warning code = -104 + -- -CTE "X" is not used in query + -- -CTE "Y" is not used in query + with + x as( + select 1 i from rdb$database + ) + ,y as( + select i from x + ) + ,z as ( + select 2 z from rdb$database + ) + select z y, z*2 x from z + ; + + + -- Should PASS but one warning will be issued: + -- SQL warning code = -104 + -- -CTE "B" is not used in query + with + a as( + select 0 a from rdb$database + ) + ,b as( + select 1 x from c rows 1 + ) + ,c as( + select 2 x from d rows 1 + ) + ,d as( + select 3 x from e rows 1 + ) + ,e as( + select a x from a rows 1 + ) + select * from e + -- union all select * from b + ; + + + -- Should FAIL with: + -- Statement failed, SQLSTATE = 42S02 + -- Dynamic SQL Error + -- -SQL error code = -204 + -- -Table unknown + -- -FOO + with recursive + a as( + select 0 a from rdb$database + union all + select a+1 from a where a.a < 1 + ) + ,b as( + select 1 a from foo rows 1 + ) + ,c as( + select 2 b from bar rows 1 + ) + select * from a; + + -- Should FAIL with: + -- Statement failed, SQLSTATE = 42000 + -- Dynamic SQL Error + -- -SQL error code = -104 + -- -CTE 'C' has cyclic dependencies + with recursive + a as( + select 0 a from rdb$database + union all + select a+1 from a where a.a < 1 + ) + ,b as( + select 1 a from c rows 1 + ) + ,c as( + select 2 b from b rows 1 + ) + select * from a; + + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Y 2 + X 4 + + X 0 + """ +expected_stderr_1 = """ + 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 + -At line: column: + + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -CTE 'C' has cyclic dependencies + """ + +@pytest.mark.version('>=3.0.3') +def test_core_5674_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5675.py b/tests/bugs/test_core_5675.py new file mode 100644 index 00000000..55a75eaa --- /dev/null +++ b/tests/bugs/test_core_5675.py @@ -0,0 +1,102 @@ +#coding:utf-8 +# +# id: bugs.core_5675 +# title: isc_vax_integer() and isc_portable_integer() work wrongly with short negative numbers +# decription: +# Confirmed bug on4.0.0.800. +# Works fine on: +# FB25SC, build 2.5.8.27089: OK, 0.422s. +# FB30SS, build 3.0.3.32876: OK, 1.484s. +# FB40SS, build 4.0.0.852: OK, 1.156s. +# +# NB. It seems that some bug exists in function _renderSizedIntegerForSPB from fdb package (services.py): +# iRaw = struct.pack(myformat, i) +# iConv = api.isc_vax_integer(iRaw, len(iRaw)) +# This function cuts off high 4 bytes when we pass to it bugint values greater than 2^31, i.e.: +# 2147483648L ==> reversed = b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' +# -2147483649L ==> reversed = b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' +# +# For this reason it was decided currently to limit scope by specifying numbers with abs() less than 2^31 - untill fdb driver will be fixed. +# See letter from dimitr 08-jan-2018 20:56 +# +# 25.08.2020: adjusted name of function from services that must work here: +# its name is "_render_sized_integer_for_spb" rather than old "_renderSizedIntegerForSPB". +# Checked on 4.0.0.2173; 3.0.7.33357; 2.5.9.27152. +# +# tracker_id: CORE-5675 +# min_versions: ['2.5.8'] +# versions: 2.5.8 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.8 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# from __future__ import print_function +# import os +# import binascii +# from fdb import services +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.close() +# con = services.connect(host='localhost', user='sysdba', password='masterkey') +# #print( con.get_server_version() ) +# +# dec_values=( 1, -1, 127, -128, 128, -256, 255, -32768, 32767, 32768, -65536, 65535, 65536 ) #, 32767, -32768, 32768, -32769, 2147483647, -2147483648, 2147483648, -2147483649, 3000000000, 3000000000000, 9223372036854775807 ) +# num_ctypes=( 'b', 'b', 'b', 'b', 'b', 'B', 'B', 'h', 'h', 'h', 'H', 'H', 'H' ) #, 'i', 'i', 'i', 'i', 'i', 'i', 'q', 'q', 'q', 'q', 'q' ) +# +# #dec_values=( 1, -1, 127, -128, 128, -256, 255, -32768, 32767, 32768, -65536, 65535, 65536 , 32767, -32768, 32768, -32769, 2147483647, -2147483648, 2147483648, -2147483649, 3000000000, 3000000000000, 9223372036854775807 ) +# #num_ctypes=( 'b', 'b', 'b', 'b', 'b', 'B', 'B', 'h', 'h', 'h', 'H', 'H', 'H' , 'i', 'i', 'i', 'i', 'i', 'i', 'q', 'q', 'q', 'q', 'q') +# +# +# for i in range(0, len(dec_values)): +# num = dec_values[i] +# fmt = num_ctypes[i] +# msg = ['Try revert bytes in decimal value:', "{:12d}".format(num), ' using struct format: ', '"'+fmt+'"'] +# try: +# # OLD name of function: (numericFormat, numericBytes) = services._renderSizedIntegerForSPB(num, fmt) +# (numericFormat, numericBytes) = services._render_sized_integer_for_spb(num, fmt) +# rev = binascii.hexlify(numericBytes) +# except Exception, e: +# rev = e[0] +# finally: +# print( ' '.join( (msg + ['; result: ',rev,]) ) ) +# +# con.close() +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Try revert bytes in decimal value: 1 using struct format: "b" ; result: 01 + Try revert bytes in decimal value: -1 using struct format: "b" ; result: ff + Try revert bytes in decimal value: 127 using struct format: "b" ; result: 7f + Try revert bytes in decimal value: -128 using struct format: "b" ; result: 80 + Try revert bytes in decimal value: 128 using struct format: "b" ; result: byte format requires -128 <= number <= 127 + Try revert bytes in decimal value: -256 using struct format: "B" ; result: ubyte format requires 0 <= number <= 255 + Try revert bytes in decimal value: 255 using struct format: "B" ; result: ubyte format requires 0 <= number <= 255 + Try revert bytes in decimal value: -32768 using struct format: "h" ; result: 0080 + Try revert bytes in decimal value: 32767 using struct format: "h" ; result: ff7f + Try revert bytes in decimal value: 32768 using struct format: "h" ; result: short format requires SHRT_MIN <= number <= SHRT_MAX + Try revert bytes in decimal value: -65536 using struct format: "H" ; result: ushort format requires 0 <= number <= USHRT_MAX + Try revert bytes in decimal value: 65535 using struct format: "H" ; result: ushort format requires 0 <= number <= USHRT_MAX + Try revert bytes in decimal value: 65536 using struct format: "H" ; result: ushort format requires 0 <= number <= USHRT_MAX + """ + +@pytest.mark.version('>=2.5.8') +@pytest.mark.xfail +def test_core_5675_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5676.py b/tests/bugs/test_core_5676.py new file mode 100644 index 00000000..186cd2f5 --- /dev/null +++ b/tests/bugs/test_core_5676.py @@ -0,0 +1,80 @@ +#coding:utf-8 +# +# id: bugs.core_5676 +# title: Consider equivalence classes for index navigation +# decription: +# Confirmed inefficiense on: +# 3.0.3.32837 +# 4.0.0.800 +# Checked on: +# 3.0.3.32852: OK, 1.250s. +# 4.0.0.830: OK, 1.375s. +# +# tracker_id: CORE-5676 +# min_versions: ['3.0.3'] +# versions: 3.0.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table document(id int primary key using index pk_document); + recreate table doc_ip_doc(id int primary key using index pk_doc_ip_doc, name varchar(100)); + + insert into document (id) select row_number() over() from rdb$types,(select 1 i from rdb$types rows 10); + insert into doc_ip_doc (id) select row_number() over() from rdb$types; + commit; + + set planonly; + + select document.id, doc_ip_doc.name + from doc_ip_doc + join document on document.id=doc_ip_doc.id + order by doc_ip_doc.id; + --PLAN JOIN (DOC_IP_DOC ORDER PK_DOC_IP_DOC, DOCUMENT INDEX (PK_DOCUMENT)) + + select document.id, doc_ip_doc.name + from doc_ip_doc + join document on document.id=doc_ip_doc.id + order by document.id; + -- OLD: PLAN SORT (JOIN (DOC_IP_DOC NATURAL, DOCUMENT INDEX (PK_DOCUMENT))) + + select doc_ip_doc.id, doc_ip_doc.name + from doc_ip_doc + join document on document.id=doc_ip_doc.id + order by id; + --PLAN JOIN (DOC_IP_DOC ORDER PK_DOC_IP_DOC, DOCUMENT INDEX (PK_DOCUMENT)) + + select document.id, doc_ip_doc.name + from doc_ip_doc + join document on document.id=doc_ip_doc.id + order by id; + -- OLD: PLAN SORT (JOIN (DOC_IP_DOC NATURAL, DOCUMENT INDEX (PK_DOCUMENT))) + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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_core_5676_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5684.py b/tests/bugs/test_core_5684.py new file mode 100644 index 00000000..7ebc3c90 --- /dev/null +++ b/tests/bugs/test_core_5684.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: bugs.core_5684 +# title: Error "no current record for fetch operation" is raised while deleting record from MON$ATTACHMENTS using ORDER BY clause +# decription: +# Checked on: +# 2.5.8.27088: OK, 1.344s. +# 3.0.3.32856: OK, 1.453s. +# 4.0.0.834: OK, 1.750s. +# +# tracker_id: CORE-5684 +# min_versions: ['2.5.8'] +# versions: 2.5.8 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.8 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + commit; + set count on; + delete from mon$attachments order by mon$attachment_id rows 1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 1 + """ + +@pytest.mark.version('>=2.5.8') +def test_core_5684_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5685.py b/tests/bugs/test_core_5685.py new file mode 100644 index 00000000..eec07457 --- /dev/null +++ b/tests/bugs/test_core_5685.py @@ -0,0 +1,362 @@ +#coding:utf-8 +# +# id: bugs.core_5685 +# title: Sometime it is impossible to cancel\\kill connection executing external query +# decription: +# 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) +# +# Confirmed bug on 3.0.2.32703 (check file "tmp_kill_5685.log" in %FBT_REPO% mp folder with result that will get "killer-ISQL") +# +# NOTE-1: console output in 4.0 slightly differs from in 3.0: a couple of messages ("-Killed by database administrator" and "-send_packet/send") +# was added to STDERR. For this reason test code was splitted on two sections, 3.0 and 4.0. +# NOTE-2: unstable results detected for 2.5.9 SuperClassic. Currently test contains min_version = 3.0.3 rather than 2.5.9 +# +# 06.03.2021. +# Removed separate section for 3.x because code for 4.x was made unified. +# Checked on: +# * Windows: 4.0.0.2377 (SS/CS), 3.0.8.33423 (SS/CS) +# * Linux: 4.0.0.2379, 3.0.8.33415 +# +# +# tracker_id: CORE-5685 +# min_versions: ['3.0.3'] +# versions: 3.0.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.3 +# resources: None + +substitutions_1 = [('.*After line.*', ''), ('.*Data source.*', '.*Data source'), ('.*HANGING_STATEMENT_BLOB_ID.*', '')] + +init_script_1 = """ + 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_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import re +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# f_hang_sql = open( os.path.join(context['temp_directory'],'tmp_hang_5685.sql'), 'w') +# f_hang_sql.write( 'set list on; set count on; select * from sp_get_data;' ) +# flush_and_close( f_hang_sql ) +# +# sql_kill=''' +# 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; +# ''' +# +# f_kill_sql = open( os.path.join(context['temp_directory'],'tmp_kill_5685.sql'), 'w') +# f_kill_sql.write( sql_kill ) +# flush_and_close( f_kill_sql ) +# +# f_hang_log = open( os.path.join(context['temp_directory'],'tmp_hang_5685.log'), 'w') +# f_hang_err = open( os.path.join(context['temp_directory'],'tmp_hang_5685.err'), 'w') +# +# +# # WARNING: we launch ISQL here in async mode in order to have ability to kill its process if it will hang! +# ############################################ +# p_hang_pid=subprocess.Popen( [ context['isql_path'], dsn, "-i", f_hang_sql.name ], +# stdout = f_hang_log, +# stderr = f_hang_err +# ) +# +# time.sleep(1) +# +# +# f_kill_log = open( os.path.join(context['temp_directory'],'tmp_kill_5685.log'), 'w') +# f_kill_err = open( os.path.join(context['temp_directory'],'tmp_kill_5685.err'), 'w') +# +# for i in (1,2): +# subprocess.call( [ context['isql_path'], dsn, "-i", f_kill_sql.name ], +# stdout = f_kill_log, +# stderr = f_kill_err +# ) +# +# flush_and_close( f_kill_log ) +# flush_and_close( f_kill_err ) +# +# ############################################## +# p_hang_pid.terminate() +# flush_and_close( f_hang_log ) +# flush_and_close( f_hang_err ) +# +# time.sleep(2) +# +# f_shut_log = open( os.path.join(context['temp_directory'],'tmp_shut_5685.log'), 'w') +# f_shut_err = open( os.path.join(context['temp_directory'],'tmp_shut_5685.err'), 'w') +# +# subprocess.call( [ context['gfix_path'], dsn, "-shut", "full", "-force", "0" ], +# stdout = f_shut_log, +# stderr = f_shut_err +# ) +# +# subprocess.call( [ context['gstat_path'], dsn, "-h"], +# stdout = f_shut_log, +# stderr = f_shut_err +# ) +# +# subprocess.call( [ context['gfix_path'], dsn, "-online" ], +# stdout = f_shut_log, +# stderr = f_shut_err +# ) +# +# subprocess.call( [ context['gstat_path'], dsn, "-h"], +# stdout = f_shut_log, +# stderr = f_shut_err +# ) +# +# flush_and_close( f_shut_log ) +# flush_and_close( f_shut_err ) +# +# # Check results: +# ################ +# +# with open( f_hang_log.name,'r') as f: +# for line in f: +# if line.split(): +# print('HANGED ATTACH, STDOUT: ', ' '.join(line.split()) ) +# +# +# # 01-mar-2021: hanged ISQL can issue *different* messages to STDERR starting from line #4: +# # case-1: +# # ------- +# # 1 Statement failed, SQLSTATE = 08003 +# # 2 connection shutdown +# # 3 -Killed by database administrator. +# # 4 Statement failed, SQLSTATE = 08006 <<< +# # 5 Error writing data to the connection. <<< +# # 6 -send_packet/send <<< +# +# # case-2: +# # 1 Statement failed, SQLSTATE = 08003 +# # 2 connection shutdown +# # 3 -Killed by database administrator. +# # 4 Statement failed, SQLSTATE = 08003 <<< +# # 5 connection shutdown <<< +# # 6 -Killed by database administrator. <<< +# +# # We can ignore messages like '-send_packet/send' and '-Killed by database administrator.', +# # but we have to take in account first two ('SQLSTATE = ...' and 'Error ... connection' / 'connection shutdown') +# # because they exactly say that session was terminated. +# # +# # This means that STDERR must contain following lines: +# # 1 // SQLSTATE = 08006 or 08003 +# # 2 // Error writing data to... / Error reading data from... / connection shutdown +# # 3 // SQLSTATE = 08006 or 08003 +# # 4 // Error writing data to... / Error reading data from... / connection shutdown +# +# # Use pattern matching for this purpose: +# # +# 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.)') +# +# msg_prefix = 'HANGED ATTACH, STDERR: ' +# with open( f_hang_err.name,'r') as f: +# for line in f: +# if line.split(): +# if pattern_for_ignored_messages.search(line): +# pass +# elif pattern_for_failed_statement.search(line): +# print( msg_prefix, '') +# elif pattern_for_connection_close.search(line): +# print( msg_prefix, '') +# else: +# print( msg_prefix, ' '.join(line.split()) ) +# +# +# with open( f_kill_log.name,'r') as f: +# for line in f: +# if line.split(): +# print('KILLER ATTACH, STDOUT: ', ' '.join(line.split()) ) +# +# with open( f_kill_err.name,'r') as f: +# for line in f: +# if line.split(): +# print('KILLER ATTACH, UNEXPECTED STDERR: ', ' '.join(line.split()) ) +# +# with open( f_shut_err.name,'r') as f: +# for line in f: +# if line.split(): +# print('DB SHUTDOWN, UNEXPECTED STDERR: ', ' '.join(line.split()) ) +# +# +# ############################### +# # Cleanup. +# time.sleep(1) +# +# f_list=( +# f_hang_sql +# ,f_hang_log +# ,f_hang_err +# ,f_kill_sql +# ,f_kill_log +# ,f_kill_err +# ,f_shut_log +# ,f_shut_err +# ) +# cleanup( f_list ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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 + """ + +@pytest.mark.version('>=3.0.3') +@pytest.mark.xfail +def test_core_5685_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5691.py b/tests/bugs/test_core_5691.py new file mode 100644 index 00000000..d3bfcbef --- /dev/null +++ b/tests/bugs/test_core_5691.py @@ -0,0 +1,234 @@ +#coding:utf-8 +# +# id: bugs.core_5691 +# title: File description on Firebird executables should be specific +# decription: +# ::: NB ::: +# We can not obtain 'File description' property using Python. +# Also this property is not accessible for WMIC interface. +# For this reason it was decided to create on-the-fly Visual Basic script and process it by CSCRIPT.EXE utility +# which exists since 2000/XP on every Windows host in %System%\\system32\\ folder. +# VB script accepts full path and filename as single mandatory argument. +# We run this script for each widely-used FB binaries (executables and DLLs). +# Its output must contain only FILE name (w/o disk and path) and its 'File description' property value. +# +# Home directory for currently used FB instance (i.e. prefix for each of files) can be found by +# invocation of FDB services.get_home_directory() method. +# +# Checked on 4.0.0.1710 SS: 1.407s. +# +# tracker_id: CORE-5691 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \\t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# \\ +# import os +# import subprocess +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# #-------------------------------------------- +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# #-------------------------------------------- +# +# fb_home = services.connect(host='localhost', user= user_name, password= user_password).get_home_directory() +# db_conn.close() +# +# +# vbs_cmd = open( os.path.join(context['temp_directory'],'tmp_5691_get_file_descr.vbs'), 'w', buffering = 0) +# +# vbs_source = \\ +# r''' +# Option Explicit +# +# if wscript.arguments.count = 0 then +# wscript.echo "Missed fully qualified file name, i.e.: drive + path + file_name" +# wscript.quit +# end if +# +# dim fullname +# dim getDetails +# +# fullname = wscript.arguments(0) +# +# rem https://www.tek-tips.com/viewthread.cfm?qid=1402419 +# +# getDetails = GetFileDetails( fullName ) +# +# +# function GetFileDetails(fullName) +# +# on error resume next +# +# dim fso +# dim objFile +# +# set fso = CreateObject("Scripting.FileSystemObject") +# set objFile = fso.GetFile(fullName) +# +# if not fso.FileExists(fullName) Then +# wscript.echo "File '" & fullName & "' does not exist." +# wscript.Quit +# end if +# +# dim fileName +# dim folderName +# +# fileName = objFile.Name +# folderName = objFile.Path +# folderName = Left(folderName, Len(folderName)-Len(fileName)) +# +# set objFile = Nothing +# set fso = Nothing +# +# dim objShell +# dim objFolder +# +# rem https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/bb776890(v=vs.85) +# rem The Windows Shell provides a powerful set of automation objects <...> +# rem You can use these objects to access <...> the file system, launch programs, and change system settings. +# +# set objShell = CreateObject("Shell.Application") +# set objFolder = objShell.NameSpace(folderName) +# +# dim i +# dim fdescr_idx +# dim propertyName +# +# i = 0 +# fdescr_idx = 0 +# do +# propertyName = vbNullString +# rem https://docs.microsoft.com/en-us/windows/win32/shell/folder-getdetailsof +# rem retrieves details about an item in a folder. for example, its size, type, or the time of its last modification. +# propertyName = objFolder.GetDetailsOf(objFolder.Items, i) +# if LCase(propertyName) = LCase("file description") then +# fdescr_idx = i +# exit do +# end if +# +# if propertyName = vbNullString then +# exit do +# end if +# i = i + 1 +# loop +# propertyName = Nothing +# rem wscript.echo "fdescr_idx=",fdescr_idx +# +# dim objFolderItem +# set objFolderItem = objFolder.ParseName(fileName) +# +# if (not objFolderItem Is Nothing) then +# dim attribName +# dim objInfo +# attribName = objFolder.GetDetailsOf(objFolder.Items, fdescr_idx) +# objInfo = objFolder.GetDetailsOf(objFolderItem, fdescr_idx) +# +# wscript.echo "'" & fileName & "' " & LCase(attribName) & ":", LCase(objInfo) +# +# attribName = Nothing +# objInfo = Nothing +# end if +# +# set objFolderItem = Nothing +# set objFolder = Nothing +# set objShell = Nothing +# end function +# ''' +# +# vbs_cmd.write(vbs_source) +# vbs_cmd.close() +# +# vbs_log = open( os.path.join(context['temp_directory'],'tmp_5691_get_file_descr.log'), 'w', buffering = 0) +# vbs_err = open( os.path.join(context['temp_directory'],'tmp_5691_get_file_descr.err'), 'w', buffering = 0) +# +# f_list = ( 'fbclient.dll', +# 'gbak.exe', +# 'gfix.exe', +# 'gstat.exe', +# 'fbguard.exe', +# 'isql.exe', +# 'fb_lock_print.exe', +# 'firebird.exe', +# 'nbackup.exe', +# 'fbtracemgr.exe', +# 'fbsvcmgr.exe', +# r'plugins\\engine13.dll', +# r'plugins\\legacy_auth.dll', +# r'plugins\\legacy_usermanager.dll', +# r'plugins\\srp.dll', +# r'plugins\\udr_engine.dll', +# r'plugins\\chacha.dll', +# r'plugins\\\\fbtrace.dll', +# ) +# for x in sorted(f_list): +# subprocess.call( [ 'cscript', '//nologo', vbs_cmd.name, ''.join( (fb_home, x) ) ], stdout = vbs_log, stderr = vbs_err ) +# +# vbs_log.close() +# vbs_err.close() +# +# with open( vbs_err.name,'r') as f: +# for line in f: +# print("Unexpected STDERR, file "+vbs_err.name+": " + line) +# +# with open( vbs_log.name,'r') as f: +# for line in f: +# print( line.lower() ) +# +# os.remove( vbs_log.name ) +# os.remove( vbs_err.name ) +# os.remove( vbs_cmd.name ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 'fb_lock_print.exe' file description: firebird lock print tool (64-bit) + 'fbclient.dll' file description: firebird client library (64-bit) + 'fbguard.exe' file description: firebird guardian (64-bit) + 'fbsvcmgr.exe' file description: firebird services management tool (64-bit) + 'fbtracemgr.exe' file description: firebird trace management tool (64-bit) + 'firebird.exe' file description: firebird server executable (64-bit) + 'gbak.exe' file description: firebird gbak tool (64-bit) + 'gfix.exe' file description: firebird gfix tool (64-bit) + 'gstat.exe' file description: firebird gstat tool (64-bit) + 'isql.exe' file description: firebird interactive query tool (64-bit) + 'nbackup.exe' file description: firebird physical backup management tool (64-bit) + 'chacha.dll' file description: firebird wire encryption plugin using chacha cypher (64-bit) + 'engine13.dll' file description: firebird engine plugin (64-bit) + 'fbtrace.dll' file description: firebird trace plugin (64-bit) + 'legacy_auth.dll' file description: firebird legacy auth plugin (64-bit) + 'legacy_usermanager.dll' file description: firebird legacy user manager plugin (64-bit) + 'srp.dll' file description: firebird srp user manager plugin (64-bit) + 'udr_engine.dll' file description: firebird user defined routines engine (64-bit) + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_5691_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5695.py b/tests/bugs/test_core_5695.py new file mode 100644 index 00000000..c662bf08 --- /dev/null +++ b/tests/bugs/test_core_5695.py @@ -0,0 +1,63 @@ +#coding:utf-8 +# +# id: bugs.core_5695 +# title: Position function does not consider the collation for blob +# decription: +# Confirmed bug on 3.0.3.32837, 4.0.0.800 +# Checked on: +# FB30SS, build 3.0.3.32876: OK, 1.094s. +# FB40SS, build 4.0.0.852: OK, 1.109s. +# +# tracker_id: CORE-5695 +# min_versions: ['3.0.3'] +# versions: 3.0.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set blob all; + set term ^; + execute block returns (res smallint) as + declare blb blob sub_type 1 segment size 80 collate unicode_ci; + declare txt varchar(255) collate unicode_ci; + begin + -- pure ASCII strings: + blb = 'A'; + txt = 'a'; + res = position(txt, blb); + suspend; + -- strings with NON-ascii characters: + blb= 'ŁÁTÉÇØΙΚΌΛΑΟΣ'; + txt = 'Łátéçøικόλαος'; + res = position(txt, blb); + suspend; + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RES 1 + RES 1 + """ + +@pytest.mark.version('>=3.0.3') +def test_core_5695_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5697.py b/tests/bugs/test_core_5697.py new file mode 100644 index 00000000..fd6a7bfe --- /dev/null +++ b/tests/bugs/test_core_5697.py @@ -0,0 +1,161 @@ +#coding:utf-8 +# +# id: bugs.core_5697 +# title: Conversion from zero numeric literals to DECFLOAT results in incorrect value +# decription: +# Confirmed wrong output from table with decfloat16 field (in WI-T4.0.0.1047, date of build: 03-JUL-2018). +# Confirmed overflow of decfloat34 when inserting values with exponent more than 385, i.e. >= 1e+385 or <= -1e385 (in WI-T4.0.0.1535, date of build: 24-JUN-2019)). +# Checked on 4.0.0.1556: OK, 1.710s. +# +# tracker_id: CORE-5697 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ ]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + recreate table df16(id_df16 int, val_df16 decfloat(16)); + recreate table df34(id_df34 int, val_df34 decfloat(34)); + commit; + + -- 06-jan-2018 + -- =========== + insert into df16 values( 1, -0); + insert into df16 values( 2, -0E300); + insert into df16 values( 3, -0E+300); + insert into df16 values( 4, -0.0E+300); + insert into df16 values( 5, 0E+300); + insert into df16 values( 6, 0E-300); + + -- 22-jun-2019 + -- =========== + insert into df16 values( 7, 0e+370); + insert into df16 values( 8, 0e-399); + insert into df16 values( 9, 0e+6111); + insert into df16 values( 10, 0e-6167); + + insert into df16 values( 11, 1e-6176); + insert into df16 values( 12, 1e+6111); -- must raise SQLSTATE = 22003 Decimal float overflow. The exponent of a result is greater than the magnitude allowed. + insert into df16 values( 13, 1e+6144); -- must raise SQLSTATE = 22003 Decimal float overflow. The exponent of a result is greater than the magnitude allowed. + insert into df16 values( 14, 1.234567890123456789012345678901234E0); + insert into df16 values( 15, 9999999999999999E+369); + + select t.* from df16 t; + + ---------------------------------------------- + + -- 22-jun-2019 + -- =========== + insert into df34 values( 1, 0e+370); + insert into df34 values( 2, 0e-399); + insert into df34 values( 3, 0e+6111); + insert into df34 values( 4, 0e-6167); + insert into df34 values( 5, 1e-6176); + insert into df34 values( 6, 1e385); -- DID raise overflow in WI-T4.0.0.1535, i.e. before this ticket was fixed; ticket sample: 1e+6111 + insert into df34 values( 7, -1e385); -- DID raise overflow in WI-T4.0.0.1535, i.e. before this ticket was fixed; ticket sample: 1e+6144 + insert into df34 values( 8, 1e+6111); + insert into df34 values( 9, 1.234567890123456789012345678901234E0); + + select t.* from df34 t; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID_DF16 1 + VAL_DF16 -0 + + ID_DF16 2 + VAL_DF16 -0E+300 + + ID_DF16 3 + VAL_DF16 -0E+300 + + ID_DF16 4 + VAL_DF16 -0E+299 + + ID_DF16 5 + VAL_DF16 0E+300 + + ID_DF16 6 + VAL_DF16 0E-300 + + ID_DF16 7 + VAL_DF16 0E+369 + + ID_DF16 8 + VAL_DF16 0E-398 + + ID_DF16 9 + VAL_DF16 0E+369 + + ID_DF16 10 + VAL_DF16 0E-398 + + ID_DF16 11 + VAL_DF16 0E-398 + + ID_DF16 14 + VAL_DF16 1.234567890123457 + + ID_DF16 15 + VAL_DF16 9.999999999999999E+384 + + + + ID_DF34 1 + VAL_DF34 0E+370 + + ID_DF34 2 + VAL_DF34 0E-399 + + ID_DF34 3 + VAL_DF34 0E+6111 + + ID_DF34 4 + VAL_DF34 0E-6167 + + ID_DF34 5 + VAL_DF34 1E-6176 + + ID_DF34 6 + VAL_DF34 1E+385 + + ID_DF34 7 + VAL_DF34 -1E+385 + + ID_DF34 8 + VAL_DF34 1E+6111 + + ID_DF34 9 + VAL_DF34 1.234567890123456789012345678901234 + + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22003 + Decimal float overflow. The exponent of a result is greater than the magnitude allowed. + + Statement failed, SQLSTATE = 22003 + Decimal float overflow. The exponent of a result is greater than the magnitude allowed. + """ + +@pytest.mark.version('>=4.0') +def test_core_5697_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5700.py b/tests/bugs/test_core_5700.py new file mode 100644 index 00000000..ed0a4633 --- /dev/null +++ b/tests/bugs/test_core_5700.py @@ -0,0 +1,55 @@ +#coding:utf-8 +# +# id: bugs.core_5700 +# title: DECFLOAT underflow should yield zero instead of an error +# decription: +# Test case is based on letter from Alex, 05-feb-2018 20:23. +# Confirmed on 4.0.0.800 (15-nov-18): evaluation of '1e-5000 / 1e5000' did raise exception: +# === +# Statement failed, SQLSTATE = 22003 +# Decimal float underflow. The exponent of a result is less than the magnitude allowed. +# === +# Checked on 4.0.0.875: OK, 1.000s. +# +# tracker_id: CORE-5700 +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: bugs.core_5700 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[\\s]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select 1e-5000 / 1e5000 as r from rdb$database; -- this should NOT raise exception since this ticket was fixed. + set decfloat traps to underflow; + select 1e-5000 / 1e5000 as r from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + R 0E-6176 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22003 + Decimal float underflow. The exponent of a result is less than the magnitude allowed. + """ + +@pytest.mark.version('>=4.0') +def test_core_5700_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5704.py b/tests/bugs/test_core_5704.py new file mode 100644 index 00000000..25a215de --- /dev/null +++ b/tests/bugs/test_core_5704.py @@ -0,0 +1,233 @@ +#coding:utf-8 +# +# id: bugs.core_5704 +# title: Avoid UPDATE of RDB$DATABASE by ALTER DATABASE statement when possible +# decription: +# Instead of doing 'nbackup -L' plus fill database with lot of new data and then 'nbackup -N' with waiting for +# delta will be integrated into main file, we can get the same result by invoking 'alter database add difference file' +# statement in the 1st attachment in RC NO_REC_VERS and WITHOUT COMMITTING it, and then attempt to establish new connect +# using ES/EDS. Second attachment should be made without any problem, despite that transaction in 1st connect not yet +# committed or rolled back. +# +# Confirmed lock of rdb$database record (which leads to inability to establish new connect) on WI-V3.0.3.32837. +# Works fine on (SS, CS): +# 3.0.3.32876: OK, 5.266s. +# 4.0.0.852: OK, 5.594s. +# +# tracker_id: CORE-5704 +# min_versions: ['3.0.3'] +# versions: 3.0.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# from subprocess import Popen +# import time +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_file = db_conn.database_name +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# usr=user_name +# pwd=user_password +# new_diff_file=os.path.join(context['temp_directory'],'tmp_new_diff_5704.tmp') +# new_main_file=os.path.join(context['temp_directory'],'tmp_new_main_5704.tmp') +# +# eds_query=''' +# 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 ='%(usr)s'; +# pwd = '%(pwd)s'; +# 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)s'; +# select * from sp_connect; +# +# rollback; +# select * from rdb$files; +# rollback; +# +# set transaction read committed no record_version lock timeout 1; +# +# alter database add file '%(new_main_file)s'; +# select * from sp_connect; +# --select * from rdb$files; +# rollback; +# select * from rdb$files; +# ''' +# +# f_eds_to_local_host_sql = open( os.path.join(context['temp_directory'],'tmp_local_host_5704.sql'), 'w') +# f_eds_to_local_host_sql.write( eds_query % locals() ) +# flush_and_close( f_eds_to_local_host_sql ) +# +# f_eds_to_local_host_log = open( os.path.join(context['temp_directory'],'tmp_local_host_5704.log'), 'w') +# f_eds_to_local_host_err = open( os.path.join(context['temp_directory'],'tmp_local_host_5704.err'), 'w') +# +# # WARNING: we launch ISQL here in async mode in order to have ability to kill its process if it will hang! +# ############################################ +# p_isql_to_local_host=subprocess.Popen( [context['isql_path'], dsn, "-i", f_eds_to_local_host_sql.name ], +# stdout = f_eds_to_local_host_log, +# stderr = f_eds_to_local_host_err +# ) +# +# time.sleep(3) +# +# p_isql_to_local_host.terminate() +# flush_and_close( f_eds_to_local_host_log ) +# flush_and_close( f_eds_to_local_host_err ) +# +# +# # Make DB shutdown and bring online because some internal server process still can be active! +# # If we skip this step than runtime error related to dropping test DB can occur! +# ######################################### +# +# f_db_reset_log=open( os.path.join(context['temp_directory'],'tmp_reset_5704.log'), 'w') +# f_db_reset_err=open( os.path.join(context['temp_directory'],'tmp_reset_5704.err'), 'w') +# +# f_db_reset_log.write('Point before DB shutdown.'+os.linesep) +# f_db_reset_log.seek(0,2) +# subprocess.call( [context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "prp_shutdown_mode", "prp_sm_full", "prp_shutdown_db", "0", +# "dbname", db_file, +# ], +# stdout = f_db_reset_log, +# stderr = f_db_reset_err +# ) +# f_db_reset_log.write(os.linesep+'Point after DB shutdown.'+os.linesep) +# +# subprocess.call( [context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "prp_db_online", +# "dbname", db_file, +# ], +# stdout = f_db_reset_log, +# stderr = f_db_reset_err +# ) +# +# f_db_reset_log.write(os.linesep+'Point after DB online.'+os.linesep) +# flush_and_close( f_db_reset_log ) +# flush_and_close( f_db_reset_err ) +# +# with open( f_eds_to_local_host_log.name,'r') as f: +# for line in f: +# if line.split(): +# print('STDOUT in ISQL: ', ' '.join(line.split()) ) +# +# with open( f_eds_to_local_host_err.name,'r') as f: +# for line in f: +# if line.split(): +# print('UNEXPECTED STDERR in '+f_eds_to_local_host_err.name+': '+line) +# +# with open( f_db_reset_log.name,'r') as f: +# for line in f: +# if line.split(): +# print('STDOUT in DB reset: ', ' '.join(line.split()) ) +# +# with open( f_db_reset_err.name,'r') as f: +# for line in f: +# if line.split(): +# print('UNEXPECTED STDERR in '+f_db_reset_log.name+': '+line) +# +# ############################### +# # Cleanup. +# time.sleep(1) +# +# f_list=( +# f_eds_to_local_host_sql +# ,f_eds_to_local_host_log +# ,f_eds_to_local_host_err +# ,f_db_reset_log +# ,f_db_reset_err +# ) +# cleanup( f_list ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + STDOUT in ISQL: CHECK_EDS_RESULT 1 + STDOUT in ISQL: Records affected: 1 + STDOUT in ISQL: Records affected: 0 + STDOUT in ISQL: CHECK_EDS_RESULT 1 + STDOUT in ISQL: Records affected: 1 + STDOUT in ISQL: Records affected: 0 + STDOUT in DB reset: Point before DB shutdown. + STDOUT in DB reset: Point after DB shutdown. + STDOUT in DB reset: Point after DB online. + """ + +@pytest.mark.version('>=3.0.3') +@pytest.mark.xfail +def test_core_5704_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5705.py b/tests/bugs/test_core_5705.py new file mode 100644 index 00000000..72e896bb --- /dev/null +++ b/tests/bugs/test_core_5705.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_5705 +# title: Store precision of DECFLOAT in RDB$FIELDS +# decription: +# Checked on LI-T4.0.0.940. +# +# tracker_id: CORE-5705 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + create domain dm_df16 as decfloat(16); + create domain dm_df34 as decfloat(34); + commit; + select rdb$field_name, rdb$field_precision + from rdb$fields + where rdb$field_name in (upper('dm_df16'), upper('dm_df34')) + order by 1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$FIELD_NAME DM_DF16 + RDB$FIELD_PRECISION 16 + + RDB$FIELD_NAME DM_DF34 + RDB$FIELD_PRECISION 34 + + Records affected: 2 + """ + +@pytest.mark.version('>=4.0') +def test_core_5705_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5706.py b/tests/bugs/test_core_5706.py new file mode 100644 index 00000000..06fd1168 --- /dev/null +++ b/tests/bugs/test_core_5706.py @@ -0,0 +1,276 @@ +#coding:utf-8 +# +# id: bugs.core_5706 +# title: Trace config with misplaced "{" lead firebird to crash +# decription: +# We create trace config with following INVALID content: +# database = (%[\\/](security[[:digit:]]).fdb|(security.db)) +# enabled = false +# { +# } +# +# database = +# { +# enabled = true +# log_connections = true +# } +# +# Then we run new process with ISQL with connect to test DB. +# This immediately should cause raise error in the 1st (trace) process: +# 1 Trace session ID 1 started +# 2 Error creating trace session for database "C:\\MIX\\FIREBIRD\\FB30\\SECURITY3.FDB": +# 3 error while parsing trace configuration +# 4 Trace parameters are not present +# NOTE. +# It was encountered that in FB 3.0.3 Classic lines 2..4 appear TWICE. See note in the ticket, 16/Jan/18 05:08 PM +# Checked on: +# 3.0.3.32876 (SS, CS) +# 4.0.0.852 (SS, CS) +# Checked again 29.07.2019 on: +# 4.0.0.1567: OK, 7.203s. +# 4.0.0.1535: OK, 11.601s. +# 4.0.0.1535: OK, 7.483s. +# 3.0.5.33160: OK, 6.882s. +# 3.0.5.33152: OK, 7.767s. +# 3.0.4.33054: OK, 8.622s. +# +# +# tracker_id: CORE-5706 +# min_versions: ['3.0.3'] +# versions: 3.0.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# from subprocess import Popen +# import difflib +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# def svc_get_fb_log( f_fb_log ): +# +# global subprocess +# subprocess.call([ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# 'action_get_fb_log' +# ], +# stdout=f_fb_log, stderr=subprocess.STDOUT +# ) +# return +# +# +# +# txt30 = r'''# Trace config, format for 3.0. Generated auto, do not edit! +# # ::: NOTE ::: +# # First 'database' section here INTENTIONALLY was written WRONG! +# database = (%[\\\\/](security[[:digit:]]).fdb|(security.db)) +# enabled = false +# { +# } +# +# database = +# { +# enabled = true +# log_connections = true +# } +# ''' +# +# fn_trccfg=open( os.path.join(context['temp_directory'],'tmp_trace_5706_3x.cfg'), 'w') +# fn_trccfg.write(txt30) +# flush_and_close( fn_trccfg ) +# +# f_fblog_before=open( os.path.join(context['temp_directory'],'tmp_5706_fblog_before.txt'), 'w') +# svc_get_fb_log( f_fblog_before ) +# flush_and_close( f_fblog_before ) +# +# +# # ############################################################## +# # S T A R T T R A C E i n S E P A R A T E P R O C E S S +# # ############################################################## +# +# fn_trclog=open( os.path.join(context['temp_directory'],'tmp_trace_5706_3x.log'), 'w') +# p_trace = Popen([context['fbsvcmgr_path'] , "localhost:service_mgr" , "action_trace_start" , "trc_cfg" , fn_trccfg.name], stdout=fn_trclog, stderr=subprocess.STDOUT) +# +# # We run here ISQL only in order to "wake up" trace session and force it to raise error in its log. +# # NO message like 'Statement failed, SQLSTATE = 08004/connection rejected by remote interface' should appear now! +# runProgram('isql', [ dsn, '-q', '-n' ], 'quit;') +# +# f_fblog_after=open( os.path.join(context['temp_directory'],'tmp_5706_fblog_after.txt'), 'w') +# svc_get_fb_log( f_fblog_after ) +# flush_and_close( f_fblog_after ) +# +# +# # _!_!_!_!_!_!_!_!_!_! do NOT reduce this delay: firebird.log get new messages NOT instantly !_!_!_!_!_!_!_!_ +# # Currently firebird.log can stay with OLD content if heavy concurrent workload exists on the same host! +# time.sleep(1) +# +# # #################################################### +# # G E T A C T I V E T R A C E S E S S I O N I D +# # #################################################### +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# +# fn_trclst=open( os.path.join(context['temp_directory'],'tmp_trace_5706_3x.lst'), 'w') +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", "action_trace_list"], stdout=fn_trclst, stderr=subprocess.STDOUT) +# flush_and_close( fn_trclst ) +# +# # Do not remove this line. +# time.sleep(1) +# +# trcssn=0 +# with open( fn_trclst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# +# # #################################################### +# # S E N D R E Q U E S T T R A C E T O S T O P +# # #################################################### +# if trcssn > 0: +# fn_nul = open(os.devnull, 'w') +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", "action_trace_stop","trc_id", trcssn], stdout=fn_nul) +# fn_nul.close() +# +# p_trace.terminate() +# fn_trclog.close() +# +# # Do not remove this line. +# #time.sleep(2) +# +# # Compare firebird.log versions BEFORE and AFTER this test: +# ###################### +# +# oldfb=open(f_fblog_before.name, 'r') +# newfb=open(f_fblog_after.name, 'r') +# +# difftext = ''.join(difflib.unified_diff( +# oldfb.readlines(), +# newfb.readlines() +# )) +# oldfb.close() +# newfb.close() +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_5706_diff.txt'), 'w') +# f_diff_txt.write(difftext) +# flush_and_close( f_diff_txt ) +# +# # Check logs: +# ############# +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# if line.startswith('+'): +# print( 'UNEXPECTED DIFF IN FIREBIRD.LOG: ' + (' '.join(line.split()).upper()) ) +# +# +# +# # NB! Lines starting from 2nd in the following error block: +# # Trace session ID 1 started +# # Error creating trace session for database "C:\\MIX\\FIREBIRD\\FB30\\SECURITY3.FDB": +# # error while parsing trace configuration +# # line 2: error while compiling regular expression "(%[\\/](security3).fdb|(security.db))" +# # - are duplicated in FB 3.0.3 Classic. +# # For this reason we collect all UNIQUE messages in the set() and output then only such distinct list. +# +# +# ''' +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# DISABLED 29.07.2019: +# 1. TRACE LOG FOR CLASSIC STRONGLY DIFFERS FROM SS. +# 2. IT'S NO MATTER WHAT TRACE LOG CONTAINS, MAIN GOAL: +# FIREBIRD.LOG MUST *NOT* DIFFER FROM ITSELF THAT IT WAS BEFORE THIS TEST RUN. +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# trc_unique_msg=set() +# with open( fn_trclog.name,'r') as f: +# for line in f: +# if 'error' in line.lower(): +# trc_unique_msg.add( ' '.join(line.split()).upper() ) +# +# for p in sorted(trc_unique_msg): +# print(p) +# ''' +# +# +# # CLEAN UP +# ########## +# time.sleep(1) +# f_list=( +# fn_trclog +# ,fn_trclst +# ,fn_trccfg +# ,f_fblog_before +# ,f_fblog_after +# ,f_diff_txt +# ) +# cleanup( f_list ) +# +# #, 'substitutions':[('FOR DATABASE.*','FOR DATABASE'), ('.*REGULAR EXPRESSION.*','REGULAR EXPRESSION ERROR'), ('TRACE SESSION ID [0-9]+ STARTED', 'TRACE SESSION ID STARTED') ] +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0.3') +@pytest.mark.xfail +def test_core_5706_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5707.py b/tests/bugs/test_core_5707.py new file mode 100644 index 00000000..6eefd2c3 --- /dev/null +++ b/tests/bugs/test_core_5707.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_5707 +# title: Begin and end of physical backup in the same transaction could crash engine +# decription: +# Confirmed crashes on: +# 3.0.3.32837 +# 4.0.0.800 +# Could NOT reproduce on 3.0.3.32882 (SS). +# Checked on: +# 30SS, build 3.0.3.32887: OK, 0.844s. +# 40SS, build 4.0.0.861: OK, 2.016s. +# +# tracker_id: CORE-5707 +# min_versions: ['3.0.3'] +# versions: 3.0.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + alter database begin backup end backup; + commit; + set autoddl off; + alter database begin backup; + alter database end backup; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DATABASE failed + -Incompatible ALTER DATABASE clauses: 'BEGIN BACKUP' and 'END BACKUP' + """ + +@pytest.mark.version('>=3.0.3') +def test_core_5707_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_5710.py b/tests/bugs/test_core_5710.py new file mode 100644 index 00000000..4c27da5a --- /dev/null +++ b/tests/bugs/test_core_5710.py @@ -0,0 +1,72 @@ +#coding:utf-8 +# +# id: bugs.core_5710 +# title: Datatype declaration DECFLOAT without precision should use a default precision +# decription: +# Checked on FB40SS, build 4.0.0.943: OK, 1.625s. +# +# tracker_id: CORE-5710 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + recreate table test( distance_small decfloat(16), distance_huge decfloat(34), distance_default decfloat ); + commit; + + select + r.rdb$field_name + ,f.rdb$field_length + ,f.rdb$field_scale + ,f.rdb$field_type + ,f.rdb$field_precision + from rdb$fields f + join rdb$relation_fields r on f.rdb$field_name = r.rdb$field_source + where + r.rdb$relation_name = upper('test') + and r.rdb$field_name starting with upper('distance') + order by r.rdb$field_position + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$FIELD_NAME DISTANCE_SMALL + RDB$FIELD_LENGTH 8 + RDB$FIELD_SCALE 0 + RDB$FIELD_TYPE 24 + RDB$FIELD_PRECISION 16 + + RDB$FIELD_NAME DISTANCE_HUGE + RDB$FIELD_LENGTH 16 + RDB$FIELD_SCALE 0 + RDB$FIELD_TYPE 25 + RDB$FIELD_PRECISION 34 + + RDB$FIELD_NAME DISTANCE_DEFAULT + RDB$FIELD_LENGTH 16 + RDB$FIELD_SCALE 0 + RDB$FIELD_TYPE 25 + RDB$FIELD_PRECISION 34 + """ + +@pytest.mark.version('>=4.0') +def test_core_5710_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5713.py b/tests/bugs/test_core_5713.py new file mode 100644 index 00000000..30d44fe8 --- /dev/null +++ b/tests/bugs/test_core_5713.py @@ -0,0 +1,58 @@ +#coding:utf-8 +# +# id: bugs.core_5713 +# title: Field alias disapears in complex query +# decription: +# Checked on: +# 3.0.3.32882: OK, 1.328s. +# 4.0.0.855: OK, 1.625s. +# +# tracker_id: CORE-5713 +# min_versions: ['3.0.3'] +# versions: 3.0.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select a1, a2 + from ( + select 1 a1, 2 a2 + from rdb$database + ) + group by 1, 2 + + union all + + select 1 a1, coalesce(cast(null as varchar(64)), 0) a2 + from rdb$database; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A1 1 + A2 2 + + A1 1 + A2 0 + """ + +@pytest.mark.version('>=3.0.3') +def test_core_5713_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5717.py b/tests/bugs/test_core_5717.py new file mode 100644 index 00000000..86078c18 --- /dev/null +++ b/tests/bugs/test_core_5717.py @@ -0,0 +1,68 @@ +#coding:utf-8 +# +# id: bugs.core_5717 +# title: Reject non-constant date/time/timestamp literals +# decription: +# Checked on 4.0.0.1479: OK, 1.631s. +# +# tracker_id: CORE-5717 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + select date '2018-01-01' from rdb$database; + select time '10:00:00' from rdb$database; + select timestamp '2018-01-01 10:00:00' from rdb$database; + select DATE 'TODAY' from rdb$database; + select DATE 'TOMORROW' from rdb$database; + select DATE 'YESTERDAY' from rdb$database; + select TIME 'NOW' from rdb$database; + select TIMESTAMP 'NOW' from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 2018-01-01 + 10:00:00.0000 + 2018-01-01 10:00:00.0000 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22018 + conversion error from string "TODAY" + + Statement failed, SQLSTATE = 22018 + conversion error from string "TOMORROW" + + Statement failed, SQLSTATE = 22018 + conversion error from string "YESTERDAY" + + Statement failed, SQLSTATE = 22018 + conversion error from string "NOW" + + Statement failed, SQLSTATE = 22018 + conversion error from string "NOW" + """ + +@pytest.mark.version('>=4.0') +def test_core_5717_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5719.py b/tests/bugs/test_core_5719.py new file mode 100644 index 00000000..c39156b6 --- /dev/null +++ b/tests/bugs/test_core_5719.py @@ -0,0 +1,192 @@ +#coding:utf-8 +# +# id: bugs.core_5719 +# title: FB >= 3 crashes when restoring backup made by FB 2.5. +# decription: +# This test also present in GTCS list, see it here: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/SV_HIDDEN_VAR_2_5.script +# Confirmed crash on: +# 3.0.3.32387 +# 4.0.0.861 +# Works fine on: +# FB30SS, build 3.0.3.32897: OK, 3.891s. +# FB40SS, build 4.0.0.872: OK, 4.421s. +# +# tracker_id: CORE-5719 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import time +# import zipfile +# import difflib +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# def svc_get_fb_log( f_fb_log ): +# +# global subprocess +# +# subprocess.call( [ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# "action_get_fb_log" +# ], +# stdout=f_fb_log, stderr=subprocess.STDOUT +# ) +# return +# +# +# zf = zipfile.ZipFile( os.path.join(context['files_location'],'core5719-ods-11_2.zip') ) +# tmpfbk = 'core5719-ods-11_2.fbk' +# zf.extract( tmpfbk, '$(DATABASE_LOCATION)') +# zf.close() +# +# tmpfbk='$(DATABASE_LOCATION)'+tmpfbk +# tmpfdb='$(DATABASE_LOCATION)'+'tmp_5719_check_restored.fdb' +# +# f_fblog_before=open( os.path.join(context['temp_directory'],'tmp_5719_fblog_before.txt'), 'w') +# svc_get_fb_log( f_fblog_before ) +# flush_and_close( f_fblog_before ) +# +# +# f_restore_log=open( os.path.join(context['temp_directory'],'tmp_5719_check_restored.log'), 'w') +# subprocess.check_call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_restore", +# "bkp_file", tmpfbk, +# "dbname", tmpfdb, +# "res_replace", +# "verbose" +# ], +# stdout=f_restore_log, +# stderr=subprocess.STDOUT) +# flush_and_close( f_restore_log ) +# +# f_fblog_after=open( os.path.join(context['temp_directory'],'tmp_5719_fblog_after.txt'), 'w') +# svc_get_fb_log( f_fblog_after ) +# flush_and_close( f_fblog_after ) +# +# +# f_validation_log=open( os.path.join(context['temp_directory'],'tmp_5719_validation.log'), 'w') +# subprocess.check_call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_validate", +# "dbname", tmpfdb, +# ], +# stdout=f_validation_log, +# stderr=subprocess.STDOUT) +# flush_and_close( f_validation_log ) +# +# # Compare firebird.log versions BEFORE and AFTER this test: +# ###################### +# +# oldfb=open(f_fblog_before.name, 'r') +# newfb=open(f_fblog_after.name, 'r') +# +# difftext = ''.join(difflib.unified_diff( +# oldfb.readlines(), +# newfb.readlines() +# )) +# oldfb.close() +# newfb.close() +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_5719_diff.txt'), 'w') +# f_diff_txt.write(difftext) +# flush_and_close( f_diff_txt ) +# +# # Check logs: +# ############# +# with open( f_restore_log.name,'r') as f: +# for line in f: +# if 'Error'.upper() in line.upper(): +# print( 'UNEXPECTED ERROR IN RESTORE LOG: ' + (' '.join(line.split()).upper()) ) +# +# with open( f_validation_log.name,'r') as f: +# for line in f: +# if 'Error'.upper() in line.upper(): +# print( 'UNEXPECTED ERROR IN VALIDATION LOG: ' + (' '.join(line.split()).upper()) ) +# +# +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# if line.startswith('+'): +# print( 'UNEXPECTED DIFF IN FIREBIRD.LOG: ' + (' '.join(line.split()).upper()) ) +# +# +# ########## +# # Cleanup: +# ########## +# time.sleep(1) +# +# f_list=( +# f_restore_log +# ,f_validation_log +# ,f_fblog_before +# ,f_fblog_after +# ,f_diff_txt +# ,tmpfbk +# ,tmpfdb +# ) +# cleanup( f_list ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_5719_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5726.py b/tests/bugs/test_core_5726.py new file mode 100644 index 00000000..bc5c5aac --- /dev/null +++ b/tests/bugs/test_core_5726.py @@ -0,0 +1,80 @@ +#coding:utf-8 +# +# id: bugs.core_5726 +# title: Unclear error message when inserting value exceeding max of dec_fixed decimal +# decription: +# FB40SS, build 4.0.0.1008: OK, 1.641s. +# Previously used: +# create table extdecimal( dec34_34 decimal(34, 34) ); +# insert into extdecimal values(1); +# -- and this raised following exception: +# SQLCODE: -901 +# Decimal float invalid operation. An indeterminant error occurred during an operation. +# numeric value is out of range +# ================================== +# Since 30.10.2019 DDL was changed: +# create table test(n numeric(38,38) ); +# insert into test values( 1.70141183460469231731687303715884105727 ); -- must PASS +# insert into test values( 1.70141183460469231731687303715884105727001 ); -- must FAIL. +# Explanation: +# 1.70141183460469231731687303715884105727 represents +# 2^127-1 // 170141183460469231731687303715884105728-1 +# +# Checked on: 4.0.0.1635 +# 25.06.2020, 4.0.0.2076: changed types in SQLDA from numeric to int128 // after discuss with Alex about CORE-6342. +# +# tracker_id: CORE-5726 +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('^((?!(sqltype|max_precise_number)).)*$', ''), ('[ \t]+', ' '), ('.*alias.*', '')] + +init_script_1 = """ + -- insert into test(n) values( + -- 1.70141183460469231731687303715); + -- insert into test(n) values(1.7014118346046923173168730371588410572700); + + recreate table test ( + id integer generated always as identity primary key, + n numeric(38,38) + ); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + insert into test(n) values( 1.70141183460469231731687303715884105727 ); + insert into test(n) values( 1.70141183460469231731687303715884105727001 ); + set sqlda_display on; + select n as "max_precise_number" from test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 01: sqltype: 32752 INT128 Nullable scale: -38 subtype: 1 len: 16 + max_precise_number 1.70141183460469231731687303715884105727 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22003 + arithmetic exception, numeric overflow, or string truncation + -numeric value is out of range + """ + +@pytest.mark.version('>=4.0') +def test_core_5726_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5728.py b/tests/bugs/test_core_5728.py new file mode 100644 index 00000000..3c4a7445 --- /dev/null +++ b/tests/bugs/test_core_5728.py @@ -0,0 +1,57 @@ +#coding:utf-8 +# +# id: bugs.core_5728 +# title: When requesting the subtype of a NUMERIC or DECIMAL column with precision in [19, 34] using isc_info_sql_sub_type, it always returns 0, instead of 1 for NUMERIC and 2 for DECIMAL. +# decription: +# Confirmed wrong result on: 4.0.0.918 +# Checked on 4.0.0.943: OK, 1.235s. +# +# 30.10.2019. Adjusted expected-stdout to current FB, new datatype was introduced: numeric(38). +# Checked on: 4.0.0.1635. +# 25.06.2020, 4.0.0.2076: changed types in SQLDA from numeric to int128 // after discuss with Alex about CORE-6342. +# +# tracker_id: CORE-5728 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('^((?!sqltype).)*$', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test( + distance_num_1 numeric(19) + ,distance_num_2 numeric(34) + ,distance_dec_1 decimal(19) + ,distance_dec_2 decimal(34) + ); + commit; + + set sqlda_display on; + select * from test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 01: sqltype: 32752 INT128 Nullable scale: 0 subtype: 1 len: 16 + 02: sqltype: 32752 INT128 Nullable scale: 0 subtype: 1 len: 16 + 03: sqltype: 32752 INT128 Nullable scale: 0 subtype: 2 len: 16 + 04: sqltype: 32752 INT128 Nullable scale: 0 subtype: 2 len: 16 + """ + +@pytest.mark.version('>=4.0') +def test_core_5728_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5737.py b/tests/bugs/test_core_5737.py new file mode 100644 index 00000000..e9a619fb --- /dev/null +++ b/tests/bugs/test_core_5737.py @@ -0,0 +1,145 @@ +#coding:utf-8 +# +# id: bugs.core_5737 +# title: Invalid parameters of gds transaction in ISQL +# decription: +# ISQL hangs when trying to show various system objects in a case when other attachment has uncommitted changes to that objects +# We create (in Python connection) one table TEST1 with PK and commit transaction. +# Then we create second (similar) table TEST2 but do not commit transaction. +# After this we launch ISQL in async. mode and ask him to perform SHOW TABLE and SHOW INDEX commands. +# ISQL: +# 1) should NOT hang (it did this because of launching Tx in read committed NO record_version); +# 2) should output only info about table TEST1 and ints PK index. +# 3) should not output any info about non-committed DDL of table TEST2. +# +# Confirmed bug on 3.0.3.32837 and 4.0.0.800 (ISQL did hang when issued any of 'SHOW TABLE' / 'SHOW INDEX' copmmand). +# Checked on: +# 3.0.3.32901: OK, 3.938s. +# 4.0.0.875: OK, 3.969s. +# +# tracker_id: CORE-5737 +# min_versions: ['3.0.3'] +# versions: 3.0.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# from subprocess import Popen +# import time +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# +# #-------------------------------------------- +# +# 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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# cur = db_conn.cursor() +# db_conn.execute_immediate('recreate table test1(id int primary key using descending index test1_id_pk_desc)') +# db_conn.commit() +# cur.execute('recreate table test2(id int primary key using descending index test2_id_pk_desc)') +# +# show_query=''' +# show table; +# show index; +# ''' +# +# f_show_command_sql = open( os.path.join(context['temp_directory'],'tmp_local_host_5737.sql'), 'w') +# f_show_command_sql.write( show_query ) +# flush_and_close( f_show_command_sql ) +# +# f_show_command_log = open( os.path.join(context['temp_directory'],'tmp_local_host_5737.log'), 'w') +# f_show_command_err = open( os.path.join(context['temp_directory'],'tmp_local_host_5737.err'), 'w') +# +# # WARNING: we launch ISQL here in async mode in order to have ability to kill its process if it will hang! +# ############################################ +# p_isql_to_local_host = subprocess.Popen( [ context['isql_path'], dsn, "-i", f_show_command_sql.name ], +# stdout = f_show_command_log, +# stderr = f_show_command_err +# ) +# +# time.sleep(2) +# +# p_isql_to_local_host.terminate() +# flush_and_close( f_show_command_log ) +# flush_and_close( f_show_command_err ) +# +# with open( f_show_command_log.name,'r') as f: +# for line in f: +# if line.split(): +# print('STDOUT: ', ' '.join(line.split()) ) +# +# +# with open( f_show_command_err.name,'r') as f: +# for line in f: +# if line.split(): +# print('STDERR: ', ' '.join(line.split()) ) +# +# cur.close() +# +# +# # Cleanup. +# ########## +# time.sleep(1) +# cleanup( (f_show_command_sql, f_show_command_log, f_show_command_err) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + STDOUT: TEST1 + STDOUT: TEST1_ID_PK_DESC UNIQUE DESCENDING INDEX ON TEST1(ID) + """ + +@pytest.mark.version('>=3.0.3') +@pytest.mark.xfail +def test_core_5737_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5742.py b/tests/bugs/test_core_5742.py new file mode 100644 index 00000000..b09b50d3 --- /dev/null +++ b/tests/bugs/test_core_5742.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_5742 +# title: Incorrect error message in iSQL when trying to create database with wrong password +# decription: +# We can just attempt to create current test database with wrong password. +# Result should contain text "SQLSTATE=28000" +# ("Your user name and password are not defined" or "install incomplete..." - no matter). +# +# Confirmed bug on 3.0.4.32917; 4.0.0.907 +# Works fine on 3.0.4.32919. +# +# tracker_id: CORE-5742 +# min_versions: ['3.0.4'] +# versions: 3.0.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [('^((?!SQLSTATE).)*$', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + commit; + create database '$(DSN)' user sysdba password 'T0tAlly$Wr0ng'; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 28000 + """ + +@pytest.mark.version('>=3.0.4') +def test_core_5742_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_5743.py b/tests/bugs/test_core_5743.py new file mode 100644 index 00000000..933094cf --- /dev/null +++ b/tests/bugs/test_core_5743.py @@ -0,0 +1,66 @@ +#coding:utf-8 +# +# id: bugs.core_5743 +# title: Conversion error when both GROUP/ORDER BY expressions and WHERE expressions contain literals +# decription: +# Confirmed bug on: 3.0.3.32901, 4.0.0.875. +# Minimal requirements for reproduce: 1) boolean field with reference in WHERE clause; 2) indexed integer field. +# Checked on: +# 3.0.4.32912: OK, 1.296s. +# 4.0.0.800: OK, 2.171s. +# 4.0.0.890: OK, 1.906s. +# +# tracker_id: CORE-5743 +# min_versions: ['3.0.4'] +# versions: 3.0.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table journal_caisse ( + annule boolean + ,periode int + ); + create index journal_caisse_idx on journal_caisse (periode); + set planonly; + select 1 as type_mvt + from journal_caisse + where + annule is false + and + (periode = ?) + group by 1 + ; + + -- sample from CORE-5749: + select 'my constant ' as dsc, count( * ) + from rdb$relations a + where a.rdb$system_flag = 99 + group by 1 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN SORT (JOURNAL_CAISSE INDEX (JOURNAL_CAISSE_IDX)) + PLAN SORT (A NATURAL) + """ + +@pytest.mark.version('>=3.0.4') +def test_core_5743_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5746.py b/tests/bugs/test_core_5746.py new file mode 100644 index 00000000..b14a1b4a --- /dev/null +++ b/tests/bugs/test_core_5746.py @@ -0,0 +1,122 @@ +#coding:utf-8 +# +# id: bugs.core_5746 +# title: Remove the restriction on create/delete, enable/disable the user indexes in system tables +# decription: +# Test verifies that one may to: +# * create two indices (common and calculated) and +# * gather statistics on them +# * make some of them inactive and return then to active state +# * drop them. +# This is checked first under SYSDBA account, then under common non-privileged user (and these attempts should raise exception) +# and finally we grant DDL privilege to this user (ALTER ANY TABLE) and check again, and this should pass OK. +# +# ::: NB ::: +# +# Restictions about create/alter/drop indexes on system tables that are checked by test for CORE-4731 should be removed. +# +# Checked on: +# 3.0.4.32944: OK, 1.500s. +# 4.0.0.952: OK, 1.079s. +# +# tracker_id: CORE-5746 +# min_versions: ['3.0.4'] +# versions: 3.0.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [('-Effective user is.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + 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; + + alter index systable_calc_idx inactive; + alter index systable_calc_idx active; + + drop index systable_comm_idx; + drop index systable_calc_idx; + commit; + + create or alter user tmp$c5746 password '123'; + commit; + + connect '$(DSN)' user tmp$c5746 password '123'; + -- this should FAIL: + create descending index systable_comm_idx on rdb$relations(rdb$format); + commit; + + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + grant alter any table to tmp$c5746; + commit; + + + 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; + + 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; + + alter index systable_calc_idx inactive; + alter index systable_calc_idx active; + + drop index systable_comm_idx; + drop index systable_calc_idx; + commit; + + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + drop user tmp$c5746; + commit; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (RDB$RELATIONS INDEX (SYSTABLE_COMM_IDX)) + SIGN_COUNT 1 + PLAN (RDB$RELATIONS INDEX (SYSTABLE_CALC_IDX)) + SIGN_COUNT 1 + + PLAN (RDB$RELATIONS INDEX (SYSTABLE_COMM_IDX)) + SIGN_COUNT 1 + PLAN (RDB$RELATIONS INDEX (SYSTABLE_CALC_IDX)) + SIGN_COUNT 1 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -CREATE INDEX SYSTABLE_COMM_IDX failed + -no permission for ALTER access to TABLE RDB$RELATIONS + """ + +@pytest.mark.version('>=3.0.4') +def test_core_5746_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5747.py b/tests/bugs/test_core_5747.py new file mode 100644 index 00000000..e98c354b --- /dev/null +++ b/tests/bugs/test_core_5747.py @@ -0,0 +1,162 @@ +#coding:utf-8 +# +# id: bugs.core_5747 +# title: User can grant usage privilege by himself +# decription: +# Confirmed bug on: 4.0.0.890; 3.0.4.32912 +# Works fine on: +# 3.0.4.32917: OK, 1.891s. +# 4.0.0.907: OK, 1.765s. +# Note: beside generator we also have to check the same issue about grant usage on exception. +# +# tracker_id: CORE-5747 +# min_versions: ['3.0.4'] +# versions: 3.0.4, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [('no G privilege with grant option on object .*', 'no USAGE privilege with grant option on object'), ('GEN_FOR_DBA_ONLY', ''), ('EXC_FOR_DBA_ONLY', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + commit; + connect '$(DSN)' user sysdba password 'masterkey'; + + create or alter user tmp$c5747 password '123'; + commit; + + recreate sequence gen_for_dba_only; + recreate exception exc_for_dba_only 'Your names is: @1 - and you should not be able to use this exception!'; + commit; + + connect '$(DSN)' user tmp$c5747 password '123'; + + grant usage on generator gen_for_dba_only to tmp$c5747; + grant usage on exception exc_for_dba_only to tmp$c5747; + commit; + + connect '$(DSN)' user tmp$c5747 password '123'; + + set list on; + + select gen_id(gen_for_dba_only,1) as next_secret_system_sequence from rdb$database; + set term ^; + execute block as + begin + exception exc_for_dba_only using (current_user); + end + ^ + set term ;^ + + commit; + connect '$(DSN)' user sysdba password 'masterkey'; + drop user tmp$c5747; + commit; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + 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 + Statement failed, SQLSTATE = 28000 + no permission for USAGE access to EXCEPTION + """ + +@pytest.mark.version('>=3.0.4,<4.0') +def test_core_5747_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + +# version: 4.0 +# resources: None + +substitutions_2 = [('no G privilege with grant option on object .*', 'no USAGE privilege with grant option on object'), ('GEN_FOR_DBA_ONLY', ''), ('EXC_FOR_DBA_ONLY', '')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + commit; + connect '$(DSN)' user sysdba password 'masterkey'; + + create or alter user tmp$c5747 password '123'; + commit; + + recreate sequence gen_for_dba_only; + recreate exception exc_for_dba_only 'Your names is: @1 - and you should not be able to use this exception!'; + commit; + + connect '$(DSN)' user tmp$c5747 password '123'; + + grant usage on generator gen_for_dba_only to tmp$c5747; + grant usage on exception exc_for_dba_only to tmp$c5747; + commit; + + connect '$(DSN)' user tmp$c5747 password '123'; + + set list on; + + select gen_id(gen_for_dba_only,1) as next_secret_system_sequence from rdb$database; + set term ^; + execute block as + begin + exception exc_for_dba_only using (current_user); + end + ^ + set term ;^ + + commit; + connect '$(DSN)' user sysdba password 'masterkey'; + drop user tmp$c5747; + commit; + + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stderr_2 = """ + 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') +def test_core_5747_2(act_2: Action): + act_2.expected_stderr = expected_stderr_2 + act_2.execute() + assert act_2.clean_expected_stderr == act_2.clean_stderr + diff --git a/tests/bugs/test_core_5750.py b/tests/bugs/test_core_5750.py new file mode 100644 index 00000000..0dc9dc18 --- /dev/null +++ b/tests/bugs/test_core_5750.py @@ -0,0 +1,134 @@ +#coding:utf-8 +# +# id: bugs.core_5750 +# title: Date-time parsing is very weak +# decription: +# Checked on: 4.0.0.1479: OK, 1.263s. +# +# 27.10.2020. +# Parser changed after following fixes: +# - CORE-6427 - Whitespace as date separator causes conversion error. +# - CORE-6429 - Timezone offset in timestamp/time literal and CAST should follow SQL standard syntax only. +# See: https://github.com/FirebirdSQL/firebird/commit/ff37d445ce844f991242b1e2c1f96b80a5d1636d +# Adjusted expected stdout/stderr after discuss with Adriano. +# Checked on 4.0.0.2238 +# +# tracker_id: CORE-5750 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + --set echo on; + + -- All these must fail: + select timestamp '2018-01-01 10 20 30' from rdb$database; + select timestamp '2018-01-01 10,20,30 40' from rdb$database; + select timestamp '31.05.2017 1:2:3.4567' from rdb$database; + select timestamp '31/05/2017 2:3:4.5678' from rdb$database; + ------------------------------------------------------------ + + -- Date components separator may be a single one (first and second occurence): dash, slash or dot. + select date '2018-01-31' from rdb$database; + select date '2018/01/31' from rdb$database; + select date '2018.01.31' from rdb$database; + select date '2018' from rdb$database; + select date '2018,01,31' from rdb$database; + select date '2018/01.31' from rdb$database; + select date '2018 01 31' from rdb$database; + + -- Time components (hours to minutes to seconds) separator may be colon. + select time '10:29:39' from rdb$database; + select time '10/29/39' from rdb$database; + select time '10.29.39' from rdb$database; + select time '10-29-39' from rdb$database; + select time '10 29 39' from rdb$database; + + -- Seconds to fractions separator may be dot. + select time '7:3:1.' from rdb$database; + select time '7:3:2.1238' from rdb$database; + select time '7:3:3,1238' from rdb$database; + + -- There could *NOT* be any separator (other than spaces) between date and time. + select timestamp '2018-01-01T01:02:03.4567' from rdb$database; + select timestamp '31.05.2017 11:22:33.4455' from rdb$database; + select timestamp '31.05.2017 + 22:33:44.5577' from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 2017-05-31 01:02:03.4567 + 2018-01-31 + 2018-01-31 + 2018-01-31 + 2018-01-31 + 10:29:39.0000 + 07:03:01.0000 + 07:03:02.1238 + 2017-05-31 11:22:33.4455 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22009 + Invalid time zone region: 20 30 + + Statement failed, SQLSTATE = 22009 + Invalid time zone region: ,20,30 40 + + Statement failed, SQLSTATE = 22018 + conversion error from string "31/05/2017 2:3:4.5678" + + Statement failed, SQLSTATE = 22018 + conversion error from string "2018" + + Statement failed, SQLSTATE = 22018 + conversion error from string "2018,01,31" + + Statement failed, SQLSTATE = 22018 + conversion error from string "2018/01.31" + + Statement failed, SQLSTATE = 22009 + Invalid time zone region: /29/39 + + Statement failed, SQLSTATE = 22009 + Invalid time zone region: .39 + + Statement failed, SQLSTATE = 22009 + Invalid time zone offset: -29-39 - must use format +/-hours:minutes and be between -14:00 and +14:00 + + Statement failed, SQLSTATE = 22009 + Invalid time zone region: 29 39 + + Statement failed, SQLSTATE = 22009 + Invalid time zone region: ,1238 + + Statement failed, SQLSTATE = 22009 + Invalid time zone region: T01:02:03.4567 + + Statement failed, SQLSTATE = 22009 + Invalid time zone region: + 22:33:44.5577 + """ + +@pytest.mark.version('>=4.0') +def test_core_5750_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5753.py b/tests/bugs/test_core_5753.py new file mode 100644 index 00000000..2c1b0cb8 --- /dev/null +++ b/tests/bugs/test_core_5753.py @@ -0,0 +1,82 @@ +#coding:utf-8 +# +# id: bugs.core_5753 +# title: Parser allows to use GRANT OPTION for FUNCTION and PACKAGE +# decription: +# Confirmed bug on: 4.0.0.890; 3.0.4.32912 +# Works fine on: +# 3.0.4.32917: OK, 0.937s. +# 4.0.0.907: OK, 1.187s. +# +# tracker_id: CORE-5753 +# min_versions: ['3.0.4'] +# versions: 3.0.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + + set term ^; + create or alter procedure sp_test as + begin + end + ^ + create or alter function sa_func(a int) returns bigint as + begin + return a * a; + end + ^ + recreate package pg_test as + begin + function pg_func(a int) returns bigint; + end + ^ + create package body pg_test as + begin + function pg_func(a int) returns bigint as + begin + return a * a; + end + end + ^ + set term ;^ + commit; + + -- following two statements have to raise error (but did not before fix): + grant execute on procedure sp_test to function sa_func with grant option; + grant execute on procedure sp_test to package pg_test with grant option; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -GRANT failed + -Dynamic SQL Error + -Using GRANT OPTION on functions not allowed + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -GRANT failed + -Dynamic SQL Error + -Using GRANT OPTION on packages not allowed + """ + +@pytest.mark.version('>=3.0.4') +def test_core_5753_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_5754.py b/tests/bugs/test_core_5754.py new file mode 100644 index 00000000..7c455e64 --- /dev/null +++ b/tests/bugs/test_core_5754.py @@ -0,0 +1,95 @@ +#coding:utf-8 +# +# id: bugs.core_5754 +# title: ALTER TRIGGER check privilege for alter database instead of table +# decription: +# 3.0.4.32917: OK, 1.485s. +# 4.0.0.907: OK, 1.843s. +# +# tracker_id: CORE-5754 +# min_versions: ['3.0.4'] +# versions: 3.0.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + + create or alter user tmp$c5754 password '123'; + commit; + + recreate table test(id int); + recreate sequence g; + commit; + + -- GRANT ALTER ANY TO [USER | ROLE] [WITH GRANT OPTION]; + -- DDL operations for managing triggers and indices re-use table privileges. + grant alter any table to tmp$c5754; + 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, 1) ); + end + ^ + set term ;^ + commit; + + connect '$(DSN)' user tmp$c5754 password '123'; + + set term ^; + + -- Following attempt to alter trigger will fail on 4.0.0.890 with message: + -- Statement failed, SQLSTATE = 28000 + -- unsuccessful metadata update + -- -ALTER TRIGGER TEST_BI failed + -- -no permission for ALTER access to DATABASE + alter trigger test_bi as + begin + -- this trigger was updated by tmp$c5754 + if ( new.id is null ) then + new.id = gen_id(g, 1); + end + ^ + set term ^; + commit; + + commit; + connect '$(DSN)' user sysdba password 'masterkey'; + drop user tmp$c5754; + commit; + + set list on; + + select 1 as result + from rdb$triggers + where rdb$trigger_name = upper('test_bi') + and rdb$trigger_source containing 'tmp$c5754' + ; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT 1 + """ + +@pytest.mark.version('>=3.0.4') +def test_core_5754_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5755.py b/tests/bugs/test_core_5755.py new file mode 100644 index 00000000..be6d3fb3 --- /dev/null +++ b/tests/bugs/test_core_5755.py @@ -0,0 +1,105 @@ +#coding:utf-8 +# +# id: bugs.core_5755 +# title: No error if the GRANT target object does not exist +# decription: +# Checked on: +# 30SS, build 3.0.4.32984: OK, 1.391s. +# 40SS, build 4.0.0.998: OK, 1.422s. +# +# ::: NOTE ::: +# 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. +# +# tracker_id: CORE-5755 +# min_versions: ['3.0.4'] +# versions: 3.0.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table table_test(x int); + create or alter procedure sp_test as begin end; + + set term ^; + create or alter function fn_test returns int as + begin + return cast( rand()*10000 as int ); + end + ^ + + create or alter package pkg_test as + begin + procedure sp_foo; + end + ^ + + recreate package body pkg_test as + begin + procedure sp_foo as + declare c int; + begin + c = 1; + end + end + ^ + set term ;^ + + recreate sequence g_test; + recreate exception x_test 'foo!'; + commit; + + grant create table to function wrong_func; + + 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; + + grant execute on package pkg_test to wrong_func; + + grant usage on sequence g_test to wrong_func; + + grant usage on exception x_test to wrong_func; + + **************/ + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + 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 + """ + +@pytest.mark.version('>=3.0.4') +def test_core_5755_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_5756.py b/tests/bugs/test_core_5756.py new file mode 100644 index 00000000..f722b087 --- /dev/null +++ b/tests/bugs/test_core_5756.py @@ -0,0 +1,57 @@ +#coding:utf-8 +# +# id: bugs.core_5756 +# title: Regression: FB crashes when trying to recreate table that is in use by DML (3.0.3; 3.0.4; 4.0.0) +# decription: +# Detected bug on 3.0.4.32819 and 4.0.0.853. +# Checked on: +# 3.0.4.32920: OK, 1.047s. +# 4.0.0.912: OK, 1.188s. +# +# tracker_id: CORE-5756 +# min_versions: ['3.0.4'] +# versions: 3.0.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + recreate table test(x int); + insert into test values(1); + select * from test; + recreate table test(x int, y int); -- this led to crash + commit; + select * from test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + X 1 + X 1 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -object TABLE "TEST" is in use + """ + +@pytest.mark.version('>=3.0.4') +def test_core_5756_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5756_addi.py b/tests/bugs/test_core_5756_addi.py new file mode 100644 index 00000000..11f18647 --- /dev/null +++ b/tests/bugs/test_core_5756_addi.py @@ -0,0 +1,237 @@ +#coding:utf-8 +# +# id: bugs.core_5756_addi +# title: Regression: FB crashes when trying to recreate table that is in use by DML +# decription: +# A bug was detected during implementation of test for CORE-5754: FB crashed with currpupting database +# after we run test script two times (letter to dimitr et al 20-feb-18 13:52). Moreover, gfix -v -full +# did not produce any messages about database state, so test DB should be restored from copy. +# Decided to change name of this .fbt after getting reply from Roman Simakov (21-feb-2018 12:19) +# that this bug was already fixed by dimitr in: +# https://github.com/FirebirdSQL/firebird/commit/9afef198c17368276ccd7a428e159c1ca5684a60 +# (Postfix for CORE-2284/CORE-5677, fixes regression CORE-5756) +# Checked on: +# 3.0.4.32920: OK, 2.625s. +# 4.0.0.912: OK, 2.781s. +# ::: NOTE ::: +# Script for test is launched here TWO times ("pass I", "pass II"). +# +# tracker_id: CORE-5756 +# min_versions: ['3.0.4'] +# versions: 3.0.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + commit; + + ------------------------------------------------- PASS I -------------------------------- + + connect '$(DSN)' user sysdba password 'masterkey'; + + create or alter user tmp$c5754 password '123'; + commit; + + create or alter trigger ddl_log_afte inactive after any ddl statement as begin end; + commit; + drop trigger ddl_log_afte; + commit; + + connect '$(DSN)' user sysdba password 'masterkey'; + + recreate table ddl_log(id int); + recreate table test(id int); + recreate sequence g; + commit; + + recreate table ddl_log ( + evn_type varchar(50) + ,obj_type varchar(50) + ,obj_name varchar(50) + ,sql_text blob sub_type text + ,last_ddl_author varchar(50) default current_user + ); + commit; + + -- DDL operations for managing triggers and indices re-use table privileges. + grant alter any table to tmp$c5754; + 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, 1) ); + end + ^ + + create or alter trigger ddl_log_afte active after any ddl statement as + begin + in autonomous transaction do + insert into ddl_log( + evn_type + ,obj_type + ,obj_name + ,sql_text + ) + values ( + rdb$get_context('DDL_TRIGGER', 'EVENT_TYPE') + ,rdb$get_context('DDL_TRIGGER', 'OBJECT_TYPE') + ,rdb$get_context('DDL_TRIGGER', 'OBJECT_NAME') + ,rdb$get_context('DDL_TRIGGER', 'SQL_TEXT') + ); + + end + ^ + + set term ;^ + commit; + + connect '$(DSN)' user tmp$c5754 password '123'; + + set term ^; + alter trigger test_bi as + begin + -- this trigger was updated by tmp$c5754 + if ( new.id is null ) then + new.id = gen_id(g, 1); + end + ^ + set term ^; + commit; + + connect '$(DSN)' user sysdba password 'masterkey'; + drop user tmp$c5754; + commit; + + set list on; + set count on; + --set echo on; + select last_ddl_author + from ddl_log + where + evn_type = upper('alter') + and obj_type = upper('trigger') + and sql_text containing 'tmp$c5754' + ; + rollback; + + ------------------------------------------------- PASS II -------------------------------- + + connect '$(DSN)' user sysdba password 'masterkey'; + + create or alter user tmp$c5754 password '123'; + commit; + + create or alter trigger ddl_log_afte inactive after any ddl statement as begin end; + commit; + drop trigger ddl_log_afte; + commit; + + connect '$(DSN)' user sysdba password 'masterkey'; + + recreate table ddl_log(id int); + recreate table test(id int); + recreate sequence g; + commit; + + recreate table ddl_log ( + evn_type varchar(50) + ,obj_type varchar(50) + ,obj_name varchar(50) + ,sql_text blob sub_type text + ,last_ddl_author varchar(50) default current_user + ); + commit; + + -- DDL operations for managing triggers and indices re-use table privileges. + grant alter any table to tmp$c5754; + 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, 1) ); + end + ^ + + create or alter trigger ddl_log_afte active after any ddl statement as + begin + in autonomous transaction do + insert into ddl_log( + evn_type + ,obj_type + ,obj_name + ,sql_text + ) + values ( + rdb$get_context('DDL_TRIGGER', 'EVENT_TYPE') + ,rdb$get_context('DDL_TRIGGER', 'OBJECT_TYPE') + ,rdb$get_context('DDL_TRIGGER', 'OBJECT_NAME') + ,rdb$get_context('DDL_TRIGGER', 'SQL_TEXT') + ); + + end + ^ + + set term ;^ + commit; + + connect '$(DSN)' user tmp$c5754 password '123'; + + set term ^; + alter trigger test_bi as + begin + -- this trigger was updated by tmp$c5754 + if ( new.id is null ) then + new.id = gen_id(g, 1); + end + ^ + set term ^; + commit; + + connect '$(DSN)' user sysdba password 'masterkey'; + drop user tmp$c5754; + commit; + + set list on; + set count on; + + select last_ddl_author + from ddl_log + where + evn_type = upper('alter') + and obj_type = upper('trigger') + and sql_text containing 'tmp$c5754' + ; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + LAST_DDL_AUTHOR TMP$C5754 + Records affected: 1 + LAST_DDL_AUTHOR TMP$C5754 + Records affected: 1 + """ + +@pytest.mark.version('>=3.0.4') +def test_core_5756_addi_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5768.py b/tests/bugs/test_core_5768.py new file mode 100644 index 00000000..fbe0b9de --- /dev/null +++ b/tests/bugs/test_core_5768.py @@ -0,0 +1,69 @@ +#coding:utf-8 +# +# id: bugs.core_5768 +# title: Implement FILTER-clause for aggregate functions (introduced in SQL:2003). This syntax allows for filtering before aggregation. +# decription: +# Checked on 4.0.0.1249: OK. +# +# tracker_id: CORE-5768 +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test(x int, y int, q int); + commit; + insert into test(x,y,q) values(null, null, 100); + insert into test(x,y,q) values(null, null, 200); + insert into test(x,y,q) values(1000, null, 111); + insert into test(x,y,q) values(1000, null, 222); + insert into test(x,y,q) values(1000, 1000, 555); + insert into test(x,y,q) values(1000, 1000, 777); + commit; + set list on; + select + sum( iif(x is null, q, null) ) sum_q_iif_x_is_null + ,sum( q )filter( where x is null ) sum_q_filter_x_is_null + ,min( sum_q_iif_y_is_null_over ) filter( where true ) chk_filter_where_true + ,min( sum_q_filter_y_is_null_over ) filter( where null is null ) chk_filter_where_n_is_n + ,min( 1 ) filter( where null ) chk_filter_where_null ------------------------------------- allowed! boolean but without left part ?.. + ,min( 1 ) filter( where not null ) chk_filter_where_not_null + from ( + select x, y, q + ,sum( iif(y is null, q, null) ) over() sum_q_iif_y_is_null_over + ,sum( q )filter( where y is null) over() sum_q_filter_y_is_null_over + from test + ) + ; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + SUM_Q_IIF_X_IS_NULL 300 + SUM_Q_FILTER_X_IS_NULL 300 + CHK_FILTER_WHERE_TRUE 633 + CHK_FILTER_WHERE_N_IS_N 633 + CHK_FILTER_WHERE_NULL + CHK_FILTER_WHERE_NOT_NULL + """ + +@pytest.mark.version('>=4.0') +def test_core_5768_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5770.py b/tests/bugs/test_core_5770.py new file mode 100644 index 00000000..c1608426 --- /dev/null +++ b/tests/bugs/test_core_5770.py @@ -0,0 +1,115 @@ +#coding:utf-8 +# +# id: bugs.core_5770 +# title: User who is allowed to manage other users must have this ability WITHOUT need to grant him RDB$ADMIN role +# decription: +# ::::: NB :::: +# Could not check actual result of fbtest execution, done only using ISQL and copy its result here. +# Checked on WI-T4.0.0.927, Win 64x. +# Checked 06.08.2018 on 4.0.0.1143: OK, 4.328s. +# +# tracker_id: CORE-5770 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('Use CONNECT or CREATE DATABASE.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set wng off; + + recreate view v_sec as + select + current_user as who_am_i + ,s.sec$user_name + ,s.sec$active + ,s.sec$admin + ,s.sec$plugin + from sec$users s + where upper(sec$user_name) = upper('tmp$c5770_bar'); + commit; + grant select on v_sec to public; + commit; + + create or alter user tmp$c5770_foo password '123' using plugin Srp grant admin role; + create or alter user tmp$c5770_bar password '456' inactive using plugin Srp; + commit; + revoke all on all from tmp$c5770_foo; + revoke all on all from tmp$c5770_bar; + commit; + + connect '$(DSN)' user tmp$c5770_foo password '123'; + --select current_user as who_am_i from rdb$database; + commit; + + -- check that sub-admin user 'foo' can make common user 'bar' ACTIVE: + alter user tmp$c5770_bar active using plugin Srp; + commit; + select * from v_sec; + commit; + + connect '$(DSN)' user tmp$c5770_bar password '456'; -- should PASS because he is ACTIVE now + select current_user as who_am_i from rdb$database; + commit; + + connect '$(DSN)' user tmp$c5770_foo password '123'; + + -- check that sub-admin user 'foo' can make common user 'bar' INACTIVE: + alter user tmp$c5770_bar inactive using plugin Srp; + commit; + select * from v_sec; + commit; + + -- this should raise SQLSTATE = 28000: user 'tmp$c5770_bar' again become inactive: + connect '$(DSN)' user tmp$c5770_bar password '456'; + select current_user as who_am_i from rdb$database; + commit; + + -- cleanup: drop foo and bar. + connect '$(DSN)' user sysdba password 'masterkey'; + drop user tmp$c5770_foo using plugin Srp; + drop user tmp$c5770_bar using plugin Srp; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHO_AM_I TMP$C5770_FOO + SEC$USER_NAME TMP$C5770_BAR + SEC$ACTIVE + SEC$ADMIN + SEC$PLUGIN Srp + + WHO_AM_I TMP$C5770_BAR + + WHO_AM_I TMP$C5770_FOO + SEC$USER_NAME TMP$C5770_BAR + SEC$ACTIVE + SEC$ADMIN + SEC$PLUGIN Srp + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 28000 + Your user name and password are not defined. Ask your database administrator to set up a Firebird login. + """ + +@pytest.mark.version('>=4.0') +def test_core_5770_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5771.py b/tests/bugs/test_core_5771.py new file mode 100644 index 00000000..5e2908c0 --- /dev/null +++ b/tests/bugs/test_core_5771.py @@ -0,0 +1,167 @@ +#coding:utf-8 +# +# id: bugs.core_5771 +# title: Restore (without replace) when database already exists crashes gbak or Firebird (when run through service manager) +# decription: +# Confirmed bug on 4.0.0.918 (as described in the ticket; 3.x is not affected). +# +# tracker_id: CORE-5771 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import time +# import difflib +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# def svc_get_fb_log( f_fb_log ): +# +# global subprocess +# +# subprocess.call( [ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# "action_get_fb_log" +# ], +# stdout=f_fb_log, stderr=subprocess.STDOUT +# ) +# return +# +# +# tmpfbk = 'tmp_core_5771.fbk' +# tmpfbk='$(DATABASE_LOCATION)'+tmpfbk +# tmpfdb='$(DATABASE_LOCATION)'+'tmp_5771_restored.fdb' +# +# runProgram('gbak',['-b', dsn, tmpfbk]) +# runProgram('gbak',['-rep', tmpfbk, 'localhost:'+tmpfdb]) +# +# f_fblog_before=open( os.path.join(context['temp_directory'],'tmp_5771_fblog_before.txt'), 'w') +# svc_get_fb_log( f_fblog_before ) +# flush_and_close( f_fblog_before ) +# +# f_restore_log=open( os.path.join(context['temp_directory'],'tmp_5771_check_restored.log'), 'w') +# f_restore_err=open( os.path.join(context['temp_directory'],'tmp_5771_check_restored.err'), 'w') +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_restore", +# "bkp_file", tmpfbk, +# "dbname", tmpfdb, +# "verbose" +# ], +# stdout=f_restore_log, +# stderr=f_restore_err) +# flush_and_close( f_restore_log ) +# flush_and_close( f_restore_err ) +# +# f_fblog_after=open( os.path.join(context['temp_directory'],'tmp_5771_fblog_after.txt'), 'w') +# svc_get_fb_log( f_fblog_after ) +# flush_and_close( f_fblog_after ) +# +# +# # Compare firebird.log versions BEFORE and AFTER this test: +# ###################### +# +# oldfb=open(f_fblog_before.name, 'r') +# newfb=open(f_fblog_after.name, 'r') +# +# difftext = ''.join(difflib.unified_diff( +# oldfb.readlines(), +# newfb.readlines() +# )) +# oldfb.close() +# newfb.close() +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_5771_diff.txt'), 'w') +# f_diff_txt.write(difftext) +# flush_and_close( f_diff_txt ) +# +# # Check logs: +# ############# +# with open( f_restore_log.name,'r') as f: +# for line in f: +# line=line.replace('$(DATABASE_LOCATION)','') +# print( 'RESTORE STDOUT:' + ' '.join( line.split() ).upper() ) +# +# with open( f_restore_err.name,'r') as f: +# for line in f: +# line=line.replace('$(DATABASE_LOCATION)','') +# print( 'RESTORE STDERR: ' + ' '.join( line.split() ).upper() ) +# +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# if line.startswith('+'): +# print( 'UNEXPECTED DIFF IN FIREBIRD.LOG: ' + (' '.join(line.split()).upper()) ) +# +# +# # Cleanup: +# ########## +# time.sleep(1) +# cleanup( (f_restore_log,f_restore_err,f_fblog_before,f_fblog_after,f_diff_txt,tmpfbk,tmpfdb) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESTORE STDOUT:GBAK:OPENED FILE TMP_CORE_5771.FBK + RESTORE STDERR: DATABASE TMP_5771_RESTORED.FDB ALREADY EXISTS. TO REPLACE IT, USE THE -REP SWITCH + RESTORE STDERR: -EXITING BEFORE COMPLETION DUE TO ERRORS + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_5771_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5773.py b/tests/bugs/test_core_5773.py new file mode 100644 index 00000000..e036ae43 --- /dev/null +++ b/tests/bugs/test_core_5773.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: bugs.core_5773 +# title: PSQL cursor doesn't see inserted record +# decription: +# Confirmed wrong result on 3.0.4.32924 +# Works fine on 3.0.4.32939: OK, 1.453s. +# +# tracker_id: CORE-5773 +# min_versions: ['3.0.4'] +# versions: 3.0.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + create or alter procedure sp_test as begin end; + recreate table test (id bigint); + commit; + + set term ^; + create or alter procedure sp_test returns ( + rowcount integer + ) as + declare id bigint; + declare c_ins cursor for ( + select id from test + ); + begin + insert into test(id) values(1); + open c_ins; + fetch c_ins into :id; + rowcount = row_count; + suspend; + close c_ins; + end^ + set term ;^ + select * from sp_test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ROWCOUNT 1 + Records affected: 1 + """ + +@pytest.mark.version('>=3.0.4') +def test_core_5773_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5776.py b/tests/bugs/test_core_5776.py new file mode 100644 index 00000000..98aca067 --- /dev/null +++ b/tests/bugs/test_core_5776.py @@ -0,0 +1,190 @@ +#coding:utf-8 +# +# id: bugs.core_5776 +# title: "Input parameter mismatch" error after altering external function into PSQL function +# decription: +# ::::: NB :::: +# Could not check actual result of fbtest execution, done only using ISQL and copy its result here. +# Checked on WI-T4.0.0.927, Win 64x. +# +# *** FOR FB 3.X ONLY *** +# Test uses UDF 'sright' declared in ib_udf.sql script which for sure present in every FB snapshot. +# After this, we try to create PSQL function with the same signature. +# +# *** FOR FB 4.X AND ABOVE *** +# Added separate code for running on FB 4.0.x: use udf_compat!UC_frac from UDR engine, and then alter it +# by changing to PSQL with the same signature. +# +# 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/ +# +# 3.0.5.33086: OK, 1.406s. +# 4.0.0.1172: OK, 6.047s. +# 4.0.0.1340: OK, 21.078s. +# 4.0.0.1378: OK, 10.391s. +# +# tracker_id: CORE-5776 +# min_versions: ['3.0.4'] +# versions: 3.0.4, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set term ^; + execute block as + begin + execute statement 'drop function sright'; + when any do begin end + end + ^ + set term ;^ + commit; + + declare external function sright + varchar(100) by descriptor, + smallint, + varchar(100) by descriptor returns parameter 3 + entry_point 'right' module_name 'fbudf'; + commit; + + + select rdb$return_argument from rdb$functions + where rdb$function_name = 'SRIGHT'; + + select rdb$argument_position, rdb$argument_name from rdb$function_arguments + where rdb$function_name = 'SRIGHT'; + + ------------------------------------------------ + + commit; + + set term ^; + alter function sright (str varchar(100), len int) returns varchar(100) + as + begin + return right(str, len); + end^ + set term ;^ + commit; + + select sright('function', 2) from rdb$database; + + + select rdb$return_argument from rdb$functions + where rdb$function_name = 'SRIGHT'; + + select rdb$argument_position, rdb$argument_name from rdb$function_arguments + where rdb$function_name = 'SRIGHT'; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$RETURN_ARGUMENT 3 + + RDB$ARGUMENT_POSITION 1 + RDB$ARGUMENT_NAME + + RDB$ARGUMENT_POSITION 2 + RDB$ARGUMENT_NAME + + RDB$ARGUMENT_POSITION 3 + RDB$ARGUMENT_NAME + + SRIGHT on + + RDB$RETURN_ARGUMENT 0 + + RDB$ARGUMENT_POSITION 0 + RDB$ARGUMENT_NAME + + RDB$ARGUMENT_POSITION 1 + RDB$ARGUMENT_NAME STR + + RDB$ARGUMENT_POSITION 2 + RDB$ARGUMENT_NAME LEN + """ + +@pytest.mark.version('>=3.0.4,<4.0') +def test_core_5776_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set list on; + + set term ^; + create or alter function the_frac( val double precision ) returns double precision as + begin + return 1. / log10( val - cast(val as int) ) ; + end + ^ + set term ;^ + commit; + + select the_frac( pi() ) as the_frac_0 from rdb$database; + commit; + + alter function the_frac( + val double precision + ) returns double precision + external name 'udf_compat!UC_frac' + engine udr; + commit; + + select the_frac( -pi() ) as the_frac_1 from rdb$database; + commit; + + ----------------------------- + + set term ^; + alter function the_frac( val double precision ) returns double precision as + begin + return 1. / exp( -(val - cast(val as int)) ) ; + end + ^ + set term ;^ + commit; + + select the_frac( -pi() ) as the_frac_2 from rdb$database; + commit; + + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + THE_FRAC_0 -1.177912798268244 + THE_FRAC_1 -0.1415926535897931 + THE_FRAC_2 0.8679747508826116 + """ + +@pytest.mark.version('>=4.0') +def test_core_5776_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/bugs/test_core_5783.py b/tests/bugs/test_core_5783.py new file mode 100644 index 00000000..fbfc9f06 --- /dev/null +++ b/tests/bugs/test_core_5783.py @@ -0,0 +1,95 @@ +#coding:utf-8 +# +# id: bugs.core_5783 +# title: execute statement ignores the text of the SQL-query after a comment of the form "-" +# decription: +# We concatenate query from several elements and use ' +# ' delimiter only to split this query into lines. +# Also, we put single-line comment in SEPARATE line between 'select' and column/value that is obtained from DB. +# Final query will lokk like this (lines are separated only by SINGLE delimiter, ascii_char(13), NO ' +# ' here!): +# === +# select +# -- comment N1 +# 'foo' as msg' +# from +# -- comment N2 +# rdb$database +# === +# This query should NOT raise any exception and must produce normal output (string 'foo'). +# Thanks to hvlad for suggestions. +# +# Confirmed bug on: +# 3.0.4.32924 +# 4.0.0.918 +# -- got: +# Error while preparing SQL statement: +# - SQLCODE: -104 +# - Dynamic SQL Error +# - SQL error code = -104 +# - Unexpected end of command - line 1, column 1 +# -104 +# 335544569 +# Checked on: +# 3.0.4.32941: OK, 1.187s. +# 4.0.0.947: OK, 1.328s. +# +# tracker_id: CORE-5783 +# min_versions: ['3.0.4'] +# versions: 3.0.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import sys +# import os +# +# cur = db_conn.cursor() +# +# # NB: one need to use TWO backslash characters ('\\r') as escape for CR only within fbtest. +# # Single '' should be used when running under "pure" Python control: +# +# sql_expr = ' '.join( ('select', '\\r', '-- comment N1', '\\r', "'foo' as msg", '\\r', 'from', '\\r', '-- comment N2', '\\r', 'rdb$database') ) +# +# for i in sql_expr.split('\\r'): +# print('Query line: ' + i) +# +# #sql_expr = 'select 1 FROM test' +# cur.execute( sql_expr ) +# for r in cur: +# print( 'Query result: ' + r[0] ) +# +# cur.close() +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Query line: select + Query line: -- comment N1 + Query line: 'foo' as msg + Query line: from + Query line: -- comment N2 + Query line: rdb$database + Query result: foo + """ + +@pytest.mark.version('>=3.0.4') +@pytest.mark.xfail +def test_core_5783_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5790.py b/tests/bugs/test_core_5790.py new file mode 100644 index 00000000..2851e0ee --- /dev/null +++ b/tests/bugs/test_core_5790.py @@ -0,0 +1,176 @@ +#coding:utf-8 +# +# id: bugs.core_5790 +# title: User with DROP DATABASE privilege can't drop database +# decription: +# Confirmed bug on 3.0.4.32924 +# Works fine on: +# 3.0.4.32947: OK, 2.906s. +# 4.0.0.955: OK, 3.453s. +# 07.02.2019: fixed wrong connection string which did use local protocol instead of required remote. +# Checked on: +# 4.0.0.1421 CS, SC, SS +# 3.0.5.33097 CS, SS +# +# tracker_id: CORE-5790 +# min_versions: ['3.0.4'] +# versions: 3.0.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# thisdb=db_conn.database_name +# tmpfdb='$(DATABASE_LOCATION)'+'tmp_5790.tmp' +# tmpusr='tmp$c5790' +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# cleanup( (tmpfdb,) ) +# +# sql_txt=''' +# create database 'localhost:%(tmpfdb)s'; +# alter database set linger to 0; +# commit; +# create or alter user %(tmpusr)s password '123'; +# commit; +# grant drop database to tmp$c5790; +# commit; +# connect 'localhost:%(tmpfdb)s' user %(tmpusr)s password '123'; +# set list on; +# set count on; +# select +# r.rdb$user -- tmp$c5790 +# ,r.rdb$grantor -- sysdba +# ,r.rdb$privilege -- o +# ,r.rdb$grant_option -- 0 +# ,r.rdb$relation_name -- sql$database +# ,r.rdb$field_name -- +# ,r.rdb$user_type -- 8 +# ,iif( r.rdb$object_type = decode( left(rdb$get_context('SYSTEM', 'ENGINE_VERSION'),1), '3',20, '4',21), 1, 0) "rdb_object_type_is_expected ?" +# from rdb$user_privileges r +# where r.rdb$user=upper('%(tmpusr)s'); +# +# -- this should NOT show any attachments: "Records affected: 0" must be shown here. +# select * from mon$attachments where mon$attachment_id != current_connection; +# commit; +# +# drop database; +# rollback; +# +# -- !!! 07.02.2019 only remote protocol must be used here !! +# -- Otherwise we will attempt to make local attach to security4.fdb +# -- 335544344 : I/O error during "CreateFile (open)" operation for file "C:\\FB SS\\SECURITY4.FDB" +# -- 335544734 : Error while trying to open file +# -- This is because securityN.fdb has by default linger = 60 seconds when we use SS, thus it is +# -- stiil kept opened by FB server process. +# +# connect 'localhost:%(thisdb)s'; -- OLD VERSION OF THIS TEST HAD ERROR HERE: connect '%(thisdb)s' +# drop user %(tmpusr)s; +# commit; +# --set list on; +# --set count on; +# --set echo on; +# --select current_user, s.* from rdb$database left join sec$users s on s.sec$user_name not containing 'SYSDBA'; +# ''' % locals() +# +# f_isql_cmd=open( os.path.join(context['temp_directory'],'tmp_5790.sql'), 'w') +# f_isql_cmd.write(sql_txt) +# flush_and_close( f_isql_cmd ) +# +# f_isql_log=open( os.path.join(context['temp_directory'],'tmp_5790.log'), 'w') +# f_isql_err=open( os.path.join(context['temp_directory'],'tmp_5790.err'), 'w') +# subprocess.call( [ context['isql_path'], '-q', '-i', f_isql_cmd.name], stdout=f_isql_log, stderr=f_isql_err ) +# flush_and_close( f_isql_log ) +# flush_and_close( f_isql_err ) +# +# if os.path.isfile(tmpfdb): +# print('### ERROR ### Database file was NOT deleted!') +# cleanup( tmpfdb, ) +# +# with open(f_isql_log.name,'r') as f: +# for line in f: +# print(line) +# +# with open(f_isql_err.name,'r') as f: +# for line in f: +# print('UNEXPECTED STDERR: ' + line) +# +# # cleanup +# ######### +# time.sleep(1) +# f_list = (f_isql_log,f_isql_err,f_isql_cmd) +# cleanup( f_list ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$USER TMP$C5790 + RDB$GRANTOR SYSDBA + RDB$PRIVILEGE O + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME SQL$DATABASE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + rdb_object_type_is_expected ? 1 + Records affected: 1 + Records affected: 0 + """ + +@pytest.mark.version('>=3.0.4') +@pytest.mark.xfail +def test_core_5790_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5793.py b/tests/bugs/test_core_5793.py new file mode 100644 index 00000000..32b1c2d6 --- /dev/null +++ b/tests/bugs/test_core_5793.py @@ -0,0 +1,180 @@ +#coding:utf-8 +# +# id: bugs.core_5793 +# title: Error returned from DbCryptPlugin::setKey() is not shown +# decription: +# +# Test database that is created by fbtest framework will be encrypted here using IBSurgeon Demo Encryption package +# ( https://ib-aid.com/download-demo-firebird-encryption-plugin/ ; https://ib-aid.com/download/crypt/CryptTest.zip ) +# License file plugins\\dbcrypt.conf with unlimited expiration was provided by IBSurgeon to Firebird Foundation (FF). +# This file was preliminary stored in FF Test machine. +# Test assumes that this file and all neccessary libraries already were stored into FB_HOME and %FB_HOME%\\plugins. +# +# Anyone who wants to run this test on his own machine must +# 1) download https://ib-aid.com/download/crypt/CryptTest.zip AND +# 2) PURCHASE LICENSE and get from IBSurgeon file plugins\\dbcrypt.conf with apropriate expiration date and other info. +# +# ################################################ ! ! ! N O T E ! ! ! ############################################## +# FF tests storage (aka "fbt-repo") does not (and will not) contain any license file for IBSurgeon Demo Encryption package! +# ######################################################################################################################### +# +# Firstly we try to encrypt DB with existing key and decrypt it aftee this - just to ensure that this mechanism works fine. +# Then we use statement 'alter database encrypt ...' with NON existing key and check parts of exception that will raise. +# From these three parts (multi-string, int and bigint numbers) we check that 1st contains phrase about missed crypt key. +# ::: NOTE :::: +# Text of messages differ in 3.0.5 vs 4.0.0: +# 3.0.5: - Missing correct crypt key +# 4.0.0: - Missing database encryption key for your attachment +# - so we use regexp tool for check pattern matching. +# Because of different text related to missing plugin, this part is replaced with phrase: +# -- both for 3.0.x and 4.0.x. +# +# Confirmed difference in error message (text decription, w/o sqlcode and gdscode): +# 1) 3.0.3.32900 +# ===== +# Error while executing SQL statement: +# - SQLCODE: -607 +# - unsuccessful metadata update +# - ALTER DATABASE failed +# - Missing correct crypt key +# ===== +# +# 2) 3.0.5.33139 - two lines were added: +# ==== +# - Plugin KeyHolder: +# - Unknown key name FOO - key can't be found in KeyHolder.conf +# ==== +# +# Checked on: +# 4.0.0.1524: OK, 4.674s. +# 3.0.5.33139: OK, 3.666s. +# +# === NOTE-1 === +# In case of "Crypt plugin DBCRYPT failed to load/607/335544351" check that all +# needed files from IBSurgeon Demo Encryption package exist in %FB_HOME% and %FB_HOME%\\plugins +# %FB_HOME%: +# 283136 fbcrypt.dll +# 2905600 libcrypto-1_1-x64.dll +# 481792 libssl-1_1-x64.dll +# +# %FB_HOME%\\plugins: +# 297984 dbcrypt.dll +# 306176 keyholder.dll +# 108 DbCrypt.conf +# 856 keyholder.conf +# +# === NOTE-2 === +# Version of DbCrypt.dll of october-2018 must be replaced because it has hard-coded +# date of expiration rather than reading it from DbCrypt.conf !! +# +# === NOTE-3 === +# firebird.conf must contain following line: +# KeyHolderPlugin = KeyHolder +# +# +# tracker_id: CORE-5793 +# min_versions: ['3.0.4'] +# versions: 3.0.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import re +# import time +# +# # Messages differ: +# # 3.0.5: - Missing correct crypt key +# # 4.0.0: - Missing database encryption key for your attachment +# # --> we can use regexp to parse exception text and try to find some common words for these messages: +# missed_key_ptn=re.compile('.*missing\\s+.*(crypt key|encryption key).*', re.IGNORECASE) +# +# print('1.1. Trying to encrypt with existing key.') +# db_conn.execute_immediate('alter database encrypt with dbcrypt key red') +# db_conn.commit() +# time.sleep(1) +# print('1.2. Delay completed, DB now must be encrypted.') +# +# print('2.1. Trying to decrypt.') +# db_conn.execute_immediate('alter database decrypt') +# db_conn.commit() +# time.sleep(2) +# print('2.2. Delay completed, DB now must be decrypted.') +# +# print('3.1. Trying to encrypt with non-existing key') +# try: +# db_conn.execute_immediate('alter database encrypt with dbcrypt key foo') +# db_conn.commit() +# time.sleep(1) +# print('3.2 ??? ERROR ??? Encrypted with key "foo" ?!') +# except Exception as e: +# for x in e.args: +# if isinstance( x, str): +# for r in x.split('\\n'): +# if missed_key_ptn.search( r ): +# print('') +# else: +# print( r ) +# else: +# print(x) +# +# finally: +# db_conn.close() +# ''' +# 1.1. Trying to encrypt with existing key. +# 1.2. Delay completed, DB now must be encrypted. +# 2.1. Trying to decrypt. +# 2.2. Delay completed, DB now must be decrypted. +# 3.1. Trying to encrypt with non-existing key +# Error while executing SQL statement: +# - SQLCODE: -607 +# - unsuccessful metadata update +# - ALTER DATABASE failed +# - Missing correct crypt key +# - Plugin KeyHolder: +# - Unknown key name FOO - key can't be found in KeyHolder.conf +# -607 +# 335544351 +# +# ''' +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 1.1. Trying to encrypt with existing key. + 1.2. Delay completed, DB now must be encrypted. + 2.1. Trying to decrypt. + 2.2. Delay completed, DB now must be decrypted. + 3.1. Trying to encrypt with non-existing key + Error while executing SQL statement: + - SQLCODE: -607 + - unsuccessful metadata update + - ALTER DATABASE failed + + - Plugin KeyHolder: + - Unknown key name FOO - key can't be found in KeyHolder.conf + -607 + 335544351 + """ + +@pytest.mark.version('>=3.0.4') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_5793_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5794.py b/tests/bugs/test_core_5794.py new file mode 100644 index 00000000..b673142f --- /dev/null +++ b/tests/bugs/test_core_5794.py @@ -0,0 +1,102 @@ +#coding:utf-8 +# +# id: bugs.core_5794 +# title: Wrong behavour FOR [AS CURSOR cursorname] with next update and delete +# decription: +# Despite that this ticket was closed with solution "Won't fix" i see that it is useful for additional +# checking of cursor stability feature (new in 3.0). +# See also: +# 1) test for CORE-3362; +# 2) comment in this ticket (CORE-5794) by hvlad: +# "Since Firebird3 <..> cursor doesn't see the changes made by "inner" statements." +# +# tracker_id: CORE-5794 +# min_versions: ['3.0.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('line:\\s[0-9]+,', 'line: x'), ('col:\\s[0-9]+', 'col: y')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test_table ( + id integer, + val integer + ); + commit; + insert into test_table (id, val) values (1, 10); + commit; + + recreate exception test_exception 'test'; + + set term ^ ; + create or alter trigger test_table_bd for test_table active before delete position 0 as + begin + rdb$set_context('USER_SESSION','TRIGGER_OLD_ID', coalesce(old.id,'null') ); + rdb$set_context('USER_SESSION','TRIGGER_OLD_VAL', coalesce(old.val,'null') ); + if (old.val >0 ) then + exception test_exception 'it is forbidden to delete row with val>0 (id = '||coalesce(old.id, 'null')||', val='||coalesce(old.val,'null')||')'; + end + ^ + + execute block as + declare curVal integer; + declare curID integer; + begin + for select id, val + from test_table + where val>0 + into curid, curval + as cursor tmpcursor + do begin + update test_table + set val=0 + where current of tmpcursor; + + -- NO error in 2.5: + delete from test_table + where current of tmpcursor; + end + end + ^ + set term ;^ + + set list on; + select mon$variable_name as ctx_var, mon$variable_value as ctx_value from mon$context_variables; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CTX_VAR TRIGGER_OLD_ID + CTX_VALUE 1 + + CTX_VAR TRIGGER_OLD_VAL + CTX_VALUE 10 + """ +expected_stderr_1 = """ + 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' line: 6, col: 9 + At block line: 16, col: 9 + """ + +@pytest.mark.version('>=3.0') +def test_core_5794_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5796.py b/tests/bugs/test_core_5796.py new file mode 100644 index 00000000..c7271a4b --- /dev/null +++ b/tests/bugs/test_core_5796.py @@ -0,0 +1,171 @@ +#coding:utf-8 +# +# id: bugs.core_5796 +# title: gstat may produce faulty report about presence of some none-encrypted pages in database +# decription: +# We create new database ('tmp_core_5796.fdb') and try to encrypt it usng IBSurgeon Demo Encryption package +# ( https://ib-aid.com/download-demo-firebird-encryption-plugin/ ; https://ib-aid.com/download/crypt/CryptTest.zip ) +# License file plugins\\dbcrypt.conf with unlimited expiration was provided by IBSurgeon to Firebird Foundation (FF). +# This file was preliminary stored in FF Test machine. +# Test assumes that this file and all neccessary libraries already were stored into FB_HOME and %FB_HOME%\\plugins. +# +# Anyone who wants to run this test on his own machine must +# 1) download https://ib-aid.com/download/crypt/CryptTest.zip AND +# 2) PURCHASE LICENSE and get from IBSurgeon file plugins\\dbcrypt.conf with apropriate expiration date and other info. +# +# ################################################ ! ! ! N O T E ! ! ! ############################################## +# FF tests storage (aka "fbt-repo") does not (and will not) contain any license file for IBSurgeon Demo Encryption package! +# ######################################################################################################################### +# +# After test database will be created, we try to encrypt it using 'alter database encrypt with ...' command +# (where = dbcrypt - name of .dll in FB_HOME\\plugins\\ folder that implements encryption). +# Then we allow engine to complete this job - take delay about 1..2 seconds BEFORE detach from database. +# +# After this we detach from DB, run 'gstat -h' and filter its attributes and messages from 'Variable header' section. +# In the output of gstat we check that its 'tail' will look like this: +# === +# Attributes force write, encrypted, plugin DBCRYPT +# Crypt checksum: MUB2NTJqchh9RshmP6xFAiIc2iI= +# Key hash: ask88tfWbinvC6b1JvS9Mfuh47c= +# Encryption key name: RED +# === +# (concrete values for checksum and hash will be ignored - see 'substitutions' section). +# +# Finally, we change this temp DB statee to full shutdown in order to have 100% ability to drop this file. +# +# === NOTE-1 === +# In case of "Crypt plugin DBCRYPT failed to load/607/335544351" check that all +# needed files from IBSurgeon Demo Encryption package exist in %FB_HOME% and %FB_HOME%\\plugins +# %FB_HOME%: +# 283136 fbcrypt.dll +# 2905600 libcrypto-1_1-x64.dll +# 481792 libssl-1_1-x64.dll +# +# %FB_HOME%\\plugins: +# 297984 dbcrypt.dll +# 306176 keyholder.dll +# 108 DbCrypt.conf +# 856 keyholder.conf +# +# === NOTE-2 === +# Version of DbCrypt.dll of october-2018 must be replaced because it has hard-coded +# date of expiration rather than reading it from DbCrypt.conf !! +# +# === NOTE-3 === +# firebird.conf must contain following line: +# KeyHolderPlugin = KeyHolder +# +# +# tracker_id: CORE-5796 +# min_versions: ['3.0.4'] +# versions: 3.0.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [('ATTRIBUTES .* ENCRYPTED, PLUGIN .*', 'ATTRIBUTES ENCRYPTED'), ('CRYPT CHECKSUM.*', 'CRYPT CHECKSUM'), ('KEY HASH.*', 'KEY HASH'), ('ENCRYPTION KEY NAME.*', 'ENCRYPTION KEY')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import time +# import subprocess +# import re +# import fdb +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.close() +# +# tmpfdb='$(DATABASE_LOCATION)'+'tmp_core_5796.fdb' +# +# if os.path.isfile( tmpfdb ): +# os.remove( tmpfdb ) +# +# con = fdb.create_database( dsn = 'localhost:'+tmpfdb ) +# con.close() +# con=fdb.connect( dsn = 'localhost:'+tmpfdb ) +# cur = con.cursor() +# cur.execute('alter database encrypt with dbcrypt key Red') +# con.commit() +# time.sleep(2) +# # ^ +# # +-------- !! ALLOW BACKGROUND ENCRYPTION PROCESS TO COMPLETE ITS JOB !! +# +# con.close() +# +# #--------------------------------- get DB header info -------------------- +# +# f_gstat_log = open( os.path.join(context['temp_directory'],'tmp_dbstat_5796.log'), 'w') +# f_gstat_err = open( os.path.join(context['temp_directory'],'tmp_dbstat_5796.err'), 'w') +# +# subprocess.call( [ "gstat", "-e", "localhost:"+tmpfdb], +# stdout = f_gstat_log, +# stderr = f_gstat_err +# ) +# +# +# f_gstat_log.close() +# f_gstat_err.close() +# +# #--------------------------------- shutdown temp DB -------------------- +# +# f_dbshut_log = open( os.path.join(context['temp_directory'],'tmp_dbshut_5796.log'), 'w') +# subprocess.call( [ "gfix", 'localhost:'+tmpfdb, "-shut", "full", "-force", "0" ], +# stdout = f_dbshut_log, +# stderr = subprocess.STDOUT +# ) +# f_dbshut_log.close() +# +# allowed_patterns = ( +# re.compile( '\\s*Attributes\\.*', re.IGNORECASE) +# ,re.compile('crypt\\s+checksum:\\s+\\S+', re.IGNORECASE) +# ,re.compile('key\\s+hash:\\s+\\S+', re.IGNORECASE) +# ,re.compile('encryption\\s+key\\s+name:\\s+\\S+', re.IGNORECASE) +# ) +# +# with open( f_gstat_log.name,'r') as f: +# for line in f: +# match2some = filter( None, [ p.search(line) for p in allowed_patterns ] ) +# if match2some: +# print( (' '.join( line.split()).upper() ) ) +# +# with open( f_gstat_err.name,'r') as f: +# for line in f: +# print("Unexpected STDERR: "+line) +# +# f_list=(f_gstat_log, f_gstat_err, f_dbshut_log) +# for i in range(len(f_list)): +# if os.path.isfile(f_list[i].name): +# os.remove(f_list[i].name) +# +# if os.path.isfile( tmpfdb ): +# os.remove( tmpfdb ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ATTRIBUTES FORCE WRITE, ENCRYPTED, PLUGIN DBCRYPT + CRYPT CHECKSUM: MUB2NTJQCHH9RSHMP6XFAIIC2II= + KEY HASH: ASK88TFWBINVC6B1JVS9MFUH47C= + ENCRYPTION KEY NAME: RED + """ + +@pytest.mark.version('>=3.0.4') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_5796_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5802.py b/tests/bugs/test_core_5802.py new file mode 100644 index 00000000..97393675 --- /dev/null +++ b/tests/bugs/test_core_5802.py @@ -0,0 +1,158 @@ +#coding:utf-8 +# +# id: bugs.core_5802 +# title: Field name max length check wrongly if national characters specified +# decription: +# Confirmed bug on 3.0.4.32972, got error: +# Statement failed, SQLSTATE = 22001 +# arithmetic exception, numeric overflow, or string truncation +# -string right truncation +# -expected length 31, actual 31 +# +# Though this ticket was fixed only for FB 4.x, Adriano notes that error message +# was corrected in FB 3.0.6. Thus we check both major versions but use different +# length of columns: 32 and 64. +# Checked on: +# 4.0.0.1753 SS: 1.630s. +# 3.0.6.33237 SS: 0.562s. +# +# 03-mar-2021. Re-implemented in order to have ability to run this test on Linux. +# Test encodes to UTF8 all needed statements (SET NAMES; CONNECT; DDL and DML) and stores this text in .sql file. +# NOTE: 'SET NAMES' contain character set that must be used for reproducing problem (WIN1251 in this test). +# Then ISQL is launched in separate (child) process which performs all necessary actions (using required charset). +# Result will be redirected to log(s) which will be opened further via codecs.open(...encoding='cp1251'). +# Finally, its content will be converted to UTF8 for showing in expected_stdout. +# +# Checked on: +# * Windows: 4.0.0.2377, 3.0.8.33420 +# * Linux: 4.0.0.2377, 3.0.8.33415 +# +# +# tracker_id: CORE-5802 +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [('[-]?At line \\d+.*', ''), ('After line \\d+.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(charset='WIN1251', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import codecs +# import subprocess +# import time +# engine = db_conn.engine_version +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# if engine < 4: +# # Maximal number of characters in the column for FB 3.x is 31. +# # Here we use name of 32 characters and this must raise error +# # with text "Name longer than database column size": +# # +# column_title = 'СъешьЖеЕщёЭтихМягкихФранкоБулок' +# else: +# # Maximal number of characters in the column for FB 4.x is 63. +# # Here we use name of 64 characters and this must raise error +# # with text "Name longer than database column size": +# # +# column_title = 'СъешьЖеЕщёЭтихПрекрасныхФранкоБулокВместоДурацкихМорковныхКотлет' +# +# # Code to be executed further in separate ISQL process: +# ############################# +# sql_txt=''' +# set bail on; +# set names win1251; +# connect '%(dsn)s' user '%(user_name)s' password '%(user_password)s'; +# +# set list on; +# set sqlda_display on; +# -- Maximal number of characters in the column for FB 3.x is 31. +# -- Here we use name of 32 characters and this must raise error +# -- with text "Name longer than database column size": +# select 1 as "%(column_title)s" from rdb$database; +# ''' % dict(globals(), **locals()) +# +# f_run_sql = open( os.path.join(context['temp_directory'], 'tmp_5802_win1251.sql'), 'w' ) +# f_run_sql.write( sql_txt.decode('utf8').encode('cp1251') ) +# flush_and_close( f_run_sql ) +# +# # result: file tmp_5802_win1251.sql is encoded in win1251 +# +# f_run_log = open( os.path.splitext(f_run_sql.name)[0]+'.log', 'w') +# subprocess.call( [ context['isql_path'], '-q', '-i', f_run_sql.name ], +# stdout = f_run_log, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_run_log ) # result: output will be encoded in win1251 +# +# with codecs.open(f_run_log.name, 'r', encoding='cp1251' ) as f: +# result_in_win1251 = f.readlines() +# +# for i in result_in_win1251: +# print( i.encode('utf8') ) +# +# # cleanup: +# ########### +# cleanup( (f_run_sql, f_run_log) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + """ + +@pytest.mark.version('>=3.0.6') +@pytest.mark.xfail +def test_core_5802_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5804.py b/tests/bugs/test_core_5804.py new file mode 100644 index 00000000..e927aacc --- /dev/null +++ b/tests/bugs/test_core_5804.py @@ -0,0 +1,1752 @@ +#coding:utf-8 +# +# id: bugs.core_5804 +# title: Multiple error in REVOKE operator +# decription: +# WARNING-1: test contains two separate sections for executing in 3.0.4+ and 4.0: +# one can NOT use 'DEFAULT' keyword in GRANT/REVOKE role statements. +# Such blocks are commented in 3.0 section. +# +# WARNING-2: 'SHOW GRANTS' command was replaced with appropriate select from in order to provide stable output. +# +# Checked on: +# WI-V3.0.4.32963, +# WI-T4.0.0.967. +# +# NB. +# Firebird never does any kind of implicit revoke if we use GRANT statement that contains "less" options that previously issued one. +# See additional explanations in the ticket 24/Apr/18 05:06 PM +# +# tracker_id: CORE-5804 +# min_versions: ['3.0.4'] +# versions: 3.0.4, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set wng off; + set list on; + set count on; + create or alter user tmp$c5804_john password '123'; + commit; + + set term ^; + create or alter procedure sp_msg (a_msg varchar(100)) returns(msg varchar(100)) as begin + msg=a_msg; + suspend; + end^ + set term ;^ + commit; + + recreate view v_roles as + select r.* + from rdb$roles r + where r.rdb$system_flag is distinct from 1 + ; + + recreate view v_grants as + select + p.rdb$user_type as usr_type + ,p.rdb$user as usr_name + ,p.rdb$grantor as who_gave + ,p.rdb$privilege as what_can + ,p.rdb$grant_option as has_grant + ,p.rdb$object_type as obj_type + ,p.rdb$relation_name as rel_name + ,p.rdb$field_name as fld_name + from rdb$database r left join rdb$user_privileges p on 1=1 + where p.rdb$user in( upper('tmp$c5804_john'), upper('tmp$r5804_boss'), upper('tmp$r5804_acnt') ) + order by 1,2,3,4,5,6,7,8 + ; + + recreate table t(f1 int, f2 int); + create role tmp$r5804_boss; + create role tmp$r5804_acnt; + commit; + revoke all on all from tmp$c5804_john; + commit; + + + --################################################################## + -- G R A N T O P T I O N + --################################################################## + + -- check revoke grant option for all table -- + --------------------------------------------- + + grant update(f1, f2) on table t to tmp$c5804_john with grant option; + commit; + + revoke grant option for update on table t from tmp$c5804_john; + commit; + + execute procedure sp_msg('revoked grant option for update of the whole table'); + select v.* from v_grants v; + commit; + + revoke all on all from tmp$c5804_john; + commit; + + -- check revoke grant option for the first field -- + --------------------------------------------------- + grant update(f1, f2) on table t to tmp$c5804_john with grant option; + commit; + + revoke grant option for update(f1) on table t from tmp$c5804_john; + commit; + + execute procedure sp_msg('revoked grant option for update only field F1'); + select v.* from v_grants v; + + commit; + revoke all on all from tmp$c5804_john; + commit; + + -- check revoke grant option for the second field -- + ---------------------------------------------------- + grant update(f1, f2) on table t to tmp$c5804_john with grant option; + commit; + + revoke grant option for update(f2) on table t from tmp$c5804_john; + commit; + + execute procedure sp_msg('revoked grant option for update only field F2'); + select v.* from v_grants v; + + revoke all on all from tmp$c5804_john; + commit; + + + -- check revoke grant option for every field -- + ----------------------------------------------- + grant update(f1, f2) on table t to tmp$c5804_john with grant option; + commit; + + revoke grant option for update(f2, f1) on table t from tmp$c5804_john; + commit; + + execute procedure sp_msg('revoked grant option for update of both fields F1 and F2 enumerated as list'); + select v.* from v_grants v; + + revoke all on all from tmp$c5804_john; + commit; + + --################################################################## + -- U P D A T E + --################################################################## + + -- check revoke update for all table -- + --------------------------------------- + grant update(f1, f2) on table t to tmp$c5804_john with grant option; + commit; + + revoke update on table t from tmp$c5804_john; + commit; + + execute procedure sp_msg('revoked privilege update for the whole table'); + select v.* from v_grants v; -- no rows should be displayed now! + + revoke all on all from tmp$c5804_john; + commit; + + -- check revoke update for the first field -- + --------------------------------------------- + grant update(f1, f2) on table t to tmp$c5804_john with grant option; + commit; + + revoke update(f1) on table t from tmp$c5804_john; + commit; + + execute procedure sp_msg('revoked privilege for update only field F1'); + select v.* from v_grants v; -- only one record with data for field 'F2' should be displayed now + + revoke all on all from tmp$c5804_john; + commit; + + -- check revoke update the second field -- + ------------------------------------------ + grant update(f1, f2) on table t to tmp$c5804_john with grant option; + commit; + + revoke update(f2) on table t from tmp$c5804_john; + commit; + + execute procedure sp_msg('revoked privilege for update only field F2'); + select v.* from v_grants v; -- only one record with data for field 'F1' should be displayed now + + revoke all on all from tmp$c5804_john; + commit; + + + -- check revoke update for every field -- + ----------------------------------------- + grant update(f1, f2) on table t to tmp$c5804_john with grant option; + commit; + + revoke update(f1, f2) on table t from tmp$c5804_john; + commit; + + execute procedure sp_msg('revoked privilege update of both fields F1 and F2 enumerated as list'); + select v.* from v_grants v; -- no rows should be displayed now + + revoke all on all from tmp$c5804_john; + commit; + + + + -- check revoke role -- + ----------------------- + grant tmp$r5804_boss to + -- role -- allowed only in 4.0 + tmp$r5804_acnt; + commit; + + -- execute procedure sp_msg('after grant tmp$r5804_boss to role tmp$r5804_acnt'); + -- select v.* from v_grants v; + + revoke tmp$r5804_boss from + -- role -- allowed only in 4.0 + tmp$r5804_acnt; + commit; + + -- execute procedure sp_msg('revoked role tmp$r5804_boss from role tmp$r5804_acnt'); + -- select v.* from v_grants v; -- no rows should be displayed now + + --################################################################# + -- R O L E S : D E F A U L T C L A U S E + --################################################################# + + /***************************************** + beg of commented block-1 + + Following is not allowed in 3.0: 'default' clause can not be used in GRANT / REVOKE role statements + + -- check revoke default of role -- + ---------------------------------- + grant default tmp$r5804_boss + -- to role -- allowed only in 4.0 + tmp$r5804_acnt; -- ==> rdb$privileges.rdb$field_name = 'D' after this + commit; + + --execute procedure sp_msg('after grant default tmp$r5804_boss to role tmp$r5804_acnt'); + --select v.* from v_roles v; + --select v.* from v_grants v; + + + execute procedure sp_msg('before revoking only default tmp$r5804_boss from role tmp$r5804_acnt'); + select v.* from v_grants v; -- ==> rdb$privileges.rdb$field_name must be 'D' + + revoke default tmp$r5804_boss from role tmp$r5804_acnt;-- revoke only default option + commit; + + execute procedure sp_msg('after revoked only default tmp$r5804_boss from role tmp$r5804_acnt'); + select v.* from v_grants v; -- ==> rdb$privileges.rdb$field_name must be NULL + + revoke tmp$r5804_boss from role tmp$r5804_acnt; -- revoke whole role + commit; + + + + -- check revoke whole role which was granted with DEFAULT clause -- + ------------------------------------------------------------------- + grant default tmp$r5804_boss to role tmp$r5804_acnt; + commit; + + revoke tmp$r5804_boss from role tmp$r5804_acnt; + commit; + + execute procedure sp_msg('after revoked role that was granted with DEFAULT clause'); + select v.* from v_grants v; -- ==> no rows must be displayed now + + + end of commented block-1 + ********************************/ + + --################################################################# + -- R O L E S : A D M I N C L A U S E + --################################################################# + + + -- check revoke admin option -- + ------------------------------- + grant tmp$r5804_boss to + -- role -- allowed only in 4.0 + tmp$r5804_acnt with admin option; -- rdb$roles.rdb$grant_option must be 2 after this + commit; + + execute procedure sp_msg('before revoke admin option from role that was granted with this'); + select v.* from v_grants v; + + revoke admin option for tmp$r5804_boss from + -- role -- allowed only in 4.0 + tmp$r5804_acnt; -- rdb$roles.rdb$grant_option must be 0 after this + commit; + + execute procedure sp_msg('after revoke admin option from role that was granted with this'); + select v.* from v_grants v; + + /******************************************* + beg of commented block-2 + + Following is not allowed in 3.0: 'default' clause can not be used in GRANT / REVOKE role statements + + -- check revoke default from role granted with admin option -- + -------------------------------------------------------------- + grant default tmp$r5804_boss to role tmp$r5804_acnt with admin option; + commit; + + execute procedure sp_msg('before revoke default tmp$r5804_boss that was granted with admin option to tmp$r5804_acnt'); + select v.* from v_grants v; + + revoke default tmp$r5804_boss from role tmp$r5804_acnt; + commit; + + execute procedure sp_msg('after revoke default tmp$r5804_boss that was granted with admin option to tmp$r5804_acnt'); + select v.* from v_grants v; + + revoke tmp$r5804_boss from role tmp$r5804_acnt; + commit; + + + -- check revoke admin option from default role -- + ------------------------------------------------- + grant default tmp$r5804_boss to role tmp$r5804_acnt with admin option; + commit; + + + execute procedure sp_msg('before revoke admin option from default role'); + select v.* from v_grants v; + + revoke admin option for tmp$r5804_boss from role tmp$r5804_acnt; + commit; + + execute procedure sp_msg('after revoke admin option from default role'); + select v.* from v_grants v; + + end of commented block-2 + *******************************************/ + + + -- added by myself: + revoke tmp$r5804_boss from + -- role + tmp$r5804_acnt; + commit; + + + + /************************************* + beg of commented block-3 + Following is not allowed in 3.0: 'default' clause can not be used in GRANT / REVOKE role statements + + + -- check revoke both GO and AO from granted role -- + --------------------------------------------------- + grant default tmp$r5804_boss to role tmp$r5804_acnt with admin option; + commit; + + execute procedure sp_msg('before revoke admin option for default role tmp$r5804_boss from role tmp$r5804_acnt'); + select v.* from v_grants v; + + revoke admin option for default tmp$r5804_boss from role tmp$r5804_acnt; + commit; + + execute procedure sp_msg('after revoke admin option for default role tmp$r5804_boss from role tmp$r5804_acnt'); + select v.* from v_grants v; + + -- me: + revoke tmp$r5804_boss from role tmp$r5804_acnt; + commit; + + end of commented block-3 + *********************************/ + + -- adding options to role grants -- + ----------------------------------- + drop role tmp$r5804_boss; + create role tmp$r5804_boss; + drop role tmp$r5804_acnt; + create role tmp$r5804_acnt; + + -- commented in 3.0: grant default tmp$r5804_boss to role tmp$r5804_acnt; + + grant tmp$r5804_boss to + -- role -- allowed in 4.0 only + tmp$r5804_acnt with admin option; + + commit; + execute procedure sp_msg('Check aux options: point-1'); + select v.* from v_grants v; + + --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + recreate table t (i int); + grant select on t to tmp$c5804_john; + commit; + execute procedure sp_msg('Check aux options: point-2a'); + select v.* from v_grants v; + + grant select on t to tmp$c5804_john with grant option; + commit; + execute procedure sp_msg('Check aux options: point-2b'); + select v.* from v_grants v; + + grant select on t to tmp$c5804_john; + commit; + execute procedure sp_msg('Check aux options: point-2c'); + select v.* from v_grants v; -- must be the same as it was at point-2a + + revoke all on t from tmp$c5804_john; + revoke tmp$r5804_boss from + -- role -- allowed in 4.0 only + tmp$r5804_acnt; + drop role tmp$r5804_boss; + drop role tmp$r5804_acnt; + commit; + + execute procedure sp_msg('Check aux options: point-2d'); + select v.* from v_grants v; -- must be empty + + --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + create role tmp$r5804_boss; + create role tmp$r5804_acnt; + grant tmp$r5804_boss to + -- role -- allowed in 4.0 only + tmp$r5804_acnt; + commit; + execute procedure sp_msg('Check aux options: point-3'); + select v.* from v_grants v; + + + grant tmp$r5804_boss to + -- role -- allowed in 4.0 only + tmp$r5804_acnt with admin option; + commit; + execute procedure sp_msg('Check aux options: point-4'); + select v.* from v_grants v; -- has_grant must be 2 + + + /************************************* + beg of commented block-4 + Following is not allowed in 3.0: 'default' clause can not be used in GRANT / REVOKE role statements + + grant default tmp$r5804_boss + -- to role -- aloowed in 4.0 only + tmp$r5804_acnt with admin option; + commit; + execute procedure sp_msg('Check aux options: point-5'); + select v.* from v_grants v; -- fld_name must be 'D' + + + grant default tmp$r5804_boss to role tmp$r5804_acnt; + commit; + execute procedure sp_msg('Check aux options: point-6'); + select v.* from v_grants v; + + end of commented block-4 + ***************************************/ + + + drop role tmp$r5804_boss; + drop role tmp$r5804_acnt; + create role tmp$r5804_boss; + create role tmp$r5804_acnt; + commit; + + /************************************* + beg of commented block-5 + Following is not allowed in 3.0: 'default' clause can not be used in GRANT / REVOKE role statements + + grant default tmp$r5804_boss to role tmp$r5804_acnt; + commit; + execute procedure sp_msg('Check aux options: point-7'); + select v.* from v_grants v; -- fld_name must be 'D' + + end of commented block-4 + **********************************/ + + grant tmp$r5804_boss to + -- role -- aloowed in 4.0 only + tmp$r5804_acnt with admin option; + commit; + execute procedure sp_msg('Check aux options: point-8'); + select v.* from v_grants v; -- has_grant must be 2 + + + ---------------------------- final ----------------------------- + commit; + drop user tmp$c5804_john; + drop role tmp$r5804_boss; + drop role tmp$r5804_acnt; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG revoked grant option for update of the whole table + + + + USR_TYPE 8 + USR_NAME TMP$C5804_JOHN + WHO_GAVE SYSDBA + WHAT_CAN U + HAS_GRANT 0 + OBJ_TYPE 0 + REL_NAME T + FLD_NAME F1 + + USR_TYPE 8 + USR_NAME TMP$C5804_JOHN + WHO_GAVE SYSDBA + WHAT_CAN U + HAS_GRANT 0 + OBJ_TYPE 0 + REL_NAME T + FLD_NAME F2 + + + Records affected: 2 + + MSG revoked grant option for update only field F1 + + + + USR_TYPE 8 + USR_NAME TMP$C5804_JOHN + WHO_GAVE SYSDBA + WHAT_CAN U + HAS_GRANT 0 + OBJ_TYPE 0 + REL_NAME T + FLD_NAME F1 + + USR_TYPE 8 + USR_NAME TMP$C5804_JOHN + WHO_GAVE SYSDBA + WHAT_CAN U + HAS_GRANT 1 + OBJ_TYPE 0 + REL_NAME T + FLD_NAME F2 + + + Records affected: 2 + + MSG revoked grant option for update only field F2 + + + + USR_TYPE 8 + USR_NAME TMP$C5804_JOHN + WHO_GAVE SYSDBA + WHAT_CAN U + HAS_GRANT 0 + OBJ_TYPE 0 + REL_NAME T + FLD_NAME F2 + + USR_TYPE 8 + USR_NAME TMP$C5804_JOHN + WHO_GAVE SYSDBA + WHAT_CAN U + HAS_GRANT 1 + OBJ_TYPE 0 + REL_NAME T + FLD_NAME F1 + + + Records affected: 2 + + MSG revoked grant option for update of both fields F1 and F2 enumerated as list + + + + USR_TYPE 8 + USR_NAME TMP$C5804_JOHN + WHO_GAVE SYSDBA + WHAT_CAN U + HAS_GRANT 0 + OBJ_TYPE 0 + REL_NAME T + FLD_NAME F1 + + USR_TYPE 8 + USR_NAME TMP$C5804_JOHN + WHO_GAVE SYSDBA + WHAT_CAN U + HAS_GRANT 0 + OBJ_TYPE 0 + REL_NAME T + FLD_NAME F2 + + + Records affected: 2 + + MSG revoked privilege update for the whole table + + + Records affected: 0 + + MSG revoked privilege for update only field F1 + + + + USR_TYPE 8 + USR_NAME TMP$C5804_JOHN + WHO_GAVE SYSDBA + WHAT_CAN U + HAS_GRANT 1 + OBJ_TYPE 0 + REL_NAME T + FLD_NAME F2 + + + Records affected: 1 + + MSG revoked privilege for update only field F2 + + + + USR_TYPE 8 + USR_NAME TMP$C5804_JOHN + WHO_GAVE SYSDBA + WHAT_CAN U + HAS_GRANT 1 + OBJ_TYPE 0 + REL_NAME T + FLD_NAME F1 + + + Records affected: 1 + + MSG revoked privilege update of both fields F1 and F2 enumerated as list + + + Records affected: 0 + + MSG before revoke admin option from role that was granted with this + + + + USR_TYPE 8 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 2 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME + + + Records affected: 1 + + MSG after revoke admin option from role that was granted with this + + + + USR_TYPE 8 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 0 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME + + + Records affected: 1 + + MSG Check aux options: point-1 + + + + USR_TYPE 8 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 2 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME + + + Records affected: 1 + + MSG Check aux options: point-2a + + + + USR_TYPE 8 + USR_NAME TMP$C5804_JOHN + WHO_GAVE SYSDBA + WHAT_CAN S + HAS_GRANT 0 + OBJ_TYPE 0 + REL_NAME T + FLD_NAME + + USR_TYPE 8 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 2 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME + + + Records affected: 2 + + MSG Check aux options: point-2b + + + + USR_TYPE 8 + USR_NAME TMP$C5804_JOHN + WHO_GAVE SYSDBA + WHAT_CAN S + HAS_GRANT 1 + OBJ_TYPE 0 + REL_NAME T + FLD_NAME + + USR_TYPE 8 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 2 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME + + + Records affected: 2 + + MSG Check aux options: point-2c + + + + USR_TYPE 8 + USR_NAME TMP$C5804_JOHN + WHO_GAVE SYSDBA + WHAT_CAN S + HAS_GRANT 1 + OBJ_TYPE 0 + REL_NAME T + FLD_NAME + + USR_TYPE 8 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 2 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME + + + Records affected: 2 + + MSG Check aux options: point-2d + + + Records affected: 0 + + MSG Check aux options: point-3 + + + + USR_TYPE 8 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 0 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME + + + Records affected: 1 + + MSG Check aux options: point-4 + + + + USR_TYPE 8 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 2 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME + + + Records affected: 1 + + MSG Check aux options: point-8 + + + + USR_TYPE 8 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 2 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME + + + Records affected: 1 + """ + +@pytest.mark.version('>=3.0.4,<4.0') +def test_core_5804_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set bail on; + set wng off; + set list on; + set count on; + + create or alter user tmp$c5804_john password '123'; + commit; + + set term ^; + create or alter procedure sp_msg (a_msg varchar(100)) returns(msg varchar(100)) as begin + msg=a_msg; + suspend; + end^ + set term ;^ + commit; + + recreate view v_roles as + select r.* + from rdb$roles r + where r.rdb$system_flag is distinct from 1 + ; + + recreate view v_grants as + select + p.rdb$user_type as usr_type + ,p.rdb$user as usr_name + ,p.rdb$grantor as who_gave + ,p.rdb$privilege as what_can + ,p.rdb$grant_option as has_grant + ,p.rdb$object_type as obj_type + ,p.rdb$relation_name as rel_name + ,p.rdb$field_name as fld_name + from rdb$database r left join rdb$user_privileges p on 1=1 + where p.rdb$user in( upper('tmp$c5804_john'), upper('tmp$r5804_boss'), upper('tmp$r5804_acnt') ) + order by 1,2,3,4,5,6,7,8 + ; + + recreate table t(f1 int, f2 int); + create role tmp$r5804_boss; + create role tmp$r5804_acnt; + commit; + revoke all on all from tmp$c5804_john; + commit; + + --################################################################## + -- G R A N T O P T I O N + --################################################################## + + -- check revoke grant option for all table -- + --------------------------------------------- + + grant update(f1, f2) on table t to tmp$c5804_john with grant option; + commit; + + revoke grant option for update on table t from tmp$c5804_john; + commit; + + execute procedure sp_msg('revoked grant option for update of the whole table'); + select v.* from v_grants v; + commit; + + revoke all on all from tmp$c5804_john; + commit; + + -- check revoke grant option for the first field -- + --------------------------------------------------- + grant update(f1, f2) on table t to tmp$c5804_john with grant option; + commit; + + revoke grant option for update(f1) on table t from tmp$c5804_john; + commit; + + execute procedure sp_msg('revoked grant option for update only field F1'); + select v.* from v_grants v; + + commit; + revoke all on all from tmp$c5804_john; + commit; + + -- check revoke grant option for the second field -- + ---------------------------------------------------- + grant update(f1, f2) on table t to tmp$c5804_john with grant option; + commit; + + revoke grant option for update(f2) on table t from tmp$c5804_john; + commit; + + execute procedure sp_msg('revoked grant option for update only field F2'); + select v.* from v_grants v; + + revoke all on all from tmp$c5804_john; + commit; + + + -- check revoke grant option for every field -- + ----------------------------------------------- + grant update(f1, f2) on table t to tmp$c5804_john with grant option; + commit; + + revoke grant option for update(f2, f1) on table t from tmp$c5804_john; + commit; + + execute procedure sp_msg('revoked grant option for update of both fields F1 and F2 enumerated as list'); + select v.* from v_grants v; + + revoke all on all from tmp$c5804_john; + commit; + + + --################################################################## + -- U P D A T E + --################################################################## + + -- check revoke update for all table -- + --------------------------------------- + grant update(f1, f2) on table t to tmp$c5804_john with grant option; + commit; + + revoke update on table t from tmp$c5804_john; + commit; + + execute procedure sp_msg('revoked privilege update for the whole table'); + select v.* from v_grants v; -- no rows should be displayed now! + + revoke all on all from tmp$c5804_john; + commit; + + -- check revoke update for the first field -- + --------------------------------------------- + grant update(f1, f2) on table t to tmp$c5804_john with grant option; + commit; + + revoke update(f1) on table t from tmp$c5804_john; + commit; + + execute procedure sp_msg('revoked privilege for update only field F1'); + select v.* from v_grants v; -- only one record with data for field 'F2' should be displayed now + + revoke all on all from tmp$c5804_john; + commit; + + -- check revoke update the second field -- + ------------------------------------------ + grant update(f1, f2) on table t to tmp$c5804_john with grant option; + commit; + + revoke update(f2) on table t from tmp$c5804_john; + commit; + + execute procedure sp_msg('revoked privilege for update only field F2'); + select v.* from v_grants v; -- only one record with data for field 'F1' should be displayed now + + revoke all on all from tmp$c5804_john; + commit; + + + -- check revoke update for every field -- + ----------------------------------------- + grant update(f1, f2) on table t to tmp$c5804_john with grant option; + commit; + + revoke update(f1, f2) on table t from tmp$c5804_john; + commit; + + execute procedure sp_msg('revoked privilege update of both fields F1 and F2 enumerated as list'); + select v.* from v_grants v; -- no rows should be displayed now + + revoke all on all from tmp$c5804_john; + commit; + + --################################################################# + -- R O L E S : D E F A U L T C L A U S E + --################################################################# + + + -- check revoke role -- + ----------------------- + grant tmp$r5804_boss to role tmp$r5804_acnt; + commit; + + --execute procedure sp_msg('after grant tmp$r5804_boss to role tmp$r5804_acnt'); + --select v.* from v_grants v; + + revoke tmp$r5804_boss from role tmp$r5804_acnt; + commit; + + -- execute procedure sp_msg('revoked role tmp$r5804_boss from role tmp$r5804_acnt'); + -- select v.* from v_grants v; -- no rows should be displayed now + + + -- check revoke default of role -- + ---------------------------------- + grant default tmp$r5804_boss to role tmp$r5804_acnt; -- ==> rdb$privileges.rdb$field_name = 'D' after this + commit; + + --execute procedure sp_msg('after grant default tmp$r5804_boss to role tmp$r5804_acnt'); + --select v.* from v_roles v; + --select v.* from v_grants v; + + + execute procedure sp_msg('before revoking only default tmp$r5804_boss from role tmp$r5804_acnt'); + select v.* from v_grants v; -- ==> rdb$privileges.rdb$field_name must be 'D' + + revoke default tmp$r5804_boss from role tmp$r5804_acnt;-- revoke only default option + commit; + + execute procedure sp_msg('after revoked only default tmp$r5804_boss from role tmp$r5804_acnt'); + select v.* from v_grants v; -- ==> rdb$privileges.rdb$field_name must be NULL + + + revoke tmp$r5804_boss from role tmp$r5804_acnt;-- revoke whole role + commit; + + + + -- check revoke whole role which was granted with DEFAULT clause -- + ------------------------------------------------------------------- + grant default tmp$r5804_boss to role tmp$r5804_acnt; + commit; + + revoke tmp$r5804_boss from role tmp$r5804_acnt; + commit; + + execute procedure sp_msg('after revoked role that was granted with DEFAULT clause'); + select v.* from v_grants v; -- ==> no rows must be displayed now + + + --################################################################# + -- R O L E S : A D M I N C L A U S E + --################################################################# + + + -- check revoke admin option -- + ------------------------------- + grant tmp$r5804_boss to role tmp$r5804_acnt with admin option; -- rdb$roles.rdb$grant_option must be 2 after this + commit; + + execute procedure sp_msg('before revoke admin option from role that was granted with this'); + select v.* from v_grants v; + + revoke admin option for tmp$r5804_boss from role tmp$r5804_acnt; -- rdb$roles.rdb$grant_option must be 0 after this + commit; + + execute procedure sp_msg('after revoke admin option from role that was granted with this'); + select v.* from v_grants v; + + + -- check revoke default from role granted with admin option -- + -------------------------------------------------------------- + grant default tmp$r5804_boss to role tmp$r5804_acnt with admin option; + commit; + + execute procedure sp_msg('before revoke default tmp$r5804_boss that was granted with admin option to tmp$r5804_acnt'); + select v.* from v_grants v; + + revoke default tmp$r5804_boss from role tmp$r5804_acnt; + commit; + + execute procedure sp_msg('after revoke default tmp$r5804_boss that was granted with admin option to tmp$r5804_acnt'); + select v.* from v_grants v; + + revoke tmp$r5804_boss from role tmp$r5804_acnt; + commit; + + + + -- check revoke admin option from default role -- + ------------------------------------------------- + grant default tmp$r5804_boss to role tmp$r5804_acnt with admin option; + commit; + + + execute procedure sp_msg('before revoke admin option from default role'); + select v.* from v_grants v; + + revoke admin option for tmp$r5804_boss from role tmp$r5804_acnt; + commit; + + execute procedure sp_msg('after revoke admin option from default role'); + select v.* from v_grants v; + + + -- me: + revoke tmp$r5804_boss from role tmp$r5804_acnt; + commit; + + -- check revoke both GO and AO from granted role -- + --------------------------------------------------- + grant default tmp$r5804_boss to role tmp$r5804_acnt with admin option; + commit; + + execute procedure sp_msg('before revoke admin option for default role tmp$r5804_boss from role tmp$r5804_acnt'); + select v.* from v_grants v; + + revoke admin option for default tmp$r5804_boss from role tmp$r5804_acnt; + commit; + + execute procedure sp_msg('after revoke admin option for default role tmp$r5804_boss from role tmp$r5804_acnt'); + select v.* from v_grants v; + + -- me: + revoke tmp$r5804_boss from role tmp$r5804_acnt; + commit; + + + -- adding options to role grants -- + ----------------------------------- + drop role tmp$r5804_boss; + create role tmp$r5804_boss; + drop role tmp$r5804_acnt; + create role tmp$r5804_acnt; + + grant default tmp$r5804_boss to role tmp$r5804_acnt; + grant tmp$r5804_boss to role tmp$r5804_acnt with admin option; + + commit; + execute procedure sp_msg('Check aux options: point-1'); + select v.* from v_grants v; + + + --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + recreate table t (i int); + grant select on t to tmp$c5804_john; + commit; + execute procedure sp_msg('Check aux options: point-2a'); + select v.* from v_grants v; + + grant select on t to tmp$c5804_john with grant option; + commit; + execute procedure sp_msg('Check aux options: point-2b'); + select v.* from v_grants v; + + grant select on t to tmp$c5804_john; + commit; + execute procedure sp_msg('Check aux options: point-2c'); + select v.* from v_grants v; -- must be the same as it was at point-2a + + revoke all on t from tmp$c5804_john; + revoke tmp$r5804_boss from role tmp$r5804_acnt; + drop role tmp$r5804_boss; + drop role tmp$r5804_acnt; + commit; + + + execute procedure sp_msg('Check aux options: point-2d'); + select v.* from v_grants v; -- must be empty + + --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + + create role tmp$r5804_boss; + create role tmp$r5804_acnt; + grant tmp$r5804_boss to role tmp$r5804_acnt; + commit; + execute procedure sp_msg('Check aux options: point-3'); + select v.* from v_grants v; + + + + grant tmp$r5804_boss to role tmp$r5804_acnt with admin option; + commit; + execute procedure sp_msg('Check aux options: point-4'); + select v.* from v_grants v; -- has_grant must be 2 + + + + grant default tmp$r5804_boss to role tmp$r5804_acnt with admin option; + commit; + execute procedure sp_msg('Check aux options: point-5'); + select v.* from v_grants v; -- fld_name must be 'D' + + + grant default tmp$r5804_boss to role tmp$r5804_acnt; + commit; + execute procedure sp_msg('Check aux options: point-6'); + select v.* from v_grants v; + + + + drop role tmp$r5804_boss; + drop role tmp$r5804_acnt; + create role tmp$r5804_boss; + create role tmp$r5804_acnt; + grant default tmp$r5804_boss to role tmp$r5804_acnt; + commit; + execute procedure sp_msg('Check aux options: point-7'); + select v.* from v_grants v; -- fld_name must be 'D' + + + + grant tmp$r5804_boss to role tmp$r5804_acnt with admin option; + commit; + execute procedure sp_msg('Check aux options: point-8'); + select v.* from v_grants v; -- has_grant must be 2 + + ---------------------------- final ----------------------------- + commit; + drop user tmp$c5804_john; + drop role tmp$r5804_boss; + drop role tmp$r5804_acnt; + commit; + + + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + MSG revoked grant option for update of the whole table + + + + USR_TYPE 8 + USR_NAME TMP$C5804_JOHN + WHO_GAVE SYSDBA + WHAT_CAN U + HAS_GRANT 0 + OBJ_TYPE 0 + REL_NAME T + FLD_NAME F1 + + USR_TYPE 8 + USR_NAME TMP$C5804_JOHN + WHO_GAVE SYSDBA + WHAT_CAN U + HAS_GRANT 0 + OBJ_TYPE 0 + REL_NAME T + FLD_NAME F2 + + + Records affected: 2 + + MSG revoked grant option for update only field F1 + + + + USR_TYPE 8 + USR_NAME TMP$C5804_JOHN + WHO_GAVE SYSDBA + WHAT_CAN U + HAS_GRANT 0 + OBJ_TYPE 0 + REL_NAME T + FLD_NAME F1 + + USR_TYPE 8 + USR_NAME TMP$C5804_JOHN + WHO_GAVE SYSDBA + WHAT_CAN U + HAS_GRANT 1 + OBJ_TYPE 0 + REL_NAME T + FLD_NAME F2 + + + Records affected: 2 + + MSG revoked grant option for update only field F2 + + + + USR_TYPE 8 + USR_NAME TMP$C5804_JOHN + WHO_GAVE SYSDBA + WHAT_CAN U + HAS_GRANT 0 + OBJ_TYPE 0 + REL_NAME T + FLD_NAME F2 + + USR_TYPE 8 + USR_NAME TMP$C5804_JOHN + WHO_GAVE SYSDBA + WHAT_CAN U + HAS_GRANT 1 + OBJ_TYPE 0 + REL_NAME T + FLD_NAME F1 + + + Records affected: 2 + + MSG revoked grant option for update of both fields F1 and F2 enumerated as list + + + + USR_TYPE 8 + USR_NAME TMP$C5804_JOHN + WHO_GAVE SYSDBA + WHAT_CAN U + HAS_GRANT 0 + OBJ_TYPE 0 + REL_NAME T + FLD_NAME F1 + + USR_TYPE 8 + USR_NAME TMP$C5804_JOHN + WHO_GAVE SYSDBA + WHAT_CAN U + HAS_GRANT 0 + OBJ_TYPE 0 + REL_NAME T + FLD_NAME F2 + + + Records affected: 2 + + MSG revoked privilege update for the whole table + + + Records affected: 0 + + MSG revoked privilege for update only field F1 + + + + USR_TYPE 8 + USR_NAME TMP$C5804_JOHN + WHO_GAVE SYSDBA + WHAT_CAN U + HAS_GRANT 1 + OBJ_TYPE 0 + REL_NAME T + FLD_NAME F2 + + + Records affected: 1 + + MSG revoked privilege for update only field F2 + + + + USR_TYPE 8 + USR_NAME TMP$C5804_JOHN + WHO_GAVE SYSDBA + WHAT_CAN U + HAS_GRANT 1 + OBJ_TYPE 0 + REL_NAME T + FLD_NAME F1 + + + Records affected: 1 + + MSG revoked privilege update of both fields F1 and F2 enumerated as list + + + Records affected: 0 + + MSG before revoking only default tmp$r5804_boss from role tmp$r5804_acnt + + + + USR_TYPE 13 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 0 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME D + + + Records affected: 1 + + MSG after revoked only default tmp$r5804_boss from role tmp$r5804_acnt + + + + USR_TYPE 13 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 0 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME + + + Records affected: 1 + + MSG after revoked role that was granted with DEFAULT clause + + + Records affected: 0 + + MSG before revoke admin option from role that was granted with this + + + + USR_TYPE 13 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 2 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME + + + Records affected: 1 + + MSG after revoke admin option from role that was granted with this + + + + USR_TYPE 13 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 0 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME + + + Records affected: 1 + + MSG before revoke default tmp$r5804_boss that was granted with admin option to tmp$r5804_acnt + + + + USR_TYPE 13 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 2 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME D + + + Records affected: 1 + + MSG after revoke default tmp$r5804_boss that was granted with admin option to tmp$r5804_acnt + + + + USR_TYPE 13 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 2 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME + + + Records affected: 1 + + MSG before revoke admin option from default role + + + + USR_TYPE 13 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 2 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME D + + + Records affected: 1 + + MSG after revoke admin option from default role + + + + USR_TYPE 13 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 0 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME D + + + Records affected: 1 + + MSG before revoke admin option for default role tmp$r5804_boss from role tmp$r5804_acnt + + + + USR_TYPE 13 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 2 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME D + + + Records affected: 1 + + MSG after revoke admin option for default role tmp$r5804_boss from role tmp$r5804_acnt + + + + USR_TYPE 13 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 0 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME + + + Records affected: 1 + + MSG Check aux options: point-1 + + + + USR_TYPE 13 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 2 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME D + + + Records affected: 1 + + MSG Check aux options: point-2a + + + + USR_TYPE 8 + USR_NAME TMP$C5804_JOHN + WHO_GAVE SYSDBA + WHAT_CAN S + HAS_GRANT 0 + OBJ_TYPE 0 + REL_NAME T + FLD_NAME + + USR_TYPE 13 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 2 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME D + + + Records affected: 2 + + MSG Check aux options: point-2b + + + + USR_TYPE 8 + USR_NAME TMP$C5804_JOHN + WHO_GAVE SYSDBA + WHAT_CAN S + HAS_GRANT 1 + OBJ_TYPE 0 + REL_NAME T + FLD_NAME + + USR_TYPE 13 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 2 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME D + + + Records affected: 2 + + MSG Check aux options: point-2c + + + + USR_TYPE 8 + USR_NAME TMP$C5804_JOHN + WHO_GAVE SYSDBA + WHAT_CAN S + HAS_GRANT 1 + OBJ_TYPE 0 + REL_NAME T + FLD_NAME + + USR_TYPE 13 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 2 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME D + + + Records affected: 2 + + MSG Check aux options: point-2d + + + Records affected: 0 + + MSG Check aux options: point-3 + + + + USR_TYPE 13 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 0 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME + + + Records affected: 1 + + MSG Check aux options: point-4 + + + + USR_TYPE 13 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 2 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME + + + Records affected: 1 + + MSG Check aux options: point-5 + + + + USR_TYPE 13 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 2 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME D + + + Records affected: 1 + + MSG Check aux options: point-6 + + + + USR_TYPE 13 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 2 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME D + + + Records affected: 1 + + MSG Check aux options: point-7 + + + + USR_TYPE 13 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 0 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME D + + + Records affected: 1 + + MSG Check aux options: point-8 + + + + USR_TYPE 13 + USR_NAME TMP$R5804_ACNT + WHO_GAVE SYSDBA + WHAT_CAN M + HAS_GRANT 2 + OBJ_TYPE 13 + REL_NAME TMP$R5804_BOSS + FLD_NAME D + + + Records affected: 1 + + """ + +@pytest.mark.version('>=4.0') +def test_core_5804_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/bugs/test_core_5808.py b/tests/bugs/test_core_5808.py new file mode 100644 index 00000000..82cd5e04 --- /dev/null +++ b/tests/bugs/test_core_5808.py @@ -0,0 +1,213 @@ +#coding:utf-8 +# +# id: bugs.core_5808 +# title: Support backup of encrypted databases +# decription: +# THIS TEST USES IBSurgeon Demo Encryption package +# ################################################ +# ( https://ib-aid.com/download-demo-firebird-encryption-plugin/ ; https://ib-aid.com/download/crypt/CryptTest.zip ) +# License file plugins\\dbcrypt.conf with unlimited expiration was provided by IBSurgeon to Firebird Foundation (FF). +# This file was preliminary stored in FF Test machine. +# Test assumes that this file and all neccessary libraries already were stored into FB_HOME and %FB_HOME%\\plugins. +# +# Anyone who wants to run this test on his own machine must +# 1) download https://ib-aid.com/download/crypt/CryptTest.zip AND +# 2) PURCHASE LICENSE and get from IBSurgeon file plugins\\dbcrypt.conf with apropriate expiration date and other info. +# +# ################################################ ! ! ! N O T E ! ! ! ############################################## +# FF tests storage (aka "fbt-repo") does not (and will not) contain any license file for IBSurgeon Demo Encryption package! +# ######################################################################################################################### +# +# After test database will be created, we try to encrypt it using 'alter database encrypt with ...' command +# (where = dbcrypt - name of .dll in FB_HOME\\plugins\\ folder that implements encryption). +# Then we allow engine to complete this job - take delay about 1..2 seconds BEFORE detach from database. +# After this we make backup of encrypted database + restore. +# +# Then we make snapshot of firebird.log, run 'gfix -v -full' of restored database and once again take snapshot of firebird.log. +# Comparison of these two logs is result of validation. It should contain line about start and line with finish info. +# The latter must look like this: "Validation finished: 0 errors, 0 warnings, 0 fixed" +# +# Checked on: +# 40sS, build 4.0.0.1487: OK, 6.552s. +# 40sC, build 4.0.0.1421: OK, 11.812s. +# 40Cs, build 4.0.0.1485: OK, 8.097s. +# +# tracker_id: CORE-5808 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import time +# import difflib +# import subprocess +# import re +# import fdb +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.close() +# +# def svc_get_fb_log( f_fb_log ): +# +# import subprocess +# +# subprocess.call( [ "fbsvcmgr", +# "localhost:service_mgr", +# "action_get_fb_log" +# ], +# stdout=f_fb_log, stderr=subprocess.STDOUT +# ) +# return +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# +# tmpfdb='$(DATABASE_LOCATION)'+'tmp_core_5808.fdb' +# tmpfbk='$(DATABASE_LOCATION)'+'tmp_core_5808.fbk' +# +# f_list=( tmpfdb, tmpfbk ) +# cleanup( f_list ) +# +# +# con = fdb.create_database( dsn = 'localhost:'+tmpfdb ) +# con.close() +# con=fdb.connect( dsn = 'localhost:'+tmpfdb ) +# cur = con.cursor() +# cur.execute('alter database encrypt with dbcrypt key Red') +# con.commit() +# +# time.sleep(1) +# # ^ +# # +-------- !! ALLOW BACKGROUND ENCRYPTION PROCESS TO COMPLETE ITS JOB !! +# +# con.close() +# +# f_backup_log = open( os.path.join(context['temp_directory'],'tmp_backup_5808.log'), 'w') +# f_backup_err = open( os.path.join(context['temp_directory'],'tmp_backup_5808.err'), 'w') +# +# subprocess.call( [ "gbak", "-v", "-b", 'localhost:' + tmpfdb, tmpfbk], +# stdout = f_backup_log, +# stderr = f_backup_err +# ) +# f_backup_log.close() +# f_backup_err.close() +# +# +# f_restore_log = open( os.path.join(context['temp_directory'],'tmp_restore_5808.log'), 'w') +# f_restore_err = open( os.path.join(context['temp_directory'],'tmp_restore_5808.err'), 'w') +# +# subprocess.call( [ "gbak", "-v", "-rep", tmpfbk, 'localhost:'+tmpfdb], +# stdout = f_restore_log, +# stderr = f_restore_err +# ) +# f_restore_log.close() +# f_restore_err.close() +# +# f_fblog_before=open( os.path.join(context['temp_directory'],'tmp_5808_fblog_before.txt'), 'w') +# svc_get_fb_log( f_fblog_before ) +# f_fblog_before.close() +# +# +# f_validate_log = open( os.path.join(context['temp_directory'],'tmp_validate_5808.log'), 'w') +# f_validate_err = open( os.path.join(context['temp_directory'],'tmp_validate_5808.err'), 'w') +# +# subprocess.call( [ "gfix", "-v", "-full", tmpfdb ], +# stdout = f_validate_log, +# stderr = f_validate_err +# ) +# f_validate_log.close() +# f_validate_err.close() +# +# f_fblog_after=open( os.path.join(context['temp_directory'],'tmp_5808_fblog_after.txt'), 'w') +# svc_get_fb_log( f_fblog_after ) +# f_fblog_after.close() +# time.sleep(1) +# +# +# # Compare firebird.log versions BEFORE and AFTER this test: +# ###################### +# +# oldfb=open(f_fblog_before.name, 'r') +# newfb=open(f_fblog_after.name, 'r') +# +# difftext = ''.join(difflib.unified_diff( +# oldfb.readlines(), +# newfb.readlines() +# )) +# oldfb.close() +# newfb.close() +# +# +# with open( f_backup_err.name,'r') as f: +# for line in f: +# print("UNEXPECTED PROBLEM ON BACKUP, STDERR: "+line) +# +# with open( f_restore_err.name,'r') as f: +# for line in f: +# print("UNEXPECTED PROBLEM ON RESTORE, STDERR: "+line) +# +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_5808_diff.txt'), 'w') +# f_diff_txt.write(difftext) +# f_diff_txt.close() +# +# allowed_patterns = ( +# re.compile( '\\+\\s+Validation\\s+started', re.IGNORECASE) +# ,re.compile( '\\+\\s+Validation\\s+finished:\\s+0\\s+errors,\\s+0\\s+warnings,\\s+0\\s+fixed', re.IGNORECASE) +# ) +# +# +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# match2some = filter( None, [ p.search(line) for p in allowed_patterns ] ) +# if match2some: +# print( (' '.join( line.split()).upper() ) ) +# +# # do NOT remove this pause otherwise some of logs will not be enable for deletion and test will finish with +# # Exception raised while executing Python test script. exception: WindowsError: 32 +# time.sleep(1) +# +# # +=+=+=+=+=+=+=+=+=+=+ +# # +=+=+= CLEANUP +=+=+= +# # +=+=+=+=+=+=+=+=+=+=+ +# +# f_list = [ i.name for i in ( f_backup_log, f_backup_err, f_restore_log, f_restore_err, f_validate_log, f_validate_err, f_fblog_before, f_fblog_after, f_diff_txt ) ] +# f_list += [ tmpfdb, tmpfbk ] +# cleanup( f_list ) +# +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + + VALIDATION STARTED + + VALIDATION FINISHED: 0 ERRORS, 0 WARNINGS, 0 FIXED + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_5808_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5823.py b/tests/bugs/test_core_5823.py new file mode 100644 index 00000000..d758f85b --- /dev/null +++ b/tests/bugs/test_core_5823.py @@ -0,0 +1,99 @@ +#coding:utf-8 +# +# id: bugs.core_5823 +# title: No permission for SELECT access to blob field in stored procedure +# decription: +# Confirmed bug on 3.0.4.33034 +# Checked on: 3.0.4.33053, 4.0.0.1249: OK +# +# tracker_id: CORE-5823 +# min_versions: ['3.0.5'] +# versions: 3.0.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [('BLOB_FIELD_ID.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter user tmp$c5823 password '123'; + commit; + set term ^; + execute block as + begin + execute statement 'drop role blob_viewer'; + when any do begin end + end + ^ + set term ;^ + commit; + create role blob_viewer; + + create or alter procedure test_proc (id integer) as begin end; + commit; + + recreate table test ( + id integer, + blb blob + ); + commit; + + insert into test (id, blb) values (1, 'blob1'); + commit; + + set term ^; + create or alter procedure test_proc (id integer) returns (blb blob) as + begin + for + select blb from test where id = :id + into blb + do suspend; + end + ^ + set term ;^ + commit; + + grant select on test to procedure test_proc; + grant execute on procedure test_proc to blob_viewer; + grant blob_viewer to tmp$c5823; + commit; + + connect '$(DSN)' user 'tmp$c5823' password '123' role 'blob_viewer'; + + set list on; + set blob on; + select mon$user, mon$role from mon$attachments where mon$attachment_id = current_connection; + + select blb as blob_field_id from test_proc(1); + commit; + + -- cleanup: + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + drop user tmp$c5823; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + + MON$USER TMP$C5823 + MON$ROLE BLOB_VIEWER + BLOB_FIELD_ID 80:0 + blob1 + """ + +@pytest.mark.version('>=3.0.5') +def test_core_5823_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5827.py b/tests/bugs/test_core_5827.py new file mode 100644 index 00000000..85c1e064 --- /dev/null +++ b/tests/bugs/test_core_5827.py @@ -0,0 +1,100 @@ +#coding:utf-8 +# +# id: bugs.core_5827 +# title: ALTER CURRENT USER fails with "no permission for <...> TABLE PLG$SRP" if current user: 1) has NO admin role and 2) wants to modify his own TAGS list +# decription: +# ::: NB ::: +# Code of this test must to be changed after ticket will be fixed! +# See line with 'grant admin role' -- it must me COMMENTED. +# Also, min_version should be set to 3.0.x rather than 4.0.0 +# +# Currently we check only ability to change TAGS list using 'ALTER CURRENT USER' statement. +# See also test for CORE-3365, but it checks only 'old' attributes which existed before FB 3.0. +# +# tracker_id: CORE-5827 +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set list on; + + set term ^; + execute block as + begin + begin + execute statement 'drop user tmp$c5827 using plugin Srp' with autonomous transaction; + when any do begin end + end + end^ + set term ;^ + commit; + + --set echo on; + + create user tmp$c5827 + password 'UseSrp' + firstname 'Mary' + + -- NB: no error will be raised if we UNCOMMENT this line; IMO this is bug, see ticket issue; + -- TODO: comment must be here, put it later when this ticket issue will be fixed. + grant admin role + + using plugin Srp + tags ( + key1 = 'val111' + ,key2 = 'val222' + ,key3 = 'val333' + ) + ; + commit; + + connect '$(DSN)' user tmp$c5827 password 'UseSrp'; + + --- passed w/o error: + alter current user + set password 'FooSrp' firstname 'Scott' lastname 'Tiger' + using plugin Srp + ; + commit; + + -- DOES raise error if current user has no admin role: + alter current user + using plugin Srp + tags ( + Foo = 'Bar' + ,key1 = 'val11' + ,Rio = '1565' + ,drop key3 + ,drop key2 + ) + ; + commit; + + -- cleanup: + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + drop user tmp$c5827 using plugin Srp; + commit; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=4.0') +def test_core_5827_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_5831.py b/tests/bugs/test_core_5831.py new file mode 100644 index 00000000..82da038e --- /dev/null +++ b/tests/bugs/test_core_5831.py @@ -0,0 +1,167 @@ +#coding:utf-8 +# +# id: bugs.core_5831 +# title: Not user friendly output of gstat at encrypted database +# decription: +# We create new database ('tmp_core_5831.fdb') and try to encrypt it usng IBSurgeon Demo Encryption package +# ( https://ib-aid.com/download-demo-firebird-encryption-plugin/ ; https://ib-aid.com/download/crypt/CryptTest.zip ) +# License file plugins\\dbcrypt.conf with unlimited expiration was provided by IBSurgeon to Firebird Foundation (FF). +# This file was preliminary stored in FF Test machine. +# Test assumes that this file and all neccessary libraries already were stored into FB_HOME and %FB_HOME%\\plugins. +# +# Anyone who wants to run this test on his own machine must +# 1) download https://ib-aid.com/download/crypt/CryptTest.zip AND +# 2) PURCHASE LICENSE and get from IBSurgeon file plugins\\dbcrypt.conf with apropriate expiration date and other info. +# +# ################################################ ! ! ! N O T E ! ! ! ############################################## +# FF tests storage (aka "fbt-repo") does not (and will not) contain any license file for IBSurgeon Demo Encryption package! +# ######################################################################################################################### +# +# After test database will be created, we try to encrypt it using 'alter database encrypt with ...' command +# (where = dbcrypt - name of .dll in FB_HOME\\plugins\\ folder that implements encryption). +# Then we allow engine to complete this job - take delay about 1..2 seconds BEFORE detach from database. +# +# After this we detach from DB, run 'gstat -h' and filter its attributes and messages from 'Variable header' section. +# In the output of gstat we check that its 'tail' will look like this: +# === +# Attributes force write, encrypted, plugin DBCRYPT +# Crypt checksum: MUB2NTJqchh9RshmP6xFAiIc2iI= +# Key hash: ask88tfWbinvC6b1JvS9Mfuh47c= +# Encryption key name: RED +# === +# (concrete values for checksum and hash will be ignored - see 'substitutions' section). +# +# Finally, we change this temp DB statee to full shutdown in order to have 100% ability to drop this file. +# +# Checked on: +# 40sS, build 4.0.0.1487: OK, 3.347s. +# 40Cs, build 4.0.0.1487: OK, 3.506s. +# 30sS, build 3.0.5.33120: OK, 2.697s. +# 30Cs, build 3.0.5.33120: OK, 3.054s. +# +# === NOTE-1 === +# In case of "Crypt plugin DBCRYPT failed to load/607/335544351" check that all +# needed files from IBSurgeon Demo Encryption package exist in %FB_HOME% and %FB_HOME%\\plugins +# %FB_HOME%: +# 283136 fbcrypt.dll +# 2905600 libcrypto-1_1-x64.dll +# 481792 libssl-1_1-x64.dll +# +# %FB_HOME%\\plugins: +# 297984 dbcrypt.dll +# 306176 keyholder.dll +# 108 DbCrypt.conf +# 856 keyholder.conf +# +# === NOTE-2 === +# Version of DbCrypt.dll of october-2018 must be replaced because it has hard-coded +# date of expiration rather than reading it from DbCrypt.conf !! +# +# +# tracker_id: CORE-5831 +# min_versions: ['3.0.4'] +# versions: 3.0.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [('CRYPT CHECKSUM.*', 'CRYPT CHECKSUM'), ('KEY HASH.*', 'KEY HASH')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import time +# import subprocess +# import re +# import fdb +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.close() +# +# tmpfdb='$(DATABASE_LOCATION)'+'tmp_core_5831.fdb' +# +# if os.path.isfile( tmpfdb ): +# os.remove( tmpfdb ) +# +# con = fdb.create_database( dsn = 'localhost:'+tmpfdb ) +# con.close() +# con=fdb.connect( dsn = 'localhost:'+tmpfdb ) +# cur = con.cursor() +# cur.execute('alter database encrypt with dbcrypt key Red') +# con.commit() +# +# time.sleep(1) +# # ^ +# # +-------- !! ALLOW BACKGROUND ENCRYPTION PROCESS TO COMPLETE ITS JOB !! +# +# con.close() +# +# f_gstat_log = open( os.path.join(context['temp_directory'],'tmp_shut_5831.log'), 'w') +# f_gstat_err = open( os.path.join(context['temp_directory'],'tmp_shut_5831.err'), 'w') +# +# subprocess.call( [ "gstat", "-h", tmpfdb], +# stdout = f_gstat_log, +# stderr = f_gstat_err +# ) +# +# subprocess.call( [ "gfix", 'localhost:'+tmpfdb, "-shut", "full", "-force", "0" ], +# stdout = f_gstat_log, +# stderr = f_gstat_err +# ) +# +# f_gstat_log.close() +# f_gstat_err.close() +# +# allowed_patterns = ( +# re.compile( '\\s*Attributes\\.*', re.IGNORECASE) +# ,re.compile('crypt\\s+checksum:\\s+\\S+', re.IGNORECASE) +# ,re.compile('key\\s+hash:\\s+\\S+', re.IGNORECASE) +# ,re.compile('encryption\\s+key\\s+name:\\s+\\S+', re.IGNORECASE) +# ) +# +# with open( f_gstat_log.name,'r') as f: +# for line in f: +# match2some = filter( None, [ p.search(line) for p in allowed_patterns ] ) +# if match2some: +# print( (' '.join( line.split()).upper() ) ) +# +# with open( f_gstat_err.name,'r') as f: +# for line in f: +# print("Unexpected STDERR: "+line) +# +# f_list=(f_gstat_log, f_gstat_err) +# for i in range(len(f_list)): +# if os.path.isfile(f_list[i].name): +# os.remove(f_list[i].name) +# +# if os.path.isfile( tmpfdb ): +# os.remove( tmpfdb ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ATTRIBUTES FORCE WRITE, ENCRYPTED, PLUGIN DBCRYPT + CRYPT CHECKSUM: MUB2NTJQCHH9RSHMP6XFAIIC2II= + KEY HASH: ASK88TFWBINVC6B1JVS9MFUH47C= + ENCRYPTION KEY NAME: RED + """ + +@pytest.mark.version('>=3.0.4') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_5831_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5833.py b/tests/bugs/test_core_5833.py new file mode 100644 index 00000000..2eb97982 --- /dev/null +++ b/tests/bugs/test_core_5833.py @@ -0,0 +1,229 @@ +#coding:utf-8 +# +# id: bugs.core_5833 +# title: Server crashes on preparing empty query when trace is enabled +# decription: +# We create DDL triggers for all cases that are enumerated in $FB_HOME/doc/sql.extensions/README.ddl_triggers.txt. +# Then query to RDB$TRIGGERS table is applied to database and its results are stored in . +# After this we do backup and restore to new file, again apply query to RDB$TRIGGERS and store results to . +# Finally we compare and but exclude from comparison lines which starts with to 'BLOB_ID' +# (these are "prefixes" for RDB$TRIGGER_BLR and RDB$TRIGGER_SOURCE). +# Difference should be empty. +# +# Confirmed bug on WI-T4.0.0.977 and WI-V3.0.4.32972. +# Works fine on: +# 30SS, build 3.0.4.32980: OK, 4.656s. +# 40SS, build 4.0.0.993: OK, 6.531s. +# +# tracker_id: CORE-5833 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import re +# import subprocess +# import time +# import difflib +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# ddl_list = ''.join( +# ( +# 'CREATE TABLE,ALTER TABLE,DROP TABLE,CREATE PROCEDURE,ALTER PROCEDURE,DROP PROCEDURE' +# , ',CREATE FUNCTION,ALTER FUNCTION,DROP FUNCTION,CREATE TRIGGER,ALTER TRIGGER,DROP TRIGGER' +# , ',CREATE EXCEPTION,ALTER EXCEPTION,DROP EXCEPTION,CREATE VIEW,ALTER VIEW,DROP VIEW' +# , ',CREATE DOMAIN,ALTER DOMAIN,DROP DOMAIN,CREATE ROLE,ALTER ROLE,DROP ROLE' +# , ',CREATE SEQUENCE,ALTER SEQUENCE,DROP SEQUENCE,CREATE USER,ALTER USER,DROP USER' +# , ',CREATE INDEX,ALTER INDEX,DROP INDEX,CREATE COLLATION,DROP COLLATION,ALTER CHARACTER SET' +# , ',CREATE PACKAGE,ALTER PACKAGE,DROP PACKAGE,CREATE PACKAGE BODY,DROP PACKAGE BODY' +# ) +# ) +# #ddl_list = 'CREATE TABLE,ALTER TABLE,DROP TABLE,CREATE PROCEDURE,ALTER PROCEDURE,DROP PROCEDURE' +# #ddl_list += ',CREATE FUNCTION,ALTER FUNCTION,DROP FUNCTION,CREATE TRIGGER,ALTER TRIGGER,DROP TRIGGER' +# #ddl_list += ',CREATE EXCEPTION,ALTER EXCEPTION,DROP EXCEPTION,CREATE VIEW,ALTER VIEW,DROP VIEW' +# #ddl_list += ',CREATE DOMAIN,ALTER DOMAIN,DROP DOMAIN,CREATE ROLE,ALTER ROLE,DROP ROLE' +# #ddl_list += ',CREATE SEQUENCE,ALTER SEQUENCE,DROP SEQUENCE,CREATE USER,ALTER USER,DROP USER' +# #ddl_list += ',CREATE INDEX,ALTER INDEX,DROP INDEX,CREATE COLLATION,DROP COLLATION,ALTER CHARACTER SET' +# #ddl_list += ',CREATE PACKAGE,ALTER PACKAGE,DROP PACKAGE,CREATE PACKAGE BODY,DROP PACKAGE BODY' +# +# +# # Initial DDL: create all triggers +# ################################## +# f_ddl_sql=open( os.path.join(context['temp_directory'],'tmp_ddl_triggers_5833.sql'), 'w') +# f_ddl_sql.write('set bail on;\\n') +# f_ddl_sql.write('set term ^;\\n') +# +# for i in ddl_list.split(','): +# for k in (1,2): +# evt_time='before' if k==1 else 'after' +# f_ddl_sql.write( 'recreate trigger trg_' + evt_time + '_' + i.replace(' ','_').lower() + ' active '+evt_time+' ' + i.lower()+ ' as \\n' ) +# f_ddl_sql.write( ' declare c rdb$field_name;\\n' ) +# f_ddl_sql.write( 'begin\\n' ) +# f_ddl_sql.write( " c = rdb$get_context('DDL_TRIGGER', 'OBJECT_NAME');\\n" ) +# f_ddl_sql.write( 'end\\n^' ) +# f_ddl_sql.write( '\\n' ) +# +# +# f_ddl_sql.write('set term ;^\\n') +# f_ddl_sql.write('commit;\\n') +# flush_and_close( f_ddl_sql ) +# +# runProgram('isql', [dsn, '-i', f_ddl_sql.name] ) +# +# # Prepare check query: +# ###################### +# sql_text=''' set blob all; +# set list on; +# set count on; +# select rdb$trigger_name, rdb$trigger_type, rdb$trigger_source as blob_id_for_trg_source, rdb$trigger_blr as blob_id_for_trg_blr +# from rdb$triggers +# where rdb$system_flag is distinct from 1 +# order by 1; +# ''' +# +# f_chk_sql=open( os.path.join(context['temp_directory'],'tmp_check_trg_5833.sql'), 'w') +# f_chk_sql.write( sql_text ) +# flush_and_close( f_chk_sql ) +# +# # Query RDB$TRIGGERS before b/r: +# ################################ +# +# f_xmeta1_log = open( os.path.join(context['temp_directory'],'tmp_xmeta1_5833.log'), 'w') +# f_xmeta1_err = open( os.path.join(context['temp_directory'],'tmp_xmeta1_5833.err'), 'w') +# +# # Add to log result of query to rdb$triggers table: +# subprocess.call( [context['isql_path'], dsn, "-i", f_chk_sql.name], +# stdout = f_xmeta1_log, +# stderr = f_xmeta1_err +# ) +# +# flush_and_close( f_xmeta1_log ) +# flush_and_close( f_xmeta1_err ) +# +# # Do backup and restore into temp file: +# ####################################### +# tmp_bkup=os.path.join(context['temp_directory'],'tmp_backup_5833.fbk') +# tmp_rest=os.path.join(context['temp_directory'],'tmp_restored_5833.fdb') +# if os.path.isfile(tmp_rest): +# os.remove(tmp_rest) +# +# runProgram('gbak', ['-b', dsn, tmp_bkup ] ) +# runProgram('gbak', ['-c', tmp_bkup, 'localhost:'+tmp_rest ] ) +# +# +# # Query RDB$TRIGGERS after b/r: +# ############################### +# +# f_xmeta2_log = open( os.path.join(context['temp_directory'],'tmp_xmeta2_5833.log'), 'w') +# f_xmeta2_err = open( os.path.join(context['temp_directory'],'tmp_xmeta2_5833.err'), 'w') +# +# subprocess.call( [context['isql_path'], 'localhost:'+tmp_rest, "-i", f_chk_sql.name], +# stdout = f_xmeta2_log, +# stderr = f_xmeta2_err +# ) +# +# flush_and_close( f_xmeta2_log ) +# flush_and_close( f_xmeta2_err ) +# +# # Every STDERR log should be EMPTY: +# ################################### +# +# f_list = ( f_xmeta1_err, f_xmeta2_err ) +# for i in range(len(f_list)): +# f_name=f_list[i].name +# if os.path.getsize(f_name) > 0: +# with open( f_name,'r') as f: +# for line in f: +# print("Unexpected STDERR, file "+f_name+": "+line) +# +# +# # DIFFERENCE between f_xmeta1_log and f_xmeta2_log should be EMPTY: +# #################### +# +# old_rdb_triggers_data=open(f_xmeta1_log.name, 'r') +# new_rdb_triggers_data=open(f_xmeta2_log.name, 'r') +# +# # NB: we should EXCLUDE from comparison lines which about to BLOB IDs for records: +# # ~~~~~~~~~~~~~~~~~~~~~ +# +# difftext = ''.join(difflib.unified_diff( +# [ line for line in old_rdb_triggers_data.readlines() if not line.startswith('BLOB_ID_FOR_TRG') ], +# [ line for line in new_rdb_triggers_data.readlines() if not line.startswith('BLOB_ID_FOR_TRG') ] +# )) +# old_rdb_triggers_data.close() +# new_rdb_triggers_data.close() +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_5833_metadata_diff.txt'), 'w') +# f_diff_txt.write(difftext) +# flush_and_close( f_diff_txt ) +# +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# print("Unexpected DIFF in metadata: "+line) +# +# # CLEANUP +# ######### +# time.sleep(1) +# cleanup( (f_ddl_sql, f_chk_sql, f_xmeta1_log, f_xmeta1_err, f_xmeta2_log, f_xmeta2_err, f_diff_txt, tmp_bkup, tmp_rest) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_5833_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5837.py b/tests/bugs/test_core_5837.py new file mode 100644 index 00000000..96618322 --- /dev/null +++ b/tests/bugs/test_core_5837.py @@ -0,0 +1,92 @@ +#coding:utf-8 +# +# id: bugs.core_5837 +# title: Inconsistent results when working with GLOBAL TEMPORARY TABLE ON COMMIT PRESERVE ROWS +# decription: +# Samples were provided by Vlad, privately. +# Confirmed bug on 3.0.4.32972, 4.0.0.955; SUPERSERVER only (see also note in the ticket) +# Works fine on: +# 3.0.4.32985, 4.0.0.1000 +# +# tracker_id: CORE-5837 +# min_versions: ['3.0.3'] +# versions: 3.0.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate global temporary table gtt(id int) on commit preserve rows; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# con1=fdb.connect( dsn = dsn ) +# con2=fdb.connect( dsn = dsn ) +# +# cur2=con2.cursor() +# +# # Following 'select count' is MANDATORY for reproduce: +# ####################################### +# cur2.execute('select count(*) from gtt'); +# for r in cur2: +# pass +# +# cur1=con1.cursor() +# cur1.execute('insert into gtt(id) values( ? )', (1,) ) +# cur1.execute('insert into gtt(id) values( ? )', (1,) ) +# +# cur2.execute('insert into gtt(id) values( ? )', (2,) ) +# +# con1.rollback() +# +# +# cur2.execute('insert into gtt(id) select 2 from rdb$types rows 200', (2,) ) +# con2.commit() +# +# cur1.execute('insert into gtt(id) values( ? )', (11,) ) +# cur1.execute('insert into gtt(id) values( ? )', (11,) ) +# +# print('con1.rollback: point before.') +# con1.rollback() +# print('con1.rollback: point after.') +# +# +# con1.close() +# con2.close() +# print('sample-2 finished OK.') +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + con1.rollback: point before. + con1.rollback: point after. + sample-2 finished OK. + """ + +@pytest.mark.version('>=3.0.3') +@pytest.mark.xfail +def test_core_5837_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5840.py b/tests/bugs/test_core_5840.py new file mode 100644 index 00000000..fb023963 --- /dev/null +++ b/tests/bugs/test_core_5840.py @@ -0,0 +1,209 @@ +#coding:utf-8 +# +# id: bugs.core_5840 +# title: Ignor of reference privilege +# decription: +# Checked on: +# 4.0.0.1000 SS +# 3.0.4.32985 SS +# +# tracker_id: CORE-5840 +# min_versions: ['3.0.4'] +# versions: 3.0.4, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set wng off; + + create or alter user tmp$c5840 password '123'; + revoke all on all from tmp$c5840; + grant create table to tmp$c5840; + commit; + + create table test1( + id int not null primary key using index test1_pk, + pid int + ); + commit; + + create table test3(id int primary key, pid int, constraint test3_fk foreign key(pid) references test1(id) using index test3_fk); + commit; + + connect '$(DSN)' user 'tmp$c5840' password '123'; + + -- this should FAIL, table must not be created at all: + create table test2( + id int primary key, + pid int, + constraint test2_fk foreign key(pid) references test1(id) using index test2_fk + ); + commit; + + --set echo on; + alter table test3 drop constraint test3_fk; -- this WAS allowed (error!) + commit; + + alter table test1 add constraint test1_fk foreign key(pid) references test1(id) using index test1_fk; + commit; + + alter table test1 drop constraint test1_fk; -- this was prohibited BEFORE this ticket; we only check this again here + commit; + + set echo off; + + set list on; + select rdb$relation_name from rdb$relations where rdb$system_flag is distinct from 1; + commit; + + -- cleanup: + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; -- mandatory! + drop user tmp$c5840; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$RELATION_NAME TEST1 + RDB$RELATION_NAME TEST3 + """ +expected_stderr_1 = """ + 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 + """ + +@pytest.mark.version('>=3.0.4,<4.0') +def test_core_5840_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set wng off; + + create or alter user tmp$c5840 password '123'; + revoke all on all from tmp$c5840; + grant create table to tmp$c5840; + commit; + + create table test1( + id int not null primary key using index test1_pk, + pid int + ); + commit; + + create table test3(id int primary key, pid int, constraint test3_fk foreign key(pid) references test1(id) using index test3_fk); + commit; + + connect '$(DSN)' user 'tmp$c5840' password '123'; + + -- this should FAIL, table must not be created at all: + create table test2( + id int primary key, + pid int, + constraint test2_fk foreign key(pid) references test1(id) using index test2_fk + ); + commit; + + --set echo on; + alter table test3 drop constraint test3_fk; -- this WAS allowed (error!) + commit; + + alter table test1 add constraint test1_fk foreign key(pid) references test1(id) using index test1_fk; + commit; + + alter table test1 drop constraint test1_fk; -- this was prohibited BEFORE this ticket; we only check this again here + commit; + + set echo off; + + set list on; + select rdb$relation_name from rdb$relations where rdb$system_flag is distinct from 1; + commit; + + -- cleanup: + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; -- mandatory! + drop user tmp$c5840; + commit; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + RDB$RELATION_NAME TEST1 + RDB$RELATION_NAME TEST3 + """ +expected_stderr_2 = """ + 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 + """ + +@pytest.mark.version('>=4.0') +def test_core_5840_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_expected_stderr == act_2.clean_stderr + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/bugs/test_core_5841.py b/tests/bugs/test_core_5841.py new file mode 100644 index 00000000..f71ea16a --- /dev/null +++ b/tests/bugs/test_core_5841.py @@ -0,0 +1,99 @@ +#coding:utf-8 +# +# id: bugs.core_5841 +# title: No permission for SELECT access to BLOB field if a TABLE is accessed using VIEW +# decription: +# Confirmed bug on 3.0.4.32985 +# Checked on both Srp and Legacy_Auth, builds: +# 3.0.4.33053: OK, 4.125s. +# 4.0.0.1224: OK, 4.203s. +# +# tracker_id: CORE-5841 +# min_versions: ['3.0'] +# versions: 3.0.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [('BLOB_FLD.*', 'BLOB_FLD')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set list on; + set blob all; + + create or alter user tmp$c5841 password '123'; + commit; + + create table test ( + name_fld varchar(64), + blob_fld blob, + bool_fld boolean, + primary key (name_fld) + ); + + create view v_test as + select + name_fld, + blob_fld, + bool_fld + from test + ; + + grant select on test to view v_test; + grant select on v_test to public; + commit; + + insert into test ( + name_fld, + blob_fld, + bool_fld) + values ( + upper('tmp$c5841'), + lpad('', 70, 'qwerty'), + true + ); + + commit; + + connect '$(DSN)' user tmp$c5841 password '123'; + + set bail off; + set count on; + select + name_fld + ,blob_fld -- content of this blob field was inaccessible before bug fix + ,bool_fld + from v_test + ; + rollback; + + connect '$(DSN)' user sysdba password 'masterkey'; + drop user tmp$c5841 ; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + NAME_FLD TMP$C5841 + BLOB_FLD 80:0 + qwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwertyqwer + BOOL_FLD + Records affected: 1 + """ + +@pytest.mark.version('>=3.0.4') +def test_core_5841_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5843.py b/tests/bugs/test_core_5843.py new file mode 100644 index 00000000..d2337a3f --- /dev/null +++ b/tests/bugs/test_core_5843.py @@ -0,0 +1,208 @@ +#coding:utf-8 +# +# id: bugs.core_5843 +# title: Wrong handling of failures of TRANSACTION START trigger +# decription: +# Confirmed wrong behaviour on 3.0.4.32972, 4.0.0.955. +# Works fine on: +# FB30SS, build 3.0.4.32988: OK, 1.328s. +# FB40SS, build 4.0.0.1008: OK, 1.500s +# (checked both on SS and CS). +# +# tracker_id: CORE-5843 +# min_versions: ['3.0.4'] +# versions: 3.0.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [('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_1 = """ + --set echo on; + set bail on; + create or alter trigger tx_rollback on transaction rollback as begin end; + create or alter trigger tx_start on transaction start as begin end; + create or alter trigger tx_commit on transaction commit as begin end; + + create or alter view v_mon as + select + t.mon$transaction_id as tx_id + ,t.mon$state as tx_state + --,a.mon$remote_process att_process + --,a.mon$attachment_name as att_name + --,a.mon$system_flag as att_sysflag + --,a.mon$user as att_user + from mon$transactions t + join mon$attachments a using (mon$attachment_id) + where mon$attachment_id = current_connection + ; + commit; + + set term ^; + + create or alter exception ex_tra_start 'transaction @1 aborted' + ^ + + create or alter procedure tx_trig_log(msg varchar(255)) + as + declare s varchar(255); + begin + s = rdb$get_context('USER_SESSION', 'tx_trig_log'); + if (s <> '') then + begin + s = s || ASCII_CHAR(10) || trim(msg) || ', current tx=' || current_transaction; + rdb$set_context('USER_SESSION', 'tx_trig_log', :s); + end + end + ^ + + create or alter trigger tx_start on transaction start as + declare s varchar(255); + begin + execute procedure tx_trig_log('trigger on transaction start '); + + if (rdb$get_context('USER_SESSION', 'tx_abort') = 1) then + begin + execute procedure tx_trig_log('exception on tx start '); + rdb$set_context('USER_SESSION', 'tx_abort', 0); + exception ex_tra_start using (current_transaction); + end + end + ^ + + create or alter trigger tx_commit on transaction commit as + declare s varchar(255); + begin + execute procedure tx_trig_log('trigger on commit'); + end + ^ + + create or alter trigger tx_rollback on transaction rollback as + declare s varchar(255); + begin + execute procedure tx_trig_log('trigger on rollback'); + end + ^ + + create or alter procedure sp_use_atx as + begin + rdb$set_context('USER_SESSION', 'tx_abort', 1); + execute procedure tx_trig_log('sp_use_atx, point_a'); + in autonomous transaction do + execute procedure tx_trig_log('sp_use_atx, point_b'); + end + ^ + set term ;^ + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set autoddl off; + set list on; + commit; + + select 'test_1, point-1' as msg, v.* from rdb$database cross join v_mon v; + + set term ^; + execute block as + declare c int; + begin + c = rdb$set_context('USER_SESSION', 'tx_abort', 1); -- flag to raise error on next tx start + end + ^ + set term ^; + commit; + + select 'test_1, point-2' as msg, v.* from rdb$database cross join v_mon v; -- it start transaction + commit; + + set count on; + select 'test_1, point-3' as msg, v.* from rdb$database cross join v_mon v; + set count off; + rollback; + + ------------------------------------------------------------- + + --connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + + set term ^; + execute block as + declare c int; + begin + c = rdb$set_context('USER_SESSION', 'tx_trig_log', ascii_char(10) || 'start: tx=' || current_transaction ); -- start logging + end + ^ + set term ^; + commit; + + select 'test2, point-a' as msg, v.* from rdb$database cross join v_mon v; + + execute procedure sp_use_atx; + + /* + Statement failed, SQLSTATE = HY000 + exception 3 + -EX_TRA_START + -transaction 692 aborted + -At trigger 'TX_START' line: 10, col: 5 + At procedure 'sp_use_atx' line: 4, col: 3 + */ + + select rdb$get_context('USER_SESSION', 'tx_trig_log') from rdb$database; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG test_1, point-1 + TX_ID 22 + TX_STATE 1 + + MSG test_1, point-3 + TX_ID 25 + TX_STATE 1 + Records affected: 1 + + MSG test2, point-a + TX_ID 28 + TX_STATE 1 + 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 + + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = HY000 + exception 1 + -EX_TRA_START + -transaction 23 aborted + -At trigger 'TX_START' line + + Statement failed, SQLSTATE = HY000 + exception 1 + -EX_TRA_START + -transaction 29 aborted + -At trigger 'TX_START' line + At procedure 'SP_USE_ATX' line + """ + +@pytest.mark.version('>=3.0.4') +def test_core_5843_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5845.py b/tests/bugs/test_core_5845.py new file mode 100644 index 00000000..1046d8b0 --- /dev/null +++ b/tests/bugs/test_core_5845.py @@ -0,0 +1,88 @@ +#coding:utf-8 +# +# id: bugs.core_5845 +# title: ORDER BY on index can cause suboptimal index choices +# decription: +# Confirmed ineffective plan on: 3.0.4.33053, 4.0.0.1249 +# Works fine on: +# 3.0.5.33084: OK, 1.344s. +# 4.0.0.1340: OK, 2.594s. +# +# tracker_id: CORE-5845 +# min_versions: ['3.0.4'] +# versions: 3.0.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test + ( + id1 integer, + id2 integer, + id3 integer, + x numeric(18,2), + constraint pk_test primary key(id1, id2, id3) + ); + create index ixa_test__x on test(x); + create index ixa_test__id1_x on test(id1, x); + commit; + -------------------------------------------------------------------------------- + + set plan on; + + select * + from test t + where t.id1=1 and t.x>0 + ; + --plan (t index (ixa_test__id1_x)) + --index ixa_test__id1_x is used + + -------------------------------------------------------------------------------- + + select * from test t + where t.id1=1 and t.x>0 + order by t.id1, t.id2, t.id3 + ; + --plan (t order pk_test index (ixa_test__x)) + --index ixa_test__x - suboptimal + --as you can see adding order by which consume some index (pk_test) + --cause suboptimal choice of index (ixa_test__x) + + -------------------------------------------------------------------------------- + + --if query is changed to order by not by index + --plan sort (t index (ixa_test__id1_x)) + + select * from test t + where + t.id1=1 + and t.x>0 + order by t.id1+0, t.id2, t.id3 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (T INDEX (IXA_TEST__ID1_X)) + PLAN SORT (T INDEX (IXA_TEST__ID1_X)) + PLAN SORT (T INDEX (IXA_TEST__ID1_X)) + """ + +@pytest.mark.version('>=3.0.4') +def test_core_5845_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5846.py b/tests/bugs/test_core_5846.py new file mode 100644 index 00000000..edef76ca --- /dev/null +++ b/tests/bugs/test_core_5846.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: bugs.core_5846 +# title: CREATE VIEW issues "Implementation of text subtype 512 not located" +# decription: +# Works fine on: +# 3.0.4.32995: OK, 1.047s. +# 4.0.0.1028: OK, 1.391s. +# +# tracker_id: CORE-5846 +# min_versions: ['3.0.4'] +# versions: 3.0.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + alter character set utf8 set default collation unicode; + create table table1( fld1 char(1) character set none ); + + -- NB: 'expected_stderr' must remain empty as result of following command. + create view view1 as + select fld1 from table1 + ; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0.4') +def test_core_5846_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_5847.py b/tests/bugs/test_core_5847.py new file mode 100644 index 00000000..6a6d85f7 --- /dev/null +++ b/tests/bugs/test_core_5847.py @@ -0,0 +1,89 @@ +#coding:utf-8 +# +# id: bugs.core_5847 +# title: "Malformed string" instead of key value in PK violation error message +# decription: +# Confirmed bug on: 3.0.4.32972, 4.0.0.955. +# Works fine on: +# FB25SC, build 2.5.9.27112: OK, 1.187s. +# FB30SS, build 3.0.4.32992: OK, 1.485s. +# FB40SS, build 4.0.0.1023: OK, 1.500s. +# +# tracker_id: CORE-5847 +# min_versions: ['2.5.9'] +# versions: 2.5.9 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.9 +# resources: None + +substitutions_1 = [('Problematic key value is .*', 'Problematic key value is')] + +init_script_1 = """ + recreate table test( + uid char(16) character set octets, + constraint test_uid_pk primary key(uid) using index test_uid_pk + ); + commit; + insert into test values( gen_uuid() ); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.close() +# +# con1 = fdb.connect(dsn = dsn, charset = 'utf8') +# con2 = fdb.connect(dsn = dsn) +# +# sql_cmd='insert into test(uid) select uid from test rows 1' +# cur1=con1.cursor() +# cur2=con2.cursor() +# for i in(1,2,): +# c = cur1 if i==1 else cur2 +# try: +# c.execute(sql_cmd) +# except Exception, e: +# for k,x in enumerate(e): +# print(i,' ',k,':',x) +# i+=1 +# +# con1.close() +# con2.close() +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 1 0 : Error while executing SQL statement: + - SQLCODE: -803 + - violation of PRIMARY or UNIQUE KEY constraint "TEST_UID_PK" on table "TEST" + - Problematic key value is ("UID" = x'AA70F788EB634073AD328C284F775A3E') + 1 1 : -803 + 1 2 : 335544665 + + 2 0 : Error while executing SQL statement: + - SQLCODE: -803 + - violation of PRIMARY or UNIQUE KEY constraint "TEST_UID_PK" on table "TEST" + - Problematic key value is ("UID" = x'AA70F788EB634073AD328C284F775A3E') + 2 1 : -803 + 2 2 : 335544665 + """ + +@pytest.mark.version('>=2.5.9') +@pytest.mark.xfail +def test_core_5847_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5852.py b/tests/bugs/test_core_5852.py new file mode 100644 index 00000000..be74fc33 --- /dev/null +++ b/tests/bugs/test_core_5852.py @@ -0,0 +1,101 @@ +#coding:utf-8 +# +# id: bugs.core_5852 +# title: There is no check of existance generator and exception when privileges are granted +# decription: +# Confirmed absenceof check on: 3.0.4.32995, 4.0.0.1028 +# Checked on: 3.0.4.32997: OK, 1.110s. +# +# tracker_id: CORE-5852 +# min_versions: ['3.0.4'] +# versions: 3.0.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate view v_grants as + select + p.rdb$user_type as usr_type + ,p.rdb$user as usr_name + ,p.rdb$grantor as who_gave + ,p.rdb$privilege as what_can + ,p.rdb$grant_option as has_grant + ,p.rdb$object_type as obj_type + ,p.rdb$relation_name as rel_name + ,p.rdb$field_name as fld_name + from rdb$database r left join rdb$user_privileges p on 1=1 + where p.rdb$user in( upper('tmp$c5852') ) + order by 1,2,3,4,5,6,7,8 + ; + + create or alter user tmp$c5852 password '123'; + commit; + + grant usage on exception no_such_exc to user tmp$c5852; + grant usage on generator no_such_gen to user tmp$c5852; + grant usage on sequence no_such_seq to user tmp$c5852; + + --grant execute on procedure no_such_proc to user tmp$c5852; + --grant execute on function no_such_func to user tmp$c5852; + --grant execute on package no_such_pkg to user tmp$c5852; + + commit; + + set list on; + set count on; + + select + usr_type + ,usr_name + ,what_can + ,has_grant + ,obj_type + ,rel_name + from v_grants; + commit; + + drop user tmp$c5852; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ +expected_stderr_1 = """ + 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 + """ + +@pytest.mark.version('>=3.0.4') +def test_core_5852_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5853.py b/tests/bugs/test_core_5853.py new file mode 100644 index 00000000..0396c6d8 --- /dev/null +++ b/tests/bugs/test_core_5853.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_5853 +# title: Forward-compatible expressions LOCALTIME and LOCALTIMESTAMP +# decription: +# 2.5.9.27115: OK, 0.375s. +# 3.0.4.33019: OK, 0.937s. +# ::: NOTE ::: +# Test for 4.0 currently is EXCLUDED because changes not yet merged in master. +# +# tracker_id: CORE-5853 +# min_versions: ['2.5.9'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set planonly; + select current_time, current_timestamp from rdb$database; + --select localtime from rdb$database; + --select localtimestamp from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (RDB$DATABASE NATURAL) + """ + +@pytest.mark.version('>=4.0') +def test_core_5853_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5854.py b/tests/bugs/test_core_5854.py new file mode 100644 index 00000000..14723ec0 --- /dev/null +++ b/tests/bugs/test_core_5854.py @@ -0,0 +1,79 @@ +#coding:utf-8 +# +# id: bugs.core_5854 +# title: Very poor "similar to" performance +# decription: +# Confirmed normal work (evaluation for less than 10 ms) on WI-T4.0.0.1598. +# Quantifier value was increased to 1000, string 'abcd.abc' is used for pattern search. +# +# ::: NOTE ::: +# doc\\sql.extensions\\README.similar_to.txt: +# Since FB 4 the repeat factor low/high values could not be greater than 1000. +# +# tracker_id: CORE-5854 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + + set term ^; + execute block as + begin + rdb$set_context( 'USER_SESSION','DTS_START', cast('now' as timestamp) ); + rdb$set_context( 'USER_SESSION','MAX_THRESHOLD_MS', 100 ); + -- ^ + -- | + -- ############################# + -- MAX ALLOWED EXECUTION TIME,MS + -- ############################# + end + ^ + set term ;^ + + select iif ('abcd.abc' similar to '[[:ALPHA:].]{1,1000}.ab' ,1,0) result + from rdb$database + ; + + set count off; + select + iif( evaluated_ms <= max_allowed_ms + ,'acceptable' + ,'TOO LONG: ' || evaluated_ms || ' ms - this is more then threshold = ' || max_allowed_ms || ' ms' + ) as duration + from ( + select + datediff( millisecond from cast(rdb$get_context( 'USER_SESSION','DTS_START') as timestamp) to current_timestamp ) evaluated_ms + ,cast( rdb$get_context( 'USER_SESSION','MAX_THRESHOLD_MS' ) as int ) as max_allowed_ms + from rdb$database + ); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT 0 + Records affected: 1 + DURATION acceptable + """ + +@pytest.mark.version('>=4.0') +def test_core_5854_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5855.py b/tests/bugs/test_core_5855.py new file mode 100644 index 00000000..e928957c --- /dev/null +++ b/tests/bugs/test_core_5855.py @@ -0,0 +1,180 @@ +#coding:utf-8 +# +# id: bugs.core_5855 +# title: Latest builds of Firebird 4.0 cannot backup DB with generators which contains space in the names +# decription: +# Confirmed bug on 4.0.0.1036, got in STDERR: +# Dynamic SQL Error +# -SQL error code = -104 +# -Token unknown - line 1, column 28 +# -sequence +# No error on 4.0.0.1040. +# Decided to apply test also against Firebird 3.x +# ::: NB::: +# As of nowadays, it is still possible to create sequence with name = single space character. +# See note in ticket, 26/Jun/18 07:58 AM. +# +# tracker_id: CORE-5855 +# min_versions: ['3.0.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('BLOB_ID.*', '')] + +init_script_1 = """ + create sequence "new sequence" start with 123 increment by -456; + commit; + comment on sequence "new sequence" is 'foo rio bar'; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# thisdb=db_conn.database_name +# tmpbkp='$(DATABASE_LOCATION)tmp_core_5855.fbk' +# tmpres='$(DATABASE_LOCATION)tmp_core_5855.tmp' +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# fn_bkp_log=open( os.path.join(context['temp_directory'],'tmp_5855_backup.log'), 'w') +# fn_bkp_err=open( os.path.join(context['temp_directory'],'tmp_5855_backup.err'), 'w') +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_backup", "dbname", thisdb, "verbose", "bkp_file", tmpbkp ], +# stdout=fn_bkp_log, stderr=fn_bkp_err) +# flush_and_close( fn_bkp_log ) +# flush_and_close( fn_bkp_err ) +# +# backup_error_flag=0 +# with open(fn_bkp_err.name,'r') as f: +# for line in f: +# backup_error_flag=1 +# print('UNEXPECTED STDERR DURING BACKUP '+fn_bkp_err.name+': '+line) +# +# cleanup( (fn_bkp_err, fn_bkp_log ) ) +# +# if backup_error_flag==0: +# fn_res_log=open( os.path.join(context['temp_directory'],'tmp_5855_restore.log'), 'w') +# fn_res_err=open( os.path.join(context['temp_directory'],'tmp_5855_restore.err'), 'w') +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_restore", "res_replace", "verbose", "bkp_file", tmpbkp, "dbname", tmpres ], +# stdout=fn_res_log, stderr=fn_res_err) +# flush_and_close( fn_res_log ) +# flush_and_close( fn_res_err ) +# +# sql_text=''' +# set list on; +# set blob all; +# set list on; +# select +# rdb$generator_name as seq_name, +# rdb$initial_value as seq_init, +# rdb$generator_increment as seq_incr, +# rdb$description as blob_id +# from rdb$generators +# where rdb$system_flag is distinct from 1; +# ''' +# +# fn_sql_chk=open( os.path.join(context['temp_directory'],'tmp_5855_check.sql'), 'w') +# fn_sql_chk.write(sql_text) +# flush_and_close( fn_sql_chk ) +# +# fn_sql_log=open( os.path.join(context['temp_directory'],'tmp_5855_check.log'), 'w') +# fn_sql_err=open( os.path.join(context['temp_directory'],'tmp_5855_check.err'), 'w') +# subprocess.call( [ context['isql_path'], 'localhost:'+tmpres, "-i", fn_sql_chk.name ], +# stdout=fn_sql_log, stderr=fn_sql_err +# ) +# +# flush_and_close( fn_sql_log ) +# flush_and_close( fn_sql_err ) +# +# for fe in ( fn_res_err, fn_sql_err ): +# with open(fe.name,'r') as f: +# for line in f: +# print('UNEXPECTED STDERR IN '+fe.name+': '+line) +# +# +# with open(fn_res_log.name,'r') as f: +# for line in f: +# # gbak: ERROR: +# if 'ERROR:' in line: +# print('UNEXPECTED ERROR IN '+fg.name+': '+line) +# +# with open(fn_sql_log.name,'r') as f: +# for line in f: +# print(line) +# +# # cleanup: +# ########## +# time.sleep(1) +# cleanup( (fn_res_err, fn_sql_err, fn_res_log, fn_sql_log, fn_sql_chk ) ) +# +# ############################################################# +# +# cleanup( (tmpbkp, tmpres) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + SEQ_NAME new sequence + SEQ_INIT 123 + SEQ_INCR -456 + foo rio bar + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_5855_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5857.py b/tests/bugs/test_core_5857.py new file mode 100644 index 00000000..9a930fc9 --- /dev/null +++ b/tests/bugs/test_core_5857.py @@ -0,0 +1,113 @@ +#coding:utf-8 +# +# id: bugs.core_5857 +# title: Varchar computed column length stores incorrect and invalid values for field +# decription: +# Confirmed wrong output on WI-T4.0.0.1036: +# RDB$FIELD_LENGTH was -2 (instead of 80), RDB$CHARACTER_SET_ID was 0 (instead of 4) +# +# Checked on: WI-V3.0.4.33000, WI-T4.0.0.1040 - ONE of test parts works fine. +# ::: NOTE ::: +# There is still problem with accommodation of resulting string in COMPUITED BY +# column when its declared length ("varchar(20)") is equal to the total of lengths +# of concatenated columns. +# Because of this one of check statements was temp-ly disabled. +# See comment in the ticked 27/Jun/18 05:27 AM. +# +# tracker_id: CORE-5857 +# min_versions: ['3.0.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test ( + id int, + vc_default_user varchar(10) character set utf8 default user, + vc_default_literal varchar(10) character set utf8 default 'Кондуит', + vc_generated varchar(20) computed by (vc_default_user || ' ' || vc_default_literal) + ); + + insert into test values( 1, 'Австралия', 'Антарктида'); + insert into test values( 2, 'Швамбрания', 'Антарктида'); + commit; + + set count on; + set list on; + + select + rf.rdb$field_name + ,ff.rdb$field_length + ,ff.rdb$character_length + ,ff.rdb$character_set_id + ,ff.rdb$collation_id + ,ff.rdb$field_type + ,ff.rdb$field_sub_type + from rdb$relation_fields rf + join rdb$fields ff on rf.rdb$field_source = ff.rdb$field_name + where upper(rf.rdb$relation_name) = upper('test') + order by 1 + ; + + select vc_generated from test where id = 1; + + -- temply disabled: select vc_generated from test where id = 2; + -- Statement failed, SQLSTATE = 22001 + -- arithmetic exception, numeric overflow, or string truncation + -- -string right truncation + -- -expected length 20, actual 21 + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$FIELD_NAME ID + RDB$FIELD_LENGTH 4 + RDB$CHARACTER_LENGTH + RDB$CHARACTER_SET_ID + RDB$COLLATION_ID + RDB$FIELD_TYPE 8 + RDB$FIELD_SUB_TYPE 0 + RDB$FIELD_NAME VC_DEFAULT_LITERAL + RDB$FIELD_LENGTH 40 + RDB$CHARACTER_LENGTH 10 + RDB$CHARACTER_SET_ID 4 + RDB$COLLATION_ID 0 + RDB$FIELD_TYPE 37 + RDB$FIELD_SUB_TYPE 0 + RDB$FIELD_NAME VC_DEFAULT_USER + RDB$FIELD_LENGTH 40 + RDB$CHARACTER_LENGTH 10 + RDB$CHARACTER_SET_ID 4 + RDB$COLLATION_ID 0 + RDB$FIELD_TYPE 37 + RDB$FIELD_SUB_TYPE 0 + RDB$FIELD_NAME VC_GENERATED + RDB$FIELD_LENGTH 80 + RDB$CHARACTER_LENGTH 20 + RDB$CHARACTER_SET_ID 4 + RDB$COLLATION_ID 0 + RDB$FIELD_TYPE 37 + RDB$FIELD_SUB_TYPE 0 + Records affected: 4 + VC_GENERATED Австралия Антарктида + Records affected: 1 + """ + +@pytest.mark.version('>=3.0') +def test_core_5857_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5858.py b/tests/bugs/test_core_5858.py new file mode 100644 index 00000000..2ef96622 --- /dev/null +++ b/tests/bugs/test_core_5858.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: bugs.core_5858 +# title: Command 'REVOKE ALL ON ALL FROM ' lead server to crash +# decription: +# Detected/confirmed bug on 4.0.0.1036. +# Works fine on 4.0.0.1040 +# +# tracker_id: CORE-5858 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set wng off; + set bail on; + revoke all on all from any_name_here; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=4.0') +def test_core_5858_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_5861.py b/tests/bugs/test_core_5861.py new file mode 100644 index 00000000..0edc84b6 --- /dev/null +++ b/tests/bugs/test_core_5861.py @@ -0,0 +1,183 @@ +#coding:utf-8 +# +# id: bugs.core_5861 +# title: GRANT OPTION is not checked for new object +# decription: +# Checked on 4.0.0.1172: OK, 4.485s. +# +# tracker_id: CORE-5861 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set list on; + + create or alter user tmp$c5861_u1 password 'pass'; + create or alter user tmp$c5861_u2 password 'pass'; + create or alter user tmp$c5861_u3 password 'pass'; + + create role role1; -- Has privileges with grant option + create role role2; -- Has privileges without errors and without grant option + create role role3; -- Must get errors in granting privileges from role2 + + grant role1 to tmp$c5861_u1; + grant role2 to tmp$c5861_u2; + grant role3 to tmp$c5861_u3; + + create procedure p as begin end; + create function f returns int as begin end; + create generator g; + create exception e 'ex'; + create table tab(id int); + create package pak as begin end; + + grant create table to role1 with grant option; + grant create procedure to role1 with grant option; + grant execute on procedure p to role1 with grant option; + grant execute on function f to role1 with grant option; + grant usage on generator g to role1 with grant option; + grant usage on exception e to role1 with grant option; + grant select on tab to role1 with grant option; + grant update(id) on tab to role1 with grant option; + grant execute on package pak to role1 with grant option; + + commit; + + connect '$(DSN)' user 'tmp$c5861_u1' password 'pass' role 'role1'; + + select rdb$role_name from rdb$roles where rdb$role_in_use(rdb$role_name); + + grant create table to role2; + grant execute on procedure p to role2; + grant execute on function f to role2; + grant usage on generator g to role2; + grant usage on exception e to role2; + grant select on tab to role2; + grant update(id) on tab to role2; + grant execute on package pak to role2; + + commit; + + -- create own objects + create table tab_of_tmp$c5861_u1(i int); + create procedure proc_of_tmp$c5861_u1 as begin end; + + commit; + + -- try to grant privileges for owned objects + grant select on table tab_of_tmp$c5861_u1 to role2; + grant execute on procedure proc_of_tmp$c5861_u1 to role2; + + commit; + + connect '$(DSN)' user 'tmp$c5861_u2' password 'pass' role 'role2'; + + -- check every privilege + create table t(i integer); + execute procedure p; + select f() from rdb$database; + select gen_id(g, 1) from rdb$database; + select * from tab; + + -- try to grant every privilege to role3 and sure this causes an error + set bail off; + + ------------------------------------------------ + grant create table to role3; + ------------------------------------------------ + grant execute on procedure p to role3; + ------------------------------------------------ + grant execute on function f to role3; + ------------------------------------------------ + grant usage on generator g to role3; + ------------------------------------------------ + grant usage on exception e to role3; + ------------------------------------------------ + grant select on tab to role3; + ------------------------------------------------ + grant update(id) on tab to role3; + ------------------------------------------------ + grant execute on package pak to role3; + + --- cleanup: + commit; + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + + drop user tmp$c5861_u1; + drop user tmp$c5861_u2; + drop user tmp$c5861_u3; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$ROLE_NAME ROLE1 + F + GEN_ID 1 + """ +expected_stderr_1 = """ + 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 + """ + +@pytest.mark.version('>=4.0') +def test_core_5861_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5862.py b/tests/bugs/test_core_5862.py new file mode 100644 index 00000000..aee47e58 --- /dev/null +++ b/tests/bugs/test_core_5862.py @@ -0,0 +1,68 @@ +#coding:utf-8 +# +# id: bugs.core_5862 +# title: Varchar computed column length stores incorrect and invalid values for field +# decription: +# Checked on FB40SS, build 4.0.0.1142: OK, 1.938s. +# +# tracker_id: CORE-5862 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test ( + id int + ,vc_default_user varchar(100) default user + ,vc_default_literal varchar(100) default 'literal' + ,vc_generated_explicit varchar(201) computed by (vc_default_user || ' ' || vc_default_literal) + ,vc_generated_implicit computed by (vc_default_user || ' ' || vc_default_literal) + ); + commit; + + set list on; + select + rf.rdb$field_name + ,ff.rdb$field_length + ,ff.rdb$character_length + from rdb$relation_fields rf + join rdb$fields ff on rf.rdb$field_source = ff.rdb$field_name + where + upper(rf.rdb$relation_name) = upper('test') + and upper(rf.rdb$field_name) starting with upper('vc_generated_') + order by rf.rdb$field_position + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$FIELD_NAME VC_GENERATED_EXPLICIT + + RDB$FIELD_LENGTH 804 + RDB$CHARACTER_LENGTH 201 + + RDB$FIELD_NAME VC_GENERATED_IMPLICIT + + RDB$FIELD_LENGTH 804 + RDB$CHARACTER_LENGTH 201 + """ + +@pytest.mark.version('>=4.0') +def test_core_5862_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5871.py b/tests/bugs/test_core_5871.py new file mode 100644 index 00000000..36fe2e5e --- /dev/null +++ b/tests/bugs/test_core_5871.py @@ -0,0 +1,141 @@ +#coding:utf-8 +# +# id: bugs.core_5871 +# title: Incorrect caching of the subquery result (procedure call) in independent queries +# decription: +# Beside stanalone stored procedure it was decided to check also stored function, and packaged SP and func. +# Checked on: FB40SS, build 4.0.0.1143: OK, 2.219s. +# +# tracker_id: CORE-5871 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create or alter procedure p1 (n int) returns (r int) as + begin + r = n; + suspend; + end + ^ + + create or alter function f1 (n int) returns int as + declare r int; + begin + r = n; + return r; + end + ^ + + create or alter package pkg + as + begin + procedure pk_p1(n int) returns(r int); + function pk_f1(n int) returns int; + end + ^ + + recreate package body pkg + as + begin + procedure pk_p1(n int) returns(r int) as + begin + r = n; + suspend; + end + + function pk_f1(n int) returns int as + declare r int; + begin + r = n; + return r; + end + end + ^ + + -------------------------------------------------------------------------------- + + + create or alter procedure sp_test returns ( s1 varchar(100), s2 varchar(100), s3 varchar(100), s4 varchar(100) ) as + declare i int; + begin + i = 0; + while (i < 3) do + begin + i = i + 1; + + select + (select + coalesce(:s1, '') || ' ' || :i || '=' || (select r from p1(:i)) + from rdb$database + ) + from rdb$database + into s1; + + select + ( + select + coalesce(:s2, '') || ' ' || :i || '=' || ( select f1(:i) from rdb$database ) + from rdb$database + ) + from rdb$database + into s2; + + + select + (select + coalesce(:s3, '') || ' ' || :i || '=' || (select r from pkg.pk_p1(:i)) + from rdb$database + ) + from rdb$database + into s3; + + select + ( + select + coalesce(:s4, '') || ' ' || :i || '=' || ( select pkg.pk_f1(:i) from rdb$database ) + from rdb$database + ) + from rdb$database + into s4; + + + end + suspend; + end + ^ + set term ;^ + commit; + + set list on; + select * from sp_test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + S1 1=1 2=2 3=3 + S2 1=1 2=2 3=3 + S3 1=1 2=2 3=3 + S4 1=1 2=2 3=3 + """ + +@pytest.mark.version('>=4.0') +def test_core_5871_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5874.py b/tests/bugs/test_core_5874.py new file mode 100644 index 00000000..4173e893 --- /dev/null +++ b/tests/bugs/test_core_5874.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: bugs.core_5874 +# title: Provide name of read-only column incorrectly referenced in UPDATE ... SET xxx +# decription: +# Table with computed field (non-ascii) that is result of addition is used here. +# UPDATE statement is used in trivial form, then as 'update or insert' and as 'merge'. +# All cases should produce STDERR with specifying table name and R/O column after dot. +# Checked on 4.0.0.1142: OK, 2.359s. +# +# tracker_id: CORE-5874 +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test(id int, x int, y int, "hozzáadása" computed by (x * y) ); + commit; + + set planonly; + + update test set "hozzáadása" = 1; + + update or insert into test(id, "hozzáadása") + values(1, 111) matching(id) + returning "hozzáadása"; + + merge into test t + using( select 1 as id, 2 as x, 3 as y from rdb$database ) s on s.id = t.id + when matched then + update set "hozzáadása" = 1 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + attempted update of read-only column TEST.hozzáadása + + Statement failed, SQLSTATE = 42000 + attempted update of read-only column TEST.hozzáadása + + Statement failed, SQLSTATE = 42000 + attempted update of read-only column TEST.hozzáadása + """ + +@pytest.mark.version('>=4.0') +def test_core_5874_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_5876.py b/tests/bugs/test_core_5876.py new file mode 100644 index 00000000..27a83e08 --- /dev/null +++ b/tests/bugs/test_core_5876.py @@ -0,0 +1,119 @@ +#coding:utf-8 +# +# id: bugs.core_5876 +# title: Provide name of udf function for "arithmetic exception, numeric overflow, or string truncation" +# decription: +# *** FOR FB 3.X ONLY *** +# Test uses UDF 'sright' declared in ib_udf.sql script which for sure present in every FB snapshot. +# After this, we try to create PSQL function with the same signature. +# +# *** FOR FB 4.X AND ABOVE *** +# Added separate code for running on FB 4.0.x: use udf_compat!UC_div from UDR engine. +# It seems that this UDR function is the only wich we can force to raise exception by passing invalid +# argument #2 that will cause zero divide. +# +# 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/ +# +# Checked on: +# 400SS, build 4.0.0.1421: OK, 1.457s. +# 302SS, build 3.0.5.33097: OK, 0.832s. +# 302Cs, build 3.0.4.33054: OK, 1.423s. +# +# tracker_id: CORE-5876 +# min_versions: ['3.0.4'] +# versions: 3.0.4, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + execute block as + begin + execute statement 'drop function substr'; + when any do begin end + end + ^ + set term ;^ + commit; + + declare external function substr + cstring(80), smallint, smallint + returns cstring(80) + entry_point 'IB_UDF_substr' + module_name 'ib_udf' + ; + commit; + + set heading off; + select substr(cast('abc' as char(1500)) || '123', 1, 1000) + from rdb$database + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22001 + arithmetic exception, numeric overflow, or string truncation + -string right truncation + -expected length 80, actual 1503 + -UDF: SUBSTR + """ + +@pytest.mark.version('>=3.0.4,<4.0') +def test_core_5876_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + create function UDR40_div ( + n1 integer, + n2 integer + ) returns double precision + external name 'udf_compat!UC_div' + engine udr; + + + commit; + set list on; + select UDR40_div( 1, 0) from rdb$database; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stderr_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 function 'UDR40_DIV' + """ + +@pytest.mark.version('>=4.0') +def test_core_5876_2(act_2: Action): + act_2.expected_stderr = expected_stderr_2 + act_2.execute() + assert act_2.clean_expected_stderr == act_2.clean_stderr + diff --git a/tests/bugs/test_core_5884.py b/tests/bugs/test_core_5884.py new file mode 100644 index 00000000..0f9012e3 --- /dev/null +++ b/tests/bugs/test_core_5884.py @@ -0,0 +1,70 @@ +#coding:utf-8 +# +# id: bugs.core_5884 +# title: Initial global mapping from srp plugin does not work +# decription: +# Confirmed bug on: 3.0.4.33020, 4.0.0.1143 ('TEST2' was shown instead of 'GTOST'). +# Checked on: +# FB30SS, build 3.0.4.33021: OK, 2.312s. +# +# tracker_id: CORE-5884 +# min_versions: ['3.0.4'] +# versions: 3.0.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + create or alter user tmp$c5884_1 password '123' using plugin Srp; + create or alter user tmp$c5884_2 password '456' using plugin Srp; + commit; + + create or alter mapping lmap using plugin srp from user tmp$c5884_1 to user ltost; + create or alter global mapping gmap using plugin srp from user tmp$c5884_2 to user gtost; + commit; + + connect '$(DSN)' user tmp$c5884_1 password '123'; + select current_user as whoami from rdb$database; + commit; + + connect '$(DSN)' user tmp$c5884_2 password '456'; + select current_user as whoami from rdb$database; + commit; + + connect '$(DSN)' user sysdba password 'masterkey'; + commit; + + + drop global mapping gmap; + drop mapping lmap; + commit; + + drop user tmp$c5884_1 using plugin Srp; + drop user tmp$c5884_2 using plugin Srp; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHOAMI LTOST + WHOAMI GTOST + """ + +@pytest.mark.version('>=3.0.4') +def test_core_5884_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5887.py b/tests/bugs/test_core_5887.py new file mode 100644 index 00000000..0180f281 --- /dev/null +++ b/tests/bugs/test_core_5887.py @@ -0,0 +1,139 @@ +#coding:utf-8 +# +# id: bugs.core_5887 +# title: Allow the use of management statements in PSQL blocks +# decription: +# ::: NB ::: +# 1. Currently test checks only ability to use SYNTAX for usage statements within PSQL blocks +# as it is described in '...\\doc\\sql.extensions\\README.management_statements_psql.md'. +# Actual affects on further work are not verified. +# 2. Deferred check of 'alter session reset': got SQLSTATE = 25000/no transaction for request. +# Sent letter to dimitr et al, 09-mar-2019 13:43. +# 3. Deferred check of 'SET TRUSTED ROLE': it is unclear for me how to implement this. +# Sent Q to Alex (same letter). +# +# All other cases are checked on 4.0.0.1421 and 4.0.0.1457: OK. +# +# 10.12.2019. Updated syntax for SET BIND. Removed (maybe temply) check of 'set time zone bind native'. +# Commits that changed syntax: +# https://github.com/FirebirdSQL/firebird/commit/ca5ee672ca3144303732d5e2b5886b32c442da91 // 08-nov-19 +# https://github.com/FirebirdSQL/firebird/commit/08096e3b879811d0e2e87b707b260c17d1542167 // 12-dec-19 +# +# Checked on 4.0.0.1685, 4.0.0.1691 +# +# +# tracker_id: CORE-5887 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + + set term ^; + execute block as + begin + begin + execute statement 'drop role acnt'; + when any do begin end + end + end + ^ + set term ;^ + commit; + + create role acnt; + commit; + + grant acnt to sysdba; + commit; + + ---------------------------------------------- + + -- NO output should be produced by further PSQL blocks: + + set term ^; + execute block as + begin + set decfloat round ceiling; + end^ + + execute block as + begin + set decfloat traps to Division_by_zero, Invalid_operation, Overflow; + end^ + + execute block as + begin + -- OLD SYNTAX: set decfloat bind native; + -- Syntax after 11-nov-2019: + -- https://github.com/FirebirdSQL/firebird/commit/a77295ba153e0c17061e2230d0ffdbaf08839114 + -- See also: doc/sql.extensions/README.set_bind.md: + -- SET BIND OF type-from TO { type-to | LEGACY }; + -- SET BIND OF type NATIVE; + + set bind of decfloat to native; + -- ^^ + -- +--- since 12-dec-2019 + end^ + + execute block as + begin + set role acnt; + end^ + + execute block as + begin + set session idle timeout 5 minute; + end^ + + execute block as + begin + set statement timeout 1 minute; + end^ + + execute block as + begin + set time zone local; + end^ + + + execute block as + begin + set bind of timestamp with time zone to legacy; + set bind of time with time zone to legacy; + end^ + ^ + + execute block as + begin + set bind of timestamp with time zone to native; + set bind of time with time zone to native; + end^ + ^ + set term ;^ + commit; + + drop role acnt; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=4.0') +def test_core_5887_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_5887_trusted_role.py b/tests/bugs/test_core_5887_trusted_role.py new file mode 100644 index 00000000..57deb16e --- /dev/null +++ b/tests/bugs/test_core_5887_trusted_role.py @@ -0,0 +1,188 @@ +#coding:utf-8 +# +# id: bugs.core_5887_trusted_role +# title: Allow the use of management statements in PSQL blocks: check only TRUSTED ROLE +# decription: +# 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. +# +# Checked on: 4.0.0.1457: OK, 2.602s. +# 25.04.2020: added command to obtain %FB_HOME% folder in order to make call of ISQL as fully qualified executable. +# Checked on 4.0.0.1935 SS/CS (both on Windows 8.1 (IMAGE-PC1) and Windows-2008 R2 (IBSurgeon-2008) hosts). +# +# Thanks to Alex for suggestions. +# +# tracker_id: CORE-5887 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import re +# import time +# import subprocess +# from subprocess import Popen +# from fdb import services +# import socket +# import getpass +# +# #--------------------------------------------- +# +# 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() +# os.fsync(file_handle.fileno()) +# +# file_handle.close() +# +# #-------------------------------------------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# # 23.08.2020: !!! REMOVING OS-VARIABLE ISC_USER IS MANDATORY HERE !!! +# # This variable could be set by other .fbts which was performed before current within batch mode (i.e. when fbt_run is called from ) +# # NB: os.unsetenv('ISC_USER') actually does NOT affect on content of os.environ dictionary, see: https://docs.python.org/2/library/os.html +# # We have to remove OS variable either by os.environ.pop() or using 'del os.environ[...]', but in any case this must be enclosed intro try/exc: +# #os.environ.pop('ISC_USER') +# try: +# del os.environ["ISC_USER"] +# except KeyError as e: +# pass +# +# +# THIS_DBA_USER=user_name +# THIS_DBA_PSWD=user_password +# +# THIS_COMPUTER_NAME = socket.gethostname() +# CURRENT_WIN_ADMIN = getpass.getuser() +# +# THIS_FDB = db_conn.database_name +# db_conn.close() +# +# fb_home = services.connect(host='localhost', user= user_name, password= user_password).get_home_directory() +# +# f_sql_cmd = open( os.path.join(context['temp_directory'],'tmp_check_5887.sql'), 'w', buffering=0) +# +# f_sql_txt=''' +# set bail on; +# -- set echo on; +# connect 'localhost:%(THIS_FDB)s' user %(THIS_DBA_USER)s password '%(THIS_DBA_PSWD)s'; +# create role tmp$role_5887; +# commit; +# grant tmp$role_5887 to "%(THIS_COMPUTER_NAME)s\\%(CURRENT_WIN_ADMIN)s"; +# 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_5887; +# commit; +# +# connect '%(THIS_COMPUTER_NAME)s:%(THIS_FDB)s' role tmp$role_5887; +# +# --show mapping; +# +# set list on; +# select 'point-1' as msg, a.mon$role,a.mon$auth_method from mon$attachments a where mon$attachment_id = current_connection; +# +# set term ^; +# execute block as +# begin +# set trusted role; +# end +# ^ +# set term ;^ +# commit; +# +# connect '%(THIS_COMPUTER_NAME)s:%(THIS_FDB)s'; +# +# select 'point-2' as msg, a.mon$role, a.mon$auth_method from mon$attachments a where mon$attachment_id = current_connection; +# commit; +# +# connect 'localhost:%(THIS_FDB)s' user %(THIS_DBA_USER)s password '%(THIS_DBA_PSWD)s'; +# drop mapping trusted_auth; +# drop mapping WIN_ADMINS; +# commit; +# --set bail off; +# --show mapping; +# ''' % locals() +# +# f_sql_cmd.write(f_sql_txt) +# flush_and_close( f_sql_cmd ) +# +# +# f_sql_log=open( os.path.join(context['temp_directory'],'tmp_5887_trusted_role.log'), 'w', buffering=0) +# subprocess.call( [ fb_home + "isql", "-q", "-i", f_sql_cmd.name ], stdout=f_sql_log, stderr=subprocess.STDOUT ) +# flush_and_close( f_sql_log ) +# +# with open( f_sql_log.name,'r') as f: +# for line in f: +# print(line) +# +# cleanup( [x.name for x in (f_sql_cmd, f_sql_log)] ) +# +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG point-1 + MON$ROLE TMP$ROLE_5887 + MON$AUTH_METHOD Mapped from Win_Sspi + + MSG point-2 + MON$ROLE TMP$ROLE_5887 + MON$AUTH_METHOD Mapped from Win_Sspi + + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_5887_trusted_role_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5892.py b/tests/bugs/test_core_5892.py new file mode 100644 index 00000000..970129f8 --- /dev/null +++ b/tests/bugs/test_core_5892.py @@ -0,0 +1,150 @@ +#coding:utf-8 +# +# id: bugs.core_5892 +# title: SQL SECURITY DEFINER context is not properly evaluated for monitoring tables +# decription: +# Test is based on ticket sample: we create non-privileged user and allow him to call TWO procedures. +# First SP is declared with DEFINER rights (i.e. with rights of SYSDBA), second - with rights of INVOKER. +# When first SP is called by this (non-privileged!) user then he should see two other connections: +# 1) that was done by him (but this is other attachment) +# 2) that was done by SYSDBA. +# When second SP is called then this user should see only ONE connection (first from previous list). +# Also this test checks ability to work with new context variable 'EFFECTIVE_USER' from 'SYSTEM' namespace. +# +# Checked on 4.0.0.1479: OK, 1.623s. +# +# tracker_id: CORE-5892 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import fdb +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.close() +# +# con1=fdb.connect( dsn = dsn ) #, user = 'SYSDBA', password = 'masterkey' ) +# con1.execute_immediate("create or alter user TMP$C5892 password '123' using plugin Srp") +# con1.commit() +# +# con2=fdb.connect( dsn = dsn, user = 'TMP$C5892', password = '123' ) +# con3=fdb.connect( dsn = dsn, user = 'TMP$C5892', password = '123' ) +# +# sp_definer_ddl = ''' +# create or alter procedure sp_test_definer returns( another_name varchar(31), another_conn_id int, execution_context varchar(31) ) SQL SECURITY DEFINER +# as +# begin +# execution_context = rdb$get_context('SYSTEM', 'EFFECTIVE_USER'); +# for +# select mon$user, mon$attachment_id +# from mon$attachments a +# where a.mon$system_flag is distinct from 1 and a.mon$attachment_id != current_connection +# into +# another_name, +# another_conn_id +# do suspend; +# end +# ''' +# +# sp_invoker_ddl = ''' +# create or alter procedure sp_test_invoker returns( another_name varchar(31), another_conn_id int, execution_context varchar(31) ) SQL SECURITY INVOKER +# as +# begin +# execution_context = rdb$get_context('SYSTEM', 'EFFECTIVE_USER'); +# for +# select mon$user, mon$attachment_id +# from mon$attachments a +# where +# a.mon$system_flag is distinct from 1 +# and a.mon$attachment_id != current_connection +# and a.mon$user = current_user +# into +# another_name, +# another_conn_id +# do suspend; +# end +# ''' +# +# con1.execute_immediate( sp_definer_ddl ) +# con1.execute_immediate( sp_invoker_ddl ) +# con1.commit() +# +# con1.execute_immediate( 'grant execute on procedure sp_test_definer to public' ) +# con1.execute_immediate( 'grant execute on procedure sp_test_invoker to public' ) +# con1.commit() +# +# sql_chk_definer='select current_user as "definer_-_who_am_i", d.another_name as "definer_-_who_else_here", d.execution_context as "definer_-_effective_user" from rdb$database r left join sp_test_definer d on 1=1' +# sql_chk_invoker='select current_user as "invoker_-_who_am_i", d.another_name as "invoker_-_who_else_here", d.execution_context as "invoker_-_effective_user" from rdb$database r left join sp_test_invoker d on 1=1' +# +# +# #--------------------------------- +# #print('=== result of call SP with DEFINER security ===') +# cur2a=con2.cursor() +# cur2a.execute( sql_chk_definer ) +# c2col=cur2a.description +# for r in cur2a: +# for i in range(0,len(c2col)): +# print( c2col[i][0],':', r[i] ) +# cur2a.close() +# +# #--------------------------------- +# +# #print('') +# #print('=== result of call SP with INVOKER security ===') +# cur2b=con2.cursor() +# cur2b.execute( sql_chk_invoker ) +# c2col=cur2b.description +# for r in cur2b: +# for i in range(0,len(c2col)): +# print( c2col[i][0],':', r[i] ) +# cur2b.close() +# +# #--------------------------------- +# +# con2.close() +# con3.close() +# +# con1.execute_immediate('drop user TMP$C5892 using plugin Srp') +# con1.close() +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + definer_-_who_am_i : TMP$C5892 + definer_-_who_else_here : SYSDBA + definer_-_effective_user : SYSDBA + + definer_-_who_am_i : TMP$C5892 + definer_-_who_else_here : TMP$C5892 + definer_-_effective_user : SYSDBA + + invoker_-_who_am_i : TMP$C5892 + invoker_-_who_else_here : TMP$C5892 + invoker_-_effective_user : TMP$C5892 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_5892_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5896.py b/tests/bugs/test_core_5896.py new file mode 100644 index 00000000..14a0cdf3 --- /dev/null +++ b/tests/bugs/test_core_5896.py @@ -0,0 +1,89 @@ +#coding:utf-8 +# +# id: bugs.core_5896 +# title: NOT NULL constraint is not synchronized after rename column +# decription: +# Confirmed bug on: 4.0.0.1166 +# Checked on: 4.0.0.1172: OK, 1.875s - works fine. +# Added check of rdb$relation_fields.rdb$null_flag after suggestion by Adriano, 26.08.2018 19:12. +# +# tracker_id: CORE-5896 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set count on; + set list on; + + + create or alter view v_chk as + select + --cc.rdb$constraint_name constr_name + rc.rdb$relation_name rel_name + ,cc.rdb$trigger_name trg_name + ,rf.rdb$null_flag null_flag + from rdb$check_constraints cc + join rdb$relation_constraints rc on cc.rdb$constraint_name = rc.rdb$constraint_name + left join rdb$relation_fields rf + on rc.rdb$relation_name = rf.rdb$relation_name + and cc.rdb$trigger_name = rf.rdb$field_name + where rc.rdb$constraint_type = upper('not null') + ; + commit; + + recreate table test ( + old_name bigint not null + ); + commit; + + select * from v_chk; + commit; + + alter table test alter old_name to new_name; + commit; + + select * from v_chk; + + -- Output BEFORE fix was: + ------------------------- + -- REL_NAME TEST + -- TRG_NAME OLD_NAME + -- NULL_FLAG + commit; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + REL_NAME TEST + TRG_NAME OLD_NAME + NULL_FLAG 1 + Records affected: 1 + + REL_NAME TEST + TRG_NAME NEW_NAME + NULL_FLAG 1 + Records affected: 1 + """ + +@pytest.mark.version('>=4.0') +def test_core_5896_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5898.py b/tests/bugs/test_core_5898.py new file mode 100644 index 00000000..a06c7474 --- /dev/null +++ b/tests/bugs/test_core_5898.py @@ -0,0 +1,124 @@ +#coding:utf-8 +# +# id: bugs.core_5898 +# title: ROLE not passed in EXECUTE STATEMENT ... ON EXTERNAL +# decription: +# Confirmed bug on: 4.0.0.1172, 3.0.4.33034. +# Checked on: +# 3.0.4.33041: OK, 2.922s. +# 4.0.0.1190: OK, 2.750s. +# +# tracker_id: CORE-5898 +# min_versions: ['3.0.4'] +# versions: 3.0.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set list on; + + create or alter user tmp$c5898 password '123'; + commit; + + create role boss; + commit; + grant boss to tmp$c5898; + commit; + + connect '$(DSN)' user 'tmp$c5898' password '123' role 'BOSS'; + select + 'BEFORE CHECKS:' as msg, + mon$user as who_am_i, + mon$role as whats_my_role, + left(mon$remote_protocol,3) what_protocol_im_using + from mon$attachments a + where mon$attachment_id=current_connection; + + set echo off; + set term ^; + execute block + returns ( check_no smallint, who_am_i varchar(32), whats_my_role varchar(32), what_protocol_im_using varchar(32)) + as + declare v_dbnm varchar(255); + declare v_sttm varchar(255); + begin + v_dbnm = rdb$get_context('SYSTEM', 'DB_NAME'); + v_sttm = 'select mon$user,mon$role, left(mon$remote_protocol,3) from mon$attachments a where mon$attachment_id=current_connection'; + + check_no=1; + execute statement v_sttm + into who_am_i, whats_my_role, what_protocol_im_using; + suspend; + + + check_no=check_no+1; + execute statement v_sttm + on external :v_dbnm + into who_am_i, whats_my_role, what_protocol_im_using; + suspend; + + end + ^ + set term ;^ + rollback; + + -- cleanup: + -- ######## + connect '$(DSN)' user 'sysdba' password 'masterkey'; + + -- |||||||||||||||||||||||||||| + -- ###################################||| 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; + + drop user tmp$c5898; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG BEFORE CHECKS: + WHO_AM_I TMP$C5898 + WHATS_MY_ROLE BOSS + WHAT_PROTOCOL_IM_USING TCP + + CHECK_NO 1 + WHO_AM_I TMP$C5898 + WHATS_MY_ROLE BOSS + WHAT_PROTOCOL_IM_USING TCP + + CHECK_NO 2 + WHO_AM_I TMP$C5898 + WHATS_MY_ROLE BOSS + WHAT_PROTOCOL_IM_USING + """ + +@pytest.mark.version('>=3.0.4') +def test_core_5898_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5904.py b/tests/bugs/test_core_5904.py new file mode 100644 index 00000000..4ebe4068 --- /dev/null +++ b/tests/bugs/test_core_5904.py @@ -0,0 +1,74 @@ +#coding:utf-8 +# +# id: bugs.core_5904 +# title: An attempt to create global mapping with long (greater than SQL identifier length) FROM field fails +# decription: +# Confirmed bug on 3.0.4.33034. +# Checked on: +# 3.0.4.33053: OK, 1.765s. +# 4.0.0.1224: OK, 2.703s. +# +# tracker_id: CORE-5904 +# min_versions: ['3.0.4'] +# versions: 3.0.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set count on; + set list on; + set bail on; + recreate view v_test as + select + rdb$map_name, + rdb$map_using, + rdb$map_plugin, + rdb$map_db, + rdb$map_from_type, + rdb$map_from, + rdb$map_to_type, + rdb$map_to + from rdb$auth_mapping; + commit; + create or alter mapping krasnorutskayag using plugin win_sspi from user 'DOMN\\КрасноруцкаяАА' to user "DOMN\\Krasnorutskaya"; + create or alter global mapping krasnorutskayag using plugin win_sspi from user 'DOMN\\КрасноруцкаяАА' to user "DOMN\\Krasnorutskaya"; + commit; + select * from v_test; + drop mapping KrasnorutskayaG; + drop global mapping KrasnorutskayaG; + commit; + select * from v_test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$MAP_NAME KRASNORUTSKAYAG + RDB$MAP_USING P + RDB$MAP_PLUGIN WIN_SSPI + RDB$MAP_DB + RDB$MAP_FROM_TYPE USER + RDB$MAP_FROM DOMN\\КрасноруцкаяАА + RDB$MAP_TO_TYPE 0 + RDB$MAP_TO DOMN\\Krasnorutskaya + Records affected: 1 + Records affected: 0 + """ + +@pytest.mark.version('>=3.0.4') +def test_core_5904_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5905.py b/tests/bugs/test_core_5905.py new file mode 100644 index 00000000..8a85248b --- /dev/null +++ b/tests/bugs/test_core_5905.py @@ -0,0 +1,240 @@ +#coding:utf-8 +# +# id: bugs.core_5905 +# title: Inconsistencies with PSQL FUNCTION vs UDF +# decription: +# *** FOR FB 3.X ONLY *** +# Test uses UDF 'strlen' declared in ib_udf.sql script which for sure present in every FB snapshot. +# After this, we try to create PSQL function with the same signature. +# +# *** FOR FB 4.X AND ABOVE *** +# Added separate code for running on FB 4.0.x. +# 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/ +# +# Confirmed inconsistence output on: 3.0.4.32972, 4.0.0.875 and 4.0.0.1172 +# (4.x - output phrase "UDF THE_FRAC" instead of "Function THE_FRAC" on attempt to drop function). +# +# Checked on: +# 3.0.5.33086: OK, 1.937s. +# 4.0.0.1340: OK, 3.157s. +# 4.0.0.1378: OK, 4.281s. +# +# tracker_id: CORE-5905 +# min_versions: ['3.0'] +# versions: 3.0.4, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + create view v_check as + select + rf.rdb$function_name as func_name + ,rf.rdb$legacy_flag as legacy_flag + from rdb$functions rf where rf.rdb$function_name = upper('substrlen') + ; + commit; + + + declare external function substrlen + cstring(255), smallint, smallint + returns cstring(255) free_it + entry_point 'IB_UDF_substrlen' module_name 'ib_udf' + ; + commit; + + set term ^; + create procedure sp_main(input_str varchar(255), i smallint, n smallint) as + declare s varchar(255); + begin + s = substrlen( input_str, i, n ); + end + ^ + set term ;^ + commit; + + select * from v_check; + commit; + + drop function substrlen; + commit; + + ----------------------------- + + set term ^; + alter function substrlen(input_str varchar(255), i smallint, n smallint) returns varchar(255) as + begin + rdb$set_context('USER_SESSION', 'WAS_PSQL_INVOKED', 'Yes'); + return substring(input_str from i for n); + end + ^ + set term ^; + commit; + + select * from v_check; + commit; + + drop function substrlen; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + FUNC_NAME SUBSTRLEN + LEGACY_FLAG 1 + + FUNC_NAME SUBSTRLEN + LEGACY_FLAG 0 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 38000 + unsuccessful metadata update + -cannot delete + -Function SUBSTRLEN + -there are 1 dependencies + + Statement failed, SQLSTATE = 38000 + unsuccessful metadata update + -cannot delete + -Function SUBSTRLEN + -there are 1 dependencies + """ + +@pytest.mark.version('>=3.0.4,<4.0') +def test_core_5905_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set list on; + create view v_check as + select + rf.rdb$function_name as func_name + ,rf.rdb$legacy_flag as legacy_flag + from rdb$functions rf + where rf.rdb$function_name = upper('the_frac') + ; + commit; + + -- See declaration sample in plugins\\udr\\UdfBackwardCompatibility.sql: + + create function the_frac( + val double precision + ) returns double precision + external name 'udf_compat!UC_frac' + engine udr; + commit; + + select the_frac( -pi() ) as the_frac_1 from rdb$database; + commit; + + set term ^; + create procedure sp_main as + declare r double precision; + begin + r = the_frac( pi() ); + end + ^ + set term ;^ + commit; + + select * from v_check; + commit; + + drop function the_frac; -- should FAIL because dependent procedure SP_MAIN does exist. + commit; + + ----------------------------- + + set term ^; + alter function the_frac( val double precision ) returns double precision as + begin + return 1. / abs(val - cast(val as int) ) ; + end + ^ + set term ;^ + commit; + + select * from v_check; + commit; + + select the_frac( -pi() ) as the_frac_2 from rdb$database; + commit; + + alter function the_frac( + val double precision + ) returns double precision + external name 'udf_compat!UC_frac' + engine udr; + commit; + + select the_frac( -pi() ) as the_frac_3 from rdb$database; + commit; + + drop function the_frac; -- should again FAIL because procedure SP_MAIN still depends on it. + commit; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + THE_FRAC_1 -0.1415926535897931 + + FUNC_NAME THE_FRAC + LEGACY_FLAG 0 + + 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 + + Statement failed, SQLSTATE = 38000 + unsuccessful metadata update + -cannot delete + -Function THE_FRAC + -there are 1 dependencies + """ + +@pytest.mark.version('>=4.0') +def test_core_5905_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_expected_stderr == act_2.clean_stderr + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/bugs/test_core_5907.py b/tests/bugs/test_core_5907.py new file mode 100644 index 00000000..21a7f033 --- /dev/null +++ b/tests/bugs/test_core_5907.py @@ -0,0 +1,244 @@ +#coding:utf-8 +# +# id: bugs.core_5907 +# title: Regression: can not launch trace if its 'database' section contains regexp pattern with curvy brackets to enclose quantifier +# decription: +# Database file name for check: {core_5907.97}.tmp // NB: outer curvy brackets ARE INCLUDED in this name. +# This name should match to pattern: (\\{core_5907.[[:DIGIT:]]{2}\\}).tmp -- but we have to duplicate every "{" and "}". +# Also, we have to duplicate '' otherwise it will be escaped by fbtest framework. +# Checked on 4.0.0.1224: OK, 14.047s. +# +# tracker_id: CORE-5907 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('.*{CORE_5907.97}.TMP', '{CORE_5907.97}.TMP'), ('.*{core_5907.97}.tmp', '{CORE_5907.97}.TMP')] + +init_script_1 = """ + recreate table test(id int); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import re +# import subprocess +# import time +# import shutil +# from fdb import services +# from subprocess import Popen +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# this_fdb = db_conn.database_name +# test_fdb = os.path.join( os.path.split(this_fdb)[0], "{core_5907.97}.tmp") # name of copy will be: %FBT_REPO% mp\\{core_5907.97}.tmp +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# txt30 = '''# Trace config, format for 3.0. Generated auto, do not edit! +# database=(%[\\\\\\\\/](\\{{core_5907.[[:DIGIT:]]{{2}}\\}}).tmp) +# { +# enabled = true +# time_threshold = 0 +# #log_statement_finish = true +# log_connections = true +# } +# ''' +# +# f_trc_cfg=open( os.path.join(context['temp_directory'],'tmp_trace_5907.cfg'), 'w') +# f_trc_cfg.write(txt30) +# flush_and_close( f_trc_cfg ) +# +# shutil.copy2( this_fdb, test_fdb ) +# +# # ############################################################## +# # S T A R T T R A C E i n S E P A R A T E P R O C E S S +# # ############################################################## +# +# f_trc_log=open( os.path.join(context['temp_directory'],'tmp_trace_5907.log'), "w") +# f_trc_err=open( os.path.join(context['temp_directory'],'tmp_trace_5907.err'), "w") +# +# p_trace = Popen( [ context['fbsvcmgr_path'], +# 'localhost:service_mgr', +# 'action_trace_start', +# 'trc_cfg', f_trc_cfg.name +# ], +# stdout = f_trc_log, stderr = f_trc_err +# ) +# +# # this delay need for trace start and finish its output about invalid section in its config file: +# time.sleep(1) +# +# # #################################################### +# # G E T A C T I V E T R A C E S E S S I O N I D +# # #################################################### +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# +# f_trc_lst = open( os.path.join(context['temp_directory'],'tmp_trace_5907.lst'), 'w') +# subprocess.call( [ context['fbsvcmgr_path'], +# 'localhost:service_mgr', +# 'action_trace_list' +# ], +# stdout=f_trc_lst +# ) +# flush_and_close( f_trc_lst ) +# +# # !!! DO NOT REMOVE THIS LINE !!! +# #time.sleep(3) +# +# trcssn=0 +# with open( f_trc_lst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# #............................................................................. +# +# #sql_cmd="insert into extdecimal(dec34_34) values (1)" +# +# sql_cmd='select mon$database_name from mon$database' +# +# con1=fdb.connect(dsn = 'localhost:' + test_fdb) +# cur=con1.cursor() +# try: +# cur.execute( sql_cmd ) +# for r in cur: +# print( r[0] ) +# except Exception,e: +# for i in e[0].split('\\n'): +# print('CLIENT GOT ERROR:',i) +# finally: +# cur.close() +# +# con1.close() +# #............................................................................. +# +# time.sleep(1) +# +# # #################################################### +# # S E N D R E Q U E S T T R A C E T O S T O P +# # #################################################### +# if trcssn>0: +# fn_nul = open(os.devnull, 'w') +# #f_trc_log=open( os.path.join(context['temp_directory'],'tmp_trace_5907.log'), "w") +# subprocess.call( [ context['fbsvcmgr_path'], +# 'localhost:service_mgr', +# 'action_trace_stop','trc_id', trcssn +# ], +# stdout=fn_nul +# ) +# fn_nul.close() +# # DO NOT REMOVE THIS LINE: +# time.sleep(1) +# +# +# p_trace.terminate() +# +# flush_and_close( f_trc_log ) +# flush_and_close( f_trc_err ) +# +# # 1. Trace STDERR log should be EMPTY: +# ###################################### +# +# # Example of STDERR when wrong database name pattern is spesified: +# # Trace session ID 11 started +# # Error creating trace session for database "": +# # Passed text: illegal line +# +# f_list = ( f_trc_err, ) +# for i in range(len(f_list)): +# f_name=f_list[i].name +# if os.path.getsize(f_name) > 0: +# with open( f_name,'r') as f: +# for line in f: +# print("Unexpected STDERR, file "+f_name+": "+line) +# +# # 2. Trace STDOUT log must contain one ATTACH and one DETACH events, e.g: +# ######################################################################### +# # 2018-09-26T09:42:26.7340 (508:02122400) ATTACH_DATABASE +# # C:\\MIX\\FIREBIRD\\QA\\FBT-REPO\\TMP\\{CORE_5907.97}.TMP (ATT_10, SYSDBA:NONE, NONE, TCPv4:127.0.0.1/4159) +# # C:\\Python27\\python.exe:2080 +# # 2018-09-26T09:42:26.7500 (508:02122400) DETACH_DATABASE +# # C:\\MIX\\FIREBIRD\\QA\\FBT-REPO\\TMP\\{CORE_5907.97}.TMP (ATT_10, SYSDBA:NONE, NONE, TCPv4:127.0.0.1/4159) +# # C:\\Python27\\python.exe:2080 +# +# msg='Found expected ' +# with open( f_trc_log.name,'r') as f: +# for line in f: +# if 'ATTACH_DATABASE' in line: +# print( msg + 'ATTACH.') +# if 'DETACH_DATABASE' in line: +# print( msg + 'DETACH.') +# +# +# # CLEANUP +# ######### +# time.sleep(1) +# cleanup( (f_trc_cfg, f_trc_log, f_trc_err, f_trc_lst, test_fdb) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + {CORE_5907.97}.TMP + Found expected ATTACH. + Found expected DETACH. + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_5907_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5908.py b/tests/bugs/test_core_5908.py new file mode 100644 index 00000000..05557af3 --- /dev/null +++ b/tests/bugs/test_core_5908.py @@ -0,0 +1,78 @@ +#coding:utf-8 +# +# id: bugs.core_5908 +# title: Enhance dynamic libraries loading related error messages +# decription: +# We intentionally try to load unit from non-existent UDR module with name "udrcpp_foo". +# Message 'module not found' issued BEFORE fix - without any detalization. +# Current output should contain phrase: 'UDR module not loaded'. +# Filtering is used for prevent output of localized message about missed UDR library. +# +# Checked on: +# 3.0.4.33053: OK, 13.968s. +# 4.0.0.1210: OK, 2.375s. +# Thanks to Alex for suggestion about test implementation. +# +# tracker_id: CORE-5908 +# min_versions: ['3.0.4'] +# versions: 3.0.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import re +# +# udr_sp_ddl=''' +# create or alter procedure gen_foo2 ( +# start_n integer not null, +# end_n integer not null +# ) returns( n integer not null ) +# external name 'udrcpp_foo!gen_rows' +# engine udr +# ''' +# +# allowed_patterns = ( +# re.compile('\\.*module\\s+not\\s+(found|loaded)\\.*', re.IGNORECASE), +# ) +# +# try: +# db_conn.execute_immediate( udr_sp_ddl ) +# db_conn.commit() # --------------------- this will fail with message about missed UDR livrary file. +# except Exception,e: +# ############################################################################## +# # We parse exception object and allow for output only such lines from it +# # that relate to missed MODULE, and no other text (localization can be here!): +# ############################################################################## +# for i in e[0].split('\\n'): +# match2some = filter( None, [ p.search(i) for p in allowed_patterns ] ) +# if match2some: +# print( (' '.join(i.split()).upper()) ) +# finally: +# db_conn.close() +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + - UDR MODULE NOT LOADED + """ + +@pytest.mark.version('>=3.0.4') +@pytest.mark.xfail +def test_core_5908_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5913.py b/tests/bugs/test_core_5913.py new file mode 100644 index 00000000..939d9110 --- /dev/null +++ b/tests/bugs/test_core_5913.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: bugs.core_5913 +# title: Add context variables with compression and encryption status of current connection +# decription: +# Checked on: +# 3.0.4.33053: OK, 6.375s. +# 4.0.0.1210: OK, 3.125s. +# +# tracker_id: CORE-5913 +# min_versions: ['3.0'] +# versions: 3.0.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select + iif( rdb$get_context('SYSTEM','WIRE_COMPRESSED') is not null, 'DEFINED', '') as ctx_wire_compressed + ,iif( rdb$get_context('SYSTEM','WIRE_ENCRYPTED') is not null, 'DEFINED', '') as ctx_wire_encrypted + from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CTX_WIRE_COMPRESSED DEFINED + CTX_WIRE_ENCRYPTED DEFINED + """ + +@pytest.mark.version('>=3.0.4') +def test_core_5913_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5921.py b/tests/bugs/test_core_5921.py new file mode 100644 index 00000000..0b4380cd --- /dev/null +++ b/tests/bugs/test_core_5921.py @@ -0,0 +1,138 @@ +#coding:utf-8 +# +# id: bugs.core_5921 +# title: Provide information about Global Commit Number, Commit Number of currently used database snapshot (if any) and Commit Numbers assigned to the committed transactions +# decription: +# From doc\\sql.extensions\\README.builtin_functions.txt about rdb$get_transaction_cn() function: +# === +# ... numbers returned by RDB$GET_TRANSACTION_CN could have values below: +# -2 - transaction is dead (rolled back) +# -1 - transaction is in limbo +# 0 - transaction is active, +# 1 - transaction committed before database started or less than OIT +# >1 - transaction committed after database started +# NULL - given transaction number is NULL or greater than database Next Transaction +# === +# Checked on: 4.0.0.1218, 2.578 s. +# ::: NB ::: +# This ISQL-based test does NOT verify cases when tx is dead or in limbo. +# Perhaps, Python-based implementation is required and will be created later. +# +# 05.03.2019: renamed RDB$GET_CONTEXT('SYSTEM', 'SNAPSHOT_CN') to RDB$GET_CONTEXT('SYSTEM', 'SNAPSHOT_NUMBER') -- see CORE-6016. Checked on 4.0.0.1455 +# +# 09.11.2019: added section with substitutions because GET_OIT_CN can differ in SS vs CS: 9 and 10. +# Checked on: +# 4.0.0.1646 SS: 1.249s. +# 4.0.0.1637 SC: 1.532s. +# 4.0.0.1633 CS: 1.576s. +# +# tracker_id: CORE-5921 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('GET_OIT_CN[ \t]+[\\d]+', 'GET_OIT_CN ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set term ^; + create or alter procedure sp_set_tx_ctx( a_ctx_var_name varchar(80) ) as + begin + rdb$set_context('USER_SESSION', :a_ctx_var_name, current_transaction); + end + ^ + set term ;^ + commit; + + set list on; + execute procedure sp_set_tx_ctx('tx_a'); + + select + iif( tx_a < tx_oit, 'For TX < OIT', iif( tx_a = tx_oit, 'For OIT', 'For TX > OIT') ) as msg_a + ,rdb$get_transaction_cn( tx_a ) as get_tx_a_cn + from ( + select + d.mon$oldest_transaction as tx_oit + ,cast( rdb$get_context('USER_SESSION','tx_a') as int ) as tx_a + from mon$database d + ) + ; + rollback; + + execute procedure sp_set_tx_ctx('tx_b'); + commit; + + select + iif( tx_b < tx_oit, 'For TX < OIT', iif( tx_b = tx_oit, 'For OIT', 'For TX > OIT') ) as msg_b + ,rdb$get_transaction_cn( tx_b ) as get_tx_b_cn + from ( + select + d.mon$oldest_transaction as tx_oit + ,cast( rdb$get_context('USER_SESSION','tx_b') as int ) as tx_b + from mon$database d + ) + ; + + select + rdb$get_transaction_cn( d.mon$oldest_transaction ) as get_oit_cn + ,rdb$get_transaction_cn( current_transaction ) as get_tx_c_cn + ,rdb$get_transaction_cn( null ) as get_tx_nul_cn + ,rdb$get_transaction_cn( mon$next_transaction + 1 ) as get_tx_nxx_cn + -- added 25.09.2018, after commit + -- https://github.com/FirebirdSQL/firebird/commit/7610a76ff3f263177d0a9f7b02cdc1784a0f3402 + -- all of these columns must contain NULL: + ,rdb$get_transaction_cn( mon$next_transaction + (9223372036854775807-mon$next_transaction) ) as get_tx_001_cn + ,rdb$get_transaction_cn( 9223372036854775807 ) as get_tx_002_cn + ,rdb$get_transaction_cn(-9223372036854775808) as get_tx_003_cn + from mon$database d; + + set term ^; + execute block returns( global_cn_sign smallint, snapshot_cn smallint ) as + begin + global_cn_sign = sign( rdb$get_context('SYSTEM', 'GLOBAL_CN') ); + snapshot_cn = sign( rdb$get_context('SYSTEM', 'SNAPSHOT_NUMBER') ); + suspend; + end + ^ + set term ;^ + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG_A For TX > OIT + GET_TX_A_CN 0 + + MSG_B For TX < OIT + GET_TX_B_CN 1 + + GET_OIT_CN 9 + GET_TX_C_CN 0 + + GET_TX_NUL_CN + GET_TX_NXX_CN + GET_TX_001_CN + GET_TX_002_CN + GET_TX_003_CN + + GLOBAL_CN_SIGN 1 + SNAPSHOT_CN 1 + """ + +@pytest.mark.version('>=4.0') +def test_core_5921_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5926.py b/tests/bugs/test_core_5926.py new file mode 100644 index 00000000..ee5e03dd --- /dev/null +++ b/tests/bugs/test_core_5926.py @@ -0,0 +1,179 @@ +#coding:utf-8 +# +# id: bugs.core_5926 +# title: Attempt to create mapping with non-ascii user name which is encoded in SINGLE-BYTE codepage leads to '-Malformed string' +# decription: +# Reproduced 'malformed string' error on: 3.0.4.33053, 4.0.0.1172. +# +# 03-mar-2021. Re-implemented in order to have ability to run this test on Linux. +# Test encodes to UTF8 all needed statements (SET NAMES; CONNECT; DDL and DML) and stores this text in .sql file. +# NOTE: 'SET NAMES' contain character set that must be used for reproducing problem (WIN1252 in this test). +# Then ISQL is launched in separate (child) process which performs all necessary actions (using required charset). +# Result will be redirected to log(s) which will be opened further via codecs.open(...encoding='cp1252'). +# Finally, its content will be converted to UTF8 for showing in expected_stdout. +# +# NB: different data are used for FB 3.x and 4.x because DDL in 4.x allows to store names with length up to 63 character. +# See variables 'mapping_name' and 'non_ascii_user_name'. +# FB 3.x restricts max_length of DB object name with value = 31 (bytes, not character!). +# +# Checked on: +# * Windows: 4.0.0.2377, 3.0.8.33420 +# * Linux: 4.0.0.2377, 3.0.8.33415 +# +# tracker_id: CORE-5926 +# min_versions: ['3.0.4'] +# versions: 3.0.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='WIN1252', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import codecs +# import subprocess +# import time +# engine = db_conn.engine_version +# db_conn.close() +# +# # 03.03.2021 REMOVING OS-VARIABLE ISC_USER IS MANDATORY HERE! +# # This variable could be set by other .fbts which was performed before current within batch mode (i.e. when fbt_run is called from ) +# # NB: os.unsetenv('ISC_USER') actually does NOT affect on content of os.environ dictionary, see: https://docs.python.org/2/library/os.html +# # We have to remove OS variable either by os.environ.pop() or using 'del os.environ[...]', but in any case this must be enclosed into try/exc: +# try: +# del os.environ["ISC_USER"] +# except KeyError as e: +# pass +# +# +# #-------------------------------------------- +# +# 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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# if engine < 4: +# # Maximal length of user name in FB 3.x is 31 (charset unicode_fss). +# #mapping_name = 'áâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ' +# mapping_name = 'áâãäåæçèéêëìíîï1' +# # mapping_name = 'áâãäåæçèéêëìíîïð' +# non_ascii_user_name = 'ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞ' +# ascii_only_user_name = 'ABCDEFGHIJKLMNOPQRSTUWYXYZ12345' +# else: +# # Maximal length of user name in FB 4.x is 63 (charset utf8). +# # +# mapping_name = 'áâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿŒ' +# non_ascii_user_name = 'ÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿŒœŠšŸŽžƒ' +# ascii_only_user_name = 'ABCDEFGHIJKLMNOPQRSTUWYXYZ12345ABCDEFGHIJKLMNOPQRSTUWYXYZ123456' +# +# # plugin_for_mapping = 'win_sspi' +# plugin_for_mapping = 'Srp' +# +# sql_txt=''' set bail on; +# set names win1252; +# connect '%(dsn)s' user '%(user_name)s' password '%(user_password)s'; +# +# create or alter mapping "%(mapping_name)s" using plugin %(plugin_for_mapping)s from user '%(non_ascii_user_name)s' to user "%(ascii_only_user_name)s"; +# commit; +# -- show mapping; +# set count on; +# set list on; +# select +# rdb$map_using +# ,rdb$map_db +# ,rdb$map_from_type +# ,rdb$map_to_type +# -- ,rdb$map_plugin +# -- 03.03.2021: do NOT show because it differs for FB 3.x and 4.x: ,rdb$map_from +# -- 03.03.2021: do NOT show because it differs for FB 3.x and 4.x: ,rdb$map_to +# from rdb$auth_mapping +# where +# upper(rdb$map_name) = upper('%(mapping_name)s') +# and rdb$map_plugin = upper('%(plugin_for_mapping)s') +# and rdb$map_from = '%(non_ascii_user_name)s' +# and rdb$map_to containing '%(ascii_only_user_name)s' +# ; +# commit; +# ''' % dict(globals(), **locals()) +# +# f_run_sql = open( os.path.join(context['temp_directory'], 'tmp_5926_win1252.sql'), 'w' ) +# f_run_sql.write( sql_txt.decode('utf8').encode('cp1252') ) +# flush_and_close( f_run_sql ) +# +# # result: file tmp_5926_win1252.sql is encoded in win1252 +# +# f_run_log = open( os.path.splitext(f_run_sql.name)[0]+'.log', 'w') +# subprocess.call( [ context['isql_path'], '-q', '-i', f_run_sql.name ], +# stdout = f_run_log, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_run_log ) # result: output will be encoded in win1252 +# +# with codecs.open(f_run_log.name, 'r', encoding='cp1252' ) as f: +# result_in_win1252 = f.readlines() +# +# for i in result_in_win1252: +# print( i.encode('utf8') ) +# +# # cleanup: +# ########### +# cleanup( (f_run_sql, f_run_log) ) +# +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$MAP_USING P + RDB$MAP_DB + RDB$MAP_FROM_TYPE USER + RDB$MAP_TO_TYPE 0 + + Records affected: 1 + """ + +@pytest.mark.version('>=3.0.4') +@pytest.mark.xfail +def test_core_5926_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5931.py b/tests/bugs/test_core_5931.py new file mode 100644 index 00000000..da50c50c --- /dev/null +++ b/tests/bugs/test_core_5931.py @@ -0,0 +1,92 @@ +#coding:utf-8 +# +# id: bugs.core_5931 +# title: SIMILAR TO does not return result when invalid pattern is used (with two adjacent special characters that should be escaped but aren't) +# decription: +# Confirmed normal work (evaluation for less than 5 ms) on WI-T4.0.0.1598 +# +# tracker_id: CORE-5931 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + + set term ^; + execute block as + begin + rdb$set_context( 'USER_SESSION','DTS_START', cast('now' as timestamp) ); + rdb$set_context( 'USER_SESSION','MAX_THRESHOLD_MS', 100 ); + -- ^ + -- | + -- ############################# + -- MAX ALLOWED EXECUTION TIME,MS + -- ############################# + end + ^ + set term ;^ + + select 1 as result from rdb$database where + ' + group by + f01, + f02, + f03, + f04, + f05, + f06, + f07, + f08, + f09, + f10, + f11, + f12, + f13 + ' + similar to + '%group[[:WHITESPACE:]]+by[[:WHITESPACE:]]+([[:ALNUM:]]|_)+([[:WHITESPACE:]]*,[[:WHITESPACE:]]*[[:ALNUM:]]+){12,}[[:WHITESPACE:]]*%' + ; + + + set count off; + select + iif( evaluated_ms <= max_allowed_ms + ,'acceptable' + ,'TOO LONG: ' || evaluated_ms || ' ms - this is more then threshold = ' || max_allowed_ms || ' ms' + ) as duration + from ( + select + datediff( millisecond from cast(rdb$get_context( 'USER_SESSION','DTS_START') as timestamp) to current_timestamp ) evaluated_ms + ,cast( rdb$get_context( 'USER_SESSION','MAX_THRESHOLD_MS' ) as int ) as max_allowed_ms + from rdb$database + ); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT 1 + Records affected: 1 + DURATION acceptable + """ + +@pytest.mark.version('>=4.0') +def test_core_5931_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5935.py b/tests/bugs/test_core_5935.py new file mode 100644 index 00000000..62a0df38 --- /dev/null +++ b/tests/bugs/test_core_5935.py @@ -0,0 +1,197 @@ +#coding:utf-8 +# +# id: bugs.core_5935 +# title: Bugcheck 165 (cannot find tip page) // Classic and SuperClassic only +# decription: +# ::: NB ::: +# Bug can be reproduced only when FIRST of ISQL sessions is lacunhed with '-n' switch. +# Second ISQL must be started *WITHOUT* this switch! +# Absence of '-n' means that ISQL always starts two transactions (first for DML and second for DDL) +# and they both are committed at the same time for each executed statement. +# Because of this, we use here two transaction for second connection and, furthermore, we use +# the same isolation levels for them, namely: SNAPSHOT for DML and READ COMMITTED for DDL. +# This is done by using custom TPB objects with apropriate properties - see 'dml_tpb' and 'ddl_tpb'. +# +# Database forced writes is changed here to OFF in order to make execution faster. +# +# Confirmed bug on 3.0.4.32972 (build date: 11-may-2018), got: +# SQLCODE: -902 / - ... consistency check (can't continue after bugcheck) / -902 / 335544333 +# firebird.log will contain after this: +# internal Firebird consistency check (cannot find tip page (165), file: tra.cpp line: 2331) +# +# Checked on 3.0.5.33084 -- all OK. +# +# +# tracker_id: CORE-5935 +# min_versions: ['3.0.5'] +# versions: 3.0.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# svc = fdb.services.connect(host = 'localhost:service_mgr') +# svc.set_write_mode(database = db_conn.database_name, mode = services.WRITE_BUFFERED) +# svc.close() +# +# db_conn.close() +# +# #FB_CLNT=sys.argv[1] +# #DB_NAME='localhost:e30' +# +# dml_tpb = fdb.TPB() +# dml_tpb.lock_resolution = fdb.isc_tpb_wait +# dml_tpb.isolation_level = fdb.isc_tpb_concurrency +# +# ddl_tpb = fdb.TPB() # READ_COMMITTED | NO_REC_VERSION | WAIT | READ_WRITE) +# ddl_tpb.lock_resolution = fdb.isc_tpb_wait +# ddl_tpb.isolation_level = (fdb.isc_tpb_read_committed, fdb.isc_tpb_no_rec_version) +# +# con1 = fdb.connect(dsn = dsn) # DB_NAME, fb_library_name = FB_CLNT ) +# +# con1.execute_immediate('recreate table a (id int)') +# con1.commit() +# +# #--------------------------------------------------------- +# +# con1.execute_immediate('create index idx_a on a(id)') +# con1.commit() +# +# sql=''' +# create or alter procedure p_gen_tx(n int) as +# declare i int = 0; +# begin +# while (i < n) do +# in autonomous transaction do +# i = i + 1; +# end +# ''' +# +# con1.execute_immediate(sql) +# con1.commit() +# con1.close() +# +# #---------------------------------------------------------- +# +# con1 = fdb.connect(dsn = dsn) # DB_NAME, fb_library_name = FB_CLNT ) +# +# tx1a = con1.trans( default_tpb = dml_tpb ) +# tx1a.begin() +# +# cur1 = tx1a.cursor() +# cur1.execute('delete from a') +# tx1a.commit() +# +# tx1a.begin() +# cur1.execute("select current_transaction, rdb$get_context('SYSTEM', 'ISOLATION_LEVEL') from rdb$database") +# for r in cur1: +# pass +# +# # --------------------------------------------------------------- +# +# con2 = fdb.connect(dsn = dsn) # DB_NAME, fb_library_name = FB_CLNT ) +# +# tx2a = con2.trans( default_tpb = dml_tpb ) +# tx2b = con2.trans( default_tpb = ddl_tpb ) +# +# tx2a.begin() +# tx2b.begin() +# +# cur2 = tx2a.cursor() +# cur2.callproc('p_gen_tx', (33000,) ) +# tx2a.commit() +# tx2b.commit() +# +# tx2a.begin() +# tx2b.begin() +# +# cur2.execute('insert into a(id) values(?)', (tx2a.transaction_id,) ) +# tx2a.commit() +# tx2b.commit() +# +# tx2a.begin() +# tx2b.begin() +# cur2.execute('set statistics index idx_a') +# tx2a.commit() +# tx2b.commit() +# +# tx2a.begin() +# tx2b.begin() +# cur2.execute('select rdb$index_name, rdb$record_version from rdb$indices where rdb$relation_name = ?', ('A',) ) +# for r in cur2: +# pass +# cur2.execute('select id from a where id > ?', (0,)) +# for r in cur2: +# pass +# tx2a.commit() +# tx2b.commit() +# +# tx2a.begin() +# tx2b.begin() +# cur2.callproc('p_gen_tx', (33000,) ) +# tx2a.commit() +# tx2b.commit() +# +# # ----------------------------------------------------------------- +# +# tx1a.commit() +# +# # ----------------------------------------------------------------- +# +# tx2a.begin() +# tx2b.begin() +# cur2.execute('select id from a where id > ?', (0,)) +# for r in cur2: +# pass +# +# # ----------------------------------------------------------------- +# +# tx1a.begin() +# cur1.execute('select id from a where id > ?', (0,)) +# for r in cur1: +# pass +# +# cur1.close() +# tx1a.rollback() +# con1.close() +# +# cur2.close() +# tx2a.rollback() +# tx2b.rollback() +# con2.close() +# +# print('Passed.') +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Passed. + """ + +@pytest.mark.version('>=3.0.5') +@pytest.mark.xfail +def test_core_5935_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5936.py b/tests/bugs/test_core_5936.py new file mode 100644 index 00000000..0aad32b6 --- /dev/null +++ b/tests/bugs/test_core_5936.py @@ -0,0 +1,170 @@ +#coding:utf-8 +# +# id: bugs.core_5936 +# title: Firebird crashes ... +# decription: +# Confirmed crash on: +# * 2.5.8.27089 SuperClassic +# * 2.5.9.27117 Classic and SuperClassic (build date: 29-sep-2018 - is earlier than fix: 08-oct-2018) +# +# Got in firebird.log: +# Access violation. +# The code attempted to access a virtual +# address without privilege to do so. +# Operating system call ReleaseSemaphore failed. Error code 6 +# +# NOTE-1: custom transaction TPB required for this ticket: fdb.isc_tpb_concurrency, fdb.isc_tpb_wait +# +# NOTE-2: current title of ticket ("Firebird server segfaults in the end of database backup") has no relation to backup action. +# I left here only first two words from it :-) +# +# Bug was fixed by one-line change in FB source, see: +# https://github.com/FirebirdSQL/firebird/commit/676a52625c074ef15e197e7b7538755195a66905 +# +# Checked on: +# 2.5.9.27119 SS: OK, 0.858s. +# 2.5.9.27129 CS/SC: OK, 15...19s +# 3.0.5.33123: OK, 4.174s. +# 3.0.2.32658: OK, 3.309s. +# 4.0.0.1501: OK, 5.602s. +# 4.0.0.1421: OK, 6.920s. +# +# tracker_id: CORE-5936 +# min_versions: ['2.5.9'] +# versions: 2.5.9 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.9 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import fdb +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# GEN_ROWS=17000 # ----- minimal value needed for making FB to crash +# +# THIS_FDB=db_conn.database_name +# db_conn.close() +# +# +# svc = services.connect(host = 'localhost', user = user_name, password = user_password) +# +# # Disable Forced Writes: +# ######################## +# svc.set_write_mode( THIS_FDB, services.WRITE_BUFFERED) +# svc.close() +# +# ddl_script=''' +# create table a (id int); +# create index idx_a on a computed by (id); +# commit; +# set term ^; +# create procedure p_gen_tx(n int) as +# declare i int = 0; +# begin +# while (i < n) do +# in autonomous transaction do +# i = i + 1; +# end ^ +# set term ;^ +# commit; +# ''' +# +# f_ddl_script = open( os.path.join(context['temp_directory'],'tmp_5936_ddl.sql'), 'w') +# f_ddl_script.write( ddl_script ) +# f_ddl_script.close() +# +# subprocess.call( ['isql', dsn, '-i', f_ddl_script.name ] ) +# +# os.remove( f_ddl_script.name ) +# +# #---------------------------------------------------- +# +# con1 = fdb.connect( dsn = dsn ) +# +# custom_tpb = fdb.TPB() +# custom_tpb.isolation_level = fdb.isc_tpb_concurrency +# custom_tpb.lock_resolution = fdb.isc_tpb_wait +# +# tx1 = con1.trans( default_tpb = custom_tpb ) +# tx1.begin() +# +# cur1 = tx1.cursor() +# cur1.execute( "select current_transaction, rdb$get_context('SYSTEM', 'ISOLATION_LEVEL') from rdb$database" ) +# for r in cur1: +# pass +# +# #------------------------------------------- +# +# con2 = fdb.connect( dsn = dsn ) +# tx2 = con2.trans( default_tpb = custom_tpb ) +# tx2.begin() +# cur2 = tx2.cursor() +# cur2.callproc( 'p_gen_tx', (GEN_ROWS,) ) +# tx2.commit() +# +# tx2.begin() +# cur2.execute( 'insert into a values(current_transaction)' ) +# tx2.commit() +# +# tx2.begin() +# cur2.execute( 'set statistics index idx_a' ) +# tx2.commit() +# +# tx2.begin() +# cur2.execute( 'select * from a where id > 0') +# for r in cur2: +# pass +# +# tx2.commit() +# +# tx2.begin() +# cur2.callproc( 'p_gen_tx', (GEN_ROWS,) ) +# tx2.commit() +# +# #-------------------------------------------- +# +# tx1.commit() +# cur1.execute( 'select * from a where id > 0') +# for r in cur1: +# pass # ----------- WI-V2.5.8.27089 crashed here +# +# print('Query completed.') +# tx1.commit() +# +# con1.close() +# con2.close() +# print('All fine.') +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Query completed. + All fine. + """ + +@pytest.mark.version('>=2.5.9') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_5936_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5939.py b/tests/bugs/test_core_5939.py new file mode 100644 index 00000000..5f992b3e --- /dev/null +++ b/tests/bugs/test_core_5939.py @@ -0,0 +1,62 @@ +#coding:utf-8 +# +# id: bugs.core_5939 +# title: Crash for "gbak -se -b database nul" +# decription: +# Bug can be reproduced on WI-V2.5.9.27117 Classic (snapshot date: 29-sep-2018). +# All fine on WI-V2.5.9.27129. +# Also checked on: +# 40sS, build 4.0.0.1479: +# 40sC, build 4.0.0.1421: +# 40Cs, build 4.0.0.1457: +# 30sS, build 3.0.5.33115 +# 30sC, build 3.0.2.32658 +# 30Cs, build 3.0.4.33054 +# +# tracker_id: CORE-5939 +# min_versions: ['2.5.9'] +# versions: 2.5.9 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.9 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# tmpfbk = 'tmp_core_5939.fbk' +# tmpfbk='$(DATABASE_LOCATION)'+tmpfbk +# +# runProgram('gbak',['-b', dsn, tmpfbk, '-se']) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + gbak: ERROR:service name parameter missing + gbak:Exiting before completion due to errors + """ + +@pytest.mark.version('>=2.5.9') +@pytest.mark.xfail +def test_core_5939_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5943.py b/tests/bugs/test_core_5943.py new file mode 100644 index 00000000..11f11fd5 --- /dev/null +++ b/tests/bugs/test_core_5943.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_5943 +# title: Server crashes preparing a query with both DISTINCT/ORDER BY and non-field expression in the select list +# decription: +# We run query from ticket and check that it does completed OK with issuing data and 'Records affected: 1'. +# Confirmed bug on: 3.0.4.33053, 4.0.0.1172 +# Works fine on: +# 2.5.9.27119: OK, 0.468s. +# 3.0.5.33084: OK, 1.484s. +# 4.0.0.1249: OK, 2.453s. +# +# tracker_id: CORE-5943 +# min_versions: ['2.5.9'] +# versions: 2.5.9 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.9 +# resources: None + +substitutions_1 = [('F02\\s+\\d+', 'F02')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + select distinct + '0' as f01 + ,a.mon$server_pid as f02 + from mon$attachments a + order by a.mon$server_pid, a.mon$server_pid + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F01 0 + F02 2344 + Records affected: 1 + """ + +@pytest.mark.version('>=2.5.9') +def test_core_5943_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5948.py b/tests/bugs/test_core_5948.py new file mode 100644 index 00000000..d6ace564 --- /dev/null +++ b/tests/bugs/test_core_5948.py @@ -0,0 +1,484 @@ +#coding:utf-8 +# +# id: bugs.core_5948 +# title: Make WIN_SSPI plugin produce keys for wirecrypt plugin +# decription: +# We create mapping from current Windows user to SYSBDBA and then make following +# changes in the firebird.conf: +# * AuthClient = Win_Sspi +# * WireCrypt = Required +# (these changes do not require restart of server because they relate to client-side). +# After this we try to connect without specifying user/password pair - it must PASS +# and we check that our attachment actualy uses wire encryption (by querying mon$ table). +# Finally, we return original firebird.conf back and create connect using common pair +# SYSDBA/masterkey. This is needed for drop mapping. +# +# Confirmed problem on 4.0.0.1227 (date of build: 01.10.2018): attempt to connect +# using Win_SSPI leads to: +# Statement failed, SQLSTATE = 28000 +# Client attempted to attach unencrypted but wire encryption is required +# +# Discussed with Alex, letters 23.06.2020. +# Checked on 4.0.0.1346 (date of build: 17.12.2018), SS/SC/CS - works fine. +# Checked on 3.0.6.33222, SS/SC/CS -- all OK. +# +# ::: NB ::: Test has separate code for 3.0.x and 4.0 because there is no column +# mon$attachments.mon$wire_encrypted in FB 3.x +# +# tracker_id: CORE-5948 +# min_versions: ['3.0.5'] +# versions: 3.0.5, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import sys +# import os +# import shutil +# import socket +# import getpass +# import time +# import datetime +# import subprocess +# from fdb import services +# +# # 23.08.2020: !!! REMOVING OS-VARIABLE ISC_USER IS MANDATORY HERE !!! +# # This variable could be set by other .fbts which was performed before current within batch mode (i.e. when fbt_run is called from ) +# # NB: os.unsetenv('ISC_USER') actually does NOT affect on content of os.environ dictionary, see: https://docs.python.org/2/library/os.html +# # We have to remove OS variable either by os.environ.pop() or using 'del os.environ[...]', but in any case this must be enclosed intro try/exc: +# #os.environ.pop('ISC_USER') +# try: +# del os.environ["ISC_USER"] +# except KeyError as e: +# pass +# +# +# THIS_COMPUTER_NAME = socket.gethostname() +# CURRENT_WIN_ADMIN = getpass.getuser() +# +# #-------------------------------------------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# db_conn.close() +# fb_home = services.connect(host='localhost', user=user_name, password=user_password).get_home_directory() +# +# dts = datetime.datetime.now().strftime("%y%m%d_%H%M%S") +# +# fbconf_cur = os.path.join(fb_home, 'firebird.conf') +# fbconf_bak = os.path.join(context['temp_directory'], 'firebird_'+dts+'.bak') +# +# sql_pre=''' +# set bail on; +# set list on; +# set count on; +# -- set echo on; +# +# recreate view v_map_info as +# select +# rdb$map_name -- test_wmap +# ,rdb$map_using -- p +# ,rdb$map_plugin -- win_sspi +# ,rdb$map_db -- +# ,rdb$map_from_type -- user +# ,iif( upper(rdb$map_from) = upper('%(THIS_COMPUTER_NAME)s\\%(CURRENT_WIN_ADMIN)s'), '', 'UNEXPECTED: ' || rdb$map_from ) as rdb_map_from +# ,rdb$map_to_type -- 0 +# ,iif( upper(rdb$map_to) = upper('%(user_name)s'), '', 'UNEXPECTED: ' || rdb$map_to ) as rdb$map_to +# ,rdb$system_flag -- 0 +# from rdb$database +# left join rdb$auth_mapping on rdb$map_name = upper('test_wmap') +# ; +# +# create or alter mapping test_wmap using plugin win_sspi from user "%(THIS_COMPUTER_NAME)s\\%(CURRENT_WIN_ADMIN)s" to user %(user_name)s; +# commit; +# +# select * from v_map_info +# ; +# +# ''' % dict(globals(), **locals()) +# +# f_prepare_sql = open( os.path.join(context['temp_directory'],'tmp_winsspi_prepare.sql'), 'w', buffering=0) +# f_prepare_sql.write(sql_pre) +# f_prepare_sql.close() +# +# f_prepare_log=open( os.path.join(context['temp_directory'],'tmp_winsspi_prepare.log'), 'w', buffering=0) +# subprocess.call( [ fb_home + "isql", dsn, "-user", user_name, "-pas", user_password, "-q", "-i", f_prepare_sql.name ], stdout=f_prepare_log, stderr=subprocess.STDOUT ) +# f_prepare_log.close() +# +# shutil.copy2( fbconf_cur, fbconf_bak ) +# +# f_fbconf=open( fbconf_cur, 'r') +# fbconf_content=f_fbconf.readlines() +# f_fbconf.close() +# for i,s in enumerate( fbconf_content ): +# line = s.lower().lstrip() +# if line.startswith( 'wirecrypt'.lower() ): +# fbconf_content[i] = '# [temply commented] ' + s +# +# if line.startswith( 'AuthClient'.lower() ): +# fbconf_content[i] = '# [temply commented] ' + s +# +# +# text2app=''' +# ### TEMPORARY CHANGED BY FBTEST FRAMEWORK ### +# AuthClient = Win_Sspi +# WireCrypt = Required +# ############################################## +# ''' +# +# fbconf_content += [ '\\n' + x for x in text2app.split('\\n') ] +# +# f_fbconf=open( fbconf_cur, 'w', buffering = 0) +# f_fbconf.writelines( fbconf_content ) +# f_fbconf.close() +# +# sql_run=''' +# set wng off; +# set bail on; +# set list on; +# -- set echo on; +# +# connect '%(dsn)s'; +# select +# mon$auth_method as auth_method -- mapped from win_sspi +# from mon$attachments where mon$attachment_id = current_connection; +# commit; +# ''' % dict(globals(), **locals()) +# +# f_connect_sql = open( os.path.join(context['temp_directory'],'tmp_winsspi_connect.sql'), 'w', buffering=0) +# f_connect_sql.write(sql_run) +# f_connect_sql.close() +# +# f_connect_log=open( os.path.join(context['temp_directory'],'tmp_winsspi_connect.log'), 'w', buffering=0) +# subprocess.call( [ fb_home + "isql", "-q", "-i", f_connect_sql.name ], stdout=f_connect_log, stderr=subprocess.STDOUT ) +# f_connect_log.close() +# +# +# # RESTORE previous content of firebird.conf. This must be done BEFORE drop mapping! +# shutil.copy2( fbconf_bak, fbconf_cur ) +# +# # DROP mapping. NB: this connect will use Srp plugin because attempt to connect using WinSSPI could failed: +# sql_end=''' +# drop mapping test_wmap; +# commit; +# set list on; +# set count on; +# select * from v_map_info; +# ''' +# +# f_cleanup_sql = open( os.path.join(context['temp_directory'],'tmp_winsspi_cleanup.sql'), 'w', buffering=0) +# f_cleanup_sql.write(sql_end) +# f_cleanup_sql.close() +# +# f_cleanup_log=open( os.path.join(context['temp_directory'],'tmp_winsspi_cleanup.log'), 'w', buffering=0) +# subprocess.call( [ fb_home + "isql", dsn, "-user", user_name, "-pas", user_password, "-q", "-i", f_cleanup_sql.name ], stdout=f_cleanup_log, stderr=subprocess.STDOUT ) +# f_cleanup_log.close() +# +# +# with open(f_prepare_log.name, 'r') as f: +# for line in f: +# if line.split(): +# print('PREPARE: ' + line) +# +# with open(f_connect_log.name, 'r') as f: +# for line in f: +# if line.split(): +# print('CONNECT: ' + line) +# +# with open(f_cleanup_log.name, 'r') as f: +# for line in f: +# if line.split(): +# print('CLEANUP: ' + line) +# +# time.sleep(1) +# +# f_list=( f_prepare_sql, f_prepare_log, f_connect_sql, f_connect_log, f_cleanup_sql, f_cleanup_log, ) +# +# # Cleanup +# ########## +# cleanup( [ i.name for i in f_list ] + [fbconf_bak] ) +# +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PREPARE: RDB$MAP_NAME TEST_WMAP + PREPARE: RDB$MAP_USING P + PREPARE: RDB$MAP_PLUGIN WIN_SSPI + PREPARE: RDB$MAP_DB + PREPARE: RDB$MAP_FROM_TYPE USER + PREPARE: RDB_MAP_FROM + PREPARE: RDB$MAP_TO_TYPE 0 + PREPARE: RDB$MAP_TO + PREPARE: RDB$SYSTEM_FLAG 0 + PREPARE: Records affected: 1 + + CONNECT: AUTH_METHOD Mapped from Win_Sspi + + CLEANUP: RDB$MAP_NAME + CLEANUP: RDB$MAP_USING + CLEANUP: RDB$MAP_PLUGIN + CLEANUP: RDB$MAP_DB + CLEANUP: RDB$MAP_FROM_TYPE + CLEANUP: RDB_MAP_FROM + CLEANUP: RDB$MAP_TO_TYPE + CLEANUP: RDB$MAP_TO + CLEANUP: RDB$SYSTEM_FLAG + CLEANUP: Records affected: 1 + """ + +@pytest.mark.version('>=3.0.5') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_5948_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +# test_script_2 +#--- +# +# import sys +# import os +# import shutil +# import socket +# import getpass +# import time +# import datetime +# import subprocess +# from fdb import services +# +# # 23.08.2020: !!! REMOVING OS-VARIABLE ISC_USER IS MANDATORY HERE !!! +# # This variable could be set by other .fbts which was performed before current within batch mode (i.e. when fbt_run is called from ) +# # NB: os.unsetenv('ISC_USER') actually does NOT affect on content of os.environ dictionary, see: https://docs.python.org/2/library/os.html +# # We have to remove OS variable either by os.environ.pop() or using 'del os.environ[...]', but in any case this must be enclosed intro try/exc: +# #os.environ.pop('ISC_USER') +# try: +# del os.environ["ISC_USER"] +# except KeyError as e: +# pass +# +# THIS_COMPUTER_NAME = socket.gethostname() +# CURRENT_WIN_ADMIN = getpass.getuser() +# +# #-------------------------------------------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# db_conn.close() +# fb_home = services.connect(host='localhost', user=user_name, password=user_password).get_home_directory() +# +# dts = datetime.datetime.now().strftime("%y%m%d_%H%M%S") +# +# fbconf_cur = os.path.join(fb_home, 'firebird.conf') +# fbconf_bak = os.path.join(context['temp_directory'], 'firebird_'+dts+'.bak') +# +# sql_pre=''' +# set bail on; +# set list on; +# set count on; +# -- set echo on; +# +# recreate view v_map_info as +# select +# rdb$map_name -- test_wmap +# ,rdb$map_using -- p +# ,rdb$map_plugin -- win_sspi +# ,rdb$map_db -- +# ,rdb$map_from_type -- user +# ,iif( upper(rdb$map_from) = upper('%(THIS_COMPUTER_NAME)s\\%(CURRENT_WIN_ADMIN)s'), '', 'UNEXPECTED: ' || rdb$map_from ) as rdb_map_from +# ,rdb$map_to_type -- 0 +# ,iif( upper(rdb$map_to) = upper('%(user_name)s'), '', 'UNEXPECTED: ' || rdb$map_to ) as rdb$map_to +# ,rdb$system_flag -- 0 +# from rdb$database +# left join rdb$auth_mapping on rdb$map_name = upper('test_wmap') +# ; +# +# create or alter mapping test_wmap using plugin win_sspi from user "%(THIS_COMPUTER_NAME)s\\%(CURRENT_WIN_ADMIN)s" to user %(user_name)s; +# commit; +# +# select * from v_map_info +# ; +# +# ''' % dict(globals(), **locals()) +# +# f_prepare_sql = open( os.path.join(context['temp_directory'],'tmp_winsspi_prepare.sql'), 'w', buffering=0) +# f_prepare_sql.write(sql_pre) +# f_prepare_sql.close() +# +# f_prepare_log=open( os.path.join(context['temp_directory'],'tmp_winsspi_prepare.log'), 'w', buffering=0) +# subprocess.call( [ fb_home + "isql", dsn, "-user", user_name, "-pas", user_password, "-q", "-i", f_prepare_sql.name ], stdout=f_prepare_log, stderr=subprocess.STDOUT ) +# f_prepare_log.close() +# +# shutil.copy2( fbconf_cur, fbconf_bak ) +# +# f_fbconf=open( fbconf_cur, 'r') +# fbconf_content=f_fbconf.readlines() +# f_fbconf.close() +# for i,s in enumerate( fbconf_content ): +# line = s.lower().lstrip() +# if line.startswith( 'wirecrypt'.lower() ): +# fbconf_content[i] = '# [temply commented] ' + s +# +# if line.startswith( 'AuthClient'.lower() ): +# fbconf_content[i] = '# [temply commented] ' + s +# +# +# text2app=''' +# ### TEMPORARY CHANGED BY FBTEST FRAMEWORK ### +# AuthClient = Win_Sspi +# WireCrypt = Required +# ############################################## +# ''' +# +# fbconf_content += [ '\\n' + x for x in text2app.split('\\n') ] +# +# f_fbconf=open( fbconf_cur, 'w', buffering = 0) +# f_fbconf.writelines( fbconf_content ) +# f_fbconf.close() +# +# sql_run=''' +# set wng off; +# set bail on; +# set list on; +# -- set echo on; +# +# connect '%(dsn)s'; +# select +# mon$auth_method as auth_method -- mapped from win_sspi +# ,mon$wire_encrypted as wire_encrypted -- +# from mon$attachments where mon$attachment_id = current_connection; +# commit; +# ''' % dict(globals(), **locals()) +# +# f_connect_sql = open( os.path.join(context['temp_directory'],'tmp_winsspi_connect.sql'), 'w', buffering=0) +# f_connect_sql.write(sql_run) +# f_connect_sql.close() +# +# f_connect_log=open( os.path.join(context['temp_directory'],'tmp_winsspi_connect.log'), 'w', buffering=0) +# subprocess.call( [ fb_home + "isql", "-q", "-i", f_connect_sql.name ], stdout=f_connect_log, stderr=subprocess.STDOUT ) +# f_connect_log.close() +# +# +# # RESTORE previous content of firebird.conf. This must be done BEFORE drop mapping! +# shutil.copy2( fbconf_bak, fbconf_cur ) +# +# # DROP mapping. NB: this connect will use Srp plugin because attempt to connect using WinSSPI could failed: +# sql_end=''' +# drop mapping test_wmap; +# commit; +# set list on; +# set count on; +# select * from v_map_info; +# ''' +# +# f_cleanup_sql = open( os.path.join(context['temp_directory'],'tmp_winsspi_cleanup.sql'), 'w', buffering=0) +# f_cleanup_sql.write(sql_end) +# f_cleanup_sql.close() +# +# f_cleanup_log=open( os.path.join(context['temp_directory'],'tmp_winsspi_cleanup.log'), 'w', buffering=0) +# subprocess.call( [ fb_home + "isql", dsn, "-user", user_name, "-pas", user_password, "-q", "-i", f_cleanup_sql.name ], stdout=f_cleanup_log, stderr=subprocess.STDOUT ) +# f_cleanup_log.close() +# +# +# with open(f_prepare_log.name, 'r') as f: +# for line in f: +# if line.split(): +# print('PREPARE: ' + line) +# +# with open(f_connect_log.name, 'r') as f: +# for line in f: +# if line.split(): +# print('CONNECT: ' + line) +# +# with open(f_cleanup_log.name, 'r') as f: +# for line in f: +# if line.split(): +# print('CLEANUP: ' + line) +# +# time.sleep(1) +# +# f_list=( f_prepare_sql, f_prepare_log, f_connect_sql, f_connect_log, f_cleanup_sql, f_cleanup_log, ) +# +# # Cleanup +# ########## +# cleanup( [ i.name for i in f_list ] + [fbconf_bak] ) +# +# +# +#--- +#act_2 = python_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + PREPARE: RDB$MAP_NAME TEST_WMAP + PREPARE: RDB$MAP_USING P + PREPARE: RDB$MAP_PLUGIN WIN_SSPI + PREPARE: RDB$MAP_DB + PREPARE: RDB$MAP_FROM_TYPE USER + PREPARE: RDB_MAP_FROM + PREPARE: RDB$MAP_TO_TYPE 0 + PREPARE: RDB$MAP_TO + PREPARE: RDB$SYSTEM_FLAG 0 + PREPARE: Records affected: 1 + + CONNECT: AUTH_METHOD Mapped from Win_Sspi + CONNECT: WIRE_ENCRYPTED + + CLEANUP: RDB$MAP_NAME + CLEANUP: RDB$MAP_USING + CLEANUP: RDB$MAP_PLUGIN + CLEANUP: RDB$MAP_DB + CLEANUP: RDB$MAP_FROM_TYPE + CLEANUP: RDB_MAP_FROM + CLEANUP: RDB$MAP_TO_TYPE + CLEANUP: RDB$MAP_TO + CLEANUP: RDB$SYSTEM_FLAG + CLEANUP: Records affected: 1 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_5948_2(db_2): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5949.py b/tests/bugs/test_core_5949.py new file mode 100644 index 00000000..06116cd8 --- /dev/null +++ b/tests/bugs/test_core_5949.py @@ -0,0 +1,84 @@ +#coding:utf-8 +# +# id: bugs.core_5949 +# title: Bugcheck could happen when read-only database with non-zero linger is set to read-write mode +# decription: +# Confirmed bug on 3.0.4.33053, got message in firebird.log: +# === +# Database: ...\\FPT-REPO\\TMP\\BUGS.CORE_5949.FDB +# internal Firebird consistency check (next transaction older than oldest active transaction (266), file: cch.cpp line: 4830) +# === +# Checked on 3.0.5.33084, 4.0.0.1249, 4.0.0.1340 -- works fine. +# +# tracker_id: CORE-5949 +# min_versions: ['3.0.5'] +# versions: 3.0.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import fdb +# from fdb import services as fbsvc +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# DB_NAME = '$(DATABASE_LOCATION)' + 'bugs.core_5949.fdb' +# +# def change_db_access_mode( a_host, a_db_name, a_required_access ): +# global fbsvc +# svc=fbsvc.connect( host = a_host ) +# svc.set_access_mode( a_db_name, a_required_access) # services.ACCESS_READ_WRITE or services.ACCESS_READ_ONLY +# svc.close() +# return None +# #------------------------------------ +# +# db_conn.execute_immediate('alter database set linger to 60') +# db_conn.commit() +# db_conn.close() +# +# #------------------------------------ +# +# change_db_access_mode( 'localhost', DB_NAME, fbsvc.ACCESS_READ_ONLY ) +# +# con=fdb.connect(dsn = dsn) +# cur=con.cursor() +# cur.execute('select r.rdb$linger, d.mon$read_only from rdb$database r cross join mon$database d') +# for r in cur: +# print(r[0],r[1]) +# con.commit() +# con.close() +# +# #------------------------------------ +# change_db_access_mode( 'localhost', DB_NAME, fbsvc.ACCESS_READ_WRITE ) +# +# print('COMPLETED.') +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 60 1 + COMPLETED. + """ + +@pytest.mark.version('>=3.0.5') +@pytest.mark.xfail +def test_core_5949_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5953.py b/tests/bugs/test_core_5953.py new file mode 100644 index 00000000..404679c4 --- /dev/null +++ b/tests/bugs/test_core_5953.py @@ -0,0 +1,158 @@ +#coding:utf-8 +# +# id: bugs.core_5953 +# title: Statement level read consistency in read-committed transactions +# decription: +# We create table with single column and inspect it TWICE by this query: 'select max(x) from test'. +# Both queries are in the single procedure, but they are separated by autonomous transaction. +# Initially (before 1st query) this table has one record with value=1, so the first query will return 1. +# Then autonomous transaction inserts into this table 10 rows with incremental values. +# After this, query runs again. +# +# Procedure is executed within READ COMMITTED transations. +# +# If current transaction was started as READ CONSISTENCY then 2nd query must return the same value as 1st. +# Otherwise 2nd query return DIFFERENT (last of newly added) value and output column MAX_X will differ. +# +# Checked on 4.0.0.1573. +# +# ::: NB ::: +# It is stated (in doc\\README.read_consistency.md ) that "In the future versions of Firebird old kinds of read-committed transactions could be removed". +# But for now we can suppose that at least in FB 4.x family these modes will be preserved and we can use them beside new (READ CONSISTENCY) mode. +# This means that we can check in this test BOTH modes and compare results, i.e.: +# 1. Start Tx in READ CONSISTENCY mode, get result_1; commit; +# 2. Start Tx in READ RECORD_VERSION, get result_2 - and it must differ from result_1. +# For this test could start Tx in READ RECORD_VERSION mode, parameter ReadConsistency in firebird.conf must be set to 0 (ZERO). +# THIS VALUE DIFFERS FROM DEFAULT, but it is not a problem for other major FB-versions: config is prepared separately for each of them. +# So, if in the future some major FB version will exclude RECORD_VERSION at all we can prepare new section of this test +# which will assume that there is no such parameter (ReadConsistency) in firebird.conf and check only one isolation mode. +# +# :::::::::::::::::::::::::::::::::::::::: NB :::::::::::::::::::::::::::::::::::: +# 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 replace 'alter sequence restart...' with subtraction of two gen values: +# c = gen_id(, -gen_id(, 0)) -- see procedure sp_restart_sequences. +# +# Checked on 4.0.0.2164 +# +# tracker_id: CORE-5953 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- drop dependencies if any: + create or alter procedure sp_restart_sequences as begin end; + create or alter view v_check as select 1 as isol_level, 1 as max_x from rdb$database; + commit; + create or alter procedure sp_run_heavy_query returns( dts timestamp, max_x int ) as begin end; + + recreate sequence g; + recreate table test(x int, constraint test_pk primary key(x) using descending index test_x_desc_pk); + commit; + + set term ^; + alter procedure sp_run_heavy_query returns( dts timestamp, max_x int ) as + begin + + execute statement 'select max(x) from test' into max_x; + dts='now'; + suspend; + + in autonomous transaction do + begin + insert into test(x) select gen_id(g,1) from rdb$types rows 10; + end + + execute statement 'select max(x) from test' into max_x; + dts='now'; + + suspend; + end + ^ + create or alter procedure sp_restart_sequences as + declare c bigint; + begin + c = gen_id(g, -gen_id(g, 0)); + end + ^ + set term ;^ + commit; + + recreate view v_check as + select + t.mon$isolation_mode as mon_isol_mode + ,rdb$get_context('SYSTEM', 'ISOLATION_LEVEL') as ctx_isol_level + ,d.max_x + from mon$transactions t + left join sp_run_heavy_query d on 1=1 + where t.mon$transaction_id = current_transaction; + + commit; + + insert into test values( gen_id(g,1) ); + commit; + + set list on; + + set transaction READ COMMITTED READ CONSISTENCY lock timeout 1; + select * from v_check; + + delete from test; + + execute procedure sp_restart_sequences; + commit; + + insert into test values( gen_id(g,1) ); + commit; + + set transaction READ COMMITTED RECORD_VERSION lock timeout 1; + select * from v_check; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MON_ISOL_MODE 4 + CTX_ISOL_LEVEL READ COMMITTED + MAX_X 1 + + MON_ISOL_MODE 4 + CTX_ISOL_LEVEL READ COMMITTED + MAX_X 1 + + + + MON_ISOL_MODE 2 + CTX_ISOL_LEVEL READ COMMITTED + MAX_X 1 + + MON_ISOL_MODE 2 + CTX_ISOL_LEVEL READ COMMITTED + MAX_X 11 + """ + +@pytest.mark.version('>=4.0') +def test_core_5953_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5957.py b/tests/bugs/test_core_5957.py new file mode 100644 index 00000000..8f97cab0 --- /dev/null +++ b/tests/bugs/test_core_5957.py @@ -0,0 +1,55 @@ +#coding:utf-8 +# +# id: bugs.core_5957 +# title: Bug in SIMILAR TO when adding numeric quantifier as bound for repetetion of expression leads to empty resultset +# decription: +# +# tracker_id: CORE-5957 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + set count on; + select 1 from rdb$database where 'SLEEP' similar to '(DELAY|SLEEP|PAUSE){1}'; -- 2.5 fails here + select 2 from rdb$database where 'SLEEP' similar to '(DELAY|SLEEP|PAUSE){1,}'; -- 2.5 fails here + select 3 from rdb$database where 'SLEEP' similar to '(DELAY|SLEEP|PAUSE)+'; + select 4 from rdb$database where 'SLEEP' similar to '(DELAY|SLEEP|PAUSE)*'; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 1 + Records affected: 1 + + 2 + Records affected: 1 + + 3 + Records affected: 1 + + 4 + Records affected: 1 + + """ + +@pytest.mark.version('>=3.0') +def test_core_5957_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5965.py b/tests/bugs/test_core_5965.py new file mode 100644 index 00000000..f89c005c --- /dev/null +++ b/tests/bugs/test_core_5965.py @@ -0,0 +1,174 @@ +#coding:utf-8 +# +# id: bugs.core_5965 +# title: FB3 Optimiser chooses less efficient plan than FB2.5 optimiser +# decription: +# 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" +# than becomes not null after obtaining at least one record for executing statement. +# We can get only one row without need to show its data by trivial cursor handling like this: +# === +# cur.execute(sql) +# for r in cur: +# pass +# break +# === +# Confirmed wrong plan for second expr in 4.0.0.1249, 3.0.4.33053 +# Works fine in 4.0.0.1340, 3.0.5.33084 +# +# tracker_id: CORE-5965 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import fdb +# import time +# import zipfile +# import difflib +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# +# zf = zipfile.ZipFile( os.path.join(context['files_location'],'core_5965.zip') ) +# tmpfbk = 'core_5965.fbk' +# zf.extract( tmpfbk, '$(DATABASE_LOCATION)') +# zf.close() +# +# tmpfbk='$(DATABASE_LOCATION)'+tmpfbk +# tmpfdb='$(DATABASE_LOCATION)'+'tmp_core_5965.fdb' +# +# f_restore_log=open( os.path.join(context['temp_directory'],'tmp_core_5965_restore.log'), 'w') +# subprocess.check_call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_restore", +# "bkp_file", tmpfbk, +# "dbname", tmpfdb, +# "res_replace", +# "verbose" +# ], +# stdout=f_restore_log, +# stderr=subprocess.STDOUT) +# flush_and_close( f_restore_log ) +# +# con=fdb.connect(dsn = 'localhost:'+tmpfdb) +# +# # https://pythonhosted.org/fdb/reference.html#fdb.Cursor +# +# cur_1=con.cursor() +# cur_2=con.cursor() +# +# sql_1=''' +# select 1 +# from opt_test +# where +# --sysid = 1 and +# clid = 23 and +# cust_type = 1 and +# cust_id = 73 +# order by order_no desc +# ; +# ''' +# +# sql_2=''' +# select 2 +# from opt_test +# where +# sysid = 1 and +# clid = 23 and +# cust_type = 1 and +# cust_id = 73 +# order by order_no desc +# ; +# +# ''' +# +# cur_1.execute(sql_1) +# for r in cur_1: +# pass +# break +# +# cur_2.execute(sql_2) +# for r in cur_2: +# pass +# break +# +# print( cur_1.plan ) +# print( cur_2.plan ) +# +# cur_1.close() +# cur_2.close() +# con.close() +# +# # Cleanup: +# ########## +# time.sleep(1) +# cleanup( (tmpfbk, tmpfdb, f_restore_log) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN SORT (OPT_TEST INDEX (O_CLID_CUSTTY_CUSTID)) + PLAN SORT (OPT_TEST INDEX (O_CLID_CUSTTY_CUSTID)) + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_5965_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5970.py b/tests/bugs/test_core_5970.py new file mode 100644 index 00000000..30b06888 --- /dev/null +++ b/tests/bugs/test_core_5970.py @@ -0,0 +1,1399 @@ +#coding:utf-8 +# +# id: bugs.core_5970 +# title: Built-in cryptographic functions +# decription: +# Issues found during implementing this test - see CORE-6185, CORE-6186. +# This test checks only ability to call ENCRYPT()/DECRYPT() functions with different parameters. +# Also, it checks that -> encrypt() -> decrypt(encrypted_source) gives the same . +# +# Checked on: +# 4.0.0.1646 SS: 3.657s. +# 4.0.0.1637 SC: 3.271s. +# 4.0.0.1633 CS: 4.191s. +# +# tracker_id: CORE-5970 +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set blob all; + set list on; + create or alter procedure sp_block_test(a_alg varchar(30)) as begin end; + create or alter procedure sp_stream_test(a_alg varchar(30)) as begin end; + commit; + + recreate table test( crypto_alg varchar(30), source_text blob, crypto_key varchar(128), crypto_iv varchar(128) ); + + recreate global temporary table gtt_tmp( + source_text blob + ,encrypted_text blob + ) on commit delete rows; + commit; + + + recreate table secure_table(secret_field varchar(1000), init_vector varchar(16) ); + insert into secure_table(secret_field, init_vector) values( lpad('',1000, 'A'), '1234567890123456'); + commit; + + --set echo on; + + -- Should NOT cause any errors when call encrypt() decrypt() for these params: + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'AES', lpad('', 65535, gen_uuid()), lpad('',16, uuid_to_char( gen_uuid() )), lpad('',16, uuid_to_char( gen_uuid() )) ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'ANUBIS', lpad('', 65535, gen_uuid()), lpad('',16, uuid_to_char( gen_uuid() )), lpad('',16, uuid_to_char( gen_uuid() )) ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'BLOWFISH', lpad('', 65535, gen_uuid()), lpad('',16, uuid_to_char( gen_uuid() )), lpad('', 8, uuid_to_char( gen_uuid() )) ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'KHAZAD', lpad('', 65535, gen_uuid()), lpad('',16, uuid_to_char( gen_uuid() )), lpad('', 8, uuid_to_char( gen_uuid() )) ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'RC5', lpad('', 65535, gen_uuid()), lpad('',16, uuid_to_char( gen_uuid() )), lpad('', 8, uuid_to_char( gen_uuid() )) ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'RC6', lpad('', 65535, gen_uuid()), lpad('',16, uuid_to_char( gen_uuid() )), lpad('',16, uuid_to_char( gen_uuid() )) ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( '"SAFER+"', lpad('', 65535, gen_uuid()), lpad('',16, uuid_to_char( gen_uuid() )), lpad('',16, uuid_to_char( gen_uuid() )) ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'TWOFISH', lpad('', 65535, gen_uuid()), lpad('',16, uuid_to_char( gen_uuid() )), lpad('',16, uuid_to_char( gen_uuid() )) ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'XTEA', lpad('', 65535, gen_uuid()), lpad('',16, uuid_to_char( gen_uuid() )), lpad('', 8, uuid_to_char( gen_uuid() )) ); + + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'CHACHA20', lpad('', 65535, gen_uuid()), lpad('',16, uuid_to_char( gen_uuid() )), lpad('', 8, uuid_to_char( gen_uuid() )) ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'RC4', lpad('', 65535, gen_uuid()), lpad('',16, uuid_to_char( gen_uuid() )), null ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'SOBER128', lpad('', 65535, gen_uuid()), lpad('',16, uuid_to_char( gen_uuid() )), lpad('', 8, uuid_to_char( gen_uuid() )) ); + + + -- Should cause FAILS: invalid length of keys: + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'AES', lpad('', 65535, gen_uuid()), lpad('',11, uuid_to_char( gen_uuid() )), lpad('',16, uuid_to_char( gen_uuid() )) ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'ANUBIS', lpad('', 65535, gen_uuid()), lpad('',12, uuid_to_char( gen_uuid() )), lpad('',16, uuid_to_char( gen_uuid() )) ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'BLOWFISH', lpad('', 65535, gen_uuid()), lpad('',13, uuid_to_char( gen_uuid() )), lpad('', 8, uuid_to_char( gen_uuid() )) ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'KHAZAD', lpad('', 65535, gen_uuid()), lpad('',14, uuid_to_char( gen_uuid() )), lpad('', 8, uuid_to_char( gen_uuid() )) ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'RC5', lpad('', 65535, gen_uuid()), lpad('',15, uuid_to_char( gen_uuid() )), lpad('', 8, uuid_to_char( gen_uuid() )) ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'RC6', lpad('', 65535, gen_uuid()), lpad('',17, uuid_to_char( gen_uuid() )), lpad('',16, uuid_to_char( gen_uuid() )) ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( '"SAFER+"', lpad('', 65535, gen_uuid()), lpad('',18, uuid_to_char( gen_uuid() )), lpad('',16, uuid_to_char( gen_uuid() )) ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'TWOFISH', lpad('', 65535, gen_uuid()), lpad('',19, uuid_to_char( gen_uuid() )), lpad('',16, uuid_to_char( gen_uuid() )) ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'XTEA', lpad('', 65535, gen_uuid()), lpad('',20, uuid_to_char( gen_uuid() )), lpad('', 8, uuid_to_char( gen_uuid() )) ); + + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'CHACHA20', lpad('', 65535, gen_uuid()), lpad('',21, uuid_to_char( gen_uuid() )), lpad('', 8, uuid_to_char( gen_uuid() )) ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'RC4', lpad('', 65535, gen_uuid()), lpad('',22, uuid_to_char( gen_uuid() )), null ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'SOBER128', lpad('', 65535, gen_uuid()), lpad('',23, uuid_to_char( gen_uuid() )), lpad('', 8, uuid_to_char( gen_uuid() )) ); + + + -- Should cause FAILS: invalid length of IVs: + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'AES', lpad('', 65535, gen_uuid()), lpad('',16, uuid_to_char( gen_uuid() )), lpad('',11, uuid_to_char( gen_uuid() )) ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'ANUBIS', lpad('', 65535, gen_uuid()), lpad('',16, uuid_to_char( gen_uuid() )), lpad('',13, uuid_to_char( gen_uuid() )) ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'BLOWFISH', lpad('', 65535, gen_uuid()), lpad('',16, uuid_to_char( gen_uuid() )), lpad('',15, uuid_to_char( gen_uuid() )) ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'KHAZAD', lpad('', 65535, gen_uuid()), lpad('',16, uuid_to_char( gen_uuid() )), lpad('',17, uuid_to_char( gen_uuid() )) ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'RC5', lpad('', 65535, gen_uuid()), lpad('',16, uuid_to_char( gen_uuid() )), lpad('',19, uuid_to_char( gen_uuid() )) ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'RC6', lpad('', 65535, gen_uuid()), lpad('',16, uuid_to_char( gen_uuid() )), lpad('',21, uuid_to_char( gen_uuid() )) ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( '"SAFER+"', lpad('', 65535, gen_uuid()), lpad('',16, uuid_to_char( gen_uuid() )), lpad('',23, uuid_to_char( gen_uuid() )) ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'TWOFISH', lpad('', 65535, gen_uuid()), lpad('',16, uuid_to_char( gen_uuid() )), lpad('',25, uuid_to_char( gen_uuid() )) ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'XTEA', lpad('', 65535, gen_uuid()), lpad('',26, uuid_to_char( gen_uuid() )), lpad('',27, uuid_to_char( gen_uuid() )) ); + + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'CHACHA20', lpad('', 65535, gen_uuid()), lpad('',16, uuid_to_char( gen_uuid() )), lpad('',29, uuid_to_char( gen_uuid() )) ); + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'RC4', lpad('', 65535, gen_uuid()), lpad('',16, uuid_to_char( gen_uuid() )), lpad('',31, uuid_to_char( gen_uuid() )) ); -- IV not needed for this alg + insert into test( crypto_alg, source_text, crypto_key, crypto_iv) values( 'SOBER128', lpad('', 65535, gen_uuid()), lpad('',16, uuid_to_char( gen_uuid() )), lpad('',33, uuid_to_char( gen_uuid() )) ); + + commit; + + set term ^; + create or alter procedure sp_block_test(a_alg varchar(30)) + returns( + encryption_algorithm varchar(30) + ,encryption_mode varchar(10) + ,enc_key_octet_length int + ,enc_init_vector_octet_length int + ,encrypted_equals_to_decrypted boolean + ,encryption_finish_gdscode int + ) as + declare v_encrypted blob; + declare v_encrypt_sttm blob; + declare v_decrypt_sttm blob; + declare s_source_text blob; + declare s_decrypted_text blob; + begin + delete from gtt_tmp; + for + select + t.source_text + ,t.crypto_alg + ,t.crypto_key + ,t.crypto_iv + from test t + where upper( t.crypto_alg ) = upper( :a_alg ) + as cursor c + do begin + + encryption_algorithm = c.crypto_alg; + enc_key_octet_length = octet_length( c.crypto_key ); + enc_init_vector_octet_length = octet_length( c.crypto_iv ); + + -- block_cipher ::= { AES | ANUBIS | BLOWFISH | KHAZAD | RC5 | RC6 | SAFER+ | TWOFISH | XTEA } + -- mode ::= { CBC | CFB | CTR | ECB | OFB } + + for + select 'CBC' as mode from rdb$database union all + select 'CFB' from rdb$database union all -- AES + select 'CTR' from rdb$database union all -- AES + select 'ECB' from rdb$database union all + select 'OFB' from rdb$database -- AES + as cursor cm + do begin + + encryption_mode = cm.mode; + encrypted_equals_to_decrypted = null; + encryption_finish_gdscode = null; + begin + + -- Mode should be specified for block ciphers. + -- Initialization vector (IV) should be specified for block ciphers in all modes except ECB and all stream ciphers except RC4. + + insert into gtt_tmp(source_text) values(c.source_text); + s_source_text = c.source_text; + + -- This caused crash when length of string was 65535; sent letter to Alex et al, 11.11.2019: + -- v_encrypt_sttm = 'select encrypt( q''{' || c.source_text || '}'' using ' || c.crypto_alg || ' mode ofb key q''{' || c.crypto_key || '}'' iv q''{' || c.crypto_iv || '}'' ) from rdb$database'; + + + v_encrypt_sttm = 'select encrypt( t.source_text using ' || c.crypto_alg || ' mode ' || cm.mode || ' key q''{' || c.crypto_key || '}'' iv q''{' || c.crypto_iv || '}'' ) from gtt_tmp t'; + execute statement v_encrypt_sttm into v_encrypted; + + update gtt_tmp t set t.encrypted_text = :v_encrypted; + + v_decrypt_sttm = 'select decrypt( t.encrypted_text using ' || c.crypto_alg || ' mode ' || cm.mode || ' key q''{' || c.crypto_key || '}'' iv q''{' || c.crypto_iv || '}'' ) from gtt_tmp t'; + execute statement v_decrypt_sttm into s_decrypted_text; + + + encrypted_equals_to_decrypted = false; + if ( hash(s_source_text) = hash(s_decrypted_text) ) then + if (s_source_text = s_decrypted_text) then + encrypted_equals_to_decrypted = true; + + when any do + begin + -- 335545230 : TomCrypt library error: Invalid argument provided. + -- 335545234 : Encrypting in CBC mode + + -- 335545224 : Initialization vector (IV) makes no sense for chosen cipher and/or mode + encryption_finish_gdscode = gdscode; + end + end + + suspend; + + delete from gtt_tmp; + + end + end + + end + ^ + + + create or alter procedure sp_stream_test(a_alg varchar(30)) + returns( + encryption_algorithm varchar(30) + ,enc_key_octet_length int + ,enc_init_vector_octet_length int + ,encrypted_equals_to_decrypted boolean + ,encryption_finish_gdscode int + ) as + declare v_encrypted blob; + declare v_encrypt_sttm blob; + declare v_decrypt_sttm blob; + declare s_source_text blob; + declare s_decrypted_text blob; + declare iv_suffix blob; + begin + delete from gtt_tmp; + for + select + t.source_text + ,t.crypto_alg + ,t.crypto_key + ,t.crypto_iv + from test t + where upper( t.crypto_alg ) = upper( :a_alg ) + as cursor c + do begin + + -- stream_cipher ::= { CHACHA20 | RC4 | SOBER128 } + + encryption_algorithm = c.crypto_alg; + enc_key_octet_length = octet_length( c.crypto_key ); + encryption_finish_gdscode = null; + begin + + -- Mode should be specified for block ciphers. + -- Initialization vector (IV) should be specified for block ciphers in all modes except ECB and all stream ciphers except RC4. + + insert into gtt_tmp(source_text) values(c.source_text); + s_source_text = c.source_text; + + enc_init_vector_octet_length = 0; + if ( upper( :a_alg ) = upper('RC4') ) then + iv_suffix= ''; + else + begin + iv_suffix= ' iv q''{' || c.crypto_iv || '}'' '; + enc_init_vector_octet_length = octet_length(c.crypto_iv); + end + + v_encrypt_sttm = 'select encrypt( t.source_text using ' || c.crypto_alg || ' key q''{' || c.crypto_key || '}'' ' || iv_suffix || ') from gtt_tmp t'; + execute statement v_encrypt_sttm into v_encrypted; + + update gtt_tmp t set t.encrypted_text = :v_encrypted; + + v_decrypt_sttm = 'select decrypt( t.encrypted_text using ' || c.crypto_alg || ' key q''{' || c.crypto_key || '}'' ' || iv_suffix || ') from gtt_tmp t'; + execute statement v_decrypt_sttm into s_decrypted_text; + + + encrypted_equals_to_decrypted = false; + if ( hash(s_source_text) = hash(s_decrypted_text) ) then + if (s_source_text = s_decrypted_text) then + encrypted_equals_to_decrypted = true; + + when any do + begin + encryption_finish_gdscode = gdscode; + end + end + + suspend; + delete from gtt_tmp; + + end + + end + ^ + set term ;^ + commit; + + --------------------------------------- + + set bail off; + + -- 1. Main checks: + -- ############### + -- 1.1 Block cipher: + select * from sp_block_test('aes'); + select * from sp_block_test('anubis'); + select * from sp_block_test('blowfish'); + select * from sp_block_test('khazad'); + select * from sp_block_test('rc5'); + select * from sp_block_test('rc6'); + select * from sp_block_test('"safer+"'); + select * from sp_block_test('twofish'); + select * from sp_block_test('xtea'); + + -- 1.2 Stream cipher: + select * from sp_stream_test('chacha20'); + select * from sp_stream_test('rc4'); + select * from sp_stream_test('sober128'); + + + -- 2. Auxiliary checks: + -- #################### + -- 2.1. "Counter length (CTR_LENGTH, bytes) may be specified only in CTR mode, default is the size of IV." + select encrypt( 'fooriobar' using AES mode CTR key q'{A8586F1E-DB13-4D}' iv q'{D2FF255D-EDE3-44}' CTR_LENGTH -123 ) as ctr_clause_case_1 from rdb$database; + select encrypt( 'fooriobar' using AES mode CTR key q'{A8586F1E-DB13-4D}' iv q'{D2FF255D-EDE3-44}' CTR_LENGTH 0 ) as ctr_clause_case_2 from rdb$database; + select encrypt( 'fooriobar' using AES mode CTR key q'{A8586F1E-DB13-4D}' iv q'{D2FF255D-EDE3-44}' CTR_LENGTH 16 ) as ctr_clause_case_3 from rdb$database; + select encrypt( 'fooriobar' using AES mode CTR key q'{A8586F1E-DB13-4D}' iv q'{D2FF255D-EDE3-44}' CTR_LENGTH 123 ) as ctr_clause_case_4 from rdb$database; + select encrypt( 'fooriobar' using AES mode OFB key q'{A8586F1E-DB13-4D}' iv q'{D2FF255D-EDE3-44}' CTR_LENGTH 16 ) as ctr_clause_case_5 from rdb$database; + + -- 2.2. "Initial counter value (COUNTER) may be specified only for CHACHA20 cipher, default is 0." + select encrypt( 'fooriobar' using CHACHA20 key q'{1110FB89-AD32-4E}' iv q'{114E811E}' counter 0 ) from rdb$database; + -- lead to crash, letter 11.11.2019 15:35 --> select encrypt( 'fooriobar' using CHACHA20 key q'{1110FB89-AD32-4E}' iv q'{114E811E}' counter cast(null as bigint) ) from rdb$database; + select encrypt( 'fooriobar' using CHACHA20 key q'{1110FB89-AD32-4E}' iv q'{114E811E}' counter 1 ) from rdb$database; + select encrypt( 'fooriobar' using CHACHA20 key q'{1110FB89-AD32-4E}' iv q'{114E811E}' counter -9223372036854775808 ) from rdb$database; + select encrypt( 'fooriobar' using CHACHA20 key q'{1110FB89-AD32-4E}' iv q'{114E811E}' counter 9223372036854775807 ) from rdb$database; + + + -- 2.3. Following query led to crash, see letter to Alex, 30.12.2018 00:15 + -- Expected STDERR: + -- Statement failed, SQLSTATE = 22023 + -- Invalid key length 9, need 16 or 32 + select encrypt('QweRtYUioP' using chacha20 key '192837465' iv '777555333') as invalid_params from rdb$database; + + + -- 4. "Functions return BLOB when first argument is blob and varbinary for all text types." + set sqlda_display on; + with + d as ( + select + cast('Functions return BLOB when first argument is blob and varbinary for all text types.' as blob) as d_blob + ,cast('Functions return BLOB when first argument is blob and varbinary for all text types.' as varchar(255) ) as d_char + ,x'0154090759DF' as e_bin + from rdb$database + ) + select + encrypt( d.d_blob using AES mode CTR key q'{A8586F1E-DB13-4D}' iv q'{D2FF255D-EDE3-44}' ) as e_blob + ,encrypt( d.d_char using AES mode CTR key q'{A8586F1E-DB13-4D}' iv q'{D2FF255D-EDE3-44}' ) as e_char + ,decrypt( d.e_bin using sober128 key 'AbcdAbcdAbcdAbcd' iv '01234567') as d_bin + from d + rows 0; + set sqlda_display off; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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: 0 NONE + : name: DECRYPT alias: D_BIN + : table: owner: + + """ +expected_stderr_1 = """ + 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 + """ + +@pytest.mark.version('>=4.0') +def test_core_5970_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5972.py b/tests/bugs/test_core_5972.py new file mode 100644 index 00000000..59a0cc4e --- /dev/null +++ b/tests/bugs/test_core_5972.py @@ -0,0 +1,190 @@ +#coding:utf-8 +# +# id: bugs.core_5972 +# title: External engine trigger crashing server if table have computed field +# decription: +# We use supplied UDR example which operates with TRIGGER for replication purpuses. +# Two databases are used here: one is 'main' (which is created by fbtest) and second +# is auxiliary and serves as slave (replica). +# +# We create table PERSONS in both databases, its DDL is taken from examples code. +# This table will be normally replicated until we add COMPUTED BY field to it. +# +# When such field is added and we issue INSERT command, standard exception must raise: +# Statement failed, SQLSTATE = 42000 +# Execute statement error at isc_dsql_prepare : +# 335544569 : Dynamic SQL Error +# 335544436 : SQL error code = -206 +# 335544578 : Column unknown +# 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 mprepl.fdb +# -At block line: ... +# -At trigger 'PERSONS_REPLICATE' +# +# We expect appearing of this exception (see try/except block): check its class and content of message. +# +# Confirmed crash on 4.0.0.1346 (built 17-dec-2018). +# Checked on 4.0.0.1391 (built 22-jan-2019): all fine, got expected exception. +# Cheked also on: +# 4.0.0.1803 SS: 2.494s. +# 4.0.0.1796 CS: 3.500s. +# 3.0.6.33265 SS: 1.578s. +# 3.0.6.33247 CS: 2.032s. +# tracker_id: CORE-5972 +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('.* At block line.*', 'At block'), ('read-only column.*', 'read-only column'), ('Statement.*', 'Statement'), ('Data source.*', 'Data source'), ('.* At trigger.*', 'At trigger')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import time +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# this_db = db_conn.database_name +# fb_major=db_conn.engine_version +# +# #-------------------------------------------- +# +# 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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# table_ddl=''' +# create table persons ( +# id integer not null, +# name varchar(60) not null, +# address varchar(60), +# info blob sub_type text, +# comp int computed by (1) -- COMPUTED_BY FIELD AS IT IS DESCRIBED IN THE TICKET +# ); +# ''' +# +# fdb_repl = os.path.join(context['temp_directory'],'tmp_5972_repl.fdb') +# cleanup( (fdb_repl,) ) +# +# con_repl = fdb.create_database( dsn = 'localhost:%(fdb_repl)s' % locals() ) +# con_repl.execute_immediate( table_ddl ) +# con_repl.commit() +# con_repl.close() +# +# +# db_conn.execute_immediate( table_ddl ) +# db_conn.commit() +# +# ddl_for_replication=''' +# create table replicate_config ( +# name varchar(31) not null, +# data_source varchar(255) not null +# ); +# +# insert into replicate_config (name, data_source) +# values ('ds1', '%(fdb_repl)s'); +# +# create trigger persons_replicate +# after insert on persons +# external name 'udrcpp_example!replicate!ds1' +# engine udr; +# +# create trigger persons_replicate2 +# after insert on persons +# external name 'udrcpp_example!replicate_persons!ds1' +# engine udr; +# commit; +# +# ''' % locals() +# +# f_apply_ddl_sql = open( os.path.join(context['temp_directory'],'tmp_5972.sql'), 'w', buffering = 0) +# f_apply_ddl_sql.write( ddl_for_replication ) +# flush_and_close( f_apply_ddl_sql ) +# +# f_apply_ddl_log = open( '.'.join( (os.path.splitext( f_apply_ddl_sql.name )[0], 'log') ), 'w', buffering = 0) +# subprocess.call( [ context['isql_path'], dsn, '-q', '-i', f_apply_ddl_sql.name ], stdout = f_apply_ddl_log, stderr = subprocess.STDOUT) +# flush_and_close( f_apply_ddl_log ) +# +# #-------------------------------- +# +# cur = db_conn.cursor() +# try: +# cur.execute( "insert into persons values (1, 'One', 'some_address', 'some_blob_info')" ) +# db_conn.commit() +# except Exception as e: +# print('Got exception:', sys.exc_info()[0]) +# print(e[0]) +# +# finally: +# db_conn.close() +# cur.close() +# +# if fb_major >= 4.0: +# runProgram( context['isql_path'], ['-q', dsn], 'ALTER EXTERNAL CONNECTIONS POOL CLEAR ALL;' ) +# +# cleanup( (f_apply_ddl_sql.name, f_apply_ddl_log.name, fdb_repl) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Got exception: + Error while executing SQL statement: + - SQLCODE: -901 + - 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 bt-repo mp mp_5972_repl.fdb + - At block line: 9, col: 5 + - At trigger 'PERSONS_REPLICATE' + """ + +@pytest.mark.version('>=3.0.6') +@pytest.mark.xfail +def test_core_5972_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5973.py b/tests/bugs/test_core_5973.py new file mode 100644 index 00000000..db1a80f2 --- /dev/null +++ b/tests/bugs/test_core_5973.py @@ -0,0 +1,117 @@ +#coding:utf-8 +# +# id: bugs.core_5973 +# title: Handling FP overflow in double precision value when converting from decfloat. +# decription: +# Confirmed wrong result for numbers that have ABS greater than max double precision limit in: WI-T4.0.0.1340 +# Works fine on: WI-T4.0.0.1457 +# +# 09.12.2019. +# Updated syntax for SET BIND command because it was changed in 11-nov-2019. +# Changed expected std_err: added text with "SQL error code = -303" +# +# Checked on: WI-T4.0.0.1685, 1.38 s. +# 05.03.2021: added subst.: max. floating point precision on Linux is 15 rather than on Windows (16 digits). +# +# tracker_id: CORE-5973 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('0.0000000000000000', '0.000000000000000')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + -- OLD SYNTAX: set decfloat bind double precision; + -- Syntax after 11-nov-2019: + -- https://github.com/FirebirdSQL/firebird/commit/a77295ba153e0c17061e2230d0ffdbaf08839114 + -- See also: doc/sql.extensions/README.set_bind.md: + -- SET BIND OF type-from TO { type-to | LEGACY }; + -- SET BIND OF type NATIVE; + + set bind of decfloat to double precision; + + set decfloat traps to Overflow, Underflow; + + -- Following four statements should raise exception: + -- ################################################# + + + -- Statement failed, SQLSTATE = 22003 + -- Decimal float overflow. The exponent of a result is greater than the magnitude allowed. + select cast( 9.999999999999999999999999999999999E6144 as decfloat(34)) as greatest_df34_for_pos_scope from rdb$database; + select cast(-9.999999999999999999999999999999999E6144 as decfloat(34)) as freatest_df34_for_neg_scope from rdb$database; + + -- Statement failed, SQLSTATE = 22003 + -- Decimal float underflow. The exponent of a result is less than the magnitude allowed. + select cast(1.0E-6143 as decfloat(34)) as approx_zero_df34_for_pos_scope from rdb$database; + select cast(-1.0E-6143 as decfloat(34)) as approx_zero__df34_for_neg_scope from rdb$database; + + + set decfloat traps to Inexact; + + -- Following four statements should NOT raise exception and issue: Infinity, Infinity, 0.000..., 0.000...: + -- ############################################################## + + -- This must issue Infinity instead of 0.000...: + select cast( 9.999999999999999999999999999999999E6144 as decfloat(34)) as greatest_df34_for_pos_scope from rdb$database; + + -- This must issue -Infinity instead of 0.000...: + select cast(-9.999999999999999999999999999999999E6144 as decfloat(34)) as greatest_df34_for_neg_scope from rdb$database; + + select cast(1.0E-6143 as decfloat(34)) as approx_zero_df34_for_pos_scope from rdb$database; + + select cast(-1.0E-6143 as decfloat(34)) as approx_zero_df34_for_neg_scope from rdb$database; + + quit; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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_1 = """ + Statement failed, SQLSTATE = 22003 + Dynamic SQL Error + -SQL error code = -303 + -Floating-point overflow. The exponent of a floating-point operation is greater than the magnitude allowed. + + Statement failed, SQLSTATE = 22003 + Dynamic SQL Error + -SQL error code = -303 + -Floating-point overflow. The exponent of a floating-point operation is greater than the magnitude allowed. + + Statement failed, SQLSTATE = 22003 + Dynamic SQL Error + -SQL error code = -303 + -Floating-point underflow. The exponent of a floating-point operation is less than the magnitude allowed. + + Statement failed, SQLSTATE = 22003 + Dynamic SQL Error + -SQL error code = -303 + -Floating-point underflow. The exponent of a floating-point operation is less than the magnitude allowed. + """ + +@pytest.mark.version('>=4.0') +def test_core_5973_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5974.py b/tests/bugs/test_core_5974.py new file mode 100644 index 00000000..8b44eba1 --- /dev/null +++ b/tests/bugs/test_core_5974.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_5974 +# title: Wrong result of select distinct with decfload/timezone/collated column +# decription: +# NB: this was regression because WI-T4.0.0.1249 (build 27.10.2018) worked OK. +# Confirmed wrong result on 4.0.0.1340 (build 08.12.2018) +# Checked on: 4.0.0.1347: OK, 2.844s. +# +# tracker_id: CORE-5974 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + recreate table test( d decfloat(34) ); + create index test_d on test(d); + commit; + + insert into test select 15514 from rdb$types rows 3; + commit; + --set plan on; + select distinct d+0 as d_distinct from test; + select d+0 as d_grouped_nat from test group by d+0; + select d as d_grouped_idx from test group by d; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + D_DISTINCT 15514 + D_GROUPED_NAT 15514 + D_GROUPED_IDX 15514 + """ + +@pytest.mark.version('>=4.0') +def test_core_5974_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5980.py b/tests/bugs/test_core_5980.py new file mode 100644 index 00000000..f8dcc77a --- /dev/null +++ b/tests/bugs/test_core_5980.py @@ -0,0 +1,85 @@ +#coding:utf-8 +# +# id: bugs.core_5980 +# title: Firebird crashes due to concurrent operations with expression indices +# decription: +# Scenario for reproducing was given by Vlad, letter 25-02-2020 19:15. +# Unfortuinately, this crash can occur only in developer build rather than release one. +# +# Although issues from ticket can NOT be reproduced, it was encountered in 2.5.0.26074 +# that statements from here lead DB to be corrupted: +# Error while commiting transaction: +# - SQLCODE: -902 +# - database file appears corrupt... +# - wrong page type +# - page 0 is of wrong type (expected 6, found 1) +# -902 +# 335544335 +# No such problem in 2.5.1 and above. +# Decided to add this .fbt just for check that DB will not be corrupted. +# +# TICKET ISSUE REMAINS IRREPRODUCIBLE (checked on following SuperServer builds: 2.5.1, 2.5.6, 2.5.9, 3.0.6, 4.0.0). +# +# tracker_id: CORE-5980 +# min_versions: ['2.5.1'] +# versions: 2.5.1 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import sys +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# fb_home = services.connect(host='localhost', user= user_name, password= user_password).get_home_directory() +# if db_conn.engine_version < 3: +# fb_home = os.path.join( fb_home, 'bin') +# +# db_conn.close() +# con1 = fdb.connect( dsn = dsn ) +# con2 = fdb.connect( dsn = dsn ) +# +# con1.execute_immediate('recreate table t1(id int)') +# con1.execute_immediate('create index t1_idx on t1 computed by (id + 0)') +# con1.commit() +# +# cur1 = con1.cursor() +# cur1.execute( 'insert into t1(id) values(?)', (1,) ) +# con1.commit() +# +# # this lead to corruption of database in 2.5.0 +# # page 0 is of wrong type (expected 6, found 1): +# # ----------------------- +# con2.execute_immediate('alter index t1_idx active') +# con2.commit() +# con2.close() +# +# con1.close() +# cur1.close() +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.1') +@pytest.mark.xfail +def test_core_5980_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5982.py b/tests/bugs/test_core_5982.py new file mode 100644 index 00000000..6e33801b --- /dev/null +++ b/tests/bugs/test_core_5982.py @@ -0,0 +1,108 @@ +#coding:utf-8 +# +# id: bugs.core_5982 +# title: error read permission for BLOB field, when it is input/output procedure`s parametr +# decription: +# Confirmed bug on WI-V3.0.4.33034 and WI-T4.0.0.1340. +# Checked on: +# 4.0.0.1421: OK, 2.098s. +# 3.0.5.33097: OK, 1.294s. +# +# 24.06.2020: changed min_version to 2.5 because problem was fixed in 2.5.9.27151. +# +# tracker_id: CORE-5982 +# min_versions: ['2.5.9'] +# versions: 2.5.9 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.9 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set term ^; + execute block as + begin + begin + execute statement 'drop user tmp$c5982' with autonomous transaction; + when any do begin end + end + end^ + set term ;^ + commit; + + + create user tmp$c5982 password '123'; + commit; + recreate table my_table ( + my_num integer + ,my_data blob + ); + commit; + + insert into my_table(my_num , my_data) values (1, 'qwerty'); + commit; + + set term ^; + create or alter procedure sp_worker(my_data blob) as + declare variable my_value blob; + begin + my_value = my_data ; + rdb$set_context('USER_SESSION', 'SP_WORKER', 'DONE BY ' || current_user ); + end + ^ + + create or alter procedure sp_main as + declare variable my_data blob; + begin + select my_data + from my_table + where my_num = 1 + into: my_data; + + execute procedure sp_worker(my_data); + + end + ^ + set term ;^ + commit; + + grant select on table my_table to procedure sp_main; + grant execute on procedure sp_worker to procedure sp_main; + grant execute on procedure sp_main to public; + commit; + + set list on; + + connect '$(DSN)' user 'tmp$c5982' password '123'; + + execute procedure sp_main; + select rdb$get_context('USER_SESSION', 'SP_WORKER') as result from rdb$database; + commit; + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + drop user tmp$c5982; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT DONE BY TMP$C5982 + """ + +@pytest.mark.version('>=2.5.9') +def test_core_5982_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5985.py b/tests/bugs/test_core_5985.py new file mode 100644 index 00000000..170e3bd6 --- /dev/null +++ b/tests/bugs/test_core_5985.py @@ -0,0 +1,108 @@ +#coding:utf-8 +# +# id: bugs.core_5985 +# title: Regression: ROLE does not passed in ES/EDS (specifying it in the statement is ignored) +# decription: +# Checked on: +# 400SS, build 4.0.0.1421: OK, 2.204s. +# 302SS, build 3.0.5.33097: OK, 1.214s. +# +# tracker_id: CORE-5985 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create user tmp$c5985_foo password '123'; + create user tmp$c5985_bar password '456'; + commit; + create role worker; + create role manager; + commit; + + grant worker to tmp$c5985_foo; + grant manager to tmp$c5985_bar; + commit; + + connect '$(DSN)' user 'tmp$c5985_bar' password '456' role manager; + + set list on; + select mon$user who_am_i, mon$role whats_my_role + from mon$attachments + where mon$attachment_id = current_connection; + + set term ^; + execute block returns(who_am_i varchar(31), whats_my_role varchar(31)) as + declare v_sttm varchar(2048); + declare v_user varchar(31) = 'tmp$c5985_foo'; + declare v_pswd varchar(31) = '123'; + declare v_role varchar(31) = 'WORKER'; + declare v_extd varchar(255); + begin + v_extd = 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME'); + v_sttm = 'select mon$user, mon$role from mon$attachments where mon$attachment_id = current_connection'; + + execute statement + v_sttm + on external v_extd + as user v_user password v_pswd role v_role + into + who_am_i, whats_my_role; + + suspend; + + end + ^ + set term ;^ + commit; + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + drop user tmp$c5985_foo; + drop user tmp$c5985_bar; + 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHO_AM_I TMP$C5985_BAR + WHATS_MY_ROLE MANAGER + + WHO_AM_I TMP$C5985_FOO + WHATS_MY_ROLE WORKER + """ + +@pytest.mark.version('>=3.0') +def test_core_5985_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5986.py b/tests/bugs/test_core_5986.py new file mode 100644 index 00000000..667841ac --- /dev/null +++ b/tests/bugs/test_core_5986.py @@ -0,0 +1,246 @@ +#coding:utf-8 +# +# id: bugs.core_5986 +# title: Incorrect evaluation of NULL IS [NOT] {FALSE | TRUE} +# decription: +# Test was implemented on the basis of 7IWD2-02-Foundation-2011-12.pdf, page 322 +# (as it was suggested by Mark Rotteveel in the ticket, see his note 17/Jan/19 03:13 PM). +# Checked on: +# 4.0.0.1421: OK, 1.485s. +# 3.0.5.33097: OK, 0.844s. +# +# tracker_id: CORE-5986 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set list on; + + -- General rules: "NOT(True) is False, NOT(False) is True, and NOT(Unknown) is Unknown" + select not true b1, not false b2, not unknown b3 + from rdb$database; + + -- Data for output in Truth-tables: + recreate table test( x boolean, y boolean ); + insert into test(x,y) select + true, true from rdb$database union all select + true, false from rdb$database union all select + true, unknown from rdb$database union all select + false, true from rdb$database union all select + false, false from rdb$database union all select + false, unknown from rdb$database union all select + unknown,true from rdb$database union all select + unknown,false from rdb$database union all select + unknown,unknown from rdb$database + ; + commit; + + -- Table 11. Truth table for the AND boolean operator. + select x, y, x and y as "x_AND_y" from test; + + -- Table 12. Truth table for the OR boolean operator. + select x, y, x or y as "x_OR_y" from test; + + -- Table 12. Truth table for the IS boolean operator. + --select x, y, x is y as "x_IS_y" from test; --> token unknown; doing this using ES + + set term ^; + execute block returns( x boolean, y boolean, "x_IS_y" boolean) as + declare run_expr varchar(128); + begin + for + select + x + ,y + ,''||coalesce(x,'unknown') || ' is ' || coalesce(y,'unknown') + from test + into x, y, run_expr + do begin + execute statement 'select ' || run_expr || ' from rdb$database' into "x_IS_y"; + suspend; + end + end + ^ + set term ;^ + /* + X Y x_AND_y + ======= ======= ======= + + + + + + + + + + + + X Y x_OR_y + ======= ======= ======= + + + + + + + + + + + + X Y x_IS_y + ======= ======= ======= + + + + + + + + + + */ + + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + B1 + B2 + B3 + + + X + Y + x_AND_y + + X + Y + x_AND_y + + X + Y + x_AND_y + + X + Y + x_AND_y + + X + Y + x_AND_y + + X + Y + x_AND_y + + X + Y + x_AND_y + + X + Y + x_AND_y + + X + Y + x_AND_y + + + X + Y + x_OR_y + + X + Y + x_OR_y + + X + Y + x_OR_y + + X + Y + x_OR_y + + X + Y + x_OR_y + + X + Y + x_OR_y + + X + Y + x_OR_y + + X + Y + x_OR_y + + X + Y + x_OR_y + + + X + Y + x_IS_y + + X + Y + x_IS_y + + X + Y + x_IS_y + + X + Y + x_IS_y + + X + Y + x_IS_y + + X + Y + x_IS_y + + X + Y + x_IS_y + + X + Y + x_IS_y + + X + Y + x_IS_y + """ + +@pytest.mark.version('>=3.0') +def test_core_5986_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5990.py b/tests/bugs/test_core_5990.py new file mode 100644 index 00000000..fa2b8257 --- /dev/null +++ b/tests/bugs/test_core_5990.py @@ -0,0 +1,182 @@ +#coding:utf-8 +# +# id: bugs.core_5990 +# title: Pool of external connections +# decription: +# Test assumes that firebird.conf contains: +# ExtConnPoolSize = 100 (or at any other value >= 6) +# ExtConnPoolLifeTime = 10 +# We run six execute blocks with COMMIT after each of them. +# When EDS pool is enabled then every new execute block will use the same attachment as it was established in the 1st EB. +# We check this by running query that show number of duplicates for each of N attachments: this number must be equal to N-1. +# ::: NB ::: +# Final statement must be 'ALTER EXTERNAL CONNECTIONS POOL CLEAR ALL' otherwise DB file will be kept by engine at least +# for 10 seconds after this test finish (see parameter 'ExtConnPoolLifeTime'). +# +# Thank hvlad for additional explanations, discuss in e-mail was 26.04.19 09:38. +# +# Checked on 4.0.0.1501 (both SS and CS): OK, 1.343s. +# +# tracker_id: CORE-5990 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate view v_conn as + select + cast(rdb$get_context('SYSTEM', 'EXT_CONN_POOL_SIZE') as int) as pool_size, + cast(rdb$get_context('SYSTEM', 'EXT_CONN_POOL_IDLE_COUNT') as int) as pool_idle, + cast(rdb$get_context('SYSTEM', 'EXT_CONN_POOL_ACTIVE_COUNT') as int) as pool_active, + cast(rdb$get_context('SYSTEM', 'EXT_CONN_POOL_LIFETIME') as int) as pool_lifetime + from rdb$database + ; + + create sequence g; + commit; + + recreate table att_info(id int, established_attach_id int); + commit; + + set term ^; + execute block as + begin + rdb$set_context('USER_SESSION', 'DBA_USER', 'SYSDBA'); + rdb$set_context('USER_SESSION', 'DBA_PSWD', 'masterkey'); + end + ^ + + execute block as + declare con1 int; + begin + execute statement 'select current_connection from rdb$database' + on external 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME') + as user rdb$get_context('USER_SESSION', 'DBA_USER') password rdb$get_context('USER_SESSION', 'DBA_PSWD') + into con1; + insert into att_info(id, established_attach_id) values( gen_id(g,1), :con1 ); + + end + ^ + commit -- <<< NOTA BENE <<<< C.O.M.M.I.T after each execute block <<< + ^ + + execute block as + declare con1 int; + begin + execute statement 'select current_connection from rdb$database' + on external 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME') + as user rdb$get_context('USER_SESSION', 'DBA_USER') password rdb$get_context('USER_SESSION', 'DBA_PSWD') + into con1; + insert into att_info(id, established_attach_id) values( gen_id(g,1), :con1 ); + + end + ^ + commit + ^ + + execute block as + declare con1 int; + begin + execute statement 'select current_connection from rdb$database' + on external 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME') + as user rdb$get_context('USER_SESSION', 'DBA_USER') password rdb$get_context('USER_SESSION', 'DBA_PSWD') + into con1; + insert into att_info(id, established_attach_id) values( gen_id(g,1), :con1 ); + + end + ^ + commit + ^ + + execute block as + declare con1 int; + begin + execute statement 'select current_connection from rdb$database' + on external 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME') + as user rdb$get_context('USER_SESSION', 'DBA_USER') password rdb$get_context('USER_SESSION', 'DBA_PSWD') + into con1; + insert into att_info(id, established_attach_id) values( gen_id(g,1), :con1 ); + + end + ^ + commit + ^ + + execute block as + declare con1 int; + begin + execute statement 'select current_connection from rdb$database' + on external 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME') + as user rdb$get_context('USER_SESSION', 'DBA_USER') password rdb$get_context('USER_SESSION', 'DBA_PSWD') + into con1; + insert into att_info(id, established_attach_id) values( gen_id(g,1), :con1 ); + + end + ^ + commit + ^ + + execute block as + declare con1 int; + begin + execute statement 'select current_connection from rdb$database' + on external 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME') + as user rdb$get_context('USER_SESSION', 'DBA_USER') password rdb$get_context('USER_SESSION', 'DBA_PSWD') + into con1; + insert into att_info(id, established_attach_id) values( gen_id(g,1), :con1 ); + + end + ^ + commit + ^ + set term ;^ + + --set echo on; + --select * from v_conn; + --select a.id, a.established_attach_id, count(*)over(partition by established_attach_id)-1 dup_cnt + + set list on; + select a.id, count(*)over(partition by established_attach_id)-1 dup_cnt + from att_info a + order by id; + + ALTER EXTERNAL CONNECTIONS POOL CLEAR ALL; -- !! mandatory otherwise database file will be kept by engine and fbtest will not able to drop it !! + commit; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + DUP_CNT 5 + ID 2 + DUP_CNT 5 + ID 3 + DUP_CNT 5 + ID 4 + DUP_CNT 5 + ID 5 + DUP_CNT 5 + ID 6 + DUP_CNT 5 + """ + +@pytest.mark.version('>=4.0') +def test_core_5990_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_5991.py b/tests/bugs/test_core_5991.py new file mode 100644 index 00000000..08ad3b74 --- /dev/null +++ b/tests/bugs/test_core_5991.py @@ -0,0 +1,301 @@ +#coding:utf-8 +# +# id: bugs.core_5991 +# title: Trace could not work correctly with quoted file names in trace configurations +# decription: +# Thank Vlad for suggestions. +# +# NOTE-1. Bug will NOT appear if PATTERN is used in database-section! +# In order to reproduce bug one need to create config file for trace with following +# _SINGLE_ file name in databases-section: +# ===== +# database = 'C:\\FBTESTING\\qa +# bt-repo mp mp_5991.o'clock.fdb' +# { +# enabled = true +# time_threshold = 0 +# log_initfini = false +# log_connections = true +# log_transactions = true +# log_statement_finish = true +# } +# ===== +# (path 'C:\\FBTESTING\\qa +# bt-repo mp' will be replaced with actual test DB location) +# +# Then we start trace session. +# +# NOTE-2: if this trace session will be forced to wait about 10 seconds, then error message will appear +# with text "error while parsing trace configuration" but DB name will be securityN.fdb. +# Moreover, an operation with any DB which has name different than specified in database-section will +# raise this error, and its text can be misleading that trace did not started at all or was terminated. +# This is because another bug (not yet fixed) which Vlad mentioned privately in letter 26.02.19 23:37. +# +# :::: NB ::::: +# We can IGNORE this error message despite it contains phrase "Error creating trace session" and go on. +# Trace session actually *WILL* be created and we have to check this here by further actions with DB. +# ::::::::::::: +# +# After this, we create database with the same name by calling fdb.create_database(). +# NOTE-3: we have to enclose DB file in double quotes and - moreover - duplicate single apostoph, +# otherwise fdb driver will create DB without it, i.e.: "tmp_5991.oclock.fdb". +# +# At the second step we do trivial statement and drop this database (tmp_5991.o'clock.fdb). +# Finally, we wait at least two seconds because trace buffer must be flushed to disk, stop trace session +# and then - open trace log for parsing it. +# Trace log MUST contain all of following phrases (each of them must occur in log at least one time): +# 1. Trace session ID started +# 2. CREATE_DATABASE +# 3. START_TRANSACTION +# 4. EXECUTE_STATEMENT_FINISH +# 5. ROLLBACK_TRANSACTION +# 6. DROP_DATABASE +# We check each line of trace for matching to patterns (based on these phrases) and put result into Python dict. +# Resulting dict must contain 'FOUND' and value for every of its keys (patterns). +# +# Confirmed bug on 3.0.4.33054. +# 01-mar-2021: adapted for work on Linux. +# Checked on 4.0.0.2377 and 3.0.8.33415 (both Windows and Linux). +# +# +# tracker_id: CORE-5991 +# min_versions: ['3.0.5'] +# versions: 3.0.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [('Trying to create.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import re +# import time +# import subprocess +# from subprocess import Popen +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# fdb_file=os.path.join( '$(DATABASE_LOCATION)', "tmp_5991.o'clock.fdb" ) +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# cleanup( fdb_file, ) +# +# if os.name == 'nt': +# fdb_trace = fdb_file.replace('/','\\\\') +# else: +# fdb_trace = fdb_file +# +# ##################################################################### +# # Prepare config for trace session that will be launched by call of FBSVCMGR: +# +# txt = ''' database = '%(fdb_trace)s' +# { +# enabled = true +# time_threshold = 0 +# log_initfini = false +# log_connections = true +# log_transactions = true +# log_statement_finish = true +# } +# ''' % locals() +# +# trc_cfg=open( os.path.join(context['temp_directory'],'tmp_trace_5991.cfg'), 'w') +# trc_cfg.write(txt) +# flush_and_close( trc_cfg ) +# +# ##################################################################### +# # Async. launch of trace session using FBSVCMGR action_trace_start: +# +# trc_log=open( os.path.join(context['temp_directory'],'tmp_trace_5991.log'), 'w') +# # Execute a child program in a new process, redirecting STDERR to the same target as of STDOUT: +# p_svcmgr = Popen( [ context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_start", +# "trc_cfg", trc_cfg.name +# ], +# stdout=trc_log, +# stderr=subprocess.STDOUT +# ) +# +# # 08.01.2020. This delay is mandatory, otherwise file with trace session info can remain (sometimes) +# # empty when we will read it at the next step: +# time.sleep(1) +# +# # Determine active trace session ID (for further stop): +# ######################## +# trc_lst=open( os.path.join(context['temp_directory'],'tmp_trace_5991.lst'), 'w') +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_list"], +# stdout=trc_lst, stderr=subprocess.STDOUT +# ) +# flush_and_close( trc_lst ) +# +# # Session ID: 5 +# # user: +# # date: 2015-08-27 15:24:14 +# # flags: active, trace +# +# sid_pattern = re.compile('Session\\s+ID[:]{0,1}\\s+\\d+', re.IGNORECASE) +# +# trc_ssn=0 +# with open( trc_lst.name,'r') as f: +# for line in f: +# if sid_pattern.search( line ) and len( line.split() ) == 3: +# trc_ssn = line.split()[2] +# break +# +# # Result: `trc_ssn` is ID of active trace session. +# # We have to terminate trace session that is running on server BEFORE we termitane process `p_svcmgr` +# +# if trc_ssn==0: +# print("Error parsing trace session ID.") +# flush_and_close( trc_log ) +# +# else: +# +# ########### W O R K W I T H D A T A B A S E ######## +# +# print( 'Trying to create: "localhost:%s"' % fdb_file.replace("'","''") ) +# con = fdb.create_database( dsn = "localhost:%s" % fdb_file.replace("'","''") ) +# print( 'Database created OK.' ) +# cur = con.cursor() +# cur.execute( "select 'Database name contains single quote.' as result from mon$database where lower(mon$database_name) similar to '%[\\/](tmp_5991.o''clock).fdb'") +# for r in cur: +# print(r[0]) +# +# cur.close() +# con.drop_database() +# print( 'Database dropped OK.') +# ##################################################################### +# +# # ::: NB ::: Here we have to be idle at least 2s (two seconds) otherwise trace log will +# # not contain some or all of messages about create DB, start Tx, ES, Tx and drop DB. +# # See also discussion with hvlad, 08.01.2020 15:16 +# # (subj: "action_trace_stop does not flush trace log (fully or partially)") +# time.sleep(2) +# +# # Stop trace session: +# ##################### +# +# trc_lst=open(trc_lst.name, "a") +# trc_lst.seek(0,2) +# +# subprocess.call( [ context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_stop", +# "trc_id",trc_ssn +# ], +# stdout=trc_lst, +# stderr=subprocess.STDOUT +# ) +# flush_and_close( trc_lst ) +# +# # 23.02.2021. DELAY FOR AT LEAST 1 SECOND REQUIRED HERE! +# # Otherwise trace log can remain empty. +# time.sleep(1) +# +# p_svcmgr.terminate() +# flush_and_close( trc_log ) +# +# allowed_patterns = { +# '1. TRACE_START' : re.compile('Trace\\s+session\\s+ID\\s+\\d+\\s+started\\.*', re.IGNORECASE) +# ,'2. DB_CREATION' : re.compile('[.*]*CREATE_DATABASE\\.*', re.IGNORECASE) +# ,'3. TX_START' : re.compile('[.*]*START_TRANSACTION\\.*', re.IGNORECASE) +# ,'4. STATEMENT_DONE' : re.compile('[.*]*EXECUTE_STATEMENT_FINISH\\.*', re.IGNORECASE) +# ,'5. TX_FINISH' : re.compile('[.*]*ROLLBACK_TRANSACTION\\.*', re.IGNORECASE) +# ,'6. DB_REMOVAL' : re.compile('[.*]*DROP_DATABASE\\.*', re.IGNORECASE) +# } +# +# found_patterns={} +# +# with open( trc_log.name,'r') as f: +# for line in f: +# if line.rstrip().split(): +# for k,v in allowed_patterns.items(): +# if v.search(line): +# found_patterns[k] = 'FOUND' +# +# for k,v in sorted( found_patterns.items() ): +# print( 'Pattern', k, ':', v) +# +# if len( found_patterns ) < len( allowed_patterns ): +# print('==== INCOMPLETE TRACE LOG: ====') +# with open( trc_log.name,'r') as f: +# for line in f: +# if line.rstrip().split(): +# print(' ' + line) +# print('=' * 31) +# +# #< cond "if trc_ssn>0" +# +# # cleanup: +# ########## +# time.sleep(1) +# cleanup( (trc_lst, trc_cfg, trc_log) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Trying to create: "localhost:C:/FBTESTING/qa/fbt-repo/tmp/tmp_5991.o''clock.fdb" + Database created OK. + Database name contains single quote. + Database dropped OK. + Pattern 1. TRACE_START : FOUND + Pattern 2. DB_CREATION : FOUND + Pattern 3. TX_START : FOUND + Pattern 4. STATEMENT_DONE : FOUND + Pattern 5. TX_FINISH : FOUND + Pattern 6. DB_REMOVAL : FOUND + """ + +@pytest.mark.version('>=3.0.5') +@pytest.mark.xfail +def test_core_5991_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_5995.py b/tests/bugs/test_core_5995.py new file mode 100644 index 00000000..e5a6c85f --- /dev/null +++ b/tests/bugs/test_core_5995.py @@ -0,0 +1,186 @@ +#coding:utf-8 +# +# id: bugs.core_5995 +# title: Creator user name is empty in user trace sessions +# decription: +# We create trivial config for trace, start session and stop it. +# Trace list must contain string: ' user: SYSDBA ' (without apostrophes). +# We search this by string using pattern matching: such line MUST contain at least two words +# (it was just 'user:' before this bug was fixed). +# Confirmed bug on: 3.0.2.32658, 3.0.4.33054, 3.0.5.33097 +# Checked on: +# 4.0.0.1421: OK, 5.186s. +# 3.0.5.33106: OK, 4.070s. +# +# tracker_id: CORE-5995 +# min_versions: ['3.0.5'] +# versions: 3.0.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import re +# import time +# import subprocess +# from subprocess import Popen +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# fdb_file=db_conn.database_name +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# ##################################################################### +# # Prepare config for trace session that will be launched by call of FBSVCMGR: +# +# txt = ''' database = %[\\\\\\\\/]bugs.core_5995.fdb +# { +# enabled = true +# time_threshold = 0 +# log_initfini = false +# log_statement_finish = true +# } +# ''' +# trc_cfg=open( os.path.join(context['temp_directory'],'tmp_trace_5995.cfg'), 'w') +# trc_cfg.write(txt) +# flush_and_close( trc_cfg ) +# +# ##################################################################### +# # Async. launch of trace session using FBSVCMGR action_trace_start: +# +# trc_log=open( os.path.join(context['temp_directory'],'tmp_trace_5995.log'), 'w') +# # Execute a child program in a new process, redirecting STDERR to the same target as of STDOUT: +# p_svcmgr = Popen( [ context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_start", +# "trc_cfg", trc_cfg.name +# ], +# stdout=trc_log, +# stderr=subprocess.STDOUT +# ) +# +# # Wait! Trace session is initialized not instantly! +# time.sleep(1) +# +# ##################################################################### +# +# # Determine active trace session ID (for further stop): +# trc_lst=open( os.path.join(context['temp_directory'],'tmp_trace_5995.lst'), 'w') +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_list"], +# stdout=trc_lst, stderr=subprocess.STDOUT +# ) +# flush_and_close( trc_lst ) +# +# # Session ID: 5 +# # user: +# # date: 2015-08-27 15:24:14 +# # flags: active, trace +# +# usr_pattern = re.compile('user[:]{0,1}\\s+\\S+', re.IGNORECASE) +# sid_pattern = re.compile('Session\\s+ID[:]{0,1}\\s+\\d+', re.IGNORECASE) +# +# trcssn=0 +# trcusr='' +# with open( trc_lst.name,'r') as f: +# for line in f: +# if sid_pattern.search( line ) and len( line.split() ) == 3: +# trcssn = line.split()[2] +# +# if usr_pattern.search(line) and len( line.split() ) >= 2: +# trcusr = line.split()[1] +# +# if trcssn and trcusr: +# break +# +# # Result: `trcssn` is ID of active trace session. +# # We have to terminate trace session that is running on server BEFORE we termitane process `p_svcmgr` +# if trcssn==0: +# print("Error parsing trace session ID.") +# else: +# +# ##################################################################### +# # Stop trace session: +# ##################################################################### +# +# trc_lst=open(trc_lst.name, "a") +# trc_lst.seek(0,2) +# print( 'Trace was started by: ' + trcusr ) +# +# subprocess.call( [ context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_stop", +# "trc_id",trcssn +# ], +# stdout=trc_lst, +# stderr=subprocess.STDOUT +# ) +# flush_and_close( trc_lst ) +# p_svcmgr.terminate() +# +# flush_and_close( trc_log ) +# +# # cleanup: +# ########## +# time.sleep(1) +# cleanup( (trc_lst, trc_cfg, trc_log) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Trace was started by: SYSDBA + """ + +@pytest.mark.version('>=3.0.5') +@pytest.mark.xfail +def test_core_5995_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6000.py b/tests/bugs/test_core_6000.py new file mode 100644 index 00000000..d60eb246 --- /dev/null +++ b/tests/bugs/test_core_6000.py @@ -0,0 +1,159 @@ +#coding:utf-8 +# +# id: bugs.core_6000 +# title: gbak issues "Your user name and password are not defined" when command switch "-fe(tch_password) ..." is specified when run as service +# decription: +# ::: NOTE ::: +# Presense of ISC_PASSWORD variable had higher priority than '-fe password_file' command switch before this ticket was fixed. +# This means that command "gbak -se ... -fe " PASSED without errors! +# +# Test creates two files, one with correct SYSDBA password and second with invalid (hope that such password: T0t@1lywr0ng - is not in use for SYSDBA). +# Also, test exports default SYSDBA password ('masterkey' ) to ISC_PASSWORD variable. +# Then we do following: +# 1) "gbak -fe " - this should FAIL with issuing "user name and password are not defined" in STDERR, +# despite that ISC_USER isnot empty and contains valid password +# 2) UNSET variable ISC_PASSWORD and run "gbak -fe " - this should PASS without any STDOUT or STDERR. +# +# Confirmed wrong behaviour on: 4.0.0.1627, 3.0.5.33178 +# Works fine on: 4.0.0.1629, 3.438s; 3.0.5.33179, 2.859s. +# +# tracker_id: CORE-6000 +# min_versions: ['3.0.5'] +# versions: 3.0.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# from subprocess import Popen +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# this_fdb = db_conn.database_name +# this_fbk=os.path.join(context['temp_directory'],'tmp_core_6000.fbk') +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# cleanup( this_fbk, ) +# +# f_psw_correct=open( os.path.join(context['temp_directory'],'tmp_psw_6000__OK.dat'), 'w') +# f_psw_correct.write( user_password ) +# flush_and_close( f_psw_correct ) +# +# f_psw_invalid=open( os.path.join(context['temp_directory'],'tmp_psw_6000_BAD.dat'), 'w') +# f_psw_invalid.write( 'T0t@1lywr0ng' ) +# flush_and_close( f_psw_invalid ) +# +# #---------------------- backup with '-fe ' -------------------------- +# +# f_log_invalid = open( os.path.join(context['temp_directory'],'tmp_isql_6000_BAD.log'), 'w') +# f_err_invalid = open( os.path.join(context['temp_directory'],'tmp_isql_6000_BAD.err'), 'w') +# +# subprocess.call( [context['gbak_path'], '-b', '-se', 'localhost:service_mgr', '-user', user_name ,'-fe', f_psw_invalid.name, this_fdb, this_fbk ], +# stdout=f_log_invalid, +# stderr=f_err_invalid +# ) +# flush_and_close( f_err_invalid ) +# flush_and_close( f_log_invalid ) +# +# #---------------------- backup with '-fe ' -------------------------- +# +# del os.environ["ISC_PASSWORD"] +# +# f_log_correct = open( os.path.join(context['temp_directory'],'tmp_isql_6000__OK.log'), 'w') +# f_err_correct = open( os.path.join(context['temp_directory'],'tmp_isql_6000__OK.err'), 'w') +# +# subprocess.call( [context['gbak_path'], '-b', '-se', 'localhost:service_mgr', '-user', user_name ,'-fe', f_psw_correct.name, this_fdb, this_fbk ], +# stdout=f_log_correct, +# stderr=f_err_correct +# ) +# flush_and_close( f_err_correct ) +# flush_and_close( f_log_correct ) +# +# # This file should be EMPTY: +# ########################### +# with open(f_log_invalid.name) as f: +# for line in f: +# print('UNEXPECTED STDOUT FOR INVALID PASSWORD: '+line) +# +# with open(f_err_invalid.name) as f: +# for line in f: +# print('EXPECTED STDERR FOR INVALID PASSWORD: '+line) +# +# with open(f_log_correct.name) as f: +# for line in f: +# print('UNEXPECTED STDOUT FOR CORRECT PASSWORD: '+line) +# +# with open(f_err_correct.name) as f: +# for line in f: +# print('UNEXPECTED STDERR FOR CORRECT PASSWORD: '+line) +# +# +# # CLEANUP +# ######### +# time.sleep(1) +# cleanup( ( f_psw_correct, f_psw_invalid, f_log_correct, f_err_correct, f_log_invalid, f_err_invalid, this_fbk ) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + EXPECTED STDERR FOR INVALID PASSWORD: gbak: ERROR:Your user name and password are not defined. Ask your database administrator to set up a Firebird login. + EXPECTED STDERR FOR INVALID PASSWORD: gbak:Exiting before completion due to errors + """ + +@pytest.mark.version('>=3.0.5') +@pytest.mark.xfail +def test_core_6000_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6003.py b/tests/bugs/test_core_6003.py new file mode 100644 index 00000000..698eab37 --- /dev/null +++ b/tests/bugs/test_core_6003.py @@ -0,0 +1,92 @@ +#coding:utf-8 +# +# id: bugs.core_6003 +# title: RDB$GET_TRANSACTION_CN works different in Super and Classic +# decription: +# Confirmed bug on 4.0.0.2411 CS: got null instead of positive number. +# Checked on intermediate build 4.0.0.2416 (08-apr-2021 09:56) - all OK. +# +# NB-1: bug can be reproduced using ISQL but it must be lacunhed with '-n' command switch. +# NB-2: connection-1 (which finally asks value of rdb$get_transaction_cn()) must start Tx1 +# *BEFORE* connection-2 will start his Tx2. +# +# tracker_id: CORE-6003 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import fdb +# import time +# import subprocess +# +# os.environ["ISC_USER"] = 'SYSDBA' +# os.environ["ISC_PASSWORD"] = 'masterkey' +# db_conn.close() +# +# #FB_CLNT=sys.argv[1] +# DB_NAME = dsn # 'localhost:e40' +# +# custom_tpb = fdb.TPB() +# custom_tpb.lock_resolution = fdb.isc_tpb_wait +# custom_tpb.isolation_level = fdb.isc_tpb_concurrency +# +# con1 = fdb.connect(dsn=DB_NAME) # , fb_library_name = FB_CLNT ) +# tx1a = con1.trans( default_tpb = custom_tpb ) +# tx1a.begin() +# +# +# con2 = fdb.connect(dsn=DB_NAME) # , fb_library_name = FB_CLNT ) +# tx2a = con2.trans( default_tpb = custom_tpb ) +# tx2a.begin() +# +# cur2 = tx2a.cursor() +# cur2.execute('select current_transaction from rdb$database') +# for r in cur2: +# trn2 = int(r[0]) +# tx2a.commit() +# +# # >>> DO NOT put it here! tx1a must be started BEFORE tx2a! >>> tx1a.begin() +# +# cur1 = tx1a.cursor() +# cur1.execute("select 'Result is ' || iif( rdb$get_transaction_cn(%d) is null, 'INCORRECT: NULL.', 'expected: NOT null.') from rdb$database" % trn2) +# for r in cur1: +# print(r[0]) +# tx1a.commit() +# +# #print(con1.firebird_version) +# cur1.close() +# cur2.close() +# con1.close() +# con2.close() +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Result is expected: NOT null. + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_6003_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6018.py b/tests/bugs/test_core_6018.py new file mode 100644 index 00000000..c8017133 --- /dev/null +++ b/tests/bugs/test_core_6018.py @@ -0,0 +1,148 @@ +#coding:utf-8 +# +# id: bugs.core_6018 +# title: Make it possible to start multiple transactions (possibly in different attachments) using the same initial transaction snapshot +# decription: +# We open first connect using FDB and set custom transaction parameter block which is used to start SNAPSHOT transaction. +# Within this first transaction (tx1a) we insert into test table record with value = -2 and commit this Tx. +# Then we do start next transaction (also SNAPSHOT; its name = 'tx1b') and obtain value of RDB$GET_CONTEXT('SYSTEM', 'SNAPSHOT_NUMBER'). +# Also, in this second 'tx1b' we add one more record into table with value = -1 using autonomous transaction --> BOTH records should be seen +# in another attachment that will be started after this moment. +# But if this (new) attachment will start Tx with requirement to use snapshot that was for Tx1a then it must see only FIRST record with value=-2. +# +# We launch then ISQL for establish another transaction and make it perform two transactions: +# 1) 'set transaction snapshot' --> must extract both records from test table +# === vs === +# 2) 'set transaction snapshot at number %(snap_num)s' --> must extract only FIRST record with value = -2. +# +# THis is done TWO times: when based snapshot is KNOWN (i.e. tx1b is alive) and after tx1b is committed and base is unknown. +# Second ISQL launch must issue error: +# Statement failed, SQLSTATE = 0B000 +# Transaction's base snapshot number does not exist +# +# Checked on: 4.0.0.1457 (SS,CS) -- works fine. +# +# tracker_id: CORE-6018 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table tsn(sn int); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import re +# import time +# import subprocess +# from subprocess import Popen +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.close() +# +# customTPB = ( [ fdb.isc_tpb_concurrency, fdb.isc_tpb_nowait ] ) +# con1 = fdb.connect( dsn = dsn ) +# +# tx1a=con1.trans( default_tpb = customTPB ) +# +# cur1=tx1a.cursor() +# cur1.execute('insert into tsn(sn) values( -2 )' ) +# tx1a.commit() +# +# sql_get_sn=''' +# execute block returns(o_sn bigint) as +# begin +# o_sn = RDB$GET_CONTEXT('SYSTEM', 'SNAPSHOT_NUMBER'); +# suspend; +# +# in autonomous transaction do +# insert into tsn(sn) values( -1 ); +# end +# ''' +# +# tx1b=con1.trans( default_tpb = customTPB ) +# cur1=tx1b.cursor() +# cur1.execute( sql_get_sn ) +# +# snap_num = -1 +# for r in cur1: +# snap_num = r[0] +# # print( r[0] ) +# +# for m in ('yet exists', 'does not exists'): +# sql_chk_sn=''' +# -- NB!! looks strange but it seems that this 'SET BAIL ON' does not work here because +# -- both records will be extracted in any case. // todo later: check it! +# --set bail on; +# set count on; +# commit; +# set transaction snapshot; +# select 'Tx base snapshot: %(m)s' as msg, t.sn as set_tx_snapshot_without_num from tsn t order by sn; +# commit; +# set transaction snapshot at number %(snap_num)s; +# select 'Tx base snapshot: %(m)s' as msg, t.sn as set_tx_snapshot_at_number_N from tsn t order by sn; +# commit; +# quit; +# ''' % ( locals() ) +# +# #print(sql_chk_sn) +# +# runProgram('isql', [ dsn, '-q' ], sql_chk_sn) +# if tx1b: +# tx1b.commit() +# +# cur1.close() +# con1.close() +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG SET_TX_SNAPSHOT_WITHOUT_NUM + ============================ =========================== + Tx base snapshot: yet exists -2 + Tx base snapshot: yet exists -1 + Records affected: 2 + MSG SET_TX_SNAPSHOT_AT_NUMBER_N + ============================ =========================== + Tx base snapshot: yet exists -2 + Records affected: 1 + + MSG SET_TX_SNAPSHOT_WITHOUT_NUM + ================================= =========================== + Tx base snapshot: does not exists -2 + Tx base snapshot: does not exists -1 + Records affected: 2 + MSG SET_TX_SNAPSHOT_AT_NUMBER_N + ================================= =========================== + Tx base snapshot: does not exists -2 + Tx base snapshot: does not exists -1 + Records affected: 2 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 0B000 + Transaction's base snapshot number does not exist + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_6018_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6023.py b/tests/bugs/test_core_6023.py new file mode 100644 index 00000000..29dd9890 --- /dev/null +++ b/tests/bugs/test_core_6023.py @@ -0,0 +1,136 @@ +#coding:utf-8 +# +# id: bugs.core_6023 +# title: FB4 unable to overwrite older ods database +# decription: +# Database (employee.fdb) with ODS 11.2 has been compressed to .zip and stored in {FBT_REPO}/files subdirectory. +# Test unpacks this .fdb and: +# 1) tries to print its header (using gstat -h) - it must fail with "Wrong ODS version, expected NN, encountered 11" +# (where is ODS major number that is supported by current FB version); +# 2) makes attempt to replace this .fdb by following action: +# /gbak -b stdout | /gbak -rep stdin +# 3) tries to make connection to just restored DB and write result. +# +# If replacement was successfull then connection *must* be estabished and it is enough to print SIGN(current_connection). +# Outcome of this ("1") means that all completed OK. +# +# Confirmed bug on 4.0.0.1803: attempt to restore fails with: +# gbak: ERROR:unsupported on-disk structure for file ...; found 11.2, support 13.0 +# gbak: ERROR: IProvider::attachDatabase failed when loading mapping cache +# gbak: ERROR:failed to create database localhost:... +# gbak:Exiting before completion due to errors +# +# ::: CAUTION ::: +# DO NOT try to run this test on any other FB build just after check build 4.0.0.1803! +# One need to STOP instance 4.0.0.1803 before this or wait for at least 130 seconds, +# otherwise checked FB will crash. Problem relates to shmem-files in C:\\ProgramData +# irebird\\. +# This problem has the same nature that is described in CORE-6476. +# See letter to Vlad et al 16.02.2021 09:02 +# ("Crash of 4.0.0.2365 when attempt to get server version just after doing the same on 4.0.0.1803") +# ::::::::::::::: +# +# Checked on 4.0.0.2365 - all OK. +# +# tracker_id: CORE-6023 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('expected [\\d]+', 'expected NN')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import zipfile +# import time +# import subprocess +# from subprocess import PIPE +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# #----------------------------------- +# +# 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() +# os.fsync(file_handle.fileno()) +# +# file_handle.close() +# +# #-------------------------------------------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# +# #-------------------------------------------- +# #print(db_conn.firebird_version) +# db_conn.close() +# +# zf = zipfile.ZipFile( os.path.join(context['files_location'],'core_6023-ods-11_2-fdb.zip') ) +# tmp_fdb_to_replace = os.path.join( '$(DATABASE_LOCATION)', 'core_6023-ods-11_2.fdb' ) +# +# zf.extract( os.path.split(tmp_fdb_to_replace)[1], '$(DATABASE_LOCATION)') +# zf.close() +# +# # Ensure that we really have deal with .fdb file with old ODS. +# # Must issue: "Wrong ODS version, expected 13, encountered 11": +# runProgram('gstat',['-h', tmp_fdb_to_replace]) +# +# f_restore_with_replace=open( os.path.join(context['temp_directory'],'tmp_6023_rep.err'), 'w') +# +# p_sender = subprocess.Popen( [ context['gbak_path'], '-b', dsn, 'stdout' ], stdout=PIPE) +# p_getter = subprocess.Popen( [ context['gbak_path'], '-rep', 'stdin', 'localhost:' + os.path.join( '$(DATABASE_LOCATION)', tmp_fdb_to_replace ) ], stdin = p_sender.stdout, stdout = PIPE, stderr = f_restore_with_replace) +# p_sender.stdout.close() +# p_getter_stdout, p_getter_stderr = p_getter.communicate() +# +# flush_and_close(f_restore_with_replace) +# +# with open(f_restore_with_replace.name) as f: +# for line in f: +# print('UNEXPECTED STDERR: '+line) +# +# +# runProgram( 'isql',['-q', 'localhost:' + os.path.join( '$(DATABASE_LOCATION)', tmp_fdb_to_replace )], 'set list on; select sign(current_connection) as restore_with_replace_result from rdb$database;' ) +# +# cleanup( (tmp_fdb_to_replace, f_restore_with_replace.name) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESTORE_WITH_REPLACE_RESULT 1 + """ +expected_stderr_1 = """ + Wrong ODS version, expected 13, encountered 11 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_6023_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6024.py b/tests/bugs/test_core_6024.py new file mode 100644 index 00000000..a5039431 --- /dev/null +++ b/tests/bugs/test_core_6024.py @@ -0,0 +1,107 @@ +#coding:utf-8 +# +# id: bugs.core_6024 +# title: FB3.0.4.33063 vs FB3.0.5.33100 manual plan cause "index cannot be used in the specified plan" +# decription: +# Confirmed bug on 3.0.5.33152 (got "index PK_WPLATA cannot be used in the specified plan"). +# On 3.0.5.33212 execution for expression WITHOUT explicit 'plan ...' clause will use: PLAN (W ORDER PK_WPLATA). +# On 3.0.5.33215 both plans are as expected. +# +# ::: NB ::: +# As of 20.12.2019, FB 4.0.0.1693 has the same problem and not yet fixed. +# +# tracker_id: CORE-6024 +# min_versions: ['3.0.5'] +# versions: 3.0.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table wplata + ( + dyr_id smallint not null, + okres_numer char(7) not null, + insp_id smallint not null, + konto_id smallint not null, + wplata_data_wyciagu date not null, + wplata_nr_wyciagu varchar(10) not null, + wplata_nr_pozycji smallint not null, + wplata_kontrahent_id integer, + constraint pk_wplata primary key (dyr_id,insp_id,konto_id,wplata_data_wyciagu,wplata_nr_wyciagu,wplata_nr_pozycji) + ); + + create index ixa_wplata__kontrahent__pk on wplata (wplata_kontrahent_id,dyr_id); + + ----------------------------------------------------------------------------------------------------- + + set plan on; + + select + w.dyr_id + , w.insp_id + , w.konto_id + , w.wplata_data_wyciagu + , w.wplata_nr_wyciagu + , w.wplata_nr_pozycji + from wplata w + where + w.wplata_kontrahent_id in (1452) + and w.dyr_id = 6 + order by + w.dyr_id + , w.insp_id + , w.konto_id + , w.wplata_data_wyciagu + , w.wplata_nr_wyciagu + , w.wplata_nr_pozycji + ; + + + select + w.dyr_id + , w.insp_id + , w.konto_id + , w.wplata_data_wyciagu + , w.wplata_nr_wyciagu + , w.wplata_nr_pozycji + from wplata w + where + w.wplata_kontrahent_id in (1452) + and w.dyr_id = 6 + plan(w order pk_wplata index(ixa_wplata__kontrahent__pk)) + order by + w.dyr_id + , w.insp_id + , w.konto_id + , w.wplata_data_wyciagu + , w.wplata_nr_wyciagu + , w.wplata_nr_pozycji + ; + + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN SORT (W INDEX (IXA_WPLATA__KONTRAHENT__PK)) + PLAN (W ORDER PK_WPLATA INDEX (IXA_WPLATA__KONTRAHENT__PK)) + """ + +@pytest.mark.version('>=3.0.5') +def test_core_6024_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6028.py b/tests/bugs/test_core_6028.py new file mode 100644 index 00000000..2b767df7 --- /dev/null +++ b/tests/bugs/test_core_6028.py @@ -0,0 +1,231 @@ +#coding:utf-8 +# +# id: bugs.core_6028 +# title: Trigger on system table restored in FB3 database and can't be deleted +# decription: +# We restore here database that was created in FB 2.5.9 and contained triggers for tables RDB$RELATION_FIELDS, MON$STATEMENTS and MON$ATTACHMENTS. +# Table RDB$RELATION_FIELDS had triggers BEFORE INSERT and AFTER INSERT. Monitoring tabled had triggers BEFORE DELETE and AFTER DELETE. +# Also, table 'TLOG' is in this database, and this table serves as log for actions: create/drop table; delete from mon$statements and delete from mon$attachments. +# For DDL like 'create table test(x int)' and 'drop table test' table TLOG will contain two records which are added there by triggers on RDB$RELATION_FIELDS. +# Further, if we create addition connection and run statement which returns at least one record (like 'select ... from rdb$database') then in 2.5 two recors +# had been added into TLOG for each of: 'DELETE FROM MON$STATEMENTS' and 'DELETE FROM MON$ATTACHMENTS'. +# +# Finally, BEFORE fix of this ticket issue (e.g. in WI-V3.0.5.33109): +# 1) restored database contained following triggers: TRG_MON_ATTACHMENTS*, TRG_MON_STATEMENTS* and TRG_RDB_REL_FIELDS* +# 2) statements 'create table' and 'drop table' led to logging following records in TLOG: +# rdb$relation_fields: record is to be created +# rdb$relation_fields: record has been created +# rdb$relation_fields: record is to be removed +# rdb$relation_fields: record has been removed +# 3) command 'delete from mon$statement' (when there was another non-system connection with one running or completed statement) +# led to logging these records in TLOG: +# mon$statements: record is to be removed +# mon$statements: record has been removed +# 4) command 'delete from mon$attachments' (when there was another non-system connection) led to logging these records in TLOG: +# mon$attachments: record is to be removed +# mon$attachments: record has been removed +# +# All of above mentioned should NOT appear in a database that is restored AFTER this ticket was fixed. +# Finally, we try to create three new triggers for tables rdb$relation-fields, mon$statements and mon$attachments. +# All of these attempts must FAIL with: +# ======== +# - no permission for ALTER access to TABLE RDB$RELATION_FIELDS +# -607 +# 335544351 +# ======== +# Ticket issue confirmed on: 3.0.5.33109 +# Checked on 3.0.5.33115: OK, 3.721s. +# +# tracker_id: CORE-6028 +# min_versions: ['3.0.5'] +# versions: 3.0.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import fdb +# import time +# import zipfile +# import difflib +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# zf = zipfile.ZipFile( os.path.join(context['files_location'],'core_6028_25.zip') ) +# tmpfbk = 'core_6028_25.fbk' +# zf.extract( tmpfbk, '$(DATABASE_LOCATION)') +# zf.close() +# +# tmpfbk='$(DATABASE_LOCATION)'+tmpfbk +# tmpfdb='$(DATABASE_LOCATION)'+'tmp_core_6028.fdb' +# +# f_restore_log=open( os.path.join(context['temp_directory'],'tmp_core_6028_restore.log'), 'w') +# subprocess.check_call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "action_restore", +# "bkp_file", tmpfbk, +# "dbname", tmpfdb, +# "res_replace", +# "verbose" +# ], +# stdout=f_restore_log, +# stderr=subprocess.STDOUT) +# flush_and_close( f_restore_log ) +# +# # https://pythonhosted.org/fdb/reference.html#fdb.Cursor +# +# con_worker=fdb.connect(dsn = 'localhost:'+tmpfdb) +# con_worker_attachment_id = con_worker.attachment_id +# +# con_worker.execute_immediate( 'create table test(id int)' ) +# con_worker.commit() +# con_worker.execute_immediate( 'drop table test' ) +# con_worker.commit() +# +# cur_worker=con_worker.cursor() +# cur_worker.execute( "select coalesce(rt.rdb$trigger_name, 'NO USER-DEFINED TRIGGERS IN JUST RESTORED DATABASE.') from rdb$database rd left join rdb$triggers rt on rt.rdb$system_flag is distinct from 1 order by 1" ) +# for r in cur_worker: +# print( r[0] ) +# +# con_killer=fdb.connect(dsn = 'localhost:'+tmpfdb) +# cur_killer=con_killer.cursor() +# +# cur_killer.execute( 'delete from mon$statements s where s.mon$attachment_id = %d' % con_worker_attachment_id ) +# con_killer.commit() +# +# cur_killer.execute( 'delete from mon$attachments a where a.mon$attachment_id = %d' % con_worker_attachment_id ) +# con_killer.commit() +# +# cur_killer.execute( "select coalesce(t.action, 'NO ACTIONS WAS LOGGED IN THE TABLE TLOG.') as sys_tabs_action from rdb$database rd left join tlog t on 1=1" ) +# for r in cur_killer: +# print( r[0] ) +# +# try: +# cur_worker.close() +# con_worker.close() +# except Exception,e: +# pass +# +# #----------------------- +# +# ddl_probes=[] +# +# ddl_probes.append( +# ''' +# create or alter trigger new_trg_rdb_rel_flds_bi for rdb$relation_fields active before insert position 0 as +# begin +# insert into tlog(id, action) values( gen_id(g, 111), 'rdb$relation_fields: record is to be created' ); +# end +# ''' +# ) +# +# ddl_probes.append( +# ''' +# create or alter trigger new_trg_mon_stm_bd for mon$statements active before delete position 0 as +# begin +# insert into tlog(id, action) values( gen_id(g, 222), 'mon$statements: record is to be removed' ); +# end +# ''' +# ) +# +# ddl_probes.append( +# ''' +# create or alter trigger new_trg_mon_att_bd for mon$attachments active before delete position 0 as +# begin +# insert into tlog(id, action) values( gen_id(g, 333), 'mon$attachments: record is to be removed' ); +# end +# ''' +# ) +# +# for s in ddl_probes: +# try: +# con_killer.execute_immediate( s ) +# except Exception,e: +# print( e[0].split('\\n')[-1] ) # Get last substring from error message: "- no permission for ALTER access to TABLE RDB$RELATION_FIELDS" +# print( e[1] ) # SQLCODE: -607 +# print( e[2] ) # gdscode: 335544351L +# +# #----------------------- +# +# cur_killer.close() +# con_killer.close() +# +# +# # Cleanup: +# ########## +# time.sleep(1) +# cleanup( (tmpfbk, tmpfdb, f_restore_log) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + NO USER-DEFINED TRIGGERS IN JUST RESTORED DATABASE. + NO ACTIONS WAS LOGGED IN THE TABLE TLOG. + + - no permission for ALTER access to TABLE RDB$RELATION_FIELDS + -607 + 335544351 + - no permission for ALTER access to TABLE MON$STATEMENTS + -607 + 335544351 + - no permission for ALTER access to TABLE MON$ATTACHMENTS + -607 + 335544351 + """ + +@pytest.mark.version('>=3.0.5') +@pytest.mark.xfail +def test_core_6028_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6033.py b/tests/bugs/test_core_6033.py new file mode 100644 index 00000000..20dde4bb --- /dev/null +++ b/tests/bugs/test_core_6033.py @@ -0,0 +1,48 @@ +#coding:utf-8 +# +# id: bugs.core_6033 +# title: SUBSTRING(CURRENT_TIMESTAMP) does not work +# decription: +# Confirmed bug on WI-T4.0.0.1457, got: +# === +# Statement failed, SQLSTATE = 22001 +# arithmetic exception, numeric overflow, or string truncation +# -string right truncation +# -expected length 34, actual 38 +# === +# Checked on 4.0.0.1479: OK, 1.299s. +# +# tracker_id: CORE-6033 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + execute block as + declare c varchar(100); + begin + c = substring(current_timestamp from 1); + end + ^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=4.0') +def test_core_6033_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_6034.py b/tests/bugs/test_core_6034.py new file mode 100644 index 00000000..f6c293a8 --- /dev/null +++ b/tests/bugs/test_core_6034.py @@ -0,0 +1,69 @@ +#coding:utf-8 +# +# id: bugs.core_6034 +# title: The original time zone should be set to the current time zone at routine invocation +# decription: +# Confirmed bug on 4.0.0.1457: FAILED. +# Checked on 4.0.0.1479: OK, 1.377s. +# +# tracker_id: CORE-6034 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set term ^; + execute block returns (ts1 varchar(100), ts2 varchar(100)) + as + declare procedure p0 returns (t1 timestamp with time zone, t2 timestamp with time zone) as + begin + set time zone 'America/New_York'; + t1 = current_timestamp; + set time zone local; + t2 = current_timestamp; + end + + declare procedure p1 returns (t1 timestamp with time zone, t2 timestamp with time zone) as + begin + set time zone 'America/Los_Angeles'; + execute procedure p0 returning_values t1, t2; + end + declare t1 timestamp with time zone; + declare t2 timestamp with time zone; + begin + -- Initial time zone: 'America/Sao_Paulo'; + execute procedure p1 returning_values t1, t2; + ts1 = substring( cast(t1 as varchar(100)) from 26 ); + ts2 = substring( cast(t2 as varchar(100)) from 26 ); + suspend; + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TS1 America/New_York + TS2 America/Los_Angeles + """ + +@pytest.mark.version('>=4.0') +def test_core_6034_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6038.py b/tests/bugs/test_core_6038.py new file mode 100644 index 00000000..cd71b078 --- /dev/null +++ b/tests/bugs/test_core_6038.py @@ -0,0 +1,79 @@ +#coding:utf-8 +# +# id: bugs.core_6038 +# title: Srp user manager sporadically creates users which can not attach +# decription: +# 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. +# Given 'N_LIMIT' is number of iterations, probability of success for ALL of +# them is 7.5%, and when N_LIMIT is 1000 then p = 0.004%. +# 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. +# +# 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. +# +# :::NOTE::: +# A new bug was found during this test implementation, affected 4.0 Classic only: CORE-6080. +# +# Checked on: +# 3.0.5.33140, SS: OK, 14.864s. +# 4.0.0.1530, SS: OK, 22.478s. +# 4.0.0.1530, Cs: OK, 39.576s. -- NB: Classic mode failed until core-6080 was fixed +# +# tracker_id: CORE-6038 +# min_versions: ['3.0.5'] +# versions: 3.0.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import fdb +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# N_LIMIT = 256 +# # ^ +# # | ############################### +# # +-------------------### number of iterations ### +# # ############################### +# +# CHECK_USR = 'tmp$c6038_srp' +# CHECK_PWD = 'QweRty#6038$=' +# +# for i in range(0, N_LIMIT): +# db_conn.execute_immediate( "create or alter user %(CHECK_USR)s password '%(CHECK_PWD)s' using plugin Srp" % locals() ) +# db_conn.commit() +# con_check = fdb.connect( dsn = dsn, user = CHECK_USR, password = CHECK_PWD ) +# con_check.close() +# db_conn.execute_immediate( "drop user %(CHECK_USR)s using plugin Srp" % locals() ) +# db_conn.commit() +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0.5') +@pytest.mark.xfail +def test_core_6038_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6040.py b/tests/bugs/test_core_6040.py new file mode 100644 index 00000000..6c5b4f74 --- /dev/null +++ b/tests/bugs/test_core_6040.py @@ -0,0 +1,119 @@ +#coding:utf-8 +# +# id: bugs.core_6040 +# title: Metadata script extracted using ISQL is invalid/incorrect when table has COMPUTED BY field +# decription: +# Confirmed bug on 3.0.5.33118, 4.0.0.1485 +# NB: 'collate' clause must present in DDL of computed_by field, otherwise extracted metadata script will be correct. +# +# Checked on: +# 4.0.0.1487: OK, 3.674s. +# 3.0.5.33120: OK, 2.622s. +# +# tracker_id: CORE-6040 +# min_versions: ['3.0.5'] +# versions: 3.0.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import time +# import subprocess +# import fdb +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.close() +# +# tmpfdb='$(DATABASE_LOCATION)'+'tmp_core_6040.fdb' +# +# if os.path.isfile( tmpfdb ): +# os.remove( tmpfdb ) +# +# con = fdb.create_database( dsn = 'localhost:'+tmpfdb, charset = 'win1252' ) +# con.close() +# con=fdb.connect( dsn = 'localhost:'+tmpfdb ) +# +# sql_ddl=''' +# recreate table users ( +# f01 varchar(32) character set win1252 not null collate win_ptbr +# ,f02 computed by ( f01 collate win_ptbr ) +# ) +# ''' +# con.execute_immediate(sql_ddl) +# con.commit() +# +# f_meta_sql = open( os.path.join(context['temp_directory'],'tmp_meta_6040.sql'), 'w') +# f_meta_err = open( os.path.join(context['temp_directory'],'tmp_meta_6040.err'), 'w') +# +# subprocess.call( [ "isql", "-x", "-ch", "win1252", 'localhost:'+tmpfdb], +# stdout = f_meta_sql, +# stderr = f_meta_err +# ) +# +# f_meta_sql.close() +# f_meta_err.close() +# +# con.execute_immediate('drop table users') +# con.commit() +# con.close() +# +# f_apply_log = open( os.path.join(context['temp_directory'],'tmp_apply_6040.log'), 'w') +# f_apply_err = open( os.path.join(context['temp_directory'],'tmp_apply_6040.err'), 'w') +# +# subprocess.call( [ "isql", "-ch", "win1252", 'localhost:'+tmpfdb, "-i", f_meta_sql.name ], +# stdout = f_apply_log, +# stderr = f_apply_err +# ) +# +# f_apply_log.close() +# f_apply_err.close() +# +# os.remove( tmpfdb ) +# time.sleep(1) +# +# with open( f_meta_err.name,'r') as f: +# for line in f: +# print("METADATA EXTRACTION PROBLEM, STDERR: "+line) +# +# with open( f_apply_log.name,'r') as f: +# for line in f: +# print("METADATA APPLYING PROBLEM, STDOUT: "+line) +# +# with open( f_apply_err.name,'r') as f: +# for line in f: +# print("METADATA APPLYING PROBLEM, STDERR: "+line) +# +# +# f_list=(f_meta_sql, f_meta_err, f_apply_log, f_apply_err) +# for i in range(len(f_list)): +# if os.path.isfile(f_list[i].name): +# os.remove(f_list[i].name) +# +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0.5') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_6040_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6043.py b/tests/bugs/test_core_6043.py new file mode 100644 index 00000000..ae1936b5 --- /dev/null +++ b/tests/bugs/test_core_6043.py @@ -0,0 +1,287 @@ +#coding:utf-8 +# +# id: bugs.core_6043 +# title: GTTs do not release used space +# decription: +# === For FB 3.x === +# Test obtains full path to $fb_home via FBSVCMGR info_get_env. +# Then it makes copy of file 'databases.conf' that is in $fb_home directory because +# following lines will be added to that 'databases.conf': +# === +# tmp_6043_keep = ... +# { +# ClearGTTAtRetaining = 0 +# } +# After this, it does connect to this alias and run statements from ticket with commit/rollback retain. +# We check that: +# * COMMIT RETAIN preserves record that was inserted in the statement before this commit; +# * ROLLBACK RETAIN does NOT delete record that was inserted before COMMIT RETAIN. +# +# Then we check the same for ClearGTTAtRetaining = 1 (i.e. for default value) - just to ensure that it works. +# Finally, previous databases.conf file is restored in initial state. +# +# === For FB 4.x === +# It is enough just to run ISQL; databases.conf can be left unchanged. +# +# 13.12.2019. +# It seems that we have to DISABLE BUFFERING in any IO operation which relates to preparing scripts, configs or logs. +# Otherwise sporadic runtime errors can occur: I/O error during "CreateFile (open)" operation for file "..." +# +# Explanation: +# https://docs.python.org/2/library/functions.html#open +# https://stackoverflow.com/questions/18984092/python-2-7-write-to-file-instantly/41506739 +# +# Checked on: +# 4.0.0.1687 SS: 1.536s. +# 4.0.0.1685 CS: 2.026s. +# 3.0.5.33207 SS: 1.435s. +# 3.0.5.33152 SC: 1.243s. +# 3.0.5.33206 CS: 2.626s. +# +# tracker_id: CORE-6043 +# min_versions: ['3.0'] +# versions: 3.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import subprocess +# import time +# import shutil +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# this_db = db_conn.database_name +# db_conn.close() +# +# svc = 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'): +# # 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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# tmp_fdb_keep=os.path.join(context['temp_directory'],'tmp_6043.keep_GTT_data.fdb') +# tmp_fdb_kill=os.path.join(context['temp_directory'],'tmp_6043.kill_GTT_data.fdb') +# +# shutil.copy2( this_db, tmp_fdb_keep ) +# shutil.copy2( this_db, tmp_fdb_kill ) +# +# dbconf = os.path.join( fb_home, 'databases.conf') +# dbcbak = os.path.join( fb_home, 'databases.bak') +# +# # Resut: fb_home is full path to FB instance home (with trailing slash). +# shutil.copy2( dbconf, dbcbak ) +# +# # ---------------------------------------------------------------------- +# +# isql_script=''' +# set list on; +# +# recreate global temporary table gtt (id int) on commit delete rows; +# commit; +# +# set count off; +# insert into gtt values (3); +# commit retain; +# +# set count on; +# select * from gtt; -- point 1 +# +# set count off; +# insert into gtt values (4); +# rollback retain; +# +# set count on; +# select * from gtt; -- point 2 +# ''' +# +# f_isql_cmd=open( os.path.join(context['temp_directory'],'tmp_isql_6043.sql'), 'w') +# f_isql_cmd.write( isql_script ) +# flush_and_close( f_isql_cmd ) +# +# # -------------------------------------------------------------------- +# +# f_dbconf=open( dbconf,'a') +# f_dbconf.seek(0, 2) +# +# alias_data=''' +# +# # Created temply by fbtest, CORE-6043. Should be removed auto. +# # WARNING! DO NOT ADD YET ANOTHER ALIAS FOR THE SAME DATABASE! +# # Attempt to connect to any of these aliases will fail with message: +# # ======= +# # Statement failed, SQLSTATE = 08004 +# # Server misconfigured - contact administrator please +# # ======= +# # Server log will contain: +# # File databases.conf contains bad data: Duplicated configuration for database +# +# tmp_6043_keep = %(tmp_fdb_keep)s +# { +# # Value of 0 makes engine to not clear GTT data on COMMIT/ROLLBACK RETAINING and let application to see it. +# # Default value is 1 (clear GTT data on commit/rollback retaining). +# # Note: in Firebird 4 default value will be changed to 0 and this setting will +# # be removed at Firebird 5. +# ClearGTTAtRetaining = 0 +# } +# +# tmp_6043_kill = %(tmp_fdb_kill)s +# { +# # Check that 1 really works as default value, i.e. clears GTT data on commit/rollback retaining. +# ClearGTTAtRetaining = 1 +# } +# +# +# ''' % locals() +# +# f_dbconf.write(alias_data) +# flush_and_close( f_dbconf ) +# +# # 4debug: shutil.copy2( fb_home+'databases.conf', fb_home+'databases.conf.check_it' ) +# +# # NB: buffering = 0 - we want this file be immediately on disk after closing in order to avoid excessive waiting for it +# ################### +# f_isql_keep_log=open( os.path.join(context['temp_directory'],'tmp_6043.keep_GTT_data.log'), 'w') +# subprocess.call([ context['isql_path'], 'localhost:tmp_6043_keep', "-q", "-i", f_isql_cmd.name], stdout=f_isql_keep_log, stderr=subprocess.STDOUT) +# flush_and_close( f_isql_keep_log ) +# +# with open( f_isql_keep_log.name,'r') as f: +# for line in f: +# if line.split(): +# print( 'When ClearGTTAtRetaining = 0: ' + line ) +# +# #################################################################### +# +# # NB: buffering = 0 - we want this file be immediately on disk after closing in order to avoid excessive waiting for it +# f_isql_kill_log=open( os.path.join(context['temp_directory'],'tmp_6043.kill_GTT_data.log'), 'w') +# subprocess.call([context['isql_path'], 'localhost:tmp_6043_kill', "-q", "-i", f_isql_cmd.name], stdout=f_isql_kill_log, stderr=subprocess.STDOUT) +# flush_and_close( f_isql_kill_log ) +# +# with open( f_isql_kill_log.name,'r') as f: +# for line in f: +# if line.split(): +# print( 'When ClearGTTAtRetaining = 1: ' + line ) +# +# #################################################################### +# +# # Restore previous content: +# shutil.move( dbcbak, dbconf ) +# +# ##################################################################### +# # Cleanup: +# time.sleep(1) +# cleanup( ( f_isql_keep_log, f_isql_kill_log, f_isql_cmd, tmp_fdb_keep, tmp_fdb_kill ) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + When ClearGTTAtRetaining = 0: ID 3 + When ClearGTTAtRetaining = 0: Records affected: 1 + When ClearGTTAtRetaining = 0: ID 3 + When ClearGTTAtRetaining = 0: Records affected: 1 + + When ClearGTTAtRetaining = 1: Records affected: 0 + When ClearGTTAtRetaining = 1: Records affected: 0 + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_6043_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + +# version: 4.0 +# resources: None + +substitutions_2 = [('[ \t]+', ' ')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set list on; + + recreate global temporary table gtt (id int) on commit delete rows; + commit; + + set count off; + insert into gtt values (4); + commit retain; + + set count on; + select * from gtt; -- point 1 + + set count off; + insert into gtt values (5); + rollback retain; + + set count on; + select * from gtt; -- point 2 + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + ID 4 + Records affected: 1 + + ID 4 + Records affected: 1 + """ + +@pytest.mark.version('>=4.0') +def test_core_6043_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/bugs/test_core_6044.py b/tests/bugs/test_core_6044.py new file mode 100644 index 00000000..691a9800 --- /dev/null +++ b/tests/bugs/test_core_6044.py @@ -0,0 +1,77 @@ +#coding:utf-8 +# +# id: bugs.core_6044 +# title: ISQL issues with increased identifier length +# decription: +# Confirmed problem on WI-T4.0.0.1421: FB crashed when we create sequence +# with name = 63 on-ascii characters and then ask it using 'show sequ' command. +# Also, FB crashe when we created a table with column which name contains 63 +# non-ascii characters and then this table metadata is queried by 'show table ' command. +# Checked on 4.0.0.1485: OK, 1.576s. +# +# 18.08.2020: added filter for 'current value: ...' of sequence. FB 4.x became incompatible +# with previous versions since 06-aug-2020. +# See also CORE-6084 and its fix: https://github.com/FirebirdSQL/firebird/commit/23dc0c6297825b2e9006f4d5a2c488702091033d +# +# +# tracker_id: CORE-6044 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('current value.*', 'current value')] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + create exception "ИсключениеДляСообщенияПользователюОНевозможностиПреобразованияя" 'Ваша строка не может быть преобразована в число.'; + create collation "КоллацияДляСортировкиСтроковыхДанныхКоторыеПредставимыКакЧислаа" for utf8 from unicode case insensitive 'NUMERIC-SORT=1'; + create domain "ДоменДляХраненияСтроковыхДанныхКоторыеПредставимыДляСортировкии" as varchar(160) character set utf8 collate "КоллацияДляСортировкиСтроковыхДанныхКоторыеПредставимыКакЧислаа"; + create sequence "ГенераторКоторыйДолженСодержатьНомераПоследнихУдаленнДокументов"; + create table "ТаблицаКотораяВсегдаДолжнаСодержатьТолькоСамуюСвежуюИнформациюю"( + "СтолбецКоторыйВсегдаДолжнаСодержатьТолькоСамуюСвежуюИнформациюю" + "ДоменДляХраненияСтроковыхДанныхКоторыеПредставимыДляСортировкии" + ,constraint + "ПервичныйКлючНаТаблицуКотораяВсегдаДолжнаСодержатьСвежайшуюИнфу" + primary key + ("СтолбецКоторыйВсегдаДолжнаСодержатьТолькоСамуюСвежуюИнформациюю") + ); + set bail off; + + show domain; -- this passed OK + show exception; -- this passed OK + show collation; -- this passed OK + show table; -- this passed OK + show sequ; -- this led to crash + show table "ТаблицаКотораяВсегдаДолжнаСодержатьТолькоСамуюСвежуюИнформациюю"; -- this also led to crash + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ДоменДляХраненияСтроковыхДанныхКоторыеПредставимыДляСортировкии + ИсключениеДляСообщенияПользователюОНевозможностиПреобразованияя; Msg: Ваша строка не может быть преобразована в число. + КоллацияДляСортировкиСтроковыхДанныхКоторыеПредставимыКакЧислаа, CHARACTER SET UTF8, FROM EXTERNAL ('UNICODE'), PAD SPACE, CASE INSENSITIVE, 'COLL-VERSION=153.88;NUMERIC-SORT=1' + ТаблицаКотораяВсегдаДолжнаСодержатьТолькоСамуюСвежуюИнформациюю + Generator ГенераторКоторыйДолженСодержатьНомераПоследнихУдаленнДокументов, current value: 0, initial value: 0, increment: 1 + СтолбецКоторыйВсегдаДолжнаСодержатьТолькоСамуюСвежуюИнформациюю (ДоменДляХраненияСтроковыхДанныхКоторыеПредставимыДляСортировкии) VARCHAR(160) CHARACTER SET UTF8 Not Null + COLLATE КоллацияДляСортировкиСтроковыхДанныхКоторыеПредставимыКакЧислаа + CONSTRAINT ПервичныйКлючНаТаблицуКотораяВсегдаДолжнаСодержатьСвежайшуюИнфу: + Primary key (СтолбецКоторыйВсегдаДолжнаСодержатьТолькоСамуюСвежуюИнформациюю) + """ + +@pytest.mark.version('>=4.0') +def test_core_6044_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6048.py b/tests/bugs/test_core_6048.py new file mode 100644 index 00000000..0ab6bc74 --- /dev/null +++ b/tests/bugs/test_core_6048.py @@ -0,0 +1,201 @@ +#coding:utf-8 +# +# id: bugs.core_6048 +# title: Provide ability to see current state of DB encryption +# decription: +# Test database that is created by fbtest framework will be encrypted here using IBSurgeon Demo Encryption package +# ( https://ib-aid.com/download-demo-firebird-encryption-plugin/ ; https://ib-aid.com/download/crypt/CryptTest.zip ) +# License file plugins\\dbcrypt.conf with unlimited expiration was provided by IBSurgeon to Firebird Foundation (FF). +# This file was preliminary stored in FF Test machine. +# Test assumes that this file and all neccessary libraries already were stored into FB_HOME and %FB_HOME%\\plugins. +# +# Anyone who wants to run this test on his own machine must +# 1) download https://ib-aid.com/download/crypt/CryptTest.zip AND +# 2) PURCHASE LICENSE and get from IBSurgeon file plugins\\dbcrypt.conf with apropriate expiration date and other info. +# +# ################################################ ! ! ! N O T E ! ! ! ############################################## +# FF tests storage (aka "fbt-repo") does not (and will not) contain any license file for IBSurgeon Demo Encryption package! +# ######################################################################################################################### +# +# Checked on: +# 4.0.0.1575: OK, 3.024s. +# +# === NOTE-1 === +# In case of "Crypt plugin DBCRYPT failed to load/607/335544351" check that all +# needed files from IBSurgeon Demo Encryption package exist in %FB_HOME% and %FB_HOME%\\plugins +# %FB_HOME%: +# 283136 fbcrypt.dll +# 2905600 libcrypto-1_1-x64.dll +# 481792 libssl-1_1-x64.dll +# +# %FB_HOME%\\plugins: +# 297984 dbcrypt.dll +# 306176 keyholder.dll +# 108 DbCrypt.conf +# 856 keyholder.conf +# +# === NOTE-2 === +# Version of DbCrypt.dll of october-2018 must be replaced because it has hard-coded +# date of expiration rather than reading it from DbCrypt.conf !! +# +# === NOTE-3 === +# firebird.conf must contain following line: +# KeyHolderPlugin = KeyHolder +# +# +# tracker_id: CORE-6048 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import time +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # 27.02.2021. +# # Name of encryption plugin depends on OS: +# # * for Windows we (currently) use plugin by IBSurgeon, its name is 'dbcrypt'; +# # later it can be replaced with built-in plugin 'fbSampleDbCrypt' +# # but currently it is included only in FB 4.x builds (not in FB 3.x). +# # Discussed tih Dimitr, Alex, Vlad, letters since: 08-feb-2021 00:22 +# # "Windows-distributive FB 3.x: it is desired to see sub-folder 'examples\\prebuild' with files for encryption, like it is in FB 4.x +# # *** DEFERRED *** +# # * for Linux we use: +# # ** 'DbCrypt_example' for FB 3.x +# # ** 'fbSampleDbCrypt' for FB 4.x+ +# # +# PLUGIN_NAME = 'dbcrypt' if os.name == 'nt' else ( '"DbCrypt_example"' if db_conn.engine_version < 4 else '"fbSampleDbCrypt"' ) +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# +# sql_scrypt=''' +# set list on; +# recreate table test(x bigint unique); +# set term ^; +# create or alter procedure sp_delay as +# declare r bigint; +# begin +# r = rand() * 9223372036854775807; +# insert into test(x) values(:r); +# begin +# -- ######################################################### +# -- ####################### D E L A Y ##################### +# -- ######################################################### +# in autonomous transaction do +# insert into test(x) values(:r); -- this will cause delay because of duplicate in index +# when any do +# begin +# -- nop -- +# end +# end +# end +# ^ +# set term ;^ +# commit; +# +# alter database encrypt with %(PLUGIN_NAME)s key Red; +# commit; +# set transaction lock timeout 2; -- THIS LOCK TIMEOUT SERVES ONLY FOR DELAY +# execute procedure sp_delay; +# rollback; +# select mon$crypt_state as "Is database encrypted ?" from mon$database; +# commit; +# +# alter database decrypt; +# commit; +# set transaction lock timeout 2; -- THIS LOCK TIMEOUT SERVES ONLY FOR DELAY +# execute procedure sp_delay; +# rollback; +# select mon$crypt_state as "Is database encrypted ?" from mon$database; +# ''' % locals() +# +# f_sql_cmd = open(os.path.join(context['temp_directory'],'tmp_core_6048.sql'), 'w') +# f_sql_cmd.write(sql_scrypt) +# flush_and_close( f_sql_cmd ) +# +# f_sql_log = open( os.path.join(context['temp_directory'],'tmp_core_6048.log'), 'w') +# +# subprocess.call( [ context['isql_path'], dsn, "-n", "-q", "-i", f_sql_cmd.name ], +# stdout = f_sql_log, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_sql_log ) +# +# with open(f_sql_log.name,'r') as f: +# for line in f: +# print(line) +# +# # cleanup: +# ########## +# time.sleep(1) +# cleanup( (f_sql_cmd,f_sql_log) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Is database encrypted ? 1 + Is database encrypted ? 0 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_6048_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6049.py b/tests/bugs/test_core_6049.py new file mode 100644 index 00000000..f2aee8f4 --- /dev/null +++ b/tests/bugs/test_core_6049.py @@ -0,0 +1,97 @@ +#coding:utf-8 +# +# id: bugs.core_6049 +# title: Builtin functions converting binary string to hexadecimal representation and vice versa +# decription: +# 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. +# +# Checked on 4.0.0.1496: OK, 1.679s. +# +# tracker_id: CORE-6049 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('INPUT message.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + recreate table test(uid binary(20)); + commit; + insert into test(uid) values( hex_decode(_octets 'CFA677DA45594D52A7D24EF9FA4C04D600000000') ); + commit; + + set list on; + set sqlda_display on; + select + t.* + ,uid = "b64_decode(b64_encode(uid))" as "b64_dec(b64_enc(uid)) result" + ,uid = "hex_decode(hex_encode(uid))" as "hex_dec(hex_enc(uid)) result" + from ( + select + uid + ,base64_encode(uid) as "b64_encode(uid)" + ,base64_decode(base64_encode(uid)) as "b64_decode(b64_encode(uid))" + ,hex_encode(uid) as "hex_encode(uid)" + ,hex_decode(hex_encode(uid)) as "hex_decode(hex_encode(uid))" + from test + ) t; + + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + OUTPUT message field count: 7 + 01: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 20 charset: 1 OCTETS + : name: UID alias: UID + : table: TEST owner: SYSDBA + 02: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 28 charset: 2 ASCII + : name: alias: b64_encode(uid) + : table: owner: + 03: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 21 charset: 1 OCTETS + : name: alias: b64_decode(b64_encode(uid)) + : table: owner: + 04: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 40 charset: 2 ASCII + : name: alias: hex_encode(uid) + : table: owner: + 05: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 20 charset: 1 OCTETS + : name: alias: hex_decode(hex_encode(uid)) + : table: owner: + 06: sqltype: 32764 BOOLEAN Nullable scale: 0 subtype: 0 len: 1 + : name: alias: b64_dec(b64_enc(uid)) result + : table: owner: + 07: sqltype: 32764 BOOLEAN Nullable scale: 0 subtype: 0 len: 1 + : name: alias: hex_dec(hex_enc(uid)) result + : table: owner: + + UID CFA677DA45594D52A7D24EF9FA4C04D600000000 + b64_encode(uid) z6Z32kVZTVKn0k75+kwE1gAAAAA= + b64_decode(b64_encode(uid)) CFA677DA45594D52A7D24EF9FA4C04D600000000 + hex_encode(uid) CFA677DA45594D52A7D24EF9FA4C04D600000000 + hex_decode(hex_encode(uid)) CFA677DA45594D52A7D24EF9FA4C04D600000000 + b64_dec(b64_enc(uid)) result + hex_dec(hex_enc(uid)) result + """ + +@pytest.mark.version('>=4.0') +def test_core_6049_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6054.py b/tests/bugs/test_core_6054.py new file mode 100644 index 00000000..2975e937 --- /dev/null +++ b/tests/bugs/test_core_6054.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_6054 +# title: Random crash 64bit fb_inet_server. Possible collation issue +# decription: +# Confirmed bug on WI-V2.5.9.27129. Major versions 3.x and 4.x was not affected. +# Works fine on WI-V2.5.9.27134. +# +# tracker_id: CORE-6054 +# min_versions: ['2.5.9'] +# versions: 2.5.9 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.9 +# resources: None + +substitutions_1 = [('-At line[:]{0,1}[\\s]+[\\d]+,[\\s]+column[:]{0,1}[\\s]+[\\d]+', '-At line: column:')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table c (id int, f1 varchar(32) character set win1251 collate win1251); + select * from c where f2 collate win1251_ua = 'x'; + set count on; + select * from c where f1 = _utf8 'x'; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42S22 + Dynamic SQL Error + -SQL error code = -206 + -Column unknown + -F2 + -At line: column: + """ + +@pytest.mark.version('>=2.5.9') +def test_core_6054_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6058.py b/tests/bugs/test_core_6058.py new file mode 100644 index 00000000..7318b09d --- /dev/null +++ b/tests/bugs/test_core_6058.py @@ -0,0 +1,85 @@ +#coding:utf-8 +# +# id: bugs.core_6058 +# title: Change behavior of skipped and repeated wall times within time zones +# decription: +# Confirmed wrong output on 4.0.0.1421. Works OK on 4.0.0.1524 +# +# 27.10.2020. +# Parser changed after following fixes: +# - CORE-6427 - Whitespace as date separator causes conversion error. +# - CORE-6429 - Timezone offset in timestamp/time literal and CAST should follow SQL standard syntax only. +# See: https://github.com/FirebirdSQL/firebird/commit/ff37d445ce844f991242b1e2c1f96b80a5d1636d +# Adjusted expected stdout/stderr after discuss with Adriano. +# Checked on 4.0.0.2238 +# +# tracker_id: CORE-6058 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Change behavior of skipped and repeated wall times within time zones + -- Within time zones, some wall times does not exist (DST starting) or repeats twice (DST ending). + + set heading off; + + -- is repeated twice (fall backward), but it must be interpreted as 1:30 AM UTC-04 instead of 1:30 AM UTC-05" + select timestamp '2017-11-05 01:30 America/New_York' from rdb$database; + select timestamp '2017-11-05 01:30 -04' from rdb$database; + select datediff( + second from + timestamp '2017-11-05 01:30 America/New_York' + to + timestamp '2017-11-05 01:30 -04' + ) from rdb$database; + + + -- does not exist, but it must be interpreted as 2:30 AM UTC-05 (equivalent to 3:30 AM UTC-04)" + select timestamp '2017-03-12 02:30 America/New_York' from rdb$database; + select timestamp '2017-03-12 02:30 -05' from rdb$database; + select datediff( + second from + timestamp '2017-03-12 02:30 America/New_York' + to + timestamp '2017-03-12 02:30 -05' + ) from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 2017-11-05 01:30:00.0000 America/New_York + 2017-03-12 03:30:00.0000 America/New_York + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22009 + Invalid time zone offset: -04 - must use format +/-hours:minutes and be between -14:00 and +14:00 + Statement failed, SQLSTATE = 22009 + Invalid time zone offset: -04 - must use format +/-hours:minutes and be between -14:00 and +14:00 + Statement failed, SQLSTATE = 22009 + Invalid time zone offset: -05 - must use format +/-hours:minutes and be between -14:00 and +14:00 + Statement failed, SQLSTATE = 22009 + Invalid time zone offset: -05 - must use format +/-hours:minutes and be between -14:00 and +14:00 + """ + +@pytest.mark.version('>=4.0') +def test_core_6058_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6068.py b/tests/bugs/test_core_6068.py new file mode 100644 index 00000000..96de1a84 --- /dev/null +++ b/tests/bugs/test_core_6068.py @@ -0,0 +1,3634 @@ +#coding:utf-8 +# +# id: bugs.core_6068 +# title: Server hangs when compiling big package with error +# decription: +# Confirmed bug on 4.0.0.1485 - FB hangs. +# Works fine on 4.0.0.1524 - compiler error is issued; 4.501s. +# +# 05-sep-2019: reduced minimal version to 3.0.5 because of commit +# https://github.com/FirebirdSQL/firebird/commit/04deca31dd5fa9b4aae3670d22fb7d97c4e5097d +# (checked on WI-V3.0.5.33166 ) +# +# tracker_id: CORE-6068 +# min_versions: ['3.0.5'] +# versions: 3.0.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [('- line .*', ''), ('At line .*', '')] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ +CREATE DOMAIN DOM$ABONENT AS +NUMERIC(9,0) +CHECK (CHAR_LENGTH(VALUE) IN (8, 9)); + +CREATE DOMAIN DOM$ABONENT_LONG AS +VARCHAR(12); + +CREATE DOMAIN DOM$ADDRESS AS +VARCHAR(200); + +CREATE DOMAIN DOM$AMOUNT AS +NUMERIC(18,2) +DEFAULT 0; + +CREATE DOMAIN DOM$BLOB AS +BLOB SUB_TYPE 0 SEGMENT SIZE 1024; + +CREATE DOMAIN DOM$BOOLEAN AS +SMALLINT +DEFAULT 0 +NOT NULL +CHECK (VALUE IN (0,1)); + +CREATE DOMAIN DOM$BOOLEAN_REAL AS +BOOLEAN; + +CREATE DOMAIN DOM$CITIZEN_NAME AS +VARCHAR(50); + +CREATE DOMAIN DOM$CITIZEN_PATRONYMIC AS +VARCHAR(50); + +CREATE DOMAIN DOM$CITIZEN_SURNAME AS +VARCHAR(50); + +CREATE DOMAIN DOM$COMMENT AS +VARCHAR(250); + +CREATE DOMAIN DOM$CURRENT_TIMESTAMP AS +TIMESTAMP +DEFAULT CURRENT_TIMESTAMP +NOT NULL; + +CREATE DOMAIN DOM$DATE AS +DATE +CHECK (VALUE BETWEEN DATE '01.01.1900' AND DATE '31.12.2100'); + +CREATE DOMAIN DOM$EMAIL AS +VARCHAR(50); + +CREATE DOMAIN DOM$EMAILS AS +VARCHAR(255); + +CREATE DOMAIN DOM$EMAIL_BODY AS +VARCHAR(5000); + +CREATE DOMAIN DOM$EMAIL_SUBJECT AS +VARCHAR(100); + +CREATE DOMAIN DOM$INN AS +VARCHAR(20) +CHECK (CHAR_LENGTH(VALUE) = 10 OR CHAR_LENGTH(VALUE) = 12); + +CREATE DOMAIN DOM$INTEGER AS +INTEGER; + +CREATE DOMAIN DOM$KEY AS +INTEGER; + +CREATE DOMAIN DOM$NAME_CONTRACTOR AS +VARCHAR(200); + +CREATE DOMAIN DOM$NAME_HUGE AS +VARCHAR(150); + +CREATE DOMAIN DOM$NAME_LONG AS +VARCHAR(100); + +CREATE DOMAIN DOM$NAME_SHORT AS +VARCHAR(25); + +CREATE DOMAIN DOM$NAME_STANDARD AS +VARCHAR(50); + +CREATE DOMAIN DOM$NAME_TINY AS +VARCHAR(10); + +CREATE DOMAIN DOM$NETWORK_PORT AS +INTEGER +CHECK (VALUE BETWEEN 0 AND 65535); + +CREATE DOMAIN DOM$NUMBER_CHECK AS +VARCHAR(6); + +CREATE DOMAIN DOM$NUMBER_EXEC_PROCESS AS +VARCHAR(20); + +CREATE DOMAIN DOM$NUMBER_FILE AS +VARCHAR(20); + +CREATE DOMAIN DOM$NUMBER_PAYMENT_ORDER AS +INTEGER +CHECK (VALUE > 0); + +CREATE DOMAIN DOM$NUMBER_WRIT_EXEC AS +VARCHAR(12) +CHECK (CHAR_LENGTH (VALUE) IN (11, 12)); + +CREATE DOMAIN DOM$PERIOD AS +INTEGER +CHECK (CHAR_LENGTH(VALUE) = 6); + +CREATE DOMAIN DOM$POSITION AS +INTEGER +NOT NULL +CHECK (VALUE > 0); + +CREATE DOMAIN DOM$SERIES_WRIT_EXEC AS +CHAR(2); + +CREATE DOMAIN DOM$STATE AS +SMALLINT +DEFAULT 0 +NOT NULL +CHECK ((VALUE >= 0) AND (VALUE <= 11)); + +CREATE DOMAIN DOM$STRING_DATE AS +VARCHAR(10); + +CREATE DOMAIN DOM$TEXT_EXCEPTION AS +VARCHAR(5000); + +CREATE DOMAIN DOM$TIME AS +TIME; + +CREATE DOMAIN DOM$TIMESTAMP AS +TIMESTAMP; + +CREATE DOMAIN DOM$VERSION AS +VARCHAR(7); + +CREATE DOMAIN DOM$YEAR AS +SMALLINT +CHECK ((VALUE >= 1960) AND (VALUE <= 2025)); + +CREATE DOMAIN D_INTEGER AS +INTEGER; + +CREATE DOMAIN D_KEY AS +INTEGER; + +CREATE DOMAIN D_LIST_ID AS +VARCHAR(1000); + +CREATE DOMAIN D_NATURAL AS +INTEGER +CHECK (VALUE >= 0); + +CREATE DOMAIN D_NUMBER AS +INTEGER +CHECK (VALUE > 0); + +CREATE DOMAIN D_QUANTITY AS +INTEGER +DEFAULT 0 +CHECK (VALUE >= 0); + +CREATE DOMAIN D_VARCHAR_10 AS +VARCHAR(10); + +CREATE DOMAIN D_VARCHAR_100 AS +VARCHAR(100); + +CREATE DOMAIN D_VARCHAR_15 AS +VARCHAR(15); + +CREATE DOMAIN D_VARCHAR_150 AS +VARCHAR(150); + +CREATE DOMAIN D_VARCHAR_200 AS +VARCHAR(200); + +CREATE DOMAIN D_VARCHAR_25 AS +VARCHAR(25); + +CREATE DOMAIN D_VARCHAR_255 AS +VARCHAR(255); + +CREATE DOMAIN D_VARCHAR_50 AS +VARCHAR(50); + +CREATE DOMAIN D_VARCHAR_500 AS +VARCHAR(500); + +CREATE DOMAIN D_VARCHAR_5000 AS +VARCHAR(5000); + + + +/******************************************************************************/ +/*** Generators ***/ +/******************************************************************************/ + +CREATE SEQUENCE IBE$LOG_TABLES_GEN START WITH 0 INCREMENT BY 1; +ALTER SEQUENCE IBE$LOG_TABLES_GEN RESTART WITH 0; + +CREATE SEQUENCE SEQ_BAT$RECEIPT$BATCH_ID START WITH 0 INCREMENT BY 1; +ALTER SEQUENCE SEQ_BAT$RECEIPT$BATCH_ID RESTART WITH 0; + +CREATE SEQUENCE SEQ_BAT$RECEIPT$RECEIPT_ID START WITH 0 INCREMENT BY 1; +ALTER SEQUENCE SEQ_BAT$RECEIPT$RECEIPT_ID RESTART WITH 0; + +CREATE SEQUENCE SEQ_DOC$LAWSUIT$WRIT_OF_EXEC_ID START WITH 0 INCREMENT BY 1; +ALTER SEQUENCE SEQ_DOC$LAWSUIT$WRIT_OF_EXEC_ID RESTART WITH 0; + +CREATE SEQUENCE SEQ_INF$ABONENT$CHARAC_GAS_ID START WITH 0 INCREMENT BY 1; +ALTER SEQUENCE SEQ_INF$ABONENT$CHARAC_GAS_ID RESTART WITH 0; + +CREATE SEQUENCE SEQ_INF$WAREHOUSE$TURNOVER_ID START WITH 0 INCREMENT BY 1; +ALTER SEQUENCE SEQ_INF$WAREHOUSE$TURNOVER_ID RESTART WITH 0; + +CREATE SEQUENCE SEQ_SYS$LOG$EXCEPTION_ID START WITH 131573 INCREMENT BY 1; +ALTER SEQUENCE SEQ_SYS$LOG$EXCEPTION_ID RESTART WITH 131573; + + + +/******************************************************************************/ +/*** Exceptions ***/ +/******************************************************************************/ + +CREATE EXCEPTION EXC$CANCEL 'Отмена'; + +CREATE EXCEPTION EXC$CHECK_DATA 'Проверка данных'; + + + +/******************************************************************************/ +/*** Stored procedures ***/ +/******************************************************************************/ + + + +SET TERM ^ ; + +CREATE PROCEDURE GET$ABONENT$CHARGING_GAS_AMURCC ( + ID_ABONENT DOM$ABONENT NOT NULL) +RETURNS ( + RESULT DOM$BOOLEAN) +AS +BEGIN + SUSPEND; +END^ + + + + + +CREATE PROCEDURE GET$ABONENT$DEFAULT_TYPE_RECEIP ( + ID_ABONENT DOM$ABONENT NOT NULL) +RETURNS ( + RESULT DOM$KEY) +AS +BEGIN + SUSPEND; +END^ + + + + + +CREATE PROCEDURE GET$ABONENT$DETERMINE_GD ( + ID_ABONENT DOM$ABONENT_LONG NOT NULL) +RETURNS ( + RESULT DOM$KEY) +AS +BEGIN + SUSPEND; +END^ + + + + + +CREATE PROCEDURE GET$WRIT_EXEC$CHECK_RESPONDENT ( + ID_WRIT_EXEC DOM$KEY NOT NULL, + RESPONDENT D_VARCHAR_100 NOT NULL) +RETURNS ( + RESULT DOM$BOOLEAN) +AS +BEGIN + SUSPEND; +END^ + + + + + +CREATE PROCEDURE GET$WRIT_EXEC$SEARCH_BY_RESPOND ( + NUMBER_FILE DOM$NUMBER_FILE NOT NULL, + RESPONDENT D_VARCHAR_100 NOT NULL) +RETURNS ( + RESULT DOM$KEY) +AS +BEGIN + SUSPEND; +END^ + + + + + +CREATE PROCEDURE OPER$EXCEPTION$CANCEL ( + TEXT D_VARCHAR_500) +AS +BEGIN + EXIT; +END^ + + + + + +CREATE PROCEDURE OPER$EXCEPTION$CHECK_DATA ( + TEXT D_VARCHAR_500) +AS +BEGIN + EXIT; +END^ + + + + + +CREATE PROCEDURE OPER$EXCEPTION$CHECK_DATA_ABONE ( + ID_ABONENT DOM$ABONENT NOT NULL, + TEXT D_VARCHAR_500 NOT NULL) +AS +BEGIN + EXIT; +END^ + + + + + +CREATE PROCEDURE OPER$EXCEPTION$CHECK_DATA_BRANC ( + ID_BRANCH DOM$KEY NOT NULL, + TEXT D_VARCHAR_500 NOT NULL) +AS +BEGIN + EXIT; +END^ + + + + + + +SET TERM ; ^ + + + +/******************************************************************************/ +/*** Stored functions ***/ +/******************************************************************************/ + + + +SET TERM ^ ; + +CREATE FUNCTION DATE_TO_PERIOD ( + VAL DOM$DATE) +RETURNS DOM$PERIOD +AS +BEGIN + RETURN NULL; +END^ + + + + + +CREATE FUNCTION DEC_PERIOD ( + VAL DOM$PERIOD) +RETURNS DOM$PERIOD +AS +BEGIN + RETURN NULL; +END^ + + + + + +CREATE FUNCTION FORMAT_DATE ( + ARG DOM$DATE) +RETURNS DOM$STRING_DATE +AS +BEGIN + RETURN NULL; +END^ + + + + + + +SET TERM ; ^ + + + +/******************************************************************************/ +/*** Package headers ***/ +/******************************************************************************/ + + + +SET TERM ^ ; + +CREATE PACKAGE PKG$ABONENT +AS +BEGIN + FUNCTION GET_GROUP_DISTRICT_FOR_PAYMENT(ID_ABONENT DOM$ABONENT NOT NULL) RETURNS DOM$KEY DETERMINISTIC; +END^ + + +CREATE PACKAGE PKG$CONNECT +AS +BEGIN + FUNCTION ID_USER() RETURNS DOM$KEY DETERMINISTIC; + FUNCTION ID_DIVISION() RETURNS DOM$KEY DETERMINISTIC; + FUNCTION ID_WORKER() RETURNS DOM$KEY DETERMINISTIC; + FUNCTION ID_CS() RETURNS DOM$KEY DETERMINISTIC; + FUNCTION ID_BRANCH() RETURNS DOM$KEY DETERMINISTIC; + FUNCTION ID_GROUP_DISTRICT() RETURNS DOM$KEY DETERMINISTIC; + + FUNCTION CURRENT_USER_SURNAME_NP RETURNS D_VARCHAR_50 DETERMINISTIC; +END^ + + +CREATE PACKAGE PKG$EXCEPTION +AS +BEGIN + PROCEDURE FOR_CITIZEN(ID_CITIZEN DOM$KEY NOT NULL, TEXT D_VARCHAR_500 NOT NULL); + PROCEDURE FOR_WORKER(ID_WORKER DOM$KEY NOT NULL, TEXT D_VARCHAR_500 NOT NULL); + PROCEDURE FOR_BATCH_RECEIPT(ID_BATCH DOM$KEY NOT NULL, TEXT D_VARCHAR_500 NOT NULL); +END^ + + +CREATE PACKAGE PKG$PAYMENT$BANK_STTM +AS +BEGIN + -- + PROCEDURE GET_LIST_BRANCH RETURNS (ID DOM$KEY, NAME DOM$NAME_STANDARD); + + -- Загрузка банковской выписки + PROCEDURE PARSE_PAYMENT_ORDERS; + PROCEDURE DETECT_SOURCE_PAYMENT(DATE_ACCOUNT DOM$DATE NOT NULL); + + -- Создание квитанций + PROCEDURE CREATE_RECEIPTS_FOR_DATE(DATE_ACCOUNT DOM$DATE); + PROCEDURE CREATE_RECEIPT(ID DOM$KEY NOT NULL, ID_ABONENT DOM$ABONENT); + PROCEDURE CREATE_INDIVID_RECEIPT(ID DOM$KEY NOT NULL, ID_ABONENT DOM$ABONENT NOT NULL); + + PROCEDURE TRY_CREATE_RECEIPT_NONACCEPT(ID_BANK DOM$KEY NOT NULL, DATE_ACCOUNT DOM$DATE NOT NULL, DATE_PAYMENT DOM$DATE NOT NULL, NUMBER_RECEIPT DOM$NUMBER_CHECK NOT NULL, AMOUNT DOM$AMOUNT NOT NULL, PURPOSE D_VARCHAR_500 NOT NULL, PAYER D_VARCHAR_200 NOT NULL) RETURNS (RESULT DOM$KEY); + PROCEDURE TRY_CREATE_RECEIPT_BAILIFF(ID_SOURCE DOM$KEY NOT NULL, DATE_ACCOUNT DOM$DATE NOT NULL, DATE_PAYMENT DOM$DATE NOT NULL, NUMBER_RECEIPT DOM$NUMBER_CHECK NOT NULL, AMOUNT DOM$AMOUNT NOT NULL, PURPOSE D_VARCHAR_500 NOT NULL) RETURNS (RESULT DOM$KEY); + PROCEDURE TRY_CREATE_RECEIPT_INDIVID(DATE_ACCOUNT DOM$DATE NOT NULL, DATE_PAYMENT DOM$DATE NOT NULL, NUMBER_RECEIPT DOM$NUMBER_CHECK NOT NULL, AMOUNT DOM$AMOUNT NOT NULL, PURPOSE D_VARCHAR_500 NOT NULL, PAYER D_VARCHAR_200 NOT NULL, ID_ABONENT DOM$ABONENT) RETURNS (RESULT DOM$KEY); + + -- Распознавание + PROCEDURE RECOGN_NONACCEPT(ID_BANK DOM$KEY NOT NULL, DATE_PAYMENT DOM$DATE NOT NULL, PURPOSE D_VARCHAR_500 NOT NULL, PAYER D_VARCHAR_200 NOT NULL) RETURNS (ID_LAWSUIT DOM$KEY, ID_WRIT_EXEC DOM$KEY, ID_EXEC_PROC DOM$KEY); + FUNCTION RECOGN_INDIVID(PURPOSE D_VARCHAR_500 NOT NULL) RETURNS DOM$ABONENT; + FUNCTION SEARCH_NUMBER_FILE(PURPOSE D_VARCHAR_500 NOT NULL, IS_NONACCEPT DOM$BOOLEAN_REAL NOT NULL) RETURNS DOM$NUMBER_FILE DETERMINISTIC; + + -- Добавление корректировок + PROCEDURE ADD_CORRECT_NONACCEPT(ID_PAYMENT DOM$KEY NOT NULL, NUMBER_FILE_OLD DOM$NUMBER_FILE NOT NULL, RESPONDENT_OLD D_VARCHAR_100 NOT NULL, NUMBER_FILE_NEW DOM$NUMBER_FILE NOT NULL, RESPONDENT_NEW D_VARCHAR_100 NOT NULL); + PROCEDURE ADD_CORRECT_BAILIFF(ID_PAYMENT DOM$KEY NOT NULL, NUMBER_FILE DOM$NUMBER_FILE NOT NULL, RESPONDENT D_VARCHAR_100 NOT NULL); + + -- Извещения + PROCEDURE SEND_NOTIFY_LOAD_BANK_STATEMENT(DATE_ACCOUNT DOM$DATE NOT NULL, RECOGN DOM$INTEGER NOT NULL, NOT_RECOGN DOM$INTEGER NOT NULL); + PROCEDURE SEND_NOTIFY_RECONG_BANK_STATEME(DATE_ACCOUNT DOM$DATE NOT NULL); + PROCEDURE SEND_NOTIFY_ERROR_LOAD_BANK_STA; + PROCEDURE SEND_NOTIFY_ERROR_DETECT_SOURCE; + PROCEDURE SEND_NOTIFY_ERROR_CREATE_ALL_RE; +END^ + + +CREATE PACKAGE PKG$SEND_EMAIL +AS +BEGIN + PROCEDURE SEND_TO_EMAILS(EMAILS DOM$EMAILS NOT NULL, EMAILS_COPY DOM$EMAILS, SUBJECT DOM$EMAIL_SUBJECT NOT NULL, BODY_MAIL DOM$EMAIL_BODY NOT NULL); + PROCEDURE SEND_TO_LIST_USERS(LIST_USERS D_LIST_ID NOT NULL, LIST_USERS_COPY D_LIST_ID, SUBJECT DOM$EMAIL_SUBJECT NOT NULL, BODY_MAIL DOM$EMAIL_BODY NOT NULL); + PROCEDURE SEND_TO_GROUP(ID_GROUP DOM$KEY NOT NULL, SUBJECT DOM$EMAIL_SUBJECT NOT NULL, BODY_MAIL DOM$EMAIL_BODY NOT NULL); +END^ + + + +SET TERM ; ^ + + + +/******************************************************************************/ +/*** Tables ***/ +/******************************************************************************/ + + + +CREATE TABLE BAT$RECEIPT$BATCH ( + ID D_KEY NOT NULL, + ID_CREATOR D_KEY NOT NULL, + ID_LOADER D_KEY, + ID_GROUP_DISTRICT DOM$KEY NOT NULL, + ID_PERIOD_ACCOUNT DOM$KEY NOT NULL, + ID_SOURCE D_KEY NOT NULL, + ID_CASHIER DOM$KEY, + ID_VERIFIED_BOOKKEEPER DOM$KEY, + TIMESTAMP_CREATION DOM$CURRENT_TIMESTAMP NOT NULL, + TIMESTAMP_LOADING DOM$TIMESTAMP, + TIMESTAMP_VERIFIED_BOOKKEEPER DOM$TIMESTAMP, + DATE_ACCOUNT DOM$DATE NOT NULL, + BEGIN_DATE_PAYMENT DOM$DATE, + END_DATE_PAYMENT DOM$DATE, + DATE_PAYMENT_ORDER DOM$DATE, + PAYMENT_ORDER DOM$NUMBER_PAYMENT_ORDER, + NUMBER_REGISTRY DOM$NUMBER_PAYMENT_ORDER, + COMMENT DOM$COMMENT, + IS_CORRECT_RECEIPT DOM$BOOLEAN, + LOADED DOM$BOOLEAN +); + + +CREATE TABLE BAT$RECEIPT$RECEIPT ( + ID D_KEY NOT NULL, + ID_BATCH D_KEY NOT NULL, + ID_CREATOR D_KEY NOT NULL, + ID_ABONENT D_KEY NOT NULL, + ID_PERIOD_FOR_PAYMENT DOM$KEY NOT NULL, + ID_TYPE_RECEIPT DOM$KEY NOT NULL, + ID_CORRECTED_RECEIPT D_KEY, + ID_REVERSED_RECEIPT DOM$KEY, + ID_READING_1 DOM$KEY, + ID_READING_2 DOM$KEY, + ID_READING_3 DOM$KEY, + ID_CS_STATEMENT DOM$KEY, + ID_LAWSUIT DOM$KEY, + ID_WRIT_EXEC DOM$KEY, + ID_EXEC_PROC DOM$KEY, + ID_BT_FINE DOM$KEY, + TIMESTAMP_CREATION DOM$CURRENT_TIMESTAMP NOT NULL, + DATE_PAYMENT DOM$DATE NOT NULL, + NUMBER DOM$NUMBER_CHECK, + AMOUNT_SERVICE_1 DOM$AMOUNT NOT NULL, + AMOUNT_SERVICE_2 DOM$AMOUNT NOT NULL, + AMOUNT_SERVICE_3 DOM$AMOUNT NOT NULL, + AMOUNT_SERVICE_4 DOM$AMOUNT NOT NULL, + AMOUNT_SERVICE_5 DOM$AMOUNT NOT NULL, + AMOUNT_FINE DOM$AMOUNT NOT NULL, + AMOUNT_RECEIPT DOM$AMOUNT NOT NULL, + AMOUNT_SERVICES COMPUTED BY (AMOUNT_RECEIPT - AMOUNT_FINE), + COMMISSION DOM$AMOUNT, + AUTODISTRIBUTE_SERVICES DOM$BOOLEAN DEFAULT 1 NOT NULL, + CASHLESS DOM$BOOLEAN NOT NULL, + PURPOSE D_VARCHAR_500, + PAYER D_VARCHAR_500 +); + + +CREATE TABLE DIR$ABONENT$ABONENT ( + ID D_KEY NOT NULL, + ID_BRANCH DOM$KEY NOT NULL, + ID_TYPE_GASSUPPLY DOM$KEY NOT NULL +); + + +CREATE TABLE DIR$DATABASE$DATABASE ( + ID DOM$KEY NOT NULL, + NAME DOM$NAME_SHORT NOT NULL, + DATA_SOURCE DOM$NAME_LONG NOT NULL, + NAME_BASE_METERS DOM$NAME_TINY, + USE_SYNC DOM$BOOLEAN NOT NULL, + MAIN_DATABASE DOM$BOOLEAN_REAL NOT NULL +); + + +CREATE TABLE DIR$ENTERPRISE$BRANCH ( + ID DOM$KEY NOT NULL, + NAME DOM$NAME_HUGE NOT NULL, + INTERNAL_NAME DOM$NAME_STANDARD NOT NULL, + USE_FOR_BANK_STATEMENT DOM$BOOLEAN_REAL, + POS DOM$INTEGER, + ID_SOURCE_PAYMENT_BAILIFF DOM$KEY, + ID_SOURCE_INDIVID_PAYMENT_ORDER DOM$KEY +); + + +CREATE TABLE DIR$ENTERPRISE$GROUP_DISTRICT ( + ID DOM$KEY NOT NULL, + ID_BRANCH DOM$KEY NOT NULL, + NAME DOM$NAME_STANDARD NOT NULL, + ID_FIRST_PERIOD DOM$PERIOD NOT NULL, + ID_LAST_PERIOD DOM$PERIOD NOT NULL, + ID_LAST_CALCED_PERIOD DOM$PERIOD NOT NULL, + ID_OPENED_PERIOD_MONTHS_DEBT DOM$PERIOD, + ID_OPENED_PERIOD_NETWORK_GAS DOM$PERIOD NOT NULL, + ID_OPENED_PERIOD_PAYMENT DOM$PERIOD NOT NULL, + ID_OPENED_PERIOD_BOTTLE DOM$PERIOD NOT NULL, + ID_OPENED_PERIOD_GTP DOM$PERIOD NOT NULL, + ID_OPENED_PERIOD_MS DOM$PERIOD NOT NULL, + ID_OPENED_PERIOD_ADS DOM$PERIOD, + ID_OPENED_PERIOD_ROS DOM$PERIOD NOT NULL, + ID_OPENED_PERIOD_EQUIPMENT DOM$PERIOD NOT NULL, + ID_OPENED_PERIOD_NOTICE DOM$PERIOD, + ID_OPENED_PERIOD_MNG_COMPANY DOM$PERIOD, + ID_OPENED_PERIOD_ABONENT DOM$PERIOD NOT NULL, + ID_OPENED_PERIOD_HOUSE DOM$PERIOD NOT NULL, + ID_OPENED_PERIOD_UNIT DOM$PERIOD NOT NULL, + ID_OPENED_PERIOD_GDP DOM$PERIOD NOT NULL, + ID_OPENED_PERIOD_COURT_EXPENSES DOM$PERIOD, + ID_OPENED_PERIOD_ENTRY_REMAINS DOM$PERIOD, + ID_OPENED_PERIOD_WH_MATERIALS DOM$PERIOD, + ID_FIRST_YEAR_INTERVAL_MS DOM$YEAR NOT NULL, + ID_FIRST_PERIOD_TURNOVER_GTP DOM$PERIOD NOT NULL, + ID_FIRST_PERIOD_TURNOVER_WAREHO DOM$PERIOD NOT NULL, + ID_FIRST_PERIOD_CHARGE_BY_AVERA DOM$PERIOD, + ID_FIRST_PERIOD_RECALC_READING DOM$PERIOD, + ID_FIRST_PERIOD_TIMESHEET DOM$PERIOD, + ID_FIRST_PERIOD_CELLPHONE DOM$PERIOD, + ID_FIRST_PERIOD_WH_MATERIAL DOM$PERIOD, + ID_FIRST_PERIOD_AUTORECALC_AVGM DOM$PERIOD, + ID_FIRST_PERIOD_RECEPT_READING DOM$PERIOD, + ID_FIRST_PERIOD_PLAN_WORKS DOM$PERIOD, + ID_FIRST_PERIOD_METER_SUMMARY DOM$PERIOD, + ID_FIRST_PERIOD_METER_HISTORY_R DOM$PERIOD, + ID_LAST_PERIOD_CHANGE_CS DOM$PERIOD NOT NULL, + ID_UNIT_BOTTLE DOM$KEY, + ID_UNIT_ABSENCE DOM$KEY NOT NULL, + ID_UNIT_DISCONNECTED DOM$KEY NOT NULL, + ID_DIVISION_RETURN_COMMIS_MATER DOM$KEY, + ID_FIRST_PERIOD_BT_CS_STATEMENT DOM$KEY, + ID_FIRST_PERIOD_CHARGE_DUTY DOM$PERIOD, + ID_FIRST_PERIOD_USE_SERIAL_BOTT DOM$PERIOD, + ID_FIRST_PERIOD_CHARGE_GAS DOM$PERIOD, + ID_FIRST_PERIOD_CHARGE_MS_MANSI DOM$PERIOD, + ID_FIRST_PERIOD_CHARGE_MS_NGPH DOM$PERIOD, + ID_FIRST_PERIOD_CHARGE_MS_DEPAR DOM$PERIOD, + ID_DIVISION_CS_PAYMENT_EXTERNAL DOM$KEY, + ID_MASTER_GROUP_DISTRICT DOM$KEY, + ID_FIRST_PERIOD_PIECEWORK DOM$PERIOD, + ID_ROUTE_FOR_NEW_HOUSE DOM$KEY NOT NULL, + ID_NF_ABONENT_FOR_PAYMENT_LAWSU DOM$ABONENT, + ID_DEFAULT_CHARGE_REGIME_MS DOM$KEY, + POS DOM$POSITION, + NAME_WITH_BRANCH DOM$NAME_HUGE NOT NULL, + PICTURE_RECEIPT_MANSION DOM$BLOB, + PICTURE_RECEIPT_NGPH DOM$BLOB, + MAX_CLAIMS_FOR_DEBT_PER_OPERATI D_NATURAL, + CHARGE_MS_NETWORK_GAS_BY_FACT DOM$BOOLEAN NOT NULL, + CHARGE_MS_METER_MANSION_BY_FACT DOM$BOOLEAN, + CHARGE_MS_NGPH_BY_FACT DOM$BOOLEAN NOT NULL, + CHARGE_MANSION_BY_AMURCC DOM$BOOLEAN NOT NULL, + CHARGE_ES_FOR_GTP DOM$BOOLEAN, + AUTOLOAD_RECEPTED_READINGS DOM$BOOLEAN NOT NULL, + USING_PHONE_IN_RECEPT_READING DOM$BOOLEAN NOT NULL, + ALLOW_PAYMENT_DUTY_WITHOUT_LAWS DOM$BOOLEAN NOT NULL, + EXTERNAL_PAYMENT_CS DOM$BOOLEAN, + CALC_MD_OLD_ALGORITHM DOM$BOOLEAN NOT NULL, + USING_CAF_FOR_LAWSUIT DOM$BOOLEAN NOT NULL, + IS_ACTIVE DOM$BOOLEAN, + IS_MAIN_GROUP_DISTRICT DOM$BOOLEAN_REAL +); + + +CREATE TABLE DIR$ENTPR$IND_PAYMENT ( + ID DOM$KEY GENERATED BY DEFAULT AS IDENTITY, + ID_BRANCH DOM$KEY NOT NULL, + NAME DOM$NAME_STANDARD NOT NULL +); + + +CREATE TABLE DIR$EXEC_PROC$BANK ( + ID DOM$KEY NOT NULL, + ID_SOURCE DOM$KEY, + POS DOM$POSITION NOT NULL, + NAME DOM$NAME_STANDARD NOT NULL, + FULL_NAME DOM$NAME_LONG NOT NULL, + NAME_IN_FILE_BANK_CLIENT DOM$NAME_LONG, + USE_INFO_ABOUT_REPRESENTATIVE DOM$BOOLEAN, + BANK_INN DOM$INN +); + + +CREATE TABLE DIR$EXEC_PROC$BANK_PURPOSE ( + ID DOM$KEY GENERATED BY DEFAULT AS IDENTITY, + ID_BANK DOM$KEY NOT NULL, + NAME DOM$NAME_LONG NOT NULL +); + + +CREATE TABLE DIR$EXEC_PROC$CORRECTION ( + ID DOM$KEY GENERATED BY DEFAULT AS IDENTITY, + PAYMENT_NUMBER_FILE DOM$NUMBER_FILE, + PAYMENT_FIO D_VARCHAR_100, + PAYMENT_PURPOSE D_VARCHAR_500, + PAYMENT_SERIAL_WRIT_EXEC DOM$NUMBER_WRIT_EXEC, + CORRECT_NUMBER_FILE DOM$NUMBER_FILE NOT NULL, + CORRECT_FIO D_VARCHAR_100 NOT NULL, + TYPE_PAYMENT DOM$INTEGER NOT NULL +); + + +CREATE TABLE DIR$GASSUPPLY$TYPE_GS ( + ID DOM$KEY NOT NULL, + ID_REGIME DOM$KEY NOT NULL, + ID_GROUP_TG DOM$KEY, + ID_TYPE_RECEIPT DOM$KEY, + ID_TYPE_CONTRACT_GAS DOM$KEY, + ID_TYPE_CONTRACT_MS DOM$KEY, + ID_TYPE_CLAIM_DEBT DOM$KEY, + ID_TYPE_LAWSUIT DOM$KEY, + ID_TYPE_GAS DOM$KEY, + ID_DEFAULT_GC_OBJECT DOM$KEY, + ID_DEFAULT_GC_LINE DOM$KEY, + POS DOM$POSITION, + NAME DOM$NAME_STANDARD NOT NULL, + SHORT_NAME DOM$NAME_SHORT NOT NULL, + IS_NETWORK_GAS DOM$BOOLEAN, + EXTERNAL_PAYMENT_CS DOM$BOOLEAN NOT NULL, + REPLICATE_PAYMENT DOM$BOOLEAN, + FORBID_CHANGE_OBJECT_AND_LINE_G DOM$BOOLEAN, + APPLY_AMORT_FINE DOM$BOOLEAN NOT NULL +); + + +CREATE TABLE DIR$PAYMENT$SOURCE ( + ID D_KEY NOT NULL, + ID_TYPE_SOURCE DOM$KEY NOT NULL, + ID_SOURCE_READING DOM$KEY, + NAME DOM$NAME_STANDARD NOT NULL, + NAME_CONTRACTOR DOM$NAME_CONTRACTOR, + POS DOM$POSITION NOT NULL, + DATE_PAYMENT_EQUAL_DATE_ACCOUNT DOM$BOOLEAN NOT NULL, + DATES_PAYMENT_EQUAL DOM$BOOLEAN NOT NULL, + LOAD_TO_BASE DOM$BOOLEAN NOT NULL, + LOAD_FROM_FILE DOM$BOOLEAN NOT NULL, + RECEIPT_HAS_NUMBER DOM$BOOLEAN NOT NULL, + RECEIPT_IS_FSA DOM$BOOLEAN, + EXIST_NUMBER_REGISTRY DOM$BOOLEAN, + EXIST_PAYMENT_ORDER DOM$BOOLEAN NOT NULL, + EXIST_CASHIER DOM$BOOLEAN NOT NULL, + IS_PAYMENT_FOR_CS DOM$BOOLEAN NOT NULL, + IS_PAYMENT_BY_BAILIFF DOM$BOOLEAN NOT NULL, + PAYMENT_FOR_LAWSUIT DOM$BOOLEAN NOT NULL, + HIDDEN DOM$BOOLEAN NOT NULL, + RETURN_RECEIPT DOM$BOOLEAN NOT NULL, + GROUP_DISTRICTS D_LIST_ID, + SELL_MATERIAL DOM$BOOLEAN DEFAULT 0 NOT NULL, + IS_RKC DOM$BOOLEAN NOT NULL, + PRINT_CHECK_IN_POSSYSTEM DOM$BOOLEAN_REAL DEFAULT FALSE NOT NULL +); + + +CREATE TABLE DIR$PAYMENT$SOURCE_GD ( + ID_SOURCE DOM$KEY NOT NULL, + ID_GROUP_DISTRICT DOM$KEY NOT NULL, + EXPORT_TO_GIS DOM$BOOLEAN DEFAULT 0 NOT NULL +); + + +CREATE TABLE DOC$ABONENT$LAWSUIT ( + ID D_KEY NOT NULL, + ID_CREATOR D_KEY NOT NULL, + ID_CLOSER D_KEY, + ID_BRANCH DOM$KEY NOT NULL, + ID_GROUP_DISTRICT DOM$KEY NOT NULL, + ID_TYPE_LAWSUIT DOM$KEY NOT NULL, + ID_KIND_LAWSUIT DOM$KEY NOT NULL, + ID_COURT_DISTRICT D_KEY, + ID_COURT_DISTRICT_DECISION DOM$KEY, + ID_ABONENT D_KEY NOT NULL, + ID_COURT_DECISION D_KEY, + ID_REASON_CANCEL D_KEY, + ID_BEGIN_PERIOD_DEBT DOM$PERIOD, + ID_END_PERIOD_DEBT DOM$PERIOD, + ID_PREPARE_REPRESENTATIVE DOM$KEY, + ID_SERVICE_COPYING_ERGN DOM$KEY, + ID_BT_COPYING_ERGN DOM$KEY, + TIMESTAMP_CREATION DOM$CURRENT_TIMESTAMP, + TIMESTAMP_CLOSING DOM$TIMESTAMP, + DATE_PREPARED DOM$DATE, + FILE_NUMBER DOM$NUMBER_FILE, + DEBT_GAS DOM$AMOUNT NOT NULL, + DEBT_MS DOM$AMOUNT NOT NULL, + DEBT_FINE DOM$AMOUNT NOT NULL, + DEBT_TOTAL COMPUTED BY (DEBT_GAS + DEBT_MS + DEBT_FINE), + COST_CERTIFICATE_ABOUT_FAMILY DOM$AMOUNT NOT NULL, + AMOUNT_LAWSUIT DOM$AMOUNT NOT NULL, + DUTY DOM$AMOUNT NOT NULL, + DATE_TRANSFERRED_TO_COURT DOM$DATE, + DECISION_GAS DOM$AMOUNT NOT NULL, + DECISION_MS DOM$AMOUNT NOT NULL, + DECISION_FINE DOM$AMOUNT NOT NULL, + DECISION_DUTY DOM$AMOUNT NOT NULL, + DECISION_COST_CAF DOM$BOOLEAN NOT NULL, + DECISION_AMOUNT_LAWSUIT COMPUTED BY (DECISION_GAS + DECISION_MS + DECISION_FINE), + DECISION_TOTAL COMPUTED BY (DECISION_GAS + DECISION_MS + DECISION_FINE + IIF(DECISION_COST_CAF = 1, COST_CERTIFICATE_ABOUT_FAMILY, 0) + DECISION_DUTY), + DUTY_SOLIDARED DOM$BOOLEAN, + STATE DOM$STATE NOT NULL, + CLOSED DOM$BOOLEAN NOT NULL, + COMMENT DOM$COMMENT, + DATE_CANCEL DOM$DATE, + COMMENT_CANCEL DOM$COMMENT, + COMMENT_DECISION DOM$COMMENT, + PAYMENT_GAS DOM$AMOUNT NOT NULL, + PAYMENT_MS DOM$AMOUNT NOT NULL, + PAYMENT_FINE DOM$AMOUNT NOT NULL, + PAYMENT_CAF DOM$AMOUNT NOT NULL, + PAYMENT_DUTY DOM$AMOUNT NOT NULL, + REST_AMOUNT_LAWSUIT DOM$AMOUNT NOT NULL, + DATE_BEGIN_LAWSUIT DOM$DATE, + DATE_END_LAWSUIT DOM$DATE, + LAWSUIT_FROM_AMURCC DOM$BOOLEAN NOT NULL, + FILE_NUMBER_SHORT D_VARCHAR_10, + NAME_LAWSUIT COMPUTED BY ('Иск' || TRIM(TRAILING FROM IIF(DATE_PREPARED IS NOT NULL, ' от ' || FORMAT_DATE(DATE_PREPARED), ' подготавливается')) + || TRIM(TRAILING FROM IIF(FILE_NUMBER IS NOT NULL, ' №' || FILE_NUMBER, '')) + || ' за ' || FORMAT_DATE(DATE_BEGIN_LAWSUIT) || ' - ' || FORMAT_DATE(DATE_END_LAWSUIT)), + REST_LAWSUIT_BY_MONTHS_DEBT DOM$AMOUNT +); + + +CREATE TABLE DOC$ABONENT$LAWSUIT_CITIZEN ( + ID D_KEY NOT NULL, + ID_LAWSUIT D_KEY NOT NULL, + ID_CITIZEN D_KEY NOT NULL +); + + +CREATE TABLE DOC$COURT_PROCESS$SUMMONS ( + ID DOM$KEY NOT NULL, + ID_CREATOR DOM$KEY NOT NULL, + ID_GROUP_DISTRICT DOM$KEY NOT NULL, + ID_COURT_DISTRICT DOM$KEY NOT NULL, + TIMESTAMP_CREATION DOM$CURRENT_TIMESTAMP, + TIMESTAMP_POSTING DOM$TIMESTAMP, + DATE_SITTING DOM$DATE NOT NULL, + TIME_SITTING DOM$TIME NOT NULL, + QUANTITY D_QUANTITY NOT NULL, + AMOUNT_LAWSUIT DOM$AMOUNT NOT NULL, + AMOUNT_DUTY DOM$AMOUNT NOT NULL, + COST_CAF DOM$AMOUNT NOT NULL, + COMMENT DOM$COMMENT +); + + +CREATE TABLE DOC$COURT_PROCESS$SUMMONS_LAWSU ( + ID DOM$KEY NOT NULL, + ID_SUMMONS DOM$KEY NOT NULL, + ID_LAWSUIT DOM$KEY NOT NULL, + TIMESTAMP_CREATION DOM$CURRENT_TIMESTAMP NOT NULL, + NUMBER_FILE DOM$NUMBER_FILE, + COMMENT DOM$COMMENT +); + + +CREATE TABLE DOC$LAWSUIT$EXEC_PROC ( + ID DOM$KEY NOT NULL, + ID_WRIT_OF_EXEC DOM$KEY NOT NULL, + ID_CREATOR DOM$KEY NOT NULL, + ID_BUMBAILIFF_COMMENCEMENT DOM$KEY, + ID_BUMBAILIFF_EXPIRE DOM$KEY, + ID_REASON_EXPIRE DOM$KEY, + ID_BANK DOM$KEY, + ID_RESULT_BANK DOM$KEY, + TIMESTAMP_CREATION DOM$CURRENT_TIMESTAMP NOT NULL, + DATE_TRANSFERENCE DOM$DATE, + NUMBER DOM$NUMBER_EXEC_PROCESS, + DATE_COMMENCEMENT DOM$DATE, + DATE_OBTAIN_COMMENCEMENT DOM$DATE, + DATE_EXPIRE DOM$DATE, + DATE_OBTAIN_EXPIRE DOM$DATE, + DATE_OBTAIN_RESULT_BANK DOM$DATE, + TO_RECOVER_GAS DOM$AMOUNT NOT NULL, + TO_RECOVER_MS DOM$AMOUNT NOT NULL, + TO_RECOVER_FINE DOM$AMOUNT NOT NULL, + TO_RECOVER_CAF DOM$AMOUNT NOT NULL, + TO_RECOVER_DUTY DOM$AMOUNT NOT NULL, + TO_RECOVER_TOTAL COMPUTED BY (TO_RECOVER_GAS + TO_RECOVER_MS + TO_RECOVER_FINE + TO_RECOVER_CAF + TO_RECOVER_DUTY), + PAYMENT_GAS DOM$AMOUNT NOT NULL, + PAYMENT_MS DOM$AMOUNT NOT NULL, + PAYMENT_FINE DOM$AMOUNT NOT NULL, + PAYMENT_CAF DOM$AMOUNT NOT NULL, + PAYMENT_DUTY DOM$AMOUNT NOT NULL, + PAYMENT_TOTAL COMPUTED BY (PAYMENT_GAS + PAYMENT_MS + PAYMENT_FINE + PAYMENT_CAF + PAYMENT_DUTY), + STATE DOM$STATE NOT NULL, + NAME_STATE COMPUTED BY (TRIM(CASE STATE + WHEN 0 THEN 'Подготовлено в ОСП' + WHEN 1 THEN 'Исполнительный лист передан в ОСП' + WHEN 2 THEN 'В исполнительном производстве' + WHEN 3 THEN 'Исполнительное производство окончено' + WHEN 4 THEN 'Подготовлено для банка' + WHEN 5 THEN 'Передано в банк' + END)), + RECOVERED_AMOUNT DOM$AMOUNT NOT NULL, + COMMENT DOM$COMMENT, + NOT_RECOVERED_AMOUNT DOM$AMOUNT NOT NULL, + AUTO_DATE_COMMENCEMENT DOM$BOOLEAN NOT NULL, + AUTO_NUMBER DOM$BOOLEAN NOT NULL, + AUTO_DATE_EXPIRE DOM$BOOLEAN NOT NULL, + AUTO_REASON_EXPIRE DOM$BOOLEAN NOT NULL, + AUTO_ID_BUMBAILIFF_COMMENCEMENT DOM$BOOLEAN DEFAULT 0, + AMOUNT_BY_BAILIFF DOM$AMOUNT, + REST_AMOUNT_BY_BAILIFF DOM$AMOUNT, + DATE_RELEVANCE DOM$DATE +); + + +CREATE TABLE REG$ABONENT$CITIZEN ( + ID D_KEY NOT NULL, + ID_CREATOR D_KEY NOT NULL, + ID_ABONENT D_KEY NOT NULL, + ID_GENDER DOM$KEY, + ID_KINSHIP DOM$KEY, + ID_PASSPORT_ISSUE D_KEY, + ID_PROPERTY_DOCUMENT DOM$KEY, + ID_ORG_PROVIDE_INF_ABOUT_OWNER DOM$KEY, + TIMESTAMP_CREATION DOM$CURRENT_TIMESTAMP NOT NULL, + SURNAME DOM$CITIZEN_SURNAME NOT NULL, + SURNAME_IN_GENETIVE DOM$CITIZEN_SURNAME, + SURNAME_IN_DATIVE DOM$CITIZEN_SURNAME, + MAIDEN_NAME DOM$CITIZEN_SURNAME, + NAME DOM$CITIZEN_NAME, + PATRONYMIC DOM$CITIZEN_PATRONYMIC, + DATE_BEGIN DOM$DATE, + DATE_END DOM$DATE, + IS_RESPONSIBILITY DOM$BOOLEAN NOT NULL, + IS_OWNER DOM$BOOLEAN NOT NULL, + IS_PENSIONER DOM$BOOLEAN NOT NULL, + SURNAME_NAME_PATRONYMIC COMPUTED BY (SURNAME || TRIM(TRAILING FROM IIF(NAME IS NOT NULL, ' ' || NAME || TRIM(TRAILING FROM IIF(PATRONYMIC IS NOT NULL, ' ' || PATRONYMIC, '')), ''))) +); + + +CREATE TABLE DOC$LAWSUIT$WRIT_OF_EXEC ( + ID DOM$KEY NOT NULL, + ID_LAWSUIT DOM$KEY NOT NULL, + ID_CREATOR DOM$KEY NOT NULL, + ID_RESPONDENT DOM$KEY NOT NULL, + ID_REASON_CLOSE DOM$KEY, + ID_CURRENT_EXEC_PROCESS DOM$KEY, + ID_TYPE_WE DOM$KEY NOT NULL, + TIMESTAMP_CREATION DOM$CURRENT_TIMESTAMP NOT NULL, + NUMBER DOM$NUMBER_WRIT_EXEC, + NUMBER_WRIT_EXEC_FOR_DUTY DOM$NUMBER_WRIT_EXEC, + DATE_OBTAINING DOM$DATE, + DATE_CLOSE DOM$DATE, + AMOUNT_GAS DOM$AMOUNT NOT NULL, + AMOUNT_MS DOM$AMOUNT NOT NULL, + AMOUNT_FINE DOM$AMOUNT NOT NULL, + AMOUNT_CAF DOM$AMOUNT NOT NULL, + AMOUNT_DUTY DOM$AMOUNT NOT NULL, + AMOUNT_TOTAL COMPUTED BY (AMOUNT_GAS + AMOUNT_MS + AMOUNT_FINE + AMOUNT_CAF + AMOUNT_DUTY), + PAYMENT_GAS DOM$AMOUNT NOT NULL, + PAYMENT_MS DOM$AMOUNT NOT NULL, + PAYMENT_FINE DOM$AMOUNT NOT NULL, + PAYMENT_CAF DOM$AMOUNT NOT NULL, + PAYMENT_DUTY DOM$AMOUNT NOT NULL, + PAYMENT_TOTAL COMPUTED BY (PAYMENT_GAS + PAYMENT_MS + PAYMENT_FINE + PAYMENT_CAF + PAYMENT_DUTY), + STATE DOM$STATE NOT NULL, + NAME_STATE COMPUTED BY (TRIM(CASE STATE + WHEN 0 THEN 'Создан' + WHEN 1 THEN 'Получен' + WHEN 2 THEN 'Передан в ОСП' + WHEN 3 THEN 'В исполнительном производстве' + WHEN 4 THEN 'Отмена исполнительного производства' + WHEN 5 THEN 'Исполнен' + WHEN 6 THEN 'Отложено' + WHEN 7 THEN 'Закрыт' + WHEN 8 THEN 'Подготовлен для ОСП' + WHEN 9 THEN 'Подготовлен для банка' + WHEN 10 THEN 'Передан в банк' + WHEN 11 THEN 'Недействительный' + END)), + QUANTITY_EXEC_PROCESS COMPUTED BY ((SELECT COUNT(*) FROM DOC$LAWSUIT$EXEC_PROC EP WHERE EP.ID_WRIT_OF_EXEC = DOC$LAWSUIT$WRIT_OF_EXEC.ID)), + DATE_RETURNING DOM$DATE, + DATE_DEFER DOM$DATE, + BALANCE_GAS COMPUTED BY (AMOUNT_GAS - PAYMENT_GAS), + BALANCE_MS COMPUTED BY (AMOUNT_MS - PAYMENT_MS), + BALANCE_FINE COMPUTED BY (AMOUNT_FINE - PAYMENT_FINE), + BALANCE_CAF COMPUTED BY (AMOUNT_CAF - PAYMENT_CAF), + BALANCE_DUTY COMPUTED BY (AMOUNT_DUTY - PAYMENT_DUTY), + BALANCE_TOTAL COMPUTED BY (AMOUNT_TOTAL - PAYMENT_TOTAL), + COMMENT DOM$COMMENT, + IS_VALID DOM$BOOLEAN, + AUTO_NUMBER DOM$BOOLEAN DEFAULT 0 NOT NULL, + NAME COMPUTED BY ((SELECT C.SURNAME_NAME_PATRONYMIC FROM REG$ABONENT$CITIZEN C WHERE C.ID = ID_RESPONDENT) || TRIM(TRAILING FROM IIF(NUMBER IS NOT NULL, ' (' || NUMBER || ')', ''))) +); + + +CREATE TABLE INF$DATABASE$CONST ( + ID DOM$KEY NOT NULL, + DB_VERSION DOM$VERSION NOT NULL, + INTERVAL_AUTOREFRESH D_NATURAL NOT NULL, + MAX_ROWS_IN_HINT D_NATURAL NOT NULL, + MAX_FILTER_HISTORY D_NATURAL NOT NULL, + MAX_REPORT_HISTORY D_NATURAL NOT NULL, + MAX_NOTES_PER_USER D_NATURAL NOT NULL, + MAX_GLOBAL_ACTION_HISTORY D_NATURAL NOT NULL, + MAX_SEARCH_HISTORY D_NATURAL NOT NULL, + EMAIL_HOST D_VARCHAR_15, + MAX_INTERVAL_MS_IN_MONTH D_NATURAL NOT NULL, + MAX_DIGIT_IN_READING D_NATURAL NOT NULL, + SHOW_RECALC_DB_COMPENSATION DOM$BOOLEAN NOT NULL, + MAX_BOTTLES_FOR_REQUEST D_NATURAL NOT NULL, + MAX_BOTTLES_FOR_SELF_DELIVERY D_NATURAL NOT NULL, + MAX_BOTTLES_FOR_INDUSTRY D_NATURAL NOT NULL, + ONLY_COURT_WORK DOM$BOOLEAN NOT NULL, + DEFAULT_SERIES_WRIT_EXEC DOM$SERIES_WRIT_EXEC NOT NULL, + PATH_TO_EXPORT_RECEPTED_READING D_VARCHAR_100, + EDDS_SEND_INTERVAL D_NUMBER, + EDDS_LISTENING_PORT DOM$NETWORK_PORT, + EDDS_URL D_VARCHAR_100, + EDDS_LOCAL_SERVICE_IP D_VARCHAR_15, + USERNAME_FOR_SEND_EMAIL_TO_EXTE D_VARCHAR_10, + PASSWORD_FOR_SEND_EMAIL_TO_EXTE D_VARCHAR_10, + HOST_OF_BAILIFFS_FTP D_VARCHAR_15, + USERNAME_FOR_BAILIFFS_FTP D_VARCHAR_15, + PASSWORD_FOR_BAILIFFS_FTP D_VARCHAR_15, + NAME_FILE_FROM_BAILIFFS D_VARCHAR_25, + ENCRYPT_GROUP_NAME D_VARCHAR_10, + TIMESTAMP_LAST_BAILIFF_FILE DOM$TIMESTAMP, + PATH_SAVE_BAILIFF_FILE D_VARCHAR_255, + BAILIFF_UPLOAD_FILE_NAME DOM$NAME_SHORT, + DATE_LAST_BAILIFF_UPLOAD DOM$DATE, + USERNAME_EMAIL_READINGS DOM$NAME_SHORT, + PASSWORD_EMAIL_READINGS DOM$NAME_SHORT, + PATH_TO_DB_SITE D_VARCHAR_100, + DEFAULT_EDDS_INCOMING_REQUEST_M DOM$NAME_HUGE, + MASTER_BASE DOM$NAME_LONG, + PATH_TO_FOLDER_RECEIPTS D_VARCHAR_100, + PATH_TO_FOLDER_READINGS D_VARCHAR_100, + PATH_TO_STORE_SCANS D_VARCHAR_100, + CONNECTION_STRING_TO_FIAS_BASE D_VARCHAR_500, + DATE_IMPORTED_ABONENTS_AMURCC DOM$DATE, + DATE_IMPORTED_METERS DOM$DATE, + STEP_POS_FOR_HOUSE DOM$POSITION NOT NULL, + DAYS_PAYMENT_TICKET D_NATURAL NOT NULL, + MONTHS_BY_AVERAGE_WO_READINGS D_NATURAL NOT NULL, + MONTHS_AUTORECALC_GAS D_NATURAL NOT NULL, + IS_MASTER_DB DOM$BOOLEAN NOT NULL, + IS_DEVELOPER_DB DOM$BOOLEAN, + TRUSTED_AUTH DOM$BOOLEAN NOT NULL, + ONLY_ABONENT_NATURE_GAS DOM$BOOLEAN NOT NULL, + POSSYSTEM_ADDRESS D_VARCHAR_100, + POSSYSTEM_USER D_VARCHAR_15, + POSSYSTEM_PASSWORD D_VARCHAR_50, + POSSYSTEM_ITEM_PRODUCT D_NATURAL, + POSSYSTEM_ITEM_WORK D_NATURAL, + POSSYSTEM_ITEM_SERVICE D_NATURAL, + POSSYSTEM_ITEM_OTHER D_NATURAL, + PATH_TO_FILE_BANK_STATEMENT D_VARCHAR_50, + LAST_DATE_BANK_STATEMENT DOM$DATE, + DATE_PRICE_MS DOM$DATE +); + + +CREATE TABLE INF$PAYMENT$BANK_STTM ( + ID DOM$KEY GENERATED BY DEFAULT AS IDENTITY, + ID_BRANCH DOM$KEY, + ID_BANK DOM$KEY, + ID_BAILIFF DOM$KEY, + DATE_ACCOUNT DOM$DATE NOT NULL, + DATE_PAYMENT DOM$DATE NOT NULL, + NUMBER DOM$NUMBER_CHECK NOT NULL, + AMOUNT DOM$AMOUNT NOT NULL, + CONTRACTOR DOM$NAME_CONTRACTOR NOT NULL, + PURPOSE D_VARCHAR_500 NOT NULL, + PAYER D_VARCHAR_200, + TIMESTAMP_CREATION DOM$CURRENT_TIMESTAMP, + RECEIPT_CREATED DOM$BOOLEAN_REAL DEFAULT FALSE NOT NULL, + IS_INDIVIDUAL_PAYMENT DOM$BOOLEAN_REAL DEFAULT FALSE NOT NULL, + NEED_RECEIPT COMPUTED BY (((ID_BANK IS NOT NULL) OR (ID_BAILIFF IS NOT NULL) OR (IS_INDIVIDUAL_PAYMENT IS TRUE)) AND (NOT RECEIPT_CREATED)) +); + + +CREATE TABLE SYS$LINK$GASSUPPLY ( + ID DOM$KEY NOT NULL, + ID_PURPOSE_COOKING_FOOD DOM$KEY NOT NULL, + ID_PURPOSE_HEATING DOM$KEY NOT NULL, + ID_TYPE_GS_NATURE_GAS_MANSION DOM$KEY NOT NULL, + ID_TYPE_GS_TANK_GAS_MANSION DOM$KEY NOT NULL, + ID_TYPE_GS_NATURE_GAS_PRIVATE DOM$KEY NOT NULL, + ID_TYPE_GS_NG_PH_IN_CONNECT DOM$KEY NOT NULL, + ID_TYPE_GS_TANK_GAS_MD DOM$KEY NOT NULL, + ID_TYPE_GS_MS_FGE_MANSION DOM$KEY NOT NULL, + ID_TYPE_GS_MS_HGE_PH DOM$KEY NOT NULL, + ID_TYPE_GS_MS_FGE_WO_CHARGE DOM$KEY NOT NULL, + ID_TYPE_GS_MS_FGE_CHARGE_OWNER DOM$KEY NOT NULL, + ID_TYPE_GS_CGBU_MANSION DOM$KEY NOT NULL, + ID_TYPE_GS_IGBU DOM$KEY NOT NULL, + ID_TYPE_GS_IGBU_MANSION_WITH_ES DOM$KEY NOT NULL, + ID_TYPE_GS_IGBU_MANSION_NO_ES DOM$KEY NOT NULL, + ID_TYPE_GS_IGBU_PRIVATE_WITH_ES DOM$KEY NOT NULL, + ID_TYPE_GS_IGBU_PRIVATE_NO_ES DOM$KEY NOT NULL, + ID_TYPE_GS_CGBU_HEATING DOM$KEY NOT NULL, + ID_TYPE_GS_IGBU_COTTAGE_AREA DOM$KEY NOT NULL, + ID_TYPE_GS_IGBU_GARDENING DOM$KEY NOT NULL, + ID_TYPE_GS_NO_CONNECT DOM$KEY NOT NULL, + ID_TYPE_GS_UNKNOWN DOM$KEY NOT NULL, + ID_TYPE_GS_BOTTLES_OF_CGBU DOM$KEY NOT NULL, + ID_TYPE_GS_INDUSTRY_BOTTLE DOM$KEY NOT NULL, + ID_TYPE_GS_DOMESTIC_BOTTLE DOM$KEY NOT NULL, + ID_TYPE_GS_DOMESTIC_TANK_GAS DOM$KEY NOT NULL, + ID_TYPE_GS_CLOSED DOM$KEY NOT NULL, + ID_TYPE_GS_NATURE_GAS_FLAT_ORG DOM$KEY NOT NULL, + ID_TYPE_GS_TANK_GAS_FLAT_ORG DOM$KEY NOT NULL, + ID_TYPE_GS_NATURE_GAS_ORG DOM$KEY NOT NULL, + ID_TYPE_GS_TANK_GAS_ORG DOM$KEY NOT NULL, + ID_TYPE_GAS_DISCONN_NETWORK_GAS DOM$KEY NOT NULL, + ID_TYPE_GAS_NATURE_GAS DOM$KEY NOT NULL, + ID_TYPE_GAS_LIQUEFIED_GAS DOM$KEY NOT NULL, + ID_TYPE_GAS_ABSENCE DOM$KEY NOT NULL, + ID_GIS_PUBLIC_SERVICE_GAS DOM$KEY, + ID_GIS_TYPE_GAS_NATURE DOM$KEY, + ID_GIS_TYPE_GAS_TANK DOM$KEY, + ID_GROUP_TYPE_GS_MANSION DOM$KEY NOT NULL, + ID_GROUP_TYPE_GS_NGPH DOM$KEY NOT NULL, + ID_GROUP_TYPE_GS_DEPARTMENT DOM$KEY NOT NULL, + ID_DEFAULT_TYPE_NORM DOM$KEY NOT NULL, + ID_TYPE_GAS_UNKNOWN DOM$KEY +); + + +CREATE TABLE SYS$LINK$PAYMENT ( + ID DOM$KEY NOT NULL, + ID_SOURCE_BY_LIST_DB DOM$KEY, + ID_SOURCE_ALIGNMENT_BALANCE DOM$KEY NOT NULL, + ID_SOURCE_TRANSFER_PAYMENT DOM$KEY NOT NULL, + ID_SOURCE_TRANSFER_BALANCE DOM$KEY, + ID_SOURCE_SBERBANK DOM$KEY, + ID_SOURCE_SBERBANK_INVOICE DOM$KEY NOT NULL, + ID_SOURCE_POST DOM$KEY, + ID_SOURCE_SITE DOM$KEY NOT NULL, + ID_METHOD_DISTRIB_BY_MONTHS_DEB DOM$KEY NOT NULL, + ID_METHOD_DISTRIB_ONE_SERVICE DOM$KEY NOT NULL, + ID_METHOD_DISTRIB_TWO_SERVICE DOM$KEY NOT NULL, + ID_METHOD_DISTRIB_NO_CHANGE DOM$KEY NOT NULL, + ID_TYPE_RECEIPT_TRANSFER DOM$KEY, + ID_TYPE_RECEIPT_VIA_BAILIFF DOM$KEY, + ID_TYPE_RECEIPT_STATEMENT_CS DOM$KEY NOT NULL, + ID_TYPE_RECEIPT_MS_IGBU DOM$KEY NOT NULL, + ID_TYPE_RECEIPT_COURT_EXPENSES DOM$KEY NOT NULL, + ID_TYPE_SOURCE_NONACCEPT_BANK DOM$KEY, + ID_TYPE_SOURCE_BAILIFF DOM$KEY, + ID_TYPE_SOURCE_PENSION_FUND DOM$KEY, + ID_SOURCE_MTSBANK DOM$KEY, + ID_SOURCE_NONACCEPT_SB DOM$KEY, + ID_SOURCE_NONACCEPT_MTSBANK DOM$KEY, + ID_SOURCE_NONACCEPT_VTB24 DOM$KEY, + ID_SOURCE_NONACCEPT_ROSBANK DOM$KEY, + ID_SOURCE_NONACCEPT_VOSTEXPRESS DOM$KEY, + ID_SOURCE_NONACCEPT_OTKRYTIE DOM$KEY, + ID_SOURCE_RKC_SOVGAVAN DOM$KEY, + ID_SOURCE_ERKC_KOMS DOM$KEY, + ID_SOURCE_ERKC_KOMS_CASHLESS DOM$KEY, + ID_SOURCE_BAILIFF DOM$KEY, + ID_SOURCE_SITE_AMURCC DOM$KEY, + ID_SOURCE_ADVICE DOM$KEY, + ID_SOURCE_RETURN DOM$KEY +); + + +CREATE TABLE SYS$LOG$EXCEPTION ( + ID DOM$KEY NOT NULL, + ID_CREATOR DOM$KEY NOT NULL, + ID_EXCEPTION DOM$KEY NOT NULL, + TIMESTAMP_CREATION DOM$CURRENT_TIMESTAMP, + TEXT DOM$TEXT_EXCEPTION NOT NULL +); + + +CREATE GLOBAL TEMPORARY TABLE TMP$PAYMENT$BANK_STTM ( + POS DOM$POSITION GENERATED BY DEFAULT AS IDENTITY, + LINE D_VARCHAR_500 NOT NULL +) ON COMMIT DELETE ROWS; + + + + +/******************************************************************************/ +/*** Autoincrement generators ***/ +/******************************************************************************/ + + +ALTER TABLE DIR$ENTPR$IND_PAYMENT ALTER ID RESTART WITH 8; +ALTER TABLE DIR$EXEC_PROC$BANK_PURPOSE ALTER ID RESTART WITH 2; +ALTER TABLE DIR$EXEC_PROC$CORRECTION ALTER ID RESTART WITH 99; +ALTER TABLE INF$PAYMENT$BANK_STTM ALTER ID RESTART WITH 12934; +ALTER TABLE TMP$PAYMENT$BANK_STTM ALTER POS RESTART WITH 531285; + + + + +/******************************************************************************/ +/*** Unique constraints ***/ +/******************************************************************************/ + +ALTER TABLE DIR$PAYMENT$SOURCE ADD CONSTRAINT UNQ_DIR$PAYMENT$SOURCE_NAME UNIQUE (NAME); + + +/******************************************************************************/ +/*** Primary keys ***/ +/******************************************************************************/ + +ALTER TABLE BAT$RECEIPT$BATCH ADD CONSTRAINT PK_BAT$RECEIPT$BATCH PRIMARY KEY (ID); +ALTER TABLE BAT$RECEIPT$RECEIPT ADD CONSTRAINT PK_BAT$RECEIPT$RECEIPT PRIMARY KEY (ID); +ALTER TABLE DIR$ABONENT$ABONENT ADD CONSTRAINT PK_DIR$ABONENT$ABONENT PRIMARY KEY (ID); +ALTER TABLE DIR$DATABASE$DATABASE ADD CONSTRAINT PK_DIR$DATABASE$DATABASE PRIMARY KEY (ID); +ALTER TABLE DIR$ENTERPRISE$BRANCH ADD CONSTRAINT PK_DIR$ENTERPRISE$BRANCH PRIMARY KEY (ID); +ALTER TABLE DIR$ENTERPRISE$GROUP_DISTRICT ADD CONSTRAINT PK_DIR$ENTERPRISE$GROUP_DISTRIC PRIMARY KEY (ID); +ALTER TABLE DIR$ENTPR$IND_PAYMENT ADD CONSTRAINT PK_DIR$ENTPR$IND_PAYMENT PRIMARY KEY (ID); +ALTER TABLE DIR$EXEC_PROC$BANK ADD CONSTRAINT PK_DIR$EXEC_PROC$BANK PRIMARY KEY (ID); +ALTER TABLE DIR$EXEC_PROC$BANK_PURPOSE ADD CONSTRAINT PK_DIR$EXEC_PROC$BANK_PURPOSE PRIMARY KEY (ID); +ALTER TABLE DIR$EXEC_PROC$CORRECTION ADD CONSTRAINT PK_DIR$EXEC_PROC$CORRECTION PRIMARY KEY (ID); +ALTER TABLE DIR$GASSUPPLY$TYPE_GS ADD CONSTRAINT PK_DIR$GASSUPPLY$TYPE_GS PRIMARY KEY (ID); +ALTER TABLE DIR$PAYMENT$SOURCE ADD CONSTRAINT PK_DIR$PAYMENT$SOURCE PRIMARY KEY (ID); +ALTER TABLE DIR$PAYMENT$SOURCE_GD ADD CONSTRAINT PK_DIR$PAYMENT$SOURCE_GD PRIMARY KEY (ID_SOURCE, ID_GROUP_DISTRICT); +ALTER TABLE DOC$ABONENT$LAWSUIT ADD CONSTRAINT PK_DOC$ABONENT$LAWSUIT PRIMARY KEY (ID); +ALTER TABLE DOC$ABONENT$LAWSUIT_CITIZEN ADD CONSTRAINT PK_DOC$ABONENT$LAWSUIT_CITIZEN PRIMARY KEY (ID); +ALTER TABLE DOC$COURT_PROCESS$SUMMONS ADD CONSTRAINT PK_DOC$COURT_PROCESS$SUMMONS PRIMARY KEY (ID); +ALTER TABLE DOC$COURT_PROCESS$SUMMONS_LAWSU ADD CONSTRAINT PK_DOC$COURT_PROCESS$SUMMONS_LA PRIMARY KEY (ID); +ALTER TABLE INF$DATABASE$CONST ADD CONSTRAINT PK_INF$DATABASE$CONST PRIMARY KEY (ID); +ALTER TABLE INF$PAYMENT$BANK_STTM ADD CONSTRAINT PK_INF$PAYMENT$BANK_STTM PRIMARY KEY (ID); +ALTER TABLE REG$ABONENT$CITIZEN ADD CONSTRAINT PK_REG$ABONENT$CITIZEN PRIMARY KEY (ID); +ALTER TABLE SYS$LINK$GASSUPPLY ADD CONSTRAINT PK_SYS$LINK$GASSUPPLY PRIMARY KEY (ID); +ALTER TABLE SYS$LINK$PAYMENT ADD CONSTRAINT PK_SYS$LINK$PAYMENT PRIMARY KEY (ID); +ALTER TABLE SYS$LOG$EXCEPTION ADD CONSTRAINT PK_SYS$LOG$EXCEPTION PRIMARY KEY (ID); +ALTER TABLE TMP$PAYMENT$BANK_STTM ADD CONSTRAINT PK_TMP$PAYMENT$BANK_STTM PRIMARY KEY (POS); + + +/******************************************************************************/ +/*** Stored procedures ***/ +/******************************************************************************/ + + + +SET TERM ^ ; + +ALTER PROCEDURE GET$ABONENT$CHARGING_GAS_AMURCC ( + ID_ABONENT DOM$ABONENT NOT NULL) +RETURNS ( + RESULT DOM$BOOLEAN) +AS +BEGIN + RESULT = 1; + + SUSPEND; +END^ + + +ALTER PROCEDURE GET$ABONENT$DEFAULT_TYPE_RECEIP ( + ID_ABONENT DOM$ABONENT NOT NULL) +RETURNS ( + RESULT DOM$KEY) +AS +BEGIN + RESULT = (SELECT TG.ID_TYPE_RECEIPT FROM DIR$ABONENT$ABONENT A INNER JOIN DIR$GASSUPPLY$TYPE_GS TG ON TG.ID = A.ID_TYPE_GASSUPPLY WHERE A.ID = :ID_ABONENT); + IF (:RESULT IS NULL) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA_ABONE(:ID_ABONENT, 'Нет типа квитанции по умолчанию.'); + + SUSPEND; +END^ + + +ALTER PROCEDURE GET$ABONENT$DETERMINE_GD ( + ID_ABONENT DOM$ABONENT_LONG NOT NULL) +RETURNS ( + RESULT DOM$KEY) +AS +BEGIN + IF (CHAR_LENGTH(:ID_ABONENT) = 6) THEN + RESULT = 15;-- Сахалин + ELSE IF (CHAR_LENGTH(:ID_ABONENT) = 12) THEN + RESULT = 12;-- Камчатка АИС РНГ + ELSE IF (LEFT(ID_ABONENT, 1) IN ('3', '4')) THEN + RESULT = 1;-- Центральный офис + ELSE IF (LEFT(ID_ABONENT, 3) = '998') THEN + RESULT = 2;-- Комсомольск + ELSE IF (LEFT(ID_ABONENT, 3) = '997') THEN + RESULT = 3;-- Амурск + ELSE IF (LEFT(ID_ABONENT, 3) = '996') THEN + RESULT = 2;-- Солнечный// По письму Смиринской Е.А. от 19.03.2019 создание сделано в Комсомольском участке + ELSE IF (LEFT(ID_ABONENT, 3) = '994') THEN + RESULT = 5;-- Чегдомын + ELSE IF ((LEFT(ID_ABONENT, 6) IN ('995000', '995001')) OR (LEFT(ID_ABONENT, 5) = '99504')) THEN + RESULT = 2;--6;-- Богородское + ELSE IF (LEFT(ID_ABONENT, 2) = '98') THEN + RESULT = 7;-- Совгавань + -- Обработка раньше, чтобы не попал в Хор + ELSE IF (LEFT(ID_ABONENT, 3) = '892') THEN + RESULT = 12;-- Камчатка + ELSE IF ((LEFT(ID_ABONENT, 3) = '291') OR (LEFT(ID_ABONENT, 3) = '292')) THEN + RESULT = 14;-- Лермонтовка + ELSE IF ((LEFT(ID_ABONENT, 1) = '2') OR (LEFT(ID_ABONENT, 2) = '92')) THEN + RESULT = 8;-- Бикин + ELSE IF ((LEFT(ID_ABONENT, 1) = '1') OR (LEFT(ID_ABONENT, 2) = '91')) THEN + RESULT = 9;-- Вяземский + ELSE IF ((LEFT(ID_ABONENT, 1) = '6') OR (LEFT(ID_ABONENT, 3) = '962')) THEN + RESULT = 10;-- Переяславка + ELSE IF ((LEFT(ID_ABONENT, 1) = '8') OR (LEFT(ID_ABONENT, 3) = '961')) THEN + RESULT = 11;-- Хор + ELSE IF (LEFT(ID_ABONENT, 6) IN ('995002', '995003')) THEN + RESULT = 2;--13;-- Де-Кастри + ELSE + RESULT = 0;-- Неизвестно + + SUSPEND; +END^ + + +ALTER PROCEDURE GET$WRIT_EXEC$CHECK_RESPONDENT ( + ID_WRIT_EXEC DOM$KEY NOT NULL, + RESPONDENT D_VARCHAR_100 NOT NULL) +RETURNS ( + RESULT DOM$BOOLEAN) +AS +DECLARE VARIABLE RESP_WRIT_EXEC D_VARCHAR_100; +BEGIN + RESP_WRIT_EXEC = (SELECT UPPER(C.SURNAME_NAME_PATRONYMIC) FROM DOC$LAWSUIT$WRIT_OF_EXEC WE INNER JOIN REG$ABONENT$CITIZEN C ON C.ID = WE.ID_RESPONDENT WHERE WE.ID = :ID_WRIT_EXEC); + RESP_WRIT_EXEC = REPLACE(:RESP_WRIT_EXEC, ' КЫЗЫ', ''); + RESP_WRIT_EXEC = REPLACE(:RESP_WRIT_EXEC, ' ОГЛЫ', ''); + RESP_WRIT_EXEC = REPLACE(:RESP_WRIT_EXEC, 'Й', 'И'); + RESPONDENT = REPLACE(:RESP_WRIT_EXEC, 'Й', 'И'); + + RESULT = IIF(:RESP_WRIT_EXEC IS NOT DISTINCT FROM :RESPONDENT, 1, 0); + + SUSPEND; +END^ + + +ALTER PROCEDURE GET$WRIT_EXEC$SEARCH_BY_RESPOND ( + NUMBER_FILE DOM$NUMBER_FILE NOT NULL, + RESPONDENT D_VARCHAR_100 NOT NULL) +RETURNS ( + RESULT DOM$KEY) +AS +DECLARE VARIABLE ID_CURRENT_WRIT_EXEC DOM$KEY; +DECLARE VARIABLE CURRENT_RESPONDENT D_VARCHAR_100; +DECLARE VARIABLE SEARCHED D_NATURAL; +DECLARE VARIABLE WITH_MAIDEN_NAME D_VARCHAR_100; +BEGIN + SEARCHED = 0; + + RESPONDENT = UPPER(REPLACE(:RESPONDENT, 'Ё', 'Е')); + + FOR SELECT + WE.ID, + UPPER(C.SURNAME_NAME_PATRONYMIC), + IIF(C.MAIDEN_NAME IS NOT NULL, UPPER(C.MAIDEN_NAME || ' ' || C.NAME || ' ' || C.PATRONYMIC), NULL) + FROM + DOC$ABONENT$LAWSUIT L + INNER JOIN DOC$LAWSUIT$WRIT_OF_EXEC WE ON WE.ID_LAWSUIT = L.ID + INNER JOIN REG$ABONENT$CITIZEN C ON C.ID = WE.ID_RESPONDENT + WHERE + (L.FILE_NUMBER STARTING WITH :NUMBER_FILE) + AND (L.STATE NOT IN (3, 5)) + INTO + :ID_CURRENT_WRIT_EXEC, + :CURRENT_RESPONDENT, + :WITH_MAIDEN_NAME + DO + BEGIN + CURRENT_RESPONDENT = REPLACE(:CURRENT_RESPONDENT, 'Ё', 'Е'); + IF (RIGHT(:CURRENT_RESPONDENT, 5) = ' ОГЛЫ') THEN + CURRENT_RESPONDENT = LEFT(:CURRENT_RESPONDENT, CHAR_LENGTH(:CURRENT_RESPONDENT) - 5); + IF (RIGHT(:CURRENT_RESPONDENT, 5) = ' КЫЗЫ') THEN + CURRENT_RESPONDENT = LEFT(:CURRENT_RESPONDENT, CHAR_LENGTH(:CURRENT_RESPONDENT) - 5); + + IF (:CURRENT_RESPONDENT IS NOT DISTINCT FROM :RESPONDENT) THEN + BEGIN + RESULT = :ID_CURRENT_WRIT_EXEC; + + SEARCHED = :SEARCHED + 1; + IF (:SEARCHED > 1) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Найдено более 1 иска по делу №' || :NUMBER_FILE || ' ответчика ' || :RESPONDENT); + + SUSPEND; + + -- В КФ есть иск, где два ответчика с одинаковыми ФИО, но разным годом рождения. Если это тот случай, пропускаем второго ответчика + IF ((:NUMBER_FILE = '2-443/2018') AND (:RESPONDENT = 'СТАРЧЕНКОВ ВЛАДИМИР ВЛАДИМИРОВИЧ')) THEN + EXIT; + -- В ЦО есть иск, где два ответчика с одинаковыми ФИО, но разным годом рождения. Если это тот случай, пропускаем второго ответчика + IF ((:NUMBER_FILE = '2-3197/2018') AND (:RESPONDENT = 'СЫРОВА ТАТЬЯНА ВЛАДИМИРОВНА')) THEN + EXIT; + END + + -- Ищем по девичьей фамилии + IF (:WITH_MAIDEN_NAME IS NOT NULL) THEN + BEGIN + CURRENT_RESPONDENT = :WITH_MAIDEN_NAME; + + CURRENT_RESPONDENT = REPLACE(:CURRENT_RESPONDENT, 'Ё', 'Е'); + IF (RIGHT(:CURRENT_RESPONDENT, 5) = ' ОГЛЫ') THEN + CURRENT_RESPONDENT = LEFT(:CURRENT_RESPONDENT, CHAR_LENGTH(:CURRENT_RESPONDENT) - 5); + IF (RIGHT(:CURRENT_RESPONDENT, 5) = ' КЫЗЫ') THEN + CURRENT_RESPONDENT = LEFT(:CURRENT_RESPONDENT, CHAR_LENGTH(:CURRENT_RESPONDENT) - 5); + + IF (:CURRENT_RESPONDENT IS NOT DISTINCT FROM :RESPONDENT) THEN + BEGIN + RESULT = :ID_CURRENT_WRIT_EXEC; + + SEARCHED = :SEARCHED + 1; + IF (:SEARCHED > 1) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Найдено более 1 иска по делу №' || :NUMBER_FILE || ' ответчика ' || :RESPONDENT); + SUSPEND; + END + END + END + + IF (:SEARCHED = 0) THEN + SUSPEND; +END^ + + +ALTER PROCEDURE OPER$EXCEPTION$CANCEL ( + TEXT D_VARCHAR_500) +AS +BEGIN + IF ((SELECT MON$READ_ONLY FROM MON$TRANSACTIONS WHERE MON$TRANSACTION_ID = CURRENT_TRANSACTION) = 0) THEN + IN AUTONOMOUS TRANSACTION DO + INSERT INTO SYS$LOG$EXCEPTION + (ID, ID_EXCEPTION, TEXT) + VALUES + (NEXT VALUE FOR SEQ_SYS$LOG$EXCEPTION_ID, 8, :TEXT); + + EXCEPTION EXC$CANCEL :TEXT; +END^ + + +ALTER PROCEDURE OPER$EXCEPTION$CHECK_DATA ( + TEXT D_VARCHAR_500) +AS +BEGIN + IF (RDB$GET_CONTEXT('SYSTEM', 'READ_ONLY') = 'FALSE') THEN + IN AUTONOMOUS TRANSACTION DO + INSERT INTO SYS$LOG$EXCEPTION + (ID, ID_EXCEPTION, TEXT) + VALUES + (NEXT VALUE FOR SEQ_SYS$LOG$EXCEPTION_ID, 7, :TEXT); + + EXCEPTION EXC$CHECK_DATA :TEXT; +END^ + + +ALTER PROCEDURE OPER$EXCEPTION$CHECK_DATA_ABONE ( + ID_ABONENT DOM$ABONENT NOT NULL, + TEXT D_VARCHAR_500 NOT NULL) +AS +BEGIN +-- EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA(COALESCE((SELECT RESULT FROM GET$ABONENT$ABONENT_AND_ADDRESS(:ID_ABONENT)), :ID_ABONENT) || '.' || ASCII_CHAR(31) || :TEXT); +END^ + + +ALTER PROCEDURE OPER$EXCEPTION$CHECK_DATA_BRANC ( + ID_BRANCH DOM$KEY NOT NULL, + TEXT D_VARCHAR_500 NOT NULL) +AS +BEGIN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA((SELECT B.INTERNAL_NAME FROM DIR$ENTERPRISE$BRANCH B WHERE B.ID = :ID_BRANCH) || '.' || ASCII_CHAR(31) || :TEXT); +END^ + + + +SET TERM ; ^ + + + +/******************************************************************************/ +/*** Stored functions ***/ +/******************************************************************************/ + + + +SET TERM ^ ; + +ALTER FUNCTION DATE_TO_PERIOD ( + VAL DOM$DATE) +RETURNS DOM$PERIOD +AS +BEGIN + RETURN 1; +END^ + + +ALTER FUNCTION DEC_PERIOD ( + VAL DOM$PERIOD) +RETURNS DOM$PERIOD +AS +begin + /* Function Text */ + return 1; +end^ + + +ALTER FUNCTION FORMAT_DATE ( + ARG DOM$DATE) +RETURNS DOM$STRING_DATE +AS +BEGIN + IF (:ARG IS NOT NULL) THEN + RETURN RIGHT(:ARG, 2) || '.' || SUBSTRING(:ARG FROM 6 FOR 2) || '.' || LEFT(:ARG, 4); + ELSE + RETURN ''; +END^ + + + +SET TERM ; ^ + + + +/******************************************************************************/ +/*** Package headers ***/ +/******************************************************************************/ + + + +SET TERM ^ ; + + +SET TERM ; ^ + + + +/******************************************************************************/ +/*** Package bodies ***/ +/******************************************************************************/ + + + +SET TERM ^ ; + +CREATE PACKAGE BODY PKG$ABONENT +AS +BEGIN + FUNCTION GET_GROUP_DISTRICT_FOR_PAYMENT(ID_ABONENT DOM$ABONENT NOT NULL) RETURNS DOM$KEY DETERMINISTIC + AS + DECLARE VARIABLE ID_BRANCH DOM$KEY; + BEGIN + RETURN (SELECT A.ID_BRANCH FROM DIR$ABONENT$ABONENT A WHERE A.ID = :ID_ABONENT); + END +END^ + + +CREATE PACKAGE BODY PKG$CONNECT +AS +BEGIN + FUNCTION ID_USER() RETURNS DOM$KEY DETERMINISTIC + AS + BEGIN + RETURN RDB$GET_CONTEXT('USER_SESSION', 'ID_USER'); + END + + FUNCTION ID_DIVISION() RETURNS DOM$KEY DETERMINISTIC + AS + BEGIN + RETURN RDB$GET_CONTEXT('USER_SESSION', 'ID_DIVISION'); + END + + FUNCTION ID_WORKER() RETURNS DOM$KEY DETERMINISTIC + AS + BEGIN + RETURN RDB$GET_CONTEXT('USER_SESSION', 'ID_WORKER'); + END + + FUNCTION ID_CS() RETURNS DOM$KEY DETERMINISTIC + AS + BEGIN + RETURN RDB$GET_CONTEXT('USER_SESSION', 'ID_CS'); + END + + FUNCTION ID_BRANCH() RETURNS DOM$KEY DETERMINISTIC + AS + BEGIN + RETURN RDB$GET_CONTEXT('USER_SESSION', 'ID_BRANCH'); + END + + FUNCTION ID_GROUP_DISTRICT() RETURNS DOM$KEY DETERMINISTIC + AS + BEGIN + RETURN RDB$GET_CONTEXT('USER_SESSION', 'ID_GROUP_DISTRICT'); + END + + FUNCTION CURRENT_USER_SURNAME_NP RETURNS D_VARCHAR_50 DETERMINISTIC + AS + BEGIN + RETURN NULL; + END +END^ + + +CREATE PACKAGE BODY PKG$EXCEPTION +AS +BEGIN + PROCEDURE FOR_CITIZEN(ID_CITIZEN DOM$KEY NOT NULL, TEXT D_VARCHAR_500 NOT NULL) + AS + DECLARE VARIABLE ID_ABONENT DOM$ABONENT; + BEGIN + END + + PROCEDURE FOR_WORKER(ID_WORKER DOM$KEY NOT NULL, TEXT D_VARCHAR_500 NOT NULL) + AS + BEGIN + END + + PROCEDURE FOR_BATCH_RECEIPT(ID_BATCH DOM$KEY NOT NULL, TEXT D_VARCHAR_500 NOT NULL) + AS + BEGIN + END +END^ + + +CREATE PACKAGE BODY PKG$PAYMENT$BANK_STTM +AS +BEGIN + PROCEDURE GET_LIST_BRANCH RETURNS (ID DOM$KEY, NAME DOM$NAME_STANDARD) + AS + BEGIN + FOR SELECT + B.ID, + B.INTERNAL_NAME + FROM + DIR$ENTERPRISE$BRANCH B + WHERE + B.USE_FOR_BANK_STATEMENT IS TRUE + ORDER BY + B.POS + INTO + :ID, + :NAME + DO + SUSPEND; + END + + PROCEDURE PARSE_PAYMENT_ORDERS + AS + DECLARE VARIABLE POS DOM$POSITION; + DECLARE VARIABLE LINE D_VARCHAR_500; + DECLARE VARIABLE NAME_BANK D_VARCHAR_100; + DECLARE VARIABLE DATE_ACCOUNT DOM$DATE; + DECLARE VARIABLE DATE_PAYMENT DOM$DATE; + DECLARE VARIABLE NUMBER_DOC DOM$NUMBER_CHECK; + DECLARE VARIABLE AMOUNT DOM$AMOUNT; + DECLARE VARIABLE PURPOSE D_VARCHAR_500; + DECLARE VARIABLE PAYER D_VARCHAR_200; + DECLARE VARIABLE SHIFT_LINE D_NATURAL; + DECLARE VARIABLE LAST_DATE_BANK_STATEMENT DOM$DATE; + DECLARE VARIABLE MAX_DATE_ACCOUNT DOM$DATE; + BEGIN + -- Проверяем наличие платежей + IF (NOT EXISTS(SELECT 1 FROM TMP$PAYMENT$BANK_STTM)) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CANCEL('Таблица выписки из банка пуста.'); + + -- + LAST_DATE_BANK_STATEMENT = (SELECT LAST_DATE_BANK_STATEMENT FROM INF$DATABASE$CONST); + IF (:LAST_DATE_BANK_STATEMENT IS NULL) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CANCEL('Не указана дата последней выписки из банка.'); + + MAX_DATE_ACCOUNT = :LAST_DATE_BANK_STATEMENT; + + -- + FOR SELECT + P.POS, + P.LINE + FROM + TMP$PAYMENT$BANK_STTM P + WHERE + P.LINE STARTING WITH 'НазначениеПлатежа=' + INTO + :POS, + :LINE + DO + BEGIN + -- У документа может отсутствовать поле "ПолучательКорсчет=" + SHIFT_LINE = IIF(LEFT((SELECT LINE FROM TMP$PAYMENT$BANK_STTM WHERE POS = :POS - 13), 18) = 'ПолучательКорсчет=', 0, 1); + + -- Определяем банк + NAME_BANK = SUBSTRING((SELECT LINE FROM TMP$PAYMENT$BANK_STTM WHERE POS = :POS - 24 + :SHIFT_LINE) FROM 17);-- Пропускаем слово "ПлательщикБанк1=" + IF (:NAME_BANK IS NULL) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('По п/п №' || :NUMBER_DOC || ' не указано название банка'); + + -- Определяем номер документа + NUMBER_DOC = RIGHT(SUBSTRING((SELECT P.LINE FROM TMP$PAYMENT$BANK_STTM P WHERE P.POS = :POS - 33 + :SHIFT_LINE) FROM 7), 6);-- Пропускаем слово "Номер=" + + -- Определяем дату оплаты + DATE_PAYMENT = SUBSTRING((SELECT P.LINE FROM TMP$PAYMENT$BANK_STTM P WHERE P.POS = :POS - 32 + :SHIFT_LINE) FROM 6);-- Пропускаем слово "Дата=" + + -- Определяем дату учета + DATE_ACCOUNT = NULLIF(SUBSTRING((SELECT P.LINE FROM TMP$PAYMENT$BANK_STTM P WHERE P.POS = :POS - 20 + :SHIFT_LINE) FROM 15), '');-- Пропускаем слово "ДатаПоступило=" + IF (:DATE_ACCOUNT IS NULL) THEN + CONTINUE; + + IF (:DATE_ACCOUNT <= :LAST_DATE_BANK_STATEMENT) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Дата учета (' || FORMAT_DATE(:DATE_ACCOUNT) + || ') у документа №' || :NUMBER_DOC || ' меньше или равна дате последней загрузки выписки (' || FORMAT_DATE(:LAST_DATE_BANK_STATEMENT) || ')'); + + IF (:DATE_ACCOUNT > :MAX_DATE_ACCOUNT) THEN + MAX_DATE_ACCOUNT = :DATE_ACCOUNT; + + -- Определяем сумму платежа + AMOUNT = SUBSTRING((SELECT P.LINE FROM TMP$PAYMENT$BANK_STTM P WHERE P.POS = :POS - 31 + :SHIFT_LINE) FROM 7);-- Пропускаем слово "Сумма=" + + -- Определяем назначение + PURPOSE = SUBSTRING(:LINE FROM 19);-- Пропускаем слово "НазначениеПлатежа=" + + -- Определяем плательщика + PAYER = SUBSTRING((SELECT P.LINE FROM TMP$PAYMENT$BANK_STTM P WHERE P.POS = :POS - 28 + :SHIFT_LINE) FROM 12);-- Пропускаем слово "Плательщик=" + + -- Создаем платеж + INSERT INTO INF$PAYMENT$BANK_STTM + (DATE_ACCOUNT, DATE_PAYMENT, NUMBER, AMOUNT, CONTRACTOR, PURPOSE, PAYER) + VALUES + (:DATE_ACCOUNT, :DATE_PAYMENT, :NUMBER_DOC, :AMOUNT, :NAME_BANK, :PURPOSE, :PAYER); + END + + UPDATE INF$DATABASE$CONST + SET + LAST_DATE_BANK_STATEMENT = :MAX_DATE_ACCOUNT; + + RDB$SET_CONTEXT('USER_SESSION', 'BANK_STTM_DATE_ACCOUNT', FORMAT_DATE(:MAX_DATE_ACCOUNT)); + END + + PROCEDURE DETECT_SOURCE_PAYMENT(DATE_ACCOUNT DOM$DATE NOT NULL) + AS + DECLARE VARIABLE ID DOM$KEY; + DECLARE VARIABLE CONTRACTOR D_VARCHAR_200; + DECLARE VARIABLE PURPOSE D_VARCHAR_500; + DECLARE VARIABLE PAYER D_VARCHAR_200; + DECLARE VARIABLE ID_BANK DOM$KEY; + DECLARE VARIABLE ID_BAILIFF DOM$KEY; + DECLARE VARIABLE ID_BRANCH DOM$KEY; + BEGIN + FOR SELECT + BS.ID, + BS.CONTRACTOR, + BS.PURPOSE, + BS.PAYER + FROM + INF$PAYMENT$BANK_STTM BS + WHERE + BS.DATE_ACCOUNT = :DATE_ACCOUNT + ORDER BY + BS.ID + INTO + :ID, + :CONTRACTOR, + :PURPOSE, + :PAYER + DO + BEGIN + IF (:PURPOSE = 'Перечисление средств в счет погашения долга взыскателю :Булатова Наталья Васильевна 680000, Россия, , , г. Хабаровск, , ул. Тихоокеанская, д. 219, , кв. 66 Исполнительный лист 00319470') THEN + BEGIN + UPDATE INF$PAYMENT$BANK_STTM B + SET + B.ID_BANK = NULL, + B.ID_BAILIFF = NULL, + B.IS_INDIVIDUAL_PAYMENT = FALSE + WHERE + B.ID = :ID; + + CONTINUE; + END + + IF (:PURPOSE LIKE '%АРБИТР%') THEN + BEGIN + UPDATE INF$PAYMENT$BANK_STTM B + SET + B.ID_BANK = NULL, + B.ID_BAILIFF = NULL, + B.IS_INDIVIDUAL_PAYMENT = FALSE + WHERE + B.ID = :ID; + + CONTINUE; + END + + -- Ищем банк в списке + ID_BANK = (SELECT B.ID FROM DIR$EXEC_PROC$BANK B WHERE :CONTRACTOR LIKE '%' || B.NAME_IN_FILE_BANK_CLIENT || '%'); + + -- Проверяем, является ли платеж безакцептным от банка + IF (:ID_BANK IS NOT NULL) THEN + IF (EXISTS(SELECT 1 FROM DIR$EXEC_PROC$BANK_PURPOSE BP WHERE (BP.ID_BANK = :ID_BANK) AND (:PURPOSE STARTING WITH BP.NAME))) THEN + BEGIN + -- Указываем, что это банк + UPDATE INF$PAYMENT$BANK_STTM B + SET + B.ID_BANK = :ID_BANK + WHERE + (B.ID = :ID) + AND (B.ID_BANK IS DISTINCT FROM :ID_BANK); + + CONTINUE; + END + + -- Определяем, является ли платеж от ССП + ID_BAILIFF = (SELECT S.ID FROM DIR$PAYMENT$SOURCE S WHERE :PAYER LIKE '%' || S.NAME_CONTRACTOR || '%'); + + IF (:ID_BAILIFF IS NOT NULL) THEN + BEGIN + -- Указываем, что это ССП + UPDATE INF$PAYMENT$BANK_STTM B + SET + B.ID_BAILIFF = :ID_BAILIFF + WHERE + (B.ID = :ID) + AND (B.ID_BAILIFF IS DISTINCT FROM :ID_BAILIFF); + + CONTINUE; + END + + -- Определяем, является ли платеж индивидуальным + IF (((:PAYER NOT LIKE '%ИП %') AND (:PAYER NOT LIKE '%Индивидуальный %') AND (:PURPOSE NOT LIKE '%т.ч. НДС%') AND (:PURPOSE NOT LIKE '%МКД-20%') AND (:PURPOSE NOT LIKE '%МКД-10%') AND (:PURPOSE NOT LIKE '%998,%') AND (:PURPOSE NOT LIKE '%ФСГ%') AND (:PURPOSE NOT LIKE '%сч/ф%') AND (:PAYER NOT LIKE 'ООО "МУЛЬТИПРОДУКТ"')) OR (:PURPOSE LIKE '%ЖКУ%')) THEN + BEGIN + ID_BRANCH = (SELECT IP.ID_BRANCH FROM DIR$ENTPR$IND_PAYMENT IP WHERE LOWER(:PURPOSE) LIKE '%' || LOWER(IP.NAME) || '%' GROUP BY IP.ID_BRANCH); + + IF (:ID_BRANCH IS NOT NULL) THEN + BEGIN + -- Указываем, что это инд. платеж + UPDATE INF$PAYMENT$BANK_STTM B + SET + B.IS_INDIVIDUAL_PAYMENT = TRUE + WHERE + (B.ID = :ID) + AND (B.IS_INDIVIDUAL_PAYMENT IS FALSE); + + CONTINUE; + END + END + + UPDATE INF$PAYMENT$BANK_STTM B + SET + B.ID_BRANCH = NULL, + B.ID_BANK = NULL, + B.ID_BAILIFF = NULL, + B.IS_INDIVIDUAL_PAYMENT = FALSE + WHERE + (B.ID = :ID) + AND ((B.ID_BRANCH IS NOT NULL) OR (B.ID_BANK IS NOT NULL) OR (B.ID_BAILIFF IS NOT NULL) OR (B.IS_INDIVIDUAL_PAYMENT IS TRUE)); + END + END + + PROCEDURE CREATE_RECEIPTS_FOR_DATE(DATE_ACCOUNT DOM$DATE) + AS + DECLARE VARIABLE ID DOM$KEY; + DECLARE VARIABLE TYPE_PAYMENT DOM$INTEGER; + DECLARE VARIABLE QUANTITY DOM$INTEGER; + DECLARE VARIABLE NOT_RECOGN DOM$INTEGER; + BEGIN + IF (:DATE_ACCOUNT IS NULL) THEN + DATE_ACCOUNT = RDB$GET_CONTEXT('USER_SESSION', 'BANK_STTM_DATE_ACCOUNT'); + + QUANTITY = 0; + + FOR SELECT + I.ID + FROM + INF$PAYMENT$BANK_STTM I + WHERE + (I.DATE_ACCOUNT = :DATE_ACCOUNT) + AND ((I.ID_BANK IS NOT NULL) OR (I.ID_BAILIFF IS NOT NULL) OR (I.IS_INDIVIDUAL_PAYMENT IS TRUE)) + AND (I.RECEIPT_CREATED IS FALSE) + INTO + :ID + DO + BEGIN + EXECUTE PROCEDURE CREATE_RECEIPT(:ID, NULL); + + QUANTITY = :QUANTITY + 1; + END + + IF (:QUANTITY > 0) THEN + BEGIN + NOT_RECOGN = (SELECT COUNT(*) FROM INF$PAYMENT$BANK_STTM I WHERE (I.DATE_ACCOUNT = :DATE_ACCOUNT) AND ((I.ID_BANK IS NOT NULL) OR (I.ID_BAILIFF IS NOT NULL) OR (I.IS_INDIVIDUAL_PAYMENT IS TRUE)) AND (I.RECEIPT_CREATED IS FALSE)); + +-- EXECUTE PROCEDURE SEND_NOTIFY_LOAD_BANK_STATEMENT(:DATE_ACCOUNT, :NOT_RECOGN); + END + ELSE + EXECUTE PROCEDURE OPER$EXCEPTION$CANCEL('Не найдено платежей для создания квитанций.'); + END + + PROCEDURE CREATE_INDIVID_RECEIPT(ID DOM$KEY NOT NULL, ID_ABONENT DOM$ABONENT NOT NULL) + AS + DECLARE VARIABLE ID_GROUP_DISTRICT DOM$KEY; + DECLARE VARIABLE ID_BRANCH DOM$KEY; + BEGIN + ID_GROUP_DISTRICT = (SELECT RESULT FROM GET$ABONENT$DETERMINE_GD(:ID_ABONENT)); + IF (:ID_GROUP_DISTRICT IS NULL) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Группа участков у абонента ' || :ID_ABONENT || ' не распознана.'); + + ID_BRANCH = (SELECT GD.ID_BRANCH FROM DIR$ENTERPRISE$GROUP_DISTRICT GD WHERE GD.ID = :ID_GROUP_DISTRICT); + IF (:ID_BRANCH IS NULL) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Филиал у абонента ' || :ID_ABONENT || ' не найден.'); + +-- IF ((SELECT B.IS_INDIVIDUAL_PAYMENT FROM INF$PAYMENT$BANK_STTM B WHERE B.ID = :ID) IS ) THEN +-- EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Платеж ' || :ID || ' не является индивидуальным.'); + + IF (:ID_BRANCH = 2) THEN + EXECUTE STATEMENT ('EXECUTE PROCEDURE PKG$PAYMENT$BANK_STTM.CREATE_RECEIPT(' || :ID || ', ' || :ID_ABONENT || ')') + ON EXTERNAL DATA SOURCE (SELECT D.DATA_SOURCE FROM DIR$DATABASE$DATABASE D WHERE D.ID = 2) + AS USER 'SYSDBA' PASSWORD 'masterkey'; + ELSE + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Филиал ' || :ID_BRANCH || ' не поддерживается для создания инд. платежей.'); + END + + PROCEDURE CREATE_RECEIPT(ID DOM$KEY NOT NULL, ID_ABONENT DOM$ABONENT) + AS + DECLARE VARIABLE DATE_ACCOUNT DOM$DATE; + DECLARE VARIABLE DATE_PAYMENT DOM$DATE; + DECLARE VARIABLE NUMBER DOM$NUMBER_CHECK; + DECLARE VARIABLE AMOUNT DOM$AMOUNT; + DECLARE VARIABLE CONTRACTOR DOM$NAME_CONTRACTOR; + DECLARE VARIABLE PURPOSE D_VARCHAR_500; + DECLARE VARIABLE PAYER D_VARCHAR_200; + DECLARE VARIABLE ID_RECEIPT DOM$KEY; + DECLARE VARIABLE ID_BANK DOM$KEY; + DECLARE VARIABLE ID_BAILIFF DOM$KEY; + DECLARE VARIABLE ID_BRANCH DOM$KEY; + DECLARE VARIABLE IS_INDIVIDUAL_PAYMENT DOM$BOOLEAN_REAL; + DECLARE VARIABLE RECEIPT_CREATED DOM$BOOLEAN_REAL; + BEGIN + -- Считываем квитанцию + SELECT + B.ID_BRANCH, + B.ID_BANK, + B.ID_BAILIFF, + B.DATE_ACCOUNT, + B.DATE_PAYMENT, + B.NUMBER, + B.AMOUNT, + B.CONTRACTOR, + B.PURPOSE, + B.PAYER, + B.IS_INDIVIDUAL_PAYMENT, + B.RECEIPT_CREATED + FROM + INF$PAYMENT$BANK_STTM B + WHERE + B.ID = :ID + INTO + :ID_BRANCH, + :ID_BANK, + :ID_BAILIFF, + :DATE_ACCOUNT, + :DATE_PAYMENT, + :NUMBER, + :AMOUNT, + :CONTRACTOR, + :PURPOSE, + :PAYER, + :IS_INDIVIDUAL_PAYMENT, + :RECEIPT_CREATED; + + IF (:RECEIPT_CREATED IS TRUE) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Квитанция по платежу ' || :ID || ' уже создана.'); + + -- Если указан банк, это безакцепт + IF ((:ID_ABONENT IS NULL) AND (:ID_BANK IS NOT NULL)) THEN + BEGIN + -- Пробуем создать в текущей базе (Хабаровск) + ID_RECEIPT = (SELECT RESULT FROM TRY_CREATE_RECEIPT_NONACCEPT(:ID_BANK, :DATE_ACCOUNT, :DATE_PAYMENT, :NUMBER, :AMOUNT, :PURPOSE, :PAYER)); + + IF (:ID_RECEIPT IS NOT NULL) THEN + BEGIN + UPDATE INF$PAYMENT$BANK_STTM BS + SET + BS.ID_BRANCH = 1, + BS.RECEIPT_CREATED = TRUE + WHERE + BS.ID = :ID; + END + ELSE + -- Если иск не найден, пробуем создать в базе Комсомольского филилала + IF (:ID_RECEIPT IS NULL) THEN + BEGIN + EXECUTE STATEMENT ('SELECT RESULT FROM PKG$PAYMENT$BANK_STTM.TRY_CREATE_RECEIPT_NONACCEPT(:ID_BANK, :DATE_ACCOUNT, :DATE_PAYMENT, :NUMBER, :AMOUNT, :PURPOSE, :PAYER)') + (ID_BANK := :ID_BANK, DATE_ACCOUNT := :DATE_ACCOUNT, DATE_PAYMENT := :DATE_PAYMENT, NUMBER := :NUMBER, AMOUNT := :AMOUNT, PURPOSE := :PURPOSE, PAYER := :PAYER) + ON EXTERNAL DATA SOURCE (SELECT D.DATA_SOURCE FROM DIR$DATABASE$DATABASE D WHERE D.ID = 2) + AS USER 'SYSDBA' PASSWORD 'masterkey' + INTO + :ID_RECEIPT; + + IF (:ID_RECEIPT IS NOT NULL) THEN + BEGIN + UPDATE INF$PAYMENT$BANK_STTM BS + SET + BS.ID_BRANCH = 2, + BS.RECEIPT_CREATED = TRUE + WHERE + BS.ID = :ID; + END + END + END + ELSE IF ((:ID_ABONENT IS NULL) AND (:ID_BAILIFF IS NOT NULL)) THEN + BEGIN + -- Определяем филиал + ID_BRANCH = (SELECT GD.ID_BRANCH FROM DIR$PAYMENT$SOURCE_GD SG INNER JOIN DIR$ENTERPRISE$GROUP_DISTRICT GD ON GD.ID = SG.ID_GROUP_DISTRICT WHERE SG.ID_SOURCE = :ID_BAILIFF); + IF (:ID_BRANCH IS NULL) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Неизвестный филиал у источника оплаты: ' || (SELECT NAME FROM DIR$PAYMENT$SOURCE WHERE ID = :ID_BAILIFF)); + + IF (:ID_BRANCH = 1) THEN + BEGIN + ID_RECEIPT = (SELECT RESULT FROM TRY_CREATE_RECEIPT_BAILIFF(:ID_BAILIFF, :DATE_ACCOUNT, :DATE_PAYMENT, :NUMBER, :AMOUNT, :PURPOSE)); + + IF (:ID_RECEIPT IS NOT NULL) THEN + BEGIN + UPDATE INF$PAYMENT$BANK_STTM BS + SET + BS.ID_BRANCH = 1, + BS.RECEIPT_CREATED = TRUE + WHERE + BS.ID = :ID; + END + END + ELSE IF (:ID_BRANCH = 2) THEN + BEGIN + EXECUTE STATEMENT ('SELECT RESULT FROM PKG$PAYMENT$BANK_STTM.TRY_CREATE_RECEIPT_BAILIFF(:ID_BAILIFF, :DATE_ACCOUNT, :DATE_PAYMENT, :NUMBER, :AMOUNT, :PURPOSE)') + (ID_BAILIFF := :ID_BAILIFF, DATE_ACCOUNT := :DATE_ACCOUNT, DATE_PAYMENT := :DATE_PAYMENT, NUMBER := :NUMBER, AMOUNT := :AMOUNT, PURPOSE := :PURPOSE) + ON EXTERNAL DATA SOURCE (SELECT D.DATA_SOURCE FROM DIR$DATABASE$DATABASE D WHERE D.ID = 2) + AS USER 'SYSDBA' PASSWORD 'masterkey' + INTO + :ID_RECEIPT; + + IF (:ID_RECEIPT IS NOT NULL) THEN + BEGIN + UPDATE INF$PAYMENT$BANK_STTM BS + SET + BS.ID_BRANCH = 2, + BS.RECEIPT_CREATED = TRUE + WHERE + BS.ID = :ID; + END + END + ELSE IF (:ID_BRANCH = 3) THEN + BEGIN + EXECUTE STATEMENT ('SELECT RESULT FROM PKG$PAYMENT$BANK_STTM.TRY_CREATE_RECEIPT_BAILIFF(:ID_BAILIFF, :DATE_ACCOUNT, :DATE_PAYMENT, :NUMBER, :AMOUNT, :PURPOSE)') + (ID_BAILIFF := :ID_BAILIFF, DATE_ACCOUNT := :DATE_ACCOUNT, DATE_PAYMENT := :DATE_PAYMENT, NUMBER := :NUMBER, AMOUNT := :AMOUNT, PURPOSE := :PURPOSE) + ON EXTERNAL DATA SOURCE (SELECT D.DATA_SOURCE FROM DIR$DATABASE$DATABASE D WHERE D.ID = 5) + AS USER 'SYSDBA' PASSWORD 'masterkey' + INTO + :ID_RECEIPT; + + IF (:ID_RECEIPT IS NOT NULL) THEN + BEGIN + UPDATE INF$PAYMENT$BANK_STTM BS + SET + BS.ID_BRANCH = 3, + BS.RECEIPT_CREATED = TRUE + WHERE + BS.ID = :ID; + END + END + ELSE + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Необрабатываемый филиал: ' || :ID_BRANCH || ' (№' || :NUMBER || ')'); + END + ELSE IF ((:IS_INDIVIDUAL_PAYMENT IS TRUE) OR (:ID_ABONENT IS NOT NULL)) THEN + BEGIN + -- Пытаемся создать в базе Комсомольска + EXECUTE STATEMENT ('SELECT RESULT FROM PKG$PAYMENT$BANK_STTM.TRY_CREATE_RECEIPT_INDIVID(:DATE_ACCOUNT, :DATE_PAYMENT, :NUMBER, :AMOUNT, :PURPOSE, :PAYER, :ID_ABONENT)') + (DATE_ACCOUNT := :DATE_ACCOUNT, DATE_PAYMENT := :DATE_PAYMENT, NUMBER := :NUMBER, AMOUNT := :AMOUNT, PURPOSE := :PURPOSE, PAYER := :PAYER, ID_ABONENT := :ID_ABONENT) + ON EXTERNAL DATA SOURCE (SELECT D.DATA_SOURCE FROM DIR$DATABASE$DATABASE D WHERE D.ID = 2) + AS USER 'SYSDBA' PASSWORD 'masterkey' + INTO + :ID_RECEIPT; + + IF (:ID_RECEIPT IS NOT NULL) THEN + BEGIN + UPDATE INF$PAYMENT$BANK_STTM BS + SET + BS.ID_BRANCH = 2, + BS.IS_INDIVIDUAL_PAYMENT = TRUE, + BS.RECEIPT_CREATED = TRUE + WHERE + BS.ID = :ID; + END +-- ELSE +-- EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Необрабатываемый филиал: ' || :ID_BRANCH); + END + END + + PROCEDURE TRY_CREATE_RECEIPT_NONACCEPT(ID_BANK DOM$KEY NOT NULL, DATE_ACCOUNT DOM$DATE NOT NULL, DATE_PAYMENT DOM$DATE NOT NULL, NUMBER_RECEIPT DOM$NUMBER_CHECK NOT NULL, AMOUNT DOM$AMOUNT NOT NULL, PURPOSE D_VARCHAR_500 NOT NULL, PAYER D_VARCHAR_200 NOT NULL) RETURNS (RESULT DOM$KEY) + AS + DECLARE VARIABLE ID_LAWSUIT DOM$KEY; + DECLARE VARIABLE ID_BATCH DOM$KEY; + DECLARE VARIABLE ID_EXEC_PROC DOM$KEY; + DECLARE VARIABLE ID_WRIT_EXEC DOM$KEY; + DECLARE VARIABLE ID_ABONENT DOM$ABONENT; + DECLARE VARIABLE PURPOSE_ORIGIN D_VARCHAR_500; + DECLARE VARIABLE ID_SOURCE DOM$KEY; + DECLARE VARIABLE COMMENT_BATCH DOM$COMMENT; + DECLARE VARIABLE ID_TYPE_RECEIPT_VIA_BAILIFF DOM$KEY; + DECLARE VARIABLE ID_TYPE_RECEIPT DOM$KEY; + DECLARE VARIABLE ID_TYPE_RECEIPT_NGPH DOM$KEY; + DECLARE VARIABLE ID_TYPE_RECEIPT_MD DOM$KEY; + DECLARE VARIABLE ID_GROUP_DISTRICT DOM$KEY; + BEGIN + PURPOSE_ORIGIN = :PURPOSE; + + ID_TYPE_RECEIPT_VIA_BAILIFF = (SELECT ID_TYPE_RECEIPT_VIA_BAILIFF FROM SYS$LINK$PAYMENT); + ID_TYPE_RECEIPT_NGPH = (SELECT TG.ID_TYPE_RECEIPT FROM DIR$GASSUPPLY$TYPE_GS TG WHERE TG.ID = (SELECT ID_TYPE_GS_NATURE_GAS_PRIVATE FROM SYS$LINK$GASSUPPLY)); + ID_TYPE_RECEIPT_MD = (SELECT TG.ID_TYPE_RECEIPT FROM DIR$GASSUPPLY$TYPE_GS TG WHERE TG.ID = (SELECT ID_TYPE_GS_TANK_GAS_MD FROM SYS$LINK$GASSUPPLY)); + + -- Ищем иск в базе + SELECT + ID_LAWSUIT, + ID_WRIT_EXEC, + ID_EXEC_PROC + FROM + RECOGN_NONACCEPT(:ID_BANK, :DATE_PAYMENT, :PURPOSE, :PAYER) + INTO + :ID_LAWSUIT, + :ID_WRIT_EXEC, + :ID_EXEC_PROC; + + -- Если иск не найден, выходим + IF (:ID_LAWSUIT IS NULL) THEN + BEGIN + RESULT = NULL; + SUSPEND; + EXIT; + END + + -- Определяем код источника оплаты + ID_SOURCE = (SELECT BANK.ID_SOURCE FROM DIR$EXEC_PROC$BANK BANK WHERE BANK.ID = :ID_BANK); + IF (:ID_SOURCE IS NULL) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Не указан источник оплаты для банка "' || (SELECT BANK.NAME FROM DIR$EXEC_PROC$BANK BANK WHERE BANK.ID = :ID_BANK) || '" (' || :PURPOSE || ').'); + + -- Запоминаем лицевой счет + ID_ABONENT = (SELECT L.ID_ABONENT FROM DOC$ABONENT$LAWSUIT L WHERE L.ID = :ID_LAWSUIT); + + -- Сразу проверяем, что тип газоснабжения у абонента корректный + IF ((SELECT A.ID_TYPE_GASSUPPLY FROM DIR$ABONENT$ABONENT A WHERE A.ID = :ID_ABONENT) NOT IN (1, 2, 3, 4, 20, 25)) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA_ABONE(:ID_ABONENT, 'Неопознанный тип газоснабжения.'); + + -- Проверяем, что такой квитанции еще нет + IF (EXISTS(SELECT 1 FROM BAT$RECEIPT$RECEIPT R INNER JOIN BAT$RECEIPT$BATCH B ON B.ID = R.ID_BATCH WHERE (B.ID_SOURCE = :ID_SOURCE) AND (R.DATE_PAYMENT = :DATE_PAYMENT) AND (R.NUMBER = :NUMBER_RECEIPT) AND (R.AMOUNT_RECEIPT = :AMOUNT))) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Квитанция №' || :NUMBER_RECEIPT || ' от ' || FORMAT_DATE(:DATE_PAYMENT) + || ' по источнику "' || (SELECT NAME FROM DIR$PAYMENT$SOURCE WHERE ID = :ID_SOURCE) || '" на сумму ' || :AMOUNT || ' уже создана'); + + -- Определяем группу участков + ID_GROUP_DISTRICT = PKG$ABONENT.GET_GROUP_DISTRICT_FOR_PAYMENT(:ID_ABONENT); + + -- Создаем пачку + IF ((SELECT A.ID_TYPE_GASSUPPLY FROM DIR$ABONENT$ABONENT A WHERE A.ID = :ID_ABONENT) = (SELECT ID_TYPE_GS_NATURE_GAS_PRIVATE FROM SYS$LINK$GASSUPPLY)) THEN + BEGIN + COMMENT_BATCH = 'ПГ ЧД'; + ID_TYPE_RECEIPT = :ID_TYPE_RECEIPT_NGPH; + END + ELSE IF ((SELECT A.ID_TYPE_GASSUPPLY FROM DIR$ABONENT$ABONENT A WHERE A.ID = :ID_ABONENT) = (SELECT ID_TYPE_GS_TANK_GAS_MD FROM SYS$LINK$GASSUPPLY)) THEN + BEGIN + COMMENT_BATCH = 'Ведомства'; + ID_TYPE_RECEIPT = :ID_TYPE_RECEIPT_MD; + END + ELSE IF ((SELECT RESULT FROM GET$ABONENT$CHARGING_GAS_AMURCC(:ID_ABONENT)) = 1) THEN + BEGIN + COMMENT_BATCH = 'АмурВЦ'; + ID_TYPE_RECEIPT = :ID_TYPE_RECEIPT_VIA_BAILIFF; + END + ELSE + BEGIN + COMMENT_BATCH = 'Не распознано'; + ID_TYPE_RECEIPT = :ID_TYPE_RECEIPT_VIA_BAILIFF; + END + + IF ((SELECT COUNT(*) FROM BAT$RECEIPT$BATCH B WHERE (B.ID_GROUP_DISTRICT = :ID_GROUP_DISTRICT) AND (B.ID_SOURCE = :ID_SOURCE) AND (B.DATE_ACCOUNT = :DATE_ACCOUNT) AND (B.IS_CORRECT_RECEIPT = 0) AND (B.COMMENT IS NOT DISTINCT FROM :COMMENT_BATCH)) > 1) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Найдено более одной пачки за ' || FORMAT_DATE(:DATE_ACCOUNT) || ' по ' || (SELECT NAME FROM DIR$PAYMENT$SOURCE WHERE ID = :ID_SOURCE)); + + -- Получаем код пачки + ID_BATCH = (SELECT B.ID FROM BAT$RECEIPT$BATCH B WHERE (B.ID_GROUP_DISTRICT = :ID_GROUP_DISTRICT) AND (B.ID_SOURCE = :ID_SOURCE) AND (B.DATE_ACCOUNT = :DATE_ACCOUNT) AND (B.IS_CORRECT_RECEIPT = 0) AND (B.COMMENT IS NOT DISTINCT FROM :COMMENT_BATCH)); + IF (:ID_BATCH IS NULL) THEN + BEGIN + INSERT INTO BAT$RECEIPT$BATCH + (ID, ID_GROUP_DISTRICT, ID_SOURCE, DATE_ACCOUNT, COMMENT) + VALUES + (NEXT VALUE FOR SEQ_BAT$RECEIPT$BATCH_ID, :ID_GROUP_DISTRICT, :ID_SOURCE, :DATE_ACCOUNT, :COMMENT_BATCH) + RETURNING + ID + INTO + :ID_BATCH; + END + ELSE IF ((SELECT B.LOADED FROM BAT$RECEIPT$BATCH B WHERE B.ID = :ID_BATCH) = 1) THEN + EXECUTE PROCEDURE PKG$EXCEPTION.FOR_BATCH_RECEIPT(:ID_BATCH, 'Пачка квитанций уже загружена.'); + + -- Создаем квитанцию + INSERT INTO BAT$RECEIPT$RECEIPT + (ID, ID_BATCH, ID_ABONENT, ID_PERIOD_FOR_PAYMENT, ID_TYPE_RECEIPT, ID_LAWSUIT, ID_WRIT_EXEC, ID_EXEC_PROC, DATE_PAYMENT, NUMBER, AUTODISTRIBUTE_SERVICES, AMOUNT_SERVICE_5, PURPOSE, PAYER) + VALUES + (NEXT VALUE FOR SEQ_BAT$RECEIPT$RECEIPT_ID, :ID_BATCH, :ID_ABONENT, DATE_TO_PERIOD(:DATE_PAYMENT), :ID_TYPE_RECEIPT, :ID_LAWSUIT, :ID_WRIT_EXEC, :ID_EXEC_PROC, :DATE_PAYMENT, :NUMBER_RECEIPT, 0, :AMOUNT, :PURPOSE_ORIGIN, :PAYER) + RETURNING + ID + INTO + :RESULT; + + SUSPEND; + END + + FUNCTION TRIM_COURT_DISTRICT(NUMBER_FILE DOM$NUMBER_FILE) RETURNS DOM$NUMBER_FILE DETERMINISTIC + AS + DECLARE VARIABLE STR_YEAR DOM$NUMBER_FILE; + DECLARE VARIABLE STR_NUMBER DOM$NUMBER_FILE; + DECLARE VARIABLE RESULT DOM$NUMBER_FILE; + DECLARE VARIABLE NYEAR DOM$INTEGER; + BEGIN + IF (POSITION('/', :NUMBER_FILE) > 1) THEN + BEGIN + STR_NUMBER = LEFT(:NUMBER_FILE, POSITION('/', :NUMBER_FILE) - 1); + STR_YEAR = SUBSTRING(:NUMBER_FILE FROM (POSITION('/', :NUMBER_FILE) + 1)); + IF (CHAR_LENGTH(:STR_YEAR) = 1) THEN + RETURN NULL; + IF (CHAR_LENGTH(:STR_YEAR) NOT IN (2, 4)) THEN + BEGIN + -- Обработка правой части вида "2-4039/2016-74" + IF (SUBSTRING(:STR_YEAR FROM 5 FOR 1) = '-') THEN + BEGIN + NYEAR = LEFT(:STR_YEAR, 4); + IF (:NYEAR NOT BETWEEN 2006 AND EXTRACT(YEAR FROM CURRENT_DATE)) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Ошибка в годе в "' || :NUMBER_FILE || '".'); + + RETURN :STR_NUMBER || '/' || :NYEAR; + END + -- Обработка правой части вида "2-3028/13-2018" + ELSE IF ((SUBSTRING(:STR_YEAR FROM 3 FOR 1) = '-') AND (CHAR_LENGTH(:STR_YEAR) = 7)) THEN + BEGIN + NYEAR = RIGHT(:STR_YEAR, 4); + IF (:NYEAR NOT BETWEEN 2006 AND EXTRACT(YEAR FROM CURRENT_DATE)) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Ошибка в годе в "' || :NUMBER_FILE || '".'); + + RETURN :STR_NUMBER || '/' || :NYEAR; + END + -- Обработка правой части вида "2-300/9-2017" + ELSE IF ((SUBSTRING(:STR_YEAR FROM 2 FOR 1) = '-') AND (CHAR_LENGTH(:STR_YEAR) = 6)) THEN + BEGIN + NYEAR = RIGHT(:STR_YEAR, 4); + IF (:NYEAR NOT BETWEEN 2006 AND EXTRACT(YEAR FROM CURRENT_DATE)) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Ошибка в годе в "' || :NUMBER_FILE || '".'); + + RETURN :STR_NUMBER || '/' || :NYEAR; + END + ELSE + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Не могу опознать год в "' || :NUMBER_FILE || '".'); +-- RETURN NULL; + END + ELSE + BEGIN + NYEAR = IIF(CHAR_LENGTH(:STR_YEAR) = 4, :STR_YEAR, '20' || :STR_YEAR); + IF (:NYEAR NOT BETWEEN 2006 AND 2019) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Ошибка в годе в "' || :NUMBER_FILE || '".'); + + RETURN :STR_NUMBER || '/' || :NYEAR; + END + END + + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Нераспознано дело "' || :NUMBER_FILE || '".'); + END + + FUNCTION CONVERT_NUMBER_FILE(NUMBER_FILE DOM$NUMBER_FILE, PURPOSE D_VARCHAR_500 NOT NULL) RETURNS DOM$NUMBER_FILE DETERMINISTIC + AS + DECLARE VARIABLE STR_YEAR DOM$NUMBER_FILE; + DECLARE VARIABLE STR_NUMBER DOM$NUMBER_FILE; + DECLARE VARIABLE RESULT DOM$NUMBER_FILE; + BEGIN + IF (POSITION('/', :NUMBER_FILE) > 1) THEN + BEGIN + STR_NUMBER = LEFT(:NUMBER_FILE, POSITION('/', :NUMBER_FILE) - 1); + STR_YEAR = SUBSTRING(:NUMBER_FILE FROM (POSITION('/', :NUMBER_FILE) + 1)); + IF (CHAR_LENGTH(:STR_YEAR) = 1) THEN + RETURN NULL; + IF (CHAR_LENGTH(:STR_YEAR) NOT IN (2, 4)) THEN + BEGIN + -- Обработка правой части вида "2-4039/2016-74" + IF (SUBSTRING(:STR_YEAR FROM 5 FOR 1) = '-') THEN + RETURN :STR_NUMBER || LEFT(:STR_YEAR, 4); + -- Обработка правой части вида "2-300/9-2017" + IF ((SUBSTRING(:STR_YEAR FROM 2 FOR 1) = '-') AND (CHAR_LENGTH(:STR_YEAR) = 6)) THEN + RETURN :STR_NUMBER || RIGHT(:STR_YEAR, 4); + -- Обработка правой части вида "2-375/10-2017" + IF ((SUBSTRING(:STR_YEAR FROM 3 FOR 1) = '-') AND (CHAR_LENGTH(:STR_YEAR) = 7)) THEN + RETURN :STR_NUMBER || RIGHT(:STR_YEAR, 4); + + RETURN NULL; + END + + --EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('В номере дела "' || :NUMBER_FILE || '" год не четыре и не два символа.'); + + IF (CHAR_LENGTH(:STR_YEAR) = 2) THEN + BEGIN + IF (CAST(:STR_YEAR AS INTEGER) > CAST(RIGHT(EXTRACT(YEAR FROM CURRENT_DATE), 2) AS INTEGER)) THEN + RETURN NULL; + --EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('В номере дела "' || :NUMBER_FILE || '" неправильный год.'); + + RETURN :STR_NUMBER || '/' || '20' || :STR_YEAR; + END + ELSE + BEGIN + IF (CAST(:STR_YEAR AS INTEGER) > EXTRACT(YEAR FROM CURRENT_DATE)) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('В номере дела "' || :NUMBER_FILE || '" неправильный год.'); + + RETURN :STR_NUMBER || '/' || RIGHT(:STR_YEAR, 2); + END + END + ELSE IF (CHAR_LENGTH(:NUMBER_FILE) <= 6) THEN + RETURN :NUMBER_FILE; + ELSE + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('В номере дела "' || :NUMBER_FILE || '" не найден слэш (' || :PURPOSE || ').'); + END + + FUNCTION SEARCH_NUMBER_FILE(PURPOSE D_VARCHAR_500 NOT NULL, IS_NONACCEPT DOM$BOOLEAN_REAL NOT NULL) RETURNS DOM$NUMBER_FILE DETERMINISTIC + AS + DECLARE VARIABLE POS_NUMBER_FILE D_INTEGER; + DECLARE VARIABLE POS_NUMBER_FILE_END D_INTEGER; + DECLARE VARIABLE SLASH_ALREADY_FOUNDED DOM$BOOLEAN; + DECLARE VARIABLE RESULT DOM$NUMBER_FILE; + BEGIN + POS_NUMBER_FILE = POSITION('2-', :PURPOSE); + + -- В ССП могут встречаться случаи, когда указан корпус/квартира и номер дела + -- в виде "г. Комсомольск-на-Амуре, , Ленина пр-кт, д. 81, корп.2-112/ 2-1929/2016" + IF (:IS_NONACCEPT IS FALSE) THEN + IF (POSITION('2-', :PURPOSE, :POS_NUMBER_FILE + 1) > 0) THEN + POS_NUMBER_FILE = POSITION('2-', :PURPOSE, :POS_NUMBER_FILE + 1); + + IF (:POS_NUMBER_FILE > 0) THEN + BEGIN + PURPOSE = SUBSTRING(:PURPOSE FROM :POS_NUMBER_FILE); + IF (LEFT(:PURPOSE, 3) = '2- ') THEN + PURPOSE = '2-' || SUBSTRING(:PURPOSE FROM 4); + PURPOSE = REPLACE(:PURPOSE, './', '/');-- Исправляем возможную опечатку в номере делу + POS_NUMBER_FILE_END = 3;-- Пропускаем "2-" + SLASH_ALREADY_FOUNDED = 0; + + -- Перебираем текст, прекращая поиск, как только находим не цифру или слэш + WHILE (:POS_NUMBER_FILE_END <= CHAR_LENGTH(:PURPOSE)) DO + BEGIN + IF (NOT((SUBSTRING(:PURPOSE FROM :POS_NUMBER_FILE_END FOR 1) BETWEEN '0' AND '9') OR (SUBSTRING(:PURPOSE FROM :POS_NUMBER_FILE_END FOR 1) = '/') OR (SUBSTRING(:PURPOSE FROM :POS_NUMBER_FILE_END FOR 1) = '-'))) THEN + BREAK; + + -- Если был найден второй слэш, то останавливаем поиск (это номер вида 2-1077/2014/2) + IF (SUBSTRING(:PURPOSE FROM :POS_NUMBER_FILE_END FOR 1) = '/') THEN + BEGIN + IF (:SLASH_ALREADY_FOUNDED = 0) THEN + SLASH_ALREADY_FOUNDED = 1; + ELSE + BREAK; + END + + POS_NUMBER_FILE_END = :POS_NUMBER_FILE_END + 1; + END + + RESULT = SUBSTRING(:PURPOSE FROM 1 FOR :POS_NUMBER_FILE_END - 1); + END + + IF (CHAR_LENGTH(:RESULT) = 2) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Не найден номер дела в строке: ' || :PURPOSE); + + RETURN :RESULT; + END + + PROCEDURE RECOGN_NONACCEPT(ID_BANK DOM$KEY NOT NULL, DATE_PAYMENT DOM$DATE NOT NULL, PURPOSE D_VARCHAR_500 NOT NULL, PAYER D_VARCHAR_200 NOT NULL) RETURNS (ID_LAWSUIT DOM$KEY, ID_WRIT_EXEC DOM$KEY, ID_EXEC_PROC DOM$KEY) + AS + DECLARE VARIABLE POS_NAME D_NATURAL; + DECLARE VARIABLE POS_PATRONYMIC D_NATURAL; + DECLARE VARIABLE POS_AFTER_PATRONYMIC D_NATURAL; + DECLARE VARIABLE FIO_BY_SB D_VARCHAR_200; + DECLARE VARIABLE NUMBER_FILE D_VARCHAR_200; + DECLARE VARIABLE NUMBER_WRIT_EXEC D_VARCHAR_100; + DECLARE VARIABLE FIO_RESPONDENT D_VARCHAR_150; + DECLARE VARIABLE TMP_ID_EXEC_PROC DOM$KEY; + DECLARE VARIABLE TMP_ID_WRIT_EXEC DOM$KEY; + DECLARE VARIABLE CONV_NUMBER_FILE DOM$NUMBER_FILE; + DECLARE VARIABLE ID_CORRECTION DOM$KEY; + DECLARE VARIABLE NUMBER_FILE_WO_CD DOM$NUMBER_FILE; + BEGIN + -- Модифицируем ФИО + FIO_BY_SB = UPPER(:PAYER); + FIO_BY_SB = REPLACE(:FIO_BY_SB, ' ОГЛЫ', ''); + FIO_BY_SB = REPLACE(:FIO_BY_SB, ' КЫЗЫ', ''); + + -- Оставляем фамилию, имя, отчество + POS_NAME = POSITION(' ', :FIO_BY_SB); + POS_PATRONYMIC = POSITION(' ', :FIO_BY_SB, :POS_NAME + 1); + POS_AFTER_PATRONYMIC = POSITION(' ', :FIO_BY_SB, :POS_PATRONYMIC + 1); + IF (:POS_AFTER_PATRONYMIC > 0) THEN + FIO_BY_SB = LEFT(:FIO_BY_SB, :POS_AFTER_PATRONYMIC - 1); + -- Учет случая, когда у ответчика нет отчества, а платеж был через Сбербанк + IF (LOWER(RIGHT(:FIO_BY_SB, CHAR_LENGTH('дальневосточный'))) = 'дальневосточный') THEN + FIO_BY_SB = LEFT(:FIO_BY_SB, CHAR_LENGTH(:FIO_BY_SB) - CHAR_LENGTH('дальневосточный') - 1); + -- exception EXC$CANCEL :FIO_BY_SB || ' ' || :POS_NAME || ' ' || :POS_PATRONYMIC || ' ' || :POS_AFTER_PATRONYMIC; + + -- Определяем номер дела + NUMBER_FILE = SEARCH_NUMBER_FILE(:PURPOSE, TRUE); + + -- Ищем необходимость исправления + ID_CORRECTION = (SELECT C.ID FROM DIR$EXEC_PROC$CORRECTION C WHERE (C.PAYMENT_NUMBER_FILE IS NOT DISTINCT FROM :NUMBER_FILE) AND (C.PAYMENT_FIO = :FIO_BY_SB)); + IF (:ID_CORRECTION IS NOT NULL) THEN + SELECT + C.CORRECT_NUMBER_FILE, + C.CORRECT_FIO + FROM + DIR$EXEC_PROC$CORRECTION C + WHERE + C.ID = :ID_CORRECTION + INTO + :NUMBER_FILE, + :FIO_BY_SB; + + -- + FIO_BY_SB = REPLACE(:FIO_BY_SB, 'Ё', 'Е'); + + -- Исправляем возможную опечатку + IF (RIGHT(:NUMBER_FILE, 4) = '/218') THEN + NUMBER_FILE = LEFT(:NUMBER_FILE, CHAR_LENGTH(:NUMBER_FILE) - 3) || '2018'; + + IF (:NUMBER_FILE IS NOT NULL) THEN + BEGIN + IF ((SELECT COUNT(*) FROM DOC$ABONENT$LAWSUIT L INNER JOIN DOC$ABONENT$LAWSUIT_CITIZEN LC ON LC.ID_LAWSUIT = L.ID INNER JOIN REG$ABONENT$CITIZEN C ON C.ID = LC.ID_CITIZEN WHERE L.FILE_NUMBER STARTING WITH :NUMBER_FILE AND UPPER(C.SURNAME_NAME_PATRONYMIC) = :FIO_BY_SB) > 1) THEN + BEGIN + IF ((SELECT COUNT(*) FROM DOC$ABONENT$LAWSUIT L INNER JOIN DOC$ABONENT$LAWSUIT_CITIZEN LC ON LC.ID_LAWSUIT = L.ID INNER JOIN REG$ABONENT$CITIZEN C ON C.ID = LC.ID_CITIZEN WHERE L.FILE_NUMBER STARTING WITH :NUMBER_FILE || '/' AND UPPER(C.SURNAME_NAME_PATRONYMIC) = :FIO_BY_SB) > 1) THEN + BEGIN + IF ((SELECT COUNT(*) FROM DOC$ABONENT$LAWSUIT L INNER JOIN DOC$ABONENT$LAWSUIT_CITIZEN LC ON LC.ID_LAWSUIT = L.ID INNER JOIN REG$ABONENT$CITIZEN C ON C.ID = LC.ID_CITIZEN WHERE L.FILE_NUMBER STARTING WITH :NUMBER_FILE || '/' AND (L.REST_LAWSUIT_BY_MONTHS_DEBT > 0) AND UPPER(C.SURNAME_NAME_PATRONYMIC) = :FIO_BY_SB) > 1) THEN + ID_LAWSUIT = NULL; + ELSE + ID_LAWSUIT = (SELECT L.ID FROM DOC$ABONENT$LAWSUIT L INNER JOIN DOC$ABONENT$LAWSUIT_CITIZEN LC ON LC.ID_LAWSUIT = L.ID INNER JOIN REG$ABONENT$CITIZEN C ON C.ID = LC.ID_CITIZEN WHERE L.FILE_NUMBER STARTING WITH :NUMBER_FILE || '/' AND (L.REST_LAWSUIT_BY_MONTHS_DEBT > 0) AND UPPER(C.SURNAME_NAME_PATRONYMIC) = :FIO_BY_SB); + END + ELSE + ID_LAWSUIT = (SELECT L.ID FROM DOC$ABONENT$LAWSUIT L INNER JOIN DOC$ABONENT$LAWSUIT_CITIZEN LC ON LC.ID_LAWSUIT = L.ID INNER JOIN REG$ABONENT$CITIZEN C ON C.ID = LC.ID_CITIZEN WHERE L.FILE_NUMBER STARTING WITH :NUMBER_FILE || '/' AND UPPER(C.SURNAME_NAME_PATRONYMIC) = :FIO_BY_SB); + END + ELSE + BEGIN + ID_LAWSUIT = (SELECT L.ID FROM DOC$ABONENT$LAWSUIT L INNER JOIN DOC$ABONENT$LAWSUIT_CITIZEN LC ON LC.ID_LAWSUIT = L.ID INNER JOIN REG$ABONENT$CITIZEN C ON C.ID = LC.ID_CITIZEN WHERE L.FILE_NUMBER STARTING WITH :NUMBER_FILE AND UPPER(C.SURNAME_NAME_PATRONYMIC) = :FIO_BY_SB); + + IF (:ID_LAWSUIT IS NULL) THEN + BEGIN + -- Если иск не найден, ищем его в истории заседаний + ID_LAWSUIT = (SELECT L.ID FROM DOC$ABONENT$LAWSUIT L INNER JOIN DOC$COURT_PROCESS$SUMMONS_LAWSU SL ON SL.ID_LAWSUIT = L.ID INNER JOIN DOC$ABONENT$LAWSUIT_CITIZEN LC ON LC.ID_LAWSUIT = L.ID INNER JOIN REG$ABONENT$CITIZEN C ON C.ID = LC.ID_CITIZEN WHERE SL.NUMBER_FILE STARTING WITH :NUMBER_FILE AND UPPER(C.SURNAME_NAME_PATRONYMIC) = :FIO_BY_SB); + + IF (:ID_LAWSUIT IS NULL) THEN + BEGIN + -- Если иск не найден, пробуем перевести номер дела в другой формат (год двумя знаками или четырьмя) + CONV_NUMBER_FILE = CONVERT_NUMBER_FILE(:NUMBER_FILE, :PURPOSE); + + IF (:CONV_NUMBER_FILE IS NOT NULL) THEN + BEGIN + ID_LAWSUIT = (SELECT L.ID FROM DOC$ABONENT$LAWSUIT L INNER JOIN DOC$ABONENT$LAWSUIT_CITIZEN LC ON LC.ID_LAWSUIT = L.ID INNER JOIN REG$ABONENT$CITIZEN C ON C.ID = LC.ID_CITIZEN WHERE L.FILE_NUMBER STARTING WITH :CONV_NUMBER_FILE AND UPPER(C.SURNAME_NAME_PATRONYMIC) = :FIO_BY_SB); + + IF (:ID_LAWSUIT IS NULL) THEN + BEGIN + ID_WRIT_EXEC = (SELECT RESULT FROM GET$WRIT_EXEC$SEARCH_BY_RESPOND(:NUMBER_FILE, :FIO_BY_SB)); + ID_LAWSUIT = (SELECT WE.ID_LAWSUIT FROM DOC$LAWSUIT$WRIT_OF_EXEC WE WHERE WE.ID = :ID_WRIT_EXEC); + + ID_EXEC_PROC = (SELECT FIRST 1 EP.ID FROM DOC$LAWSUIT$EXEC_PROC EP WHERE (EP.ID_WRIT_OF_EXEC = :ID_WRIT_EXEC) AND (EP.ID_BANK IS NOT NULL) AND (EP.DATE_TRANSFERENCE <= :DATE_PAYMENT) ORDER BY EP.DATE_TRANSFERENCE DESC); + END + ELSE + NUMBER_FILE = :CONV_NUMBER_FILE; + END + + -- Если иск не найден, пробуем отрезать номер участка из дела + IF (:ID_LAWSUIT IS NULL) THEN + BEGIN + NUMBER_FILE_WO_CD = TRIM_COURT_DISTRICT(:NUMBER_FILE); + IF (:NUMBER_FILE_WO_CD IS NOT NULL) THEN + ID_LAWSUIT = (SELECT L.ID FROM DOC$ABONENT$LAWSUIT L INNER JOIN DOC$ABONENT$LAWSUIT_CITIZEN LC ON LC.ID_LAWSUIT = L.ID INNER JOIN REG$ABONENT$CITIZEN C ON C.ID = LC.ID_CITIZEN WHERE L.FILE_NUMBER STARTING WITH :NUMBER_FILE_WO_CD AND UPPER(C.SURNAME_NAME_PATRONYMIC) = :FIO_BY_SB); + END + END + END + END + + -- Ищем иск по номеру дела и ответчику + IF ((:ID_LAWSUIT IS NOT NULL) AND (:ID_EXEC_PROC IS NULL)) THEN + BEGIN + -- IF ((SELECT COUNT(*) FROM DOC$LAWSUIT$EXEC_PROC EP INNER JOIN DOC$LAWSUIT$WRIT_OF_EXEC WE ON WE.ID = EP.ID_WRIT_OF_EXEC INNER JOIN REG$ABONENT$CITIZEN C ON C.ID = WE.ID_RESPONDENT WHERE WE.ID_LAWSUIT = :ID_ISK AND UPPER(C.SURNAME_NAME_PATRONYMIC) = UPPER(:FIO_BY_SB) AND EP.ID_BANK IS NOT NULL) AND (EP.DATE_TRANSFERENCE < :DATE_PAYMENT) > 1) THEN + -- EXCEPTION CHECK_EXCEPTION 'Более 1 ИП: ' || COALESCE(:FIO_BY_SB, ''); + + ID_EXEC_PROC = NULL; + + FOR SELECT + EP.ID, + EP.ID_WRIT_OF_EXEC, + REPLACE(UPPER(C.SURNAME_NAME_PATRONYMIC), 'Ё', 'Е') + FROM + DOC$LAWSUIT$EXEC_PROC EP + INNER JOIN DOC$LAWSUIT$WRIT_OF_EXEC WE ON WE.ID = EP.ID_WRIT_OF_EXEC + INNER JOIN REG$ABONENT$CITIZEN C ON C.ID = WE.ID_RESPONDENT + WHERE + WE.ID_LAWSUIT = :ID_LAWSUIT + AND (EP.ID_BANK IS NOT NULL) + AND (EP.DATE_TRANSFERENCE <= :DATE_PAYMENT) + ORDER BY + EP.DATE_TRANSFERENCE DESC + INTO + :TMP_ID_EXEC_PROC, + :TMP_ID_WRIT_EXEC, + :FIO_RESPONDENT + DO + BEGIN + IF (RIGHT(:FIO_RESPONDENT, 5) = ' ОГЛЫ') THEN + FIO_RESPONDENT = LEFT(:FIO_RESPONDENT, CHAR_LENGTH(:FIO_RESPONDENT) - 5); + IF (RIGHT(:FIO_RESPONDENT, 5) = ' КЫЗЫ') THEN + FIO_RESPONDENT = LEFT(:FIO_RESPONDENT, CHAR_LENGTH(:FIO_RESPONDENT) - 5); + + IF (:FIO_RESPONDENT = :FIO_BY_SB) THEN + BEGIN + ID_EXEC_PROC = :TMP_ID_EXEC_PROC; + ID_WRIT_EXEC = :TMP_ID_WRIT_EXEC; + BREAK; + END + END + + IF (:ID_EXEC_PROC IS NULL) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('По иску №' || :NUMBER_FILE || ', ИП по ответчику "' || :FIO_BY_SB || '" на ' || FORMAT_DATE(:DATE_PAYMENT) || ' не найдено.'); + END + ELSE IF (:ID_WRIT_EXEC IS NULL) THEN + BEGIN + ID_WRIT_EXEC = (SELECT RESULT FROM GET$WRIT_EXEC$SEARCH_BY_RESPOND(:NUMBER_FILE, :FIO_BY_SB)); + + IF (:ID_WRIT_EXEC IS NOT NULL) THEN + BEGIN + ID_EXEC_PROC = (SELECT FIRST 1 EP.ID FROM DOC$LAWSUIT$EXEC_PROC EP WHERE EP.ID_WRIT_OF_EXEC = :ID_WRIT_EXEC AND EP.DATE_TRANSFERENCE < :DATE_PAYMENT ORDER BY EP.DATE_TRANSFERENCE DESC); + + IF (:ID_EXEC_PROC IS NULL) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Не найдено ИП (' || :NUMBER_WRIT_EXEC || ', оплачено ' || FORMAT_DATE(:DATE_PAYMENT) || ') по строке: ' || :PURPOSE); + + ID_LAWSUIT = (SELECT WE.ID_LAWSUIT FROM DOC$LAWSUIT$WRIT_OF_EXEC WE WHERE WE.ID = :ID_WRIT_EXEC); + END + END + END + ELSE IF (POSITION('№ ВС ', :PURPOSE) > 0) THEN + BEGIN + -- Проверка наличия номера после ВС + PURPOSE = REPLACE(:PURPOSE, '№ ВС №', '№ ВС'); + + IF (SUBSTRING(:PURPOSE FROM POSITION('№ ВС ', :PURPOSE) + 2 FOR 12) CONTAINING '№ ') THEN + BEGIN + NUMBER_WRIT_EXEC = REPLACE(SUBSTRING(:PURPOSE FROM POSITION('№ ВС ', :PURPOSE) + 2 FOR 14), ' ', ''); + END + ELSE IF (SUBSTRING(:PURPOSE FROM POSITION('№ ВС ', :PURPOSE) + 2 FOR 12) CONTAINING '№') THEN + BEGIN + NUMBER_WRIT_EXEC = REPLACE(SUBSTRING(:PURPOSE FROM POSITION('№ ВС ', :PURPOSE) + 2 FOR 13), ' ', ''); + END + ELSE + NUMBER_WRIT_EXEC = REPLACE(SUBSTRING(:PURPOSE FROM POSITION('№ ВС ', :PURPOSE) + 2 FOR 12), ' ', ''); + + -- exception CHECK_EXCEPTION :NUMBER_WRIT_EXEC; + -- Ищем исполнительное производство + ID_EXEC_PROC = (SELECT FIRST 1 EP.ID FROM DOC$LAWSUIT$EXEC_PROC EP INNER JOIN DOC$LAWSUIT$WRIT_OF_EXEC WE ON WE.ID = EP.ID_WRIT_OF_EXEC WHERE ((WE.NUMBER = :NUMBER_WRIT_EXEC) OR (WE.NUMBER_WRIT_EXEC_FOR_DUTY = :NUMBER_WRIT_EXEC)) AND (EP.ID_BANK = :ID_BANK) AND (EP.DATE_TRANSFERENCE <= :DATE_PAYMENT) ORDER BY EP.DATE_TRANSFERENCE DESC); + IF (:ID_EXEC_PROC IS NULL) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Не найдено ИП (' || :NUMBER_WRIT_EXEC || ', оплачено ' || FORMAT_DATE(:DATE_PAYMENT) || ') по строке: ' || :PURPOSE); + + ID_LAWSUIT = (SELECT WE.ID_LAWSUIT FROM DOC$LAWSUIT$EXEC_PROC EP INNER JOIN DOC$LAWSUIT$WRIT_OF_EXEC WE ON WE.ID = EP.ID_WRIT_OF_EXEC WHERE EP.ID = :ID_EXEC_PROC); + END + + IF ((:ID_EXEC_PROC IS NOT NULL) AND (:ID_WRIT_EXEC IS NULL)) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Указано ИП, но не указан ИЛ.'); + + SUSPEND; + END + + PROCEDURE RECOGN_BAILIFF(DATE_PAYMENT DOM$DATE NOT NULL, PURPOSE D_VARCHAR_500 NOT NULL) RETURNS (ID_LAWSUIT DOM$KEY, ID_WRIT_EXEC DOM$KEY, ID_EXEC_PROC DOM$KEY) + AS + DECLARE VARIABLE POS_NUMBER_WRIT_EXEC D_INTEGER; + DECLARE VARIABLE NUMBER_WRIT_EXEC TYPE OF DOM$NUMBER_WRIT_EXEC; + DECLARE VARIABLE ID_ABONENT DOM$ABONENT; + DECLARE VARIABLE POS_SNP_RESPONDENT D_INTEGER; + DECLARE VARIABLE POS_SNP_RESPONDENT_END D_INTEGER; + DECLARE VARIABLE SNP_RESPONDENT D_VARCHAR_100; + DECLARE VARIABLE NUMBER_FILE DOM$NUMBER_FILE; + DECLARE VARIABLE NUMBER_FILE_WO_CD DOM$NUMBER_FILE; + DECLARE VARIABLE ID_CORRECTION DOM$KEY; + BEGIN + -- У госпошлины нет реквизитов + IF (POSITION('(ИНН 0; КПП 0) Перечисление ГОСПОШЛИНЫ в АО "Газпром газораспределение дальний Восток":', :PURPOSE) > 0) THEN + BEGIN + SUSPEND; + EXIT; + END + + -- Ищем нераспознаваемый платеж + ID_CORRECTION = (SELECT C.ID FROM DIR$EXEC_PROC$CORRECTION C WHERE C.PAYMENT_PURPOSE = :PURPOSE); + + IF (:ID_CORRECTION IS NOT NULL) THEN + SELECT + C.CORRECT_NUMBER_FILE, + UPPER(C.CORRECT_FIO) + FROM + DIR$EXEC_PROC$CORRECTION C + WHERE + C.ID = :ID_CORRECTION + INTO + :NUMBER_FILE, + :SNP_RESPONDENT; + + -- Получаем ФИО ответчика + IF (:SNP_RESPONDENT IS NULL) THEN + BEGIN + POS_SNP_RESPONDENT = POSITION('Перечисление в АО "Газпром газораспределение дальний Восток":', :PURPOSE); + IF (:POS_SNP_RESPONDENT > 0) THEN + POS_SNP_RESPONDENT = :POS_SNP_RESPONDENT + CHAR_LENGTH('Перечисление в АО "Газпром газораспределение дальний Восток":'); + + IF (:POS_SNP_RESPONDENT = 0) THEN + BEGIN + POS_SNP_RESPONDENT = POSITION('Перечисление средств в счет погашения долга взыскателю :', :PURPOSE); + IF (:POS_SNP_RESPONDENT > 0) THEN + POS_SNP_RESPONDENT = :POS_SNP_RESPONDENT + CHAR_LENGTH('Перечисление средств в счет погашения долга взыскателю :'); + END + + IF (:POS_SNP_RESPONDENT = 0) THEN + BEGIN + POS_SNP_RESPONDENT = POSITION('КМС ГОСПОШЛИНА в пользу АО "ГАЗПРОМ газораспределение Дальний Восток"":', :PURPOSE); + IF (:POS_SNP_RESPONDENT > 0) THEN + POS_SNP_RESPONDENT = :POS_SNP_RESPONDENT + CHAR_LENGTH('КМС ГОСПОШЛИНА в пользу АО "ГАЗПРОМ газораспределение Дальний Восток"":'); + END + + IF (:POS_SNP_RESPONDENT = 0) THEN + BEGIN + POS_SNP_RESPONDENT = POSITION('КМС ДОЛГА в пользу АО "ГАЗПРОМ газораспределение Дальний Восток":', :PURPOSE); + IF (:POS_SNP_RESPONDENT > 0) THEN + POS_SNP_RESPONDENT = :POS_SNP_RESPONDENT + CHAR_LENGTH('КМС ДОЛГА в пользу АО "ГАЗПРОМ газораспределение Дальний Восток":'); + END + + IF (:POS_SNP_RESPONDENT = 0) THEN + BEGIN + POS_SNP_RESPONDENT = POSITION('КМС ДОЛГА в пользу ОАО "ХАБАРОВСККРАЙГАЗ":', :PURPOSE); + IF (:POS_SNP_RESPONDENT > 0) THEN + POS_SNP_RESPONDENT = :POS_SNP_RESPONDENT + CHAR_LENGTH('КМС ДОЛГА в пользу ОАО "ХАБАРОВСККРАЙГАЗ":'); + END + + IF (:POS_SNP_RESPONDENT = 0) THEN + BEGIN + POS_SNP_RESPONDENT = POSITION('Перечисление средств в счет погашения долга взыскателю :', :PURPOSE); + IF (:POS_SNP_RESPONDENT > 0) THEN + POS_SNP_RESPONDENT = :POS_SNP_RESPONDENT + CHAR_LENGTH('Перечисление средств в счет погашения долга взыскателю :'); + END + + IF (:POS_SNP_RESPONDENT = 0) THEN + BEGIN + POS_SNP_RESPONDENT = POSITION('(долг):', :PURPOSE); + IF (:POS_SNP_RESPONDENT > 0) THEN + POS_SNP_RESPONDENT = :POS_SNP_RESPONDENT + CHAR_LENGTH('(долг):'); + END + + IF (:POS_SNP_RESPONDENT = 0) THEN + BEGIN + POS_SNP_RESPONDENT = POSITION('(госпошлина):', :PURPOSE); + IF (:POS_SNP_RESPONDENT > 0) THEN + POS_SNP_RESPONDENT = :POS_SNP_RESPONDENT + CHAR_LENGTH('(госпошлина):'); + END + + IF (:POS_SNP_RESPONDENT = 0) THEN + BEGIN + POS_SNP_RESPONDENT = POSITION('Перечисление средств :', :PURPOSE); + IF (:POS_SNP_RESPONDENT > 0) THEN + POS_SNP_RESPONDENT = :POS_SNP_RESPONDENT + CHAR_LENGTH('Перечисление средств :'); + END + + IF (:POS_SNP_RESPONDENT = 0) THEN + BEGIN + POS_SNP_RESPONDENT = POSITION('Долг с:', :PURPOSE); + IF (:POS_SNP_RESPONDENT > 0) THEN + POS_SNP_RESPONDENT = :POS_SNP_RESPONDENT + CHAR_LENGTH('Долг с:'); + END + + IF (:POS_SNP_RESPONDENT = 0) THEN + BEGIN + POS_SNP_RESPONDENT = POSITION('Долг с :', :PURPOSE); + IF (:POS_SNP_RESPONDENT > 0) THEN + POS_SNP_RESPONDENT = :POS_SNP_RESPONDENT + CHAR_LENGTH('Долг с :'); + END + + IF (:POS_SNP_RESPONDENT = 0) THEN + BEGIN + POS_SNP_RESPONDENT = POSITION('Долг с ', :PURPOSE); + IF (:POS_SNP_RESPONDENT > 0) THEN + POS_SNP_RESPONDENT = :POS_SNP_RESPONDENT + CHAR_LENGTH('Долг с '); + END + + IF (:POS_SNP_RESPONDENT = 0) THEN + BEGIN + POS_SNP_RESPONDENT = POSITION('Задолженность (АОГазпром газораспред.ДВ): ', :PURPOSE); + IF (:POS_SNP_RESPONDENT > 0) THEN + POS_SNP_RESPONDENT = :POS_SNP_RESPONDENT + CHAR_LENGTH('Задолженность (АОГазпром газораспред.ДВ): '); + END + + IF (:POS_SNP_RESPONDENT = 0) THEN + BEGIN + POS_SNP_RESPONDENT = POSITION('КМС СУДЕБНЫЕ РАСХ в пользу АО "ГАЗПРОМ газораспределение Дальний Восток":', :PURPOSE); + IF (:POS_SNP_RESPONDENT > 0) THEN + POS_SNP_RESPONDENT = :POS_SNP_RESPONDENT + CHAR_LENGTH('КМС СУДЕБНЫЕ РАСХ в пользу АО "ГАЗПРОМ газораспределение Дальний Восток":'); + END + + -- УФК по Хабаровскому краю (ОСП по Советско-Гаванскому району УФССП России по Хабаровскому краю и Еврейской автономной области) + IF (:POS_SNP_RESPONDENT = 0) THEN + BEGIN + -- Пример оплаты: + -- ДОЛГ ЗА ГАЗ ПО С/ПРИКАЗУ 2-1974/2018 ОТ 09.08.2018 Фамилия Имя Отчество адрес + POS_SNP_RESPONDENT = POSITION('ДОЛГ ЗА ГАЗ ПО С/ПРИКАЗУ ', :PURPOSE); + IF (:POS_SNP_RESPONDENT > 0) THEN + BEGIN + POS_SNP_RESPONDENT = POSITION(' ', :PURPOSE, 42) + 1;-- Ищем пробел после окончания даты приказа + END + END + + IF (:POS_SNP_RESPONDENT = 0) THEN + BEGIN + POS_SNP_RESPONDENT = POSITION(':', :PURPOSE); + IF (:POS_SNP_RESPONDENT > 0) THEN + POS_SNP_RESPONDENT = :POS_SNP_RESPONDENT + CHAR_LENGTH(':'); + END + + IF (:POS_SNP_RESPONDENT > 0) THEN + BEGIN + POS_SNP_RESPONDENT_END = POSITION(' ', :PURPOSE, :POS_SNP_RESPONDENT);-- Фамилия + IF (:POS_SNP_RESPONDENT_END = 0) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Нет окончания фамилии'); + + POS_SNP_RESPONDENT_END = POSITION(' ', :PURPOSE, :POS_SNP_RESPONDENT_END + 1);-- Имя + IF (:POS_SNP_RESPONDENT_END = 0) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Нет окончания имени'); + + POS_SNP_RESPONDENT_END = POSITION(' ', :PURPOSE, :POS_SNP_RESPONDENT_END + 1);-- Отчество + IF (:POS_SNP_RESPONDENT_END = 0) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Нет окончания отчества'); + + SNP_RESPONDENT = REPLACE(:SNP_RESPONDENT, 'Ё', 'Е'); + SNP_RESPONDENT = UPPER(SUBSTRING(:PURPOSE FROM :POS_SNP_RESPONDENT FOR (:POS_SNP_RESPONDENT_END - :POS_SNP_RESPONDENT))); + + IF (RIGHT(:SNP_RESPONDENT, '1') = ',') THEN + SNP_RESPONDENT = TRIM(LEFT(:SNP_RESPONDENT, CHAR_LENGTH(:SNP_RESPONDENT) - 1)); + IF (RIGHT(:SNP_RESPONDENT, '1') = '.') THEN + SNP_RESPONDENT = TRIM(LEFT(:SNP_RESPONDENT, CHAR_LENGTH(:SNP_RESPONDENT) - 1)); + END + ELSE IF (POSITION('ФС ', :PURPOSE) = 0) THEN + BEGIN + SUSPEND; + EXIT; + END + END + + -- EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Не найдено ФИО ответчика'); + + -- Ищем номер ИЛ + POS_NUMBER_WRIT_EXEC = POSITION('ВС N ', :PURPOSE); + IF (:POS_NUMBER_WRIT_EXEC > 0) THEN + POS_NUMBER_WRIT_EXEC = :POS_NUMBER_WRIT_EXEC + 5; + + IF (:POS_NUMBER_WRIT_EXEC = 0) THEN + BEGIN + POS_NUMBER_WRIT_EXEC = POSITION('ВС ', UPPER(:PURPOSE)); + IF (:POS_NUMBER_WRIT_EXEC > 0) THEN + POS_NUMBER_WRIT_EXEC = :POS_NUMBER_WRIT_EXEC + 3; + END + + IF (:POS_NUMBER_WRIT_EXEC = 0) THEN + BEGIN + POS_NUMBER_WRIT_EXEC = POSITION('ФС N ', :PURPOSE); + IF (:POS_NUMBER_WRIT_EXEC > 0) THEN + POS_NUMBER_WRIT_EXEC = :POS_NUMBER_WRIT_EXEC + 5; + END + + IF (:POS_NUMBER_WRIT_EXEC = 0) THEN + BEGIN + POS_NUMBER_WRIT_EXEC = POSITION('ФС ', UPPER(:PURPOSE)); + IF (:POS_NUMBER_WRIT_EXEC > 0) THEN + POS_NUMBER_WRIT_EXEC = :POS_NUMBER_WRIT_EXEC + 3; + END + + IF (:POS_NUMBER_WRIT_EXEC = 0) THEN + BEGIN + POS_NUMBER_WRIT_EXEC = POSITION('ВС', UPPER(:PURPOSE)); + IF (:POS_NUMBER_WRIT_EXEC > 0) THEN + POS_NUMBER_WRIT_EXEC = :POS_NUMBER_WRIT_EXEC + 2; + + -- Это может быть часть текста "Хабаровский" + IF (:POS_NUMBER_WRIT_EXEC > 0) THEN + IF (SUBSTRING(:PURPOSE FROM :POS_NUMBER_WRIT_EXEC FOR 1) NOT BETWEEN '0' AND '9') THEN + POS_NUMBER_WRIT_EXEC = 0; + END + + IF (:POS_NUMBER_WRIT_EXEC = 0) THEN + BEGIN + POS_NUMBER_WRIT_EXEC = POSITION('ИД ', :PURPOSE); + IF (:POS_NUMBER_WRIT_EXEC > 0) THEN + POS_NUMBER_WRIT_EXEC = :POS_NUMBER_WRIT_EXEC + 3; + END + + IF (:POS_NUMBER_WRIT_EXEC = 0) THEN + BEGIN + POS_NUMBER_WRIT_EXEC = POSITION('ИСПОЛНИТЕЛЬН ЛИСТ ', UPPER(:PURPOSE)); + IF (:POS_NUMBER_WRIT_EXEC > 0) THEN + POS_NUMBER_WRIT_EXEC = :POS_NUMBER_WRIT_EXEC + CHAR_LENGTH('ИСПОЛНИТЕЛЬН ЛИСТ '); + END + + IF (:POS_NUMBER_WRIT_EXEC = 0) THEN + BEGIN + POS_NUMBER_WRIT_EXEC = POSITION('ИСПОЛНИТЕЛЬН ', UPPER(:PURPOSE)); + IF (:POS_NUMBER_WRIT_EXEC > 0) THEN + POS_NUMBER_WRIT_EXEC = :POS_NUMBER_WRIT_EXEC + CHAR_LENGTH('ИСПОЛНИТЕЛЬН '); + END + + IF (:POS_NUMBER_WRIT_EXEC = 0) THEN + BEGIN + POS_NUMBER_WRIT_EXEC = POSITION('ИСПОЛНИТЕЛЬНЫЙ ', UPPER(:PURPOSE)); + IF (:POS_NUMBER_WRIT_EXEC > 0) THEN + POS_NUMBER_WRIT_EXEC = :POS_NUMBER_WRIT_EXEC + CHAR_LENGTH('ИСПОЛНИТЕЛЬНЫЙ '); + END + + IF (:POS_NUMBER_WRIT_EXEC = 0) THEN + BEGIN + POS_NUMBER_WRIT_EXEC = POSITION('ИСПОЛНИТЕЛ ЛИСТ ', UPPER(:PURPOSE)); + IF (:POS_NUMBER_WRIT_EXEC > 0) THEN + POS_NUMBER_WRIT_EXEC = :POS_NUMBER_WRIT_EXEC + CHAR_LENGTH('ИСПОЛНИТЕЛ ЛИСТ '); + END + + IF (:POS_NUMBER_WRIT_EXEC = 0) THEN + BEGIN + POS_NUMBER_WRIT_EXEC = POSITION('ИСП ЛИСТ ', UPPER(:PURPOSE)); + IF (:POS_NUMBER_WRIT_EXEC > 0) THEN + POS_NUMBER_WRIT_EXEC = :POS_NUMBER_WRIT_EXEC + CHAR_LENGTH('ИСП ЛИСТ '); + END + + IF (:POS_NUMBER_WRIT_EXEC > 0) THEN + BEGIN + NUMBER_WRIT_EXEC = 'ВС' || SUBSTRING(:PURPOSE FROM :POS_NUMBER_WRIT_EXEC FOR 9); + + -- Ищем опечатку в номере ИЛ + ID_CORRECTION = (SELECT C.ID FROM DIR$EXEC_PROC$CORRECTION C WHERE C.PAYMENT_SERIAL_WRIT_EXEC = :NUMBER_WRIT_EXEC AND C.TYPE_PAYMENT = 2); + + IF (:ID_CORRECTION IS NOT NULL) THEN + SELECT + C.CORRECT_NUMBER_FILE, + UPPER(C.CORRECT_FIO) + FROM + DIR$EXEC_PROC$CORRECTION C + WHERE + C.ID = :ID_CORRECTION + INTO + :NUMBER_FILE, + :SNP_RESPONDENT; + END + + IF (:NUMBER_FILE IS NULL) THEN + IF (:POS_NUMBER_WRIT_EXEC > 0) THEN + BEGIN + NUMBER_WRIT_EXEC = 'ВС' || SUBSTRING(:PURPOSE FROM :POS_NUMBER_WRIT_EXEC FOR 9); + + IF (CHAR_LENGTH(:NUMBER_WRIT_EXEC) <> 11) THEN + BEGIN + -- Если номер ИЛ не полный, пытается найти его по совпадению известной части и ФИО + ID_WRIT_EXEC = (SELECT WE.ID FROM DOC$LAWSUIT$WRIT_OF_EXEC WE INNER JOIN REG$ABONENT$CITIZEN C ON C.ID = WE.ID_RESPONDENT WHERE (UPPER(C.SURNAME_NAME_PATRONYMIC) = :SNP_RESPONDENT) AND (WE.NUMBER STARTING WITH :NUMBER_WRIT_EXEC)); + + IF (:ID_WRIT_EXEC IS NULL) THEN + EXIT; + END + ELSE + BEGIN + -- EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Неправильный номер ИЛ: ' || COALESCE(:NUMBER_WRIT_EXEC, '') || '.'); + + IF ((SELECT COUNT(*) FROM DOC$LAWSUIT$WRIT_OF_EXEC WE WHERE WE.NUMBER = :NUMBER_WRIT_EXEC) > 1) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Более 1 исп. листа с №' || :NUMBER_WRIT_EXEC || '.' || ASCII_CHAR(31) || 'Устраните дубликаты.'); + + ID_WRIT_EXEC = (SELECT WE.ID FROM DOC$LAWSUIT$WRIT_OF_EXEC WE WHERE WE.NUMBER = :NUMBER_WRIT_EXEC); + IF (:ID_WRIT_EXEC IS NULL) THEN + ID_WRIT_EXEC = (SELECT WE.ID FROM DOC$LAWSUIT$WRIT_OF_EXEC WE WHERE WE.NUMBER_WRIT_EXEC_FOR_DUTY = :NUMBER_WRIT_EXEC); + END + + IF (:ID_WRIT_EXEC IS NULL) THEN + BEGIN + NUMBER_WRIT_EXEC = 'ФС' || SUBSTRING(:PURPOSE FROM :POS_NUMBER_WRIT_EXEC FOR 9); + + ID_WRIT_EXEC = (SELECT WE.ID FROM DOC$LAWSUIT$WRIT_OF_EXEC WE WHERE WE.NUMBER = :NUMBER_WRIT_EXEC); + IF (:ID_WRIT_EXEC IS NULL) THEN + ID_WRIT_EXEC = (SELECT WE.ID FROM DOC$LAWSUIT$WRIT_OF_EXEC WE WHERE WE.NUMBER_WRIT_EXEC_FOR_DUTY = :NUMBER_WRIT_EXEC); + END + + IF (:ID_WRIT_EXEC IS NOT NULL) THEN + BEGIN + -- EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Исполнительный лист №' || :NUMBER_WRIT_EXEC || ' не найден.'); + + ID_EXEC_PROC = (SELECT FIRST 1 EP.ID FROM DOC$LAWSUIT$EXEC_PROC EP WHERE EP.ID_WRIT_OF_EXEC = :ID_WRIT_EXEC AND EP.ID_BANK IS NULL AND EP.DATE_TRANSFERENCE < :DATE_PAYMENT ORDER BY EP.DATE_TRANSFERENCE DESC); + IF (:ID_EXEC_PROC IS NOT NULL) THEN + BEGIN + -- EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Исполнительное производство по исп. листу №' || :NUMBER_WRIT_EXEC || ' не найдено.'); + + ID_LAWSUIT = (SELECT WE.ID_LAWSUIT FROM DOC$LAWSUIT$WRIT_OF_EXEC WE WHERE WE.ID = :ID_WRIT_EXEC); + + -- Проверяем соответствие ФИО + IF (:SNP_RESPONDENT IS NOT NULL) THEN + IF ((SELECT RESULT FROM GET$WRIT_EXEC$CHECK_RESPONDENT(:ID_WRIT_EXEC, :SNP_RESPONDENT)) = 0) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Другое ФИО у ответчика. В квитанции "' || COALESCE(:SNP_RESPONDENT, '') + || '", в ИЛ "' || COALESCE((SELECT UPPER(C.SURNAME_NAME_PATRONYMIC) FROM DOC$LAWSUIT$WRIT_OF_EXEC WE INNER JOIN REG$ABONENT$CITIZEN C ON C.ID = WE.ID_RESPONDENT WHERE WE.ID = :ID_WRIT_EXEC), 'NULL') || '".'); + END + END + END + + -- Ищем иск по номеру дела + IF (:ID_LAWSUIT IS NULL) THEN + BEGIN + IF (:NUMBER_FILE IS NULL) THEN + NUMBER_FILE = SEARCH_NUMBER_FILE(:PURPOSE, FALSE); + + -- Ищем необходимость исправления + ID_CORRECTION = (SELECT C.ID FROM DIR$EXEC_PROC$CORRECTION C WHERE (C.PAYMENT_NUMBER_FILE IS NOT DISTINCT FROM :NUMBER_FILE) AND (UPPER(C.PAYMENT_FIO) = :SNP_RESPONDENT)); + + IF (:ID_CORRECTION IS NOT NULL) THEN + SELECT + C.CORRECT_NUMBER_FILE, + UPPER(C.CORRECT_FIO) + FROM + DIR$EXEC_PROC$CORRECTION C + WHERE + C.ID = :ID_CORRECTION + INTO + :NUMBER_FILE, + :SNP_RESPONDENT; + +-- exception EXC$CHECK_DATA COALESCE(:NUMBER_FILE, '') || ' ' || COALESCE(:SNP_RESPONDENT, ''); + + IF (:NUMBER_FILE IS NOT NULL) THEN + BEGIN + -- Получаем исполнительный лист + ID_WRIT_EXEC = (SELECT RESULT FROM GET$WRIT_EXEC$SEARCH_BY_RESPOND(:NUMBER_FILE, :SNP_RESPONDENT)); + + IF (:ID_WRIT_EXEC IS NULL) THEN + BEGIN + -- Убираем номер участка + NUMBER_FILE_WO_CD = TRIM_COURT_DISTRICT(:NUMBER_FILE); + IF (:NUMBER_FILE IS NOT NULL) THEN + BEGIN + ID_WRIT_EXEC = (SELECT RESULT FROM GET$WRIT_EXEC$SEARCH_BY_RESPOND(:NUMBER_FILE_WO_CD, :SNP_RESPONDENT)); + IF (:ID_WRIT_EXEC IS NOT NULL) THEN + NUMBER_FILE = :NUMBER_FILE_WO_CD; + END + END + + IF (:ID_WRIT_EXEC IS NULL) THEN + BEGIN + -- Меняем формат года + NUMBER_FILE = CONVERT_NUMBER_FILE(:NUMBER_FILE, :PURPOSE); + IF (:NUMBER_FILE IS NULL) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Пустой номер дела после конвертации: ' || :PURPOSE); + + ID_WRIT_EXEC = (SELECT RESULT FROM GET$WRIT_EXEC$SEARCH_BY_RESPOND(:NUMBER_FILE, :SNP_RESPONDENT)); + END + + IF (:ID_WRIT_EXEC IS NOT NULL) THEN + BEGIN + -- EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Иск №' || :NUMBER_FILE || ' не найден (ответчик ' || :SNP_RESPONDENT || ').'); + + ID_LAWSUIT = (SELECT WE.ID_LAWSUIT FROM DOC$LAWSUIT$WRIT_OF_EXEC WE WHERE WE.ID = :ID_WRIT_EXEC); + + -- Получаем исполнительное производство + ID_EXEC_PROC = (SELECT FIRST 1 EP.ID FROM DOC$LAWSUIT$EXEC_PROC EP WHERE EP.ID_WRIT_OF_EXEC = :ID_WRIT_EXEC AND EP.ID_BANK IS NULL AND EP.DATE_TRANSFERENCE < :DATE_PAYMENT ORDER BY EP.DATE_TRANSFERENCE DESC); + IF (:ID_EXEC_PROC IS NULL) THEN + BEGIN + NUMBER_WRIT_EXEC = (SELECT WE.NUMBER FROM DOC$LAWSUIT$WRIT_OF_EXEC WE WHERE WE.ID = :ID_WRIT_EXEC); + -- EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Исполнительное производство по исп. листу №' || COALESCE(:NUMBER_WRIT_EXEC, '') || ' дела ' || :NUMBER_FILE || ' не найдено.'); + END + END + END + END + + IF (:ID_EXEC_PROC IS NOT NULL) THEN + BEGIN + IF (:ID_LAWSUIT IS NULL) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Иск не указан'); + IF (:ID_WRIT_EXEC IS NULL) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('ИЛ не указан'); + END + ELSE + BEGIN + ID_LAWSUIT = NULL; + ID_WRIT_EXEC = NULL; + END + + SUSPEND; + END + + PROCEDURE TRY_CREATE_RECEIPT_BAILIFF(ID_SOURCE DOM$KEY NOT NULL, DATE_ACCOUNT DOM$DATE NOT NULL, DATE_PAYMENT DOM$DATE NOT NULL, NUMBER_RECEIPT DOM$NUMBER_CHECK NOT NULL, AMOUNT DOM$AMOUNT NOT NULL, PURPOSE D_VARCHAR_500 NOT NULL) RETURNS (RESULT DOM$KEY) + AS + DECLARE VARIABLE ID_BATCH DOM$KEY; + DECLARE VARIABLE ID_NF_ABONENT_FOR_PAYMENT_LAWSU DOM$ABONENT; + DECLARE VARIABLE ID_LAWSUIT DOM$KEY; + DECLARE VARIABLE ID_WRIT_EXEC DOM$KEY; + DECLARE VARIABLE ID_EXEC_PROC DOM$KEY; + DECLARE VARIABLE ID_GROUP_DISTRICT DOM$KEY; + BEGIN + -- Ищем иск в базе + SELECT + ID_LAWSUIT, + ID_WRIT_EXEC, + ID_EXEC_PROC + FROM + RECOGN_BAILIFF(:DATE_PAYMENT, :PURPOSE) + INTO + :ID_LAWSUIT, + :ID_WRIT_EXEC, + :ID_EXEC_PROC; + + -- Если иск не найден, выходим + IF (:ID_LAWSUIT IS NULL) THEN + BEGIN + RESULT = NULL; + SUSPEND; + EXIT; + END + +-- ID_NF_ABONENT_FOR_PAYMENT_LAWSU = (SELECT ID_NF_ABONENT_FOR_PAYMENT_LAWSU FROM DIR$ENTERPRISE$GROUP_DISTRICT WHERE ID = PKG$CONNECT.ID_GROUP_DISTRICT()); +-- IF (:ID_NF_ABONENT_FOR_PAYMENT_LAWSU IS NULL) THEN +-- EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('В группе участков "' +-- || (SELECT NAME FROM DIR$ENTERPRISE$GROUP_DISTRICT WHERE ID = PKG$CONNECT.ID_GROUP_DISTRICT()) +-- || '" не указан лицевой счет для неопознанных платежей.' || ASCII_CHAR(31) || 'Убедитесь, что у вас сейчас правильная группа участков.'); +-- + -- Запоминаем группу участков иска + ID_GROUP_DISTRICT = PKG$ABONENT.GET_GROUP_DISTRICT_FOR_PAYMENT((SELECT L.ID_ABONENT FROM DOC$ABONENT$LAWSUIT L WHERE L.ID = :ID_LAWSUIT)); + + ID_SOURCE = COALESCE((SELECT B.ID_SOURCE_PAYMENT_BAILIFF FROM DIR$ENTERPRISE$GROUP_DISTRICT GD INNER JOIN DIR$ENTERPRISE$BRANCH B ON B.ID = GD.ID_BRANCH WHERE GD.ID = :ID_GROUP_DISTRICT), :ID_SOURCE); + + -- Проверяем дублирование оплаты + IF (EXISTS(SELECT 1 FROM BAT$RECEIPT$RECEIPT R INNER JOIN BAT$RECEIPT$BATCH B ON B.ID = R.ID_BATCH WHERE (B.ID_SOURCE = :ID_SOURCE) AND (R.DATE_PAYMENT = :DATE_PAYMENT) AND (R.NUMBER = :NUMBER_RECEIPT))) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Квитанция №' || :NUMBER_RECEIPT || ' от ' || FORMAT_DATE(:DATE_PAYMENT) || ' на сумму ' || :AMOUNT || ' уже создана.'); + + -- Создаем пачку + IF ((SELECT COUNT(*) FROM BAT$RECEIPT$BATCH B WHERE (B.ID_GROUP_DISTRICT = :ID_GROUP_DISTRICT) AND (B.ID_SOURCE = :ID_SOURCE) AND (B.DATE_ACCOUNT = :DATE_ACCOUNT)) > 1) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('За ' || FORMAT_DATE(:DATE_ACCOUNT) || ' найдено более 1 пачки квитанций.'); + + ID_BATCH = (SELECT B.ID FROM BAT$RECEIPT$BATCH B WHERE (B.ID_GROUP_DISTRICT = :ID_GROUP_DISTRICT) AND (B.ID_SOURCE = :ID_SOURCE) AND (B.DATE_ACCOUNT = :DATE_ACCOUNT)); + IF (:ID_BATCH IS NULL) THEN + BEGIN + INSERT INTO BAT$RECEIPT$BATCH + (ID, ID_GROUP_DISTRICT, ID_SOURCE, DATE_ACCOUNT) + VALUES + (NEXT VALUE FOR SEQ_BAT$RECEIPT$BATCH_ID, :ID_GROUP_DISTRICT, :ID_SOURCE, :DATE_ACCOUNT) + RETURNING + ID + INTO + :ID_BATCH; + END + ELSE IF ((SELECT B.LOADED FROM BAT$RECEIPT$BATCH B WHERE B.ID = :ID_BATCH) = 1) THEN + EXECUTE PROCEDURE PKG$EXCEPTION.FOR_BATCH_RECEIPT(:ID_BATCH, 'Пачка квитанций уже загружена.'); + + -- Создаем квитанцию + INSERT INTO BAT$RECEIPT$RECEIPT + (ID, ID_BATCH, ID_ABONENT, ID_PERIOD_FOR_PAYMENT, ID_TYPE_RECEIPT, ID_LAWSUIT, ID_WRIT_EXEC, ID_EXEC_PROC, DATE_PAYMENT, NUMBER, AUTODISTRIBUTE_SERVICES, AMOUNT_SERVICE_5, PURPOSE) + VALUES + (NEXT VALUE FOR SEQ_BAT$RECEIPT$RECEIPT_ID, :ID_BATCH, (SELECT ID_ABONENT FROM DOC$ABONENT$LAWSUIT WHERE ID = :ID_LAWSUIT), DATE_TO_PERIOD(:DATE_PAYMENT), (SELECT ID_TYPE_RECEIPT_VIA_BAILIFF FROM SYS$LINK$PAYMENT), :ID_LAWSUIT, :ID_WRIT_EXEC, :ID_EXEC_PROC, :DATE_PAYMENT, :NUMBER_RECEIPT, 0, :AMOUNT, :PURPOSE) + RETURNING + ID + INTO + :RESULT; + + SUSPEND; + END + + FUNCTION DETECT_PERS_ACCOUNT(PURPOSE D_VARCHAR_500 NOT NULL, TEXT_BEFORE D_VARCHAR_25 NOT NULL, TEXT_AFTER D_VARCHAR_10 NOT NULL) RETURNS DOM$ABONENT + AS + DECLARE VARIABLE POS DOM$INTEGER; + DECLARE VARIABLE RES DOM$ABONENT; + BEGIN + POS = POSITION(:TEXT_BEFORE, :PURPOSE); + IF (:POS > 0) THEN + BEGIN + PURPOSE = SUBSTRING(:PURPOSE FROM :POS + CHAR_LENGTH(:TEXT_BEFORE)); + + IF (SUBSTRING(:PURPOSE FROM 10 FOR CHAR_LENGTH(:TEXT_AFTER)) = :TEXT_AFTER) THEN + BEGIN + RES = LEFT(:PURPOSE, 9); + RETURN :RES; + WHEN ANY DO + RETURN NULL; + END + END + + RETURN NULL; + END + + FUNCTION RECOGN_INDIVID(PURPOSE D_VARCHAR_500 NOT NULL) RETURNS DOM$ABONENT + AS + DECLARE VARIABLE TEMP D_VARCHAR_500; + DECLARE VARIABLE ID_ABONENT DOM$ABONENT; + BEGIN + PURPOSE = REPLACE(REPLACE(:PURPOSE, '-', ''), ' ', ''); + + -- Поиск лицевого счета по шаблону + -- ПАО "МТС-БАНК" + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'л/сч', 'Плата'); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'л/с', ','); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + -- АО "ТИНЬКОФФ БАНК" + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'л/счет', '.'); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'ЛСИ', ';'); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'Л/счет', 'за'); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'л/с', ''); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + -- ПАО "ПОЧТА БАНК" + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'ЛС//№', '//'); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'л/с', ';'); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'ЛС//№', '('); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + -- РНКО "ПЛАТЕЖНЫЙ ЦЕНТР" (ООО) + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'ЛС', ','); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'Л.С', ','); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + -- ПАО "ПРОМСВЯЗЬБАНК" + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'ЛС //№', '//'); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + -- НКО "ПЕРСПЕКТИВА" (ООО) + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'Номерлицевогосчета', ';'); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + -- ДАЛЬНЕВОСТОЧНЫЙ ФИЛИАЛ ПАО РОСБАНК + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'ЛС', ':'); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'ЛС', ''); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'лс', ''); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'л/счет:', ')'); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'л/счет', ',Адрес'); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'л/счет', ''); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'Лицеврйсчет', 'Комсомольс'); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + -- ДАЛЬНЕВОСТОЧНЫЙ БАНК ПАО СБЕРБАНК + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'Оплатанал/счет', 'за'); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'л/сч', ','); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'л/счету', 'ул'); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + -- ВОЛГО-ВЯТСКИЙ БАНК ПАО СБЕРБАНК + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'Л/СЧВ', ''); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'Л/СЧ', ''); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + -- ООО КБ "ПЛАТИНА" + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'Л/счет', '/'); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + -- ФИЛИАЛ № 2754 БАНКА ВТБ (ПАО) + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'лицевойсчет', 'пред'); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + -- АО "СК "Колымская" + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'пол/с', 'по'); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + -- ФИЛИАЛ ЦЕНТРАЛЬНЫЙ ПАО БАНКА "ФК ОТКРЫТИЕ" + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'ЛСИ', '///'); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + -- ООО НКО "ЯНДЕКС.ДЕНЬГИ" + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'посчету', 'за'); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + -- ООО "ХКФ БАНК" + ID_ABONENT = DETECT_PERS_ACCOUNT(:PURPOSE, 'Л/счет', 'N'); + IF (:ID_ABONENT IS NOT NULL) THEN + RETURN :ID_ABONENT; + + RETURN NULL; + END + + PROCEDURE TRY_CREATE_RECEIPT_INDIVID(DATE_ACCOUNT DOM$DATE NOT NULL, DATE_PAYMENT DOM$DATE NOT NULL, NUMBER_RECEIPT DOM$NUMBER_CHECK NOT NULL, AMOUNT DOM$AMOUNT NOT NULL, PURPOSE D_VARCHAR_500 NOT NULL, PAYER D_VARCHAR_200 NOT NULL, ID_ABONENT DOM$ABONENT) RETURNS (RESULT DOM$KEY) + AS + DECLARE VARIABLE ID_BRANCH DOM$KEY; + DECLARE VARIABLE ID_SOURCE DOM$KEY; + DECLARE VARIABLE ID_BATCH DOM$KEY; + DECLARE VARIABLE ID_GROUP_DISTRICT DOM$KEY; + DECLARE VARIABLE COMMENT_BATCH DOM$COMMENT; + BEGIN + IF (:ID_ABONENT IS NULL) THEN + BEGIN + -- Пробуем распознать плательщика + ID_ABONENT = RECOGN_INDIVID(:PURPOSE); + + -- Получаем лицевой счет + IF (:ID_ABONENT IS NULL) THEN + BEGIN + EXIT; +-- EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Лицевой счет не распознан: "' || :PURPOSE || '" (' || :NUMBER_RECEIPT || ').'); + + /* ID_ABONENT = (SELECT ID_NF_ABONENT_FOR_PAYMENT_LAWSU FROM DIR$ENTERPRISE$GROUP_DISTRICT WHERE ID = :ID_GROUP_DISTRICT); + + IF (:ID_ABONENT IS NULL) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('В группе участков "' + || (SELECT NAME FROM DIR$ENTERPRISE$GROUP_DISTRICT WHERE ID = :ID_GROUP_DISTRICT) + || '" не указан лицевой счет для неопознанных платежей.');*/ + END + END + + -- Получаем филиал по абоненту + ID_BRANCH = (SELECT A.ID_BRANCH FROM DIR$ABONENT$ABONENT A WHERE A.ID = :ID_ABONENT); + IF (:ID_BRANCH IS NULL) THEN + BEGIN + SUSPEND; + EXIT; + END + + -- Определяем источник оплаты + ID_SOURCE = (SELECT ID_SOURCE_INDIVID_PAYMENT_ORDER FROM DIR$ENTERPRISE$BRANCH WHERE ID = :ID_BRANCH); + IF (:ID_SOURCE IS NULL) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA_BRANC(:ID_BRANCH, 'Не указан источник оплаты для индивидуальных платежей.'); + + -- Определяем группу участков + IF (:ID_BRANCH = 2) THEN + ID_GROUP_DISTRICT = 2; + ELSE + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA_BRANC(:ID_BRANCH, 'Не указана группа участков по умолчанию.'); + + -- Определяем, кто ведет учет + IF ((SELECT RESULT FROM GET$ABONENT$CHARGING_GAS_AMURCC(:ID_ABONENT)) = 1) THEN + COMMENT_BATCH = 'АмурВЦ'; + ELSE + COMMENT_BATCH = 'Общество'; + + -- Ищем пачку квитанций + ID_BATCH = (SELECT B.ID FROM BAT$RECEIPT$BATCH B WHERE (B.ID_GROUP_DISTRICT = :ID_GROUP_DISTRICT) AND (B.ID_SOURCE = :ID_SOURCE) AND (B.DATE_ACCOUNT = :DATE_ACCOUNT) AND (B.COMMENT IS NOT DISTINCT FROM :COMMENT_BATCH)); + + IF (:ID_BATCH IS NULL) THEN + BEGIN + INSERT INTO BAT$RECEIPT$BATCH + (ID, ID_GROUP_DISTRICT, ID_SOURCE, DATE_ACCOUNT, COMMENT) + VALUES + (NEXT VALUE FOR SEQ_BAT$RECEIPT$BATCH_ID, :ID_GROUP_DISTRICT, :ID_SOURCE, :DATE_ACCOUNT, :COMMENT_BATCH) + RETURNING + ID + INTO + :ID_BATCH; + END + ELSE IF ((SELECT B.LOADED FROM BAT$RECEIPT$BATCH B WHERE B.ID = :ID_BATCH) = 1) THEN + EXECUTE PROCEDURE PKG$EXCEPTION.FOR_BATCH_RECEIPT(:ID_BATCH, 'Пачка квитанций уже загружена.'); + + -- Создаем квитанцию + INSERT INTO BAT$RECEIPT$RECEIPT + (ID, ID_BATCH, ID_ABONENT, ID_PERIOD_FOR_PAYMENT, ID_TYPE_RECEIPT, DATE_PAYMENT, NUMBER, AUTODISTRIBUTE_SERVICES, AMOUNT_SERVICE_1, PURPOSE, PAYER) + VALUES + (NEXT VALUE FOR SEQ_BAT$RECEIPT$RECEIPT_ID, :ID_BATCH, :ID_ABONENT, DEC_PERIOD(DATE_TO_PERIOD(:DATE_PAYMENT)), (SELECT RESULT FROM GET$ABONENT$DEFAULT_TYPE_RECEIP(:ID_ABONENT)), :DATE_PAYMENT, :NUMBER_RECEIPT, 1, :AMOUNT, :PURPOSE, :PAYER) + RETURNING + ID + INTO + :RESULT; + + SUSPEND; + END + + PROCEDURE ADD_CORRECT_NONACCEPT(ID_PAYMENT DOM$KEY NOT NULL, NUMBER_FILE_OLD DOM$NUMBER_FILE NOT NULL, RESPONDENT_OLD D_VARCHAR_100 NOT NULL, NUMBER_FILE_NEW DOM$NUMBER_FILE NOT NULL, RESPONDENT_NEW D_VARCHAR_100 NOT NULL) + AS + DECLARE VARIABLE ID_CORRECTION DOM$KEY; + BEGIN + -- Проверяем, что квитанция не создана + IF ((SELECT B.RECEIPT_CREATED FROM INF$PAYMENT$BANK_STTM B WHERE B.ID = :ID_PAYMENT) IS TRUE) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Платеж с кодом ' || :ID_PAYMENT || ' уже создан.'); + + -- Проверяем, что это безакцепт + IF ((SELECT B.ID_BANK FROM INF$PAYMENT$BANK_STTM B WHERE B.ID = :ID_PAYMENT) IS NULL) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Платеж с кодом ' || :ID_PAYMENT || ' не является оплатой безакцепта.'); + + -- Ищем повтор + IF (EXISTS(SELECT 1 FROM DIR$EXEC_PROC$CORRECTION C WHERE (C.PAYMENT_NUMBER_FILE = :NUMBER_FILE_OLD) AND (C.PAYMENT_FIO = :RESPONDENT_OLD) AND (C.TYPE_PAYMENT = 1))) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Корректировка уже есть в справочнике.'); + + -- Добавляем + IN AUTONOMOUS TRANSACTION DO + INSERT INTO DIR$EXEC_PROC$CORRECTION + (PAYMENT_NUMBER_FILE, PAYMENT_FIO, CORRECT_NUMBER_FILE, CORRECT_FIO, TYPE_PAYMENT) + VALUES + (:NUMBER_FILE_OLD, :RESPONDENT_OLD, :NUMBER_FILE_NEW, :RESPONDENT_NEW, 1) + RETURNING + ID + INTO + :ID_CORRECTION; + + -- Создаем квитанцию + BEGIN + EXECUTE PROCEDURE CREATE_RECEIPT(:ID_PAYMENT, NULL); + + WHEN ANY DO + BEGIN + IN AUTONOMOUS TRANSACTION DO + DELETE FROM DIR$EXEC_PROC$CORRECTION WHERE ID = :ID_CORRECTION; + + EXCEPTION; + -- ### this is line 1731 which was mentioned in the ticket ### -- END + END + + -- Проверяем, что она создалась + IF ((SELECT B.RECEIPT_CREATED FROM INF$PAYMENT$BANK_STTM B WHERE B.ID = :ID_PAYMENT) IS FALSE) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Платеж с кодом ' || :ID_PAYMENT || ' не распознался.' || ASCII_CHAR(31) || 'Проверьте реквизиты.'); + END + + PROCEDURE ADD_CORRECT_BAILIFF(ID_PAYMENT DOM$KEY NOT NULL, NUMBER_FILE DOM$NUMBER_FILE NOT NULL, RESPONDENT D_VARCHAR_100 NOT NULL) + AS + DECLARE VARIABLE PURPOSE D_VARCHAR_500; + BEGIN + -- Проверяем, что квитанция не создана + IF ((SELECT B.RECEIPT_CREATED FROM INF$PAYMENT$BANK_STTM B WHERE B.ID = :ID_PAYMENT) IS TRUE) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Платеж с кодом ' || :ID_PAYMENT || ' уже создан.'); + + -- Проверяем, что это ССП + IF ((SELECT B.ID_BAILIFF FROM INF$PAYMENT$BANK_STTM B WHERE B.ID = :ID_PAYMENT) IS NULL) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Платеж с кодом ' || :ID_PAYMENT || ' не является оплатой от ССП.'); + + -- Ищем повтор + PURPOSE = (SELECT B.PURPOSE FROM INF$PAYMENT$BANK_STTM B WHERE B.ID = :ID_PAYMENT); + IF (EXISTS(SELECT 1 FROM DIR$EXEC_PROC$CORRECTION C WHERE (C.PAYMENT_PURPOSE = :PURPOSE) AND (C.TYPE_PAYMENT = 2))) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Назначение уже есть в справочнике.'); + + -- Добавляем + INSERT INTO DIR$EXEC_PROC$CORRECTION + (PAYMENT_PURPOSE, CORRECT_NUMBER_FILE, CORRECT_FIO, TYPE_PAYMENT) + VALUES + (:PURPOSE, :NUMBER_FILE, :RESPONDENT, 2); + + -- Создаем квитанцию + EXECUTE PROCEDURE CREATE_RECEIPT(:ID_PAYMENT, NULL); + + -- Проверяем, что она создалась + IF ((SELECT B.RECEIPT_CREATED FROM INF$PAYMENT$BANK_STTM B WHERE B.ID = :ID_PAYMENT) IS FALSE) THEN + EXECUTE PROCEDURE OPER$EXCEPTION$CHECK_DATA('Платеж с кодом ' || :ID_PAYMENT || ' не распознался.' || ASCII_CHAR(31) || 'Проверьте реквизиты.'); + END + + PROCEDURE SEND_NOTIFY_LOAD_BANK_STATEMENT(DATE_ACCOUNT DOM$DATE NOT NULL, RECOGN DOM$INTEGER NOT NULL, NOT_RECOGN DOM$INTEGER NOT NULL) + AS + BEGIN + EXECUTE PROCEDURE PKG$SEND_EMAIL.SEND_TO_EMAILS('ulezlova@gazdv.ru,kuzmina2@gazdv.ru,muratova@gazdv.ru,smirinskayaea@gazdv.ru', 'kuzmin@gazdv.ru', 'Загружена выписка из банк-клиента за ' || FORMAT_DATE(:DATE_ACCOUNT), + TRIM(IIF(:NOT_RECOGN = 0, 'Распознаны все платежи.', 'Не распознано платежей: ' || :NOT_RECOGN || '.'))); + END + + PROCEDURE SEND_NOTIFY_RECONG_BANK_STATEME(DATE_ACCOUNT DOM$DATE NOT NULL) + AS + BEGIN + EXECUTE PROCEDURE PKG$SEND_EMAIL.SEND_TO_EMAILS('ulezlova@gazdv.ru,kuzmina2@gazdv.ru,muratova@gazdv.ru,smirinskayaea@gazdv.ru', 'kuzmin@gazdv.ru', 'Распознана выписка за ' || FORMAT_DATE(:DATE_ACCOUNT), + 'Распознаны все платежи.'); + END + + PROCEDURE SEND_NOTIFY_ERROR_LOAD_BANK_STA + AS + BEGIN + EXECUTE PROCEDURE PKG$SEND_EMAIL.SEND_TO_EMAILS('kuzmin@gazdv.ru,ryazanov@gazdv.ru', NULL, 'Ошибка при загрузке выписки из банк-клиента', 'Загружал пользователь: ' || PKG$CONNECT.CURRENT_USER_SURNAME_NP()); + END + + PROCEDURE SEND_NOTIFY_ERROR_DETECT_SOURCE + AS + BEGIN + EXECUTE PROCEDURE PKG$SEND_EMAIL.SEND_TO_EMAILS('kuzmin@gazdv.ru,ryazanov@gazdv.ru', 'ulezlova@gazdv.ru,kuzmina2@gazdv.ru,muratova@gazdv.ru,smirinskayaea@gazdv.ru', 'Ошибка при поиске источников оплаты в выписке', 'Загружал пользователь: ' || PKG$CONNECT.CURRENT_USER_SURNAME_NP()); + END + + PROCEDURE SEND_NOTIFY_ERROR_CREATE_ALL_RE + AS + BEGIN + EXECUTE PROCEDURE PKG$SEND_EMAIL.SEND_TO_EMAILS('kuzmin@gazdv.ru,ryazanov@gazdv.ru', 'ulezlova@gazdv.ru,kuzmina2@gazdv.ru,muratova@gazdv.ru,smirinskayaea@gazdv.ru', 'Ошибка при создании квитанций по выписке', 'Загружал пользователь: ' || PKG$CONNECT.CURRENT_USER_SURNAME_NP()); + END +END^ + + +CREATE PACKAGE BODY PKG$SEND_EMAIL +AS +BEGIN + PROCEDURE SEND_TO_EMAILS(EMAILS DOM$EMAILS NOT NULL, EMAILS_COPY DOM$EMAILS, SUBJECT DOM$EMAIL_SUBJECT NOT NULL, BODY_MAIL DOM$EMAIL_BODY NOT NULL) + AS + DECLARE VARIABLE ERROR D_VARCHAR_255; + BEGIN + END + + PROCEDURE SEND_TO_LIST_USERS(LIST_USERS D_LIST_ID NOT NULL, LIST_USERS_COPY D_LIST_ID, SUBJECT DOM$EMAIL_SUBJECT NOT NULL, BODY_MAIL DOM$EMAIL_BODY NOT NULL) + AS + DECLARE VARIABLE EMAILS DOM$EMAILS; + DECLARE VARIABLE EMAILS_COPY DOM$EMAILS; + BEGIN + END + + PROCEDURE SEND_TO_GROUP(ID_GROUP DOM$KEY NOT NULL, SUBJECT DOM$EMAIL_SUBJECT NOT NULL, BODY_MAIL DOM$EMAIL_BODY NOT NULL) + AS + DECLARE VARIABLE EMAILS DOM$EMAILS; + BEGIN + END +END^ + + + +SET TERM ; ^ + + + +/******************************************************************************/ +/*** Descriptions ***/ +/******************************************************************************/ + +COMMENT ON DOMAIN DOM$ABONENT IS +'Лицевой счет'; + +COMMENT ON DOMAIN DOM$ABONENT_LONG IS +'Длинный лицевой счет'; + +COMMENT ON DOMAIN DOM$ADDRESS IS +'Адрес'; + +COMMENT ON DOMAIN DOM$AMOUNT IS +'Сумма'; + +COMMENT ON DOMAIN DOM$CITIZEN_NAME IS +'Имя'; + +COMMENT ON DOMAIN DOM$CITIZEN_PATRONYMIC IS +'Отчество'; + +COMMENT ON DOMAIN DOM$CITIZEN_SURNAME IS +'Фамилия'; + +COMMENT ON DOMAIN DOM$COMMENT IS +'Примечание'; + +COMMENT ON DOMAIN DOM$CURRENT_TIMESTAMP IS +'Текущее дата/время'; + +COMMENT ON DOMAIN DOM$EMAIL IS +'E-mail'; + +COMMENT ON DOMAIN DOM$EMAILS IS +'Список эл. почтовых ящиков'; + +COMMENT ON DOMAIN DOM$NAME_CONTRACTOR IS +'Наименование контрагента (в 1С)'; + +COMMENT ON DOMAIN DOM$NAME_LONG IS +'Наименование элемента справочника большой длины'; + +COMMENT ON DOMAIN DOM$NAME_SHORT IS +'Наименование короткой длины'; + +COMMENT ON DOMAIN DOM$NAME_STANDARD IS +'Наименование элемента справочника обычной длины'; + +COMMENT ON DOMAIN DOM$NAME_TINY IS +'Наименование маленькой длины'; + +COMMENT ON DOMAIN DOM$NETWORK_PORT IS +'Номер порта'; + +COMMENT ON DOMAIN DOM$NUMBER_CHECK IS +'Номер чека (квитанции)'; + +COMMENT ON DOMAIN DOM$NUMBER_EXEC_PROCESS IS +'Номер исполнительного производства'; + +COMMENT ON DOMAIN DOM$NUMBER_FILE IS +'Номер дела'; + +COMMENT ON DOMAIN DOM$NUMBER_PAYMENT_ORDER IS +'Номер платежного поручения'; + +COMMENT ON DOMAIN DOM$NUMBER_WRIT_EXEC IS +'Номер исполнительного листа'; + +COMMENT ON DOMAIN DOM$PERIOD IS +'Период'; + +COMMENT ON DOMAIN DOM$POSITION IS +'Позиция записи'; + +COMMENT ON DOMAIN DOM$SERIES_WRIT_EXEC IS +'Серия исполнительного листа'; + +COMMENT ON DOMAIN DOM$STATE IS +'Код состояния документа'; + +COMMENT ON DOMAIN DOM$STRING_DATE IS +'Дата в строковом представлении'; + +COMMENT ON DOMAIN DOM$TIME IS +'Время'; + +COMMENT ON DOMAIN DOM$VERSION IS +'Версия базы данных (Major.Minor.Release)'; + + + +/******************************************************************************/ +/*** Descriptions ***/ +/******************************************************************************/ + +COMMENT ON TABLE SYS$LOG$EXCEPTION IS +'Лог исключений в базе данных'; + + + +/******************************************************************************/ +/*** Descriptions ***/ +/******************************************************************************/ + +COMMENT ON PROCEDURE GET$ABONENT$DETERMINE_GD IS +'Определяет группу участков абонента по его лицевому счету'; + + + +/******************************************************************************/ +/*** Privileges ***/ +/******************************************************************************/ + + +/* Privileges of users */ +GRANT USAGE ON EXCEPTION EXC$CANCEL TO PUBLIC; +GRANT ALL ON SYS$LOG$EXCEPTION TO READER_ROLE; +GRANT EXECUTE ON PROCEDURE GET$ABONENT$DETERMINE_GD TO READER_ROLE; +GRANT EXECUTE ON PROCEDURE OPER$EXCEPTION$CANCEL TO READER_ROLE; +GRANT ALL ON SYS$LOG$EXCEPTION TO USER_ROLE; +GRANT EXECUTE ON PROCEDURE GET$ABONENT$DETERMINE_GD TO USER_ROLE; +GRANT EXECUTE ON PROCEDURE GET$WRIT_EXEC$SEARCH_BY_RESPOND TO USER_ROLE; +GRANT EXECUTE ON PROCEDURE OPER$EXCEPTION$CANCEL TO USER_ROLE; + +/* Privileges of procedures */ +GRANT SELECT ON DOC$ABONENT$LAWSUIT TO PROCEDURE GET$WRIT_EXEC$SEARCH_BY_RESPOND; +GRANT SELECT ON DOC$LAWSUIT$WRIT_OF_EXEC TO PROCEDURE GET$WRIT_EXEC$SEARCH_BY_RESPOND; +GRANT SELECT ON REG$ABONENT$CITIZEN TO PROCEDURE GET$WRIT_EXEC$SEARCH_BY_RESPOND; +GRANT EXECUTE ON PROCEDURE OPER$EXCEPTION$CHECK_DATA TO PROCEDURE GET$WRIT_EXEC$SEARCH_BY_RESPOND; +GRANT INSERT ON SYS$LOG$EXCEPTION TO PROCEDURE OPER$EXCEPTION$CANCEL; +GRANT USAGE ON EXCEPTION EXC$CANCEL TO PROCEDURE OPER$EXCEPTION$CANCEL; +GRANT USAGE ON SEQUENCE SEQ_SYS$LOG$EXCEPTION_ID TO PROCEDURE OPER$EXCEPTION$CANCEL; +exit; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ +Statement failed, SQLSTATE = 42000 +Dynamic SQL Error +-SQL error code = -104 +-Token unknown - line 1735, column 9 +-IF + """ + +@pytest.mark.version('>=3.0.5') +def test_core_6068_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_6071.py b/tests/bugs/test_core_6071.py new file mode 100644 index 00000000..54979e75 --- /dev/null +++ b/tests/bugs/test_core_6071.py @@ -0,0 +1,245 @@ +#coding:utf-8 +# +# id: bugs.core_6071 +# title: Restore of encrypted backup of database with SQL dialect 1 fails +# decription: +# +# We create new database ('tmp_core_6071.fdb') and try to encrypt it using IBSurgeon Demo Encryption package +# ( https://ib-aid.com/download-demo-firebird-encryption-plugin/ ; https://ib-aid.com/download/crypt/CryptTest.zip ) +# License file plugins\\dbcrypt.conf with unlimited expiration was provided by IBSurgeon to Firebird Foundation (FF). +# This file was preliminary stored in FF Test machine. +# Test assumes that this file and all neccessary libraries already were stored into FB_HOME and %FB_HOME%\\plugins. +# +# Anyone who wants to run this test on his own machine must +# 1) download https://ib-aid.com/download/crypt/CryptTest.zip AND +# 2) PURCHASE LICENSE and get from IBSurgeon file plugins\\dbcrypt.conf with apropriate expiration date and other info. +# +# ################################################ ! ! ! N O T E ! ! ! ############################################## +# FF tests storage (aka "fbt-repo") does not (and will not) contain any license file for IBSurgeon Demo Encryption package! +# ######################################################################################################################### +# +# After test database will be created, we try to encrypt it using 'alter database encrypt with ...' command +# (where = dbcrypt - name of .dll in FB_HOME\\plugins\\ folder that implements encryption). +# Then we allow engine to complete this job - take delay about 1..2 seconds BEFORE detach from database. +# +# After this we: +# 1. Change temp DB state to full shutdown and bring it online - in order to be sure that we will able to drop this file later; +# 2. Make backup of this temp DB, using gbak utility and '-KEYHOLDER ' command switch. +# NB! According to additional explanation by Alex, ticket issue occured *only* when "gbak -KEYHOLDER ..." used rather than fbsvcmgr. +# 3. Make restore from just created backup. +# 4. Make validation of just restored database by issuing command "gfix -v -full ..." +# ( i.e. validate both data and metadata rather than online val which can check user data only). +# 5. Check that NO errors occured on any above mentioned steps. Also check that backup and restore STDOUT logs contain expected +# text about successful completition +# +# Confirmed bug on 4.0.0.1485 (build date: 11-apr-2019), got error on restore: +# SQL error code = -817 +# Metadata update statement is not allowed by the current database SQL dialect 1 +# +# Works fine on 4.0.0.1524, time ~8s. +# +# === NOTE-1 === +# In case of "Crypt plugin DBCRYPT failed to load/607/335544351" check that all +# needed files from IBSurgeon Demo Encryption package exist in %FB_HOME% and %FB_HOME%\\plugins +# %FB_HOME%: +# 283136 fbcrypt.dll +# 2905600 libcrypto-1_1-x64.dll +# 481792 libssl-1_1-x64.dll +# +# %FB_HOME%\\plugins: +# 297984 dbcrypt.dll +# 306176 keyholder.dll +# 108 DbCrypt.conf +# 856 keyholder.conf +# +# === NOTE-2 === +# Version of DbCrypt.dll of october-2018 must be replaced because it has hard-coded +# date of expiration rather than reading it from DbCrypt.conf !! +# +# === NOTE-3 === +# firebird.conf must contain following line: +# KeyHolderPlugin = KeyHolder +# +# +# tracker_id: CORE-6071 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('\\d+ BYTES WRITTEN', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import time +# import subprocess +# import re +# import fdb +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.close() +# +# tmpfdb='$(DATABASE_LOCATION)'+'tmp_core_6071.fdb' +# tmpbkp='$(DATABASE_LOCATION)'+'tmp_core_6071.fbk' +# +# gbak_backup_finish_ptn=re.compile('gbak:closing\\s+file,\\s+committing,\\s+and\\s+finishing.*', re.IGNORECASE) +# gbak_restore_finish_ptn=re.compile('gbak:adjusting\\s+the\\s+ONLINE\\s+and\\s+FORCED\\s+WRITES\\s+.*', re.IGNORECASE) +# +# if os.path.isfile( tmpfdb ): +# os.remove( tmpfdb ) +# +# con = fdb.create_database( dsn = 'localhost:'+tmpfdb, sql_dialect = 1 ) +# con.close() +# con=fdb.connect( dsn = 'localhost:'+tmpfdb ) +# cur = con.cursor() +# cur.execute('alter database encrypt with dbcrypt key Red') +# con.commit() +# time.sleep(2) +# # ^ +# # +-------- !! ALLOW BACKGROUND ENCRYPTION PROCESS TO COMPLETE ITS JOB !! +# +# con.close() +# +# #---------- aux func for cleanup: --------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# +# +# #-------------------------- shutdown temp DB and bring it online -------------------- +# +# f_dbshut_log = open( os.path.join(context['temp_directory'],'tmp_dbshut_6071.log'), 'w') +# subprocess.call( [ "gfix", 'localhost:'+tmpfdb, "-shut", "full", "-force", "0" ], +# stdout = f_dbshut_log, +# stderr = subprocess.STDOUT +# ) +# subprocess.call( [ "gfix", 'localhost:'+tmpfdb, "-online" ], +# stdout = f_dbshut_log, +# stderr = subprocess.STDOUT +# ) +# f_dbshut_log.close() +# +# #--------------------------- backup and restore -------------------------------------- +# fn_bkp_log=open( os.path.join(context['temp_directory'],'tmp_backup_6071.log'), 'w') +# fn_bkp_err=open( os.path.join(context['temp_directory'],'tmp_backup_6071.err'), 'w') +# +# +# subprocess.call([ "gbak.exe" +# ,"-b" +# ,"-v" +# ,"-KEYHOLDER", "KeyHolder" +# ,"-crypt", "DbCrypt" +# ,'localhost:' + tmpfdb +# ,tmpbkp +# ], +# stdout=fn_bkp_log, stderr=fn_bkp_err) +# +# fn_bkp_log.close() +# fn_bkp_err.close() +# +# +# fn_res_log=open( os.path.join(context['temp_directory'],'tmp_restore_6071.log'), 'w') +# fn_res_err=open( os.path.join(context['temp_directory'],'tmp_restore_6071.err'), 'w') +# +# # C:\\FB SS\\gbak.exe -rep -KEYHOLDER KeyHolder C:\\FBTESTING\\qa\\misc\\C6071.fbk /:C:\\FBTESTING\\qa\\misc\\c6071.restored.FDB +# subprocess.call([ "gbak" +# ,"-rep" +# ,"-v" +# ,"-KEYHOLDER", "KeyHolder" +# ,tmpbkp +# ,'localhost:' + tmpfdb +# ], +# stdout=fn_res_log, stderr=fn_res_err) +# +# fn_res_log.close() +# fn_res_err.close() +# +# #-------------------------- validate just restored database -------------------- +# +# f_valid_log = open( os.path.join(context['temp_directory'],'tmp_valid_6071.log'), 'w') +# subprocess.call( [ "gfix", 'localhost:'+tmpfdb, "-v", "-full" ], +# stdout = f_valid_log, +# stderr = subprocess.STDOUT +# ) +# f_valid_log.close() +# +# #----------------------------------------------- +# +# # Check that all was fine: +# +# with open(f_dbshut_log.name,'r') as f: +# for line in f: +# print('UNEXPECTED SHUTDOWN OUTPUT: ' + line) +# +# with open(fn_bkp_err.name,'r') as f: +# for line in f: +# print('UNEXPECTED BACKUP STDERR: ' + line) +# +# with open(fn_res_err.name,'r') as f: +# for line in f: +# print('UNEXPECTED RESTORE STDERR: ' + line) +# +# with open(f_dbshut_log.name,'r') as f: +# for line in f: +# print('UNEXPECTED VALIDATION OUTPUT: ' + line) +# +# # gbak -b should finish with line: +# # gbak:closing file, committing, and finishing. 512 bytes written +# with open(fn_bkp_log.name,'r') as f: +# for line in f: +# if gbak_backup_finish_ptn.search(line): +# print('EXPECTED BACKUP FINISH FOUND: '+line.upper() ) +# +# #gbak_backup_finish_ptn=re.compile('gbak:closing\\s+file,\\s+committing,\\s+and\\s+finishing.*', re.IGNORECASE) +# +# # gbak -c should finish with lines: +# # gbak:finishing, closing, and going home +# # gbak:adjusting the ONLINE and FORCED WRITES flags +# #gbak_restore_finish_ptn=re.compile('gbak:adjusting\\s+the\\s+ONLINE\\s+and\\s+FORCED\\s+WRITES\\s+.*', re.IGNORECASE) +# with open(fn_res_log.name,'r') as f: +# for line in f: +# if gbak_restore_finish_ptn.search(line): +# print('EXPECTED RESTORE FINISH FOUND: '+line.upper() ) +# +# +# # Allow all file buffers to be flushed on disk before we will drop them: +# time.sleep(1) +# +# # cleanup +# ########## +# +# f_list = [ i.name for i in ( f_dbshut_log, fn_bkp_log, fn_bkp_err, fn_res_log, fn_res_err, f_valid_log ) ] +# f_list += [ tmpfdb, tmpbkp ] +# cleanup( f_list ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + EXPECTED BACKUP FINISH FOUND: GBAK:CLOSING FILE, COMMITTING, AND FINISHING. + EXPECTED RESTORE FINISH FOUND: GBAK:ADJUSTING THE ONLINE AND FORCED WRITES FLAGS + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_6071_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6078.py b/tests/bugs/test_core_6078.py new file mode 100644 index 00000000..b9cfa61a --- /dev/null +++ b/tests/bugs/test_core_6078.py @@ -0,0 +1,518 @@ +#coding:utf-8 +# +# id: bugs.core_6078 +# title: Permissions for create or alter statements are not checked +# decription: +# The problem occured for all kind of DB objects which allow 'create OR ALTER' statement to be applied against themselves. +# Test creates non-privileged user and checks for all such objects that this user can NOT create any object because missing +# privilege to do this. +# Confirmed bug on 3.0.5.33140 and 4.0.0.1532. +# +# +# Refactored 20.01.2020: +# 1. Changed code in order to make its code more flexible because 3.0 and 4.0 have significant differences in stdout/stderr. +# Common SQL code was stored in fbt-repo +# iles\\core_6078.sql with embedding there variable name: '%(dsn)s' -- it is known from here. +# Content of this file is stored in variable 'sql_text' and this variable is changed using common Python rule for substitutions: +# sql_text % dict(globals(), **locals() +# Then we save this variable to temporarily .sql script and run it. +# 2. Added check for other kinds of DB objects: users, database, domain, table, column of table, charset and local/global mappings. +# +# Checked on: +# 4.0.0.1748 SS: 2.346s. +# 3.0.6.33236 SS: 1.898s. +# +# tracker_id: CORE-6078 +# min_versions: ['3.0.5'] +# versions: 3.0.5, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [('.*After line \\d+.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import time +# import subprocess +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# this_db = db_conn.database_name +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# f_sql=open(os.path.join(context['files_location'],'core_6078.sql'),'r') +# sql_text = f_sql.read() +# flush_and_close( f_sql ) +# +# f_sql_chk = open( os.path.join(context['temp_directory'],'tmp_core_6078.sql'), 'w', buffering = 0) +# f_sql_chk.write( sql_text % dict(globals(), **locals()) ) +# flush_and_close( f_sql_chk ) +# +# f_sql_log = open( '.'.join( (os.path.splitext( f_sql_chk.name )[0], 'log') ), 'w', buffering = 0) +# subprocess.call( [ context['isql_path'], '-q', '-i', f_sql_chk.name ], stdout = f_sql_log, stderr = subprocess.STDOUT) +# flush_and_close( f_sql_log ) +# +# with open( f_sql_log.name,'r') as f: +# for line in f: +# if line.strip(): +# print( line ) +# +# # cleanup +# ######### +# time.sleep(1) +# cleanup( (f_sql_log, f_sql_chk) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Statement failed, SQLSTATE = 28000 + modify record error + -no permission for UPDATE access to COLUMN PLG$SRP_VIEW.PLG$ACTIVE + + 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 DM_TEST failed + -no permission for ALTER access to DOMAIN DM_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 + -ALTER INDEX TEST_UID failed + -no permission for ALTER access to TABLE TEST + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -COMMENT ON TEST failed + -no permission for ALTER access to TABLE TEST + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -CREATE OR ALTER TRIGGER TEST_BI failed + -no permission for ALTER access to TABLE TEST + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -CREATE OR ALTER TRIGGER TRG$START failed + -no permission for ALTER access to DATABASE + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -CREATE OR ALTER TRIGGER TRIG_DDL_SP failed + -no permission for ALTER access to DATABASE + + + ALTERED_TRIGGER_NAME TEST_BI + ALTERED_TRIGGER_SOURCE c:3d0 + as + begin + new.uid = gen_uuid(); + end + + + Records affected: 1 + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE OR ALTER PACKAGE PKG_TEST failed + -There is no privilege for this operation + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -RECREATE PACKAGE BODY PKG_TEST failed + -There is no privilege for this operation + + + ALTERED_PKG_NAME + + + Records affected: 1 + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE OR ALTER FUNCTION FN_C6078 failed + -There is no privilege for this operation + + + ALTERED_STANDALONE_FUNC + + + Records affected: 1 + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE OR ALTER PROCEDURE SP_C6078 failed + -There is no privilege for this operation + + + ALTERED_STANDALONE_PROC + + + Records affected: 1 + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE OR ALTER VIEW V_C6078 failed + -There is no privilege for this operation + + + ALTERED_VIEW_NAME + + + Records affected: 1 + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER SEQUENCE SQ_C6078 failed + -There is no privilege for this operation + + + ALTERED_SEQUENCE_NAME + + + Records affected: 1 + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE OR ALTER EXCEPTION EX_C6078 failed + -There is no privilege for this operation + + + ALTERED_EXCEPTION_NAME + + + Records affected: 1 + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE OR ALTER FUNCTION WAIT_EVENT failed + -There is no privilege for this operation + + + ALTERED_UDR_BASED_FUNC + + + Records affected: 1 + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER CHARACTER SET UTF8 failed + -no permission for ALTER access to CHARACTER SET UTF8 + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER MAPPING LOCAL_MAP_C6078 failed + -Unable to perform operation. You must be either SYSDBA or owner of the database + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER MAPPING GLOBAL_MAP_C6078 failed + -Unable to perform operation. You must be either SYSDBA or owner of the database + """ + +@pytest.mark.version('>=3.0.5') +@pytest.mark.xfail +def test_core_6078_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + +# version: 4.0 +# resources: None + +substitutions_2 = [('.*After line \\d+.*', '')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +# test_script_2 +#--- +# +# import os +# import sys +# import time +# import subprocess +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# this_db = db_conn.database_name +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# f_sql=open(os.path.join(context['files_location'],'core_6078.sql'),'r') +# sql_text = f_sql.read() +# flush_and_close( f_sql ) +# +# f_sql_chk = open( os.path.join(context['temp_directory'],'tmp_core_6078.sql'), 'w', buffering = 0) +# f_sql_chk.write( sql_text % dict(globals(), **locals()) ) +# flush_and_close( f_sql_chk ) +# +# +# f_sql_log = open( '.'.join( (os.path.splitext( f_sql_chk.name )[0], 'log') ), 'w', buffering = 0) +# subprocess.call( [ context['isql_path'], '-q', '-i', f_sql_chk.name ], stdout = f_sql_log, stderr = subprocess.STDOUT) +# flush_and_close( f_sql_log ) +# +# with open( f_sql_log.name,'r') as f: +# for line in f: +# if line.strip(): +# print( line ) +# +# # cleanup: +# ########## +# time.sleep(1) +# cleanup( (f_sql_log, f_sql_chk) ) +# +# +# +#--- +#act_2 = python_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + Statement failed, SQLSTATE = 28000 + modify record error + -no permission for UPDATE access to COLUMN 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 DM_TEST failed + -no permission for ALTER access to DOMAIN DM_TEST + -Effective user is TMP$C6078_0 + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER TABLE TEST failed + -no permission for ALTER access to TABLE TEST + -Effective user is TMP$C6078_0 + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER TABLE TEST failed + -no permission for ALTER access to TABLE TEST + -Effective user is TMP$C6078_0 + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER INDEX TEST_UID failed + -no permission for ALTER access to TABLE TEST + -Effective user is TMP$C6078_0 + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -COMMENT ON TEST failed + -no permission for ALTER access to TABLE TEST + -Effective user is TMP$C6078_0 + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -CREATE OR ALTER TRIGGER TEST_BI failed + -no permission for ALTER access to TABLE TEST + -Effective user is TMP$C6078_0 + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -CREATE OR ALTER TRIGGER TRG$START failed + -no permission for ALTER access to DATABASE + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -CREATE OR ALTER TRIGGER TRIG_DDL_SP failed + -no permission for ALTER access to DATABASE + + + ALTERED_TRIGGER_NAME TEST_BI + ALTERED_TRIGGER_SOURCE c:3cc + as + begin + new.uid = gen_uuid(); + end + + + Records affected: 1 + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE OR ALTER PACKAGE PKG_TEST failed + -No permission for CREATE PACKAGE operation + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -RECREATE PACKAGE BODY 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 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 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 V_C6078 failed + -No permission for CREATE VIEW operation + + ALTERED_VIEW_NAME + + + Records affected: 1 + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER SEQUENCE 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 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 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 UTF8 failed + -no permission for ALTER access to CHARACTER SET 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') +@pytest.mark.xfail +def test_core_6078_2(db_2): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6083.py b/tests/bugs/test_core_6083.py new file mode 100644 index 00000000..85d2d51a --- /dev/null +++ b/tests/bugs/test_core_6083.py @@ -0,0 +1,70 @@ +#coding:utf-8 +# +# id: bugs.core_6083 +# title: USING PLUGIN clause does not work in RECREATE USER +# decription: +# Confirmed bug on WI-T4.0.0.1530, got: +# === +# Statement failed, SQLSTATE = 23000 +# add record error +# -violation of PRIMARY or UNIQUE KEY constraint "INTEG_5" on table "PLG$SRP" +# -Problematic key value is ("PLG$USER_NAME" = 'TMP$C6083') +# === +# Checked on 4.0.0.1532, SS and CS: OK, 2.085s. +# +# tracker_id: CORE-6083 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Following code should NOT raise any output: neither in STDOUT nor in STDERR. + set bail on; + set term ^; + execute block as + begin + begin + -- Here we 'silently drop' user if it remained after previous (failed) run of this test. + -- Exception about non-existent user will be suppressed: + execute statement( 'drop user tmp$c6083 using plugin Srp' ) with autonomous transaction; + when any do + begin + end + end + end + ^ + set term ;^ + commit; + + recreate user tmp$c6083 password '123' using plugin Srp; + recreate user tmp$c6083 password '456' using plugin Srp; -- THIS (second) statement raised error before ticket was fixed. + commit; + + connect '$(DSN)' user tmp$c6083 password '456'; -- here we want to be sure that user was created SUCCESSFULLY. + commit; + + connect '$(DSN)' user sysdba password 'masterkey'; + + drop user tmp$c6083 using plugin Srp; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=4.0') +def test_core_6083_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_6084.py b/tests/bugs/test_core_6084.py new file mode 100644 index 00000000..a98db028 --- /dev/null +++ b/tests/bugs/test_core_6084.py @@ -0,0 +1,158 @@ +#coding:utf-8 +# +# id: bugs.core_6084 +# title: CREATE SEQUENCE START WITH has wrong initial value +# decription: +# Behaviour of 'next value for ' and gen_id(, N) has been changed: +# 1) first, it returns to caller value that was NOT YET changed (i.e. 'current'), and +# 2) only after this it increments sequence. +# When clause 'START WITH' absent then initial value of sequence must be 1. +# +# Test verifies several possible cases for this by making different START/INCREMENT clauses combination. +# See also: doc/README.incompatibilities.3to4.txt +# See also: tests +# unctional\\generatorlter_01.fbt +# +# Checked on 4.0.0.2131. +# +# tracker_id: CORE-6084 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + --set echo on; + + recreate sequence gen_nxtval; recreate sequence gen_common; + select 'case-00' as msg, (next value for gen_nxtval) as gen_nxtval, gen_id(gen_common,1) as gen_common_gen_id from rdb$database; + + recreate sequence gen_nxtval start with 1; recreate sequence gen_common start with 1; + select 'case-01' as msg, (next value for gen_nxtval) as gen_nxtval, gen_id(gen_common,1) as gen_common_gen_id from rdb$database; + + recreate sequence gen_nxtval start with 1 increment by 2; recreate sequence gen_common start with 1 increment by 2; + select 'case-02' as msg, (next value for gen_nxtval) as gen_nxtval, gen_id(gen_common,2) as gen_common_gen_id from rdb$database; + + recreate sequence gen_nxtval start with 1 increment by -1; recreate sequence gen_common start with 1 increment by -1; + select 'case-03' as msg, (next value for gen_nxtval) as gen_nxtval, gen_id(gen_common,-1) as gen_common_gen_id from rdb$database; + + recreate sequence gen_nxtval start with 1 increment by -2; recreate sequence gen_common start with 1 increment by -2; + select 'case-04' as msg, (next value for gen_nxtval) as gen_nxtval, gen_id(gen_common,-2) as gen_common_gen_id from rdb$database; + + recreate sequence gen_nxtval increment by 2; recreate sequence gen_common increment by 2; + select 'case-05' as msg, (next value for gen_nxtval) as gen_nxtval, gen_id(gen_common,2) as gen_common_gen_id from rdb$database; + + recreate sequence gen_nxtval increment by -1; recreate sequence gen_common increment by -1; + select 'case-06' as msg, (next value for gen_nxtval) as gen_nxtval, gen_id(gen_common,-1) as gen_common_gen_id from rdb$database; + + recreate sequence gen_nxtval increment by -2; recreate sequence gen_common increment by -2; + select 'case-07' as msg, (next value for gen_nxtval) as gen_nxtval, gen_id(gen_common,-2) as gen_common_gen_id from rdb$database; + + recreate sequence gen_nxtval increment by 1000000000; recreate sequence gen_common increment by 1000000000; + select 'case-08' as msg, (next value for gen_nxtval) as gen_nxtval, gen_id(gen_common, 1000000000) as gen_common_gen_id from rdb$database; + + recreate sequence gen_nxtval increment by -1000000000; recreate sequence gen_common increment by -1000000000; + select 'case-09' as msg, (next value for gen_nxtval) as gen_nxtval, gen_id(gen_common, -1000000000) as gen_common_gen_id from rdb$database; + + recreate sequence gen_nxtval start with 9223372036854775807 increment by -1; recreate sequence gen_common start with 9223372036854775807 increment by -1; + select 'case-10' as msg, (next value for gen_nxtval) as gen_nxtval, gen_id(gen_common,-1) as gen_common_gen_id from rdb$database; + + recreate sequence gen_nxtval start with 9223372036854775807 increment by -2147483647; recreate sequence gen_common start with 9223372036854775807 increment by -2147483647; + select 'case-11' as msg, (next value for gen_nxtval) as gen_nxtval, gen_id(gen_common,-2147483647) as gen_common_gen_id from rdb$database; + + recreate sequence gen_nxtval start with -9223372036854775808 increment by 2147483647; recreate sequence gen_common start with -9223372036854775808 increment by 2147483647; + select 'case-12' as msg, (next value for gen_nxtval) as gen_nxtval, gen_id(gen_common,2147483647) as gen_common_gen_id from rdb$database; + + recreate table test(id int generated always as identity); + insert into test default values; + insert into test default values; + select 'case-13' as msg, id from test; + commit; + + recreate table test(id bigint generated always as identity); + insert into test default values; + insert into test default values; + select 'case-14' as msg, id from test; + commit; + + recreate table test(id bigint generated always as identity (start with -9223372036854775808) ); + insert into test default values; + insert into test default values; + select 'case-15' as msg, id from test; + commit; + + recreate table test(id bigint generated always as identity (start with -9223372036854775808 increment by 2147483647) ); + insert into test default values; + insert into test default values; + select 'case-16' as msg, id from test; + commit; + + recreate table test(id bigint generated always as identity (increment by 2147483647) ); + insert into test default values; + insert into test default values; + select 'case-17' as msg, id from test; + commit; + + recreate table test(id bigint generated always as identity (start with 9223372036854775807 increment by -2147483647) ); + insert into test default values; + insert into test default values; + select 'case-18' as msg, id from test; + commit; + + recreate table test(id bigint generated always as identity (increment by -2147483647) ); + insert into test default values; + insert into test default values; + select 'case-19' as msg, id from test; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + case-00 1 1 + case-01 1 1 + case-02 1 1 + case-03 1 1 + case-04 1 1 + case-05 1 1 + case-06 1 1 + case-07 1 1 + case-08 1 1 + case-09 1 1 + case-10 9223372036854775807 9223372036854775807 + case-11 9223372036854775807 9223372036854775807 + case-12 -9223372036854775808 -9223372036854775808 + case-13 1 + case-13 2 + case-14 1 + case-14 2 + case-15 -9223372036854775808 + case-15 -9223372036854775807 + case-16 -9223372036854775808 + case-16 -9223372034707292161 + case-17 1 + case-17 2147483648 + case-18 9223372036854775807 + case-18 9223372034707292160 + case-19 1 + case-19 -2147483646 + """ + +@pytest.mark.version('>=4.0') +def test_core_6084_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6086.py b/tests/bugs/test_core_6086.py new file mode 100644 index 00000000..13508852 --- /dev/null +++ b/tests/bugs/test_core_6086.py @@ -0,0 +1,886 @@ +#coding:utf-8 +# +# id: bugs.core_6086 +# title: Creating of the large procedure crashes the server. +# decription: +# Confirmed bug on: WI-T4.0.0.1534, WI-V3.0.5.33141 +# Checked on: +# 4.0.0.1535: OK, 2.051s. +# 3.0.5.33142: OK, 1.364s. +# +# tracker_id: CORE-6086 +# min_versions: ['3.0.5'] +# versions: 3.0.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='WIN1251', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + CREATE GLOBAL TEMPORARY TABLE SESSION_EDIT ( + ID INTEGER NOT NULL, + ID_SESSION INTEGER NOT NULL, + I1 INTEGER, + I2 INTEGER, + I3 INTEGER, + I4 INTEGER, + I5 INTEGER, + N1 NUMERIC(18,4), + N2 NUMERIC(18,4), + N3 NUMERIC(18,4), + N4 NUMERIC(18,4), + SYSDAY TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + D1 DATE, + D2 DATE, + I6 INTEGER, + I7 INTEGER, + I8 INTEGER, + N5 NUMERIC(18,4), + N6 NUMERIC(18,4), + N7 NUMERIC(18,4), + N8 NUMERIC(18,4), + N9 NUMERIC(18,4), + N10 NUMERIC(18,4), + N11 NUMERIC(18,4), + N12 NUMERIC(18,4), + VID INTEGER, + ID_ITEM INTEGER, + N13 NUMERIC(18,4), + N14 NUMERIC(18,4), + N15 NUMERIC(18,4), + N16 NUMERIC(18,4), + N17 NUMERIC(18,4), + N18 NUMERIC(18,4), + N19 NUMERIC(18,4), + N20 NUMERIC(18,4), + N21 NUMERIC(18,4), + N22 NUMERIC(18,4), + V1 VARCHAR(32), + V2 VARCHAR(252), + V3 VARCHAR(32), + V4 VARCHAR(252), + V5 VARCHAR(20), + V6 VARCHAR(20), + V7 VARCHAR(40), + V8 VARCHAR(40), + V9 VARCHAR(40), + V10 VARCHAR(1024), + V11 VARCHAR(1024), + B1 BIGINT + ) ON COMMIT PRESERVE ROWS; + + ALTER TABLE SESSION_EDIT ADD CONSTRAINT PK_SESSION_EDIT PRIMARY KEY (ID); + + set term ^; + + create or alter procedure get_rows(a int) returns(num int) as + begin + suspend; + end + ^ + + create or alter procedure CALC_ITEM_SUMMA ( + ID_FIRMA integer, + D1 date, + D2 date, + MAND_CAT integer, + BL_CAT integer, + ID_NPRICE integer = null, + OST integer = 1, + MAND_CAT2 integer = null) + returns ( + ID_SESSION integer) + AS + declare vid1 int = 1; -- Выпуск + declare vid2 int = 2; -- Расход сырья по изделиям (рецепт) + declare vid3 int = 3; -- Закупка ГИ + declare vid4 int = 4; -- Переработка в сырье + declare vid5 int = 5; -- Расход по документам + declare vid6 int = 6; -- Переработка приход + declare vid7 int = 7; -- Переработка расход + declare vid8 int = 8; -- Остаток на начало + declare vid9 int = 9; -- Свернутые Выпуск + остатки + расход по изделию + declare vid10 int = 10; -- Реализация + declare vid11 int = 11; -- Н/р по реализации + declare vid12 int = 12; -- Остаток на конец + declare vid99 int = 99; -- Накладные расходы + declare vid20 int = 20; -- Готовые расчеты + declare vid22 int = 22; -- Прочие движения по ГИ (сведенный) + declare vid23 int = 23; -- Промежуточные расчеты (расчет расхода сырья) + declare vid24 int = 24; -- Промежуточные расчеты (расчет переработки) + declare vid25 int = 25; -- Промежуточные расчеты (перераспределение переработки) + declare id_item int; + declare items numeric(18,3); + declare summa numeric(18,2); + declare items0 numeric(18,3); + declare summa0 numeric(18,2); + declare summa1 numeric(18,2); + declare items1 numeric(18,3); + declare items2 numeric(18,3); + declare summa2 numeric(18,2); + declare items3 numeric(18,3); + declare items4 numeric(18,3); + declare items5 numeric(18,3); + declare id0 int; + declare id1 int; + declare k int; + declare n int; + declare type_v int; + begin + -- Получаем данные из документов + --select id_session from calc_item_summa_save(:id_firma, :d1, :d2, :mand_cat, :bl_cat, :id_nprice, :ost, :mand_cat2) + --into id_session; + + -- распределение прочего расхода сырья + for select id_item, n1, n2, id from session_edit + where id_session = :id_session and vid = :vid5 + into id_item, items0, summa0, id0 do + begin + items1 = 0; summa1 = 0; + select sum(n1+n4), sum(n2) from session_edit + where id_session = :id_session and vid = :vid2 and id_item = :id_item and i5 = 0 + into items1, summa1; + + if (items1 <> 0) then + begin + for select n1+n4, n2, id from session_edit + where id_session = :id_session and vid = :vid2 and id_item = :id_item and i5 = 0 + order by 2, 1 + into items, summa, id1 do + begin + items2 = 1e0 * items0 * items / items1; + if (items0 <> 0) then + summa2 = 1e0 * items2 * summa0 / items0; + else + summa2 = coalesce(1e0 * summa0 * summa / nullif(summa1, 0), 0); + + update session_edit set + n5 = :items2, + n6 = :summa2 + where id = :id1; + end + + items2 = 0; summa2 = 0; + select sum(n5), sum(n6) from session_edit + where id_session = :id_session and vid = :vid2 and id_item = :id_item and i5 = 0 + into items2, summa2; + + if (items2 <> items0 or summa2 <> summa0) then + update session_edit set + n5 = n5 + :items0 - :items2, + n6 = n6 + :summa0 - :summa2 + where id = :id1; + + update session_edit set + i4 = 1 + where id = :id0; + end + end + + -- распределение стоимости расхода сырья вне рецептов + for select sum(n2) from session_edit + where id_session = :id_session and vid = :vid5 and i4 is null + having sum(n2) <> 0 + into summa0 do + begin + summa1 = 0; + select sum(n2+n6) from session_edit + where id_session = :id_session and vid = :vid2 + into summa1; + + if (summa1 <> 0) then + update session_edit set + n7 = cast(1e0*(n2+n6)*:summa0/:summa1 as numeric(12,2)) + where id_session = :id_session and vid = :vid2; + + summa2 = 0; + select sum(n7) from session_edit where id_session = :id_session and vid = :vid2 + into summa2; + + if (summa2 <> summa0) then + update session_edit set + n7 = n7 + :summa0 - :summa2 + where id_session = :id_session and vid = :vid2 + order by n2 desc + rows 1; + + update session_edit set + i4 = 1 + where id_session = :id_session and i2 = :vid5; + end + + -- Списываем остаток из расхода изделий + for select id, id_item, n1, n2 from session_edit s + where id_session = :id_session and vid = :vid8 and n1 > 0 + into id0, id_item, items0, summa0 do + begin + items2 = 0; + select sum(n1) from session_edit + where id_session = :id_session and vid = :vid2 and id_item = :id_item + into items2; + + -- Убираем из выпуска + items1 = minvalue(items0, items2); + if (items1 > 0) then + begin + summa1 = iif(items1 = items0, summa0, 1e0*items1*summa0/items0); + + for select id, n1 from session_edit + where id_session = :id_session and vid = :vid2 and id_item = :id_item + order by 2 + into id1, items do + begin + items = 1e0*items1*items/items2; + summa = 1e0*items*summa0/items0; + + update session_edit set + n11 = :items, + n12 = :summa, + n1 = n1 - :items + where id = :id1; + end + + select sum(n11), sum(n12) from session_edit + where id_session = :id_session and vid = :vid2 and id_item = :id_item + into items, summa; + + if (items <> items1 or summa <> summa1) then + update session_edit set + n11 = n11 + :items1 - :items, + n12 = n12 + :summa1 - :summa, + n1 = n1 - :items1 + :items + where id = :id1; + + update session_edit set + n3 = :items1, + n4 = :summa1 + where id = :id0; + + items0 = items0 - items1; + summa0 = summa0 - summa1; + end + + if (items0 <> 0) then + begin + items2 = 0; + select sum(n1) from session_edit + where id_session = :id_session and vid = :vid7 and id_item = :id_item + into items2; + + -- Убираем из переработки + items1 = minvalue(items0, items2); + if (items1 > 0) then + begin + summa1 = iif(items1 = items0, summa0, 1e0*items1*summa0/items0); + + for select id, n1 from session_edit + where id_session = :id_session and vid = :vid7 and id_item = :id_item + order by 2 + into id1, items do + begin + items = 1e0*items1*items/items2; + summa = 1e0*items*summa0/items0; + + update session_edit set + n11 = :items, + n12 = :summa, + n1 = n1 - :items + where id = :id1; + end + + select sum(n11), sum(n12) from session_edit + where id_session = :id_session and vid = :vid7 and id_item = :id_item + into items, summa; + + if (items <> items1 or summa <> summa1) then + update session_edit set + n11 = n11 + :items1 - :items, + n12 = n12 + :summa1 - :summa, + n1 = n1 - :items1 + :items + where id = :id1; + + update session_edit set + n5 = :items1, + n6 = :summa1 + where id = :id0; + + items0 = items0 - items1; + summa0 = summa0 - summa1; + end + end + end + + -- Списываем закупку из расхода изделий + for select id, id_item, n1, n2 from session_edit s + where id_session = :id_session and vid = :vid3 and n1 > 0 + into id0, id_item, items0, summa0 do + begin + items2 = 0; + select sum(n1) from session_edit + where id_session = :id_session and vid = :vid2 and id_item = :id_item + into items2; + + -- Убираем из выпуска + items1 = minvalue(items0, items2); + if (items1 > 0) then + begin + summa1 = iif(items1 = items0, summa0, 1e0*items1*summa0/items0); + + for select id, n1 from session_edit + where id_session = :id_session and vid = :vid2 and id_item = :id_item + order by 2 + into id1, items do + begin + items = 1e0*items1*items/items2; + summa = 1e0*items*summa0/items0; + + update session_edit set + n13 = :items, + n14 = :summa, + n1 = n1 - :items + where id = :id1; + end + + select sum(n13), sum(n14) from session_edit + where id_session = :id_session and vid = :vid2 and id_item = :id_item + into items, summa; + + if (items <> items1 or summa <> summa1) then + update session_edit set + n13 = n13 + :items1 - :items, + n14 = n14 + :summa1 - :summa, + n1 = n1 - :items1 + :items + where id = :id1; + + update session_edit set + n3 = :items1, + n4 = :summa1 + where id = :id0; + + items0 = items0 - items1; + summa0 = summa0 - summa1; + end + + if (items0 <> 0) then + begin + items2 = 0; + select sum(n1) from session_edit + where id_session = :id_session and vid = :vid7 and id_item = :id_item + into items2; + + -- Убираем из переработки + items1 = minvalue(items0, items2); + if (items1 > 0) then + begin + summa1 = iif(items1 = items0, summa0, 1e0*items1*summa0/items0); + + for select id, n1 from session_edit + where id_session = :id_session and vid = :vid7 and id_item = :id_item + order by 2 + into id1, items do + begin + items = 1e0*items1*items/items2; + summa = 1e0*items*summa0/items0; + + update session_edit set + n13 = :items, + n14 = :summa, + n1 = n1 - :items + where id = :id1; + end + + select sum(n13), sum(n14) from session_edit + where id_session = :id_session and vid = :vid7 and id_item = :id_item + into items, summa; + + if (items <> items1 or summa <> summa1) then + update session_edit set + n13 = n13 + :items1 - :items, + n14 = n14 + :summa1 - :summa, + n1 = n1 - :items1 + :items + where id = :id1; + + update session_edit set + n5 = :items1, + n6 = :summa1 + where id = :id0; + + items0 = items0 - items1; + summa0 = summa0 - summa1; + end + end + end + + insert into session_edit(id_session, vid, id_item, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n16, n17, n18, n19) + select :id_session, :vid9, id_item, sum(items), sum(summa), sum(summa_inv), sum(summa_in), sum(items_in), sum(items_b), + sum(summa_b), sum(items_prih), sum(summa_prih), sum(items_p_in), sum(items_t), sum(summa_t), max(price_b), sum(items_end) + from (select id_item, + sum(n1+n4+n5) items, + sum(n2+n6+n7) summa, + sum(n6+n7) summa_inv, + null ITEMS_in, + null summa_in, + 0 items_b, + 0 summa_b, + 0 items_prih, + 0 summa_prih, + 0 items_p_in, + 0 items_t, + 0 summa_t, + 0 price_b, + 0 items_end + from session_edit + where id_session = :id_session and vid = :vid2 + group by 1 + union all + select id_item, 0, 0, 0, n1, n2, 0, 0, 0, 0, 0, 0, 0, 0, 0 from session_edit where id_session = :id_session and vid = :vid1 -- приход ГИ + union all + select id_item, 0, 0, 0, 0, 0, 0, 0, n1, n2, 0, 0, 0, 0, 0 from session_edit where id_session = :id_session and vid = :vid3 -- закупка ГИ + union all + select id_item, 0, 0, 0, 0, 0, n1, n2, 0, 0, 0, 0, 0, n3, 0 from session_edit where id_session = :id_session and vid = :vid8 -- остаток ГИ + union all + select id_item, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, n1 from session_edit where id_session = :id_session and vid = :vid12 -- остаток ГИ (на конец) + union all + select id_item, 0, 0, 0, 0, 0, 0, 0, 0, 0, n1, 0, 0, 0, 0 from session_edit where id_session = :id_session and vid = :vid6 -- переработка приход ГИ + union all + select id_item, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, n1, n2, 0, 0 from session_edit where id_session = :id_session and vid = :vid4 + union all + select distinct id_item, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 from session_edit where id_session = :id_session and vid in (:vid7, :vid10, :vid22)) + group by id_item; + + insert into session_edit(id_session, vid, id_item, n1, n2, n3, n5) + with recursive + -- Расход по поличеству сырья на изделие + rashod as ( + select id_item, + i1, + sum(n1+n4+n5) items + from session_edit + where id_session = :id_session and vid = :vid2 + group by 1, 2), + -- Расход сырья по изделиям + остатки + prices0 as ( + select id_item, + n1 items, + n2 summa, + n3 summa_inv, + n5 items_in + from session_edit + where id_session = :id_session and vid = :vid9), + prices as ( + select id_item, items, summa, summa_inv, items_in from prices0 + union all + select p0.id_item, + p0.items_in, + 1e0 * r.items * p.summa / nullif(p.items, 0), + 1e0 * r.items * p.summa_inv / nullif(p.items, 0), + p0.items_in + from prices0 p0 + join rashod r on r.i1 = p0.id_item + join prices p on p.id_item = r.id_item), + total as ( + select id_item, + min(items_in) items_in, + sum(summa) summa, + sum(summa_inv) summa_inv, + min(items) items + from prices + group by id_item + having min(items_in) is not null) + select :id_session, :vid23, + id_item, + items_in, + summa, + summa_inv, + items + from total; + + insert into session_edit(id_session, vid, id_item, n1, n2, n3, n5, i1, i2) + with recursive + -- Расход по поличеству сырья на изделие + rashod as ( + select id_item, + i1, + sum(n1+n4+n5) items, + sum(n11) items_b, + sum(n13) items_prih + from session_edit + where id_session = :id_session and vid = :vid2 + group by 1, 2), + -- Расход сырья по изделиям + остатки + prices0 as ( + select s.id_item, + s.n1 items_in, + s.n2 summa, + s.n3 summa_inv, + s.n5 items, + s9.n6 items_b, + s9.n7 summa_b, + s9.n8 items_prih, + s9.n9 summa_prih, + s9.n10 items_p_in, + s9.n18 price_b + from session_edit s + join session_edit s9 on s9.id_session = s.id_session and s.id_item = s9.id_item and s9.vid = :vid9 + -- join item i on i.id = s.id_item and i.group_id = 2 + where s.id_session = :id_session and s.vid = :vid23), + prices as ( + select id_item, cast(null as int) i1, 0.0000 summa, 0.0000 summa_inv, items_b, summa_b, items_in, summa summa_in, summa_inv summa_inv_in, items_prih, summa_prih, 0.0000 items_r, 0.0000 summa_r, price_b from prices0 + union all + select p0.id_item, + p.id_item, + 1e0*r.items*p.summa_in/nullif(p.items_in, 0), + 1e0*r.items*p.summa_inv_in/nullif(p.items_in, 0), + p0.items_b, + p0.summa_b, + 0, + 0, + 0, + p0.items_prih, + p0.summa_prih, + r.items_b + r.items_prih + r.items, + coalesce(1e0*r.items_b * p.summa_b / nullif(p.items_b, 0), 0)+ + coalesce(1e0*r.items_prih * p.summa_prih / nullif(p.items_prih, 0), 0)+ + coalesce(1e0*r.items * p.summa_r / nullif(p.items_in, 0), 0), + p0.price_b + from prices0 p0 + join rashod r on r.i1 = p0.id_item + join prices p on p.id_item = r.id_item), + prices2 as ( + select id_item, items_in items, summa_in summa, summa_inv_in summa_inv, cast(summa_r as numeric(12,2)) summa_r, items_prih, summa_prih, items_b, summa_b, price_b, 1 vid from prices + union all + select i1, -items_r, -summa, -summa_inv, -cast(summa_r as numeric(12,2)), null, null, null, null, null, -1 from prices where i1 is not null), + vipusk as ( + select id_item, + sum(items) items, + sum(summa) summa, + sum(summa_inv) summa_inv, + sum(summa_r) summa_r, + coalesce(nullif(coalesce(sum(summa+summa_r)/nullif(sum(items), 0), 0), 0), max(price_b)) price_ceh, + min(items_b) items_b, + min(summa_b) summa_b, + min(items_prih) items_prih, + min(summa_prih) summa_prih + from prices2 p + group by 1), + -- Расход по переработке + rashod2 as ( + select id_item, + i1, + n1 items, + n2 koef, + n11 items_b, + n13 items_prih + from session_edit + where id_session = :id_session and vid = :vid7), + -- Увеличение себестоимости по переработке + pererabotka as ( + select r.i1 id_item, + r.id_item id_item2, + min(p0.items_p_in) items, + sum(1e0 * r.items * r.koef * v.summa /nullif(v.items, 0)) summa, + sum(1e0 * r.items * r.koef * v.summa_inv / nullif(v.items, 0)) summa_inv, + sum(r.items +r.items_b + r.items_prih) items_r, + cast(coalesce(sum(1e0 * r.items * r.koef * v.summa_r /nullif(v.items, 0)), 0)+ + coalesce(sum(1e0 * r.items_b * r.koef * v.summa_b /nullif(v.items_b, 0)), 0)+ + coalesce(sum(1e0 * r.items_prih * r.koef * v.summa_prih /nullif(v.items_prih, 0)), 0) + + coalesce(sum(iif(v.items = 0, 1e0 * r.items * r.koef * v.price_ceh, 0)), 0) as numeric(12,2)) summa_r + from rashod2 r + join vipusk v on r.id_item = v.id_item + left join prices0 p0 on p0.id_item = r.i1 + group by 1, 2), + total as ( + select id_item, items, summa, summa_inv, summa_r, cast(null as int) id_item2, 0 vid + from vipusk + union all + select id_item, items, summa, summa_inv, summa_r, id_item2, 1 vid + from pererabotka + union all + select id_item2, -items_r, -summa, -summa_inv, -summa_r, id_item, 2 vid + from pererabotka) + select :id_session, :vid24, + id_item, + items n1, + summa n2, + summa_inv n3, + summa_r n5, + id_item2 i1, + vid i2 + from total; + + insert into session_edit(id_session, vid, id_item, n1, n2, n3, n5, i1, i2) + with + total as ( + select id_item, + max(iif(i2 = 1, n1, 0)) + sum(iif(i2 = 1, 0, n1)) items, + sum(n2) summa, + sum(n3) summa_inv, + sum(n5) summa_r, + '~'||cast(substring(list(distinct i1, '~') from 1 for 20000) as varchar(20000)) sid_item2 + from session_edit + where id_session = :id_session and vid = :vid24 + group by 1), + total1 as ( + select id_item, summa, summa_inv, summa_r, + (select first 1 t.id_item from total t where t1.sid_item2 containing '~'||t.id_item||'~' and t.items <> 0 order by t.summa + t.summa_r desc) id_item2 + from total t1 + where items = 0 and (summa <> 0 or summa_inv <> 0 or summa_r <> 0)), + total2 as ( + select id_item2 id_item, summa, summa_inv, summa_r from total1 + where id_item2 is not null + union all + select id_item, -summa, -summa_inv, -summa_r from total1 + where id_item2 is not null) + select :id_session, :vid25, + id_item, + cast(null as numeric(12, 3)) items, + summa, + summa_inv n3, + summa_r n5, + cast(null as int) id_item2, + 3 i2 + from total2; + + insert into session_edit(id_session, vid, id_item, n1, n2, n3, n6, n7, n8, n9, n10, n11, n12, n13, n14) + with + total as ( + select s.id_item, + max(iif(s.i2 = 1, s.n1, 0)) + sum(iif(s.i2 = 1, 0, s.n1)) items, + sum(s.n2) summa, + sum(s.n3) summa_inv, + sum(s.n5) summa_r, + min(s9.n6) items_b, + min(s9.n7) summa_b, + min(s9.n8) items_prih, + min(s9.n9) summa_prih, + min(s9.n10) items_p_in, + min(s9.n16) items_t, + min(s9.n17) summa_t, + min(s9.n18) price_b, + min(s9.n19) items_end + from session_edit s + join session_edit s9 on s9.id_session = s.id_session and s.id_item = s9.id_item and s9.vid = :vid9 + where s.id_session = :id_session and s.vid in (:vid24, :vid25) + group by 1) + select :id_session, :vid20, + id_item, + cast(items as numeric(12,3)) n1, + cast(summa as numeric(12,2)) n2, + cast(summa_inv as numeric(12,2)) n3, + cast(summa_prih as numeric(12,2)) n6, + cast(items_prih as numeric(12,3)) n7, + cast(summa_b as numeric(12,2)) n8, + cast(items_b as numeric(12,3)) n9, + cast(summa_r as numeric(12,2)) n10, + cast(items_t as numeric(12,3)) n11, + cast(summa_t as numeric(12,2)) n12, + cast(price_b as numeric(12,4)) n13, + cast(items_end as numeric(12,3)) n14 + from total; + /* + merge into session_edit s + using (select s.id, i.group_id i2 from session_edit s + left join item i on i.id = s.id_item + where s.id_session = :id_session and s.vid in (:vid20, :vid23)) c on c.id = s.id + when matched then + update set i2 = c.i2, n4 = 0; + */ + -- Выравниваем сырье + for select sum(n2+n6+n7) summa, + sum(n6+n7) summa_inv + from session_edit + where id_session = :id_session and vid = :vid2 + into summa, summa1 do + for select sum(n2) summa, sum(n3) summa_inv + from session_edit + where id_session = :id_session and vid = :vid20 + into items, items1 do + update session_edit set + n2 = n2 + :summa - :items, + n3 = n3 + :summa1 - :items1 + where id_session = :id_session and vid = :vid20 + order by n2 desc + rows 1; + + -- распределение переменных Н/Р (пропорционально сумме сырья) + for select sum(n1) from session_edit + where id_session = :id_session and vid = :vid99 and i1 = 2 + having sum(n1) <> 0 + into summa0 do + begin + summa1 = 0; + select sum(n2) from session_edit where id_session = :id_session and vid = :vid20 and i2 = 2 + into summa1; + summa1 = nullif(summa1, 0); + + update session_edit set + n4 = cast(coalesce(1e0 * :summa0 * n2 / :summa1, 0) as numeric(12,2)) + where id_session = :id_session and vid in (:vid20, :vid23) and i2 = 2; + + summa2 = 0; + select sum(n4) from session_edit where id_session = :id_session and vid = :vid20 and i2 = 2 + into summa2; + + if (summa2 <> summa0) then + update session_edit set + n4 = n4 + :summa0 - :summa2 + where id_session = :id_session and vid = :vid20 and i2 = 2 + order by n4 desc + rows 1; + end + + update session_edit set + n4 = 0 + where id_session = :id_session and vid in (:vid20, :vid23) and i2 = 5; + + -- распределение Н/Р по изделиям (пропорционально выбранному виду) + for select iif(i1 = 3, 2, 1) vid, sum(n1) from session_edit + where id_session = :id_session and vid = :vid99 and n1 <> 0 and i1 in (0,1,3) + group by 1 + having sum(n1) <> 0 + into k, summa0 do + for select num from get_rows(3) + into n do + begin + summa1 = 0; + select sum(decode(:n, 1, n2, 2, n5, 3, n6)) from session_edit + where id_session = :id_session and vid = :vid10 + into summa1; + + type_v = (n-1)*2+k; + + if (summa1 <> 0) then + insert into session_edit(id_session, vid, id_item, i1, n1) + select id_session, :vid11, id_item, :type_v, cast(1e0*decode(:n, 1, n2, 2, n5, 3, n6)*:summa0/:summa1 as numeric(12,2)) + from session_edit + where id_session = :id_session and vid = :vid10; + + summa2 = 0; + select sum(n1) from session_edit where id_session = :id_session and vid = :vid11 and i1 = :type_v + into summa2; + + if (summa2 <> summa0) then + update session_edit set + n1 = n1 + :summa0 - :summa2 + where id_session = :id_session and vid = :vid11 and i1 = :type_v + order by n1 desc + rows 1; + end + + -- Распределение Н/р по ГИ + merge into session_edit s + using (select id_item, + sum(iif(i1 = 1, n1, 0)) n7, + sum(iif(i1 = 2, n1, 0)) n8, + sum(iif(i1 = 3, n1, 0)) n9, + sum(iif(i1 = 4, n1, 0)) n10, + sum(iif(i1 = 5, n1, 0)) n11, + sum(iif(i1 = 6, n1, 0)) n12 + from session_edit + where id_session = :id_session and vid = :vid11 + group by 1) c on s.id_session = :id_session and s.id_item = c.id_item and s.vid = :vid10 + when matched then + update set n7 = c.n7, + n8 = c.n8, + n9 = c.n9, + n10 = c.n10, + n11 = c.n11, + n12 = c.n12; + + -- Расчет остатка на конец + if (ost = 1) then + begin + for select s.id_item, + s23.n1 items, + s.n1-s23.n1 items_r, + s.n1, + s.n7 items_prih, + s.n9 items_b, + s.n14 items_end, + s12.n2 summa_end, + s.id + from session_edit s + left join session_edit s23 on s23.id_session = s.id_session and s23.id_item = s.id_item and s23.vid = :vid23 + left join session_edit s12 on s12.id_session = s.id_session and s12.id_item = s.id_item and s12.vid = :vid12 + where s.id_session = :id_session and s.vid = :vid20 + into id_item, items, items4, items5, items1, items0, items2, summa, id0 do + begin + items3 = maxvalue(items2, 0); + + if (items3 = 0) then + begin + items = 0; + items4 = 0; + end else + begin + items5 = minvalue(items3, items5); + items3 = items3 - items5; + + if (items5 <> items + items4) then + begin + items = maxvalue(minvalue(items5, items), 0); + items4 = items5 - items; + end + end + + items1 = maxvalue(minvalue(items3, items1), 0); + items3 = items3 - items1; + + items0 = maxvalue(minvalue(items3, items0), 0); + items3 = items3 - items0; + + merge into session_edit s + using (select s.id, :items2 items_end, + cast(coalesce(:summa, + coalesce(1e0 * :items * (s23.n2 + s23.n4) / nullif(s23.n1, 0), 0) + + coalesce(1e0 * :items4 * (s23.n2 + s23.n4 - s.n2 - s.n10 - s.n4) / nullif(s23.n1 - s.n1, 0), 0) + + coalesce(1e0 * :items1 * s.n6 / nullif(s.n7, 0), 0) + + coalesce(1e0 * :items0 * s.n8 / nullif(s.n9, 0), 0) + + coalesce(1e0 * :items3 * s.n13, 0)) as numeric(12,2)) summa_end + from session_edit s + left join session_edit s23 on s23.id_session = s.id_session and s23.id_item = s.id_item and s23.vid = :vid23 + where s.id = :id0) c on c.id = s.id + when matched then + update set + n14 = items_end, + n15 = summa_end; + end + end else + update session_edit set + n14 = 0, + n15 = 0 + where id_session = :id_session and vid = :vid20; + + suspend; + end + ^ + set term ;^ + commit; + + set heading off; + select 'Completed successfully.' from rdb$database; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Completed successfully. + """ + +@pytest.mark.version('>=3.0.5') +def test_core_6086_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6087.py b/tests/bugs/test_core_6087.py new file mode 100644 index 00000000..1f5c4f66 --- /dev/null +++ b/tests/bugs/test_core_6087.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_6087 +# title: Problem with casting within UNION +# decription: +# Confirmed bug on WI-T4.0.0.1533. +# Checked on 4.0.0.1534: OK, 1.465s. +# +# tracker_id: CORE-6087 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select cast(0.1234 as int) as result from rdb$database + union all + select cast(0.1234 as numeric(18,4)) from rdb$database + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT 0.0000 + RESULT 0.1234 + """ + +@pytest.mark.version('>=4.0') +def test_core_6087_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6088.py b/tests/bugs/test_core_6088.py new file mode 100644 index 00000000..02458c28 --- /dev/null +++ b/tests/bugs/test_core_6088.py @@ -0,0 +1,80 @@ +#coding:utf-8 +# +# id: bugs.core_6088 +# title: "SIMILAR TO" hangs when processing parenthesis +# decription: +# Confirmed normal work (evaluation for less than 5 ms) on WI-T4.0.0.1598 +# 31.12.2020: increased max duration threshold from 100 to 150 ms. +# +# tracker_id: CORE-6088 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + + set term ^; + execute block as + begin + rdb$set_context( 'USER_SESSION','DTS_START', cast('now' as timestamp) ); + rdb$set_context( 'USER_SESSION','MAX_THRESHOLD_MS', 150 ); + -- ^ + -- | + -- ############################# + -- MAX ALLOWED EXECUTION TIME,MS + -- ############################# + end + ^ + set term ;^ + + + select 1 as result from RDB$DATABASE + where 'a-b c(d)' + similar to '[[:WHITESPACE:]a-z\\-]{0,199}' escape '\\' + -- ^ + -- | + -- ATTENTION: TWO BACKSLASHES MUST BE HERE WHEN USE FBT_RUN TO CHECK + -- ############### + ; + + set count off; + select + iif( evaluated_ms <= max_allowed_ms + ,'acceptable' + ,'TOO LONG: ' || evaluated_ms || ' ms - this is more then threshold = ' || max_allowed_ms || ' ms' + ) as duration + from ( + select + datediff( millisecond from cast(rdb$get_context( 'USER_SESSION','DTS_START') as timestamp) to current_timestamp ) evaluated_ms + ,cast( rdb$get_context( 'USER_SESSION','MAX_THRESHOLD_MS' ) as int ) as max_allowed_ms + from rdb$database + ); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + DURATION acceptable + """ + +@pytest.mark.version('>=4.0') +def test_core_6088_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6089.py b/tests/bugs/test_core_6089.py new file mode 100644 index 00000000..b041d080 --- /dev/null +++ b/tests/bugs/test_core_6089.py @@ -0,0 +1,142 @@ +#coding:utf-8 +# +# id: bugs.core_6089 +# title: BLOBs are unnecessarily copied during UPDATE after a table format change +# decription: +# It's not easy to obtain BLOB_ID using only fdb. Rather in ISQL blob_id will be shown always (even if we do not want this :)). +# This test runs ISQL with commands that were provided in the ticket and parses its result by extracting only column BLOB_ID. +# Each BLOB_ID is added to set(), so eventually we can get total number of UNIQUE blob IDs that were generated during test. +# This number must be equal to number of records in the table (three in this test). +# +# Confirmed bug on: 4.0.0.1535; 3.0.5.33142. +# Works fine on: +# 4.0.0.1556: OK, 3.384s. +# 3.0.5.33152: OK, 2.617s. +# +# +# tracker_id: CORE-6089 +# min_versions: ['3.0.5'] +# versions: 3.0.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import re +# import subprocess +# import time +# import fdb +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# allowed_patterns = ( re.compile('COL2_BLOB_ID\\s+\\S+', re.IGNORECASE), ) +# +# sql_txt=''' +# set bail on; +# set list on; +# set blob off; +# recreate table t (col1 int, col2 blob); +# recreate view v as select col2 as col2_blob_id from t; -- NB: alias for column have to be matched to re.compile() argument +# commit; +# +# insert into t values (1, '1'); +# insert into t values (2, '2'); +# insert into t values (3, '3'); +# commit; +# +# select v.* from v; +# update t set col1 = -col1; +# select v.* from v; +# +# +# rollback; +# alter table t add col3 date; +# select v.* from v; +# update t set col1 = -col1; +# select v.* from v; -- bug was here +# quit; +# ''' +# +# f_isql_cmd=open( os.path.join(context['temp_directory'],'tmp_6089.sql'), 'w') +# f_isql_cmd.write( sql_txt ) +# flush_and_close( f_isql_cmd ) +# +# f_isql_log=open( os.path.join(context['temp_directory'],'tmp_6089.log'), 'w') +# +# subprocess.call([context['isql_path'], dsn, "-q", "-i", f_isql_cmd.name], stdout=f_isql_log, stderr=subprocess.STDOUT) +# flush_and_close( f_isql_log ) +# +# blob_id_set=set() +# with open( f_isql_log.name,'r') as f: +# for line in f: +# match2some = filter( None, [ p.search(line) for p in allowed_patterns ] ) +# if match2some: +# blob_id_set.add( line.split()[1] ) +# +# print( 'Number of unique blob IDs: ' + str(len(blob_id_set)) ) +# +# # Cleanup. +# ########## +# cleanup( (f_isql_cmd, f_isql_log) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Number of unique blob IDs: 3 + """ + +@pytest.mark.version('>=3.0.5') +@pytest.mark.xfail +def test_core_6089_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6090.py b/tests/bugs/test_core_6090.py new file mode 100644 index 00000000..0c25e1c4 --- /dev/null +++ b/tests/bugs/test_core_6090.py @@ -0,0 +1,164 @@ +#coding:utf-8 +# +# id: bugs.core_6090 +# title: BLOB fields may be suddenly set to NULLs during UPDATE after a table format change +# decription: +# It's not easy to obtain BLOB_ID using only fdb. Rather in ISQL blob_id will be shown always (even if we do not want this :)). +# This test runs ISQL with commands that were provided in the ticket and parses its result by extracting only column BLOB_ID. +# Each BLOB_ID is added to set(), so eventually we can get total number of UNIQUE blob IDs that were generated during test. +# This number must be equal to number of records in the table (three in this test). +# Beside of this, we check that all blobs are not null, see 'null_blob_cnt' counter. +# +# Confirmed bug on: 4.0.0.1535; 3.0.5.33142. +# Works fine on: +# 4.0.0.1556: OK, 3.342s. +# 3.0.5.33152: OK, 2.652s. +# +# tracker_id: CORE-6090 +# min_versions: ['3.0.5'] +# versions: 3.0.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import re +# import subprocess +# import time +# import fdb +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# allowed_patterns = ( re.compile('BLOB_ID\\s+\\S+', re.IGNORECASE), ) +# +# sql_txt=''' +# set bail on; +# set blob all; +# set list on; +# +# recreate view v as select 1 x from rdb$database; +# commit; +# recreate table test (n1 int, n2 int, n3 int, blob_id blob); +# recreate view v as select blob_id from test; +# commit; +# +# insert into test values (0, 0, null, '0:foo'); +# insert into test values (1, 1, 1, '1:rio'); +# insert into test values (2, 2, 2, '2:bar'); +# commit; +# +# select 1 as point, v.* from v; +# +# update test set n1 = 1 where n2 >= 0; -- n1 should be set to 1 in all three rows +# select 2 as point, v.* from v; +# rollback; +# +# update test set n1 = 1 where n2 >= 0 and n3 >= 0; -- n1 should be set to 1 in 2nd and 3rd rows +# select 3 as point, v.* from v; +# rollback; +# +# alter table test add col5 date; +# commit; +# +# update test set n1 = 1 where n2 >= 0; -- n1 should be set to 1 in all three rows +# select 4 as point, v.* from v; -- Here blob_id were changed because of other bug, see CORE-6089, but contents is correct +# rollback; +# +# update test set n1 = 1 where n2 >= 0 and n3 >= 0; +# -- n1 should be set to 1 in 2nd and 3rd rows +# select 5 as point, v.* from v; -- BUG: BLOB_ID in the second row was nullified!!! +# +# quit; +# ''' +# +# f_isql_cmd=open( os.path.join(context['temp_directory'],'tmp_6090.sql'), 'w') +# f_isql_cmd.write( sql_txt ) +# flush_and_close( f_isql_cmd ) +# +# f_isql_log=open( os.path.join(context['temp_directory'],'tmp_6090.log'), 'w') +# +# subprocess.call([context['isql_path'], dsn, "-q", "-i", f_isql_cmd.name], stdout=f_isql_log, stderr=subprocess.STDOUT) +# flush_and_close( f_isql_log ) +# +# blob_id_set=set() +# null_blob_cnt=0 +# with open( f_isql_log.name,'r') as f: +# for line in f: +# match2some = filter( None, [ p.search(line) for p in allowed_patterns ] ) +# if match2some: +# blob_id_set.add( line.split()[1] ) +# if '' in line.lower(): +# null_blob_cnt += 1 +# +# print( 'Number of unique blob IDs: ' + str(len(blob_id_set)) ) +# print( 'Number of nullified blobs: ' + str(null_blob_cnt) ) +# +# # Cleanup. +# ########## +# time.sleep(1) +# cleanup( (f_isql_cmd, f_isql_log) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Number of unique blob IDs: 3 + Number of nullified blobs: 0 + """ + +@pytest.mark.version('>=3.0.5') +@pytest.mark.xfail +def test_core_6090_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6095.py b/tests/bugs/test_core_6095.py new file mode 100644 index 00000000..e784c90f --- /dev/null +++ b/tests/bugs/test_core_6095.py @@ -0,0 +1,273 @@ +#coding:utf-8 +# +# id: bugs.core_6095 +# title: Extend trace record for COMMIT/ROLLBACK RETAINING to allow chaining of transaction ids +# decription: +# Test prepares trace config with requrement to watch only for TRANSACTION events. +# Then it starts trace session and makes several changes withing retained Tx. +# (this is done by invocation con.commit() method with argument 'retaining = True'). +# +# Every COMMIT_RETAINING event in the trace log must contain following *new* elements: +# 1) "INIT_" token with ID of transaction that originated changes; it must be shown in the same line with "TRA_" info; +# 2) "New number " - ID that will be assigned to the next transaction in this 'chain'; it must be shown in separate line. +# +# All lines containing "INIT_" must have the same value of transaction that started changes but this value itself can depend +# on FB major version and (maybe) of server mode: CS / SC /SS. For this reason we must save this number as special 'base' that +# will be subtracted from concrete values during parsing of trace lines - see 'tx_base' variable here. +# +# We parse trace log and pay attention for lines like: "(TRA_nnn, INIT_mmm, ..." and "New number ". +# Each interesting numbers are extracted from these lines and is subtracted from them. +# Finally, we display resulting values. +# 1) number after phrase "Tx that is origin of changes:" must always be equal to zero; +# 2) number after phrase "Tx that finished now" must be: +# 2.1) LESS for 1 than value in the next line: "NEW NUMBER" for subsequent Tx..." - for all DML statements EXCEPT LAST; +# 2.2) EQUALS to "NEW NUMBER" for subsequent Tx..." for LAST statement because it does not change anything (updates empty table); +# +# Checked on 4.0.0.1784 SS: 6.327s; 3.0.6.33255 SS: 5.039s. +# +# tracker_id: CORE-6095 +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create sequence g; + create table test(id int primary key, x int); + set term ^; + create trigger test_bi for test active before insert position 0 as + begin + new.id = coalesce(new.id, gen_id(g, 1) ); + end + ^ + create procedure sp_worker(a_x int) as + begin + insert into test(x) values(:a_x); + end + ^ + set term ;^ + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import re +# import time +# import subprocess +# from subprocess import Popen +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# fdb_name = os.path.split(db_conn.database_name)[1] +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# # Prepare config for trace session that will be launched: +# ######################################################### +# txt = ''' +# database= %%[\\\\\\\\/]%(fdb_name)s +# { +# enabled = true +# log_initfini = false +# time_threshold = 0 +# log_transactions = true +# } +# ''' % locals() +# +# trc_cfg=open( os.path.join(context['temp_directory'],'tmp_trace_6095.cfg'), 'w') +# trc_cfg.write(txt) +# flush_and_close( trc_cfg ) +# +# # Async. launch of trace session using FBSVCMGR action_trace_start: +# ################################################################### +# trc_log=open( os.path.join(context['temp_directory'],'tmp_trace_6095.log'), 'w', buffering = 0) +# # Execute a child program in a new process, redirecting STDERR to the same target as of STDOUT: +# p_svcmgr = Popen( [ context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_start", +# "trc_cfg", trc_cfg.name +# ], +# stdout=trc_log, +# stderr=subprocess.STDOUT +# ) +# +# # 08.01.2020. This delay is mandatory, otherwise file with trace session info can remain (sometimes) +# # empty when we will read it at the next step: +# time.sleep(1) +# +# # Determine active trace session ID (for further stop): +# ####################################################### +# trc_lst=open( os.path.join(context['temp_directory'],'tmp_trace_6095.lst'), 'w', buffering = 0) +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_list"], +# stdout=trc_lst, stderr=subprocess.STDOUT +# ) +# flush_and_close( trc_lst ) +# +# # Session ID: 5 +# # user: +# # date: 2015-08-27 15:24:14 +# # flags: active, trace +# +# sid_pattern = re.compile('Session\\s+ID[:]{0,1}\\s+\\d+', re.IGNORECASE) +# +# trc_ssn=0 +# with open( trc_lst.name,'r') as f: +# for line in f: +# if sid_pattern.search( line ) and len( line.split() ) == 3: +# trc_ssn = line.split()[2] +# break +# +# # Result: `trc_ssn` is ID of active trace session. +# # We have to terminate trace session that is running on server BEFORE we termitane process `p_svcmgr` +# +# if trc_ssn==0: +# print("Error parsing trace session ID.") +# +# else: +# +# ########### W O R K W I T H D A T A B A S E ######## +# +# con = fdb.connect( dsn = dsn ) +# cur = con.cursor() +# +# con.execute_immediate( 'insert into test(x) values(123)' ) +# con.commit( retaining = True ) # (TRA_12, ... ; next line: "New number 13" +# +# cur.callproc( 'sp_worker', (456,) ) # (TRA_13, INIT_12, ... +# con.commit( retaining = True ) # (TRA_13, INIT_12, ... ; next line: "New number 14" +# +# con.execute_immediate( 'delete from test' ) # (TRA_14, INIT_12, ... +# con.commit( retaining = True ) # (TRA_14, INIT_12, ... ; next line: "New number 15" +# +# # This statement does not change anything: +# con.execute_immediate( 'update test set x = -x' ) # (TRA_15, INIT_12, ... +# con.commit( retaining = True ) # (TRA_15, INIT_12, ... ; next line: "New number 15" -- THE SAME AS PREVIOUS! +# +# cur.close() +# ##################################################################### +# +# # ::: NB ::: Here we have to be idle at least 2s (two seconds) otherwise trace log will +# # not contain some or all of messages about create DB, start Tx, ES, Tx and drop DB. +# # See also discussion with hvlad, 08.01.2020 15:16 +# # (subj: "action_trace_stop does not flush trace log (fully or partially)") +# time.sleep(2) +# +# # Stop trace session: +# ##################### +# +# trc_lst=open(trc_lst.name, "a") +# trc_lst.seek(0,2) +# +# subprocess.call( [ context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_trace_stop", +# "trc_id",trc_ssn +# ], +# stdout=trc_lst, +# stderr=subprocess.STDOUT +# ) +# flush_and_close( trc_lst ) +# +# p_svcmgr.terminate() +# +# +# allowed_patterns = [ +# re.compile('\\s*\\(TRA_\\d+,', re.IGNORECASE) +# ,re.compile('\\s*New\\s+number\\s+\\d+\\s*', re.IGNORECASE) +# ] +# +# tx_base = -1 +# with open( trc_log.name,'r') as f: +# for line in f: +# if line.rstrip().split(): +# for p in allowed_patterns: +# if p.search(line): +# if '(TRA_' in line: +# words = line.replace(',',' ').replace('_',' ').replace('(',' ').split() +# # Result: +# # 1) for tx WITHOUT retaining: ['TRA', '12', 'READ', 'COMMITTED', '|', 'REC', 'VERSION', '|', 'WAIT', '|', 'READ', 'WRITE)'] +# # 2) for tx which is RETAINED: ['TRA', '13', 'INIT', '12', 'READ', 'COMMITTED', '|', 'REC', 'VERSION', '|', 'WAIT', '|', 'READ', 'WRITE)'] +# # 0 1 2 3 +# +# tx_base = int(words[1]) if tx_base == -1 else tx_base +# +# if words[2] == 'INIT': +# tx_origin_of_changes = int(words[3]) - tx_base +# tx_that_finished_now = int(words[1]) - tx_base +# print('Found "INIT_" token in "TRA_" record. Tx that is origin of changes: ', tx_origin_of_changes, '; Tx that finished now:', tx_that_finished_now) +# elif 'number' in line: +# tx_for_subsequent_changes = int(line.split()[2]) - tx_base # New number 15 --> 15 +# print('Found record with "NEW NUMBER" for subsequent Tx numbers: ', tx_for_subsequent_changes) +# +# +# #< cond "if trc_ssn>0" +# flush_and_close( trc_log ) +# +# +# # cleanup: +# ########## +# time.sleep(1) +# cleanup( (trc_lst, trc_cfg, trc_log) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Found record with "NEW NUMBER" for subsequent Tx numbers: 1 + Found "INIT_" token in "TRA_" record. Tx that is origin of changes: 0 ; Tx that finished now: 1 + Found record with "NEW NUMBER" for subsequent Tx numbers: 2 + Found "INIT_" token in "TRA_" record. Tx that is origin of changes: 0 ; Tx that finished now: 2 + Found record with "NEW NUMBER" for subsequent Tx numbers: 3 + Found "INIT_" token in "TRA_" record. Tx that is origin of changes: 0 ; Tx that finished now: 3 + Found record with "NEW NUMBER" for subsequent Tx numbers: 3 + """ + +@pytest.mark.version('>=3.0.6') +@pytest.mark.xfail +def test_core_6095_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6097.py b/tests/bugs/test_core_6097.py new file mode 100644 index 00000000..d056b3f5 --- /dev/null +++ b/tests/bugs/test_core_6097.py @@ -0,0 +1,141 @@ +#coding:utf-8 +# +# id: bugs.core_6097 +# title: Connection does not see itself in the MON$ATTACHMENTS when Domain/Username (using SSPI) is 31 bytes long +# decription: +# Could not reproduce bug on WI-V3.0.4.33054, discussed this with dimitr and alex. +# Problem can appear randomly when some byte in memory contains value not equal to 0x0. +# It was decided to implement test that +# * adds user with name of 31 octets (15 non-ascii, plus 1 ascii character: "Ковалевский_Олег"); +# * launches ISQL utility as separate process with trying to connect do test DB using this non-ascii login; +# * count record in mon$attachments table that belongs to current attachment. Result must be: 1. +# ::: NB ::: +# As of fdb 2.0.1 and fbtest 1.0.7, there is NO ability to run macros runProgram() with specifying non-ascii user name +# in its parameters list: errror 'invalid user/password' will raise in this case. The same error will be raised if we +# try to launch isql directly in subprocess.call(). For this reason it was decided to create temporary BATCH file (.bat) +# that contains necessary command to run isql.exe, i.e. we actually invoke new instance of cmd.exe. +# The reason of why 'invalid user/password' raises (in other cases) remains unclear for me. +# Checked on: +# 4.0.0.1564: OK, 3.910s. +# 4.0.0.1535: OK, 4.052s. +# 3.0.5.33160: OK, 1.971s. +# 3.0.5.33152: OK, 3.860s. +# +# tracker_id: CORE-6097 +# min_versions: ['3.0.5'] +# versions: 3.0.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import time +# import fdb +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.close() +# +# fb_home = services.connect(host='localhost', user= user_name, password= user_password).get_home_directory() +# +# sql_txt=''' +# -- fb_home = %s +# set bail on; +# set count on; +# set list on; +# create or alter user "Ковалевский_Олег" password '123' using plugin Srp; +# commit; +# set list on; +# select sec$user_name, octet_length(trim(sec$user_name)) as octets_in_name from sec$users where sec$user_name = 'Ковалевский_Олег'; +# commit; +# ''' % (fb_home,) +# +# f_init_sql=open( os.path.join(context['temp_directory'],'tmp_6097_prepare.sql'), 'w') +# f_init_sql.write( sql_txt ) +# f_init_sql.close() +# +# f_init_log=open( os.path.join(context['temp_directory'],'tmp_6097_prepare.log'), 'w') +# +# subprocess.call([ fb_home+"isql", dsn, "-q", "-ch", "utf8", "-i", f_init_sql.name], stdout=f_init_log, stderr=subprocess.STDOUT) +# f_init_log.close() +# +# # does not work, raises 'invalid user/password': +# #runProgram( fb_home+'isql', [dsn, "-q", "-user", "Ковалевский_Олег", "-pas", "123" ], 'set list on; set count on; select * from mon$attachments where mon$attachment_id = current_connection;') +# +# f_check_sql=open( os.path.join(context['temp_directory'],'tmp_6097_check.sql'), 'w') +# #f_check_sql.write( 'set list on; select count(*) as "Can_i_see_myself ?" from mon$attachments where mon$attachment_id = current_connection;' ) +# f_check_sql.write( 'set count on; set list on; select mon$user as who_am_i, left(mon$remote_protocol,3) as mon_protocol, mon$auth_method as mon_auth_method from mon$attachments where mon$attachment_id = current_connection;' ) +# f_check_sql.close() +# +# f_bat_text=''' +# @echo off +# chcp 65001 1>nul +# %s %s -user "Ковалевский_Олег" -pas 123 -ch utf8 -q -i %s +# ''' % ( fb_home+'isql.exe', dsn, f_check_sql.name ) +# #''' % ( fb_home+'isql.exe', 'localhost:employee', f_check_sql.name ) +# +# f_check_bat=open( os.path.join(context['temp_directory'],'tmp_6097_check.bat'), 'w') +# f_check_bat.write( f_bat_text ) +# f_check_bat.close() +# +# f_check_log=open( os.path.join(context['temp_directory'],'tmp_6097_check.log'), 'w') +# # does not work, raises 'invalid user/password': subprocess.call(["isql", dsn, "-q", "-user", "Ковалевский_Олег", "-pas", "123", "-ch", "utf8", "-i", f_check_sql.name], stdout=f_run_log, stderr=subprocess.STDOUT) +# subprocess.call([f_check_bat.name], stdout=f_check_log, stderr=subprocess.STDOUT) +# f_check_log.close() +# +# # Let redirected output of isql be flushed on disk: +# time.sleep(1) +# +# with open( f_init_log.name,'r') as f: +# for line in f: +# print(line) +# +# with open( f_check_log.name,'r') as f: +# for line in f: +# print(line) +# +# # Cleanup. +# ########## +# +# f_list = (f_init_sql, f_init_log, f_check_sql, f_check_bat, f_check_log) +# for i in range(len(f_list)): +# if os.path.isfile(f_list[i].name): +# os.remove(f_list[i].name) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + SEC$USER_NAME Ковалевский_Олег + OCTETS_IN_NAME 31 + Records affected: 1 + + WHO_AM_I Ковалевский_Олег + MON_PROTOCOL TCP + MON_AUTH_METHOD Srp + Records affected: 1 + """ + +@pytest.mark.version('>=3.0.5') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_6097_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6108.py b/tests/bugs/test_core_6108.py new file mode 100644 index 00000000..b95f175a --- /dev/null +++ b/tests/bugs/test_core_6108.py @@ -0,0 +1,61 @@ +#coding:utf-8 +# +# id: bugs.core_6108 +# title: Regression: FB3 throws "Datatypes are not comparable in expression" in procedure parameters +# decription: +# Confirmed bug on 4.0.0.1567; 3.0.5.33160. +# Works fine on 4.0.0.1573; 3.0.x is still affected +# +# tracker_id: CORE-6108 +# min_versions: ['2.5'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# proc_ddl=''' +# create or alter procedure test_proc ( a_dts timestamp) returns ( o_dts timestamp) as +# begin +# o_dts = a_dts; +# suspend; +# end +# ''' +# +# db_conn.execute_immediate( proc_ddl ) +# db_conn.commit() +# +# cur=db_conn.cursor() +# +# sttm="select o_dts from test_proc('2019-'|| COALESCE( ?, 1) ||'-01' )" +# cur.execute( sttm, ( 3, ) ) +# for r in cur: +# print(r[0]) +# cur.close() +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 2019-03-01 00:00:00 + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_core_6108_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6109.py b/tests/bugs/test_core_6109.py new file mode 100644 index 00000000..897f24a6 --- /dev/null +++ b/tests/bugs/test_core_6109.py @@ -0,0 +1,56 @@ +#coding:utf-8 +# +# id: bugs.core_6109 +# title: Changing FLOAT to a SQL standard compliant FLOAT datatype +# decription: +# Checked on 4.0.0.1763 SS: 1.453s. +# +# tracker_id: CORE-6109 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('^((?!(sqltype)).)*$', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test( + r real + ,f float + ,f01 float( 1) + ,f24 float(24) + ,f25 float(25) + ,f53 float(53) + ); + + set list on; + set sqlda_display on; + select * from test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 01: sqltype: 482 FLOAT Nullable scale: 0 subtype: 0 len: 4 + 02: sqltype: 482 FLOAT Nullable scale: 0 subtype: 0 len: 4 + 03: sqltype: 482 FLOAT Nullable scale: 0 subtype: 0 len: 4 + 04: sqltype: 482 FLOAT Nullable scale: 0 subtype: 0 len: 4 + 05: sqltype: 480 DOUBLE Nullable scale: 0 subtype: 0 len: 8 + 06: sqltype: 480 DOUBLE Nullable scale: 0 subtype: 0 len: 8 + """ + +@pytest.mark.version('>=4.0') +def test_core_6109_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6116.py b/tests/bugs/test_core_6116.py new file mode 100644 index 00000000..19abbac3 --- /dev/null +++ b/tests/bugs/test_core_6116.py @@ -0,0 +1,125 @@ +#coding:utf-8 +# +# id: bugs.core_6116 +# title: The Metadata script extracted using ISQL of a database restored from a Firebird 2.5.9 Backup is invalid/incorrect when table has COMPUTED BY field +# decription: +# Test uses backup of preliminary created database in FB 2.5.9, DDL is the same as in the ticket. +# This .fbk is restored and we launch ISQL -X in order to get metadata. Then we check that two +# in this script with "COMPUTED BY" phrase contain non zero number as width of this field: +# 1) line that belongs to CREATE TABLE statement: +# FULL_NAME VARCHAR(100) ... COMPUTED BY ... +# 2) line with ALTER COLUMN statement: +# ALTER FULL_NAME TYPE VARCHAR(100) ... COMPUTED BY ... +# +# Confirmed bug on: 4.0.0.1723; 3.0.5.33225: found "VARCHAR(0)" in above mentioned lines. +# Checked on: 4.0.0.1737; 3.0.6.33236 - works fine. +# +# tracker_id: CORE-6116 +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core6116-25.fbk', init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import subprocess +# import re +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# f_metadata_sql=open( os.path.join(context['temp_directory'],'tmp_meta_6116.sql'), 'w') +# subprocess.call([ context['isql_path'], '-x', dsn ], stdout=f_metadata_sql, stderr=subprocess.STDOUT) +# flush_and_close( f_metadata_sql ) +# +# # FULL_NAME VARCHAR(0) CHARACTER SET WIN1252 COMPUTED BY +# comp_field_initial_ptn = re.compile( 'FULL_NAME\\s+VARCHAR\\(\\d+\\).*COMPUTED BY', re.IGNORECASE ) +# comp_field_altered_ptn = re.compile( 'ALTER\\s+FULL_NAME\\s+TYPE\\s+VARCHAR\\(\\d+\\).*COMPUTED BY', re.IGNORECASE ) +# +# # CREATE TABLE statement must contain line: +# # FULL_NAME VARCHAR(100) CHARACTER SET WIN1252 COMPUTED BY (CAST(NULL AS VARCHAR(1) CHARACTER SET WIN1252) COLLATE WIN_PTBR), +# # ALTER FULL_NAME statement must contain line: +# # ALTER FULL_NAME TYPE VARCHAR(100) CHARACTER SET WIN1252 COMPUTED BY ((first_name || ' ' || last_name || ' (' || user_name || ')') collate win_ptbr); +# +# +# # This should be empty: +# with open( f_metadata_sql.name,'r') as f: +# for line in f: +# if comp_field_initial_ptn.search(line): +# words = line.replace('(',' ').replace(')',' ').split() # ['FULL_NAME', 'VARCHAR', '0', ... , 'COMPUTED', 'BY'] +# print( 'Length in "CREATE TABLE" statement: ' + words[2] ) +# +# if comp_field_altered_ptn.search(line): +# words = line.replace('(',' ').replace(')',' ').split() # ['ALTER', 'FULL_NAME', 'TYPE', 'VARCHAR', '0', ... , 'COMPUTED', 'BY'] +# print( 'Length in "ALTER COLUMN" statement: ' + words[4] ) +# +# # cleanup: +# ########## +# time.sleep(1) +# cleanup( (f_metadata_sql,) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Length in "CREATE TABLE" statement: 100 + Length in "ALTER COLUMN" statement: 100 + """ + +@pytest.mark.version('>=3.0.6') +@pytest.mark.xfail +def test_core_6116_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6134.py b/tests/bugs/test_core_6134.py new file mode 100644 index 00000000..80f7023a --- /dev/null +++ b/tests/bugs/test_core_6134.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: bugs.core_6134 +# title: Win_Sspi in the list of auth plugins leads message about failed login to be changed (from 'Your user name and password are not defined...' to 'Missing security context ...') +# decription: +# Test assumes that firebird.conf parameter AuthClient is: Legacy_Auth,Srp,Win_Sspi. +# This is done automaticaally by script that is launched daily on Firebird test machine. +# Checked on: 4.0.0.1598, WI-V3.0.5.33168 -- all fine. +# +# tracker_id: CORE-6134 +# min_versions: ['3.0.5'] +# versions: 3.0.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [('-At block line: [\\d]+, col: [\\d]+', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + set term ^; + execute block returns (whoami varchar(32)) as + begin + execute statement 'select current_user from rdb$database' + as user 'SYSDBA' + password 'ful1yWr0ng' -- or use here some other password that is for sure invalid + into whoami; + suspend; + end + ^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 28000 + Your user name and password are not defined. Ask your database administrator to set up a Firebird login. + """ + +@pytest.mark.version('>=3.0.5') +def test_core_6134_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_6137.py b/tests/bugs/test_core_6137.py new file mode 100644 index 00000000..0819565f --- /dev/null +++ b/tests/bugs/test_core_6137.py @@ -0,0 +1,66 @@ +#coding:utf-8 +# +# id: bugs.core_6137 +# title: Server crashes when it run SQL +# decription: +# Confirmed bug on: 4.0.0.1573, 3.0.5.33166 +# (got in firebird.log: "internal Firebird consistency check (invalid SEND request (167), file: JrdStatement.cpp line: 327)") +# +# Checked on: 4.0.0.1575: OK, 1.834s; 3.0.5.33168: OK, 0.916s. +# Checked on: 2.5.9.27142 (10.09.2019), but previous snapshot 2.5.9.27139 (03.06.2019) also worked fine - without bugcheck. +# +# tracker_id: CORE-6137 +# min_versions: ['2.5.9'] +# versions: 2.5.9 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.9 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table tmp_labelbarcode ( + id integer not null, + barcode char(20) not null, + idlabel integer not null + ); + + alter table tmp_labelbarcode add primary key (id); + create index tmlb_barcode on tmp_labelbarcode (barcode); + create index tmlb_idlabel on tmp_labelbarcode (idlabel); + create unique index tmp_labelbarcode_idx1 on tmp_labelbarcode (barcode, idlabel); + commit; + + insert into tmp_labelbarcode (id, barcode, idlabel) values (224423, '4627136039368', 278164); + commit; + + set count on; + --set echo on; + + select tmp_labelbarcode.BARCODE + from tmp_labelbarcode + where tmp_labelbarcode.BARCODE = '462713603936820000004620016596753' + order by tmp_labelbarcode.BARCODE + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ + +@pytest.mark.version('>=2.5.9') +def test_core_6137_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6138.py b/tests/bugs/test_core_6138.py new file mode 100644 index 00000000..847086de --- /dev/null +++ b/tests/bugs/test_core_6138.py @@ -0,0 +1,100 @@ +#coding:utf-8 +# +# id: bugs.core_6138 +# title: Inconsistent behavior regarding visibility of master record on detail inserts +# decription: +# Confirmed bug on: 3.0.5.33152 (built 14.09.19), 4.0.0.1598 (built 08.09.19): +# no error raised when second attach tried to insert record into child table +# after first attach did commit (but main record was not visible to 2nd attach +# because of SNAPSHOT isolation level). +# +# Works fine on: +# 4.0.0.1639 SS: 1.745s. +# 4.0.0.1633 CS: 2.266s. +# 3.0.5.33183 SS: 1.265s. +# 3.0.5.33178 CS: 1.611s. +# +# tracker_id: CORE-6138 +# min_versions: ['3.0.5'] +# versions: 3.0.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.close() +# +# custom_tpb = fdb.TPB() +# custom_tpb.isolation_level = fdb.isc_tpb_concurrency +# custom_tpb.lock_resolution = fdb.isc_tpb_nowait +# +# con1=fdb.connect( dsn = dsn ) +# con2=fdb.connect( dsn = dsn ) +# con2.begin( tpb = custom_tpb ) +# +# #print( 'FDB version: ' + fdb.__version__ ) +# #print( 'Firebird version: ' + con1.firebird_version ) +# +# con1.execute_immediate( 'create table a (id int primary key)' ) +# con1.execute_immediate( 'create table b (id int primary key, id_a int, constraint fk_b__a foreign key(id_a) references a(id) on update cascade on delete cascade)' ) +# con1.commit() +# +# con1.begin( tpb = custom_tpb ) +# cur1=con1.cursor() +# cur1.execute('insert into a(id) values( ? )', ( 1, ) ) +# +# con2.commit() +# con2.begin(tpb = custom_tpb ) +# cur2=con2.cursor() +# cur2.execute('select id from a') +# +# con1.commit() +# try: +# cur2.execute( 'insert into b (id, id_a) values (?, ?)', (1, 1,) ) +# print('UNEXPECTED SUCCESS: CHILD RECORD INSERTED W/O ERROR.') +# except Exception as e: +# +# print( ('EXPECTED: FK violation encountered.' if '335544466' in repr(e) else 'Unknown/unexpected exception.') ) +# +# # print( x for x in e ) # Python 3.x: TypeError: 'DatabaseError' object is not iterable +# # print( e[0] ) # Python 3.x: TypeError: 'DatabaseError' object is not subscriptable +# +# finally: +# cur2.close() +# +# con2.close() +# +# cur1.close() +# con1.close() +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + EXPECTED: FK violation encountered. + """ + +@pytest.mark.version('>=3.0.5') +@pytest.mark.xfail +def test_core_6138_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6141.py b/tests/bugs/test_core_6141.py new file mode 100644 index 00000000..c7c7a8d2 --- /dev/null +++ b/tests/bugs/test_core_6141.py @@ -0,0 +1,231 @@ +#coding:utf-8 +# +# id: bugs.core_6141 +# title: fbsvcmgr action_repair rpr_list_limbo_trans does not show list of transactions in LIMBO state +# decription: +# Test creates two databases with the same DDL (single table with single field): DBNAME_A, DBNAME_B. +# Then it makes instance of fdb.ConnectionGroup() for adding to it two connections (start distibuted work). +# First connection adds bulk of records, each in separate transaction. Second connection adds only one record. +# Number of separate transactions which are used for inserting records see in variable LIMBO_COUNT, +# and it must be not less then 150 (at least for the moment when this test is written: dec-2019). +# Then we change state of DBNAME_A to full shutdown, without doing commit or retain before this. +# Finally, we return this database state to online. +# Since that point header of DBNAME_A contains some data about limbo transactions. +# We make output of them using two ways: gfix -list and fbsvcmgr rpr_list_limbo_trans. +# Output should contain lines with ID of transactions in limbo state. +# NOTE: NOT ALL TRANSACTIONS CAN BE SHOWN BECAUSE THEIR LIST CAN BE EXTREMELY LONG. +# We count number of lines with limbo info using regexp and check that number of these lines equal to expected, +# ignoring concrete values of transaction IDs. +# +# NB-1. +# Output from gfix and fbsvcmgr differs, see pattern_for_limbo_in_gfix_output and pattern_for_limbo_in_fsvc_output. +# +# NB-2. +# Only 'gfix -list' produces output which final row is: "More limbo transactions than fit. Try again". +# No such message in the output of fbsvcmgr, it just show some Tx ID (last that it can display). +# +# Checked on: +# 4.0.0.1691 SS: 6.718s. +# 4.0.0.1691 CS: 6.532s. +# 3.0.5.33212 SS: 4.152s. +# 3.0.5.33212 CS: 5.770s. +# +# tracker_id: CORE-6141 +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import sys +# import time +# import subprocess +# import re +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# DBNAME_A = os.path.join(context['temp_directory'],'tmp_6141_a.fdb') +# DBNAME_B = os.path.join(context['temp_directory'],'tmp_6141_b.fdb') +# +# LIMBO_COUNT = 255 +# cleanup( (DBNAME_A,DBNAME_B) ) +# +# con1 = fdb.create_database( dsn = 'localhost:' + DBNAME_A) +# con2 = fdb.create_database( dsn = 'localhost:' + DBNAME_B) +# con1.execute_immediate( 'create table test(id int, x int, constraint test_pk primary key(id) using index test_pk)' ) +# con1.commit() +# +# con2.execute_immediate( 'create table test(id int, x int, constraint test_pk primary key(id) using index test_pk)' ) +# con2.commit() +# +# con1.close() +# con2.close() +# +# cgr = fdb.ConnectionGroup() +# +# con1 = fdb.connect( dsn = 'localhost:' + DBNAME_A) +# con2 = fdb.connect( dsn = 'localhost:' + DBNAME_B) +# +# cgr.add(con1) +# cgr.add(con2) +# +# # https://pythonhosted.org/fdb/reference.html#fdb.TPB +# # https://pythonhosted.org/fdb/reference.html#fdb.Connection.trans +# +# custom_tpb = fdb.TPB() +# custom_tpb.access_mode = fdb.isc_tpb_write +# custom_tpb.isolation_level = (fdb.isc_tpb_read_committed, fdb.isc_tpb_rec_version) +# custom_tpb.lock_resolution = fdb.isc_tpb_nowait +# +# tx1_list=[] +# for i in range(0, LIMBO_COUNT): +# tx1_list += [ con1.trans( default_tpb = custom_tpb ) ] +# +# cur_list=[] +# for i, tx1 in enumerate(tx1_list): +# tx1.begin() +# cur=tx1.cursor() +# cur.execute( "insert into test(id, x) values( ?, ? )", ( i, i*11111 ) ) +# cur.close() +# tx1.prepare() +# +# +# tx2 = con2.trans( default_tpb = custom_tpb ) +# cur2=tx2.cursor() +# cur2.execute( "insert into test(id, x) values( ?, ? )", (-2, -2222222) ) +# cur2.close() +# +# tx2.prepare() +# tx2.commit() +# +# svc = services.connect(host='localhost', user=user_name, password=user_password) +# svc.shutdown( DBNAME_A, services.SHUT_FULL, services.SHUT_FORCE, 0) +# +# print('Database is in full shutdown state now.') +# +# for tx1 in tx1_list: +# try: +# tx1.close() +# except: +# pass +# +# # Result for DBNAME_A when it will be returned online +# # and we query table TEST: +# # Statement failed, SQLSTATE = HY000 +# # record from transaction is stuck in limbo +# # See also "gfix -list \\path o\\dbname_a" +# +# cgr.clear() +# print('ConnectionGroup instance has been cleared.') +# +# svc.bring_online( DBNAME_A, services.SHUT_NORMAL ) +# print('Database has been brought ONLINE.') +# +# svc.close() +# con2.close() +# +# try: +# # This will fail for sure because DB state was changed to full shutdown +# con1.close() +# except: +# pass +# +# f_gfix_list_log=open( os.path.join(context['temp_directory'],'tmp_6141_gfix_list.log'), 'w', buffering = 0) +# subprocess.call( [ context['gfix_path'], '-list', DBNAME_A ], stdout=f_gfix_list_log, stderr=subprocess.STDOUT ) +# flush_and_close( f_gfix_list_log ) +# +# +# f_svc_list_log=open( os.path.join(context['temp_directory'],'tmp_6141_fbsvc_list.log'), 'w', buffering = 0) +# subprocess.call( [ context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_repair', 'rpr_list_limbo_trans', 'dbname', DBNAME_A ], stdout=f_svc_list_log, stderr=subprocess.STDOUT ) +# flush_and_close( f_svc_list_log ) +# +# pattern_for_limbo_in_gfix_output=re.compile('Transaction\\s+\\d+\\s+.*limbo', re.IGNORECASE) +# pattern_for_limbo_in_fsvc_output=re.compile('Transaction\\s+in\\s+limbo:\\s+\\d+', re.IGNORECASE) +# +# for i,g in enumerate( (f_gfix_list_log, f_svc_list_log) ): +# lines_with_limbo_info=0 +# log_name = 'gfix -list' if i== 0 else 'fbsvcmgr rpr_list_limbo_trans' +# pattern_for_match = pattern_for_limbo_in_gfix_output if i==0 else pattern_for_limbo_in_fsvc_output +# msg = "Number of lines related to limbo Tx in '%(log_name)s' output: " % locals() +# with open( g.name,'r') as f: +# for line in f: +# if pattern_for_match.search(line): +# lines_with_limbo_info += 1 +# else: +# print( 'Additional output from ' + ('GFIX: ' if i==0 else 'FBSVCMGR: ') + line ) +# print( msg + str(lines_with_limbo_info) ) +# +# # CLEANUP +# ######### +# time.sleep(1) +# cleanup( (DBNAME_A, DBNAME_B, f_gfix_list_log.name, f_svc_list_log.name) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Database is in full shutdown state now. + ConnectionGroup instance has been cleared. + Database has been brought ONLINE. + Additional output from GFIX: More limbo transactions than fit. Try again + Number of lines related to limbo Tx in 'gfix -list' output: 146 + Number of lines related to limbo Tx in 'fbsvcmgr rpr_list_limbo_trans' output: 146 + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_6141_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6142.py b/tests/bugs/test_core_6142.py new file mode 100644 index 00000000..a76a237c --- /dev/null +++ b/tests/bugs/test_core_6142.py @@ -0,0 +1,173 @@ +#coding:utf-8 +# +# id: bugs.core_6142 +# title: Error "connection lost to database" could happen when application creates few local attachments (using XNET) simultaneously +# decription: +# Test uses 15 threads and each of them launches loop for 10 iterations with making attach/detach from DB. +# We use Python package with name "threading" here, but it should be declared as global inside class because of fbtest specific +# (otherwise test will failed with message "global name 'threading' is not defined"). +# No such declaration is needed in normal way (i.e. when running code directly from Python, w/o using fbtest). +# Each instance of worker thread has dict() for storing its ID (as a key) and pair of values (success and fail count) as value. +# +# We have to ensure at the final point that for every of threads: +# * 1) number of SUCCESSFUL attempts is equal to limit that is declared here as LOOP_CNT. +# * 2) number of FAILED attempts is ZERO. +# +# Confirmed bug on 4.0.0.1598, 3.0.5.33166 (checked both SS and CS). +# It was enough 3 threads (which tried to establish attachments at the same time) to get runtime error: +# "- SQLCODE: -901 / - connection lost to database". +# +# Checked on 4.0.0.1607, 3.0.5.33171. +# :: NB :: +# Execution time for this test strongly depends on major version and server mode: +# 4.0 Classic: ~9"; 3.0.5 Classic: ~5"; +# 4.0 Super: ~5"; 3.0.5 Super: ~1". +# +# tracker_id: CORE-6142 +# min_versions: ['3.0.5'] +# versions: 3.0.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [('^((?!OVERALL RESULT).)*$', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import threading +# import datetime as py_dt +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# DB_PROT = 'xnet://' +# DB_NAME = os.path.join(context['temp_directory'],'bugs.core_6142.fdb') +# DB_USER = user_name +# DB_PSWD = user_password +# +# LOOP_CNT=10 +# THREADS_CNT=15 +# +# def showtime(): +# global py_dt +# return ''.join( (py_dt.datetime.now().strftime("%H:%M:%S.%f")[:11],'.') ) +# +# class workerThread(threading.Thread): +# global threading, showtime, make_db_attach +# def __init__(self, threadID, name, num_of_iterations): +# threading.Thread.__init__(self) +# self.threadID = threadID +# self.name = name +# self.num_of_iterations = num_of_iterations +# self.results_dict = { threadID : [0,0] } +# def run(self): +# print( showtime(), "Starting " + self.name ) +# +# make_db_attach( self.threadID, self.name, self.num_of_iterations, self.results_dict ) +# +# print( showtime(), "Exiting " + self.name) +# +# 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( threadID, threadName, num_of_iterations, results_dict ): +# global DB_PROT, DB_NAME, DB_USER, DB_PSWD, FB_CLNT +# global showtime +# i = 1 +# while i<= num_of_iterations: +# +# con = None +# att = 0 +# #print( showtime(), "%(threadName)s, iter %(i)s" % locals(), " - trying to: fdb.connect( dsn = '%(DB_PROT)s%(DB_NAME)s', user = '%(DB_USER)s', password = %(DB_PSWD)s, fb_library_name = '%(FB_CLNT)s' ) \\n" % globals() ) +# print( showtime(), "%(threadName)s, iter %(i)s" % locals(), " - trying to: fdb.connect( dsn = '%(DB_PROT)s%(DB_NAME)s' )\\n" % globals() ) +# +# try: +# #con = fdb.connect( dsn = DB_PROT + DB_NAME, user = DB_USER, password = DB_PSWD, fb_library_name = FB_CLNT ) +# con = fdb.connect( dsn = DB_PROT + DB_NAME, user = DB_USER, password = DB_PSWD ) +# att = con.attachment_id +# fbv = con.firebird_version +# print( showtime(), "%(threadName)s, iter %(i)s: attach_id=%(att)s has been created FB version: %(fbv)s.\\n" % locals() ) +# +# if False: +# cur = con.cursor() +# cur.execute('select count(*) from ( select 1 x from rdb$types a,rdb$types b,(select 1 i from rdb$types rows ( 30+rand()*30 ) ) )' ) +# for r in cur: +# pass +# cur.close() +# +# print( showtime(), "%(threadName)s, iter %(i)s: attach_id=%(att)s is to be closed.\\n" % locals() ) +# con.close() +# print( showtime(), "%(threadName)s, iter %(i)s: attach_id=%(att)s has been closed.\\n" % locals() ) +# results_dict[ threadID ][0] += 1 +# +# except Exception,e: +# results_dict[ threadID ][1] += 1 +# for k,x in enumerate(e): +# print( showtime(), "%(threadName)s, iter %(i)s: exception occured:\\n%(x)s\\n" % locals() ) +# +# i += 1 +# +# +# # Create new threads: +# # ################### +# threads_list=[] +# for i in range(0, THREADS_CNT): +# threads_list.append( workerThread( i+1, "Thread-%d" % (i+1), LOOP_CNT) ) +# +# # Start new Threads +# # ################# +# for t in threads_list: +# t.start() +# +# +# # Wait for all threads to complete +# for t in threads_list: +# t.join() +# +# for t in threads_list: +# t.show_results() +# +# print( showtime(), "##### Exiting Main Thread #####\\n") +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID of thread: 1. OVERALL RESULT: PASSED=10, FAILED=0 + ID of thread: 2. OVERALL RESULT: PASSED=10, FAILED=0 + ID of thread: 3. OVERALL RESULT: PASSED=10, FAILED=0 + ID of thread: 4. OVERALL RESULT: PASSED=10, FAILED=0 + ID of thread: 5. OVERALL RESULT: PASSED=10, FAILED=0 + ID of thread: 6. OVERALL RESULT: PASSED=10, FAILED=0 + ID of thread: 7. OVERALL RESULT: PASSED=10, FAILED=0 + ID of thread: 8. OVERALL RESULT: PASSED=10, FAILED=0 + ID of thread: 9. OVERALL RESULT: PASSED=10, FAILED=0 + ID of thread: 10. OVERALL RESULT: PASSED=10, FAILED=0 + ID of thread: 11. OVERALL RESULT: PASSED=10, FAILED=0 + ID of thread: 12. OVERALL RESULT: PASSED=10, FAILED=0 + ID of thread: 13. OVERALL RESULT: PASSED=10, FAILED=0 + ID of thread: 14. OVERALL RESULT: PASSED=10, FAILED=0 + ID of thread: 15. OVERALL RESULT: PASSED=10, FAILED=0 + """ + +@pytest.mark.version('>=3.0.5') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_6142_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6143.py b/tests/bugs/test_core_6143.py new file mode 100644 index 00000000..819db221 --- /dev/null +++ b/tests/bugs/test_core_6143.py @@ -0,0 +1,201 @@ +#coding:utf-8 +# +# id: bugs.core_6143 +# title: Error 'Multiple maps found for ...' is raised in not appropriate case +# decription: +# Confirmed bug on: 4.0.0.1535, 3.0.5.33152. +# Checked on: +# 4.0.0.1614: OK, 2.740s. +# 3.0.5.33172: OK, 2.282s. +# ::: NB ::: +# There was issue about mapping of ROLES: currently mapping can be done only for trusted role. +# But documentation does not mention about this. One can conclude that mapping should work +# as for trusted role and also for "usual" way (i.e. when used specifies 'ROLE ...' clause). +# Discussion about this with Alex was in 23-sep-2019, and his solution not yet known. +# For this reason it was decided to comment code that relates tgo ROLE mapping in this test. +# +# tracker_id: CORE-6143 +# min_versions: ['3.0.5'] +# versions: 3.0.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- set echo on; + set list on; + set wng off; + + set term ^; + execute block as + begin + execute statement 'drop role tmp$r6143_boss'; + when any do + begin + end + end + ^ + set term ;^ + commit; + + create or alter view v_show_mapping as + select + a.rdb$map_name + ,a.rdb$map_using + ,a.rdb$map_plugin + ,a.rdb$map_db + ,a.rdb$map_from_type + ,a.rdb$map_from + ,a.rdb$map_to_type + ,a.rdb$map_to + from rdb$database d + left join rdb$auth_mapping a on 1=1 + where rdb$map_from containing 'tmp$c6143' or rdb$map_from containing 'tmp$r6143' + ; + commit; + grant select on v_show_mapping to public; + + create or alter user tmp$c6143_foo password '123' using plugin Srp; + commit; + revoke all on all from tmp$c6143_foo; + commit; + + create role tmp$r6143_boss; + commit; + + -- ++++++++++++++++++++++++ T E S T L O C A L M A P P I N G +++++++++++++++++++++++ + + + create or alter mapping lmap_foo2bar_a using plugin srp from user tmp$c6143_foo to user tmp$c6143_bar; + create or alter mapping lmap_foo2bar_b using plugin srp from user tmp$c6143_foo to user tmp$c6143_bar; + + create or alter mapping lmap_boss2acnt_a using plugin srp from role tmp$r6143_boss to role tmp$r6143_acnt; + create or alter mapping lmap_boss2acnt_b using plugin srp from role tmp$c6143_boss to role tmp$r6143_acnt; + commit; + + grant tmp$r6143_boss to user tmp$c6143_bar; + commit; + + + connect '$(DSN)' user tmp$c6143_foo password '123' role tmp$r6143_boss; + select + 'Connected OK when local mapping is duplicated.' as msg + ,current_user as who_am_i -- <<< TMP$C6143_BAR must be shown here, *NOT* tmp$c6143_foo + -- temply diabled, wait for solution by Alex, see letters to him 23.09.2019 12:02: + -- ,current_role as what_my_role -- <<< WHAT ROLE MUST BE SHOWN HERE, *BOSS or *ACNT ??? + from rdb$database; + + set count on; + select * from v_show_mapping; + set count on; + commit; + + + connect '$(DSN)' user sysdba password 'masterkey'; + commit; + drop mapping lmap_foo2bar_a; + drop mapping lmap_foo2bar_b; + drop mapping lmap_boss2acnt_a; + drop mapping lmap_boss2acnt_b; + commit; + + -- ++++++++++++++++++++++++ T E S T G L O B A L M A P P I N G +++++++++++++++++++++++ + + + create or alter global mapping gmap_foo2rio_a using plugin srp from user tmp$c6143_foo to user tmp$c6143_rio; + create or alter global mapping gmap_foo2rio_b using plugin srp from user tmp$c6143_foo to user tmp$c6143_rio; + + create or alter global mapping gmap_boss2mngr_a using plugin srp from role tmp$r6143_boss to role tmp$r6143_mngr; + create or alter global mapping gmap_boss2mngr_b using plugin srp from role tmp$c6143_boss to role tmp$r6143_mngr; + commit; + + connect '$(DSN)' user tmp$c6143_foo password '123' role tmp$r6143_boss; + select + 'Connected OK when global mapping is duplicated.' as msg + ,current_user as who_am_i -- <<< TMP$C6143_RIO must be shown here, *NOT* tmp$c6143_foo + -- temply diabled, wait for solution by Alex, see letters to him 23.09.2019 12:02: + -- ,current_role as what_my_role -- <<< WHAT ROLE MUST BE SHOWN HERE, *BOSS or *MNGR or... NONE ??? + from rdb$database; + commit; + + + connect '$(DSN)' user sysdba password 'masterkey'; + commit; + drop global mapping gmap_foo2rio_a; + drop global mapping gmap_foo2rio_b; + drop global mapping gmap_boss2mngr_a; + drop global mapping gmap_boss2mngr_b; + commit; + drop user tmp$c6143_foo using plugin Srp; + commit; + drop role tmp$r6143_boss; + commit; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG Connected OK when local mapping is duplicated. + WHO_AM_I TMP$C6143_BAR + + RDB$MAP_NAME LMAP_FOO2BAR_A + RDB$MAP_USING P + RDB$MAP_PLUGIN SRP + RDB$MAP_DB + RDB$MAP_FROM_TYPE USER + RDB$MAP_FROM TMP$C6143_FOO + RDB$MAP_TO_TYPE 0 + RDB$MAP_TO TMP$C6143_BAR + + RDB$MAP_NAME LMAP_FOO2BAR_B + RDB$MAP_USING P + RDB$MAP_PLUGIN SRP + RDB$MAP_DB + RDB$MAP_FROM_TYPE USER + RDB$MAP_FROM TMP$C6143_FOO + RDB$MAP_TO_TYPE 0 + RDB$MAP_TO TMP$C6143_BAR + + RDB$MAP_NAME LMAP_BOSS2ACNT_A + RDB$MAP_USING P + RDB$MAP_PLUGIN SRP + RDB$MAP_DB + RDB$MAP_FROM_TYPE ROLE + RDB$MAP_FROM TMP$R6143_BOSS + RDB$MAP_TO_TYPE 1 + RDB$MAP_TO TMP$R6143_ACNT + + RDB$MAP_NAME LMAP_BOSS2ACNT_B + RDB$MAP_USING P + RDB$MAP_PLUGIN SRP + RDB$MAP_DB + RDB$MAP_FROM_TYPE ROLE + RDB$MAP_FROM TMP$C6143_BOSS + RDB$MAP_TO_TYPE 1 + RDB$MAP_TO TMP$R6143_ACNT + + Records affected: 4 + + MSG Connected OK when global mapping is duplicated. + WHO_AM_I TMP$C6143_RIO + + Records affected: 1 + """ + +@pytest.mark.version('>=3.0.5') +def test_core_6143_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6144.py b/tests/bugs/test_core_6144.py new file mode 100644 index 00000000..40cb7311 --- /dev/null +++ b/tests/bugs/test_core_6144.py @@ -0,0 +1,74 @@ +#coding:utf-8 +# +# id: bugs.core_6144 +# title: Inconsistent behaviour of the NEW context variable in AFTER UPDATE OR DELETE triggers +# decription: +# Confirmed problem on: 4.0.0.1607, 3.0.5.33171 and 2.5.9.27143: new.v was assigned to 1 in AD trigger. +# Checked on: +# build 4.0.0.1614: OK, 1.472s. +# build 3.0.5.33172: OK, 0.802s. +# build 2.5.9.27144: OK, 0.376s. +# +# tracker_id: CORE-6144 +# min_versions: ['2.5.9'] +# versions: 2.5.9 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.9 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table test (id integer not null primary key); + commit; + + insert into test (id) values (1); + commit; + alter table test add v integer default 1 not null; + commit; + insert into test (id) values (2); + commit; + create exception exc_not_null_in_AD_trigger 'new.v is NOT null in AD trigger ?!'; + commit; + + set term ^; + create or alter trigger test_null for test after update or delete as + begin + if (new.v is not null) then -- new.v should be NULL if the trigger runs after DELETE statement + begin + rdb$set_context('USER_SESSION', 'AD_TRIGGER_NEW_V', new.v); + exception exc_not_null_in_AD_trigger; + end + end + ^ + set term ;^ + commit; + + delete from test where id = 2; -- no errors + delete from test where id = 1; -- trigger throws exception + + set list on; + select rdb$get_context('USER_SESSION', 'AD_TRIGGER_NEW_V') as "new_v value in AD trigger:" + from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + new_v value in AD trigger: + """ + +@pytest.mark.version('>=2.5.9') +def test_core_6144_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6145.py b/tests/bugs/test_core_6145.py new file mode 100644 index 00000000..c1ffcf0b --- /dev/null +++ b/tests/bugs/test_core_6145.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: bugs.core_6145 +# title: Wrong result in "similar to" with non latin characters +# decription: +# Confirmed bug on 4.0.0.1607 +# Checked on: +# 4.0.0.1614: OK, 1.509s. +# 3.0.5.33171: OK, 0.682s. +# 2.5.9.27142: OK, 0.629s. +# +# tracker_id: CORE-6145 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set count on; + set heading off; + select 1 from rdb$database where 'я' similar to '%Я%'; + select 2 from rdb$database where 'Я' similar to '%я%'; + select 3 from rdb$database where 'я' similar to '[Яя]'; + select 4 from rdb$database where 'Я' similar to 'я'; + select 5 from rdb$database where 'Я' similar to 'Я'; + select 6 from rdb$database where 'Я' similar to '[яЯ]'; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + + Records affected: 0 + + 3 + Records affected: 1 + + Records affected: 0 + + 5 + Records affected: 1 + + 6 + Records affected: 1 + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.platform('Windows') +def test_core_6145_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6147.py b/tests/bugs/test_core_6147.py new file mode 100644 index 00000000..d3d68501 --- /dev/null +++ b/tests/bugs/test_core_6147.py @@ -0,0 +1,373 @@ +#coding:utf-8 +# +# id: bugs.core_6147 +# title: PLG$SRP table, PLG$SRP_VIEW View instructions are strangely added in the metadata script extracted when Windows trusted authentication is enabled +# decription: +# ::: NOTE ::: +# References to the table PLG$SRP and view PLG$SRP_VIEW *always* present in extracted metadata, +# regardless of using auth plugin (and this is NOT a bug!). +# +# Fix was introduced in 4.0.0.2087: extracted metadata must contain "OR ALTER" clause in: +# CREATE OR ALTER GLOBAL MAPPING TRUSTED_AUTH_C6147 ... +# ^^^^^^^^ +# Builds before 4.0.0.2084 did not add this clause in extracted metadata script (checked 4.0.0.2076). +# (see also discussion with Alex, 02-jun-2020 08:23). +# +# ### NB ### +# For unclear reason ALTER EXTERNAL CONNECTIONS POOL CLEAR ALL + DROP DATABASE do not work as expected in this test: +# test DB remains opened by firebird.exe about 5...7 seconds after test finish, and 'drop database' does not issues any error. +# Because of this it was decided to forcedly change DB state to full shutdown in order to have ability to drop it. +# 22.02.2021: perhaps, this was somehow related to core-6441. +# +# NOTES FOR WINDOWS: +# ################## +# We create copy of %FIREBIRD_HOME%\\database.conf and change it content by adding lines: +# tmp_alias_6147 = ... +# { +# SecurityDatabase = tmp_alias_6147 +# } +# Then we create trest DB in embedded mode, create SYSDBA that belongs to this DB and create global mapping. +# We check content of rdb$auth_mapping table after this step in order to ensure that mapping was actually created. +# After this we do connect to DB using Win_SSPI and extract metadata. +# +# NOTES FOR LINUX: +# ################ +# 03-mar-2021. This test can run on Linux but we have to use plugin = Srp instead of win_sspi. +# This is done by check result of os.name (see below). +# Local mapping (i.e. in RDB$DATABASE) will *not* be created in this case (in contrary to win_sspi), +# thus we create and drop it "manually" in order to pass expected results check. +# +# Checked on: +# * Windows: 4.0.0.2377 SS/CS (done for both win_sspi and Srp, but only win_sspi is used in this test for Windows) +# * Linux: 4.0.0.2377 SS/CS (done for Srp) +# +# tracker_id: CORE-6147 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('.*===.*', ''), ('PLUGIN .*', 'PLUGIN')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import datetime +# import time +# import shutil +# import re +# from fdb import services +# +# this_fdb = db_conn.database_name +# +# if os.name == 'nt': +# # On Windows we test what it was initially described in the ticket (trusted auth.): +# PLUGIN_FOR_MAPPING = 'win_sspi' +# else: +# # On Linux currently we can check only Srp plugin +# # but results must be the same as for win_sspi: +# PLUGIN_FOR_MAPPING = 'Srp' +# +# +# # 23.08.2020: !!! REMOVING OS-VARIABLE ISC_USER IS MANDATORY HERE !!! +# # This variable could be set by other .fbts which was performed before current within batch mode (i.e. when fbt_run is called from ) +# # NB: os.unsetenv('ISC_USER') actually does NOT affect on content of os.environ dictionary, see: https://docs.python.org/2/library/os.html +# # We have to remove OS variable either by os.environ.pop() or using 'del os.environ[...]', but in any case this must be enclosed intro try/exc: +# #os.environ.pop('ISC_USER') +# try: +# del os.environ["ISC_USER"] +# except KeyError as e: +# pass +# +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# svc = services.connect(host='localhost', user= user_name, password= user_password) +# fb_home = svc.get_home_directory() +# svc.close() +# # Resut: fb_home is full path to FB instance home (with trailing slash). +# +# dts = datetime.datetime.now().strftime("%y%m%d_%H%M%S") +# +# dbconf = os.path.join( fb_home, 'databases.conf') +# dbcbak = os.path.join( fb_home, 'databases_'+dts+'.bak') +# +# shutil.copy2( dbconf, dbcbak ) +# +# tmp_fdb=os.path.join(context['temp_directory'],'tmp_6147.fdb') +# cleanup( (tmp_fdb,) ) +# +# text2app=''' +# +# # Temporarily added by fbtest, CORE-6147. Should be removed auto: +# ############################## +# tmp_alias_6147 = %(tmp_fdb)s +# { +# SecurityDatabase = tmp_alias_6147 +# } +# ############################## +# ''' % locals() +# +# f_dbconf=open( dbconf, 'a') +# f_dbconf.seek(0, 2) +# f_dbconf.write( text2app ) +# flush_and_close( f_dbconf ) +# +# +# SHOW_MAP_INFO_QUERY = ''' +# set count on; +# -- set echo on; +# set width map_name 31; +# set width map_type 10; +# set width map_plugin 16; +# set width from_type 10; +# set width map_from 10; +# set width to_type 10; +# set width map_to 10; +# select * from v_map_info; +# ''' +# +# if PLUGIN_FOR_MAPPING == 'Srp': +# db_connect_string = this_fdb +# sql_txt= ''' +# set bail on; +# connect 'localhost:%(db_connect_string)s' user %(user_name)s password '%(user_password)s'; +# commit; +# -- ::: NB ::: +# -- Local mapping will NOT be created when use Srp; create it here in order to have the same results +# -- as for win_sspi: +# create or alter mapping trusted_auth_c6147 using plugin %(PLUGIN_FOR_MAPPING)s from any user to user; +# commit; +# ''' % dict(globals(), **locals()) +# else: +# db_connect_string = 'tmp_alias_6147' +# sql_txt= ''' +# set bail on; +# -- do NOT use 'localhost:' here! Otherwise: +# -- Statement failed, SQLSTATE = 28000 +# -- Your user name and password are not defined. ... +# create database '%(db_connect_string)s' user %(user_name)s; +# create user %(user_name)s password '%(user_password)s'; +# commit; +# ''' % dict(globals(), **locals()) +# +# sql_txt += ''' +# -- ::: NB ::: +# -- When used plugin is win_sspi then *TWO* mappings will be created here: "local' (in rdb$auth_mapping) +# -- and g;pbal (in sec$global_auth_mapping). This is NOT so when used plugin = Srp (only global mapping will be made). +# create or alter global mapping trusted_auth_c6147 using plugin %(PLUGIN_FOR_MAPPING)s from any user to user; +# commit; +# +# recreate view v_map_info as +# select +# map_name +# ,map_type +# -- ,map_plugin +# ,from_type +# ,map_from +# ,to_type +# ,map_to +# from +# ( +# select +# rdb$map_name as map_name +# ,'local' as map_type +# ,rdb$map_plugin as map_plugin +# ,rdb$map_from_type as from_type +# ,rdb$map_from as map_from +# ,rdb$map_to_type as to_type +# ,rdb$map_to as map_to +# from rdb$auth_mapping +# UNION ALL +# select +# sec$map_name +# ,'global' +# ,sec$map_plugin +# ,sec$map_from_type +# ,sec$map_from +# ,sec$map_to_type +# ,sec$map_to +# from sec$global_auth_mapping +# ) t +# where +# t.map_name = upper('trusted_auth_c6147') +# and t.map_plugin = upper('%(PLUGIN_FOR_MAPPING)s') +# ; +# commit; +# +# %(SHOW_MAP_INFO_QUERY)s +# +# ''' % dict(globals(), **locals()) +# +# f_prepare_sql = open( os.path.join(context['temp_directory'],'tmp_6147_prepare.sql'), 'w') +# f_prepare_sql.write(sql_txt) +# flush_and_close( f_prepare_sql ) +# +# f_prepare_log=open( os.path.join(context['temp_directory'],'tmp_6147_prepare.log'), 'w') +# subprocess.call( [ context['isql_path'], "-q", "-i", f_prepare_sql.name ], stdout=f_prepare_log, stderr=subprocess.STDOUT ) +# flush_and_close( f_prepare_log ) +# +# +# # Extract metadata from test DB: +# ################## +# f_medatata_log=open( os.path.join(context['temp_directory'],'tmp_6147_meta.mapping.sql'), 'w') +# subprocess.call( [ context['isql_path'], '-x', 'localhost:%(db_connect_string)s' % locals(),'-user', user_name, '-pas', user_password ], stdout=f_medatata_log, stderr=subprocess.STDOUT ) +# flush_and_close( f_medatata_log ) +# +# +# # Remove global mapping: +# ######################## +# f_cleanup_sql = open( os.path.join(context['temp_directory'],'tmp_6147_cleanup.sql'), 'w') +# sql_txt=''' +# set bail on; +# -- NB: here we have to connect as "common" SYSDBA (using Srp) rather than Win_SSPI. +# -- Otherwise global mapping can not be deleted: +# -- ############################################ +# -- Statement failed, SQLSTATE = 28000 +# -- unsuccessful metadata update +# -- -DROP MAPPING TRUSTED_AUTH_C6147 failed +# -- -Unable to perform operation +# -- -System privilege CHANGE_MAPPING_RULES is missing +# -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# -- This I can not explain: why user who did create global mapping can not delete it ??? +# -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# connect 'localhost:%(db_connect_string)s' user %(user_name)s password '%(user_password)s'; +# drop global mapping trusted_auth_c6147; +# ''' % dict(globals(), **locals()) +# +# if PLUGIN_FOR_MAPPING == 'Srp': +# sql_txt += ''' +# -- Delete record from rdb$auth_mapping (only when used plugin = 'Srp'): +# drop mapping trusted_auth_c6147; +# ''' +# +# sql_txt += ''' +# commit; +# +# %(SHOW_MAP_INFO_QUERY)s +# quit; +# +# -- DOES NOT HELP! DATABASE FILE REMAINS OPENED BY FIREBIRD! +# -- ALTER EXTERNAL CONNECTIONS POOL CLEAR ALL; -- !! mandatory otherwise database file will be kept by engine and fbtest will not able to drop it !! +# -- drop database; --> does not raise errot when clear pool but DB file still remains opened !!! +# ''' % dict(globals(), **locals()) +# +# f_cleanup_sql.write(sql_txt) +# flush_and_close( f_cleanup_sql ) +# +# # DROP MAPPING: +# ############### +# f_cleanup_log = open( os.path.join(context['temp_directory'],'tmp_6147_cleanup.log'), 'w') +# subprocess.call( [ context['isql_path'], "-q", "-i", f_cleanup_sql.name ], stdout=f_cleanup_log, stderr=subprocess.STDOUT ) +# flush_and_close( f_cleanup_log ) +# +# subprocess.call( [context['gfix_path'], 'localhost:%(db_connect_string)s' % locals(), '-shut', 'single', '-force', '0', '-user', user_name, '-pas', user_password] ) +# +# # RESTORE original config: +# ########################## +# shutil.move( dbcbak, dbconf) +# +# with open(f_prepare_log.name, 'r') as f: +# for line in f: +# if line.split(): +# print('AFTER_MADE_MAPPING: ' + line) +# +# allowed_patterns = ( +# re.compile('MAPPING TRUSTED_AUTH_C6147', re.IGNORECASE) +# ,re.compile('SQLSTATE', re.IGNORECASE) +# ,re.compile('Missing security', re.IGNORECASE) +# ,re.compile('Your user', re.IGNORECASE) +# ) +# +# with open(f_medatata_log.name, 'r') as f: +# for line in f: +# match2some = [ p.search(line) for p in allowed_patterns ] +# if max(match2some): +# print('EXTRACTED_METADATA: ' + line) +# +# with open(f_cleanup_log.name, 'r') as f: +# for line in f: +# if line.split(): +# print('AFTER_DROP_MAPPING: ' + line) +# +# # CLEANUP: +# ########## +# time.sleep(1) +# f_list=( +# f_prepare_sql +# ,f_prepare_log +# ,f_medatata_log +# ,f_cleanup_sql +# ,f_cleanup_log +# ,tmp_fdb +# ) +# cleanup( f_list ) +# +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +AFTER_MADE_MAPPING: MAP_NAME MAP_TYPE FROM_TYPE MAP_FROM TO_TYPE MAP_TO +AFTER_MADE_MAPPING: =============================== ========== ========== ========== ======= ========== +AFTER_MADE_MAPPING: TRUSTED_AUTH_C6147 local USER * 0 +AFTER_MADE_MAPPING: TRUSTED_AUTH_C6147 global USER * 0 +AFTER_MADE_MAPPING: Records affected: 2 + +EXTRACTED_METADATA: CREATE MAPPING TRUSTED_AUTH_C6147 USING PLUGIN +EXTRACTED_METADATA: CREATE OR ALTER GLOBAL MAPPING TRUSTED_AUTH_C6147 USING PLUGIN + +AFTER_DROP_MAPPING: Records affected: 0 + + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_6147_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6158.py b/tests/bugs/test_core_6158.py new file mode 100644 index 00000000..32f66361 --- /dev/null +++ b/tests/bugs/test_core_6158.py @@ -0,0 +1,164 @@ +#coding:utf-8 +# +# id: bugs.core_6158 +# title: substring similar - extra characters in the result for non latin characters +# decription: +# Confirmed regression on build 4.0.0.1629, 4.0.0.1631 +# Worked as expected on 4.0.0.1535 (build 24.06.2019, before replacement old regexp library with 're2') +# Works fine on: 4.0.0.1632 (build 19.10.2019) +# +# 05-mar-2021. Re-implemented in order to have ability to run this test on Linux. +# Test encodes to UTF8 all needed statements (SET NAMES; CONNECT; DDL and DML) and stores this text in .sql file. +# NOTE: 'SET NAMES' contain character set that must be used for reproducing problem (WIN1251 in this test). +# Then ISQL is launched in separate (child) process which performs all necessary actions (using required charset). +# Result will be redirected to log(s) which will be opened further via codecs.open(...encoding='cp1251'). +# Finally, its content will be converted to UTF8 for showing in expected_stdout. +# Checked on: +# * Windows: 4.0.0.2377 +# * Linux: 4.0.0.2379 +# +# +# tracker_id: CORE-6158 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('RESULT_3_BLOB_ID.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(charset='WIN1251', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import codecs +# import subprocess +# import time +# engine = db_conn.engine_version +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# # Put patterns outside of sql_txt in order to avoid replacement percent sign +# # with its duplicate ('%' --> '%%') because of Python substitution requirements: +# pattern_01 = '%/#*(=){3,}#"%#"(=){3,}#*/%' +# pattern_02 = '%/#*(#-){3,}#"%#"(#-){3,}#*/%' +# +# sql_txt=''' set bail on; +# set names win1251; +# connect '%(dsn)s' user '%(user_name)s' password '%(user_password)s'; +# +# +# -- This is needed to get "cannot transliterate character between character sets" +# -- on build 4.0.0.1631, see comment in the tracker 18/Oct/19 02:57 PM: +# create domain T_A64 as varchar (64) character set WIN1251 collate WIN1251; +# create table VALUT_LIST (NAME T_A64 not null); +# commit; +# insert into VALUT_LIST (NAME) values ('Российский рубль'); +# insert into VALUT_LIST (NAME) values ('Турецкая лира'); +# insert into VALUT_LIST (NAME) values ('Доллар США'); +# commit; +# +# set list on; +# set blob all; +# +# select substring(' +# aaa +# /*==== Комментарий между символами "равно" ====*/ +# bbb +# ccc +# ddd +# eee +# fff +# jjj +# ' similar '%(pattern_01)s' escape '#') as result1 +# from rdb$database; +# +# -- additional check for special character '-' as delimiter: +# select substring('здесь написан /*---- Комментарий между символами "дефис" ----*/ - и больше ничего!' similar '%(pattern_02)s' escape '#') as result2 +# from rdb$database; +# +# -- Confirmed fail on 4.0.0.1631 with "cannot transliterate character between character sets": +# select substring(list(T.NAME, '; ') from 1 for 250) as result_3_blob_id from VALUT_LIST T; +# +# +# ''' % dict(globals(), **locals()) +# +# f_run_sql = open( os.path.join(context['temp_directory'], 'tmp_6158_win1251.sql'), 'w' ) +# f_run_sql.write( sql_txt.decode('utf8').encode('cp1251') ) +# flush_and_close( f_run_sql ) +# +# # result: file tmp_6158_win1251.sql is encoded in win1251 +# +# f_run_log = open( os.path.splitext(f_run_sql.name)[0]+'.log', 'w') +# subprocess.call( [ context['isql_path'], '-q', '-i', f_run_sql.name ], +# stdout = f_run_log, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_run_log ) # result: output will be encoded in win1251 +# +# with codecs.open(f_run_log.name, 'r', encoding='cp1251' ) as f: +# result_in_win1251 = f.readlines() +# +# for i in result_in_win1251: +# print( i.encode('utf8') ) +# +# # cleanup: +# ########### +# cleanup( (f_run_sql, f_run_log) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT1 = Комментарий между символами "равно" = + RESULT2 - Комментарий между символами "дефис" - + Российский рубль; Турецкая лира; Доллар США + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_6158_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6159.py b/tests/bugs/test_core_6159.py new file mode 100644 index 00000000..04500edc --- /dev/null +++ b/tests/bugs/test_core_6159.py @@ -0,0 +1,60 @@ +#coding:utf-8 +# +# id: bugs.core_6159 +# title: SUBSTRING SIMILAR is described with wrong data type in DSQL +# decription: +# Confirmed correct work on 4.0.0.1627. +# FB 3.x and 4.0.0.1535 raises exception after select substring(blob_field similar ) from ...: +# Statement failed, SQLSTATE = 42000 +# Invalid SIMILAR TO pattern +# +# tracker_id: CORE-6159 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('^((?!sqltype|harc|lobb|affected).)*$', ''), ('[ \t]+', ' '), ('Nullable.*', 'Nullable')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test(id int, s varchar(1000), b blob); + insert into test(id, s,b) values( 1, 'charchar', 'fooobaar' ); + insert into test(id, s,b) values( 2, 'fooobaar', 'blobblob' ); + commit; + + set list on; + set blob on; + set sqlda_display on; + set count on; + select x from (select substring( s similar 'c#"harc#"har' escape '#') x from test ) where x is not null; + select x from (select substring( b similar 'b#"lobb#"lob' escape '#') x from test ) where x is not null; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 01: sqltype: 448 VARYING Nullable + X harc + Records affected: 1 + + 01: sqltype: 520 BLOB Nullable + lobb + Records affected: 1 + """ + +@pytest.mark.version('>=4.0') +def test_core_6159_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6160.py b/tests/bugs/test_core_6160.py new file mode 100644 index 00000000..0aa703ed --- /dev/null +++ b/tests/bugs/test_core_6160.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: bugs.core_6160 +# title: SUBSTRING of non-text/-blob is described to return NONE character set in DSQL +# decription: +# Confirmed output of: ' ... charset: 0 NONE' on 4.0.0.1627. +# Works as described in the ticket since 4.0.0.1632 ('... charset: 2 ASCII'). +# NOTE. In the 'substitution' section we remove all rows except line with phrase 'charset' in it. +# Furter, we have to remove digital ID for this charset because it can be changed in the future: +# 'charset: 2 ASCII' --> 'charset: ASCII' +# +# tracker_id: CORE-6160 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('^((?!charset).)*$', ''), ('[ \t]+', ' '), ('.*charset: [\\d]+', 'charset:')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- 01: sqltype: 448 VARYING scale: 0 subtype: 0 len: 1 charset: 2 ASCII + set sqlda_display on; + set planonly; + select substring(1 from 1 for 1) from rdb$database; + select substring(current_date from 1 for 1) from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + charset: ASCII + charset: ASCII + """ + +@pytest.mark.version('>=4.0') +def test_core_6160_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6163.py b/tests/bugs/test_core_6163.py new file mode 100644 index 00000000..4bdfc8b5 --- /dev/null +++ b/tests/bugs/test_core_6163.py @@ -0,0 +1,508 @@ +#coding:utf-8 +# +# id: bugs.core_6163 +# title: Generator pages are not encrypted +# decription: +# Database in this test is encrypted using IBSurgeon Demo Encryption package +# ( https://ib-aid.com/download-demo-firebird-encryption-plugin/ ; https://ib-aid.com/download/crypt/CryptTest.zip ) +# License file plugins\\dbcrypt.conf with unlimited expiration was provided by IBSurgeon to Firebird Foundation (FF). +# This file was preliminary stored in FF Test machine. +# Test assumes that this file and all neccessary libraries already were stored into FB_HOME and %FB_HOME%\\plugins. +# +# Anyone who wants to run this test on his own machine must +# 1) download https://ib-aid.com/download/crypt/CryptTest.zip AND +# 2) PURCHASE LICENSE and get from IBSurgeon file plugins\\dbcrypt.conf with apropriate expiration date and other info. +# +# ################################################ ! ! ! N O T E ! ! ! ############################################## +# FF tests storage (aka "fbt-repo") does not (and will not) contain any license file for IBSurgeon Demo Encryption package! +# ######################################################################################################################### +# +# Several sequences are created in this test. +# Then we obtain generator page ID and page size by querying RDB$PAGES and MON$DATABASE tables. +# After this, we check that values of sequences *PRESENT* in NON-encrypted database by opening DB file in 'rb' mode +# and reading content of its generator page. +# Further, we encrypt database and wait for 1 second in order to give engine complete this job. +# Finally, we read generator page again. NO any value of secuences must be found at this point. +# +# Encryprion is performed by 'alter database encrypt with key ...' statement, +# where = dbcrypt - is the name of .dll in FB_HOME\\plugins\\ folder that implements encryption. +# +# === NOTE-1 === +# In case of "Crypt plugin DBCRYPT failed to load/607/335544351" check that all +# needed files from IBSurgeon Demo Encryption package exist in %FB_HOME% and %FB_HOME%\\plugins +# %FB_HOME%: +# 283136 fbcrypt.dll +# 2905600 libcrypto-1_1-x64.dll +# 481792 libssl-1_1-x64.dll +# +# %FB_HOME%\\plugins: +# 297984 dbcrypt.dll +# 306176 keyholder.dll +# 108 DbCrypt.conf +# 856 keyholder.conf +# +# === NOTE-2 === +# Version of DbCrypt.dll of october-2018 must be replaced because it has hard-coded +# date of expiration rather than reading it from DbCrypt.conf !! +# +# === NOTE-3 === +# firebird.conf must contain following line: +# KeyHolderPlugin = KeyHolder +# +# Confirmed non-encrypted content of generators page on: 4.0.0.1627; 3.0.5.33178. +# Checked on: 4.0.0.1633: OK, 2.260s; 3.0.5.33180: OK, 1.718s. +# +# :::::::::::::::::::::::::::::::::::::::: NB :::::::::::::::::::::::::::::::::::: +# 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 +# Checked on 4.0.0.2164, 3.0.7.33356 +# +# 28.02.2021 +# For unknown reason 3.x and 4.x Classic hangs during run this test, both on Linux and (unexpectedly) Windows. +# Fortunately, simple solution was found. +# FB hangs only when encryption is done in ISQL but we wait for its finish within 'main' (Python) code (rather than in ISQL). +# If we force ISQL *itself* wait for several seconds than all fine. +# So, the only way to avoid hang (at least nowadays, 01-mar-2021) is to make encryption *and* waiting for its finish +# within ONE attachment to the database that is created by ISQL. +# Because of this, 'init_script' contains special table and procedure for making pauses: 'tets' and 'sp_delay'. +# Procedure 'sp_delay' must be called within Tx which was declared as SET TRANSACTION LOCK TIMEOU where = 1...3. +# +# Checked on: 4.0.0.2372 SS/CS; 3.0.8.33420 SS/CS. +# +# +# tracker_id: CORE-6163 +# min_versions: ['3.0.5'] +# versions: 3.0.5, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [('^((?!(FOUND.|Database\\s+encrypted)).)*$', ''), ('[ \t]+', ' ')] + +init_script_1 = """ + recreate table test(x bigint unique); + set term ^; + create or alter procedure sp_delay as + declare r bigint; + begin + r = rand() * 9223372036854775807; + insert into test(x) values(:r); + begin + -- ######################################################### + -- ####################### D E L A Y ##################### + -- ######################################################### + in autonomous transaction do + insert into test(x) values(:r); -- this will cause delay because of duplicate in index + when any do + begin + -- nop -- + end + end + end + ^ + set term ;^ + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import binascii +# import time +# #import shutil +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# this_fdb = db_conn.database_name +# # ::: NB ::: DO NOT close db_conn now! We can close it only after encryption will finish! +# +# db_conn.execute_immediate('create sequence gen_ba0bab start with 12192683') +# db_conn.execute_immediate('create sequence gen_badf00d start with 195948557') +# db_conn.execute_immediate('create sequence gen_caca0 start with 830624') +# db_conn.execute_immediate('create sequence gen_c0ffee start with 12648430') +# db_conn.execute_immediate('create sequence gen_dec0de start with 14598366') +# db_conn.execute_immediate('create sequence gen_decade start with 14600926') +# db_conn.execute_immediate('create sequence gen_7FFFFFFF start with 2147483647') +# db_conn.commit() +# +# ###################################################################################### +# +# def check_page_for_readable_values(dbname, gen_page_number, pg_size, check_sequence_values): +# +# global binascii +# +# db_handle = open( dbname, "rb") +# db_handle.seek( gen_page_number * pg_size ) +# page_content = db_handle.read( pg_size ) +# # read_binary_content( db_handle, gen_page_number * pg_size, pg_size ) +# db_handle.close() +# page_as_hex=binascii.hexlify( page_content ) +# +# # Iterate for each sequence value: +# for n in check_sequence_values: +# +# # Get HEX representation of digital value. +# # NOTE: format( 830624, 'x') is 'caca0' contains five (odd number!) characters. +# hex_string = format(abs(n),'x') +# +# # Here we 'pad' hex representation to EVEN number of digits in it, +# # otherwise binascii.hexlify fails with "Odd-length string error": +# hex_string = ''.join( ('0' * ( len(hex_string)%2 ), hex_string ) ) +# +# # ::: NOTE ::: +# # Generator value is stored in REVERSED bytes order. +# # dec 830624 --> hex 0x0caca0 --> 0c|ac|a0 --> stored in page as three bytes: {a0; ac; 0c} +# +# # Decode string that is stored in variable 'hex_string' to HEX number, +# # REVERSE its bytes and convert it to string again for further search +# # in page content: +# n_as_reversed_hex = binascii.hexlify( hex_string.decode('hex')[::-1] ) +# +# print(n, n_as_reversed_hex, 'FOUND.' if n_as_reversed_hex in page_as_hex else 'NOT FOUND.' ) +# # print(n, n_as_reversed_hex, 'UNEXPECTEDLY FOUND AT POS. ' + '{:5d}'.format( page_as_hex.index(n_as_reversed_hex) ) if n_as_reversed_hex in page_as_hex else 'Not found (expected).' ) +# +# ###################################################################################### +# +# +# cur=db_conn.cursor() +# get_current_seq_values=''' +# execute block returns( gen_curr bigint) as +# declare gen_name rdb$generator_name; +# begin +# for +# select rdb$generator_name from rdb$generators where rdb$system_flag is distinct from 1 order by rdb$generator_id +# into gen_name +# do begin +# execute statement 'execute block returns(g bigint) as begin g = gen_id('|| gen_name ||', 0); suspend; end' into gen_curr; +# suspend; +# end +# end +# ''' +# +# # Obtain current values of user generators: +# # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# cur.execute(get_current_seq_values) +# check_sequence_values=[] +# for r in cur: +# check_sequence_values += r[0], +# +# +# # Obtain page size and number of generators page: +# # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# cur.execute('select m.mon$page_size,min(rdb$page_number) from mon$database m cross join rdb$pages p where p.rdb$page_type = 9 group by 1') +# pg_size, gen_page_number = -1,-1 +# for r in cur: +# pg_size=r[0] +# gen_page_number=r[1] +# # print(r[0],r[1]) +# cur.close() +# db_conn.close() +# +# # Read gen page, convert it to hex and check whether generator values can be found there or no: +# # Expected result: YES for all values because DB not encrypted now. +# # ~~~~~~~~~~~~~~~ +# check_page_for_readable_values(this_fdb, gen_page_number, pg_size, check_sequence_values) +# +# # 27.02.2021. +# # Name of encryption plugin depends on OS: +# # * for Windows we (currently) use plugin by IBSurgeon, its name is 'dbcrypt'; +# # later it can be replaced with built-in plugin 'fbSampleDbCrypt' +# # but currently it is included only in FB 4.x builds (not in FB 3.x). +# # Discussed tih Dimitr, Alex, Vlad, letters since: 08-feb-2021 00:22 +# # "Windows-distributive FB 3.x: it is desired to see sub-folder 'examples\\prebuild' with files for encryption, like it is in FB 4.x +# # *** DEFERRED *** +# # * for Linux we use: +# # ** 'DbCrypt_example' for FB 3.x +# # ** 'fbSampleDbCrypt' for FB 4.x+ +# # +# PLUGIN_NAME = 'dbcrypt' if os.name == 'nt' else ( '"DbCrypt_example"' if db_conn.engine_version < 4 else '"fbSampleDbCrypt"' ) +# +# sql_cmd=''' +# -- ################################################ +# -- ### e n c r y p t d a t a b a s e ### +# -- ################################################ +# alter database encrypt with %(PLUGIN_NAME)s key Red; +# commit; +# +# +# -- 01.03.2021: we have to wait for several seconds +# -- until encryption will be finished. But we must do +# -- this delay within the same attachment as those that +# -- launched encryption process. +# -- The reason of that weird effect currently is unknown. +# -- Here we make pause using 'set transaction lock timeout': +# +# set transaction lock timeout 2; -- THIS LOCK TIMEOUT SERVES ONLY FOR DELAY +# execute procedure sp_delay; +# rollback; +# show database; +# quit; +# ''' % locals() +# +# runProgram('isql', [ dsn ], sql_cmd) +# +# # Read again gen page, convert it to hex and check whether generator values can be found there or no. +# # Expected result: NOT for all values because DB was encrypted. +# # ~~~~~~~~~~~~~~~~ +# check_page_for_readable_values(this_fdb, gen_page_number, pg_size, check_sequence_values) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +12192683 ab0bba FOUND. +195948557 0df0ad0b FOUND. +830624 a0ac0c FOUND. +12648430 eeffc0 FOUND. +14598366 dec0de FOUND. +14600926 decade FOUND. +2147483647 ffffff7f FOUND. + +Database encrypted + +12192683 ab0bba NOT FOUND. +195948557 0df0ad0b NOT FOUND. +830624 a0ac0c NOT FOUND. +12648430 eeffc0 NOT FOUND. +14598366 dec0de NOT FOUND. +14600926 decade NOT FOUND. +2147483647 ffffff7f NOT FOUND. + """ + +@pytest.mark.version('>=3.0.5') +@pytest.mark.xfail +def test_core_6163_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + +# version: 4.0 +# resources: None + +substitutions_2 = [('^((?!(FOUND.|Database\\s+encrypted)).)*$', ''), ('[ \t]+', ' ')] + +init_script_2 = """ + recreate table test(x bigint unique); + set term ^; + create or alter procedure sp_delay as + declare r bigint; + begin + r = rand() * 9223372036854775807; + insert into test(x) values(:r); + begin + -- ######################################################### + -- ####################### D E L A Y ##################### + -- ######################################################### + in autonomous transaction do + insert into test(x) values(:r); -- this will cause delay because of duplicate in index + when any do + begin + -- nop -- + end + end + end + ^ + set term ;^ + commit; + + """ + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +# test_script_2 +#--- +# +# import os +# import sys +# import binascii +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# this_fdb = db_conn.database_name +# +# db_conn.execute_immediate('create sequence gen_ba0bab start with 12192683') +# db_conn.execute_immediate('create sequence gen_badf00d start with 195948557') +# db_conn.execute_immediate('create sequence gen_caca0 start with 830624') +# db_conn.execute_immediate('create sequence gen_c0ffee start with 12648430') +# db_conn.execute_immediate('create sequence gen_dec0de start with 14598366') +# db_conn.execute_immediate('create sequence gen_decade start with 14600926') +# db_conn.execute_immediate('create sequence gen_7FFFFFFF start with 2147483647') +# db_conn.commit() +# +# # ::: NB ::: DO NOT close db_conn now! We can close it only after encryption will finish! +# +# ###################################################################################### +# +# def check_page_for_readable_values(dbname, gen_page_number, pg_size, check_sequence_values): +# +# global binascii +# +# db_handle = open( dbname, "rb") +# db_handle.seek( gen_page_number * pg_size ) +# page_content = db_handle.read( pg_size ) +# # read_binary_content( db_handle, gen_page_number * pg_size, pg_size ) +# db_handle.close() +# page_as_hex=binascii.hexlify( page_content ) +# +# # Iterate for each sequence value: +# for n in check_sequence_values: +# +# # Get HEX representation of digital value. +# # NOTE: format( 830624, 'x') is 'caca0' contains five (odd number!) characters. +# hex_string = format(abs(n),'x') +# +# # Here we 'pad' hex representation to EVEN number of digits in it, +# # otherwise binascii.hexlify fails with "Odd-length string error": +# hex_string = ''.join( ('0' * ( len(hex_string)%2 ), hex_string ) ) +# +# # ::: NOTE ::: +# # Generator value is stored in REVERSED bytes order. +# # dec 830624 --> hex 0x0caca0 --> 0c|ac|a0 --> stored in page as three bytes: {a0; ac; 0c} +# +# # Decode string that is stored in variable 'hex_string' to HEX number, +# # REVERSE its bytes and convert it to string again for further search +# # in page content: +# n_as_reversed_hex = binascii.hexlify( hex_string.decode('hex')[::-1] ) +# +# print(n, n_as_reversed_hex, 'FOUND.' if n_as_reversed_hex in page_as_hex else 'NOT FOUND.' ) +# # print(n, n_as_reversed_hex, 'UNEXPECTEDLY FOUND AT POS. ' + '{:5d}'.format( page_as_hex.index(n_as_reversed_hex) ) if n_as_reversed_hex in page_as_hex else 'Not found (expected).' ) +# +# ###################################################################################### +# +# cur=db_conn.cursor() +# get_current_seq_values=''' +# execute block returns( gen_curr bigint) as +# declare gen_name rdb$generator_name; +# begin +# for +# select rdb$generator_name from rdb$generators where rdb$system_flag is distinct from 1 order by rdb$generator_id +# into gen_name +# do begin +# execute statement 'execute block returns(g bigint) as begin g = gen_id('|| gen_name ||', 0); suspend; end' into gen_curr; +# suspend; +# end +# end +# ''' +# +# # Obtain current values of user generators: +# # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# cur.execute(get_current_seq_values) +# check_sequence_values=[] +# for r in cur: +# check_sequence_values += r[0], +# #print('check_sequence_values=',check_sequence_values) +# +# +# +# # Obtain page size and number of generators page: +# # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# cur.execute('select m.mon$page_size,min(rdb$page_number) from mon$database m cross join rdb$pages p where p.rdb$page_type = 9 group by 1') +# pg_size, gen_page_number = -1,-1 +# for r in cur: +# pg_size=r[0] +# gen_page_number=r[1] +# # print(r[0],r[1]) +# +# # 28.02.2021, temporary: +# srv_mode='UNKNOWN' +# cur.execute("select rdb$config_value from rdb$config where rdb$config_name='ServerMode'") +# for r in cur: +# srv_mode=r[0] +# +# cur.close() +# db_conn.close() +# +# # Read gen page, convert it to hex and check whether generator values can be found there or no: +# # Expected result: YES for all values because DB not encrypted now. +# # ~~~~~~~~~~~~~~~ +# check_page_for_readable_values(this_fdb, gen_page_number, pg_size, check_sequence_values) +# +# +# # 27.02.2021. +# # Name of encryption plugin depends on OS: +# # * for Windows we (currently) use plugin by IBSurgeon, its name is 'dbcrypt'; +# # later it can be replaced with built-in plugin 'fbSampleDbCrypt' +# # but currently it is included only in FB 4.x builds (not in FB 3.x). +# # Discussed tih Dimitr, Alex, Vlad, letters since: 08-feb-2021 00:22 +# # "Windows-distributive FB 3.x: it is desired to see sub-folder 'examples\\prebuild' with files for encryption, like it is in FB 4.x +# # *** DEFERRED *** +# # * for Linux we use: +# # ** 'DbCrypt_example' for FB 3.x +# # ** 'fbSampleDbCrypt' for FB 4.x+ +# # +# PLUGIN_NAME = 'dbcrypt' if os.name == 'nt' else ( '"DbCrypt_example"' if db_conn.engine_version < 4 else '"fbSampleDbCrypt"' ) +# +# sql_cmd=''' +# -- ################################################ +# -- ### e n c r y p t d a t a b a s e ### +# -- ################################################ +# alter database encrypt with %(PLUGIN_NAME)s key Red; +# commit; +# +# -- 01.03.2021: we have to wait for several seconds +# -- until encryption will be finished. But we must do +# -- this delay within the same attachment as those that +# -- launched encryption process. +# -- The reason of that weird effect currently is unknown. +# -- Here we make pause using 'set transaction lock timeout': +# +# set transaction lock timeout 2; -- THIS LOCK TIMEOUT SERVES ONLY FOR DELAY +# execute procedure sp_delay; +# rollback; +# show database; +# quit; +# ''' % locals() +# +# runProgram('isql', [ dsn ], sql_cmd) +# +# # Read again gen page, convert it to hex and check whether generator values can be found there or no. +# # Expected result: NOT FOUND, for all values (because DB was encrypted). +# # ~~~~~~~~~~~~~~~~ +# check_page_for_readable_values(this_fdb, gen_page_number, pg_size, check_sequence_values) +# +# +#--- +#act_2 = python_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ +12192682 aa0bba FOUND. +195948556 0cf0ad0b FOUND. +830623 9fac0c FOUND. +12648429 edffc0 FOUND. +14598365 ddc0de FOUND. +14600925 ddcade FOUND. +2147483646 feffff7f FOUND. + +Database encrypted + +12192682 aa0bba NOT FOUND. +195948556 0cf0ad0b NOT FOUND. +830623 9fac0c NOT FOUND. +12648429 edffc0 NOT FOUND. +14598365 ddc0de NOT FOUND. +14600925 ddcade NOT FOUND. +2147483646 feffff7f NOT FOUND. + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_6163_2(db_2): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6166.py b/tests/bugs/test_core_6166.py new file mode 100644 index 00000000..ef4d906d --- /dev/null +++ b/tests/bugs/test_core_6166.py @@ -0,0 +1,202 @@ +#coding:utf-8 +# +# id: bugs.core_6166 +# title: Problems with long object names (> 255 bytes) +# decription: +# We define several objects with non-ascii names of max allowed length (63 characters) and make check statements. +# Result no matter, but these statements must finished without errors. +# Then we extract metadata and add the same set of check statements to this sql script. +# Applying of this script to empty (another) database must end also without any error. +# +# Confirmed problem on 4.0.0.1633: ISQL crashed when performing script which contains DDL with non-ascii names +# of max allowed len (63 characters). +# +# Checked on 4.0.0.1635: OK, 4.821s. +# +# tracker_id: CORE-6166 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# sql_ddl=''' +# set term ^; +# recreate package "ПакетДляРешенияЛинейныхГиперболическихИТрансцендентныхУравнений" as +# begin +# function "МетодЗейделяДляЛинейныхГиперболическихИТрансцендентныхУравнений"() returns int; +# function "МетодНьютонаДляЛинейныхГиперболическихИТрансцендентныхУравнений"() returns int; +# end +# ^ +# recreate package body "ПакетДляРешенияЛинейныхГиперболическихИТрансцендентныхУравнений" as +# begin +# function "МетодЗейделяДляЛинейныхГиперболическихИТрансцендентныхУравнений"() returns int as +# begin +# return 123; +# end +# function "МетодНьютонаДляЛинейныхГиперболическихИТрансцендентныхУравнений"() returns int as +# begin +# return 456; +# end +# +# end +# ^ +# set term ;^ +# commit; +# create table "КоэффициентыДляЛинейныхГиперболическихИТрансцендентныхУравнений" ( +# "КоэффициентЦДляЛинейныхГиперболическихИТрансцендентныхУравнений" int +# ,"КоэффициентЫДляЛинейныхГиперболическихИТрансцендентныхУравнений" int +# ,"КоэффициентЧДляЛинейныхГиперболическихИТрансцендентныхУравнений" int +# ); +# create unique index "КоэффициентыЛинейныхГиперболическихИТрансцендентныхУравненийЦЫЧ" +# on "КоэффициентыДляЛинейныхГиперболическихИТрансцендентныхУравнений" ( +# "КоэффициентЦДляЛинейныхГиперболическихИТрансцендентныхУравнений" +# ,"КоэффициентЫДляЛинейныхГиперболическихИТрансцендентныхУравнений" +# ,"КоэффициентЧДляЛинейныхГиперболическихИТрансцендентныхУравнений" +# ); +# commit; +# +# ''' +# +# sql_chk=''' +# +# show package; +# show index "КоэффициентыДляЛинейныхГиперболическихИТрансцендентныхУравнений"; +# set list on; +# select "ПакетДляРешенияЛинейныхГиперболическихИТрансцендентныхУравнений"."МетодЗейделяДляЛинейныхГиперболическихИТрансцендентныхУравнений"() from rdb$database; +# select "ПакетДляРешенияЛинейныхГиперболическихИТрансцендентныхУравнений"."МетодНьютонаДляЛинейныхГиперболическихИТрансцендентныхУравнений"() from rdb$database; +# rollback; +# ''' +# +# +# f_chk_query_sql=open( os.path.join(context['temp_directory'],'tmp_6166_chk_query.sql'), 'w') +# f_chk_query_sql.write( sql_ddl + sql_chk ) +# flush_and_close( f_chk_query_sql ) +# +# f_chk_query_log = open( os.path.join(context['temp_directory'],'tmp_isql_6166_chk_query.log'), 'w' ) +# f_chk_query_err = open( os.path.join(context['temp_directory'],'tmp_isql_6166_chk_query.err'), 'w') +# subprocess.call( [context['isql_path'], dsn, "-ch", "utf8", "-i", f_chk_query_sql.name], stdout=f_chk_query_log, stderr=f_chk_query_err ) +# flush_and_close( f_chk_query_log ) +# flush_and_close( f_chk_query_err ) +# +# +# if os.path.getsize( f_chk_query_err.name ) == 0: +# with open( f_chk_query_log.name,'r') as f: +# for line in f: +# if line.split(): +# print('CHECK STATEMENTS, INITIAL: '+line) +# +# f_chk_metadata_sql=open( os.path.join(context['temp_directory'],'tmp_6166_metadata.sql'), 'w') +# subprocess.call( [context['isql_path'], dsn, "-ch", "utf8", "-x" ], stdout=f_chk_metadata_sql, stderr=subprocess.STDOUT ) +# f_chk_metadata_sql.write( sql_chk ) +# flush_and_close( f_chk_metadata_sql ) +# +# f_chk_metadata_fdb = os.path.join(context['temp_directory'],'tmp_6166_metadata.fdb') +# if os.path.isfile( f_chk_metadata_fdb ): +# os.remove( f_chk_metadata_fdb ) +# chk_conn = fdb.create_database( dsn = 'localhost:'+f_chk_metadata_fdb ) +# chk_conn.close() +# +# f_chk_metadata_log = open( os.path.join(context['temp_directory'],'tmp_6166_metadata.log'), 'w' ) +# f_chk_metadata_err = open( os.path.join(context['temp_directory'],'tmp_6166_metadata.err'), 'w' ) +# subprocess.call( [context['isql_path'], 'localhost:'+f_chk_metadata_fdb, "-ch", "utf8", "-i", f_chk_metadata_sql.name ], stdout=f_chk_metadata_log, stderr=f_chk_metadata_err ) +# flush_and_close( f_chk_metadata_log ) +# flush_and_close( f_chk_metadata_err ) +# +# with open( f_chk_metadata_err.name,'r') as f: +# for line in f: +# if line.split(): +# print('UNEXPECTED ERROR IN THE EXTRACTED METADATA SQL: '+line) +# +# with open( f_chk_metadata_log.name,'r') as f: +# for line in f: +# if line.split(): +# print('CHECK STATEMENTS ON EXTRACTED METADATA: '+line) +# +# else: +# with open( f_chk_query_err.name,'r') as f: +# for line in f: +# if line.split(): +# print('UNEXPECTED ERROR IN INITIAL CHECK STATEMENTS: '+line) +# +# # cleanup: +# ########## +# time.sleep(1) +# cleanup( ( f_chk_query_sql, f_chk_query_log, f_chk_query_err, f_chk_metadata_sql, f_chk_metadata_log, f_chk_metadata_err,f_chk_metadata_fdb ) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CHECK STATEMENTS, INITIAL: ПакетДляРешенияЛинейныхГиперболическихИТрансцендентныхУравнений + CHECK STATEMENTS, INITIAL: КоэффициентыЛинейныхГиперболическихИТрансцендентныхУравненийЦЫЧ UNIQUE INDEX ON КоэффициентыДляЛинейныхГиперболическихИТрансцендентныхУравнений(КоэффициентЦДляЛинейныхГиперболическихИТрансцендентныхУравнений, КоэффициентЫДляЛинейныхГиперболическихИТрансцендентныхУравнений, КоэффициентЧДляЛинейныхГиперболическихИТрансцендентныхУравнений) + CHECK STATEMENTS, INITIAL: МетодЗейделяДляЛинейныхГиперболическихИТрансцендентныхУравнений 123 + CHECK STATEMENTS, INITIAL: МетодНьютонаДляЛинейныхГиперболическихИТрансцендентныхУравнений 456 + + CHECK STATEMENTS ON EXTRACTED METADATA: ПакетДляРешенияЛинейныхГиперболическихИТрансцендентныхУравнений + CHECK STATEMENTS ON EXTRACTED METADATA: КоэффициентыЛинейныхГиперболическихИТрансцендентныхУравненийЦЫЧ UNIQUE INDEX ON КоэффициентыДляЛинейныхГиперболическихИТрансцендентныхУравнений(КоэффициентЦДляЛинейныхГиперболическихИТрансцендентныхУравнений, КоэффициентЫДляЛинейныхГиперболическихИТрансцендентныхУравнений, КоэффициентЧДляЛинейныхГиперболическихИТрансцендентныхУравнений) + CHECK STATEMENTS ON EXTRACTED METADATA: МетодЗейделяДляЛинейныхГиперболическихИТрансцендентныхУравнений 123 + CHECK STATEMENTS ON EXTRACTED METADATA: МетодНьютонаДляЛинейныхГиперболическихИТрансцендентныхУравнений 456 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_6166_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6171.py b/tests/bugs/test_core_6171.py new file mode 100644 index 00000000..914d0b50 --- /dev/null +++ b/tests/bugs/test_core_6171.py @@ -0,0 +1,83 @@ +#coding:utf-8 +# +# id: bugs.core_6171 +# title: "No current record for fetch operation" with queries with aggregated subselect +# decription: +# Confrmed bug on: 4.0.0.1635, 3.0.5.33182. +# Works fine on: +# 4.0.0.1639 SS: 1.291s. +# 3.0.5.33183 SS: 0.769s. +# +# tracker_id: CORE-6171 +# min_versions: ['3.0.5'] +# versions: 3.0.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + recreate table tmain( s varchar(10) ); + recreate table tdetl( s varchar(10), u int ); + commit; + + insert into tmain(s) values('foo'); + insert into tmain(s) values('bar'); + insert into tmain(s) values('rio'); + insert into tmain(s) values('boo'); + insert into tmain(s) values(''); + commit; + + insert into tdetl(s, u) values('foo', 100); + insert into tdetl(s, u) values('bar', 200); + insert into tdetl(s, u) values('rio', 300); + insert into tdetl(s, u) values('boo', 400); + commit; + + create index tmain_s on tmain(s); + commit; + + set heading off; + set plan on; + + select r.s + from tmain r + where + r.s = '' + or ( + select sum(d.u) + from tdetl d + where d.s = r.s + ) > 0 + ; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (D NATURAL) + PLAN (R NATURAL) + + foo + bar + rio + boo + """ + +@pytest.mark.version('>=3.0.5') +def test_core_6171_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6181.py b/tests/bugs/test_core_6181.py new file mode 100644 index 00000000..40fb1575 --- /dev/null +++ b/tests/bugs/test_core_6181.py @@ -0,0 +1,66 @@ +#coding:utf-8 +# +# id: bugs.core_6181 +# title: Operations when using "SET DECFLOAT BIND BIGINT,n" with result of 11+ digits, fail with "Decimal float invalid operation" +# decription: +# Confirmed bug on: 4.0.0.1633 SS: FAILED. +# Checked on 4.0.0.1646 CS: 1.219s. +# +# 10.12.2019. Updated syntax for SET BIND command because it was changed in 11-nov-2019. +# Replaced 'bigint,3' with numeric(18,3) - can not specify scale using comma delimiter, i.e. ",3" +# +# Checked on: WI-T4.0.0.1685. +# +# +# tracker_id: CORE-6181 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + -- OLD SYNTAX: set decfloat bind bigint,3; + -- Syntax after 11-nov-2019: + -- https://github.com/FirebirdSQL/firebird/commit/a77295ba153e0c17061e2230d0ffdbaf08839114 + -- See also: doc/sql.extensions/README.set_bind.md: + -- SET BIND OF type-from TO { type-to | LEGACY }; + -- SET BIND OF type NATIVE; + + set bind of decfloat to numeric(18,3); + + select cast('1234567.890' as DECFLOAT(34)) as test_01 from rdb$database; + select cast('1234567.8901' as DECFLOAT(34)) as test_02 from rdb$database; + select cast('12345678.901' as DECFLOAT(34)) as test_03 from rdb$database; -- 12345678.901 + select cast('12345678.90' as DECFLOAT(34)) as test_04 from rdb$database; -- Expected result is: 12345678.900 + select cast('9223372036854775.807' as DECFLOAT(34)) as test_05 from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TEST_01 1234567.890 + TEST_02 1234567.890 + TEST_03 12345678.901 + TEST_04 12345678.900 + TEST_05 9223372036854775.807 + """ + +@pytest.mark.version('>=4.0') +def test_core_6181_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6182.py b/tests/bugs/test_core_6182.py new file mode 100644 index 00000000..707548b3 --- /dev/null +++ b/tests/bugs/test_core_6182.py @@ -0,0 +1,262 @@ +#coding:utf-8 +# +# id: bugs.core_6182 +# title: ExtConnPoolLifeTime acts as countdown for activity in MOST RECENT database (of several) rather then separate for each of used databases +# decription: +# We create one main ('head') DB (only for make single attach to it) and four test databases for making EDS connections to each of them from main DB. +# Special user is created using LEGACY plugin because of comment in the ticket by hvlad 06/Nov/19 01:36 PM. +# ~~~~~~ +# Then we do subsequent connections to each of these databases using EDS mechanism, with delay betnwe them (and also with final delay). +# Total sum of seconds that execution was paused is 4 * TDELAY - must be GREATER than config parameter ExtConnPoolLifeTime. +# After last delay will elapsed, we again establish connections to each of these databases and try to execute DROP DATABASE statements. +# +# Main idea: FIRST of this databases (which was firstly used to EDS connection) must have NO any attachments in its ExtPool and DROP must pass w/o any problems. +# +# ::: NOTE ::: ATTENTION ::: ACHTUNG ::: +# +# We can not issue 'DROP DATABASE' immediately becase if some connection remains in ExtPool then FDB will raise exception that can not be catched. +# For this reason we have to kill all attachments using 'DELETE FROM MON$ATTACHMENTS' statement. Number of attachments that were deleted will show +# whether there was some 'auxiliary' connections or not. For the first of checked databases this number must be 0 (zero). +# Otherwise one can state that the problem with ExtPool still exists. +# +# Checked on: +# 4.0.0.1646 SS/SC: ~19s (most of time is idle because of delays that is necessary for check that connections disappeared from ExtPool) +# 4.0.0.1646 CS: 21.339s - but this test is not needed for this acrh. +# +# tracker_id: CORE-6182 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import time +# import subprocess +# import fdb +# from fdb import services +# +# DB_PATH = context['temp_directory'] +# # os.sep.join( db_conn.database_name.split(os.sep)[:-1] ) +# +# DB_USER=user_name +# DB_PSWD=user_password +# +# EDS_USER='tmp$c6182_leg' +# EDS_PSWD='123' +# +# #-------------------------------------------- +# +# 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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# TDELAY=3 +# DB_CNT=4 +# +# ddl_main=''' +# set bail on; +# create or alter user %(EDS_USER)s password '%(EDS_PSWD)s' using plugin Legacy_UserManager; +# commit; +# +# set term ^; +# create procedure sp_do_eds ( a_target_db varchar(128) ) returns( source_dts timestamp, who_is_connecting varchar(128), source_db varchar(128), target_db varchar(128), target_dts timestamp ) as +# begin +# source_dts = cast('now' as timestamp); +# for +# execute statement +# ('select cast(? as varchar(128)) as connect_from_db, current_user, mon$database_name as connect_to_db, cast(''now'' as timestamp) from mon$database') +# ( rdb$get_context('SYSTEM', 'DB_NAME') ) +# on external +# 'localhost:' || a_target_db +# as +# user '%(EDS_USER)s' +# password '%(EDS_PSWD)s' +# into who_is_connecting, source_db, target_db, target_dts +# do +# suspend; +# end +# ^ +# set term ;^ +# commit; +# grant execute on procedure sp_do_eds to %(EDS_USER)s; +# grant drop database to %(EDS_USER)s; +# commit; +# ''' % locals() +# +# f_isql1=open( os.path.join(context['temp_directory'],'tmp-c6182-ddl1.sql'), 'w') +# f_isql1.write( ddl_main ) +# flush_and_close( f_isql1 ) +# +# +# ddl_eds=''' +# set bail on; +# set term ^; +# -- create procedure sp_del_att returns( list_of_killed varchar(255) ) as +# create procedure sp_del_att returns( num_of_killed smallint ) as +# begin +# num_of_killed = 0; +# for +# select mon$attachment_id as killed_att +# from mon$attachments +# where mon$system_flag is distinct from 1 and mon$attachment_id != current_connection +# as cursor c +# do +# begin +# -- list_of_killed = list_of_killed || c.killed_att || ','; +# delete from mon$attachments where current of c; +# num_of_killed = num_of_killed + 1; +# end +# suspend; +# end +# ^ +# set term ;^ +# commit; +# grant execute on procedure sp_del_att to public; +# commit; +# ''' +# +# +# f_isql2=open( os.path.join(context['temp_directory'],'tmp-c6182-ddl2.sql'), 'w') +# f_isql2.write( ddl_eds ) +# flush_and_close( f_isql2 ) +# +# +# for i in range(0, DB_CNT+1): +# dbx = os.path.join( DB_PATH, ( ('c6182_tmp4eds.%d.fdb' % i) if i > 0 else 'c6182_tmpmain.fdb' ) ) +# cleanup( (dbx,) ) +# +# con=fdb.create_database(dsn = 'localhost:' + dbx, user = user_name, password = user_password) +# con.close() +# subprocess.call( [context['isql_path'], '-user', DB_USER, '-pas', DB_PSWD, 'localhost:' + dbx, '-i', (f_isql1.name if i==0 else f_isql2.name) ]) +# +# +# #----------------------------------------- +# +# con = fdb.connect( dsn = 'localhost:' + os.path.join(DB_PATH, 'c6182_tmpmain.fdb'), user = EDS_USER, password = EDS_PSWD) +# +# cur = con.cursor() +# for i in range(1, DB_CNT+1): +# dbx = os.path.join( DB_PATH, ('c6182_tmp4eds.%d.fdb' % i) ) +# cur.execute( 'select * from sp_do_eds(?)', (dbx,) ) +# for r in cur: +# pass +# # 2debug only: print(r) +# +# cur.close() +# con.commit() +# +# time.sleep( TDELAY ) +# +# #-------------------------------------------- +# con.drop_database() +# con.close() +# #-------------------------------------------- +# +# for i in range(1, DB_CNT+1): +# dbx = os.path.join( DB_PATH, ('c6182_tmp4eds.%d.fdb' % i) ) +# +# con = fdb.connect( 'localhost:' + dbx, user = user_name, password = user_password) +# cur = con.cursor() +# cur.callproc( 'sp_del_att' ) +# for r in cur: +# if i == 1: +# print( 'Number of deleted attachments for DB # %d: %d' % (i, r[0] ) ) +# else: +# # All subseq. databases are not interested for us +# pass +# +# cur.close() +# con.commit() +# +# try: +# con.drop_database() +# except Exception as e: +# ls=repr(e).split('\\n') +# print( ls[-2] ) +# finally: +# con.close() +# +# #-------------------------------------------- +# +# svc = services.connect( host='localhost', user = user_name, password = user_password) +# for i in range(1, DB_CNT+1): +# dbx = os.path.join( DB_PATH, ('c6182_tmp4eds.%d.fdb' % i) ) +# if os.path.isfile(dbx): +# print('UNEXPECTED presence of DB '+dbx) +# svc.shutdown(database = dbx, shutdown_mode = fdb.services.SHUT_FULL, shutdown_method = fdb.services.SHUT_FORCE, timeout = 0 ) +# svc.bring_online( database = dbx ) +# os.remove(dbx) +# +# # commented 05.01.2020: +# ####################### +# # Unable to perform the requested Service API action: +# # - SQLCODE: -85 +# # - The user name specified was not found in the security database +# # -85 +# # 335544753 +# # ---xxx --- svc.remove_user( EDS_USER ) +# +# svc.close() +# +# # Use ISQL instead of FDB Services instance to drop user which was created with Legacy_UserManager plugin +# # and this plugin now is NOT in the head of UserManager config parameter: +# runProgram(context['isql_path'],[ dsn, '-user', DB_USER, '-pas', DB_PSWD ], 'drop user %(EDS_USER)s using plugin Legacy_UserManager;' % locals() ) +# +# cleanup( (f_isql1, f_isql2) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Number of deleted attachments for DB # 1: 0 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_6182_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6185.py b/tests/bugs/test_core_6185.py new file mode 100644 index 00000000..a33bd81f --- /dev/null +++ b/tests/bugs/test_core_6185.py @@ -0,0 +1,82 @@ +#coding:utf-8 +# +# id: bugs.core_6185 +# title: Some (wrong ?) parameters of ENCRYPT() leads FB to crash +# decription: +# Confirmed crash on 4.0.0.1637. +# Checked on 4.0.0.1691 SS: OK, 1.658s. +# +# tracker_id: CORE-6185 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set blob all; + + create or alter procedure sp_block_test(a_alg varchar(30)) as begin end; + commit; + + recreate table test( crypto_alg varchar(30), source_text blob, crypto_key varchar(128), crypto_iv varchar(16) ); + commit; + + insert into test( crypto_alg, source_text, crypto_key, crypto_iv ) + values( 'AES', lpad('', 65533, gen_uuid()), '0101010101010101', lpad('',16, uuid_to_char( gen_uuid() )) ); + commit; + + set term ^; + create or alter procedure sp_block_test( a_alg varchar(30) ) returns( result_msg varchar(80) ) + as + declare v_encrypted blob; + declare v_encrypt_sttm blob; + begin + for + select + t.source_text + ,t.crypto_alg + ,t.crypto_key + ,t.crypto_iv + from test t + where upper( t.crypto_alg ) = upper( :a_alg ) + as cursor c + do begin + v_encrypt_sttm = 'select encrypt( q''{' || c.source_text || '}'' using ' || c.crypto_alg || ' mode ofb key q''{' || c.crypto_key || '}'' iv q''{' || c.crypto_iv || '}'' ) from rdb$database'; + execute statement v_encrypt_sttm into v_encrypted; + end + result_msg = 'String has been encrypted.'; + suspend; + end + ^ + set term ;^ + commit; + + select result_msg from sp_block_test('aes'); + select encrypt( 'fooriobar' using CHACHA20 key q'{1110FB89-AD32-4E}' iv q'{114E811E}' counter cast(null as bigint) ) as encrypt_str from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT_MSG String has been encrypted. + ENCRYPT_STR 8E709DDA89912F172C + """ + +@pytest.mark.version('>=4.0') +def test_core_6185_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6186.py b/tests/bugs/test_core_6186.py new file mode 100644 index 00000000..586e3999 --- /dev/null +++ b/tests/bugs/test_core_6186.py @@ -0,0 +1,52 @@ +#coding:utf-8 +# +# id: bugs.core_6186 +# title: Original content of column which is involved into ENCRYPT() is displayed as distorted view after this call +# decription: +# Confirmed bug on 4.0.0.1637 +# Checked on 4.0.0.1691: OK, 1.124s. +# +# tracker_id: CORE-6186 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + with + a as ( + select 'Encrypts/decrypts data using symmetric cipher' as s_origin + from rdb$database + ) + select + a.s_origin + ,encrypt( a.s_origin using aes mode ofb key '0123456789012345' iv 'abcdefghhgfedcba') as s_encrypted + from a + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + S_ORIGIN Encrypts/decrypts data using symmetric cipher + S_ENCRYPTED 910805BDA8B05C475E8B5D3D0971D58649EA0D549FEA1633A8811429183E925E1C2C77CE4E3B9DCDFA0C75997E + """ + +@pytest.mark.version('>=4.0') +def test_core_6186_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6205.py b/tests/bugs/test_core_6205.py new file mode 100644 index 00000000..e501c897 --- /dev/null +++ b/tests/bugs/test_core_6205.py @@ -0,0 +1,588 @@ +#coding:utf-8 +# +# id: bugs.core_6205 +# title: Generate proper error for UNION DISTINCT with more than 255 columns +# decription: +# Confirmed bug on 4.0.0.1691, got STDERR: +# Statement failed, SQLSTATE = HY000 +# invalid request BLR at offset 5668 +# -BLR syntax error: expected record selection expression clause at offset 5669, encountered 24 +# +# Checked on 4.0.0.1693: OK, 1.196s. +# +# tracker_id: CORE-6205 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + select + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256 + from rdb$database + + union all + + select + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256 + from rdb$database + ; + + select + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256 + from rdb$database + + union --all + + select + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256 + from rdb$database + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CONSTANT 1 + CONSTANT 2 + CONSTANT 3 + CONSTANT 4 + CONSTANT 5 + CONSTANT 6 + CONSTANT 7 + CONSTANT 8 + CONSTANT 9 + CONSTANT 10 + CONSTANT 11 + CONSTANT 12 + CONSTANT 13 + CONSTANT 14 + CONSTANT 15 + CONSTANT 16 + CONSTANT 17 + CONSTANT 18 + CONSTANT 19 + CONSTANT 20 + CONSTANT 21 + CONSTANT 22 + CONSTANT 23 + CONSTANT 24 + CONSTANT 25 + CONSTANT 26 + CONSTANT 27 + CONSTANT 28 + CONSTANT 29 + CONSTANT 30 + CONSTANT 31 + CONSTANT 32 + CONSTANT 33 + CONSTANT 34 + CONSTANT 35 + CONSTANT 36 + CONSTANT 37 + CONSTANT 38 + CONSTANT 39 + CONSTANT 40 + CONSTANT 41 + CONSTANT 42 + CONSTANT 43 + CONSTANT 44 + CONSTANT 45 + CONSTANT 46 + CONSTANT 47 + CONSTANT 48 + CONSTANT 49 + CONSTANT 50 + CONSTANT 51 + CONSTANT 52 + CONSTANT 53 + CONSTANT 54 + CONSTANT 55 + CONSTANT 56 + CONSTANT 57 + CONSTANT 58 + CONSTANT 59 + CONSTANT 60 + CONSTANT 61 + CONSTANT 62 + CONSTANT 63 + CONSTANT 64 + CONSTANT 65 + CONSTANT 66 + CONSTANT 67 + CONSTANT 68 + CONSTANT 69 + CONSTANT 70 + CONSTANT 71 + CONSTANT 72 + CONSTANT 73 + CONSTANT 74 + CONSTANT 75 + CONSTANT 76 + CONSTANT 77 + CONSTANT 78 + CONSTANT 79 + CONSTANT 80 + CONSTANT 81 + CONSTANT 82 + CONSTANT 83 + CONSTANT 84 + CONSTANT 85 + CONSTANT 86 + CONSTANT 87 + CONSTANT 88 + CONSTANT 89 + CONSTANT 90 + CONSTANT 91 + CONSTANT 92 + CONSTANT 93 + CONSTANT 94 + CONSTANT 95 + CONSTANT 96 + CONSTANT 97 + CONSTANT 98 + CONSTANT 99 + CONSTANT 100 + CONSTANT 101 + CONSTANT 102 + CONSTANT 103 + CONSTANT 104 + CONSTANT 105 + CONSTANT 106 + CONSTANT 107 + CONSTANT 108 + CONSTANT 109 + CONSTANT 110 + CONSTANT 111 + CONSTANT 112 + CONSTANT 113 + CONSTANT 114 + CONSTANT 115 + CONSTANT 116 + CONSTANT 117 + CONSTANT 118 + CONSTANT 119 + CONSTANT 120 + CONSTANT 121 + CONSTANT 122 + CONSTANT 123 + CONSTANT 124 + CONSTANT 125 + CONSTANT 126 + CONSTANT 127 + CONSTANT 128 + CONSTANT 129 + CONSTANT 130 + CONSTANT 131 + CONSTANT 132 + CONSTANT 133 + CONSTANT 134 + CONSTANT 135 + CONSTANT 136 + CONSTANT 137 + CONSTANT 138 + CONSTANT 139 + CONSTANT 140 + CONSTANT 141 + CONSTANT 142 + CONSTANT 143 + CONSTANT 144 + CONSTANT 145 + CONSTANT 146 + CONSTANT 147 + CONSTANT 148 + CONSTANT 149 + CONSTANT 150 + CONSTANT 151 + CONSTANT 152 + CONSTANT 153 + CONSTANT 154 + CONSTANT 155 + CONSTANT 156 + CONSTANT 157 + CONSTANT 158 + CONSTANT 159 + CONSTANT 160 + CONSTANT 161 + CONSTANT 162 + CONSTANT 163 + CONSTANT 164 + CONSTANT 165 + CONSTANT 166 + CONSTANT 167 + CONSTANT 168 + CONSTANT 169 + CONSTANT 170 + CONSTANT 171 + CONSTANT 172 + CONSTANT 173 + CONSTANT 174 + CONSTANT 175 + CONSTANT 176 + CONSTANT 177 + CONSTANT 178 + CONSTANT 179 + CONSTANT 180 + CONSTANT 181 + CONSTANT 182 + CONSTANT 183 + CONSTANT 184 + CONSTANT 185 + CONSTANT 186 + CONSTANT 187 + CONSTANT 188 + CONSTANT 189 + CONSTANT 190 + CONSTANT 191 + CONSTANT 192 + CONSTANT 193 + CONSTANT 194 + CONSTANT 195 + CONSTANT 196 + CONSTANT 197 + CONSTANT 198 + CONSTANT 199 + CONSTANT 200 + CONSTANT 201 + CONSTANT 202 + CONSTANT 203 + CONSTANT 204 + CONSTANT 205 + CONSTANT 206 + CONSTANT 207 + CONSTANT 208 + CONSTANT 209 + CONSTANT 210 + CONSTANT 211 + CONSTANT 212 + CONSTANT 213 + CONSTANT 214 + CONSTANT 215 + CONSTANT 216 + CONSTANT 217 + CONSTANT 218 + CONSTANT 219 + CONSTANT 220 + CONSTANT 221 + CONSTANT 222 + CONSTANT 223 + CONSTANT 224 + CONSTANT 225 + CONSTANT 226 + CONSTANT 227 + CONSTANT 228 + CONSTANT 229 + CONSTANT 230 + CONSTANT 231 + CONSTANT 232 + CONSTANT 233 + CONSTANT 234 + CONSTANT 235 + CONSTANT 236 + CONSTANT 237 + CONSTANT 238 + CONSTANT 239 + CONSTANT 240 + CONSTANT 241 + CONSTANT 242 + CONSTANT 243 + CONSTANT 244 + CONSTANT 245 + CONSTANT 246 + CONSTANT 247 + CONSTANT 248 + CONSTANT 249 + CONSTANT 250 + CONSTANT 251 + CONSTANT 252 + CONSTANT 253 + CONSTANT 254 + CONSTANT 255 + CONSTANT 256 + + CONSTANT 1 + CONSTANT 2 + CONSTANT 3 + CONSTANT 4 + CONSTANT 5 + CONSTANT 6 + CONSTANT 7 + CONSTANT 8 + CONSTANT 9 + CONSTANT 10 + CONSTANT 11 + CONSTANT 12 + CONSTANT 13 + CONSTANT 14 + CONSTANT 15 + CONSTANT 16 + CONSTANT 17 + CONSTANT 18 + CONSTANT 19 + CONSTANT 20 + CONSTANT 21 + CONSTANT 22 + CONSTANT 23 + CONSTANT 24 + CONSTANT 25 + CONSTANT 26 + CONSTANT 27 + CONSTANT 28 + CONSTANT 29 + CONSTANT 30 + CONSTANT 31 + CONSTANT 32 + CONSTANT 33 + CONSTANT 34 + CONSTANT 35 + CONSTANT 36 + CONSTANT 37 + CONSTANT 38 + CONSTANT 39 + CONSTANT 40 + CONSTANT 41 + CONSTANT 42 + CONSTANT 43 + CONSTANT 44 + CONSTANT 45 + CONSTANT 46 + CONSTANT 47 + CONSTANT 48 + CONSTANT 49 + CONSTANT 50 + CONSTANT 51 + CONSTANT 52 + CONSTANT 53 + CONSTANT 54 + CONSTANT 55 + CONSTANT 56 + CONSTANT 57 + CONSTANT 58 + CONSTANT 59 + CONSTANT 60 + CONSTANT 61 + CONSTANT 62 + CONSTANT 63 + CONSTANT 64 + CONSTANT 65 + CONSTANT 66 + CONSTANT 67 + CONSTANT 68 + CONSTANT 69 + CONSTANT 70 + CONSTANT 71 + CONSTANT 72 + CONSTANT 73 + CONSTANT 74 + CONSTANT 75 + CONSTANT 76 + CONSTANT 77 + CONSTANT 78 + CONSTANT 79 + CONSTANT 80 + CONSTANT 81 + CONSTANT 82 + CONSTANT 83 + CONSTANT 84 + CONSTANT 85 + CONSTANT 86 + CONSTANT 87 + CONSTANT 88 + CONSTANT 89 + CONSTANT 90 + CONSTANT 91 + CONSTANT 92 + CONSTANT 93 + CONSTANT 94 + CONSTANT 95 + CONSTANT 96 + CONSTANT 97 + CONSTANT 98 + CONSTANT 99 + CONSTANT 100 + CONSTANT 101 + CONSTANT 102 + CONSTANT 103 + CONSTANT 104 + CONSTANT 105 + CONSTANT 106 + CONSTANT 107 + CONSTANT 108 + CONSTANT 109 + CONSTANT 110 + CONSTANT 111 + CONSTANT 112 + CONSTANT 113 + CONSTANT 114 + CONSTANT 115 + CONSTANT 116 + CONSTANT 117 + CONSTANT 118 + CONSTANT 119 + CONSTANT 120 + CONSTANT 121 + CONSTANT 122 + CONSTANT 123 + CONSTANT 124 + CONSTANT 125 + CONSTANT 126 + CONSTANT 127 + CONSTANT 128 + CONSTANT 129 + CONSTANT 130 + CONSTANT 131 + CONSTANT 132 + CONSTANT 133 + CONSTANT 134 + CONSTANT 135 + CONSTANT 136 + CONSTANT 137 + CONSTANT 138 + CONSTANT 139 + CONSTANT 140 + CONSTANT 141 + CONSTANT 142 + CONSTANT 143 + CONSTANT 144 + CONSTANT 145 + CONSTANT 146 + CONSTANT 147 + CONSTANT 148 + CONSTANT 149 + CONSTANT 150 + CONSTANT 151 + CONSTANT 152 + CONSTANT 153 + CONSTANT 154 + CONSTANT 155 + CONSTANT 156 + CONSTANT 157 + CONSTANT 158 + CONSTANT 159 + CONSTANT 160 + CONSTANT 161 + CONSTANT 162 + CONSTANT 163 + CONSTANT 164 + CONSTANT 165 + CONSTANT 166 + CONSTANT 167 + CONSTANT 168 + CONSTANT 169 + CONSTANT 170 + CONSTANT 171 + CONSTANT 172 + CONSTANT 173 + CONSTANT 174 + CONSTANT 175 + CONSTANT 176 + CONSTANT 177 + CONSTANT 178 + CONSTANT 179 + CONSTANT 180 + CONSTANT 181 + CONSTANT 182 + CONSTANT 183 + CONSTANT 184 + CONSTANT 185 + CONSTANT 186 + CONSTANT 187 + CONSTANT 188 + CONSTANT 189 + CONSTANT 190 + CONSTANT 191 + CONSTANT 192 + CONSTANT 193 + CONSTANT 194 + CONSTANT 195 + CONSTANT 196 + CONSTANT 197 + CONSTANT 198 + CONSTANT 199 + CONSTANT 200 + CONSTANT 201 + CONSTANT 202 + CONSTANT 203 + CONSTANT 204 + CONSTANT 205 + CONSTANT 206 + CONSTANT 207 + CONSTANT 208 + CONSTANT 209 + CONSTANT 210 + CONSTANT 211 + CONSTANT 212 + CONSTANT 213 + CONSTANT 214 + CONSTANT 215 + CONSTANT 216 + CONSTANT 217 + CONSTANT 218 + CONSTANT 219 + CONSTANT 220 + CONSTANT 221 + CONSTANT 222 + CONSTANT 223 + CONSTANT 224 + CONSTANT 225 + CONSTANT 226 + CONSTANT 227 + CONSTANT 228 + CONSTANT 229 + CONSTANT 230 + CONSTANT 231 + CONSTANT 232 + CONSTANT 233 + CONSTANT 234 + CONSTANT 235 + CONSTANT 236 + CONSTANT 237 + CONSTANT 238 + CONSTANT 239 + CONSTANT 240 + CONSTANT 241 + CONSTANT 242 + CONSTANT 243 + CONSTANT 244 + CONSTANT 245 + CONSTANT 246 + CONSTANT 247 + CONSTANT 248 + CONSTANT 249 + CONSTANT 250 + CONSTANT 251 + CONSTANT 252 + CONSTANT 253 + CONSTANT 254 + CONSTANT 255 + CONSTANT 256 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 54011 + Dynamic SQL Error + -SQL error code = -104 + -Invalid command + -Cannot have more than 255 items in DISTINCT / UNION DISTINCT list + """ + +@pytest.mark.version('>=4.0') +def test_core_6205_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6206.py b/tests/bugs/test_core_6206.py new file mode 100644 index 00000000..1ebb8e0d --- /dev/null +++ b/tests/bugs/test_core_6206.py @@ -0,0 +1,64 @@ +#coding:utf-8 +# +# id: bugs.core_6206 +# title: VARCHAR of insufficient length used for set bind of decfloat to varchar +# decription: +# Confirmed bug on 4.0.0.1685 +# Checked on 4.0.0.1691: OK, 1.165s. +# +# 26.06.2020: changed SET BIND argument from numeric(38) to INT128, adjusted output +# (letter from Alex, 25.06.2020 17:56; needed after discuss CORE-6342). +# Checked on 4.0.0.2078. +# +# tracker_id: CORE-6206 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('charset.*', ''), ('^((?!(sqltype)).)*$', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set sqlda_display on; + set list on; + + set bind of decfloat to char; + select -1.234567890123456789012345678901234E+6144 as decfloat_to_char from rdb$database; + + set bind of decfloat to varchar; + select -1.234567890123456789012345678901234E+6144 as decfloat_to_varchar from rdb$database; + + --set bind of numeric(38) to char; + set bind of int128 to char; + select 12345678901234567890123456789012345678 as n38_to_char from rdb$database; + + --set bind of numeric(38) to varchar; + set bind of int128 to char; + select 12345678901234567890123456789012345678 as n38_to_varchar from rdb$database; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 01: sqltype: 452 TEXT scale: 0 subtype: 0 len: 42 + 01: sqltype: 448 VARYING scale: 0 subtype: 0 len: 42 + 01: sqltype: 452 TEXT scale: 0 subtype: 0 len: 47 + 01: sqltype: 452 TEXT scale: 0 subtype: 0 len: 47 + """ + +@pytest.mark.version('>=4.0') +def test_core_6206_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6208.py b/tests/bugs/test_core_6208.py new file mode 100644 index 00000000..bf08b5fb --- /dev/null +++ b/tests/bugs/test_core_6208.py @@ -0,0 +1,278 @@ +#coding:utf-8 +# +# id: bugs.core_6208 +# title: Grant lost in security.db after backup/restore cycle +# decription: +# Ticket shows scenario with local protocol which allows security.db to be overwritten. +# This can not be done when we work using remote protocol, but we can exploit ability +# to change security DB. This is done by specifying parameter SecurityDatabase in databases.conf +# and its value is equal to alias of test database that we use: +# tmp_6208 = { +# SecurityDatabase = tmp_6208 +# } +# +# Test DB is named here 'fdb_init' and it is created by file copy of $FB_HOME\\securityN.db +# Then file 'databases.conf' as adjusted so that SecurityDatabase will point to this test DB. +# After this we can connect to $fdb_ini, create user (his name: 'TMP6208DBA') and give him +# privilege to create database. +# +# Futher, we make backup of this test DB and restore it. New database name is 'fdb_rest'. +# After this, we change state of test DB to full shutdown and overwrite it by $fdb_rest. +# Finaly, we make connection to this DB (that was just overwritten) and check that output +# of 'show grants' command contains: +# +# GRANT CREATE DATABASE TO USER TMP6208DBA +# +# Confirmed lost of grant on 4.0.0.1691 (build 14-dec-2019). +# +# 26.08.2020. +# IT CRUSIAL FOR THIS TEST DO MAKE ALL RESTORE AND FURTHER ACTIONS IN LOCAL/EMBEDDED PROTOCOL. +# Discissed with Alex, see letter 24.08.2020 19:49. +# +# Main problem is in SuperClassic: after restore finish, we can not connect to this DB by TCP, +# error is +# "Statement failed, SQLSTATE = 08006 / Error occurred during login, please check server firebird.log for details" +# Server log contains in this case: "Srp Server / connection shutdown / Database is shutdown." +# +# Checked initially on 4.0.0.1712 SC: 11s, 4.0.0.1714 SS, CS (7s, 16s). +# Checked again 26.08.2020 on 4.0.0.2173 SS/CS/SC. +# +# tracker_id: CORE-6208 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('\t+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import time +# import subprocess +# import shutil +# from subprocess import PIPE +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# this_db = db_conn.database_name +# fb_vers = str(db_conn.engine_version)[:1] # character for security.db file: engine = 4.0 --> '4' +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# def svc_get_fb_log( fb_home, f_fb_log ): +# +# global subprocess +# subprocess.call( [ fb_home + "fbsvcmgr", +# "localhost:service_mgr", +# "action_get_fb_log" +# ], +# stdout=f_fb_log, stderr=subprocess.STDOUT +# ) +# return +# +# svc = services.connect(host='localhost', user= user_name, password= user_password) +# fb_home = svc.get_home_directory() +# svc.close() +# dbconf = os.path.join(fb_home, 'databases.conf') +# dbcbak = os.path.join(fb_home, 'databases.bak') +# +# sec_db = context['isc4_path'] +# +# fdb_init = os.path.join(context['temp_directory'],'tmp_6208_initial.fdb') +# fdb_bkup = os.path.join(context['temp_directory'],'tmp_6208_initial.fbk') +# fdb_rest = os.path.join(context['temp_directory'],'tmp_6208_restored.fdb') +# +# cleanup( (fdb_init, fdb_rest) ) +# +# shutil.copy2( sec_db, fdb_init ) +# +# # Resut: fb_home is full path to FB instance home (with trailing slash). +# shutil.copy2( dbconf, dbcbak) +# +# alias_data=''' +# # Added temporarily for executing test core_6208.fbt +# tmp_6208 = %(fdb_init)s { +# # RemoteAccess = true +# SecurityDatabase = tmp_6208 +# } +# ''' % locals() +# +# f_dbconf=open( dbconf,'a', buffering = 0) +# f_dbconf.seek(0, 2) +# f_dbconf.write(alias_data) +# flush_and_close( f_dbconf ) +# +# sql_init=''' +# set bail on; +# create or alter user tmp6208dba password '123' using plugin Srp; +# grant create database to user tmp6208dba; +# alter database set linger to 0; +# commit; +# ''' +# runProgram('isql',[ fdb_init ], sql_init) +# +# ######################################################################### +# +# f_backup_log = open( os.path.join(context['temp_directory'],'tmp_6208.backup.log'), 'w', buffering = 0) +# f_backup_err = open( ''.join( (os.path.splitext(f_backup_log.name)[0], '.err' ) ), 'w', buffering = 0) +# +# subprocess.call( [ context['gfix_path'], '-h', '54321', fdb_init ], stdout = f_backup_log, stderr = f_backup_err) +# subprocess.call( [ context['gstat_path'], '-h', fdb_init ], stdout = f_backup_log, stderr = f_backup_err) +# subprocess.call( [ context['gbak_path'], '-b', fdb_init, fdb_bkup, '-v', '-st', 'tdrw' ], stdout = f_backup_log, stderr = f_backup_err) +# +# flush_and_close( f_backup_log ) +# flush_and_close( f_backup_err ) +# +# ######################################################################## +# +# cleanup( (fdb_rest,) ) +# +# f_restore_log = open( os.path.join(context['temp_directory'],'tmp_6208.restore.log'), 'w', buffering = 0) +# f_restore_err = open( ''.join( (os.path.splitext(f_restore_log.name)[0], '.err' ) ), 'w', buffering = 0) +# +# subprocess.call( [ context['gbak_path'], '-c', fdb_bkup, fdb_rest, '-v', '-st', 'tdrw' ], stdout = f_restore_log, stderr = f_restore_err) +# +# flush_and_close( f_restore_log ) +# flush_and_close( f_restore_err ) +# +# ######################################################################## +# +# runProgram('gfix',['-shut', 'full', '-force', '0', fdb_init] ) +# runProgram('gfix',['-shut', 'full', '-force', '0', fdb_rest] ) +# +# shutil.move( fdb_rest, fdb_init ) +# +# runProgram('gfix',['-online', fdb_init] ) +# +# sql_chk=''' +# set bail on; +# set list on; +# -- set echo on; +# -- ########################## +# -- SuperClassic: +# -- Statement failed, SQLSTATE = 08006 +# -- Error occurred during login, please check server firebird.log for details +# -- firebird.log: +# -- Srp Server +# -- connection shutdown +# -- Database is shutdown. +# -- ########################## +# -- connect 'localhost:%(fdb_init)s' user tmp6208dba password '123'; +# connect '%(fdb_init)s' user tmp6208dba password '123'; +# select +# d.mon$owner as "mon$database.mon$owner" +# ,d.mon$sec_database as "mon$database.mon$sec_database" +# ,r.rdb$linger as "rdb$database.rdb$linger" +# --,a.mon$remote_protocol as "mon$attachments.mon$remote_protocol" +# ,current_user as whoami +# from mon$database d +# join mon$attachments a on a.mon$attachment_id = current_connection +# cross join rdb$database r +# +# ; +# +# select +# s.sec$user_name as "sec$users.sec_user" +# ,c.sec$user_type as "sec$db_creators.sec$user_type" +# from sec$users s +# left join sec$db_creators c on s.sec$user_name = c.sec$user +# where sec$user_name = upper('TMP6208DBA'); +# rollback; +# +# connect '%(fdb_init)s'; +# drop user tmp6208dba using plugin Srp; +# commit; +# ''' % locals() +# +# f_chk_sql = open( os.path.join(context['temp_directory'],'tmp_6208_chk.sql'), 'w', buffering = 0) +# f_chk_sql.write(sql_chk) +# flush_and_close( f_chk_sql ) +# +# f_chk_log = open( os.path.join(context['temp_directory'],'tmp_6208_chk.log'), 'w', buffering = 0) +# subprocess.call( [context['isql_path'], "-q", "-i", f_chk_sql.name ], stdout = f_chk_log, stderr = subprocess.STDOUT) +# flush_and_close( f_chk_log ) +# +# #######runProgram('isql',[ fdb_init ], 'drop user tmp6208dba using plugin Srp; commit;') +# +# f_shut_log = open( os.path.join(context['temp_directory'],'tmp_6208_shut.log'), 'w', buffering = 0) +# subprocess.call( [ context['gfix_path'], "-shut", "full", "-force", "0", fdb_init ], stdout = f_shut_log, stderr = subprocess.STDOUT) +# subprocess.call( [ context['gstat_path'], "-h", fdb_init ], stdout = f_shut_log, stderr = subprocess.STDOUT) +# flush_and_close( f_shut_log ) +# +# +# # Restore previous content: +# shutil.move( dbcbak, dbconf ) +# +# with open(f_chk_log.name,'r') as f: +# for line in f: +# print(line) +# +# +# # cleanup: +# ########## +# time.sleep(1) +# cleanup( (f_backup_log, f_backup_err, f_restore_log, f_restore_err, f_chk_sql, f_chk_log, f_shut_log, fdb_init, fdb_bkup) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + mon$database.mon$owner SYSDBA + mon$database.mon$sec_database Self + rdb$database.rdb$linger 0 + WHOAMI TMP6208DBA + sec$users.sec_user TMP6208DBA + sec$db_creators.sec$user_type 8 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_6208_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6211.py b/tests/bugs/test_core_6211.py new file mode 100644 index 00000000..49cd9884 --- /dev/null +++ b/tests/bugs/test_core_6211.py @@ -0,0 +1,132 @@ +#coding:utf-8 +# +# id: bugs.core_6211 +# title: Command "ISQL -X" can not extract ROLE name when use multi-byte charset for connection (4.x only is affected) +# decription: +# Checked on 4.0.0.1713: 1.219s. +# +# tracker_id: CORE-6211 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import difflib +# import subprocess +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# this_db = db_conn.database_name +# +# #-------------------------------------------- +# +# 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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# sql_ddl=''' +# set bail on; +# create role Nachalnik4ukotkiNachalnik4ukotkiNachalnik4ukotkiNachalnik4ukotk; -- ASCII only +# create role "НачальникЧукоткиНачальникЧукоткиНачальникЧукоткиНачальникЧукотк"; -- Cyrillic, two bytes per character +# create role "‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰"; -- U+2030 PER MILLE SIGN, three bytes per character: E2 80 B0 +# create role "🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀"; -- U+1F680 ROCKET, four bytes per character: F0 9F 9A 80 +# commit; +# set list on; +# set count on; +# select rdb$role_name as r_name from rdb$roles where rdb$system_flag is distinct from 1; +# ''' +# +# f_init_ddl=open( os.path.join(context['temp_directory'],'tmp_6211_init_ddl.sql'), 'w', buffering = 0) +# f_init_ddl.write(sql_ddl) +# flush_and_close( f_init_ddl ) +# +# f_init_log = open( os.path.join(context['temp_directory'],'tmp_6211_init_ddl.log'), 'w', buffering = 0) +# f_init_err = open( os.path.join(context['temp_directory'],'tmp_6211_init_ddl.err'), 'w', buffering = 0) +# subprocess.call( [ context['isql_path'], dsn, '-ch', 'utf8', '-i', f_init_ddl.name ], stdout = f_init_log,stderr = f_init_err) +# flush_and_close( f_init_log ) +# flush_and_close( f_init_err ) +# +# f_meta_log1 = open( os.path.join(context['temp_directory'],'tmp_6211_extracted_meta.sql'), 'w', buffering = 0) +# f_meta_err1 = open( os.path.join(context['temp_directory'],'tmp_6211_extracted_meta.err'), 'w', buffering = 0) +# subprocess.call( [ context['isql_path'], dsn, '-x', '-ch', 'utf8' ], stdout = f_meta_log1, stderr = f_meta_err1) +# flush_and_close( f_meta_log1 ) +# flush_and_close( f_meta_err1 ) +# +# f_list=(f_init_err, f_meta_err1,) +# for i in range(len(f_list)): +# f_name=f_list[i].name +# if os.path.getsize(f_name) > 0: +# with open( f_name,'r') as f: +# for line in f: +# print("Unexpected STDERR, file "+f_name+": "+line) +# +# with open( f_meta_log1.name,'r') as f: +# for line in f: +# if 'CREATE ROLE' in line: +# print(line) +# +# # cleanup: +# ########## +# time.sleep(1) +# cleanup( ( f_init_ddl, f_init_log, f_init_err, f_meta_err1, f_meta_log1, f_meta_err1 ) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CREATE ROLE NACHALNIK4UKOTKINACHALNIK4UKOTKINACHALNIK4UKOTKINACHALNIK4UKOTK; + CREATE ROLE "НачальникЧукоткиНачальникЧукоткиНачальникЧукоткиНачальникЧукотк"; + CREATE ROLE "‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰"; + CREATE ROLE "🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀"; + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_6211_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6216.py b/tests/bugs/test_core_6216.py new file mode 100644 index 00000000..c8eaf220 --- /dev/null +++ b/tests/bugs/test_core_6216.py @@ -0,0 +1,107 @@ +#coding:utf-8 +# +# id: bugs.core_6216 +# title: request size limit exceeded when selecting from a table with large number of indicies +# decription: +# Confirmed bug on 3.0.6.33240. +# Checked on 3.0.6.33273, 4.0.0.1810 - works fine. +# +# tracker_id: CORE-6216 +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table TABLE_TEST + ( + FIELD0 bigint not null, + FIELD1 bigint, + FIELD2 bigint, + FIELD3 bigint, + FIELD4 bigint, + FIELD5 bigint, + FIELD6 bigint, + FIELD7 bigint, + FIELD8 bigint, + FIELD9 bigint, + FIELD10 bigint, + FIELD11 bigint, + FIELD12 bigint, + FIELD13 bigint, + FIELD14 bigint, + FIELD15 bigint, + FIELD16 bigint, + FIELD17 bigint, + FIELD18 bigint, + FIELD19 bigint, + FIELD20 bigint, + FIELD21 bigint, + constraint PK_TABLE_TEST primary key (FIELD0) + ); + + create index TABLE_TEST_FIELD2 on TABLE_TEST(FIELD2); + create index TABLE_TEST_FIELD3 on TABLE_TEST(FIELD3); + create index TABLE_TEST_FIELD4 on TABLE_TEST(FIELD4); + create index TABLE_TEST_FIELD5 on TABLE_TEST(FIELD5); + create index TABLE_TEST_FIELD6 on TABLE_TEST(FIELD6); + create index TABLE_TEST_FIELD7 on TABLE_TEST(FIELD6); + create index TABLE_TEST_FIELD8 on TABLE_TEST(FIELD8); + create index TABLE_TEST_FIELD9 on TABLE_TEST(FIELD9); + create index TABLE_TEST_FIELD10 on TABLE_TEST(FIELD10); + create index TABLE_TEST_FIELD11 on TABLE_TEST(FIELD11); + create index TABLE_TEST_FIELD12 on TABLE_TEST(FIELD12); + create index TABLE_TEST_FIELD13 on TABLE_TEST(FIELD13); + create index TABLE_TEST_FIELD14 on TABLE_TEST(FIELD14); + create index TABLE_TEST_FIELD15 on TABLE_TEST(FIELD15); + create index TABLE_TEST_FIELD16 on TABLE_TEST(FIELD16); + create index TABLE_TEST_FIELD17 on TABLE_TEST(FIELD17); + create index TABLE_TEST_FIELD18 on TABLE_TEST(FIELD18); + create index TABLE_TEST_FIELD19 on TABLE_TEST(FIELD19); + create index TABLE_TEST_FIELD20 on TABLE_TEST(FIELD20); + create index TABLE_TEST_FIELD21 on TABLE_TEST(FIELD21); + + set list on; + + SELECT + (select field1 + from TABLE_TEST t + where t.field1 in (90,288,991020000000001,991020000000002,272,316,368,376,225,254,262,133,237,361,210,384,336,275,285,339,346,10,17,52,53,68,108,109,116,125,126,142,153,155,180,189,205,206,208,216,218,221,223,238,240,256,266,274,276,289,291,293,334,337,343,352,369,377,990004324,3,5,6,15,16,28,33,36,25,111,129,137,235,284,350,363,371,207,209,224,228,239,263,281,282,96,43,226,236,280,331,333,375,67,178,181,366,391,22,185,4,87,134,166,164,103,197,39,98,172,261,386,106,118,345,392,40,122,184,257,200,379,367,143,194,85,18,30,123,139,147,296,297,45,991020000000007,349,38,144,145,146,170,182,187,190,233,271,277,299,300,389,95,83,312,330,232,267,310,241,227,302,303,304,305,306,307,308,311,314,319,321,322,324,327,335,340,342,351,353,354,355,356,357,358,359,360,365,373,381,388,991020000000005,990000000000016,990000000000101,990000000000102,990000000000201,990000000000202,990000000000203,990000000002001,990000000002002,990000000002003,990000000002004,990000000002005,990000000002006,990000000002007,990000000002008,990000000002009,990000000002010,990000000002011,990000000002012,990000000002013,990000000002014,990000000002015,990000000002016,990000000002017,990000000002018,990000000002019,990000000002020,990000000002021,990000000002022,990000000002023,990000000002024,990000000002025,990000000002027,990000000002028,990000000002030,990000000002031,990000000002033,990000000002034,990000000002038,990000000002039,990000000002040,990000000002041,90,288,991020000000001,991020000000002,272,316,368,376,225,254,262,133,237,361,210,384,336,275,285,339,346,10,17,52,53,68,108,109,116,125,126,142,153,155,180,189,205,206,208,216,218,221,223,238,240,256,266,274,276,289,291,293,334,337,343,352,369,377,990004324,3,5,6,15,16,28,33,36,25,111,129,137,235,284,350,363,371,207,209,224,228,239,263,281,282,96,43,226,236,280,331,333,375,67,178,181,366,391,22,185,4,87,134,166,164,103,197,39,98,172,261,386,106,118,345,392,40,122,184,257,200,379,367,143,194,85,18,30,123,139,147,296,297,45,991020000000007,349,38,144,145,146,170,182,187,190,233,271,277,299,300,389,95,83,312,330,232,267,310,241,227,302,303,304,305,306,307,308,311,314,319,321,322,324,327,335,340,342,351,353,354,355,356,357,358,359,360,365,373,381,388,991020000000005,990000000000016,990000000000101,990000000000102,990000000000201,990000000000202,990000000000203,990000000002001,990000000002002,990000000002003,990000000002004,990000000002005,990000000002006,990000000002007,990000000002008,990000000002009,990000000002010,990000000002011,990000000002012,990000000002013,990000000002014,990000000002015,990000000002016,990000000002017,990000000002018,990000000002019,990000000002020,990000000002021,990000000002022,990000000002023,990000000002024,990000000002025,990000000002027,990000000002028,990000000002030,990000000002031,990000000002033,990000000002034,990000000002038,990000000002039,990000000002040,99000000000204190,288,991020000000001,991020000000002,272,316,368,376,225,254,262,133,237,361,210,384,336,275,285,339,346,10,17,52,53,68,108,109,116,125,126,142,153,155,180,189,205,206,208,216,218,221,223,238,240,256,266,274,276,289,291,293,334,337,343,352,369,377,990004324,3,5,6,15,16,28,33,36,25,111,129,137,235,284,350,363,371,207,209,224,228,239,263,281,282,96,43,226,236,280,331,333,375,67,178,181,366,391,22,185,4,87,134,166,164,103,197,39,98,172,261,386,106,118,345,392,40,122,184,257,200,379,367,143,194,85,18,30,123,139,147,296,297,45,991020000000007,349,38,144,145,146,170,182,187,190,233,271,277,299,300,389,95,83,312,330,232,267,310,241,227,302,303,304,305,306,307,308,311,314,319,321,322,324,327,335,340,342,351,353,354,355,356,357,358,359,360,365,373,381,388,991020000000005,990000000000016,990000000000101,990000000000102,990000000000201,990000000000202,990000000000203,990000000002001,990000000002002,990000000002003,990000000002004,990000000002005,990000000002006,990000000002007,990000000002008,990000000002009,990000000002010,990000000002011,990000000002012,990000000002013,990000000002014,990000000002015,990000000002016,990000000002017,990000000002018,990000000002019,990000000002020,990000000002021,990000000002022,990000000002023,990000000002024,990000000002025,990000000002027,990000000002028,990000000002030,990000000002031,990000000002033,990000000002034,990000000002038,990000000002039,990000000002040,99000000000204190,288,991020000000001,991020000000002,272,316,368,376,225,254,262,133,237,361,210,384,336,275,285,339,346,10,17,52,53,68,108,109,116,125,126,142,153,155,180,189,205,206,208,216,218,221,223,238,240,256,266,274,276,289,291,293,334,337,343,352,369,377,990004324,3,5,6,15,16,28,33,36,25,111,129,137,235,284,350,363,371,207,209,224,228,239,263,281,282,96,43,226,236,280,331,333,375,67,178,181,366,391,22,185,4,87,134,166,164,103,197,39,98,172,261,386,106,118,345,392,40,122,184,257,200,379,367,143,194,85,18,30,123,139,147,296,297,45,991020000000007,349,38,144,145,146,170,182,187,190,233,271,277,299,300,389,95,83,312,330,232,267,310,241,227,302,303,304,305,306,307,308,311,314,319,321,322,324,327,335,340,342,351,353,354,355,356,357,358,359,360,365,373,381,388,991020000000005,990000000000016,990000000000101,990000000000102,990000000000201,990000000000202,990000000000203,990000000002001,990000000002002,990000000002003,990000000002004,990000000002005,990000000002006,990000000002007,990000000002008,990000000002009,990000000002010,990000000002011,990000000002012,990000000002013,990000000002014,990000000002015,990000000002016,990000000002017,990000000002018,990000000002019,990000000002020,990000000002021,990000000002022,990000000002023,990000000002024,990000000002025,990000000002027,990000000002028,990000000002030,990000000002031,990000000002033,990000000002034,990000000002038,990000000002039,990000000002040,99000000000204190,288,991020000000001,991020000000002,272,316,368,376,225,254,262,133,237,361,210,384,336,275,285,339,346,10,17,52,53,68,108,109,116,125,126,142,153,155,180,189,205,206,208,216,218,221,223,238,240,256,266,274,276,289,291,293,334,337,343,352,369,377,990004324,3,5,6,15,16,28,33,36,25,111,129,137,235,284,350,363,371,207,209,224,228,239,263,281,282,96,43,226,236,280,331,333,375,67,178,181,366,391,22,185,4,87,134,166,164,103,197,39,98,172,261,386,106,118,345,392,40,122,184,257,200,379,367,143,194,85,18,30,123,139,147,296,297,45,991020000000007,349,38,144,145,146,170,182,187,190,233,271,277,299,300,389,95,83,312,330,232,267,310,241,227,302,303,304,305,306,307,308,311,314,319,321,322,324,327,335,340,342,351,353,354,355,356,357,358,359,360,365,373,381,388,991020000000005,990000000000016,990000000000101,990000000000102,990000000000201,990000000000202,990000000000203,990000000002001,990000000002002,990000000002003,990000000002004,990000000002005,990000000002006,990000000002007,990000000002008,990000000002009,990000000002010,990000000002011,990000000002012,990000000002013,990000000002014,990000000002015,990000000002016,990000000002017,990000000002018,990000000002019,990000000002020,990000000002021,990000000002022,990000000002023,990000000002024,990000000002025,990000000002027,990000000002028,990000000002030,990000000002031,990000000002033,990000000002034,990000000002038,990000000002039,990000000002040,99000000000204190,288,991020000000001,991020000000002,272,316,368,376,225,254,262,133,237,361,210,384,336,275,285,339,346,10,17,52,53,68,108,109,116,125,126,142,153,155,180,189,205,206,208,216,218,221,223,238,240,256,266,274,276,289,291,293,334,337,343,352,369,377,990004324,3,5,6,15,16,28,33,36,25,111,129,137,235,284,350,363,371,207,209,224,228,239,263,281,282,96,43,226,236,280,331,333,375,67,178,181,366,391,22,185,4,87,134,166,164,103,197,39,98,172,261,386,106,118,345,392,40,122,184,257,200,379,367,143,194,85,18,30,123,139,147,296,297,45,991020000000007,349,38,144,145,146,170,182,187,190,233,271,277,299,300,389,95,83,312,330,232,267,310,241,227,302,303,304,305,306,307,308,311,314,319,321,322,324,327,335,340,342,351,353,354,355,356,357,358,359,360,365,373,381,388,991020000000005,990000000000016,990000000000101,990000000000102,990000000000201,990000000000202,990000000000203,990000000002001,990000000002002,990000000002003,990000000002004,990000000002005,990000000002006,990000000002007,990000000002008,990000000002009,990000000002010,990000000002011,990000000002012,990000000002013,990000000002014,990000000002015,990000000002016,990000000002017,990000000002018,990000000002019,990000000002020,990000000002021,990000000002022,990000000002023,990000000002024,990000000002025,990000000002027,990000000002028,990000000002030,990000000002031,990000000002033,990000000002034,990000000002038,990000000002039,990000000002040,990000000002041) + ), + (select field1 + from TABLE_TEST t + where t.field1 in (90,288,991020000000001,991020000000002,272,316,368,376,225,254,262,133,237,361,210,384,336,275,285,339,346,10,17,52,53,68,108,109,116,125,126,142,153,155,180,189,205,206,208,216,218,221,223,238,240,256,266,274,276,289,291,293,334,337,343,352,369,377,990004324,3,5,6,15,16,28,33,36,25,111,129,137,235,284,350,363,371,207,209,224,228,239,263,281,282,96,43,226,236,280,331,333,375,67,178,181,366,391,22,185,4,87,134,166,164,103,197,39,98,172,261,386,106,118,345,392,40,122,184,257,200,379,367,143,194,85,18,30,123,139,147,296,297,45,991020000000007,349,38,144,145,146,170,182,187,190,233,271,277,299,300,389,95,83,312,330,232,267,310,241,227,302,303,304,305,306,307,308,311,314,319,321,322,324,327,335,340,342,351,353,354,355,356,357,358,359,360,365,373,381,388,991020000000005,990000000000016,990000000000101,990000000000102,990000000000201,990000000000202,990000000000203,990000000002001,990000000002002,990000000002003,990000000002004,990000000002005,990000000002006,990000000002007,990000000002008,990000000002009,990000000002010,990000000002011,990000000002012,990000000002013,990000000002014,990000000002015,990000000002016,990000000002017,990000000002018,990000000002019,990000000002020,990000000002021,990000000002022,990000000002023,990000000002024,990000000002025,990000000002027,990000000002028,990000000002030,990000000002031,990000000002033,990000000002034,990000000002038,990000000002039,990000000002040,990000000002041,90,288,991020000000001,991020000000002,272,316,368,376,225,254,262,133,237,361,210,384,336,275,285,339,346,10,17,52,53,68,108,109,116,125,126,142,153,155,180,189,205,206,208,216,218,221,223,238,240,256,266,274,276,289,291,293,334,337,343,352,369,377,990004324,3,5,6,15,16,28,33,36,25,111,129,137,235,284,350,363,371,207,209,224,228,239,263,281,282,96,43,226,236,280,331,333,375,67,178,181,366,391,22,185,4,87,134,166,164,103,197,39,98,172,261,386,106,118,345,392,40,122,184,257,200,379,367,143,194,85,18,30,123,139,147,296,297,45,991020000000007,349,38,144,145,146,170,182,187,190,233,271,277,299,300,389,95,83,312,330,232,267,310,241,227,302,303,304,305,306,307,308,311,314,319,321,322,324,327,335,340,342,351,353,354,355,356,357,358,359,360,365,373,381,388,991020000000005,990000000000016,990000000000101,990000000000102,990000000000201,990000000000202,990000000000203,990000000002001,990000000002002,990000000002003,990000000002004,990000000002005,990000000002006,990000000002007,990000000002008,990000000002009,990000000002010,990000000002011,990000000002012,990000000002013,990000000002014,990000000002015,990000000002016,990000000002017,990000000002018,990000000002019,990000000002020,990000000002021,990000000002022,990000000002023,990000000002024,990000000002025,990000000002027,990000000002028,990000000002030,990000000002031,990000000002033,990000000002034,990000000002038,990000000002039,990000000002040,99000000000204190,288,991020000000001,991020000000002,272,316,368,376,225,254,262,133,237,361,210,384,336,275,285,339,346,10,17,52,53,68,108,109,116,125,126,142,153,155,180,189,205,206,208,216,218,221,223,238,240,256,266,274,276,289,291,293,334,337,343,352,369,377,990004324,3,5,6,15,16,28,33,36,25,111,129,137,235,284,350,363,371,207,209,224,228,239,263,281,282,96,43,226,236,280,331,333,375,67,178,181,366,391,22,185,4,87,134,166,164,103,197,39,98,172,261,386,106,118,345,392,40,122,184,257,200,379,367,143,194,85,18,30,123,139,147,296,297,45,991020000000007,349,38,144,145,146,170,182,187,190,233,271,277,299,300,389,95,83,312,330,232,267,310,241,227,302,303,304,305,306,307,308,311,314,319,321,322,324,327,335,340,342,351,353,354,355,356,357,358,359,360,365,373,381,388,991020000000005,990000000000016,990000000000101,990000000000102,990000000000201,990000000000202,990000000000203,990000000002001,990000000002002,990000000002003,990000000002004,990000000002005,990000000002006,990000000002007,990000000002008,990000000002009,990000000002010,990000000002011,990000000002012,990000000002013,990000000002014,990000000002015,990000000002016,990000000002017,990000000002018,990000000002019,990000000002020,990000000002021,990000000002022,990000000002023,990000000002024,990000000002025,990000000002027,990000000002028,990000000002030,990000000002031,990000000002033,990000000002034,990000000002038,990000000002039,990000000002040,99000000000204190,288,991020000000001,991020000000002,272,316,368,376,225,254,262,133,237,361,210,384,336,275,285,339,346,10,17,52,53,68,108,109,116,125,126,142,153,155,180,189,205,206,208,216,218,221,223,238,240,256,266,274,276,289,291,293,334,337,343,352,369,377,990004324,3,5,6,15,16,28,33,36,25,111,129,137,235,284,350,363,371,207,209,224,228,239,263,281,282,96,43,226,236,280,331,333,375,67,178,181,366,391,22,185,4,87,134,166,164,103,197,39,98,172,261,386,106,118,345,392,40,122,184,257,200,379,367,143,194,85,18,30,123,139,147,296,297,45,991020000000007,349,38,144,145,146,170,182,187,190,233,271,277,299,300,389,95,83,312,330,232,267,310,241,227,302,303,304,305,306,307,308,311,314,319,321,322,324,327,335,340,342,351,353,354,355,356,357,358,359,360,365,373,381,388,991020000000005,990000000000016,990000000000101,990000000000102,990000000000201,990000000000202,990000000000203,990000000002001,990000000002002,990000000002003,990000000002004,990000000002005,990000000002006,990000000002007,990000000002008,990000000002009,990000000002010,990000000002011,990000000002012,990000000002013,990000000002014,990000000002015,990000000002016,990000000002017,990000000002018,990000000002019,990000000002020,990000000002021,990000000002022,990000000002023,990000000002024,990000000002025,990000000002027,990000000002028,990000000002030,990000000002031,990000000002033,990000000002034,990000000002038,990000000002039,990000000002040,99000000000204190,288,991020000000001,991020000000002,272,316,368,376,225,254,262,133,237,361,210,384,336,275,285,339,346,10,17,52,53,68,108,109,116,125,126,142,153,155,180,189,205,206,208,216,218,221,223,238,240,256,266,274,276,289,291,293,334,337,343,352,369,377,990004324,3,5,6,15,16,28,33,36,25,111,129,137,235,284,350,363,371,207,209,224,228,239,263,281,282,96,43,226,236,280,331,333,375,67,178,181,366,391,22,185,4,87,134,166,164,103,197,39,98,172,261,386,106,118,345,392,40,122,184,257,200,379,367,143,194,85,18,30,123,139,147,296,297,45,991020000000007,349,38,144,145,146,170,182,187,190,233,271,277,299,300,389,95,83,312,330,232,267,310,241,227,302,303,304,305,306,307,308,311,314,319,321,322,324,327,335,340,342,351,353,354,355,356,357,358,359,360,365,373,381,388,991020000000005,990000000000016,990000000000101,990000000000102,990000000000201,990000000000202,990000000000203,990000000002001,990000000002002,990000000002003,990000000002004,990000000002005,990000000002006,990000000002007,990000000002008,990000000002009,990000000002010,990000000002011,990000000002012,990000000002013,990000000002014,990000000002015,990000000002016,990000000002017,990000000002018,990000000002019,990000000002020,990000000002021,990000000002022,990000000002023,990000000002024,990000000002025,990000000002027,990000000002028,990000000002030,990000000002031,990000000002033,990000000002034,990000000002038,990000000002039,990000000002040,99000000000204190,288,991020000000001,991020000000002,272,316,368,376,225,254,262,133,237,361,210,384,336,275,285,339,346,10,17,52,53,68,108,109,116,125,126,142,153,155,180,189,205,206,208,216,218,221,223,238,240,256,266,274,276,289,291,293,334,337,343,352,369,377,990004324,3,5,6,15,16,28,33,36,25,111,129,137,235,284,350,363,371,207,209,224,228,239,263,281,282,96,43,226,236,280,331,333,375,67,178,181,366,391,22,185,4,87,134,166,164,103,197,39,98,172,261,386,106,118,345,392,40,122,184,257,200,379,367,143,194,85,18,30,123,139,147,296,297,45,991020000000007,349,38,144,145,146,170,182,187,190,233,271,277,299,300,389,95,83,312,330,232,267,310,241,227,302,303,304,305,306,307,308,311,314,319,321,322,324,327,335,340,342,351,353,354,355,356,357,358,359,360,365,373,381,388,991020000000005,990000000000016,990000000000101,990000000000102,990000000000201,990000000000202,990000000000203,990000000002001,990000000002002,990000000002003,990000000002004,990000000002005,990000000002006,990000000002007,990000000002008,990000000002009,990000000002010,990000000002011,990000000002012,990000000002013,990000000002014,990000000002015,990000000002016,990000000002017,990000000002018,990000000002019,990000000002020,990000000002021,990000000002022,990000000002023,990000000002024,990000000002025,990000000002027,990000000002028,990000000002030,990000000002031,990000000002033,990000000002034,990000000002038,990000000002039,990000000002040,990000000002041) + ), + (select field1 + from TABLE_TEST t + where t.field1 in (90,288,991020000000001,991020000000002,272,316,368,376,225,254,262,133,237,361,210,384,336,275,285,339,346,10,17,52,53,68,108,109,116,125,126,142,153,155,180,189,205,206,208,216,218,221,223,238,240,256,266,274,276,289,291,293,334,337,343,352,369,377,990004324,3,5,6,15,16,28,33,36,25,111,129,137,235,284,350,363,371,207,209,224,228,239,263,281,282,96,43,226,236,280,331,333,375,67,178,181,366,391,22,185,4,87,134,166,164,103,197,39,98,172,261,386,106,118,345,392,40,122,184,257,200,379,367,143,194,85,18,30,123,139,147,296,297,45,991020000000007,349,38,144,145,146,170,182,187,190,233,271,277,299,300,389,95,83,312,330,232,267,310,241,227,302,303,304,305,306,307,308,311,314,319,321,322,324,327,335,340,342,351,353,354,355,356,357,358,359,360,365,373,381,388,991020000000005,990000000000016,990000000000101,990000000000102,990000000000201,990000000000202,990000000000203,990000000002001,990000000002002,990000000002003,990000000002004,990000000002005,990000000002006,990000000002007,990000000002008,990000000002009,990000000002010,990000000002011,990000000002012,990000000002013,990000000002014,990000000002015,990000000002016,990000000002017,990000000002018,990000000002019,990000000002020,990000000002021,990000000002022,990000000002023,990000000002024,990000000002025,990000000002027,990000000002028,990000000002030,990000000002031,990000000002033,990000000002034,990000000002038,990000000002039,990000000002040,990000000002041,90,288,991020000000001,991020000000002,272,316,368,376,225,254,262,133,237,361,210,384,336,275,285,339,346,10,17,52,53,68,108,109,116,125,126,142,153,155,180,189,205,206,208,216,218,221,223,238,240,256,266,274,276,289,291,293,334,337,343,352,369,377,990004324,3,5,6,15,16,28,33,36,25,111,129,137,235,284,350,363,371,207,209,224,228,239,263,281,282,96,43,226,236,280,331,333,375,67,178,181,366,391,22,185,4,87,134,166,164,103,197,39,98,172,261,386,106,118,345,392,40,122,184,257,200,379,367,143,194,85,18,30,123,139,147,296,297,45,991020000000007,349,38,144,145,146,170,182,187,190,233,271,277,299,300,389,95,83,312,330,232,267,310,241,227,302,303,304,305,306,307,308,311,314,319,321,322,324,327,335,340,342,351,353,354,355,356,357,358,359,360,365,373,381,388,991020000000005,990000000000016,990000000000101,990000000000102,990000000000201,990000000000202,990000000000203,990000000002001,990000000002002,990000000002003,990000000002004,990000000002005,990000000002006,990000000002007,990000000002008,990000000002009,990000000002010,990000000002011,990000000002012,990000000002013,990000000002014,990000000002015,990000000002016,990000000002017,990000000002018,990000000002019,990000000002020,990000000002021,990000000002022,990000000002023,990000000002024,990000000002025,990000000002027,990000000002028,990000000002030,990000000002031,990000000002033,990000000002034,990000000002038,990000000002039,990000000002040,99000000000204190,288,991020000000001,991020000000002,272,316,368,376,225,254,262,133,237,361,210,384,336,275,285,339,346,10,17,52,53,68,108,109,116,125,126,142,153,155,180,189,205,206,208,216,218,221,223,238,240,256,266,274,276,289,291,293,334,337,343,352,369,377,990004324,3,5,6,15,16,28,33,36,25,111,129,137,235,284,350,363,371,207,209,224,228,239,263,281,282,96,43,226,236,280,331,333,375,67,178,181,366,391,22,185,4,87,134,166,164,103,197,39,98,172,261,386,106,118,345,392,40,122,184,257,200,379,367,143,194,85,18,30,123,139,147,296,297,45,991020000000007,349,38,144,145,146,170,182,187,190,233,271,277,299,300,389,95,83,312,330,232,267,310,241,227,302,303,304,305,306,307,308,311,314,319,321,322,324,327,335,340,342,351,353,354,355,356,357,358,359,360,365,373,381,388,991020000000005,990000000000016,990000000000101,990000000000102,990000000000201,990000000000202,990000000000203,990000000002001,990000000002002,990000000002003,990000000002004,990000000002005,990000000002006,990000000002007,990000000002008,990000000002009,990000000002010,990000000002011,990000000002012,990000000002013,990000000002014,990000000002015,990000000002016,990000000002017,990000000002018,990000000002019,990000000002020,990000000002021,990000000002022,990000000002023,990000000002024,990000000002025,990000000002027,990000000002028,990000000002030,990000000002031,990000000002033,990000000002034,990000000002038,990000000002039,990000000002040,99000000000204190,288,991020000000001,991020000000002,272,316,368,376,225,254,262,133,237,361,210,384,336,275,285,339,346,10,17,52,53,68,108,109,116,125,126,142,153,155,180,189,205,206,208,216,218,221,223,238,240,256,266,274,276,289,291,293,334,337,343,352,369,377,990004324,3,5,6,15,16,28,33,36,25,111,129,137,235,284,350,363,371,207,209,224,228,239,263,281,282,96,43,226,236,280,331,333,375,67,178,181,366,391,22,185,4,87,134,166,164,103,197,39,98,172,261,386,106,118,345,392,40,122,184,257,200,379,367,143,194,85,18,30,123,139,147,296,297,45,991020000000007,349,38,144,145,146,170,182,187,190,233,271,277,299,300,389,95,83,312,330,232,267,310,241,227,302,303,304,305,306,307,308,311,314,319,321,322,324,327,335,340,342,351,353,354,355,356,357,358,359,360,365,373,381,388,991020000000005,990000000000016,990000000000101,990000000000102,990000000000201,990000000000202,990000000000203,990000000002001,990000000002002,990000000002003,990000000002004,990000000002005,990000000002006,990000000002007,990000000002008,990000000002009,990000000002010,990000000002011,990000000002012,990000000002013,990000000002014,990000000002015,990000000002016,990000000002017,990000000002018,990000000002019,990000000002020,990000000002021,990000000002022,990000000002023,990000000002024,990000000002025,990000000002027,990000000002028,990000000002030,990000000002031,990000000002033,990000000002034,990000000002038,990000000002039,990000000002040,99000000000204190,288,991020000000001,991020000000002,272,316,368,376,225,254,262,133,237,361,210,384,336,275,285,339,346,10,17,52,53,68,108,109,116,125,126,142,153,155,180,189,205,206,208,216,218,221,223,238,240,256,266,274,276,289,291,293,334,337,343,352,369,377,990004324,3,5,6,15,16,28,33,36,25,111,129,137,235,284,350,363,371,207,209,224,228,239,263,281,282,96,43,226,236,280,331,333,375,67,178,181,366,391,22,185,4,87,134,166,164,103,197,39,98,172,261,386,106,118,345,392,40,122,184,257,200,379,367,143,194,85,18,30,123,139,147,296,297,45,991020000000007,349,38,144,145,146,170,182,187,190,233,271,277,299,300,389,95,83,312,330,232,267,310,241,227,302,303,304,305,306,307,308,311,314,319,321,322,324,327,335,340,342,351,353,354,355,356,357,358,359,360,365,373,381,388,991020000000005,990000000000016,990000000000101,990000000000102,990000000000201,990000000000202,990000000000203,990000000002001,990000000002002,990000000002003,990000000002004,990000000002005,990000000002006,990000000002007,990000000002008,990000000002009,990000000002010,990000000002011,990000000002012,990000000002013,990000000002014,990000000002015,990000000002016,990000000002017,990000000002018,990000000002019,990000000002020,990000000002021,990000000002022,990000000002023,990000000002024,990000000002025,990000000002027,990000000002028,990000000002030,990000000002031,990000000002033,990000000002034,990000000002038,990000000002039,990000000002040,99000000000204190,288,991020000000001,991020000000002,272,316,368,376,225,254,262,133,237,361,210,384,336,275,285,339,346,10,17,52,53,68,108,109,116,125,126,142,153,155,180,189,205,206,208,216,218,221,223,238,240,256,266,274,276,289,291,293,334,337,343,352,369,377,990004324,3,5,6,15,16,28,33,36,25,111,129,137,235,284,350,363,371,207,209,224,228,239,263,281,282,96,43,226,236,280,331,333,375,67,178,181,366,391,22,185,4,87,134,166,164,103,197,39,98,172,261,386,106,118,345,392,40,122,184,257,200,379,367,143,194,85,18,30,123,139,147,296,297,45,991020000000007,349,38,144,145,146,170,182,187,190,233,271,277,299,300,389,95,83,312,330,232,267,310,241,227,302,303,304,305,306,307,308,311,314,319,321,322,324,327,335,340,342,351,353,354,355,356,357,358,359,360,365,373,381,388,991020000000005,990000000000016,990000000000101,990000000000102,990000000000201,990000000000202,990000000000203,990000000002001,990000000002002,990000000002003,990000000002004,990000000002005,990000000002006,990000000002007,990000000002008,990000000002009,990000000002010,990000000002011,990000000002012,990000000002013,990000000002014,990000000002015,990000000002016,990000000002017,990000000002018,990000000002019,990000000002020,990000000002021,990000000002022,990000000002023,990000000002024,990000000002025,990000000002027,990000000002028,990000000002030,990000000002031,990000000002033,990000000002034,990000000002038,990000000002039,990000000002040,990000000002041) + ) + from rdb$database; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + FIELD1 + FIELD1 + FIELD1 + """ + +@pytest.mark.version('>=3.0.6') +def test_core_6216_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6218.py b/tests/bugs/test_core_6218.py new file mode 100644 index 00000000..e0116bc6 --- /dev/null +++ b/tests/bugs/test_core_6218.py @@ -0,0 +1,73 @@ +#coding:utf-8 +# +# id: bugs.core_6218 +# title: COUNT(DISTINCT ) leads FB to crash when there are duplicate values of this field +# decription: +# Checked on 4.0.0.1731 +# +# tracker_id: CORE-6218 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test(n decfloat); + commit; + + insert into test values( 0 ); + insert into test values( 0 ); + commit; + + set list on; + set explain on; + + 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 ] + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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 + """ + +@pytest.mark.version('>=4.0') +def test_core_6218_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6219.py b/tests/bugs/test_core_6219.py new file mode 100644 index 00000000..4bf16607 --- /dev/null +++ b/tests/bugs/test_core_6219.py @@ -0,0 +1,148 @@ +#coding:utf-8 +# +# id: bugs.core_6219 +# title: Add support for special (inf/nan) values when sorting DECFLOAT values +# decription: +# Old descr: DECFLOAT values and queries with ORDER BY and/or windowed (analitical) functions. +# Confirmed wrong order of data in 4.0.0.1796. +# Checked on 4.0.0.1799 - all fine. +# +# tracker_id: CORE-6219 +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set decfloat traps to; + + + recreate table test0(n decfloat); + commit; + + insert into test0 values( cast('-0' as decfloat ) ); + insert into test0 values( cast('NaN' as decfloat ) ); + insert into test0 values( cast('sNaN' as decfloat ) ); + insert into test0 values( cast('-NaN' as decfloat ) ); + insert into test0 values( cast('-SNaN' as decfloat ) ); + insert into test0 values( cast('0' as decfloat ) ); + insert into test0 values( cast('-inf' as decfloat ) ); + insert into test0 values( cast('-0.10' as decfloat ) ); + insert into test0 values( cast('0.10' as decfloat ) ); + insert into test0 values( cast('inf' as decfloat ) ); + insert into test0 values( cast('0.100' as decfloat ) ); + insert into test0 values( cast('-0.100' as decfloat ) ); + commit; + + ----------------------------------------------------------------------------- + + select + t.* + ,iif( "-nan" < "-snan", '-nan LSS -snan', iif( "-nan" > "-snan", '-nan GTR -snan', iif("-nan" = "-snan", '-nan EQU -snan', 'UNKNOWN') ) ) as "Arithmetic: -nan vs to -snan:" + ,iif( "-snan" < "-inf", '-snan LSS -inf', iif( "-snan" > "-inf", '-snan GTR -inf', iif("-snan" = "-inf", '-snan EQU -inf', 'UNKNOWN') ) ) as "Arithmetic: -snan vs to -inf:" + ,iif( "-inf" < "-0.1", '-inf LSS -0.1', iif( "-inf" > "-0.1", '-inf GTR -0.1', iif("-inf" = "-0.1", '-inf EQU -0.1', 'UNKNOWN') ) ) as "Arithmetic: -inf vs to -0.1:" + ,iif( "-0.1" < "-0.10", '-0.1 LSS -0.10', iif( "-0.1" > "-0.10", '-0.1 GTR -0.10', iif("-0.1" = "-0.10", '-0.1 EQU -0.10', 'UNKNOWN') ) ) as "Arithmetic: -0.1 vs to -0.10:" + ,iif( "-0.10" < "-0", '-0.10 LSS -0', iif( "-0.10" > "-0", '-0.10 GTR -0', iif("-0.10" = "-0", '-0.10 EQU -0', 'UNKNOWN') ) ) as "Arithmetic: -0.10 vs to -0:" + ,iif( "-0" < "0", '-0 LSS 0', iif( "-0" > "0", '-0 GTR 0', iif("-0" = "0", '-0 EQU 0', 'UNKNOWN') ) ) as "Arithmetic: -0 vs to 0:" + ,iif( "0" < "0.10", '0 LSS 0.10', iif( "0" > "0.10", '0 GTR 0.10', iif("0" = "0.10", '0 EQU 0.10', 'UNKNOWN') ) ) as "Arithmetic: 0 vs to 0.10:" + ,iif( "0.10" < "0.1", '0.10 LSS 0.1', iif( "0.10" > "0.1", '0.10 GTR 0.1', iif("0.10" = "0.1", '0.10 EQU 0.1', 'UNKNOWN') ) ) as "Arithmetic: 0.10 vs to 0.1:" + ,iif( "0.1" < "inf", '0.1 LSS inf', iif( "0.1" > "inf", '0.1 GTR inf', iif("0.1" = "inf", '0.1 EQU inf', 'UNKNOWN') ) ) as "Arithmetic: 0.1 vs to inf:" + ,iif( "inf" < "snan", 'inf LSS snan', iif( "inf" > "snan", 'inf GTR snan', iif("inf" = "snan", 'inf EQU snan', 'UNKNOWN') ) ) as "Arithmetic: inf vs to snan:" + ,iif( "snan" < "nan", 'snan LSS nan', iif( "snan" > "nan", 'snan GTR nan', iif("snan" = "nan", 'snan EQU nan', 'UNKNOWN') ) ) as "Arithmetic: snan vs to nan:" + from ( + select + -cast('foo' as decfloat) as "-nan" + ,-cast('snan' as decfloat) as "-snan" + ,-cast(1/1e-9999 as decfloat) as "-inf" + ,-cast(0.1 as decfloat) as "-0.1" + ,-cast(0.10 as decfloat) as "-0.10" + ,-cast(0 as decfloat) as "-0" + ,cast(0 as decfloat) as "0" + ,cast(0.10 as decfloat) as "0.10" + ,cast(0.1 as decfloat) as "0.1" + ,cast(1/1e-9999 as decfloat) as "inf" + ,cast('snan' as decfloat) as "snan" + ,cast('bar' as decfloat) as "nan" + from rdb$database + ) t; + + ----------------------------------------------------------------------------- + + select n as data_ordered_by_n from test0 order by n; + + select lead(n)over(order by n) as data_lead_n from test0; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + -nan -NaN + -snan -sNaN + -inf -Infinity + -0.1 -0.1 + -0.10 -0.10 + -0 -0 + 0 0 + 0.10 0.10 + 0.1 0.1 + inf Infinity + snan sNaN + nan NaN + Arithmetic: -nan vs to -snan: -nan EQU -snan + Arithmetic: -snan vs to -inf: -snan EQU -inf + Arithmetic: -inf vs to -0.1: -inf LSS -0.1 + Arithmetic: -0.1 vs to -0.10: -0.1 EQU -0.10 + Arithmetic: -0.10 vs to -0: -0.10 LSS -0 + Arithmetic: -0 vs to 0: -0 EQU 0 + Arithmetic: 0 vs to 0.10: 0 LSS 0.10 + Arithmetic: 0.10 vs to 0.1: 0.10 EQU 0.1 + Arithmetic: 0.1 vs to inf: 0.1 LSS inf + Arithmetic: inf vs to snan: inf EQU snan + Arithmetic: snan vs to nan: snan EQU nan + + DATA_ORDERED_BY_N -NaN + DATA_ORDERED_BY_N -sNaN + DATA_ORDERED_BY_N -Infinity + DATA_ORDERED_BY_N -0.10 + DATA_ORDERED_BY_N -0.100 + DATA_ORDERED_BY_N 0 + DATA_ORDERED_BY_N -0 + DATA_ORDERED_BY_N 0.10 + DATA_ORDERED_BY_N 0.100 + DATA_ORDERED_BY_N Infinity + DATA_ORDERED_BY_N sNaN + DATA_ORDERED_BY_N NaN + + DATA_LEAD_N -sNaN + DATA_LEAD_N -Infinity + DATA_LEAD_N -0.10 + DATA_LEAD_N -0.100 + DATA_LEAD_N 0 + DATA_LEAD_N -0 + DATA_LEAD_N 0.10 + DATA_LEAD_N 0.100 + DATA_LEAD_N Infinity + DATA_LEAD_N sNaN + DATA_LEAD_N NaN + DATA_LEAD_N + """ + +@pytest.mark.version('>=4.0') +def test_core_6219_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6227.py b/tests/bugs/test_core_6227.py new file mode 100644 index 00000000..52b24bec --- /dev/null +++ b/tests/bugs/test_core_6227.py @@ -0,0 +1,59 @@ +#coding:utf-8 +# +# id: bugs.core_6227 +# title: isc_info_svc_user_dbpath always returns alias of main security database +# decription: +# String returned by sevrice manager for 'info_user_dbpath' query must contain PATH + file/alias +# rather than only file name or alias of security.db. +# If we call os.path.split() then this string will be splitted onto PATH and ALIAS. +# The first token (PATH) must contain at least one character if we try to split it using os.sep delimiter. +# We check that length of this path is more than zero. +# Note that befor fix reply was: ('', security.db') - so the PATH was empty string rather that None! +# +# Checked on: +# 4.0.0.1726 SS: 1.849s. +# 3.0.5.33232 SS: 0.704s. +# +# tracker_id: CORE-6227 +# min_versions: ['3.0.5'] +# versions: 3.0.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# from fdb import services +# +# svc = services.connect(host='localhost', user= user_name, password= user_password) +# security_db_info = svc.get_security_database_path() +# svc.close() +# +# print( 'Is DIRECTORY included into security DB info ? => ', ( 'YES' if os.path.split(security_db_info)[0] else ('NO. >' + security_db_info + '<' ) ) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Is DIRECTORY included into security DB info ? => YES + """ + +@pytest.mark.version('>=3.0.5') +@pytest.mark.xfail +def test_core_6227_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6233.py b/tests/bugs/test_core_6233.py new file mode 100644 index 00000000..8fecd734 --- /dev/null +++ b/tests/bugs/test_core_6233.py @@ -0,0 +1,164 @@ +#coding:utf-8 +# +# id: bugs.core_6233 +# title: Wrong dependencies of stored function on view after backup and restore +# decription: +# We make backup of this test DB and restore it to other name using PIPE mechanism +# in order to skip creation of unneeded .fbk file +# See: https://docs.python.org/2/library/subprocess.html#replacing-shell-pipeline +# Confirmed bug on 4.0.0.1740. +# Checked on 4.0.0.1743: works OK. +# Checked result of backporting fix to on 3.0.6.33265: OK. +# +# tracker_id: CORE-6233 +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import time +# import subprocess +# import shutil +# from subprocess import PIPE +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# this_db = db_conn.database_name +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# fdb_rest = os.path.join(context['temp_directory'],'tmp_6233_restored.fdb') +# cleanup( (fdb_rest,) ) +# +# sql_init=''' +# set bail on; +# create or alter procedure p1 as begin end; +# create or alter function f1 returns integer as begin end; +# commit; +# +# set term ^; +# create or alter view v1 as +# select 1 as n from rdb$database +# ^ +# +# create or alter function f1 returns integer as +# declare ret integer; +# begin +# select n from v1 into ret; +# return ret; +# end +# ^ +# +# create or alter procedure p1 returns (ret integer) as +# begin +# select n from v1 into ret; +# end +# ^ +# set term ;^ +# commit; +# +# ''' +# runProgram('isql', [ dsn], sql_init) +# +# +# # https://docs.python.org/2/library/subprocess.html#replacing-shell-pipeline +# # output=`dmesg | grep hda` +# # becomes: +# # p1 = Popen(["dmesg"], stdout=PIPE) +# # p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE) +# # p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits. +# # output = p2.communicate()[0] +# # gbak -b localhost:$fdb_init stdout | gbak -rep stdin localhost:$fdb_rest +# +# p_sender = subprocess.Popen( [ context['gbak_path'], '-b', dsn, 'stdout' ], stdout=PIPE) +# p_getter = subprocess.Popen( [ context['gbak_path'], '-c', 'stdin', 'localhost:' + fdb_rest ], stdin = p_sender.stdout, stdout = PIPE ) +# p_sender.stdout.close() +# p_getter_stdout, p_getter_stderr = p_getter.communicate() +# +# +# sql_chk=''' +# set list on; +# set count on; +# select +# RDB$DEPENDENT_NAME as dep_name +# ,RDB$DEPENDED_ON_NAME as dep_on_name +# from rdb$dependencies +# order by 1,2; +# ''' +# +# runProgram('isql',[ 'localhost:' + fdb_rest ], sql_chk) +# +# cleanup( (fdb_rest,) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DEP_NAME F1 + DEP_ON_NAME V1 + DEP_NAME F1 + DEP_ON_NAME V1 + DEP_NAME P1 + DEP_ON_NAME V1 + DEP_NAME P1 + DEP_ON_NAME V1 + DEP_NAME V1 + DEP_ON_NAME RDB$DATABASE + Records affected: 5 + """ + +@pytest.mark.version('>=3.0.6') +@pytest.mark.xfail +def test_core_6233_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6236.py b/tests/bugs/test_core_6236.py new file mode 100644 index 00000000..a6764ef1 --- /dev/null +++ b/tests/bugs/test_core_6236.py @@ -0,0 +1,75 @@ +#coding:utf-8 +# +# id: bugs.core_6236 +# title: RDB$TIME_ZONE_UTIL package has wrong privilege for PUBLIC +# decription: +# Thanks Adriano for suggestion about this test implementation. +# We create non-privileged user ('tmp$c6236') and do connect of him +# with trying to use package function rdb$time_zone_util.database_version(). +# It must pass without any errors (result of call no matter). +# +# Confirmed exception on 4.0.0.1714: no permission for EXECUTE access to PACKAGE RDB$TIME_ZONE_UTIL +# Checked on 4.0.0.1740 SS: 1.400s - works fine. +# ::: NB ::: +# Command 'SHOW GRANTS' does not display privileges on system objects thus we do not use it here. +# +# tracker_id: CORE-6236 +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import sys +# import inspect +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.execute_immediate("create or alter user tmp$c6236 password '123'") +# db_conn.commit() +# +# con = fdb.connect( dsn = dsn, user = 'tmp$c6236', password ='123' ) +# cur = con.cursor() +# try: +# cur.execute('select rdb$time_zone_util.database_version() is not null as db_vers_defined from rdb$database') +# hdr=cur.description +# for r in cur: +# for i in range(0,len(hdr)): +# print( hdr[i][0],':', r[i] ) +# except Exception as e: +# print('Unexpected exception in ', inspect.stack()[0][3], ': ', sys.exc_info()[0]) +# print(e) +# +# cur.close() +# con.close() +# +# db_conn.execute_immediate("drop user tmp$c6236") +# db_conn.commit() +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DB_VERS_DEFINED : True + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_6236_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6237.py b/tests/bugs/test_core_6237.py new file mode 100644 index 00000000..166f5a87 --- /dev/null +++ b/tests/bugs/test_core_6237.py @@ -0,0 +1,125 @@ +#coding:utf-8 +# +# id: bugs.core_6237 +# title: Performance problem when using SRP plugin +# decription: +# :::::::::::::::::::: N O T A B E N E ::::::::::::::::: +# It is crusial for this test that firebird.conf have following _SEQUENCE_ of auth-plugins: Srp, ..., Legacy_Auth +# -- i.e. Srp must be specified BEFORE Legacy. +# Slow time of attach establishing can NOT be seen otherwise; rather almost no difference will be in that case. +# ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +# +# Test creates two users: one usingLegacy plugin and second using Srp. +# Then we make ~20...30 pairs of attach/detach by each of these users and get total time difference for these actions. +# Ratio between these total differences must be limited with threshold. Its value was determined after dozen of runs +# and it seems to be reasonable assign to it value 1.25 (see MIN_RATIO_THRESHOLD in the code). +# +# Test output will contain ALERT if total time of vs +# will be greater than MIN_RATIO_THRESHOLD. +# +# Reproduced on on several builds 4.x before 17.01.2020 (tested: 4.0.0.1712 CS, 4.0.0.1731 CS - got ratio = ~1.95). +# Reproduced also on 3.0.5.33221 Classic - got ratio ~1.50 ... 1.70; could NOT reproduce on 3.0.5 SuperClassic / SuperServer. +# Checked on: +# 4.0.0.1763 SS: 15.592s. +# 4.0.0.1763 CS: 23.725s. +# 3.0.6.33240 SS: 7.294s. +# 3.0.6.33240 CS: 17.407s. +# +# +# tracker_id: CORE-6237 +# min_versions: ['3.0.5'] +# versions: 3.0.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import datetime +# from datetime import timedelta +# +# def showtime(): +# global datetime +# return ''.join( (datetime.datetime.now().strftime("%H:%M:%S.%f")[:12],'.') ) +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # Number of attach/detach actions for each of checked plugin: +# N_ITER=50 +# +# # Minimal ratio (for ALERT) between total time when Srp is used vs such value for Legacy auth plugin. +# # Will be evaluated as datediff(millisecond ...) that were spent for making N_ITER attach/detach actions. +# +# MIN_RATIO_THRESHOLD = 1.41 +# # ^ +# # ################### +# # ### THRESHOLD ### +# # ################### +# +# db_conn.execute_immediate("create or alter user tmp_c6237_leg password 'leg' using plugin Legacy_UserManager") +# db_conn.execute_immediate("create or alter user tmp_c6237_srp password 'srp' using plugin Srp") +# db_conn.commit() +# db_conn.close() +# +# +# elap_ms_for_leg_auth, elap_ms_for_srp_auth = 0,0 +# +# for j in range(0,2): +# v_user = 'tmp_c6237_leg' if j==0 else 'tmp_c6237_srp' +# v_pass = 'leg' if j==0 else 'srp' +# +# ta = datetime.datetime.now() +# for i in range(0, N_ITER): +# conx=fdb.connect(dsn = dsn, user = v_user, password = v_pass ) +# conx.close() +# +# tb = datetime.datetime.now() +# diff=tb-ta +# +# if j == 0: +# elap_ms_for_leg_auth = int(diff.seconds) * 1000 + diff.microseconds / 1000 +# else: +# elap_ms_for_srp_auth = int(diff.seconds) * 1000 + diff.microseconds / 1000 +# +# db_conn = fdb.connect(dsn = dsn) +# db_conn.execute_immediate("drop user tmp_c6237_leg using plugin Legacy_UserManager") +# db_conn.execute_immediate("drop user tmp_c6237_srp using plugin Srp") +# db_conn.commit() +# db_conn.close() +# +# # print( 'Legacy, ms: ', elap_ms_for_leg_auth, '; Srp, ms: ', elap_ms_for_srp_auth, '; 1.00 * elap_ms_for_srp_auth / elap_ms_for_leg_auth=', 1.00 * elap_ms_for_srp_auth / elap_ms_for_leg_auth ) +# +# elapsed_time_ratio = 1.00 * elap_ms_for_srp_auth / elap_ms_for_leg_auth +# if elapsed_time_ratio < MIN_RATIO_THRESHOLD: +# msg = 'EXPECTED. Ratio of total elapsed time when use Srp vs Legacy is less then threshold.' +# else: +# msg = 'Ratio Srp/Legacy: %(elapsed_time_ratio)s - is GREATER than threshold = %(MIN_RATIO_THRESHOLD)s. Total time spent for Srp: %(elap_ms_for_srp_auth)s ms; for Legacy: %(elap_ms_for_leg_auth)s ms.' % locals() +# +# print(msg) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + EXPECTED. Ratio of total elapsed time when use Srp vs Legacy is less then threshold. + """ + +@pytest.mark.version('>=3.0.5') +@pytest.mark.xfail +def test_core_6237_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6238.py b/tests/bugs/test_core_6238.py new file mode 100644 index 00000000..b486d31b --- /dev/null +++ b/tests/bugs/test_core_6238.py @@ -0,0 +1,72 @@ +#coding:utf-8 +# +# id: bugs.core_6238 +# title: DECFLOAT: subtraction Num1 - Num2 leads to "Decimal float overflow" if Num2 is specified in scientific notation and less than max double ( 1.7976931348623157e308 ) +# decription: +# Checked on 4.0.0.1753: works fine. +# +# tracker_id: CORE-6238 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- All following statements raised before fix: + -- Statement failed, SQLSTATE = 22003 + -- Decimal float overflow. The exponent of a result is greater than the magnitude allowed. + + set list on; + select (d - 1e0) as result_01 from (select 9.999999999999999999999999999999998E+6144 d from rdb$database); + select (d - 1.79769313e308) as result_02 from (select 9.999999999999999999999999999999998E+6144 d from rdb$database); + select (d - cast( 1e0 as float) ) as result_03 from (select 9.999999999999999999999999999999998E+6144 d from rdb$database); + select (d + 1.79769313e-308 ) as result_04 from (select 9.999999999999999999999999999999998E+6144 d from rdb$database); + + -- This EB was added only to check that no error will be while executing statements in it. + -- See letter to Alex, 31.01.2020 11:34, and his postfix for this ticket: + -- https://github.com/FirebirdSQL/firebird/commit/0ef5a1a1c1bf42021b378e1691aaccfd75a454b4 + set term ^; + execute block as + declare dt date; + declare tm time; + declare ts timestamp; + begin + select current_date + cast(1 as numeric(19,0)) from rdb$database into dt; + select current_date + cast(1 as decfloat) from rdb$database into dt; + + select current_time + cast(1 as numeric(19,0)) from rdb$database into tm; + select current_time + cast(1 as decfloat) from rdb$database into tm; + + select current_timestamp + cast(1 as decfloat) from rdb$database into ts; + select current_timestamp + cast(1 as decfloat) from rdb$database into ts; + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT_01 9.999999999999999999999999999999998E+6144 + RESULT_02 9.999999999999999999999999999999998E+6144 + RESULT_03 9.999999999999999999999999999999998E+6144 + RESULT_04 9.999999999999999999999999999999998E+6144 + """ + +@pytest.mark.version('>=4.0') +def test_core_6238_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6239.py b/tests/bugs/test_core_6239.py new file mode 100644 index 00000000..4c0c78c9 --- /dev/null +++ b/tests/bugs/test_core_6239.py @@ -0,0 +1,147 @@ +#coding:utf-8 +# +# id: bugs.core_6239 +# title: Procedures and EXECUTE BLOCK without RETURNS should not be allowed to use SUSPEND +# decription: +# Checked on 4.0.0.1763. +# +# tracker_id: CORE-6239 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- these two collations and domain not needed for TEST per se. + -- We create them here only for reference in declaration of SP input params, see below: + create collation nums_coll for utf8 from unicode case insensitive 'NUMERIC-SORT=1'; + create collation name_coll for utf8 from unicode no pad case insensitive accent insensitive; + create domain dm_test varchar(20) character set utf8 default 'foo' not null collate nums_coll; + commit; + + -- All following statements should be declined with + -- Statement failed, SQLSTATE = 42000 + -- Dynamic SQL Error + -- -SQL error code = -104 + -- -SUSPEND could not be used without RETURNS clause in PROCEDURE or EXECUTE BLOCK + + set term ^ ; + execute block as + begin + suspend; + end + ^ + + execute block (a_x int not null = ?) as + begin + suspend; + end + ^ + + create or alter procedure sp_missed_returns_in_its_header_1 as + begin + -- we use SUSPEND clause but there is no + -- output parameters in this SP header: + suspend; + end + ^ + + create or alter procedure sp_missed_returns_in_its_header_2 (a_x varchar(10) not null) as + begin + suspend; + end + ^ + + create or alter procedure sp_missed_returns_in_its_header_3 (p1 varchar(20) character set utf8 not null collate nums_coll default 'foo') SQL SECURITY DEFINER as + begin + suspend; + end + ^ + + + recreate package pg_test_1 as + begin + procedure pg_proc( + p1 varchar(20) character set utf8 not null collate nums_coll default 'foo' + ,p2 dm_test default 'qwe' + ,p3 dm_test default 'bar' + ,p4 dm_test collate name_coll default 'rio' + ); + end + ^ + + create package body pg_test_1 as + begin + procedure pg_proc( + p1 varchar(20) character set utf8 not null collate nums_coll + ,p2 dm_test + ,p3 dm_test + ,p4 dm_test collate name_coll + ) as + begin + suspend; + end + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + 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 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 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 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 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_core_6239_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_6241.py b/tests/bugs/test_core_6241.py new file mode 100644 index 00000000..68d51139 --- /dev/null +++ b/tests/bugs/test_core_6241.py @@ -0,0 +1,120 @@ +#coding:utf-8 +# +# id: bugs.core_6241 +# title: Values greater than number of days between 01.01.0001 and 31.12.9999 (=3652058) can be added or subtracted from DATE +# decription: +# Checked on 4.0.0.1761. +# +# tracker_id: CORE-6241 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + -- J4YI: + -- select datediff( day from date '01.02.2020' to date '31.12.9999') from rdb$database; -- 2914603 + -- select datediff( day from date '01.01.0001' to date '01.02.2020') from rdb$database; -- 737455 + -- select datediff( day from date '01.01.0001' to date '31.12.9999') from rdb$database; -- 3652058 + -- set echo on; + + -- ################# 1. ADDITION ################## + + select date '01.02.2020' + 2914603 as EXPECTED_9999_12_31 from rdb$database; -- OK, as expected: 9999-12-31 + + select date '01.02.2020' + 2914604 from rdb$database; -- OK, as expected: SQLSTATE = 22008 (value exceeds the range for valid dates) + + select date '01.02.2020' + 2147483647 from rdb$database; -- OK, as expected: SQLSTATE = 22008 + + select date '01.02.2020' + 2147483648 from rdb$database; -- OK, as expected: SQLSTATE = 22008 + + select date '01.02.2020' + 4294229840 from rdb$database; -- OK, as expected: SQLSTATE = 22008 + + select date '01.02.2020' + 4294229841 from rdb$database; -- ISSUED WRONG RESULT: 0001-01-01; NB: 4294967296 - 4294229841 = 737455 -- days since 01.01.0001 to 01.02.2020 + + select date '01.02.2020' + 9223372036854775807 from rdb$database; -- ISSUED WRONG RESULT: 2020-01-31 + + + -- ############### 2. SUBTRACTION ################# + + select date '01.02.2020' - 737455 as EXPECTED_0001_01_01 from rdb$database; -- OK, as expected: 0001-01-01 + + select date '01.02.2020' - 737456 from rdb$database; -- OK, as expected: SQLSTATE = 22008 (value exceeds the range for valid dates) + + select date '01.02.2020' - 2147483648 from rdb$database; -- OK, as expected: SQLSTATE = 22008 + + select date '01.02.2020' - 4292052692 from rdb$database; -- OK, as expected: SQLSTATE = 22008 + + select date '01.02.2020' - 4292052693 from rdb$database; -- ISSUED WRONG RESULT: 9999-12-31; NB: 4294967296 - 4292052693 = 2914603 -- days since 01.02.2020 to 31.12.9999 + + select date '01.02.2020' - 9223372036854775807 from rdb$database; -- ISSUED WRONG RESULT: 2020-02-02 + + select date '01.02.2020' + -9223372036854775808 from rdb$database; -- ISSUED WRONG RESULT: 2020-02-01 + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + EXPECTED_9999_12_31 9999-12-31 + EXPECTED_0001_01_01 0001-01-01 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22008 + value exceeds the range for valid dates + + Statement failed, SQLSTATE = 22008 + value exceeds the range for valid dates + + Statement failed, SQLSTATE = 22008 + value exceeds the range for valid dates + + Statement failed, SQLSTATE = 22008 + value exceeds the range for valid dates + + Statement failed, SQLSTATE = 22008 + value exceeds the range for valid dates + + Statement failed, SQLSTATE = 22008 + value exceeds the range for valid dates + + Statement failed, SQLSTATE = 22008 + value exceeds the range for valid dates + + Statement failed, SQLSTATE = 22008 + value exceeds the range for valid dates + + Statement failed, SQLSTATE = 22008 + value exceeds the range for valid dates + + Statement failed, SQLSTATE = 22008 + value exceeds the range for valid dates + + Statement failed, SQLSTATE = 22008 + value exceeds the range for valid dates + + Statement failed, SQLSTATE = 22008 + value exceeds the range for valid dates + """ + +@pytest.mark.version('>=4.0') +def test_core_6241_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6246.py b/tests/bugs/test_core_6246.py new file mode 100644 index 00000000..86bf108c --- /dev/null +++ b/tests/bugs/test_core_6246.py @@ -0,0 +1,153 @@ +#coding:utf-8 +# +# id: bugs.core_6246 +# title: Problem with too many number of columns in resultset. +# decription: +# We create .sql with 32767 columns and run it with requirement to display SQLDA. +# All lines in produced output with 'charset: ' substring must contain only one value: +# * '3' for FB 3.x; '4' for FB 4.x. +# If some charset ID differs from expected, we raise error and terminate check furter lines. +# +# Confirmed bug on 3.0.6.33272: first 32108 fields are shown in SQLDA with 'charset: 0 NONE'. +# String 'charset: 3 UNICODE_FSS' appeared only since 32109-th column and up to the end. +# +# Checked on 3.0.6.33273 - works fine. +# Checked on 4.0.0.2353 - works fine // 30.01.2021 +# +# Comment before 30-jan-2021: +# --------------------------- +# Attempt to run query with 32767 columns on 4.0 will raise: +# Statement failed, SQLSTATE = HY000 +# request size limit exceeded +# Section for 4.0 intentionally contains temp message about missed implementation. +# Will be removed after fix CORE-6216 (see commet by Adriano in CORE-6246, date: 22/Mar/20 01:40 AM). +# --------------------------- +# 30.01.2021: CORE-6212 was fixed. Section for 4.0 deleted; common code is used for 3.x and 4.x. +# +# tracker_id: CORE-6246 +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import sys +# import subprocess +# from fdb import services +# +# #-------------------------------------------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# +# #-------------------------------------------- +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# fb_major=db_conn.engine_version # type: double! +# db_conn.close() +# +# MAX_FOR_PASS=32767 +# #MAX_FOR_PASS=32 +# +# fld_list = ','.join( ('x1.rdb$field_name',) * MAX_FOR_PASS ) +# +# # Create .sql with columns: +# ########################################## +# sql_test=''' +# set sqlda_display on; +# set planonly; +# select +# %(fld_list)s +# from rdb$fields as x1 rows 1; +# ''' % locals() +# +# f_pass_sql = open( os.path.join(context['temp_directory'],'tmp_6246_pass.sql'), 'w', buffering = 0) +# f_pass_sql.write( sql_test ) +# f_pass_sql.close() +# +# f_pass_log = open( '.'.join( (os.path.splitext( f_pass_sql.name )[0], 'log') ), 'w', buffering = 0) +# f_pass_err = open( '.'.join( (os.path.splitext( f_pass_sql.name )[0], 'err') ), 'w', buffering = 0) +# +# # This can take about 25-30 seconds: +# #################################### +# subprocess.call( [ context['isql_path'], dsn, '-q', '-i', f_pass_sql.name ], stdout = f_pass_log, stderr = f_pass_err) +# +# f_pass_log.close() +# f_pass_err.close() +# +# # Checks: +# ######### +# # 1. Result of STDERR must be empty: +# with open(f_pass_err.name,'r') as f: +# for line in f: +# if line.split(): +# print('UNEXPECTED STDERR: '+line) +# +# # 1. For FB 3.x: only "charset: 3" must present in any string that describes column: +# # NN: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 93 charset: 3 UNICODE_FSS +# # ^ +# # 0 1 2 3 4 5 6 7 8 9 10 11 12 13 +# # 2. For FB 4.x: only "charset: 4" must present in any string that describes column: +# # NN: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 252 charset: 4 UTF8 +# # ^ +# # 0 1 2 3 4 5 6 7 8 9 10 11 12 13 +# # ^ +# # we must check this token +# # +# # where 'NN:' is '01:', '02:', '03:', ... '32767:' +# +# ############## ::: N O T E ::: ################# +# expected_charset_id = '3' if fb_major < 4 else '4' +# ################################################## +# +# charset_id_position = -1 +# i=0 +# with open(f_pass_log.name,'r') as f: +# for line in f: +# i += 1 +# if 'sqltype:' in line: +# if charset_id_position < 0: +# charset_id_position = [ (n,w) for n,w in enumerate( line.split() ) if w.lower() == 'charset:'.lower() ][0][0] + 1 +# +# # charset_id = line.split()[-2] +# charset_id = line.split()[ charset_id_position ] +# if charset_id != expected_charset_id: +# print('At least one UNEXPECTED charset in SQLDA at position: %d. Line No: %d, charset_id: %s' % (charset_id_position, i, charset_id) ) +# print(line) +# break +# +# if charset_id_position < 0: +# # ISQL log is empty or not contains 'sqltype:' in any line. +# print('UNEXPECTED RESULT: no lines with expected pattern found.') +# +# cleanup( [ i.name for i in ( f_pass_sql, f_pass_log, f_pass_err) ] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0.6') +@pytest.mark.xfail +def test_core_6246_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6248.py b/tests/bugs/test_core_6248.py new file mode 100644 index 00000000..0d55308b --- /dev/null +++ b/tests/bugs/test_core_6248.py @@ -0,0 +1,366 @@ +#coding:utf-8 +# +# id: bugs.core_6248 +# title: A number of errors when database name is longer than 255 symbols +# decription: +# Test verifies that one may to create DB with total path plus name length L = 255 and 259 characters. +# Each DB is then subject for 'gbak -b', 'gbak -c', 'gstat -h', 'gfix -sweep' and 'gfix -v -full'. +# All these commands must NOT issue something to their STDERR. +# +# STDOUT-log of initial SQL must contain full DB name. +# Changed part of firebird.log for SWEEP and VALIDATION also must have full DB name (this is verified using regexp): +# +[tab]Database: C:\\FBTESTING\\QA\\FBT-REPO\\TMP\\ABC.FDB // for validation +# +[tab]Database "C:\\FBTESTING\\QA\\FBT-REPO\\TMP\\ABC.FDB // for sweep +# +# STDOUT-logs of backup, restore and gstat currently (09-mar-2020) have only truncated name (~235...241 chars). +# This may change in the future if FB developers will decide to fix this small inconveniences. +# +# For L=259 we must see in backup log following phrase: +# gbak:text for attribute 7 is too large in put_asciz(), truncating to 255 bytes +# - but currently this is not checked here. +# +# Checked on 4.0.0.1796. +# Checked on 4.0.0.2353: rdb$get_context('SYSTEM','DB_NAME') do not cut off full path and name to database +# and can return string with length = 32K, i.e. exceeding length of mon$database_name. +# See commit of 29-01-2021: +# https://github.com/FirebirdSQL/firebird/commit/d4835cab7f48288490ed83541132555c5cd0376d +# +# tracker_id: CORE-6248 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import tempfile +# import difflib +# import re +# import time +# import subprocess +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# this_db = db_conn.database_name +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# def svc_get_fb_log( f_fb_log ): +# +# global subprocess +# subprocess.call([ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# "action_get_fb_log" +# ], +# stdout=f_fb_log, stderr=subprocess.STDOUT +# ) +# +# return +# +# #-------------------------------------------- +# +# def check_long_dbname(required_name_len, chars2fil): +# +# global time, tempfile, subprocess, difflib +# global flush_and_close, cleanup, svc_get_fb_log, re +# +# MINIMAL_LEN_TO_SHOW=255 +# REDUCE_NAME_LEN_BY=0 +# +# folder = tempfile.gettempdir() +# folder = context['temp_directory'] +# #folder = os.path.dirname(os.path.abspath(__file__)) +# +# f_name = ( chars2fil * 1000) [ : required_name_len - len(folder) - len('.fdb') - REDUCE_NAME_LEN_BY ] + '.fdb' +# +# dbname = os.path.join( folder, f_name ) +# +# bkname = dbname[:-4] + '.fbk' +# +# cleanup( (dbname,) ) +# +# sql_ddl=''' create database 'localhost:%(dbname)s'; +# set list on; +# +# create exception exc_dbname_diff q'{Value in mon$database.mon$database_name differs from rdb$get_context('SYSTEM', 'DB_NAME'):@1@2@3=== vs ===@4@5}'; +# set term ^; +# execute block returns( +# mon_database_column varchar(260) +# ,sys_context_db_name varchar(260) +# ) as +# declare lf char(1) = x'0A'; +# begin +# select +# mon$database_name as mon_database_column +# from mon$database +# into mon_database_column; +# +# sys_context_db_name = rdb$get_context('SYSTEM', 'DB_NAME'); +# +# if ( substring( sys_context_db_name from 1 for 255 ) is distinct from mon_database_column ) then +# begin +# exception exc_dbname_diff using( +# lf +# ,mon_database_column +# ,lf +# ,lf +# ,sys_context_db_name +# ); +# end +# +# suspend; +# end +# ^ +# set term ;^ +# commit; +# ''' % locals() +# +# +# f_sql_chk = open( os.path.join(context['temp_directory'],'tmp_6248_ddl.sql'), 'w') +# f_sql_chk.write(sql_ddl) +# flush_and_close( f_sql_chk ) +# +# ######################################################################## +# +# f_ddl_log = open( os.path.join(context['temp_directory'],'tmp_6248.ddl_'+str(required_name_len)+'.log'), 'w', buffering = 0) +# f_ddl_err = open( ''.join( (os.path.splitext(f_sql_chk.name)[0], '.err' ) ), 'w', buffering = 0) +# +# subprocess.call( [ context['isql_path'], '-q', '-i', f_sql_chk.name ], stdout = f_ddl_log, stderr = f_ddl_err) +# +# flush_and_close( f_ddl_log ) +# flush_and_close( f_ddl_err ) +# +# ######################################################################## +# +# f_backup_log = open( os.path.join(context['temp_directory'],'tmp_6248.backup_'+str(required_name_len)+'.log'), 'w', buffering = 0) +# f_backup_err = open( ''.join( (os.path.splitext(f_backup_log.name)[0], '.err' ) ), 'w', buffering = 0) +# +# subprocess.call( [ context['gbak_path'], '-b', '-se', 'localhost:servce_mgr', dbname, bkname, '-v', '-st', 'tdrw' ], stdout = f_backup_log, stderr = f_backup_err) +# +# flush_and_close( f_backup_log ) +# flush_and_close( f_backup_err ) +# +# ######################################################################## +# +# os.remove(dbname) +# +# f_restore_log = open( os.path.join(context['temp_directory'],'tmp_6248.restore_'+str(required_name_len)+'.log'), 'w', buffering = 0) +# f_restore_err = open( ''.join( (os.path.splitext(f_restore_log.name)[0], '.err' ) ), 'w', buffering = 0) +# +# subprocess.call( [ context['gbak_path'], '-rep', '-se', 'localhost:servce_mgr', bkname, dbname, '-v', '-st', 'tdrw' ], stdout = f_restore_log, stderr = f_restore_err) +# +# flush_and_close( f_restore_log ) +# flush_and_close( f_restore_err ) +# +# ######################################################################## +# +# f_gstat_log = open( os.path.join(context['temp_directory'],'tmp_6248.gstat_'+str(required_name_len)+'.log'), 'w', buffering = 0) +# f_gstat_err = open( ''.join( (os.path.splitext(f_gstat_log.name)[0], '.err' ) ), 'w', buffering = 0) +# +# subprocess.call( [ context['gstat_path'], '-h', 'localhost:' + dbname ], stdout = f_gstat_log, stderr = f_gstat_err) +# +# flush_and_close( f_gstat_log ) +# flush_and_close( f_gstat_err ) +# +# ######################################################################## +# +# f_fblog_sweep_before = open( os.path.join(context['temp_directory'],'tmp_6248.fblog_before_sweep_'+str(required_name_len)+'.log'), 'w', buffering = 0) +# svc_get_fb_log( f_fblog_sweep_before ) +# flush_and_close( f_fblog_sweep_before ) +# +# f_sweep_log = open( os.path.join(context['temp_directory'],'tmp_6248.sweep_'+str(required_name_len)+'.log'), 'w', buffering = 0) +# f_sweep_err = open( ''.join( (os.path.splitext(f_sweep_log.name)[0], '.err' ) ), 'w', buffering = 0) +# +# subprocess.call( [ context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_repair', 'dbname', dbname, 'rpr_sweep_db' ], stdout = f_sweep_log, stderr = f_sweep_err) +# +# flush_and_close( f_sweep_log ) +# flush_and_close( f_sweep_err ) +# +# # Here we let firebird.log to be fulfilled with text about just finished SWEEP: +# time.sleep(1) +# +# f_fblog_sweep_after = open( os.path.join(context['temp_directory'],'tmp_6248.fblog_after_sweep_'+str(required_name_len)+'.log'), 'w', buffering = 0) +# svc_get_fb_log( f_fblog_sweep_after ) +# flush_and_close( f_fblog_sweep_after ) +# +# oldfb=open(f_fblog_sweep_before.name, 'r') +# newfb=open(f_fblog_sweep_after.name, 'r') +# +# difftext = ''.join(difflib.unified_diff( +# oldfb.readlines(), +# newfb.readlines() +# )) +# oldfb.close() +# newfb.close() +# +# f_diff_sweep = open( os.path.join(context['temp_directory'],'tmp_6248.fblog_diff_sweep_'+str(required_name_len)+'.log'), 'w', buffering = 0) +# f_diff_sweep.write(difftext) +# flush_and_close( f_diff_sweep ) +# +# ######################################################################## +# +# f_fblog_validate_before = open( os.path.join(context['temp_directory'],'tmp_6248.fblog_before_validate_'+str(required_name_len)+'.log'), 'w', buffering = 0) +# svc_get_fb_log( f_fblog_validate_before ) +# flush_and_close( f_fblog_validate_before ) +# +# f_valid_log = open( os.path.join(context['temp_directory'],'tmp_6248.valid_'+str(required_name_len)+'.log'), 'w', buffering = 0) +# f_valid_err = open( ''.join( (os.path.splitext(f_valid_log.name)[0], '.err' ) ), 'w', buffering = 0) +# +# subprocess.call( [ context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_repair', 'dbname', dbname, 'rpr_validate_db', 'rpr_full' ], stdout = f_valid_log, stderr = f_valid_err) +# +# flush_and_close( f_valid_log ) +# flush_and_close( f_valid_err ) +# +# # Here we let firebird.log to be fulfilled with text about just finished VALIDATION: +# time.sleep(1) +# +# f_fblog_validate_after = open( os.path.join(context['temp_directory'],'tmp_6248.fblog_after_validate_'+str(required_name_len)+'.log'), 'w', buffering = 0) +# svc_get_fb_log( f_fblog_validate_after ) +# flush_and_close( f_fblog_validate_after ) +# +# +# f_fblog_validate_after = open( os.path.join(context['temp_directory'],'tmp_6248.fblog_after_validate_'+str(required_name_len)+'.log'), 'w', buffering = 0) +# svc_get_fb_log( f_fblog_validate_after ) +# flush_and_close( f_fblog_validate_after ) +# +# oldfb=open(f_fblog_validate_before.name, 'r') +# newfb=open(f_fblog_validate_after.name, 'r') +# +# difftext = ''.join(difflib.unified_diff( +# oldfb.readlines(), +# newfb.readlines() +# )) +# oldfb.close() +# newfb.close() +# +# f_diff_validate = open( os.path.join(context['temp_directory'],'tmp_6248.fblog_diff_validate_'+str(required_name_len)+'.log'), 'w', buffering = 0) +# f_diff_validate.write(difftext) +# flush_and_close( f_diff_validate ) +# +# +# ######################################################################## +# +# chk_list = (f_ddl_err, f_backup_err, f_restore_err, f_gstat_err, f_sweep_err, f_valid_err) +# for c in chk_list: +# with open(c.name,'r') as f: +# for line in f: +# if line.split(): +# print('UNEXPECTED ERROR, file:' + c.name +': ', line ) +# +# dbname_present_map = {} +# +# # diff VALIDATION: +# # +[tab]Database: C:\\FBTESTING\\QA\\FBT-REPO\\TMP\\ABC.FDB +# # diff SWEEP: +# # +[tab]Database "C:\\FBTESTING\\QA\\FBT-REPO\\TMP\\ABC.FDB +# dbptrn = re.compile('\\+\\s+Database[:]{0,1}\\s+"{0,1}', re.IGNORECASE) +# +# # STDOUT results: we have to check that AT LEAST 255 characters of database name present in log. +# chk_list = (f_ddl_log, f_backup_log, f_restore_log, f_gstat_log, f_diff_sweep, f_diff_validate) +# for c in chk_list: +# +# # Name of STDOUT-log will serve as KEY for dbname_present_map{}, e.g.: +# # C:\\FBTESTING\\qa +# bt-repo mp mp_6248.backup_255.log --> tmp_6248.backup_255 +# stdout_file = os.path.split( os.path.splitext( c.name )[0] )[1] +# +# dbname_present_map[ stdout_file ] = 'DB NAME NOT FOUND' +# with open(c.name,'r') as f: +# for line in f: +# if c not in (f_diff_sweep, f_diff_validate) or line.startswith('+') and dbptrn.search(line): +# if dbname[:MINIMAL_LEN_TO_SHOW].upper() in line.upper(): +# dbname_present_map[ stdout_file ] = 'found at least ' + str(MINIMAL_LEN_TO_SHOW)+' characters' +# break +# elif dbname[:128].upper() in line.upper(): +# dbname_present_map[ stdout_file ] = 'found truncated DB name.' +# break +# +# for k,v in sorted( dbname_present_map.items() ): +# print(k, ':', v) +# +# # Other STDOUT results will be analyzed after get developers resolution about +# # truncation of DB names to ~235...241 characters. +# # See notes of: 06/Mar/20 06:38 AM; 06/Mar/20 06:45 AM; 09/Mar/20 07:53 AM. +# # Currently we do nothing and just remove them: +# +# time.sleep(1) +# cleanup( (f_sql_chk.name, bkname, dbname, f_ddl_err, f_backup_err, f_restore_err, f_gstat_err, f_sweep_err, f_valid_err, f_ddl_log, f_backup_log, f_restore_log, f_gstat_log, f_sweep_log, f_valid_log, f_fblog_sweep_before, f_fblog_sweep_after, f_diff_sweep, f_fblog_validate_before, f_fblog_validate_after, f_diff_validate) ) +# +# +# #-------------------------------------------- +# +# check_long_dbname(255, 'abc255def') +# check_long_dbname(259, 'qwe259rty') +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + tmp_6248.backup_255 : found truncated DB name. + tmp_6248.ddl_255 : found at least 255 characters + tmp_6248.fblog_diff_sweep_255 : found at least 255 characters + tmp_6248.fblog_diff_validate_255 : found at least 255 characters + tmp_6248.gstat_255 : found truncated DB name. + tmp_6248.restore_255 : found truncated DB name. + + tmp_6248.backup_259 : found truncated DB name. + tmp_6248.ddl_259 : found at least 255 characters + tmp_6248.fblog_diff_sweep_259 : found at least 255 characters + tmp_6248.fblog_diff_validate_259 : found at least 255 characters + tmp_6248.gstat_259 : found truncated DB name. + tmp_6248.restore_259 : found truncated DB name. + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_6248_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6250.py b/tests/bugs/test_core_6250.py new file mode 100644 index 00000000..c4c1ed71 --- /dev/null +++ b/tests/bugs/test_core_6250.py @@ -0,0 +1,175 @@ +#coding:utf-8 +# +# id: bugs.core_6250 +# title: Signature mismatch when creating package body on identical packaged procedure header +# decription: +# Thank Adriano for suggestion. +# Bug existed because backup/restore process changed value of RDB$PROCEDURE_PARAMETERS.RDB$NULL_FLAG +# for procedure parameter from NULL to 0 (zero). +# Test creates trivial package and stores its package body in variable that will be used after b/r. +# Then we do backup / restore and attempt to apply this stored package body again, see 'sql_pk_body'. +# +# Confirmed bug on: 4.0.0.1766, 3.0.6.33247. Attempt to apply 'recreate package ...' with the same SQL code fails with: +# Statement failed, SQLSTATE = 42000 / ... / -Procedure ... has a signature mismatch on package body ... +# Bug was partially fixed in snapshots 4.0.0.1782 and 3.0.6.33252: problem remained if procedure parameter was of built-in +# datatype rather than domain (i.e. this parameter type was TIMESTAMP or INT etc, instead of apropriate domain). +# +# Completely fixed in snapshots 4.0.0.1783 and 3.0.6.33254 (checked 23.02.2020). +# Added special check for parameter that is declared of built-in datatype rather than domain. +# +# tracker_id: CORE-6250 +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import time +# import subprocess +# from fdb import services +# from subprocess import PIPE +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# dba_privileged_name = 'tmp_c6250_cooldba' +# non_privileged_name = 'tmp_c6250_manager' +# +# this_db = db_conn.database_name +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# fdb_rest = os.path.join(context['temp_directory'],'tmp_6250_restored.fdb') +# +# cleanup( (fdb_rest,) ) +# +# # This part of DDL will be used twise: +# sql_pk_body = ''' +# set term ^; +# recreate package body pg_test1 as +# begin +# procedure sp_test1 ( a_since dm_dts ) as begin end +# end +# ^ +# recreate package body pg_test2 as +# begin +# procedure sp_test2 ( a_since timestamp ) as begin end +# end +# ^ +# set term ;^ +# ''' +# +# sql_init = ''' +# create domain dm_dts timestamp; +# commit; +# set term ^; +# create or alter package pg_test1 as +# begin +# procedure sp_test1 ( a_since dm_dts ) ; +# end +# ^ +# create or alter package pg_test2 as +# begin +# procedure sp_test2 ( a_since timestamp ) ; +# end +# ^ +# set term ;^ +# +# %(sql_pk_body)s +# +# commit; +# ''' % dict(globals(), **locals()) +# +# runProgram('isql',[ 'localhost:' + this_db ], sql_init ) +# +# # https://docs.python.org/2/library/subprocess.html#replacing-shell-pipeline +# # gbak -b localhost:$fdb_init stdout | gbak -rep stdin localhost:$fdb_rest +# +# p_sender = subprocess.Popen( [ context['gbak_path'], '-b', 'localhost:' + this_db, 'stdout' ], stdout=PIPE) +# p_getter = subprocess.Popen( [ context['gbak_path'], '-c', 'stdin', 'localhost:' + fdb_rest ], stdin = p_sender.stdout, stdout = PIPE ) +# p_sender.stdout.close() +# p_getter_stdout, p_getter_stderr = p_getter.communicate() +# +# +# f_sql_pk_body = open( os.path.join(context['temp_directory'],'tmp_core_6250_run.sql'), 'w', buffering = 0) +# f_sql_pk_body.write( sql_pk_body ) +# flush_and_close( f_sql_pk_body ) +# +# f_run_pk_body_log = open( '.'.join( (os.path.splitext( f_sql_pk_body.name )[0], 'log') ), 'w', buffering = 0) +# f_run_pk_body_err = open( '.'.join( (os.path.splitext( f_sql_pk_body.name )[0], 'err') ), 'w', buffering = 0) +# subprocess.call( [ context['isql_path'], 'localhost:' + fdb_rest, '-q', '-i', f_sql_pk_body.name ], stdout = f_run_pk_body_log, stderr = f_run_pk_body_err) +# flush_and_close( f_run_pk_body_log ) +# flush_and_close( f_run_pk_body_err ) +# +# +# # Check for UNEXPECTED output: +# ############################# +# for g in ( f_run_pk_body_log, f_run_pk_body_err): +# with open( g.name,'r') as f: +# for line in f: +# if line.strip(): +# print( 'UNEXPECTED ' +('STDOUT' if g == f_run_pk_body_log else 'STDERR')+ ': ' + line ) +# +# # Cleanup +# ######### +# time.sleep(1) +# cleanup( [ i.name for i in ( f_sql_pk_body, f_run_pk_body_log, f_run_pk_body_err, ) ] + [ fdb_rest, ] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0.6') +@pytest.mark.xfail +def test_core_6250_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6251.py b/tests/bugs/test_core_6251.py new file mode 100644 index 00000000..a4d5f0e1 --- /dev/null +++ b/tests/bugs/test_core_6251.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: bugs.core_6251 +# title: Regression: crash when built-in function LEFT() or RIGHT() missed 2nd argument (number of characters to be taken) +# decription: +# Confirmed crash on: 4.0.0.1773; 3.0.6.33247 +# Checked on: 4.0.0.1779; 3.0.6.33251 - works fine. +# +# tracker_id: CORE-6251 +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test( s varchar(10) ); + commit; + insert into test(s) values('1'); + select 1 from test f where right( f.s ) = '1'; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 39000 + function RIGHT could not be matched + """ + +@pytest.mark.version('>=3.0.6') +def test_core_6251_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_6252.py b/tests/bugs/test_core_6252.py new file mode 100644 index 00000000..366fc13a --- /dev/null +++ b/tests/bugs/test_core_6252.py @@ -0,0 +1,113 @@ +#coding:utf-8 +# +# id: bugs.core_6252 +# title: UNIQUE / PRIMARY KEY constraint can be violated when AUTODDL = OFF and mixing commands for DDL and DML +# decription: +# Reproduced bug on 3.0.6.33247, 4.0.0.1782. +# Checked on 3.0.6.33255; 4.0.0.1785 (both - SS and CS) - works fine. +# +# tracker_id: CORE-6252 +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set autoddl off; -- [ !! ] + commit; + + recreate table test1( + a int not null, + b int not null + ); + + recreate table test2( + u int not null, + v int not null + ); + + commit; + + insert into test1(a, b) values (1,1); + insert into test1(a, b) values (1,2); + + insert into test2(u, v) values (1,1); + insert into test2(u, v) values (1,2); + commit; + + + ------------------------------------------------------- + update test1 set b = 1; + alter table test1 add constraint test1_unq unique (a); + commit; + + ------------------------------------------------------- + rollback; -- otherwise exception about PK violation will be supressed by 1st one (about test1_UNQ) + ------------------------------------------------------- + + update test2 set v = 1; + alter table test2 add constraint test2_pk primary key (u); + commit; + + set list on; + select * from test1; + select * from test2; + rollback; + + -- We have to ensure that there are no indices that were created (before this bug fixed) + -- for maintainace of PK/UNQ constraints: + select + ri.rdb$index_name idx_name + ,ri.rdb$unique_flag idx_uniq + from rdb$database r + left join rdb$indices ri on + ri.rdb$relation_name starting with 'TEST' + and ri.rdb$system_flag is distinct from 1 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A 1 + B 1 + A 1 + B 2 + + U 1 + V 1 + U 1 + V 1 + + IDX_NAME + IDX_UNIQ + """ +expected_stderr_1 = """ + 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) + """ + +@pytest.mark.version('>=3.0.6') +def test_core_6252_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6254.py b/tests/bugs/test_core_6254.py new file mode 100644 index 00000000..0f9cddcb --- /dev/null +++ b/tests/bugs/test_core_6254.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_6254 +# title: AV in engine when using SET TRANSACTION and ON TRANSACTION START trigger uses EXECUTE STATEMENT against current transaction +# decription: +# Confirmed crash on: WI-V3.0.6.33251; WI-T4.0.0.1779 +# Checked on: 3.0.6.33252; WI-T4.0.0.1782 - works fine. +# +# tracker_id: CORE-6254 +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set term ^; + create or alter trigger trg_tx_start on transaction start as + declare tx int; + begin + execute statement ('select current_transaction from rdb$database') into tx; + end + ^ + set term ;^ + commit; + + set transaction; + select sign(current_transaction) as s from rdb$database; + commit; -- this raised AV + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + S 1 + """ + +@pytest.mark.version('>=3.0.6') +def test_core_6254_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6262.py b/tests/bugs/test_core_6262.py new file mode 100644 index 00000000..bdd76b1b --- /dev/null +++ b/tests/bugs/test_core_6262.py @@ -0,0 +1,159 @@ +#coding:utf-8 +# +# id: bugs.core_6262 +# title: SHOW DOMAIN/TABLE does not display character set of system objects +# decription: +# We gather all system domains which belongs to TEXT family by query to rdb$fields. +# Then for each record from its resulset we issue statement: 'SHOW DOMAIN ... ;' +# and write it to .SQL file. After all records will be processed, we run ISQL and +# perform this script. Every row from its output must contain phrase 'CHARACTER SET'. +# +# Checked on 4.0.0.1803. +# +# ::: NB ::: additional filtering: "where f.rdb$character_set_id > 1" is needed when +# we query rdb$fields. Otherwise we get some domains without 'CHARACTER SET' phrases +# domains definition: +# rdb$character_set_id=0: +# show domain RDB$EDIT_STRING; +# RDB$EDIT_STRING VARCHAR(127) Nullable +# show domain RDB$MESSAGE; +# RDB$MESSAGE VARCHAR(1023) Nullable +# rdb$character_set_id=1: +# RDB$SYSTEM_PRIVILEGES BINARY(8) Nullable +# +# tracker_id: CORE-6262 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import time +# import subprocess +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# #-------------------------------------------- +# +# 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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# f_sql_chk = open( os.path.join(context['temp_directory'],'tmp_6262_chk.sql'), 'w') +# +# cur = db_conn.cursor() +# sql=''' +# select 'show domain '|| trim(f.rdb$field_name) ||';' as show_expr +# from rdb$fields f +# where f.rdb$character_set_id > 1 +# order by f.rdb$field_name +# ''' +# +# cur.execute(sql) +# text_domains_count = 0 +# for r in cur: +# f_sql_chk.write( r[0]+os.linesep ) +# text_domains_count += 1 +# +# flush_and_close( f_sql_chk ) +# db_conn.close() +# +# +# f_sql_log = open( ''.join( (os.path.splitext(f_sql_chk.name)[0], '.log' ) ), 'w') +# f_sql_err = open( ''.join( (os.path.splitext(f_sql_log.name)[0], '.err' ) ), 'w') +# +# subprocess.call( [ context['isql_path'], dsn, '-i', f_sql_chk.name ], stdout = f_sql_log, stderr = f_sql_err) +# +# flush_and_close( f_sql_log ) +# flush_and_close( f_sql_err ) +# +# # Checks: +# ######### +# # 1. Result of STDERR must be empty: +# with open(f_sql_err.name,'r') as f: +# for line in f: +# if line.split(): +# print('UNEXPECTED STDERR: '+line) +# +# # 2. All lines in STDOUT have to contain phrase 'CHARACTER SET': +# +# lines_with_charset, lines_without_charset = 0, 0 +# +# with open(f_sql_log.name,'r') as f: +# for line in f: +# if line.split(): +# if 'CHARACTER SET' in line: +# lines_with_charset += 1 +# else: +# lines_without_charset += 1 +# +# if lines_with_charset > 0: +# print('Number of lines with specified charset: ' + ( 'SAME AS' if lines_with_charset == text_domains_count else str(lines_with_charset)+' - LESS THEN' ) + ' NUMBER OF TEXT DOMAINS' ) +# else: +# print('SOMETHING WAS WRONG: COULD NOT FIND ANY LINE WITH "CHARACTER SET" PHRASE') +# +# print('Number of lines with missed charset:',lines_without_charset) +# +# # cleanup +# ######### +# time.sleep(1) +# cleanup( (f_sql_chk, f_sql_log, f_sql_err ) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Number of lines with specified charset: SAME AS NUMBER OF TEXT DOMAINS + Number of lines with missed charset: 0 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_6262_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6264.py b/tests/bugs/test_core_6264.py new file mode 100644 index 00000000..bf8d06dc --- /dev/null +++ b/tests/bugs/test_core_6264.py @@ -0,0 +1,137 @@ +#coding:utf-8 +# +# id: bugs.core_6264 +# title: gbak with PIPE to stdout: invalid content if user '-se :service_mgr' command switch +# decription: +# NB: bug can be reproduced only if we create batch file and run it from Python using shell invocation, +# i.e. via subprocess.call(). Python builtin PIPE mechanism does not show any errors. +# For this reason, we create temp batch scenario, add necessary commands there and run it. +# Currently this scenario exists only for Windows. It will be implemented for POSIX later. +# +# Confirmed bug on 3.0.6.33276, 4.0.0.1850. +# Works fine on 3.0.6.33277, 4.0.0.1854 +# +# tracker_id: CORE-6264 +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import sys +# import time +# import subprocess +# from subprocess import PIPE +# from fdb import services +# +# #-------------------------------------------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# +# #-------------------------------------------- +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# fb_home = services.connect(host='localhost', user= user_name, password= user_password).get_home_directory() +# this_db = db_conn.database_name +# db_conn.close() +# +# tmp4restore=os.path.join(context['temp_directory'],'tmp_6264_check_restore.tmp') +# +# cleanup( (tmp4restore,) ) +# +# +# # BACKUP-RESTORE: +# # C:\\FB SS\\gbak.exe -b -se localhost:service_mgr employee stdout | C:\\FB SS\\gbak -c stdin C: emp\\employee.check-restore.tmp +# +# fb_gbak = fb_home+'gbak' +# fb_gfix = fb_home+'gfix' +# txt = ''' +# @echo off +# setlocal enabledelayedexpansion enableextensions +# set ISC_USER=%(user_name)s +# set ISC_PASSWORD=%(user_password)s +# if exist %(tmp4restore)s del %(tmp4restore)s +# if exist %(tmp4restore)s ( +# echo ### ERROR ### +# echo Can not drop file %(tmp4restore)s +# ) else ( +# %(fb_gbak)s -b -se localhost:service_mgr %(this_db)s stdout | %(fb_gbak)s -c stdin %(tmp4restore)s +# if exist %(tmp4restore)s ( +# %(fb_gfix)s -v -full localhost:%(tmp4restore)s +# %(fb_gfix)s -shut full -force 0 localhost:%(tmp4restore)s +# del %(tmp4restore)s +# ) +# +# ) +# ''' % dict(globals(), **locals()) +# +# f_tmp_bat=open( os.path.join(context['temp_directory'],'tmp_run_6264.bat'), 'w', buffering = 0) +# f_tmp_bat.write(txt) +# f_tmp_bat.close() +# +# ##################### +# # DOES NOT WORK HERE: +# ##################### +# # https://docs.python.org/2/library/subprocess.html#replacing-shell-pipeline +# #p_sender = subprocess.Popen( [ fb_home+'gbak', '-b', '-se', 'localhost:service_mgr', this_db, 'stdout' ], stdout=PIPE) +# #p_getter = subprocess.Popen( [ fb_home+'gbak', '-c', 'stdin', tmp4restore ], stdin = p_sender.stdout, stdout = PIPE ) +# #p_sender.stdout.close() +# #p_getter_stdout, p_getter_stderr = p_getter.communicate() +# #print('p_getter_stdout:', p_getter_stdout) -- returns EMPTY string +# #print('p_getter_stderr:', p_getter_stderr) -- returns None. +# ###################### +# +# f_bat_log=open( os.path.join(context['temp_directory'],'tmp_c6264.log'), "w", buffering = 0) +# f_bat_err=open( os.path.join(context['temp_directory'],'tmp_c6264.err'), "w", buffering = 0) +# +# subprocess.call( [ f_tmp_bat.name ], stdout=f_bat_log, stderr=f_bat_err) +# +# f_bat_log.close() +# f_bat_err.close() +# +# # Both STDOUT and STDERR results must be empty, which means no errors: +# ######################## +# with open(f_bat_log.name, 'r') as f: +# for line in f: +# if line.split(): +# print( ''.join( ( 'UNEXPECTED STDOUT: ', line.strip() ) ) ) +# +# with open(f_bat_err.name, 'r') as f: +# for line in f: +# if line.split(): +# print( ''.join( ( 'UNEXPECTED STDERR: ', line.strip() ) ) ) +# +# cleanup( [ i.name for i in ( f_tmp_bat,f_bat_log,f_bat_err ) ] + [tmp4restore,] ) +# +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0.6') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_6264_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6265.py b/tests/bugs/test_core_6265.py new file mode 100644 index 00000000..da4051dc --- /dev/null +++ b/tests/bugs/test_core_6265.py @@ -0,0 +1,162 @@ +#coding:utf-8 +# +# id: bugs.core_6265 +# title: mapping rules destroyed by backup / restore +# decription: +# Confirmed bug on: 4.0.0.1796 CS; 3.0.6.33247 CS. +# Works fine on: 4.0.0.1806 SS; 3.0.6.33272 CS. +# +# tracker_id: CORE-6265 +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import sys +# import time +# import subprocess +# from subprocess import PIPE +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# sql_init=''' +# create role boss; +# create mapping map_boss using plugin win_sspi from user Bill to role boss; +# commit; +# create view v_map as +# select +# rdb$map_name, +# rdb$map_using, +# rdb$map_plugin, +# rdb$map_db, +# rdb$map_from_type, +# rdb$map_from, +# rdb$map_to_type, +# rdb$map_to +# from rdb$auth_mapping; +# commit; +# set list on; +# set count on; +# select * from v_map; +# ''' +# +# f_init_sql = open( os.path.join(context['temp_directory'],'tmp_6265.sql'), 'w', buffering = 0) +# f_init_sql.write( sql_init ) +# flush_and_close( f_init_sql ) +# +# f_init_log = open( '.'.join( (os.path.splitext( f_init_sql.name )[0], 'log') ), 'w', buffering = 0) +# subprocess.call( [ context['isql_path'], dsn, '-q', '-i', f_init_sql.name ], stdout = f_init_log, stderr = subprocess.STDOUT) +# flush_and_close( f_init_log ) +# +# this_restored_1=os.path.join(context['temp_directory'],'tmp_6265_1.tmp') +# this_restored_2=os.path.join(context['temp_directory'],'tmp_6265_2.tmp') +# +# cleanup( (this_restored_1, this_restored_2) ) +# +# # https://docs.python.org/2/library/subprocess.html#replacing-shell-pipeline +# # output=`dmesg | grep hda` +# # becomes: +# # p1 = Popen(["dmesg"], stdout=PIPE) +# # p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE) +# # p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits. +# # output = p2.communicate()[0] +# # gbak -b localhost:$fdb_init stdout | gbak -rep stdin localhost:$fdb_rest +# +# # BACKUP-RESTORE #1: +# # ~~~~~~~~~~~~~~~~~~ +# p_sender = subprocess.Popen( [ context['gbak_path'], '-b', dsn, 'stdout' ], stdout=PIPE) +# p_getter = subprocess.Popen( [ context['gbak_path'], '-c', 'stdin', 'localhost:' + this_restored_1 ], stdin = p_sender.stdout, stdout = PIPE ) +# p_sender.stdout.close() +# p_getter_stdout, p_getter_stderr = p_getter.communicate() +# +# #--------------------------------------------------------- +# +# # BACKUP-RESTORE #2: +# # ~~~~~~~~~~~~~~~~~~ +# p_sender = subprocess.Popen( [ context['gbak_path'], '-b', 'localhost:' + this_restored_1, 'stdout' ], stdout=PIPE) +# p_getter = subprocess.Popen( [ context['gbak_path'], '-c', 'stdin', 'localhost:' + this_restored_2 ], stdin = p_sender.stdout, stdout = PIPE ) +# p_sender.stdout.close() +# p_getter_stdout, p_getter_stderr = p_getter.communicate() +# +# #---------------------------------------------------------- +# +# runProgram(context['isql_path'],[ 'localhost:' + this_restored_2 ], 'set list on; set count on; select * from v_map;') +# +# # cleanup: +# ########## +# time.sleep(1) +# cleanup( (this_restored_1, this_restored_2, f_init_sql, f_init_log) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$MAP_NAME MAP_BOSS + RDB$MAP_USING P + RDB$MAP_PLUGIN WIN_SSPI + RDB$MAP_DB + RDB$MAP_FROM_TYPE USER + RDB$MAP_FROM BILL + RDB$MAP_TO_TYPE 1 + RDB$MAP_TO BOSS + Records affected: 1 + """ + +@pytest.mark.version('>=3.0.6') +@pytest.mark.xfail +def test_core_6265_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6266.py b/tests/bugs/test_core_6266.py new file mode 100644 index 00000000..37a25a5b --- /dev/null +++ b/tests/bugs/test_core_6266.py @@ -0,0 +1,104 @@ +#coding:utf-8 +# +# id: bugs.core_6266 +# title: Deleting records from MON$ATTACHMENTS using ORDER BY clause doesn't close the corresponding attachments +# decription: +# Old title: Don't close attach while deleting record from MON$ATTACHMENTS using ORDER BY clause. +# Confirmed bug on 3.0.6.33271. +# Checked on 3.0.6.33272 (SS/CS) - works fine. +# 22.04.2020. Checked separately on 4.0.0.1931 SS/CS: all OK. FB 4.0 can also be tested since this build. +# +# tracker_id: CORE-6266 +# min_versions: ['3.0.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import sys +# import time +# import fdb +# +# ATT_CNT=5 +# ATT_DELAY=1 +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# con_list={} +# for i in range(0, ATT_CNT): +# if i > 0: +# time.sleep( ATT_DELAY ) +# +# c = fdb.connect(dsn = dsn) +# a = c.attachment_id +# con_list[ i ] = (a, c) +# # print('created attachment ', (a,c) ) +# +# con_admin = con_list[0][1] +# +# #print(con_admin.firebird_version) +# +# # this removes ALL connections --> should NOT be used for reproducing ticket issue: +# #con_admin.execute_immediate('delete from mon$attachments where mon$attachment_id != current_connection order by mon$timestamp') +# +# # this removes ALL connections --> should NOT be used for reproducing ticket issue: +# #con_admin.execute_immediate('delete from mon$attachments where mon$system_flag is distinct from 1 and mon$attachment_id != current_connection order by mon$timestamp') +# +# # This DOES NOT remove all attachments (only 'last' in order of timestamp), but +# # DELETE statement must NOT contain phrase 'mon$attachment_id != current_connection': +# con_admin.execute_immediate('delete from mon$attachments where mon$system_flag is distinct from 1 order by mon$timestamp') +# +# con_admin.commit() +# +# cur_admin = con_admin.cursor() +# cur_admin.execute('select mon$attachment_id,mon$user from mon$attachments where mon$system_flag is distinct from 1 and mon$attachment_id != current_connection' ) +# i=0 +# for r in cur_admin: +# print( '### ACHTUNG ### STILL ALIVE ATTACHMENT DETECTED: ', r[0], r[1].strip(), '###' ) +# i += 1 +# print('Number of attachments that remains alive: ',i) +# +# cur_admin.close() +# +# #print('Final cleanup before quit from Python.') +# +# for k,v in sorted( con_list.items() ): +# #print('attempt to close attachment ', v[0] ) +# try: +# v[1].close() +# #print('done.') +# except Exception as e: +# pass +# #print('Got exception:', sys.exc_info()[0]) +# #print(e[0]) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Number of attachments that remains alive: 0 + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_core_6266_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6272.py b/tests/bugs/test_core_6272.py new file mode 100644 index 00000000..13c9ec99 --- /dev/null +++ b/tests/bugs/test_core_6272.py @@ -0,0 +1,207 @@ +#coding:utf-8 +# +# id: bugs.core_6272 +# title: Failed attach to database not traced +# decription: +# NB: connect to services must be done using LOCAL protocol rather than remote. +# Otherwise trace log will have only records about connect/disconnect to security.db. +# NO messages about failed search of non-existing database will appear. +# This is known bug, see Alex's issue in the tracker, 07-apr-2020 10:39. +# +# Checked on 4.0.0.1865 SS/CS. +# +# 04-mar-2021. +# Adapted to be run both on Windows and Linux. +# NOTE-1. There is difference between Windows and Linux message for gdscode = 335544344: +# * WINDOWS: 335544344 : I/O error during "CreateFile (open)" operation ... +# * LINUX: 335544344 : I/O error during "open" operation ... +# NOTE-2. Some messages can appear in the trace log ONE or TWO times (SS/CS ?). +# Because of this, we are interested only for at least one occurence of each message +# rather than for each of them (see 'found_patterns', type: set()). +# +# tracker_id: CORE-6272 +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import time +# import re +# from fdb import services +# from subprocess import Popen +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # Obtain engine version: +# engine = str(db_conn.engine_version) # convert to text because 'float' object has no attribute 'startswith' +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# txt = ''' +# database +# { +# enabled = true +# log_connections = true +# log_errors = true +# log_initfini = false +# } +# ''' +# +# f_trc_cfg=open( os.path.join(context['temp_directory'],'tmp_trace_6272.cfg'), 'w') +# f_trc_cfg.write(txt) +# flush_and_close( f_trc_cfg ) +# +# # ############################################################## +# # S T A R T T R A C E i n S E P A R A T E P R O C E S S +# # ############################################################## +# +# f_trc_log=open( os.path.join(context['temp_directory'],'tmp_trace_6272.log'), "w") +# f_trc_err=open( os.path.join(context['temp_directory'],'tmp_trace_6272.err'), "w") +# +# # ::: NB ::: DO NOT USE 'localhost:service_mgr' here! Use only local protocol: +# p_trace = Popen( [ context['fbsvcmgr_path'], 'service_mgr', 'action_trace_start' , 'trc_cfg', f_trc_cfg.name],stdout=f_trc_log,stderr=f_trc_err) +# +# time.sleep(1) +# +# # #################################################### +# # G E T A C T I V E T R A C E S E S S I O N I D +# # #################################################### +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# +# f_trc_lst = open( os.path.join(context['temp_directory'],'tmp_trace_6272.lst'), 'w') +# subprocess.call([ context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_list'], stdout=f_trc_lst) +# flush_and_close( f_trc_lst ) +# +# # !!! DO NOT REMOVE THIS LINE !!! +# time.sleep(1) +# +# trcssn=0 +# with open( f_trc_lst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# +# #------------------------------------------------ +# +# try: +# con = fdb.connect(dsn = 'localhost:non_such_alias') +# except Exception,e: +# # print('Error:', e) +# pass +# +# #------------------------------------------------ +# +# # Let trace log to be entirely written on disk: +# time.sleep(1) +# +# # #################################################### +# # S E N D R E Q U E S T T R A C E T O S T O P +# # #################################################### +# if trcssn>0: +# fn_nul = open(os.devnull, 'w') +# subprocess.call([ context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_stop','trc_id', trcssn], stdout=fn_nul) +# fn_nul.close() +# # DO NOT REMOVE THIS LINE: +# time.sleep(1) +# +# p_trace.terminate() +# flush_and_close( f_trc_log ) +# flush_and_close( f_trc_err ) +# +# # Every of following patterns must be found at *least* one time in the trace log: +# allowed_patterns = [ +# re.compile('FAILED\\s+ATTACH_DATABASE', re.IGNORECASE) +# ,re.compile('ERROR\\s+AT\\s+JProvider(:){1,2}attachDatabase', re.IGNORECASE) +# # ::: NB ::: windows and linux messages *differ* for this gdscode: +# ,re.compile('335544344\\s*(:)?\\s+I(/)?O\\s+error', re.IGNORECASE) +# ,re.compile('335544734\\s*(:)\\s+?Error\\s+while', re.IGNORECASE) +# ] +# found_patterns = set() +# +# with open(f_trc_log.name, 'r') as f: +# for line in f: +# for p in allowed_patterns: +# if p.search(line): +# found_patterns.add( p.pattern ) +# +# # cleanup: +# ########## +# time.sleep(1) +# cleanup( ( f_trc_log, f_trc_err, f_trc_cfg, f_trc_lst ) ) +# +# for p in sorted(found_patterns): +# print('FOUND pattern: ' + p) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + FOUND pattern: 335544344\\s*(:)?\\s+I(/)?O\\s+error + FOUND pattern: 335544734\\s*(:)\\s+?Error\\s+while + FOUND pattern: ERROR\\s+AT\\s+JProvider(:){1,2}attachDatabase + FOUND pattern: FAILED\\s+ATTACH_DATABASE + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_6272_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6278.py b/tests/bugs/test_core_6278.py new file mode 100644 index 00000000..22645ff2 --- /dev/null +++ b/tests/bugs/test_core_6278.py @@ -0,0 +1,285 @@ +#coding:utf-8 +# +# id: bugs.core_6278 +# title: Efficient table scans for DBKEY-based range conditions +# decription: +# We create table with very wide column and add there about 300 rows from rdb$types, with random data +# (in order to prevent RLE-compression which eventually can reduce number of data pages). +# Then we extract all values of rdb$db_key from this table and take into processing two of them. +# First value has 'distance' from starting db_key = 1/3 of total numbers of rows, second has similar +# distance from final db_key. +# Finally we launch trace and start query with SCOPED expression for RDB$DB_KEY: +# select count(*) from tmp_test_6278 where rdb$db_key between ? and ? +# +# Trace must contain after this explained plan with "lower bound, upper bound" phrase and table statistics +# which shows number of reads = count of rows plus 1. +# ::: NOTE::: +# Before fix trace table statistics did not reflect scoped WHERE-expression on RDB$DB_KEY column. +# +# Checked on 4.0.0.1869 - works fine. +# +# tracker_id: CORE-6278 +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import time +# import re +# from fdb import services +# from subprocess import Popen +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# txt = ''' +# database=%[\\\\\\\\/]security?.fdb +# { +# enabled = false +# } +# database=%[\\\\\\\\/]bugs.core_6278.fdb +# { +# enabled = true +# log_initfini = false +# time_threshold = 0 +# log_errors = false +# log_statement_finish = true +# +# exclude_filter = "%(execute block)%" +# include_filter = "%(select count)%" +# +# #log_statement_prepare = true +# print_perf = true +# print_plan = true +# explain_plan = true +# } +# ''' +# +# f_trc_cfg=open( os.path.join(context['temp_directory'],'tmp_trace_6278.cfg'), 'w', buffering = 0) +# f_trc_cfg.write(txt) +# flush_and_close( f_trc_cfg ) +# +# # ############################################################## +# # S T A R T T R A C E i n S E P A R A T E P R O C E S S +# # ############################################################## +# +# f_trc_log=open( os.path.join(context['temp_directory'],'tmp_trace_6278.log'), "w", buffering = 0) +# f_trc_err=open( os.path.join(context['temp_directory'],'tmp_trace_6278.err'), "w", buffering = 0) +# +# # ::: NB ::: DO NOT USE 'localhost:service_mgr' here! Use only local protocol: +# p_trace = Popen( [ context['fbsvcmgr_path'], 'service_mgr', 'action_trace_start' , 'trc_cfg', f_trc_cfg.name],stdout=f_trc_log,stderr=f_trc_err) +# +# time.sleep(1) +# +# # #################################################### +# # G E T A C T I V E T R A C E S E S S I O N I D +# # #################################################### +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# +# f_trc_lst = open( os.path.join(context['temp_directory'],'tmp_trace_6278.lst'), 'w', buffering = 0) +# subprocess.call([ context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_list'], stdout=f_trc_lst) +# flush_and_close( f_trc_lst ) +# +# # !!! DO NOT REMOVE THIS LINE !!! +# time.sleep(1) +# +# trcssn=0 +# with open( f_trc_lst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# +# #------------------------------------------------ +# sql = ''' +# recreate table tmp_test_6278(s varchar(32700)); +# insert into tmp_test_6278 select lpad('',32700,gen_uuid()) from rdb$types; +# commit; +# set heading off; +# set term ^; +# execute block returns( +# count_intermediate_rows int +# ) as +# declare dbkey_1 char(8) character set octets; +# declare dbkey_2 char(8) character set octets; +# declare sttm varchar(255); +# begin +# select max(iif( ri=1, dbkey, null)), max(iif( ri=2, dbkey, null)) +# from ( +# select dbkey, row_number()over(order by dbkey) ri +# from ( +# select +# dbkey +# ,row_number()over(order by dbkey) ra +# ,row_number()over(order by dbkey desc) rd +# from (select rdb$db_key as dbkey from tmp_test_6278) +# ) +# where +# ra = (ra+rd)/3 +# or rd = (ra+rd)/3 +# ) x +# into dbkey_1, dbkey_2; +# +# sttm = q'{select count(*) from tmp_test_6278 where rdb$db_key between ? and ?}'; +# execute statement (sttm) (dbkey_1, dbkey_2) into count_intermediate_rows; +# suspend; +# end +# ^ +# set term ;^ +# commit; +# ''' +# +# f_sql_cmd=open( os.path.join(context['temp_directory'],'tmp_c6278_run.sql'), 'w') +# f_sql_cmd.write(sql) +# flush_and_close( f_sql_cmd ) +# +# f_isql_log=open( os.path.join(context['temp_directory'],'tmp_c6278_run.log'), 'w', buffering = 0) +# f_isql_err=open( os.path.join(context['temp_directory'],'tmp_c6278_run.err'), 'w', buffering = 0) +# +# ###################### +# # S T A R T I S Q L +# ###################### +# subprocess.call( [ context['isql_path'], dsn, '-q', '-i', f_sql_cmd.name], +# stdout=f_isql_log, +# stderr=f_isql_err +# ) +# flush_and_close( f_isql_log ) +# flush_and_close( f_isql_err ) +# +# #------------------------------------------------ +# +# # Let trace log to be entirely written on disk: +# time.sleep(1) +# +# # #################################################### +# # S E N D R E Q U E S T T R A C E T O S T O P +# # #################################################### +# if trcssn>0: +# fn_nul = open(os.devnull, 'w') +# subprocess.call([ context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_stop','trc_id', trcssn], stdout=fn_nul) +# fn_nul.close() +# # DO NOT REMOVE THIS LINE: +# time.sleep(1) +# +# p_trace.terminate() +# flush_and_close( f_trc_log ) +# flush_and_close( f_trc_err ) +# +# +# allowed_patterns = [ +# re.compile(' Table "TMP_TEST_6278"', re.IGNORECASE) +# ,re.compile('TMP_TEST_6278\\s+\\d+', re.IGNORECASE) +# ] +# +# #---------------------------------------------------------------------- +# +# # Parse STDOUT result of ISQL: extract from log result of +# # select count(*) from tmp_test_6278 where rdb$db_key between ? and ?. +# # It must be ~1/3 of rows in RDB$TYPES table for empty database: +# +# with open(f_isql_log.name, 'r') as f: +# for line in f: +# if line.split(): +# count_intermediate_rows = int( line.rstrip().split()[0] ) +# break +# +# # Result of STDERR for ISQL must be empty: +# with open(f_isql_err.name, 'r') as f: +# for line in f: +# if line.split(): +# print('UNEXPECTED STDERR IN ISQL RESULT: ' + line) +# +# #--------------------------------------------------------------------- +# +# # Parse trace log: +# # 1. Extract token from EXPLAINED plan: it must contain "lower bound, upper bound" clause that was introduced by this ticket; +# # 2. Number of reads (currently they are shown under NATURAL read column) must be equal to result obtained in ISQL, plus 1. +# # NB: before fix this number of reads was always equal to the total number of records, regardless on presense of additional +# # WHERE-condition on rdb$db_key column. +# # ----------------------------------------- +# with open(f_trc_log.name, 'r') as f: +# for line in f: +# for p in allowed_patterns: +# if p.search(line): +# if line.startswith('TMP_TEST_6278'): +# trace_reads_statistics = int( line.rstrip().split()[1] ) +# print( 'Reads difference: ' + ('EXPECTED.' if (trace_reads_statistics - count_intermediate_rows) <= 1 else 'UNEXPECTED: ' + str( (trace_reads_statistics - count_intermediate_rows) ) ) ) +# else: +# print(line) +# +# # CLEANUP: +# ########## +# time.sleep(1) +# cleanup( ( f_trc_log, f_trc_err, f_trc_cfg, f_trc_lst, f_isql_log, f_isql_err, f_sql_cmd ) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + -> Table "TMP_TEST_6278" Full Scan (lower bound, upper bound) + Reads difference: EXPECTED. + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_6278_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6279.py b/tests/bugs/test_core_6279.py new file mode 100644 index 00000000..f918e6ea --- /dev/null +++ b/tests/bugs/test_core_6279.py @@ -0,0 +1,199 @@ +#coding:utf-8 +# +# id: bugs.core_6279 +# title: Put options in user management statements in any order +# decription: +# According to new syntax that is described in doc\\sql.extensions\\README.user_management, any statement that +# creates or modifies user, must now look like this: +# CREATE OR ALTER USER name [ SET ] [ options ]; +# where OPTIONS is a list of following options: +# - PASSWORD 'password' +# - FIRSTNAME 'firstname' +# - MIDDLENAME 'middlename' +# - LASTNAME 'lastname' +# - ACTIVE +# - INACTIVE +# - USING PLUGIN name +# - TAGS ( tag [, tag [, tag ...]] ) +# +# We add all options from this list, except 'INACTIVE', as separate records to the table 'TSYNTAX', field: 'token'. +# Then we generate all possible combinations of these options with requirement that each of them occurs in a generated +# record only once (see: f_generate_sql_with_combos). +# Query will contain 7 columns, one per each option, and we further concatenate them to the string. +# As result, this 'suffix part' will contain all tokens in all possible places will be created. +# We will add this 'suffix part' to 'create or alter user ...' statement. +# +# Finally, we redirect result of this query to a new .sql script (see: f_ddl_combinations_script) and run it. +# NOTE: total number of 'CREATE OR ALTER USER' statements in it will be 10080. +# +# Result of this .sql must be EMPTY: all statements have to be executed without error. +# +# It is crusial for this test to make .sql script run within SINGLE transaction otherwise performance will suffer. +# Also, we must inject 'SET BAIL ON;' at the start line of this script in order to make it stop when first error occurs. +# +# Checked on 4.0.0.1876 SS/CS: OK, 6.659/7.722s +# +# tracker_id: CORE-6279 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import time +# import subprocess +# from subprocess import Popen +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql_init=''' +# recreate table tsyntax( token varchar(100) ); +# commit; +# insert into tsyntax( token ) values( 'password ''bar'' ' ); +# insert into tsyntax( token ) values( 'firstname ''john'' ' ); +# insert into tsyntax( token ) values( 'middlename ''ozzy'' ' ); +# insert into tsyntax( token ) values( 'lastname ''osbourne'' ' ); +# insert into tsyntax( token ) values( 'active' ); +# insert into tsyntax( token ) values( 'inactive' ); +# insert into tsyntax( token ) values( 'using plugin Srp' ); +# insert into tsyntax( token ) values( 'tags ( foo = ''bar'', rio = ''gee'' )' ); +# commit; +# +# set heading off; +# select 'set bail on;' from rdb$database union all +# select 'set echo off;' from rdb$database union all +# select 'commit;' from rdb$database union all +# select 'set autoddl off;' from rdb$database union all +# select 'commit;' from rdb$database +# ; +# +# with +# t as ( +# select * +# from tsyntax x +# where x.token not in ('inactive') +# ) +# ,b as ( +# select trim(a.token) as a, trim(b.token) as b, trim(c.token) as c, trim(d.token) as d, trim(e.token) as e, trim(f.token) as f, trim(g.token) as g +# from t a +# left join t b on b.token not in (a.token) +# left join t c on c.token not in (a.token, b.token) +# left join t d on d.token not in (a.token, b.token, c.token) +# left join t e on e.token not in (a.token, b.token, c.token, d.token) +# left join t f on f.token not in (a.token, b.token, c.token, d.token, e.token) +# left join t g on g.token not in (a.token, b.token, c.token, d.token, e.token, f.token) +# ) +# ,c as ( +# select a || ' ' || b || ' ' || c || ' ' || d || ' ' || e || ' ' || f || ' ' || g || ';' as ddl_expr +# from b +# ) +# select 'create or alter user tmp$c6279 ' || ddl_expr from c +# union all +# select 'create or alter user tmp$c6279 ' || replace(ddl_expr, ' active', ' inactive') from c; +# +# select 'rollback;' from rdb$database +# ; +# +# ''' +# +# +# f_generate_sql_with_combos=open( os.path.join(context['temp_directory'],'tmp_c6279_pre.sql'), 'w') +# f_generate_sql_with_combos.write(sql_init) +# flush_and_close( f_generate_sql_with_combos ) +# +# f_ddl_combinations_script=open( os.path.join(context['temp_directory'],'tmp_c6279_run.sql'), 'w', buffering = 0) +# f_create_combinations_err=open( os.path.join(context['temp_directory'],'tmp_c6279_pre.err'), 'w', buffering = 0) +# +# # PREPARING. GENERATE .SQL STATEMENTS WITH ALL POSSIBLE COMBINATIONS OF OPTIONS: +# ############ +# subprocess.call( [context['isql_path'], dsn, '-q', '-i', f_generate_sql_with_combos.name], stdout=f_ddl_combinations_script, stderr=f_create_combinations_err ) +# flush_and_close( f_ddl_combinations_script ) +# flush_and_close( f_create_combinations_err ) +# +# #------------------------------------------------------------------------------------------------ +# +# f_run_ddl_combinations_log=open( os.path.join(context['temp_directory'],'tmp_c6279_run.log'), 'w', buffering = 0) +# f_run_ddl_combinations_err=open( os.path.join(context['temp_directory'],'tmp_c6279_run.err'), 'w', buffering = 0) +# +# # MAIN QUERY. CHECK ALL POSSIBLE COMBINATIONS OF OPTIONS: +# ############# +# subprocess.call( [context['isql_path'], dsn, '-q', '-i', f_ddl_combinations_script.name], stdout=f_run_ddl_combinations_log, stderr=f_run_ddl_combinations_err ) +# flush_and_close( f_run_ddl_combinations_log ) +# flush_and_close( f_run_ddl_combinations_err ) +# +# # Checks: +# ######### +# # Both for prepare (creating main .sql) and for main sql script STDOUT and STDERR must be empty: +# for r in (f_run_ddl_combinations_log, f_create_combinations_err, f_run_ddl_combinations_err): +# with open(r.name, 'r') as f: +# for line in f: +# if line.split(): +# print('UNEXPECTED OUTPUT IN ISQL RESULT: ' + line.strip() +'; file: ' + r.name ) +# +# # Cleanup: +# ########## +# time.sleep(1) +# +# cleanup( ( f_generate_sql_with_combos,f_ddl_combinations_script,f_create_combinations_err,f_run_ddl_combinations_log,f_run_ddl_combinations_err ) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_6279_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6280.py b/tests/bugs/test_core_6280.py new file mode 100644 index 00000000..bcd64fbc --- /dev/null +++ b/tests/bugs/test_core_6280.py @@ -0,0 +1,70 @@ +#coding:utf-8 +# +# id: bugs.core_6280 +# title: MERGE statement loses parameters in WHEN (NOT) MATCHED clause that will never be matched, crashes server in some situations +# decription: +# Confirmed crash on WI-V3.0.5.33220, WI-T4.0.0.1871 - but only when run MERGE statements with parameters from Python. NO crash when run it from ISQL. +# No crash on 4.0.0.1881, but message "No SQLDA for input values provided" will raise for any number of input parameters: 2 or 3. +# 18.04.2020: checked on 3.0.6.33288. Reduced minimal allowed version to 3.0.6. +# +# tracker_id: CORE-6280 +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table t(i int not null primary key, j int); + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# cur=db_conn.cursor() +# stm=''' +# merge into t +# using (select 1 x from rdb$database) on 1 = 1 +# when matched then +# update set j = ? +# when matched and i = ? then +# delete +# when not matched then +# insert (i, j) values (1, ?) +# ''' +# +# try: +# cur.execute( stm ) (1,2,) +# # cur.execute( stm ) (1,2,3,) -- also leads to "No SQLDA for input values provided" +# except Exception as e: +# print(e[0]) +# finally: +# cur.close() +# db_conn.close() +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Error while executing SQL statement: + - SQLCODE: -902 + - Dynamic SQL Error + - SQLDA error + - No SQLDA for input values provided + """ + +@pytest.mark.version('>=3.0.6') +@pytest.mark.xfail +def test_core_6280_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6281.py b/tests/bugs/test_core_6281.py new file mode 100644 index 00000000..b1178881 --- /dev/null +++ b/tests/bugs/test_core_6281.py @@ -0,0 +1,519 @@ +#coding:utf-8 +# +# id: bugs.core_6281 +# title: Invalid timestamp errors with RDB$TIME_ZONE_UTIL.TRANSITIONS +# decription: +# NB: it isn crusial for this test to add 'GMT' after each of timestamp values if we are in the Eastern hemisphere. +# Otherwise (e.g. 'timestamp '0001-01-01', timestamp '9999-12-31') leads to: +# Statement failed, SQLSTATE = 22008 +# value exceeds the range for valid timestamps +# -At procedure 'RDB$TIME_ZONE_UTIL.TRANSITIONS' +# +# Checked on 4.0.0.1876: all OK. +# +# tracker_id: CORE-6281 +# min_versions: [] +# versions: 4.0.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + select p.* + from rdb$time_zone_util.transitions('Europe/Moscow', timestamp '0001-01-01 GMT', timestamp '9999-12-31 GMT') p + order by p.rdb$zone_offset, p.rdb$dst_offset, p.rdb$effective_offset, p.rdb$start_timestamp, p.rdb$end_timestamp; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$START_TIMESTAMP 1922-09-30 21:00:00.0000 GMT + RDB$END_TIMESTAMP 1930-06-20 21:59:59.9999 GMT + RDB$ZONE_OFFSET 120 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 120 + + RDB$START_TIMESTAMP 1991-09-29 00:00:00.0000 GMT + RDB$END_TIMESTAMP 1992-01-18 23:59:59.9999 GMT + RDB$ZONE_OFFSET 120 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 120 + + RDB$START_TIMESTAMP 1991-03-30 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1991-09-28 23:59:59.9999 GMT + RDB$ZONE_OFFSET 120 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 0001-01-01 00:00:00.0000 GMT + RDB$END_TIMESTAMP 1916-07-02 21:29:42.9999 GMT + RDB$ZONE_OFFSET 150 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 150 + + RDB$START_TIMESTAMP 1916-07-02 21:29:43.0000 GMT + RDB$END_TIMESTAMP 1917-07-01 20:28:40.9999 GMT + RDB$ZONE_OFFSET 151 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 151 + + RDB$START_TIMESTAMP 1917-12-27 20:28:41.0000 GMT + RDB$END_TIMESTAMP 1918-05-31 19:28:40.9999 GMT + RDB$ZONE_OFFSET 151 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 151 + + RDB$START_TIMESTAMP 1917-07-01 20:28:41.0000 GMT + RDB$END_TIMESTAMP 1917-12-27 20:28:40.9999 GMT + RDB$ZONE_OFFSET 151 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 211 + + RDB$START_TIMESTAMP 1918-09-15 20:28:41.0000 GMT + RDB$END_TIMESTAMP 1919-05-31 19:28:40.9999 GMT + RDB$ZONE_OFFSET 151 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 211 + + RDB$START_TIMESTAMP 1918-05-31 19:28:41.0000 GMT + RDB$END_TIMESTAMP 1918-09-15 20:28:40.9999 GMT + RDB$ZONE_OFFSET 151 + RDB$DST_OFFSET 120 + RDB$EFFECTIVE_OFFSET 271 + + RDB$START_TIMESTAMP 1919-05-31 19:28:41.0000 GMT + RDB$END_TIMESTAMP 1919-06-30 23:59:59.9999 GMT + RDB$ZONE_OFFSET 151 + RDB$DST_OFFSET 120 + RDB$EFFECTIVE_OFFSET 271 + + RDB$START_TIMESTAMP 1919-08-15 20:00:00.0000 GMT + RDB$END_TIMESTAMP 1921-02-14 19:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 1921-09-30 20:00:00.0000 GMT + RDB$END_TIMESTAMP 1922-09-30 20:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 1930-06-20 22:00:00.0000 GMT + RDB$END_TIMESTAMP 1981-03-31 20:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 1981-09-30 20:00:00.0000 GMT + RDB$END_TIMESTAMP 1982-03-31 20:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 1982-09-30 20:00:00.0000 GMT + RDB$END_TIMESTAMP 1983-03-31 20:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 1983-09-30 20:00:00.0000 GMT + RDB$END_TIMESTAMP 1984-03-31 20:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 1984-09-29 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1985-03-30 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 1985-09-28 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1986-03-29 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 1986-09-27 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1987-03-28 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 1987-09-26 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1988-03-26 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 1988-09-24 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1989-03-25 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 1989-09-23 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1990-03-24 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 1990-09-29 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1991-03-30 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 1992-01-19 00:00:00.0000 GMT + RDB$END_TIMESTAMP 1992-03-28 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 1992-09-26 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1993-03-27 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 1993-09-25 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1994-03-26 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 1994-09-24 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1995-03-25 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 1995-09-23 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1996-03-30 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 1996-10-26 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1997-03-29 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 1997-10-25 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1998-03-28 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 1998-10-24 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1999-03-27 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 1999-10-30 23:00:00.0000 GMT + RDB$END_TIMESTAMP 2000-03-25 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 2000-10-28 23:00:00.0000 GMT + RDB$END_TIMESTAMP 2001-03-24 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 2001-10-27 23:00:00.0000 GMT + RDB$END_TIMESTAMP 2002-03-30 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 2002-10-26 23:00:00.0000 GMT + RDB$END_TIMESTAMP 2003-03-29 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 2003-10-25 23:00:00.0000 GMT + RDB$END_TIMESTAMP 2004-03-27 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 2004-10-30 23:00:00.0000 GMT + RDB$END_TIMESTAMP 2005-03-26 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 2005-10-29 23:00:00.0000 GMT + RDB$END_TIMESTAMP 2006-03-25 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 2006-10-28 23:00:00.0000 GMT + RDB$END_TIMESTAMP 2007-03-24 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 2007-10-27 23:00:00.0000 GMT + RDB$END_TIMESTAMP 2008-03-29 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 2008-10-25 23:00:00.0000 GMT + RDB$END_TIMESTAMP 2009-03-28 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 2009-10-24 23:00:00.0000 GMT + RDB$END_TIMESTAMP 2010-03-27 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 2010-10-30 23:00:00.0000 GMT + RDB$END_TIMESTAMP 2011-03-26 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 2014-10-25 22:00:00.0000 GMT + RDB$END_TIMESTAMP 9999-12-31 23:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 180 + + RDB$START_TIMESTAMP 1919-07-01 00:00:00.0000 GMT + RDB$END_TIMESTAMP 1919-08-15 19:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 1921-02-14 20:00:00.0000 GMT + RDB$END_TIMESTAMP 1921-03-20 18:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 1921-08-31 19:00:00.0000 GMT + RDB$END_TIMESTAMP 1921-09-30 19:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 1981-03-31 21:00:00.0000 GMT + RDB$END_TIMESTAMP 1981-09-30 19:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 1982-03-31 21:00:00.0000 GMT + RDB$END_TIMESTAMP 1982-09-30 19:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 1983-03-31 21:00:00.0000 GMT + RDB$END_TIMESTAMP 1983-09-30 19:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 1984-03-31 21:00:00.0000 GMT + RDB$END_TIMESTAMP 1984-09-29 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 1985-03-30 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1985-09-28 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 1986-03-29 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1986-09-27 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 1987-03-28 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1987-09-26 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 1988-03-26 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1988-09-24 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 1989-03-25 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1989-09-23 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 1990-03-24 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1990-09-29 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 1992-03-28 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1992-09-26 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 1993-03-27 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1993-09-25 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 1994-03-26 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1994-09-24 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 1995-03-25 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1995-09-23 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 1996-03-30 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1996-10-26 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 1997-03-29 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1997-10-25 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 1998-03-28 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1998-10-24 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 1999-03-27 23:00:00.0000 GMT + RDB$END_TIMESTAMP 1999-10-30 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 2000-03-25 23:00:00.0000 GMT + RDB$END_TIMESTAMP 2000-10-28 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 2001-03-24 23:00:00.0000 GMT + RDB$END_TIMESTAMP 2001-10-27 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 2002-03-30 23:00:00.0000 GMT + RDB$END_TIMESTAMP 2002-10-26 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 2003-03-29 23:00:00.0000 GMT + RDB$END_TIMESTAMP 2003-10-25 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 2004-03-27 23:00:00.0000 GMT + RDB$END_TIMESTAMP 2004-10-30 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 2005-03-26 23:00:00.0000 GMT + RDB$END_TIMESTAMP 2005-10-29 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 2006-03-25 23:00:00.0000 GMT + RDB$END_TIMESTAMP 2006-10-28 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 2007-03-24 23:00:00.0000 GMT + RDB$END_TIMESTAMP 2007-10-27 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 2008-03-29 23:00:00.0000 GMT + RDB$END_TIMESTAMP 2008-10-25 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 2009-03-28 23:00:00.0000 GMT + RDB$END_TIMESTAMP 2009-10-24 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 2010-03-27 23:00:00.0000 GMT + RDB$END_TIMESTAMP 2010-10-30 22:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET 240 + + RDB$START_TIMESTAMP 1921-03-20 19:00:00.0000 GMT + RDB$END_TIMESTAMP 1921-08-31 18:59:59.9999 GMT + RDB$ZONE_OFFSET 180 + RDB$DST_OFFSET 120 + RDB$EFFECTIVE_OFFSET 300 + + RDB$START_TIMESTAMP 2011-03-26 23:00:00.0000 GMT + RDB$END_TIMESTAMP 2014-10-25 21:59:59.9999 GMT + RDB$ZONE_OFFSET 240 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET 240 + + + Records affected: 78 + """ + +@pytest.mark.version('>=4.0.0') +def test_core_6281_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6282.py b/tests/bugs/test_core_6282.py new file mode 100644 index 00000000..7edc39de --- /dev/null +++ b/tests/bugs/test_core_6282.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: bugs.core_6282 +# title: Change type of MON$ATTACHMENTS.MON$IDLE_TIMER and MON$STATEMENTS.MON$STATEMENT_TIMER to TIMESTAMP WITH TIME ZONE +# decription: +# Checked on 4.0.0.1881. +# +# tracker_id: CORE-6282 +# min_versions: [] +# versions: 4.0.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0.0 +# resources: None + +substitutions_1 = [('^((?!(sqltype)).)*$', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set sqlda_display on; + set list on; + select a.mon$idle_timer, s.mon$statement_timer from mon$attachments a join mon$statements s using(mon$attachment_id) rows 0; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 01: sqltype: 32754 TIMESTAMP WITH TIME ZONE Nullable scale: 0 subtype: 0 len: 12 + 02: sqltype: 32754 TIMESTAMP WITH TIME ZONE Nullable scale: 0 subtype: 0 len: 12 + """ + +@pytest.mark.version('>=4.0.0') +def test_core_6282_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6285.py b/tests/bugs/test_core_6285.py new file mode 100644 index 00000000..53712d81 --- /dev/null +++ b/tests/bugs/test_core_6285.py @@ -0,0 +1,133 @@ +#coding:utf-8 +# +# id: bugs.core_6285 +# title: SQL-level replication management +# decription: +# Test only verifies ability to use statements described in the ticket. +# Checked on 4.0.0.1920. +# +# 28.10.2020 +# Replaced 'ADD ... to publication' and 'DROP ... from publication' with +# 'INCLUDE ...' and 'EXCLUDE ...' respectively (after reply from dimitr). +# Checked on 4.0.0.2240. +# +# tracker_id: CORE-6285 +# min_versions: [] +# versions: 4.0.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set bail on; + set count on; + -- set echo on; + recreate table test1(id int primary key, x int); + recreate table test2(id int primary key, x int); + recreate table test3(id int primary key, x int); + commit; + + select 'rdb$pub: initial content for a NEW database' as msg, p.* from RDB$PUBLICATIONS p; + alter database enable publication; + commit; + select 'rdb$pub after enable for the WHOLE DATABASE' as msg, p.* from RDB$PUBLICATIONS p; + + alter database disable publication; + commit; + select 'rdb$pub after disable for the WHOLE DATABASE' as msg, p.* from RDB$PUBLICATIONS p; + commit; + + alter database include all to publication; + commit; + select 'rdb$pub after ADD ALL tables to publication' as msg, p.* from RDB$PUBLICATION_TABLES p; + + + alter database exclude all from publication; + commit; + select 'rdb$pub after DROP ALL tables from publication' as msg, p.* from rdb$database left join RDB$PUBLICATION_TABLES p on 1=1; + + + alter database include table test2, test3 to publication; + commit; + select 'rdb$pub after ADD LIST of some tables to publication' as msg, p.* from RDB$PUBLICATION_TABLES p; + + alter database exclude table test2, test3 from publication; + commit; + 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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 + MSG rdb$pub after ADD ALL tables to publication + RDB$PUBLICATION_NAME RDB$DEFAULT + RDB$TABLE_NAME TEST2 + MSG rdb$pub after ADD ALL tables to publication + RDB$PUBLICATION_NAME RDB$DEFAULT + RDB$TABLE_NAME TEST3 + Records affected: 3 + + MSG rdb$pub after DROP ALL tables from publication + RDB$PUBLICATION_NAME + RDB$TABLE_NAME + Records affected: 1 + + MSG rdb$pub after ADD LIST of some tables to publication + RDB$PUBLICATION_NAME RDB$DEFAULT + RDB$TABLE_NAME TEST2 + + MSG rdb$pub after ADD LIST of some tables to publication + RDB$PUBLICATION_NAME RDB$DEFAULT + RDB$TABLE_NAME TEST3 + Records affected: 2 + + MSG rdb$pub after DROP LIST of some tables from publication + RDB$PUBLICATION_NAME + RDB$TABLE_NAME + Records affected: 1 + """ + +@pytest.mark.version('>=4.0.0') +def test_core_6285_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6286.py b/tests/bugs/test_core_6286.py new file mode 100644 index 00000000..456b37a7 --- /dev/null +++ b/tests/bugs/test_core_6286.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: bugs.core_6286 +# title: Make usage of TIMESTAMP/TIME WITH TIME ZONE convenient for users when appropriate ICU library is not installed on the client side +# decription: +# Test only verifies ability to use 'EXTENDED' clause in SET BIND statement. +# We can not simulate absense of appropriate ICU library and for this reason values of time/timestamp are suppressednot checked. +# Checked on 4.0.0.1905. +# +# tracker_id: CORE-6286 +# min_versions: [] +# versions: 4.0.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0.0 +# resources: None + +substitutions_1 = [('^((?!(sqltype|extended)).)*$', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set sqlda_display on; + + set bind of time with time zone to extended; + select time '11:11:11.111 Indian/Cocos' as "check_bind_time_with_zone_to_extended" from rdb$database; + + set bind of timestamp with time zone to extended; + select timestamp '2018-12-31 12:31:42.543 Pacific/Fiji' as "check_bind_timestamp_with_zone_to_extended" from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 01: sqltype: 32750 EXTENDED TIME WITH TIME ZONE scale: 0 subtype: 0 len: 8 + : name: CONSTANT alias: check_bind_time_with_zone_to_extended + check_bind_time_with_zone_to_extended + + 01: sqltype: 32748 EXTENDED TIMESTAMP WITH TIME ZONE scale: 0 subtype: 0 len: 12 + : name: CONSTANT alias: check_bind_timestamp_with_zone_to_extended + check_bind_timestamp_with_zone_to_extended + """ + +@pytest.mark.version('>=4.0.0') +def test_core_6286_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6290.py b/tests/bugs/test_core_6290.py new file mode 100644 index 00000000..6303781d --- /dev/null +++ b/tests/bugs/test_core_6290.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: bugs.core_6290 +# title: Hex number used at end of statement (e.g. CREATE DOMAIN ... DEFAULT) may read invalid memory and produce wrong values or exceptions +# decription: +# Checked on 3.0.6.33289, 4.0.0.1931. +# +# tracker_id: CORE-6290 +# min_versions: [] +# versions: 3.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- All following statements should not produce neither STDOUT nor STDERR: + + create domain dm_test_01 as double precision default 100000000; + create domain dm_test_02 as bigint default 0xf0000000; + ---------------------------------------------------------------- + create domain dm_test_03 as int default 1; + create domain dm_test_04 as bigint default 0xf0000000; + ---------------------------------------------------------------- + create domain dm_test_05 as date default 'TODAY'; + create domain dm_test_06 as bigint default 0x0F0000000; + ---------------------------------------------------------------- + create domain dm_test_07 as boolean default true; + create domain dm_test_08 as bigint default 0x0F0000000; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0.6') +def test_core_6290_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_6291.py b/tests/bugs/test_core_6291.py new file mode 100644 index 00000000..c34c5ca3 --- /dev/null +++ b/tests/bugs/test_core_6291.py @@ -0,0 +1,68 @@ +#coding:utf-8 +# +# id: bugs.core_6291 +# title: Statement "CREATE DOMAIN [dm_name] as BIGINT" raises "numeric value is out of range" if its default value is -9223372036854775808 +# decription: +# Checked on 4.0.0.2100 - all OK. +# (intermediate snapshot with timestamp: 10.07.20 11:44) +# +# tracker_id: CORE-6291 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + create domain dm_bigint_absolute_max as bigint default 9223372036854775807; + create domain dm_bigint_absolute_min as bigint default -9223372036854775808; + create domain dm_int128_absolute_max as int128 default 170141183460469231731687303715884105727; + create domain dm_int128_absolute_min as int128 default -170141183460469231731687303715884105728; + + create table test1( + n_bigint_absol_max bigint default 9223372036854775807 + ,n_bigint_absol_min bigint default -9223372036854775808 + ,n_int128_absol_max int128 default 170141183460469231731687303715884105727 + ,n_int128_absol_min int128 default -170141183460469231731687303715884105728 + ,n_dm_bigint_absol_max dm_bigint_absolute_max + ,n_dm_bigint_absol_min dm_bigint_absolute_min + ,n_dm_int128_absol_max dm_int128_absolute_max + ,n_dm_int128_absol_min dm_int128_absolute_min + ); + commit; + + insert into test1 default values; + select * from test1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + N_BIGINT_ABSOL_MAX 9223372036854775807 + N_BIGINT_ABSOL_MIN -9223372036854775808 + N_INT128_ABSOL_MAX 170141183460469231731687303715884105727 + N_INT128_ABSOL_MIN -170141183460469231731687303715884105728 + N_DM_BIGINT_ABSOL_MAX 9223372036854775807 + N_DM_BIGINT_ABSOL_MIN -9223372036854775808 + N_DM_INT128_ABSOL_MAX 170141183460469231731687303715884105727 + N_DM_INT128_ABSOL_MIN -170141183460469231731687303715884105728 + """ + +@pytest.mark.version('>=4.0') +def test_core_6291_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6294.py b/tests/bugs/test_core_6294.py new file mode 100644 index 00000000..0255d3f6 --- /dev/null +++ b/tests/bugs/test_core_6294.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_6294 +# title: Negative 128-bit integer constants are not accepted in DEFAULT clause +# decription: +# Checked on 4.0.0.2104 +# +# tracker_id: CORE-6294 +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('^((?!sqltype|FIELD_).)*$', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + create domain dm_test as numeric(20,2) default -9999999999999999991; + create table test (x dm_test, y numeric(20,2) default -9999999999999999991); + set sqlda_display on; + insert into test default values returning x as field_x, y as field_y; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 01: sqltype: 32752 INT128 Nullable scale: -2 subtype: 1 len: 16 + : name: X alias: FIELD_X + 02: sqltype: 32752 INT128 Nullable scale: -2 subtype: 1 len: 16 + : name: Y alias: FIELD_Y + + FIELD_X -9999999999999999991.00 + FIELD_Y -9999999999999999991.00 + """ + +@pytest.mark.version('>=4.0') +def test_core_6294_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6300.py b/tests/bugs/test_core_6300.py new file mode 100644 index 00000000..5736daab --- /dev/null +++ b/tests/bugs/test_core_6300.py @@ -0,0 +1,56 @@ +#coding:utf-8 +# +# id: bugs.core_6300 +# title: Next attachment id, next statement id - get this info via MON$ query and rdb$get_context() +# decription: +# Check SQLDA output by query mon$database columns and context variabled that are described in doc/sql.extensions/README.context_variables2 +# See also: https://github.com/FirebirdSQL/firebird/commit/22ad236f625716f5f2885f8d9e783cca9516f7b3 +# Checked on 4.0.0.2170. +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: bugs.core_6300 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('^((?!sqltype|name:).)*$', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set sqlda_display on; + set planonly; + select mon$guid,mon$file_id,mon$next_attachment,mon$next_statement, rdb$get_context('SYSTEM', 'DB_GUID'), rdb$get_context('SYSTEM', 'DB_FILE_ID') + from mon$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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_core_6300_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6309.py b/tests/bugs/test_core_6309.py new file mode 100644 index 00000000..91669c11 --- /dev/null +++ b/tests/bugs/test_core_6309.py @@ -0,0 +1,219 @@ +#coding:utf-8 +# +# id: bugs.core_6309 +# title: fbsvcmgr can not decode information buffer returned by gfix list limbo service +# decription: +# Test creates two databases and uses fdb.ConnectionGroup() for working with them using two connections. +# Then we add several rows in both databases (using autonomous transactions for one of them) and change state +# of this DB to full shutdown (see 'dbname_a'). +# After this we return 'dbname_a' to online. +# At this point this DB must contain dozen transaction in limbo state. +# Both 'gfix -list' and 'fbsvcmgr action_repair rpr_list_limbo_trans' can display only 146 transactions because +# of limited internal buffer size which is used. +# We check that number of lines which are issued by these utilities is equal. +# NB-1: concrete numbers of transactions will DIFFER on SS/SC/CS. We must check only *number* of lines. +# NB-2: we can not use svc.get_limbo_transaction_ids( ) because FDB raises exception: +# File "builddist.win-amd64\\egg +# db\\services.py", line 736, in get_limbo_transaction_ids +# struct.error: unpack requires a string argument of length 4 +# Because of this, external child processes are called to obtain Tx list: gfix and fbcvmgr. +# +# Confirmed bug on 4.0.0.1633: fbsvcmgr issues 0 rows instead of expected 146. +# Checked on: +# 4.0.0.2195 SS: 5.967s. +# 4.0.0.2000 SS: 5.506s. +# 4.0.0.2195 CS: 7.313s. +# 3.0.7.33358 SS: 4.973s. +# 3.0.7.33358 CS: 5.698s. +# +# tracker_id: CORE-6309 +# min_versions: ['3.0.7'] +# versions: 3.0.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import sys +# import os +# import shutil +# import time +# import datetime +# import re +# from datetime import timedelta +# import subprocess +# from fdb import services +# +# LIMBO_COUNT = 250 +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_name=db_conn.database_name +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# dbname_a=os.path.join(context['temp_directory'],'c6309_a.fdb') +# dbname_b=os.path.join(context['temp_directory'],'c6309_b.fdb') +# +# cleanup( (dbname_a, dbname_b) ) +# +# con1 = fdb.create_database( dsn = 'localhost:' + dbname_a ) +# con2 = fdb.create_database( dsn = 'localhost:' + dbname_b ) +# +# init_ddl = 'create table test(id int, x int, constraint test_pk primary key(id) using index test_pk)' +# con1.execute_immediate(init_ddl) +# con1.commit() +# +# con2.execute_immediate(init_ddl) +# con2.commit() +# +# cgr = fdb.ConnectionGroup() +# cgr.add(con1) +# cgr.add(con2) +# +# tx1_list=[] +# for i in range(0, LIMBO_COUNT): +# tx1_list += [ con1.trans() ] +# +# cur_list=[] +# for i, tx1 in enumerate(tx1_list): +# tx1.begin() +# cur=tx1.cursor() +# cur.execute( "insert into test(id, x) values( ?, ? )", ( i, i*11111 ) ) +# cur.close() +# tx1.prepare() +# +# tx2 = con2.trans() +# cur2=tx2.cursor() +# cur2.execute( "insert into test(id, x) values( ?, ? )", (-2, -2222222) ) +# cur2.close() +# +# tx2.prepare() +# tx2.commit() +# +# svc = services.connect(host='localhost', user=user_name, password=user_password) +# svc.shutdown( dbname_a, services.SHUT_FULL, services.SHUT_FORCE, 0) +# +# for tx1 in tx1_list: +# try: +# tx1.close() +# except: +# pass +# +# # Result for DBNAME_A when it will be returned online +# # and we query table TEST: +# # Statement failed, SQLSTATE = HY000 +# # record from transaction is stuck in limbo +# # See also "gfix -list \\path o\\dbname_a" +# +# cgr.clear() +# svc.bring_online( dbname_a, services.SHUT_NORMAL ) +# svc.close() +# con2.close() +# +# try: +# # This will fail for sure because DB state was changed to full shutdown +# con1.close() +# except: +# pass +# +# svc.close() +# +# +# f_limbo_gfix=open( os.path.join(context['temp_directory'],'tmp_c6309_gfix_list.log'), 'w', buffering=0) +# subprocess.call( [ context['gfix_path'], "localhost:" + dbname_a, "-list" ], stdout=f_limbo_gfix, stderr=subprocess.STDOUT ) +# flush_and_close( f_limbo_gfix ) +# +# f_limbo_fbsvc=open( os.path.join(context['temp_directory'],'tmp_c6309_fbsvc_list.log'), 'w', buffering=0) +# subprocess.call( [ context['fbsvcmgr_path'], "localhost:service_mgr", "action_repair", "rpr_list_limbo_trans", "dbname", dbname_a], stdout=f_limbo_fbsvc, stderr=subprocess.STDOUT ) +# flush_and_close( f_limbo_fbsvc ) +# +# # 'gfix -list' issues: +# # Transaction 3 is in limbo. +# # Transaction 5 is in limbo. +# # ... +# # (totally 146 lines + "More limbo transactions than fit. Try again") +# +# # 'fbsvcmgr rpr_list_limbo_trans' issues: +# # Transaction in limbo: 3 +# # Transaction in limbo: 5 +# # ... +# # (totally exactly 146 lines, without any other message). +# +# p=re.compile( 'Transaction\\s+(\\d+\\s+(is\\s+)?in\\s+limbo)|(in\\s+limbo(:)?\\s+\\d+)', re.IGNORECASE ) +# +# f_list = (f_limbo_gfix, f_limbo_fbsvc) +# found_limbos = [0, 0] +# for i, g in enumerate(f_list): +# with open(g.name, 'r') as f: +# for line in f: +# found_limbos[i] += 1 if p.search(line) else 0 +# +# for x in found_limbos: +# print(x) +# +# # Cleanup +# ########## +# time.sleep(1) +# cleanup( (f_limbo_gfix, f_limbo_fbsvc, dbname_a, dbname_b) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 146 + 146 + """ + +@pytest.mark.version('>=3.0.7') +@pytest.mark.xfail +def test_core_6309_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6310.py b/tests/bugs/test_core_6310.py new file mode 100644 index 00000000..37c0f241 --- /dev/null +++ b/tests/bugs/test_core_6310.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: bugs.core_6310 +# title: Varchar length limit is not enforced when assigning string with trailing spaces in MBCS +# decription: +# Confirmed bug on 3.0.6.33289, 4.0.0.1954 +# Checked on 3.0.6.33294, 4.0.0.2000 - works fine. +# +# tracker_id: CORE-6310 +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select char_length(cast(_utf8 '123 ' as varchar(5) character set utf8)) as char_len from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CHAR_LEN 5 + """ + +@pytest.mark.version('>=3.0.6') +def test_core_6310_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6314.py b/tests/bugs/test_core_6314.py new file mode 100644 index 00000000..f8c14eae --- /dev/null +++ b/tests/bugs/test_core_6314.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: bugs.core_6314 +# title: Assigning RDB$DB_KEY to MBCS CHAR/VARCHAR does not enforce the target limit +# decription: +# In order to prevent receiving non-ascii characters in output we try to get only octet_length of this. +# Confirmed bug on 3.0.6.33289, 4.0.0.1954 (get result = 2 instead of raising error). +# Checked on 3.0.6.33294, 4.0.0.2000 - works fine. +# +# tracker_id: CORE-6314 +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select octet_length(x) as cast_dbkey_to_char2_length from (select cast(rdb$db_key as char(2) character set utf8) x from rdb$database); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22001 + arithmetic exception, numeric overflow, or string truncation + -string right truncation + -expected length 2, actual 8 + """ + +@pytest.mark.version('>=3.0.6') +def test_core_6314_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_6316.py b/tests/bugs/test_core_6316.py new file mode 100644 index 00000000..f9436120 --- /dev/null +++ b/tests/bugs/test_core_6316.py @@ -0,0 +1,391 @@ +#coding:utf-8 +# +# id: bugs.core_6316 +# title: Unable to specify new 32k page size +# decription: +# NOTE. Issues remain for some kind of commands: parser should be more rigorous. +# Sent letter to Alex and Dmitry, 29.05.2020 12:28. +# Checked on 4.0.0.2006. +# +# tracker_id: CORE-6316 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('Token unknown.*line.*', 'Token unknown')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# #import fdb +# from fdb import services +# +# DB_NAME=os.path.join(context['temp_directory'],'tmp_6316.fdb') +# DB_USER=user_name +# DB_PSWD=user_password +# page_list= ( +# "9223372036854775809" +# ,"9223372036854775808" +# ,"9223372036854775807" +# ,"4294967297" +# ,"4294967296" +# ,"4294967295" +# ,"2147483649" +# ,"2147483648" +# ,"2147483647" +# ,"65537" +# ,"32769" +# ,"32768" +# ,"32767" +# ,"16385" +# ,"16384" +# ,"16383" +# ,"8193" +# ,"8192" +# ,"8191" +# ,"4097" +# ,"4096" +# ,"4095" +# ,"2049" +# ,"2048" +# ,"2047" +# ,"1025" +# ,"1024" +# ,"1023" +# ,"0" +# ,"0x10000" +# ,"0xFFFF" +# ,"0x8000" +# ,"0x7FFF" +# ,"0x4000" +# ,"0x3FFF" +# ,"0x2000" +# ,"0x1FFF" +# ,"0x1000" +# ,"0xFFF" +# ,"0x800" +# ,"0x7FF" +# ,"0x400" +# ,"0x3FF" +# ,"default" +# ,"null" +# ,"qwerty" +# ,"-32768" +# ) +# +# sttm_proto="create database 'localhost:%(DB_NAME)s' user %(DB_USER)s password '%(DB_PSWD)s' page_size %(i)s" +# +# svc = services.connect( user = DB_USER, password = DB_PSWD ) +# #k=0 +# for i in page_list: +# for j in (1,2): +# if os.path.isfile(DB_NAME): +# os.remove(DB_NAME) +# +# try: +# # ::: NB ::: No error occured until we specify 'DEFAULT CHARACTER SET ....' +# sttm_actual = sttm_proto % locals() + ( ' default character set win1251' if j==1 else '' ) +# +# #print('Try create with page_size=%(i)s, clause "DEFAULT CHARACTER SET": ' % locals() + ( 'present' if 'default character set' in sttm_actual else 'absent' ) ) +# print('') +# print(sttm_actual.replace("'localhost:%(DB_NAME)s'" % locals(), "...").replace("user %(DB_USER)s " % locals(), '').replace("password '%(DB_PSWD)s' " % locals(), '')) +# con = None +# con = fdb.create_database( sql = sttm_actual) +# +# if con: +# con.execute_immediate('alter database set linger to 0') +# con.commit() +# cur = con.cursor() +# cur.execute('select mon$database_name,mon$page_size,left(cast(mon$creation_date as varchar(50)),24) from mon$database') +# for r in cur: +# print('DB created. Actual page_size:', r[1] ) +# cur.close() +# con.close() +# +# if os.path.isfile(DB_NAME): +# svc.shutdown( DB_NAME, services.SHUT_FULL, services.SHUT_FORCE, 0) +# os.remove(DB_NAME) +# +# except Exception as e: +# print(e[0]) +# +# svc.close() +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + create database ... page_size 9223372036854775809 default character set win1251 + Error while creating database: + - SQLCODE: -104 + - Dynamic SQL Error + - SQL error code = -104 + - Token unknown + - 9223372036854775809 + create database ... page_size 9223372036854775809 + DB created. Actual page_size: 32768 + create database ... page_size 9223372036854775808 default character set win1251 + Error while creating database: + - SQLCODE: -104 + - Dynamic SQL Error + - SQL error code = -104 + - Token unknown + - 9223372036854775808 + create database ... page_size 9223372036854775808 + DB created. Actual page_size: 32768 + create database ... page_size 9223372036854775807 default character set win1251 + Error while creating database: + - SQLCODE: -104 + - Dynamic SQL Error + - SQL error code = -104 + - Token unknown + - 9223372036854775807 + create database ... page_size 9223372036854775807 + DB created. Actual page_size: 32768 + create database ... page_size 4294967297 default character set win1251 + Error while creating database: + - SQLCODE: -104 + - Dynamic SQL Error + - SQL error code = -104 + - Token unknown + - 4294967297 + create database ... page_size 4294967297 + DB created. Actual page_size: 32768 + create database ... page_size 4294967296 default character set win1251 + Error while creating database: + - SQLCODE: -104 + - Dynamic SQL Error + - SQL error code = -104 + - Token unknown + - 4294967296 + create database ... page_size 4294967296 + DB created. Actual page_size: 32768 + create database ... page_size 4294967295 default character set win1251 + Error while creating database: + - SQLCODE: -104 + - Dynamic SQL Error + - SQL error code = -104 + - Token unknown + - 4294967295 + create database ... page_size 4294967295 + DB created. Actual page_size: 32768 + create database ... page_size 2147483649 default character set win1251 + Error while creating database: + - SQLCODE: -104 + - Dynamic SQL Error + - SQL error code = -104 + - Token unknown + - 2147483649 + create database ... page_size 2147483649 + DB created. Actual page_size: 32768 + create database ... page_size 2147483648 default character set win1251 + Error while creating database: + - SQLCODE: -104 + - Dynamic SQL Error + - SQL error code = -104 + - Token unknown + - 2147483648 + create database ... page_size 2147483648 + DB created. Actual page_size: 32768 + create database ... page_size 2147483647 default character set win1251 + DB created. Actual page_size: 32768 + create database ... page_size 2147483647 + DB created. Actual page_size: 32768 + create database ... page_size 65537 default character set win1251 + DB created. Actual page_size: 32768 + create database ... page_size 65537 + DB created. Actual page_size: 32768 + create database ... page_size 32769 default character set win1251 + DB created. Actual page_size: 32768 + create database ... page_size 32769 + DB created. Actual page_size: 32768 + create database ... page_size 32768 default character set win1251 + DB created. Actual page_size: 32768 + create database ... page_size 32768 + DB created. Actual page_size: 32768 + create database ... page_size 32767 default character set win1251 + DB created. Actual page_size: 16384 + create database ... page_size 32767 + DB created. Actual page_size: 16384 + create database ... page_size 16385 default character set win1251 + DB created. Actual page_size: 16384 + create database ... page_size 16385 + DB created. Actual page_size: 16384 + create database ... page_size 16384 default character set win1251 + DB created. Actual page_size: 16384 + create database ... page_size 16384 + DB created. Actual page_size: 16384 + create database ... page_size 16383 default character set win1251 + DB created. Actual page_size: 8192 + create database ... page_size 16383 + DB created. Actual page_size: 8192 + create database ... page_size 8193 default character set win1251 + DB created. Actual page_size: 8192 + create database ... page_size 8193 + DB created. Actual page_size: 8192 + create database ... page_size 8192 default character set win1251 + DB created. Actual page_size: 8192 + create database ... page_size 8192 + DB created. Actual page_size: 8192 + create database ... page_size 8191 default character set win1251 + DB created. Actual page_size: 4096 + create database ... page_size 8191 + DB created. Actual page_size: 4096 + create database ... page_size 4097 default character set win1251 + DB created. Actual page_size: 4096 + create database ... page_size 4097 + DB created. Actual page_size: 4096 + create database ... page_size 4096 default character set win1251 + DB created. Actual page_size: 4096 + create database ... page_size 4096 + DB created. Actual page_size: 4096 + create database ... page_size 4095 default character set win1251 + DB created. Actual page_size: 4096 + create database ... page_size 4095 + DB created. Actual page_size: 4096 + create database ... page_size 2049 default character set win1251 + DB created. Actual page_size: 4096 + create database ... page_size 2049 + DB created. Actual page_size: 4096 + create database ... page_size 2048 default character set win1251 + DB created. Actual page_size: 4096 + create database ... page_size 2048 + DB created. Actual page_size: 4096 + create database ... page_size 2047 default character set win1251 + DB created. Actual page_size: 4096 + create database ... page_size 2047 + DB created. Actual page_size: 4096 + create database ... page_size 1025 default character set win1251 + DB created. Actual page_size: 4096 + create database ... page_size 1025 + DB created. Actual page_size: 4096 + create database ... page_size 1024 default character set win1251 + DB created. Actual page_size: 4096 + create database ... page_size 1024 + DB created. Actual page_size: 4096 + create database ... page_size 1023 default character set win1251 + DB created. Actual page_size: 4096 + create database ... page_size 1023 + DB created. Actual page_size: 4096 + create database ... page_size 0 default character set win1251 + DB created. Actual page_size: 8192 + create database ... page_size 0 + DB created. Actual page_size: 8192 + create database ... page_size 0x10000 default character set win1251 + DB created. Actual page_size: 8192 + create database ... page_size 0x10000 + DB created. Actual page_size: 8192 + create database ... page_size 0xFFFF default character set win1251 + DB created. Actual page_size: 8192 + create database ... page_size 0xFFFF + DB created. Actual page_size: 8192 + create database ... page_size 0x8000 default character set win1251 + DB created. Actual page_size: 8192 + create database ... page_size 0x8000 + DB created. Actual page_size: 8192 + create database ... page_size 0x7FFF default character set win1251 + DB created. Actual page_size: 8192 + create database ... page_size 0x7FFF + DB created. Actual page_size: 8192 + create database ... page_size 0x4000 default character set win1251 + DB created. Actual page_size: 8192 + create database ... page_size 0x4000 + DB created. Actual page_size: 8192 + create database ... page_size 0x3FFF default character set win1251 + DB created. Actual page_size: 8192 + create database ... page_size 0x3FFF + DB created. Actual page_size: 8192 + create database ... page_size 0x2000 default character set win1251 + DB created. Actual page_size: 8192 + create database ... page_size 0x2000 + DB created. Actual page_size: 8192 + create database ... page_size 0x1FFF default character set win1251 + DB created. Actual page_size: 8192 + create database ... page_size 0x1FFF + DB created. Actual page_size: 8192 + create database ... page_size 0x1000 default character set win1251 + DB created. Actual page_size: 8192 + create database ... page_size 0x1000 + DB created. Actual page_size: 8192 + create database ... page_size 0xFFF default character set win1251 + DB created. Actual page_size: 8192 + create database ... page_size 0xFFF + DB created. Actual page_size: 8192 + create database ... page_size 0x800 default character set win1251 + DB created. Actual page_size: 8192 + create database ... page_size 0x800 + DB created. Actual page_size: 8192 + create database ... page_size 0x7FF default character set win1251 + DB created. Actual page_size: 8192 + create database ... page_size 0x7FF + DB created. Actual page_size: 8192 + create database ... page_size 0x400 default character set win1251 + DB created. Actual page_size: 8192 + create database ... page_size 0x400 + DB created. Actual page_size: 8192 + create database ... page_size 0x3FF default character set win1251 + DB created. Actual page_size: 8192 + create database ... page_size 0x3FF + DB created. Actual page_size: 8192 + create database ... page_size default default character set win1251 + Error while creating database: + - SQLCODE: -104 + - Dynamic SQL Error + - SQL error code = -104 + - Token unknown + - default + create database ... page_size default + DB created. Actual page_size: 8192 + create database ... page_size null default character set win1251 + Error while creating database: + - SQLCODE: -104 + - Dynamic SQL Error + - SQL error code = -104 + - Token unknown + - null + create database ... page_size null + DB created. Actual page_size: 8192 + create database ... page_size qwerty default character set win1251 + Error while creating database: + - SQLCODE: -104 + - Dynamic SQL Error + - SQL error code = -104 + - Token unknown + - qwerty + create database ... page_size qwerty + DB created. Actual page_size: 8192 + create database ... page_size -32768 default character set win1251 + Error while creating database: + - SQLCODE: -104 + - Dynamic SQL Error + - SQL error code = -104 + - Token unknown + - - + create database ... page_size -32768 + Error while creating database: + - SQLCODE: -104 + - Dynamic SQL Error + - SQL error code = -104 + - Token unknown + - - + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_6316_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6317.py b/tests/bugs/test_core_6317.py new file mode 100644 index 00000000..1650f8bf --- /dev/null +++ b/tests/bugs/test_core_6317.py @@ -0,0 +1,82 @@ +#coding:utf-8 +# +# id: bugs.core_6317 +# title: Server is crashing on long GRANT statement +# decription: +# Confirmed crash on: 4.0.0.1963 SC; 3.0.6.33289 SC +# Checked on: 4.0.0.2006 SS/SC, 3.0.6.33296 SS/SC -- all fine. +# +# tracker_id: CORE-6317 +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set wng off; + create or alter user tmp$c6317 password '123'; + revoke all on all from tmp$c6317; + commit; + + recreate table test (id integer); + insert into test(id) values(1); + commit; + + grant select, select, select, select, select, select, select, select, select, select, select, select, select, select, select, select on test to tmp$c6317; + commit; + + set list on; + select + rdb$user -- tmp$c6317 + ,rdb$relation_name -- test + ,rdb$privilege -- S + ,rdb$grant_option -- 0 + ,rdb$field_name -- + ,rdb$object_type -- 0 + from rdb$user_privileges p + where upper(p.rdb$relation_name) = upper('test') and rdb$user = upper('tmp$c6317') + order by rdb$privilege + ; + commit; + + connect '$(DSN)' user tmp$c6317 password '123'; + select * from test; + commit; + + connect '$(DSN)' user sysdba password 'masterkey'; + drop user tmp$c6317; + commit; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$USER TMP$C6317 + RDB$RELATION_NAME TEST + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$FIELD_NAME + RDB$OBJECT_TYPE 0 + + ID 1 + """ + +@pytest.mark.version('>=3.0.6') +def test_core_6317_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6318.py b/tests/bugs/test_core_6318.py new file mode 100644 index 00000000..59717bc2 --- /dev/null +++ b/tests/bugs/test_core_6318.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: bugs.core_6318 +# title: CAST('NOW' as TIME) raises exception +# decription: +# Confirmed bug on 4.0.0.1954, 4.0.0.2000 +# Checked on 4.0.0.2004 - works fine. +# +# tracker_id: CORE-6318 +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + select cast('now' as time) is not null from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + + """ + +@pytest.mark.version('>=4.0') +def test_core_6318_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6319.py b/tests/bugs/test_core_6319.py new file mode 100644 index 00000000..1ee383f5 --- /dev/null +++ b/tests/bugs/test_core_6319.py @@ -0,0 +1,306 @@ +#coding:utf-8 +# +# id: bugs.core_6319 +# title: NBACKUP locks db file on error +# decription: +# We create level-0 copy of test DB (so called "stand-by DB") and obtain DB backup GUID for just performed action. +# Then we create incremental copy using this GUID ("nbk_level_1") and obtain new DB backup GUID again. +# After this we repeat - create next incrementa copy using this (new) GUID ("nbk_level_2"). +# +# (note: cursor for 'select h.rdb$guid from rdb$backup_history h order by h.rdb$backup_id desc rows 1' can be used +# to get last database backup GUID instead of running 'gstat -h'). +# +# Further, we try to apply two incrementa copies but in WRONG order of restore: specify twise instead +# of proper order: and after this - . +# +# First and second attempts should issue THE SAME message: +# "Wrong order of backup files or invalid incremental backup file detected, file: ". +# +# We do this check both for NBACKUP and FBSVCMGR. +# +# Confirmed bug on 4.0.0.2000: second attempt to run restore using FBSVCMGR issues: +# ===== +# Error opening database file: [disk]:\\path o\\standby_db.dfb +# process cannot access the file because it is being used by another process +# ===== +# - and file could not be deleted after this until restart of FB. +# +# Works fine on 4.0.0.2025 CS/SS. +# 13.06.2020: adapted for use both in 3.x and 4.x; checked on 4.0.0.2037, 3.0.6.33307 - all OK. +# +# ::: NOTE ::: +# bug has nothing with '-inplace' option that present only in FB 4.x - it was also in FB 3.x. +# Fix for 3.x was 11.06.2020 12:36, include in "aedc22: Fixed assert in Statement::freeClientData()", +# see: https://github.com/FirebirdSQL/firebird/commit/fdf758099c6872579ad6b825027fe81fea3ae1b5 +# +# 20.01.2021. CRITICAL NOTE (detected when run tests against HQbird 33288, ServerMode = Classic). +# ######################### +# Method "codecs.open()" must be used to process logs, instead of 'plain' open() ! +# Any FB utility which have access problems with file can/will report *part* of error message in localized form. +# This text is not in utf-8 (at least in case of Windows) and thus can not be converted and correctly displayed: +# PROBLEM ON "ATTACH DATABASE". +# I/O ERROR DURING "CREATEFILE (OPEN)" OPERATION FOR FILE "C:/HQBWORK/1IMPORTANT/QA-RUNDAILY/FBT-REPO/TMP/BUGS.CORE_6319.FDB" +# -ERROR WHILE TRYING TO OPEN FILE +# // <<< CAN BE IN LOCALIZED FORM! +# SQLCODE:-902 +# +# Because of this, fbt_db utility will fail on attempt to store in ANNOTATIONS table such message with "335544849 : Malformed string". +# The worst part is that no any other tests will be saved, i.e. we will have DB with EMPTY result, despite the fact that a problem +# occured only on one test (the reason is that fbt_db does all actions within the single transaction). +# +# Because of this all messages that are iussued by nbackup/fbsvcmgr or all other utilities must be handled using codecs.open() +# method with request to IGNORE all non-ascii character (do NOT try to show it) and take next one. +# Example: "with codecs.open( e.name, 'r', encoding = 'utf-8', errors = 'ignore' ) as f: ..." +# +# Checked (after replace "open(): with "codecs.open(... errors = 'ignore')" call) on: +# 4.0.0.2307 SS: 2.639s; 4.0.0.2324 CS: 3.610s; 3.0.8.33401 SS: 2.210s; 3.0.8.33401 CS: 3.400s. +# +# +# tracker_id: CORE-6319 +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import time +# import shutil +# import codecs +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_source=db_conn.database_name +# +# nbk_level_0 = os.path.splitext(db_source)[0] + '.standby.fdb' +# +# # this is for 3.x only by using command: +# # nbackup -r db_3x_restore nbk_level_0 nbk_level_1 nbk_level_2 +# db_3x_restore = os.path.splitext(db_source)[0] + '.restored_in_3x.fdb' +# +# nbk_level_1 = os.path.splitext(db_source)[0] + '.nbk_01' +# nbk_level_2 = os.path.splitext(db_source)[0] + '.nbk_02' +# +# #-------------------------------------------- +# +# 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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# cleanup( (db_3x_restore, nbk_level_0, nbk_level_1, nbk_level_2,) ) +# +# # 1. Create standby copy: make clone of source DB using nbackup -b 0: +# ######################## +# f_nbk0_log=open( os.path.join(context['temp_directory'],'tmp_nbk0_6319.log'), 'w') +# f_nbk0_err=open( os.path.join(context['temp_directory'],'tmp_nbk0_6319.err'), 'w') +# subprocess.call( [ context['nbackup_path'], '-b', '0', db_source, nbk_level_0], stdout=f_nbk0_log, stderr=f_nbk0_err ) +# flush_and_close( f_nbk0_log ) +# flush_and_close( f_nbk0_err ) +# +# get_last_bkup_guid_sttm = 'select h.rdb$guid from rdb$backup_history h order by h.rdb$backup_id desc rows 1' +# +# # Read DB-backup GUID after this 1st nbackup run: +# ##################### +# cur = db_conn.cursor() +# cur.execute(get_last_bkup_guid_sttm) +# for r in cur: +# db_guid = r[0] +# +# +# # Create 1st copy using just obtained DB backup GUID: +# ############ +# nbk_call_01 = [ context['nbackup_path'], '-b' ] + ( [ db_guid ] if db_conn.engine_version >= 4.0 else [ '1' ] ) + [ db_source, nbk_level_1 ] +# +# f_nbk1_log=open( os.path.join(context['temp_directory'],'tmp_nbk1_6319.log'), 'w') +# f_nbk1_err=open( os.path.join(context['temp_directory'],'tmp_nbk1_6319.err'), 'w') +# subprocess.call( nbk_call_01, stdout=f_nbk1_log, stderr=f_nbk1_err ) +# flush_and_close( f_nbk1_log ) +# flush_and_close( f_nbk1_err ) +# +# # Re-read DB backup GUID: it is changed after each new nbackup! +# ######################## +# cur.execute(get_last_bkup_guid_sttm) +# for r in cur: +# db_guid = r[0] +# +# # Create 2nd copy using LAST obtained GUID of backup: +# ############ +# nbk_call_02 = [ context['nbackup_path'], '-b' ] + ( [ db_guid ] if db_conn.engine_version >= 4.0 else [ '2' ] ) + [ db_source, nbk_level_2 ] +# +# f_nbk2_log=open( os.path.join(context['temp_directory'],'tmp_nbk2_6319.log'), 'w') +# f_nbk2_err=open( os.path.join(context['temp_directory'],'tmp_nbk2_6319.err'), 'w') +# subprocess.call( nbk_call_02, stdout=f_nbk2_log, stderr=f_nbk2_err ) +# flush_and_close( f_nbk2_log ) +# flush_and_close( f_nbk2_err ) +# +# # Try to merge standby DB and SECOND copy, i.e. wrongly skip 1st incremental copy. +# # NB: we do this TWISE. And both time this attempt should fail with: +# # "Wrong order of backup files or invalid incremental backup file detected, file: ..." +# ######################## +# +# if db_conn.engine_version >= 4.0: +# nbk_wrong_call = [ context['nbackup_path'], '-inplace', '-restore', 'localhost:'+ nbk_level_0, nbk_level_2] +# else: +# # Invalid level 2 of incremental backup file: C:/FBTESTING/qa/fbt-repo/tmp/tmp_core_6319.nbk_02, expected 1 +# nbk_wrong_call = [ context['nbackup_path'], '-restore', db_3x_restore, nbk_level_0, nbk_level_2] +# +# f_nbk_poor_log=open( os.path.join(context['temp_directory'],'tmp_nbk_poor_6319.log'), 'w') +# f_nbk_poor_err=open( os.path.join(context['temp_directory'],'tmp_nbk_poor_6319.err'), 'w') +# +# cleanup( (db_3x_restore,) ) +# subprocess.call( nbk_wrong_call, stdout=f_nbk_poor_log, stderr=f_nbk_poor_err ) # [1] +# cleanup( (db_3x_restore,) ) +# subprocess.call( nbk_wrong_call, stdout=f_nbk_poor_log, stderr=f_nbk_poor_err ) # [2] +# +# # FB 3.0.6.33307: +# #Invalid level 2 of incremental backup file: , expected 1 +# #Invalid level 2 of incremental backup file: , expected 1 +# # FB 4.0.0.2037: +# # Wrong order of backup files or invalid incremental backup file detected, file: +# # Wrong order of backup files or invalid incremental backup file detected, file: +# +# flush_and_close( f_nbk_poor_log ) +# flush_and_close( f_nbk_poor_err ) +# +# cleanup( (db_3x_restore,) ) +# +# # Try to do the same using FBSVCMGR. +# # We also do this twise and both attempts must finish the same as previous pair: +# # Wrong order of backup files or invalid incremental backup file detected, file: C:/FBTESTING/qa/fbt-repo/tmp/tmp_core_6319.nbk_02 +# +# if db_conn.engine_version >= 4.0: +# fbsvc_call_01 = [ context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_nrest', 'nbk_inplace', 'dbname', nbk_level_0, 'nbk_file', nbk_level_1] +# fbsvc_call_02 = [ context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_nrest', 'nbk_inplace', 'dbname', nbk_level_0, 'nbk_file', nbk_level_2] +# else: +# fbsvc_call_01 = [ context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_nrest', 'dbname', db_3x_restore, 'nbk_file', nbk_level_0, 'nbk_file', nbk_level_1, 'nbk_file', nbk_level_2] +# fbsvc_call_02 = [ context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_nrest', 'dbname', db_3x_restore, 'nbk_file', nbk_level_0, 'nbk_file', nbk_level_2, 'nbk_file', nbk_level_2] +# +# # On 4.0.0.2000 second attempt raised: +# # Error opening database file: [disk]:\\path o\\standby_db.dfb +# # process cannot access the file because it is being used by another process +# #################### +# f_svc_poor_log=open( os.path.join(context['temp_directory'],'tmp_svc_res_poor_6319.log'), 'w') +# f_svc_poor_err=open( os.path.join(context['temp_directory'],'tmp_svc_res_poor_6319.err'), 'w') +# +# cleanup( (db_3x_restore,) ) +# subprocess.call( fbsvc_call_02, stdout=f_svc_poor_log, stderr=f_svc_poor_err ) # [1] +# cleanup( (db_3x_restore,) ) +# subprocess.call( fbsvc_call_02, stdout=f_svc_poor_log, stderr=f_svc_poor_err ) # [2] +# +# # FB 3.0.6.33307: +# #Invalid level 2 of incremental backup file: C:/FBTESTING/qa/fbt-repo/tmp/tmp_core_6319.nbk_02, expected 1 +# #Invalid level 2 of incremental backup file: C:/FBTESTING/qa/fbt-repo/tmp/tmp_core_6319.nbk_02, expected 1 +# # FB 4.0.0.2037: +# # Wrong order of backup files or invalid incremental backup file detected, file: +# # Wrong order of backup files or invalid incremental backup file detected, file: +# +# flush_and_close( f_svc_poor_log ) +# flush_and_close( f_svc_poor_err ) +# cleanup( (db_3x_restore,) ) +# +# # Try to apply incremental copies in proper order, also using FBSVCMGR. +# # No errors must occur in this case: +# #################################### +# f_svc_good_log=open( os.path.join(context['temp_directory'],'tmp_svc_res_good_6319.log'), 'w') +# f_svc_good_err=open( os.path.join(context['temp_directory'],'tmp_svc_res_good_6319.err'), 'w') +# +# cleanup( (db_3x_restore,) ) +# +# subprocess.call( fbsvc_call_01, stdout=f_svc_good_log, stderr=f_svc_good_err ) +# if db_conn.engine_version >= 4.0: +# subprocess.call( fbsvc_call_02, stdout=f_svc_good_log, stderr=f_svc_good_err ) +# +# flush_and_close( f_svc_good_log ) +# flush_and_close( f_svc_good_err ) +# +# +# # Check. All of these files must be empty: +# ################################### +# f_list=(f_nbk0_err, f_nbk1_err, f_nbk2_err, f_nbk_poor_log, f_svc_poor_log, f_svc_good_log, f_svc_good_err) +# for i in range(len(f_list)): +# # WRONG >>> with open( f_list[i].name,'r') as f:: <<< LOCALIZED MESSAGE CAN PRESENT IN CASE OF FILE-ACCESS PROBLEMS! +# with codecs.open( f_list[i].name, 'r', encoding = 'utf-8', errors = 'ignore' ) as f: +# for line in f: +# if line.split(): +# print( 'UNEXPECTED output in file '+f_list[i].name+': '+line.upper() ) +# +# # BOTH lines in every of: {f_nbk_poor_err, f_svc_poor_err} -- must be equal: +# # "Wrong order of backup files or invalid incremental backup file detected, file ..." +# for e in (f_nbk_poor_err, f_svc_poor_err): +# i=0 +# # WRONG >>> with open( e.name,'r') as f: <<< LOCALIZED MESSAGE CAN PRESENT IN CASE OF FILE-ACCESS PROBLEMS! +# with codecs.open( e.name, 'r', encoding = 'utf-8', errors = 'ignore' ) as f: +# for line in f: +# if line: +# i += 1 +# if db_conn.engine_version < 4 and 'Invalid level 2 of incremental backup file' in line: +# print( 'Attempt %d. Error message is expected.' % i ) +# elif db_conn.engine_version >= 4 and ('Wrong order of backup' in line or 'invalid incremental backup' in line): +# print( 'Attempt %d. Error message is expected.' % i ) +# else: +# print( ('Attempt %d. Error message is UNEXPECTED: ' + line + ', file: ' + e.name ) % i ) +# +# # Cleanup. +# ########## +# time.sleep(1) +# cleanup( (f_nbk0_log,f_nbk0_err, f_nbk1_log,f_nbk1_err, f_nbk2_log,f_nbk2_err, f_nbk_poor_log, f_nbk_poor_err, f_svc_poor_log, f_svc_poor_err, f_svc_good_log, f_svc_good_err, db_3x_restore, nbk_level_0, nbk_level_1, nbk_level_2 ) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Attempt 1. Error message is expected. + Attempt 2. Error message is expected. + Attempt 1. Error message is expected. + Attempt 2. Error message is expected. + """ + +@pytest.mark.version('>=3.0.6') +@pytest.mark.xfail +def test_core_6319_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6324.py b/tests/bugs/test_core_6324.py new file mode 100644 index 00000000..d11ca161 --- /dev/null +++ b/tests/bugs/test_core_6324.py @@ -0,0 +1,95 @@ +#coding:utf-8 +# +# id: bugs.core_6324 +# title: Alter domain operation for domain with collation specified revert its collation to database default +# decription: +# NB: current behaviour contradicts ticket notes! +# FB *must* change collation of altered domain, see issue by dimitr in the ticket 06/Jun/20 08:04 AM: +# "character set is not a part of the domain itself, it's a part of its data type". +# +# Checked on: 4.0.0.2035 ; 3.0.6.33296 ; 2.5.9.27149 +# +# tracker_id: CORE-6324 +# min_versions: ['2.5.9'] +# versions: 2.5.9 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.9 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set width fld_name 20; + set width cset_name 20; + set width coll_name 20; + set list on; + + recreate view v_test as + select + f.rdb$field_name fld_name + --,f.rdb$character_set_id cset_id + --,f.rdb$collation_id coll_id + ,c.rdb$character_set_name cset_name + ,s.rdb$collation_name coll_name + from rdb$fields f + left join rdb$character_sets c on f.rdb$character_set_id = c.rdb$character_set_id + left join rdb$collations s on + f.rdb$collation_id = s.rdb$collation_id + and c.rdb$character_set_id = s.rdb$character_set_id + where f.rdb$field_name = upper('dm_test'); + + create domain dm_test varchar(1000) character set win1250 collate pxw_plk; + commit; + + select 'POINT-1' msg, v.* from v_test v; + commit; + + -- Required result: collation must change from PXW_PLK to WIN1250. + alter domain dm_test type varchar(1000) character set win1250; + commit; + + select 'POINT-2' msg, v.* from v_test v; + commit; + + -- Required result: collation must be REMOVED: + alter domain dm_test type varchar(1000); + commit; + + select 'POINT-3' msg, v.* from v_test v; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG POINT-1 + FLD_NAME DM_TEST + CSET_NAME WIN1250 + COLL_NAME PXW_PLK + + MSG POINT-2 + FLD_NAME DM_TEST + CSET_NAME WIN1250 + COLL_NAME WIN1250 + + MSG POINT-3 + FLD_NAME DM_TEST + CSET_NAME UTF8 + COLL_NAME UTF8 + + """ + +@pytest.mark.version('>=2.5.9') +def test_core_6324_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6328.py b/tests/bugs/test_core_6328.py new file mode 100644 index 00000000..09d3a066 --- /dev/null +++ b/tests/bugs/test_core_6328.py @@ -0,0 +1,52 @@ +#coding:utf-8 +# +# id: bugs.core_6328 +# title: FB4 Beta 2 may still be using the current date for TIME WITH TIME ZONE and extended wire protocol. +# decription: +# Confirmed bug on 4.0.0.2104 (got TZ_HOUR = -4 instead of expected -5). +# Checked on 4.0.0.2108 (intermediate build of 17.07.2020 16:34) - works fine. +# +# tracker_id: CORE-6328 +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bind of time zone to extended; + create table test ( + timecol time with time zone + ); + + insert into test(timecol) values('11:31:05.0001 america/new_york'); + + set list on; + select extract(timezone_hour from timecol) as tz_hour, extract(timezone_minute from timecol) as tz_minute + from test; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TZ_HOUR -5 + TZ_MINUTE 0 + """ + +@pytest.mark.version('>=4.0') +def test_core_6328_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6329.py b/tests/bugs/test_core_6329.py new file mode 100644 index 00000000..4f0dd4cc --- /dev/null +++ b/tests/bugs/test_core_6329.py @@ -0,0 +1,162 @@ +#coding:utf-8 +# +# id: bugs.core_6329 +# title: GBAK with service_mgr and WinSSPI authentication for Windows SYSTEM user producing error in clumplet API +# decription: +# Confirmed bug on 4.0.0.2035 SS: got +# "gbak: ERROR:Internal error when using clumplet API: attempt to store 866 bytes in a clumplet with maximum size 255 bytes" +# +# Checked on 4.0.0.2066 SS/CS, 3.0.6.33212 SS/CS. +# +# tracker_id: CORE-6329 +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import sys +# import os +# import re +# import time +# import subprocess +# from fdb import services +# import socket +# import getpass +# +# THIS_DBA_USER=user_name +# THIS_DBA_PSWD=user_password +# +# THIS_COMPUTER_NAME = socket.gethostname() +# CURRENT_WIN_ADMIN = getpass.getuser() +# +# ########################################## +# THIS_FDB = db_conn.database_name +# THIS_FBK=os.path.join(context['temp_directory'],'tmp_6329.fbk') +# ########################################## +# +# #-------------------------------------------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# +# fb_home = services.connect(host='localhost', user= THIS_DBA_USER, password= THIS_DBA_PSWD).get_home_directory() +# +# f_sql_make_map = open( os.path.join(context['temp_directory'],'tmp_6329.sql'), 'w', buffering=0) +# f_sql_txt=''' +# set bail on; +# connect 'localhost:%(THIS_FDB)s' user %(THIS_DBA_USER)s password '%(THIS_DBA_PSWD)s'; +# +# create or alter global mapping win_system using plugin win_sspi from user "%(THIS_COMPUTER_NAME)s\\%(CURRENT_WIN_ADMIN)s" to user %(THIS_DBA_USER)s; +# commit; +# ''' % locals() +# +# f_sql_make_map.write(f_sql_txt) +# f_sql_make_map.close() +# +# # do NOT remove this delay otherwise can get 'Windows error 2: file not found'. +# time.sleep(1) +# +# f_prepare_log=open( os.path.join(context['temp_directory'],'tmp_6329_prepare.log'), 'w', buffering=0) +# subprocess.call( [ fb_home + "isql", "-q", "-i", f_sql_make_map.name ], stdout=f_prepare_log, stderr=subprocess.STDOUT ) +# f_prepare_log.close() +# +# f_backup_log=open( os.path.join(context['temp_directory'],'tmp_6329_backup.log'), 'w', buffering=0) +# subprocess.call( [ fb_home + "gbak", "-v", "-b", "-se", "localhost:service_mgr", THIS_FDB, THIS_FBK], stdout=f_backup_log, stderr=subprocess.STDOUT ) +# f_backup_log.close() +# +# +# # Remove global mapping: +# ######################## +# +# f_sql_drop_map = open( os.path.join(context['temp_directory'],'tmp_6329_cleanup.sql'), 'w', buffering=0) +# f_sql_txt=''' +# set bail on; +# connect 'localhost:%(THIS_FDB)s' user %(THIS_DBA_USER)s password '%(THIS_DBA_PSWD)s'; +# +# drop global mapping win_system; +# commit; +# ''' % locals() +# f_sql_drop_map.write(f_sql_txt) +# f_sql_drop_map.close() +# +# f_cleanup_log = open( os.path.join(context['temp_directory'],'tmp_6329_cleanup.log'), 'w', buffering=0) +# subprocess.call( [ fb_home + "isql", "-q", "-i", f_sql_drop_map.name ], stdout=f_cleanup_log, stderr=subprocess.STDOUT ) +# f_cleanup_log.close() +# +# # Checks: +# ######### +# +# with open( f_prepare_log.name,'r') as f: +# for line in f: +# if line.split(): +# print('UNEXPECTED OUTPUT in '+f_prepare_log.name+': '+line) +# +# +# allowed_patterns = ( +# re.compile('gbak:.*closing.*commit.*finish',re.IGNORECASE), +# ) +# +# with open( f_backup_log.name,'r') as f: +# for line in f: +# if 'ERROR' in line: +# print('UNEXPECTED STDERR in '+f_backup_log.name+': '+line) +# elif 'closing' in line: +# match2some = filter( None, [ p.search(line) for p in allowed_patterns ] ) +# if match2some: +# print('EXPECTED output found in the backup log') +# +# with open( f_cleanup_log.name,'r') as f: +# for line in f: +# if line.split(): +# print('UNEXPECTED OUTPUT in '+f_cleanup_log.name+': '+line) +# +# # Cleanup: +# ########## +# +# # do NOT remove this pause otherwise some of logs will not be enable for deletion and test will finish with +# # Exception raised while executing Python test script. exception: WindowsError: 32 +# time.sleep(1) +# +# f_list=( f_sql_make_map, f_sql_drop_map, f_prepare_log, f_backup_log, f_cleanup_log ) +# cleanup( [ i.name for i in f_list ] ) +# +# os.remove(THIS_FBK) +# +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + EXPECTED output found in the backup log + """ + +@pytest.mark.version('>=3.0.6') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_6329_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6336.py b/tests/bugs/test_core_6336.py new file mode 100644 index 00000000..0dc769a3 --- /dev/null +++ b/tests/bugs/test_core_6336.py @@ -0,0 +1,7512 @@ +#coding:utf-8 +# +# id: bugs.core_6336 +# title: Regression in FB 4.x: error "Implementation of text subtype not located" on attempt to use some collations defined in fbintl.conf +# decription: +# Test uses list of character sets and collations defined in %FB_HOME%\\intl +# bintl.conf. +# For each charset we try following: +# 1) alter database set default character set ; +# 2) alter this set default collation ; +# 3) create unicode collation for this and alter so that default collation is ; +# 4) for each of other (non-unicode) collations alter with set default collation to . +# Each of these actions is verified by creating several DB objects: domains, table, view and stored procedure. +# Every created DB object will use fields/parameters which refer to current charset and collation, i.e.: +# * create two domains of type VARCHAR; one of them will be later modified so that its default collation will be dropped; +# * create one domain of type BLOB; it can not be modified anyway because of implementation limits; +# * create table with two fields (varchar and blob) of these domains; +# * create view which refers to rdb$fields (this statement did FAIL and it was the reason of creation this ticket); +# * create stored proc with parameters of these domains. +# Finally, we do query to RDB$ tables in order to show data related to these domains. +# +# Following is what occurs for iso8859_1 (and similarly for all other charsets): +# ======== +# alter database set default character set iso8859_1 +# alter character set iso8859_1 set default collation iso8859_1 +# create collation co_non_unc for iso8859_1 from iso8859_1 PAD SPACE +# create domain dm_text varchar(50) character set iso8859_1 collate co_non_unc +# create domain dm_name varchar(50) character set iso8859_1 collate iso8859_1 +# create domain dm_blob blob character set iso8859_1 collate iso8859_1 +# ... +# -- here we check that 'collate co_non_unc' will be cuted off and default collation will be restored for this domain: +# alter domain dm_text type char(50) character set iso8859_1 +# +# +# +# create collation ISO8859_1_UNICODE for iso8859_1 +# alter character set iso8859_1 set default collation ISO8859_1_UNICODE +# create collation co_unicode for iso8859_1 from iso8859_1_unicode case insensitive accent insensitive 'NUMERIC-SORT=1' +# create domain dm_text varchar(50) character set iso8859_1 collate co_unicode +# create domain dm_name varchar(50) character set iso8859_1 collate co_unicode +# create domain dm_blob blob character set iso8859_1 collate co_unicode +# ... +# -- here we check that 'collate co_unicode' will be cuted off and default collation will be restored for this domain: +# alter domain dm_text type char(50) character set iso8859_1 +# +# +# +# +# alter character set iso8859_1 set default collation da_da +# create collation co_non_unc for iso8859_1 from da_da PAD SPACE +# create domain dm_text varchar(50) character set iso8859_1 collate co_non_unc +# create domain dm_name varchar(50) character set iso8859_1 collate da_da +# create domain dm_blob blob character set iso8859_1 collate da_da +# ... +# -- here we check that 'collate co_non_unc' will be cuted off and default collation will be restored for this domain: +# alter domain dm_text type char(50) character set iso8859_1 +# +# +# +# ... and so on for all other collations defined for charset ISO8859_1 ... +# ======== +# +# Checked on 4.0.0.2114 SS. Time of execution: 73.668s. +# +# tracker_id: CORE-6336 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# runProgram('gfix',[dsn,'-w','async']) +# +# sql_text=''' +# set list on; +# --set bail on; +# set blob all; +# set width f_name 20; +# set width cset_name 20; +# set width coll_name 20; +# set width cset_default_coll 20; +# set width domain_coll_name 20; +# +# --set echo on; +# --shell del c: emp mp4test.fdb 2>nul; +# connect '%(dsn)s'; +# set autoddl off; +# SET KEEP_TRAN_PARAMS ON; +# +# --create database '%(dsn)s'; +# +# commit; +# set transaction READ COMMITTED NO RECORD_VERSION NO WAIT; +# +# set term ^; +# create procedure sp_cleanup as +# begin +# begin +# execute statement 'drop procedure sp_info'; +# when any do begin end +# end +# +# begin +# execute statement 'drop table t_info'; +# when any do begin end +# end +# +# begin +# execute statement 'drop view v_info'; +# when any do begin end +# end +# +# begin +# execute statement 'drop domain dm_name'; +# when any do begin end +# end +# +# begin +# execute statement 'drop domain dm_text'; +# when any do begin end +# end +# +# begin +# execute statement 'drop domain dm_blob'; +# when any do begin end +# end +# +# begin +# execute statement 'drop collation co_unicode'; +# when any do begin end +# end +# +# begin +# execute statement 'drop collation co_non_unc'; +# when any do begin end +# end +# end +# ^ +# +# create procedure sp_add_objects ( a_cset varchar(50), a_coll varchar(50) ) as +# begin +# +# /* +# create collation win1252_unicode_ci for win1252 from win1252_unicode case insensitive; +# */ +# -- NB: COLLATE clause can be used only in CREATE domain statement. ALTER domain does not allow this. +# if ( right(upper(a_coll),8) = upper('_UNICODE') ) then +# begin +# execute statement 'create collation co_unicode for ' || a_cset || ' from ' || a_coll || q'{ case insensitive accent insensitive 'NUMERIC-SORT=1'}'; +# execute statement 'create domain dm_text varchar(50) character set ' || a_cset || ' collate co_unicode'; +# execute statement 'create domain dm_name varchar(50) character set ' || a_cset || ' collate co_unicode'; +# execute statement 'create domain dm_blob blob character set ' || a_cset || ' collate co_unicode'; +# end +# else +# begin +# -- CREATE COLLATION PT_PT2 FOR ISO8859_1 FROM PT_PT 'SPECIALS-FIRST=1'; +# -- create collation co_non_unc for SJIS_0208 from SJIS_0208 'SPECIALS-FIRST=1'; ==> invalid collation attr; the same for DISABLE-COMPRESSIONS=1 +# execute statement 'create collation co_non_unc for ' || a_cset || ' from ' || a_coll || ' PAD SPACE'; +# execute statement 'create domain dm_text varchar(50) character set ' || a_cset || ' collate co_non_unc'; +# execute statement 'create domain dm_name varchar(50) character set ' || a_cset || ' collate ' || a_coll; +# execute statement 'create domain dm_blob blob character set ' || a_cset || ' collate ' || a_coll ; +# end +# +# execute statement q'{recreate view v_name as select f.rdb$field_name as f_name from rdb$fields f where f.rdb$field_name = upper('dm_name')}'; +# +# execute statement q'{recreate view v_blob as select f.rdb$field_name as f_name from rdb$fields f where f.rdb$field_name = upper('dm_blob')}'; +# +# execute statement 'recreate table t_info(f_name dm_name, f_blob dm_blob)'; +# +# execute statement q'{create procedure sp_info(a_name dm_name, a_blob dm_blob) returns(o_name dm_name, o_blob dm_blob) as begin suspend; end }'; +# +# execute statement +# q'{recreate view v_info as +# select +# cast(f.rdb$field_name as varchar(20)) as f_name +# ,f.rdb$character_set_id as cset_id +# ,f.rdb$collation_id as coll_id +# ,cast(c.rdb$character_set_name as varchar(20)) as cset_name +# ,cast(c.rdb$default_collate_name as varchar(20)) as cset_default_coll +# ,cast(k.rdb$collation_name as varchar(20)) as domain_coll_name +# ,k.rdb$collation_attributes as coll_attr +# ,cast(k.rdb$specific_attributes as varchar(8190)) as coll_spec +# from rdb$fields f +# left join rdb$character_sets c on f.rdb$character_set_id = c.rdb$character_set_id +# left join rdb$collations k on c.rdb$character_set_id = k.rdb$character_set_id and f.rdb$collation_id = k.rdb$collation_id +# where f.rdb$field_name in ( upper('dm_text'), upper('dm_name'), upper('dm_blob') ) +# order by f_name +# }' +# ; +# +# +# -- Here we try to REMOVE collation attribute from domain: +# execute statement 'alter domain dm_text type char(50) character set ' || a_cset ; +# +# -- dm_blob: "Cannot change datatype ... Changing datatype is not supported for BLOB or ARRAY columns." +# -- NB: this is so even when a new type is the same as old: BLOB. +# -- execute statement 'alter domain dm_blob type blob character set ' || a_cset ; +# +# end +# ^ +# set term ;^ +# commit; +# +# --################################ S J I S _ 0 2 0 8 ############################# +# +# alter database set default character set SJIS_0208 ; +# +# +# alter character set SJIS_0208 set default collation SJIS_0208; +# commit; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('SJIS_0208', 'SJIS_0208'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation sjis_0208_unicode for sjis_0208; +# alter character set SJIS_0208 set default collation SJIS_0208_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('SJIS_0208', 'SJIS_0208_UNICODE'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --################################ E U C J _ 0 2 0 8 ############################# +# +# alter database set default character set EUCJ_0208; +# alter character set EUCJ_0208 set default collation EUCJ_0208; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('EUCJ_0208', 'EUCJ_0208'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# create collation EUCJ_0208_UNICODE for EUCJ_0208; +# alter character set EUCJ_0208 set default collation EUCJ_0208_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('EUCJ_0208', 'EUCJ_0208_UNICODE'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# --################################ D O S 4 3 7 ############################# +# +# alter database set default character set DOS437; +# +# alter character set DOS437 set default collation DOS437; +# create collation DOS437_UNICODE for DOS437; +# alter character set DOS437 set default collation DOS437_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS437', 'DOS437_UNICODE'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set DOS437 set default collation DB_DEU437; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS437', 'DB_DEU437'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set DOS437 set default collation DB_ESP437; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS437', 'DB_ESP437'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set DOS437 set default collation DB_FIN437; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS437', 'DB_FIN437'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set DOS437 set default collation DB_FRA437; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS437', 'DB_FRA437'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set DOS437 set default collation DB_ITA437; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS437', 'DB_ITA437'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set DOS437 set default collation DB_NLD437; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS437', 'DB_NLD437'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set DOS437 set default collation DB_SVE437; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS437', 'DB_SVE437'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set DOS437 set default collation DB_UK437; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS437', 'DB_UK437'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set DOS437 set default collation DB_US437; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS437', 'DB_US437'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set DOS437 set default collation PDOX_ASCII; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS437', 'PDOX_ASCII'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set DOS437 set default collation PDOX_INTL; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS437', 'PDOX_INTL'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set DOS437 set default collation PDOX_SWEDFIN; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS437', 'PDOX_SWEDFIN'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# --################################ D O S 8 5 0 ############################# +# +# alter database set default character set dos850; +# +# alter character set dos850 set default collation dos850; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS850', 'DOS850'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation DOS850_UNICODE for DOS850; +# alter character set dos850 set default collation DOS850_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS850', 'DOS850_UNICODE'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set dos850 set default collation DB_DEU850; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS850', 'DB_DEU850'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set dos850 set default collation DB_FRA850; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS850', 'DB_FRA850'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set dos850 set default collation DB_FRC850; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS850', 'DB_FRC850'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set dos850 set default collation DB_ITA850; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS850', 'DB_ITA850'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set dos850 set default collation DB_NLD850; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS850', 'DB_NLD850'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set dos850 set default collation DB_PTB850; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS850', 'DB_PTB850'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set dos850 set default collation DB_SVE850; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS850', 'DB_SVE850'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set dos850 set default collation DB_UK850; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS850', 'DB_UK850'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set dos850 set default collation DB_US850; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS850', 'DB_US850'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --################################ D O S 8 6 5 ############################# +# +# alter database set default character set dos865; +# +# alter character set dos865 set default collation dos865; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS865', 'DOS865'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation DOS865_UNICODE for DOS865; +# alter character set dos865 set default collation DOS865_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS865', 'DOS865_UNICODE'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set dos865 set default collation DB_DAN865; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS865', 'DB_DAN865'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set dos865 set default collation DB_NOR865; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS865', 'DB_NOR865'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set dos865 set default collation PDOX_NORDAN4; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('DOS865', 'PDOX_NORDAN4'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --############################## I S O 8 8 5 9 _ 1 ########################### +# +# alter database set default character set iso8859_1 ; +# +# alter character set iso8859_1 set default collation iso8859_1; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('iso8859_1', 'iso8859_1'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation ISO8859_1_UNICODE for iso8859_1; +# alter character set iso8859_1 set default collation ISO8859_1_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('iso8859_1', 'iso8859_1_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set iso8859_1 set default collation da_da; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('iso8859_1', 'da_da'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set iso8859_1 set default collation de_de; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('iso8859_1', 'de_de'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set iso8859_1 set default collation du_nl; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('iso8859_1', 'du_nl'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set iso8859_1 set default collation en_uk; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('iso8859_1', 'en_uk'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set iso8859_1 set default collation en_us; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('iso8859_1', 'en_us'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set iso8859_1 set default collation es_es; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('iso8859_1', 'es_es'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set iso8859_1 set default collation es_es_ci_ai; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('iso8859_1', 'es_es_ci_ai'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set iso8859_1 set default collation fi_fi; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('iso8859_1', 'fi_fi'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set iso8859_1 set default collation fr_ca; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('iso8859_1', 'fr_ca'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set iso8859_1 set default collation fr_fr; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('iso8859_1', 'fr_fr'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set iso8859_1 set default collation is_is; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('iso8859_1', 'is_is'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set iso8859_1 set default collation it_it; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('iso8859_1', 'it_it'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set iso8859_1 set default collation no_no; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('iso8859_1', 'no_no'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set iso8859_1 set default collation sv_sv; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('iso8859_1', 'sv_sv'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set iso8859_1 set default collation pt_br; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('iso8859_1', 'pt_br'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set iso8859_1 set default collation pt_pt; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('iso8859_1', 'pt_pt'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --############################## I S O 8 8 5 9 _ 2 ########################### +# +# alter database set default character set ISO8859_2; +# +# alter character set iso8859_2 set default collation ISO8859_2; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('ISO8859_2', 'ISO8859_2'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation ISO8859_2_UNICODE for iso8859_2; +# alter character set iso8859_2 set default collation ISO8859_2_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('ISO8859_2', 'ISO8859_2_UNICODE'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set iso8859_2 set default collation CS_CZ; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('ISO8859_2', 'CS_CZ'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set iso8859_2 set default collation ISO_HUN; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('ISO8859_2', 'ISO_HUN'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set iso8859_2 set default collation ISO_PLK; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('ISO8859_2', 'ISO_PLK'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --############################## I S O 8 8 5 9 _ 3 ########################### +# +# alter database set default character set ISO8859_3; +# +# alter character set iso8859_3 set default collation ISO8859_3; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('ISO8859_3', 'ISO8859_3'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation ISO8859_3_UNICODE for iso8859_3; +# alter character set iso8859_3 set default collation ISO8859_3_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('ISO8859_3', 'ISO8859_3_UNICODE'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --############################## I S O 8 8 5 9 _ 4 ########################### +# +# alter database set default character set ISO8859_4; +# +# alter character set iso8859_4 set default collation ISO8859_4; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('ISO8859_4', 'ISO8859_4'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation ISO8859_4_UNICODE for iso8859_4; +# alter character set iso8859_4 set default collation ISO8859_4_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('ISO8859_4', 'ISO8859_4_UNICODE'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --############################## I S O 8 8 5 9 _ 5 ########################### +# +# alter database set default character set ISO8859_5; +# +# alter character set iso8859_5 set default collation ISO8859_5; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('ISO8859_5', 'ISO8859_5'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation ISO8859_5_UNICODE for iso8859_5; +# alter character set iso8859_5 set default collation ISO8859_5_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('ISO8859_5', 'ISO8859_5_UNICODE'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --############################## I S O 8 8 5 9 _ 6 ########################### +# +# alter database set default character set ISO8859_6; +# +# alter character set iso8859_6 set default collation ISO8859_6; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('ISO8859_6', 'ISO8859_6'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation ISO8859_6_UNICODE for iso8859_6; +# alter character set iso8859_6 set default collation ISO8859_6_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('ISO8859_6', 'ISO8859_6_UNICODE'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --############################## I S O 8 8 5 9 _ 7 ########################### +# +# alter database set default character set ISO8859_7; +# +# alter character set iso8859_7 set default collation ISO8859_7; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('ISO8859_7', 'ISO8859_7'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation ISO8859_7_UNICODE for iso8859_7; +# alter character set iso8859_7 set default collation ISO8859_7_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('ISO8859_7', 'ISO8859_7_UNICODE'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --############################## I S O 8 8 5 9 _ 8 ########################### +# +# alter database set default character set ISO8859_8; +# +# alter character set iso8859_8 set default collation ISO8859_8; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('ISO8859_8', 'ISO8859_8'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation ISO8859_8_UNICODE for iso8859_8; +# alter character set iso8859_8 set default collation ISO8859_8_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('ISO8859_8', 'ISO8859_8_UNICODE'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# --############################## I S O 8 8 5 9 _ 9 ########################### +# +# alter database set default character set ISO8859_9; +# +# alter character set iso8859_9 set default collation ISO8859_9; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('ISO8859_9', 'ISO8859_9'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation ISO8859_9_UNICODE for iso8859_9; +# alter character set iso8859_9 set default collation ISO8859_9_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('ISO8859_9', 'ISO8859_9_UNICODE'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# --############################## I S O 8 8 5 9 _ 1 3 ########################### +# +# alter database set default character set ISO8859_13; +# +# alter character set iso8859_13 set default collation ISO8859_13; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('ISO8859_13', 'ISO8859_13'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation ISO8859_13_UNICODE for iso8859_13; +# alter character set iso8859_13 set default collation ISO8859_13_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('ISO8859_13', 'ISO8859_13_UNICODE'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set iso8859_13 set default collation LT_LT; +# recreate view v_info as select f.rdb$field_name as f_name from rdb$fields f where f.rdb$field_name = upper('dm_name'); +# commit; +# connect '%(dsn)s'; +# +# +# --################################ D O S 8 5 2 ############################# +# +# alter database set default character set dos852; +# +# alter character set dos852 set default collation dos852; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos852', 'dos852'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation DOS852_UNICODE for DOS852; +# alter character set dos852 set default collation DOS852_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos852', 'dos852_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set dos852 set default collation DB_CSY; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos852', 'DB_CSY'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set dos852 set default collation DB_PLK; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos852', 'DB_PLK'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set dos852 set default collation DB_SLO; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos852', 'DB_SLO'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set dos852 set default collation PDOX_CSY; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos852', 'PDOX_CSY'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set dos852 set default collation PDOX_HUN; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos852', 'PDOX_HUN'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set dos852 set default collation PDOX_PLK; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos852', 'PDOX_PLK'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set dos852 set default collation PDOX_SLO; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos852', 'PDOX_SLO'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# --################################ D O S 8 5 7 ############################# +# +# alter database set default character set dos857; +# +# alter character set dos857 set default collation dos857; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos857', 'dos857'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation DOS857_UNICODE for dos857; +# alter character set dos857 set default collation DOS857_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos857', 'dos857_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set dos857 set default collation DB_TRK; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos857', 'db_trk'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --################################ D O S 8 6 0 ############################# +# +# alter database set default character set dos860; +# +# alter character set dos860 set default collation dos860; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos860', 'dos860'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation DOS860_UNICODE for dos860; +# alter character set dos860 set default collation DOS860_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos860', 'dos860_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set dos860 set default collation DB_PTG860; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos860', 'DB_PTG860'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --################################ D O S 8 6 1 ############################# +# +# alter database set default character set dos861; +# +# alter character set dos861 set default collation dos861; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos861', 'dos861'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation DOS861_UNICODE for dos861; +# alter character set dos861 set default collation DOS861_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos861', 'dos861_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set dos861 set default collation PDOX_ISL; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos861', 'pdox_isl'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --################################ D O S 8 6 3 ############################# +# +# alter database set default character set dos863; +# +# alter character set dos863 set default collation dos863; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos863', 'dos863'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation DOS863_UNICODE for dos863; +# alter character set dos863 set default collation DOS863_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos863', 'dos863_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set dos863 set default collation DB_FRC863; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos863', 'db_frc863'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# --################################ C Y R L ############################# +# +# alter database set default character set cyrl; +# +# alter character set cyrl set default collation cyrl; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('cyrl', 'cyrl'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation cyrl_UNICODE for cyrl; +# alter character set cyrl set default collation cyrl_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('cyrl', 'cyrl_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set cyrl set default collation DB_RUS; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('cyrl', 'db_rus'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set cyrl set default collation PDOX_CYRL; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('cyrl', 'pdox_cyrl'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --################################ D O S 7 3 7 ############################# +# +# alter database set default character set dos737; +# +# alter character set dos737 set default collation dos737; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos737', 'dos737'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation DOS737_UNICODE for DOS737; +# alter character set dos737 set default collation DOS737_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos737', 'dos737_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# --################################ D O S 7 7 5 ############################# +# +# alter database set default character set dos775; +# +# alter character set dos775 set default collation dos775; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos775', 'dos775'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation DOS775_UNICODE for DOS775; +# alter character set dos775 set default collation DOS775_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos775', 'dos775_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --################################ D O S 8 5 8 ############################# +# +# alter database set default character set dos858; +# +# alter character set dos858 set default collation dos858; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos858', 'dos858'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation DOS858_UNICODE for DOS858; +# alter character set dos858 set default collation DOS858_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos858', 'dos858_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# --################################ D O S 8 6 2 ############################# +# +# alter database set default character set dos862; +# +# alter character set dos862 set default collation dos862; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos862', 'dos862'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation DOS862_UNICODE for DOS862; +# alter character set dos862 set default collation DOS862_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos862', 'dos862_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# --################################ D O S 8 6 4 ############################# +# +# alter database set default character set dos864; +# +# alter character set dos864 set default collation dos864; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos864', 'dos864'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation DOS864_UNICODE for DOS864; +# alter character set dos864 set default collation DOS864_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos864', 'dos864_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# --################################ D O S 8 6 6 ############################# +# +# alter database set default character set dos866; +# +# alter character set dos866 set default collation dos866; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos866', 'dos866'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation DOS866_UNICODE for DOS866; +# alter character set dos866 set default collation DOS866_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos866', 'dos866_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# --################################ D O S 8 6 9 ############################# +# +# alter database set default character set dos869; +# +# alter character set dos869 set default collation dos869; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos869', 'dos869'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation DOS869_UNICODE for DOS869; +# alter character set dos869 set default collation DOS869_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('dos869', 'dos869_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# --############################### W I N 1 2 5 0 ############################# +# +# alter database set default character set win1250; +# +# alter character set win1250 set default collation win1250; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1250', 'win1250'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation win1250_UNICODE for win1250; +# alter character set win1250 set default collation win1250_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1250', 'win1250_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set win1250 set default collation PXW_CSY; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1250', 'pxw_csy'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set win1250 set default collation PXW_HUN; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1250', 'pxw_hun'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set win1250 set default collation PXW_HUNDC; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1250', 'pxw_hundc'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set win1250 set default collation PXW_PLK; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1250', 'pxw_plk'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set win1250 set default collation PXW_SLOV; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1250', 'pxw_slov'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set win1250 set default collation BS_BA; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1250', 'bs_ba'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set win1250 set default collation WIN_CZ; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1250', 'win_cz'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set win1250 set default collation WIN_CZ_CI_AI; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1250', 'WIN_CZ_CI_AI'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --############################### W I N 1 2 5 1 ############################# +# +# alter database set default character set win1251; +# +# alter character set win1251 set default collation win1251; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1251', 'win1251'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation win1251_UNICODE for win1251; +# alter character set win1251 set default collation win1251_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1251', 'win1251_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set win1251 set default collation PXW_CYRL; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1251', 'pxw_cyrl'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set win1251 set default collation WIN1251_UA; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1251', 'win1251_ua'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --############################### W I N 1 2 5 2 ############################# +# +# alter database set default character set win1252; +# +# alter character set win1252 set default collation win1252; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1252', 'win1252'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation win1252_UNICODE for win1252; +# alter character set win1252 set default collation win1252_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1252', 'win1252_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set win1252 set default collation PXW_INTL; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1252', 'pxw_intl'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set win1252 set default collation PXW_INTL850; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1252', 'pxw_intl850'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set win1252 set default collation PXW_NORDAN4; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1252', 'pxw_nordan4'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set win1252 set default collation WIN_PTBR; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1252', 'win_ptbr'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set win1252 set default collation PXW_SPAN; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1252', 'pxw_span'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set win1252 set default collation PXW_SWEDFIN; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1252', 'pxw_swedfin'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --############################### W I N 1 2 5 3 ############################# +# +# alter database set default character set win1253; +# +# alter character set win1253 set default collation win1253; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1253', 'win1253'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation win1253_UNICODE for win1253; +# alter character set win1253 set default collation win1253_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1253', 'win1253_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set win1253 set default collation PXW_GREEK; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1253', 'pxw_greek'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --############################### W I N 1 2 5 4 ############################# +# +# alter database set default character set win1254; +# +# alter character set win1254 set default collation win1254; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1254', 'win1254'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation win1254_UNICODE for win1254; +# alter character set win1254 set default collation win1254_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1254', 'win1254_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set win1254 set default collation PXW_TURK; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1254', 'pxw_turk'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# --################################## N E X T ############################### +# +# alter database set default character set next; +# +# alter character set next set default collation next; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('next', 'next'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation NEXT_UNICODE for next; +# alter character set next set default collation NEXT_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('next', 'next_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set next set default collation NXT_DEU; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('next', 'nxt_deu'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set next set default collation NXT_ESP; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('next', 'nxt_esp'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set next set default collation NXT_FRA; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('next', 'nxt_fra'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set next set default collation NXT_ITA; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('next', 'nxt_ita'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set next set default collation NXT_US; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('next', 'nxt_us'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --############################### W I N 1 2 5 5 ############################# +# +# alter database set default character set win1255; +# +# alter character set win1255 set default collation win1255; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1255', 'win1255'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation win1255_UNICODE for win1255; +# alter character set win1255 set default collation win1255_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1255', 'win1255_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --############################### W I N 1 2 5 6 ############################# +# +# alter database set default character set win1256; +# +# alter character set win1256 set default collation win1256; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1256', 'win1256'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation win1256_UNICODE for win1256; +# alter character set win1256 set default collation win1256_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1256', 'win1256_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --############################### W I N 1 2 5 7 ############################# +# +# alter database set default character set win1257; +# +# alter character set win1257 set default collation win1257; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1257', 'win1257'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation win1257_UNICODE for win1257; +# alter character set win1257 set default collation win1257_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1257', 'win1257_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set win1257 set default collation WIN1257_EE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1257', 'win1257_ee'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set win1257 set default collation WIN1257_LT; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1257', 'win1257_lt'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set win1257 set default collation WIN1257_LV; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1257', 'win1257_lv'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --############################## K S C _ 5 6 0 1 ############################# +# +# alter database set default character set ksc_5601; +# +# alter character set ksc_5601 set default collation ksc_5601; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('ksc_5601', 'ksc_5601'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation ksc_5601_UNICODE for ksc_5601; +# alter character set ksc_5601 set default collation ksc_5601_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('ksc_5601', 'ksc_5601_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set ksc_5601 set default collation KSC_DICTIONARY; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('ksc_5601', 'KSC_DICTIONARY'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --################################# B I G _ 5 ############################### +# +# alter database set default character set big_5; +# +# alter character set big_5 set default collation big_5; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('big_5', 'big_5'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation big_5_UNICODE for big_5; +# alter character set big_5 set default collation big_5_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('big_5', 'big_5_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --############################# G B _ 2 3 1 2 ############################### +# +# alter database set default character set gb_2312; +# +# alter character set gb_2312 set default collation gb_2312; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('gb_2312', 'gb_2312'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation gb_2312_UNICODE for gb_2312; +# alter character set gb_2312 set default collation gb_2312_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('gb_2312', 'gb_2312_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --############################# K O I 8 R ################################# +# +# alter database set default character set koi8r; +# +# alter character set koi8r set default collation koi8r; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('koi8r', 'koi8r'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation koi8r_UNICODE for koi8r; +# alter character set koi8r set default collation koi8r_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('koi8r', 'koi8r_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set koi8r set default collation koi8r_ru; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('koi8r', 'koi8r_ru'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --############################# K O I 8 U ################################# +# +# alter database set default character set koi8u; +# +# alter character set koi8u set default collation koi8u; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('koi8u', 'koi8u'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation koi8u_UNICODE for koi8u; +# alter character set koi8u set default collation koi8u_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('koi8u', 'koi8u_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# alter character set koi8u set default collation koi8u_ua; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('koi8u', 'koi8u_ua'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --############################### W I N 1 2 5 8 ############################# +# +# alter database set default character set win1258; +# +# alter character set win1258 set default collation win1258; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1258', 'win1258'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# create collation win1258_UNICODE for win1258; +# alter character set win1258 set default collation win1258_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('win1258', 'win1258_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --################################ T I S 6 2 0 ############################## +# +# alter database set default character set tis620; +# +# alter character set tis620 set default collation tis620; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('tis620', 'tis620'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# -- pre-registered as system collation, SKIP creation: create collation tis620_UNICODE for tis620; +# alter character set tis620 set default collation tis620_UNICODE; +# commit; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('tis620', 'tis620_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --################################## G B K ################################ +# +# alter database set default character set gbk; +# +# alter character set gbk set default collation gbk; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('gbk', 'gbk'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# -- pre-registered as system collation, SKIP creation: create collation gbk_UNICODE for gbk; +# alter character set gbk set default collation gbk_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('gbk', 'gbk_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --################################ C 9 6 4 3 C ############################## +# +# alter database set default character set cp943c; +# +# alter character set cp943c set default collation cp943c; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('cp943c', 'cp943c'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# -- pre-registered as system collation, SKIP creation: create collation cp943c_UNICODE for cp943c; +# alter character set cp943c set default collation cp943c_UNICODE; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('cp943c', 'cp943c_unicode'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# +# --################################ G B 1 8 0 3 0 ############################## +# +# alter database set default character set gb18030; +# +# alter character set gb18030 set default collation gb18030; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('gb18030', 'gb18030'); +# commit; +# select * from v_info; +# commit; +# connect '%(dsn)s'; +# +# -- pre-registered as system collation, SKIP creation: create collation gb18030_UNICODE for gb18030; +# alter character set gb18030 set default collation gb18030_UNICODE; +# commit; +# -- remove existing objects: +# execute procedure sp_cleanup; +# commit; +# execute procedure sp_add_objects('gb18030', 'gb18030_unicode'); +# commit; +# select * from v_info; +# commit; +# ''' % dict(globals(), **locals()) +# +# fb_home = services.connect(host='localhost', user= user_name, password= user_password).get_home_directory() +# +# f_sql_cmd=open( os.path.join(context['temp_directory'],'tmp_6336.sql'), 'w') +# f_sql_cmd.write(sql_text) +# flush_and_close( f_sql_cmd ) +# +# f_sql_log=open( os.path.join(context['temp_directory'],'tmp_6336.log'), 'w') +# f_sql_err=open( os.path.join(context['temp_directory'],'tmp_6336.err'), 'w') +# subprocess.call( [ context['isql_path'] , "-q", "-i", f_sql_cmd.name ], stdout=f_sql_log, stderr=f_sql_err ) +# flush_and_close( f_sql_log ) +# flush_and_close( f_sql_err ) +# +# with open(f_sql_err.name, 'r') as f: +# for line in f: +# print('UNEXPECTED STDERR: ' + line) +# +# with open(f_sql_log.name, 'r') as f: +# for line in f: +# print(line) +# +# +# cleanup( ( f_sql_cmd, f_sql_log, f_sql_err ) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F_NAME DM_BLOB + CSET_ID 5 + COLL_ID 0 + CSET_NAME SJIS_0208 + CSET_DEFAULT_COLL SJIS_0208 + DOMAIN_COLL_NAME SJIS_0208 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 5 + COLL_ID 0 + CSET_NAME SJIS_0208 + CSET_DEFAULT_COLL SJIS_0208 + DOMAIN_COLL_NAME SJIS_0208 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 5 + COLL_ID 0 + CSET_NAME SJIS_0208 + CSET_DEFAULT_COLL SJIS_0208 + DOMAIN_COLL_NAME SJIS_0208 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 5 + COLL_ID 126 + CSET_NAME SJIS_0208 + CSET_DEFAULT_COLL SJIS_0208_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 5 + COLL_ID 126 + CSET_NAME SJIS_0208 + CSET_DEFAULT_COLL SJIS_0208_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 5 + COLL_ID 125 + CSET_NAME SJIS_0208 + CSET_DEFAULT_COLL SJIS_0208_UNICODE + DOMAIN_COLL_NAME SJIS_0208_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 6 + COLL_ID 0 + CSET_NAME EUCJ_0208 + CSET_DEFAULT_COLL EUCJ_0208 + DOMAIN_COLL_NAME EUCJ_0208 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 6 + COLL_ID 0 + CSET_NAME EUCJ_0208 + CSET_DEFAULT_COLL EUCJ_0208 + DOMAIN_COLL_NAME EUCJ_0208 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 6 + COLL_ID 0 + CSET_NAME EUCJ_0208 + CSET_DEFAULT_COLL EUCJ_0208 + DOMAIN_COLL_NAME EUCJ_0208 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 6 + COLL_ID 126 + CSET_NAME EUCJ_0208 + CSET_DEFAULT_COLL EUCJ_0208_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 6 + COLL_ID 126 + CSET_NAME EUCJ_0208 + CSET_DEFAULT_COLL EUCJ_0208_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 6 + COLL_ID 125 + CSET_NAME EUCJ_0208 + CSET_DEFAULT_COLL EUCJ_0208_UNICODE + DOMAIN_COLL_NAME EUCJ_0208_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 10 + COLL_ID 125 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DOS437_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 10 + COLL_ID 125 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DOS437_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 10 + COLL_ID 126 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DOS437_UNICODE + DOMAIN_COLL_NAME DOS437_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 10 + COLL_ID 4 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DB_DEU437 + DOMAIN_COLL_NAME DB_DEU437 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 10 + COLL_ID 4 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DB_DEU437 + DOMAIN_COLL_NAME DB_DEU437 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 10 + COLL_ID 4 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DB_DEU437 + DOMAIN_COLL_NAME DB_DEU437 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 10 + COLL_ID 5 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DB_ESP437 + DOMAIN_COLL_NAME DB_ESP437 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 10 + COLL_ID 5 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DB_ESP437 + DOMAIN_COLL_NAME DB_ESP437 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 10 + COLL_ID 5 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DB_ESP437 + DOMAIN_COLL_NAME DB_ESP437 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 10 + COLL_ID 6 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DB_FIN437 + DOMAIN_COLL_NAME DB_FIN437 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 10 + COLL_ID 6 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DB_FIN437 + DOMAIN_COLL_NAME DB_FIN437 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 10 + COLL_ID 6 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DB_FIN437 + DOMAIN_COLL_NAME DB_FIN437 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 10 + COLL_ID 7 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DB_FRA437 + DOMAIN_COLL_NAME DB_FRA437 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 10 + COLL_ID 7 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DB_FRA437 + DOMAIN_COLL_NAME DB_FRA437 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 10 + COLL_ID 7 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DB_FRA437 + DOMAIN_COLL_NAME DB_FRA437 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 10 + COLL_ID 8 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DB_ITA437 + DOMAIN_COLL_NAME DB_ITA437 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 10 + COLL_ID 8 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DB_ITA437 + DOMAIN_COLL_NAME DB_ITA437 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 10 + COLL_ID 8 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DB_ITA437 + DOMAIN_COLL_NAME DB_ITA437 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 10 + COLL_ID 9 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DB_NLD437 + DOMAIN_COLL_NAME DB_NLD437 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 10 + COLL_ID 9 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DB_NLD437 + DOMAIN_COLL_NAME DB_NLD437 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 10 + COLL_ID 9 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DB_NLD437 + DOMAIN_COLL_NAME DB_NLD437 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 10 + COLL_ID 10 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DB_SVE437 + DOMAIN_COLL_NAME DB_SVE437 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 10 + COLL_ID 10 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DB_SVE437 + DOMAIN_COLL_NAME DB_SVE437 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 10 + COLL_ID 10 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DB_SVE437 + DOMAIN_COLL_NAME DB_SVE437 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 10 + COLL_ID 11 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DB_UK437 + DOMAIN_COLL_NAME DB_UK437 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 10 + COLL_ID 11 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DB_UK437 + DOMAIN_COLL_NAME DB_UK437 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 10 + COLL_ID 11 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DB_UK437 + DOMAIN_COLL_NAME DB_UK437 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 10 + COLL_ID 12 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DB_US437 + DOMAIN_COLL_NAME DB_US437 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 10 + COLL_ID 12 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DB_US437 + DOMAIN_COLL_NAME DB_US437 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 10 + COLL_ID 12 + CSET_NAME DOS437 + CSET_DEFAULT_COLL DB_US437 + DOMAIN_COLL_NAME DB_US437 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 10 + COLL_ID 1 + CSET_NAME DOS437 + CSET_DEFAULT_COLL PDOX_ASCII + DOMAIN_COLL_NAME PDOX_ASCII + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 10 + COLL_ID 1 + CSET_NAME DOS437 + CSET_DEFAULT_COLL PDOX_ASCII + DOMAIN_COLL_NAME PDOX_ASCII + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 10 + COLL_ID 1 + CSET_NAME DOS437 + CSET_DEFAULT_COLL PDOX_ASCII + DOMAIN_COLL_NAME PDOX_ASCII + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 10 + COLL_ID 2 + CSET_NAME DOS437 + CSET_DEFAULT_COLL PDOX_INTL + DOMAIN_COLL_NAME PDOX_INTL + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 10 + COLL_ID 2 + CSET_NAME DOS437 + CSET_DEFAULT_COLL PDOX_INTL + DOMAIN_COLL_NAME PDOX_INTL + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 10 + COLL_ID 2 + CSET_NAME DOS437 + CSET_DEFAULT_COLL PDOX_INTL + DOMAIN_COLL_NAME PDOX_INTL + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 10 + COLL_ID 3 + CSET_NAME DOS437 + CSET_DEFAULT_COLL PDOX_SWEDFIN + DOMAIN_COLL_NAME PDOX_SWEDFIN + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 10 + COLL_ID 3 + CSET_NAME DOS437 + CSET_DEFAULT_COLL PDOX_SWEDFIN + DOMAIN_COLL_NAME PDOX_SWEDFIN + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 10 + COLL_ID 3 + CSET_NAME DOS437 + CSET_DEFAULT_COLL PDOX_SWEDFIN + DOMAIN_COLL_NAME PDOX_SWEDFIN + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 11 + COLL_ID 0 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DOS850 + DOMAIN_COLL_NAME DOS850 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 11 + COLL_ID 0 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DOS850 + DOMAIN_COLL_NAME DOS850 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 11 + COLL_ID 0 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DOS850 + DOMAIN_COLL_NAME DOS850 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 11 + COLL_ID 126 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DOS850_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 11 + COLL_ID 126 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DOS850_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 11 + COLL_ID 125 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DOS850_UNICODE + DOMAIN_COLL_NAME DOS850_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 11 + COLL_ID 2 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DB_DEU850 + DOMAIN_COLL_NAME DB_DEU850 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 11 + COLL_ID 2 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DB_DEU850 + DOMAIN_COLL_NAME DB_DEU850 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 11 + COLL_ID 2 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DB_DEU850 + DOMAIN_COLL_NAME DB_DEU850 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 11 + COLL_ID 4 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DB_FRA850 + DOMAIN_COLL_NAME DB_FRA850 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 11 + COLL_ID 4 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DB_FRA850 + DOMAIN_COLL_NAME DB_FRA850 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 11 + COLL_ID 4 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DB_FRA850 + DOMAIN_COLL_NAME DB_FRA850 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 11 + COLL_ID 1 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DB_FRC850 + DOMAIN_COLL_NAME DB_FRC850 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 11 + COLL_ID 1 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DB_FRC850 + DOMAIN_COLL_NAME DB_FRC850 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 11 + COLL_ID 1 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DB_FRC850 + DOMAIN_COLL_NAME DB_FRC850 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 11 + COLL_ID 5 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DB_ITA850 + DOMAIN_COLL_NAME DB_ITA850 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 11 + COLL_ID 5 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DB_ITA850 + DOMAIN_COLL_NAME DB_ITA850 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 11 + COLL_ID 5 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DB_ITA850 + DOMAIN_COLL_NAME DB_ITA850 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 11 + COLL_ID 6 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DB_NLD850 + DOMAIN_COLL_NAME DB_NLD850 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 11 + COLL_ID 6 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DB_NLD850 + DOMAIN_COLL_NAME DB_NLD850 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 11 + COLL_ID 6 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DB_NLD850 + DOMAIN_COLL_NAME DB_NLD850 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 11 + COLL_ID 7 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DB_PTB850 + DOMAIN_COLL_NAME DB_PTB850 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 11 + COLL_ID 7 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DB_PTB850 + DOMAIN_COLL_NAME DB_PTB850 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 11 + COLL_ID 7 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DB_PTB850 + DOMAIN_COLL_NAME DB_PTB850 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 11 + COLL_ID 8 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DB_SVE850 + DOMAIN_COLL_NAME DB_SVE850 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 11 + COLL_ID 8 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DB_SVE850 + DOMAIN_COLL_NAME DB_SVE850 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 11 + COLL_ID 8 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DB_SVE850 + DOMAIN_COLL_NAME DB_SVE850 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 11 + COLL_ID 9 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DB_UK850 + DOMAIN_COLL_NAME DB_UK850 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 11 + COLL_ID 9 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DB_UK850 + DOMAIN_COLL_NAME DB_UK850 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 11 + COLL_ID 9 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DB_UK850 + DOMAIN_COLL_NAME DB_UK850 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 11 + COLL_ID 10 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DB_US850 + DOMAIN_COLL_NAME DB_US850 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 11 + COLL_ID 10 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DB_US850 + DOMAIN_COLL_NAME DB_US850 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 11 + COLL_ID 10 + CSET_NAME DOS850 + CSET_DEFAULT_COLL DB_US850 + DOMAIN_COLL_NAME DB_US850 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 12 + COLL_ID 0 + CSET_NAME DOS865 + CSET_DEFAULT_COLL DOS865 + DOMAIN_COLL_NAME DOS865 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 12 + COLL_ID 0 + CSET_NAME DOS865 + CSET_DEFAULT_COLL DOS865 + DOMAIN_COLL_NAME DOS865 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 12 + COLL_ID 0 + CSET_NAME DOS865 + CSET_DEFAULT_COLL DOS865 + DOMAIN_COLL_NAME DOS865 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 12 + COLL_ID 126 + CSET_NAME DOS865 + CSET_DEFAULT_COLL DOS865_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 12 + COLL_ID 126 + CSET_NAME DOS865 + CSET_DEFAULT_COLL DOS865_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 12 + COLL_ID 125 + CSET_NAME DOS865 + CSET_DEFAULT_COLL DOS865_UNICODE + DOMAIN_COLL_NAME DOS865_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 12 + COLL_ID 2 + CSET_NAME DOS865 + CSET_DEFAULT_COLL DB_DAN865 + DOMAIN_COLL_NAME DB_DAN865 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 12 + COLL_ID 2 + CSET_NAME DOS865 + CSET_DEFAULT_COLL DB_DAN865 + DOMAIN_COLL_NAME DB_DAN865 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 12 + COLL_ID 2 + CSET_NAME DOS865 + CSET_DEFAULT_COLL DB_DAN865 + DOMAIN_COLL_NAME DB_DAN865 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 12 + COLL_ID 3 + CSET_NAME DOS865 + CSET_DEFAULT_COLL DB_NOR865 + DOMAIN_COLL_NAME DB_NOR865 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 12 + COLL_ID 3 + CSET_NAME DOS865 + CSET_DEFAULT_COLL DB_NOR865 + DOMAIN_COLL_NAME DB_NOR865 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 12 + COLL_ID 3 + CSET_NAME DOS865 + CSET_DEFAULT_COLL DB_NOR865 + DOMAIN_COLL_NAME DB_NOR865 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 12 + COLL_ID 1 + CSET_NAME DOS865 + CSET_DEFAULT_COLL PDOX_NORDAN4 + DOMAIN_COLL_NAME PDOX_NORDAN4 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 12 + COLL_ID 1 + CSET_NAME DOS865 + CSET_DEFAULT_COLL PDOX_NORDAN4 + DOMAIN_COLL_NAME PDOX_NORDAN4 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 12 + COLL_ID 1 + CSET_NAME DOS865 + CSET_DEFAULT_COLL PDOX_NORDAN4 + DOMAIN_COLL_NAME PDOX_NORDAN4 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 21 + COLL_ID 0 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL ISO8859_1 + DOMAIN_COLL_NAME ISO8859_1 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 21 + COLL_ID 0 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL ISO8859_1 + DOMAIN_COLL_NAME ISO8859_1 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 21 + COLL_ID 0 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL ISO8859_1 + DOMAIN_COLL_NAME ISO8859_1 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 21 + COLL_ID 126 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL ISO8859_1_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 21 + COLL_ID 126 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL ISO8859_1_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 21 + COLL_ID 125 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL ISO8859_1_UNICODE + DOMAIN_COLL_NAME ISO8859_1_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 21 + COLL_ID 1 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL DA_DA + DOMAIN_COLL_NAME DA_DA + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 21 + COLL_ID 1 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL DA_DA + DOMAIN_COLL_NAME DA_DA + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 21 + COLL_ID 1 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL DA_DA + DOMAIN_COLL_NAME DA_DA + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 21 + COLL_ID 6 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL DE_DE + DOMAIN_COLL_NAME DE_DE + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 21 + COLL_ID 6 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL DE_DE + DOMAIN_COLL_NAME DE_DE + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 21 + COLL_ID 6 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL DE_DE + DOMAIN_COLL_NAME DE_DE + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 21 + COLL_ID 2 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL DU_NL + DOMAIN_COLL_NAME DU_NL + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 21 + COLL_ID 2 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL DU_NL + DOMAIN_COLL_NAME DU_NL + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 21 + COLL_ID 2 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL DU_NL + DOMAIN_COLL_NAME DU_NL + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 21 + COLL_ID 12 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL EN_UK + DOMAIN_COLL_NAME EN_UK + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 21 + COLL_ID 12 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL EN_UK + DOMAIN_COLL_NAME EN_UK + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 21 + COLL_ID 12 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL EN_UK + DOMAIN_COLL_NAME EN_UK + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 21 + COLL_ID 14 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL EN_US + DOMAIN_COLL_NAME EN_US + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 21 + COLL_ID 14 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL EN_US + DOMAIN_COLL_NAME EN_US + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 21 + COLL_ID 14 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL EN_US + DOMAIN_COLL_NAME EN_US + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 21 + COLL_ID 10 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL ES_ES + DOMAIN_COLL_NAME ES_ES + COLL_ATTR 1 + COLL_SPEC DISABLE-COMPRESSIONS=1;SPECIALS-FIRST=1 + + F_NAME DM_NAME + CSET_ID 21 + COLL_ID 10 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL ES_ES + DOMAIN_COLL_NAME ES_ES + COLL_ATTR 1 + COLL_SPEC DISABLE-COMPRESSIONS=1;SPECIALS-FIRST=1 + + F_NAME DM_TEXT + CSET_ID 21 + COLL_ID 10 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL ES_ES + DOMAIN_COLL_NAME ES_ES + COLL_ATTR 1 + COLL_SPEC DISABLE-COMPRESSIONS=1;SPECIALS-FIRST=1 + + + + F_NAME DM_BLOB + CSET_ID 21 + COLL_ID 17 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL ES_ES_CI_AI + DOMAIN_COLL_NAME ES_ES_CI_AI + COLL_ATTR 7 + COLL_SPEC DISABLE-COMPRESSIONS=1;SPECIALS-FIRST=1 + + F_NAME DM_NAME + CSET_ID 21 + COLL_ID 17 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL ES_ES_CI_AI + DOMAIN_COLL_NAME ES_ES_CI_AI + COLL_ATTR 7 + COLL_SPEC DISABLE-COMPRESSIONS=1;SPECIALS-FIRST=1 + + F_NAME DM_TEXT + CSET_ID 21 + COLL_ID 17 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL ES_ES_CI_AI + DOMAIN_COLL_NAME ES_ES_CI_AI + COLL_ATTR 7 + COLL_SPEC DISABLE-COMPRESSIONS=1;SPECIALS-FIRST=1 + + + + F_NAME DM_BLOB + CSET_ID 21 + COLL_ID 3 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL FI_FI + DOMAIN_COLL_NAME FI_FI + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 21 + COLL_ID 3 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL FI_FI + DOMAIN_COLL_NAME FI_FI + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 21 + COLL_ID 3 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL FI_FI + DOMAIN_COLL_NAME FI_FI + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 21 + COLL_ID 5 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL FR_CA + DOMAIN_COLL_NAME FR_CA + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 21 + COLL_ID 5 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL FR_CA + DOMAIN_COLL_NAME FR_CA + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 21 + COLL_ID 5 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL FR_CA + DOMAIN_COLL_NAME FR_CA + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 21 + COLL_ID 4 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL FR_FR + DOMAIN_COLL_NAME FR_FR + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 21 + COLL_ID 4 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL FR_FR + DOMAIN_COLL_NAME FR_FR + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 21 + COLL_ID 4 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL FR_FR + DOMAIN_COLL_NAME FR_FR + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 21 + COLL_ID 7 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL IS_IS + DOMAIN_COLL_NAME IS_IS + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 21 + COLL_ID 7 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL IS_IS + DOMAIN_COLL_NAME IS_IS + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 21 + COLL_ID 7 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL IS_IS + DOMAIN_COLL_NAME IS_IS + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 21 + COLL_ID 8 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL IT_IT + DOMAIN_COLL_NAME IT_IT + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 21 + COLL_ID 8 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL IT_IT + DOMAIN_COLL_NAME IT_IT + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 21 + COLL_ID 8 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL IT_IT + DOMAIN_COLL_NAME IT_IT + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 21 + COLL_ID 9 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL NO_NO + DOMAIN_COLL_NAME NO_NO + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 21 + COLL_ID 9 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL NO_NO + DOMAIN_COLL_NAME NO_NO + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 21 + COLL_ID 9 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL NO_NO + DOMAIN_COLL_NAME NO_NO + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 21 + COLL_ID 11 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL SV_SV + DOMAIN_COLL_NAME SV_SV + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 21 + COLL_ID 11 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL SV_SV + DOMAIN_COLL_NAME SV_SV + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 21 + COLL_ID 11 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL SV_SV + DOMAIN_COLL_NAME SV_SV + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 21 + COLL_ID 16 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL PT_BR + DOMAIN_COLL_NAME PT_BR + COLL_ATTR 7 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 21 + COLL_ID 16 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL PT_BR + DOMAIN_COLL_NAME PT_BR + COLL_ATTR 7 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 21 + COLL_ID 16 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL PT_BR + DOMAIN_COLL_NAME PT_BR + COLL_ATTR 7 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 21 + COLL_ID 15 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL PT_PT + DOMAIN_COLL_NAME PT_PT + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 21 + COLL_ID 15 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL PT_PT + DOMAIN_COLL_NAME PT_PT + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 21 + COLL_ID 15 + CSET_NAME ISO8859_1 + CSET_DEFAULT_COLL PT_PT + DOMAIN_COLL_NAME PT_PT + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 22 + COLL_ID 0 + CSET_NAME ISO8859_2 + CSET_DEFAULT_COLL ISO8859_2 + DOMAIN_COLL_NAME ISO8859_2 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 22 + COLL_ID 0 + CSET_NAME ISO8859_2 + CSET_DEFAULT_COLL ISO8859_2 + DOMAIN_COLL_NAME ISO8859_2 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 22 + COLL_ID 0 + CSET_NAME ISO8859_2 + CSET_DEFAULT_COLL ISO8859_2 + DOMAIN_COLL_NAME ISO8859_2 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 22 + COLL_ID 126 + CSET_NAME ISO8859_2 + CSET_DEFAULT_COLL ISO8859_2_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 22 + COLL_ID 126 + CSET_NAME ISO8859_2 + CSET_DEFAULT_COLL ISO8859_2_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 22 + COLL_ID 125 + CSET_NAME ISO8859_2 + CSET_DEFAULT_COLL ISO8859_2_UNICODE + DOMAIN_COLL_NAME ISO8859_2_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 22 + COLL_ID 1 + CSET_NAME ISO8859_2 + CSET_DEFAULT_COLL CS_CZ + DOMAIN_COLL_NAME CS_CZ + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 22 + COLL_ID 1 + CSET_NAME ISO8859_2 + CSET_DEFAULT_COLL CS_CZ + DOMAIN_COLL_NAME CS_CZ + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 22 + COLL_ID 1 + CSET_NAME ISO8859_2 + CSET_DEFAULT_COLL CS_CZ + DOMAIN_COLL_NAME CS_CZ + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 22 + COLL_ID 2 + CSET_NAME ISO8859_2 + CSET_DEFAULT_COLL ISO_HUN + DOMAIN_COLL_NAME ISO_HUN + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 22 + COLL_ID 2 + CSET_NAME ISO8859_2 + CSET_DEFAULT_COLL ISO_HUN + DOMAIN_COLL_NAME ISO_HUN + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 22 + COLL_ID 2 + CSET_NAME ISO8859_2 + CSET_DEFAULT_COLL ISO_HUN + DOMAIN_COLL_NAME ISO_HUN + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 22 + COLL_ID 3 + CSET_NAME ISO8859_2 + CSET_DEFAULT_COLL ISO_PLK + DOMAIN_COLL_NAME ISO_PLK + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 22 + COLL_ID 3 + CSET_NAME ISO8859_2 + CSET_DEFAULT_COLL ISO_PLK + DOMAIN_COLL_NAME ISO_PLK + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 22 + COLL_ID 3 + CSET_NAME ISO8859_2 + CSET_DEFAULT_COLL ISO_PLK + DOMAIN_COLL_NAME ISO_PLK + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 23 + COLL_ID 0 + CSET_NAME ISO8859_3 + CSET_DEFAULT_COLL ISO8859_3 + DOMAIN_COLL_NAME ISO8859_3 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 23 + COLL_ID 0 + CSET_NAME ISO8859_3 + CSET_DEFAULT_COLL ISO8859_3 + DOMAIN_COLL_NAME ISO8859_3 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 23 + COLL_ID 0 + CSET_NAME ISO8859_3 + CSET_DEFAULT_COLL ISO8859_3 + DOMAIN_COLL_NAME ISO8859_3 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 23 + COLL_ID 126 + CSET_NAME ISO8859_3 + CSET_DEFAULT_COLL ISO8859_3_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 23 + COLL_ID 126 + CSET_NAME ISO8859_3 + CSET_DEFAULT_COLL ISO8859_3_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 23 + COLL_ID 125 + CSET_NAME ISO8859_3 + CSET_DEFAULT_COLL ISO8859_3_UNICODE + DOMAIN_COLL_NAME ISO8859_3_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 34 + COLL_ID 0 + CSET_NAME ISO8859_4 + CSET_DEFAULT_COLL ISO8859_4 + DOMAIN_COLL_NAME ISO8859_4 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 34 + COLL_ID 0 + CSET_NAME ISO8859_4 + CSET_DEFAULT_COLL ISO8859_4 + DOMAIN_COLL_NAME ISO8859_4 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 34 + COLL_ID 0 + CSET_NAME ISO8859_4 + CSET_DEFAULT_COLL ISO8859_4 + DOMAIN_COLL_NAME ISO8859_4 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 34 + COLL_ID 126 + CSET_NAME ISO8859_4 + CSET_DEFAULT_COLL ISO8859_4_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 34 + COLL_ID 126 + CSET_NAME ISO8859_4 + CSET_DEFAULT_COLL ISO8859_4_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 34 + COLL_ID 125 + CSET_NAME ISO8859_4 + CSET_DEFAULT_COLL ISO8859_4_UNICODE + DOMAIN_COLL_NAME ISO8859_4_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 35 + COLL_ID 0 + CSET_NAME ISO8859_5 + CSET_DEFAULT_COLL ISO8859_5 + DOMAIN_COLL_NAME ISO8859_5 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 35 + COLL_ID 0 + CSET_NAME ISO8859_5 + CSET_DEFAULT_COLL ISO8859_5 + DOMAIN_COLL_NAME ISO8859_5 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 35 + COLL_ID 0 + CSET_NAME ISO8859_5 + CSET_DEFAULT_COLL ISO8859_5 + DOMAIN_COLL_NAME ISO8859_5 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 35 + COLL_ID 126 + CSET_NAME ISO8859_5 + CSET_DEFAULT_COLL ISO8859_5_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 35 + COLL_ID 126 + CSET_NAME ISO8859_5 + CSET_DEFAULT_COLL ISO8859_5_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 35 + COLL_ID 125 + CSET_NAME ISO8859_5 + CSET_DEFAULT_COLL ISO8859_5_UNICODE + DOMAIN_COLL_NAME ISO8859_5_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 36 + COLL_ID 0 + CSET_NAME ISO8859_6 + CSET_DEFAULT_COLL ISO8859_6 + DOMAIN_COLL_NAME ISO8859_6 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 36 + COLL_ID 0 + CSET_NAME ISO8859_6 + CSET_DEFAULT_COLL ISO8859_6 + DOMAIN_COLL_NAME ISO8859_6 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 36 + COLL_ID 0 + CSET_NAME ISO8859_6 + CSET_DEFAULT_COLL ISO8859_6 + DOMAIN_COLL_NAME ISO8859_6 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 36 + COLL_ID 126 + CSET_NAME ISO8859_6 + CSET_DEFAULT_COLL ISO8859_6_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 36 + COLL_ID 126 + CSET_NAME ISO8859_6 + CSET_DEFAULT_COLL ISO8859_6_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 36 + COLL_ID 125 + CSET_NAME ISO8859_6 + CSET_DEFAULT_COLL ISO8859_6_UNICODE + DOMAIN_COLL_NAME ISO8859_6_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 37 + COLL_ID 0 + CSET_NAME ISO8859_7 + CSET_DEFAULT_COLL ISO8859_7 + DOMAIN_COLL_NAME ISO8859_7 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 37 + COLL_ID 0 + CSET_NAME ISO8859_7 + CSET_DEFAULT_COLL ISO8859_7 + DOMAIN_COLL_NAME ISO8859_7 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 37 + COLL_ID 0 + CSET_NAME ISO8859_7 + CSET_DEFAULT_COLL ISO8859_7 + DOMAIN_COLL_NAME ISO8859_7 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 37 + COLL_ID 126 + CSET_NAME ISO8859_7 + CSET_DEFAULT_COLL ISO8859_7_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 37 + COLL_ID 126 + CSET_NAME ISO8859_7 + CSET_DEFAULT_COLL ISO8859_7_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 37 + COLL_ID 125 + CSET_NAME ISO8859_7 + CSET_DEFAULT_COLL ISO8859_7_UNICODE + DOMAIN_COLL_NAME ISO8859_7_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 38 + COLL_ID 0 + CSET_NAME ISO8859_8 + CSET_DEFAULT_COLL ISO8859_8 + DOMAIN_COLL_NAME ISO8859_8 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 38 + COLL_ID 0 + CSET_NAME ISO8859_8 + CSET_DEFAULT_COLL ISO8859_8 + DOMAIN_COLL_NAME ISO8859_8 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 38 + COLL_ID 0 + CSET_NAME ISO8859_8 + CSET_DEFAULT_COLL ISO8859_8 + DOMAIN_COLL_NAME ISO8859_8 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 38 + COLL_ID 126 + CSET_NAME ISO8859_8 + CSET_DEFAULT_COLL ISO8859_8_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 38 + COLL_ID 126 + CSET_NAME ISO8859_8 + CSET_DEFAULT_COLL ISO8859_8_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 38 + COLL_ID 125 + CSET_NAME ISO8859_8 + CSET_DEFAULT_COLL ISO8859_8_UNICODE + DOMAIN_COLL_NAME ISO8859_8_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 39 + COLL_ID 0 + CSET_NAME ISO8859_9 + CSET_DEFAULT_COLL ISO8859_9 + DOMAIN_COLL_NAME ISO8859_9 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 39 + COLL_ID 0 + CSET_NAME ISO8859_9 + CSET_DEFAULT_COLL ISO8859_9 + DOMAIN_COLL_NAME ISO8859_9 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 39 + COLL_ID 0 + CSET_NAME ISO8859_9 + CSET_DEFAULT_COLL ISO8859_9 + DOMAIN_COLL_NAME ISO8859_9 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 39 + COLL_ID 126 + CSET_NAME ISO8859_9 + CSET_DEFAULT_COLL ISO8859_9_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 39 + COLL_ID 126 + CSET_NAME ISO8859_9 + CSET_DEFAULT_COLL ISO8859_9_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 39 + COLL_ID 125 + CSET_NAME ISO8859_9 + CSET_DEFAULT_COLL ISO8859_9_UNICODE + DOMAIN_COLL_NAME ISO8859_9_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 40 + COLL_ID 0 + CSET_NAME ISO8859_13 + CSET_DEFAULT_COLL ISO8859_13 + DOMAIN_COLL_NAME ISO8859_13 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 40 + COLL_ID 0 + CSET_NAME ISO8859_13 + CSET_DEFAULT_COLL ISO8859_13 + DOMAIN_COLL_NAME ISO8859_13 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 40 + COLL_ID 0 + CSET_NAME ISO8859_13 + CSET_DEFAULT_COLL ISO8859_13 + DOMAIN_COLL_NAME ISO8859_13 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 40 + COLL_ID 126 + CSET_NAME ISO8859_13 + CSET_DEFAULT_COLL ISO8859_13_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 40 + COLL_ID 126 + CSET_NAME ISO8859_13 + CSET_DEFAULT_COLL ISO8859_13_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 40 + COLL_ID 125 + CSET_NAME ISO8859_13 + CSET_DEFAULT_COLL ISO8859_13_UNICODE + DOMAIN_COLL_NAME ISO8859_13_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 45 + COLL_ID 0 + CSET_NAME DOS852 + CSET_DEFAULT_COLL DOS852 + DOMAIN_COLL_NAME DOS852 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 45 + COLL_ID 0 + CSET_NAME DOS852 + CSET_DEFAULT_COLL DOS852 + DOMAIN_COLL_NAME DOS852 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 45 + COLL_ID 0 + CSET_NAME DOS852 + CSET_DEFAULT_COLL DOS852 + DOMAIN_COLL_NAME DOS852 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 45 + COLL_ID 126 + CSET_NAME DOS852 + CSET_DEFAULT_COLL DOS852_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 45 + COLL_ID 126 + CSET_NAME DOS852 + CSET_DEFAULT_COLL DOS852_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 45 + COLL_ID 125 + CSET_NAME DOS852 + CSET_DEFAULT_COLL DOS852_UNICODE + DOMAIN_COLL_NAME DOS852_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 45 + COLL_ID 1 + CSET_NAME DOS852 + CSET_DEFAULT_COLL DB_CSY + DOMAIN_COLL_NAME DB_CSY + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 45 + COLL_ID 1 + CSET_NAME DOS852 + CSET_DEFAULT_COLL DB_CSY + DOMAIN_COLL_NAME DB_CSY + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 45 + COLL_ID 1 + CSET_NAME DOS852 + CSET_DEFAULT_COLL DB_CSY + DOMAIN_COLL_NAME DB_CSY + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 45 + COLL_ID 2 + CSET_NAME DOS852 + CSET_DEFAULT_COLL DB_PLK + DOMAIN_COLL_NAME DB_PLK + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 45 + COLL_ID 2 + CSET_NAME DOS852 + CSET_DEFAULT_COLL DB_PLK + DOMAIN_COLL_NAME DB_PLK + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 45 + COLL_ID 2 + CSET_NAME DOS852 + CSET_DEFAULT_COLL DB_PLK + DOMAIN_COLL_NAME DB_PLK + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 45 + COLL_ID 4 + CSET_NAME DOS852 + CSET_DEFAULT_COLL DB_SLO + DOMAIN_COLL_NAME DB_SLO + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 45 + COLL_ID 4 + CSET_NAME DOS852 + CSET_DEFAULT_COLL DB_SLO + DOMAIN_COLL_NAME DB_SLO + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 45 + COLL_ID 4 + CSET_NAME DOS852 + CSET_DEFAULT_COLL DB_SLO + DOMAIN_COLL_NAME DB_SLO + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 45 + COLL_ID 5 + CSET_NAME DOS852 + CSET_DEFAULT_COLL PDOX_CSY + DOMAIN_COLL_NAME PDOX_CSY + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 45 + COLL_ID 5 + CSET_NAME DOS852 + CSET_DEFAULT_COLL PDOX_CSY + DOMAIN_COLL_NAME PDOX_CSY + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 45 + COLL_ID 5 + CSET_NAME DOS852 + CSET_DEFAULT_COLL PDOX_CSY + DOMAIN_COLL_NAME PDOX_CSY + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 45 + COLL_ID 7 + CSET_NAME DOS852 + CSET_DEFAULT_COLL PDOX_HUN + DOMAIN_COLL_NAME PDOX_HUN + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 45 + COLL_ID 7 + CSET_NAME DOS852 + CSET_DEFAULT_COLL PDOX_HUN + DOMAIN_COLL_NAME PDOX_HUN + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 45 + COLL_ID 7 + CSET_NAME DOS852 + CSET_DEFAULT_COLL PDOX_HUN + DOMAIN_COLL_NAME PDOX_HUN + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 45 + COLL_ID 6 + CSET_NAME DOS852 + CSET_DEFAULT_COLL PDOX_PLK + DOMAIN_COLL_NAME PDOX_PLK + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 45 + COLL_ID 6 + CSET_NAME DOS852 + CSET_DEFAULT_COLL PDOX_PLK + DOMAIN_COLL_NAME PDOX_PLK + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 45 + COLL_ID 6 + CSET_NAME DOS852 + CSET_DEFAULT_COLL PDOX_PLK + DOMAIN_COLL_NAME PDOX_PLK + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 45 + COLL_ID 8 + CSET_NAME DOS852 + CSET_DEFAULT_COLL PDOX_SLO + DOMAIN_COLL_NAME PDOX_SLO + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 45 + COLL_ID 8 + CSET_NAME DOS852 + CSET_DEFAULT_COLL PDOX_SLO + DOMAIN_COLL_NAME PDOX_SLO + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 45 + COLL_ID 8 + CSET_NAME DOS852 + CSET_DEFAULT_COLL PDOX_SLO + DOMAIN_COLL_NAME PDOX_SLO + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 46 + COLL_ID 0 + CSET_NAME DOS857 + CSET_DEFAULT_COLL DOS857 + DOMAIN_COLL_NAME DOS857 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 46 + COLL_ID 0 + CSET_NAME DOS857 + CSET_DEFAULT_COLL DOS857 + DOMAIN_COLL_NAME DOS857 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 46 + COLL_ID 0 + CSET_NAME DOS857 + CSET_DEFAULT_COLL DOS857 + DOMAIN_COLL_NAME DOS857 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 46 + COLL_ID 126 + CSET_NAME DOS857 + CSET_DEFAULT_COLL DOS857_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 46 + COLL_ID 126 + CSET_NAME DOS857 + CSET_DEFAULT_COLL DOS857_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 46 + COLL_ID 125 + CSET_NAME DOS857 + CSET_DEFAULT_COLL DOS857_UNICODE + DOMAIN_COLL_NAME DOS857_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 46 + COLL_ID 1 + CSET_NAME DOS857 + CSET_DEFAULT_COLL DB_TRK + DOMAIN_COLL_NAME DB_TRK + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 46 + COLL_ID 1 + CSET_NAME DOS857 + CSET_DEFAULT_COLL DB_TRK + DOMAIN_COLL_NAME DB_TRK + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 46 + COLL_ID 1 + CSET_NAME DOS857 + CSET_DEFAULT_COLL DB_TRK + DOMAIN_COLL_NAME DB_TRK + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 13 + COLL_ID 0 + CSET_NAME DOS860 + CSET_DEFAULT_COLL DOS860 + DOMAIN_COLL_NAME DOS860 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 13 + COLL_ID 0 + CSET_NAME DOS860 + CSET_DEFAULT_COLL DOS860 + DOMAIN_COLL_NAME DOS860 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 13 + COLL_ID 0 + CSET_NAME DOS860 + CSET_DEFAULT_COLL DOS860 + DOMAIN_COLL_NAME DOS860 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 13 + COLL_ID 126 + CSET_NAME DOS860 + CSET_DEFAULT_COLL DOS860_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 13 + COLL_ID 126 + CSET_NAME DOS860 + CSET_DEFAULT_COLL DOS860_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 13 + COLL_ID 125 + CSET_NAME DOS860 + CSET_DEFAULT_COLL DOS860_UNICODE + DOMAIN_COLL_NAME DOS860_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 13 + COLL_ID 1 + CSET_NAME DOS860 + CSET_DEFAULT_COLL DB_PTG860 + DOMAIN_COLL_NAME DB_PTG860 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 13 + COLL_ID 1 + CSET_NAME DOS860 + CSET_DEFAULT_COLL DB_PTG860 + DOMAIN_COLL_NAME DB_PTG860 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 13 + COLL_ID 1 + CSET_NAME DOS860 + CSET_DEFAULT_COLL DB_PTG860 + DOMAIN_COLL_NAME DB_PTG860 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 47 + COLL_ID 0 + CSET_NAME DOS861 + CSET_DEFAULT_COLL DOS861 + DOMAIN_COLL_NAME DOS861 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 47 + COLL_ID 0 + CSET_NAME DOS861 + CSET_DEFAULT_COLL DOS861 + DOMAIN_COLL_NAME DOS861 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 47 + COLL_ID 0 + CSET_NAME DOS861 + CSET_DEFAULT_COLL DOS861 + DOMAIN_COLL_NAME DOS861 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 47 + COLL_ID 126 + CSET_NAME DOS861 + CSET_DEFAULT_COLL DOS861_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 47 + COLL_ID 126 + CSET_NAME DOS861 + CSET_DEFAULT_COLL DOS861_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 47 + COLL_ID 125 + CSET_NAME DOS861 + CSET_DEFAULT_COLL DOS861_UNICODE + DOMAIN_COLL_NAME DOS861_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 47 + COLL_ID 1 + CSET_NAME DOS861 + CSET_DEFAULT_COLL PDOX_ISL + DOMAIN_COLL_NAME PDOX_ISL + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 47 + COLL_ID 1 + CSET_NAME DOS861 + CSET_DEFAULT_COLL PDOX_ISL + DOMAIN_COLL_NAME PDOX_ISL + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 47 + COLL_ID 1 + CSET_NAME DOS861 + CSET_DEFAULT_COLL PDOX_ISL + DOMAIN_COLL_NAME PDOX_ISL + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 14 + COLL_ID 0 + CSET_NAME DOS863 + CSET_DEFAULT_COLL DOS863 + DOMAIN_COLL_NAME DOS863 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 14 + COLL_ID 0 + CSET_NAME DOS863 + CSET_DEFAULT_COLL DOS863 + DOMAIN_COLL_NAME DOS863 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 14 + COLL_ID 0 + CSET_NAME DOS863 + CSET_DEFAULT_COLL DOS863 + DOMAIN_COLL_NAME DOS863 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 14 + COLL_ID 126 + CSET_NAME DOS863 + CSET_DEFAULT_COLL DOS863_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 14 + COLL_ID 126 + CSET_NAME DOS863 + CSET_DEFAULT_COLL DOS863_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 14 + COLL_ID 125 + CSET_NAME DOS863 + CSET_DEFAULT_COLL DOS863_UNICODE + DOMAIN_COLL_NAME DOS863_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 14 + COLL_ID 1 + CSET_NAME DOS863 + CSET_DEFAULT_COLL DB_FRC863 + DOMAIN_COLL_NAME DB_FRC863 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 14 + COLL_ID 1 + CSET_NAME DOS863 + CSET_DEFAULT_COLL DB_FRC863 + DOMAIN_COLL_NAME DB_FRC863 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 14 + COLL_ID 1 + CSET_NAME DOS863 + CSET_DEFAULT_COLL DB_FRC863 + DOMAIN_COLL_NAME DB_FRC863 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 50 + COLL_ID 0 + CSET_NAME CYRL + CSET_DEFAULT_COLL CYRL + DOMAIN_COLL_NAME CYRL + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 50 + COLL_ID 0 + CSET_NAME CYRL + CSET_DEFAULT_COLL CYRL + DOMAIN_COLL_NAME CYRL + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 50 + COLL_ID 0 + CSET_NAME CYRL + CSET_DEFAULT_COLL CYRL + DOMAIN_COLL_NAME CYRL + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 50 + COLL_ID 126 + CSET_NAME CYRL + CSET_DEFAULT_COLL CYRL_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 50 + COLL_ID 126 + CSET_NAME CYRL + CSET_DEFAULT_COLL CYRL_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 50 + COLL_ID 125 + CSET_NAME CYRL + CSET_DEFAULT_COLL CYRL_UNICODE + DOMAIN_COLL_NAME CYRL_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 50 + COLL_ID 1 + CSET_NAME CYRL + CSET_DEFAULT_COLL DB_RUS + DOMAIN_COLL_NAME DB_RUS + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 50 + COLL_ID 1 + CSET_NAME CYRL + CSET_DEFAULT_COLL DB_RUS + DOMAIN_COLL_NAME DB_RUS + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 50 + COLL_ID 1 + CSET_NAME CYRL + CSET_DEFAULT_COLL DB_RUS + DOMAIN_COLL_NAME DB_RUS + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 50 + COLL_ID 2 + CSET_NAME CYRL + CSET_DEFAULT_COLL PDOX_CYRL + DOMAIN_COLL_NAME PDOX_CYRL + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 50 + COLL_ID 2 + CSET_NAME CYRL + CSET_DEFAULT_COLL PDOX_CYRL + DOMAIN_COLL_NAME PDOX_CYRL + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 50 + COLL_ID 2 + CSET_NAME CYRL + CSET_DEFAULT_COLL PDOX_CYRL + DOMAIN_COLL_NAME PDOX_CYRL + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 9 + COLL_ID 0 + CSET_NAME DOS737 + CSET_DEFAULT_COLL DOS737 + DOMAIN_COLL_NAME DOS737 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 9 + COLL_ID 0 + CSET_NAME DOS737 + CSET_DEFAULT_COLL DOS737 + DOMAIN_COLL_NAME DOS737 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 9 + COLL_ID 0 + CSET_NAME DOS737 + CSET_DEFAULT_COLL DOS737 + DOMAIN_COLL_NAME DOS737 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 9 + COLL_ID 126 + CSET_NAME DOS737 + CSET_DEFAULT_COLL DOS737_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 9 + COLL_ID 126 + CSET_NAME DOS737 + CSET_DEFAULT_COLL DOS737_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 9 + COLL_ID 125 + CSET_NAME DOS737 + CSET_DEFAULT_COLL DOS737_UNICODE + DOMAIN_COLL_NAME DOS737_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 15 + COLL_ID 0 + CSET_NAME DOS775 + CSET_DEFAULT_COLL DOS775 + DOMAIN_COLL_NAME DOS775 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 15 + COLL_ID 0 + CSET_NAME DOS775 + CSET_DEFAULT_COLL DOS775 + DOMAIN_COLL_NAME DOS775 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 15 + COLL_ID 0 + CSET_NAME DOS775 + CSET_DEFAULT_COLL DOS775 + DOMAIN_COLL_NAME DOS775 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 15 + COLL_ID 126 + CSET_NAME DOS775 + CSET_DEFAULT_COLL DOS775_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 15 + COLL_ID 126 + CSET_NAME DOS775 + CSET_DEFAULT_COLL DOS775_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 15 + COLL_ID 125 + CSET_NAME DOS775 + CSET_DEFAULT_COLL DOS775_UNICODE + DOMAIN_COLL_NAME DOS775_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 16 + COLL_ID 0 + CSET_NAME DOS858 + CSET_DEFAULT_COLL DOS858 + DOMAIN_COLL_NAME DOS858 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 16 + COLL_ID 0 + CSET_NAME DOS858 + CSET_DEFAULT_COLL DOS858 + DOMAIN_COLL_NAME DOS858 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 16 + COLL_ID 0 + CSET_NAME DOS858 + CSET_DEFAULT_COLL DOS858 + DOMAIN_COLL_NAME DOS858 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 16 + COLL_ID 126 + CSET_NAME DOS858 + CSET_DEFAULT_COLL DOS858_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 16 + COLL_ID 126 + CSET_NAME DOS858 + CSET_DEFAULT_COLL DOS858_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 16 + COLL_ID 125 + CSET_NAME DOS858 + CSET_DEFAULT_COLL DOS858_UNICODE + DOMAIN_COLL_NAME DOS858_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 17 + COLL_ID 0 + CSET_NAME DOS862 + CSET_DEFAULT_COLL DOS862 + DOMAIN_COLL_NAME DOS862 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 17 + COLL_ID 0 + CSET_NAME DOS862 + CSET_DEFAULT_COLL DOS862 + DOMAIN_COLL_NAME DOS862 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 17 + COLL_ID 0 + CSET_NAME DOS862 + CSET_DEFAULT_COLL DOS862 + DOMAIN_COLL_NAME DOS862 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 17 + COLL_ID 126 + CSET_NAME DOS862 + CSET_DEFAULT_COLL DOS862_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 17 + COLL_ID 126 + CSET_NAME DOS862 + CSET_DEFAULT_COLL DOS862_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 17 + COLL_ID 125 + CSET_NAME DOS862 + CSET_DEFAULT_COLL DOS862_UNICODE + DOMAIN_COLL_NAME DOS862_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 18 + COLL_ID 0 + CSET_NAME DOS864 + CSET_DEFAULT_COLL DOS864 + DOMAIN_COLL_NAME DOS864 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 18 + COLL_ID 0 + CSET_NAME DOS864 + CSET_DEFAULT_COLL DOS864 + DOMAIN_COLL_NAME DOS864 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 18 + COLL_ID 0 + CSET_NAME DOS864 + CSET_DEFAULT_COLL DOS864 + DOMAIN_COLL_NAME DOS864 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 18 + COLL_ID 126 + CSET_NAME DOS864 + CSET_DEFAULT_COLL DOS864_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 18 + COLL_ID 126 + CSET_NAME DOS864 + CSET_DEFAULT_COLL DOS864_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 18 + COLL_ID 125 + CSET_NAME DOS864 + CSET_DEFAULT_COLL DOS864_UNICODE + DOMAIN_COLL_NAME DOS864_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 48 + COLL_ID 0 + CSET_NAME DOS866 + CSET_DEFAULT_COLL DOS866 + DOMAIN_COLL_NAME DOS866 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 48 + COLL_ID 0 + CSET_NAME DOS866 + CSET_DEFAULT_COLL DOS866 + DOMAIN_COLL_NAME DOS866 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 48 + COLL_ID 0 + CSET_NAME DOS866 + CSET_DEFAULT_COLL DOS866 + DOMAIN_COLL_NAME DOS866 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 48 + COLL_ID 126 + CSET_NAME DOS866 + CSET_DEFAULT_COLL DOS866_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 48 + COLL_ID 126 + CSET_NAME DOS866 + CSET_DEFAULT_COLL DOS866_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 48 + COLL_ID 125 + CSET_NAME DOS866 + CSET_DEFAULT_COLL DOS866_UNICODE + DOMAIN_COLL_NAME DOS866_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 49 + COLL_ID 0 + CSET_NAME DOS869 + CSET_DEFAULT_COLL DOS869 + DOMAIN_COLL_NAME DOS869 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 49 + COLL_ID 0 + CSET_NAME DOS869 + CSET_DEFAULT_COLL DOS869 + DOMAIN_COLL_NAME DOS869 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 49 + COLL_ID 0 + CSET_NAME DOS869 + CSET_DEFAULT_COLL DOS869 + DOMAIN_COLL_NAME DOS869 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 49 + COLL_ID 126 + CSET_NAME DOS869 + CSET_DEFAULT_COLL DOS869_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 49 + COLL_ID 126 + CSET_NAME DOS869 + CSET_DEFAULT_COLL DOS869_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 49 + COLL_ID 125 + CSET_NAME DOS869 + CSET_DEFAULT_COLL DOS869_UNICODE + DOMAIN_COLL_NAME DOS869_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 51 + COLL_ID 0 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL WIN1250 + DOMAIN_COLL_NAME WIN1250 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 51 + COLL_ID 0 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL WIN1250 + DOMAIN_COLL_NAME WIN1250 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 51 + COLL_ID 0 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL WIN1250 + DOMAIN_COLL_NAME WIN1250 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 51 + COLL_ID 126 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL WIN1250_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 51 + COLL_ID 126 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL WIN1250_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 51 + COLL_ID 125 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL WIN1250_UNICODE + DOMAIN_COLL_NAME WIN1250_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 51 + COLL_ID 1 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL PXW_CSY + DOMAIN_COLL_NAME PXW_CSY + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 51 + COLL_ID 1 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL PXW_CSY + DOMAIN_COLL_NAME PXW_CSY + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 51 + COLL_ID 1 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL PXW_CSY + DOMAIN_COLL_NAME PXW_CSY + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 51 + COLL_ID 5 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL PXW_HUN + DOMAIN_COLL_NAME PXW_HUN + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 51 + COLL_ID 5 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL PXW_HUN + DOMAIN_COLL_NAME PXW_HUN + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 51 + COLL_ID 5 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL PXW_HUN + DOMAIN_COLL_NAME PXW_HUN + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 51 + COLL_ID 2 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL PXW_HUNDC + DOMAIN_COLL_NAME PXW_HUNDC + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 51 + COLL_ID 2 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL PXW_HUNDC + DOMAIN_COLL_NAME PXW_HUNDC + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 51 + COLL_ID 2 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL PXW_HUNDC + DOMAIN_COLL_NAME PXW_HUNDC + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 51 + COLL_ID 3 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL PXW_PLK + DOMAIN_COLL_NAME PXW_PLK + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 51 + COLL_ID 3 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL PXW_PLK + DOMAIN_COLL_NAME PXW_PLK + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 51 + COLL_ID 3 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL PXW_PLK + DOMAIN_COLL_NAME PXW_PLK + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 51 + COLL_ID 4 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL PXW_SLOV + DOMAIN_COLL_NAME PXW_SLOV + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 51 + COLL_ID 4 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL PXW_SLOV + DOMAIN_COLL_NAME PXW_SLOV + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 51 + COLL_ID 4 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL PXW_SLOV + DOMAIN_COLL_NAME PXW_SLOV + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 51 + COLL_ID 6 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL BS_BA + DOMAIN_COLL_NAME BS_BA + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 51 + COLL_ID 6 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL BS_BA + DOMAIN_COLL_NAME BS_BA + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 51 + COLL_ID 6 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL BS_BA + DOMAIN_COLL_NAME BS_BA + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 51 + COLL_ID 7 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL WIN_CZ + DOMAIN_COLL_NAME WIN_CZ + COLL_ATTR 3 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 51 + COLL_ID 7 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL WIN_CZ + DOMAIN_COLL_NAME WIN_CZ + COLL_ATTR 3 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 51 + COLL_ID 7 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL WIN_CZ + DOMAIN_COLL_NAME WIN_CZ + COLL_ATTR 3 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 51 + COLL_ID 8 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL WIN_CZ_CI_AI + DOMAIN_COLL_NAME WIN_CZ_CI_AI + COLL_ATTR 7 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 51 + COLL_ID 8 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL WIN_CZ_CI_AI + DOMAIN_COLL_NAME WIN_CZ_CI_AI + COLL_ATTR 7 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 51 + COLL_ID 8 + CSET_NAME WIN1250 + CSET_DEFAULT_COLL WIN_CZ_CI_AI + DOMAIN_COLL_NAME WIN_CZ_CI_AI + COLL_ATTR 7 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 52 + COLL_ID 0 + CSET_NAME WIN1251 + CSET_DEFAULT_COLL WIN1251 + DOMAIN_COLL_NAME WIN1251 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 52 + COLL_ID 0 + CSET_NAME WIN1251 + CSET_DEFAULT_COLL WIN1251 + DOMAIN_COLL_NAME WIN1251 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 52 + COLL_ID 0 + CSET_NAME WIN1251 + CSET_DEFAULT_COLL WIN1251 + DOMAIN_COLL_NAME WIN1251 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 52 + COLL_ID 126 + CSET_NAME WIN1251 + CSET_DEFAULT_COLL WIN1251_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 52 + COLL_ID 126 + CSET_NAME WIN1251 + CSET_DEFAULT_COLL WIN1251_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 52 + COLL_ID 125 + CSET_NAME WIN1251 + CSET_DEFAULT_COLL WIN1251_UNICODE + DOMAIN_COLL_NAME WIN1251_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 52 + COLL_ID 1 + CSET_NAME WIN1251 + CSET_DEFAULT_COLL PXW_CYRL + DOMAIN_COLL_NAME PXW_CYRL + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 52 + COLL_ID 1 + CSET_NAME WIN1251 + CSET_DEFAULT_COLL PXW_CYRL + DOMAIN_COLL_NAME PXW_CYRL + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 52 + COLL_ID 1 + CSET_NAME WIN1251 + CSET_DEFAULT_COLL PXW_CYRL + DOMAIN_COLL_NAME PXW_CYRL + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 52 + COLL_ID 2 + CSET_NAME WIN1251 + CSET_DEFAULT_COLL WIN1251_UA + DOMAIN_COLL_NAME WIN1251_UA + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 52 + COLL_ID 2 + CSET_NAME WIN1251 + CSET_DEFAULT_COLL WIN1251_UA + DOMAIN_COLL_NAME WIN1251_UA + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 52 + COLL_ID 2 + CSET_NAME WIN1251 + CSET_DEFAULT_COLL WIN1251_UA + DOMAIN_COLL_NAME WIN1251_UA + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 53 + COLL_ID 0 + CSET_NAME WIN1252 + CSET_DEFAULT_COLL WIN1252 + DOMAIN_COLL_NAME WIN1252 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 53 + COLL_ID 0 + CSET_NAME WIN1252 + CSET_DEFAULT_COLL WIN1252 + DOMAIN_COLL_NAME WIN1252 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 53 + COLL_ID 0 + CSET_NAME WIN1252 + CSET_DEFAULT_COLL WIN1252 + DOMAIN_COLL_NAME WIN1252 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 53 + COLL_ID 126 + CSET_NAME WIN1252 + CSET_DEFAULT_COLL WIN1252_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 53 + COLL_ID 126 + CSET_NAME WIN1252 + CSET_DEFAULT_COLL WIN1252_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 53 + COLL_ID 125 + CSET_NAME WIN1252 + CSET_DEFAULT_COLL WIN1252_UNICODE + DOMAIN_COLL_NAME WIN1252_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 53 + COLL_ID 1 + CSET_NAME WIN1252 + CSET_DEFAULT_COLL PXW_INTL + DOMAIN_COLL_NAME PXW_INTL + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 53 + COLL_ID 1 + CSET_NAME WIN1252 + CSET_DEFAULT_COLL PXW_INTL + DOMAIN_COLL_NAME PXW_INTL + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 53 + COLL_ID 1 + CSET_NAME WIN1252 + CSET_DEFAULT_COLL PXW_INTL + DOMAIN_COLL_NAME PXW_INTL + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 53 + COLL_ID 2 + CSET_NAME WIN1252 + CSET_DEFAULT_COLL PXW_INTL850 + DOMAIN_COLL_NAME PXW_INTL850 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 53 + COLL_ID 2 + CSET_NAME WIN1252 + CSET_DEFAULT_COLL PXW_INTL850 + DOMAIN_COLL_NAME PXW_INTL850 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 53 + COLL_ID 2 + CSET_NAME WIN1252 + CSET_DEFAULT_COLL PXW_INTL850 + DOMAIN_COLL_NAME PXW_INTL850 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 53 + COLL_ID 3 + CSET_NAME WIN1252 + CSET_DEFAULT_COLL PXW_NORDAN4 + DOMAIN_COLL_NAME PXW_NORDAN4 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 53 + COLL_ID 3 + CSET_NAME WIN1252 + CSET_DEFAULT_COLL PXW_NORDAN4 + DOMAIN_COLL_NAME PXW_NORDAN4 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 53 + COLL_ID 3 + CSET_NAME WIN1252 + CSET_DEFAULT_COLL PXW_NORDAN4 + DOMAIN_COLL_NAME PXW_NORDAN4 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 53 + COLL_ID 6 + CSET_NAME WIN1252 + CSET_DEFAULT_COLL WIN_PTBR + DOMAIN_COLL_NAME WIN_PTBR + COLL_ATTR 7 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 53 + COLL_ID 6 + CSET_NAME WIN1252 + CSET_DEFAULT_COLL WIN_PTBR + DOMAIN_COLL_NAME WIN_PTBR + COLL_ATTR 7 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 53 + COLL_ID 6 + CSET_NAME WIN1252 + CSET_DEFAULT_COLL WIN_PTBR + DOMAIN_COLL_NAME WIN_PTBR + COLL_ATTR 7 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 53 + COLL_ID 4 + CSET_NAME WIN1252 + CSET_DEFAULT_COLL PXW_SPAN + DOMAIN_COLL_NAME PXW_SPAN + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 53 + COLL_ID 4 + CSET_NAME WIN1252 + CSET_DEFAULT_COLL PXW_SPAN + DOMAIN_COLL_NAME PXW_SPAN + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 53 + COLL_ID 4 + CSET_NAME WIN1252 + CSET_DEFAULT_COLL PXW_SPAN + DOMAIN_COLL_NAME PXW_SPAN + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 53 + COLL_ID 5 + CSET_NAME WIN1252 + CSET_DEFAULT_COLL PXW_SWEDFIN + DOMAIN_COLL_NAME PXW_SWEDFIN + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 53 + COLL_ID 5 + CSET_NAME WIN1252 + CSET_DEFAULT_COLL PXW_SWEDFIN + DOMAIN_COLL_NAME PXW_SWEDFIN + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 53 + COLL_ID 5 + CSET_NAME WIN1252 + CSET_DEFAULT_COLL PXW_SWEDFIN + DOMAIN_COLL_NAME PXW_SWEDFIN + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 54 + COLL_ID 0 + CSET_NAME WIN1253 + CSET_DEFAULT_COLL WIN1253 + DOMAIN_COLL_NAME WIN1253 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 54 + COLL_ID 0 + CSET_NAME WIN1253 + CSET_DEFAULT_COLL WIN1253 + DOMAIN_COLL_NAME WIN1253 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 54 + COLL_ID 0 + CSET_NAME WIN1253 + CSET_DEFAULT_COLL WIN1253 + DOMAIN_COLL_NAME WIN1253 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 54 + COLL_ID 126 + CSET_NAME WIN1253 + CSET_DEFAULT_COLL WIN1253_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 54 + COLL_ID 126 + CSET_NAME WIN1253 + CSET_DEFAULT_COLL WIN1253_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 54 + COLL_ID 125 + CSET_NAME WIN1253 + CSET_DEFAULT_COLL WIN1253_UNICODE + DOMAIN_COLL_NAME WIN1253_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 54 + COLL_ID 1 + CSET_NAME WIN1253 + CSET_DEFAULT_COLL PXW_GREEK + DOMAIN_COLL_NAME PXW_GREEK + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 54 + COLL_ID 1 + CSET_NAME WIN1253 + CSET_DEFAULT_COLL PXW_GREEK + DOMAIN_COLL_NAME PXW_GREEK + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 54 + COLL_ID 1 + CSET_NAME WIN1253 + CSET_DEFAULT_COLL PXW_GREEK + DOMAIN_COLL_NAME PXW_GREEK + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 55 + COLL_ID 0 + CSET_NAME WIN1254 + CSET_DEFAULT_COLL WIN1254 + DOMAIN_COLL_NAME WIN1254 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 55 + COLL_ID 0 + CSET_NAME WIN1254 + CSET_DEFAULT_COLL WIN1254 + DOMAIN_COLL_NAME WIN1254 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 55 + COLL_ID 0 + CSET_NAME WIN1254 + CSET_DEFAULT_COLL WIN1254 + DOMAIN_COLL_NAME WIN1254 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 55 + COLL_ID 126 + CSET_NAME WIN1254 + CSET_DEFAULT_COLL WIN1254_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 55 + COLL_ID 126 + CSET_NAME WIN1254 + CSET_DEFAULT_COLL WIN1254_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 55 + COLL_ID 125 + CSET_NAME WIN1254 + CSET_DEFAULT_COLL WIN1254_UNICODE + DOMAIN_COLL_NAME WIN1254_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 55 + COLL_ID 1 + CSET_NAME WIN1254 + CSET_DEFAULT_COLL PXW_TURK + DOMAIN_COLL_NAME PXW_TURK + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 55 + COLL_ID 1 + CSET_NAME WIN1254 + CSET_DEFAULT_COLL PXW_TURK + DOMAIN_COLL_NAME PXW_TURK + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 55 + COLL_ID 1 + CSET_NAME WIN1254 + CSET_DEFAULT_COLL PXW_TURK + DOMAIN_COLL_NAME PXW_TURK + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 19 + COLL_ID 0 + CSET_NAME NEXT + CSET_DEFAULT_COLL NEXT + DOMAIN_COLL_NAME NEXT + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 19 + COLL_ID 0 + CSET_NAME NEXT + CSET_DEFAULT_COLL NEXT + DOMAIN_COLL_NAME NEXT + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 19 + COLL_ID 0 + CSET_NAME NEXT + CSET_DEFAULT_COLL NEXT + DOMAIN_COLL_NAME NEXT + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 19 + COLL_ID 126 + CSET_NAME NEXT + CSET_DEFAULT_COLL NEXT_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 19 + COLL_ID 126 + CSET_NAME NEXT + CSET_DEFAULT_COLL NEXT_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 19 + COLL_ID 125 + CSET_NAME NEXT + CSET_DEFAULT_COLL NEXT_UNICODE + DOMAIN_COLL_NAME NEXT_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 19 + COLL_ID 2 + CSET_NAME NEXT + CSET_DEFAULT_COLL NXT_DEU + DOMAIN_COLL_NAME NXT_DEU + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 19 + COLL_ID 2 + CSET_NAME NEXT + CSET_DEFAULT_COLL NXT_DEU + DOMAIN_COLL_NAME NXT_DEU + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 19 + COLL_ID 2 + CSET_NAME NEXT + CSET_DEFAULT_COLL NXT_DEU + DOMAIN_COLL_NAME NXT_DEU + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 19 + COLL_ID 5 + CSET_NAME NEXT + CSET_DEFAULT_COLL NXT_ESP + DOMAIN_COLL_NAME NXT_ESP + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 19 + COLL_ID 5 + CSET_NAME NEXT + CSET_DEFAULT_COLL NXT_ESP + DOMAIN_COLL_NAME NXT_ESP + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 19 + COLL_ID 5 + CSET_NAME NEXT + CSET_DEFAULT_COLL NXT_ESP + DOMAIN_COLL_NAME NXT_ESP + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 19 + COLL_ID 3 + CSET_NAME NEXT + CSET_DEFAULT_COLL NXT_FRA + DOMAIN_COLL_NAME NXT_FRA + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 19 + COLL_ID 3 + CSET_NAME NEXT + CSET_DEFAULT_COLL NXT_FRA + DOMAIN_COLL_NAME NXT_FRA + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 19 + COLL_ID 3 + CSET_NAME NEXT + CSET_DEFAULT_COLL NXT_FRA + DOMAIN_COLL_NAME NXT_FRA + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 19 + COLL_ID 4 + CSET_NAME NEXT + CSET_DEFAULT_COLL NXT_ITA + DOMAIN_COLL_NAME NXT_ITA + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 19 + COLL_ID 4 + CSET_NAME NEXT + CSET_DEFAULT_COLL NXT_ITA + DOMAIN_COLL_NAME NXT_ITA + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 19 + COLL_ID 4 + CSET_NAME NEXT + CSET_DEFAULT_COLL NXT_ITA + DOMAIN_COLL_NAME NXT_ITA + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 19 + COLL_ID 1 + CSET_NAME NEXT + CSET_DEFAULT_COLL NXT_US + DOMAIN_COLL_NAME NXT_US + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 19 + COLL_ID 1 + CSET_NAME NEXT + CSET_DEFAULT_COLL NXT_US + DOMAIN_COLL_NAME NXT_US + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 19 + COLL_ID 1 + CSET_NAME NEXT + CSET_DEFAULT_COLL NXT_US + DOMAIN_COLL_NAME NXT_US + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 58 + COLL_ID 0 + CSET_NAME WIN1255 + CSET_DEFAULT_COLL WIN1255 + DOMAIN_COLL_NAME WIN1255 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 58 + COLL_ID 0 + CSET_NAME WIN1255 + CSET_DEFAULT_COLL WIN1255 + DOMAIN_COLL_NAME WIN1255 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 58 + COLL_ID 0 + CSET_NAME WIN1255 + CSET_DEFAULT_COLL WIN1255 + DOMAIN_COLL_NAME WIN1255 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 58 + COLL_ID 126 + CSET_NAME WIN1255 + CSET_DEFAULT_COLL WIN1255_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 58 + COLL_ID 126 + CSET_NAME WIN1255 + CSET_DEFAULT_COLL WIN1255_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 58 + COLL_ID 125 + CSET_NAME WIN1255 + CSET_DEFAULT_COLL WIN1255_UNICODE + DOMAIN_COLL_NAME WIN1255_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 59 + COLL_ID 0 + CSET_NAME WIN1256 + CSET_DEFAULT_COLL WIN1256 + DOMAIN_COLL_NAME WIN1256 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 59 + COLL_ID 0 + CSET_NAME WIN1256 + CSET_DEFAULT_COLL WIN1256 + DOMAIN_COLL_NAME WIN1256 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 59 + COLL_ID 0 + CSET_NAME WIN1256 + CSET_DEFAULT_COLL WIN1256 + DOMAIN_COLL_NAME WIN1256 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 59 + COLL_ID 126 + CSET_NAME WIN1256 + CSET_DEFAULT_COLL WIN1256_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 59 + COLL_ID 126 + CSET_NAME WIN1256 + CSET_DEFAULT_COLL WIN1256_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 59 + COLL_ID 125 + CSET_NAME WIN1256 + CSET_DEFAULT_COLL WIN1256_UNICODE + DOMAIN_COLL_NAME WIN1256_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 60 + COLL_ID 0 + CSET_NAME WIN1257 + CSET_DEFAULT_COLL WIN1257 + DOMAIN_COLL_NAME WIN1257 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 60 + COLL_ID 0 + CSET_NAME WIN1257 + CSET_DEFAULT_COLL WIN1257 + DOMAIN_COLL_NAME WIN1257 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 60 + COLL_ID 0 + CSET_NAME WIN1257 + CSET_DEFAULT_COLL WIN1257 + DOMAIN_COLL_NAME WIN1257 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 60 + COLL_ID 126 + CSET_NAME WIN1257 + CSET_DEFAULT_COLL WIN1257_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 60 + COLL_ID 126 + CSET_NAME WIN1257 + CSET_DEFAULT_COLL WIN1257_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 60 + COLL_ID 125 + CSET_NAME WIN1257 + CSET_DEFAULT_COLL WIN1257_UNICODE + DOMAIN_COLL_NAME WIN1257_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 60 + COLL_ID 1 + CSET_NAME WIN1257 + CSET_DEFAULT_COLL WIN1257_EE + DOMAIN_COLL_NAME WIN1257_EE + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 60 + COLL_ID 1 + CSET_NAME WIN1257 + CSET_DEFAULT_COLL WIN1257_EE + DOMAIN_COLL_NAME WIN1257_EE + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 60 + COLL_ID 1 + CSET_NAME WIN1257 + CSET_DEFAULT_COLL WIN1257_EE + DOMAIN_COLL_NAME WIN1257_EE + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 60 + COLL_ID 2 + CSET_NAME WIN1257 + CSET_DEFAULT_COLL WIN1257_LT + DOMAIN_COLL_NAME WIN1257_LT + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 60 + COLL_ID 2 + CSET_NAME WIN1257 + CSET_DEFAULT_COLL WIN1257_LT + DOMAIN_COLL_NAME WIN1257_LT + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 60 + COLL_ID 2 + CSET_NAME WIN1257 + CSET_DEFAULT_COLL WIN1257_LT + DOMAIN_COLL_NAME WIN1257_LT + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 60 + COLL_ID 3 + CSET_NAME WIN1257 + CSET_DEFAULT_COLL WIN1257_LV + DOMAIN_COLL_NAME WIN1257_LV + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 60 + COLL_ID 3 + CSET_NAME WIN1257 + CSET_DEFAULT_COLL WIN1257_LV + DOMAIN_COLL_NAME WIN1257_LV + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 60 + COLL_ID 3 + CSET_NAME WIN1257 + CSET_DEFAULT_COLL WIN1257_LV + DOMAIN_COLL_NAME WIN1257_LV + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 44 + COLL_ID 0 + CSET_NAME KSC_5601 + CSET_DEFAULT_COLL KSC_5601 + DOMAIN_COLL_NAME KSC_5601 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 44 + COLL_ID 0 + CSET_NAME KSC_5601 + CSET_DEFAULT_COLL KSC_5601 + DOMAIN_COLL_NAME KSC_5601 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 44 + COLL_ID 0 + CSET_NAME KSC_5601 + CSET_DEFAULT_COLL KSC_5601 + DOMAIN_COLL_NAME KSC_5601 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 44 + COLL_ID 126 + CSET_NAME KSC_5601 + CSET_DEFAULT_COLL KSC_5601_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 44 + COLL_ID 126 + CSET_NAME KSC_5601 + CSET_DEFAULT_COLL KSC_5601_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 44 + COLL_ID 125 + CSET_NAME KSC_5601 + CSET_DEFAULT_COLL KSC_5601_UNICODE + DOMAIN_COLL_NAME KSC_5601_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 44 + COLL_ID 1 + CSET_NAME KSC_5601 + CSET_DEFAULT_COLL KSC_DICTIONARY + DOMAIN_COLL_NAME KSC_DICTIONARY + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 44 + COLL_ID 1 + CSET_NAME KSC_5601 + CSET_DEFAULT_COLL KSC_DICTIONARY + DOMAIN_COLL_NAME KSC_DICTIONARY + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 44 + COLL_ID 1 + CSET_NAME KSC_5601 + CSET_DEFAULT_COLL KSC_DICTIONARY + DOMAIN_COLL_NAME KSC_DICTIONARY + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 56 + COLL_ID 0 + CSET_NAME BIG_5 + CSET_DEFAULT_COLL BIG_5 + DOMAIN_COLL_NAME BIG_5 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 56 + COLL_ID 0 + CSET_NAME BIG_5 + CSET_DEFAULT_COLL BIG_5 + DOMAIN_COLL_NAME BIG_5 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 56 + COLL_ID 0 + CSET_NAME BIG_5 + CSET_DEFAULT_COLL BIG_5 + DOMAIN_COLL_NAME BIG_5 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 56 + COLL_ID 126 + CSET_NAME BIG_5 + CSET_DEFAULT_COLL BIG_5_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 56 + COLL_ID 126 + CSET_NAME BIG_5 + CSET_DEFAULT_COLL BIG_5_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 56 + COLL_ID 125 + CSET_NAME BIG_5 + CSET_DEFAULT_COLL BIG_5_UNICODE + DOMAIN_COLL_NAME BIG_5_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 57 + COLL_ID 0 + CSET_NAME GB_2312 + CSET_DEFAULT_COLL GB_2312 + DOMAIN_COLL_NAME GB_2312 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 57 + COLL_ID 0 + CSET_NAME GB_2312 + CSET_DEFAULT_COLL GB_2312 + DOMAIN_COLL_NAME GB_2312 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 57 + COLL_ID 0 + CSET_NAME GB_2312 + CSET_DEFAULT_COLL GB_2312 + DOMAIN_COLL_NAME GB_2312 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 57 + COLL_ID 126 + CSET_NAME GB_2312 + CSET_DEFAULT_COLL GB_2312_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 57 + COLL_ID 126 + CSET_NAME GB_2312 + CSET_DEFAULT_COLL GB_2312_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 57 + COLL_ID 125 + CSET_NAME GB_2312 + CSET_DEFAULT_COLL GB_2312_UNICODE + DOMAIN_COLL_NAME GB_2312_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 63 + COLL_ID 0 + CSET_NAME KOI8R + CSET_DEFAULT_COLL KOI8R + DOMAIN_COLL_NAME KOI8R + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 63 + COLL_ID 0 + CSET_NAME KOI8R + CSET_DEFAULT_COLL KOI8R + DOMAIN_COLL_NAME KOI8R + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 63 + COLL_ID 0 + CSET_NAME KOI8R + CSET_DEFAULT_COLL KOI8R + DOMAIN_COLL_NAME KOI8R + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 63 + COLL_ID 126 + CSET_NAME KOI8R + CSET_DEFAULT_COLL KOI8R_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 63 + COLL_ID 126 + CSET_NAME KOI8R + CSET_DEFAULT_COLL KOI8R_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 63 + COLL_ID 125 + CSET_NAME KOI8R + CSET_DEFAULT_COLL KOI8R_UNICODE + DOMAIN_COLL_NAME KOI8R_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 63 + COLL_ID 1 + CSET_NAME KOI8R + CSET_DEFAULT_COLL KOI8R_RU + DOMAIN_COLL_NAME KOI8R_RU + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 63 + COLL_ID 1 + CSET_NAME KOI8R + CSET_DEFAULT_COLL KOI8R_RU + DOMAIN_COLL_NAME KOI8R_RU + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 63 + COLL_ID 1 + CSET_NAME KOI8R + CSET_DEFAULT_COLL KOI8R_RU + DOMAIN_COLL_NAME KOI8R_RU + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 64 + COLL_ID 0 + CSET_NAME KOI8U + CSET_DEFAULT_COLL KOI8U + DOMAIN_COLL_NAME KOI8U + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 64 + COLL_ID 0 + CSET_NAME KOI8U + CSET_DEFAULT_COLL KOI8U + DOMAIN_COLL_NAME KOI8U + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 64 + COLL_ID 0 + CSET_NAME KOI8U + CSET_DEFAULT_COLL KOI8U + DOMAIN_COLL_NAME KOI8U + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 64 + COLL_ID 126 + CSET_NAME KOI8U + CSET_DEFAULT_COLL KOI8U_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 64 + COLL_ID 126 + CSET_NAME KOI8U + CSET_DEFAULT_COLL KOI8U_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 64 + COLL_ID 125 + CSET_NAME KOI8U + CSET_DEFAULT_COLL KOI8U_UNICODE + DOMAIN_COLL_NAME KOI8U_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 64 + COLL_ID 1 + CSET_NAME KOI8U + CSET_DEFAULT_COLL KOI8U_UA + DOMAIN_COLL_NAME KOI8U_UA + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 64 + COLL_ID 1 + CSET_NAME KOI8U + CSET_DEFAULT_COLL KOI8U_UA + DOMAIN_COLL_NAME KOI8U_UA + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 64 + COLL_ID 1 + CSET_NAME KOI8U + CSET_DEFAULT_COLL KOI8U_UA + DOMAIN_COLL_NAME KOI8U_UA + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 65 + COLL_ID 0 + CSET_NAME WIN1258 + CSET_DEFAULT_COLL WIN1258 + DOMAIN_COLL_NAME WIN1258 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 65 + COLL_ID 0 + CSET_NAME WIN1258 + CSET_DEFAULT_COLL WIN1258 + DOMAIN_COLL_NAME WIN1258 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 65 + COLL_ID 0 + CSET_NAME WIN1258 + CSET_DEFAULT_COLL WIN1258 + DOMAIN_COLL_NAME WIN1258 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 65 + COLL_ID 126 + CSET_NAME WIN1258 + CSET_DEFAULT_COLL WIN1258_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 65 + COLL_ID 126 + CSET_NAME WIN1258 + CSET_DEFAULT_COLL WIN1258_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 6 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 65 + COLL_ID 125 + CSET_NAME WIN1258 + CSET_DEFAULT_COLL WIN1258_UNICODE + DOMAIN_COLL_NAME WIN1258_UNICODE + COLL_ATTR 0 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 66 + COLL_ID 0 + CSET_NAME TIS620 + CSET_DEFAULT_COLL TIS620 + DOMAIN_COLL_NAME TIS620 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 66 + COLL_ID 0 + CSET_NAME TIS620 + CSET_DEFAULT_COLL TIS620 + DOMAIN_COLL_NAME TIS620 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 66 + COLL_ID 0 + CSET_NAME TIS620 + CSET_DEFAULT_COLL TIS620 + DOMAIN_COLL_NAME TIS620 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 66 + COLL_ID 126 + CSET_NAME TIS620 + CSET_DEFAULT_COLL TIS620_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 7 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 66 + COLL_ID 126 + CSET_NAME TIS620 + CSET_DEFAULT_COLL TIS620_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 7 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 66 + COLL_ID 1 + CSET_NAME TIS620 + CSET_DEFAULT_COLL TIS620_UNICODE + DOMAIN_COLL_NAME TIS620_UNICODE + COLL_ATTR 1 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 67 + COLL_ID 0 + CSET_NAME GBK + CSET_DEFAULT_COLL GBK + DOMAIN_COLL_NAME GBK + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 67 + COLL_ID 0 + CSET_NAME GBK + CSET_DEFAULT_COLL GBK + DOMAIN_COLL_NAME GBK + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 67 + COLL_ID 0 + CSET_NAME GBK + CSET_DEFAULT_COLL GBK + DOMAIN_COLL_NAME GBK + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 67 + COLL_ID 126 + CSET_NAME GBK + CSET_DEFAULT_COLL GBK_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 7 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 67 + COLL_ID 126 + CSET_NAME GBK + CSET_DEFAULT_COLL GBK_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 7 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 67 + COLL_ID 1 + CSET_NAME GBK + CSET_DEFAULT_COLL GBK_UNICODE + DOMAIN_COLL_NAME GBK_UNICODE + COLL_ATTR 1 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 68 + COLL_ID 0 + CSET_NAME CP943C + CSET_DEFAULT_COLL CP943C + DOMAIN_COLL_NAME CP943C + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 68 + COLL_ID 0 + CSET_NAME CP943C + CSET_DEFAULT_COLL CP943C + DOMAIN_COLL_NAME CP943C + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 68 + COLL_ID 0 + CSET_NAME CP943C + CSET_DEFAULT_COLL CP943C + DOMAIN_COLL_NAME CP943C + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 68 + COLL_ID 126 + CSET_NAME CP943C + CSET_DEFAULT_COLL CP943C_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 7 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 68 + COLL_ID 126 + CSET_NAME CP943C + CSET_DEFAULT_COLL CP943C_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 7 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 68 + COLL_ID 1 + CSET_NAME CP943C + CSET_DEFAULT_COLL CP943C_UNICODE + DOMAIN_COLL_NAME CP943C_UNICODE + COLL_ATTR 1 + COLL_SPEC COLL-VERSION=153.88 + + + + F_NAME DM_BLOB + CSET_ID 69 + COLL_ID 0 + CSET_NAME GB18030 + CSET_DEFAULT_COLL GB18030 + DOMAIN_COLL_NAME GB18030 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_NAME + CSET_ID 69 + COLL_ID 0 + CSET_NAME GB18030 + CSET_DEFAULT_COLL GB18030 + DOMAIN_COLL_NAME GB18030 + COLL_ATTR 1 + COLL_SPEC + + F_NAME DM_TEXT + CSET_ID 69 + COLL_ID 0 + CSET_NAME GB18030 + CSET_DEFAULT_COLL GB18030 + DOMAIN_COLL_NAME GB18030 + COLL_ATTR 1 + COLL_SPEC + + + + F_NAME DM_BLOB + CSET_ID 69 + COLL_ID 126 + CSET_NAME GB18030 + CSET_DEFAULT_COLL GB18030_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 7 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_NAME + CSET_ID 69 + COLL_ID 126 + CSET_NAME GB18030 + CSET_DEFAULT_COLL GB18030_UNICODE + DOMAIN_COLL_NAME CO_UNICODE + COLL_ATTR 7 + COLL_SPEC COLL-VERSION=153.88;NUMERIC-SORT=1 + + F_NAME DM_TEXT + CSET_ID 69 + COLL_ID 1 + CSET_NAME GB18030 + CSET_DEFAULT_COLL GB18030_UNICODE + DOMAIN_COLL_NAME GB18030_UNICODE + COLL_ATTR 1 + COLL_SPEC COLL-VERSION=153.88 + + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_6336_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6337.py b/tests/bugs/test_core_6337.py new file mode 100644 index 00000000..7b15e507 --- /dev/null +++ b/tests/bugs/test_core_6337.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: bugs.core_6337 +# title: SubType information is lost when calculating arithmetic expressions +# decription: +# Confirmed bug on 4.0.0.2035. +# Checked on 4.0.0.2068 - works fine. +# 25.06.2020, 4.0.0.2076: changed types in SQLDA from numeric to int128 // after discuss with Alex about CORE-6342. +# +# tracker_id: CORE-6337 +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('^((?!sqltype).)*$', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set sqlda_display on; + set list on; + select cast(1 as numeric(18,2)) * cast(1 as numeric(18,2)) from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 01: sqltype: 32752 INT128 scale: -4 subtype: 1 len: 16 + """ + +@pytest.mark.version('>=4.0') +def test_core_6337_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6340.py b/tests/bugs/test_core_6340.py new file mode 100644 index 00000000..422263df --- /dev/null +++ b/tests/bugs/test_core_6340.py @@ -0,0 +1,592 @@ +#coding:utf-8 +# +# id: bugs.core_6340 +# title: Alternate quoting does not work on some particular cases +# decription: +# Checked on build 4.0.0.2073 with timestamp 24.06.2020 13:40 (intermediate). +# NOTE: test tries several cases + checks that string with maximum limit of length (65533) can be properly parsed. +# 04.07.2020: changed min_version to 3.0.6 - checked on 3.0.6.33332. +# +# tracker_id: CORE-6340 +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ +-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +-- ::: NB ::: DO NOT MAKE INDENTATION OF TEXT THAT IS BELOW ::: +-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +set list on; + +select 'point-0.01' as msg, q'{{}' as result from rdb$database; +select 'point-0.02' as msg, q'{}}' as result from rdb$database; +select 'point-0.03' as msg, q'!'!' as result from rdb$database; + + +select 'point-1.01' as msg, q'!' '!' as result from rdb$database; +select 'point-1.02' as msg, q'!'!' as result from rdb$database; +select 'point-1.03' as msg, q'!' !' as result from rdb$database; +select 'point-1.04' as msg, q'!'!' as result from rdb$database; +select 'point-1.05' as msg, q'!'''!' as result from rdb$database; +select 'point-1.06' as msg, q'! +' +!' as result from rdb$database; + +select 'point-1.07' as msg, q'!!' as result from rdb$database; + +select 'point-1.08' as msg, q'!!!' as result from rdb$database; + +select 'point-1.09' as msg, q'! +! +!' as result from rdb$database; + +select 'point-1.10' as msg, q'!q!' as result from rdb$database; + +select 'point-1.11' as msg, q'!q'!' as result from rdb$database; + +select 'point-1.12' as msg, q'!'q'!' as result from rdb$database; + +select 'point-1.13' as msg, q'!'!q'!' as result from rdb$database; + +select 'point-1.14' as msg, q'!!!!' as result from rdb$database; + +-- max allowed len = 65533 (not including q'! and !'): +-- -string right truncation / -expected length 65533, actual 65534 +select 'point-1.15' as msg, q'!'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''!' as result from rdb$database; + + +select 'point-2.01' as msg, q'<''' >' as results from rdb$database; +select 'point-2.02' as msg, q'<'<'>' as results from rdb$database; +select 'point-2.03' as msg, q'<'<<'>' as results from rdb$database; +select 'point-2.04' as msg, q'<'<<<'>' as results from rdb$database; +select 'point-2.05' as msg, q'<'>' as results from rdb$database; +select 'point-2.06' as msg, q'<'>>' as results from rdb$database; +select 'point-2.07' as msg, q'<'>>>' as results from rdb$database; + + +select 'point-3.01' as msg, q'!' '!' as result from rdb$database; +select 'point-3.02' as msg, q'!'!' as result from rdb$database; +select 'point-3.03' as msg, q'!' !' as result from rdb$database; +select 'point-3.04' as msg, q'!'!' as result from rdb$database; +select 'point-3.05' as msg, q'!'''!' as result from rdb$database; +select 'point-3.06' as msg, q'! +' +!' as result from rdb$database; + +select 'point-3.07' as msg, q'!!' as result from rdb$database; + +select 'point-3.08' as msg, q'!!!' as result from rdb$database; + +select 'point-3.09' as msg, q'! +! +!' as result from rdb$database; + +select 'point-3.10' as msg, q'!q!' as result from rdb$database; + +select 'point-3.11' as msg, q'!q'!' as result from rdb$database; + +select 'point-3.12' as msg, q'!'q'!' as result from rdb$database; + +select 'point-3.13' as msg, q'!'!q'!' as result from rdb$database; + + +select 'point-3.14' as msg, q'!! +''!' as result from rdb$database; + + +select 'point-3.15' as msg, q'! +! +'!' as result from rdb$database; + +select 'point-3.16' as msg, q'! +'! +'' +'! +!' as result from rdb$database; + + +select 'point-4.01' as msg, q'|' '|' as result from rdb$database; +select 'point-4.02' as msg, q'|'|' as result from rdb$database; +select 'point-4.03' as msg, q'|' |' as result from rdb$database; +select 'point-4.04' as msg, q'|'|' as result from rdb$database; +select 'point-4.05' as msg, q'|'''|' as result from rdb$database; +select 'point-4.06' as msg, q'| +' +|' as result from rdb$database; + +select 'point-4.07' as msg, q'||' as result from rdb$database; + +select 'point-4.08' as msg, q'|||' as result from rdb$database; + +select 'point-4.09' as msg, q'| +| +|' as result from rdb$database; + +select 'point-4.10' as msg, q'|q|' as result from rdb$database; + +select 'point-4.11' as msg, q'|q'|' as result from rdb$database; + +select 'point-4.12' as msg, q'|'q'|' as result from rdb$database; + +select 'point-4.13' as msg, q'|'|q'|' as result from rdb$database; + +select 'point-4.14' as msg, q'|||'||''||q'|||' as result from rdb$database; + +select 'point-4.15' as msg, q'| +| +'|' as result from rdb$database; + +select 'point-4.16' as msg, q'| +'| +'' +'| +|' as result from rdb$database; + +--select 'point-4.17' as msg, q'||'||'||' as result from rdb$database; + +-- select 'point-4.18' as msg, q'##'##'##' as result from rdb$database; + +select 'point-4.19' as msg, q'{{'||'}}' as result from rdb$database; + +select 'point-4.20' as msg, q'|| '|| '||' as result from rdb$database; + +select 'point-4.21' as msg, q'||'||'||' as result from rdb$database; + +select 'point-4.22' as msg, q'||||'||'|||' as result from rdb$database; + +select 'point-4.23' as msg, q'+'||'+' as result from rdb$database; +--set heading off; + +--set echo on; + +select 'point-5.01' as msg, q'q'||'qq' as result from rdb$database; -- expected: '||'q + +select 'point-5.02' as msg, q'q' 'q' as result from rdb$database; -- expected: ' ' + +select 'point-5.03' as msg, q'q'q' as result from rdb$database; -- expected: ' + +select 'point-5.04' as msg, q'q'||'q||'q 'q' as result from rdb$database; -- expected: '||'q||'q ' + +select 'point-5.05' as msg, q'q'''q' as result from rdb$database; -- expected: ''' + +select 'point-5.06' as msg, q'q +' +q' as result from rdb$database; -- expected: ' followed by [CR/]LF + +select 'point-5.07' as msg, q'qq' as result from rdb$database; -- expected: empty string + +select 'point-5.08' as msg, q'qqq' as result from rdb$database; -- expected: q + +select 'point-5.09' as msg, q'qqQ'qq' as result from rdb$database; -- expected: qQ'q + +select 'point-5.10' as msg, q'q 'q 'q' as result from rdb$database; -- expected: [space]'q ' + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +MSG point-0.01 +RESULT { + + + +MSG point-0.02 +RESULT } + + + +MSG point-0.03 +RESULT ' + + + +MSG point-1.01 +RESULT ' ' + + + +MSG point-1.02 +RESULT ' + + + +MSG point-1.03 +RESULT ' + + + +MSG point-1.04 +RESULT ' + + + +MSG point-1.05 +RESULT ''' + + + +MSG point-1.06 +RESULT +' + + + + +MSG point-1.07 +RESULT + + + +MSG point-1.08 +RESULT ! + + + +MSG point-1.09 +RESULT +! + + + + +MSG point-1.10 +RESULT q + + + +MSG point-1.11 +RESULT q' + + + +MSG point-1.12 +RESULT 'q' + + + +MSG point-1.13 +RESULT '!q' + + + +MSG point-1.14 +RESULT !! + + + +MSG point-1.15 +RESULT ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + + + +MSG point-2.01 +RESULTS ''' + + + +MSG point-2.02 +RESULTS '<' + + + +MSG point-2.03 +RESULTS '<<' + + + +MSG point-2.04 +RESULTS '<<<' + + + +MSG point-2.05 +RESULTS ' + + + +MSG point-2.06 +RESULTS '> + + + +MSG point-2.07 +RESULTS '>> + + + +MSG point-3.01 +RESULT ' ' + + + +MSG point-3.02 +RESULT ' + + + +MSG point-3.03 +RESULT ' + + + +MSG point-3.04 +RESULT ' + + + +MSG point-3.05 +RESULT ''' + + + +MSG point-3.06 +RESULT +' + + + + +MSG point-3.07 +RESULT + + + +MSG point-3.08 +RESULT ! + + + +MSG point-3.09 +RESULT +! + + + + +MSG point-3.10 +RESULT q + + + +MSG point-3.11 +RESULT q' + + + +MSG point-3.12 +RESULT 'q' + + + +MSG point-3.13 +RESULT '!q' + + + +MSG point-3.14 +RESULT ! +'' + + + +MSG point-3.15 +RESULT +! +' + + + +MSG point-3.16 +RESULT +'! +'' +'! + + + + +MSG point-4.01 +RESULT ' ' + + + +MSG point-4.02 +RESULT ' + + + +MSG point-4.03 +RESULT ' + + + +MSG point-4.04 +RESULT ' + + + +MSG point-4.05 +RESULT ''' + + + +MSG point-4.06 +RESULT +' + + + + +MSG point-4.07 +RESULT + + + +MSG point-4.08 +RESULT | + + + +MSG point-4.09 +RESULT +| + + + + +MSG point-4.10 +RESULT q + + + +MSG point-4.11 +RESULT q' + + + +MSG point-4.12 +RESULT 'q' + + + +MSG point-4.13 +RESULT '|q' + + + +MSG point-4.14 +RESULT || + + + +MSG point-4.15 +RESULT +| +' + + + +MSG point-4.16 +RESULT +'| +'' +'| + + + + +MSG point-4.19 +RESULT {'||'} + + + +MSG point-4.20 +RESULT | '|| '| + + + +MSG point-4.21 +RESULT || + + + +MSG point-4.22 +RESULT ||||| + + + +MSG point-4.23 +RESULT '||' + + + +MSG point-5.01 +RESULT '||'q + + + +MSG point-5.02 +RESULT ' ' + + + +MSG point-5.03 +RESULT ' + + + +MSG point-5.04 +RESULT '||'q||'q ' + + + +MSG point-5.05 +RESULT ''' + + + +MSG point-5.06 +RESULT +' + + + + +MSG point-5.07 +RESULT + + + +MSG point-5.08 +RESULT q + + + +MSG point-5.09 +RESULT qQ'q + + + +MSG point-5.10 +RESULT 'q ' + """ + +@pytest.mark.version('>=3.0.6') +def test_core_6340_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6342.py b/tests/bugs/test_core_6342.py new file mode 100644 index 00000000..dfae0596 --- /dev/null +++ b/tests/bugs/test_core_6342.py @@ -0,0 +1,248 @@ +#coding:utf-8 +# +# id: bugs.core_6342 +# title: Make explicit basic type for high precision numerics - INT128 +# decription: +# Initial discuss with Alex: letter 24.06.2020 18:29. +# This test most probably will be added by another checks, currently it has initial state. +# We verify that: +# 1) one may to write: create table test( x int128 ); -- i.e. explicitly specify type = 'int128' +# 2) table column can refer to domain which was declared as int128 +# 3) one may to write SET BIND OF INT128 TO ans vice versa. +# +# Checked on 4.0.0.2073. +# +# tracker_id: CORE-6342 +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('^((?!sqltype).)*$', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test1(x int); + + set term ^; + execute block as + begin + begin + execute statement 'drop domain dm_128_a'; + when any do begin end + end + begin + execute statement 'drop domain dm_128_b'; + when any do begin end + end + begin + execute statement 'drop domain dm_128_c'; + when any do begin end + end + end + ^ + set term ;^ + + create domain dm_128_a int128; + create domain dm_128_b as numeric(20,2) default -9999999999999999991; -- CORE-6294 + --create domain dm_128_c as bigint default -9223372036854775808; -- CORE-6291 + create domain dm_128_c as int128 default -9223372036854775807; + recreate table test1(x int128 default 9999999999999999991, a dm_128_a default 9223372036854775807, b dm_128_b, c dm_128_c); + + set sqlda_display on; + select * from test1; + commit; + set sqlda_display off; + ------------------------- + + + recreate table test2(x numeric(19), y numeric(38,38)); + + set bind of numeric to decimal; + set sqlda_display on; + select * from test2; + set sqlda_display off; + + ---------------------------- + + set bind of int128 to smallint; + + recreate table test3(x int128); + set sqlda_display on; + select * from test3; + commit; + set sqlda_display off; + + ---------------------------- + + set bind of int128 to decimal; + + recreate table test4(x int128); + set sqlda_display on; + select * from test4; + commit; + set sqlda_display off; + + + ---------------------------- + + set bind of int128 to numeric; + + recreate table test5(x int128); + set sqlda_display on; + select * from test5; + commit; + set sqlda_display off; + + ---------------------------- + + set bind of int128 to int; + + recreate table test6(x int128); + set sqlda_display on; + select * from test6; + commit; + set sqlda_display off; + + ---------------------------- + + set bind of int128 to bigint; + + recreate table test7(x int128); + set sqlda_display on; + select * from test7; + commit; + set sqlda_display off; + + ---------------------------- + + set bind of int128 to double precision; + + recreate table test8(x int128); + set sqlda_display on; + select * from test8; + commit; + set sqlda_display off; + + + ---------------------------- + + set bind of int128 to float; + + recreate table test9(x int128); + set sqlda_display on; + select * from test9; + commit; + set sqlda_display off; + + --############################# + + set bind of smallint to int128; + + recreate table test10(x smallint); + set sqlda_display on; + select * from test10; + commit; + set sqlda_display off; + + --------------------------------- + + set bind of int to int128; + + recreate table test11(x int); + set sqlda_display on; + select * from test11; + commit; + set sqlda_display off; + + --------------------------------- + + set bind of bigint to int128; + + recreate table test12(x bigint); + set sqlda_display on; + select * from test12; + commit; + set sqlda_display off; + + --------------------------------- + + set bind of numeric to int128; + + recreate table test13(x numeric(9,2)); + set sqlda_display on; + select * from test13; + commit; + set sqlda_display off; + + --------------------------------- + + set bind of decimal to int128; + + recreate table test14(x decimal(19,19)); + set sqlda_display on; + select * from test14; + commit; + set sqlda_display off; + + --------------------------------- + + set bind of double precision to int128; + + recreate table test15(x double precision); + set sqlda_display on; + select * from test15; + commit; + set sqlda_display off; + + --------------------------------- + + set bind of float to int128; + + recreate table test16(x float); + set sqlda_display on; + select * from test16; + commit; + set sqlda_display off; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 01: sqltype: 32752 INT128 Nullable scale: 0 subtype: 0 len: 16 + 02: sqltype: 32752 INT128 Nullable scale: 0 subtype: 0 len: 16 + 03: sqltype: 32752 INT128 Nullable scale: -2 subtype: 1 len: 16 + 04: sqltype: 32752 INT128 Nullable scale: 0 subtype: 0 len: 16 + 01: sqltype: 32752 INT128 Nullable scale: 0 subtype: 2 len: 16 + 02: sqltype: 32752 INT128 Nullable scale: -38 subtype: 2 len: 16 + 01: sqltype: 500 SHORT Nullable scale: 0 subtype: 0 len: 2 + 01: sqltype: 32752 INT128 Nullable scale: 0 subtype: 2 len: 16 + 01: sqltype: 32752 INT128 Nullable scale: 0 subtype: 1 len: 16 + 01: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + 01: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + 01: sqltype: 480 DOUBLE Nullable scale: 0 subtype: 0 len: 8 + 01: sqltype: 482 FLOAT Nullable scale: 0 subtype: 0 len: 4 + 01: sqltype: 32752 INT128 Nullable scale: 0 subtype: 0 len: 16 + 01: sqltype: 32752 INT128 Nullable scale: 0 subtype: 0 len: 16 + 01: sqltype: 32752 INT128 Nullable scale: 0 subtype: 0 len: 16 + 01: sqltype: 32752 INT128 Nullable scale: -2 subtype: 1 len: 16 + 01: sqltype: 32752 INT128 Nullable scale: -19 subtype: 2 len: 16 + 01: sqltype: 32752 INT128 Nullable scale: 0 subtype: 0 len: 16 + 01: sqltype: 32752 INT128 Nullable scale: 0 subtype: 0 len: 16 + """ + +@pytest.mark.version('>=4.0') +def test_core_6342_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6343.py b/tests/bugs/test_core_6343.py new file mode 100644 index 00000000..bc483246 --- /dev/null +++ b/tests/bugs/test_core_6343.py @@ -0,0 +1,140 @@ +#coding:utf-8 +# +# id: bugs.core_6343 +# title: Rolled back transaction produces unexpected results leading to duplicate values in PRIMARY KEY field +# decription: +# Confirmed bug on 3.0.6.33322: duplicates in PK remain after test script. +# Checked on 3.0.6.33326 - all fine. +# +# NOTE: 3.0.x only was affected. No such problem in 4.x +# +# tracker_id: CORE-6343 +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [('line:.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter procedure sp_test as begin end; + + create global temporary table gtt_table ( + id integer not null + ) on commit delete rows; + + create table test ( + id integer not null primary key + ); + set term ^; + create or alter procedure sp_test returns ( id1 integer) + as + declare variable v integer; + begin + insert into gtt_table values(1); + insert into gtt_table values(2); + insert into gtt_table values(3); + + for + select id from gtt_table + into :id1 do + begin + insert into test (id) values (:id1); + + -- NOTE: it is mandatory to make "unnecessary" query to rdb$database + -- in order to reproduce bug. Do not replace it with "pure PSQL". + for + select 1 from rdb$database into :v + do + if (:id1=3) then + id1 = 1/0; -- do NOT suppress this exception otherwise bug will not shown + + suspend; + + delete from test; + end + end + ^ + set term ;^ + commit; + ----------------------------------- + set heading off; + -- Iteration #1 + select * from sp_test; + rollback; + select * from test; + + + -- Iteration #2 + select * from sp_test; + rollback; + select * from test; + + + -- Iteration #3 + select * from sp_test; + rollback; + select * from test; + + + -- Iteration #4 + select * from sp_test; + rollback; + select * from test; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 1 + 2 + + 1 + 2 + + 1 + 2 + + 1 + 2 + """ +expected_stderr_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. + -At procedure 'SP_TEST' + + 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' + + 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' + + 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_core_6343_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6345.py b/tests/bugs/test_core_6345.py new file mode 100644 index 00000000..e052c88a --- /dev/null +++ b/tests/bugs/test_core_6345.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: bugs.core_6345 +# title: Server crashes on overflow of division result +# decription: +# Confirmed bug on 4.0.0.2076, 3.0.6.33322 +# Checked on 4.0.0.2078, 3.0.6.33326 - all OK. +# (intermediate snapshots with timestamps: 26.06.20 06:36, 07:26) +# +# tracker_id: CORE-6345 +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + select -922337203685477.5808/-1.0 from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22003 + Integer overflow. The result of an integer operation caused the most significant bit of the result to carry. + """ + +@pytest.mark.version('>=3.0.6') +def test_core_6345_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_6348.py b/tests/bugs/test_core_6348.py new file mode 100644 index 00000000..1043bd59 --- /dev/null +++ b/tests/bugs/test_core_6348.py @@ -0,0 +1,194 @@ +#coding:utf-8 +# +# id: bugs.core_6348 +# title: Wire compression causes freezes +# decription: +# We create copy of %FIREBIRD_HOME% +# irebird.conf and change it content by adding line: +# WireCompression = true +# +# Then we use pre-created large binary file which can not be compressed (it is .7z) and +# check how long it is loaded into blob field of test table. +# +# ::: NOTE ::: +# EXTERNAL script for execution by Python is created here! +# Otherwise one can not reproduce problem described in the ticket if original firebird.conf +# does NOT contain 'WireCompression' or its value is set to false. +# We have to launch NEW (child) Python process which will run fully separately from current. +# +# Dozen measures show that after this CORE was fixed, blob is loaded for less 5 seconds +# on usual PC with HDD/ram=12gb/CPU 3.07 MHz. +# +# It was decided to use THRESHOLD about 15 seconds to make conclusion that all remains fine. +# May be this threshold needs to be sometime revised. +# +# Confirmed bug on 4.0.0.1994: blob loading time is more than 120s. +# Checked on 4.0.0.2089 -- all fine, blob is loaded for less than 5s. +# +# tracker_id: CORE-6348 +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# from subprocess import Popen +# import datetime +# import time +# import shutil +# from fdb import services +# from datetime import datetime as dt +# from datetime import timedelta +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# ############################# +# ### T H R E S H O L D ### +# ############################# +# MAX_SECONDS_FOR_LOAD = 15 +# +# db_conn.close() +# +# #----------------------------------- +# def showtime(): +# global dt +# return ''.join( (dt.now().strftime("%H:%M:%S.%f")[:11],'.') ) +# #----------------------------------- +# +# 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() +# os.fsync(file_handle.fileno()) +# +# file_handle.close() +# +# #-------------------------------------------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# #-------------------------------------------- +# +# +# fb_home = services.connect(host='localhost', user= user_name, password= user_password).get_home_directory() +# # Resut: fb_home is full path to FB instance home (with trailing slash). +# +# dts = datetime.datetime.now().strftime("%y%m%d_%H%M%S") +# +# fbconf_cur = os.path.join( fb_home, 'firebird.conf') +# fbconf_bak = os.path.join( fb_home, 'firebird'+dts+'.bak') +# +# shutil.copy2( fb_home+'firebird.conf', fbconf_bak ) +# +# f_fbconf=open( fbconf_cur, 'r') +# fbconf_content=f_fbconf.readlines() +# f_fbconf.close() +# for i,s in enumerate( fbconf_content ): +# line = s.lower().lstrip() +# if line.startswith( 'wirecompression'.lower() ): +# fbconf_content[i] = '# [temply commented by fbtest for core_6348.fbt] ' + s +# +# +# text2app=''' +# ### TEMPORARY CHANGED FOR CORE_6348.FBT ### +# WireCompression = true +# ############################################## +# ''' +# +# fbconf_content += [ os.linesep + x for x in text2app.split( os.linesep ) ] +# +# f_fbconf=open( fbconf_cur, 'w', buffering = 0) +# f_fbconf.writelines( fbconf_content ) +# flush_and_close( f_fbconf ) +# +# FB_CLNT = os.path.join(fb_home, 'fbclient.dll') +# BLOB_FILE = os.path.join(context['files_location'],'core_6348.bin') +# +# external_python_code='''from __future__ import print_function +# from datetime import datetime as dt +# from datetime import timedelta +# import fdb +# con = fdb.connect( dsn = r'%(dsn)s', user='%(user_name)s', password='%(user_password)s', fb_library_name = r'%(FB_CLNT)s' ) +# con.execute_immediate('create table test(b blob)') +# con.commit() +# +# cur=con.cursor() +# blob_src = r'%(BLOB_FILE)s' +# blob_handle = open( blob_src, 'rb') +# +# da=dt.now() +# cur.execute('insert into test(b) values(?)',[blob_handle]) +# db=dt.now() +# +# blob_handle.close() +# diff=db-da +# print( 'Acceptable' if diff.seconds < %(MAX_SECONDS_FOR_LOAD)s else 'BLOB LOADED TOO SLOW: ' + str(diff.seconds) + 's, THRESHOLD IS: ' + str(%(MAX_SECONDS_FOR_LOAD)s)+'s' ) +# +# cur.close() +# con.commit() +# con.close() +# ''' % dict(globals(), **locals()) +# +# f_extern_py=open( os.path.join(context['temp_directory'],'tmp_6348.py'), 'w') +# f_extern_py.write(external_python_code) +# flush_and_close( f_extern_py ) +# +# f_external_py_log = open( os.path.join(context['temp_directory'],'tmp_6348.log'), 'w') +# subprocess.call( [sys.executable, f_extern_py.name], stdout = f_external_py_log, stderr = subprocess.STDOUT ) +# flush_and_close( f_external_py_log ) +# +# # Restore original content of firebird.conf: +# ################## +# shutil.copy2( fbconf_bak, fb_home+'firebird.conf' ) +# os.remove( fbconf_bak ) +# +# with open(f_external_py_log.name, 'r') as f: +# for line in f: +# print(line) +# +# time.sleep(1) +# +# # Cleanup +# ######### +# f_list=( f_extern_py, f_external_py_log ) +# cleanup( [ i.name for i in f_list ] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Acceptable + """ + +@pytest.mark.version('>=3.0.6') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_6348_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6351.py b/tests/bugs/test_core_6351.py new file mode 100644 index 00000000..bd65672d --- /dev/null +++ b/tests/bugs/test_core_6351.py @@ -0,0 +1,93 @@ +#coding:utf-8 +# +# id: bugs.core_6351 +# title: Computed field could be wrongly evaluated as NULL +# decription: +# Confirmed bug on 4.0.0.2087. +# Checked on 4.0.0.2170, 3.0.7.33357 -- all fine. +# +# tracker_id: +# min_versions: ['3.0.7'] +# versions: 3.0.7 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create table t1 + ( + id int, + f1 computed by ('abcd'), + f2 computed by ('xyz') + ); + commit; + + set term ^; + create or alter procedure p_t1 (id int) + returns (val varchar(32)) + as + begin + val = 'unknown'; + + select f2 from t1 where id = :id + into :val; + + suspend; + end^ + set term ;^ + commit; + + alter table t1 + alter f1 computed by ((select val from p_t1(id))); + + alter table t1 + alter f2 computed by ('id = ' || id); + commit; + + insert into t1 values (1); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select 'case-1' as msg, p.val from p_t1(1) p; + select t.* from t1 t; + commit; + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + + select t.* from t1 t; + select 'case-2' as msg, p.val from p_t1(1) p; + exit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG case-1 + VAL id = 1 + ID 1 + F1 id = 1 + F2 id = 1 + + ID 1 + F1 id = 1 + F2 id = 1 + MSG case-2 + VAL id = 1 + """ + +@pytest.mark.version('>=3.0.7') +def test_core_6351_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6353.py b/tests/bugs/test_core_6353.py new file mode 100644 index 00000000..f6022148 --- /dev/null +++ b/tests/bugs/test_core_6353.py @@ -0,0 +1,256 @@ +#coding:utf-8 +# +# id: bugs.core_6353 +# title: INT128 has problems with some PSQL objects +# decription: +# Checked on 4.0.0.2104. +# +# tracker_id: CORE-6353 +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('line: [\\d]+, col: [\\d]+', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + create exception ex_zero_div_not_allowed 'Can not delete @1 by zero'; + commit; + + create sequence g1 start with 9223372036854775807; + create sequence g2 start with -9223372036854775808; + + /* + THIS WILL *NOT* WORK IN ANY FUTURE VERSION OF FB 4.X, + SEE LETTER FROM ALEX, 13.07.2020 10:50 (SUBJECT: "i128"): + create sequence g3 start with 170141183460469231731687303715884105727; + create sequence g4 start with -170141183460469231731687303715884105728; + */ + + ------------------------------------------------- + recreate table test0( id int128 generated always as identity, id2 computed by (170141183460469231731687303715884105727 - id) ); + insert into test0 default values; + select * from test0; + commit; + + -- FAILS, CORE-6365: recreate table test0( id int128 generated always as identity (start with -9223372036854775808 increment by 9223372036854775807), id2 computed by (id+9223372036854775807) ); + + recreate table test0( id int128 generated always as identity (start with -9223372036854775808 increment by 2147483647), id2 computed by (id+9223372036854775807) ); + insert into test0 default values; + select * from test0; + commit; + + -- FAILS, CORE-6365: recreate table test0( id int128 generated always as identity (start with 9223372036854775807 increment by -2147483648), id2 computed by (id-9223372036854775808) ); + + recreate table test0( id int128 generated always as identity (start with 9223372036854775807 increment by -2147483647), id2 computed by (id-9223372036854775808) ); + insert into test0 default values; + select * from test0; + commit; + + ------------------------------------------------- + + recreate table test0( i_min int128, i_max int128); + create index test0_i_min_asc on test0(i_min); + create descending index test0_i_min_dec on test0(i_min); + create index test0_i_max_asc on test0(i_max); + create descending index test0_i_max_dec on test0(i_max); + + recreate view v_test0 as select * from test0; + commit; + + insert into test0(i_min, i_max) values(-170141183460469231731687303715884105728, 170141183460469231731687303715884105727); + insert into v_test0(i_min, i_max) values(-170141183460469231731687303715884105728, 170141183460469231731687303715884105727); + + select * from v_test0; + set plan on; + select max(i_min) from v_test0; + select min(i_min) from v_test0; + select max(i_max) from v_test0; + select min(i_max) from v_test0; + set plan off; + commit; + + ------------------------------------------------- + + create domain dm_int128_great1 as int128 default 170141183460469231731687303715884105727; + create domain dm_int128_least1 as int128 default -170141183460469231731687303715884105728; + + recreate table test1( i_min dm_int128_least1, i_max dm_int128_great1); + alter table test1 + add constraint test1_chk + check( + i_min in(170141183460469231731687303715884105727, -170141183460469231731687303715884105728) + and + i_max in(170141183460469231731687303715884105727, -170141183460469231731687303715884105728) + ); + + recreate view v_test1 as select * from test1; + commit; + + insert into test1 default values; + insert into v_test1 default values; + commit; + + select * from v_test1; + commit; + + --------------------------------------------------------- + + create domain dm_int128_great2 as int128 default 170141183460469231731687303715884105727 check(value in(170141183460469231731687303715884105727, -170141183460469231731687303715884105728)); + create domain dm_int128_least2 as int128 default -170141183460469231731687303715884105728 check(value in(170141183460469231731687303715884105727, -170141183460469231731687303715884105728)); + commit; + + recreate table test2( i_min dm_int128_least2, i_max dm_int128_great2); + recreate view v_test2 as select * from test2; + commit; + + insert into test2 default values; + + insert into v_test2 default values; + commit; + + select * from v_test2; + commit; + + -- these two must fail because of check violation: + insert into test2(i_min, i_max) values(-2,2); + insert into v_test2(i_min, i_max) values(2,-2); + + --------------------------------------------------------- + + recreate view v_test3 as + select -170141183460469231731687303715884105728 as v_min from rdb$database + union all + select 170141183460469231731687303715884105727 as v_min from rdb$database; + commit; + + select * from v_test3; + commit; + + ----------------------------------------------------------- + + recreate table test4( i_min int128, i_max int128); + commit; + insert into test4(i_min, i_max) values(-170141183460469231731687303715884105728, 170141183460469231731687303715884105727); + commit; + + set term ^; + create or alter procedure sp_min( + a_min type of column test4.i_min default -170141183460469231731687303715884105728 + ) returns( + p_min type of column test4.i_min + ) as + begin + select i_max from test4 where i_min >= :a_min rows 1 into p_min; + suspend; + end + ^ + + create or alter procedure sp_max( + a_max type of column test4.i_max default 170141183460469231731687303715884105727 + ) returns( + p_max type of column test4.i_max + ) as + begin + select i_min from test4 where i_min <= :a_max rows 1 into p_max; + suspend; + end + ^ + + create or alter procedure sp_zero_div(a_delimiter int128 ) returns(p_min decfloat) as -- type of column test4.i_min) as + declare v_min type of column test4.i_min; + begin + select min(i_min) from test4 into v_min; + begin + p_min = v_min / a_delimiter; + when sqlstate '22012' do -- 335544778 + exception ex_zero_div_not_allowed using( v_min ); + when any do + exception; + end + + suspend; + end + ^ + set term ;^ + commit; + + select * from sp_min; + + select * from sp_max; + + select * from sp_zero_div(0); + + select * from sp_zero_div( '-170141183460469231731687303715884105728' ); + + select * from sp_zero_div( '170141183460469231731687303715884105727' ); + rollback; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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 (V_TEST0 TEST0 ORDER TEST0_I_MIN_DEC) + MAX -170141183460469231731687303715884105728 + PLAN (V_TEST0 TEST0 ORDER TEST0_I_MIN_ASC) + MIN -170141183460469231731687303715884105728 + PLAN (V_TEST0 TEST0 ORDER TEST0_I_MAX_DEC) + MAX 170141183460469231731687303715884105727 + PLAN (V_TEST0 TEST0 ORDER 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 + V_MIN -170141183460469231731687303715884105728 + V_MIN 170141183460469231731687303715884105727 + P_MIN 170141183460469231731687303715884105727 + P_MAX -170141183460469231731687303715884105728 + P_MIN 1 + P_MIN -1 + """ +expected_stderr_1 = """ + 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" + Statement failed, SQLSTATE = HY000 + exception 1 + -EX_ZERO_DIV_NOT_ALLOWED + -Can not delete -170141183460469231731687303715884105728 by zero + -At procedure 'SP_ZERO_DIV' line: 8, col: 12 + """ + +@pytest.mark.version('>=4.0') +def test_core_6353_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6355.py b/tests/bugs/test_core_6355.py new file mode 100644 index 00000000..72b451aa --- /dev/null +++ b/tests/bugs/test_core_6355.py @@ -0,0 +1,63 @@ +#coding:utf-8 +# +# id: bugs.core_6355 +# title: TRUNC() does not accept second argument = -128 (but shows it as required boundary in error message) +# decription: +# Checked on 4.0.0.2091 - all OK. +# (intermediate snapshot with timestamp: 08.07.20 15:10) +# +# tracker_id: CORE-6355 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + select trunc(0,-128) from rdb$database; + select trunc(9223372036854775807,-128) from rdb$database; + select trunc(170141183460469231731687303715884105727,-128) from rdb$database; + select trunc(-9223372036854775808,-128) from rdb$database; + select trunc(-170141183460469231731687303715884105728,-128) from rdb$database; + + -- (optional) check upper bound (127): + select trunc(0,127) from rdb$database; + select trunc(9223372036854775807,127) from rdb$database; + select trunc(170141183460469231731687303715884105727,127) from rdb$database; + select trunc(-9223372036854775808,127) from rdb$database; + select trunc(-170141183460469231731687303715884105728,127) from rdb$database; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 0 + 0 + 0 + 0 + 0 + 0 + 9223372036854775807 + 170141183460469231731687303715884105727 + -9223372036854775808 + -170141183460469231731687303715884105728 + """ + +@pytest.mark.version('>=4.0') +def test_core_6355_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6356.py b/tests/bugs/test_core_6356.py new file mode 100644 index 00000000..860b3246 --- /dev/null +++ b/tests/bugs/test_core_6356.py @@ -0,0 +1,66 @@ +#coding:utf-8 +# +# id: bugs.core_6356 +# title: ROUND() does not allow second argument >=1 when its first argument is more than MAX_BIGINT / 10 +# decription: +# Checked on 4.0.0.2091 - all OK. +# (intermediate snapshot with timestamp: 08.07.20 15:10) +# +# tracker_id: CORE-6356 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + select round( 9223372036854775807, 1) from rdb$database; + select round( 170141183460469231731687303715884105727, 1) from rdb$database; + + + select round( -9223372036854775808, 1) from rdb$database; + select round( -170141183460469231731687303715884105728, 1) from rdb$database; + + select round( 9223372036854775807, 127) from rdb$database; + select round( 170141183460469231731687303715884105727, 127) from rdb$database; + + select round( -9223372036854775808, -128) from rdb$database; + select round( -170141183460469231731687303715884105728, -128) from rdb$database; + + select round( -9223372036854775808, 127) from rdb$database; + select round( -170141183460469231731687303715884105728, 127) from rdb$database; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 9223372036854775807 + 170141183460469231731687303715884105727 + -9223372036854775808 + -170141183460469231731687303715884105728 + 9223372036854775807 + 170141183460469231731687303715884105727 + 0 + 0 + -9223372036854775808 + -170141183460469231731687303715884105728 + """ + +@pytest.mark.version('>=4.0') +def test_core_6356_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6357.py b/tests/bugs/test_core_6357.py new file mode 100644 index 00000000..de691bf1 --- /dev/null +++ b/tests/bugs/test_core_6357.py @@ -0,0 +1,148 @@ +#coding:utf-8 +# +# id: bugs.core_6357 +# title: LEAD() and LAG() do not allow to specify 3rd argument ("DEFAULT" value when pointer is out of scope) of INT128 datatype. +# decription: +# Checked on 4.0.0.2091 - all OK. +# (intermediate snapshot with timestamp: 08.07.20 15:10) +# +# tracker_id: CORE-6357 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('^((?!sqltype|FIELD_A|LAG_FOR|LEAD_FOR).)*$', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + recreate table test1 (a smallint); + recreate table test2 (a bigint); + recreate table test3 (a int128); + recreate table test4 (a decfloat); + + insert into test1 values (1); + insert into test1 values (2); + + insert into test2 select * from test1; + insert into test3 select * from test1; + insert into test4 select * from test1; + + set list on; + set sqlda_display on; + + select a as field_a, lead(a, 1, 32767)over(order by a) lead_for_smallint from test1; + select a as field_a, lag(a, 1, -32768)over(order by a) lag_for_smallint from test1; + + select a as field_a, lead(a, 1, 9223372036854775807)over(order by a) lead_for_bigint from test2; + select a as field_a, lag(a, 1, -9223372036854775808)over(order by a) lag_for_bigint from test2; + + select a as field_a, lead(a, 1, 170141183460469231731687303715884105727)over(order by a) lead_for_int128 from test3; + select a as field_a, lag(a, 1, -170141183460469231731687303715884105728)over(order by a) lag_for_int128 from test3; + + select a as field_a, lag(a, 1, -9.999999999999999999999999999999999e6144) over (order by a) lag_for_decfloat_1 from test4; + select a as field_a, lag(a, 1, -1.0e-6143)over(order by a) lag_for_decfloat_2 from test4; + select a as field_a, lag(a, 1, 1.0e-6143)over(order by a) lag_for_decfloat_3 from test4; + select a as field_a, lag(a, 1, 9.999999999999999999999999999999999e6144)over(order by a) lag_for_decfloat_4 from test4; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 01: sqltype: 500 SHORT Nullable scale: 0 subtype: 0 len: 2 + : name: A alias: FIELD_A + 02: sqltype: 500 SHORT Nullable scale: 0 subtype: 0 len: 2 + : name: LEAD alias: LEAD_FOR_SMALLINT + FIELD_A 1 + LEAD_FOR_SMALLINT 2 + FIELD_A 2 + LEAD_FOR_SMALLINT 32767 + 01: sqltype: 500 SHORT Nullable scale: 0 subtype: 0 len: 2 + : name: A alias: FIELD_A + 02: sqltype: 500 SHORT Nullable scale: 0 subtype: 0 len: 2 + : name: LAG alias: LAG_FOR_SMALLINT + FIELD_A 1 + LAG_FOR_SMALLINT -32768 + FIELD_A 2 + LAG_FOR_SMALLINT 1 + 01: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: A alias: FIELD_A + 02: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: LEAD alias: LEAD_FOR_BIGINT + FIELD_A 1 + LEAD_FOR_BIGINT 2 + FIELD_A 2 + LEAD_FOR_BIGINT 9223372036854775807 + 01: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: A alias: FIELD_A + 02: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: LAG alias: LAG_FOR_BIGINT + FIELD_A 1 + LAG_FOR_BIGINT -9223372036854775808 + FIELD_A 2 + LAG_FOR_BIGINT 1 + 01: sqltype: 32752 INT128 Nullable scale: 0 subtype: 0 len: 16 + : name: A alias: FIELD_A + 02: sqltype: 32752 INT128 Nullable scale: 0 subtype: 0 len: 16 + : name: LEAD alias: LEAD_FOR_INT128 + FIELD_A 1 + LEAD_FOR_INT128 2 + FIELD_A 2 + LEAD_FOR_INT128 170141183460469231731687303715884105727 + 01: sqltype: 32752 INT128 Nullable scale: 0 subtype: 0 len: 16 + : name: A alias: FIELD_A + 02: sqltype: 32752 INT128 Nullable scale: 0 subtype: 0 len: 16 + : name: LAG alias: LAG_FOR_INT128 + FIELD_A 1 + LAG_FOR_INT128 -170141183460469231731687303715884105728 + FIELD_A 2 + LAG_FOR_INT128 1 + 01: sqltype: 32762 DECFLOAT(34) Nullable scale: 0 subtype: 0 len: 16 + : name: A alias: FIELD_A + 02: sqltype: 32762 DECFLOAT(34) Nullable scale: 0 subtype: 0 len: 16 + : name: LAG alias: LAG_FOR_DECFLOAT_1 + FIELD_A 1 + LAG_FOR_DECFLOAT_1 -9.999999999999999999999999999999999E+6144 + FIELD_A 2 + LAG_FOR_DECFLOAT_1 1 + 01: sqltype: 32762 DECFLOAT(34) Nullable scale: 0 subtype: 0 len: 16 + : name: A alias: FIELD_A + 02: sqltype: 32762 DECFLOAT(34) Nullable scale: 0 subtype: 0 len: 16 + : name: LAG alias: LAG_FOR_DECFLOAT_2 + FIELD_A 1 + LAG_FOR_DECFLOAT_2 -1.0E-6143 + FIELD_A 2 + LAG_FOR_DECFLOAT_2 1 + 01: sqltype: 32762 DECFLOAT(34) Nullable scale: 0 subtype: 0 len: 16 + : name: A alias: FIELD_A + 02: sqltype: 32762 DECFLOAT(34) Nullable scale: 0 subtype: 0 len: 16 + : name: LAG alias: LAG_FOR_DECFLOAT_3 + FIELD_A 1 + LAG_FOR_DECFLOAT_3 1.0E-6143 + FIELD_A 2 + LAG_FOR_DECFLOAT_3 1 + 01: sqltype: 32762 DECFLOAT(34) Nullable scale: 0 subtype: 0 len: 16 + : name: A alias: FIELD_A + 02: sqltype: 32762 DECFLOAT(34) Nullable scale: 0 subtype: 0 len: 16 + : name: LAG alias: LAG_FOR_DECFLOAT_4 + FIELD_A 1 + LAG_FOR_DECFLOAT_4 9.999999999999999999999999999999999E+6144 + FIELD_A 2 + LAG_FOR_DECFLOAT_4 1 + """ + +@pytest.mark.version('>=4.0') +def test_core_6357_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6358.py b/tests/bugs/test_core_6358.py new file mode 100644 index 00000000..0ae6c611 --- /dev/null +++ b/tests/bugs/test_core_6358.py @@ -0,0 +1,121 @@ +#coding:utf-8 +# +# id: bugs.core_6358 +# title: Adding NOT NULL column with DEFAULT value may cause default values to update when selecting or have the wrong charset +# decription: +# Confirmed bug on 4.0.0.2089 +# Checked on 4.0.0.2090 - all OK. +# (intermediate snapshot with timestamps: 07-JUL-2020, 18:06) +# +# Checked on 3.0.7.33340 - all OK +# (intermediate snapshot with timestamps: 10-JUL-2020, 15:50) +# +# tracker_id: CORE-6358 +# min_versions: ['3.0.7'] +# versions: 3.0.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.7 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + -- Part 1: adding field of timestamp datatype with default value = 'now' + -- ####### + + create table tdelay(id int primary key); + create sequence g; + set term ^; + create procedure sp_delay returns( dts1 timestamp, dts2 timestamp, elap_ms int ) as + declare c int; + declare v_id int; + begin + execute statement 'select count(*) from rdb$database /* do you really think that i am in work now ? */' into c; + v_id = gen_id(g,1); + dts1 = cast('now' as timestamp); + insert into tdelay(id) values( :v_id ); + in autonomous transaction do + begin + execute statement ('insert into tdelay(id) values(?)') ( :v_id ); + when any do + begin + -- nop -- + end + end + delete from tdelay where id = :v_id; + dts2 = cast('now' as timestamp); + elap_ms = datediff( millisecond from dts1 to dts2); + suspend; + end + ^ + set term ;^ + commit; + + ----------------------------- + recreate table t (n integer); + insert into t values (1); + commit; + alter table t add dts timestamp default 'now' not null; + commit; + ----------------------------- + + set transaction lock timeout 1; + -- ^^^ ### DELAY ### + set term ^; + execute block returns( diff_ms int ) as + declare c int; + declare t1 timestamp; + declare t2 timestamp; + begin + select dts from t into t1; + + -- HERE WE MAKE DELAY: + -- ################### + select count(*) from sp_delay p into c; + + select dts from t into t2; + diff_ms = datediff(millisecond from t1 to t2); + suspend; + end^ + set term ;^ + + + -- Part 2: adding field with charset that differs from current client connection charset. + --################################## + + recreate table t2 (n integer); + insert into t2 values (1); + commit; + alter table t2 add c1 varchar(10) character set win1252 default '123áé456' not null; + insert into t2 (n) values (2); + select * from t2; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DIFF_MS 0 + + N 1 + C1 123áé456 + N 2 + C1 123áé456 + """ + +@pytest.mark.version('>=3.0.7') +def test_core_6358_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6362.py b/tests/bugs/test_core_6362.py new file mode 100644 index 00000000..b6cd2291 --- /dev/null +++ b/tests/bugs/test_core_6362.py @@ -0,0 +1,184 @@ +#coding:utf-8 +# +# id: bugs.core_6362 +# title: Better diagnostic when 'Missing security context' +# decription: +# ::: NB ::: +# List of AuthClient plugins must contain Win_Sspi in order to reproduce this test expected results. +# Otherwise firebird.log will not contain any message like "Available context(s): ..." +# +# Checked on 3.0.7.33348, 4.0.0.2119 (SS/CS): OK. +# +# 01-mar-2021: attribute 'platform' was restricted to 'Windows'. +# 05-mar-2021: list of plugins specified in AuthServer *also* must contain Win_Sspi. +# +# 11-mar-2021. As of FB 3.x, messages appears in the firebird.log more than one time. +# Because of this, we are interested only for at least one occurence of each message +# rather than for each of them (see 'found_patterns', type: set()). +# +# tracker_id: CORE-6362 +# min_versions: ['3.0.7'] +# versions: 3.0.7 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.7 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import re +# import difflib +# from fdb import services +# import time +# +# os.unsetenv("ISC_USER") +# os.unsetenv("ISC_PASSWORD") +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# def svc_get_fb_log( f_fb_log ): +# +# global subprocess +# subprocess.call( [ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# "user", user_name, +# "password", user_password, +# "action_get_fb_log" +# ], +# stdout=f_fb_log, stderr=subprocess.STDOUT +# ) +# return +# +# #-------------------------------------------- +# +# # Get FB log *before* unsuccessful attempt to obtain server version: +# ##################### +# +# f_fblog_before=open( os.path.join(context['temp_directory'],'tmp_6362_fblog_before.txt'), 'w') +# svc_get_fb_log( f_fblog_before ) +# flush_and_close( f_fblog_before ) +# +# f_svc_log=open( os.path.join(context['temp_directory'],'tmp_6362_info_server.log'), 'w') +# f_svc_err=open( os.path.join(context['temp_directory'],'tmp_6362_info_server.err'), 'w') +# +# # This must FAIL because we do not specify user/password pair and there absent in OS env.: +# ################ +# subprocess.call( [context['fbsvcmgr_path'], 'localhost:service_mgr', 'info_server_version'], stdout=f_svc_log, stderr=f_svc_err ) +# flush_and_close( f_svc_log ) +# flush_and_close( f_svc_err ) +# +# # Get FB log *after* unsuccessful attempt to obtain server version: +# #################### +# f_fblog_after=open( os.path.join(context['temp_directory'],'tmp_6362_fblog_after.txt'), 'w') +# svc_get_fb_log( f_fblog_after ) +# flush_and_close( f_fblog_after ) +# +# old_fb_log=open(f_fblog_before.name, 'r') +# new_fb_log=open(f_fblog_after.name, 'r') +# +# fb_log_diff = ''.join(difflib.unified_diff( +# old_fb_log.readlines(), +# new_fb_log.readlines() +# )) +# old_fb_log.close() +# new_fb_log.close() +# +# f_diff=open( os.path.join(context['temp_directory'],'tmp_6362_fblog_diff.txt'), 'w') +# f_diff.write(fb_log_diff) +# flush_and_close( f_diff ) +# +# # Missing security context required for C:\\FB SS\\SECURITY4.FDB +# # Available context(s): USER IMAGE-PC1\\PASHAZ plugin Win_Sspi +# +# allowed_patterns = ( +# re.compile('Missing\\s+security\\s+context\\.*', re.IGNORECASE) +# ,re.compile('Available context\\.*', re.IGNORECASE) +# ) +# found_patterns = set() +# +# print('Error message on attempt to get server version w/o user/password and ISC_USER/ISC_PASSWORD:') +# with open( f_svc_err.name,'r') as f: +# for line in f: +# print(line) +# +# with open( f_diff.name,'r') as f: +# for line in f: +# if line.startswith('+'): +# for p in allowed_patterns: +# if p.search(line): +# found_patterns.add( p.pattern ) +# +# print('Found patterns in firebird.log diff file:') +# for p in sorted(found_patterns): +# print(p) +# +# +# # Cleanup. +# ########## +# time.sleep(1) +# cleanup( (f_svc_log, f_svc_err, f_fblog_before, f_fblog_after, f_diff) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Error message on attempt to get server version w/o user/password and ISC_USER/ISC_PASSWORD: + Missing security context for services manager + + Found patterns in firebird.log diff file: + Available context\\.* + Missing\\s+security\\s+context\\.* + """ + +@pytest.mark.version('>=3.0.7') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_6362_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6377.py b/tests/bugs/test_core_6377.py new file mode 100644 index 00000000..be17c585 --- /dev/null +++ b/tests/bugs/test_core_6377.py @@ -0,0 +1,120 @@ +#coding:utf-8 +# +# id: bugs.core_6377 +# title: Unable to restore database with tables using GENERATED ALWAYS AS IDENTITY columns (ERROR:OVERRIDING SYSTEM VALUE should be used) +# decription: +# Confirmed on 4.0.0.2126, got in STDERR when restore: +# gbak: ERROR:OVERRIDING SYSTEM VALUE should be used to override the value of an identity column defined as 'GENERATED ALWAYS' in table/view IDENTITY_ALWAYS +# gbak: ERROR:gds_$compile_request failed +# gbak:Exiting before completion due to errors +# +# Checked on 4.0.0.2170 SS/CS -- all fine. +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create table identity_always(id bigint generated always as identity constraint pk_identity_always primary key); + insert into identity_always default values; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# from subprocess import PIPE +# from fdb import services +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# # https://docs.python.org/2/library/subprocess.html#replacing-shell-pipeline +# +# tmp_restdb = os.path.join(context['temp_directory'],'tmp_6377_rest.fdb') +# cleanup( (tmp_restdb,) ) +# +# f_br_err=open( os.path.join(context['temp_directory'],'tmp_6377_br.err'), 'w') +# p_sender = subprocess.Popen( [ context['gbak_path'], '-b', dsn, 'stdout' ], stdout=PIPE) +# p_getter = subprocess.Popen( [ context['gbak_path'], '-rep', 'stdin', 'localhost:' + tmp_restdb ], stdin = p_sender.stdout, stdout = PIPE, stderr = f_br_err) +# p_sender.stdout.close() +# p_getter_stdout, p_getter_stderr = p_getter.communicate() +# +# flush_and_close(f_br_err) +# +# # This must PASS without errors: +# runProgram('isql', [ 'localhost:' + tmp_restdb ], 'insert into identity_always default values;') +# +# # CHECK RESULTS +# ############### +# with open(f_br_err.name,'r') as g: +# for line in g: +# if line: +# print( 'UNEXPECTED STDERR IN ' + g.name + ':' + line) +# +# # Cleanup. +# ########## +# time.sleep(1) +# cleanup( (f_br_err,tmp_restdb ) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_6377_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6379.py b/tests/bugs/test_core_6379.py new file mode 100644 index 00000000..bb465f79 --- /dev/null +++ b/tests/bugs/test_core_6379.py @@ -0,0 +1,211 @@ +#coding:utf-8 +# +# id: bugs.core_6379 +# title: Bugcheck 179 +# decription: +# Could not reproduce with scenario described in the ticket. +# Test uses steps described by letter from me to Vlad, date: 15-JUL-2020 10:53 (subj: "read consistency tests"). +# Scripts for initial test can be found here: +# https://drive.google.com/drive/folders/1CEOSVfOMHzlZ1F3Gi0Jv3TEbvWLs9DPR?usp=sharing +# +# Reproduced problem on 4.0.0.2108 SS: +# 1. Content of firebird.log: +# deadlock +# update conflicts with concurrent update +# concurrent transaction number is 12 +# internal Firebird consistency check (wrong record version (185), file: Savepoint.cpp line: 267) +# 2. Client gets: +# Statement failed, SQLSTATE 08006 +# Error reading data from the connection. +# +# Statement failed, SQLSTATE 08006 +# Error writing data to the connection. +# -send_packet/send +# +# Checked on 4.0.0.2170 SS/CS - all fine. +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# from subprocess import Popen +# from fdb import services +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql_init=''' +# create table test(id int generated by default as identity, x int, s varchar(32765) ); +# set term ^; +# execute block as +# declare n_limit int = 1000; +# declare i int = 1; +# begin +# rdb$set_context('USER_SESSION', 'N_LIMIT', n_limit); +# while (i <= n_limit) do +# begin +# insert into test(x, s) values(0, lpad('', 32765, gen_uuid())); +# i = i + 1; +# end +# end +# ^ +# set term ^; +# commit; +# +# delete from test order by id rows ( cast( rdb$get_context('USER_SESSION', 'N_LIMIT') as int) - 13 ); +# commit; +# ''' +# runProgram('isql', [ dsn, '-q' ], sql_init) +# +# con_lock_1 = fdb.connect( dsn = dsn ) +# con_lock_2 = fdb.connect( dsn = dsn ) +# +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# con_lock_1.execute_immediate( 'update test set x = -1111 order by id rows 6 to 6' ) +# +# +# # Scenario for WORKER: +# ###################### +# sql_text=''' +# connect '%(dsn)s'; +# set autoddl off; +# commit; +# set transaction read committed read consistency; +# set count on; +# +# set bail on; +# delete from test; +# +# set heading on; +# select rdb$db_key, id, x from test order by rdb$db_key; +# ''' % dict(globals(), **locals()) +# +# f_worker_sql=open( os.path.join(context['temp_directory'],'tmp_6379.sql'), 'w') +# f_worker_sql.write(sql_text) +# flush_and_close(f_worker_sql) +# +# f_worker_log=open( ''.join( ( os.path.splitext(f_worker_sql.name)[0], '.log') ), 'w') +# f_worker_err=open( ''.join( ( os.path.splitext(f_worker_log.name)[0], '.err') ), 'w') +# +# ############################################################################ +# ### L A U N C H W O R K E R U S I N G I S Q L, A S Y N C. ### +# ############################################################################ +# +# p_worker = Popen( [ context['isql_path'], '-pag', '9999', '-q', '-i', f_worker_sql.name ],stdout=f_worker_log, stderr=f_worker_err) +# time.sleep(1) +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# con_lock_2.execute_immediate( 'insert into test(x) values(3333)' ) +# con_lock_2.commit() +# +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# con_lock_1.commit() +# con_lock_2.commit() +# +# # Here we wait for ISQL complete its mission: +# p_worker.wait() +# +# flush_and_close(f_worker_log) +# flush_and_close(f_worker_err) +# +# # Close lockers: +# ################ +# for c in (con_lock_1, con_lock_2): +# c.close() +# +# +# # CHECK RESULTS +# ############### +# with open(f_worker_log.name,'r') as f: +# for line in f: +# print(line) +# +# with open(f_worker_err.name,'r') as g: +# for line in g: +# if line: +# print( 'UNEXPECTED STDERR IN ' + g.name + ':' + line) +# +# +# # Cleanup. +# ########## +# time.sleep(1) +# cleanup( (f_worker_sql, f_worker_log, f_worker_err) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 14 + Records affected: 0 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_6379_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6382.py b/tests/bugs/test_core_6382.py new file mode 100644 index 00000000..7dbf13bd --- /dev/null +++ b/tests/bugs/test_core_6382.py @@ -0,0 +1,97 @@ +#coding:utf-8 +# +# id: bugs.core_6382 +# title: FK-trigger accessing a table prevents concurrent DDL command from dropping that table +# decription: +# Test creates two tables which are linked by master-detail relationship. +# We add one record into the main table and then update it with issuing further COMMIT. +# After this we try to DROP this table in another connect. +# +# If this connect started WAIT transaction (i.e. without lock timeout) then it can hang forever if case of +# regression of this fix. Because of this, we change its waiting mode by adding lock_timeout parameter to +# TPB and set it to 1 second. +# +# BEFORE fix this lead to: +# DatabaseError: / Error while commiting transaction: / - SQLCODE: -901 +# - lock time-out on wait transaction / - unsuccessful metadata update +# - object TABLE "T_DETL" is in use / -901 / 335544510 +# +# AFTER fix this DROP TABLE statement must pass without any error. +# +# Checked on 4.0.0.2141. +# +# tracker_id: CORE-6382 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table t_detl(id int primary key using index t_detl_pk, pid int); + recreate table t_main(id int primary key using index t_main_pk); + alter table t_detl add constraint t_detl_fk foreign key(pid) references t_main(id) on update cascade using index t_detl_fk; + commit; + insert into t_main values(123); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import fdb +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# custom_tpb = fdb.TPB() +# custom_tpb.lock_resolution = fdb.isc_tpb_wait +# +# # NB: adding this timeout does NOT change WAIT-nature of transaction as it is considered by engine. +# # (in other words: such transaction will not became 'no wait' which must not be used in this test): +# custom_tpb.lock_timeout = 1 +# +# con1 = fdb.connect( dsn = dsn, isolation_level = custom_tpb) +# con2 = fdb.connect( dsn = dsn, isolation_level = custom_tpb) +# +# con1.execute_immediate('update t_main set id=-id') +# con1.commit() +# +# con2.execute_immediate('drop table t_detl') +# con2.commit() +# +# cur=con2.cursor() +# cur.execute( "select r.rdb$relation_name from rdb$database d left join rdb$relations r on r.rdb$relation_name = upper('t_detl')" ) +# for r in cur: +# print(r[0]) +# cur.close() +# con2.close() +# con1.close() +# +# print('Passed.') +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + None + Passed. + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_6382_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6385.py b/tests/bugs/test_core_6385.py new file mode 100644 index 00000000..88247ab5 --- /dev/null +++ b/tests/bugs/test_core_6385.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: bugs.core_6385 +# title: Wrong line and column information after IF statement +# decription: +# DO NOT make indentation or excessive empty lines in the code that is executed by ISQL. +# Checked on 4.0.0.2170. +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('^((?!At\\s+block\\s+line).)*$', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ +set term ^; +execute block +as + declare n integer; +begin + if (1 = 1) then + n = 1; + n = n / 0; +end^ +set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ +-At block line: 7, col: 5 + """ + +@pytest.mark.version('>=4.0') +def test_core_6385_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_6389.py b/tests/bugs/test_core_6389.py new file mode 100644 index 00000000..2f53ec72 --- /dev/null +++ b/tests/bugs/test_core_6389.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: bugs.core_6389 +# title: Using binary string literal to assign to user-defined blob sub-types yield conversion error "filter not found to convert type 1 to type -13" +# decription: +# Confirmed bug on 4.0.0.2087. +# Checked on 4.0.0.2170 -- all fine. +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table blob13(id integer generated by default as identity primary key, blobfield blob sub_type -13); + commit; + -- This must pass w/o errors: + insert into blob13 (blobfield) values (x'ab01'); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=4.0') +def test_core_6389_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_6392.py b/tests/bugs/test_core_6392.py new file mode 100644 index 00000000..88fc52d6 --- /dev/null +++ b/tests/bugs/test_core_6392.py @@ -0,0 +1,236 @@ +#coding:utf-8 +# +# id: bugs.core_6392 +# title: Space in database path prevent working gbak -se ... -b "pat to/database" backup +# decription: +# Test creates windows BATCH file for main job: +# * create folder with spaces and some non-alphabetic characters (use "[", "]", "(", ")" etc); +# * create .sql script which will make database with spaces and non-alphabetic characters in this folder; +# * try to backup and restore using "simple" gbak commend (i.e. without "-se" command switch); +# * try to backup and restore using "-se" command switch; +# * try to backup and restore using services manager. +# Batch output is redirected to log and then we parse this log with expectation to find there messages +# which prove successful results for each action. +# +# Confirmed bug on 4.0.0.2173. +# Checked on 3.0.7.33358; 4.0.0.2180 SS/SC/CS: all fine. +# +# ::: NOTE ::: +# Some problem still exists when DB file or folder has name which last character is '.' or ' ' (dot or space). +# Database will be created but attempt to backup raises: "gbak: ERROR:cannot open backup file ..." +# +# tracker_id: CORE-6392 +# min_versions: ['3.0.7'] +# versions: 3.0.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.7 +# resources: None + +substitutions_1 = [('[\t ]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import time +# import subprocess +# import re +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# #--------------------------------------------- +# +# 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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# #-------------------------------------------- +# +# fb_home = os.path.split( services.connect(host='localhost', user= user_name, password= user_password).get_home_directory() )[0] +# db_conn.close() +# +# # tmpdir='c:\\\\temp\\\\folder with spaces ' +# # gbak: ERROR:cannot open backup file c: emp +# older with spaces \\db with spaces. . .fbk +# +# # tmpdir='c:\\\\temp\\\\folder with spaces..' +# # gbak: ERROR:cannot open backup file c: emp +# older with spaces..\\db with spaces. . .fbk +# +# #tmpdir='c:\\\\temp\\\\^!very strange^! folder with (many) spaces; created temporary, only for core-6392^! ' +# +# #dbname='(strange name^!) DB with #lot# of excessive spaces; created temporary, only for core-6392^!. . .fdb' +# # gbak: ERROR:cannot open backup file // but database is created OK. +# +# #dbname='(strange name^!) DB with #lot# of excessive spaces, created temporary, only for core-6392^!. . .fdb' +# # gbak: ERROR:cannot open backup file // but database is created OK. +# +# tmpdir='c:\\\\temp\\\\ [[[ strange ]]] folder with {{{ lot of }}} spaces^!' +# dbname='DB with very^! ))) strange ((( name; created for core-6392.fdb' +# +# bkname=( '.'.join( dbname.split('.')[:-1] )+'.fbk' if '.' in dbname else dbname+'.fbk' ) +# +# extbat=os.path.join(context['temp_directory'],'tmp_6392.bat') +# extlog=os.path.splitext(extbat)[0]+'.log' +# exterr=os.path.splitext(extbat)[0]+'.err' +# +# chksql="iif( upper(mon$database_name) = upper( q'{%(tmpdir)s\\%(dbname)s}' ), 'SUCCESS.', '### ERROR: DB HAS DIFFERENT NAME ###')" % locals() +# chksql=chksql.replace('^', '^^').replace(')', '^)') +# # echo select 'c: emp\\ [[[ strange ]]] folder with {{{ lot of }}} spaces^^!\\DB with very^^! ^)^)^) strange ((( name; created for core-6392.fdb' from rdb$database; +# +# runcmd=''' +# @echo off +# setlocal enabledelayedexpansion enableextensions +# set ISC_USER=%(user_name)s +# set ISC_PASSWORD=%(user_password)s +# set FB_HOME=%(fb_home)s\\\\ +# +# set tmpsql=%%~dpn0.sql +# +# del %(extlog)s 2>nul +# +# mkdir "%(tmpdir)s" 2>nul +# if exist "%(tmpdir)s" ( +# echo Directory created OK. +# ) else ( +# echo Could NOT create directory "%(tmpdir)s". ABEND. +# goto :final +# ) +# +# if exist "%(tmpdir)s\\%(dbname)s" del "%(tmpdir)s\\%(dbname)s" +# +# ( +# echo set bail on; +# echo create database "%(tmpdir)s\\%(dbname)s"; +# echo set list on; +# echo select %(chksql)s as "CHECK POINT. Result:" from mon$database; +# ) > !tmpsql! +# +# echo CHECK POINT. Trying to create database. +# !FB_HOME!isql.exe -q -i !tmpsql! +# +# del !tmpsql! +# +# echo CHECK POINT. Trying to BACKUP without "-se" switch. +# !FB_HOME!gbak.exe -b -verbi 999999 -st tdrw localhost:"%(tmpdir)s\\%(dbname)s" "%(tmpdir)s\\%(bkname)s" +# if exist "%(tmpdir)s\\%(bkname)s" ( +# echo CHECK POINT. Trying to restore without "-se". +# !FB_HOME!gbak.exe -rep -verbi 999999 -st tdrw "%(tmpdir)s\\%(bkname)s" localhost:"%(tmpdir)s\\%(dbname)s" +# ) +# +# echo. +# echo CHECK POINT. Trying to backup using gbak WITH "-se" switch. +# if exist "%(tmpdir)s\\%(bkname)s" del "%(tmpdir)s\\%(bkname)s" +# !FB_HOME!gbak.exe -b -verbi 999999 -st tdrw -se localhost:service_mgr "%(tmpdir)s\\%(dbname)s" "%(tmpdir)s\\%(bkname)s" +# if exist "%(tmpdir)s\\%(bkname)s" ( +# echo CHECK POINT. Trying to restore using gbak WITH "-se" switch. +# !FB_HOME!gbak.exe -rep -verbi 999999 -st tdrw -se localhost:service_mgr "%(tmpdir)s\\%(bkname)s" "%(tmpdir)s\\%(dbname)s" +# ) +# +# echo. +# echo CHECK POINT. Trying to backup using fbsvcmgr. +# if exist "%(tmpdir)s\\%(bkname)s" del "%(tmpdir)s\\%(bkname)s" +# +# !FB_HOME!fbsvcmgr.exe localhost:service_mgr action_backup dbname "%(tmpdir)s\\%(dbname)s" bkp_file "%(tmpdir)s\\%(bkname)s" verbint 999999 bkp_stat tdrw +# if exist "%(tmpdir)s\\%(bkname)s" ( +# echo CHECK POINT. Trying to restore using fbsvcmgr. +# !FB_HOME!fbsvcmgr.exe localhost:service_mgr action_restore res_replace bkp_file "%(tmpdir)s\\%(bkname)s" dbname "%(tmpdir)s\\%(dbname)s" verbint 999999 res_stat tdrw +# ) +# +# :final +# if exist "%(tmpdir)s\\%(dbname)s" del "%(tmpdir)s\\%(dbname)s" +# if exist "%(tmpdir)s\\%(bkname)s" del "%(tmpdir)s\\%(bkname)s" +# rmdir "%(tmpdir)s" +# echo Bye-bye from %%~f0 +# ''' % dict(globals(), **locals()) +# +# f_extbat=open( extbat, 'w' ) +# f_extbat.write(runcmd) +# flush_and_close(f_extbat) +# +# f_extlog=open( extlog, 'w' ) +# subprocess.call( [ extbat ], stdout = f_extlog, stderr = subprocess.STDOUT ) +# flush_and_close(f_extlog) +# +# allowed_patterns = [ re.compile(p, re.IGNORECASE) for p in +# ( +# 'check\\s+point' +# ,'closing\\s+file(,)?\\s+committing(,)?\\s+.*finishing' +# ,'finishing(,)?\\s+closing(,)?\\s+.*going\\s+home' +# ) +# ] +# +# with open(f_extlog.name, 'r') as f: +# for line in f: +# if 'gbak: ERROR' in line: +# print('UNEXPECTED ERROR occured: ' + line) +# else: +# for p in allowed_patterns: +# if p.search(line): +# print( (line if 'CHECK POINT' in line else p.search(line).group() ) ) +# +# # CLEANUP +# ######### +# time.sleep(1) +# #cleanup( [extbat, extlog] ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CHECK POINT. Trying to create database. + CHECK POINT. Result: SUCCESS. + + CHECK POINT. Trying to BACKUP without "-se" switch. + closing file, committing, and finishing + + CHECK POINT. Trying to restore without "-se". + finishing, closing, and going home + + CHECK POINT. Trying to backup using gbak WITH "-se" switch. + closing file, committing, and finishing + + CHECK POINT. Trying to restore using gbak WITH "-se" switch. + finishing, closing, and going home + + CHECK POINT. Trying to backup using fbsvcmgr. + closing file, committing, and finishing + + CHECK POINT. Trying to restore using fbsvcmgr. + finishing, closing, and going home + """ + +@pytest.mark.version('>=3.0.7') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_6392_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6395.py b/tests/bugs/test_core_6395.py new file mode 100644 index 00000000..11042aef --- /dev/null +++ b/tests/bugs/test_core_6395.py @@ -0,0 +1,186 @@ +#coding:utf-8 +# +# id: bugs.core_6395 +# title: Allow usage of time zone displacement in config DefaultTimeZone +# decription: +# We make backup of current firebird.conf for changing it two times: +# 1. Add line with DefaultTimeZone = -7:00 and get local time by making *LOCAL* connect to current DB; +# 2. Restore previous firebird.conf from its .bak-copy do second change: add line with DefaultTimeZone = 7:00. +# Then we run second local connect. +# +# Each connect will ask FB to return CURRENT_TIME value (with casting it to '%H:%M:%S' format). +# Expected result: values must change from 1st to 2nd run for 14 hours (840 minutes). +# +# ::: NB ::: +# 1. Affect of changed parameter DefaultTimeZone can be seen only if DB is attached using LOCAL protocol. +# 2. FDB driver loads client library only *once* before this test launch and, in turn, this library reads firebird.conf. +# For this reason we have to launch separate (child) process two times, which will be forced to load firebird.conf +# every launch. This is why subprocess.call(['isql', ...]) is needed here rather than just query DB using cursor of +# pre-existing db_conn connection (see routine 'get_local_time'). +# +# Confirmed improvement on 4.0.0.2185. +# Value of time did not differ on previous builds (checked 4..0.2170). +# +# +# tracker_id: CORE-6395 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import sys +# import os +# import shutil +# import socket +# import getpass +# import time +# import datetime +# from datetime import timedelta +# import subprocess +# from fdb import services +# +# db_name=db_conn.database_name +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# def get_local_time( fb_home, db_name ): +# +# global flush_and_close +# global subprocess +# global cleanup +# +# sql_chk='select substring( cast(cast(current_time as time) as varchar(13)) from 1 for 8) from rdb$database' +# +# f_connect_sql = open( os.path.join(context['temp_directory'],'tmp_6396_check.sql'), 'w') +# f_connect_sql.write('set heading off; ' + sql_chk + ';' ) +# flush_and_close( f_connect_sql ) +# +# f_connect_log=open( os.path.join(context['temp_directory'],'tmp_6396_check.log'), 'w') +# subprocess.call( [ context['isql_path'], db_name, "-i", f_connect_sql.name ], stdout=f_connect_log, stderr=subprocess.STDOUT ) +# flush_and_close( f_connect_log ) +# +# changed_time = '00:00:00' +# with open(f_connect_log.name,'r') as f: +# for line in f: +# if line.split(): +# changed_time = line.strip() +# +# cleanup( [x.name for x in (f_connect_sql, f_connect_log)] ) +# return changed_time +# +# #--------------------------------------------- +# +# svc = services.connect(host='localhost', user=user_name, password=user_password) +# fb_home = svc.get_home_directory() +# svc.close() +# +# dts = datetime.datetime.now().strftime("%y%m%d_%H%M%S") +# +# fbconf_cur = os.path.join(fb_home, 'firebird.conf') +# fbconf_bak = os.path.join(context['temp_directory'], 'firebird_'+dts+'.bak') +# +# shutil.copy2( fbconf_cur, fbconf_bak ) +# +# f_fbconf=open( fbconf_cur, 'r') +# fbconf_content=f_fbconf.readlines() +# flush_and_close( f_fbconf ) +# +# for i,s in enumerate( fbconf_content ): +# line = s.lower().lstrip() +# if line.startswith( 'DefaultTimeZone'.lower() ): +# fbconf_content[i] = '# [temply commented] ' + s +# +# text2app=''' +# ### TEMPORARY CHANGED BY FBTEST FRAMEWORK ### +# DefaultTimeZone = -7:00 +# ############################################## +# ''' +# +# f_fbconf=open( fbconf_cur, 'w') +# f_fbconf.writelines( fbconf_content + [ '\\n' + x for x in text2app.split('\\n') ] ) +# flush_and_close( f_fbconf ) +# #.......................................... +# +# changed_time1 = get_local_time( fb_home, db_name ) +# +# # RESTORE previous content of firebird.conf. This must be done BEFORE drop mapping! +# shutil.copy2( fbconf_bak, fbconf_cur ) +# +# ################################################## +# +# text2app=''' +# ### TEMPORARY CHANGED BY FBTEST FRAMEWORK ### +# DefaultTimeZone = +7:00 +# ############################################## +# ''' +# +# f_fbconf=open( fbconf_cur, 'w') +# f_fbconf.writelines( fbconf_content + [ '\\n' + x for x in text2app.split('\\n') ] ) +# flush_and_close( f_fbconf ) +# +# changed_time2 = get_local_time( fb_home, db_name ) +# +# # RESTORE previous content of firebird.conf. This must be done BEFORE drop mapping! +# shutil.move( fbconf_bak, fbconf_cur ) +# +# print( (datetime.datetime.strptime(changed_time2, '%H:%M:%S') - datetime.datetime.strptime(changed_time1, '%H:%M:%S')).seconds // 60 ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 840 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_6395_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6397.py b/tests/bugs/test_core_6397.py new file mode 100644 index 00000000..ccbbe7fd --- /dev/null +++ b/tests/bugs/test_core_6397.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: bugs.core_6397 +# title: Message length error with COALESCE and TIME/TIMESTAMP WITHOUT TIME ZONE and WITH TIME ZONE +# decription: +# We user ISQL "out nul;" command in order to supress STDOUT. STDERR is not redirected and must be empty. +# Confirmed bug on 4.0.0.2173. +# Checked on 4.0.0.2188 -- all fine. +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + out nul; + select coalesce(localtimestamp, current_timestamp) as result from rdb$database; + out; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=4.0') +@pytest.mark.platform('Windows') +def test_core_6397_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_6398.py b/tests/bugs/test_core_6398.py new file mode 100644 index 00000000..1a31b509 --- /dev/null +++ b/tests/bugs/test_core_6398.py @@ -0,0 +1,97 @@ +#coding:utf-8 +# +# id: bugs.core_6398 +# title: Error converting string with hex representation of integer to smallint +# decription: +# Bug initially was detected when adapted some of GTCS-tests which tries to convert +# numeric values from all possible combinations of datatypes. +# Particularly, conversion error was when try to cast "0x7fffffffffffffff" to bigint. +# See letter to Alex et al, 08-JUN-2020 15:38. +# +# It was decided to check here not only cast to smallint but also to other integer dadatypes. +# +# Confirmed bug on 4.0.0.2188. +# Checked on 4.0.0.2191 - all OK. +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + create or alter procedure "blob_smallint_explicit_cast" ( a blob ) returns ( b smallint ) as + begin + b = cast(a as smallint); + suspend; + end + ^ + create or alter procedure "blob_int_explicit_cast" ( a blob ) returns ( b int ) as + begin + b = cast(a as int); + suspend; + end + ^ + create or alter procedure "blob_bigint_explicit_cast" ( a blob ) returns ( b bigint ) as + begin + b = cast(a as bigint); + suspend; + end + ^ + create or alter procedure "blob_int128_explicit_cast" ( a blob ) returns ( b int128 ) as + begin + b = cast(a as int128); + suspend; + end + ^ + set term ;^ + commit; + + set heading off; + + select p.b as "blob_smallint_explicit_cast" from "blob_smallint_explicit_cast"('0x7fff') p; + + -- FAILED before fix: "numeric value is out of range": + select p.b as "blob_smallint_explicit_cast" from "blob_smallint_explicit_cast"('0x8000') p; + + select p.b as "blob_int_explicit_cast" from "blob_int_explicit_cast"('0x7fffffff') p; + select p.b as "blob_int_explicit_cast" from "blob_int_explicit_cast"('0x80000000') p; + + select p.b as "blob_bigint_explicit_cast" from "blob_bigint_explicit_cast"('0x7fffffffffffffff') p; + select p.b as "blob_bigint_explicit_cast" from "blob_bigint_explicit_cast"('0x8000000000000000') p; + + select p.b as "blob_int128_explicit_cast" from "blob_int128_explicit_cast"('0x7fffffffffffffffffffffffffffffff') p; + select p.b as "blob_int128_explicit_cast" from "blob_int128_explicit_cast"('0x80000000000000000000000000000000') p; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 32767 + -32768 + 2147483647 + -2147483648 + 9223372036854775807 + -9223372036854775808 + 170141183460469231731687303715884105727 + -170141183460469231731687303715884105728 + """ + +@pytest.mark.version('>=4.0') +def test_core_6398_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6403.py b/tests/bugs/test_core_6403.py new file mode 100644 index 00000000..dcf5d410 --- /dev/null +++ b/tests/bugs/test_core_6403.py @@ -0,0 +1,253 @@ +#coding:utf-8 +# +# id: bugs.core_6403 +# title: Some PSQL statements may lead to exceptions report wrong line/column +# decription: +# We make list of strings, each of them is a multi-line statement starting with 'EXECUTE BLOCK ...'. +# Inside every EB one of following loops is checked: +# * while () do ... +# * for select into ... +# -- where uses several arguments (because of loop) and eventually fails with zero division. +# In the BEGIN ... END block we have several lines of code which operates with arguments (see ticket examples). +# When fails then we catch error stack and parse it by searching line '- At block line: N, col: C'. +# These values (N and C) are compared later with those which are expected. +# +# In order to proper evaluate expected values of (N,C) we split source expression onto separate lines and numerate them. +# Also, within each line we search special marker: "/*!*/" (without qoutes). +# If line contains this marker then we find its position and subtract 5 from it (this is length of "while" word). +# NB: this requer that betwee "for" and "/*!*/" we must put two space characters (see below). +# +# Finally, we compare values in two dictionaries: +# source_expr_positions_map - K = sequential number of exprerssion in the "main list"; V = line/col of token that causes problem; +# actual_stack_positions_map - K = the same as in source_expr_positions_map; V = line/col values that were parsed from error stack. +# All pairs for apropriate expressions must be equal. +# +# If some difference will be found then we show this error stack, expected line/col coordinates and actual ones, as in this example: +# ================== +# 3 UNEXPECTED MISMATCH between expected and actual values of line/col: +# * expected (position of problematic token): 6, 5 +# * actual (result of error message parsing): 10, 9 +# * source message of error: +# Error while executing SQL statement: +# - SQLCODE: -802 +# - 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: 10, col: 9 +# Expression: +# ....:....1....:....2....:....3....:....4....:....5....:....6....:....7....:....8 +# : 12345678901234567890123456789012345678901234567890123456789012345678901234567890 +# 1 : execute block +# 2 : as +# 3 : declare n int = 5; +# 4 : declare c int; +# 5 : begin +# 6 : for /*!*/ select 100/:n from rdb$types into c +# 7 : -- ^^ NB: two spaces here. +# 8 : do begin +# 9 : insert into test(x) values(sqrt(:n)); +# 10 : n = n - 1; +# 11 : end +# 12 : end +# ================== +# +# Confirmed bug on 4.0.0.2195. +# Checked 4.0.0.2204: all fine. +# +# tracker_id: CORE-6403 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# from __future__ import print_function +# +# import os +# import sys +# import re +# import string +# +# #import fdb +# #FB_CLNT=sys.argv[1] +# #con=fdb.connect(dsn='localhost:e40', fb_library_name = FB_CLNT) +# #print(con.firebird_version) +# +# DEBUG_FLAG=0 +# +# db_conn.execute_immediate('recreate table test(x int)') +# db_conn.commit() +# +# sttm_list = [ +# '''execute block +# as +# declare n integer = 0; +# begin +# while/*!*/ (1 / n > 0) +# do +# begin +# n = n - 1; +# end +# end''' +# , +# '''execute +# block as declare n integer = 1; begin +# while/*!*/ +# ( +# 1 / n > 0 +# ) +# do +# begin +# n +# = n - 1; +# end +# end''' +# , +# '''execute block +# as +# begin +# while/*!*/ ( (select coalesce(t.x,0) from rdb$database r left join test t on 1=1) <= 1 ) +# do +# begin +# insert into test(x) values(1); +# insert into test(x) values(2); +# insert into test(x) values(3); +# end +# end''' +# , +# '''execute block +# as +# declare n int = 5; +# declare c int; +# begin +# for /*!*/ select 100/:n from rdb$types into c +# -- ^^ NB: two spaces here. +# do begin +# insert into test(x) values(sqrt(:n)); +# n = n - 1; +# end +# end''' +# , +# '''execute block +# as +# declare n int = 5; +# declare c int; +# begin +# delete from test; +# while ( n >= 0 ) do +# begin +# for /*!*/ execute statement ( +# 'select 100 / cast(? as int) +# from rdb$database +# ' +# ) ( n ) into c +# -- ^^ NB: two spaces here. +# do begin +# -- insert into test(x) values(sqrt(:n)); +# insert into test(x) values( :n ); +# end +# n = n - 1; +# end +# end''' +# ] +# +# sttm_map = {} +# source_expr_positions_map = {} +# for i,s in enumerate(sttm_list): +# sttm_lines = s.splitlines() +# for j, line in enumerate(sttm_lines): +# problematic_expr_position = line.find('/*!*/')-5 +# sttm_map[ i, j+1 ] = ( line, 1 + problematic_expr_position ) +# if problematic_expr_position>=0: +# source_expr_positions_map[ i ] = (j+1, 1 + problematic_expr_position ) +# +# if DEBUG_FLAG: +# for k,v in sorted(sttm_map.items()): +# print(k,':::',v) +# +# for k,v in sorted(source_expr_positions_map.items()): +# print(k,':::',v) +# +# +# # - At block line: 3, col: 1 +# p=re.compile( '(- )?At\\s+block\\s+line(:)?\\s+\\d+(,)?\\s+col(:)?\\s+\\d+', re.IGNORECASE) +# +# allchars=string.maketrans('','') +# nodigits=allchars.translate(allchars, string.digits + string.whitespace) +# +# actual_stack_positions_map = {} +# +# for i,s in enumerate(sttm_list): +# if DEBUG_FLAG: +# print('execute ',i) +# try: +# db_conn.execute_immediate(s) +# except Exception as e: +# if DEBUG_FLAG: +# print(e[0]) +# for msg in e[0].splitlines(): +# if DEBUG_FLAG: +# print('msg:',msg) +# if p.match(msg): +# if DEBUG_FLAG: +# print(p) +# print( msg.translate(allchars, nodigits) ) +# # '- At block line: 3, col: 1' ==> ' 3 1' +# line_col_pair = msg.translate(allchars, nodigits).split() +# actual_stack_positions_map[ i ] = ( int(line_col_pair[0]), int(line_col_pair[1]), e[0] ) +# +# if DEBUG_FLAG: +# for k,v in sorted(actual_stack_positions_map.items()): +# print(k,'###',v) +# +# for k,v in sorted(source_expr_positions_map.items()): +# w = actual_stack_positions_map.get(k) +# if w and v[:2] == w[:2]: +# print('Test %d PASSED' % k) # expected line/col in source code matches error stack pair. +# else: +# print(k, 'UNEXPECTED MISMATCH between expected and actual values of line/col:') +# print(' * expected (position of problematic token): %d, %d' % (v[0], v[1]) ) +# if w: +# print(' * actual (result of error message parsing): %d, %d' % (w[0], w[1]) ) +# print(' * source message of error:') +# for i in w[2].splitlines(): +# print( ' ' * 8, i ) +# else: +# print(' * actual: NONE') +# +# print('Expression:') +# for i,s in enumerate( sttm_list[k].splitlines() ): +# if i == 0: +# print( '%s %s' % (" " * 6, ''.join( [ '....:....' + str(j) for j in range(1,9)] ) ) ) +# print( '%s : %s' % ( " " * 4, "1234567890" * 8) ) +# print( '%s : %s' % ( "{:4g}".format(i+1), s) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Test 0 PASSED + Test 1 PASSED + Test 2 PASSED + Test 3 PASSED + Test 4 PASSED + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_6403_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6408.py b/tests/bugs/test_core_6408.py new file mode 100644 index 00000000..f68387dc --- /dev/null +++ b/tests/bugs/test_core_6408.py @@ -0,0 +1,64 @@ +#coding:utf-8 +# +# id: bugs.core_6408 +# title: RETURNING clause in MERGE cannot reference column in aliased target table using qualified reference (alias.column) if DELETE action present +# decription: +# Confirmed problem on 4.0.0.2225 ("-SQL error code = -206 / -Column unknown / -D.VAL" +# Checked on 4.0.0.2240 - all fine. +# +# tracker_id: CORE-6408 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + recreate table dummy2 ( + id integer constraint pk_dummy2 primary key, + val varchar(50) + ); + commit; + insert into dummy2 (id) values (1); + commit; + + merge into dummy2 as d + using (select 1, 'ab' from rdb$database) as src(id, val) + on d.id = src.id + when matched and d.id = 2 then delete + when matched then update set d.val = src.val + returning + d.val ---- this was not allowed before fix ("Statement failed, SQLSTATE = 42S22 ... Column unknown") + ,new.val + ,old.val + ,src.val + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + VAL ab + CONSTANT ab + VAL + VAL ab + """ + +@pytest.mark.version('>=4.0') +def test_core_6408_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6411.py b/tests/bugs/test_core_6411.py new file mode 100644 index 00000000..345117a5 --- /dev/null +++ b/tests/bugs/test_core_6411.py @@ -0,0 +1,159 @@ +#coding:utf-8 +# +# id: bugs.core_6411 +# title: FB crashes on attempt to create table with number of fields greater than 5460 +# decription: +# 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. +# +# tracker_id: CORE-6411 +# min_versions: ['3.0.7'] +# versions: 3.0.7 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.7 +# resources: None + +substitutions_1 = [('.*(-)?After line \\d+.*', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import sys +# import subprocess +# import time +# +# db_file=db_conn.database_name +# db_conn.close() +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# #-------------------------------------------- +# +# 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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# subprocess.call([ context['fbsvcmgr_path'], "localhost:service_mgr", +# "action_properties", "prp_write_mode", "prp_wm_async", +# "dbname", db_file ] +# ) +# #-------------------------------------------- +# +# for iter in range(0,2): +# FLD_COUNT = 8064 + iter +# +# ddl_init = 'recreate table tdata(id bigint primary key' +# ddl_addi = '\\n'.join( (',f%d bigint' %i for i in range(1,FLD_COUNT)) ) +# ddl_expr = ''.join( ( ddl_init, ddl_addi, ')' ) ) +# +# upd_init = 'update or insert into tdata values( 1' +# upd_addi = '\\n'.join( ( ',' + str(i) for i in range(1,FLD_COUNT)) ) +# upd_expr = ''.join( ( upd_init, upd_addi, ') matching(id)' ) ) +# +# +# sel_init = 'select ' +# sel_addi = '+'.join( ( str(i) for i in range(0,FLD_COUNT)) ) +# sel_expr = ''.join( ( sel_init, sel_addi, ' as fields_total from tdata' ) ) +# +# sql_expr= ''' +# set bail on; +# %(ddl_expr)s; +# commit; +# connect '%(dsn)s'; +# %(upd_expr)s; +# set list on; +# %(sel_expr)s; +# quit; +# ''' % dict(globals(), **locals()) +# +# f_run_sql = open( os.path.join(context['temp_directory'],'tmp_run_6411.sql'), 'w') +# f_run_sql.write(sql_expr) +# f_run_sql.close() +# +# f_run_log = open( os.path.join(context['temp_directory'],'tmp_run_6411.log'), 'w') +# +# p_hanged_isql=subprocess.call( [ context['isql_path'], dsn, "-i", f_run_sql.name ], +# stdout = f_run_log, +# stderr = subprocess.STDOUT +# ) +# flush_and_close(f_run_log) +# +# with open(f_run_log.name,'r') as f: +# for line in f: +# if line.strip(): +# print('iter: %(iter)s, FLD_COUNT: %(FLD_COUNT)s, result: %(line)s' % locals()) +# #< for iter in range(0,2) +# +# # Cleanup. +# ########## +# time.sleep(1) +# cleanup( (f_run_sql, f_run_log) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + iter: 0, FLD_COUNT: 8064, result: FIELDS_TOTAL 32510016 + iter: 1, FLD_COUNT: 8065, result: Statement failed, SQLSTATE = 54000 + iter: 1, FLD_COUNT: 8065, result: unsuccessful metadata update + iter: 1, FLD_COUNT: 8065, result: -new record size of 65536 bytes is too big + iter: 1, FLD_COUNT: 8065, result: -TABLE TDATA + """ + +@pytest.mark.version('>=3.0.7') +@pytest.mark.xfail +def test_core_6411_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6412.py b/tests/bugs/test_core_6412.py new file mode 100644 index 00000000..ccb32aee --- /dev/null +++ b/tests/bugs/test_core_6412.py @@ -0,0 +1,208 @@ +#coding:utf-8 +# +# id: bugs.core_6412 +# title: Firebird is freezing when trying to manage users via triggers +# decription: +# Confirmed hang on 4.0.0.2214 +# +# Checked on 4.0.0.2249 - no hang, but if this test runs in loop, w/o pauses for at least ~4s, then starting from 2nd run following fail raises: +# Statement failed, SQLSTATE = 08006 +# Error occurred during login, please check server firebird.log for details +# Error occurred during login, please check server firebird.log for details +# This was because of: http://tracker.firebirdsql.org/browse/CORE-6441 (fixed). +# +# Content of firebird.log will be added with following lines: +# Srp Server +# connection shutdown +# Database is shutdown. +# Sent report to Alex et al, 09.11.2020. +# +# tracker_id: CORE-6412 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('\t+', ' '), ('TCPv.*', 'TCP')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import time +# import subprocess +# import shutil +# import uuid +# from fdb import services +# +# svc = services.connect(host='localhost', user = user_name, password = user_password) +# fb_home=svc.get_home_directory() +# svc.close() +# +# dbconf = os.path.join(fb_home,'databases.conf') +# dbcbak = os.path.join(fb_home,'databases.bak') +# +# try: +# del os.environ["ISC_USER"] +# except KeyError as e: +# pass +# +# #-------------------------------------------- +# +# def svc_get_fb_log( fb_home, f_fb_log ): +# +# global subprocess +# subprocess.call( [ fb_home + "fbsvcmgr", +# "localhost:service_mgr", +# "action_get_fb_log" +# ], +# stdout=f_fb_log, stderr=subprocess.STDOUT +# ) +# return +# +# #-------------------------------------------- +# +# 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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# fdb_test = os.path.join(context['temp_directory'],'tmp_6412.fdb') +# +# +# # NB: fb_home is full path to FB instance home (with trailing slash). +# shutil.copy2( dbconf, dbcbak ) +# +# tmp_alias = 'self_security_6412' +# +# alias_data=''' +# +# # Added temporarily for executing test core_6412.fbt +# %(tmp_alias)s = %(fdb_test)s { +# # RemoteAccess = true +# SecurityDatabase = %(tmp_alias)s +# } +# ''' % locals() +# +# f_dbconf=open(fb_home+'databases.conf','a') +# f_dbconf.seek(0, 2) +# f_dbconf.write( alias_data ) +# flush_and_close( f_dbconf ) +# +# cleanup( (fdb_test,) ) +# +# sql_init=''' +# set bail on; +# create database '%(tmp_alias)s'; +# alter database set linger to 0; +# create user SYSDBA password 'QweRty' using plugin Srp; +# commit; +# +# connect 'localhost:%(tmp_alias)s' user sysdba password 'QweRty'; +# +# set list on; +# select a.mon$remote_protocol, +# d.mon$sec_database +# from mon$attachments a cross join mon$database d +# where a.mon$attachment_id = current_connection; +# +# CREATE TABLE USERS +# ( +# AUTHENTICATION VARCHAR(32) CHARACTER SET WIN1252 COLLATE WIN_PTBR +# ); +# COMMIT; +# +# SET TERM ^ ; +# CREATE TRIGGER USERS_AI_AU_AD FOR USERS +# ACTIVE AFTER INSERT OR UPDATE OR DELETE POSITION 0 +# AS +# BEGIN +# IF ((OLD.AUTHENTICATION IS NOT NULL) AND ((NEW.AUTHENTICATION IS NULL) OR (OLD.AUTHENTICATION<>NEW.AUTHENTICATION))) THEN +# BEGIN +# EXECUTE STATEMENT 'REVOKE RDB$ADMIN FROM "' || OLD.AUTHENTICATION || '" GRANTED BY "SYSDBA"'; +# EXECUTE STATEMENT 'DROP USER "' || OLD.AUTHENTICATION || '" USING PLUGIN SRP'; +# END +# +# IF ((NEW.AUTHENTICATION IS NOT NULL) AND ((OLD.AUTHENTICATION IS NULL) OR (OLD.AUTHENTICATION<>NEW.AUTHENTICATION))) THEN +# BEGIN +# EXECUTE STATEMENT 'GRANT RDB$ADMIN TO "' || NEW.AUTHENTICATION || '" GRANTED BY "SYSDBA"'; +# EXECUTE STATEMENT 'CREATE OR ALTER USER "' || NEW.AUTHENTICATION || '" SET PASSWORD ''123456'' USING PLUGIN SRP GRANT ADMIN ROLE'; +# END +# END^ +# SET TERM ; ^ +# COMMIT; +# +# INSERT INTO USERS (AUTHENTICATION) VALUES ('AAA'); +# COMMIT; +# +# +# UPDATE USERS SET AUTHENTICATION='BBB' WHERE AUTHENTICATION='AAA'; +# COMMIT; +# +# set list on; +# select 'Completed' as result from rdb$database; +# quit; +# +# ''' % locals() +# +# runProgram( 'isql',[ '-q' ], sql_init) +# runProgram( 'gfix',[ '-shut', 'full', '-force', '0', 'localhost:' + fdb_test, '-user', 'SYSDBA', '-pas', 'QweRty' ]) +# +# shutil.move( dbcbak, dbconf ) +# +# cleanup( (fdb_test,) ) +# +# # This delay is necessary for running this test multiple times (in loop) on SS and SC. +# # Otherwise we get runtime error "SQLSTATE = 08006 / Error occurred during login, please check server firebird.log" +# # and firebird.log will be filled with: "Srp Server / connection shutdown / Database is shutdown." +# # Delay must be not less than 4 seconds. Tested on 4.0.0.2249. +# ############# +# # 03-mar-2021: can be deleted (related to CORE-6441) >>> time.sleep(4) +# ############# +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MON$REMOTE_PROTOCOL TCPv6 + MON$SEC_DATABASE Self + RESULT Completed + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_6412_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6414.py b/tests/bugs/test_core_6414.py new file mode 100644 index 00000000..8bf58162 --- /dev/null +++ b/tests/bugs/test_core_6414.py @@ -0,0 +1,149 @@ +#coding:utf-8 +# +# id: bugs.core_6414 +# 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 +# decription: +# 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. +# +# All failed statements must have SQLSTATE = 22001. +# Confirmed wrong result on 4.0.0.2225: some statements failed with SQLSTATE=22000 (malformed string), +# some issue wrong value of "actual M" for length. +# +# Checked on 4.0.0.2228 -- all OK. +# +# tracker_id: CORE-6414 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- must fail with "expected length 1, actual 6" + recreate table test(nm varchar(1) character set utf8 default 'qwerty' not null); + + -- must fail with "expected length 1, actual 6" + recreate table test(nm varchar(1) character set utf8 default '€€€€€€' not null); + + create domain dm_ascii varchar(1) character set utf8 default 'qwertyu' not null; + + create domain dm_utf8 varchar(1) character set utf8 default '€€€€€€€' not null; + + -- must fail with "expected length 1, actual 7" + recreate table test(nm dm_ascii); + + -- must fail with "expected length 1, actual 7" + recreate table test(nm dm_utf8); + + create domain dm_utf8_nullable varchar(1) character set utf8 default '€€€€€€€€'; + + -- must fail with "expected length 1, actual 8" + recreate table test(nm dm_utf8_nullable not null); + + recreate table test(nm dm_utf8_nullable); -- must pass + + -- must fail with "expected length 1, actual 8" (because table 'test' exists) + alter domain dm_utf8_nullable set not null; + + ---------------------------------------------------------- + + recreate table test(id int); + alter domain dm_utf8_nullable set not null; + + + alter table test + add nm2 varchar(1) character set utf8 default '€€' + not null -- leads to "expected length 1, actual 2" + ; + + + alter table test + add nm3 varchar(1) character set utf8 default '€€€' + ,alter nm3 set not null -- leads to "expected length 1, actual 3" + ; + + alter table test + add nm4 varchar(3) character set utf8 default '€€€' + ,alter nm4 type varchar(4) + ,alter nm4 set default '€€€€€' + ,alter nm4 set not null -- leads to "expected length 4, actual 5" + ; + + alter table test + add nm5 varchar(1) character set utf8 + ,alter nm5 type dm_utf8_nullable -- leads to "expected length 1, actual 8" + ; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22001 + arithmetic exception, numeric overflow, or string truncation + -string right truncation + -expected length 1, actual 6 + + Statement failed, SQLSTATE = 22001 + arithmetic exception, numeric overflow, or string truncation + -string right truncation + -expected length 1, actual 6 + + Statement failed, SQLSTATE = 22001 + arithmetic exception, numeric overflow, or string truncation + -string right truncation + -expected length 1, actual 7 + + Statement failed, SQLSTATE = 22001 + arithmetic exception, numeric overflow, or string truncation + -string right truncation + -expected length 1, actual 7 + + Statement failed, SQLSTATE = 22001 + arithmetic exception, numeric overflow, or string truncation + -string right truncation + -expected length 1, actual 8 + + Statement failed, SQLSTATE = 22001 + arithmetic exception, numeric overflow, or string truncation + -string right truncation + -expected length 1, actual 8 + + Statement failed, SQLSTATE = 22001 + arithmetic exception, numeric overflow, or string truncation + -string right truncation + -expected length 1, actual 2 + + Statement failed, SQLSTATE = 22001 + arithmetic exception, numeric overflow, or string truncation + -string right truncation + -expected length 1, actual 3 + + Statement failed, SQLSTATE = 22001 + arithmetic exception, numeric overflow, or string truncation + -string right truncation + -expected length 4, actual 5 + + Statement failed, SQLSTATE = 22001 + arithmetic exception, numeric overflow, or string truncation + -string right truncation + -expected length 1, actual 8 + """ + +@pytest.mark.version('>=4.0') +def test_core_6414_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_6419.py b/tests/bugs/test_core_6419.py new file mode 100644 index 00000000..0e47d724 --- /dev/null +++ b/tests/bugs/test_core_6419.py @@ -0,0 +1,84 @@ +#coding:utf-8 +# +# id: bugs.core_6419 +# title: Truncation of strings to put in MON$ tables do not work correctly +# decription: +# We create two context variables, one consists only of ASCII characters, second contains UTF-8 character for euro currensy. +# Both variables have lenght = 90 *characters*. +# These variables are stored in mon$context_variables WITHOUT any adjusting to character set, i.e. it is NONE. +# When we query to them from mon$context_variables, output of first must be truncated to 80 *octets*. +# Output of second ALSO must be exactly 80 *octets*, but this leads to unreadable last character: not all bytes +# of 'euro' currency (which requires 3 bytes in utf-8) will be issued. +# +# This is considered now as EXPECTED RESULT(!), in contrary to previous one which raised exception SQLSTATE = 22001 +# (string right truncation / -expected length 80, actual 90). See comments in the ticket by Adriano, 21-oct-2020 03:31 PM. +# +# In order to avoid Python-specific exception ('UnicodeDecodeError: utf8') we avoid to display second (utf8) variable. +# Rather, we just show its octet_length and char_length. +# +# Checked on 4.0.0.2228 -- all OK. +# +# tracker_id: CORE-6419 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + set term ^; + execute block as + begin + rdb$set_context('USER_SESSION', '12345678901234567890123456789012345678901234567890123456789012345678901234567890abcdefghij', '1'); + rdb$set_context('USER_SESSION', 'ASDFGHJKLP€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€', '1'); + end + ^ + set term ;^ + + + select + c.mon$variable_name as mon_context_name + ,octet_length(c.mon$variable_name) mon_context_length + from mon$context_variables c + where mon$variable_name starting with '1234567890' + ; + + select + char_length(c.mon$variable_name) utf8_context_char_length + ,octet_length(c.mon$variable_name) utf8_context_octet_length + from mon$context_variables c + where mon$variable_name starting with 'ASDFGHJKLP€€€' + ; + -- NOTE. DO NOT output mon$variable_name for second query, result will be: UnicodeDecodeError: utf8 + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MON_CONTEXT_NAME 12345678901234567890123456789012345678901234567890123456789012345678901234567890 + MON_CONTEXT_LENGTH 80 + Records affected: 1 + + UTF8_CONTEXT_CHAR_LENGTH 80 + UTF8_CONTEXT_OCTET_LENGTH 80 + Records affected: 1 + """ + +@pytest.mark.version('>=4.0') +def test_core_6419_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6421.py b/tests/bugs/test_core_6421.py new file mode 100644 index 00000000..bcc673d9 --- /dev/null +++ b/tests/bugs/test_core_6421.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: bugs.core_6421 +# title: Parameter in offset expression in LAG, LEAD, NTH_VALUE window functions requires explicit cast to BIGINT or INTEGER +# decription: +# Confirmed bug on 4.0.0.2225, got: SQLSTATE = HY004 / Dynamic SQL Error / -SQL error code = -804 / -Data type unknown +# Checked on intermediate build 4.0.0.2235 (timestamp: 26.10.2020 01:19): all fine. +# +# tracker_id: CORE-6421 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('PLAN .*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set planonly; + + select rdb$relation_name, lag(rdb$relation_name, ?) over (order by rdb$relation_name) from rdb$relations; + select rdb$relation_name, lead(rdb$relation_name, ?) over (order by rdb$relation_name) from rdb$relations; + select rdb$relation_name, nth_value(rdb$relation_name, ?) over (order by rdb$relation_name) from rdb$relations; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=4.0') +def test_core_6421_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_6427.py b/tests/bugs/test_core_6427.py new file mode 100644 index 00000000..1c2b0321 --- /dev/null +++ b/tests/bugs/test_core_6427.py @@ -0,0 +1,94 @@ +#coding:utf-8 +# +# id: bugs.core_6427 +# title: Whitespace as date separator causes conversion error +# decription: +# NOTE: only space and TAB are allowed to usage as whitespace. +# Characters like chr(10) or chr(13) are not allowed: +# cast( '01.01.00 03:04:05.678' || ascii_char(10) as timestamp) +# -- leads to "Statement failed, SQLSTATE = 22009 / Invalid time zone region:" +# +# Checked on 4.0.0.2238. +# +# tracker_id: CORE-6427 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + + select cast('01 jan 1900' as timestamp) from rdb$database; + + -- NB: max allowed length for string which is to be converted to timestamp is 130: + select cast('01' || lpad('',120,' ') || 'jan 1900' as timestamp) from rdb$database; + select cast('01' || lpad('',120,ascii_char(9)) || 'jan 1900' as timestamp) from rdb$database; + select cast('01 jan' || lpad('',120,ascii_char(9)) || '1900' as timestamp) from rdb$database; + + select cast('01 jan ' || ascii_char(9) || '1900 1:1 ' as timestamp) from rdb$database; + select cast('01 jan'|| ascii_char(9) || ascii_char(9) || '1900 1:11 ' as timestamp) from rdb$database; + select cast('01 jan 1900 11:1'|| ascii_char(9) as timestamp) from rdb$database; + select cast( ascii_char(9) || '01' || ascii_char(9) ||'jan 1900 11:11' || ascii_char(9) as timestamp) from rdb$database; + + select cast('01 jan 00' as timestamp) from rdb$database; + select cast('01 jan 00 00:00' as timestamp) from rdb$database; + + select cast('01 01 1900' as timestamp) from rdb$database; + select cast('01 01 00' as timestamp) from rdb$database; + select cast('1' || ascii_char(9) || '1 0' as timestamp) from rdb$database; + select cast('1 1' || ascii_char(9) || '1' as timestamp) from rdb$database; + select cast('1 1' || ascii_char(9) || '9999' as timestamp) from rdb$database; + + select cast('01 01 2000' as timestamp) from rdb$database; + select cast('12 01 2000' as timestamp) from rdb$database; + -- conversion error (for unknown reason though...) select cast('13 01 2000' as timestamp) from rdb$database; + + select cast('01 01 00' || ascii_char(9) || '23:2.2' as timestamp) from rdb$database; + select cast('01 01' || ascii_char(9) || '00' || ascii_char(9) || '3:45:5.9' as timestamp) from rdb$database; + + select cast( ascii_char(9) || '01 01 00' || ascii_char(9) || '3:4:5.678' as timestamp) from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 1900-01-01 00:00:00.0000 + 1900-01-01 00:00:00.0000 + 1900-01-01 00:00:00.0000 + 1900-01-01 00:00:00.0000 + 1900-01-01 01:01:00.0000 + 1900-01-01 01:11:00.0000 + 1900-01-01 11:01:00.0000 + 1900-01-01 11:11:00.0000 + 2000-01-01 00:00:00.0000 + 2000-01-01 00:00:00.0000 + 1900-01-01 00:00:00.0000 + 2000-01-01 00:00:00.0000 + 2000-01-01 00:00:00.0000 + 2001-01-01 00:00:00.0000 + 9999-01-01 00:00:00.0000 + 2000-01-01 00:00:00.0000 + 2000-12-01 00:00:00.0000 + 2000-01-01 23:02:00.2000 + 2000-01-01 03:45:05.9000 + 2000-01-01 03:04:05.6780 + """ + +@pytest.mark.version('>=4.0') +def test_core_6427_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6429.py b/tests/bugs/test_core_6429.py new file mode 100644 index 00000000..1c181ee5 --- /dev/null +++ b/tests/bugs/test_core_6429.py @@ -0,0 +1,351 @@ +#coding:utf-8 +# +# id: bugs.core_6429 +# title: Timezone offset in timestamp/time literal, CAST, SET TIME ZONE and AT TIME ZONE should follow SQL standard syntax only +# decription: +# Test verifies miscelaneous forms of OFFSET for timezone part. +# According to note by Adriano (see ticket), values that represent HOURS and MINUTES, *can* be written in single-character form, +# i.e. 'H' and 'M' (rather than form 'HH' and 'MM' which was proposed by Mark). +# It looks srange but currently offset parts can be written with leading (non-valuable) zeroes. +# +# Checked on 4.0.0.2240. +# +# tracker_id: CORE-6429 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + + + -- ################################## CHECK SET TIME ZONE ############################################ + + set time zone '-0:0'; -- must pass + + set time zone '-00:00'; -- must pass + + set time zone '+0:0'; -- must pass + + set time zone '+00:00'; -- must pass + + -- Despite on very strange view, these statements all pass: + set time zone '+0: 0'; + + set time zone '- 0: 0'; + + set time zone ' + 0 : 0 '; + + -- Also passes! + set time zone ' + 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 : 00001 '; + + + -- All following must fail: + set time zone ''; + + set time zone ' '; + + set time zone ' '; -- TAB + + -- CR/LF + set time zone ' + '; + + set time zone '00:00'; + + set time zone '0:0'; + + + set time zone '+14:01'; -- must fail with "use format +/-hours:minutes and be between -14:00 and +14:00" + + set time zone '-14:01'; -- must fail with "use format +/-hours:minutes and be between -14:00 and +14:00" + + set time zone ' -0: -0'; -- must fail with "use format +/-hours:minutes and be between -14:00 and +14:00" + + set time zone '-0:0:'; -- must fail with "use format +/-hours:minutes and be between -14:00 and +14:00" + + set time zone '-0:+0'; -- must fail with "use format +/-hours:minutes and be between -14:00 and +14:00" + + set time zone '-0: +0'; -- must fail with "use format +/-hours:minutes and be between -14:00 and +14:00" + + set time zone '-0:0.0'; -- must fail with "use format +/-hours:minutes and be between -14:00 and +14:00" + + set time zone '+00:00.0'; -- must fail with "use format +/-hours:minutes and be between -14:00 and +14:00" + + -- ######################### CHECK TIMEZONE OFFSET IN TIMESTAMP LITERALS ########################## + + select timestamp '2018-01-02 02:02:02.2222 -03:00' from rdb$database; -- must pass + + select timestamp '2018-01-02 02:02:02.2222 -3:0' from rdb$database; + + select timestamp '2018-01-02 02:02:02.2222 -14:0' from rdb$database; + + select timestamp '2018-01-02 02:02:02.2222 +14:0' from rdb$database; + + -- also PASSES! + select timestamp '2018-01-02 02:02:02.2222 +0000000000000000000000000000014 : 00000000000000000000000000000000000000000000000000000000000' from rdb$database; + + + select timestamp '2018-01-02 02:02:02.2222 + 0: 0' from rdb$database; + + select timestamp '2018-01-02 02:02:02.2222 - 0 : 0 ' from rdb$database; + + -- Must fail: + -- Statement failed, SQLSTATE = 22009 / Invalid time zone region + select timestamp '2018-01-02 02:02:02.2222 0 : 0 ' from rdb$database; + + select timestamp '2018-01-02 02:02:02.2222 11:1' from rdb$database; + + -- ######################### CHECK TIMEZONE OFFSET IN TIME LITERALS ########################## + + + select time '03:03:03.3333 -03:00' from rdb$database; -- must pass + + select time '03:03:03.3333 -3:0' from rdb$database; + + select time '03:03:03.3333 -14:0' from rdb$database; + + select time '03:03:03.3333 +14:0' from rdb$database; + + -- also PASSES! + select time '03:03:03.3333 +0000000000000000000000000000014 : 00000000000000000000000000000000000000000000000000000000000' from rdb$database; + + + select time '03:03:03.3333 + 0: 0' from rdb$database; + + select time '03:03:03.3333 - 0 : 0 ' from rdb$database; + + -- Must fail: + -- Statement failed, SQLSTATE = 22009 / Invalid time zone region + select time '03:03:03.3333 0 : 0 ' from rdb$database; + + select time '03:03:03.3333 11:1' from rdb$database; + + -- ######################### CHECK CAST TO TIMESTAMP LITERALS WITH TIMEZONE ########################## + + select cast( '2018-01-02 04:04:04.4444 -03:00' as timestamp with time zone) from rdb$database; -- must pass + + select cast( '2018-01-02 04:04:04.4444 -3:0' as timestamp with time zone) from rdb$database; + + select cast( '2018-01-02 04:04:04.4444 -14:0' as timestamp with time zone) from rdb$database; + + select cast( '2018-01-02 04:04:04.4444 +14:0' as timestamp with time zone) from rdb$database; + + -- also PASSES! + select cast( '2018-01-02 04:04:04.4444 +0000000000000000000000000000014 : 00000000000000000000000000000000000000000000000000000000000' as timestamp with time zone) from rdb$database; + + + select cast( '2018-01-02 04:04:04.4444 + 0: 0' as timestamp with time zone) from rdb$database; + + select cast( '2018-01-02 04:04:04.4444 - 0 : 0 ' as timestamp with time zone) from rdb$database; + + -- Must fail: + -- Statement failed, SQLSTATE = 22009 / Invalid time zone region + select cast( '2018-01-02 04:04:04.4444 0 : 0 ' as timestamp with time zone) from rdb$database; + + select cast( '2018-01-02 04:04:04.4444 11:1' as timestamp with time zone) from rdb$database; + + -- ######################### CHECK IMPLICIT CAST WITH USING 'AT TIME ZONE' ########################## + + select time '05:05:05.5555' at time zone '-03:00' from rdb$database; -- must pass + + select time '05:05:05.5555' at time zone '-3:0' from rdb$database; + + select time '05:05:05.5555' at time zone '-14:0' from rdb$database; + + select time '05:05:05.5555' at time zone '+14:0' from rdb$database; + + -- also PASSES! + select time '05:05:05.5555' at time zone '+0000000000000000000000000000014 : 00000000000000000000000000000000000000000000000000000000000' from rdb$database; + + + select time '05:05:05.5555' at time zone '+ 0: 0' from rdb$database; + + select time '05:05:05.5555' at time zone ' - 0 : 0 ' from rdb$database; + + -- Must fail: + -- Statement failed, SQLSTATE = 22009 / Invalid time zone region + select time '05:05:05.5555' at time zone ' 0 : 0 ' from rdb$database; + + select time '05:05:05.5555' at time zone '11:1' from rdb$database; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 2018-01-02 02:02:02.2222 -03:00 + + + 2018-01-02 02:02:02.2222 -03:00 + + + 2018-01-02 02:02:02.2222 -14:00 + + + 2018-01-02 02:02:02.2222 +14:00 + + + 2018-01-02 02:02:02.2222 +14:00 + + + 2018-01-02 02:02:02.2222 +00:00 + + + 2018-01-02 02:02:02.2222 +00:00 + + + 03:03:03.3333 -03:00 + + + 03:03:03.3333 -03:00 + + + 03:03:03.3333 -14:00 + + + 03:03:03.3333 +14:00 + + + 03:03:03.3333 +14:00 + + + 03:03:03.3333 +00:00 + + + 03:03:03.3333 +00:00 + + + 2018-01-02 04:04:04.4444 -03:00 + + + 2018-01-02 04:04:04.4444 -03:00 + + + 2018-01-02 04:04:04.4444 -14:00 + + + 2018-01-02 04:04:04.4444 +14:00 + + + 2018-01-02 04:04:04.4444 +14:00 + + + 2018-01-02 04:04:04.4444 +00:00 + + + 2018-01-02 04:04:04.4444 +00:00 + + + + + 01:04:05.5555 -03:00 + + + 01:04:05.5555 -03:00 + + + 14:04:05.5555 -14:00 + + + 18:04:05.5555 +14:00 + + + 18:04:05.5555 +14:00 + + + 04:04:05.5555 +00:00 + + + 04:04:05.5555 +00:00 + + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22009 + Invalid time zone region: + + Statement failed, SQLSTATE = 22009 + Invalid time zone region: + + Statement failed, SQLSTATE = 22009 + Invalid time zone region: + + Statement failed, SQLSTATE = 22009 + Invalid time zone region: + + + Statement failed, SQLSTATE = 22009 + Invalid time zone region: 00:00 + + Statement failed, SQLSTATE = 22009 + Invalid time zone region: 0:0 + + Statement failed, SQLSTATE = 22009 + Invalid time zone offset: +14:01 - must use format +/-hours:minutes and be between -14:00 and +14:00 + + Statement failed, SQLSTATE = 22009 + Invalid time zone offset: -14:01 - must use format +/-hours:minutes and be between -14:00 and +14:00 + + Statement failed, SQLSTATE = 22009 + Invalid time zone offset: -0: -0 - must use format +/-hours:minutes and be between -14:00 and +14:00 + + Statement failed, SQLSTATE = 22009 + Invalid time zone offset: -0:0: - must use format +/-hours:minutes and be between -14:00 and +14:00 + + Statement failed, SQLSTATE = 22009 + Invalid time zone offset: -0:+0 - must use format +/-hours:minutes and be between -14:00 and +14:00 + + Statement failed, SQLSTATE = 22009 + Invalid time zone offset: -0: +0 - must use format +/-hours:minutes and be between -14:00 and +14:00 + + Statement failed, SQLSTATE = 22009 + Invalid time zone offset: -0:0.0 - must use format +/-hours:minutes and be between -14:00 and +14:00 + + Statement failed, SQLSTATE = 22009 + Invalid time zone offset: +00:00.0 - must use format +/-hours:minutes and be between -14:00 and +14:00 + + Statement failed, SQLSTATE = 22009 + Invalid time zone region: 0 : 0 + + Statement failed, SQLSTATE = 22009 + Invalid time zone region: 11:1 + + Statement failed, SQLSTATE = 22009 + Invalid time zone region: 0 : 0 + + Statement failed, SQLSTATE = 22009 + Invalid time zone region: 11:1 + + Statement failed, SQLSTATE = 22009 + Invalid time zone region: 0 : 0 + + Statement failed, SQLSTATE = 22009 + Invalid time zone region: 11:1 + + Statement failed, SQLSTATE = 22009 + Invalid time zone region: 0 : 0 + + Statement failed, SQLSTATE = 22009 + Invalid time zone region: 11:1 + """ + +@pytest.mark.version('>=4.0') +def test_core_6429_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6437.py b/tests/bugs/test_core_6437.py new file mode 100644 index 00000000..0da40d0d --- /dev/null +++ b/tests/bugs/test_core_6437.py @@ -0,0 +1,127 @@ +#coding:utf-8 +# +# id: bugs.core_6437 +# title: gfix cannot set big value for buffers +# decription: +# New database must be created in THIS code rather than "outside" (in fbtest) for reproducing bug. +# Confirmed bug on 4.0.0.2225. +# Checked on Windows: +# 4.0.0.2249 SS: 3.284s. +# 3.0.2.32703 SS: 2.645s. +# 3.0.7.33387 SS: 3.301s. +# 3.0.6.33328 CS: 6.145s. +# +# ::: NB ::: +# On build 4.0.0.2225 attempt to change buffers via gfix failed when value was >= 524337 for DB with page_size=8192. +# Perhaps this was related to allocating memory more than 2Gb plus small addition (exact value: 2.00018692 Gb). +# Ouput of gfix in this case contained: +# ======= +# I/O error during "ReadFile" operation for file "C:\\FBTESTING\\QA\\FBT-REPO\\TMP\\TMP_GFIX_6437.FDB" +# -Error while trying to read from file +# -Invalid attempt to access memory address << localized message! +# ======= +# Test creates database with page size = 8192 and tries to run 'gfix -buffers 524337', with further checking that: +# * output of gfix is empty; +# * page buffers has been changed and equals to this new value. +# +# DO NOT change this value to some "really too big" value otherwise it will fail with "unable to allocate memory"! +# Checked again (15.03.2021) on: +# * Windows: 4.0.0.2387, 3.0.8.33426 +# * Linux: 4.0.0.2387, 3.0.8.33426 +# +# tracker_id: CORE-6437 +# min_versions: ['3.0.8'] +# versions: 3.0.8 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.8 +# resources: None + +substitutions_1 = [('^((?!(File|file|Page buffers)|(Page size)).)*$', ''), ('[\t ]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# from fdb import services +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# db_name = os.path.join(context['temp_directory'],'tmp_gfix_6437.fdb') +# +# cleanup( (db_name,) ) +# +# runProgram('isql',[ '-q' ], "create database '%(db_name)s' page_size 8192;" % locals()) +# +# f_run_log=open( os.path.join(context['temp_directory'],'tmp_gfix_6437.log'), 'w') +# subprocess.call( [ context['gfix_path'], db_name, "-buffers", "524337" ], stdout=f_run_log, stderr=subprocess.STDOUT ) +# flush_and_close(f_run_log) +# +# time.sleep(1) +# with open(f_run_log.name,'r') as f: +# for line in f: +# print('UNEXPECTED GFIX OUTPUT: ' + line) +# +# runProgram('gstat',[ '-h', db_name ]) +# +# cleanup( (db_name, f_run_log,) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Page size 8192 + Page buffers 524337 + """ + +@pytest.mark.version('>=3.0.8') +@pytest.mark.xfail +def test_core_6437_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6438.py b/tests/bugs/test_core_6438.py new file mode 100644 index 00000000..d7ccc47d --- /dev/null +++ b/tests/bugs/test_core_6438.py @@ -0,0 +1,114 @@ +#coding:utf-8 +# +# id: bugs.core_6438 +# title: ISQL: bad headers when text columns has >= 80 characters +# decription: +# Test creates .sql script with query that contains literal (similar to descriped in the ticket, but much longer). +# Then we parse result of this query and compare length of header and data. They both must be equal to the same value. +# Confirmed truncated length of header on 4.0.0.2225 +# Checked on 4.0.0.2249 - all fine. +# +# tracker_id: CORE-6438 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import sys +# import os +# import time +# import subprocess +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# data = '1' * 65533 +# sql_run = '''select '%(data)s' as " ", 1 as " " from rdb$database;''' % locals() +# +# f_run_sql = open( os.path.join(context['temp_directory'],'tmp_6438.sql'), 'w') +# f_run_sql.write(sql_run) +# flush_and_close(f_run_sql) +# +# f_run_log=open( os.path.join(context['temp_directory'],'tmp_6438.log'), 'w') +# subprocess.call( [ context['isql_path'], dsn, "-i", f_run_sql.name ], stdout=f_run_log, stderr=subprocess.STDOUT ) +# flush_and_close(f_run_log) +# +# hdr_len, txt_len = 0,0 +# with open(f_run_log.name,'r') as f: +# for line in f: +# if line.startswith('='): +# hdr_len = len(line.split()[0]) +# elif line.startswith('1'): +# txt_len = len(line.split()[0]) +# +# print('hdr_len:', hdr_len) +# print('txt_len:', txt_len) +# +# # Cleanup +# ########## +# cleanup( ( f_run_sql, f_run_log ) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +hdr_len: 65533 +txt_len: 65533 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_6438_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6440.py b/tests/bugs/test_core_6440.py new file mode 100644 index 00000000..9cbfbf3e --- /dev/null +++ b/tests/bugs/test_core_6440.py @@ -0,0 +1,76 @@ +#coding:utf-8 +# +# id: bugs.core_6440 +# title: Expression indexes containing COALESCE inside cannot be matched by the optimizer after migration from v2.5 to v3.0 +# decription: +# Confirmed bug on 3.0.7.33388 (wrong plans of queris specified in the ticked; need to RESTORE database from 2.5 on 3.x). +# Test uses .fbk that was created on FB 2.5.9, file: core6440-ods11.fbk +# +# Checked on 4.0.0.2269; 3.0.8.33390 -- all OK. +# +# tracker_id: CORE-6440 +# min_versions: [] +# versions: 3.0.8 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.8 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='core6440-ods11.fbk', init=init_script_1) + +test_script_1 = """ + set planonly; + --set echo on; + + --Uses a proper index: PLAN (TEST INDEX (PK_TEST)) + select * from test where field_1 = 1; + + + + --Uses a proper index: PLAN (TEST INDEX (TEST_IDX4)) + select * from test where (UPPER(FIELD_2)) = 'TEST1'; + + + + --Doesn't uses a proper index: PLAN (TEST NATURAL) + select * from test where (UPPER(COALESCE(FIELD_2,''))) = 'TEST1'; + + + + --Uses PLAN (TEST INDEX (TEST_IDX2)) + select * from test where (UPPER(FIELD_2)||UPPER(FIELD_3)) = 'TEST1TEST1_1'; + + + + --Doesn't uses a proper index: PLAN (TEST NATURAL) + select * from test where (UPPER(COALESCE(FIELD_2,''))||UPPER(COALESCE(FIELD_3,''))) = 'TEST1TEST1_1'; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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)) + """ + +@pytest.mark.version('>=3.0.8') +def test_core_6440_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6441.py b/tests/bugs/test_core_6441.py new file mode 100644 index 00000000..578cced9 --- /dev/null +++ b/tests/bugs/test_core_6441.py @@ -0,0 +1,187 @@ +#coding:utf-8 +# +# id: bugs.core_6441 +# title: Srp plugin keeps connection after database has been removed for ~10 seconds (SS and SC). +# decription: +# Test is based on CORE-6412, but instead of complex DDL it only creates DB and makes connection. +# Then it leaves ISQL and 'main' code changes DB state to full shutdown and removes database. +# After this, test immediatelly starts next iteration with the same actions. All of them must pass. +# Total number of iterations = 3. +# +# Confirmed bug on 4.0.0.2265: +# Statement failed, SQLSTATE = 08006 +# Error occurred during login, please check server firebird.log for details +# Error occurred during login, please check server firebird.log for details +# +# NB. Content of firebird.log will be added with following lines: +# Srp Server +# connection shutdown +# Database is shutdown. +# This is expected (got reply from Alex, e-mail 19.11.2020 11:12). +# +# Checked on 3.0.8.33392 SS/SC, 4.0.0.2269 SC/SS - all fine. +# +# 03-mar-2021: fixed call syntax in runProgram() macros. +# Checked on: +# * WINDOWS: 335544344 : I/O error during "CreateFile (open)" operation ... +# * LINUX: 335544344 : I/O error during "open" operation ... +# +# tracker_id: CORE-6441 +# min_versions: ['3.0.8'] +# versions: 3.0.8 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.8 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import time +# import subprocess +# import shutil +# from fdb import services +# +# from fdb import services +# +# svc = services.connect(host='localhost', user = user_name, password = user_password) +# fb_home=svc.get_home_directory() +# svc.close() +# +# dbconf = os.path.join(fb_home,'databases.conf') +# dbcbak = os.path.join(fb_home,'databases.bak') +# +# try: +# del os.environ["ISC_USER"] +# except KeyError as e: +# pass +# +# #-------------------------------------------- +# +# 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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# fdb_test = os.path.join(context['temp_directory'],'tmp_6441.fdb') +# +# shutil.copy2( dbconf, dbcbak ) +# tmp_alias = 'self_security_6441' +# +# alias_data=''' +# +# # Added temporarily for executing test core_6441.fbt +# %(tmp_alias)s = %(fdb_test)s { +# # RemoteAccess = true +# SecurityDatabase = %(tmp_alias)s +# } +# ''' % locals() +# +# f_dbconf=open( dbconf, 'a') +# f_dbconf.seek(0, 2) +# f_dbconf.write( alias_data ) +# flush_and_close( f_dbconf ) +# +# cleanup( (fdb_test,) ) +# +# sql_init=''' +# set bail on; +# set list on; +# +# create database '%(tmp_alias)s'; +# +# select %(i)s as iteration_no, 'DB creation completed OK.' as msg from rdb$database; +# +# alter database set linger to 0; +# create user SYSDBA password 'QweRty' using plugin Srp; +# commit; +# +# connect 'localhost:%(tmp_alias)s' user sysdba password 'QweRty'; +# +# select %(i)s as iteration_no, 'Remote connection established OK.' as msg from rdb$database; +# +# set term ^; +# execute block as +# declare v_dummy varchar(20); +# begin +# select left(a.mon$remote_protocol,3) as mon_protocol +# from mon$attachments a +# where a.mon$attachment_id = current_connection +# into v_dummy; +# end +# ^ +# set term ;^ +# quit; +# ''' +# +# for i in range(0,3): +# runProgram('isql',[ '-q' ], sql_init % locals() ) +# runProgram('gfix',[ '-shut', 'full', '-force', '0', 'localhost:' + fdb_test, '-user', 'SYSDBA', '-pas', 'QweRty' ]) +# cleanup( (fdb_test,) ) +# +# shutil.move( dbcbak, dbconf ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ITERATION_NO 0 + MSG DB creation completed OK. + ITERATION_NO 0 + MSG Remote connection established OK. + + ITERATION_NO 1 + MSG DB creation completed OK. + ITERATION_NO 1 + MSG Remote connection established OK. + + ITERATION_NO 2 + MSG DB creation completed OK. + ITERATION_NO 2 + MSG Remote connection established OK. + """ + +@pytest.mark.version('>=3.0.8') +@pytest.mark.xfail +def test_core_6441_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6444.py b/tests/bugs/test_core_6444.py new file mode 100644 index 00000000..0a5d9d45 --- /dev/null +++ b/tests/bugs/test_core_6444.py @@ -0,0 +1,429 @@ +#coding:utf-8 +# +# id: bugs.core_6444 +# title: Ability to query Firebird configuration using SQL +# decription: +# Test found FB_HOME directory and makes copy its firebird.conf and database.conf files. +# Then it found free TCP port and overwrites content of firebird.conf: this new port +# will be specified for RemoveServicePort and some other parameters also will be added. +# File \\databases.conf is also changed: we add new alias for database that will +# be self-security and specify lot of per-database parameters for it. +# Some numeric parameters intentionally will be assigned to huge bigint values, namely: +# * FileSystemCacheThreshold +# * TempCacheLimit +# Their huge values do not affect on actual work; this is done only for check proper +# interpretation of them. +# +# After this test launches Firebird as application (see async. call of Popen()) and make +# connect to new database by launching ISQL. +# When connect is established, we query RDB$CONFIG table two times: +# * as SYSDBA (in this case all config parameters and their actual values must be seen); +# * as NON-privileged user (zero rows must be issued for query to RDB$CONFIG). +# +# Finally (after return from ISQL) test terminates Firebird application process. +# Checked on 4.0.0.2365. +# +# ::: CAUTION-1 ::: +# This test will fail if new parameter will appear in firebird.conf or if old one removed from there. +# One need to adjust expected_stdout in this case. +# +# ::: CAUTION-2 ::: +# Windows Firewall can block attempt to launch FB as application (dialog window appears in this case). +# One may need to configure Firewall so that process +# irebird.exe is enable to operate on any port. +# +# Perhaps, following command will be useful: netsh advfirewall set privateprofile state off +# +# ::: CAUTION-3 ::: +# 13.02.2021 Currently this test must be executed only on Windows! +# On Linux it terminates with runtime ERROR ('E') and firebird.conf + databases.conf remains in $FB_HOME +# with changed parameters. +# For Classic this prevents all subsequent tests to be executed normally: all of them will also finish with 'E'. +# This problem will be solved later. +# +# tracker_id: CORE-6444 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('[=]+', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import sys +# import os +# import shutil +# import time +# import datetime +# import tempfile +# import subprocess +# from fdb import services +# +# #-------------------------------------------- +# +# 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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# +# #-------------------------------------------- +# +# def find_free_port(): +# import socket +# from contextlib import closing +# # 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) +# return s.getsockname()[1] +# +# #-------------------------------------------- +# +# FB_HOME = services.connect(host='localhost', user=user_name, password=user_password).get_home_directory() +# +# fb_vers = str(db_conn.engine_version)[:1] # character for security.db file: engine = 4.0 --> '4' +# sec_db = FB_HOME + 'security' + fb_vers+ '.fdb' +# +# db_conn.close() +# +# fdb_test = os.path.join(context['temp_directory'],'tmp_c6444.fdb') +# +# dts = datetime.datetime.now().strftime("%y%m%d_%H%M%S") +# +# fbconf_cur = os.path.join(FB_HOME, 'firebird.conf') +# fbconf_bak = os.path.join(context['temp_directory'], 'firebird_'+dts+'.bak') +# +# dbconf_cur = os.path.join(FB_HOME, 'databases.conf') +# dbconf_bak = os.path.join(context['temp_directory'], 'databases_'+dts+'.bak') +# +# shutil.copy2( fbconf_cur, fbconf_bak ) +# shutil.copy2( dbconf_cur, dbconf_bak ) +# +# shutil.copy2( sec_db, fdb_test ) +# +# TMPDIR = os.path.join( FB_HOME, 'examples' ) # tempfile.gettempdir() +# TMP_FREE_PORT = find_free_port() +# #TMP_FREE_PORT = 57456 +# +# cfg_params_to_change= { +# 'AllowEncryptedSecurityDatabase' : 'true' +# ,'AuthClient' : 'Srp' +# ,'AuthServer' : 'Legacy_Auth, Srp' +# ,'BugcheckAbort' : '1' +# ,'ClientBatchBuffer' : '256k' +# ,'ConnectionIdleTimeout' : '77' # will be also specified in databases.conf; effective value must be from databases.conf, NOT from here! +# ,'ConnectionTimeout' : '123' +# ,'DeadlockTimeout' : '15' +# ,'DatabaseAccess' : 'None' # In order to display only ALIAS of database rather than its full name +# ,'DefaultDbCachePages' : '1234' # will be also specified in databases.conf; effective value must be from databases.conf, NOT from here! +# ,'DefaultTimeZone' : '-7:00' +# ,'DummyPacketInterval' : '11' +# ,'EventMemSize' : '12321' +# ,'ExtConnPoolLifeTime' : '1212' +# ,'ExtConnPoolSize' : '123' +# ,'FileSystemCacheThreshold' : '8589934591G' +# ,'IpcName' : 'fb4x_tmp_c6444' +# ,'IPv6V6Only' : '1' +# ,'InlineSortThreshold' : '8k' +# ,'LockHashSlots' : '33333' # will be also specified in databases.conf; effective value must be from databases.conf, NOT from here! +# ,'LockMemSize' : '17m' # will be also specified in databases.conf; effective value must be from databases.conf, NOT from here! +# ,'MaxUserTraceLogSize' : '100' +# ,'ReadConsistency' : '0' +# ,'RemoteServiceName' : 'tmp_fbs_6444' +# ,'RemoteServicePort' : str(TMP_FREE_PORT) +# ,'ServerMode' : 'SuperClassic' +# ,'StatementTimeout' : '777' # will be also specified in databases.conf; effective value must be from databases.conf, NOT from here! +# ,'TcpLoopbackFastPath' : '0' +# ,'TcpNoNagle' : 'false' +# ,'TcpRemoteBufferSize' : '5555' +# ,'TempBlockSize' : '5m' +# ,'TempDirectories' : os.path.normpath( TMPDIR ) +# ,'UDFaccess' : 'Restrict UDF' +# ,'UseFileSystemCache' : 'false' +# ,'WireCompression' : 'true' +# ,'WireCrypt' : 'Required' +# ,'WireCryptPlugin' : 'Arc4' +# +# } +# +# f_fbconf=open( fbconf_cur, 'w') +# for k,v in sorted(cfg_params_to_change.items()): +# f_fbconf.write( ''.join( (k, ' = ', v, '\\n') ) ) +# flush_and_close( f_fbconf ) +# +# alias_data=''' +# # Added temporarily for executing test core_6444.fbt +# tmp_6444 = %(fdb_test)s { +# +# SecurityDatabase = tmp_6444 +# +# RemoteAccess = true +# DatabaseGrowthIncrement = 123m +# DataTypeCompatibility = 3.0 +# DefaultDbCachePages = 4321 +# ClearGTTAtRetaining = 1 +# +# # Set number of minutes after which idle attachment will be disconnected by the engine. Zero means no timeout is set. +# ConnectionIdleTimeout = 99 +# +# ExternalFileAccess = Full +# +# LockHashSlots = 49999 +# LockMemSize = 29m +# +# MaxIdentifierByteLength = 31 +# MaxIdentifierCharLength = 31 +# MaxUnflushedWrites = 111 +# MaxUnflushedWriteTime = 15 +# +# Providers = Engine13, Remote +# +# SnapshotsMemSize = 99m +# +# # Set number of seconds after which statement execution will be automatically cancelled by the engine. Zero means no timeout is set. +# StatementTimeout = 999 +# +# TempBlockSize = 3m +# TempCacheLimit = 8589934591G +# +# TipCacheBlockSize = 3m +# +# UserManager = Legacy_UserManager, Srp +# } +# ''' % locals() +# +# f_dbconf=open( dbconf_cur, 'w') +# f_dbconf.write(alias_data) +# flush_and_close( f_dbconf ) +# +# p_tmp_fb_pid = subprocess.Popen( [ FB_HOME+'firebird', '-a'] ) +# +# time.sleep(2) +# +# sql_text=''' +# -- set echo on; +# set wng off; +# connect 'tmp_6444'; +# create or alter user sysdba password 'masterkey' using plugin Srp; +# create or alter user tmp$c6444 password '123' using plugin Srp; +# revoke all on all from tmp$c6444; +# create or alter view v_config as +# select +# g.rdb$config_name param_name +# ,iif(trim(g.rdb$config_value)='', '[empty]' +# ,iif( g.rdb$config_name = 'TempDirectories' and upper(g.rdb$config_value) = upper('%(TMPDIR)s') or g.rdb$config_name = 'RemoteServicePort' and g.rdb$config_value = %(TMP_FREE_PORT)s +# ,'[MATCHES]' +# ,g.rdb$config_value) +# ) param_value +# ,iif(trim(g.rdb$config_default)='', '[empty]', replace(g.rdb$config_default,'%(FB_HOME)s','') ) param_default +# ,g.rdb$config_is_set param_is_set +# ,g.rdb$config_source param_source +# from rdb$config g +# order by param_name +# ; +# commit; +# grant select on v_config to tmp$c6444; +# commit; +# +# connect 'localhost/%(TMP_FREE_PORT)s:tmp_6444' user sysdba password 'masterkey'; +# +# set count on; +# set width param_name 50; +# set width param_value 64; +# set width param_default 64; +# set width param_source 64; +# +# select * from v_config; -- SYSDBA: must see all parameters with their effective values +# +# commit; +# connect 'localhost/%(TMP_FREE_PORT)s:tmp_6444' user tmp$c6444 password '123'; +# +# select * from v_config; -- NON-PRIVILEGED user: must see 0 rows +# +# /* +# -- for debug only: +# set list on; +# select +# current_user as who_am_i +# ,m.mon$database_name as db_name +# ,m.mon$page_buffers as db_buffers +# ,m.mon$sec_database as db_sec_name +# ,a.mon$remote_protocol +# ,a.mon$idle_timeout +# ,a.mon$statement_timeout +# ,a.mon$wire_compressed +# ,a.mon$wire_encrypted +# ,a.mon$wire_crypt_plugin +# from mon$database m +# cross join mon$attachments a +# where a.mon$attachment_id = current_connection +# ; +# */ +# +# commit; +# connect 'localhost/%(TMP_FREE_PORT)s:tmp_6444' user sysdba password 'masterkey'; +# drop user tmp$c6444 using plugin Srp; +# commit; +# +# ''' % locals() +# +# f_sql_cmd = open( os.path.join(context['temp_directory'],'tmp_c6444.sql'), 'w') +# f_sql_cmd.write( sql_text ) +# flush_and_close( f_sql_cmd ) +# +# f_sql_log=open( os.path.join(context['temp_directory'],'tmp_c6444.log'), 'w') +# f_sql_err=open( os.path.join(context['temp_directory'],'tmp_c6444.err'), 'w') +# +# #subprocess.call( [FB_HOME+'isql', 'localhost/%(TMP_FREE_PORT)s:tmp_6444' % locals(), '-i', f_sql_cmd.name], stdout=f_sql_log, stderr=f_sql_err ) +# subprocess.call( [FB_HOME+'isql', '-q', '-pag', '999999', '-i', f_sql_cmd.name, '-user', 'SYSDBA'], stdout=f_sql_log, stderr=f_sql_err ) +# +# flush_and_close( f_sql_log ) +# flush_and_close( f_sql_err ) +# +# p_tmp_fb_pid.terminate() +# +# shutil.move( fbconf_bak, fbconf_cur ) +# shutil.move( dbconf_bak, dbconf_cur ) +# +# +# with open(f_sql_err.name, 'r') as f: +# for line in f: +# if line.split(): +# print('UNEXPECTED STDERR: ' + line) +# +# with open(f_sql_log.name, 'r') as f: +# for line in f: +# if line.split(): +# print(line) +# +# time.sleep(1) +# +# f_list=( f_sql_log, f_sql_err, f_sql_cmd ) +# +# # Cleanup +# ########## +# cleanup( [ i.name for i in f_list ] + [fdb_test] ) +# +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PARAM_NAME PARAM_VALUE PARAM_DEFAULT PARAM_IS_SET PARAM_SOURCE + ================================================== ================================================================ ================================================================ ============ ================================================================ + AllowEncryptedSecurityDatabase true false firebird.conf + AuditTraceConfigFile [empty] [empty] + AuthClient Srp Srp256, Srp, Win_Sspi, Legacy_Auth firebird.conf + AuthServer Legacy_Auth, Srp Srp256 firebird.conf + BugcheckAbort true false firebird.conf + ClearGTTAtRetaining true false databases.conf + ClientBatchBuffer 262144 131072 firebird.conf + ConnectionIdleTimeout 99 0 databases.conf + ConnectionTimeout 123 180 firebird.conf + CpuAffinityMask 0 0 + DataTypeCompatibility 3.0 databases.conf + DatabaseAccess None Full firebird.conf + DatabaseGrowthIncrement 128974848 134217728 databases.conf + DeadlockTimeout 15 10 firebird.conf + DefaultDbCachePages 4321 2048 databases.conf + DefaultTimeZone -7:00 firebird.conf + DummyPacketInterval 11 0 firebird.conf + EventMemSize 12321 65536 firebird.conf + ExtConnPoolLifeTime 1212 7200 firebird.conf + ExtConnPoolSize 123 0 firebird.conf + ExternalFileAccess Full None databases.conf + FileSystemCacheSize 0 0 + FileSystemCacheThreshold 9223372035781033984 65536 firebird.conf + GCPolicy combined combined + GuardianOption 1 1 + IPv6V6Only true false firebird.conf + InlineSortThreshold 8192 1000 firebird.conf + IpcName fb4x_tmp_c6444 FIREBIRD firebird.conf + KeyHolderPlugin [empty] [empty] + LegacyHash true true + LockAcquireSpins 0 0 + LockHashSlots 49999 8191 databases.conf + LockMemSize 30408704 1048576 databases.conf + MaxIdentifierByteLength 31 252 databases.conf + MaxIdentifierCharLength 31 63 databases.conf + MaxUnflushedWriteTime 15 5 databases.conf + MaxUnflushedWrites 111 100 databases.conf + MaxUserTraceLogSize 100 10 firebird.conf + OutputRedirectionFile nul nul + ProcessPriorityLevel 0 0 + Providers Engine13, Remote Remote, Engine13, Loopback databases.conf + ReadConsistency false true firebird.conf + Redirection false false + RelaxedAliasChecking false false + RemoteAccess true true databases.conf + RemoteAuxPort 0 0 + RemoteBindAddress + RemoteFileOpenAbility false false + RemotePipeName interbas interbas + RemoteServiceName tmp_fbs_6444 gds_db firebird.conf + RemoteServicePort [MATCHES] 0 firebird.conf + SecurityDatabase tmp_6444 security4.fdb databases.conf + ServerMode SuperClassic Super firebird.conf + SnapshotsMemSize 103809024 65536 databases.conf + StatementTimeout 999 0 databases.conf + TcpLoopbackFastPath false true firebird.conf + TcpNoNagle false true firebird.conf + TcpRemoteBufferSize 5555 8192 firebird.conf + TempBlockSize 5242880 1048576 firebird.conf + TempCacheLimit 9223372035781033984 67108864 databases.conf + TempDirectories [MATCHES] firebird.conf + TipCacheBlockSize 3145728 4194304 databases.conf + TraceDSQL 0 0 + TracePlugin fbtrace fbtrace + UdfAccess Restrict UDF None firebird.conf + UseFileSystemCache false true firebird.conf + UserManager Legacy_UserManager, Srp Srp databases.conf + WireCompression true false firebird.conf + WireCrypt Required Required firebird.conf + WireCryptPlugin Arc4 ChaCha, Arc4 firebird.conf + + Records affected: 70 + Records affected: 0 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_6444_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6447.py b/tests/bugs/test_core_6447.py new file mode 100644 index 00000000..2909233c --- /dev/null +++ b/tests/bugs/test_core_6447.py @@ -0,0 +1,63 @@ +#coding:utf-8 +# +# id: bugs.core_6447 +# title: Unexpectedly different text of message for parameterized expression starting from second run +# decription: +# Previous title: "SET SQLDA_DISPLAY ON: different text of message for parameterized expression starting from second run" +# Confirmed bug on: 4.0.0.2267, 3.0.8.33390. +# Checked on 4.0.0.2269; 3.0.8.33391 -- all OK. +# +# tracker_id: CORE-6447 +# min_versions: ['3.0.8'] +# versions: 3.0.8 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.8 +# resources: None + +substitutions_1 = [('^((?!sqltype|SQLSTATE|(e|E)rror|number|SQLDA).)*$', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set sqlda_display on; + select 1 from rdb$database where current_connection = ? and current_transaction = ?; + select 1 from rdb$database where current_connection = ? and current_transaction = ?; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 01: sqltype: 580 INT64 scale: 0 subtype: 0 len: 8 + 02: sqltype: 580 INT64 scale: 0 subtype: 0 len: 8 + 01: sqltype: 496 LONG scale: 0 subtype: 0 len: 4 + + 01: sqltype: 580 INT64 scale: 0 subtype: 0 len: 8 + 02: sqltype: 580 INT64 scale: 0 subtype: 0 len: 8 + 01: sqltype: 496 LONG scale: 0 subtype: 0 len: 4 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 07002 + Dynamic SQL Error + -SQLDA error + -No SQLDA for input values provided + + Statement failed, SQLSTATE = 07002 + Dynamic SQL Error + -SQLDA error + -No SQLDA for input values provided + """ + +@pytest.mark.version('>=3.0.8') +def test_core_6447_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6452.py b/tests/bugs/test_core_6452.py new file mode 100644 index 00000000..292b90cf --- /dev/null +++ b/tests/bugs/test_core_6452.py @@ -0,0 +1,59 @@ +#coding:utf-8 +# +# id: bugs.core_6452 +# title: SIMILAR TO leads to an infinite loop +# decription: +# One more test to check 're2' library. +# Confirmed on 3.0.8, no problems with 4.0 (checked on 4.0.0.2296). +# +# tracker_id: CORE-6452 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + select + 1 + from + RDB$DATABASE + where + ' + + + + + + + + + + + + ' similar to '%title="_{3,40}" value="true"%'; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 1 + """ + +@pytest.mark.version('>=4.0') +def test_core_6452_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6453.py b/tests/bugs/test_core_6453.py new file mode 100644 index 00000000..1f45f14c --- /dev/null +++ b/tests/bugs/test_core_6453.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: bugs.core_6453 +# title: EXECUTE STATEMENT fails on FB 4.x if containing time/timestamp with time zone parameters +# decription: +# Confirmed bug on 4.0.0.2265 +# Checked on 4.0.0.2303; 3.0.8.33393; 2.5.9.27152 +# +# tracker_id: CORE-6453 +# min_versions: ['2.5'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^; + execute block as + declare sttm varchar(100); + declare result varchar(100); + begin + sttm = 'select current_time from rdb$database'; + execute statement sttm into result; + + sttm = 'select current_timestamp from rdb$database'; + execute statement sttm into result; + end + ^ + set term ;^ + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5.0') +def test_core_6453_1(act_1: Action): + act_1.execute() + diff --git a/tests/bugs/test_core_6458.py b/tests/bugs/test_core_6458.py new file mode 100644 index 00000000..39cb8a04 --- /dev/null +++ b/tests/bugs/test_core_6458.py @@ -0,0 +1,157 @@ +#coding:utf-8 +# +# id: bugs.core_6458 +# title: Regression: Cancel Query function no longer works +# decription: +# We create .sql script with 'heavy query' that for sure will run more than several seconds. +# Then we launch asynchronous ISQL process to perform this query and take small pause for 1-2 second. +# 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 ::: +# subprocess.Popen() must have argument: creationflags = subprocess.CREATE_NEW_PROCESS_GROUP +# Otherwise we can not send signal Ctrl_C_EVENT to the child process. +# 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. +# +# tracker_id: CORE-6458 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import platform +# import subprocess +# import signal +# import datetime +# import time +# import re +# +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# FB_HOME = services.connect(host='localhost', user= user_name, password= user_password).get_home_directory() +# FB_BINS = os.path.join( FB_HOME, 'bin'+os.sep if platform.system() == 'Linux' else '' ) +# +# +# #-------------------------------------------- +# def showtime(): +# global datetime +# return ''.join( (datetime.datetime.now().strftime("%H:%M:%S.%f")[:11],'.') ) +# #-------------------------------------------- +# 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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# if os.path.isfile( f_names_list[i]): +# print('ERROR: can not remove file ' + f_names_list[i]) +# exit(1) +# #------------------------------------------------- +# +# f_sql_cmd = open( os.path.join(context['temp_directory'],'tmp-c6458.sql'),'w') +# f_sql_cmd.write("set list on; select count(*) as LONG_QUERY_RESULT from (select 1 i from rdb$types a,rdb$types b,rdb$types c);") +# f_sql_cmd.close() +# +# f_sql_log = open( os.path.splitext(f_sql_cmd.name)[0] + '.log','w') +# f_sql_err = open( os.path.splitext(f_sql_cmd.name)[0] + '.err','w') +# +# try: +# p_long = subprocess.Popen( [ os.path.join(FB_BINS, 'isql'), dsn, '-q', '-i', f_sql_cmd.name] +# ,stdout=f_sql_log +# ,stderr=f_sql_err +# ,creationflags = subprocess.CREATE_NEW_PROCESS_GROUP # <<< MANDATORY FOR SENDING CTRL_C SIGNAL <<< +# ) +# time.sleep(1) +# p_long.send_signal(signal.CTRL_C_EVENT) +# p_long.wait() +# print('Was ISQL process terminated ? => ', p_long.poll()) +# except Exception,e: +# print(e) +# finally: +# flush_and_close( f_sql_log ) +# flush_and_close( f_sql_err ) +# #-------------------------------------------------- +# +# with open(f_sql_log.name) as f: +# for line in f: +# if line.split(): +# print('UNEXPECTED STDOUT: ', line) +# +# allowed_patterns = ( +# re.compile('.*SQLSTATE\\s+=\\s+HY008', re.IGNORECASE) +# ,re.compile('operation\\s+(was\\s+)?cancelled', re.IGNORECASE) +# ) +# +# with open(f_sql_err.name) as f: +# for line in f: +# if line.split(): +# match2some = filter( None, [ p.search(line) for p in allowed_patterns ] ) +# if match2some: +# print( (' '.join(line.split()).lower()) ) +# +# # cleanup +# ######### +# time.sleep(1) +# cleanup( [ i.name for i in (f_sql_cmd, f_sql_log, f_sql_err) ] ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Was ISQL process terminated ? => 1 + statement failed, sqlstate = hy008 + operation was cancelled + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_6458_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6460.py b/tests/bugs/test_core_6460.py new file mode 100644 index 00000000..d29b5c1a --- /dev/null +++ b/tests/bugs/test_core_6460.py @@ -0,0 +1,68 @@ +#coding:utf-8 +# +# id: bugs.core_6460 +# title: Incorrect query result when using named window +# decription: +# Confirmed bug on 4.0.0.2265. Discussed with Vlad 21.12.2020 (subj: "fresh fails on 4.0.0.2298"). +# Checked on 4.0.0.2307 -- all OK. +# More examples will be implemented later. +# +# tracker_id: CORE-6460 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test ( + emp_no smallint, + dept_no char(3), + salary numeric(10,2) + ); + commit; + + insert into test (emp_no, dept_no, salary) values ( 85, 'd01', 99999); + insert into test (emp_no, dept_no, salary) values (127, 'd01', 11111); + commit; + + select e.emp_no, e.dept_no, e.salary, + last_value(e.salary) over (order by e.salary, e.emp_no) as last_2, + last_value(e.salary) over w2 as last_w2, + last_value(e.salary) over (order by e.salary, e.emp_no RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as last_3, + last_value(e.salary) over w3 as last_w3, + last_value(e.salary) over w4 as last_w4 + from test e + window + w1 as (), + w2 as (w1 order by e.salary, e.emp_no), + w3 as (w1 order by e.salary, e.emp_no RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING), + w4 as (w2 RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) + order by e.emp_no + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + EMP_NO DEPT_NO SALARY LAST_2 LAST_W2 LAST_3 LAST_W3 LAST_W4 + 85 d01 99999.00 99999.00 99999.00 99999.00 99999.00 99999.00 + 127 d01 11111.00 11111.00 11111.00 99999.00 99999.00 99999.00 + """ + +@pytest.mark.version('>=4.0') +def test_core_6460_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6466.py b/tests/bugs/test_core_6466.py new file mode 100644 index 00000000..25ca4d42 --- /dev/null +++ b/tests/bugs/test_core_6466.py @@ -0,0 +1,142 @@ +#coding:utf-8 +# +# id: bugs.core_6466 +# title: Comments before the first line of code are removed (when extract metadata) +# decription: +# Lot of comments (multi-line blocks) are inserted before each clause/token of created SP +# (in its declaration of name, input and output parameters, sections of variables and after +# final 'end'). +# Comments before 'AS' clause will be removed after SP commit (i.e. they must not be shown +# when metadata is axtracted - at least for current versions of FB). +# First comment _after_ 'AS' clause (and before 1st 'declare variable' statement) *must* +# be preserved. +# Comment after final 'end' of procedure must also be preserved. +# +# Confirmed bug on: +# * 4.0.0.2353 - final comment ('950' in this script) was not stored; +# * 3.0.8.33401 - comments before first declaration of variable ('900') and after final +# 'end' ('950') were not stored. +# Checked on 4.0.0.2365, 3.0.8.33415 -- all fine. +# +# tracker_id: CORE-6466 +# min_versions: ['3.0.8'] +# versions: 3.0.8 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.8 +# resources: None + +substitutions_1 = [('^((?!comment-[\\d]+).)*$', ''), ('[ \t]+', ' ')] + +init_script_1 = """ + set term ^; + create or alter procedure sp_test1 + /* + comment-100 + */ + ( + /* + comment-150 + */ + int_a int + /* + comment-200 + */ + , + /* + comment-230 + */ + int_b int + /* + comment-250 + */ + ) + /* + comment-300 + */ + returns + /* + comment-400 + */ + ( + /* + comment-500 + */ + out_a + /* + comment-600 + */ + int + /* + comment-700 + */ + ,out_b int + /* + comment-750 + */ + ) + /* + comment-800 + */ + as + /* + comment-900 + */ + declare + /* + comment-910 + */ + int_c + /* + comment-920 + */ + int = 2 + /* + comment-930 + */ + ; + /* + comment-940 + */ + begin + /* code */ + int_b=int_a+int_c+2; + suspend; + end + /* + comment-950 + */ + ^ + commit + ^ + set term ;^ + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# runProgram('isql', [dsn, '-x', '-user', user_name, '-pas', user_password], ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + comment-900 + comment-910 + comment-920 + comment-930 + comment-940 + comment-950 + """ + +@pytest.mark.version('>=3.0.8') +@pytest.mark.xfail +def test_core_6466_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6469.py b/tests/bugs/test_core_6469.py new file mode 100644 index 00000000..78859c8f --- /dev/null +++ b/tests/bugs/test_core_6469.py @@ -0,0 +1,613 @@ +#coding:utf-8 +# +# id: bugs.core_6469 +# title: Provide ability to see in the trace log actions related to session management (e.g. ALTER SESSION RESET) +# decription: +# 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. +# +# Checked on: +# * Windows: 4.0.0.2235, 4.0.0.2377 (both on SS/CS). +# * Linux: 4.0.0.2377 SS/CS. +# +# tracker_id: CORE-6469 +# min_versions: ['4.0'] +# versions: 4.0, 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import re +# import subprocess +# import time +# import socket +# import getpass +# import re +# from fdb import services +# from subprocess import Popen +# +# # REMOVING OS-VARIABLE ISC_USER IS MANDATORY HERE !!! +# # This variable could be set by other .fbts which was performed before current within batch mode (i.e. when fbt_run is called from ) +# # NB: os.unsetenv('ISC_USER') actually does NOT affect on content of os.environ dictionary, see: https://docs.python.org/2/library/os.html +# # We have to remove OS variable either by os.environ.pop() or using 'del os.environ[...]', but in any case this must be enclosed intro try/exc: +# #os.environ.pop('ISC_USER') +# try: +# del os.environ["ISC_USER"] +# except KeyError as e: +# pass +# +# +# THIS_DBA_USER=user_name +# THIS_DBA_PSWD=user_password +# +# THIS_COMPUTER_NAME = socket.gethostname() +# CURRENT_WIN_ADMIN = getpass.getuser() +# +# THIS_FDB = db_conn.database_name +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql=''' +# set bail on; +# set list on; +# set echo on; +# connect 'localhost:%(THIS_FDB)s' user %(THIS_DBA_USER)s password '%(THIS_DBA_PSWD)s'; +# set term ^; +# execute block as +# begin +# execute statement 'drop role tmp$r6469'; +# when any do begin end +# end +# ^ +# set term ;^ +# commit; +# +# create role TMP$R6469; +# grant tmp$r6469 to "%(THIS_COMPUTER_NAME)s\\%(CURRENT_WIN_ADMIN)s"; +# 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)s:%(THIS_FDB)s' 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 'localhost:%(THIS_FDB)s' user %(THIS_DBA_USER)s password '%(THIS_DBA_PSWD)s'; +# drop mapping trusted_auth; +# drop mapping win_admins; +# commit; +# ''' % locals() +# +# f_sql_cmd=open( os.path.join(context['temp_directory'],'tmp_c6469_cmd.sql'), 'w') +# f_sql_cmd.write(sql) +# flush_and_close( f_sql_cmd ) +# +# txt = '''# Generated auto, do not edit! +# database=%[\\\\\\\\/]security?.fdb +# { +# enabled = false +# } +# database=%[\\\\\\\\/]bugs.core_6469.fdb +# { +# enabled = true +# time_threshold = 0 +# log_initfini = false +# log_warnings = false +# log_errors = true +# log_statement_finish = true +# } +# ''' +# +# f_trc_cfg=open( os.path.join(context['temp_directory'],'tmp_c6469_trc.cfg'), 'w') +# f_trc_cfg.write(txt) +# flush_and_close( f_trc_cfg ) +# +# # ############################################################## +# # S T A R T T R A C E i n S E P A R A T E P R O C E S S +# # ############################################################## +# +# f_trc_log=open( os.path.join(context['temp_directory'],'tmp_c6469_trc.log'), "w") +# f_trc_err=open( os.path.join(context['temp_directory'],'tmp_c6469_trc.err'), "w") +# +# p_trace = Popen( [ context['fbsvcmgr_path'], 'localhost:service_mgr', 'user', user_name, 'password', user_password, 'action_trace_start', 'trc_cfg', f_trc_cfg.name], +# stdout=f_trc_log, +# stderr=f_trc_err +# ) +# +# time.sleep(1) +# +# f_isql_log=open( os.path.join(context['temp_directory'],'tmp_c6469_run.log'), 'w') +# f_isql_err=open( os.path.join(context['temp_directory'],'tmp_c6469_run.err'), 'w') +# +# ###################### +# # S T A R T I S Q L +# ###################### +# subprocess.call( [context['isql_path'], '-q', '-i', f_sql_cmd.name], +# stdout=f_isql_log, +# stderr=subprocess.STDOUT +# #stderr=f_isql_err +# ) +# flush_and_close( f_isql_log ) +# flush_and_close( f_isql_err ) +# +# +# # #################################################### +# # G E T A C T I V E T R A C E S E S S I O N I D +# # #################################################### +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# +# f_trc_lst = open( os.path.join(context['temp_directory'],'tmp_c6469_trc_session_idle.lst'), 'w') +# subprocess.call([context['fbsvcmgr_path'], 'localhost:service_mgr', 'user', user_name, 'password', user_password, 'action_trace_list' ], stdout=f_trc_lst) +# flush_and_close( f_trc_lst ) +# +# trcssn=0 +# with open( f_trc_lst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# +# +# # #################################################### +# # S E N D R E Q U E S T T R A C E T O S T O P +# # #################################################### +# if trcssn>0: +# fn_nul = open(os.devnull, 'w') +# subprocess.call([context['fbsvcmgr_path'], 'localhost:service_mgr', 'user', user_name, 'password', user_password, 'action_trace_stop','trc_id', trcssn], stdout=fn_nul) +# fn_nul.close() +# # DO NOT REMOVE THIS LINE: +# time.sleep(1) +# +# p_trace.terminate() +# flush_and_close( f_trc_log ) +# flush_and_close( f_trc_err ) +# +# +# # Following files must be EMPTY: +# ################# +# f_list=(f_trc_err,f_isql_err,) +# for i in range(len(f_list)): +# f_name=f_list[i].name +# if os.path.getsize(f_name) > 0: +# with open( f_name,'r') as f: +# for line in f: +# print("Unexpected TRCERR, file "+f_name+": "+line) +# +# +# allowed_patterns = ( +# 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) +# ) +# +# with open(f_trc_log.name) as f: +# for line in f: +# if line.split(): +# match2some = filter( None, [ p.search(line) for p in allowed_patterns ] ) +# if match2some: +# print( (' '.join(line.split()).lower()) ) +# +# # CLEANUP +# ######### +# time.sleep(1) +# cleanup( (f_trc_cfg, f_trc_lst, f_trc_log, f_trc_err, f_sql_cmd, f_isql_log, f_isql_err ) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 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 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_core_6469_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +# test_script_2 +#--- +# +# import os +# import re +# import subprocess +# import time +# import socket +# import getpass +# import re +# from fdb import services +# from subprocess import Popen +# +# # REMOVING OS-VARIABLE ISC_USER IS MANDATORY HERE !!! +# # This variable could be set by other .fbts which was performed before current within batch mode (i.e. when fbt_run is called from ) +# # NB: os.unsetenv('ISC_USER') actually does NOT affect on content of os.environ dictionary, see: https://docs.python.org/2/library/os.html +# # We have to remove OS variable either by os.environ.pop() or using 'del os.environ[...]', but in any case this must be enclosed intro try/exc: +# #os.environ.pop('ISC_USER') +# try: +# del os.environ["ISC_USER"] +# except KeyError as e: +# pass +# +# +# THIS_DBA_USER=user_name +# THIS_DBA_PSWD=user_password +# +# THIS_COMPUTER_NAME = socket.gethostname() +# CURRENT_WIN_ADMIN = getpass.getuser() +# +# THIS_FDB = db_conn.database_name +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql=''' +# set bail on; +# set list on; +# connect 'localhost:%(THIS_FDB)s' user %(THIS_DBA_USER)s password '%(THIS_DBA_PSWD)s'; +# set term ^; +# execute block as +# begin +# execute statement 'drop role tmp$r6469'; +# when any do begin end +# end +# ^ +# set term ;^ +# commit; +# +# create 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; +# +# -- connect 'localhost:%(THIS_FDB)s' user %(THIS_DBA_USER)s password '%(THIS_DBA_PSWD)s'; +# 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; +# ''' % locals() +# +# f_sql_cmd=open( os.path.join(context['temp_directory'],'tmp_c6469_cmd.sql'), 'w') +# f_sql_cmd.write(sql) +# flush_and_close( f_sql_cmd ) +# +# txt = '''# Generated auto, do not edit! +# database=%[\\\\\\\\/]security?.fdb +# { +# enabled = false +# } +# database=%[\\\\\\\\/]bugs.core_6469.fdb +# { +# enabled = true +# log_initfini = false +# log_warnings = false +# log_errors = true +# time_threshold = 0 +# log_connections = true +# log_statement_finish = true +# } +# ''' +# +# f_trc_cfg=open( os.path.join(context['temp_directory'],'tmp_c6469_trc.cfg'), 'w') +# f_trc_cfg.write(txt) +# flush_and_close( f_trc_cfg ) +# +# # ############################################################## +# # S T A R T T R A C E i n S E P A R A T E P R O C E S S +# # ############################################################## +# +# f_trc_log=open( os.path.join(context['temp_directory'],'tmp_c6469_trc.log'), "w") +# f_trc_err=open( os.path.join(context['temp_directory'],'tmp_c6469_trc.err'), "w") +# +# p_trace = Popen( [ context['fbsvcmgr_path'], 'localhost:service_mgr', 'user', user_name, 'password', user_password, 'action_trace_start', 'trc_cfg', f_trc_cfg.name], +# stdout=f_trc_log, +# stderr=f_trc_err +# ) +# +# time.sleep(1) +# +# f_isql_log=open( os.path.join(context['temp_directory'],'tmp_c6469_run.log'), 'w') +# f_isql_err=open( os.path.join(context['temp_directory'],'tmp_c6469_run.err'), 'w') +# +# ###################### +# # S T A R T I S Q L +# ###################### +# subprocess.call( [context['isql_path'], '-q', '-i', f_sql_cmd.name], +# stdout=f_isql_log, +# stderr=subprocess.STDOUT +# #stderr=f_isql_err +# ) +# flush_and_close( f_isql_log ) +# flush_and_close( f_isql_err ) +# +# # 04.03.2021: do NOT remove this delay! +# time.sleep(1) +# +# # #################################################### +# # G E T A C T I V E T R A C E S E S S I O N I D +# # #################################################### +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# +# f_trc_lst = open( os.path.join(context['temp_directory'],'tmp_c6469_trc_session_idle.lst'), 'w') +# subprocess.call([context['fbsvcmgr_path'], 'localhost:service_mgr', 'user', user_name, 'password', user_password, 'action_trace_list' ], stdout=f_trc_lst) +# flush_and_close( f_trc_lst ) +# +# trcssn=0 +# with open( f_trc_lst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# +# +# # #################################################### +# # S E N D R E Q U E S T T R A C E T O S T O P +# # #################################################### +# if trcssn>0: +# fn_nul = open(os.devnull, 'w') +# subprocess.call([context['fbsvcmgr_path'], 'localhost:service_mgr', 'user', user_name, 'password', user_password, 'action_trace_stop','trc_id', trcssn], stdout=fn_nul) +# fn_nul.close() +# # DO NOT REMOVE THIS LINE: +# time.sleep(1) +# +# p_trace.terminate() +# flush_and_close( f_trc_log ) +# flush_and_close( f_trc_err ) +# +# +# # Following files must be EMPTY: +# ################# +# f_list=(f_trc_err,f_isql_err,) +# for i in range(len(f_list)): +# f_name=f_list[i].name +# if os.path.getsize(f_name) > 0: +# with open( f_name,'r') as f: +# for line in f: +# print("Unexpected TRCERR, file "+f_name+": "+line) +# +# +# allowed_patterns = ( +# 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) +# ) +# +# with open(f_trc_log.name) as f: +# for line in f: +# if line.split(): +# match2some = filter( None, [ p.search(line) for p in allowed_patterns ] ) +# if match2some: +# print( (' '.join(line.split()).lower()) ) +# +# # CLEANUP +# ######### +# time.sleep(1) +# cleanup( (f_trc_cfg, f_trc_lst, f_trc_log, f_trc_err, f_sql_cmd, f_isql_log, f_isql_err ) ) +# +# +#--- +#act_2 = python_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + 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 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.platform('Linux') +@pytest.mark.xfail +def test_core_6469_2(db_2): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6474.py b/tests/bugs/test_core_6474.py new file mode 100644 index 00000000..c441da30 --- /dev/null +++ b/tests/bugs/test_core_6474.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: bugs.core_6474 +# title: Report replica mode through isc_database_info, MON$DATABASE and SYSTEM context +# decription: +# Text verifies only ability to query replication-related info from mon$database and system context namespace. +# Query to isc_database_info does not perform. +# +# Checked on 4.0.0.2342. +# tracker_id: CORE-6474 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select mon$replica_mode as mon_replica_mode from mon$database; + select '>' || rdb$get_context('SYSTEM','REPLICA_MODE') || '<' as ctx_replica_mode from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MON_REPLICA_MODE 0 + CTX_REPLICA_MODE >< + """ + +@pytest.mark.version('>=4.0') +def test_core_6474_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6479.py b/tests/bugs/test_core_6479.py new file mode 100644 index 00000000..da6dfb98 --- /dev/null +++ b/tests/bugs/test_core_6479.py @@ -0,0 +1,60 @@ +#coding:utf-8 +# +# id: bugs.core_6479 +# title: COMMENT ON USER can only apply comment on user defined by the default usermanager plugin +# decription: +# ::: NOTE ::: +# There is no sense to check for Legacy_UserManarer: comment for user will not be stored in the sec$users for this plugin. +# Test verifies only Srp. Discussed with Alex, 12.03.2021 +# +# Checked on: 4.0.02386, 3.0.8.33425 +# +# tracker_id: CORE-6479 +# min_versions: ['3.0.8'] +# versions: 3.0.8 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.8 +# resources: None + +substitutions_1 = [('SEC_DESCR_BLOB_ID .*', ''), ('[\t ]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter user tmp$c6479_srp password '123' using plugin Srp; + commit; + comment on user tmp$c6479_srp using plugin Srp is 'This is description for Srp-user'; + -- ================ + commit; + + set list on; + set count on; + select s.sec$user_name, s.sec$plugin, s.sec$description as sec_descr_blob_id + from sec$users s + where s.sec$user_name = upper('tmp$c6479_srp') + ; + drop user tmp$c6479_srp using plugin Srp; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + SEC$USER_NAME TMP$C6479_SRP + SEC$PLUGIN Srp + This is description for Srp-user + Records affected: 1 + """ + +@pytest.mark.version('>=3.0.8') +def test_core_6479_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6486.py b/tests/bugs/test_core_6486.py new file mode 100644 index 00000000..d7ed0a9b --- /dev/null +++ b/tests/bugs/test_core_6486.py @@ -0,0 +1,80 @@ +#coding:utf-8 +# +# id: bugs.core_6486 +# title: FETCH RELATIVE has an off by one error for the first row +# decription: +# Confirmed bug on 4.0.0.2365. +# Checked on 3.0.8.33423, 4.0.0.2369 - works OK. +# tracker_id: CORE-6486 +# min_versions: ['3.0.8'] +# versions: 3.0.8 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.8 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set term ^; + execute block returns(id_fetch_rel1 int, rc_fetch_rel1 int) as + declare c scroll cursor for + ( + select 1 id from rdb$database union all + select 2 id from rdb$database union all + select 3 id from rdb$database + ) + ; + begin + open c; + fetch relative 1 from c; + id_fetch_rel1 = c.id; + rc_fetch_rel1 = row_count; + suspend; + close c; + end + ^ + + execute block returns(id_fetch_next int, rc_fetch_next int) as + declare c scroll cursor for + ( + select 1 id from rdb$database union all + select 2 id from rdb$database union all + select 3 id from rdb$database + ) + ; + begin + open c; + fetch next from c; + id_fetch_next = c.id; + rc_fetch_next = row_count; + suspend; + close c; + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID_FETCH_REL1 1 + RC_FETCH_REL1 1 + ID_FETCH_NEXT 1 + RC_FETCH_NEXT 1 + """ + +@pytest.mark.version('>=3.0.8') +def test_core_6486_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6487.py b/tests/bugs/test_core_6487.py new file mode 100644 index 00000000..7a3eb62b --- /dev/null +++ b/tests/bugs/test_core_6487.py @@ -0,0 +1,89 @@ +#coding:utf-8 +# +# id: bugs.core_6487 +# title: FETCH ABSOLUTE and RELATIVE beyond bounds of cursor should always position immediately before-first or after-last +# decription: +# Confirmed bug on 4.0.0.2365, 3.0.8.33415. +# Checked on 4.0.0.2369, 3.0.8.33416 - works OK. +# tracker_id: CORE-6487 +# min_versions: ['3.0.8'] +# versions: 3.0.8 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.8 +# resources: None + +substitutions_1 = [('-At block line:.*', '-At block line')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + set term ^; + execute block returns(id int, rc int) as + declare c scroll cursor for + ( + select 1 id from rdb$database union all + select 2 id from rdb$database union all + select 3 id from rdb$database + ) + ; + begin + open c; + fetch absolute 9223372036854775807 from c; + + fetch relative -(9223372036854775807-2) from c; + id = c.id; + rc = row_count; + suspend; + + close c; + end + ^ + + execute block returns(id int, rc int) as + declare c scroll cursor for + ( + select 1 id from rdb$database union all + select 2 id from rdb$database union all + select 3 id from rdb$database + ) + ; + begin + open c; + fetch absolute -9223372036854775808 from c; + + fetch relative (9223372036854775806) from c; + id = c.id; + rc = row_count; + suspend; + + close c; + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = HY109 + Cursor C is not positioned in a valid record + -At block line: 14, col: 5 + + Statement failed, SQLSTATE = HY109 + Cursor C is not positioned in a valid record + -At block line: 14, col: 5 + """ + +@pytest.mark.version('>=3.0.8') +def test_core_6487_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_6489.py b/tests/bugs/test_core_6489.py new file mode 100644 index 00000000..ebbbbac3 --- /dev/null +++ b/tests/bugs/test_core_6489.py @@ -0,0 +1,81 @@ +#coding:utf-8 +# +# id: bugs.core_6489 +# title: User without ALTER ANY ROLE privilege can use COMMENT ON ROLE +# decription: +# Test creates two users: one of them has no any rights, second is granted with 'alter any role' privilege. +# First user ('junior') must not have ability to add comment to rdb$admin role, but second ('senior') must +# be able to set comment to any string and make it null. +# +# Confirmed bug on 4.0.0.2384, 3.0.8.33425 +# Checked on: 4.0.0.2387, 3.0.8.33426 -- all OK. +# +# NOTE: +# phrase '-Effective user is ...' presents only in FB 4.x and is suppressed here. +# +# tracker_id: CORE-6489 +# min_versions: ['3.0.8'] +# versions: 3.0.8 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.8 +# resources: None + +substitutions_1 = [('ROLE_DESCR_BLOB_ID .*', ''), ('[\t ]+', ' '), ('(-)?Effective user is.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter user tmp$c6489_junior password '123' using plugin Srp; + create or alter user tmp$c6489_senior password '456' using plugin Srp; + commit; + grant alter any role to user tmp$c6489_senior; + commit; + + connect '$(DSN)' user tmp$c6489_junior password '123'; + comment on role rdb$admin is 'Comment by tmp$c6489_junior'; + commit; + + connect '$(DSN)' user tmp$c6489_senior password '456'; + comment on role rdb$admin is 'Comment by tmp$c6489_senior'; + commit; + + set list on; + select r.rdb$description as role_descr_blob_id from rdb$roles r where r.rdb$role_name = upper('rdb$admin'); + commit; + + comment on role rdb$admin is null; + commit; + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + drop user tmp$c6489_junior using plugin Srp; + drop user tmp$c6489_senior using plugin Srp; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Comment by tmp$c6489_senior + """ +expected_stderr_1 = """ + 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 + """ + +@pytest.mark.version('>=3.0.8') +def test_core_6489_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6494.py b/tests/bugs/test_core_6494.py new file mode 100644 index 00000000..135f5f56 --- /dev/null +++ b/tests/bugs/test_core_6494.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: bugs.core_6494 +# title: Inconsistent translation "string->timestamp->string->timestamp" in dialect 1 +# decription: +# Confirmed bug on: 4.0.0.2406, 3.0.8.33441. +# Checked on: 4.0.0.2416, 3.0.8.33445 - all fine. +# +# tracker_id: CORE-6494 +# min_versions: ['3.0.8'] +# versions: 3.0.8 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.8 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=1, init=init_script_1) + +test_script_1 = """ + set heading off; + select cast(cast(cast(cast('2-dec-0083' as timestamp) as varchar(64))as timestamp)as varchar(64)) from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 02-DEC-0083 + """ + +@pytest.mark.version('>=3.0.8') +def test_core_6494_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6496.py b/tests/bugs/test_core_6496.py new file mode 100644 index 00000000..847a9c31 --- /dev/null +++ b/tests/bugs/test_core_6496.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: bugs.core_6496 +# title: string_to_datetime and '\\0' symbol +# decription: +# ascii_char(0) was allowed to be concatenated with string and pass then to cast(... as timestamp) +# up to 4.0.0.1227 (29-09-2018), and is forbidden since 4.0.0.1346 (17.12.2018). +# FB 3.x allows this character to be used and issues timestamp instead of error. +# +# tracker_id: CORE-6496 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + select cast('5.3.2021 01:02:03.1234' || ascii_char(0) as timestamp) from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22009 + Invalid time zone region: + """ + +@pytest.mark.version('>=4.0') +def test_core_6496_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/bugs/test_core_6499.py b/tests/bugs/test_core_6499.py new file mode 100644 index 00000000..6bbff251 --- /dev/null +++ b/tests/bugs/test_core_6499.py @@ -0,0 +1,77 @@ +#coding:utf-8 +# +# id: bugs.core_6499 +# title: Regression: can not get statistics for selected table(s) via services, get "found unknown switch" error +# decription: +# Test creates several tables and request statistics for one of them usin Services API. +# Output must contain for one and only one (selected) table - TEST_01 (and its index). +# All lines from output which do not include this name are ignored (see 'subst' section). +# +# Confirmed bug on 4.0.0.2377, 3.0.8.33420, got: +# Unable to perform the requested Service API action: +# - SQLCODE: -901 +# - found unknown switch +# -901 +# 336920577 +# Checked on: 4.0.0.2384, 3.0.8.33424 -- all fine. +# +# tracker_id: CORE-6499 +# min_versions: ['3.0.8'] +# versions: 3.0.8 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.8 +# resources: None + +substitutions_1 = [('^((?!TEST_01\\s+\\(|TEST_01_ID\\s+\\().)*$', ''), ('TEST_01\\s+\\(.*', 'TEST_01'), ('Index TEST_01_ID\\s+\\(.*', 'Index TEST_01_ID'), ('[ \t]+', ' ')] + +init_script_1 = """ + recreate table test_01(id int); + recreate table test__01(id int); + recreate table test__011(id int); + commit; + insert into test_01 select row_number()over() from rdb$types; + commit; + create index test_01_id on test_01(id); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_name=db_conn.database_name +# db_conn.close() +# +# svc = services.connect(host='localhost') +# # print(svc.get_server_version()) +# svc.get_statistics(database = db_name, show_user_data_pages=1, show_user_index_pages=1, tables = 'TEST_01') +# info = svc.readlines() +# svc.wait() +# for r in info: +# print(r) +# svc.close() +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TEST_01 (128) + Index TEST_01_ID (0) + """ + +@pytest.mark.version('>=3.0.8') +@pytest.mark.xfail +def test_core_6499_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6509.py b/tests/bugs/test_core_6509.py new file mode 100644 index 00000000..3886e803 --- /dev/null +++ b/tests/bugs/test_core_6509.py @@ -0,0 +1,125 @@ +#coding:utf-8 +# +# id: bugs.core_6509 +# title: Segfault when gfix requests for database page buffer more memory than available from OS +# decription: +# Confirmed crash on 4.0.0.2377 (Windows and Linux) +# Checked on 4.0.0.2384 - all OK, get STDERR: "unable to allocate memory from operating system" +# NB: currently acceptable value for '-buffers' is limited from 50 to 2147483646. +# +# tracker_id: CORE-6509 +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=32768, sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import sys +# import re +# import time +# +# so=sys.stdout +# se=sys.stderr +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_name = db_conn.database_name +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# f_log = open( os.path.join(context['temp_directory'],'tmp_c6509.log'), 'w') +# f_err = open( os.path.join(context['temp_directory'],'tmp_c6509.err'), 'w') +# sys.stdout = f_log +# sys.stderr = f_err +# +# runProgram('gstat',[ '-h', db_name ]) +# runProgram('gfix',[dsn,'-buffers','2147483646']) +# runProgram('gstat',[ '-h', db_name ]) +# +# sys.stdout = so +# sys.stderr = se +# +# flush_and_close( f_log ) +# flush_and_close( f_err ) +# +# pattern_for_page_buffers = re.compile('\\s*Page\\s+buffers\\s+\\d+', re.IGNORECASE) +# +# buffers_set=set() +# with open(f_log.name,'r') as f: +# for line in f: +# if pattern_for_page_buffers.search(line): +# buffers_set.add( line.split()[2] ) +# # print('gstat output:', line) +# +# print( 'Buffers value was ' + ('not changed (expected)' if len(buffers_set) == 1 else 'UNEXPECTEDLY changed: ' + (', '.join(buffers_set)) ) ) +# +# with open(f_err.name,'r') as f: +# for line in f: +# print('STDERR in gfix:', line) +# +# # cleanup: +# ########## +# time.sleep(1) +# cleanup( (f_log,f_err) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Buffers value was not changed (expected) + STDERR in gfix: unable to allocate memory from operating system + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_6509_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6517.py b/tests/bugs/test_core_6517.py new file mode 100644 index 00000000..530cc903 --- /dev/null +++ b/tests/bugs/test_core_6517.py @@ -0,0 +1,76 @@ +#coding:utf-8 +# +# id: bugs.core_6517 +# 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 +# decription: +# Confirmed bug on 4.0.0.2394, 3.0.8.33426 +# Checked on 4.0.0.2401, 3.0.8.33435 -- all OK. +# +# tracker_id: CORE-6517 +# min_versions: ['3.0.8'] +# versions: 3.0.8 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.8 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# temp_fdb = os.path.join( '$(DATABASE_LOCATION)', 'tmp_core_6517.tmp' ) +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# cleanup( (temp_fdb,) ) +# con = fdb.create_database('create database "%s" default character set utf8' % temp_fdb) +# # print( con.database_name ) +# con.close() +# +# # CLEANUP +# ######### +# time.sleep(1) +# cleanup( (temp_fdb,) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0.8') +@pytest.mark.xfail +def test_core_6517_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6521.py b/tests/bugs/test_core_6521.py new file mode 100644 index 00000000..6687838e --- /dev/null +++ b/tests/bugs/test_core_6521.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: bugs.core_6521 +# title: CAST of Infinity values to FLOAT doesn't work +# decription: +# Confirmed bug on 4.0.0.2394, 3.0.8.33426 +# Checked on intermediate builds 4.0.0.2401 (03-apr-2021 09:36), 3.0.8.33435 (03-apr-2021 09:35) -- all OK. +# +# tracker_id: CORE-6521 +# min_versions: ['3.0.8'] +# versions: 3.0.8 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.8 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + select cast(log(1, 1.5) as float) from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Infinity + """ + +@pytest.mark.version('>=3.0.8') +def test_core_6521_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6526.py b/tests/bugs/test_core_6526.py new file mode 100644 index 00000000..da260a7c --- /dev/null +++ b/tests/bugs/test_core_6526.py @@ -0,0 +1,58 @@ +#coding:utf-8 +# +# id: bugs.core_6526 +# title: AV in engine when StatementTimeout is active for user statement and some internal DSQL statement was executed as part of overall execution process +# decription: +# Confirmed crash on 4.0.0.2387. +# Checked on 4.0.0.2394 SS/CS - works OK. +# +# tracker_id: CORE-6526 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set heading off; + set term ^; + execute block as begin + in autonomous transaction do + execute statement 'set statistics index rdb$index_0'; + end + ^ + set statement timeout 60 + ^ + execute block as begin + in autonomous transaction do + execute statement 'set statistics index rdb$index_0'; + end + ^ + set term ;^ + commit; + select 'Done.' from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Done. + """ + +@pytest.mark.version('>=4.0') +def test_core_6526_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6527.py b/tests/bugs/test_core_6527.py new file mode 100644 index 00000000..a46c81f4 --- /dev/null +++ b/tests/bugs/test_core_6527.py @@ -0,0 +1,204 @@ +#coding:utf-8 +# +# id: bugs.core_6527 +# title: Regression: inline comment of SP parameter with closing parenthesis leads to incorrect SQL when trying to extract metadata +# decription: +# Confirmed bug on 4.0.0.2394, 3.0.8.33426 +# Checked on 4.0.0.2401, 3.0.8.33435 -- all OK. +# +# tracker_id: CORE-6527 +# min_versions: ['3.0.8'] +# versions: 3.0.8 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.8 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import shutil +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# this_fdb = db_conn.database_name +# temp_fdb = os.path.join( '$(DATABASE_LOCATION)', 'tmp_core_6527.tmp' ) +# db_conn.close() +# +# shutil.copy(this_fdb, temp_fdb) +# +# #-------------------------------------------- +# +# 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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql_ddl=''' +# set term ^; +# create or alter procedure sp_test( +# a_base_doc_id int, +# a_base_doc_oper_id int default null -- (one of parameters to standalone procedure) +# ) +# as +# declare v_info varchar(100); +# begin +# +# v_info = 'base_doc='||a_base_doc_id; +# end +# ^ +# create or alter function fn_test( +# a_base_doc_id int, +# a_base_doc_oper_id int default null -- (one of parameters to standalone function) +# ) +# returns int +# as +# declare v_info varchar(100); +# begin +# +# v_info = 'base_doc='||a_base_doc_id; +# return 1; +# end +# ^ +# +# create or alter package pg_test as +# begin +# procedure sp_test( +# a_base_doc_id int, +# a_base_doc_oper_id int default null -- (one of parameters to packaged procedure) +# ); +# function fn_test( +# a_base_doc_id int, +# a_base_doc_oper_id int default null -- (one of parameters to packaged procedure) +# ) returns int; +# end +# ^ +# recreate package body pg_test as +# begin +# procedure sp_test( +# a_base_doc_id int, +# a_base_doc_oper_id int -- (one of parameters to packaged procedure) +# ) as +# begin +# -- nop -- +# end +# +# function fn_test( +# a_base_doc_id int, +# a_base_doc_oper_id int -- (one of parameters to packaged procedure) +# ) returns int as +# begin +# return 1; +# end +# end +# ^ +# set term ;^ +# commit; +# ''' +# +# f_init_sql = open( os.path.join(context['temp_directory'], 'tmp_6527_init.sql'), 'w' ) +# f_init_sql.write( sql_ddl ) +# flush_and_close( f_init_sql ) +# +# +# f_init_log = open( os.path.join(context['temp_directory'], 'tmp_6527_init.log'), 'w' ) +# f_init_err = open( os.path.join(context['temp_directory'], 'tmp_6527_init.err'), 'w' ) +# +# subprocess.call( [ context['isql_path'], dsn, "-q", "-i", f_init_sql.name ], +# stdout = f_init_log, +# stderr = f_init_err +# ) +# +# flush_and_close( f_init_log ) +# flush_and_close( f_init_err ) +# +# f_meta_sql = open( os.path.join(context['temp_directory'],'tmp_meta_6527.sql'), 'w') +# f_meta_err = open( os.path.join(context['temp_directory'],'tmp_meta_6527.err'), 'w') +# +# subprocess.call( [ context['isql_path'], "-x", dsn], +# stdout = f_meta_sql, +# stderr = f_meta_err +# ) +# +# flush_and_close( f_meta_sql ) +# flush_and_close( f_meta_err ) +# +# f_apply_log = open( os.path.join(context['temp_directory'],'tmp_apply_6527.log'), 'w') +# f_apply_err = open( os.path.join(context['temp_directory'],'tmp_apply_6527.err'), 'w') +# +# subprocess.call( [ context['isql_path'], 'localhost:'+temp_fdb, "-i", f_meta_sql.name ], +# stdout = f_apply_log, +# stderr = f_apply_err +# ) +# +# flush_and_close( f_apply_log ) +# flush_and_close( f_apply_err ) +# +# # Check: +# ######## +# +# # Output must be empty: +# with open( f_meta_err.name,'r') as f: +# for line in f: +# print("METADATA EXTRACTION PROBLEM, STDERR: "+line) +# +# # Output must be empty: +# with open( f_apply_err.name,'r') as f: +# for line in f: +# print("METADATA APPLYING PROBLEM, STDERR: "+line) +# +# # CLEANUP +# ######### +# time.sleep(1) +# cleanup( (f_init_sql, f_init_log, f_init_err,f_meta_sql, f_meta_err, f_apply_log, f_apply_err, temp_fdb) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0.8') +@pytest.mark.xfail +def test_core_6527_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6529.py b/tests/bugs/test_core_6529.py new file mode 100644 index 00000000..57ec7be8 --- /dev/null +++ b/tests/bugs/test_core_6529.py @@ -0,0 +1,66 @@ +#coding:utf-8 +# +# id: bugs.core_6529 +# title: Error "no current record for fetch operation" when sorting by a international string +# decription: +# Confirmed bug on 4.0.0.2394, got: +# - SQLCODE: -508 / - no current record for fetch operation / -508 / 335544348 +# Checked on 4.0.0.2401 - all OK. +# +# tracker_id: CORE-6529 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# db_conn.execute_immediate('recreate table t (f varchar(32765) character set win1251)') +# db_conn.commit() +# +# cur = db_conn.cursor() +# +# cur.execute( "insert into t(f) values(?)", ('W' * 1000,) ) +# # no commit here! +# +# try: +# cur.execute('select f from t order by 1') +# for r in cur: +# pass +# print('Passed.') +# except Exception,e: +# print('Exception in cursor:') +# print( '-' * 30 ) +# for x in e: +# print(x) +# print( '-' * 30 ) +# finally: +# cur.close() +# db_conn.close() +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Passed. + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_core_6529_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/bugs/test_core_6531.py b/tests/bugs/test_core_6531.py new file mode 100644 index 00000000..885ce775 --- /dev/null +++ b/tests/bugs/test_core_6531.py @@ -0,0 +1,86 @@ +#coding:utf-8 +# +# id: bugs.core_6531 +# title: COMPUTED BY column looses charset and collate of source field when is either of type BLOB or VARCHAR casted to BLOB +# decription: +# Confirmed bug on 4.0.0.2394, 3.0.8.33426 +# Checked on intermediate builds 4.0.0.2401 (03-apr-2021 09:36), 3.0.8.33435 (03-apr-2021 09:35) -- all OK. +# +# tracker_id: CORE-6531 +# min_versions: ['3.0.8'] +# versions: 3.0.8 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.8 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create collation name_coll for utf8 from unicode case insensitive; + commit; + + create domain dm_name_ci as blob sub_type text character set utf8 collate name_coll; + commit; + + recreate table test( + id int + ,b1 dm_name_ci + ,calc_b1 computed by ( b1 ) + ----------------------------------------------------- + ,c1 varchar(10) character set utf8 collate name_coll + ,calc_c1 computed by ( cast(c1 as blob sub_type text character set utf8) collate name_coll ) -- ==> SQLDA: "charset: 0 NONE" + --,calc_c1 computed by ( (select list(x.c1) from test x where x.id = test.id) ) -- ==> SQLDA: "charset: 0 NONE" + --,calc_c1 computed by ( cast(c1 as varchar(10) character set utf8) collate name_coll ) -- ==> SQLDA: "charset: 32260 UTF8" // OK + ); + + insert into test(id, b1, c1) values(1,'qWE','qWE'); + insert into test(id, b1, c1) values(2,'QWe','QWe'); + insert into test(id, b1, c1) values(3,'qwE','qwE'); + commit; + + set list on; + set count on; + -- set echo on; + + --------------------------------------------- + + select id + from test where calc_c1 starting with 'qwe' + order by id; + + --------------------------------------------- + + select id + from test where calc_b1 starting with 'qwe' + order by id; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + ID 2 + ID 3 + Records affected: 3 + + ID 1 + ID 2 + ID 3 + Records affected: 3 + """ + +@pytest.mark.version('>=3.0.8') +def test_core_6531_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6532.py b/tests/bugs/test_core_6532.py new file mode 100644 index 00000000..d149ffc8 --- /dev/null +++ b/tests/bugs/test_core_6532.py @@ -0,0 +1,100 @@ +#coding:utf-8 +# +# id: bugs.core_6532 +# title: Results of concatenation with blob has no info about collation of source columns (which are declared with such info) +# decription: +# Confirmed bug on 4.0.0.2394, 3.0.8.33426 +# Checked on intermediate builds 4.0.0.2401 (03-apr-2021 09:36), 3.0.8.33435 (03-apr-2021 09:35) -- all OK. +# +# tracker_id: CORE-6532 +# min_versions: ['3.0.8'] +# versions: 3.0.8 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.8 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create collation name_coll for utf8 from unicode case insensitive; + commit; + + --create domain dm_name_ci as varchar(10) character set utf8 collate name_coll; + create domain dm_name_ci as blob sub_type text character set utf8 collate name_coll; + commit; + + recreate table test( + id int + ,c1 varchar(10) character set utf8 collate name_coll + ,b1 dm_name_ci + --,b1 blob sub_type text character set utf8 collate name_coll -- same result + ); + + insert into test(id, c1, b1) values(1,'qWE','qWE'); + insert into test(id, c1, b1) values(2,'QWe','QWe'); + insert into test(id, c1, b1) values(3,'qwE','qwE'); + commit; + + set count on; + -- set echo on; + set list on; + + --------------------------------------------- + + select id from test + where + b1 starting with 'qwe' -- Records affected: 3 // OK + order by id + ; + + + --------------------------------------------- + + select id from test + where + b1 || b1 starting with 'qwe' -- Was wrong: "Records affected: 0" + order by id + ; + + -------------------------------------------- + + select id from test + where + c1 || cast(c1 as blob sub_type text character set utf8) collate name_coll starting with 'qwe' -- Was wrong: "Records affected: 0" + order by id + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + ID 2 + ID 3 + Records affected: 3 + + ID 1 + ID 2 + ID 3 + Records affected: 3 + + ID 1 + ID 2 + ID 3 + Records affected: 3 + """ + +@pytest.mark.version('>=3.0.8') +def test_core_6532_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/bugs/test_core_6534.py b/tests/bugs/test_core_6534.py new file mode 100644 index 00000000..6857efb2 --- /dev/null +++ b/tests/bugs/test_core_6534.py @@ -0,0 +1,55 @@ +#coding:utf-8 +# +# id: bugs.core_6534 +# title: Hash join cannot match records using some TIME ZONE / DECFLOAT keys +# decription: +# Confirmed bug on 4.0.0.2387. +# Checked on intermediate build 4.0.0.2406 (built 06-apr-2021 12:40) - all OK. +# +# tracker_id: CORE-6534 +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- All subsequent statements must return non-empty result: + set heading off; + select 1 from (select timestamp '01.01.2021 13:00:00 +03:00' as ts from rdb$database) natural join (select timestamp '01.01.2021 12:00:00 +02:00' as ts from rdb$database); + select 2 from (select cast(10 as decfloat) as df from rdb$database) natural join (select cast(10.000 as decfloat) as df from rdb$database); + select 3 from (select cast('+0' as decfloat) as df from rdb$database) natural join (select cast('-0' as decfloat) as df from rdb$database); + select 4 from (select cast('+0' as float) as f from rdb$database) natural join (select cast('-0' as float) as f from rdb$database); + select 5 from (select cast('+0' as double precision) as d from rdb$database) natural join (select cast('-0' as double precision) as d from rdb$database); + select 6 from (select cast('0E-6176' as decfloat) as d from rdb$database) natural join (select cast('0e0' as decfloat) as d from rdb$database); + select 7 from (select time '05:05:05.5555' at time zone '-10:0' t from rdb$database) natural join (select time '05:05:05.5555' at time zone '+14:0' t from rdb$database); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 1 + 2 + 3 + 4 + 5 + 6 + 7 + """ + +@pytest.mark.version('>=4.0') +def test_core_6534_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/__init__.py b/tests/functional/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/arno/__init__.py b/tests/functional/arno/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/arno/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/arno/derived_tables/__init__.py b/tests/functional/arno/derived_tables/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/arno/derived_tables/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/arno/derived_tables/test_01.py b/tests/functional/arno/derived_tables/test_01.py new file mode 100644 index 00000000..025f77b2 --- /dev/null +++ b/tests/functional/arno/derived_tables/test_01.py @@ -0,0 +1,68 @@ +#coding:utf-8 +# +# id: functional.arno.derived_tables.derived_tables_01 +# title: Simple derived table 1 +# decription: Test simple derived table +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.derived_tables.derived_tables_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL, + DESCRIPTION VARCHAR(10) +); + +COMMIT; + +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (0, NULL); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (1, 'one'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (2, 'two'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (3, 'three'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (4, 'four'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (5, 'five'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (6, 'six'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (7, 'seven'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (8, 'eight'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (9, 'nine'); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT + dt.* +FROM + (SELECT * FROM Table_10 t10) dt; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ ID DESCRIPTION +============ =========== + 0 + 1 one + 2 two + 3 three + 4 four + 5 five + 6 six + 7 seven + 8 eight + 9 nine""" + +@pytest.mark.version('>=2.0') +def test_derived_tables_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/derived_tables/test_02.py b/tests/functional/arno/derived_tables/test_02.py new file mode 100644 index 00000000..35a383e7 --- /dev/null +++ b/tests/functional/arno/derived_tables/test_02.py @@ -0,0 +1,68 @@ +#coding:utf-8 +# +# id: functional.arno.derived_tables.derived_tables_02 +# title: Simple derived table 2 +# decription: Test unnamed (no relation alias) derived table +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.derived_tables.derived_tables_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL, + DESCRIPTION VARCHAR(10) +); + +COMMIT; + +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (0, NULL); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (1, 'one'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (2, 'two'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (3, 'three'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (4, 'four'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (5, 'five'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (6, 'six'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (7, 'seven'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (8, 'eight'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (9, 'nine'); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT + * +FROM + (SELECT * FROM Table_10 t10); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ ID DESCRIPTION +============ =========== + 0 + 1 one + 2 two + 3 three + 4 four + 5 five + 6 six + 7 seven + 8 eight + 9 nine""" + +@pytest.mark.version('>=2.0') +def test_derived_tables_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/derived_tables/test_03.py b/tests/functional/arno/derived_tables/test_03.py new file mode 100644 index 00000000..52cac83a --- /dev/null +++ b/tests/functional/arno/derived_tables/test_03.py @@ -0,0 +1,68 @@ +#coding:utf-8 +# +# id: functional.arno.derived_tables.derived_tables_03 +# title: Simple derived table 3 +# decription: Test explicit column names for derived table +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.derived_tables.derived_tables_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL, + DESCRIPTION VARCHAR(10) +); + +COMMIT; + +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (0, NULL); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (1, 'one'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (2, 'two'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (3, 'three'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (4, 'four'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (5, 'five'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (6, 'six'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (7, 'seven'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (8, 'eight'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (9, 'nine'); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT + dt.* +FROM + (SELECT * FROM Table_10 t10) dt (TEST_ID, TEST_DESC); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ TEST_ID TEST_DESC +============ ========== + 0 + 1 one + 2 two + 3 three + 4 four + 5 five + 6 six + 7 seven + 8 eight + 9 nine""" + +@pytest.mark.version('>=2.0') +def test_derived_tables_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/derived_tables/test_04.py b/tests/functional/arno/derived_tables/test_04.py new file mode 100644 index 00000000..6482752c --- /dev/null +++ b/tests/functional/arno/derived_tables/test_04.py @@ -0,0 +1,62 @@ +#coding:utf-8 +# +# id: functional.arno.derived_tables.derived_tables_04 +# title: Simple derived table 4 +# decription: Derived table column names must be unique. +# tracker_id: +# min_versions: [] +# versions: 2.5.0 +# qmid: functional.arno.derived_tables.derived_tables_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL, + DESCRIPTION VARCHAR(10) +); + +COMMIT; + +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (0, NULL); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (1, 'one'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (2, 'two'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (3, 'three'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (4, 'four'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (5, 'five'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (6, 'six'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (7, 'seven'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (8, 'eight'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (9, 'nine'); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT + dt.* +FROM + (SELECT ID, ID FROM Table_10 t10) dt; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42000 +Dynamic SQL Error +-SQL error code = -104 +-Invalid command +-column ID was specified multiple times for derived table DT +""" + +@pytest.mark.version('>=2.5.0') +def test_derived_tables_04_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/arno/derived_tables/test_05.py b/tests/functional/arno/derived_tables/test_05.py new file mode 100644 index 00000000..ac3e1333 --- /dev/null +++ b/tests/functional/arno/derived_tables/test_05.py @@ -0,0 +1,62 @@ +#coding:utf-8 +# +# id: functional.arno.derived_tables.derived_tables_05 +# title: Simple derived table 5 +# decription: Derived table column names must be unique. +# tracker_id: +# min_versions: [] +# versions: 2.5.0 +# qmid: functional.arno.derived_tables.derived_tables_05 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL, + DESCRIPTION VARCHAR(10) +); + +COMMIT; + +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (0, NULL); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (1, 'one'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (2, 'two'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (3, 'three'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (4, 'four'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (5, 'five'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (6, 'six'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (7, 'seven'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (8, 'eight'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (9, 'nine'); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT + dt.* +FROM + (SELECT * FROM Table_10 t10) dt (ID, ID); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42000 +Dynamic SQL Error +-SQL error code = -104 +-Invalid command +-column ID was specified multiple times for derived table DT +""" + +@pytest.mark.version('>=2.5.0') +def test_derived_tables_05_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/arno/derived_tables/test_06.py b/tests/functional/arno/derived_tables/test_06.py new file mode 100644 index 00000000..ebf87fed --- /dev/null +++ b/tests/functional/arno/derived_tables/test_06.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: functional.arno.derived_tables.derived_tables_06 +# title: Derived table 6 outer reference +# decription: Outer reference inside derived table to other relations in from clause is not allowed. +# tracker_id: +# min_versions: [] +# versions: 2.5.0 +# qmid: functional.arno.derived_tables.derived_tables_06 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [('column.*', '')] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL, + DESCRIPTION VARCHAR(10) +); + +COMMIT; + +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (0, NULL); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (1, 'one'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (2, 'two'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (3, 'three'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (4, 'four'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (5, 'five'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (6, 'six'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (7, 'seven'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (8, 'eight'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (9, 'nine'); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT + dt.* +FROM + Table_10 t10 + JOIN (SELECT * FROM Table_10 t2 WHERE t2.ID = t10.ID) dt ON (1 = 1); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42S22 +Dynamic SQL Error +-SQL error code = -206 +-Column unknown +-T10.ID +-At line 5, column 53 + +""" + +@pytest.mark.version('>=2.5.0') +def test_derived_tables_06_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/arno/derived_tables/test_07.py b/tests/functional/arno/derived_tables/test_07.py new file mode 100644 index 00000000..044904ad --- /dev/null +++ b/tests/functional/arno/derived_tables/test_07.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: functional.arno.derived_tables.derived_tables_07 +# title: Derived table 7 outer reference +# decription: Outer reference inside derived table to other relations in from clause is not allowed. +# tracker_id: +# min_versions: [] +# versions: 2.5.0 +# qmid: functional.arno.derived_tables.derived_tables_07 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [('column.*', '')] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL, + DESCRIPTION VARCHAR(10) +); + +COMMIT; + +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (0, NULL); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (1, 'one'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (2, 'two'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (3, 'three'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (4, 'four'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (5, 'five'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (6, 'six'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (7, 'seven'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (8, 'eight'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (9, 'nine'); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT + dt.* +FROM + Table_10 t10 + LEFT JOIN (SELECT * FROM Table_10 t2 WHERE t2.ID = t10.ID) dt ON (1 = 1); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42S22 +Dynamic SQL Error +-SQL error code = -206 +-Column unknown +-T10.ID +-At line 5, column 58 + +""" + +@pytest.mark.version('>=2.5.0') +def test_derived_tables_07_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/arno/derived_tables/test_08.py b/tests/functional/arno/derived_tables/test_08.py new file mode 100644 index 00000000..2a9405af --- /dev/null +++ b/tests/functional/arno/derived_tables/test_08.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: functional.arno.derived_tables.derived_tables_08 +# title: Derived table 8 outer reference +# decription: Outer reference inside derived table to other relations in from clause is not allowed. +# tracker_id: +# min_versions: [] +# versions: 2.5.0 +# qmid: functional.arno.derived_tables.derived_tables_08 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [('column.*', '')] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL, + DESCRIPTION VARCHAR(10) +); + +COMMIT; + +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (0, NULL); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (1, 'one'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (2, 'two'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (3, 'three'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (4, 'four'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (5, 'five'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (6, 'six'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (7, 'seven'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (8, 'eight'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (9, 'nine'); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT + dt.* +FROM + Table_10 t10 + FULL JOIN (SELECT * FROM Table_10 t2 WHERE t2.ID = t10.ID) dt ON (1 = 1); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42S22 +Dynamic SQL Error +-SQL error code = -206 +-Column unknown +-T10.ID +-At line 5, column 58 + +""" + +@pytest.mark.version('>=2.5.0') +def test_derived_tables_08_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/arno/derived_tables/test_09.py b/tests/functional/arno/derived_tables/test_09.py new file mode 100644 index 00000000..72e9a153 --- /dev/null +++ b/tests/functional/arno/derived_tables/test_09.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: functional.arno.derived_tables.derived_tables_09 +# title: Derived table 9 outer reference +# decription: Outer reference inside derived table to other relations in from clause is not allowed. +# tracker_id: +# min_versions: [] +# versions: 2.5.0 +# qmid: functional.arno.derived_tables.derived_tables_09 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [('column.*', '')] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL, + DESCRIPTION VARCHAR(10) +); + +COMMIT; + +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (0, NULL); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (1, 'one'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (2, 'two'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (3, 'three'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (4, 'four'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (5, 'five'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (6, 'six'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (7, 'seven'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (8, 'eight'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (9, 'nine'); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT + dt.* +FROM + Table_10 t10 + FULL JOIN (SELECT * FROM Table_10 t2 WHERE t2.ID = t10.ID) dt ON (1 = 1); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42S22 +Dynamic SQL Error +-SQL error code = -206 +-Column unknown +-T10.ID +-At line 5, column 58 + +""" + +@pytest.mark.version('>=2.5.0') +def test_derived_tables_09_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/arno/derived_tables/test_10.py b/tests/functional/arno/derived_tables/test_10.py new file mode 100644 index 00000000..7929d928 --- /dev/null +++ b/tests/functional/arno/derived_tables/test_10.py @@ -0,0 +1,70 @@ +#coding:utf-8 +# +# id: functional.arno.derived_tables.derived_tables_10 +# title: Derived table 10 outer reference +# decription: Outer reference to upper scope-level is allowed. Such as fields inside derived table part of sub-query. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.derived_tables.derived_tables_10 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL, + DESCRIPTION VARCHAR(10) +); + +COMMIT; + +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (0, NULL); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (1, 'one'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (2, 'two'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (3, 'three'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (4, 'four'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (5, 'five'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (6, 'six'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (7, 'seven'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (8, 'eight'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (9, 'nine'); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT + t10.ID, + (SELECT dt.Description FROM (SELECT t1.Description FROM + Table_10 t1 WHERE t1.ID = t10.ID) dt) AS Description +FROM + Table_10 t10; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ ID DESCRIPTION +============ =========== + 0 + 1 one + 2 two + 3 three + 4 four + 5 five + 6 six + 7 seven + 8 eight + 9 nine""" + +@pytest.mark.version('>=2.0') +def test_derived_tables_10_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/derived_tables/test_11.py b/tests/functional/arno/derived_tables/test_11.py new file mode 100644 index 00000000..43b91c75 --- /dev/null +++ b/tests/functional/arno/derived_tables/test_11.py @@ -0,0 +1,71 @@ +#coding:utf-8 +# +# id: functional.arno.derived_tables.derived_tables_11 +# title: Derived table 11 outer reference +# decription: Outer reference to upper scope-level is allowed. Such as fields inside derived table part of sub-query (IN-predicate). +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.derived_tables.derived_tables_11 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL, + DESCRIPTION VARCHAR(10) +); + +COMMIT; + +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (0, NULL); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (1, 'one'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (2, 'two'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (3, 'three'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (4, 'four'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (5, 'five'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (6, 'six'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (7, 'seven'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (8, 'eight'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (9, 'nine'); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT + t10.ID, + t10.Description +FROM + Table_10 t10 +WHERE + t10.ID IN (SELECT dt.ID FROM (SELECT t1.ID FROM + Table_10 t1 WHERE t1.ID = t10.ID) dt);""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ ID DESCRIPTION +============ =========== + 0 + 1 one + 2 two + 3 three + 4 four + 5 five + 6 six + 7 seven + 8 eight + 9 nine""" + +@pytest.mark.version('>=2.0') +def test_derived_tables_11_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/derived_tables/test_12.py b/tests/functional/arno/derived_tables/test_12.py new file mode 100644 index 00000000..8c280ceb --- /dev/null +++ b/tests/functional/arno/derived_tables/test_12.py @@ -0,0 +1,71 @@ +#coding:utf-8 +# +# id: functional.arno.derived_tables.derived_tables_12 +# title: Derived table 12 outer reference +# decription: Outer reference to upper scope-level is allowed. Such as fields inside derived table part of sub-query (EXISTS). +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.derived_tables.derived_tables_12 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL, + DESCRIPTION VARCHAR(10) +); + +COMMIT; + +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (0, NULL); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (1, 'one'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (2, 'two'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (3, 'three'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (4, 'four'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (5, 'five'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (6, 'six'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (7, 'seven'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (8, 'eight'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (9, 'nine'); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT + t10.ID, + t10.Description +FROM + Table_10 t10 +WHERE + EXISTS(SELECT dt.ID FROM (SELECT t1.ID FROM + Table_10 t1 WHERE t1.ID = t10.ID) dt);""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ ID DESCRIPTION +============ =========== + 0 + 1 one + 2 two + 3 three + 4 four + 5 five + 6 six + 7 seven + 8 eight + 9 nine""" + +@pytest.mark.version('>=2.0') +def test_derived_tables_12_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/derived_tables/test_13.py b/tests/functional/arno/derived_tables/test_13.py new file mode 100644 index 00000000..9ee70cf8 --- /dev/null +++ b/tests/functional/arno/derived_tables/test_13.py @@ -0,0 +1,67 @@ +#coding:utf-8 +# +# id: functional.arno.derived_tables.derived_tables_13 +# title: Simple derived table +# decription: Test DISTINCT inside derived table. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.derived_tables.derived_tables_13 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL, + DESCRIPTION VARCHAR(10) +); + +COMMIT; + +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (0, NULL); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (1, 'one'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (2, 'two'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (3, 'three'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (4, 'five'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (5, 'five'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (6, 'five'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (7, 'seven'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (8, 'eight'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (9, 'nine'); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT + dt.DESCRIPTION +FROM + (SELECT DISTINCT DESCRIPTION FROM Table_10 t10) dt (DESCRIPTION); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """DESCRIPTION +=========== + +eight +five +nine +one +seven +three +two +""" + +@pytest.mark.version('>=2.0') +def test_derived_tables_13_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/derived_tables/test_14.py b/tests/functional/arno/derived_tables/test_14.py new file mode 100644 index 00000000..ae3b0de6 --- /dev/null +++ b/tests/functional/arno/derived_tables/test_14.py @@ -0,0 +1,63 @@ +#coding:utf-8 +# +# id: functional.arno.derived_tables.derived_tables_14 +# title: Simple derived table +# decription: Test FIRST / SKIP inside derived table. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.derived_tables.derived_tables_14 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL, + DESCRIPTION VARCHAR(10) +); + +COMMIT; + +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (0, NULL); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (1, 'one'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (2, 'two'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (3, 'three'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (4, 'four'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (5, 'five'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (6, 'six'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (7, 'seven'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (8, 'eight'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (9, 'nine'); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT + dt.ID, + dt.DESCRIPTION +FROM + (SELECT FIRST 4 SKIP 2 ID, DESCRIPTION FROM Table_10 t10 ORDER BY ID) dt (ID, DESCRIPTION) +WHERE + dt.ID >= 4; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ ID DESCRIPTION +============ =========== + 4 four + 5 five""" + +@pytest.mark.version('>=2.0') +def test_derived_tables_14_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/derived_tables/test_15.py b/tests/functional/arno/derived_tables/test_15.py new file mode 100644 index 00000000..583ff650 --- /dev/null +++ b/tests/functional/arno/derived_tables/test_15.py @@ -0,0 +1,71 @@ +#coding:utf-8 +# +# id: functional.arno.derived_tables.derived_tables_15 +# title: Simple derived table +# decription: Test UNION inside derived table. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.derived_tables.derived_tables_15 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL, + DESCRIPTION VARCHAR(10) +); + +COMMIT; + +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (0, NULL); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (1, 'one'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (2, 'two'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (3, 'three'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (4, 'four'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (5, 'five'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (6, 'six'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (7, 'seven'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (8, 'eight'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (9, 'nine'); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT + dt.ID, + dt.DESCRIPTION +FROM + (SELECT t1.ID, t1.DESCRIPTION FROM Table_10 t1 WHERE t1.ID <= 4 + UNION ALL + SELECT t1.ID, t1.DESCRIPTION FROM Table_10 t1 WHERE t1.ID >= 5) dt (ID, DESCRIPTION); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ ID DESCRIPTION +============ =========== + 0 + 1 one + 2 two + 3 three + 4 four + 5 five + 6 six + 7 seven + 8 eight + 9 nine""" + +@pytest.mark.version('>=2.0') +def test_derived_tables_15_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/derived_tables/test_16.py b/tests/functional/arno/derived_tables/test_16.py new file mode 100644 index 00000000..6d0c8e7e --- /dev/null +++ b/tests/functional/arno/derived_tables/test_16.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: functional.arno.derived_tables.derived_tables_16 +# title: Simple derived table +# decription: Test aggregate inside derived table. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.derived_tables.derived_tables_16 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL, + GROUPID INTEGER, + DESCRIPTION VARCHAR(10) +); + +COMMIT; + +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (0, NULL, NULL); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (1, 1, 'one'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (2, 1, 'two'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (3, 2, 'three'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (4, 2, 'four'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (5, 2, 'five'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (6, 3, 'six'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (7, 3, 'seven'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (8, 3, 'eight'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (9, 3, 'nine'); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT + dt.* +FROM + (SELECT t1.GROUPID, Count(t1.ID) FROM Table_10 t1 GROUP BY t1.GROUPID) dt (GROUPID, ID_COUNT); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ GROUPID ID_COUNT +============ ===================== + 1 + 1 2 + 2 3 + 3 4 + +""" + +@pytest.mark.version('>=3.0') +def test_derived_tables_16_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/derived_tables/test_17.py b/tests/functional/arno/derived_tables/test_17.py new file mode 100644 index 00000000..5904449f --- /dev/null +++ b/tests/functional/arno/derived_tables/test_17.py @@ -0,0 +1,64 @@ +#coding:utf-8 +# +# id: functional.arno.derived_tables.derived_tables_17 +# title: Simple derived table +# decription: Test aggregate inside derived table. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.derived_tables.derived_tables_17 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL, + GROUPID INTEGER, + DESCRIPTION VARCHAR(10) +); + +COMMIT; + +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (0, NULL, NULL); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (1, 1, 'one'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (2, 1, 'two'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (3, 2, 'three'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (4, 2, 'four'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (5, 2, 'five'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (6, 3, 'six'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (7, 3, 'seven'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (8, 3, 'eight'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (9, 3, 'nine'); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT + dt.* +FROM + (SELECT t1.GROUPID, Count(t1.ID) FROM Table_10 t1 GROUP BY t1.GROUPID) dt (GROUPID, ID_COUNT) +WHERE + dt.ID_COUNT = 2; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ GROUPID ID_COUNT +============ ===================== + 1 2 + +""" + +@pytest.mark.version('>=3.0') +def test_derived_tables_17_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/derived_tables/test_18.py b/tests/functional/arno/derived_tables/test_18.py new file mode 100644 index 00000000..db5a7b7d --- /dev/null +++ b/tests/functional/arno/derived_tables/test_18.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: functional.arno.derived_tables.derived_tables_18 +# title: Simple derived table +# decription: Test aggregate inside derived table. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.derived_tables.derived_tables_18 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL, + GROUPID INTEGER, + DESCRIPTION VARCHAR(10) +); + +COMMIT; + +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (0, NULL, NULL); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (1, 1, 'one'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (2, 1, 'two'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (3, 2, 'three'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (4, 2, 'four'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (5, 2, 'five'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (6, 3, 'six'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (7, 3, 'seven'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (8, 3, 'eight'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (9, 3, 'nine'); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT + dt.* +FROM + (SELECT t1.GROUPID, Count(t1.ID) FROM Table_10 t1 GROUP BY t1.GROUPID) dt (GROUPID, ID_COUNT) +WHERE + dt.GROUPID >= 2; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ GROUPID ID_COUNT +============ ===================== + 2 3 + 3 4 + +""" + +@pytest.mark.version('>=3.0') +def test_derived_tables_18_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/derived_tables/test_19.py b/tests/functional/arno/derived_tables/test_19.py new file mode 100644 index 00000000..7d8e456a --- /dev/null +++ b/tests/functional/arno/derived_tables/test_19.py @@ -0,0 +1,69 @@ +#coding:utf-8 +# +# id: functional.arno.derived_tables.derived_tables_19 +# title: Simple derived table +# decription: Test sub-select inside derived table. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.derived_tables.derived_tables_19 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL, + GROUPID INTEGER, + DESCRIPTION VARCHAR(10) +); + +COMMIT; + +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (0, NULL, NULL); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (1, 1, 'one'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (2, 1, 'two'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (3, 2, 'three'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (4, 2, 'four'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (5, 2, 'five'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (6, 3, 'six'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (7, 3, 'seven'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (8, 3, 'eight'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (9, 3, 'nine'); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT + dt.* +FROM + (SELECT t2.ID, t2.GROUPID, (SELECT t1.GROUPID FROM Table_10 t1 WHERE t1.ID = t2.ID) FROM Table_10 t2) dt (ID, GROUPID1, GROUPID2); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ ID GROUPID1 GROUPID2 +============ ============ ============ + 0 + 1 1 1 + 2 1 1 + 3 2 2 + 4 2 2 + 5 2 2 + 6 3 3 + 7 3 3 + 8 3 3 + 9 3 3""" + +@pytest.mark.version('>=2.0') +def test_derived_tables_19_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/derived_tables/test_20.py b/tests/functional/arno/derived_tables/test_20.py new file mode 100644 index 00000000..b13a468c --- /dev/null +++ b/tests/functional/arno/derived_tables/test_20.py @@ -0,0 +1,70 @@ +#coding:utf-8 +# +# id: functional.arno.derived_tables.derived_tables_20 +# title: Simple derived table +# decription: Test sub-select inside derived table. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.derived_tables.derived_tables_20 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL, + GROUPID INTEGER, + DESCRIPTION VARCHAR(10) +); + +COMMIT; + +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (0, NULL, NULL); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (1, 1, 'one'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (2, 1, 'two'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (3, 2, 'three'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (4, 2, 'four'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (5, 2, 'five'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (6, 3, 'six'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (7, 3, 'seven'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (8, 3, 'eight'); +INSERT INTO Table_10 (ID, GROUPID, DESCRIPTION) VALUES (9, 3, 'nine'); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT + dt.* +FROM + (SELECT + t2.GROUPID, + (SELECT MIN(t1.ID) FROM Table_10 t1 WHERE t1.GROUPID = t2.GROUPID), + (SELECT MAX(t1.ID) FROM Table_10 t1 WHERE t1.GROUPID = t2.GROUPID) + FROM + Table_10 t2 + GROUP BY + t2.GROUPID) dt (GROUPID, MIN_ID, MAX_ID); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ GROUPID MIN_ID MAX_ID +============ ============ ============ + + 1 1 2 + 2 3 5 + 3 6 9""" + +@pytest.mark.version('>=2.0') +def test_derived_tables_20_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/derived_tables/test_21.py b/tests/functional/arno/derived_tables/test_21.py new file mode 100644 index 00000000..5c243bb9 --- /dev/null +++ b/tests/functional/arno/derived_tables/test_21.py @@ -0,0 +1,61 @@ +#coding:utf-8 +# +# id: functional.arno.derived_tables.derived_tables_21 +# title: Implicit derived table by IN predicate +# decription: IN predicate uses derived table internally and should ignore column-name checks (Aggregate functions are unnamed by default). +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.derived_tables.derived_tables_21 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL, + DESCRIPTION VARCHAR(10) +); + +COMMIT; + +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (0, NULL); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (1, 'one'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (2, 'two'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (3, 'three'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (4, 'four'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (5, 'five'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (6, 'six'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (7, 'seven'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (8, 'eight'); +INSERT INTO Table_10 (ID, DESCRIPTION) VALUES (9, 'nine'); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT + t10.ID, + t10.Description +FROM + Table_10 t10 +WHERE + t10.ID IN (SELECT MAX(t1.ID) FROM Table_10 t1);""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ ID DESCRIPTION +============ =========== + 9 nine""" + +@pytest.mark.version('>=2.0') +def test_derived_tables_21_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/derived_tables/test_22.py b/tests/functional/arno/derived_tables/test_22.py new file mode 100644 index 00000000..412d68d1 --- /dev/null +++ b/tests/functional/arno/derived_tables/test_22.py @@ -0,0 +1,93 @@ +#coding:utf-8 +# +# id: functional.arno.derived_tables.derived_tables_22 +# title: Derived table outer reference (triggers) +# decription: NEW/OLD context variables should be available inside the derived table. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.derived_tables.derived_tables_22 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE TABLEA +( + ID INTEGER NOT NULL, + DESCRIPTION VARCHAR(50), + PARENTID INTEGER, + CONSTRAINT PK_TABLEA PRIMARY KEY (ID), + CONSTRAINT FK_TABLEA_TABLEA + FOREIGN KEY (PARENTID) REFERENCES TABLEA (ID) + ON DELETE NO ACTION ON UPDATE CASCADE +); + +COMMIT; + +SET TERM ^^ ; +CREATE TRIGGER TABLEA_BI FOR TABLEA ACTIVE BEFORE INSERT POSITION 0 AS +DECLARE PREV_ID INTEGER; +BEGIN + PREV_ID = NULL; + SELECT ID FROM (SELECT MAX(a.ID) AS ID FROM TABLEA a WHERE a.ID < NEW.ID) INTO :PREV_ID; + NEW.PARENTID = PREV_ID; +END +^^ +SET TERM ; ^^ + + +SET TERM ^^ ; +CREATE TRIGGER TABLEA_BU FOR TABLEA ACTIVE BEFORE UPDATE POSITION 0 AS +DECLARE PREV_ID INTEGER; +BEGIN + PREV_ID = NULL; + SELECT ID FROM (SELECT MAX(a.ID) AS ID FROM TABLEA a WHERE a.ID < OLD.ID) INTO :PREV_ID; + SELECT ID FROM (SELECT MAX(a.ID) AS ID FROM TABLEA a WHERE a.ID < NEW.ID) INTO :PREV_ID; + NEW.PARENTID = PREV_ID; +END +^^ +SET TERM ; ^^ + + +SET TERM ^^ ; +CREATE TRIGGER TABLEA_BD FOR TABLEA ACTIVE BEFORE DELETE POSITION 0 AS +DECLARE PREV_ID INTEGER; +BEGIN + PREV_ID = NULL; + SELECT ID FROM (SELECT MAX(a.ID) AS ID FROM TABLEA a WHERE a.ID < OLD.ID) INTO :PREV_ID; +END +^^ +SET TERM ; ^^ + +COMMIT;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """INSERT INTO TABLEA (ID, DESCRIPTION) VALUES (1, 'Blue'); +INSERT INTO TABLEA (ID, DESCRIPTION) VALUES (2, 'Red'); +INSERT INTO TABLEA (ID, DESCRIPTION) VALUES (4, 'Green'); +INSERT INTO TABLEA (ID, DESCRIPTION) VALUES (8, 'Yellow'); +COMMIT; +SELECT * FROM TABLEA; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ ID DESCRIPTION PARENTID +============ ================================================== ============ + 1 Blue + 2 Red 1 + 4 Green 2 + 8 Yellow 4""" + +@pytest.mark.version('>=2.0') +def test_derived_tables_22_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/indices/__init__.py b/tests/functional/arno/indices/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/arno/indices/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/arno/indices/test_lower_bound_asc_02_segments_01.py b/tests/functional/arno/indices/test_lower_bound_asc_02_segments_01.py new file mode 100644 index 00000000..d422a4e8 --- /dev/null +++ b/tests/functional/arno/indices/test_lower_bound_asc_02_segments_01.py @@ -0,0 +1,85 @@ +#coding:utf-8 +# +# id: functional.arno.indexes.lower_bound_asc_02_segments_01 +# title: ASC 2-segment index lower bound +# decription: Check if all 5 values are fetched with "equals" operator over first segment and "greater than or equal" operator on second segment. +# 2 values are bound to the upper segments and 1 value is bound to the lower segment. +# tracker_id: +# min_versions: [] +# versions: 1.5 +# qmid: functional.arno.indexes.lower_bound_asc_02_segments_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_2_10 ( + F1 INTEGER, + F2 INTEGER +); + +COMMIT; + +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 1); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 2); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 3); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 4); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 5); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 6); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 7); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 8); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 9); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 10); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 1); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 2); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 3); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 4); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 5); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 6); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 7); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 8); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 9); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 10); + +COMMIT; + +CREATE ASC INDEX I_Table_2_10_ASC ON Table_2_10 (F1, F2); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + t.F1, + t.F2 +FROM + Table_2_10 t +WHERE + t.F1 = 2 and t.F2 >= 6;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (T INDEX (I_TABLE_2_10_ASC)) + + F1 F2 +============ ============ + + 2 6 + 2 7 + 2 8 + 2 9 + 2 10 +""" + +@pytest.mark.version('>=1.5') +def test_lower_bound_asc_02_segments_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/indices/test_lower_bound_desc_02_segments_01.py b/tests/functional/arno/indices/test_lower_bound_desc_02_segments_01.py new file mode 100644 index 00000000..c84940d1 --- /dev/null +++ b/tests/functional/arno/indices/test_lower_bound_desc_02_segments_01.py @@ -0,0 +1,85 @@ +#coding:utf-8 +# +# id: functional.arno.indexes.lower_bound_desc_02_segments_01 +# title: DESC 2-segment index lower bound +# decription: Check if all 5 values are fetched with "equals" operator over first segment and "lower than or equal" operator on second segment. +# 2 values are bound to the lower segments and 1 value is bound to the upper segment. +# tracker_id: +# min_versions: [] +# versions: 1.5 +# qmid: functional.arno.indexes.lower_bound_desc_02_segments_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_2_10 ( + F1 INTEGER, + F2 INTEGER +); + +COMMIT; + +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 1); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 2); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 3); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 4); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 5); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 6); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 7); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 8); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 9); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 10); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 1); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 2); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 3); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 4); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 5); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 6); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 7); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 8); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 9); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 10); + +COMMIT; + +CREATE DESC INDEX I_Table_2_10_DESC ON Table_2_10 (F1, F2); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + t.F1, + t.F2 +FROM + Table_2_10 t +WHERE + t.F1 = 2 and t.F2 <= 5;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (T INDEX (I_TABLE_2_10_DESC)) + + F1 F2 +============ ============ + + 2 1 + 2 2 + 2 3 + 2 4 + 2 5 +""" + +@pytest.mark.version('>=1.5') +def test_lower_bound_desc_02_segments_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/indices/test_starting_with_01.py b/tests/functional/arno/indices/test_starting_with_01.py new file mode 100644 index 00000000..c90bb7a4 --- /dev/null +++ b/tests/functional/arno/indices/test_starting_with_01.py @@ -0,0 +1,89 @@ +#coding:utf-8 +# +# id: functional.arno.indexes.starting_with_01 +# title: STARTING WITH charset NONE +# decription: STARTING WITH - Select from table with 2 entries +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.indexes.starting_with_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE A_TEST (F1 VARCHAR(5), F2 VARCHAR(5), F3 VARCHAR(5)); +CREATE INDEX IDX_A_TEST_F1 ON A_TEST(F1); +CREATE DESC INDEX IDX_A_TEST_F2 ON A_TEST(F2); +COMMIT; +INSERT INTO A_TEST (F1, F2, F3) VALUES('', '', ''); +INSERT INTO A_TEST (F1, F2, F3) VALUES(NULL, NULL, NULL); +INSERT INTO A_TEST (F1, F2, F3) VALUES('a', 'a', 'a'); +INSERT INTO A_TEST (F1, F2, F3) VALUES('b', 'b', 'b'); +COMMIT; + +SET TERM ^; + +CREATE PROCEDURE PR_A_TEST_STARTING_WITH(I_START_VALUE VARCHAR(5)) +RETURNS(O_FIELD VARCHAR(32), O_COUNT integer) +AS +BEGIN + /* First retrieve results for indexed ASC field */ + O_FIELD = 'F1 - INDEXED ASC'; + SELECT COUNT(*) FROM A_TEST + WHERE F1 STARTING WITH :I_START_VALUE + INTO :O_COUNT; + + SUSPEND; + + /* Second retrieve results for indexed DESC field */ + O_FIELD = 'F2 - INDEXED DESC'; + SELECT COUNT(*) FROM A_TEST + WHERE F2 STARTING WITH :I_START_VALUE + INTO :O_COUNT; + + SUSPEND; + + /* Thirth for unindexed field */ + O_FIELD = 'F3 - NOT INDEXED'; + SELECT COUNT(*) FROM A_TEST + WHERE F3 STARTING WITH :I_START_VALUE + INTO :O_COUNT; + + SUSPEND; +END^ + +SET TERM ;^ + +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN OFF; +SELECT O_FIELD, O_COUNT FROM PR_A_TEST_STARTING_WITH(''); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """O_FIELD O_COUNT +================================ ============ + +F1 - INDEXED ASC 3 +F2 - INDEXED DESC 3 +F3 - NOT INDEXED 3""" + +@pytest.mark.version('>=2.0') +def test_starting_with_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/indices/test_starting_with_02.py b/tests/functional/arno/indices/test_starting_with_02.py new file mode 100644 index 00000000..46dd6de0 --- /dev/null +++ b/tests/functional/arno/indices/test_starting_with_02.py @@ -0,0 +1,89 @@ +#coding:utf-8 +# +# id: functional.arno.indexes.starting_with_02 +# title: STARTING WITH charset ISO8859_1 +# decription: STARTING WITH - Select from table with 2 entries +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.indexes.starting_with_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE A_TEST (F1 VARCHAR(5), F2 VARCHAR(5), F3 VARCHAR(5)); +CREATE INDEX IDX_A_TEST_F1 ON A_TEST(F1); +CREATE DESC INDEX IDX_A_TEST_F2 ON A_TEST(F2); +COMMIT; +INSERT INTO A_TEST (F1, F2, F3) VALUES('', '', ''); +INSERT INTO A_TEST (F1, F2, F3) VALUES(NULL, NULL, NULL); +INSERT INTO A_TEST (F1, F2, F3) VALUES('a', 'a', 'a'); +INSERT INTO A_TEST (F1, F2, F3) VALUES('b', 'b', 'b'); +COMMIT; + +SET TERM ^; + +CREATE PROCEDURE PR_A_TEST_STARTING_WITH(I_START_VALUE VARCHAR(5)) +RETURNS(O_FIELD VARCHAR(32), O_COUNT integer) +AS +BEGIN + /* First retrieve results for indexed ASC field */ + O_FIELD = 'F1 - INDEXED ASC'; + SELECT COUNT(*) FROM A_TEST + WHERE F1 STARTING WITH :I_START_VALUE + INTO :O_COUNT; + + SUSPEND; + + /* Second retrieve results for indexed DESC field */ + O_FIELD = 'F2 - INDEXED DESC'; + SELECT COUNT(*) FROM A_TEST + WHERE F2 STARTING WITH :I_START_VALUE + INTO :O_COUNT; + + SUSPEND; + + /* Thirth for unindexed field */ + O_FIELD = 'F3 - NOT INDEXED'; + SELECT COUNT(*) FROM A_TEST + WHERE F3 STARTING WITH :I_START_VALUE + INTO :O_COUNT; + + SUSPEND; +END^ + +SET TERM ;^ + +""" + +db_1 = db_factory(charset='ISO8859_1', sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN OFF; +SELECT O_FIELD, O_COUNT FROM PR_A_TEST_STARTING_WITH(''); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """O_FIELD O_COUNT +================================ ============ + +F1 - INDEXED ASC 3 +F2 - INDEXED DESC 3 +F3 - NOT INDEXED 3""" + +@pytest.mark.version('>=2.0') +def test_starting_with_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/indices/test_timestamps_01.py b/tests/functional/arno/indices/test_timestamps_01.py new file mode 100644 index 00000000..828a790d --- /dev/null +++ b/tests/functional/arno/indices/test_timestamps_01.py @@ -0,0 +1,76 @@ +#coding:utf-8 +# +# id: functional.arno.indexes.timestamps_01 +# title: TIMESTAMP in index with values below julian date +# decription: Datetime values below the julian date (firebird base date '1858-11-17') should be stored in correct order. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.indexes.timestamps_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """ + create table era ( + begindatetime timestamp not null, + enddatetime timestamp not null + ); + commit; + + insert into era (begindatetime, enddatetime) values ('1500-01-01', '1550-12-31'); + insert into era (begindatetime, enddatetime) values ('1858-11-17', '1858-11-17'); + insert into era (begindatetime, enddatetime) values ('1858-11-15 18:00', '1858-11-15 20:00'); + insert into era (begindatetime, enddatetime) values ('1858-11-16 12:00', '1858-11-16 13:00'); + insert into era (begindatetime, enddatetime) values ('1858-11-18 16:00', '1858-11-18 17:00'); + insert into era (begindatetime, enddatetime) values ('2004-04-08 02:00', '2004-04-08 02:09'); + commit; + + create unique asc index pk_begindatetime on era (begindatetime); + create unique asc index pk_enddatetime on era (enddatetime); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Queries with RANGE index scan now have in the plan only "ORDER" + -- clause (index navigation) without bitmap building. + -- See: http://tracker.firebirdsql.org/browse/CORE-1550 + -- ("the same index should never appear in both ORDER and INDEX parts of the same plan item") + set plan on; + select + e.begindatetime, + e.enddatetime + from + era e + where + e.begindatetime >= '1700-01-01' + order by + begindatetime asc; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (E ORDER PK_BEGINDATETIME) + BEGINDATETIME ENDDATETIME + ========================= ========================= + 1858-11-15 18:00:00.0000 1858-11-15 20:00:00.0000 + 1858-11-16 12:00:00.0000 1858-11-16 13:00:00.0000 + 1858-11-17 00:00:00.0000 1858-11-17 00:00:00.0000 + 1858-11-18 16:00:00.0000 1858-11-18 17:00:00.0000 + 2004-04-08 02:00:00.0000 2004-04-08 02:09:00.0000 + """ + +@pytest.mark.version('>=3.0') +def test_timestamps_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/indices/test_upper_bound_asc_01_segments_01.py b/tests/functional/arno/indices/test_upper_bound_asc_01_segments_01.py new file mode 100644 index 00000000..06669188 --- /dev/null +++ b/tests/functional/arno/indices/test_upper_bound_asc_01_segments_01.py @@ -0,0 +1,96 @@ +#coding:utf-8 +# +# id: functional.arno.indexes.upper_bound_asc_01_segments_01 +# title: ASC single index upper bound +# decription: Check if all 15 values are fetched with "lower than or equal" operator. +# tracker_id: +# min_versions: [] +# versions: 1.5 +# qmid: functional.arno.indexes.upper_bound_asc_01_segments_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_66 ( + ID INTEGER +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_66 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 2147483647; + WHILE (FillID > 0) DO + BEGIN + INSERT INTO Table_66 (ID) VALUES (:FillID); + FillID = FillID / 2; + END + INSERT INTO Table_66 (ID) VALUES (NULL); + INSERT INTO Table_66 (ID) VALUES (0); + INSERT INTO Table_66 (ID) VALUES (NULL); + FillID = -2147483648; + WHILE (FillID < 0) DO + BEGIN + INSERT INTO Table_66 (ID) VALUES (:FillID); + FillID = FillID / 2; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_66; + +COMMIT; + +CREATE ASC INDEX I_Table_66_ASC ON Table_66 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + ID +FROM + Table_66 t66 +WHERE + t66.ID <= -131072;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (T66 INDEX (I_TABLE_66_ASC)) + + ID +============ + + -2147483648 + -1073741824 + -536870912 + -268435456 + -134217728 + -67108864 + -33554432 + -16777216 + -8388608 + -4194304 + -2097152 + -1048576 + -524288 + -262144 + -131072""" + +@pytest.mark.version('>=1.5') +def test_upper_bound_asc_01_segments_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/indices/test_upper_bound_asc_01_segments_02.py b/tests/functional/arno/indices/test_upper_bound_asc_01_segments_02.py new file mode 100644 index 00000000..4677b2e3 --- /dev/null +++ b/tests/functional/arno/indices/test_upper_bound_asc_01_segments_02.py @@ -0,0 +1,117 @@ +#coding:utf-8 +# +# id: functional.arno.indexes.upper_bound_asc_01_segments_02 +# title: ASC single index upper bound +# decription: Check if all 32 values are fetched with "lower than" operator. +# tracker_id: +# min_versions: [] +# versions: 1.5 +# qmid: functional.arno.indexes.upper_bound_asc_01_segments_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_66 ( + ID INTEGER +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_66 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 2147483647; + WHILE (FillID > 0) DO + BEGIN + INSERT INTO Table_66 (ID) VALUES (:FillID); + FillID = FillID / 2; + END + INSERT INTO Table_66 (ID) VALUES (NULL); + INSERT INTO Table_66 (ID) VALUES (0); + INSERT INTO Table_66 (ID) VALUES (NULL); + FillID = -2147483648; + WHILE (FillID < 0) DO + BEGIN + INSERT INTO Table_66 (ID) VALUES (:FillID); + FillID = FillID / 2; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_66; + +COMMIT; + +CREATE ASC INDEX I_Table_66_ASC ON Table_66 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + ID +FROM + Table_66 t66 +WHERE + t66.ID < 0;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (T66 INDEX (I_TABLE_66_ASC)) + + ID +============ + + -2147483648 + -1073741824 + -536870912 + -268435456 + -134217728 + -67108864 + -33554432 + -16777216 + -8388608 + -4194304 + -2097152 + -1048576 + -524288 + -262144 + -131072 + -65536 + -32768 + -16384 + -8192 + -4096 + + ID +============ + -2048 + -1024 + -512 + -256 + -128 + -64 + -32 + -16 + -8 + -4 + -2 + -1 +""" + +@pytest.mark.version('>=1.5') +def test_upper_bound_asc_01_segments_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/indices/test_upper_bound_asc_01_segments_03.py b/tests/functional/arno/indices/test_upper_bound_asc_01_segments_03.py new file mode 100644 index 00000000..bfb67555 --- /dev/null +++ b/tests/functional/arno/indices/test_upper_bound_asc_01_segments_03.py @@ -0,0 +1,75 @@ +#coding:utf-8 +# +# id: functional.arno.indexes.upper_bound_asc_01_segments_03 +# title: ASC single index upper bound +# decription: Check if all 5 values are fetched with "lower than or equal" operator. +# tracker_id: +# min_versions: [] +# versions: 1.5 +# qmid: functional.arno.indexes.upper_bound_asc_01_segments_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_A15 ( + ID VARCHAR(15) +); + +INSERT INTO Table_A15 (ID) VALUES (NULL); +INSERT INTO Table_A15 (ID) VALUES ('A'); +INSERT INTO Table_A15 (ID) VALUES ('AA'); +INSERT INTO Table_A15 (ID) VALUES ('AAA'); +INSERT INTO Table_A15 (ID) VALUES ('AAAA'); +INSERT INTO Table_A15 (ID) VALUES ('AAAAB'); +INSERT INTO Table_A15 (ID) VALUES ('AAAB'); +INSERT INTO Table_A15 (ID) VALUES ('AAB'); +INSERT INTO Table_A15 (ID) VALUES ('AB'); +INSERT INTO Table_A15 (ID) VALUES ('B'); +INSERT INTO Table_A15 (ID) VALUES ('BA'); +INSERT INTO Table_A15 (ID) VALUES ('BAA'); +INSERT INTO Table_A15 (ID) VALUES ('BAAA'); +INSERT INTO Table_A15 (ID) VALUES ('BAAAA'); +INSERT INTO Table_A15 (ID) VALUES ('BAAAB'); + +COMMIT; + +CREATE ASC INDEX I_Table_A15_ASC ON Table_A15 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + ID +FROM + Table_A15 a15 +WHERE + a15.ID <= 'AAAAB';""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (A15 INDEX (I_TABLE_A15_ASC)) + +ID +=============== + +A +AA +AAA +AAAA +AAAAB +""" + +@pytest.mark.version('>=1.5') +def test_upper_bound_asc_01_segments_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/indices/test_upper_bound_asc_01_segments_04.py b/tests/functional/arno/indices/test_upper_bound_asc_01_segments_04.py new file mode 100644 index 00000000..34288cbf --- /dev/null +++ b/tests/functional/arno/indices/test_upper_bound_asc_01_segments_04.py @@ -0,0 +1,75 @@ +#coding:utf-8 +# +# id: functional.arno.indexes.upper_bound_asc_01_segments_04 +# title: ASC single index upper bound +# decription: Check if all 5 values are fetched with "lower than or equal" operator. +# tracker_id: +# min_versions: [] +# versions: 1.5 +# qmid: functional.arno.indexes.upper_bound_asc_01_segments_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_A15 ( + ID VARCHAR(15) +); + +INSERT INTO Table_A15 (ID) VALUES (NULL); +INSERT INTO Table_A15 (ID) VALUES ('A'); +INSERT INTO Table_A15 (ID) VALUES ('AA'); +INSERT INTO Table_A15 (ID) VALUES ('AAA'); +INSERT INTO Table_A15 (ID) VALUES ('AAAA'); +INSERT INTO Table_A15 (ID) VALUES ('AAAAB'); +INSERT INTO Table_A15 (ID) VALUES ('AAAB'); +INSERT INTO Table_A15 (ID) VALUES ('AAB'); +INSERT INTO Table_A15 (ID) VALUES ('AB'); +INSERT INTO Table_A15 (ID) VALUES ('B'); +INSERT INTO Table_A15 (ID) VALUES ('BA'); +INSERT INTO Table_A15 (ID) VALUES ('BAA'); +INSERT INTO Table_A15 (ID) VALUES ('BAAA'); +INSERT INTO Table_A15 (ID) VALUES ('BAAAA'); +INSERT INTO Table_A15 (ID) VALUES ('BAAAB'); + +COMMIT; + +CREATE ASC INDEX I_Table_A15_ASC ON Table_A15 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + ID +FROM + Table_A15 a15 +WHERE + a15.ID < 'AAAB';""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (A15 INDEX (I_TABLE_A15_ASC)) + +ID +=============== + +A +AA +AAA +AAAA +AAAAB +""" + +@pytest.mark.version('>=1.5') +def test_upper_bound_asc_01_segments_04_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/indices/test_upper_bound_asc_02_segments_01.py b/tests/functional/arno/indices/test_upper_bound_asc_02_segments_01.py new file mode 100644 index 00000000..5e6e610f --- /dev/null +++ b/tests/functional/arno/indices/test_upper_bound_asc_02_segments_01.py @@ -0,0 +1,85 @@ +#coding:utf-8 +# +# id: functional.arno.indexes.upper_bound_asc_02_segments_01 +# title: ASC 2-segment index upper bound +# decription: Check if all 5 values are fetched with "equals" operator over first segment and "lower than or equal" operator on second segment. +# 2 values are bound to the upper segments and 1 value is bound to the lower segments. +# tracker_id: +# min_versions: [] +# versions: 1.5 +# qmid: functional.arno.indexes.upper_bound_asc_02_segments_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_2_10 ( + F1 INTEGER, + F2 INTEGER +); + +COMMIT; + +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 1); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 2); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 3); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 4); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 5); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 6); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 7); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 8); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 9); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 10); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 1); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 2); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 3); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 4); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 5); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 6); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 7); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 8); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 9); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 10); + +COMMIT; + +CREATE ASC INDEX I_Table_2_10_ASC ON Table_2_10 (F1, F2); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + t.F1, + t.F2 +FROM + Table_2_10 t +WHERE + t.F1 = 2 and t.F2 <= 5;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (T INDEX (I_TABLE_2_10_ASC)) + + F1 F2 +============ ============ + + 2 1 + 2 2 + 2 3 + 2 4 + 2 5 +""" + +@pytest.mark.version('>=1.5') +def test_upper_bound_asc_02_segments_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/indices/test_upper_bound_desc_01_segments_01.py b/tests/functional/arno/indices/test_upper_bound_desc_01_segments_01.py new file mode 100644 index 00000000..5aef2e51 --- /dev/null +++ b/tests/functional/arno/indices/test_upper_bound_desc_01_segments_01.py @@ -0,0 +1,97 @@ +#coding:utf-8 +# +# id: functional.arno.indexes.upper_bound_desc_01_segments_01 +# title: DESC single index upper bound +# decription: Check if all 15 values are fetched with "greater than or equal" operator. +# tracker_id: +# min_versions: [] +# versions: 1.5 +# qmid: functional.arno.indexes.upper_bound_desc_01_segments_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_66 ( + ID INTEGER +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_66 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 2147483647; + WHILE (FillID > 0) DO + BEGIN + INSERT INTO Table_66 (ID) VALUES (:FillID); + FillID = FillID / 2; + END + INSERT INTO Table_66 (ID) VALUES (NULL); + INSERT INTO Table_66 (ID) VALUES (0); + INSERT INTO Table_66 (ID) VALUES (NULL); + FillID = -2147483648; + WHILE (FillID < 0) DO + BEGIN + INSERT INTO Table_66 (ID) VALUES (:FillID); + FillID = FillID / 2; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_66; + +COMMIT; + +CREATE DESC INDEX I_Table_66_DESC ON Table_66 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + ID +FROM + Table_66 t66 +WHERE + t66.ID >= 131071;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (T66 INDEX (I_TABLE_66_DESC)) + + ID +============ + + 2147483647 + 1073741823 + 536870911 + 268435455 + 134217727 + 67108863 + 33554431 + 16777215 + 8388607 + 4194303 + 2097151 + 1048575 + 524287 + 262143 + 131071 +""" + +@pytest.mark.version('>=1.5') +def test_upper_bound_desc_01_segments_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/indices/test_upper_bound_desc_01_segments_02.py b/tests/functional/arno/indices/test_upper_bound_desc_01_segments_02.py new file mode 100644 index 00000000..5a93e954 --- /dev/null +++ b/tests/functional/arno/indices/test_upper_bound_desc_01_segments_02.py @@ -0,0 +1,96 @@ +#coding:utf-8 +# +# id: functional.arno.indexes.upper_bound_desc_01_segments_02 +# title: DESC single index upper bound +# decription: Check if all 15 values are fetched with "greater than" operator. +# tracker_id: +# min_versions: [] +# versions: 1.5 +# qmid: functional.arno.indexes.upper_bound_desc_01_segments_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_66 ( + ID INTEGER +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_66 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 2147483647; + WHILE (FillID > 0) DO + BEGIN + INSERT INTO Table_66 (ID) VALUES (:FillID); + FillID = FillID / 2; + END + INSERT INTO Table_66 (ID) VALUES (NULL); + INSERT INTO Table_66 (ID) VALUES (0); + INSERT INTO Table_66 (ID) VALUES (NULL); + FillID = -2147483648; + WHILE (FillID < 0) DO + BEGIN + INSERT INTO Table_66 (ID) VALUES (:FillID); + FillID = FillID / 2; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_66; + +COMMIT; + +CREATE DESC INDEX I_Table_66_DESC ON Table_66 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + ID +FROM + Table_66 t66 +WHERE + t66.ID > 131071;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (T66 INDEX (I_TABLE_66_DESC)) + + ID +============ + + 2147483647 + 1073741823 + 536870911 + 268435455 + 134217727 + 67108863 + 33554431 + 16777215 + 8388607 + 4194303 + 2097151 + 1048575 + 524287 + 262143 +""" + +@pytest.mark.version('>=1.5') +def test_upper_bound_desc_01_segments_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/indices/test_upper_bound_desc_02_segments_01.py b/tests/functional/arno/indices/test_upper_bound_desc_02_segments_01.py new file mode 100644 index 00000000..51156ea1 --- /dev/null +++ b/tests/functional/arno/indices/test_upper_bound_desc_02_segments_01.py @@ -0,0 +1,85 @@ +#coding:utf-8 +# +# id: functional.arno.indexes.upper_bound_desc_02_segments_01 +# title: DESC 2-segment index upper bound +# decription: Check if all 5 values are fetched with "equals" operator over first segment and "greater than or equal" operator on second segment. +# 2 values are bound to the upper segments and 1 value is bound to the lower segment. +# tracker_id: +# min_versions: [] +# versions: 1.5 +# qmid: functional.arno.indexes.upper_bound_desc_02_segments_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_2_10 ( + F1 INTEGER, + F2 INTEGER +); + +COMMIT; + +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 1); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 2); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 3); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 4); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 5); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 6); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 7); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 8); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 9); +INSERT INTO Table_2_10 (F1, F2) VALUES (1, 10); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 1); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 2); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 3); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 4); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 5); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 6); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 7); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 8); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 9); +INSERT INTO Table_2_10 (F1, F2) VALUES (2, 10); + +COMMIT; + +CREATE DESC INDEX I_Table_2_10_DESC ON Table_2_10 (F1, F2); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + t.F1, + t.F2 +FROM + Table_2_10 t +WHERE + t.F1 = 1 and t.F2 >= 6;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (T INDEX (I_TABLE_2_10_DESC)) + + F1 F2 +============ ============ + + 1 6 + 1 7 + 1 8 + 1 9 + 1 10 +""" + +@pytest.mark.version('>=1.5') +def test_upper_bound_desc_02_segments_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/indices/test_upper_lower_bounds_01.py b/tests/functional/arno/indices/test_upper_lower_bounds_01.py new file mode 100644 index 00000000..33f58287 --- /dev/null +++ b/tests/functional/arno/indices/test_upper_lower_bounds_01.py @@ -0,0 +1,115 @@ +#coding:utf-8 +# +# id: functional.arno.indices.upper_lower_bounds_01 +# title: upper and lower bounds +# decription: equal comparison should be prefered. +# Lower and Upper bounds are bound by the same value. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.indexes.upper_lower_bounds_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_1000 ( + ID INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_1000 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 1000) DO + BEGIN + INSERT INTO Table_1000 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_1000; + +COMMIT; + +CREATE UNIQUE ASC INDEX PK_Table_1000 ON Table_1000 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# class readsInformation: +# sequential = {} +# indexed = {} +# sequentialStart = {} +# indexedStart = {} +# systemTables = False +# #-- +# def start(self): +# self.sequentialStart = db_conn.db_info(kdb.isc_info_read_seq_count) +# self.indexedStart = db_conn.db_info(kdb.isc_info_read_idx_count) +# #-- +# def addSequential(self, relationID, count): +# self.sequential[relationID] = count - self.sequentialStart.get(relationID,0) +# #-- +# def addIndexed(self, relationID, count): +# self.indexed[relationID] = count - self.indexedStart.get(relationID,0) +# #-- +# def difference(self): +# seqReads = db_conn.db_info(kdb.isc_info_read_seq_count) +# idxReads = db_conn.db_info(kdb.isc_info_read_idx_count) +# for tabid, reads in seqReads.items(): +# if (self.systemTables) or (tabid >= 128): +# self.addSequential(tabid, reads) +# for tabid, reads in idxReads.items(): +# if (self.systemTables) or (tabid >= 128): +# self.addIndexed(tabid, reads) +# #-- +# def show(self): +# print ('sequential : ',self.sequential) +# print ('indexed : ',self.indexed) +# +# cursor=db_conn.cursor() +# +# ri = readsInformation() +# ri.start() +# +# cursor.execute("SELECT Count(*) FROM Table_1000 t1000 WHERE t1000.ID > 1 and t1000.ID >= 100 and t1000.ID = 500 and t1000.ID <= 900 and t1000.ID < 1000") +# printData(cursor) +# +# # Get statistics and put out differences +# ri.difference() +# ri.show() +# +# #SET PLAN ON; +# #SET STATS ON; +# #SELECT B.B_INFO, A.A_VALUE FROM TableB B LEFT JOIN TableA A ON (1 = 0); +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """COUNT +-------------------- +1 +sequential : {} +indexed : {128: 1} +""" + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_upper_lower_bounds_01_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/arno/indices/test_upper_lower_bounds_02.py b/tests/functional/arno/indices/test_upper_lower_bounds_02.py new file mode 100644 index 00000000..deb671b6 --- /dev/null +++ b/tests/functional/arno/indices/test_upper_lower_bounds_02.py @@ -0,0 +1,114 @@ +#coding:utf-8 +# +# id: functional.arno.indices.upper_lower_bounds_02 +# title: upper and lower bounds +# decription: "Less or equal than" should be prefered above "less than" and "greater or equal than" above "greater than". +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.indexes.upper_lower_bounds_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_1000 ( + ID INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_1000 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 1000) DO + BEGIN + INSERT INTO Table_1000 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_1000; + +COMMIT; + +CREATE UNIQUE ASC INDEX PK_Table_1000 ON Table_1000 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# class readsInformation: +# sequential = {} +# indexed = {} +# sequentialStart = {} +# indexedStart = {} +# systemTables = False +# #-- +# def start(self): +# self.sequentialStart = db_conn.db_info(kdb.isc_info_read_seq_count) +# self.indexedStart = db_conn.db_info(kdb.isc_info_read_idx_count) +# #-- +# def addSequential(self, relationID, count): +# self.sequential[relationID] = count - self.sequentialStart.get(relationID,0) +# #-- +# def addIndexed(self, relationID, count): +# self.indexed[relationID] = count - self.indexedStart.get(relationID,0) +# #-- +# def difference(self): +# seqReads = db_conn.db_info(kdb.isc_info_read_seq_count) +# idxReads = db_conn.db_info(kdb.isc_info_read_idx_count) +# for tabid, reads in seqReads.items(): +# if (self.systemTables) or (tabid >= 128): +# self.addSequential(tabid, reads) +# for tabid, reads in idxReads.items(): +# if (self.systemTables) or (tabid >= 128): +# self.addIndexed(tabid, reads) +# #-- +# def show(self): +# print ('sequential : ',self.sequential) +# print ('indexed : ',self.indexed) +# +# cursor=db_conn.cursor() +# +# ri = readsInformation() +# ri.start() +# +# cursor.execute("SELECT Count(*) FROM Table_1000 t1000 WHERE t1000.ID > 1 and t1000.ID >= 400 and t1000.ID <= 600 and t1000.ID < 1000") +# printData(cursor) +# +# # Get statistics and put out differences +# ri.difference() +# ri.show() +# +# #SET PLAN ON; +# #SET STATS ON; +# #SELECT B.B_INFO, A.A_VALUE FROM TableB B LEFT JOIN TableA A ON (1 = 0); +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """COUNT +-------------------- +201 +sequential : {} +indexed : {128: 201} +""" + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_upper_lower_bounds_02_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/arno/optimizer/__init__.py b/tests/functional/arno/optimizer/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/arno/optimizer/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/arno/optimizer/test_opt_aggregate_distribution_01.py b/tests/functional/arno/optimizer/test_opt_aggregate_distribution_01.py new file mode 100644 index 00000000..102abd7e --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_aggregate_distribution_01.py @@ -0,0 +1,97 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_aggregate_distribution_01 +# title: Try to deliver HAVING CLAUSE conjunctions to the WHERE clause +# decription: Comparisons which doesn't contain (anywhere hiding in the expression) aggregate-functions should be delivered to the where clause. The underlying aggregate stream could possible use it for a index and speed it up. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_aggregate_distribution_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Colors ( + ColorID INTEGER NOT NULL, + ColorName VARCHAR(20) +); + +CREATE TABLE Flowers ( + FlowerID INTEGER NOT NULL, + FlowerName VARCHAR(30), + ColorID INTEGER +); + +COMMIT; + +/* Value 0 represents -no value- */ +INSERT INTO Colors (ColorID, ColorName) VALUES (0, 'Not defined'); +INSERT INTO Colors (ColorID, ColorName) VALUES (1, 'Red'); +INSERT INTO Colors (ColorID, ColorName) VALUES (2, 'White'); +INSERT INTO Colors (ColorID, ColorName) VALUES (3, 'Blue'); +INSERT INTO Colors (ColorID, ColorName) VALUES (4, 'Yellow'); +INSERT INTO Colors (ColorID, ColorName) VALUES (5, 'Black'); +INSERT INTO Colors (ColorID, ColorName) VALUES (6, 'Purple'); + +/* insert some data with references */ +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (1, 'Red Rose', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (2, 'White Rose', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (3, 'Blue Rose', 3); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (4, 'Yellow Rose', 4); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (5, 'Black Rose', 5); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (6, 'Red Tulip', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (7, 'White Tulip', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (8, 'Yellow Tulip', 4); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (9, 'Blue Gerbera', 3); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (10, 'Purple Gerbera', 6); + +COMMIT; + +/* Normally these indexes are created by the primary/foreign keys, + but we don't want to rely on them for this test */ +CREATE UNIQUE ASC INDEX PK_Colors ON Colors (ColorID); +CREATE UNIQUE ASC INDEX PK_Flowers ON Flowers (FlowerID); +CREATE ASC INDEX FK_Flowers_Colors ON Flowers (ColorID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + f.ColorID, + c.ColorName, + Count(*) +FROM + Flowers f + LEFT JOIN Colors c ON (c.ColorID = f.ColorID) +GROUP BY + f.ColorID, c.ColorName +HAVING + Count(*) >= 2;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN SORT (JOIN (F NATURAL, C INDEX (PK_COLORS))) + + COLORID COLORNAME COUNT +============ ==================== ===================== + 1 Red 2 + 2 White 2 + 3 Blue 2 + 4 Yellow 2 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_aggregate_distribution_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_aggregate_distribution_02.py b/tests/functional/arno/optimizer/test_opt_aggregate_distribution_02.py new file mode 100644 index 00000000..62a2cf44 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_aggregate_distribution_02.py @@ -0,0 +1,104 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_aggregate_distribution_02 +# title: Try to deliver HAVING CLAUSE conjunctions to the WHERE clause +# decription: Comparisons which doesn't contain (anywhere hiding in the expression) aggregate-functions should be delivered to the where clause. The underlying aggregate stream could possible use it for a index and speed it up. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_aggregate_distribution_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Colors ( + ColorID INTEGER NOT NULL, + ColorName VARCHAR(20) +); + +CREATE TABLE Flowers ( + FlowerID INTEGER NOT NULL, + FlowerName VARCHAR(30), + ColorID INTEGER +); + +COMMIT; + +/* Value 0 represents -no value- */ +INSERT INTO Colors (ColorID, ColorName) VALUES (0, 'Not defined'); +INSERT INTO Colors (ColorID, ColorName) VALUES (1, 'Red'); +INSERT INTO Colors (ColorID, ColorName) VALUES (2, 'White'); +INSERT INTO Colors (ColorID, ColorName) VALUES (3, 'Blue'); +INSERT INTO Colors (ColorID, ColorName) VALUES (4, 'Yellow'); +INSERT INTO Colors (ColorID, ColorName) VALUES (5, 'Black'); +INSERT INTO Colors (ColorID, ColorName) VALUES (6, 'Purple'); + +/* insert some data with references */ +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (1, 'Red Rose', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (2, 'White Rose', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (3, 'Blue Rose', 3); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (4, 'Yellow Rose', 4); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (5, 'Black Rose', 5); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (6, 'Red Tulip', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (7, 'White Tulip', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (8, 'Yellow Tulip', 4); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (9, 'Blue Gerbera', 3); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (10, 'Purple Gerbera', 6); + +COMMIT; + +/* Normally these indexes are created by the primary/foreign keys, + but we don't want to rely on them for this test */ +CREATE UNIQUE ASC INDEX PK_Colors ON Colors (ColorID); +CREATE UNIQUE ASC INDEX PK_Flowers ON Flowers (FlowerID); +CREATE ASC INDEX FK_Flowers_Colors ON Flowers (ColorID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + f.ColorID, + c.ColorName, + Count(*) +FROM + Flowers f + LEFT JOIN Colors c ON (c.ColorID = f.ColorID) +GROUP BY + f.ColorID, c.ColorName +HAVING + Count(*) >= 2 and + MIN(f.FlowerID) >= 1 and + MAX(f.FlowerID) >= 1 and + AVG(f.FlowerID) >= 1 and + Count(DISTINCT f.FlowerID) >= 2 and + MIN(DISTINCT f.FlowerID) >= 1 and + MAX(DISTINCT f.FlowerID) >= 1 and + AVG(DISTINCT f.FlowerID) >= 1;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN SORT (JOIN (F NATURAL, C INDEX (PK_COLORS))) + + COLORID COLORNAME COUNT +============ ==================== ===================== + 1 Red 2 + 2 White 2 + 3 Blue 2 + 4 Yellow 2 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_aggregate_distribution_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_aggregate_distribution_03.py b/tests/functional/arno/optimizer/test_opt_aggregate_distribution_03.py new file mode 100644 index 00000000..4ea39777 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_aggregate_distribution_03.py @@ -0,0 +1,94 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_aggregate_distribution_03 +# title: Try to deliver HAVING CLAUSE conjunctions to the WHERE clause +# decription: Comparisons which doesn't contain (anywhere hiding in the expression) aggregate-functions should be delivered to the where clause. The underlying aggregate stream could possible use it for a index and speed it up. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_aggregate_distribution_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Colors ( + ColorID INTEGER NOT NULL, + ColorName VARCHAR(20) +); + +CREATE TABLE Flowers ( + FlowerID INTEGER NOT NULL, + FlowerName VARCHAR(30), + ColorID INTEGER +); + +COMMIT; + +/* Value 0 represents -no value- */ +INSERT INTO Colors (ColorID, ColorName) VALUES (0, 'Not defined'); +INSERT INTO Colors (ColorID, ColorName) VALUES (1, 'Red'); +INSERT INTO Colors (ColorID, ColorName) VALUES (2, 'White'); +INSERT INTO Colors (ColorID, ColorName) VALUES (3, 'Blue'); +INSERT INTO Colors (ColorID, ColorName) VALUES (4, 'Yellow'); +INSERT INTO Colors (ColorID, ColorName) VALUES (5, 'Black'); +INSERT INTO Colors (ColorID, ColorName) VALUES (6, 'Purple'); + +/* insert some data with references */ +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (1, 'Red Rose', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (2, 'White Rose', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (3, 'Blue Rose', 3); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (4, 'Yellow Rose', 4); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (5, 'Black Rose', 5); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (6, 'Red Tulip', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (7, 'White Tulip', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (8, 'Yellow Tulip', 4); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (9, 'Blue Gerbera', 3); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (10, 'Purple Gerbera', 6); + +COMMIT; + +/* Normally these indexes are created by the primary/foreign keys, + but we don't want to rely on them for this test */ +CREATE UNIQUE ASC INDEX PK_Colors ON Colors (ColorID); +CREATE UNIQUE ASC INDEX PK_Flowers ON Flowers (FlowerID); +CREATE ASC INDEX FK_Flowers_Colors ON Flowers (ColorID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + f.ColorID, + c.ColorName, + Count(*) +FROM + Flowers f + LEFT JOIN Colors c ON (c.ColorID = f.ColorID) +GROUP BY + f.ColorID, c.ColorName +HAVING + f.ColorID = 1;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN SORT (JOIN (F INDEX (FK_FLOWERS_COLORS), C INDEX (PK_COLORS))) + + COLORID COLORNAME COUNT +============ ==================== ===================== + 1 Red 2 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_aggregate_distribution_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_aggregate_distribution_04.py b/tests/functional/arno/optimizer/test_opt_aggregate_distribution_04.py new file mode 100644 index 00000000..288d2c1f --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_aggregate_distribution_04.py @@ -0,0 +1,102 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_aggregate_distribution_04 +# title: Try to deliver HAVING CLAUSE conjunctions to the WHERE clause +# decription: Comparisons which doesn't contain (anywhere hiding in the expression) aggregate-functions should be delivered to the where clause. The underlying aggregate stream could possible use it for a index and speed it up. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_aggregate_distribution_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Colors ( + ColorID INTEGER NOT NULL, + ColorName VARCHAR(20) +); + +CREATE TABLE Flowers ( + FlowerID INTEGER NOT NULL, + FlowerName VARCHAR(30), + ColorID INTEGER +); + +COMMIT; + +/* Value 0 represents -no value- */ +INSERT INTO Colors (ColorID, ColorName) VALUES (0, 'Not defined'); +INSERT INTO Colors (ColorID, ColorName) VALUES (1, 'Red'); +INSERT INTO Colors (ColorID, ColorName) VALUES (2, 'White'); +INSERT INTO Colors (ColorID, ColorName) VALUES (3, 'Blue'); +INSERT INTO Colors (ColorID, ColorName) VALUES (4, 'Yellow'); +INSERT INTO Colors (ColorID, ColorName) VALUES (5, 'Black'); +INSERT INTO Colors (ColorID, ColorName) VALUES (6, 'Purple'); + +/* insert some data with references */ +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (1, 'Red Rose', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (2, 'White Rose', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (3, 'Blue Rose', 3); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (4, 'Yellow Rose', 4); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (5, 'Black Rose', 5); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (6, 'Red Tulip', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (7, 'White Tulip', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (8, 'Yellow Tulip', 4); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (9, 'Blue Gerbera', 3); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (10, 'Purple Gerbera', 6); + +COMMIT; + +/* Normally these indexes are created by the primary/foreign keys, + but we don't want to rely on them for this test */ +CREATE UNIQUE ASC INDEX PK_Colors ON Colors (ColorID); +CREATE UNIQUE ASC INDEX PK_Flowers ON Flowers (FlowerID); +CREATE ASC INDEX FK_Flowers_Colors ON Flowers (ColorID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + f.ColorID, + c.ColorName, + Count(*) +FROM + Flowers f + LEFT JOIN Colors c ON (c.ColorID = f.ColorID) +GROUP BY + f.ColorID, c.ColorName +HAVING + Count(*) >= 2 and + MIN(f.FlowerID) >= 1 and + MAX(f.FlowerID) >= 1 and + AVG(f.FlowerID) >= 1 and + f.ColorID = 2 and + Count(DISTINCT f.FlowerID) >= 2 and + MIN(DISTINCT f.FlowerID) >= 1 and + MAX(DISTINCT f.FlowerID) >= 1 and + AVG(DISTINCT f.FlowerID) >= 1;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN SORT (JOIN (F INDEX (FK_FLOWERS_COLORS), C INDEX (PK_COLORS))) + + COLORID COLORNAME COUNT +============ ==================== ===================== + 2 White 2 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_aggregate_distribution_04_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_aggregate_distribution_05.py b/tests/functional/arno/optimizer/test_opt_aggregate_distribution_05.py new file mode 100644 index 00000000..35f4e703 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_aggregate_distribution_05.py @@ -0,0 +1,113 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_aggregate_distribution_05 +# title: Try to deliver HAVING CLAUSE conjunctions to the WHERE clause +# decription: Comparisons which doesn't contain (anywhere hiding in the expression) aggregate-functions should be delivered to the where clause. The underlying aggregate stream could possible use it for a index and speed it up. VIEWs that contain aggregate queries always (as expected) add WHERE clause (on that VIEW) inside the HAVING clause from the aggregate. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_aggregate_distribution_05 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Colors ( + ColorID INTEGER NOT NULL, + ColorName VARCHAR(20) +); + +CREATE TABLE Flowers ( + FlowerID INTEGER NOT NULL, + FlowerName VARCHAR(30), + ColorID INTEGER +); + +COMMIT; + +CREATE VIEW UsedColors ( + ColorID, + ColorName, + ColorUsed +) AS +SELECT + f.ColorID, + c.ColorName, + Count(*) +FROM + Flowers f + LEFT JOIN Colors c ON (c.ColorID = f.ColorID) +GROUP BY + f.ColorID, c.ColorName; + +COMMIT; + +/* Value 0 represents -no value- */ +INSERT INTO Colors (ColorID, ColorName) VALUES (0, 'Not defined'); +INSERT INTO Colors (ColorID, ColorName) VALUES (1, 'Red'); +INSERT INTO Colors (ColorID, ColorName) VALUES (2, 'White'); +INSERT INTO Colors (ColorID, ColorName) VALUES (3, 'Blue'); +INSERT INTO Colors (ColorID, ColorName) VALUES (4, 'Yellow'); +INSERT INTO Colors (ColorID, ColorName) VALUES (5, 'Black'); +INSERT INTO Colors (ColorID, ColorName) VALUES (6, 'Purple'); + +/* insert some data with references */ +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (1, 'Red Rose', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (2, 'White Rose', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (3, 'Blue Rose', 3); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (4, 'Yellow Rose', 4); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (5, 'Black Rose', 5); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (6, 'Red Tulip', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (7, 'White Tulip', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (8, 'Yellow Tulip', 4); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (9, 'Blue Gerbera', 3); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (10, 'Purple Gerbera', 6); + +COMMIT; + +/* Normally these indexes are created by the primary/foreign keys, + but we don't want to rely on them for this test */ +CREATE UNIQUE ASC INDEX PK_Colors ON Colors (ColorID); +CREATE UNIQUE ASC INDEX PK_Flowers ON Flowers (FlowerID); +CREATE ASC INDEX FK_Flowers_Colors ON Flowers (ColorID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + v.ColorID, + v.ColorName, + v.ColorUsed +FROM + UsedColors v +WHERE + v.ColorID >= 1;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN SORT (JOIN (V F INDEX (FK_FLOWERS_COLORS), V C INDEX (PK_COLORS))) + + COLORID COLORNAME COLORUSED +============ ==================== ===================== + 1 Red 2 + 2 White 2 + 3 Blue 2 + 4 Yellow 2 + 5 Black 1 + 6 Purple 1 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_aggregate_distribution_05_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_aggregate_distribution_06.py b/tests/functional/arno/optimizer/test_opt_aggregate_distribution_06.py new file mode 100644 index 00000000..652712c5 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_aggregate_distribution_06.py @@ -0,0 +1,112 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_aggregate_distribution_06 +# title: Try to deliver HAVING CLAUSE conjunctions to the WHERE clause +# decription: Comparisons which doesn't contain (anywhere hiding in the expression) aggregate-functions should be delivered to the where clause. The underlying aggregate stream could possible use it for a index and speed it up. VIEWs that contain aggregate queries always (as expected) add WHERE clause (on that VIEW) inside the HAVING clause from the aggregate. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_aggregate_distribution_06 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Colors ( + ColorID INTEGER NOT NULL, + ColorName VARCHAR(20) +); + +CREATE TABLE Flowers ( + FlowerID INTEGER NOT NULL, + FlowerName VARCHAR(30), + ColorID INTEGER +); + +COMMIT; + +CREATE VIEW UsedColors ( + ColorID, + ColorName, + ColorUsed +) AS +SELECT + f.ColorID, + c.ColorName, + Count(*) +FROM + Flowers f + LEFT JOIN Colors c ON (c.ColorID = f.ColorID) +GROUP BY + f.ColorID, c.ColorName; + +COMMIT; + +/* Value 0 represents -no value- */ +INSERT INTO Colors (ColorID, ColorName) VALUES (0, 'Not defined'); +INSERT INTO Colors (ColorID, ColorName) VALUES (1, 'Red'); +INSERT INTO Colors (ColorID, ColorName) VALUES (2, 'White'); +INSERT INTO Colors (ColorID, ColorName) VALUES (3, 'Blue'); +INSERT INTO Colors (ColorID, ColorName) VALUES (4, 'Yellow'); +INSERT INTO Colors (ColorID, ColorName) VALUES (5, 'Black'); +INSERT INTO Colors (ColorID, ColorName) VALUES (6, 'Purple'); + +/* insert some data with references */ +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (1, 'Red Rose', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (2, 'White Rose', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (3, 'Blue Rose', 3); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (4, 'Yellow Rose', 4); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (5, 'Black Rose', 5); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (6, 'Red Tulip', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (7, 'White Tulip', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (8, 'Yellow Tulip', 4); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (9, 'Blue Gerbera', 3); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (10, 'Purple Gerbera', 6); + +COMMIT; + +/* Normally these indexes are created by the primary/foreign keys, + but we don't want to rely on them for this test */ +CREATE UNIQUE ASC INDEX PK_Colors ON Colors (ColorID); +CREATE UNIQUE ASC INDEX PK_Flowers ON Flowers (FlowerID); +CREATE ASC INDEX FK_Flowers_Colors ON Flowers (ColorID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + v.ColorID, + v.ColorName, + v.ColorUsed +FROM + UsedColors v +WHERE + v.ColorID >= 2 and + v.ColorID <= 5 and + v.ColorUsed = 2;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN SORT (JOIN (V F INDEX (FK_FLOWERS_COLORS), V C INDEX (PK_COLORS))) + + COLORID COLORNAME COLORUSED +============ ==================== ===================== + 2 White 2 + 3 Blue 2 + 4 Yellow 2 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_aggregate_distribution_06_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_aggregate_distribution_07.py b/tests/functional/arno/optimizer/test_opt_aggregate_distribution_07.py new file mode 100644 index 00000000..32b4d3c9 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_aggregate_distribution_07.py @@ -0,0 +1,99 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_aggregate_distribution_07 +# title: Try to deliver HAVING CLAUSE conjunctions to the WHERE clause +# decription: Comparisons which doesn't contain (anywhere hiding in the expression) aggregate-functions should be delivered to the where clause. The underlying aggregate stream could possible use it for a index and speed it up. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_aggregate_distribution_07 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Colors ( + ColorID INTEGER NOT NULL, + ColorName VARCHAR(20) +); + +CREATE TABLE Flowers ( + FlowerID INTEGER NOT NULL, + FlowerName VARCHAR(30), + ColorID INTEGER +); + +COMMIT; + +/* Value 0 represents -no value- */ +INSERT INTO Colors (ColorID, ColorName) VALUES (0, 'Not defined'); +INSERT INTO Colors (ColorID, ColorName) VALUES (1, 'Red'); +INSERT INTO Colors (ColorID, ColorName) VALUES (2, 'White'); +INSERT INTO Colors (ColorID, ColorName) VALUES (3, 'Blue'); +INSERT INTO Colors (ColorID, ColorName) VALUES (4, 'Yellow'); +INSERT INTO Colors (ColorID, ColorName) VALUES (5, 'Black'); +INSERT INTO Colors (ColorID, ColorName) VALUES (6, 'Purple'); + +/* insert some data with references */ +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (1, 'Red Rose', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (2, 'White Rose', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (3, 'Blue Rose', 3); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (4, 'Yellow Rose', 4); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (5, 'Black Rose', 5); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (6, 'Red Tulip', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (7, 'White Tulip', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (8, 'Yellow Tulip', 4); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (9, 'Blue Gerbera', 3); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (10, 'Purple Gerbera', 6); + +COMMIT; + +/* Normally these indexes are created by the primary/foreign keys, + but we don't want to rely on them for this test */ +CREATE UNIQUE ASC INDEX PK_Colors ON Colors (ColorID); +CREATE UNIQUE ASC INDEX PK_Flowers ON Flowers (FlowerID); +CREATE ASC INDEX FK_Flowers_Colors ON Flowers (ColorID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + f.ColorID, + c.ColorName, + Count(*) +FROM + Flowers f + LEFT JOIN Colors c ON (c.ColorID = f.ColorID) +GROUP BY + f.ColorID, c.ColorName +HAVING + f.ColorID >= 1;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN SORT (JOIN (F INDEX (FK_FLOWERS_COLORS), C INDEX (PK_COLORS))) + + COLORID COLORNAME COUNT +============ ==================== ===================== + 1 Red 2 + 2 White 2 + 3 Blue 2 + 4 Yellow 2 + 5 Black 1 + 6 Purple 1 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_aggregate_distribution_07_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_aggregate_distribution_08.py b/tests/functional/arno/optimizer/test_opt_aggregate_distribution_08.py new file mode 100644 index 00000000..36b8391e --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_aggregate_distribution_08.py @@ -0,0 +1,98 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_aggregate_distribution_08 +# title: Try to deliver HAVING CLAUSE conjunctions to the WHERE clause +# decription: Comparisons which doesn't contain (anywhere hiding in the expression) aggregate-functions should be delivered to the where clause. The underlying aggregate stream could possible use it for a index and speed it up. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_aggregate_distribution_08 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Colors ( + ColorID INTEGER NOT NULL, + ColorName VARCHAR(20) +); + +CREATE TABLE Flowers ( + FlowerID INTEGER NOT NULL, + FlowerName VARCHAR(30), + ColorID INTEGER +); + +COMMIT; + +/* Value 0 represents -no value- */ +INSERT INTO Colors (ColorID, ColorName) VALUES (0, 'Not defined'); +INSERT INTO Colors (ColorID, ColorName) VALUES (1, 'Red'); +INSERT INTO Colors (ColorID, ColorName) VALUES (2, 'White'); +INSERT INTO Colors (ColorID, ColorName) VALUES (3, 'Blue'); +INSERT INTO Colors (ColorID, ColorName) VALUES (4, 'Yellow'); +INSERT INTO Colors (ColorID, ColorName) VALUES (5, 'Black'); +INSERT INTO Colors (ColorID, ColorName) VALUES (6, 'Purple'); + +/* insert some data with references */ +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (1, 'Red Rose', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (2, 'White Rose', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (3, 'Blue Rose', 3); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (4, 'Yellow Rose', 4); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (5, 'Black Rose', 5); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (6, 'Red Tulip', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (7, 'White Tulip', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (8, 'Yellow Tulip', 4); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (9, 'Blue Gerbera', 3); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (10, 'Purple Gerbera', 6); + +COMMIT; + +/* Normally these indexes are created by the primary/foreign keys, + but we don't want to rely on them for this test */ +CREATE UNIQUE ASC INDEX PK_Colors ON Colors (ColorID); +CREATE UNIQUE ASC INDEX PK_Flowers ON Flowers (FlowerID); +CREATE ASC INDEX FK_Flowers_Colors ON Flowers (ColorID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + f.ColorID, + c.ColorName, + Count(*) +FROM + Flowers f + LEFT JOIN Colors c ON (c.ColorID = f.ColorID) +GROUP BY + f.ColorID, c.ColorName +HAVING + f.ColorID > 1;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN SORT (JOIN (F INDEX (FK_FLOWERS_COLORS), C INDEX (PK_COLORS))) + + COLORID COLORNAME COUNT +============ ==================== ===================== + 2 White 2 + 3 Blue 2 + 4 Yellow 2 + 5 Black 1 + 6 Purple 1 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_aggregate_distribution_08_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_aggregate_distribution_09.py b/tests/functional/arno/optimizer/test_opt_aggregate_distribution_09.py new file mode 100644 index 00000000..34fc3dd4 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_aggregate_distribution_09.py @@ -0,0 +1,97 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_aggregate_distribution_09 +# title: Try to deliver HAVING CLAUSE conjunctions to the WHERE clause +# decription: Comparisons which doesn't contain (anywhere hiding in the expression) aggregate-functions should be delivered to the where clause. The underlying aggregate stream could possible use it for a index and speed it up. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_aggregate_distribution_09 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Colors ( + ColorID INTEGER NOT NULL, + ColorName VARCHAR(20) +); + +CREATE TABLE Flowers ( + FlowerID INTEGER NOT NULL, + FlowerName VARCHAR(30), + ColorID INTEGER +); + +COMMIT; + +/* Value 0 represents -no value- */ +INSERT INTO Colors (ColorID, ColorName) VALUES (0, 'Not defined'); +INSERT INTO Colors (ColorID, ColorName) VALUES (1, 'Red'); +INSERT INTO Colors (ColorID, ColorName) VALUES (2, 'White'); +INSERT INTO Colors (ColorID, ColorName) VALUES (3, 'Blue'); +INSERT INTO Colors (ColorID, ColorName) VALUES (4, 'Yellow'); +INSERT INTO Colors (ColorID, ColorName) VALUES (5, 'Black'); +INSERT INTO Colors (ColorID, ColorName) VALUES (6, 'Purple'); + +/* insert some data with references */ +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (1, 'Red Rose', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (2, 'White Rose', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (3, 'Blue Rose', 3); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (4, 'Yellow Rose', 4); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (5, 'Black Rose', 5); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (6, 'Red Tulip', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (7, 'White Tulip', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (8, 'Yellow Tulip', 4); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (9, 'Blue Gerbera', 3); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (10, 'Purple Gerbera', 6); + +COMMIT; + +/* Normally these indexes are created by the primary/foreign keys, + but we don't want to rely on them for this test */ +CREATE UNIQUE ASC INDEX PK_Colors ON Colors (ColorID); +CREATE UNIQUE ASC INDEX PK_Flowers ON Flowers (FlowerID); +CREATE ASC INDEX FK_Flowers_Colors ON Flowers (ColorID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + f.ColorID, + c.ColorName, + Count(*) +FROM + Flowers f + LEFT JOIN Colors c ON (c.ColorID = f.ColorID) +GROUP BY + f.ColorID, c.ColorName +HAVING + f.ColorID <= 4;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN SORT (JOIN (F INDEX (FK_FLOWERS_COLORS), C INDEX (PK_COLORS))) + + COLORID COLORNAME COUNT +============ ==================== ===================== + 1 Red 2 + 2 White 2 + 3 Blue 2 + 4 Yellow 2 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_aggregate_distribution_09_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_aggregate_distribution_10.py b/tests/functional/arno/optimizer/test_opt_aggregate_distribution_10.py new file mode 100644 index 00000000..6c38d4f3 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_aggregate_distribution_10.py @@ -0,0 +1,97 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_aggregate_distribution_10 +# title: Try to deliver HAVING CLAUSE conjunctions to the WHERE clause +# decription: Comparisons which doesn't contain (anywhere hiding in the expression) aggregate-functions should be delivered to the where clause. The underlying aggregate stream could possible use it for a index and speed it up. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_aggregate_distribution_10 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Colors ( + ColorID INTEGER NOT NULL, + ColorName VARCHAR(20) +); + +CREATE TABLE Flowers ( + FlowerID INTEGER NOT NULL, + FlowerName VARCHAR(30), + ColorID INTEGER +); + +COMMIT; + +/* Value 0 represents -no value- */ +INSERT INTO Colors (ColorID, ColorName) VALUES (0, 'Not defined'); +INSERT INTO Colors (ColorID, ColorName) VALUES (1, 'Red'); +INSERT INTO Colors (ColorID, ColorName) VALUES (2, 'White'); +INSERT INTO Colors (ColorID, ColorName) VALUES (3, 'Blue'); +INSERT INTO Colors (ColorID, ColorName) VALUES (4, 'Yellow'); +INSERT INTO Colors (ColorID, ColorName) VALUES (5, 'Black'); +INSERT INTO Colors (ColorID, ColorName) VALUES (6, 'Purple'); + +/* insert some data with references */ +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (1, 'Red Rose', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (2, 'White Rose', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (3, 'Blue Rose', 3); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (4, 'Yellow Rose', 4); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (5, 'Black Rose', 5); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (6, 'Red Tulip', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (7, 'White Tulip', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (8, 'Yellow Tulip', 4); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (9, 'Blue Gerbera', 3); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (10, 'Purple Gerbera', 6); + +COMMIT; + +/* Normally these indexes are created by the primary/foreign keys, + but we don't want to rely on them for this test */ +CREATE UNIQUE ASC INDEX PK_Colors ON Colors (ColorID); +CREATE UNIQUE ASC INDEX PK_Flowers ON Flowers (FlowerID); +CREATE ASC INDEX FK_Flowers_Colors ON Flowers (ColorID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + f.ColorID, + c.ColorName, + Count(*) +FROM + Flowers f + LEFT JOIN Colors c ON (c.ColorID = f.ColorID) +GROUP BY + f.ColorID, c.ColorName +HAVING + f.ColorID < 5;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN SORT (JOIN (F INDEX (FK_FLOWERS_COLORS), C INDEX (PK_COLORS))) + + COLORID COLORNAME COUNT +============ ==================== ===================== + 1 Red 2 + 2 White 2 + 3 Blue 2 + 4 Yellow 2 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_aggregate_distribution_10_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_aggregate_distribution_11.py b/tests/functional/arno/optimizer/test_opt_aggregate_distribution_11.py new file mode 100644 index 00000000..6c956004 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_aggregate_distribution_11.py @@ -0,0 +1,96 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_aggregate_distribution_11 +# title: Try to deliver HAVING CLAUSE conjunctions to the WHERE clause +# decription: Comparisons which doesn't contain (anywhere hiding in the expression) aggregate-functions should be delivered to the where clause. The underlying aggregate stream could possible use it for a index and speed it up. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_aggregate_distribution_11 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Colors ( + ColorID INTEGER NOT NULL, + ColorName VARCHAR(20) +); + +CREATE TABLE Flowers ( + FlowerID INTEGER NOT NULL, + FlowerName VARCHAR(30), + ColorID INTEGER +); + +COMMIT; + +/* Value 0 represents -no value- */ +INSERT INTO Colors (ColorID, ColorName) VALUES (0, 'Not defined'); +INSERT INTO Colors (ColorID, ColorName) VALUES (1, 'Red'); +INSERT INTO Colors (ColorID, ColorName) VALUES (2, 'White'); +INSERT INTO Colors (ColorID, ColorName) VALUES (3, 'Blue'); +INSERT INTO Colors (ColorID, ColorName) VALUES (4, 'Yellow'); +INSERT INTO Colors (ColorID, ColorName) VALUES (5, 'Black'); +INSERT INTO Colors (ColorID, ColorName) VALUES (6, 'Purple'); + +/* insert some data with references */ +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (1, 'Red Rose', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (2, 'White Rose', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (3, 'Blue Rose', 3); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (4, 'Yellow Rose', 4); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (5, 'Black Rose', 5); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (6, 'Red Tulip', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (7, 'White Tulip', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (8, 'Yellow Tulip', 4); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (9, 'Blue Gerbera', 3); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (10, 'Purple Gerbera', 6); + +COMMIT; + +/* Normally these indexes are created by the primary/foreign keys, + but we don't want to rely on them for this test */ +CREATE UNIQUE ASC INDEX PK_Colors ON Colors (ColorID); +CREATE UNIQUE ASC INDEX PK_Flowers ON Flowers (FlowerID); +CREATE ASC INDEX FK_Flowers_Colors ON Flowers (ColorID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + f.ColorID, + c.ColorName, + Count(*) +FROM + Flowers f + LEFT JOIN Colors c ON (c.ColorID = f.ColorID) +GROUP BY + f.ColorID, c.ColorName +HAVING + f.ColorID BETWEEN 2 and 4;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN SORT (JOIN (F INDEX (FK_FLOWERS_COLORS), C INDEX (PK_COLORS))) + + COLORID COLORNAME COUNT +============ ==================== ===================== + 2 White 2 + 3 Blue 2 + 4 Yellow 2 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_aggregate_distribution_11_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_aggregate_distribution_12.py b/tests/functional/arno/optimizer/test_opt_aggregate_distribution_12.py new file mode 100644 index 00000000..51e189f2 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_aggregate_distribution_12.py @@ -0,0 +1,89 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_aggregate_distribution_12 +# title: Try to deliver HAVING CLAUSE conjunctions to the WHERE clause +# decription: Comparisons which doesn't contain (anywhere hiding in the expression) aggregate-functions should be delivered to the where clause. The underlying aggregate stream could possible use it for a index and speed it up. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_aggregate_distribution_12 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Colors ( + ColorID INTEGER NOT NULL, + ColorName VARCHAR(20) +); + +CREATE TABLE Flowers ( + FlowerID INTEGER NOT NULL, + FlowerName VARCHAR(30), + ColorID INTEGER +); + +COMMIT; + +/* Value 0 represents -no value- */ +INSERT INTO Colors (ColorID, ColorName) VALUES (0, 'Not defined'); +INSERT INTO Colors (ColorID, ColorName) VALUES (1, 'Red'); +INSERT INTO Colors (ColorID, ColorName) VALUES (2, 'White'); +INSERT INTO Colors (ColorID, ColorName) VALUES (3, 'Blue'); +INSERT INTO Colors (ColorID, ColorName) VALUES (4, 'Yellow'); +INSERT INTO Colors (ColorID, ColorName) VALUES (5, 'Black'); +INSERT INTO Colors (ColorID, ColorName) VALUES (6, 'Purple'); + +/* insert some data with references */ +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (1, 'Red Rose', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (2, 'White Rose', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (3, 'Blue Rose', 3); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (4, 'Yellow Rose', 4); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (5, 'Black Rose', 5); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (6, 'Red Tulip', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (7, 'White Tulip', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (8, 'Yellow Tulip', 4); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (9, 'Blue Gerbera', 3); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (10, 'Purple Gerbera', 6); + +COMMIT; + +/* Normally these indexes are created by the primary/foreign keys, + but we don't want to rely on them for this test */ +CREATE UNIQUE ASC INDEX PK_Colors ON Colors (ColorID); +CREATE UNIQUE ASC INDEX PK_Flowers ON Flowers (FlowerID); +CREATE ASC INDEX FK_Flowers_Colors ON Flowers (ColorID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + f.ColorID, + c.ColorName, + Count(*) +FROM + Flowers f + LEFT JOIN Colors c ON (c.ColorID = f.ColorID) +GROUP BY + f.ColorID, c.ColorName +HAVING + f.ColorID IS NULL;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN SORT (JOIN (F INDEX (FK_FLOWERS_COLORS), C INDEX (PK_COLORS))) +""" + +@pytest.mark.version('>=2.0') +def test_opt_aggregate_distribution_12_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_aggregate_distribution_13.py b/tests/functional/arno/optimizer/test_opt_aggregate_distribution_13.py new file mode 100644 index 00000000..3cd55147 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_aggregate_distribution_13.py @@ -0,0 +1,96 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_aggregate_distribution_13 +# title: Try to deliver HAVING CLAUSE conjunctions to the WHERE clause +# decription: Comparisons which doesn't contain (anywhere hiding in the expression) aggregate-functions should be delivered to the where clause. The underlying aggregate stream could possible use it for a index and speed it up. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_aggregate_distribution_13 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Colors ( + ColorID INTEGER NOT NULL, + ColorName VARCHAR(20) +); + +CREATE TABLE Flowers ( + FlowerID INTEGER NOT NULL, + FlowerName VARCHAR(30), + ColorID INTEGER +); + +COMMIT; + +/* Value 0 represents -no value- */ +INSERT INTO Colors (ColorID, ColorName) VALUES (0, 'Not defined'); +INSERT INTO Colors (ColorID, ColorName) VALUES (1, 'Red'); +INSERT INTO Colors (ColorID, ColorName) VALUES (2, 'White'); +INSERT INTO Colors (ColorID, ColorName) VALUES (3, 'Blue'); +INSERT INTO Colors (ColorID, ColorName) VALUES (4, 'Yellow'); +INSERT INTO Colors (ColorID, ColorName) VALUES (5, 'Black'); +INSERT INTO Colors (ColorID, ColorName) VALUES (6, 'Purple'); + +/* insert some data with references */ +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (1, 'Red Rose', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (2, 'White Rose', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (3, 'Blue Rose', 3); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (4, 'Yellow Rose', 4); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (5, 'Black Rose', 5); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (6, 'Red Tulip', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (7, 'White Tulip', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (8, 'Yellow Tulip', 4); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (9, 'Blue Gerbera', 3); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (10, 'Purple Gerbera', 6); + +COMMIT; + +/* Normally these indexes are created by the primary/foreign keys, + but we don't want to rely on them for this test */ +CREATE UNIQUE ASC INDEX PK_Colors ON Colors (ColorID); +CREATE UNIQUE ASC INDEX PK_Flowers ON Flowers (FlowerID); +CREATE ASC INDEX FK_Flowers_Colors ON Flowers (ColorID); +CREATE ASC INDEX I_Colors_ColorName ON Colors (ColorName); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + f.ColorID, + c.ColorName, + Count(*) +FROM + Colors c + LEFT JOIN Flowers f ON (f.ColorID = c.ColorID) +GROUP BY + f.ColorID, c.ColorName +HAVING + c.ColorName STARTING WITH 'B';""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN SORT (JOIN (C INDEX (I_COLORS_COLORNAME), F INDEX (FK_FLOWERS_COLORS))) + + COLORID COLORNAME COUNT +============ ==================== ===================== + 3 Blue 2 + 5 Black 1 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_aggregate_distribution_13_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_aggregate_distribution_14.py b/tests/functional/arno/optimizer/test_opt_aggregate_distribution_14.py new file mode 100644 index 00000000..8ede3c8b --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_aggregate_distribution_14.py @@ -0,0 +1,96 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_aggregate_distribution_14 +# title: Try to deliver HAVING CLAUSE conjunctions to the WHERE clause +# decription: Comparisons which doesn't contain (anywhere hiding in the expression) aggregate-functions should be delivered to the where clause. The underlying aggregate stream could possible use it for a index and speed it up. +# tracker_id: CORE-2417 +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_aggregate_distribution_14 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Colors ( + ColorID INTEGER NOT NULL, + ColorName VARCHAR(20) +); + +CREATE TABLE Flowers ( + FlowerID INTEGER NOT NULL, + FlowerName VARCHAR(30), + ColorID INTEGER +); + +COMMIT; + +/* Value 0 represents -no value- */ +INSERT INTO Colors (ColorID, ColorName) VALUES (0, 'Not defined'); +INSERT INTO Colors (ColorID, ColorName) VALUES (1, 'Red'); +INSERT INTO Colors (ColorID, ColorName) VALUES (2, 'White'); +INSERT INTO Colors (ColorID, ColorName) VALUES (3, 'Blue'); +INSERT INTO Colors (ColorID, ColorName) VALUES (4, 'Yellow'); +INSERT INTO Colors (ColorID, ColorName) VALUES (5, 'Black'); +INSERT INTO Colors (ColorID, ColorName) VALUES (6, 'Purple'); + +/* insert some data with references */ +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (1, 'Red Rose', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (2, 'White Rose', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (3, 'Blue Rose', 3); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (4, 'Yellow Rose', 4); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (5, 'Black Rose', 5); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (6, 'Red Tulip', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (7, 'White Tulip', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (8, 'Yellow Tulip', 4); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (9, 'Blue Gerbera', 3); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (10, 'Purple Gerbera', 6); + +COMMIT; + +/* Normally these indexes are created by the primary/foreign keys, + but we don't want to rely on them for this test */ +CREATE UNIQUE ASC INDEX PK_Colors ON Colors (ColorID); +CREATE UNIQUE ASC INDEX PK_Flowers ON Flowers (FlowerID); +CREATE ASC INDEX FK_Flowers_Colors ON Flowers (ColorID); +CREATE ASC INDEX I_Colors_ColorName ON Colors (ColorName); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + f.ColorID, + c.ColorName, + Count(*) +FROM + Colors c + LEFT JOIN Flowers f ON (f.ColorID = c.ColorID) +GROUP BY + f.ColorID, c.ColorName +HAVING + c.ColorName LIKE 'B%';""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN SORT (JOIN (C INDEX (I_COLORS_COLORNAME), F INDEX (FK_FLOWERS_COLORS))) + + COLORID COLORNAME COUNT +============ ==================== ===================== + 3 Blue 2 + 5 Black 1 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_aggregate_distribution_14_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_avoid_index_usage.py b/tests/functional/arno/optimizer/test_opt_avoid_index_usage.py new file mode 100644 index 00000000..4f06474a --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_avoid_index_usage.py @@ -0,0 +1,58 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_avoid_index_usage +# title: AVOID index usage in WHERE = +# decription: +# Samples here are from CORE-3051. +# Confirmed usage 'PLAN INDEX ...' in FB 2.0.0.12724 +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: functional.arno.optimizer.opt_avoid_index_usage + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + recreate table t(x varchar(10), y varchar(10)); + create index t_x_asc on t(x); + create descending index t_y_desc on t(y); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set planonly; + --set echo on; + select * from t where x = 0; + select * from t where y = 0; + select * from t where x > 0; + select * from t where y < 0; + select * from t where x between 0 and 1; + select * from t where y between 0 and 1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (T NATURAL) + PLAN (T NATURAL) + PLAN (T NATURAL) + PLAN (T NATURAL) + PLAN (T NATURAL) + PLAN (T NATURAL) + """ + +@pytest.mark.version('>=2.5.0') +def test_opt_avoid_index_usage_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_full_join_01.py b/tests/functional/arno/optimizer/test_opt_full_join_01.py new file mode 100644 index 00000000..752fa465 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_full_join_01.py @@ -0,0 +1,162 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_full_join_01 +# title: FULL OUTER JOIN, list all values +# decription: +# TableX FULL OUTER JOIN TableY with relation in the ON clause. +# Three tables are used, where 1 table (RC) holds references to the two other tables (R and C). +# The two tables R and C contain both 1 value that isn't inside RC. +# ===== +# Refactored 01-mar-2016. Checked on: WI-V2.5.6.26970, WI-V3.0.0.32366 +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: functional.arno.optimizer.opt_full_join_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import time +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# engine = str(db_conn.engine_version) +# db_conn.close() +# +# sql_cmd=''' +# create table relations ( +# relationid integer, +# relationname varchar(35) +# ); +# +# create table categories ( +# categoryid integer, +# description varchar(20) +# ); +# +# create table relationcategories ( +# relationid integer, +# categoryid integer +# ); +# commit; +# +# insert into relations (relationid, relationname) values (1, 'diving snorkel shop'); +# insert into relations (relationid, relationname) values (2, 'bakery garbage'); +# insert into relations (relationid, relationname) values (3, 'racing turtle'); +# insert into relations (relationid, relationname) values (4, 'folding air-hook shop'); +# +# insert into categories (categoryid, description) values (1, 'relation'); +# insert into categories (categoryid, description) values (2, 'debtor'); +# insert into categories (categoryid, description) values (3, 'creditor'); +# insert into categories (categoryid, description) values (4, 'newsletter'); +# +# insert into relationcategories (relationid, categoryid) values (1, 1); +# insert into relationcategories (relationid, categoryid) values (2, 1); +# insert into relationcategories (relationid, categoryid) values (3, 1); +# insert into relationcategories (relationid, categoryid) values (1, 2); +# insert into relationcategories (relationid, categoryid) values (2, 2); +# insert into relationcategories (relationid, categoryid) values (1, 3); +# commit; +# +# -- Normally these indexes are created by the primary/foreign keys, +# -- but we don't want to rely on them for this test +# create unique asc index pk_relations on relations (relationid); +# create unique asc index pk_categories on categories (categoryid); +# create unique asc index pk_relationcategories on relationcategories (relationid, categoryid); +# create asc index fk_rc_relations on relationcategories (relationid); +# create asc index fk_rc_categories on relationcategories (categoryid); +# commit; +# +# set plan on; +# -- set list on; +# -- FULL JOIN should return ... +# select +# r.relationname, +# rc.relationid, +# rc.categoryid, +# c.description +# from relations r +# full join relationcategories rc on (rc.relationid = r.relationid) +# full join categories c on (c.categoryid = rc.categoryid) +# order by +# rc.relationid desc +# ,r.relationname +# ,rc.categoryid +# ,c.description +# ; +# ''' +# f_sql=open( os.path.join(context['temp_directory'],'tmp_opt_full_join_01.tmp'), 'w') +# f_sql.write(sql_cmd) +# f_sql.close() +# +# f_log = open( os.path.join(context['temp_directory'],'tmp_opt_full_join_01.log'), 'w') +# +# subprocess.call( [ context['isql_path'], dsn, "-i", f_sql.name], +# stdout=f_log, +# stderr=subprocess.STDOUT +# ) +# f_log.close() +# time.sleep(1) +# +# plan_25 = 'PLAN SORT (JOIN (C NATURAL, JOIN (RC NATURAL, R NATURAL)))' +# plan_30 = 'PLAN SORT (JOIN (JOIN (C NATURAL, JOIN (JOIN (RC NATURAL, R INDEX (PK_RELATIONS)), JOIN (R NATURAL, RC INDEX (FK_RC_RELATIONS)))), JOIN (JOIN (JOIN (RC NATURAL, R INDEX (PK_RELATIONS)), JOIN (R NATURAL, RC INDEX (FK_RC_RELATIONS))), C NATURAL)))' +# with open(f_log.name) as f: +# for line in f: +# if line.upper().startswith('PLAN '): +# if engine.startswith('2.'): +# plan_expected=plan_25 +# else: +# plan_expected=plan_30 +# +# # Remove trailing whitespaces and newline character: +# if line.upper().rstrip() == plan_expected: +# print( 'Actual plan plan coincides with the expected.' ) +# else: +# print( 'Actual plan: '+line+' - differs from expected: '+plan_expected) +# else: +# print(line ) +# +# os.remove(f_log.name) +# os.remove(f_sql.name) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Actual plan plan coincides with the expected. + RELATIONNAME RELATIONID CATEGORYID DESCRIPTION + =================================== ============ ============ ============= + racing turtle 3 1 relation + bakery garbage 2 1 relation + bakery garbage 2 2 debtor + diving snorkel shop 1 1 relation + diving snorkel shop 1 2 debtor + diving snorkel shop 1 3 creditor + newsletter + folding air-hook shop + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_opt_full_join_01_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/arno/optimizer/test_opt_full_join_02.py b/tests/functional/arno/optimizer/test_opt_full_join_02.py new file mode 100644 index 00000000..3f041eab --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_full_join_02.py @@ -0,0 +1,167 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_full_join_02 +# title: FULL OUTER JOIN, list all values, but filtered in WHERE clause +# decription: +# TableX FULL OUTER JOIN TableY with relation in the ON clause. +# Three tables are used, where 1 table (RC) holds references to the two other tables (R and C). +# The two tables R and C contain both 1 value that isn't inside RC. +# ===== +# Refactored 01-mar-2016. Checked on: WI-V2.5.6.26970, WI-V3.0.0.32366 +# +# 27.12.2020: added 'rc.categoryid' to 'order by' list in order to have always stable sort result. +# Mismatch with expected result due to different position of records with the same 'rc.relationid' +# occured on 4.0.0.2298. CHecked on 4.0.0.2303. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: functional.arno.optimizer.opt_full_join_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import time +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# engine = str(db_conn.engine_version) +# db_conn.close() +# +# sql_cmd=''' +# create table relations ( +# relationid integer, +# relationname varchar(35) +# ); +# +# create table categories ( +# categoryid integer, +# description varchar(20) +# ); +# +# create table relationcategories ( +# relationid integer, +# categoryid integer +# ); +# commit; +# +# insert into relations (relationid, relationname) values (1, 'diving snorkel shop'); +# insert into relations (relationid, relationname) values (2, 'bakery garbage'); +# insert into relations (relationid, relationname) values (3, 'racing turtle'); +# insert into relations (relationid, relationname) values (4, 'folding air-hook shop'); +# +# insert into categories (categoryid, description) values (1, 'relation'); +# insert into categories (categoryid, description) values (2, 'debtor'); +# insert into categories (categoryid, description) values (3, 'creditor'); +# insert into categories (categoryid, description) values (4, 'newsletter'); +# +# insert into relationcategories (relationid, categoryid) values (1, 1); +# insert into relationcategories (relationid, categoryid) values (2, 1); +# insert into relationcategories (relationid, categoryid) values (3, 1); +# insert into relationcategories (relationid, categoryid) values (1, 2); +# insert into relationcategories (relationid, categoryid) values (2, 2); +# insert into relationcategories (relationid, categoryid) values (1, 3); +# commit; +# +# -- normally these indexes are created by the primary/foreign keys, +# -- but we don't want to rely on them for this test +# create unique asc index pk_relations on relations (relationid); +# create unique asc index pk_categories on categories (categoryid); +# create unique asc index pk_relationcategories on relationcategories (relationid, categoryid); +# create asc index fk_rc_relations on relationcategories (relationid); +# create asc index fk_rc_categories on relationcategories (categoryid); +# commit; +# +# set plan on; +# --set list on; +# +# --full join should return ... +# select +# r.relationname, +# rc.relationid, +# rc.categoryid, +# c.description +# from +# relations r +# full join relationcategories rc on (rc.relationid = r.relationid) +# full join categories c on (c.categoryid = rc.categoryid) +# where +# r.relationid >= 2 +# order by +# rc.relationid desc +# ,rc.categoryid +# ; +# ''' +# +# f_sql=open( os.path.join(context['temp_directory'],'tmp_opt_full_join_02.tmp'), 'w') +# f_sql.write(sql_cmd) +# f_sql.close() +# +# f_log = open( os.path.join(context['temp_directory'],'tmp_opt_full_join_02.log'), 'w') +# +# subprocess.call( [context['isql_path'], dsn, "-i", f_sql.name], +# stdout=f_log, +# stderr=subprocess.STDOUT +# ) +# f_log.close() +# time.sleep(1) +# +# plan_25 = 'PLAN SORT (JOIN (C NATURAL, JOIN (RC NATURAL, R INDEX (PK_RELATIONS))))' +# plan_30 = 'PLAN SORT (JOIN (JOIN (C NATURAL, JOIN (JOIN (RC NATURAL, R INDEX (PK_RELATIONS)), JOIN (R INDEX (PK_RELATIONS), RC INDEX (FK_RC_RELATIONS)))), JOIN (JOIN (JOIN (RC NATURAL, R INDEX (PK_RELATIONS)), JOIN (R INDEX (PK_RELATIONS), RC INDEX (FK_RC_RELATIONS))), C NATURAL)))' +# with open(f_log.name) as f: +# for line in f: +# if line.upper().startswith('PLAN '): +# if engine.startswith('2.'): +# plan_expected=plan_25 +# else: +# plan_expected=plan_30 +# +# # Remove trailing whitespaces and newline character: +# if line.upper().rstrip() == plan_expected: +# print( 'Actual plan plan coincides with the expected.' ) +# else: +# print( 'Actual plan: '+line+' - differs from expected: '+plan_expected) +# else: +# print(line ) +# +# # Cleanup +# ######### +# os.remove(f_log.name) +# os.remove(f_sql.name) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Actual plan plan coincides with the expected. + + RELATIONNAME RELATIONID CATEGORYID DESCRIPTION + =================================== ============ ============ ============ + racing turtle 3 1 relation + bakery garbage 2 1 relation + bakery garbage 2 2 debtor + folding air-hook shop + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_opt_full_join_02_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/arno/optimizer/test_opt_full_join_03.py b/tests/functional/arno/optimizer/test_opt_full_join_03.py new file mode 100644 index 00000000..b75ee295 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_full_join_03.py @@ -0,0 +1,173 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_full_join_03 +# title: FULL OUTER JOIN, list all values, but filtered in WHERE clause +# decription: +# TableX FULL OUTER JOIN TableY with relation in the ON clause. +# Three tables are used, where 1 table (RC) holds references to the two other tables (R and C). +# The two tables R and C contain both 1 value that isn't inside RC. +# ===== +# Refactored 01-mar-2016. Checked on: WI-V2.5.6.26970, WI-V3.0.0.32366 +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: functional.arno.optimizer.opt_full_join_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import time +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# engine = str(db_conn.engine_version) +# db_conn.close() +# +# sql_cmd=''' +# create table relations ( +# relationid integer, +# relationname varchar(35) +# ); +# +# create table categories ( +# categoryid integer, +# description varchar(20) +# ); +# +# create table relationcategories ( +# relationid integer, +# categoryid integer +# ); +# commit; +# +# insert into relations (relationid, relationname) values (1, 'diving snorkel shop'); +# insert into relations (relationid, relationname) values (2, 'bakery garbage'); +# insert into relations (relationid, relationname) values (3, 'racing turtle'); +# insert into relations (relationid, relationname) values (4, 'folding air-hook shop'); +# +# insert into categories (categoryid, description) values (1, 'relation'); +# insert into categories (categoryid, description) values (2, 'debtor'); +# insert into categories (categoryid, description) values (3, 'creditor'); +# insert into categories (categoryid, description) values (4, 'newsletter'); +# +# insert into relationcategories (relationid, categoryid) values (1, 1); +# insert into relationcategories (relationid, categoryid) values (2, 1); +# insert into relationcategories (relationid, categoryid) values (3, 1); +# insert into relationcategories (relationid, categoryid) values (1, 2); +# insert into relationcategories (relationid, categoryid) values (2, 2); +# insert into relationcategories (relationid, categoryid) values (1, 3); +# +# commit; +# +# -- Normally these indexes are created by the primary/foreign keys, +# -- but we don't want to rely on them for this test +# create unique asc index pk_relations on relations (relationid); +# create unique asc index pk_categories on categories (categoryid); +# create unique asc index pk_relationcategories on relationcategories (relationid, categoryid); +# create asc index fk_rc_relations on relationcategories (relationid); +# create asc index fk_rc_categories on relationcategories (categoryid); +# +# commit; +# +# +# set plan on; +# set list on; +# -- full join should return ... +# select +# r.relationname, +# rc.relationid, +# rc.categoryid, +# c.description +# from +# relations r +# full join relationcategories rc on (rc.relationid = r.relationid) +# full join categories c on (c.categoryid = rc.categoryid) +# where +# c.categoryid >= 2 +# order by +# rc.categoryid desc; +# ''' +# +# f_sql=open( os.path.join(context['temp_directory'],'tmp_opt_full_join_03.tmp'), 'w') +# f_sql.write(sql_cmd) +# f_sql.close() +# +# f_log = open( os.path.join(context['temp_directory'],'tmp_opt_full_join_03.log'), 'w') +# +# subprocess.call( [context['isql_path'], dsn, "-i", f_sql.name], +# stdout=f_log, +# stderr=subprocess.STDOUT +# ) +# f_log.close() +# time.sleep(1) +# +# plan_25 = 'PLAN SORT (JOIN (C INDEX (PK_CATEGORIES), JOIN (RC NATURAL, R NATURAL)))' +# plan_30 = 'PLAN SORT (JOIN (JOIN (C INDEX (PK_CATEGORIES), JOIN (JOIN (RC NATURAL, R INDEX (PK_RELATIONS)), JOIN (R NATURAL, RC INDEX (FK_RC_RELATIONS)))), JOIN (JOIN (JOIN (RC NATURAL, R INDEX (PK_RELATIONS)), JOIN (R NATURAL, RC INDEX (FK_RC_RELATIONS))), C INDEX (PK_CATEGORIES))))' +# with open(f_log.name) as f: +# for line in f: +# if line.upper().startswith('PLAN '): +# if engine.startswith('2.'): +# plan_expected=plan_25 +# else: +# plan_expected=plan_30 +# +# # Remove trailing whitespaces and newline character: +# if line.upper().rstrip() == plan_expected: +# print( 'Actual plan plan coincides with the expected.' ) +# else: +# print( 'Actual plan: '+line+' - differs from expected: '+plan_expected) +# else: +# print(line ) +# +# # Cleanup +# ######### +# os.remove(f_log.name) +# os.remove(f_sql.name) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Actual plan plan coincides with the expected. + + RELATIONNAME diving snorkel shop + RELATIONID 1 + CATEGORYID 3 + DESCRIPTION creditor + RELATIONNAME diving snorkel shop + RELATIONID 1 + CATEGORYID 2 + DESCRIPTION debtor + RELATIONNAME bakery garbage + RELATIONID 2 + CATEGORYID 2 + DESCRIPTION debtor + RELATIONNAME + RELATIONID + CATEGORYID + DESCRIPTION newsletter + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_opt_full_join_03_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/arno/optimizer/test_opt_full_join_04.py b/tests/functional/arno/optimizer/test_opt_full_join_04.py new file mode 100644 index 00000000..9d5dcbc0 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_full_join_04.py @@ -0,0 +1,188 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_full_join_04 +# title: FULL OUTER JOIN, list all values, but filtered in WHERE clause +# decription: +# TableX FULL OUTER JOIN TableY with relation in the ON clause. +# Three tables are used, where 1 table (RC) holds references to the two other tables (R and C). +# The two tables R and C contain both 1 value that isn't inside RC. +# ===== +# NB: 'UNION ALL' is used here, so PLAN for 2.5 will be of TWO separate rows. +# ===== +# Refactored 01-mar-2016. Checked on: WI-V2.5.6.26970, WI-V3.0.0.32366 +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: functional.arno.optimizer.opt_full_join_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import time +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# engine = str(db_conn.engine_version) +# db_conn.close() +# +# sql_cmd=''' +# create table relations ( +# relationid integer, +# relationname varchar(35) +# ); +# +# create table categories ( +# categoryid integer, +# description varchar(20) +# ); +# +# create table relationcategories ( +# relationid integer, +# categoryid integer +# ); +# +# commit; +# +# insert into relations (relationid, relationname) values (1, 'diving snorkel shop'); +# insert into relations (relationid, relationname) values (2, 'bakery garbage'); +# insert into relations (relationid, relationname) values (3, 'racing turtle'); +# insert into relations (relationid, relationname) values (4, 'folding air-hook shop'); +# +# insert into categories (categoryid, description) values (1, 'relation'); +# insert into categories (categoryid, description) values (2, 'debtor'); +# insert into categories (categoryid, description) values (3, 'creditor'); +# insert into categories (categoryid, description) values (4, 'newsletter'); +# +# insert into relationcategories (relationid, categoryid) values (1, 1); +# insert into relationcategories (relationid, categoryid) values (2, 1); +# insert into relationcategories (relationid, categoryid) values (3, 1); +# insert into relationcategories (relationid, categoryid) values (1, 2); +# insert into relationcategories (relationid, categoryid) values (2, 2); +# insert into relationcategories (relationid, categoryid) values (1, 3); +# +# commit; +# +# -- normally these indexes are created by the primary/foreign keys, +# -- but we don't want to rely on them for this test +# create unique asc index pk_relations on relations (relationid); +# create unique asc index pk_categories on categories (categoryid); +# create unique asc index pk_relationcategories on relationcategories (relationid, categoryid); +# create asc index fk_rc_relations on relationcategories (relationid); +# create asc index fk_rc_categories on relationcategories (categoryid); +# +# commit; +# +# set plan on; +# set list on; +# +# select +# r.relationname, +# rc.relationid, +# rc.categoryid, +# c.description +# from +# relations r +# full join relationcategories rc on (rc.relationid = r.relationid) +# full join categories c on (c.categoryid = rc.categoryid) +# where +# rc.categoryid is null and c.categoryid >= 1 +# +# UNION ALL --- ::::::: U N I O N A L L ::::::: +# +# select +# r.relationname, +# rc.relationid, +# rc.categoryid, +# c.description +# from +# relations r +# full join relationcategories rc on (rc.relationid = r.relationid) +# full join categories c on (c.categoryid = rc.categoryid) +# where +# rc.relationid is null and r.relationid >= 1; +# ''' +# +# f_sql=open( os.path.join(context['temp_directory'],'tmp_opt_full_join_04.tmp'), 'w') +# f_sql.write(sql_cmd) +# f_sql.close() +# +# f_log = open( os.path.join(context['temp_directory'],'tmp_opt_full_join_04.log'), 'w') +# +# subprocess.call( [context['isql_path'], dsn, "-i", f_sql.name], +# stdout=f_log, +# stderr=subprocess.STDOUT +# ) +# f_log.close() +# time.sleep(1) +# +# # NB: plan for 2.5 contains TWO rows! +# plan_25_1 = 'PLAN JOIN (C NATURAL, JOIN (RC NATURAL, R INDEX (PK_RELATIONS)))' +# plan_25_2 = 'PLAN JOIN (C INDEX (PK_CATEGORIES), JOIN (RC NATURAL, R NATURAL))' +# +# # plan for 3.0 contains only ONE row: +# plan_30_1 = 'PLAN (JOIN (JOIN (C INDEX (PK_CATEGORIES), JOIN (JOIN (RC NATURAL, R INDEX (PK_RELATIONS)), JOIN (R NATURAL, RC INDEX (FK_RC_RELATIONS)))), JOIN (JOIN (JOIN (RC NATURAL, R INDEX (PK_RELATIONS)), JOIN (R NATURAL, RC INDEX (FK_RC_RELATIONS))), C INDEX (PK_CATEGORIES))), JOIN (JOIN (C NATURAL, JOIN (JOIN (RC NATURAL, R INDEX (PK_RELATIONS)), JOIN (R INDEX (PK_RELATIONS), RC INDEX (FK_RC_RELATIONS)))), JOIN (JOIN (JOIN (RC NATURAL, R INDEX (PK_RELATIONS)), JOIN (R INDEX (PK_RELATIONS), RC INDEX (FK_RC_RELATIONS))), C NATURAL)))' +# plan_30_2 = '' +# +# with open(f_log.name) as f: +# for line in f: +# if line.upper().startswith('PLAN '): +# if engine.startswith('2.'): +# plan_expected_1=plan_25_1 +# plan_expected_2=plan_25_2 +# else: +# plan_expected_1=plan_30_1 +# plan_expected_2=plan_30_2 +# +# # Remove trailing whitespaces and newline character: +# if line.upper().rstrip() == plan_expected_1 or line.upper().rstrip() == plan_expected_2: +# if line.upper().rstrip() == plan_expected_1: +# print( 'Actual plan plan coincides with the expected.' ) +# else: +# print( 'Actual plan: '+line+' - differs from expected: '+plan_expected) +# else: +# print(line ) +# +# # Cleanup +# ######### +# os.remove(f_log.name) +# os.remove(f_sql.name) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Actual plan plan coincides with the expected. + + RELATIONNAME + RELATIONID + CATEGORYID + DESCRIPTION newsletter + RELATIONNAME folding air-hook shop + RELATIONID + CATEGORYID + DESCRIPTION + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_opt_full_join_04_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/arno/optimizer/test_opt_inner_join_01.py b/tests/functional/arno/optimizer/test_opt_inner_join_01.py new file mode 100644 index 00000000..52c9e856 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_inner_join_01.py @@ -0,0 +1,93 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_inner_join_01 +# title: INNER JOIN join order +# decription: With a INNER JOIN the table with the smallest expected result should be the first one in process order. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_inner_join_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_100 ( + ID INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_10 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 10) DO + BEGIN + INSERT INTO Table_10 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_100 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 100) DO + BEGIN + INSERT INTO Table_100 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_10; +EXECUTE PROCEDURE PR_FillTable_100; + +COMMIT; + +CREATE UNIQUE ASC INDEX PK_Table_10 ON Table_10 (ID); +CREATE UNIQUE ASC INDEX PK_Table_100 ON Table_100 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + Count(*) +FROM + Table_100 t100 + JOIN Table_10 t10 ON (t10.ID = t100.ID); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN JOIN (T10 NATURAL, T100 INDEX (PK_TABLE_100)) + + COUNT +===================== + 10 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_inner_join_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_inner_join_02.py b/tests/functional/arno/optimizer/test_opt_inner_join_02.py new file mode 100644 index 00000000..2e6d74b7 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_inner_join_02.py @@ -0,0 +1,115 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_inner_join_02 +# title: INNER JOIN join order +# decription: With a INNER JOIN the table with the smallest expected result should be the first one in process order. +# When all tables have the same avg. recordsize (recordformat) the next table should be the second smallest. +# Note that calculation is based on page-size. Thus for tables which use the same nr. of data-pages, but have in reality different nr. of records the table N could be bigger as table N+1 in the order. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_inner_join_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_100 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_3K ( + ID INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_10 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 10) DO + BEGIN + INSERT INTO Table_10 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_100 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 100) DO + BEGIN + INSERT INTO Table_100 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_3K +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 3000) DO + BEGIN + INSERT INTO Table_3K (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_10; +EXECUTE PROCEDURE PR_FillTable_100; +EXECUTE PROCEDURE PR_FillTable_3K; + +COMMIT; + +CREATE UNIQUE ASC INDEX PK_Table_10 ON Table_10 (ID); +CREATE UNIQUE ASC INDEX PK_Table_100 ON Table_100 (ID); +CREATE UNIQUE ASC INDEX PK_Table_3K ON Table_3K (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + Count(*) +FROM + Table_3K t3K + JOIN Table_100 t100 ON (t100.ID = t3K.ID) + JOIN Table_10 t10 ON (t10.ID = t100.ID); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN JOIN (T10 NATURAL, T100 INDEX (PK_TABLE_100), T3K INDEX (PK_TABLE_3K)) + + COUNT +===================== + 10 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_inner_join_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_inner_join_03.py b/tests/functional/arno/optimizer/test_opt_inner_join_03.py new file mode 100644 index 00000000..76cbec26 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_inner_join_03.py @@ -0,0 +1,134 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_inner_join_03 +# title: INNER JOIN join order +# decription: +# With a INNER JOIN the relation with the smallest expected result should be the first one in process order. +# The next relation should be the next relation with expected smallest result based on previous relation +# and do on till last relation. +# Before 2.0, Firebird did stop checking order possibilties above 7 relations. +# +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_inner_join_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """CREATE TABLE Table_1 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_1K ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_2K ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_3K ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_4K ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_5K ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_6K ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_8K ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_10K ( + ID INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_10K +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 10000) DO + BEGIN + INSERT INTO Table_10K (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +INSERT INTO Table_1 (ID) VALUES (1); +EXECUTE PROCEDURE PR_FillTable_10K; +INSERT INTO Table_1K (ID) SELECT ID FROM Table_10K WHERE ID <= 1000; +INSERT INTO Table_2K (ID) SELECT ID FROM Table_10K WHERE ID <= 2000; +INSERT INTO Table_3K (ID) SELECT ID FROM Table_10K WHERE ID <= 3000; +INSERT INTO Table_4K (ID) SELECT ID FROM Table_10K WHERE ID <= 4000; +INSERT INTO Table_5K (ID) SELECT ID FROM Table_10K WHERE ID <= 5000; +INSERT INTO Table_6K (ID) SELECT ID FROM Table_10K WHERE ID <= 6000; +INSERT INTO Table_8K (ID) SELECT ID FROM Table_10K WHERE ID <= 8000; + +COMMIT; + +CREATE UNIQUE ASC INDEX PK_Table_1 ON Table_1 (ID); +CREATE UNIQUE ASC INDEX PK_Table_1K ON Table_1K (ID); +CREATE UNIQUE ASC INDEX PK_Table_2K ON Table_2K (ID); +CREATE UNIQUE ASC INDEX PK_Table_3K ON Table_3K (ID); +CREATE UNIQUE ASC INDEX PK_Table_4K ON Table_4K (ID); +CREATE UNIQUE ASC INDEX PK_Table_5K ON Table_5K (ID); +CREATE UNIQUE ASC INDEX PK_Table_6K ON Table_6K (ID); +CREATE UNIQUE ASC INDEX PK_Table_8K ON Table_8K (ID); +CREATE UNIQUE ASC INDEX PK_Table_10K ON Table_10K (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + Count(*) +FROM + Table_5K t5K + JOIN Table_6K t6K ON (t6K.ID = t5K.ID) + JOIN Table_8K t8K ON (t8K.ID = t6K.ID) + JOIN Table_10K t10K ON (t10K.ID = t8K.ID) + JOIN Table_3K t3K ON (t3K.ID = t10K.ID) + JOIN Table_4K t4K ON (t4K.ID = t3K.ID) + JOIN Table_1K t1K ON (t1K.ID = t4K.ID) + JOIN Table_2K t2K ON (t2K.ID = t1K.ID) + JOIN Table_1 t1 ON (t1.ID = t2K.ID); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN JOIN (T1 NATURAL, T1K INDEX (PK_TABLE_1K), T2K INDEX (PK_TABLE_2K), T3K INDEX (PK_TABLE_3K), T4K INDEX (PK_TABLE_4K), T5K INDEX (PK_TABLE_5K), T6K INDEX (PK_TABLE_6K), T8K INDEX (PK_TABLE_8K), T10K INDEX (PK_TABLE_10K)) + + COUNT +============ + + 1 +""" + +@pytest.mark.version('>=2.0') +def test_opt_inner_join_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_inner_join_04.py b/tests/functional/arno/optimizer/test_opt_inner_join_04.py new file mode 100644 index 00000000..c9586f4b --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_inner_join_04.py @@ -0,0 +1,332 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_inner_join_04 +# title: INNER JOIN join order LIKE and IS NULL +# decription: IS NULL should also be used for determing join order. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_inner_join_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Countries ( + CountryID INTEGER NOT NULL, + CountryName VARCHAR(50), + ISO3166_1_A2 CHAR(2) +); + +CREATE TABLE Relations ( + RelationID INTEGER, + RelationName VARCHAR(35), + Location VARCHAR(50), + Address VARCHAR(50), + ZipCode VARCHAR(12), + CountryID INTEGER +); + +COMMIT; + +/* + COUNTRIES + --------- + Exporting all rows +*/ +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (1, 'AFGHANISTAN', 'AF'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (2, 'ALBANIA', 'AL'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (3, 'ALGERIA', 'DZ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (4, 'AMERICAN SAMOA', 'AS'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (5, 'ANDORRA', 'AD'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (6, 'ANGOLA', 'AO'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (7, 'ANGUILLA', 'AI'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (8, 'ANTARCTICA', 'AQ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (9, 'ANTIGUA AND BARBUDA', 'AG'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (10, 'ARGENTINA', 'AR'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (11, 'ARMENIA', 'AM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (12, 'ARUBA', 'AW'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (13, 'AUSTRALIA', 'AU'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (14, 'AUSTRIA', 'AT'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (15, 'AZERBAIJAN', 'AZ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (16, 'BAHAMAS', 'BS'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (17, 'BAHRAIN', 'BH'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (18, 'BANGLADESH', 'BD'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (19, 'BARBADOS', 'BB'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (20, 'BELARUS', 'BY'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (21, 'BELGIUM', 'BE'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (22, 'BELIZE', 'BZ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (23, 'BENIN', 'BJ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (24, 'BERMUDA', 'BM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (25, 'BHUTAN', 'BT'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (26, 'BOLIVIA', 'BO'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (27, 'BOSNIA AND HERZEGOVINA', 'BA'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (28, 'BOTSWANA', 'BW'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (29, 'BOUVET ISLAND', 'BV'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (30, 'BRAZIL', 'BR'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (31, 'BRITISH INDIAN OCEAN TERRITORY', 'IO'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (32, 'BRUNEI DARUSSALAM', 'BN'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (33, 'BULGARIA', 'BG'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (34, 'BURKINA FASO', 'BF'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (35, 'BURUNDI', 'BI'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (36, 'CAMBODIA', 'KH'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (37, 'CAMEROON', 'CM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (38, 'CANADA', 'CA'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (39, 'CAPE VERDE', 'CV'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (40, 'CAYMAN ISLANDS', 'KY'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (41, 'CENTRAL AFRICAN REPUBLIC', 'CF'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (42, 'CHAD', 'TD'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (43, 'CHILE', 'CL'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (44, 'CHINA', 'CN'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (45, 'CHRISTMAS ISLAND', 'CX'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (46, 'COCOS (KEELING) ISLANDS', 'CC'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (47, 'COLOMBIA', 'CO'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (48, 'COMOROS', 'KM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (49, 'CONGO', 'CG'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (50, 'CONGO, THE DEMOCRATIC REPUBLIC OF THE', 'CD'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (51, 'COOK ISLANDS', 'CK'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (52, 'COSTA RICA', 'CR'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (53, 'COTE D''IVOIRE', 'CI'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (54, 'CROATIA', 'HR'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (55, 'CUBA', 'CU'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (56, 'CYPRUS', 'CY'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (57, 'CZECH REPUBLIC', 'CZ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (58, 'DENMARK', 'DK'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (59, 'DJIBOUTI', 'DJ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (60, 'DOMINICA', 'DM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (61, 'DOMINICAN REPUBLIC', 'DO'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (62, 'EAST TIMOR', 'TL'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (63, 'ECUADOR', 'EC'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (64, 'EGYPT', 'EG'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (65, 'EL SALVADOR', 'SV'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (66, 'EQUATORIAL GUINEA', 'GQ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (67, 'ERITREA', 'ER'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (68, 'ESTONIA', 'EE'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (69, 'ETHIOPIA', 'ET'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (70, 'FALKLAND ISLANDS (MALVINAS)', 'FK'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (71, 'FAROE ISLANDS', 'FO'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (72, 'FIJI', 'FJ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (73, 'FINLAND', 'FI'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (74, 'FRANCE', 'FR'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (75, 'FRENCH GUIANA', 'GF'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (76, 'FRENCH POLYNESIA', 'PF'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (77, 'FRENCH SOUTHERN TERRITORIES', 'TF'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (78, 'GABON', 'GA'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (79, 'GAMBIA', 'GM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (80, 'GEORGIA', 'GE'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (81, 'GERMANY', 'DE'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (82, 'GHANA', 'GH'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (83, 'GIBRALTAR', 'GI'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (84, 'GREECE', 'GR'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (85, 'GREENLAND', 'GL'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (86, 'GRENADA', 'GD'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (87, 'GUADELOUPE', 'GP'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (88, 'GUAM', 'GU'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (89, 'GUATEMALA', 'GT'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (90, 'GUINEA', 'GN'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (91, 'GUINEA-BISSAU', 'GW'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (92, 'GUYANA', 'GY'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (93, 'HAITI', 'HT'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (94, 'HEARD ISLAND AND MCDONALD ISLANDS', 'HM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (95, 'HOLY SEE (VATICAN CITY STATE)', 'VA'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (96, 'HONDURAS', 'HN'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (97, 'HONG KONG', 'HK'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (98, 'HUNGARY', 'HU'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (99, 'ICELAND', 'IS'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (100, 'INDIA', 'IN'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (101, 'INDONESIA', 'ID'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (102, 'IRAN, ISLAMIC REPUBLIC OF', 'IR'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (103, 'IRAQ', 'IQ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (104, 'IRELAND', 'IE'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (105, 'ISRAEL', 'IL'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (106, 'ITALY', 'IT'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (107, 'JAMAICA', 'JM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (108, 'JAPAN', 'JP'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (109, 'JORDAN', 'JO'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (110, 'KAZAKHSTAN', 'KZ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (111, 'KENYA', 'KE'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (112, 'KIRIBATI', 'KI'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (113, 'KOREA, DEMOCRATIC PEOPLE''S REPUBLIC OF', 'KP'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (114, 'KOREA, REPUBLIC OF', 'KR'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (115, 'KUWAIT', 'KW'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (116, 'KYRGYZSTAN', 'KG'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (117, 'LAO PEOPLE''S DEMOCRATIC REPUBLIC', 'LA'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (118, 'LATVIA', 'LV'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (119, 'LEBANON', 'LB'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (120, 'LESOTHO', 'LS'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (121, 'LIBERIA', 'LR'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (122, 'LIBYAN ARAB JAMAHIRIYA', 'LY'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (123, 'LIECHTENSTEIN', 'LI'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (124, 'LITHUANIA', 'LT'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (125, 'LUXEMBOURG', 'LU'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (126, 'MACAO', 'MO'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (127, 'MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF', 'MK'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (128, 'MADAGASCAR', 'MG'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (129, 'MALAWI', 'MW'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (130, 'MALAYSIA', 'MY'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (131, 'MALDIVES', 'MV'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (132, 'MALI', 'ML'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (133, 'MALTA', 'MT'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (134, 'MARSHALL ISLANDS', 'MH'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (135, 'MARTINIQUE', 'MQ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (136, 'MAURITANIA', 'MR'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (137, 'MAURITIUS', 'MU'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (138, 'MAYOTTE', 'YT'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (139, 'MEXICO', 'MX'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (140, 'MICRONESIA, FEDERATED STATES OF', 'FM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (141, 'MOLDOVA, REPUBLIC OF', 'MD'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (142, 'MONACO', 'MC'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (143, 'MONGOLIA', 'MN'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (144, 'MONTSERRAT', 'MS'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (145, 'MOROCCO', 'MA'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (146, 'MOZAMBIQUE', 'MZ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (147, 'MYANMAR', 'MM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (148, 'NAMIBIA', 'NA'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (149, 'NAURU', 'NR'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (150, 'NEPAL', 'NP'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (151, 'NETHERLANDS', 'NL'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (152, 'NETHERLANDS ANTILLES', 'AN'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (153, 'NEW CALEDONIA', 'NC'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (154, 'NEW ZEALAND', 'NZ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (155, 'NICARAGUA', 'NI'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (156, 'NIGER', 'NE'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (157, 'NIGERIA', 'NG'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (158, 'NIUE', 'NU'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (159, 'NORFOLK ISLAND', 'NF'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (160, 'NORTHERN MARIANA ISLANDS', 'MP'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (161, 'NORWAY', 'NO'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (162, 'OMAN', 'OM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (163, 'PAKISTAN', 'PK'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (164, 'PALAU', 'PW'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (165, 'PALESTINIAN TERRITORY, OCCUPIED', 'PS'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (166, 'PANAMA', 'PA'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (167, 'PAPUA NEW GUINEA', 'PG'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (168, 'PARAGUAY', 'PY'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (169, 'PERU', 'PE'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (170, 'PHILIPPINES', 'PH'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (171, 'PITCAIRN', 'PN'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (172, 'POLAND', 'PL'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (173, 'PORTUGAL', 'PT'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (174, 'PUERTO RICO', 'PR'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (175, 'QATAR', 'QA'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (176, 'REUNION', 'RE'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (177, 'ROMANIA', 'RO'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (178, 'RUSSIAN FEDERATION', 'RU'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (179, 'RWANDA', 'RW'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (180, 'SAINT HELENA', 'SH'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (181, 'SAINT KITTS AND NEVIS', 'KN'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (182, 'SAINT LUCIA', 'LC'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (183, 'SAINT PIERRE AND MIQUELON', 'PM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (184, 'SAINT VINCENT AND THE GRENADINES', 'VC'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (185, 'SAMOA', 'WS'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (186, 'SAN MARINO', 'SM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (187, 'SAO TOME AND PRINCIPE', 'ST'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (188, 'SAUDI ARABIA', 'SA'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (189, 'SENEGAL', 'SN'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (190, 'SEYCHELLES', 'SC'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (191, 'SIERRA LEONE', 'SL'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (192, 'SINGAPORE', 'SG'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (193, 'SLOVAKIA', 'SK'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (194, 'SLOVENIA', 'SI'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (195, 'SOLOMON ISLANDS', 'SB'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (196, 'SOMALIA', 'SO'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (197, 'SOUTH AFRICA', 'ZA'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (198, 'SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS', 'GS'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (199, 'SPAIN', 'ES'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (200, 'SRI LANKA', 'LK'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (201, 'SUDAN', 'SD'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (202, 'SURINAME', 'SR'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (203, 'SVALBARD AND JAN MAYEN', 'SJ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (204, 'SWAZILAND', 'SZ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (205, 'SWEDEN', 'SE'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (206, 'SWITZERLAND', 'CH'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (207, 'SYRIAN ARAB REPUBLIC', 'SY'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (208, 'TAIWAN, PROVINCE OF CHINA', 'TW'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (209, 'TAJIKISTAN', 'TJ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (210, 'TANZANIA, UNITED REPUBLIC OF', 'TZ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (211, 'THAILAND', 'TH'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (212, 'TOGO', 'TG'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (213, 'TOKELAU', 'TK'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (214, 'TONGA', 'TO'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (215, 'TRINIDAD AND TOBAGO', 'TT'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (216, 'TUNISIA', 'TN'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (217, 'TURKEY', 'TR'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (218, 'TURKMENISTAN', 'TM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (219, 'TURKS AND CAICOS ISLANDS', 'TC'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (220, 'TUVALU', 'TV'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (221, 'UGANDA', 'UG'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (222, 'UKRAINE', 'UA'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (223, 'UNITED ARAB EMIRATES', 'AE'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (224, 'UNITED KINGDOM', 'GB'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (225, 'UNITED STATES', 'US'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (226, 'UNITED STATES MINOR OUTLYING ISLANDS', 'UM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (227, 'URUGUAY', 'UY'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (228, 'UZBEKISTAN', 'UZ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (229, 'VANUATU', 'VU'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (230, 'VENEZUELA', 'VE'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (231, 'VIET NAM', 'VN'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (232, 'VIRGIN ISLANDS, BRITISH', 'VG'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (233, 'VIRGIN ISLANDS, U.S.', 'VI'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (234, 'WALLIS AND FUTUNA', 'WF'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (235, 'WESTERN SAHARA', 'EH'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (236, 'YEMEN', 'YE'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (237, 'YUGOSLAVIA', 'YU'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (238, 'ZAMBIA', 'ZM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (239, 'ZIMBABWE', 'ZW'); + + +/* + RELATIONS + --------- + Exporting all rows +*/ +INSERT INTO RELATIONS(RELATIONID, RELATIONNAME, LOCATION, ADDRESS, ZIPCODE, COUNTRYID) VALUES (101, 'University Amsterdam', 'Amsterdam', 'De Boelelaan 1081A', '1081 HV', 151); +INSERT INTO RELATIONS(RELATIONID, RELATIONNAME, LOCATION, ADDRESS, ZIPCODE, COUNTRYID) VALUES (102, 'University Brussel', 'ELSENE', 'Pleinlaan 2', '1050', 21); +INSERT INTO RELATIONS(RELATIONID, RELATIONNAME, LOCATION, ADDRESS, ZIPCODE, COUNTRYID) VALUES (103, 'University Leiden', 'Leiden', 'Niels Bohrweg 1', '2333 CA', 151); +INSERT INTO RELATIONS(RELATIONID, RELATIONNAME, LOCATION, ADDRESS, ZIPCODE, COUNTRYID) VALUES (104, 'University Delft', 'Delft', 'Julianalaan 134', '2628 BL', 151); + +COMMIT; + +/* Normally these indexes are created by the primary/foreign keys, but we don't want to rely on them for this test */ + +CREATE UNIQUE ASC INDEX PK_Countries ON Countries (CountryID); +CREATE UNIQUE ASC INDEX PK_Relations ON Relations (RelationID); +CREATE ASC INDEX FK_Relations_Countries ON Relations (CountryID); +CREATE UNIQUE ASC INDEX I_RelationName ON Relations (RelationName); +CREATE UNIQUE ASC INDEX I_CountryName ON Countries (CountryName); + + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + Count(*) +FROM + RELATIONS r + JOIN COUNTRIES c ON (c.COUNTRYID = r.COUNTRYID) +WHERE + c.COUNTRYID IS NULL;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN JOIN (C INDEX (PK_COUNTRIES), R INDEX (FK_RELATIONS_COUNTRIES)) + + COUNT +===================== + 0 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_inner_join_04_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_inner_join_05.py b/tests/functional/arno/optimizer/test_opt_inner_join_05.py new file mode 100644 index 00000000..48261a83 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_inner_join_05.py @@ -0,0 +1,337 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_inner_join_05 +# title: INNER JOIN join order LIKE and STARTING WITH +# decription: LIKE and STARTING WITH should also be used for determing join order. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_inner_join_05 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Countries ( + CountryID INTEGER NOT NULL, + CountryName VARCHAR(50), + ISO3166_1_A2 CHAR(2) +); + +CREATE TABLE Relations ( + RelationID INTEGER, + RelationName VARCHAR(35), + Location VARCHAR(50), + Address VARCHAR(50), + ZipCode VARCHAR(12), + CountryID INTEGER +); + +COMMIT; + +/* + COUNTRIES + --------- + Exporting all rows +*/ +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (1, 'AFGHANISTAN', 'AF'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (2, 'ALBANIA', 'AL'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (3, 'ALGERIA', 'DZ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (4, 'AMERICAN SAMOA', 'AS'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (5, 'ANDORRA', 'AD'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (6, 'ANGOLA', 'AO'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (7, 'ANGUILLA', 'AI'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (8, 'ANTARCTICA', 'AQ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (9, 'ANTIGUA AND BARBUDA', 'AG'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (10, 'ARGENTINA', 'AR'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (11, 'ARMENIA', 'AM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (12, 'ARUBA', 'AW'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (13, 'AUSTRALIA', 'AU'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (14, 'AUSTRIA', 'AT'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (15, 'AZERBAIJAN', 'AZ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (16, 'BAHAMAS', 'BS'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (17, 'BAHRAIN', 'BH'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (18, 'BANGLADESH', 'BD'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (19, 'BARBADOS', 'BB'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (20, 'BELARUS', 'BY'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (21, 'BELGIUM', 'BE'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (22, 'BELIZE', 'BZ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (23, 'BENIN', 'BJ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (24, 'BERMUDA', 'BM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (25, 'BHUTAN', 'BT'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (26, 'BOLIVIA', 'BO'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (27, 'BOSNIA AND HERZEGOVINA', 'BA'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (28, 'BOTSWANA', 'BW'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (29, 'BOUVET ISLAND', 'BV'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (30, 'BRAZIL', 'BR'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (31, 'BRITISH INDIAN OCEAN TERRITORY', 'IO'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (32, 'BRUNEI DARUSSALAM', 'BN'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (33, 'BULGARIA', 'BG'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (34, 'BURKINA FASO', 'BF'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (35, 'BURUNDI', 'BI'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (36, 'CAMBODIA', 'KH'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (37, 'CAMEROON', 'CM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (38, 'CANADA', 'CA'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (39, 'CAPE VERDE', 'CV'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (40, 'CAYMAN ISLANDS', 'KY'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (41, 'CENTRAL AFRICAN REPUBLIC', 'CF'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (42, 'CHAD', 'TD'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (43, 'CHILE', 'CL'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (44, 'CHINA', 'CN'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (45, 'CHRISTMAS ISLAND', 'CX'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (46, 'COCOS (KEELING) ISLANDS', 'CC'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (47, 'COLOMBIA', 'CO'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (48, 'COMOROS', 'KM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (49, 'CONGO', 'CG'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (50, 'CONGO, THE DEMOCRATIC REPUBLIC OF THE', 'CD'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (51, 'COOK ISLANDS', 'CK'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (52, 'COSTA RICA', 'CR'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (53, 'COTE D''IVOIRE', 'CI'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (54, 'CROATIA', 'HR'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (55, 'CUBA', 'CU'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (56, 'CYPRUS', 'CY'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (57, 'CZECH REPUBLIC', 'CZ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (58, 'DENMARK', 'DK'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (59, 'DJIBOUTI', 'DJ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (60, 'DOMINICA', 'DM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (61, 'DOMINICAN REPUBLIC', 'DO'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (62, 'EAST TIMOR', 'TL'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (63, 'ECUADOR', 'EC'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (64, 'EGYPT', 'EG'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (65, 'EL SALVADOR', 'SV'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (66, 'EQUATORIAL GUINEA', 'GQ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (67, 'ERITREA', 'ER'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (68, 'ESTONIA', 'EE'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (69, 'ETHIOPIA', 'ET'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (70, 'FALKLAND ISLANDS (MALVINAS)', 'FK'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (71, 'FAROE ISLANDS', 'FO'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (72, 'FIJI', 'FJ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (73, 'FINLAND', 'FI'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (74, 'FRANCE', 'FR'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (75, 'FRENCH GUIANA', 'GF'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (76, 'FRENCH POLYNESIA', 'PF'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (77, 'FRENCH SOUTHERN TERRITORIES', 'TF'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (78, 'GABON', 'GA'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (79, 'GAMBIA', 'GM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (80, 'GEORGIA', 'GE'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (81, 'GERMANY', 'DE'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (82, 'GHANA', 'GH'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (83, 'GIBRALTAR', 'GI'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (84, 'GREECE', 'GR'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (85, 'GREENLAND', 'GL'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (86, 'GRENADA', 'GD'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (87, 'GUADELOUPE', 'GP'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (88, 'GUAM', 'GU'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (89, 'GUATEMALA', 'GT'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (90, 'GUINEA', 'GN'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (91, 'GUINEA-BISSAU', 'GW'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (92, 'GUYANA', 'GY'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (93, 'HAITI', 'HT'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (94, 'HEARD ISLAND AND MCDONALD ISLANDS', 'HM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (95, 'HOLY SEE (VATICAN CITY STATE)', 'VA'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (96, 'HONDURAS', 'HN'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (97, 'HONG KONG', 'HK'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (98, 'HUNGARY', 'HU'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (99, 'ICELAND', 'IS'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (100, 'INDIA', 'IN'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (101, 'INDONESIA', 'ID'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (102, 'IRAN, ISLAMIC REPUBLIC OF', 'IR'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (103, 'IRAQ', 'IQ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (104, 'IRELAND', 'IE'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (105, 'ISRAEL', 'IL'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (106, 'ITALY', 'IT'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (107, 'JAMAICA', 'JM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (108, 'JAPAN', 'JP'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (109, 'JORDAN', 'JO'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (110, 'KAZAKHSTAN', 'KZ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (111, 'KENYA', 'KE'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (112, 'KIRIBATI', 'KI'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (113, 'KOREA, DEMOCRATIC PEOPLE''S REPUBLIC OF', 'KP'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (114, 'KOREA, REPUBLIC OF', 'KR'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (115, 'KUWAIT', 'KW'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (116, 'KYRGYZSTAN', 'KG'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (117, 'LAO PEOPLE''S DEMOCRATIC REPUBLIC', 'LA'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (118, 'LATVIA', 'LV'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (119, 'LEBANON', 'LB'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (120, 'LESOTHO', 'LS'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (121, 'LIBERIA', 'LR'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (122, 'LIBYAN ARAB JAMAHIRIYA', 'LY'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (123, 'LIECHTENSTEIN', 'LI'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (124, 'LITHUANIA', 'LT'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (125, 'LUXEMBOURG', 'LU'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (126, 'MACAO', 'MO'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (127, 'MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF', 'MK'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (128, 'MADAGASCAR', 'MG'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (129, 'MALAWI', 'MW'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (130, 'MALAYSIA', 'MY'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (131, 'MALDIVES', 'MV'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (132, 'MALI', 'ML'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (133, 'MALTA', 'MT'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (134, 'MARSHALL ISLANDS', 'MH'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (135, 'MARTINIQUE', 'MQ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (136, 'MAURITANIA', 'MR'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (137, 'MAURITIUS', 'MU'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (138, 'MAYOTTE', 'YT'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (139, 'MEXICO', 'MX'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (140, 'MICRONESIA, FEDERATED STATES OF', 'FM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (141, 'MOLDOVA, REPUBLIC OF', 'MD'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (142, 'MONACO', 'MC'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (143, 'MONGOLIA', 'MN'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (144, 'MONTSERRAT', 'MS'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (145, 'MOROCCO', 'MA'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (146, 'MOZAMBIQUE', 'MZ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (147, 'MYANMAR', 'MM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (148, 'NAMIBIA', 'NA'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (149, 'NAURU', 'NR'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (150, 'NEPAL', 'NP'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (151, 'NETHERLANDS', 'NL'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (152, 'NETHERLANDS ANTILLES', 'AN'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (153, 'NEW CALEDONIA', 'NC'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (154, 'NEW ZEALAND', 'NZ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (155, 'NICARAGUA', 'NI'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (156, 'NIGER', 'NE'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (157, 'NIGERIA', 'NG'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (158, 'NIUE', 'NU'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (159, 'NORFOLK ISLAND', 'NF'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (160, 'NORTHERN MARIANA ISLANDS', 'MP'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (161, 'NORWAY', 'NO'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (162, 'OMAN', 'OM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (163, 'PAKISTAN', 'PK'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (164, 'PALAU', 'PW'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (165, 'PALESTINIAN TERRITORY, OCCUPIED', 'PS'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (166, 'PANAMA', 'PA'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (167, 'PAPUA NEW GUINEA', 'PG'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (168, 'PARAGUAY', 'PY'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (169, 'PERU', 'PE'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (170, 'PHILIPPINES', 'PH'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (171, 'PITCAIRN', 'PN'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (172, 'POLAND', 'PL'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (173, 'PORTUGAL', 'PT'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (174, 'PUERTO RICO', 'PR'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (175, 'QATAR', 'QA'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (176, 'REUNION', 'RE'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (177, 'ROMANIA', 'RO'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (178, 'RUSSIAN FEDERATION', 'RU'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (179, 'RWANDA', 'RW'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (180, 'SAINT HELENA', 'SH'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (181, 'SAINT KITTS AND NEVIS', 'KN'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (182, 'SAINT LUCIA', 'LC'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (183, 'SAINT PIERRE AND MIQUELON', 'PM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (184, 'SAINT VINCENT AND THE GRENADINES', 'VC'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (185, 'SAMOA', 'WS'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (186, 'SAN MARINO', 'SM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (187, 'SAO TOME AND PRINCIPE', 'ST'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (188, 'SAUDI ARABIA', 'SA'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (189, 'SENEGAL', 'SN'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (190, 'SEYCHELLES', 'SC'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (191, 'SIERRA LEONE', 'SL'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (192, 'SINGAPORE', 'SG'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (193, 'SLOVAKIA', 'SK'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (194, 'SLOVENIA', 'SI'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (195, 'SOLOMON ISLANDS', 'SB'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (196, 'SOMALIA', 'SO'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (197, 'SOUTH AFRICA', 'ZA'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (198, 'SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS', 'GS'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (199, 'SPAIN', 'ES'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (200, 'SRI LANKA', 'LK'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (201, 'SUDAN', 'SD'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (202, 'SURINAME', 'SR'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (203, 'SVALBARD AND JAN MAYEN', 'SJ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (204, 'SWAZILAND', 'SZ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (205, 'SWEDEN', 'SE'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (206, 'SWITZERLAND', 'CH'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (207, 'SYRIAN ARAB REPUBLIC', 'SY'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (208, 'TAIWAN, PROVINCE OF CHINA', 'TW'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (209, 'TAJIKISTAN', 'TJ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (210, 'TANZANIA, UNITED REPUBLIC OF', 'TZ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (211, 'THAILAND', 'TH'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (212, 'TOGO', 'TG'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (213, 'TOKELAU', 'TK'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (214, 'TONGA', 'TO'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (215, 'TRINIDAD AND TOBAGO', 'TT'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (216, 'TUNISIA', 'TN'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (217, 'TURKEY', 'TR'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (218, 'TURKMENISTAN', 'TM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (219, 'TURKS AND CAICOS ISLANDS', 'TC'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (220, 'TUVALU', 'TV'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (221, 'UGANDA', 'UG'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (222, 'UKRAINE', 'UA'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (223, 'UNITED ARAB EMIRATES', 'AE'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (224, 'UNITED KINGDOM', 'GB'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (225, 'UNITED STATES', 'US'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (226, 'UNITED STATES MINOR OUTLYING ISLANDS', 'UM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (227, 'URUGUAY', 'UY'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (228, 'UZBEKISTAN', 'UZ'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (229, 'VANUATU', 'VU'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (230, 'VENEZUELA', 'VE'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (231, 'VIET NAM', 'VN'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (232, 'VIRGIN ISLANDS, BRITISH', 'VG'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (233, 'VIRGIN ISLANDS, U.S.', 'VI'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (234, 'WALLIS AND FUTUNA', 'WF'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (235, 'WESTERN SAHARA', 'EH'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (236, 'YEMEN', 'YE'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (237, 'YUGOSLAVIA', 'YU'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (238, 'ZAMBIA', 'ZM'); +INSERT INTO COUNTRIES(COUNTRYID, COUNTRYNAME, ISO3166_1_A2) VALUES (239, 'ZIMBABWE', 'ZW'); + +/* + RELATIONS + --------- + Exporting all rows +*/ +INSERT INTO RELATIONS(RELATIONID, RELATIONNAME, LOCATION, ADDRESS, ZIPCODE, COUNTRYID) VALUES (101, 'University Amsterdam', 'Amsterdam', 'De Boelelaan 1081A', '1081 HV', 151); +INSERT INTO RELATIONS(RELATIONID, RELATIONNAME, LOCATION, ADDRESS, ZIPCODE, COUNTRYID) VALUES (102, 'University Brussel', 'ELSENE', 'Pleinlaan 2', '1050', 21); +INSERT INTO RELATIONS(RELATIONID, RELATIONNAME, LOCATION, ADDRESS, ZIPCODE, COUNTRYID) VALUES (103, 'University Leiden', 'Leiden', 'Niels Bohrweg 1', '2333 CA', 151); +INSERT INTO RELATIONS(RELATIONID, RELATIONNAME, LOCATION, ADDRESS, ZIPCODE, COUNTRYID) VALUES (104, 'University Delft', 'Delft', 'Julianalaan 134', '2628 BL', 151); + +COMMIT; + +/* Normally these indexes are created by the primary/foreign keys, but we don't want to rely on them for this test */ + +CREATE UNIQUE ASC INDEX PK_Countries ON Countries (CountryID); +CREATE UNIQUE ASC INDEX PK_Relations ON Relations (RelationID); +CREATE ASC INDEX FK_Relations_Countries ON Relations (CountryID); +CREATE UNIQUE ASC INDEX I_RelationName ON Relations (RelationName); +CREATE UNIQUE ASC INDEX I_CountryName ON Countries (CountryName); + + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + r.RelationName, + c.CountryName +FROM + RELATIONS r + JOIN COUNTRIES c ON (c.COUNTRYID = r.COUNTRYID) +WHERE + c.CountryName LIKE 'N%' +ORDER BY + r.RelationName DESC; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN SORT (JOIN (C INDEX (I_COUNTRYNAME), R INDEX (FK_RELATIONS_COUNTRIES))) + +RELATIONNAME COUNTRYNAME +=================================== ================================================== + +University Leiden NETHERLANDS +University Delft NETHERLANDS +University Amsterdam NETHERLANDS +""" + +@pytest.mark.version('>=2.0') +def test_opt_inner_join_05_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_inner_join_06.py b/tests/functional/arno/optimizer/test_opt_inner_join_06.py new file mode 100644 index 00000000..9e981715 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_inner_join_06.py @@ -0,0 +1,112 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_inner_join_06 +# title: INNER JOIN join order and VIEW +# decription: With a INNER JOIN the table with the smallest expected result should be the first one in process order. +# All inner joins are combined to 1 inner join, because then a order can be decided between them. Relations from a VIEW can also be "merged" to the 1 inner join (of course not with outer joins/unions/etc..) +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_inner_join_06 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_100 ( + ID INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_10 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 10) DO + BEGIN + INSERT INTO Table_10 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_100 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 100) DO + BEGIN + INSERT INTO Table_100 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +CREATE VIEW View_10 ( + ID +) +AS +SELECT + ID +FROM + Table_10; + +CREATE VIEW View_100 ( + ID +) +AS +SELECT + ID +FROM + Table_100; + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_10; +EXECUTE PROCEDURE PR_FillTable_100; + +COMMIT; + +CREATE UNIQUE ASC INDEX PK_Table_10 ON Table_10 (ID); +CREATE UNIQUE ASC INDEX PK_Table_100 ON Table_100 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + Count(*) +FROM + View_100 v100 + JOIN View_10 v10 ON (v10.ID = v100.ID); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN JOIN (V10 TABLE_10 NATURAL, V100 TABLE_100 INDEX (PK_TABLE_100)) + + COUNT +===================== + 10 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_inner_join_06_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_inner_join_07.py b/tests/functional/arno/optimizer/test_opt_inner_join_07.py new file mode 100644 index 00000000..7c6cdb0c --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_inner_join_07.py @@ -0,0 +1,151 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_inner_join_07 +# title: INNER JOIN join order and VIEW +# decription: With a INNER JOIN the relation with the smallest expected result should be the first one in process order. The next relation should be the next relation with expected smallest result based on previous relation and do on till last relation. +# +# Old/Current limitation in Firebird does stop checking order possibilties above 7 relations. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_inner_join_07 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """CREATE TABLE Table_1 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_1K ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_2K ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_3K ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_4K ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_5K ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_6K ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_8K ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_10K ( + ID INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_10K +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 10000) DO + BEGIN + INSERT INTO Table_10K (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +CREATE VIEW View_A ( + ID1K, + ID6K +) +AS +SELECT + t1K.ID, + t6K.ID +FROM + Table_6K t6K + JOIN Table_1K t1K ON (t1K.ID = t6K.ID); + +CREATE VIEW View_B ( + ID3K, + ID10K +) +AS +SELECT + t3K.ID, + t10K.ID +FROM + Table_3K t3K + JOIN Table_10K t10K ON (t10K.ID = t3K.ID); + +COMMIT; + +INSERT INTO Table_1 (ID) VALUES (1); +EXECUTE PROCEDURE PR_FillTable_10K; +INSERT INTO Table_1K (ID) SELECT ID FROM Table_10K WHERE ID <= 1000; +INSERT INTO Table_2K (ID) SELECT ID FROM Table_10K WHERE ID <= 2000; +INSERT INTO Table_3K (ID) SELECT ID FROM Table_10K WHERE ID <= 3000; +INSERT INTO Table_4K (ID) SELECT ID FROM Table_10K WHERE ID <= 4000; +INSERT INTO Table_5K (ID) SELECT ID FROM Table_10K WHERE ID <= 5000; +INSERT INTO Table_6K (ID) SELECT ID FROM Table_10K WHERE ID <= 6000; +INSERT INTO Table_8K (ID) SELECT ID FROM Table_10K WHERE ID <= 8000; + +COMMIT; + +CREATE UNIQUE ASC INDEX PK_Table_1 ON Table_1 (ID); +CREATE UNIQUE ASC INDEX PK_Table_1K ON Table_1K (ID); +CREATE UNIQUE ASC INDEX PK_Table_2K ON Table_2K (ID); +CREATE UNIQUE ASC INDEX PK_Table_3K ON Table_3K (ID); +CREATE UNIQUE ASC INDEX PK_Table_4K ON Table_4K (ID); +CREATE UNIQUE ASC INDEX PK_Table_5K ON Table_5K (ID); +CREATE UNIQUE ASC INDEX PK_Table_6K ON Table_6K (ID); +CREATE UNIQUE ASC INDEX PK_Table_8K ON Table_8K (ID); +CREATE UNIQUE ASC INDEX PK_Table_10K ON Table_10K (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + Count(*) +FROM + View_B vb + JOIN View_A va ON (va.ID1K = vb.ID10K); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN JOIN (VA T1K NATURAL, VB T3K INDEX (PK_TABLE_3K), VA T6K INDEX (PK_TABLE_6K), VB T10K INDEX (PK_TABLE_10K)) + + + COUNT +============ + + 1000 +""" + +@pytest.mark.version('>=2.0') +def test_opt_inner_join_07_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_inner_join_08.py b/tests/functional/arno/optimizer/test_opt_inner_join_08.py new file mode 100644 index 00000000..07bbd4a8 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_inner_join_08.py @@ -0,0 +1,143 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_inner_join_08 +# title: INNER JOIN join order and VIEW +# decription: Try to merge the top INNER JOINs of VIEWS/TABLES together to 1 inner join. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_inner_join_08 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_1 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_50 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_100 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_250 ( + ID INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_50 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 50) DO + BEGIN + INSERT INTO Table_50 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_100 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 100) DO + BEGIN + INSERT INTO Table_100 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_250 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 250) DO + BEGIN + INSERT INTO Table_250 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + + +CREATE VIEW View_A ( + ID1, + ID250 +) +AS +SELECT + t1.ID, + t250.ID +FROM + Table_1 t1 + LEFT JOIN Table_250 t250 ON (t250.ID = t1.ID); + +CREATE VIEW View_B ( + ID50, + ID100 +) +AS +SELECT + t50.ID, + t100.ID +FROM + Table_50 t50 + JOIN Table_100 t100 ON (t100.ID = t50.ID); + +COMMIT; + +INSERT INTO Table_1 (ID) VALUES (1); +EXECUTE PROCEDURE PR_FillTable_50; +EXECUTE PROCEDURE PR_FillTable_100; +EXECUTE PROCEDURE PR_FillTable_250; + +COMMIT; + +CREATE UNIQUE ASC INDEX PK_Table_1 ON Table_1 (ID); +CREATE UNIQUE ASC INDEX PK_Table_50 ON Table_50 (ID); +CREATE UNIQUE ASC INDEX PK_Table_100 ON Table_100 (ID); +CREATE UNIQUE ASC INDEX PK_Table_250 ON Table_250 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + Count(*) +FROM + View_B vb + JOIN View_A va ON (va.ID1 = vb.ID100); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN JOIN (JOIN (VA T1 NATURAL, VA T250 INDEX (PK_TABLE_250)), JOIN (VB T50 INDEX (PK_TABLE_50), VB T100 INDEX (PK_TABLE_100))) + + COUNT +===================== + 1 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_inner_join_08_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_inner_join_09.py b/tests/functional/arno/optimizer/test_opt_inner_join_09.py new file mode 100644 index 00000000..cb06b8bc --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_inner_join_09.py @@ -0,0 +1,126 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_inner_join_09 +# title: INNER JOIN join order and distribution +# decription: With a INNER JOIN the relation with the smallest expected result should be the first one in process order. The next relation should be the next relation with expected smallest result based on previous relation and do on till last relation. +# +# Distribution is tested if it's conjunctions are distributed from WHERE clause. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_inner_join_09 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """CREATE TABLE Table_1 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_50 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_100 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_250 ( + ID INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_50 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 50) DO + BEGIN + INSERT INTO Table_50 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_100 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 100) DO + BEGIN + INSERT INTO Table_100 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_250 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 250) DO + BEGIN + INSERT INTO Table_250 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +INSERT INTO Table_1 (ID) VALUES (1); +EXECUTE PROCEDURE PR_FillTable_50; +EXECUTE PROCEDURE PR_FillTable_100; +EXECUTE PROCEDURE PR_FillTable_250; + +COMMIT; + +CREATE UNIQUE ASC INDEX PK_Table_1 ON Table_1 (ID); +CREATE UNIQUE ASC INDEX PK_Table_50 ON Table_50 (ID); +CREATE UNIQUE ASC INDEX PK_Table_100 ON Table_100 (ID); +CREATE UNIQUE ASC INDEX PK_Table_250 ON Table_250 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + Count(*) +FROM + Table_50 t50 + JOIN Table_100 t100 ON (t100.ID = t50.ID) + JOIN Table_1 t1 ON (1 = 1) + JOIN Table_250 t250 ON (1 = 1) +WHERE + t250.ID = t1.ID and + t100.ID = t1.ID; + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN JOIN (T1 NATURAL, T50 INDEX (PK_TABLE_50), T100 INDEX (PK_TABLE_100), T250 INDEX (PK_TABLE_250)) + + COUNT +============ + + 1 +""" + +@pytest.mark.version('>=2.0') +def test_opt_inner_join_09_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_inner_join_10.py b/tests/functional/arno/optimizer/test_opt_inner_join_10.py new file mode 100644 index 00000000..1389d743 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_inner_join_10.py @@ -0,0 +1,114 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_inner_join_10 +# title: INNER JOIN join order +# decription: With a INNER JOIN the relation with the smallest expected result should be the first one in process order. The next relation should be the next relation with expected smallest result based on previous relation and do on till last relation. +# It is expected that a unique index gives fewer results then non-unique index. Thus non-unique indexes will be at the end by determing join order. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_inner_join_10 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """CREATE TABLE Table_50 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_100 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_250 ( + ID INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_50 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 50) DO + BEGIN + INSERT INTO Table_50 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_100 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 100) DO + BEGIN + INSERT INTO Table_100 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_250 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 250) DO + BEGIN + INSERT INTO Table_250 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_50; +EXECUTE PROCEDURE PR_FillTable_100; +EXECUTE PROCEDURE PR_FillTable_250; + +COMMIT; + +CREATE UNIQUE ASC INDEX PK_Table_50 ON Table_50 (ID); +CREATE UNIQUE ASC INDEX PK_Table_100 ON Table_100 (ID); +CREATE ASC INDEX I_Table_250 ON Table_250 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + Count(*) +FROM + Table_50 t50 + JOIN Table_100 t100 ON (t100.ID = t50.ID) + JOIN Table_250 t250 ON (t250.ID = t100.ID); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN JOIN (T50 NATURAL, T100 INDEX (PK_TABLE_100), T250 INDEX (I_TABLE_250)) + + COUNT +============ + + 50 +""" + +@pytest.mark.version('>=2.0') +def test_opt_inner_join_10_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_inner_join_merge_01.py b/tests/functional/arno/optimizer/test_opt_inner_join_merge_01.py new file mode 100644 index 00000000..25bb337d --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_inner_join_merge_01.py @@ -0,0 +1,89 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_inner_join_merge_01 +# title: INNER JOIN join merge +# decription: X JOIN Y ON (X.Field = Y.Field) +# When no index can be used on a INNER JOIN and there's a relation setup between X and Y then a MERGE should be performed. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_inner_join_merge_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_100 ( + ID INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_10 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 10) DO + BEGIN + INSERT INTO Table_10 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_100 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 100) DO + BEGIN + INSERT INTO Table_100 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_10; +EXECUTE PROCEDURE PR_FillTable_100; + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + Count(*) +FROM + Table_100 t100 + JOIN Table_10 t10 ON (t10.ID = t100.ID); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN HASH (T100 NATURAL, T10 NATURAL) + + COUNT +===================== + 10 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_inner_join_merge_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_inner_join_merge_02.py b/tests/functional/arno/optimizer/test_opt_inner_join_merge_02.py new file mode 100644 index 00000000..04efd80a --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_inner_join_merge_02.py @@ -0,0 +1,108 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_inner_join_merge_02 +# title: INNER JOIN join merge +# decription: X JOIN Y ON (X.Field = Y.Field) +# When no index can be used on a INNER JOIN and there's a relation setup between X and Y then a MERGE should be performed. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_inner_join_merge_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_100 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_1000 ( + ID INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_10 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 10) DO + BEGIN + INSERT INTO Table_10 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_100 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 100) DO + BEGIN + INSERT INTO Table_100 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_1000 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 1000) DO + BEGIN + INSERT INTO Table_1000 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_10; +EXECUTE PROCEDURE PR_FillTable_100; +EXECUTE PROCEDURE PR_FillTable_1000; + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + Count(*) +FROM + Table_1000 t1000 + JOIN Table_100 t100 ON (t100.ID = t1000.ID) + JOIN Table_10 t10 ON (t10.ID = t100.ID); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN HASH (T1000 NATURAL, T100 NATURAL, T10 NATURAL) + + COUNT +===================== + 10 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_inner_join_merge_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_inner_join_merge_03.py b/tests/functional/arno/optimizer/test_opt_inner_join_merge_03.py new file mode 100644 index 00000000..f6078e8d --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_inner_join_merge_03.py @@ -0,0 +1,89 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_inner_join_merge_03 +# title: INNER JOIN join merge +# decription: X JOIN Y ON (X.Field + (10 * 2) = Y.Field + 20) +# When no index can be used on a INNER JOIN and there's a relation setup between X and Y then a MERGE should be performed. Also when expressions are used. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_inner_join_merge_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_100 ( + ID INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_10 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 10) DO + BEGIN + INSERT INTO Table_10 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_100 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 100) DO + BEGIN + INSERT INTO Table_100 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_10; +EXECUTE PROCEDURE PR_FillTable_100; + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + Count(*) +FROM + Table_100 t100 + JOIN Table_10 t10 ON (t10.ID + (2 * 10) = t100.ID + 20); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN HASH (T100 NATURAL, T10 NATURAL) + + COUNT +===================== + 10 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_inner_join_merge_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_inner_join_merge_04.py b/tests/functional/arno/optimizer/test_opt_inner_join_merge_04.py new file mode 100644 index 00000000..26231765 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_inner_join_merge_04.py @@ -0,0 +1,100 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_inner_join_merge_04 +# title: INNER JOIN join merge and NULLs +# decription: X JOIN Y ON (X.Field = Y.Field) +# When no index can be used on a INNER JOIN and there's a relation setup between X and Y then a MERGE should be performed. +# An equality between NULLs should not be seen as true. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_inner_join_merge_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER +); + +CREATE TABLE Table_100 ( + ID INTEGER +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_10 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 15) DO + BEGIN + IF (FillID <= 10) THEN + BEGIN + INSERT INTO Table_10 (ID) VALUES (:FillID); + END ELSE BEGIN + INSERT INTO Table_10 (ID) VALUES (NULL); + END + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_100 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 110) DO + BEGIN + IF (FillID <= 100) THEN + BEGIN + INSERT INTO Table_100 (ID) VALUES (:FillID); + END ELSE BEGIN + INSERT INTO Table_100 (ID) VALUES (NULL); + END + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_10; +EXECUTE PROCEDURE PR_FillTable_100; + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + Count(*) +FROM + Table_100 t100 + JOIN Table_10 t10 ON (t10.ID = t100.ID); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN HASH (T100 NATURAL, T10 NATURAL) + + COUNT +===================== + 10 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_inner_join_merge_04_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_inner_join_merge_05.py b/tests/functional/arno/optimizer/test_opt_inner_join_merge_05.py new file mode 100644 index 00000000..a0ac053c --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_inner_join_merge_05.py @@ -0,0 +1,119 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_inner_join_merge_05 +# title: INNER JOIN join merge and VIEWs +# decription: X JOIN Y ON (X.Field = Y.Field) +# When no index can be used on a INNER JOIN and there's a relation setup between X and Y then a MERGE should be performed. Of course also when a VIEW is used. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_inner_join_merge_05 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_100 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_1000 ( + ID INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_10 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 10) DO + BEGIN + INSERT INTO Table_10 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_100 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 100) DO + BEGIN + INSERT INTO Table_100 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_1000 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 1000) DO + BEGIN + INSERT INTO Table_1000 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +CREATE VIEW View_A ( + ID10, + ID100 +) +AS +SELECT + t10.ID, + t100.ID +FROM + Table_100 t100 + JOIN Table_10 t10 ON (t10.ID = t100.ID); + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_10; +EXECUTE PROCEDURE PR_FillTable_100; +EXECUTE PROCEDURE PR_FillTable_1000; + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + Count(*) +FROM + Table_1000 t1000 + JOIN View_A va ON (va.ID100 = t1000.ID); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN HASH (T1000 NATURAL, VA T100 NATURAL, VA T10 NATURAL) + + COUNT +===================== + 10 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_inner_join_merge_05_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_inner_join_merge_06.py b/tests/functional/arno/optimizer/test_opt_inner_join_merge_06.py new file mode 100644 index 00000000..ef2b96e8 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_inner_join_merge_06.py @@ -0,0 +1,105 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_inner_join_merge_06 +# title: INNER JOIN join merge and SP +# decription: X JOIN Y ON (X.Field = Y.Field) +# When no index can be used on a INNER JOIN and there's a relation setup between X and Y then a MERGE should be performed. Test with selectable Stored Procedure. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_inner_join_merge_06 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_100 ( + ID INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_10 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 10) DO + BEGIN + INSERT INTO Table_10 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_100 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 100) DO + BEGIN + INSERT INTO Table_100 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_List_1000 +RETURNS ( + ID Integer +) +AS +BEGIN + ID = 2; + WHILE (ID <= 1000) DO + BEGIN + SUSPEND; + ID = ID + 2; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_10; +EXECUTE PROCEDURE PR_FillTable_100; + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + Count(*) +FROM + Table_100 t100 + JOIN Table_10 t10 ON (t10.ID = t100.ID) + JOIN PR_List_1000 sp1000 ON (sp1000.ID = t10.ID); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN HASH (T100 NATURAL, T10 NATURAL, SP1000 NATURAL) + + COUNT +===================== + 5 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_inner_join_merge_06_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_left_join_01.py b/tests/functional/arno/optimizer/test_opt_left_join_01.py new file mode 100644 index 00000000..83301200 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_left_join_01.py @@ -0,0 +1,82 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_left_join_01 +# title: LEFT OUTER JOIN with no match at all +# decription: TableX LEFT OUTER JOIN TableY with no match, thus result should contain all NULLs for TableY references. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_left_join_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Colors ( + ColorID INTEGER NOT NULL, + ColorName VARCHAR(20) +); + +CREATE TABLE Flowers ( + FlowerID INTEGER NOT NULL, + FlowerName VARCHAR(30), + ColorID INTEGER +); + +COMMIT; + +/* Value 0 represents -no value- */ +INSERT INTO Colors (ColorID, ColorName) VALUES (0, 'Not defined'); +INSERT INTO Colors (ColorID, ColorName) VALUES (1, 'Red'); +INSERT INTO Colors (ColorID, ColorName) VALUES (2, 'Yellow'); + +/* insert some data with references */ +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (1, 'Rose', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (2, 'Tulip', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (3, 'Gerbera', 0); + +COMMIT; + +/* Normally these indexes are created by the primary/foreign keys, + but we don't want to rely on them for this test */ +CREATE UNIQUE ASC INDEX PK_Colors ON Colors (ColorID); +CREATE UNIQUE ASC INDEX PK_Flowers ON Flowers (FlowerID); +CREATE ASC INDEX FK_Flowers_Colors ON Flowers (ColorID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +/* LEFT JOIN should return all NULLs */ +SELECT + f.FlowerName, + c.ColorName +FROM + Flowers f + LEFT JOIN Colors c ON (1 = 0); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN JOIN (F NATURAL, C NATURAL) +FLOWERNAME COLORNAME +============================== ==================== + +Rose +Tulip +Gerbera + +""" + +@pytest.mark.version('>=2.0') +def test_opt_left_join_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_left_join_02.py b/tests/functional/arno/optimizer/test_opt_left_join_02.py new file mode 100644 index 00000000..95a061ae --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_left_join_02.py @@ -0,0 +1,84 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_left_join_02 +# title: LEFT OUTER JOIN with no match and IS NULL in WHERE clause +# decription: TableX LEFT OUTER JOIN TableY with no match, thus result should contain all NULLs for TableY references. WHERE clause contains IS NULL on a field which is also in a single segment index. +# The WHERE clause shouldn't be distributed to the joined table. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_left_join_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Colors ( + ColorID INTEGER NOT NULL, + ColorName VARCHAR(20) +); + +CREATE TABLE Flowers ( + FlowerID INTEGER NOT NULL, + FlowerName VARCHAR(30), + ColorID INTEGER +); + +COMMIT; + +/* Value 0 represents -no value- */ +INSERT INTO Colors (ColorID, ColorName) VALUES (0, 'Not defined'); +INSERT INTO Colors (ColorID, ColorName) VALUES (1, 'Red'); +INSERT INTO Colors (ColorID, ColorName) VALUES (2, 'Yellow'); + +/* insert some data with references */ +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (1, 'Rose', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (2, 'Tulip', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (3, 'Gerbera', 0); + +COMMIT; + +/* Normally these indexes are created by the primary/foreign keys, + but we don't want to rely on them for this test */ +CREATE UNIQUE ASC INDEX PK_Colors ON Colors (ColorID); +CREATE UNIQUE ASC INDEX PK_Flowers ON Flowers (FlowerID); +CREATE ASC INDEX FK_Flowers_Colors ON Flowers (ColorID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +/* LEFT JOIN should return all NULLs */ +SELECT + f.FlowerName, + c.ColorName +FROM + Flowers f + LEFT JOIN Colors c ON (1 = 0) +WHERE + c.ColorID IS NULL; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN JOIN (F NATURAL, C NATURAL) +FLOWERNAME COLORNAME +============================== ==================== + +Rose +Tulip +Gerbera +""" + +@pytest.mark.version('>=2.0') +def test_opt_left_join_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_left_join_03.py b/tests/functional/arno/optimizer/test_opt_left_join_03.py new file mode 100644 index 00000000..2fc02cac --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_left_join_03.py @@ -0,0 +1,83 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_left_join_03 +# title: LEFT OUTER JOIN with full match and reference in WHERE clause +# decription: TableX LEFT OUTER JOIN TableY with full match. +# ON clause contains (1 = 1) and WHERE clause contains relation between TableX and TableY. The WHERE comparison should be distributed to TableY. Thus TableY should use the index. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_left_join_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Colors ( + ColorID INTEGER NOT NULL, + ColorName VARCHAR(20) +); + +CREATE TABLE Flowers ( + FlowerID INTEGER NOT NULL, + FlowerName VARCHAR(30), + ColorID INTEGER +); + +COMMIT; + +/* Value 0 represents -no value- */ +INSERT INTO Colors (ColorID, ColorName) VALUES (0, 'Not defined'); +INSERT INTO Colors (ColorID, ColorName) VALUES (1, 'Red'); +INSERT INTO Colors (ColorID, ColorName) VALUES (2, 'Yellow'); + +/* insert some data with references */ +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (1, 'Rose', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (2, 'Tulip', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (3, 'Gerbera', 0); + +COMMIT; + +/* Normally these indexes are created by the primary/foreign keys, + but we don't want to rely on them for this test */ +CREATE UNIQUE ASC INDEX PK_Colors ON Colors (ColorID); +CREATE UNIQUE ASC INDEX PK_Flowers ON Flowers (FlowerID); +CREATE ASC INDEX FK_Flowers_Colors ON Flowers (ColorID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +/* LEFT JOIN should return a match for every Flowers record */ +SELECT + f.FlowerName, + c.ColorName +FROM + Flowers f + LEFT JOIN Colors c ON (1 = 1) +WHERE + f.ColorID = c.ColorID;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN JOIN (F NATURAL, C INDEX (PK_COLORS)) +FLOWERNAME COLORNAME +============================== ==================== + +Rose Red +Tulip Yellow +Gerbera Not defined +""" + +@pytest.mark.version('>=2.0') +def test_opt_left_join_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_left_join_04.py b/tests/functional/arno/optimizer/test_opt_left_join_04.py new file mode 100644 index 00000000..9f38074d --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_left_join_04.py @@ -0,0 +1,83 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_left_join_04 +# title: LEFT OUTER JOIN with full match +# decription: TableX LEFT OUTER JOIN TableY with full match. Every reference from TableY should have a value. +# +# This test also tests if not the ON clause is distributed to the outer context TableX. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_left_join_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Colors ( + ColorID INTEGER NOT NULL, + ColorName VARCHAR(20) +); + +CREATE TABLE Flowers ( + FlowerID INTEGER NOT NULL, + FlowerName VARCHAR(30), + ColorID INTEGER +); + +COMMIT; + +/* Value 0 represents -no value- */ +INSERT INTO Colors (ColorID, ColorName) VALUES (0, 'Not defined'); +INSERT INTO Colors (ColorID, ColorName) VALUES (1, 'Red'); +INSERT INTO Colors (ColorID, ColorName) VALUES (2, 'Yellow'); + +/* insert some data with references */ +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (1, 'Rose', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (2, 'Tulip', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (3, 'Gerbera', 0); + +COMMIT; + +/* Normally these indexes are created by the primary/foreign keys, + but we don't want to rely on them for this test */ +CREATE UNIQUE ASC INDEX PK_Colors ON Colors (ColorID); +CREATE UNIQUE ASC INDEX PK_Flowers ON Flowers (FlowerID); +CREATE ASC INDEX FK_Flowers_Colors ON Flowers (ColorID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +/* LEFT JOIN should return all lookups */ +SELECT + f.FlowerName, + c.ColorName +FROM + Flowers f + LEFT JOIN Colors c ON (c.ColorID = f.ColorID); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN JOIN (F NATURAL, C INDEX (PK_COLORS)) +FLOWERNAME COLORNAME +============================== ==================== + +Rose Red +Tulip Yellow +Gerbera Not defined +""" + +@pytest.mark.version('>=2.0') +def test_opt_left_join_04_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_left_join_05.py b/tests/functional/arno/optimizer/test_opt_left_join_05.py new file mode 100644 index 00000000..843ff716 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_left_join_05.py @@ -0,0 +1,83 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_left_join_05 +# title: LEFT OUTER JOIN with full match, but limited in ON clause +# decription: TableX LEFT OUTER JOIN TableY with full match, but TableY results limited in ON clause. Which should result in partial NULL results. +# +# This test also tests if not the ON clause is distributed to the outer context TableX. Also if not the extra created nodes (comparisons) from a equality node and a A # B node (# =, <, <=, >=, >) are distributed to the outer context. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_left_join_05 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Colors ( + ColorID INTEGER NOT NULL, + ColorName VARCHAR(20) +); + +CREATE TABLE Flowers ( + FlowerID INTEGER NOT NULL, + FlowerName VARCHAR(30), + ColorID INTEGER +); + +COMMIT; + +/* Value 0 represents -no value- */ +INSERT INTO Colors (ColorID, ColorName) VALUES (0, 'Not defined'); +INSERT INTO Colors (ColorID, ColorName) VALUES (1, 'Red'); +INSERT INTO Colors (ColorID, ColorName) VALUES (2, 'Yellow'); + +/* insert some data with references */ +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (1, 'Rose', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (2, 'Tulip', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (3, 'Gerbera', 0); + +COMMIT; + +/* Normally these indexes are created by the primary/foreign keys, + but we don't want to rely on them for this test */ +CREATE UNIQUE ASC INDEX PK_Colors ON Colors (ColorID); +CREATE UNIQUE ASC INDEX PK_Flowers ON Flowers (FlowerID); +CREATE ASC INDEX FK_Flowers_Colors ON Flowers (ColorID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +/* LEFT JOIN should return all lookups except the 0 value */ +SELECT + f.FlowerName, + c.ColorName +FROM + Flowers f + LEFT JOIN Colors c ON ((c.ColorID = f.ColorID) AND + (c.ColorID >= 1)); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN JOIN (F NATURAL, C INDEX (PK_COLORS)) +FLOWERNAME COLORNAME +============================== ==================== + +Rose Red +Tulip Yellow +Gerbera """ + +@pytest.mark.version('>=2.0') +def test_opt_left_join_05_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_left_join_06.py b/tests/functional/arno/optimizer/test_opt_left_join_06.py new file mode 100644 index 00000000..eb988a70 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_left_join_06.py @@ -0,0 +1,88 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_left_join_06 +# title: LEFT OUTER JOIN with full match, but limited in ON clause +# decription: TableX LEFT OUTER JOIN TableY with full match, but TableY results limited in ON clause. Which should result in partial NULL results. +# +# This test also tests if not the ON clause is distributed to the outer context TableX. Also if not the extra created nodes (comparisons) from a equality node and a A # B node (# =, <, <=, >=, >) are distributed to the outer context. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_left_join_06 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Colors ( + ColorID INTEGER NOT NULL, + ColorName VARCHAR(20) +); + +CREATE TABLE Flowers ( + FlowerID INTEGER NOT NULL, + FlowerName VARCHAR(30), + ColorID INTEGER +); + +COMMIT; + +/* Value 0 represents -no value- */ +INSERT INTO Colors (ColorID, ColorName) VALUES (0, 'Not defined'); +INSERT INTO Colors (ColorID, ColorName) VALUES (1, 'Red'); +INSERT INTO Colors (ColorID, ColorName) VALUES (2, 'Yellow'); + +/* insert some data with references */ +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (1, 'Rose', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (2, 'Tulip', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (3, 'Gerbera', 0); + +COMMIT; + +/* Normally these indexes are created by the primary/foreign keys, + but we don't want to rely on them for this test */ +CREATE UNIQUE ASC INDEX PK_Colors ON Colors (ColorID); +CREATE UNIQUE ASC INDEX PK_Flowers ON Flowers (FlowerID); +CREATE ASC INDEX FK_Flowers_Colors ON Flowers (ColorID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +/* LEFT JOIN should return all lookups except the 0 value */ +SELECT + f1.FlowerName, + f2.FlowerName, + c.ColorName +FROM + Flowers f1 + LEFT JOIN Flowers f2 ON (1 = 1) + LEFT JOIN Colors c ON (c.ColorID = f1.ColorID) AND (c.ColorID > 0) +WHERE + (f2.ColorID = f1.ColorID) AND + (c.ColorID > 0); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN JOIN (JOIN (F1 NATURAL, F2 INDEX (FK_FLOWERS_COLORS)), C INDEX (PK_COLORS)) + +FLOWERNAME FLOWERNAME COLORNAME +============================== ============================== ==================== + +Rose Rose Red +Tulip Tulip Yellow +""" + +@pytest.mark.version('>=2.0') +def test_opt_left_join_06_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_left_join_07.py b/tests/functional/arno/optimizer/test_opt_left_join_07.py new file mode 100644 index 00000000..64f99a64 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_left_join_07.py @@ -0,0 +1,86 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_left_join_07 +# title: 4 JOINed tables with 1 LEFT OUTER JOIN +# decription: A INNER JOINed TableD to a LEFT JOINed TableC should be able to access the outer TableB of TableC. Also TableB is INNER JOINed to TableA. Three indexes can and should be used here. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_left_join_07 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Colors ( + ColorID INTEGER NOT NULL, + ColorName VARCHAR(20) +); + +CREATE TABLE Flowers ( + FlowerID INTEGER NOT NULL, + FlowerName VARCHAR(30), + ColorID INTEGER +); + +COMMIT; + +/* Value 0 represents -no value- */ +INSERT INTO Colors (ColorID, ColorName) VALUES (0, 'Not defined'); +INSERT INTO Colors (ColorID, ColorName) VALUES (1, 'Red'); +INSERT INTO Colors (ColorID, ColorName) VALUES (2, 'Yellow'); + +/* insert some data with references */ +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (1, 'Rose', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (2, 'Tulip', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (3, 'Gerbera', 0); + +COMMIT; + +/* Normally these indexes are created by the primary/foreign keys, + but we don't want to rely on them for this test */ +CREATE UNIQUE ASC INDEX PK_Colors ON Colors (ColorID); +CREATE UNIQUE ASC INDEX PK_Flowers ON Flowers (FlowerID); +CREATE ASC INDEX FK_Flowers_Colors ON Flowers (ColorID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +/* 4 joined tables with 1 LEFT JOIN */ +SELECT + f.ColorID, + c1.ColorID, + c2.ColorID, + c3.ColorID +FROM + Flowers f + JOIN Colors c1 ON (c1.ColorID = f.ColorID) + LEFT JOIN Colors c2 ON (c2.ColorID = c1.ColorID) + JOIN Colors c3 ON (c3.ColorID = c1.ColorID); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN JOIN (JOIN (JOIN (F NATURAL, C1 INDEX (PK_COLORS)), C2 INDEX (PK_COLORS)), C3 INDEX (PK_COLORS)) + + COLORID COLORID COLORID COLORID +============ ============ ============ ============ + + 1 1 1 1 + 2 2 2 2 + 0 0 0 0 +""" + +@pytest.mark.version('>=2.0') +def test_opt_left_join_07_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_left_join_08.py b/tests/functional/arno/optimizer/test_opt_left_join_08.py new file mode 100644 index 00000000..fe08ba55 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_left_join_08.py @@ -0,0 +1,86 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_left_join_08 +# title: LEFT OUTER JOIN with full match, but limited in ON and WHERE clause +# decription: TableX LEFT OUTER JOIN TableY with full match, but TableY results limited in ON clause. Which should result in partial NULL results for TableY. Due the WHERE clause a index for TableX should be used. +# tracker_id: +# min_versions: [] +# versions: 2.5 +# qmid: functional.arno.optimizer.opt_left_join_08 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Colors ( + ColorID INTEGER NOT NULL, + ColorName VARCHAR(20) +); + +CREATE TABLE Flowers ( + FlowerID INTEGER NOT NULL, + FlowerName VARCHAR(30), + ColorID INTEGER +); + +COMMIT; + +/* Value 0 represents -no value- */ +INSERT INTO Colors (ColorID, ColorName) VALUES (0, 'Not defined'); +INSERT INTO Colors (ColorID, ColorName) VALUES (1, 'Red'); +INSERT INTO Colors (ColorID, ColorName) VALUES (2, 'Yellow'); + +/* insert some data with references */ +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (1, 'Rose', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (2, 'Tulip', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (3, 'Gerbera', 0); + +COMMIT; + +/* Normally these indexes are created by the primary/foreign keys, + but we don't want to rely on them for this test */ +CREATE UNIQUE ASC INDEX PK_Colors ON Colors (ColorID); +CREATE UNIQUE ASC INDEX PK_Flowers ON Flowers (FlowerID); +CREATE ASC INDEX FK_Flowers_Colors ON Flowers (ColorID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +/* */ +SELECT + f.ColorID, + c.ColorID +FROM + Flowers f + LEFT JOIN Colors c ON (c.ColorID = f.ColorID) AND + (c.ColorID > 0) +WHERE + f.ColorID >= 0; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +PLAN JOIN (F INDEX (FK_FLOWERS_COLORS), C INDEX (PK_COLORS)) + + COLORID COLORID +============ ============ + 1 1 + 2 2 + 0 + +""" + +@pytest.mark.version('>=2.5') +def test_opt_left_join_08_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_left_join_09.py b/tests/functional/arno/optimizer/test_opt_left_join_09.py new file mode 100644 index 00000000..f21d75ee --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_left_join_09.py @@ -0,0 +1,83 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_left_join_09 +# title: LEFT OUTER JOIN with full match, but limited in ON and WHERE clause +# decription: TableX LEFT OUTER JOIN TableY with full match, but TableY results limited in ON clause. Which should result in partial NULL results for TableY, but these are not visible because they are filtered in the WHERE clause by "greater or equal than" operator. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_left_join_09 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Colors ( + ColorID INTEGER NOT NULL, + ColorName VARCHAR(20) +); + +CREATE TABLE Flowers ( + FlowerID INTEGER NOT NULL, + FlowerName VARCHAR(30), + ColorID INTEGER +); + +COMMIT; + +/* Value 0 represents -no value- */ +INSERT INTO Colors (ColorID, ColorName) VALUES (0, 'Not defined'); +INSERT INTO Colors (ColorID, ColorName) VALUES (1, 'Red'); +INSERT INTO Colors (ColorID, ColorName) VALUES (2, 'Yellow'); + +/* insert some data with references */ +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (1, 'Rose', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (2, 'Tulip', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (3, 'Gerbera', 0); + +COMMIT; + +/* Normally these indexes are created by the primary/foreign keys, + but we don't want to rely on them for this test */ +CREATE UNIQUE ASC INDEX PK_Colors ON Colors (ColorID); +CREATE UNIQUE ASC INDEX PK_Flowers ON Flowers (FlowerID); +CREATE ASC INDEX FK_Flowers_Colors ON Flowers (ColorID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + f.ColorID, + c1.ColorID, + c2.ColorID +FROM + Flowers f + LEFT JOIN Colors c1 ON (c1.ColorID = f.ColorID) AND + (c1.ColorID >= 1) + JOIN Colors c2 ON (c2.ColorID = f.ColorID);""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN JOIN (JOIN (F NATURAL, C1 INDEX (PK_COLORS)), C2 INDEX (PK_COLORS)) + + COLORID COLORID COLORID +============ ============ ============ + + 1 1 1 + 2 2 2 + 0 0 +""" + +@pytest.mark.version('>=2.0') +def test_opt_left_join_09_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_left_join_10.py b/tests/functional/arno/optimizer/test_opt_left_join_10.py new file mode 100644 index 00000000..2c9c9801 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_left_join_10.py @@ -0,0 +1,84 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_left_join_10 +# title: LEFT OUTER JOIN with IS NULL burried in WHERE clause +# decription: TableX LEFT OUTER JOIN TableY with no match, thus result should contain all NULLs for TableY references. WHERE clause contains IS NULL on a field which is also in a single segment index. +# The WHERE clause shouldn't be distributed to the joined table. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_left_join_10 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Colors ( + ColorID INTEGER NOT NULL, + ColorName VARCHAR(20) +); + +CREATE TABLE Flowers ( + FlowerID INTEGER NOT NULL, + FlowerName VARCHAR(30), + ColorID INTEGER +); + +COMMIT; + +/* Value 0 represents -no value- */ +INSERT INTO Colors (ColorID, ColorName) VALUES (0, 'Not defined'); +INSERT INTO Colors (ColorID, ColorName) VALUES (1, 'Red'); +INSERT INTO Colors (ColorID, ColorName) VALUES (2, 'Yellow'); + +/* insert some data with references */ +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (1, 'Rose', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (2, 'Tulip', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (3, 'Gerbera', 0); + +COMMIT; + +/* Normally these indexes are created by the primary/foreign keys, + but we don't want to rely on them for this test */ +CREATE UNIQUE ASC INDEX PK_Colors ON Colors (ColorID); +CREATE UNIQUE ASC INDEX PK_Flowers ON Flowers (FlowerID); +CREATE ASC INDEX FK_Flowers_Colors ON Flowers (ColorID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +/* LEFT JOIN should return all NULLs */ +SELECT + f.FlowerName, + c.ColorName +FROM + Flowers f + LEFT JOIN Colors c ON (1 = 0) +WHERE + c.ColorID IS NULL or c.ColorID = 1; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN JOIN (F NATURAL, C NATURAL) +FLOWERNAME COLORNAME +============================== ==================== + +Rose +Tulip +Gerbera +""" + +@pytest.mark.version('>=2.0') +def test_opt_left_join_10_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_left_join_11.py b/tests/functional/arno/optimizer/test_opt_left_join_11.py new file mode 100644 index 00000000..5edf5745 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_left_join_11.py @@ -0,0 +1,88 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_left_join_11 +# title: LEFT OUTER JOIN with STARTING WITH in WHERE clause +# decription: +# TableX LEFT OUTER JOIN TableY with no match, thus result should contain all NULLs for TableY references. +# WHERE clause contains STARTING WITH on a field which is also in a single segment index. +# The WHERE clause should be distributed to the joined table. +# +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_left_join_11 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + CREATE TABLE Colors ( + ColorID INTEGER NOT NULL, + ColorName VARCHAR(20) + ); + + CREATE TABLE Flowers ( + FlowerID INTEGER NOT NULL, + FlowerName VARCHAR(30), + ColorID INTEGER + ); + + COMMIT; + + /* Value 0 represents -no value- */ + INSERT INTO Colors (ColorID, ColorName) VALUES (0, 'Not defined'); + INSERT INTO Colors (ColorID, ColorName) VALUES (1, 'Red'); + INSERT INTO Colors (ColorID, ColorName) VALUES (2, 'Yellow'); + + /* insert some data with references */ + INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (1, 'Rose', 1); + INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (2, 'Tulip', 2); + INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (3, 'Gerbera', 0); + + COMMIT; + + /* Normally these indexes are created by the primary/foreign keys, + but we don't want to rely on them for this test */ + CREATE UNIQUE ASC INDEX PK_Colors ON Colors (ColorID); + CREATE UNIQUE ASC INDEX PK_Flowers ON Flowers (FlowerID); + CREATE ASC INDEX FK_Flowers_Colors ON Flowers (ColorID); + CREATE ASC INDEX I_Colors_Name ON Colors (ColorName); + + COMMIT; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set planonly; + SET PLAN ON; + -- WHERE clause should be distributed to LEFT JOIN ON clause + -- Avoid using index on c.ColorID with "+ 0" + SELECT + f.FlowerName, + c.ColorName + FROM + Flowers f + LEFT JOIN Colors c ON (c.ColorID + 0 = f.ColorID) + WHERE + c.ColorName STARTING WITH 'R' -- index I_Colors_Name exists for this field + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN JOIN (F NATURAL, C INDEX (I_COLORS_NAME)) + """ + +@pytest.mark.version('>=2.0') +def test_opt_left_join_11_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_left_join_12.py b/tests/functional/arno/optimizer/test_opt_left_join_12.py new file mode 100644 index 00000000..58d90fcf --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_left_join_12.py @@ -0,0 +1,84 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_left_join_12 +# title: LEFT OUTER JOIN with distribution CASE +# decription: TableX LEFT OUTER JOIN TableY with partial match. WHERE clause contains CASE expression based on TableY. +# The WHERE clause should not be distributed to the joined table. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_left_join_12 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Colors ( + ColorID INTEGER NOT NULL, + ColorName VARCHAR(20) +); + +CREATE TABLE Flowers ( + FlowerID INTEGER NOT NULL, + FlowerName VARCHAR(30), + ColorID INTEGER +); + +COMMIT; + +/* Value 0 represents -no value- */ +INSERT INTO Colors (ColorID, ColorName) VALUES (0, 'Not defined'); +INSERT INTO Colors (ColorID, ColorName) VALUES (1, 'Red'); +INSERT INTO Colors (ColorID, ColorName) VALUES (2, 'Yellow'); + +/* insert some data with references */ +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (1, 'Rose', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (2, 'Tulip', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (3, 'Gerbera', 0); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (4, 'Blanc', NULL); + +COMMIT; + +/* Normally these indexes are created by the primary/foreign keys, + but we don't want to rely on them for this test */ +CREATE UNIQUE ASC INDEX PK_Colors ON Colors (ColorID); +CREATE UNIQUE ASC INDEX PK_Flowers ON Flowers (FlowerID); +CREATE ASC INDEX FK_Flowers_Colors ON Flowers (ColorID); +CREATE ASC INDEX I_Colors_Name ON Colors (ColorName); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +/* LEFT JOIN should return all NULLs */ +SELECT + f.FlowerName, + c.ColorName +FROM + Flowers f + LEFT JOIN Colors c ON (c.ColorID = f.ColorID) +WHERE + CASE WHEN c.ColorID >= 0 THEN 0 ELSE 1 END = 1;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN JOIN (F NATURAL, C INDEX (PK_COLORS)) + +FLOWERNAME COLORNAME +============================== ==================== + +Blanc +""" + +@pytest.mark.version('>=2.0') +def test_opt_left_join_12_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_left_join_13.py b/tests/functional/arno/optimizer/test_opt_left_join_13.py new file mode 100644 index 00000000..5a96a0af --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_left_join_13.py @@ -0,0 +1,93 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_left_join_13 +# title: LEFT OUTER JOIN VIEW with full match +# decription: TableX LEFT OUTER JOIN ViewY with full match. Every reference from ViewY should have a value. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_left_join_13 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Colors ( + ColorID INTEGER NOT NULL, + ColorName VARCHAR(20) +); + +CREATE TABLE Flowers ( + FlowerID INTEGER NOT NULL, + FlowerName VARCHAR(30), + ColorID INTEGER +); + +CREATE VIEW VW_Colors ( + ColorID, + ColorName +) +AS +SELECT + c.ColorID, + c.ColorName +FROM + Colors c +; + +COMMIT; + +/* Value 0 represents -no value- */ +INSERT INTO Colors (ColorID, ColorName) VALUES (0, 'Not defined'); +INSERT INTO Colors (ColorID, ColorName) VALUES (1, 'Red'); +INSERT INTO Colors (ColorID, ColorName) VALUES (2, 'Yellow'); + +/* insert some data with references */ +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (1, 'Rose', 1); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (2, 'Tulip', 2); +INSERT INTO Flowers (FlowerID, FlowerName, ColorID) VALUES (3, 'Gerbera', 0); + +COMMIT; + +/* Normally these indexes are created by the primary/foreign keys, + but we don't want to rely on them for this test */ +CREATE UNIQUE ASC INDEX PK_Colors ON Colors (ColorID); +CREATE UNIQUE ASC INDEX PK_Flowers ON Flowers (FlowerID); +CREATE ASC INDEX FK_Flowers_Colors ON Flowers (ColorID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +/* LEFT JOIN should return all lookups */ +SELECT + f.FlowerName, + vc.ColorName +FROM + Flowers f + LEFT JOIN VW_Colors vc ON (vc.ColorID = f.ColorID); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN JOIN (F NATURAL, VC C INDEX (PK_COLORS)) +FLOWERNAME COLORNAME +============================== ==================== + +Rose Red +Tulip Yellow +Gerbera Not defined +""" + +@pytest.mark.version('>=2.0') +def test_opt_left_join_13_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_mixed_joins_01.py b/tests/functional/arno/optimizer/test_opt_mixed_joins_01.py new file mode 100644 index 00000000..5aa5c161 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_mixed_joins_01.py @@ -0,0 +1,111 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_mixed_joins_01 +# title: Mixed JOINS +# decription: Tables without indexes should be merged (when inner join) and those who can use a index, should use it. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_mixed_joins_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_100 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_1000 ( + ID INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_10 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 10) DO + BEGIN + INSERT INTO Table_10 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_100 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 100) DO + BEGIN + INSERT INTO Table_100 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_1000 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 1000) DO + BEGIN + INSERT INTO Table_1000 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_10; +EXECUTE PROCEDURE PR_FillTable_100; +EXECUTE PROCEDURE PR_FillTable_1000; + +COMMIT; + +CREATE UNIQUE ASC INDEX PK_Table_100 ON Table_100 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + Count(*) +FROM + Table_1000 t1000 + JOIN Table_100 t100 ON (t100.ID = t1000.ID) + JOIN Table_10 t10 ON (t10.ID = t100.ID); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN HASH (T1000 NATURAL, JOIN (T10 NATURAL, T100 INDEX (PK_TABLE_100))) + + COUNT +===================== + 10 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_mixed_joins_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_mixed_joins_02.py b/tests/functional/arno/optimizer/test_opt_mixed_joins_02.py new file mode 100644 index 00000000..48393aea --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_mixed_joins_02.py @@ -0,0 +1,111 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_mixed_joins_02 +# title: Mixed JOINS +# decription: Tables without indexes should be merged (when inner join) and those who can use a index, should use it. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_mixed_joins_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_10 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_100 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_1000 ( + ID INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_10 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 10) DO + BEGIN + INSERT INTO Table_10 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_100 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 100) DO + BEGIN + INSERT INTO Table_100 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_1000 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 1000) DO + BEGIN + INSERT INTO Table_1000 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_10; +EXECUTE PROCEDURE PR_FillTable_100; +EXECUTE PROCEDURE PR_FillTable_1000; + +COMMIT; + +CREATE UNIQUE ASC INDEX PK_Table_100 ON Table_100 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + Count(*) +FROM + Table_1000 t1000 + LEFT JOIN Table_100 t100 ON (t100.ID = t1000.ID) + JOIN Table_10 t10 ON (t10.ID = t100.ID); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN HASH (T10 NATURAL, JOIN (T1000 NATURAL, T100 INDEX (PK_TABLE_100))) + + COUNT +===================== + 10 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_mixed_joins_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_mixed_joins_03.py b/tests/functional/arno/optimizer/test_opt_mixed_joins_03.py new file mode 100644 index 00000000..75933208 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_mixed_joins_03.py @@ -0,0 +1,118 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_mixed_joins_03 +# title: Mixed JOINS +# decription: Tables without indexes should be merged (when inner join) and those who can use a index, should use it. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_mixed_joins_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_1 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_10 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_100 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_1000 ( + ID INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_10 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 10) DO + BEGIN + INSERT INTO Table_10 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_100 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 100) DO + BEGIN + INSERT INTO Table_100 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_1000 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 1000) DO + BEGIN + INSERT INTO Table_1000 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +INSERT INTO Table_1 (ID) VALUES (1); +EXECUTE PROCEDURE PR_FillTable_10; +EXECUTE PROCEDURE PR_FillTable_100; +EXECUTE PROCEDURE PR_FillTable_1000; + +COMMIT; + +CREATE UNIQUE ASC INDEX PK_Table_1 ON Table_1 (ID); +CREATE UNIQUE ASC INDEX PK_Table_100 ON Table_100 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + Count(*) +FROM + Table_10 t10 + LEFT JOIN Table_1 t1 ON (t1.ID = t10.ID) + JOIN Table_1000 t1000 ON (t1000.ID = t10.ID) + JOIN Table_100 t100 ON (t100.ID = t1000.ID); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN HASH (T1000 NATURAL, JOIN (JOIN (T10 NATURAL, T1 INDEX (PK_TABLE_1)), T100 INDEX (PK_TABLE_100))) + + COUNT +===================== + 10 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_mixed_joins_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_mixed_joins_04.py b/tests/functional/arno/optimizer/test_opt_mixed_joins_04.py new file mode 100644 index 00000000..3ba7e5b2 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_mixed_joins_04.py @@ -0,0 +1,124 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_mixed_joins_04 +# title: Mixed JOINS +# decription: Tables without indexes should be merged (when inner join) and those who can use a index, should use it. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_mixed_joins_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_1 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_10 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_50 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_100 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_1000 ( + ID INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_10 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 10) DO + BEGIN + INSERT INTO Table_10 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_100 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 100) DO + BEGIN + INSERT INTO Table_100 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_1000 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 1000) DO + BEGIN + INSERT INTO Table_1000 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +INSERT INTO Table_1 (ID) VALUES (1); +EXECUTE PROCEDURE PR_FillTable_10; +EXECUTE PROCEDURE PR_FillTable_100; +EXECUTE PROCEDURE PR_FillTable_1000; +INSERT INTO Table_50 SELECT ID FROM Table_100 t WHERE t.ID <= 50; + +COMMIT; + +CREATE UNIQUE ASC INDEX PK_Table_1 ON Table_1 (ID); +CREATE UNIQUE ASC INDEX PK_Table_50 ON Table_50 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + Count(*) +FROM + Table_10 t10 + LEFT JOIN Table_1 t1 ON (t1.ID = t10.ID) + JOIN Table_100 t100 ON (t100.ID = t10.ID) + LEFT JOIN Table_50 t50 ON (t50.ID = t100.ID) + JOIN Table_1000 t1000 ON (t1000.ID = t100.ID); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN HASH (T1000 NATURAL, JOIN (HASH (T100 NATURAL, JOIN (T10 NATURAL, T1 INDEX (PK_TABLE_1))), T50 INDEX (PK_TABLE_50))) + + COUNT +===================== + 10 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_mixed_joins_04_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_mixed_joins_05.py b/tests/functional/arno/optimizer/test_opt_mixed_joins_05.py new file mode 100644 index 00000000..e5d6b30a --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_mixed_joins_05.py @@ -0,0 +1,131 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_mixed_joins_05 +# title: Mixed JOINS +# decription: Tables without indexes should be merged (when inner join) and those who can use a index, should use it. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_mixed_joins_05 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_1 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_10 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_50 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_100 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_500 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_1000 ( + ID INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_10 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 10) DO + BEGIN + INSERT INTO Table_10 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_100 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 100) DO + BEGIN + INSERT INTO Table_100 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_1000 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 1000) DO + BEGIN + INSERT INTO Table_1000 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +INSERT INTO Table_1 (ID) VALUES (1); +EXECUTE PROCEDURE PR_FillTable_10; +EXECUTE PROCEDURE PR_FillTable_100; +EXECUTE PROCEDURE PR_FillTable_1000; +INSERT INTO Table_50 SELECT ID FROM Table_100 t WHERE t.ID <= 50; +INSERT INTO Table_500 SELECT ID FROM Table_1000 t WHERE t.ID <= 500; + +COMMIT; + +CREATE UNIQUE ASC INDEX PK_Table_1 ON Table_1 (ID); +CREATE UNIQUE ASC INDEX PK_Table_50 ON Table_50 (ID); +CREATE UNIQUE ASC INDEX PK_Table_500 ON Table_500 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + Count(*) +FROM + Table_500 t500 + LEFT JOIN Table_1 t1 ON (t1.ID = t500.ID) + JOIN Table_1000 t1000 ON (t1000.ID = t500.ID) + LEFT JOIN Table_10 t10 ON (t10.ID = t1000.ID) + JOIN Table_50 t50 ON (t50.ID = t10.ID) + JOIN Table_100 t100 ON (t100.ID = t500.ID); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN HASH (T100 NATURAL, JOIN (JOIN (HASH (T1000 NATURAL, JOIN (T500 NATURAL, T1 INDEX (PK_TABLE_1))), T10 NATURAL), T50 INDEX (PK_TABLE_50))) + + COUNT +===================== + 10 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_mixed_joins_05_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_mixed_joins_06.py b/tests/functional/arno/optimizer/test_opt_mixed_joins_06.py new file mode 100644 index 00000000..31a5787b --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_mixed_joins_06.py @@ -0,0 +1,130 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_mixed_joins_06 +# title: Mixed JOINS +# decription: Tables without indexes should be merged (when inner join) and those who can use a index, should use it. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_mixed_joins_06 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_1 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_10 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_50 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_100 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_500 ( + ID INTEGER NOT NULL +); + +CREATE TABLE Table_1000 ( + ID INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_10 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 10) DO + BEGIN + INSERT INTO Table_10 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_100 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 100) DO + BEGIN + INSERT INTO Table_100 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ + +CREATE PROCEDURE PR_FillTable_1000 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 1000) DO + BEGIN + INSERT INTO Table_1000 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +INSERT INTO Table_1 (ID) VALUES (1); +EXECUTE PROCEDURE PR_FillTable_10; +EXECUTE PROCEDURE PR_FillTable_100; +EXECUTE PROCEDURE PR_FillTable_1000; +INSERT INTO Table_50 SELECT ID FROM Table_100 t WHERE t.ID <= 50; +INSERT INTO Table_500 SELECT ID FROM Table_1000 t WHERE t.ID <= 500; + +COMMIT; + +CREATE UNIQUE ASC INDEX PK_Table_1 ON Table_1 (ID); +CREATE UNIQUE ASC INDEX PK_Table_50 ON Table_50 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + Count(*) +FROM + Table_500 t500 + LEFT JOIN Table_1 t1 ON (t1.ID = t500.ID) + JOIN Table_1000 t1000 ON (t1000.ID = t500.ID) + JOIN Table_10 t10 ON (t10.ID = t1000.ID) + JOIN Table_50 t50 ON (t50.ID = t10.ID) + JOIN Table_100 t100 ON (t100.ID = t500.ID); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN HASH (T1000 NATURAL, T100 NATURAL, T10 NATURAL, JOIN (JOIN (T500 NATURAL, T1 INDEX (PK_TABLE_1)), T50 INDEX (PK_TABLE_50))) + + COUNT +===================== + 10 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_mixed_joins_06_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_multi_index_selection_01.py b/tests/functional/arno/optimizer/test_opt_multi_index_selection_01.py new file mode 100644 index 00000000..c660e6b0 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_multi_index_selection_01.py @@ -0,0 +1,95 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_multi_index_selection_01 +# title: Unique index selection (multi segment) +# decription: Check if it will select only the index with the unique index when equal operator is performed on all segments in index. Also prefer ASC index above DESC unique index. +# Unique index together with equals operator will always be the best index to choose. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_multi_index_selection_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE SelectionTest ( + F1 INTEGER NOT NULL, + F2 INTEGER NOT NULL, + F3 INTEGER +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_SelectionTest +AS +DECLARE VARIABLE FillID INTEGER; +DECLARE VARIABLE FillF1 INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 1000) DO + BEGIN + FillF1 = (:FillID / 100); + INSERT INTO SelectionTest + (F1, F2, F3) + VALUES + (:FillF1, :FILLID - (:FILLF1 * 100), :FILLID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +/* Fill table with data */ +EXECUTE PROCEDURE PR_SelectionTest; + +COMMIT; + +/* Create indexes */ +CREATE UNIQUE ASC INDEX I_F1_F2_UNIQUE_ASC ON SelectionTest (F1, F2); +CREATE UNIQUE DESC INDEX I_F1_F2_UNIQUE_DESC ON SelectionTest (F1, F2); +CREATE ASC INDEX I_F1_F2_ASC ON SelectionTest (F1, F2); +CREATE DESC INDEX I_F1_F2_DESC ON SelectionTest (F1, F2); +CREATE ASC INDEX I_F2_F1_ASC ON SelectionTest (F2, F1); +CREATE DESC INDEX I_F2_F1_DESC ON SelectionTest (F2, F1); +CREATE ASC INDEX I_F1_F2_F3_ASC ON SelectionTest (F1, F2, F3); +CREATE ASC INDEX I_F2_F1_F3_ASC ON SelectionTest (F2, F1, F3); +CREATE ASC INDEX I_F3_F2_F1_ASC ON SelectionTest (F3, F2, F1); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + st.F1, st.F2, st.F3 +FROM + SelectionTest st +WHERE + st.F1 = 5 and + st.F2 = 50 and + st.F3 = 550; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (ST INDEX (I_F1_F2_UNIQUE_ASC)) + + F1 F2 F3 +============ ============ ============ + + 5 50 550 +""" + +@pytest.mark.version('>=2.0') +def test_opt_multi_index_selection_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_multi_index_selection_02.py b/tests/functional/arno/optimizer/test_opt_multi_index_selection_02.py new file mode 100644 index 00000000..3dc163f4 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_multi_index_selection_02.py @@ -0,0 +1,105 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_multi_index_selection_02 +# title: Best match index selection (multi segment) +# decription: Check if it will select the indexes which can be used. +# (Indexes with selectivity more than 10x the best are ignored) +# See SELECTIVITY_THRESHOLD_FACTOR in opt.cpp +# +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_multi_index_selection_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE SelectionTest ( + F1 INTEGER NOT NULL, + F2 INTEGER NOT NULL, + F3 INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_SelectionTest +AS +DECLARE VARIABLE FillID INTEGER; +DECLARE VARIABLE FillF1 INTEGER; +DECLARE VARIABLE FillF2 INTEGER; +DECLARE VARIABLE FillF3 INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 999) DO + BEGIN + FILLF1 = (FILLID / 10) * 10; + FILLF2 = FILLID - FILLF1; + FILLF3 = (FILLID / 150) * 150; + INSERT INTO SelectionTest + (F1, F2, F3) + VALUES + (:FILLF1, :FILLF2, :FILLF3); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +/* Fill table with data */ +EXECUTE PROCEDURE PR_SelectionTest; + +COMMIT; + +/* Create indexes */ +CREATE ASC INDEX I_F1_F2_ASC ON SelectionTest (F1, F2); +CREATE ASC INDEX I_F3_F2_ASC ON SelectionTest (F3, F2); +CREATE ASC INDEX I_F1_ASC ON SelectionTest (F1); +CREATE ASC INDEX I_F3_ASC ON SelectionTest (F3); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + st.F1, st.F2, st.F3 +FROM + SelectionTest st +WHERE + st.F1 = 150 and + st.F2 = 0 and + st.F3 = 150; + +/* +SELECT + i.RDB$INDEX_NAME AS INDEX_NAME, + CAST(i.RDB$STATISTICS AS NUMERIC(18,5)) AS SELECTIVITY +FROM + RDB$INDICES i +WHERE + i.RDB$RELATION_NAME = 'SELECTIONTEST'; +*/""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (ST INDEX (I_F1_F2_ASC)) + + F1 F2 F3 +============ ============ ============ + + 150 0 150 +""" + +@pytest.mark.version('>=2.0') +def test_opt_multi_index_selection_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_multi_index_selection_03.py b/tests/functional/arno/optimizer/test_opt_multi_index_selection_03.py new file mode 100644 index 00000000..be27f2c7 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_multi_index_selection_03.py @@ -0,0 +1,102 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_multi_index_selection_03 +# title: Best match index selection (multi segment) +# decription: Check if it will select the indexes which can be used. +# Full-segment-matched indexes have higher priority as partial matched indexes. +# (Indexes with selectivity more than 10x the best are ignored) +# See SELECTIVITY_THRESHOLD_FACTOR in opt.cpp +# +# All indexes have the same selectivity, because F1 is unique and included in every index. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_multi_index_selection_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE SelectionTest ( + F1 INTEGER NOT NULL, + F2 INTEGER NOT NULL, + F3 INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_SelectionTest +AS +DECLARE VARIABLE FillID INTEGER; +DECLARE VARIABLE FillF2 INTEGER; +DECLARE VARIABLE FillF3 INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 999) DO + BEGIN + FILLF2 = (FILLID / 10) * 10; + FILLF3 = FILLID - FILLF2; + INSERT INTO SelectionTest + (F1, F2, F3) + VALUES + (:FILLID, :FILLF2, :FILLF3); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +/* Fill table with data */ +EXECUTE PROCEDURE PR_SelectionTest; + +COMMIT; + +/* Create indexes */ +CREATE ASC INDEX I_F1_ASC ON SelectionTest (F1); +CREATE ASC INDEX I_F1_F2_ASC ON SelectionTest (F1, F2); +CREATE ASC INDEX I_F1_F2_F3_ASC ON SelectionTest (F1, F2, F3); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + st.F1, st.F2, st.F3 +FROM + SelectionTest st +WHERE + st.F1 = 555; + +/* +SELECT + i.RDB$INDEX_NAME AS INDEX_NAME, + CAST(i.RDB$STATISTICS AS NUMERIC(18,5)) AS SELECTIVITY +FROM + RDB$INDICES i +WHERE + i.RDB$RELATION_NAME = 'SELECTIONTEST'; +*/""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (ST INDEX (I_F1_ASC)) + + F1 F2 F3 +============ ============ ============ + + 555 550 5 +""" + +@pytest.mark.version('>=2.0') +def test_opt_multi_index_selection_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_multi_index_selection_04.py b/tests/functional/arno/optimizer/test_opt_multi_index_selection_04.py new file mode 100644 index 00000000..ae705cdf --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_multi_index_selection_04.py @@ -0,0 +1,94 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_multi_index_selection_04 +# title: Best match index selection (multi segment) +# decription: Check if it will select the index with the best selectivity and with the biggest segment match. +# 2 equals operators and 1 greater or equal operator and every index combination (up to two segments and only ASC) is made. The best here is using 2 indexes, except if the index for the "greater or equal" operator is much worser as the index used for the other two operators. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_multi_index_selection_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE SelectionTest ( + F1 INTEGER NOT NULL, + F2 INTEGER, + F3 INTEGER +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_SelectionTest +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 1000) DO + BEGIN + INSERT INTO SelectionTest + (F1, F2, F3) + VALUES + (:FillID, (:FILLID / 2) * 2, :FILLID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +/* Fill table with data */ +EXECUTE PROCEDURE PR_SelectionTest; + +COMMIT; + +/* Create indexes */ +CREATE UNIQUE ASC INDEX I_F1_UNIQUE_ASC ON SelectionTest (F1); +CREATE ASC INDEX I_F1_ASC ON SelectionTest (F1); +CREATE ASC INDEX I_F2_ASC ON SelectionTest (F2); +CREATE ASC INDEX I_F3_ASC ON SelectionTest (F3); +CREATE ASC INDEX I_F1_F2_ASC ON SelectionTest (F1, F2); +CREATE ASC INDEX I_F1_F3_ASC ON SelectionTest (F1, F3); +CREATE ASC INDEX I_F2_F1_ASC ON SelectionTest (F2, F1); +CREATE ASC INDEX I_F2_F3_ASC ON SelectionTest (F2, F3); +CREATE ASC INDEX I_F3_F1_ASC ON SelectionTest (F3, F1); +CREATE ASC INDEX I_F3_F2_ASC ON SelectionTest (F3, F2); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + st.F1, st.F2, st.F3 +FROM + SelectionTest st +WHERE + st.F1 >= 1 and + st.F2 = 100 and + st.F3 = 100; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (ST INDEX (I_F3_F2_ASC)) + + F1 F2 F3 +============ ============ ============ + + 100 100 100 +""" + +@pytest.mark.version('>=2.0') +def test_opt_multi_index_selection_04_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_multi_index_selection_05.py b/tests/functional/arno/optimizer/test_opt_multi_index_selection_05.py new file mode 100644 index 00000000..0d534a0d --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_multi_index_selection_05.py @@ -0,0 +1,100 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_multi_index_selection_05 +# title: Best match index selection (multi segment) +# decription: Check if it will select the index with the best selectivity and with the biggest segment match. +# 2 equals operators and 1 greater or equal operator and every index combination is made (only ASC). The best here is using 1 index (F2_F3_F1 or F3_F2_F1). +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_multi_index_selection_05 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE SelectionTest ( + F1 INTEGER NOT NULL, + F2 INTEGER, + F3 INTEGER +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_SelectionTest +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 1000) DO + BEGIN + INSERT INTO SelectionTest + (F1, F2, F3) + VALUES + (:FillID, (:FILLID / 2) * 2, :FILLID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +/* Fill table with data */ +EXECUTE PROCEDURE PR_SelectionTest; + +COMMIT; + +/* Create indexes */ +CREATE UNIQUE ASC INDEX I_F1_UNIQUE_ASC ON SelectionTest (F1); +CREATE ASC INDEX I_F1_ASC ON SelectionTest (F1); +CREATE ASC INDEX I_F2_ASC ON SelectionTest (F2); +CREATE ASC INDEX I_F3_ASC ON SelectionTest (F3); +CREATE ASC INDEX I_F1_F2_ASC ON SelectionTest (F1, F2); +CREATE ASC INDEX I_F1_F3_ASC ON SelectionTest (F1, F3); +CREATE ASC INDEX I_F1_F2_F3_ASC ON SelectionTest (F1, F2, F3); +CREATE ASC INDEX I_F1_F3_F2_ASC ON SelectionTest (F1, F3, F2); +CREATE ASC INDEX I_F2_F1_ASC ON SelectionTest (F2, F1); +CREATE ASC INDEX I_F2_F3_ASC ON SelectionTest (F2, F3); +CREATE ASC INDEX I_F2_F1_F3_ASC ON SelectionTest (F2, F1, F3); +CREATE ASC INDEX I_F2_F3_F1_ASC ON SelectionTest (F2, F3, F1); +CREATE ASC INDEX I_F3_F1_ASC ON SelectionTest (F3, F1); +CREATE ASC INDEX I_F3_F2_ASC ON SelectionTest (F3, F2); +CREATE ASC INDEX I_F3_F1_F2_ASC ON SelectionTest (F3, F1, F2); +CREATE ASC INDEX I_F3_F2_F1_ASC ON SelectionTest (F3, F2, F1); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + st.F1, st.F2, st.F3 +FROM + SelectionTest st +WHERE + st.F1 >= 1 and + st.F2 = 100 and + st.F3 = 100; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (ST INDEX (I_F3_F2_F1_ASC)) + + F1 F2 F3 +============ ============ ============ + + 100 100 100 +""" + +@pytest.mark.version('>=2.0') +def test_opt_multi_index_selection_05_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_multi_index_selection_07.py b/tests/functional/arno/optimizer/test_opt_multi_index_selection_07.py new file mode 100644 index 00000000..61ff7672 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_multi_index_selection_07.py @@ -0,0 +1,101 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_multi_index_selection_07 +# title: Best match index selection (multi segment) +# decription: Check if it will select the index with the best selectivity and match. +# IS NULL should also be used in compound indexes (Only in new index structure ODS > FB 1.5.1) +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_multi_index_selection_07 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE SelectionTest ( + F1 INTEGER NOT NULL, + F2 INTEGER +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_SelectionTest +AS +DECLARE VARIABLE FillID INTEGER; +DECLARE VARIABLE FillF2 INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 1000) DO + BEGIN + + IF (FillID <= 100) THEN + BEGIN + FillF2 = NULL; + END ELSE BEGIN + FillF2 = FillID - 100; + END + + INSERT INTO SelectionTest + (F1, F2) + VALUES + ((:FillID / 5) * 5, :FILLF2); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +/* Fill table with data */ +EXECUTE PROCEDURE PR_SelectionTest; + +COMMIT; + +/* Create indexes */ +CREATE ASC INDEX I_F1_ASC ON SelectionTest (F1); +CREATE DESC INDEX I_F1_DESC ON SelectionTest (F1); +CREATE ASC INDEX I_F2_ASC ON SelectionTest (F2); +CREATE DESC INDEX I_F2_DESC ON SelectionTest (F2); +CREATE ASC INDEX I_F1_F2_ASC ON SelectionTest (F1, F2); +CREATE DESC INDEX I_F1_F2_DESC ON SelectionTest (F1, F2); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + st.F1, st.F2 +FROM + SelectionTest st +WHERE + st.F1 = 55 and + st.F2 IS NULL; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (ST INDEX (I_F1_F2_ASC)) + + F1 F2 +============ ============ + + 55 + 55 + 55 + 55 + 55 +""" + +@pytest.mark.version('>=2.0') +def test_opt_multi_index_selection_07_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_multi_index_selection_08.py b/tests/functional/arno/optimizer/test_opt_multi_index_selection_08.py new file mode 100644 index 00000000..9de2a553 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_multi_index_selection_08.py @@ -0,0 +1,90 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_multi_index_selection_08 +# title: Best match index selection (multi segment) +# decription: STARTING WITH can also use a index and it should in fact be possible to use a compound index. Of course the STARTING WITH conjunction can only be bound the end (of all possible matches, same as >, >=, <, <=). +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_multi_index_selection_08 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE SelectionTest ( + F1 INTEGER NOT NULL, + F2 VARCHAR(18) +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_SelectionTest +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 1000) DO + BEGIN + INSERT INTO SelectionTest + (F1, F2) + VALUES + ((:FillID / 100) * 100, + :FILLID - ((:FillID / 100) * 100)); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +/* Fill table with data */ +EXECUTE PROCEDURE PR_SelectionTest; + +COMMIT; + +/* Create indexes */ +CREATE ASC INDEX I_F1_ASC ON SelectionTest (F1); +CREATE DESC INDEX I_F1_DESC ON SelectionTest (F1); +CREATE ASC INDEX I_F2_ASC ON SelectionTest (F2); +CREATE DESC INDEX I_F2_DESC ON SelectionTest (F2); +CREATE ASC INDEX I_F1_F2_ASC ON SelectionTest (F1, F2); +CREATE DESC INDEX I_F1_F2_DESC ON SelectionTest (F1, F2); +CREATE ASC INDEX I_F2_F1_ASC ON SelectionTest (F2, F1); +CREATE DESC INDEX I_F2_F1_DESC ON SelectionTest (F2, F1); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + st.F1, st.F2 +FROM + SelectionTest st +WHERE + st.F1 = 100 and + st.F2 STARTING WITH '55'; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (ST INDEX (I_F1_F2_ASC)) + + F1 F2 +============ ================== + + 100 55 +""" + +@pytest.mark.version('>=2.0') +def test_opt_multi_index_selection_08_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_selectivity_01.py b/tests/functional/arno/optimizer/test_opt_selectivity_01.py new file mode 100644 index 00000000..2fe28d7b --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_selectivity_01.py @@ -0,0 +1,111 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_selectivity_01 +# title: SELECTIVITY - SET STATISTICS +# decription: Check if selectivity is calculated correctly. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_selectivity_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE SelectivityTest ( + F1 INTEGER NOT NULL, + F2 INTEGER, + F5 INTEGER, + F50 INTEGER +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_SelectivityTest +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 1000) DO + BEGIN + INSERT INTO SelectivityTest + (F1, F2, F5, F50) + VALUES + (:FillID, + (:FILLID / 2) * 2, + (:FILLID / 5) * 5, + (:FILLID / 50) * 50); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +/* First create indexes */ +CREATE UNIQUE ASC INDEX I_F01_ASC ON SelectivityTest (F1); +CREATE UNIQUE DESC INDEX I_F01_DESC ON SelectivityTest (F1); +CREATE ASC INDEX I_F02_ASC ON SelectivityTest (F2); +CREATE DESC INDEX I_F02_DESC ON SelectivityTest (F2); +CREATE ASC INDEX I_F05_ASC ON SelectivityTest (F5); +CREATE DESC INDEX I_F05_DESC ON SelectivityTest (F5); +CREATE ASC INDEX I_F50_ASC ON SelectivityTest (F50); +CREATE DESC INDEX I_F50_DESC ON SelectivityTest (F50); + +COMMIT; + +/* Fill table with data */ +EXECUTE PROCEDURE PR_SelectivityTest; + +/* Update selectivity */ +SET STATISTICS INDEX I_F01_ASC; +SET STATISTICS INDEX I_F01_DESC; +SET STATISTICS INDEX I_F02_ASC; +SET STATISTICS INDEX I_F02_DESC; +SET STATISTICS INDEX I_F05_ASC; +SET STATISTICS INDEX I_F05_DESC; +SET STATISTICS INDEX I_F50_ASC; +SET STATISTICS INDEX I_F50_DESC; + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN OFF; +SELECT + CAST(RDB$INDEX_NAME AS VARCHAR(31)) AS INDEX_NAME, + CAST(RDB$STATISTICS AS NUMERIC(18,5)) AS SELECTIVITY +FROM + RDB$INDICES +WHERE + RDB$RELATION_NAME = 'SELECTIVITYTEST' +ORDER BY + RDB$INDEX_NAME; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """INDEX_NAME SELECTIVITY +=============================== ===================== + +I_F01_ASC 0.00100 +I_F01_DESC 0.00100 +I_F02_ASC 0.00200 +I_F02_DESC 0.00200 +I_F05_ASC 0.00498 +I_F05_DESC 0.00498 +I_F50_ASC 0.04762 +I_F50_DESC 0.04762 +""" + +@pytest.mark.version('>=2.0') +def test_opt_selectivity_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_selectivity_02.py b/tests/functional/arno/optimizer/test_opt_selectivity_02.py new file mode 100644 index 00000000..460f8269 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_selectivity_02.py @@ -0,0 +1,102 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_selectivity_02 +# title: SELECTIVITY - CREATE INDEX +# decription: Check if selectivity is calculated correctly. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_selectivity_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE SelectivityTest ( + F1 INTEGER NOT NULL, + F2 INTEGER, + F5 INTEGER, + F50 INTEGER +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_SelectivityTest +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 1000) DO + BEGIN + INSERT INTO SelectivityTest + (F1, F2, F5, F50) + VALUES + (:FillID, + (:FILLID / 2) * 2, + (:FILLID / 5) * 5, + (:FILLID / 50) * 50); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +/* Fill table with data */ +EXECUTE PROCEDURE PR_SelectivityTest; + +COMMIT; + + +/* Create indexes */ +CREATE UNIQUE ASC INDEX I_F01_ASC ON SelectivityTest (F1); +CREATE UNIQUE DESC INDEX I_F01_DESC ON SelectivityTest (F1); +CREATE ASC INDEX I_F02_ASC ON SelectivityTest (F2); +CREATE DESC INDEX I_F02_DESC ON SelectivityTest (F2); +CREATE ASC INDEX I_F05_ASC ON SelectivityTest (F5); +CREATE DESC INDEX I_F05_DESC ON SelectivityTest (F5); +CREATE ASC INDEX I_F50_ASC ON SelectivityTest (F50); +CREATE DESC INDEX I_F50_DESC ON SelectivityTest (F50); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN OFF; +SELECT + CAST(RDB$INDEX_NAME AS CHAR(31)) AS INDEX_NAME, + CAST(RDB$STATISTICS AS NUMERIC(18,5)) AS SELECTIVITY +FROM + RDB$INDICES +WHERE + RDB$RELATION_NAME = 'SELECTIVITYTEST' +ORDER BY + RDB$INDEX_NAME; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """INDEX_NAME SELECTIVITY +=============================== ===================== + +I_F01_ASC 0.00100 +I_F01_DESC 0.00100 +I_F02_ASC 0.00200 +I_F02_DESC 0.00200 +I_F05_ASC 0.00498 +I_F05_DESC 0.00498 +I_F50_ASC 0.04762 +I_F50_DESC 0.04762 +""" + +@pytest.mark.version('>=2.0') +def test_opt_selectivity_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_selectivity_03.py b/tests/functional/arno/optimizer/test_opt_selectivity_03.py new file mode 100644 index 00000000..b64492ea --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_selectivity_03.py @@ -0,0 +1,125 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_selectivity_03 +# title: SELECTIVITY - INDEX INACTIVE / ACTIVE +# decription: Check if selectivity is calculated correctly. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_selectivity_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE SelectivityTest ( + F1 INTEGER NOT NULL, + F2 INTEGER, + F5 INTEGER, + F50 INTEGER +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_SelectivityTest +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 1000) DO + BEGIN + INSERT INTO SelectivityTest + (F1, F2, F5, F50) + VALUES + (:FillID, + (:FILLID / 2) * 2, + (:FILLID / 5) * 5, + (:FILLID / 50) * 50); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +/* Create indexes */ +CREATE UNIQUE ASC INDEX I_F01_ASC ON SelectivityTest (F1); +CREATE UNIQUE DESC INDEX I_F01_DESC ON SelectivityTest (F1); +CREATE ASC INDEX I_F02_ASC ON SelectivityTest (F2); +CREATE DESC INDEX I_F02_DESC ON SelectivityTest (F2); +CREATE ASC INDEX I_F05_ASC ON SelectivityTest (F5); +CREATE DESC INDEX I_F05_DESC ON SelectivityTest (F5); +CREATE ASC INDEX I_F50_ASC ON SelectivityTest (F50); +CREATE DESC INDEX I_F50_DESC ON SelectivityTest (F50); + +COMMIT; + +/* Deactivate indexes */ +ALTER INDEX I_F01_ASC INACTIVE; +ALTER INDEX I_F01_DESC INACTIVE; +ALTER INDEX I_F02_ASC INACTIVE; +ALTER INDEX I_F02_DESC INACTIVE; +ALTER INDEX I_F05_ASC INACTIVE; +ALTER INDEX I_F05_DESC INACTIVE; +ALTER INDEX I_F50_ASC INACTIVE; +ALTER INDEX I_F50_DESC INACTIVE; + +COMMIT; + +/* Fill table with data */ +EXECUTE PROCEDURE PR_SelectivityTest; + +COMMIT; + +/* Activate indexes */ +ALTER INDEX I_F01_ASC ACTIVE; +ALTER INDEX I_F01_DESC ACTIVE; +ALTER INDEX I_F02_ASC ACTIVE; +ALTER INDEX I_F02_DESC ACTIVE; +ALTER INDEX I_F05_ASC ACTIVE; +ALTER INDEX I_F05_DESC ACTIVE; +ALTER INDEX I_F50_ASC ACTIVE; +ALTER INDEX I_F50_DESC ACTIVE; + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN OFF; +SELECT + CAST(RDB$INDEX_NAME AS CHAR(31)) AS INDEX_NAME, + CAST(RDB$STATISTICS AS NUMERIC(18,5)) AS SELECTIVITY +FROM + RDB$INDICES +WHERE + RDB$RELATION_NAME = 'SELECTIVITYTEST' +ORDER BY + RDB$INDEX_NAME; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """INDEX_NAME SELECTIVITY +=============================== ===================== + +I_F01_ASC 0.00100 +I_F01_DESC 0.00100 +I_F02_ASC 0.00200 +I_F02_DESC 0.00200 +I_F05_ASC 0.00498 +I_F05_DESC 0.00498 +I_F50_ASC 0.04762 +I_F50_DESC 0.04762 +""" + +@pytest.mark.version('>=2.0') +def test_opt_selectivity_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_single_index_selection_01.py b/tests/functional/arno/optimizer/test_opt_single_index_selection_01.py new file mode 100644 index 00000000..123aa1d3 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_single_index_selection_01.py @@ -0,0 +1,92 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_single_index_selection_01 +# title: Unique index selection (single segment) +# decription: Check if it will select only the index with the unique index when equal operator is performed on field in index. Also prefer ASC index above DESC unique index. +# Unique index together with equals operator will always be the best index to choose. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_single_index_selection_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE SelectionTest ( + F1 INTEGER NOT NULL, + F2 INTEGER, + F3 INTEGER +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_SelectionTest +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 1000) DO + BEGIN + INSERT INTO SelectionTest + (F1, F2, F3) + VALUES + (:FillID, :FILLID, :FILLID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +/* Fill table with data */ +EXECUTE PROCEDURE PR_SelectionTest; + +COMMIT; + +/* Create indexes */ +CREATE UNIQUE ASC INDEX I_F1_UNIQUE_ASC ON SelectionTest (F1); +CREATE UNIQUE DESC INDEX I_F1_UNIQUE_DESC ON SelectionTest (F1); +CREATE ASC INDEX I_F1_ASC ON SelectionTest (F1); +CREATE DESC INDEX I_F1_DESC ON SelectionTest (F1); +CREATE ASC INDEX I_F2_ASC ON SelectionTest (F2); +CREATE DESC INDEX I_F2_DESC ON SelectionTest (F2); +CREATE ASC INDEX I_F3_ASC ON SelectionTest (F3); +CREATE DESC INDEX I_F3_DESC ON SelectionTest (F3); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + st.F1, st.F2, st.F3 +FROM + SelectionTest st +WHERE + st.F1 = 500 and + st.F2 = 500 and + st.F3 = 500; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (ST INDEX (I_F1_UNIQUE_ASC)) + + F1 F2 F3 +============ ============ ============ + + 500 500 500 +""" + +@pytest.mark.version('>=2.0') +def test_opt_single_index_selection_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_single_index_selection_02.py b/tests/functional/arno/optimizer/test_opt_single_index_selection_02.py new file mode 100644 index 00000000..5038a388 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_single_index_selection_02.py @@ -0,0 +1,87 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_single_index_selection_02 +# title: Best match index selection (single segment) +# decription: Check if it will select the index with the best selectivity. +# UNIQUE index is the best and prefer ASC index. +# Only the equals conjunctions should be bound to the index, because it's the most selective. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_single_index_selection_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE SelectionTest ( + F1 INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_SelectionTest +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 1000) DO + BEGIN + INSERT INTO SelectionTest + (F1) + VALUES + (:FillID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +/* Fill table with data */ +EXECUTE PROCEDURE PR_SelectionTest; + +COMMIT; + +/* Create indexes */ +CREATE UNIQUE ASC INDEX I_F1_UNIQUE_ASC ON SelectionTest (F1); +CREATE UNIQUE DESC INDEX I_F1_UNIQUE_DESC ON SelectionTest (F1); +CREATE ASC INDEX I_F1_ASC ON SelectionTest (F1); +CREATE DESC INDEX I_F1_DESC ON SelectionTest (F1); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + st.F1 +FROM + SelectionTest st +WHERE + st.F1 > 1 and + st.F1 = 500 and + st.F1 < 1000; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (ST INDEX (I_F1_UNIQUE_ASC)) + + F1 +============ + + 500 +""" + +@pytest.mark.version('>=2.0') +def test_opt_single_index_selection_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_single_index_selection_03.py b/tests/functional/arno/optimizer/test_opt_single_index_selection_03.py new file mode 100644 index 00000000..e09c222a --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_single_index_selection_03.py @@ -0,0 +1,91 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_single_index_selection_03 +# title: Best match index selection (single segment) +# decription: +# Check if it will select the indexes which can be used. +# Also prefer ASC index above DESC unique index. +# Unique index isn't the only best to use here, because +# there's not a equals operator on it. +# +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_single_index_selection_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """CREATE TABLE SelectionTest ( + F1 INTEGER NOT NULL, + F2 INTEGER +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_SelectionTest +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 1000) DO + BEGIN + INSERT INTO SelectionTest + (F1, F2) + VALUES + (:FillID, (:FILLID / 2) * 2); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +/* Fill table with data */ +EXECUTE PROCEDURE PR_SelectionTest; + +COMMIT; + +/* Create indexes */ +CREATE UNIQUE ASC INDEX I_F1_UNIQUE_ASC ON SelectionTest (F1); +CREATE UNIQUE DESC INDEX I_F1_UNIQUE_DESC ON SelectionTest (F1); +CREATE ASC INDEX I_F2_ASC ON SelectionTest (F2); +CREATE DESC INDEX I_F2_DESC ON SelectionTest (F2); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + st.F1, st.F2 +FROM + SelectionTest st +WHERE + st.F2 = 100 and + st.F1 >= 1; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (ST INDEX (I_F2_ASC)) + + F1 F2 +============ ============ + 100 100 + 101 100 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_single_index_selection_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_single_index_selection_05.py b/tests/functional/arno/optimizer/test_opt_single_index_selection_05.py new file mode 100644 index 00000000..5689f479 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_single_index_selection_05.py @@ -0,0 +1,104 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_single_index_selection_05 +# title: Best match index selection (single segment) ASC and DESC +# decription: Check if it will select the indexes which can be used. Also prefer ASC index above DESC unique index. +# Index selectivity difference factor 20 and 200. +# +# selectivity = (1 / (count - duplicates)); +# +# best = 0.001 +# 999 / 20 = 49, 0..49 = 50 different values, = 0.02 +# 999 / 200 = 4, 0..4 = 5 different values, = 0.2 +# +# In FB2.0 there isn't a selectivity factor anymore, but index are based on there "total cost". +# The cost for index F1 and F2 together is the best total cost. +# +# Cost = (data-pages * totalSelectivity) + total index cost. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_single_index_selection_05 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE SelectionTest ( + F1 INTEGER NOT NULL, + F2 INTEGER NOT NULL, + F3 INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_SelectionTest +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 999) DO + BEGIN + INSERT INTO SelectionTest + (F1, F2, F3) + VALUES + (:FILLID, + (:FILLID / 20) * 20, + (:FILLID / 200) * 200); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +/* Fill table with data */ +EXECUTE PROCEDURE PR_SelectionTest; + +COMMIT; + +/* Create indexes */ +CREATE ASC INDEX I_F1_ASC ON SelectionTest (F1); +CREATE ASC INDEX I_F2_ASC ON SelectionTest (F2); +CREATE ASC INDEX I_F3_ASC ON SelectionTest (F3); +CREATE DESC INDEX I_F1_DESC ON SelectionTest (F1); +CREATE DESC INDEX I_F2_DESC ON SelectionTest (F2); +CREATE DESC INDEX I_F3_DESC ON SelectionTest (F3); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + st.F1, st.F2, st.F3 +FROM + SelectionTest st +WHERE + st.F1 = 200 and + st.F2 = 200 and + st.F3 = 200; + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (ST INDEX (I_F1_ASC)) + + F1 F2 F3 +============ ============ ============ + + 200 200 200 +""" + +@pytest.mark.version('>=3.0') +def test_opt_single_index_selection_05_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_single_index_selection_06.py b/tests/functional/arno/optimizer/test_opt_single_index_selection_06.py new file mode 100644 index 00000000..00372168 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_single_index_selection_06.py @@ -0,0 +1,91 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_single_index_selection_06 +# title: Best match index selection (single segment) +# decription: Check if it will select the index with the best selectivity. Also prefer ASC index above DESC unique index. +# Unique index isn't the best to use here (as the only one), because there's not a equals operator on it. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_single_index_selection_06 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE SelectionTest ( + F1 INTEGER NOT NULL, + F2 INTEGER, + F3 INTEGER +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_SelectionTest +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 1000) DO + BEGIN + INSERT INTO SelectionTest + (F1, F2, F3) + VALUES + (:FillID, (:FILLID / 2) * 2, :FILLID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +/* Fill table with data */ +EXECUTE PROCEDURE PR_SelectionTest; + +COMMIT; + +/* Create indexes */ +CREATE UNIQUE ASC INDEX I_F1_UNIQUE_ASC ON SelectionTest (F1); +CREATE ASC INDEX I_F1_ASC ON SelectionTest (F1); +CREATE DESC INDEX I_F1_DESC ON SelectionTest (F1); +CREATE ASC INDEX I_F2_ASC ON SelectionTest (F2); +CREATE DESC INDEX I_F2_DESC ON SelectionTest (F2); +CREATE ASC INDEX I_F3_ASC ON SelectionTest (F3); +CREATE DESC INDEX I_F3_DESC ON SelectionTest (F3); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + st.F1, st.F2, st.F3 +FROM + SelectionTest st +WHERE + st.F1 >= 1 and + st.F2 = 100 and + st.F3 = 100; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (ST INDEX (I_F3_ASC)) + + F1 F2 F3 +============ ============ ============ + + 100 100 100 +""" + +@pytest.mark.version('>=3.0') +def test_opt_single_index_selection_06_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_single_index_selection_07.py b/tests/functional/arno/optimizer/test_opt_single_index_selection_07.py new file mode 100644 index 00000000..b4c8cea6 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_single_index_selection_07.py @@ -0,0 +1,96 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_single_index_selection_07 +# title: Best match index selection (single segment) +# decription: Check if it will select the index with the best selectivity. +# IS NULL can also use a index, but 1 index is enough and prefer ASC index. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_single_index_selection_07 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE SelectionTest ( + F1 INTEGER NOT NULL, + F2 INTEGER +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_SelectionTest +AS +DECLARE VARIABLE FillID INTEGER; +DECLARE VARIABLE FillF2 INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 1000) DO + BEGIN + + IF (FillID <= 100) THEN + BEGIN + FillF2 = NULL; + END ELSE BEGIN + FillF2 = FillID - 100; + END + + INSERT INTO SelectionTest + (F1, F2) + VALUES + (:FillID, :FILLF2); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +/* Fill table with data */ +EXECUTE PROCEDURE PR_SelectionTest; + +COMMIT; + +/* Create indexes */ +CREATE UNIQUE ASC INDEX I_F1_UNIQUE_ASC ON SelectionTest (F1); +CREATE ASC INDEX I_F1_ASC ON SelectionTest (F1); +CREATE DESC INDEX I_F1_DESC ON SelectionTest (F1); +CREATE ASC INDEX I_F2_ASC ON SelectionTest (F2); +CREATE DESC INDEX I_F2_DESC ON SelectionTest (F2); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + st.F1, st.F2 +FROM + SelectionTest st +WHERE + st.F1 = 55 and + st.F2 IS NULL; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (ST INDEX (I_F1_UNIQUE_ASC)) + + F1 F2 +============ ============ + + 55 +""" + +@pytest.mark.version('>=2.0') +def test_opt_single_index_selection_07_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_single_index_selection_08.py b/tests/functional/arno/optimizer/test_opt_single_index_selection_08.py new file mode 100644 index 00000000..e8885ce3 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_single_index_selection_08.py @@ -0,0 +1,87 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_single_index_selection_08 +# title: Best match index selection (single segment) +# decription: Check if it will select the index with the best selectivity. +# STARTING WITH can also use a index, but 1 index is enough and prefer ASC index. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_single_index_selection_08 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE SelectionTest ( + F1 INTEGER NOT NULL, + F2 VARCHAR(18) +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_SelectionTest +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 1000) DO + BEGIN + INSERT INTO SelectionTest + (F1, F2) + VALUES + (:FillID, :FILLID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +/* Fill table with data */ +EXECUTE PROCEDURE PR_SelectionTest; + +COMMIT; + +/* Create indexes */ +CREATE UNIQUE ASC INDEX I_F1_UNIQUE_ASC ON SelectionTest (F1); +CREATE ASC INDEX I_F1_ASC ON SelectionTest (F1); +CREATE DESC INDEX I_F1_DESC ON SelectionTest (F1); +CREATE ASC INDEX I_F2_ASC ON SelectionTest (F2); +CREATE DESC INDEX I_F2_DESC ON SelectionTest (F2); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + st.F1, st.F2 +FROM + SelectionTest st +WHERE + st.F1 <= 49 and + st.F2 STARTING WITH '5'; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (ST INDEX (I_F2_ASC, I_F1_ASC)) + + F1 F2 +============ ================== + + 5 5 +""" + +@pytest.mark.version('>=2.0') +def test_opt_single_index_selection_08_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_single_index_selection_09.py b/tests/functional/arno/optimizer/test_opt_single_index_selection_09.py new file mode 100644 index 00000000..b349f50c --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_single_index_selection_09.py @@ -0,0 +1,85 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_single_index_selection_09 +# title: Best match index selection (single segment) OR +# decription: Check if it will select the index with the best selectivity. +# UNIQUE index is the best and prefer ASC index. Only 1 index per conjunction is enough. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_single_index_selection_09 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE SelectionTest ( + F1 INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_SelectionTest +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 1000) DO + BEGIN + INSERT INTO SelectionTest + (F1) + VALUES + (:FillID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +/* Fill table with data */ +EXECUTE PROCEDURE PR_SelectionTest; + +COMMIT; + +/* Create indexes */ +CREATE UNIQUE ASC INDEX I_F1_UNIQUE_ASC ON SelectionTest (F1); +CREATE UNIQUE DESC INDEX I_F1_UNIQUE_DESC ON SelectionTest (F1); +CREATE ASC INDEX I_F1_ASC ON SelectionTest (F1); +CREATE DESC INDEX I_F1_DESC ON SelectionTest (F1); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + st.F1 +FROM + SelectionTest st +WHERE + st.F1 = 1 or + st.F1 = 5000; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (ST INDEX (I_F1_UNIQUE_ASC, I_F1_UNIQUE_ASC)) + + F1 +============ + + 1 +""" + +@pytest.mark.version('>=2.0') +def test_opt_single_index_selection_09_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_single_index_selection_10.py b/tests/functional/arno/optimizer/test_opt_single_index_selection_10.py new file mode 100644 index 00000000..65737bb1 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_single_index_selection_10.py @@ -0,0 +1,85 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_single_index_selection_10 +# title: Best match index selection (single segment) OR +# decription: Check if it will select the index with the best selectivity. +# UNIQUE index is the best and prefer ASC index. 1 index per OR conjunction is enough and the equals conjunctions should be bound to the index, because it's the most selective. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_single_index_selection_10 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE SelectionTest ( + F1 INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_SelectionTest +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 1000) DO + BEGIN + INSERT INTO SelectionTest + (F1) + VALUES + (:FillID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +/* Fill table with data */ +EXECUTE PROCEDURE PR_SelectionTest; + +COMMIT; + +/* Create indexes */ +CREATE UNIQUE ASC INDEX I_F1_UNIQUE_ASC ON SelectionTest (F1); +CREATE UNIQUE DESC INDEX I_F1_UNIQUE_DESC ON SelectionTest (F1); +CREATE ASC INDEX I_F1_ASC ON SelectionTest (F1); +CREATE DESC INDEX I_F1_DESC ON SelectionTest (F1); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + st.F1 +FROM + SelectionTest st +WHERE + st.F1 = 5000 or + (st.F1 >= 1 and st.F1 <= 1000 and st.F1 = 500); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (ST INDEX (I_F1_UNIQUE_ASC, I_F1_UNIQUE_ASC)) + + F1 +============ + + 500 +""" + +@pytest.mark.version('>=2.0') +def test_opt_single_index_selection_10_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_single_index_selection_11.py b/tests/functional/arno/optimizer/test_opt_single_index_selection_11.py new file mode 100644 index 00000000..a95386a1 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_single_index_selection_11.py @@ -0,0 +1,96 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_single_index_selection_11 +# title: Best match index selection (single segment) +# decription: Check if it will select the best index. +# IS NULL can return more records thus prefer equal. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_single_index_selection_11 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE SelectionTest ( + F1 INTEGER NOT NULL, + F2 INTEGER +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_SelectionTest +AS +DECLARE VARIABLE FillID INTEGER; +DECLARE VARIABLE FillF2 INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 1000) DO + BEGIN + + IF (FillID <= 100) THEN + BEGIN + FillF2 = NULL; + END ELSE BEGIN + FillF2 = FillID - 100; + END + + INSERT INTO SelectionTest + (F1, F2) + VALUES + (:FillID, :FILLF2); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +/* Fill table with data */ +EXECUTE PROCEDURE PR_SelectionTest; + +COMMIT; + +/* Create indexes */ +CREATE UNIQUE ASC INDEX I_F1_UNIQUE_ASC ON SelectionTest (F1); +CREATE ASC INDEX I_F1_ASC ON SelectionTest (F1); +CREATE DESC INDEX I_F1_DESC ON SelectionTest (F1); +CREATE ASC INDEX I_F2_ASC ON SelectionTest (F2); +CREATE DESC INDEX I_F2_DESC ON SelectionTest (F2); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + st.F1, st.F2 +FROM + SelectionTest st +WHERE + st.F2 IS NULL and + st.F1 = 55; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (ST INDEX (I_F1_UNIQUE_ASC)) + + F1 F2 +============ ============ + + 55 +""" + +@pytest.mark.version('>=2.0') +def test_opt_single_index_selection_11_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_sort_by_index_01.py b/tests/functional/arno/optimizer/test_opt_sort_by_index_01.py new file mode 100644 index 00000000..1520368a --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_sort_by_index_01.py @@ -0,0 +1,186 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_sort_by_index_01 +# title: ORDER BY ASC using index (unique) +# decription: ORDER BY X +# When a index can be used for sorting, use it. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_sort_by_index_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_100 ( + ID INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_100 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 100) DO + BEGIN + INSERT INTO Table_100 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_100; + +COMMIT; + +CREATE ASC INDEX PK_Table_100 ON Table_100 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + * +FROM + Table_100 t100 +ORDER BY + t100.ID ASC;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (T100 ORDER PK_TABLE_100) + + ID +============ + + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + + ID +============ + 21 + 22 + 23 + 24 + 25 + 26 + 27 + 28 + 29 + 30 + 31 + 32 + 33 + 34 + 35 + 36 + 37 + 38 + 39 + 40 + + ID +============ + 41 + 42 + 43 + 44 + 45 + 46 + 47 + 48 + 49 + 50 + 51 + 52 + 53 + 54 + 55 + 56 + 57 + 58 + 59 + 60 + + ID +============ + 61 + 62 + 63 + 64 + 65 + 66 + 67 + 68 + 69 + 70 + 71 + 72 + 73 + 74 + 75 + 76 + 77 + 78 + 79 + 80 + + ID +============ + 81 + 82 + 83 + 84 + 85 + 86 + 87 + 88 + 89 + 90 + 91 + 92 + 93 + 94 + 95 + 96 + 97 + 98 + 99 + 100 +""" + +@pytest.mark.version('>=2.0') +def test_opt_sort_by_index_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_sort_by_index_02.py b/tests/functional/arno/optimizer/test_opt_sort_by_index_02.py new file mode 100644 index 00000000..e655cd87 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_sort_by_index_02.py @@ -0,0 +1,186 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_sort_by_index_02 +# title: ORDER BY DESC using index (unique) +# decription: ORDER BY X +# When a index can be used for sorting, use it. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_sort_by_index_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_100 ( + ID INTEGER NOT NULL +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_100 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 1; + WHILE (FillID <= 100) DO + BEGIN + INSERT INTO Table_100 (ID) VALUES (:FillID); + FillID = FillID + 1; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_100; + +COMMIT; + +CREATE DESC INDEX PK_Table_100_DESC ON Table_100 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + * +FROM + Table_100 t100 +ORDER BY + t100.ID DESC;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (T100 ORDER PK_TABLE_100_DESC) + + ID +============ + + 100 + 99 + 98 + 97 + 96 + 95 + 94 + 93 + 92 + 91 + 90 + 89 + 88 + 87 + 86 + 85 + 84 + 83 + 82 + 81 + + ID +============ + 80 + 79 + 78 + 77 + 76 + 75 + 74 + 73 + 72 + 71 + 70 + 69 + 68 + 67 + 66 + 65 + 64 + 63 + 62 + 61 + + ID +============ + 60 + 59 + 58 + 57 + 56 + 55 + 54 + 53 + 52 + 51 + 50 + 49 + 48 + 47 + 46 + 45 + 44 + 43 + 42 + 41 + + ID +============ + 40 + 39 + 38 + 37 + 36 + 35 + 34 + 33 + 32 + 31 + 30 + 29 + 28 + 27 + 26 + 25 + 24 + 23 + 22 + 21 + + ID +============ + 20 + 19 + 18 + 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 +""" + +@pytest.mark.version('>=2.0') +def test_opt_sort_by_index_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_sort_by_index_03.py b/tests/functional/arno/optimizer/test_opt_sort_by_index_03.py new file mode 100644 index 00000000..17b3e7b7 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_sort_by_index_03.py @@ -0,0 +1,157 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_sort_by_index_03 +# title: ORDER BY ASC using index (non-unique) +# decription: ORDER BY X +# When a index can be used for sorting, use it. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_sort_by_index_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_66 ( + ID INTEGER +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_66 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 2147483647; + WHILE (FillID > 0) DO + BEGIN + INSERT INTO Table_66 (ID) VALUES (:FillID); + FillID = FillID / 2; + END + INSERT INTO Table_66 (ID) VALUES (NULL); + INSERT INTO Table_66 (ID) VALUES (0); + INSERT INTO Table_66 (ID) VALUES (NULL); + FillID = -2147483648; + WHILE (FillID < 0) DO + BEGIN + INSERT INTO Table_66 (ID) VALUES (:FillID); + FillID = FillID / 2; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_66; + +COMMIT; + +CREATE ASC INDEX I_Table_66_ASC ON Table_66 (ID); +CREATE DESC INDEX I_Table_66_DESC ON Table_66 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + ID +FROM + Table_66 t66 +ORDER BY + t66.ID ASC;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (T66 ORDER I_TABLE_66_ASC) + + ID +============ + + + -2147483648 + -1073741824 + -536870912 + -268435456 + -134217728 + -67108864 + -33554432 + -16777216 + -8388608 + -4194304 + -2097152 + -1048576 + -524288 + -262144 + -131072 + -65536 + -32768 + -16384 + + ID +============ + -8192 + -4096 + -2048 + -1024 + -512 + -256 + -128 + -64 + -32 + -16 + -8 + -4 + -2 + -1 + 0 + 1 + 3 + 7 + 15 + 31 + + ID +============ + 63 + 127 + 255 + 511 + 1023 + 2047 + 4095 + 8191 + 16383 + 32767 + 65535 + 131071 + 262143 + 524287 + 1048575 + 2097151 + 4194303 + 8388607 + 16777215 + 33554431 + + ID +============ + 67108863 + 134217727 + 268435455 + 536870911 + 1073741823 + 2147483647""" + +@pytest.mark.version('>=2.0') +def test_opt_sort_by_index_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_sort_by_index_04.py b/tests/functional/arno/optimizer/test_opt_sort_by_index_04.py new file mode 100644 index 00000000..76f47746 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_sort_by_index_04.py @@ -0,0 +1,159 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_sort_by_index_04 +# title: ORDER BY DESC using index (non-unique) +# decription: ORDER BY X +# When a index can be used for sorting, use it. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_sort_by_index_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_66 ( + ID INTEGER +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_66 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 2147483647; + WHILE (FillID > 0) DO + BEGIN + INSERT INTO Table_66 (ID) VALUES (:FillID); + FillID = FillID / 2; + END + INSERT INTO Table_66 (ID) VALUES (NULL); + INSERT INTO Table_66 (ID) VALUES (0); + INSERT INTO Table_66 (ID) VALUES (NULL); + FillID = -2147483648; + WHILE (FillID < 0) DO + BEGIN + INSERT INTO Table_66 (ID) VALUES (:FillID); + FillID = FillID / 2; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_66; + +COMMIT; + +CREATE ASC INDEX I_Table_66_ASC ON Table_66 (ID); +CREATE DESC INDEX I_Table_66_DESC ON Table_66 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + ID +FROM + Table_66 t66 +ORDER BY + t66.ID DESC;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (T66 ORDER I_TABLE_66_DESC) + + ID +============ + + 2147483647 + 1073741823 + 536870911 + 268435455 + 134217727 + 67108863 + 33554431 + 16777215 + 8388607 + 4194303 + 2097151 + 1048575 + 524287 + 262143 + 131071 + 65535 + 32767 + 16383 + 8191 + 4095 + + ID +============ + 2047 + 1023 + 511 + 255 + 127 + 63 + 31 + 15 + 7 + 3 + 1 + 0 + -1 + -2 + -4 + -8 + -16 + -32 + -64 + -128 + + ID +============ + -256 + -512 + -1024 + -2048 + -4096 + -8192 + -16384 + -32768 + -65536 + -131072 + -262144 + -524288 + -1048576 + -2097152 + -4194304 + -8388608 + -16777216 + -33554432 + -67108864 + -134217728 + + ID +============ + -268435456 + -536870912 + -1073741824 + -2147483648 + + +""" + +@pytest.mark.version('>=2.0') +def test_opt_sort_by_index_04_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_sort_by_index_05.py b/tests/functional/arno/optimizer/test_opt_sort_by_index_05.py new file mode 100644 index 00000000..e952dfa2 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_sort_by_index_05.py @@ -0,0 +1,83 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_sort_by_index_05 +# title: MAX() and DESC index (non-unique) +# decription: SELECT MAX(FieldX) FROM X +# When a index can be used for sorting, use it. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_sort_by_index_05 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_66 ( + ID INTEGER +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_66 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 2147483647; + WHILE (FillID > 0) DO + BEGIN + INSERT INTO Table_66 (ID) VALUES (:FillID); + FillID = FillID / 2; + END + INSERT INTO Table_66 (ID) VALUES (NULL); + INSERT INTO Table_66 (ID) VALUES (0); + INSERT INTO Table_66 (ID) VALUES (NULL); + FillID = -2147483648; + WHILE (FillID < 0) DO + BEGIN + INSERT INTO Table_66 (ID) VALUES (:FillID); + FillID = FillID / 2; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_66; + +COMMIT; + +CREATE ASC INDEX I_Table_66_ASC ON Table_66 (ID); +CREATE DESC INDEX I_Table_66_DESC ON Table_66 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + MAX(t66.ID) AS MAX_ID +FROM + Table_66 t66;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (T66 ORDER I_TABLE_66_DESC) + + MAX_ID +============ + + 2147483647 +""" + +@pytest.mark.version('>=2.0') +def test_opt_sort_by_index_05_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_sort_by_index_06.py b/tests/functional/arno/optimizer/test_opt_sort_by_index_06.py new file mode 100644 index 00000000..7933de37 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_sort_by_index_06.py @@ -0,0 +1,82 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_sort_by_index_06 +# title: MAX() and ASC index (non-unique) +# decription: SELECT MAX(FieldX) FROM X +# ASC index cannot be used for MAX() aggregate function. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_sort_by_index_06 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_66 ( + ID INTEGER +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_66 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 2147483647; + WHILE (FillID > 0) DO + BEGIN + INSERT INTO Table_66 (ID) VALUES (:FillID); + FillID = FillID / 2; + END + INSERT INTO Table_66 (ID) VALUES (NULL); + INSERT INTO Table_66 (ID) VALUES (0); + INSERT INTO Table_66 (ID) VALUES (NULL); + FillID = -2147483648; + WHILE (FillID < 0) DO + BEGIN + INSERT INTO Table_66 (ID) VALUES (:FillID); + FillID = FillID / 2; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_66; + +COMMIT; + +CREATE ASC INDEX I_Table_66_ASC ON Table_66 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + MAX(t66.ID) AS MAX_ID +FROM + Table_66 t66;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (T66 NATURAL) + + MAX_ID +============ + + 2147483647 +""" + +@pytest.mark.version('>=2.0') +def test_opt_sort_by_index_06_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_sort_by_index_07.py b/tests/functional/arno/optimizer/test_opt_sort_by_index_07.py new file mode 100644 index 00000000..dc0d156d --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_sort_by_index_07.py @@ -0,0 +1,83 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_sort_by_index_07 +# title: MIN() and ASC index (non-unique) +# decription: SELECT MIN(FieldX) FROM X +# When a index can be used for sorting, use it. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_sort_by_index_07 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_66 ( + ID INTEGER +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_66 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 2147483647; + WHILE (FillID > 0) DO + BEGIN + INSERT INTO Table_66 (ID) VALUES (:FillID); + FillID = FillID / 2; + END + INSERT INTO Table_66 (ID) VALUES (NULL); + INSERT INTO Table_66 (ID) VALUES (0); + INSERT INTO Table_66 (ID) VALUES (NULL); + FillID = -2147483648; + WHILE (FillID < 0) DO + BEGIN + INSERT INTO Table_66 (ID) VALUES (:FillID); + FillID = FillID / 2; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_66; + +COMMIT; + +CREATE ASC INDEX I_Table_66_ASC ON Table_66 (ID); +CREATE DESC INDEX I_Table_66_DESC ON Table_66 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + MIN(t66.ID) AS MIN_ID +FROM + Table_66 t66;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (T66 ORDER I_TABLE_66_ASC) + + MIN_ID +============ + + -2147483648 +""" + +@pytest.mark.version('>=2.0') +def test_opt_sort_by_index_07_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_sort_by_index_08.py b/tests/functional/arno/optimizer/test_opt_sort_by_index_08.py new file mode 100644 index 00000000..c56d49b2 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_sort_by_index_08.py @@ -0,0 +1,82 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_sort_by_index_08 +# title: MIN() and DESC index (non-unique) +# decription: SELECT MIN(FieldX) FROM X +# DESC index cannot be used for MIN() aggregate function. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_sort_by_index_08 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_66 ( + ID INTEGER +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_66 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 2147483647; + WHILE (FillID > 0) DO + BEGIN + INSERT INTO Table_66 (ID) VALUES (:FillID); + FillID = FillID / 2; + END + INSERT INTO Table_66 (ID) VALUES (NULL); + INSERT INTO Table_66 (ID) VALUES (0); + INSERT INTO Table_66 (ID) VALUES (NULL); + FillID = -2147483648; + WHILE (FillID < 0) DO + BEGIN + INSERT INTO Table_66 (ID) VALUES (:FillID); + FillID = FillID / 2; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_66; + +COMMIT; + +CREATE DESC INDEX I_Table_66_DESC ON Table_66 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + MIN(t66.ID) AS MIN_ID +FROM + Table_66 t66;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (T66 NATURAL) + + MIN_ID +============ + + -2147483648 +""" + +@pytest.mark.version('>=2.0') +def test_opt_sort_by_index_08_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_sort_by_index_09.py b/tests/functional/arno/optimizer/test_opt_sort_by_index_09.py new file mode 100644 index 00000000..d6224dca --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_sort_by_index_09.py @@ -0,0 +1,117 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_sort_by_index_09 +# title: ORDER BY ASC using index (non-unique) +# decription: ORDER BY X +# If WHERE clause is present it should also use index if possible. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_sort_by_index_09 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """ + create table table_66 (id integer); + commit; + set term ^ ; + create procedure pr_filltable_66 as + declare fillid integer; + begin + fillid = 2147483647; + while (fillid > 0) do + begin + insert into table_66 (id) values (:fillid); + fillid = fillid / 2; + end + insert into table_66 (id) values (null); + insert into table_66 (id) values (0); + insert into table_66 (id) values (null); + fillid = -2147483648; + while (fillid < 0) do + begin + insert into table_66 (id) values (:fillid); + fillid = fillid / 2; + end + end + ^ + set term ; ^ + commit; + + execute procedure pr_filltable_66; + commit; + + create asc index i_table_66_asc on table_66 (id); + create desc index i_table_66_desc on table_66 (id); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Queries with RANGE index scan now have in the plan only "ORDER" + -- clause (index navigation) without bitmap building. + -- See: http://tracker.firebirdsql.org/browse/CORE-1550 + -- ("the same index should never appear in both ORDER and INDEX parts of the same plan item") + + -- ::::::::::::::::::::::::::::::::::::::::::::::: + -- do *NOT* use SET E`XPLAIN untill extremely need. + -- Always consult with Dmitry before doing this! + -- ::::::::::::::::::::::::::::::::::::::::::::::: + + set plan on; + + select id as id_asc + from table_66 t66 + where t66.id between -20 and 20 + order by t66.id asc; + + select id as id_desc + from table_66 t66 + where t66.id between -20 and 20 + order by t66.id desc; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (T66 ORDER I_TABLE_66_ASC) + ID_ASC + -16 + -8 + -4 + -2 + -1 + 0 + 1 + 3 + 7 + 15 + + PLAN (T66 ORDER I_TABLE_66_DESC) + ID_DESC + 15 + 7 + 3 + 1 + 0 + -1 + -2 + -4 + -8 + -16 + """ + +@pytest.mark.version('>=3.0') +def test_opt_sort_by_index_09_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_sort_by_index_10.py b/tests/functional/arno/optimizer/test_opt_sort_by_index_10.py new file mode 100644 index 00000000..384ac0b5 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_sort_by_index_10.py @@ -0,0 +1,82 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_sort_by_index_10 +# title: ORDER BY ASC using index (multi) +# decription: ORDER BY X, Y +# When more fields are given in ORDER BY clause try to use a compound index. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_sort_by_index_10 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """ + recreate table test_idx ( + id1 integer, + id2 integer + ); + insert into test_idx(id1, id2) + select (r/10)*10, r - (r/10)*10 + from (select row_number()over() r from rdb$types rows 50); + insert into test_idx (id1, id2) values (0, null); + insert into test_idx (id1, id2) values (null, 0); + insert into test_idx (id1, id2) values (null, null); + commit; + + create asc index idx_id1_asc on test_idx(id1); + create desc index idx_id1_desc on test_idx(id1); + create asc index idx_id2_asc on test_idx(id2); + create desc index idx_id2_desc on test_idx(id2); + create asc index idx_id1_id2_asc on test_idx(id1, id2); + create desc index idx_id1_id2_desc on test_idx(id1, id2); + create asc index idx_id2_id1_asc on test_idx(id2, id1); + create desc index idx_id2_id1_desc on test_idx(id2, id1); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Queries with RANGE index scan now have in the plan only "ORDER" + -- clause (index navigation) without bitmap building. + -- See: http://tracker.firebirdsql.org/browse/CORE-1550 + -- ("the same index should never appear in both ORDER and INDEX parts of the same plan item") + + set plan on; + select t.id1, t.id2 + from test_idx t + where t.id1 = 40 ----------------- --- must navigate through the leaf level of idx_id1_id2_asc, *without* bitmap! + order by t.id1 asc, t.id2 asc; ---/ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (T ORDER IDX_ID1_ID2_ASC) + + ID1 ID2 + 40 0 + 40 1 + 40 2 + 40 3 + 40 4 + 40 5 + 40 6 + 40 7 + 40 8 + 40 9 + """ + +@pytest.mark.version('>=3.0') +def test_opt_sort_by_index_10_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_sort_by_index_11.py b/tests/functional/arno/optimizer/test_opt_sort_by_index_11.py new file mode 100644 index 00000000..2427dcc1 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_sort_by_index_11.py @@ -0,0 +1,209 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_sort_by_index_11 +# title: ORDER BY ASC using index (multi) +# decription: +# ORDER BY X, Y +# When more fields are given in ORDER BY clause try to use a compound index. +# +# Refactored 26-feb-2016: use common code for 2.5 and 3.0 with checking that +# actual plan matches expected one that is defined in differ variables: plan_25 & plan_30. +# If actual plan will differ from expected message about this will contain BOTH plans +# (actual and expected), otherwise only text about matching will appear - but NO plan content +# because it depends on FB version. +# +# Checked on WI-V2.5.6.26970 +# 3.0.0.32358 -- plan was invalid +# 3.0.2.32708, 4.0.0.572 -- changed expected plan string after letter from dimitr, 21-mar-2017 09:08 +# +# 22.12.2019. +# 1. Denied from common code for all major versions, it was a bad idea: we need EXPLAINED PLAN here +# and this set of rows must be displayed explicitly, without just showing brief result of comparison. +# For this reason separate sections for each majoer FB version was returned. +# 2. Added several other statements in order to have more different plans. +# Checked on: +# 4.0.0.1693 SS: 1.283s. +# 3.0.5.33215 SS: 0.664s. +# 2.5.9.27149 SC: 0.282s. +# +# 25.07.2020: removed section for 4.0 because expected size must be equal in both major FB version, as it is given for 3.0. +# (letter from dimitr, 25.07.2020 12:42). Checked on 3.0.7.33348, 4.0.0.2119 +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter procedure sp_fill_data as begin end; + recreate table test ( + id1 int, + id2 int + ); + + set term ^; + create or alter procedure sp_fill_data + as + declare x int; + declare y int; + begin + x = 1; + while (x <= 50) do + begin + y = (x / 10) * 10; + insert into test(id1, id2) values(:y, :x - :y); + x = x + 1; + end + insert into test (id1, id2) values (0, null); + insert into test (id1, id2) values (null, 0); + insert into test (id1, id2) values (null, null); + end + ^ + set term ;^ + commit; + + execute procedure sp_fill_data; + commit; + + create asc index test_id1_asc on test (id1); + create desc index test_id1_des on test (id1); + + create asc index test_id2_asc on test (id2); + create desc index test_id2_des on test (id2); + + create asc index test_id1_id2_asc on test (id1, id2); + create desc index test_id1_id2_des on test (id1, id2); + + create asc index test_id2_id1_asc on test (id2, id1); + create desc index test_id2_id1_des on test (id2, id1); + commit; + + set explain on; + set planonly; + + select t.id2, t.id1 + from test t + where t.id1 = 30 and t.id2 >= 5 + order by t.id2 asc, t.id1 asc + ; + + select t.id2, t.id1 + from test t + where t.id1 = 30 and t.id2 <= 5 + order by t.id2 desc, t.id1 desc + ; + + select t.id2, t.id1 + from test t + where t.id1 >= 30 and t.id2 = 5 + order by t.id2 asc, t.id1 asc + ; + + select t.id2, t.id1 + from test t + where t.id1 <= 30 and t.id2 = 5 + order by t.id2 desc, t.id1 desc + ; + + + + select t.id2, t.id1 + from test t + where t.id1 <= 30 and t.id2 <= 5 + order by t.id2 asc, t.id1 asc + ; + + select t.id2, t.id1 + from test t + where t.id1 <= 30 and t.id2 <= 5 + order by t.id2 desc, t.id1 desc + ; + + select t.id2, t.id1 + from test t + where t.id1 >= 30 and t.id2 >= 5 + order by t.id2 asc, t.id1 asc + ; + + select t.id2, t.id1 + from test t + where t.id1 >= 30 and t.id2 >= 5 + order by t.id2 desc, t.id1 desc + ; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Select Expression + -> Sort (record length: 36, key length: 16) + -> Filter + -> Table "TEST" as "T" Access By ID + -> Bitmap + -> Index "TEST_ID1_ID2_ASC" Range Scan (lower bound: 2/2, upper bound: 1/2) + + Select Expression + -> Sort (record length: 36, key length: 16) + -> Filter + -> Table "TEST" as "T" Access By ID + -> Bitmap + -> Index "TEST_ID1_ID2_ASC" Range Scan (lower bound: 1/2, upper bound: 2/2) + + Select Expression + -> Filter + -> Table "TEST" as "T" Access By ID + -> Index "TEST_ID2_ID1_ASC" Range Scan (lower bound: 2/2, upper bound: 1/2) + + Select Expression + -> Filter + -> Table "TEST" as "T" Access By ID + -> Index "TEST_ID2_ID1_DES" Range Scan (lower bound: 2/2, upper bound: 1/2) + + Select Expression + -> Filter + -> Table "TEST" as "T" Access By ID + -> Index "TEST_ID2_ID1_ASC" Range Scan (upper bound: 1/2) + -> Bitmap + -> Index "TEST_ID1_ASC" Range Scan (upper bound: 1/1) + + Select Expression + -> Filter + -> Table "TEST" as "T" Access By ID + -> Index "TEST_ID2_ID1_DES" Range Scan (lower bound: 1/2) + -> Bitmap + -> Index "TEST_ID1_ASC" Range Scan (upper bound: 1/1) + + Select Expression + -> Filter + -> Table "TEST" as "T" Access By ID + -> Index "TEST_ID2_ID1_ASC" Range Scan (lower bound: 1/2) + -> Bitmap + -> Index "TEST_ID1_ASC" Range Scan (lower bound: 1/1) + + Select Expression + -> Filter + -> Table "TEST" as "T" Access By ID + -> Index "TEST_ID2_ID1_DES" Range Scan (upper bound: 1/2) + -> Bitmap + -> Index "TEST_ID1_ASC" Range Scan (lower bound: 1/1) + """ + +@pytest.mark.version('>=3.0') +def test_opt_sort_by_index_11_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_sort_by_index_12.py b/tests/functional/arno/optimizer/test_opt_sort_by_index_12.py new file mode 100644 index 00000000..2e19161f --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_sort_by_index_12.py @@ -0,0 +1,105 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_sort_by_index_12 +# title: ORDER BY ASC, DESC using index (multi) +# decription: ORDER BY X ASC, Y DESC +# When more fields are given in ORDER BY clause try to use a compound index, but look out for mixed directions. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_sort_by_index_12 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """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); +CREATE ASC INDEX I_Table_53_ID1_ID2_ASC ON Table_53 (ID1, ID2); +CREATE DESC INDEX I_Table_53_ID1_ID2_DESC ON Table_53 (ID1, ID2); +CREATE ASC INDEX I_Table_53_ID2_ID1_ASC ON Table_53 (ID2, ID1); +CREATE DESC INDEX I_Table_53_ID2_ID1_DESC ON Table_53 (ID2, ID1); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + t53.ID1, t53.ID2 +FROM + Table_53 t53 +WHERE + t53.ID1 BETWEEN 10 and 20 and + t53.ID2 <= 5 +ORDER BY + t53.ID1 ASC, t53.ID2 DESC;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN SORT (T53 INDEX (I_TABLE_53_ID2_ASC, I_TABLE_53_ID1_ASC)) + + ID1 ID2 +============ ============ + 10 5 + 10 4 + 10 3 + 10 2 + 10 1 + 10 0 + 20 5 + 20 4 + 20 3 + 20 2 + 20 1 + 20 0 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_sort_by_index_12_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_sort_by_index_13.py b/tests/functional/arno/optimizer/test_opt_sort_by_index_13.py new file mode 100644 index 00000000..63a68503 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_sort_by_index_13.py @@ -0,0 +1,82 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_sort_by_index_13 +# title: ORDER BY ASC using index (multi) +# decription: WHERE X = 1 ORDER BY Y ASC +# WHERE clause and ORDER BY nodes can sometimes be merged to get optimal result from compound index. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_sort_by_index_13 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """ + recreate table test_idx ( + id1 integer, + id2 integer + ); + insert into test_idx(id1, id2) + select (r/10)*10, r - (r/10)*10 + from (select row_number()over() r from rdb$types rows 50); + insert into test_idx (id1, id2) values (0, null); + insert into test_idx (id1, id2) values (null, 0); + insert into test_idx (id1, id2) values (null, null); + commit; + + create asc index idx_id1_asc on test_idx(id1); + create desc index idx_id1_desc on test_idx(id1); + create asc index idx_id2_asc on test_idx(id2); + create desc index idx_id2_desc on test_idx(id2); + create asc index idx_id1_id2_asc on test_idx(id1, id2); + create desc index idx_id1_id2_desc on test_idx(id1, id2); + create asc index idx_id2_id1_asc on test_idx(id2, id1); + create desc index idx_id2_id1_desc on test_idx(id2, id1); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Queries with RANGE index scan now have in the plan only "ORDER" + -- clause (index navigation) without bitmap building. + -- See: http://tracker.firebirdsql.org/browse/CORE-1550 + -- ("the same index should never appear in both ORDER and INDEX parts of the same plan item") + + set plan on; + select t.id1, t.id2 + from test_idx t + where t.id1 = 10 ---- --- must navigate through the leaf level of idx_id1_id2_asc, *without* bitmap! + order by t.id2 asc; ----/ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (T ORDER IDX_ID1_ID2_ASC) + + ID1 ID2 + 10 0 + 10 1 + 10 2 + 10 3 + 10 4 + 10 5 + 10 6 + 10 7 + 10 8 + 10 9 + """ + +@pytest.mark.version('>=3.0') +def test_opt_sort_by_index_13_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_sort_by_index_14.py b/tests/functional/arno/optimizer/test_opt_sort_by_index_14.py new file mode 100644 index 00000000..86339625 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_sort_by_index_14.py @@ -0,0 +1,159 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_sort_by_index_14 +# title: ORDER BY ASC NULLS FIRST using index +# decription: ORDER BY X ASC NULLS FIRST +# When a index can be used for sorting, use it. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_sort_by_index_14 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_66 ( + ID INTEGER +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_66 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 2147483647; + WHILE (FillID > 0) DO + BEGIN + INSERT INTO Table_66 (ID) VALUES (:FillID); + FillID = FillID / 2; + END + INSERT INTO Table_66 (ID) VALUES (NULL); + INSERT INTO Table_66 (ID) VALUES (0); + INSERT INTO Table_66 (ID) VALUES (NULL); + FillID = -2147483648; + WHILE (FillID < 0) DO + BEGIN + INSERT INTO Table_66 (ID) VALUES (:FillID); + FillID = FillID / 2; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_66; + +COMMIT; + +CREATE ASC INDEX I_Table_66_ASC ON Table_66 (ID); +CREATE DESC INDEX I_Table_66_DESC ON Table_66 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + ID +FROM + Table_66 t66 +ORDER BY + t66.ID ASC NULLS FIRST;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (T66 ORDER I_TABLE_66_ASC) + + ID +============ + + + + -2147483648 + -1073741824 + -536870912 + -268435456 + -134217728 + -67108864 + -33554432 + -16777216 + -8388608 + -4194304 + -2097152 + -1048576 + -524288 + -262144 + -131072 + -65536 + -32768 + -16384 + + ID +============ + -8192 + -4096 + -2048 + -1024 + -512 + -256 + -128 + -64 + -32 + -16 + -8 + -4 + -2 + -1 + 0 + 1 + 3 + 7 + 15 + 31 + + ID +============ + 63 + 127 + 255 + 511 + 1023 + 2047 + 4095 + 8191 + 16383 + 32767 + 65535 + 131071 + 262143 + 524287 + 1048575 + 2097151 + 4194303 + 8388607 + 16777215 + 33554431 + + ID +============ + 67108863 + 134217727 + 268435455 + 536870911 + 1073741823 + 2147483647 +""" + +@pytest.mark.version('>=2.0') +def test_opt_sort_by_index_14_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_sort_by_index_15.py b/tests/functional/arno/optimizer/test_opt_sort_by_index_15.py new file mode 100644 index 00000000..fe002c27 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_sort_by_index_15.py @@ -0,0 +1,159 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_sort_by_index_15 +# title: ORDER BY ASC NULLS LAST using index +# decription: ORDER BY X ASC NULLS LAST +# When a index can be used for sorting, use it. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_sort_by_index_15 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_66 ( + ID INTEGER +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_66 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 2147483647; + WHILE (FillID > 0) DO + BEGIN + INSERT INTO Table_66 (ID) VALUES (:FillID); + FillID = FillID / 2; + END + INSERT INTO Table_66 (ID) VALUES (NULL); + INSERT INTO Table_66 (ID) VALUES (0); + INSERT INTO Table_66 (ID) VALUES (NULL); + FillID = -2147483648; + WHILE (FillID < 0) DO + BEGIN + INSERT INTO Table_66 (ID) VALUES (:FillID); + FillID = FillID / 2; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_66; + +COMMIT; + +CREATE ASC INDEX I_Table_66_ASC ON Table_66 (ID); +CREATE DESC INDEX I_Table_66_DESC ON Table_66 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + ID +FROM + Table_66 t66 +ORDER BY + t66.ID ASC NULLS LAST;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN SORT (T66 NATURAL) + + ID +============ + -2147483648 + -1073741824 + -536870912 + -268435456 + -134217728 + -67108864 + -33554432 + -16777216 + -8388608 + -4194304 + -2097152 + -1048576 + -524288 + -262144 + -131072 + -65536 + -32768 + -16384 + -8192 + -4096 + + ID +============ + -2048 + -1024 + -512 + -256 + -128 + -64 + -32 + -16 + -8 + -4 + -2 + -1 + 0 + 1 + 3 + 7 + 15 + 31 + 63 + 127 + + ID +============ + 255 + 511 + 1023 + 2047 + 4095 + 8191 + 16383 + 32767 + 65535 + 131071 + 262143 + 524287 + 1048575 + 2097151 + 4194303 + 8388607 + 16777215 + 33554431 + 67108863 + 134217727 + + ID +============ + 268435455 + 536870911 + 1073741823 + 2147483647 + + + +""" + +@pytest.mark.version('>=3.0') +def test_opt_sort_by_index_15_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_sort_by_index_16.py b/tests/functional/arno/optimizer/test_opt_sort_by_index_16.py new file mode 100644 index 00000000..0bf64271 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_sort_by_index_16.py @@ -0,0 +1,159 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_sort_by_index_16 +# title: ORDER BY DESC NULLS FIRST using index +# decription: ORDER BY X DESC NULLS FIRST +# When a index can be used for sorting, use it. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_sort_by_index_16 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_66 ( + ID INTEGER +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_66 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 2147483647; + WHILE (FillID > 0) DO + BEGIN + INSERT INTO Table_66 (ID) VALUES (:FillID); + FillID = FillID / 2; + END + INSERT INTO Table_66 (ID) VALUES (NULL); + INSERT INTO Table_66 (ID) VALUES (0); + INSERT INTO Table_66 (ID) VALUES (NULL); + FillID = -2147483648; + WHILE (FillID < 0) DO + BEGIN + INSERT INTO Table_66 (ID) VALUES (:FillID); + FillID = FillID / 2; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_66; + +COMMIT; + +CREATE ASC INDEX I_Table_66_ASC ON Table_66 (ID); +CREATE DESC INDEX I_Table_66_DESC ON Table_66 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + ID +FROM + Table_66 t66 +ORDER BY + t66.ID DESC NULLS FIRST;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN SORT (T66 NATURAL) + + ID +============ + + + 2147483647 + 1073741823 + 536870911 + 268435455 + 134217727 + 67108863 + 33554431 + 16777215 + 8388607 + 4194303 + 2097151 + 1048575 + 524287 + 262143 + 131071 + 65535 + 32767 + 16383 + + ID +============ + 8191 + 4095 + 2047 + 1023 + 511 + 255 + 127 + 63 + 31 + 15 + 7 + 3 + 1 + 0 + -1 + -2 + -4 + -8 + -16 + -32 + + ID +============ + -64 + -128 + -256 + -512 + -1024 + -2048 + -4096 + -8192 + -16384 + -32768 + -65536 + -131072 + -262144 + -524288 + -1048576 + -2097152 + -4194304 + -8388608 + -16777216 + -33554432 + + ID +============ + -67108864 + -134217728 + -268435456 + -536870912 + -1073741824 + -2147483648 + +""" + +@pytest.mark.version('>=3.0') +def test_opt_sort_by_index_16_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_sort_by_index_17.py b/tests/functional/arno/optimizer/test_opt_sort_by_index_17.py new file mode 100644 index 00000000..b4b626b0 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_sort_by_index_17.py @@ -0,0 +1,159 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_sort_by_index_17 +# title: ORDER BY DESC NULLS LAST using index +# decription: ORDER BY X DESC NULLS LAST +# When a index can be used for sorting, use it. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_sort_by_index_17 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE Table_66 ( + ID INTEGER +); + +SET TERM ^^ ; +CREATE PROCEDURE PR_FillTable_66 +AS +DECLARE VARIABLE FillID INTEGER; +BEGIN + FillID = 2147483647; + WHILE (FillID > 0) DO + BEGIN + INSERT INTO Table_66 (ID) VALUES (:FillID); + FillID = FillID / 2; + END + INSERT INTO Table_66 (ID) VALUES (NULL); + INSERT INTO Table_66 (ID) VALUES (0); + INSERT INTO Table_66 (ID) VALUES (NULL); + FillID = -2147483648; + WHILE (FillID < 0) DO + BEGIN + INSERT INTO Table_66 (ID) VALUES (:FillID); + FillID = FillID / 2; + END +END +^^ +SET TERM ; ^^ + +COMMIT; + +EXECUTE PROCEDURE PR_FillTable_66; + +COMMIT; + +CREATE ASC INDEX I_Table_66_ASC ON Table_66 (ID); +CREATE DESC INDEX I_Table_66_DESC ON Table_66 (ID); + +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + ID +FROM + Table_66 t66 +ORDER BY + t66.ID DESC NULLS LAST;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """PLAN (T66 ORDER I_TABLE_66_DESC) + + ID +============ + + 2147483647 + 1073741823 + 536870911 + 268435455 + 134217727 + 67108863 + 33554431 + 16777215 + 8388607 + 4194303 + 2097151 + 1048575 + 524287 + 262143 + 131071 + 65535 + 32767 + 16383 + 8191 + 4095 + + ID +============ + 2047 + 1023 + 511 + 255 + 127 + 63 + 31 + 15 + 7 + 3 + 1 + 0 + -1 + -2 + -4 + -8 + -16 + -32 + -64 + -128 + + ID +============ + -256 + -512 + -1024 + -2048 + -4096 + -8192 + -16384 + -32768 + -65536 + -131072 + -262144 + -524288 + -1048576 + -2097152 + -4194304 + -8388608 + -16777216 + -33554432 + -67108864 + -134217728 + + ID +============ + -268435456 + -536870912 + -1073741824 + -2147483648 + + +""" + +@pytest.mark.version('>=2.0') +def test_opt_sort_by_index_17_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + 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 new file mode 100644 index 00000000..2dffb6bf --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_sort_by_index_18.py @@ -0,0 +1,99 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_sort_by_index_18 +# title: ORDER BY ASC using index (single) and WHERE clause +# decription: WHERE X = 1 ORDER BY Y +# Index for both X and Y should be used when available. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.arno.optimizer.opt_sort_by_index_18 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """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; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET PLAN ON; +SELECT + t53.ID2, + t53.ID1 +FROM + Table_53 t53 +WHERE + t53.ID1 = 30 +ORDER BY + t53.ID2 ASC;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """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 +""" + +@pytest.mark.version('>=2.0') +def test_opt_sort_by_index_18_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/arno/optimizer/test_opt_sort_by_index_19.py b/tests/functional/arno/optimizer/test_opt_sort_by_index_19.py new file mode 100644 index 00000000..72bdc810 --- /dev/null +++ b/tests/functional/arno/optimizer/test_opt_sort_by_index_19.py @@ -0,0 +1,99 @@ +#coding:utf-8 +# +# id: functional.arno.optimizer.opt_sort_by_index_19 +# title: ORDER BY ASC using index (multi) and WHERE clause +# decription: WHERE X = 1 ORDER BY Y +# When multi-segment index is present with X as first and Y as second this index can be used. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.arno.optimizer.opt_sort_by_index_19 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter procedure pr_filltable_53 as begin end; + commit; + + recreate table table_53 ( + id1 integer, + id2 integer + ); + + set term ^; + create or alter 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); + create asc index i_table_53_id1_id2_asc on table_53 (id1, id2); + create desc index i_table_53_id1_id2_desc on table_53 (id1, id2); + create asc index i_table_53_id2_id1_asc on table_53 (id2, id1); + create desc index i_table_53_id2_id1_desc on table_53 (id2, id1); + + commit; + + set planonly; + select + t53.id2, + t53.id1 + from table_53 t53 + where t53.id1 = 30 + order by t53.id2 asc + ; + -- Checked on WI-V3.0.0.32060: + -- PLAN (T53 ORDER I_TABLE_53_ID1_ID2_ASC) + -- Explained: + -- Select Expression + -- -> Filter + -- -> Table "TABLE_53" as "T53" Access By ID + -- -> Index "I_TABLE_53_ID1_ID2_ASC" Range Scan (partial match: 1/2) + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (T53 ORDER I_TABLE_53_ID1_ID2_ASC) + """ + +@pytest.mark.version('>=3.0') +def test_opt_sort_by_index_19_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/basic/__init__.py b/tests/functional/basic/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/basic/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/basic/db/__init__.py b/tests/functional/basic/db/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/basic/db/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/basic/db/test_01.py b/tests/functional/basic/db/test_01.py new file mode 100644 index 00000000..192f26c9 --- /dev/null +++ b/tests/functional/basic/db/test_01.py @@ -0,0 +1,76 @@ +#coding:utf-8 +# +# id: functional.basic.db.01 +# title: Empty DB - RDB$DATABASE content +# decription: Check the correct content of RDB$DATABASE for freh, empty database. +# tracker_id: +# min_versions: [] +# versions: 3.0, 4.0 +# qmid: functional.basic.db.db_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('RDB\\$SECURITY_CLASS[ ]+SQL\\$.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set blob all; + select * from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$DESCRIPTION + RDB$RELATION_ID 128 + RDB$SECURITY_CLASS SQL$362 + RDB$CHARACTER_SET_NAME NONE + RDB$LINGER + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [('RDB\\$SECURITY_CLASS[ ]+SQL\\$.*', '')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set list on; + set blob all; + select * from rdb$database; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + RDB$DESCRIPTION + RDB$RELATION_ID 128 + RDB$SECURITY_CLASS SQL$362 + RDB$CHARACTER_SET_NAME NONE + RDB$LINGER + RDB$SQL_SECURITY + """ + +@pytest.mark.version('>=4.0') +def test_01_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/functional/basic/db/test_02.py b/tests/functional/basic/db/test_02.py new file mode 100644 index 00000000..dfc451ed --- /dev/null +++ b/tests/functional/basic/db/test_02.py @@ -0,0 +1,666 @@ +#coding:utf-8 +# +# id: functional.basic.db.db_02 +# title: Empty DB - RDB$CHARACTER_SETS +# decription: Check the correct content of RDB$CHARACTER_SETS for empty database +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.basic.db.db_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('RDB\\$SECURITY_CLASS[ ]+SQL\\$.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set blob all; + set count on; + select * from rdb$character_sets order by rdb$character_set_id; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$CHARACTER_SET_NAME NONE + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME NONE + RDB$CHARACTER_SET_ID 0 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$182 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME OCTETS + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME OCTETS + RDB$CHARACTER_SET_ID 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$183 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME ASCII + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME ASCII + RDB$CHARACTER_SET_ID 2 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$184 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME UNICODE_FSS + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME UNICODE_FSS + RDB$CHARACTER_SET_ID 3 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 3 + RDB$SECURITY_CLASS SQL$185 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME UTF8 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME UTF8 + RDB$CHARACTER_SET_ID 4 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 4 + RDB$SECURITY_CLASS SQL$186 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME SJIS_0208 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME SJIS_0208 + RDB$CHARACTER_SET_ID 5 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 2 + RDB$SECURITY_CLASS SQL$187 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME EUCJ_0208 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME EUCJ_0208 + RDB$CHARACTER_SET_ID 6 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 2 + RDB$SECURITY_CLASS SQL$188 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME DOS737 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME DOS737 + RDB$CHARACTER_SET_ID 9 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$208 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME DOS437 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME DOS437 + RDB$CHARACTER_SET_ID 10 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$189 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME DOS850 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME DOS850 + RDB$CHARACTER_SET_ID 11 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$190 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME DOS865 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME DOS865 + RDB$CHARACTER_SET_ID 12 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$191 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME DOS860 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME DOS860 + RDB$CHARACTER_SET_ID 13 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$204 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME DOS863 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME DOS863 + RDB$CHARACTER_SET_ID 14 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$206 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME DOS775 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME DOS775 + RDB$CHARACTER_SET_ID 15 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$209 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME DOS858 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME DOS858 + RDB$CHARACTER_SET_ID 16 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$210 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME DOS862 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME DOS862 + RDB$CHARACTER_SET_ID 17 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$211 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME DOS864 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME DOS864 + RDB$CHARACTER_SET_ID 18 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$212 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME NEXT + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME NEXT + RDB$CHARACTER_SET_ID 19 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$220 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME ISO8859_1 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME ISO8859_1 + RDB$CHARACTER_SET_ID 21 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$192 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME ISO8859_2 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME ISO8859_2 + RDB$CHARACTER_SET_ID 22 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$193 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME ISO8859_3 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME ISO8859_3 + RDB$CHARACTER_SET_ID 23 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$194 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME ISO8859_4 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME ISO8859_4 + RDB$CHARACTER_SET_ID 34 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$195 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME ISO8859_5 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME ISO8859_5 + RDB$CHARACTER_SET_ID 35 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$196 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME ISO8859_6 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME ISO8859_6 + RDB$CHARACTER_SET_ID 36 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$197 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME ISO8859_7 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME ISO8859_7 + RDB$CHARACTER_SET_ID 37 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$198 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME ISO8859_8 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME ISO8859_8 + RDB$CHARACTER_SET_ID 38 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$199 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME ISO8859_9 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME ISO8859_9 + RDB$CHARACTER_SET_ID 39 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$200 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME ISO8859_13 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME ISO8859_13 + RDB$CHARACTER_SET_ID 40 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$201 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME KSC_5601 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME KSC_5601 + RDB$CHARACTER_SET_ID 44 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 2 + RDB$SECURITY_CLASS SQL$224 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME DOS852 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME DOS852 + RDB$CHARACTER_SET_ID 45 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$202 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME DOS857 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME DOS857 + RDB$CHARACTER_SET_ID 46 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$203 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME DOS861 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME DOS861 + RDB$CHARACTER_SET_ID 47 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$205 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME DOS866 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME DOS866 + RDB$CHARACTER_SET_ID 48 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$213 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME DOS869 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME DOS869 + RDB$CHARACTER_SET_ID 49 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$214 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME CYRL + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME CYRL + RDB$CHARACTER_SET_ID 50 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$207 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME WIN1250 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME WIN1250 + RDB$CHARACTER_SET_ID 51 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$215 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME WIN1251 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME WIN1251 + RDB$CHARACTER_SET_ID 52 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$216 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME WIN1252 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME WIN1252 + RDB$CHARACTER_SET_ID 53 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$217 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME WIN1253 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME WIN1253 + RDB$CHARACTER_SET_ID 54 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$218 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME WIN1254 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME WIN1254 + RDB$CHARACTER_SET_ID 55 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$219 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME BIG_5 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME BIG_5 + RDB$CHARACTER_SET_ID 56 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 2 + RDB$SECURITY_CLASS SQL$225 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME GB_2312 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME GB_2312 + RDB$CHARACTER_SET_ID 57 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 2 + RDB$SECURITY_CLASS SQL$226 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME WIN1255 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME WIN1255 + RDB$CHARACTER_SET_ID 58 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$221 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME WIN1256 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME WIN1256 + RDB$CHARACTER_SET_ID 59 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$222 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME WIN1257 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME WIN1257 + RDB$CHARACTER_SET_ID 60 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$223 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME KOI8R + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME KOI8R + RDB$CHARACTER_SET_ID 63 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$227 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME KOI8U + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME KOI8U + RDB$CHARACTER_SET_ID 64 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$228 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME WIN1258 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME WIN1258 + RDB$CHARACTER_SET_ID 65 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$229 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME TIS620 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME TIS620 + RDB$CHARACTER_SET_ID 66 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 1 + RDB$SECURITY_CLASS SQL$230 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME GBK + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME GBK + RDB$CHARACTER_SET_ID 67 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 2 + RDB$SECURITY_CLASS SQL$231 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME CP943C + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME CP943C + RDB$CHARACTER_SET_ID 68 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 2 + RDB$SECURITY_CLASS SQL$232 + RDB$OWNER_NAME SYSDBA + + RDB$CHARACTER_SET_NAME GB18030 + RDB$FORM_OF_USE + RDB$NUMBER_OF_CHARACTERS + RDB$DEFAULT_COLLATE_NAME GB18030 + RDB$CHARACTER_SET_ID 69 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BYTES_PER_CHARACTER 4 + RDB$SECURITY_CLASS SQL$233 + RDB$OWNER_NAME SYSDBA + + + Records affected: 52 + """ + +@pytest.mark.version('>=3.0') +def test_db_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/basic/db/test_03.py b/tests/functional/basic/db/test_03.py new file mode 100644 index 00000000..bf918ce9 --- /dev/null +++ b/tests/functional/basic/db/test_03.py @@ -0,0 +1,1843 @@ +#coding:utf-8 +# +# id: functional.basic.db.db_03 +# title: Empty DB - RDB$COLLATIONS +# decription: Check the correct content of RDB$COLLATIONS on empty DB. +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: functional.basic.db.db_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('RDB\\$SPECIFIC_ATTRIBUTES.*', ''), ('COLL-VERSION=\\d+\\.\\d+\\.\\d+\\.\\d+', ''), ('COLL-VERSION=\\d+\\.\\d+', ''), ('RDB\\$SECURITY_CLASS[ ]+SQL\\$.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set blob all; + set count on; + -- NB: rdb$collation_name is UNIQUE. + select * from rdb$collations order by rdb$collation_name; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + + RDB$COLLATION_NAME ASCII + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 2 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$236 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME BIG_5 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 56 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$368 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME BS_BA + RDB$COLLATION_ID 6 + RDB$CHARACTER_SET_ID 51 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$337 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME CP943C + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 68 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$379 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME CP943C_UNICODE + RDB$COLLATION_ID 1 + RDB$CHARACTER_SET_ID 68 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES 1d:1e9 + COLL-VERSION=153.88 + RDB$SECURITY_CLASS SQL$380 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME CS_CZ + RDB$COLLATION_ID 1 + RDB$CHARACTER_SET_ID 22 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$293 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME CYRL + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 50 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$321 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DA_DA + RDB$COLLATION_ID 1 + RDB$CHARACTER_SET_ID 21 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$274 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DB_CSY + RDB$COLLATION_ID 1 + RDB$CHARACTER_SET_ID 45 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$306 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DB_DAN865 + RDB$COLLATION_ID 2 + RDB$CHARACTER_SET_ID 12 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$271 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DB_DEU437 + RDB$COLLATION_ID 4 + RDB$CHARACTER_SET_ID 10 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$249 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DB_DEU850 + RDB$COLLATION_ID 2 + RDB$CHARACTER_SET_ID 11 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$260 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DB_ESP437 + RDB$COLLATION_ID 5 + RDB$CHARACTER_SET_ID 10 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$250 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DB_ESP850 + RDB$COLLATION_ID 3 + RDB$CHARACTER_SET_ID 11 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$261 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DB_FIN437 + RDB$COLLATION_ID 6 + RDB$CHARACTER_SET_ID 10 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$251 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DB_FRA437 + RDB$COLLATION_ID 7 + RDB$CHARACTER_SET_ID 10 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$252 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DB_FRA850 + RDB$COLLATION_ID 4 + RDB$CHARACTER_SET_ID 11 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$262 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DB_FRC850 + RDB$COLLATION_ID 1 + RDB$CHARACTER_SET_ID 11 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$259 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DB_FRC863 + RDB$COLLATION_ID 1 + RDB$CHARACTER_SET_ID 14 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$320 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DB_ITA437 + RDB$COLLATION_ID 8 + RDB$CHARACTER_SET_ID 10 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$253 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DB_ITA850 + RDB$COLLATION_ID 5 + RDB$CHARACTER_SET_ID 11 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$263 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DB_NLD437 + RDB$COLLATION_ID 9 + RDB$CHARACTER_SET_ID 10 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$254 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DB_NLD850 + RDB$COLLATION_ID 6 + RDB$CHARACTER_SET_ID 11 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$264 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DB_NOR865 + RDB$COLLATION_ID 3 + RDB$CHARACTER_SET_ID 12 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$272 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DB_PLK + RDB$COLLATION_ID 2 + RDB$CHARACTER_SET_ID 45 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$307 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DB_PTB850 + RDB$COLLATION_ID 7 + RDB$CHARACTER_SET_ID 11 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$265 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DB_PTG860 + RDB$COLLATION_ID 1 + RDB$CHARACTER_SET_ID 13 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$316 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DB_RUS + RDB$COLLATION_ID 1 + RDB$CHARACTER_SET_ID 50 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$322 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DB_SLO + RDB$COLLATION_ID 4 + RDB$CHARACTER_SET_ID 45 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$308 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DB_SVE437 + RDB$COLLATION_ID 10 + RDB$CHARACTER_SET_ID 10 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$255 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DB_SVE850 + RDB$COLLATION_ID 8 + RDB$CHARACTER_SET_ID 11 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$266 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DB_TRK + RDB$COLLATION_ID 1 + RDB$CHARACTER_SET_ID 46 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$314 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DB_UK437 + RDB$COLLATION_ID 11 + RDB$CHARACTER_SET_ID 10 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$256 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DB_UK850 + RDB$COLLATION_ID 9 + RDB$CHARACTER_SET_ID 11 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$267 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DB_US437 + RDB$COLLATION_ID 12 + RDB$CHARACTER_SET_ID 10 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$257 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DB_US850 + RDB$COLLATION_ID 10 + RDB$CHARACTER_SET_ID 11 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$268 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DE_DE + RDB$COLLATION_ID 6 + RDB$CHARACTER_SET_ID 21 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$279 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DOS437 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 10 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$245 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DOS737 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 9 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$324 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DOS775 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 15 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$325 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DOS850 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 11 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$258 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DOS852 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 45 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$305 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DOS857 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 46 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$313 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DOS858 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 16 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$326 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DOS860 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 13 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$315 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DOS861 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 47 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$317 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DOS862 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 17 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$327 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DOS863 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 14 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$319 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DOS864 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 18 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$328 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DOS865 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 12 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$269 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DOS866 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 48 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$329 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DOS869 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 49 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$330 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME DU_NL + RDB$COLLATION_ID 2 + RDB$CHARACTER_SET_ID 21 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$275 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME EN_UK + RDB$COLLATION_ID 12 + RDB$CHARACTER_SET_ID 21 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$285 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME EN_US + RDB$COLLATION_ID 14 + RDB$CHARACTER_SET_ID 21 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$286 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME ES_ES + RDB$COLLATION_ID 10 + RDB$CHARACTER_SET_ID 21 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES 1d:1e0 + DISABLE-COMPRESSIONS=1;SPECIALS-FIRST=1 + RDB$SECURITY_CLASS SQL$283 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME ES_ES_CI_AI + RDB$COLLATION_ID 17 + RDB$CHARACTER_SET_ID 21 + RDB$COLLATION_ATTRIBUTES 7 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES 1d:1e1 + DISABLE-COMPRESSIONS=1;SPECIALS-FIRST=1 + RDB$SECURITY_CLASS SQL$289 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME EUCJ_0208 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 6 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$244 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME FI_FI + RDB$COLLATION_ID 3 + RDB$CHARACTER_SET_ID 21 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$276 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME FR_CA + RDB$COLLATION_ID 5 + RDB$CHARACTER_SET_ID 21 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$278 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME FR_CA_CI_AI + RDB$COLLATION_ID 19 + RDB$CHARACTER_SET_ID 21 + RDB$COLLATION_ATTRIBUTES 7 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME FR_CA + RDB$SPECIFIC_ATTRIBUTES 1d:1e3 + SPECIALS-FIRST=1 + RDB$SECURITY_CLASS SQL$291 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME FR_FR + RDB$COLLATION_ID 4 + RDB$CHARACTER_SET_ID 21 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$277 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME FR_FR_CI_AI + RDB$COLLATION_ID 18 + RDB$CHARACTER_SET_ID 21 + RDB$COLLATION_ATTRIBUTES 7 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME FR_FR + RDB$SPECIFIC_ATTRIBUTES 1d:1e2 + SPECIALS-FIRST=1 + RDB$SECURITY_CLASS SQL$290 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME GB18030 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 69 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$381 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME GB18030_UNICODE + RDB$COLLATION_ID 1 + RDB$CHARACTER_SET_ID 69 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES 1d:1ea + COLL-VERSION=153.88 + RDB$SECURITY_CLASS SQL$382 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME GBK + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 67 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$377 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME GBK_UNICODE + RDB$COLLATION_ID 1 + RDB$CHARACTER_SET_ID 67 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES 1d:1e8 + COLL-VERSION=153.88 + RDB$SECURITY_CLASS SQL$378 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME GB_2312 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 57 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$369 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME ISO8859_1 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 21 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$273 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME ISO8859_13 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 40 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$303 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME ISO8859_2 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 22 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$292 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME ISO8859_3 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 23 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$296 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME ISO8859_4 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 34 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$297 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME ISO8859_5 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 35 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$298 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME ISO8859_6 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 36 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$299 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME ISO8859_7 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 37 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$300 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME ISO8859_8 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 38 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$301 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME ISO8859_9 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 39 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$302 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME ISO_HUN + RDB$COLLATION_ID 2 + RDB$CHARACTER_SET_ID 22 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$294 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME ISO_PLK + RDB$COLLATION_ID 3 + RDB$CHARACTER_SET_ID 22 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$295 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME IS_IS + RDB$COLLATION_ID 7 + RDB$CHARACTER_SET_ID 21 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$280 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME IT_IT + RDB$COLLATION_ID 8 + RDB$CHARACTER_SET_ID 21 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$281 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME KOI8R + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 63 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$370 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME KOI8R_RU + RDB$COLLATION_ID 1 + RDB$CHARACTER_SET_ID 63 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$371 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME KOI8U + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 64 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$372 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME KOI8U_UA + RDB$COLLATION_ID 1 + RDB$CHARACTER_SET_ID 64 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$373 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME KSC_5601 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 44 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$366 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME KSC_DICTIONARY + RDB$COLLATION_ID 1 + RDB$CHARACTER_SET_ID 44 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$367 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME LT_LT + RDB$COLLATION_ID 1 + RDB$CHARACTER_SET_ID 40 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$304 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME NEXT + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 19 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$354 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME NONE + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 0 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$234 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME NO_NO + RDB$COLLATION_ID 9 + RDB$CHARACTER_SET_ID 21 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$282 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME NXT_DEU + RDB$COLLATION_ID 2 + RDB$CHARACTER_SET_ID 19 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$356 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME NXT_ESP + RDB$COLLATION_ID 5 + RDB$CHARACTER_SET_ID 19 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$359 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME NXT_FRA + RDB$COLLATION_ID 3 + RDB$CHARACTER_SET_ID 19 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$357 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME NXT_ITA + RDB$COLLATION_ID 4 + RDB$CHARACTER_SET_ID 19 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$358 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME NXT_US + RDB$COLLATION_ID 1 + RDB$CHARACTER_SET_ID 19 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$355 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME OCTETS + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 1 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$235 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME PDOX_ASCII + RDB$COLLATION_ID 1 + RDB$CHARACTER_SET_ID 10 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$246 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME PDOX_CSY + RDB$COLLATION_ID 5 + RDB$CHARACTER_SET_ID 45 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$309 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME PDOX_CYRL + RDB$COLLATION_ID 2 + RDB$CHARACTER_SET_ID 50 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$323 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME PDOX_HUN + RDB$COLLATION_ID 7 + RDB$CHARACTER_SET_ID 45 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$311 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME PDOX_INTL + RDB$COLLATION_ID 2 + RDB$CHARACTER_SET_ID 10 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$247 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME PDOX_ISL + RDB$COLLATION_ID 1 + RDB$CHARACTER_SET_ID 47 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$318 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME PDOX_NORDAN4 + RDB$COLLATION_ID 1 + RDB$CHARACTER_SET_ID 12 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$270 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME PDOX_PLK + RDB$COLLATION_ID 6 + RDB$CHARACTER_SET_ID 45 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$310 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME PDOX_SLO + RDB$COLLATION_ID 8 + RDB$CHARACTER_SET_ID 45 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$312 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME PDOX_SWEDFIN + RDB$COLLATION_ID 3 + RDB$CHARACTER_SET_ID 10 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$248 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME PT_BR + RDB$COLLATION_ID 16 + RDB$CHARACTER_SET_ID 21 + RDB$COLLATION_ATTRIBUTES 7 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$288 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME PT_PT + RDB$COLLATION_ID 15 + RDB$CHARACTER_SET_ID 21 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$287 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME PXW_CSY + RDB$COLLATION_ID 1 + RDB$CHARACTER_SET_ID 51 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$332 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME PXW_CYRL + RDB$COLLATION_ID 1 + RDB$CHARACTER_SET_ID 52 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$341 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME PXW_GREEK + RDB$COLLATION_ID 1 + RDB$CHARACTER_SET_ID 54 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$351 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME PXW_HUN + RDB$COLLATION_ID 5 + RDB$CHARACTER_SET_ID 51 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$336 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME PXW_HUNDC + RDB$COLLATION_ID 2 + RDB$CHARACTER_SET_ID 51 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$333 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME PXW_INTL + RDB$COLLATION_ID 1 + RDB$CHARACTER_SET_ID 53 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$344 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME PXW_INTL850 + RDB$COLLATION_ID 2 + RDB$CHARACTER_SET_ID 53 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$345 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME PXW_NORDAN4 + RDB$COLLATION_ID 3 + RDB$CHARACTER_SET_ID 53 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$346 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME PXW_PLK + RDB$COLLATION_ID 3 + RDB$CHARACTER_SET_ID 51 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$334 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME PXW_SLOV + RDB$COLLATION_ID 4 + RDB$CHARACTER_SET_ID 51 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$335 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME PXW_SPAN + RDB$COLLATION_ID 4 + RDB$CHARACTER_SET_ID 53 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$347 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME PXW_SWEDFIN + RDB$COLLATION_ID 5 + RDB$CHARACTER_SET_ID 53 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$348 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME PXW_TURK + RDB$COLLATION_ID 1 + RDB$CHARACTER_SET_ID 55 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$353 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME SJIS_0208 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 5 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$243 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME SV_SV + RDB$COLLATION_ID 11 + RDB$CHARACTER_SET_ID 21 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$284 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME TIS620 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 66 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$375 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME TIS620_UNICODE + RDB$COLLATION_ID 1 + RDB$CHARACTER_SET_ID 66 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES 1d:1e7 + COLL-VERSION=153.88 + RDB$SECURITY_CLASS SQL$376 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME UCS_BASIC + RDB$COLLATION_ID 1 + RDB$CHARACTER_SET_ID 4 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$239 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME UNICODE + RDB$COLLATION_ID 2 + RDB$CHARACTER_SET_ID 4 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES 1d:1e4 + COLL-VERSION=153.88 + RDB$SECURITY_CLASS SQL$240 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME UNICODE_CI + RDB$COLLATION_ID 3 + RDB$CHARACTER_SET_ID 4 + RDB$COLLATION_ATTRIBUTES 3 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME UNICODE + RDB$SPECIFIC_ATTRIBUTES 1d:1e5 + COLL-VERSION=153.88 + RDB$SECURITY_CLASS SQL$241 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME UNICODE_CI_AI + RDB$COLLATION_ID 4 + RDB$CHARACTER_SET_ID 4 + RDB$COLLATION_ATTRIBUTES 7 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME UNICODE + RDB$SPECIFIC_ATTRIBUTES 1d:1e6 + COLL-VERSION=153.88 + RDB$SECURITY_CLASS SQL$242 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME UNICODE_FSS + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 3 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$237 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME UTF8 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 4 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$238 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME WIN1250 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 51 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$331 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME WIN1251 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 52 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$340 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME WIN1251_UA + RDB$COLLATION_ID 2 + RDB$CHARACTER_SET_ID 52 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$342 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME WIN1252 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 53 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$343 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME WIN1253 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 54 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$350 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME WIN1254 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 55 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$352 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME WIN1255 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 58 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$360 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME WIN1256 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 59 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$361 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME WIN1257 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 60 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$362 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME WIN1257_EE + RDB$COLLATION_ID 1 + RDB$CHARACTER_SET_ID 60 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$363 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME WIN1257_LT + RDB$COLLATION_ID 2 + RDB$CHARACTER_SET_ID 60 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$364 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME WIN1257_LV + RDB$COLLATION_ID 3 + RDB$CHARACTER_SET_ID 60 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$365 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME WIN1258 + RDB$COLLATION_ID 0 + RDB$CHARACTER_SET_ID 65 + RDB$COLLATION_ATTRIBUTES 1 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$374 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME WIN_CZ + RDB$COLLATION_ID 7 + RDB$CHARACTER_SET_ID 51 + RDB$COLLATION_ATTRIBUTES 3 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$338 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME WIN_CZ_CI_AI + RDB$COLLATION_ID 8 + RDB$CHARACTER_SET_ID 51 + RDB$COLLATION_ATTRIBUTES 7 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$339 + RDB$OWNER_NAME SYSDBA + + RDB$COLLATION_NAME WIN_PTBR + RDB$COLLATION_ID 6 + RDB$CHARACTER_SET_ID 53 + RDB$COLLATION_ATTRIBUTES 7 + RDB$SYSTEM_FLAG 1 + RDB$DESCRIPTION + RDB$FUNCTION_NAME + RDB$BASE_COLLATION_NAME + RDB$SPECIFIC_ATTRIBUTES + RDB$SECURITY_CLASS SQL$349 + RDB$OWNER_NAME SYSDBA + + + Records affected: 149 + """ + +@pytest.mark.version('>=3.0') +def test_db_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/basic/db/test_04.py b/tests/functional/basic/db/test_04.py new file mode 100644 index 00000000..cc1117c7 --- /dev/null +++ b/tests/functional/basic/db/test_04.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: functional.basic.db.04 +# title: Empty DB - RDB$EXCEPTIONS +# decription: Check for correct content of RDB$EXCEPTIONS in empty database. +# tracker_id: +# min_versions: [] +# versions: 2.5 +# qmid: functional.basic.db.db_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + -- NB: rdb$exception_name is UNIQUE column. + select * from rdb$exceptions order by rdb$exception_name; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ + +@pytest.mark.version('>=2.5') +def test_04_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/basic/db/test_05.py b/tests/functional/basic/db/test_05.py new file mode 100644 index 00000000..a91f84d5 --- /dev/null +++ b/tests/functional/basic/db/test_05.py @@ -0,0 +1,48 @@ +#coding:utf-8 +# +# id: functional.basic.db.05 +# title: Empty DB - RDB$DEPENDENCIES +# decription: Check for correct content of RDB$DEPENDENCIES in empty database. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.basic.db.db_05 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + select * from rdb$dependencies + order by + rdb$dependent_name + ,rdb$depended_on_name + ,rdb$field_name + ,rdb$dependent_type + ,rdb$depended_on_type + ,rdb$package_name -- avail. only for FB 3.0+ + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ + +@pytest.mark.version('>=3.0') +def test_05_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/basic/db/test_06.py b/tests/functional/basic/db/test_06.py new file mode 100644 index 00000000..a14b1f8f --- /dev/null +++ b/tests/functional/basic/db/test_06.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: functional.basic.db.06 +# title: Empty DB - RDB$FIELD_DIMENSIONS +# decription: Check for correct content of RDB$FIELD_DIMENSIONS in empty database. +# tracker_id: +# min_versions: [] +# versions: 2.5 +# qmid: functional.basic.db.db_06 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + select * from rdb$field_dimensions order by rdb$field_name; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ + +@pytest.mark.version('>=2.5') +def test_06_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/basic/db/test_07.py b/tests/functional/basic/db/test_07.py new file mode 100644 index 00000000..e38e8ef8 --- /dev/null +++ b/tests/functional/basic/db/test_07.py @@ -0,0 +1,10026 @@ +#coding:utf-8 +# +# id: functional.basic.db.db_07 +# title: Empty DB - RDB$FIELDS +# decription: +# Check for correct content of RDB$FIELDS in empty database. +# Checked on: +# 2.5.9.27126: OK, 0.625s. +# 3.0.5.33086: OK, 1.766s. +# 4.0.0.1378: OK, 6.063s. +# +# tracker_id: +# min_versions: ['2.5.5'] +# versions: 3.0, 4.0 +# qmid: functional.basic.db.db_07 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('RDB\\$DEFAULT_VALUE.*', ''), ('RDB\\$SECURITY_CLASS[ ]+SQL\\$.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set blob all; + set count on; + select * from rdb$fields order by rdb$field_name; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +RDB$FIELD_NAME MON$SEC_DATABASE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 7 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 2 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 1 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 2 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$142 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$ACL +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$31 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$ARGUMENT_MECHANISM +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$128 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$ARGUMENT_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 31 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 31 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$127 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$ATTACHMENT_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 16 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$99 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$AUTH_METHOD +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 255 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 2 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 2 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$140 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$BACKUP_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$91 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$BACKUP_LEVEL +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$92 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$BACKUP_STATE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$116 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$BOOLEAN +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 1 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 23 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$130 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$BOUND +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$65 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$CALL_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 16 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$101 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$CHARACTER_SET_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$83 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$CHARACTER_SET_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 31 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 31 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$82 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$CLIENT_VERSION +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 255 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 2 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 2 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$135 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$COLLATION_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$85 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$COLLATION_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 31 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 31 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$84 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$CONSTRAINT_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 31 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 31 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$69 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$CONSTRAINT_TYPE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 11 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 0 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$70 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$CONTEXT_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 255 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 255 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$2 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$CONTEXT_VAR_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 80 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 0 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$121 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$CONTEXT_VAR_VALUE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 32765 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 0 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$122 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$COUNTER +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 16 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$111 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$DBKEY_LENGTH +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$16 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$DEBUG_INFO +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 9 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$118 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$DEFERRABLE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE 2:1e0 + blr_version5, + blr_literal, blr_text2, 2,0, 2,0, 'N','O', + blr_eoc + +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 3 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 0 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$71 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$DESCRIPTION +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 1 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$3 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$DESCRIPTOR +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 6 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$51 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$DIMENSION +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$66 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$DIMENSIONS +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$44 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$EDIT_STRING +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 127 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 0 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$4 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$ENGINE_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 31 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 31 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$123 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$EXCEPTION_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 31 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 31 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$87 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$EXCEPTION_NUMBER +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$88 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$EXTERNAL_DESCRIPTION +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 8 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$61 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$EXTERNAL_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 255 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 0 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$42 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FIELD_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$5 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FIELD_LENGTH +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$11 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FIELD_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 31 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 31 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$6 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FIELD_POSITION +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$12 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FIELD_PRECISION +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$90 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FIELD_SCALE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$13 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FIELD_SUB_TYPE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$26 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FIELD_TYPE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$14 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FILE_FLAGS +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$37 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FILE_LENGTH +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$36 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FILE_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 255 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 0 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$32 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FILE_NAME2 +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 255 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 255 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$33 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FILE_PARTITIONS +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$74 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FILE_P_OFFSET +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$89 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FILE_SEQUENCE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$34 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FILE_START +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$35 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FORMAT +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$15 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FUNCTION_BLR +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 2 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$126 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FUNCTION_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$125 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FUNCTION_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 31 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 31 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$41 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FUNCTION_TYPE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$52 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$GENERATOR_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$64 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$GENERATOR_INCREMENT +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 1 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$149 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$GENERATOR_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 31 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 31 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$63 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$GENERATOR_VALUE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 16 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$139 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$GENERIC_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 31 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 31 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$40 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$GENERIC_TYPE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$47 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$GUID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 38 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 0 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$93 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$HOST_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 255 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 255 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$137 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$IDENTITY_TYPE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$129 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$INDEX_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$9 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$INDEX_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 31 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 31 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$10 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$ISOLATION_MODE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$114 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$LINGER +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$141 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$LOCK_TIMEOUT +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$115 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$MAP_DB +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 31 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 31 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$145 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$MAP_FROM +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 255 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 255 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$147 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$MAP_FROM_TYPE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 31 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 1 +RDB$CHARACTER_LENGTH 31 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$146 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$MAP_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 31 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 1 +RDB$CHARACTER_LENGTH 31 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$143 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$MAP_TO +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 31 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 31 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$148 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$MAP_USING +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 1 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 1 +RDB$CHARACTER_LENGTH 1 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$144 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$MATCH_OPTION +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE 2:1e1 + blr_version5, + blr_literal, blr_text2, 2,0, 4,0, 'F','U','L','L', + blr_eoc + +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 7 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 0 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$72 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$MECHANISM +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$50 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$MESSAGE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 1023 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 0 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$57 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$MESSAGE_NUMBER +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$58 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$NULL_FLAG +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$68 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$NUMBER_OF_CHARACTERS +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$86 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$OBJECT_TYPE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$49 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$ODS_NUMBER +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$105 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$OS_USER +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 255 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 255 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$138 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PACKAGE_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 31 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 31 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$124 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PAGE_BUFFERS +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$107 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PAGE_NUMBER +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$17 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PAGE_SEQUENCE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$18 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PAGE_SIZE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$106 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PAGE_TYPE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$19 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PARAMETER_MECHANISM +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$119 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PARAMETER_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 31 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 31 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$79 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PARAMETER_NUMBER +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$80 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PARAMETER_TYPE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$81 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$103 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PLAN +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 1 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$150 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PLUGIN +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 31 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 31 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$96 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PRIVILEGE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 6 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 0 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$60 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PROCEDURE_BLR +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 2 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$75 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PROCEDURE_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$76 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PROCEDURE_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 31 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 31 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$78 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PROCEDURE_PARAMETERS +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$77 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PROCEDURE_TYPE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$98 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$QUERY_HEADER +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 1 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$20 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$RELATION_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$21 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$RELATION_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 31 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 31 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$22 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$RELATION_TYPE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$97 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$REMOTE_ADDRESS +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 255 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 2 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 2 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$113 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$REMOTE_PROTOCOL +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 10 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 2 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 2 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$112 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$REMOTE_VERSION +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 255 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 2 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 2 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$136 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$RULE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE 2:1e2 + blr_version5, + blr_literal, blr_text2, 2,0, 8,0, 'R','E','S','T','R','I','C','T', + blr_eoc + +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 11 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 0 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$73 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$RUNTIME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 5 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$45 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$SCN +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$94 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$SECURITY_CLASS +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 31 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 31 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$30 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$SEGMENT_COUNT +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$23 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$SEGMENT_LENGTH +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$24 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$SHADOW_NUMBER +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$62 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$SHUTDOWN_MODE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$108 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$SOURCE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 1 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$25 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$SOURCE_INFO +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$120 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$SPECIFIC_ATTRIBUTES +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 1 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$95 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$SQL_DIALECT +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$109 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$STATE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$104 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$STATEMENT_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 16 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$100 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$STATISTICS +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 27 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$67 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$STAT_GROUP +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$117 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$STAT_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$102 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$SWEEP_INTERVAL +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$110 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$SYSTEM_FLAG +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 1 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$7 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$SYSTEM_NULLFLAG +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$8 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$TIMESTAMP +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 35 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$55 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$TRANSACTION_DESCRIPTION +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 7 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$56 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$TRANSACTION_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 16 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$53 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$TRANSACTION_STATE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$54 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$TRIGGER_BLR +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 2 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$38 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$TRIGGER_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 31 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 31 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$39 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$TRIGGER_SEQUENCE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$46 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$TRIGGER_TYPE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 16 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$48 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$TYPE_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 31 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 31 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$43 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$USER +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 31 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 31 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$59 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$VALIDATION_BLR +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 2 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$28 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$VALUE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 2 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$29 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$VIEW_BLR +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 2 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$27 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$VIEW_CONTEXT +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$1 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME SEC$KEY +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 31 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 31 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$132 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME SEC$NAME_PART +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 32 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 32 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$134 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME SEC$USER_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 31 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 31 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$131 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME SEC$VALUE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 255 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 255 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 3 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$133 +RDB$OWNER_NAME SYSDBA + +Records affected: 150 + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_db_07_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [('RDB\\$DEFAULT_VALUE.*', ''), ('RDB\\$SECURITY_CLASS[ ]+SQL\\$.*', '')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set list on; + set blob all; + set count on; + -- NB: 'rdb$field_name' is unique, see DDL: + -- ALTER TABLE RDB$FIELDS ADD CONSTRAINT RDB$INDEX_2 UNIQUE (RDB$FIELD_NAME); + select * from rdb$fields order by rdb$field_name; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ +RDB$FIELD_NAME MON$IDLE_TIMEOUT +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 1 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$153 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME MON$IDLE_TIMER +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 12 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 29 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$154 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME MON$SEC_DATABASE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 7 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 2 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 1 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 2 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$142 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME MON$STATEMENT_TIMEOUT +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 1 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$155 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME MON$STATEMENT_TIMER +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 12 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 29 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$156 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME MON$WIRE_CRYPT_PLUGIN +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$163 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$ACL +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$31 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$ARGUMENT_MECHANISM +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$128 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$ARGUMENT_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$127 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$ATTACHMENT_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 16 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$99 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$AUTH_METHOD +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 255 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 2 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 2 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$140 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$BACKUP_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$91 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$BACKUP_LEVEL +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$92 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$BACKUP_STATE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$116 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$BOOLEAN +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 1 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 23 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$130 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$BOUND +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$65 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$CALL_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 16 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$101 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$CHARACTER_SET_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$83 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$CHARACTER_SET_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$82 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$CLIENT_VERSION +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 255 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 2 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 2 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$135 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$COLLATION_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$85 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$COLLATION_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$84 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$CONFIG_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 1 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$166 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$CONFIG_IS_SET +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 1 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 23 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 1 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$169 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$CONFIG_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 63 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 2 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 1 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 2 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$167 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$CONFIG_VALUE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 1020 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 255 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$168 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$CONSTRAINT_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$69 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$CONSTRAINT_TYPE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 11 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 0 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$70 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$CONTEXT_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 1020 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 255 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$2 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$CONTEXT_VAR_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 80 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 0 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$121 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$CONTEXT_VAR_VALUE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 32765 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 0 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$122 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$COUNTER +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 16 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$111 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$CRYPT_STATE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$162 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$DBKEY_LENGTH +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$16 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$DBTZ_VERSION +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 10 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 2 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 2 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$161 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$DEBUG_INFO +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 9 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$118 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$DEFERRABLE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE 2:1e0 + blr_version5, + blr_literal, blr_text2, 2,0, 2,0, 'N','O', + blr_eoc + +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 3 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 0 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$71 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$DESCRIPTION +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 1 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$3 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$DESCRIPTOR +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 6 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$51 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$DIMENSION +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$66 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$DIMENSIONS +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$44 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$EDIT_STRING +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 127 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 0 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$4 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$ENGINE_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$123 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$EXCEPTION_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$87 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$EXCEPTION_NUMBER +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$88 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$EXTERNAL_DESCRIPTION +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 8 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$61 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$EXTERNAL_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 255 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 0 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$42 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FIELD_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$5 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FIELD_LENGTH +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$11 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FIELD_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$6 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FIELD_POSITION +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$12 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FIELD_PRECISION +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$90 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FIELD_SCALE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$13 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FIELD_SUB_TYPE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$26 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FIELD_TYPE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$14 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FILE_FLAGS +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$37 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FILE_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 255 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 2 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 1 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 2 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$165 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FILE_LENGTH +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$36 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FILE_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 255 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 0 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$32 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FILE_NAME2 +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 1020 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 255 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$33 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FILE_PARTITIONS +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$74 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FILE_P_OFFSET +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$89 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FILE_SEQUENCE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$34 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FILE_START +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$35 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FORMAT +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$15 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FUNCTION_BLR +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 2 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$126 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FUNCTION_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$125 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FUNCTION_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$41 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$FUNCTION_TYPE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$52 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$GENERATOR_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$64 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$GENERATOR_INCREMENT +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 1 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$149 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$GENERATOR_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$63 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$GENERATOR_VALUE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 16 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$139 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$GENERIC_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$40 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$GENERIC_TYPE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$47 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$GUID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 38 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 0 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$93 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$HOST_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 1020 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 255 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$137 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$IDENTITY_TYPE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$129 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$INDEX_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$9 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$INDEX_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$10 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$ISOLATION_MODE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$114 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$LINGER +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$141 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$LOCK_TIMEOUT +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$115 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$MAP_DB +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$145 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$MAP_FROM +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 1020 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 255 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$147 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$MAP_FROM_TYPE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 1 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$146 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$MAP_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 1 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$143 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$MAP_TO +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$148 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$MAP_USING +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 1 +RDB$CHARACTER_LENGTH 1 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$144 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$MATCH_OPTION +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE 2:1e1 + blr_version5, + blr_literal, blr_text2, 2,0, 4,0, 'F','U','L','L', + blr_eoc + +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 7 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 0 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$72 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$MECHANISM +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$50 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$MESSAGE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 1023 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 0 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$57 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$MESSAGE_NUMBER +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$58 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$NULL_FLAG +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$68 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$NUMBER_OF_CHARACTERS +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$86 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$OBJECT_TYPE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$49 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$ODS_NUMBER +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$105 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$OS_USER +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 1020 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 255 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$138 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PACKAGE_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$124 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PAGE_BUFFERS +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$107 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PAGE_NUMBER +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$17 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PAGE_SEQUENCE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$18 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PAGE_SIZE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$106 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PAGE_TYPE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$19 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PARAMETER_MECHANISM +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$119 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PARAMETER_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$79 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PARAMETER_NUMBER +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$80 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PARAMETER_TYPE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$81 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$103 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PLAN +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 1 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$150 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PLUGIN +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$96 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PRIVILEGE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 6 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 0 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$60 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PROCEDURE_BLR +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 2 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$75 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PROCEDURE_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$76 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PROCEDURE_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$78 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PROCEDURE_PARAMETERS +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$77 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PROCEDURE_TYPE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$98 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$PUBLICATION_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 1 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$164 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$QUERY_HEADER +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 1 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$20 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$RELATION_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$21 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$RELATION_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$22 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$RELATION_TYPE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$97 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$REMOTE_ADDRESS +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 255 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 2 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 2 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$113 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$REMOTE_PROTOCOL +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 10 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 2 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 2 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$112 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$REMOTE_VERSION +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 255 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 2 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 2 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$136 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$REPLICA_MODE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$170 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$RULE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE 2:1e2 + blr_version5, + blr_literal, blr_text2, 2,0, 8,0, 'R','E','S','T','R','I','C','T', + blr_eoc + +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 11 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 0 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$73 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$RUNTIME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 5 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$45 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$SCN +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$94 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$SECURITY_CLASS +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$30 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$SEGMENT_COUNT +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$23 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$SEGMENT_LENGTH +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$24 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$SHADOW_NUMBER +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$62 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$SHUTDOWN_MODE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$108 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$SOURCE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 1 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$25 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$SOURCE_INFO +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$120 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$SPECIFIC_ATTRIBUTES +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 1 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$95 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$SQL_DIALECT +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$109 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$SQL_SECURITY +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 1 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 23 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$152 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$STATE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$104 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$STATEMENT_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 16 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$100 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$STATISTICS +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 27 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$67 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$STAT_GROUP +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$117 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$STAT_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$102 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$SWEEP_INTERVAL +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$110 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$SYSTEM_FLAG +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 1 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$7 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$SYSTEM_NULLFLAG +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$8 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$SYSTEM_PRIVILEGES +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE 2:1e3 + blr_version5, + blr_literal, blr_text2, 1,0, 8,0, 0,0,0,0,0,0,0,0, + blr_eoc + +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 1 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 1 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$151 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$TIMESTAMP +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 35 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$55 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$TIMESTAMP_TZ +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 12 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 29 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$160 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$TIME_ZONE_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 4 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 8 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$157 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$TIME_ZONE_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$158 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$TIME_ZONE_OFFSET +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$159 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$TRANSACTION_DESCRIPTION +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 7 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$56 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$TRANSACTION_ID +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 16 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$53 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$TRANSACTION_STATE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$54 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$TRIGGER_BLR +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 2 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$38 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$TRIGGER_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$39 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$TRIGGER_SEQUENCE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$46 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$TRIGGER_TYPE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 16 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$48 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$TYPE_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$43 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$USER +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 14 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$59 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$VALIDATION_BLR +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 2 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$28 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$VALUE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 2 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$29 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$VIEW_BLR +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 8 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 261 +RDB$FIELD_SUB_TYPE 2 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH 80 +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$27 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME RDB$VIEW_CONTEXT +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 2 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 7 +RDB$FIELD_SUB_TYPE +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH +RDB$COLLATION_ID +RDB$CHARACTER_SET_ID +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$1 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME SEC$KEY +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$132 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME SEC$NAME_PART +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 128 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 32 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$134 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME SEC$USER_NAME +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 252 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 63 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$131 +RDB$OWNER_NAME SYSDBA + +RDB$FIELD_NAME SEC$VALUE +RDB$QUERY_NAME +RDB$VALIDATION_BLR +RDB$VALIDATION_SOURCE +RDB$COMPUTED_BLR +RDB$COMPUTED_SOURCE +RDB$DEFAULT_VALUE +RDB$DEFAULT_SOURCE +RDB$FIELD_LENGTH 1020 +RDB$FIELD_SCALE 0 +RDB$FIELD_TYPE 37 +RDB$FIELD_SUB_TYPE 3 +RDB$MISSING_VALUE +RDB$MISSING_SOURCE +RDB$DESCRIPTION +RDB$SYSTEM_FLAG 1 +RDB$QUERY_HEADER +RDB$SEGMENT_LENGTH +RDB$EDIT_STRING +RDB$EXTERNAL_LENGTH +RDB$EXTERNAL_SCALE +RDB$EXTERNAL_TYPE +RDB$DIMENSIONS +RDB$NULL_FLAG 0 +RDB$CHARACTER_LENGTH 255 +RDB$COLLATION_ID 0 +RDB$CHARACTER_SET_ID 4 +RDB$FIELD_PRECISION +RDB$SECURITY_CLASS SQL$133 +RDB$OWNER_NAME SYSDBA + + +Records affected: 170 + """ + +@pytest.mark.version('>=4.0') +def test_db_07_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/functional/basic/db/test_08.py b/tests/functional/basic/db/test_08.py new file mode 100644 index 00000000..bd814d21 --- /dev/null +++ b/tests/functional/basic/db/test_08.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: functional.basic.db.08 +# title: Empty DB - RDB$FILES +# decription: Check for correct content of RDB$FILES in empty database; +# tracker_id: +# min_versions: [] +# versions: 2.5 +# qmid: functional.basic.db.db_08 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + select * from rdb$files + order by + rdb$file_name + ,rdb$file_sequence + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ + +@pytest.mark.version('>=2.5') +def test_08_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/basic/db/test_09.py b/tests/functional/basic/db/test_09.py new file mode 100644 index 00000000..7836ec64 --- /dev/null +++ b/tests/functional/basic/db/test_09.py @@ -0,0 +1,31 @@ +#coding:utf-8 +# +# id: functional.basic.db.09 +# title: Empty DB - RDB$FILTERS +# decription: Check for correct content of RDB$FILTERS in empty database. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.basic.db.db_09 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select * from RDB$FILTERS;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=1.0') +def test_09_1(act_1: Action): + act_1.execute() + diff --git a/tests/functional/basic/db/test_10.py b/tests/functional/basic/db/test_10.py new file mode 100644 index 00000000..0c828cc0 --- /dev/null +++ b/tests/functional/basic/db/test_10.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: functional.basic.db.10 +# title: Empty DB - RDB$FORMATS +# decription: Check for correct content of RDB$FORMATS in empty database. +# tracker_id: +# min_versions: [] +# versions: 2.5 +# qmid: functional.basic.db.db_10 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + set blob all; + select * from rdb$formats + order by + rdb$relation_id + ,rdb$format + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ + +@pytest.mark.version('>=2.5') +def test_10_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/basic/db/test_11.py b/tests/functional/basic/db/test_11.py new file mode 100644 index 00000000..9499364e --- /dev/null +++ b/tests/functional/basic/db/test_11.py @@ -0,0 +1,99 @@ +#coding:utf-8 +# +# id: functional.basic.db.db_11 +# title: New DB - RDB$FUNCTIONS +# decription: +# Check for correct content of RDB$FUNCTIONS in a new database. +# Checked on: +# 2.5.9.27126: OK, 1.734s. +# 3.0.5.33086: OK, 1.250s. +# 4.0.0.1378: OK, 5.422s. +# +# tracker_id: +# min_versions: [] +# versions: 3.0, 4.0 +# qmid: functional.basic.db.db_12 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + select * + from rdb$functions rf + order by rdb$engine_name, rf.rdb$package_name, rf.rdb$function_name, rdb$module_name, rdb$entrypoint; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_db_11_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set list on; + set count on; + select * + from rdb$functions rf + order by rdb$engine_name, rf.rdb$package_name, rf.rdb$function_name, rdb$module_name, rdb$entrypoint; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + RDB$FUNCTION_NAME DATABASE_VERSION + RDB$FUNCTION_TYPE + RDB$QUERY_NAME + RDB$DESCRIPTION + RDB$MODULE_NAME + RDB$ENTRYPOINT + RDB$RETURN_ARGUMENT 0 + RDB$SYSTEM_FLAG 1 + RDB$ENGINE_NAME SYSTEM + RDB$PACKAGE_NAME RDB$TIME_ZONE_UTIL + RDB$PRIVATE_FLAG 0 + RDB$FUNCTION_SOURCE + RDB$FUNCTION_ID 1 + RDB$FUNCTION_BLR + RDB$VALID_BLR 1 + RDB$DEBUG_INFO + RDB$SECURITY_CLASS + RDB$OWNER_NAME SYSDBA + RDB$LEGACY_FLAG + RDB$DETERMINISTIC_FLAG + RDB$SQL_SECURITY + + Records affected: 1 + """ + +@pytest.mark.version('>=4.0') +def test_db_11_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/functional/basic/db/test_13.py b/tests/functional/basic/db/test_13.py new file mode 100644 index 00000000..2d13bf1e --- /dev/null +++ b/tests/functional/basic/db/test_13.py @@ -0,0 +1,172 @@ +#coding:utf-8 +# +# id: functional.basic.db.db_13 +# title: Empty DB - RDB$GENERATORS +# decription: Check for correct content of RDB$GENERATORS in empty database; +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.basic.db.db_13 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('GEN_DESCR_BLOB_ID.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- 28.10.2015. + -- 1. Removed from comparison values of RDB$SECURITY_CLASS because its values often differ in 3.0 recent builds. + -- 2. Field rdb$description has been moved at the end of output (select) list. + -- 3. Added query to select FIELDS list of table because main check does not use asterisk + -- and we have to know if DDL of table will have any changes in future. + + set blob all; + set count on; + set list on; + + -- Query for check whether fields list of table was changed: + select rf.rdb$field_name + from rdb$relation_fields rf + where rf.rdb$relation_name = upper('rdb$generators') + order by rf.rdb$field_name; + + -- Main test query: + select + rdb$generator_id + ,rdb$generator_name + ,rdb$system_flag + ,rdb$initial_value + ,rdb$generator_increment + ,rdb$owner_name + ,rdb$description as gen_descr_blob_id + from rdb$generators g + order by g.rdb$generator_id; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$FIELD_NAME RDB$GENERATOR_ID + RDB$FIELD_NAME RDB$GENERATOR_INCREMENT + RDB$FIELD_NAME RDB$GENERATOR_NAME + RDB$FIELD_NAME RDB$INITIAL_VALUE + RDB$FIELD_NAME RDB$OWNER_NAME + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$FIELD_NAME RDB$SYSTEM_FLAG + + Records affected: 8 + + RDB$GENERATOR_ID 1 + RDB$GENERATOR_NAME RDB$SECURITY_CLASS + RDB$SYSTEM_FLAG 1 + RDB$INITIAL_VALUE 0 + RDB$GENERATOR_INCREMENT 0 + RDB$OWNER_NAME SYSDBA + GEN_DESCR_BLOB_ID + + RDB$GENERATOR_ID 2 + RDB$GENERATOR_NAME SQL$DEFAULT + RDB$SYSTEM_FLAG 1 + RDB$INITIAL_VALUE 0 + RDB$GENERATOR_INCREMENT 0 + RDB$OWNER_NAME SYSDBA + GEN_DESCR_BLOB_ID + + RDB$GENERATOR_ID 3 + RDB$GENERATOR_NAME RDB$PROCEDURES + RDB$SYSTEM_FLAG 1 + RDB$INITIAL_VALUE 0 + RDB$GENERATOR_INCREMENT 0 + RDB$OWNER_NAME SYSDBA + GEN_DESCR_BLOB_ID 14:1e0 + Procedure ID + + RDB$GENERATOR_ID 4 + RDB$GENERATOR_NAME RDB$EXCEPTIONS + RDB$SYSTEM_FLAG 1 + RDB$INITIAL_VALUE 0 + RDB$GENERATOR_INCREMENT 0 + RDB$OWNER_NAME SYSDBA + GEN_DESCR_BLOB_ID 14:1e1 + Exception ID + + RDB$GENERATOR_ID 5 + RDB$GENERATOR_NAME RDB$CONSTRAINT_NAME + RDB$SYSTEM_FLAG 1 + RDB$INITIAL_VALUE 0 + RDB$GENERATOR_INCREMENT 0 + RDB$OWNER_NAME SYSDBA + GEN_DESCR_BLOB_ID 14:1e2 + Implicit constraint name + + RDB$GENERATOR_ID 6 + RDB$GENERATOR_NAME RDB$FIELD_NAME + RDB$SYSTEM_FLAG 1 + RDB$INITIAL_VALUE 0 + RDB$GENERATOR_INCREMENT 0 + RDB$OWNER_NAME SYSDBA + GEN_DESCR_BLOB_ID 14:1e3 + Implicit domain name + + RDB$GENERATOR_ID 7 + RDB$GENERATOR_NAME RDB$INDEX_NAME + RDB$SYSTEM_FLAG 1 + RDB$INITIAL_VALUE 0 + RDB$GENERATOR_INCREMENT 0 + RDB$OWNER_NAME SYSDBA + GEN_DESCR_BLOB_ID 14:1e4 + Implicit index name + + RDB$GENERATOR_ID 8 + RDB$GENERATOR_NAME RDB$TRIGGER_NAME + RDB$SYSTEM_FLAG 1 + RDB$INITIAL_VALUE 0 + RDB$GENERATOR_INCREMENT 0 + RDB$OWNER_NAME SYSDBA + GEN_DESCR_BLOB_ID 14:1e5 + Implicit trigger name + + RDB$GENERATOR_ID 9 + RDB$GENERATOR_NAME RDB$BACKUP_HISTORY + RDB$SYSTEM_FLAG 1 + RDB$INITIAL_VALUE 0 + RDB$GENERATOR_INCREMENT 0 + RDB$OWNER_NAME SYSDBA + GEN_DESCR_BLOB_ID 14:1e6 + Nbackup technology + + RDB$GENERATOR_ID 10 + RDB$GENERATOR_NAME RDB$FUNCTIONS + RDB$SYSTEM_FLAG 1 + RDB$INITIAL_VALUE 0 + RDB$GENERATOR_INCREMENT 0 + RDB$OWNER_NAME SYSDBA + GEN_DESCR_BLOB_ID 14:1e7 + Function ID + + RDB$GENERATOR_ID 11 + RDB$GENERATOR_NAME RDB$GENERATOR_NAME + RDB$SYSTEM_FLAG 1 + RDB$INITIAL_VALUE 0 + RDB$GENERATOR_INCREMENT 0 + RDB$OWNER_NAME SYSDBA + GEN_DESCR_BLOB_ID 14:1e8 + Implicit generator name + + Records affected: 11 + """ + +@pytest.mark.version('>=3.0') +def test_db_13_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/basic/db/test_14.py b/tests/functional/basic/db/test_14.py new file mode 100644 index 00000000..2e29b44b --- /dev/null +++ b/tests/functional/basic/db/test_14.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: functional.basic.db.14 +# title: Empty DB - RDB$CHECK_CONSTRAINTS +# decription: Check for correct content of RDB$CHECK_CONSTRAINTS in empty database. +# tracker_id: +# min_versions: [] +# versions: 2.5 +# qmid: functional.basic.db.db_14 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + select * from rdb$check_constraints + order by + rdb$constraint_name + ,rdb$trigger_name + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ + +@pytest.mark.version('>=2.5') +def test_14_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/basic/db/test_15.py b/tests/functional/basic/db/test_15.py new file mode 100644 index 00000000..549bbca8 --- /dev/null +++ b/tests/functional/basic/db/test_15.py @@ -0,0 +1,783 @@ +#coding:utf-8 +# +# id: functional.basic.db.db_15 +# title: Empty DB - RDB$INDEX_SEGMENTS +# decription: +# Check for correct content of RDB$INDEX_SEGMENTS in empty database. +# Checked on: +# 2.5.9.27126: OK, 0.531s. +# 3.0.5.33086: OK, 3.907s. +# 4.0.0.1378: OK, 5.297s. +# +# tracker_id: +# min_versions: [] +# versions: 3.0, 4.0 +# qmid: functional.basic.db.db_15 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('RDB\\$INDEX_NAME[\\s]+RDB\\$INDEX.*', 'RDB\\$INDEX_NAME RDB\\$INDEX')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + select rs.* + from rdb$index_segments rs + order by lpad( trim(replace(rdb$index_name, 'RDB$INDEX_', '')),31,'0'), rdb$field_name; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$INDEX_NAME RDB$INDEX_0 + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_1 + RDB$FIELD_NAME RDB$RELATION_ID + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_2 + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_3 + RDB$FIELD_NAME RDB$FIELD_SOURCE + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_4 + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_5 + RDB$FIELD_NAME RDB$INDEX_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_6 + RDB$FIELD_NAME RDB$INDEX_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_7 + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_8 + RDB$FIELD_NAME RDB$TRIGGER_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_9 + RDB$FIELD_NAME RDB$FUNCTION_NAME + RDB$FIELD_POSITION 1 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_9 + RDB$FIELD_NAME RDB$PACKAGE_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_10 + RDB$FIELD_NAME RDB$FUNCTION_NAME + RDB$FIELD_POSITION 1 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_10 + RDB$FIELD_NAME RDB$PACKAGE_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_11 + RDB$FIELD_NAME RDB$GENERATOR_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_12 + RDB$FIELD_NAME RDB$CONSTRAINT_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_13 + RDB$FIELD_NAME RDB$CONSTRAINT_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_14 + RDB$FIELD_NAME RDB$CONSTRAINT_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_15 + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_15 + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$FIELD_POSITION 1 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_16 + RDB$FIELD_NAME RDB$FORMAT + RDB$FIELD_POSITION 1 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_16 + RDB$FIELD_NAME RDB$RELATION_ID + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_17 + RDB$FIELD_NAME RDB$INPUT_SUB_TYPE + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_17 + RDB$FIELD_NAME RDB$OUTPUT_SUB_TYPE + RDB$FIELD_POSITION 1 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_18 + RDB$FIELD_NAME RDB$PACKAGE_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_18 + RDB$FIELD_NAME RDB$PARAMETER_NAME + RDB$FIELD_POSITION 2 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_18 + RDB$FIELD_NAME RDB$PROCEDURE_NAME + RDB$FIELD_POSITION 1 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_19 + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_20 + RDB$FIELD_NAME RDB$COLLATION_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_21 + RDB$FIELD_NAME RDB$PACKAGE_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_21 + RDB$FIELD_NAME RDB$PROCEDURE_NAME + RDB$FIELD_POSITION 1 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_22 + RDB$FIELD_NAME RDB$PROCEDURE_ID + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_23 + RDB$FIELD_NAME RDB$EXCEPTION_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_24 + RDB$FIELD_NAME RDB$EXCEPTION_NUMBER + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_25 + RDB$FIELD_NAME RDB$CHARACTER_SET_ID + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_26 + RDB$FIELD_NAME RDB$CHARACTER_SET_ID + RDB$FIELD_POSITION 1 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_26 + RDB$FIELD_NAME RDB$COLLATION_ID + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_27 + RDB$FIELD_NAME RDB$DEPENDENT_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_28 + RDB$FIELD_NAME RDB$DEPENDED_ON_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_29 + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_30 + RDB$FIELD_NAME RDB$USER + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_31 + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_32 + RDB$FIELD_NAME RDB$TRANSACTION_ID + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_33 + RDB$FIELD_NAME RDB$VIEW_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_34 + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_35 + RDB$FIELD_NAME RDB$TRIGGER_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_36 + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_37 + RDB$FIELD_NAME RDB$TYPE_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_38 + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_39 + RDB$FIELD_NAME RDB$ROLE_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_40 + RDB$FIELD_NAME RDB$TRIGGER_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_41 + RDB$FIELD_NAME RDB$FOREIGN_KEY + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_42 + RDB$FIELD_NAME RDB$CONSTRAINT_TYPE + RDB$FIELD_POSITION 1 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_42 + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_43 + RDB$FIELD_NAME RDB$INDEX_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_44 + RDB$FIELD_NAME RDB$BACKUP_ID + RDB$FIELD_POSITION 1 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_44 + RDB$FIELD_NAME RDB$BACKUP_LEVEL + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_45 + RDB$FIELD_NAME RDB$FUNCTION_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_46 + RDB$FIELD_NAME RDB$GENERATOR_ID + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_47 + RDB$FIELD_NAME RDB$PACKAGE_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_48 + RDB$FIELD_NAME RDB$FIELD_SOURCE + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_49 + RDB$FIELD_NAME RDB$FIELD_SOURCE + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_50 + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$FIELD_POSITION 1 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_50 + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_51 + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$FIELD_POSITION 1 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_51 + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_52 + RDB$FIELD_NAME RDB$MAP_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_53 + RDB$FIELD_NAME RDB$FUNCTION_ID + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + + Records affected: 67 + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_db_15_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [('RDB\\$INDEX_NAME[\\s]+RDB\\$INDEX.*', 'RDB\\$INDEX_NAME RDB\\$INDEX')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set list on; + set count on; + select rs.* + from rdb$index_segments rs + order by lpad( trim(replace(rdb$index_name, 'RDB$INDEX_', '')),31,'0'), rdb$field_name; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + RDB$INDEX_NAME RDB$INDEX_0 + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_1 + RDB$FIELD_NAME RDB$RELATION_ID + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_2 + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_3 + RDB$FIELD_NAME RDB$FIELD_SOURCE + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_4 + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_5 + RDB$FIELD_NAME RDB$INDEX_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_6 + RDB$FIELD_NAME RDB$INDEX_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_7 + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_8 + RDB$FIELD_NAME RDB$TRIGGER_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_9 + RDB$FIELD_NAME RDB$FUNCTION_NAME + RDB$FIELD_POSITION 1 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_9 + RDB$FIELD_NAME RDB$PACKAGE_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_10 + RDB$FIELD_NAME RDB$FUNCTION_NAME + RDB$FIELD_POSITION 1 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_10 + RDB$FIELD_NAME RDB$PACKAGE_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_11 + RDB$FIELD_NAME RDB$GENERATOR_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_12 + RDB$FIELD_NAME RDB$CONSTRAINT_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_13 + RDB$FIELD_NAME RDB$CONSTRAINT_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_14 + RDB$FIELD_NAME RDB$CONSTRAINT_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_15 + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_15 + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$FIELD_POSITION 1 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_16 + RDB$FIELD_NAME RDB$FORMAT + RDB$FIELD_POSITION 1 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_16 + RDB$FIELD_NAME RDB$RELATION_ID + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_17 + RDB$FIELD_NAME RDB$INPUT_SUB_TYPE + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_17 + RDB$FIELD_NAME RDB$OUTPUT_SUB_TYPE + RDB$FIELD_POSITION 1 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_18 + RDB$FIELD_NAME RDB$PACKAGE_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_18 + RDB$FIELD_NAME RDB$PARAMETER_NAME + RDB$FIELD_POSITION 2 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_18 + RDB$FIELD_NAME RDB$PROCEDURE_NAME + RDB$FIELD_POSITION 1 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_19 + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_20 + RDB$FIELD_NAME RDB$COLLATION_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_21 + RDB$FIELD_NAME RDB$PACKAGE_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_21 + RDB$FIELD_NAME RDB$PROCEDURE_NAME + RDB$FIELD_POSITION 1 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_22 + RDB$FIELD_NAME RDB$PROCEDURE_ID + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_23 + RDB$FIELD_NAME RDB$EXCEPTION_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_24 + RDB$FIELD_NAME RDB$EXCEPTION_NUMBER + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_25 + RDB$FIELD_NAME RDB$CHARACTER_SET_ID + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_26 + RDB$FIELD_NAME RDB$CHARACTER_SET_ID + RDB$FIELD_POSITION 1 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_26 + RDB$FIELD_NAME RDB$COLLATION_ID + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_27 + RDB$FIELD_NAME RDB$DEPENDENT_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_27 + RDB$FIELD_NAME RDB$DEPENDENT_TYPE + RDB$FIELD_POSITION 1 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_28 + RDB$FIELD_NAME RDB$DEPENDED_ON_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_28 + RDB$FIELD_NAME RDB$DEPENDED_ON_TYPE + RDB$FIELD_POSITION 1 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_28 + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$FIELD_POSITION 2 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_29 + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_30 + RDB$FIELD_NAME RDB$USER + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_31 + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_32 + RDB$FIELD_NAME RDB$TRANSACTION_ID + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_33 + RDB$FIELD_NAME RDB$VIEW_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_34 + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_35 + RDB$FIELD_NAME RDB$TRIGGER_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_36 + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_37 + RDB$FIELD_NAME RDB$TYPE_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_38 + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_39 + RDB$FIELD_NAME RDB$ROLE_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_40 + RDB$FIELD_NAME RDB$TRIGGER_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_41 + RDB$FIELD_NAME RDB$FOREIGN_KEY + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_42 + RDB$FIELD_NAME RDB$CONSTRAINT_TYPE + RDB$FIELD_POSITION 1 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_42 + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_43 + RDB$FIELD_NAME RDB$INDEX_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_44 + RDB$FIELD_NAME RDB$BACKUP_ID + RDB$FIELD_POSITION 1 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_44 + RDB$FIELD_NAME RDB$BACKUP_LEVEL + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_45 + RDB$FIELD_NAME RDB$FUNCTION_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_46 + RDB$FIELD_NAME RDB$GENERATOR_ID + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_47 + RDB$FIELD_NAME RDB$PACKAGE_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_48 + RDB$FIELD_NAME RDB$FIELD_SOURCE + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_49 + RDB$FIELD_NAME RDB$FIELD_SOURCE + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_50 + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$FIELD_POSITION 1 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_50 + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_51 + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$FIELD_POSITION 1 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_51 + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_52 + RDB$FIELD_NAME RDB$MAP_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_53 + RDB$FIELD_NAME RDB$FUNCTION_ID + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_54 + RDB$FIELD_NAME RDB$GUID + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_55 + RDB$FIELD_NAME RDB$PUBLICATION_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_56 + RDB$FIELD_NAME RDB$PUBLICATION_NAME + RDB$FIELD_POSITION 1 + RDB$STATISTICS + + RDB$INDEX_NAME RDB$INDEX_56 + RDB$FIELD_NAME RDB$TABLE_NAME + RDB$FIELD_POSITION 0 + RDB$STATISTICS + + Records affected: 74 + """ + +@pytest.mark.version('>=4.0') +def test_db_15_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/functional/basic/db/test_16.py b/tests/functional/basic/db/test_16.py new file mode 100644 index 00000000..62af0d76 --- /dev/null +++ b/tests/functional/basic/db/test_16.py @@ -0,0 +1,1719 @@ +#coding:utf-8 +# +# id: functional.basic.db.db_16 +# title: Empty DB - RDB$INDICES +# decription: +# Check for correct content of RDB$INDICES in empty database. +# Checked on: +# 2.5.9.27126: OK, 0.640s. +# 3.0.5.33086: OK, 1.532s. +# 4.0.0.1378: OK, 5.922s. +# +# tracker_id: +# min_versions: [] +# versions: 3.0, 4.0 +# qmid: functional.basic.db.db_16 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('RDB\\$INDEX_NAME[\\s]+RDB\\$INDEX.*', 'RDB\\$INDEX_NAME RDB\\$INDEX'), ('DECRIPTN_BLOB_ID.*', ''), ('EXPR_BLR_BLOB_ID.*', ''), ('EXPR_SRC_BLOB_ID.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- 28.10.2015: + -- Added blocks in subst-section in order to ignore concrete values in RBD$INDEX_** (i.e. suffixes). + -- Moved all BLOB fields at the end of output, suppress comparison of their IDs. + -- Added query to select FIELDS list of table because main check does not use asterisk + -- and we have to know if DDL of table will have any changes in future. + + set list on; + set blob all; + set count on; + + -- Query for check whether fields list of table was changed: + select rf.rdb$field_name + from rdb$relation_fields rf + where rf.rdb$relation_name = upper('rdb$indices') + order by rf.rdb$field_name; + + -- Main test query: + select + rdb$index_name + ,rdb$relation_name + ,rdb$index_id + ,rdb$unique_flag + ,rdb$segment_count + ,rdb$index_inactive + ,rdb$index_type + ,rdb$system_flag + ,rdb$statistics + ,rdb$foreign_key + ,rdb$description as decriptn_blob_id + ,rdb$expression_blr as expr_blr_blob_id + ,rdb$expression_source as expr_src_blob_id + from rdb$indices + order by rdb$index_name; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$FIELD_NAME RDB$EXPRESSION_BLR + RDB$FIELD_NAME RDB$EXPRESSION_SOURCE + RDB$FIELD_NAME RDB$FOREIGN_KEY + RDB$FIELD_NAME RDB$INDEX_ID + RDB$FIELD_NAME RDB$INDEX_INACTIVE + RDB$FIELD_NAME RDB$INDEX_NAME + RDB$FIELD_NAME RDB$INDEX_TYPE + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$FIELD_NAME RDB$SEGMENT_COUNT + RDB$FIELD_NAME RDB$STATISTICS + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$FIELD_NAME RDB$UNIQUE_FLAG + Records affected: 13 + + RDB$INDEX_NAME RDB$INDEX_0 + RDB$RELATION_NAME RDB$RELATIONS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_1 + RDB$RELATION_NAME RDB$RELATIONS + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_10 + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 2 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_11 + RDB$RELATION_NAME RDB$GENERATORS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_12 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_13 + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_14 + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_15 + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$INDEX_ID 3 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 2 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_16 + RDB$RELATION_NAME RDB$FORMATS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 2 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_17 + RDB$RELATION_NAME RDB$FILTERS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 2 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_18 + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 3 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_19 + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_2 + RDB$RELATION_NAME RDB$FIELDS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_20 + RDB$RELATION_NAME RDB$COLLATIONS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_21 + RDB$RELATION_NAME RDB$PROCEDURES + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 2 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_22 + RDB$RELATION_NAME RDB$PROCEDURES + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_23 + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_24 + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_25 + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_26 + RDB$RELATION_NAME RDB$COLLATIONS + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 2 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_27 + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_28 + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_29 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_3 + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_30 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_31 + RDB$RELATION_NAME RDB$INDICES + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_32 + RDB$RELATION_NAME RDB$TRANSACTIONS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_33 + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_34 + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_35 + RDB$RELATION_NAME RDB$TRIGGER_MESSAGES + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_36 + RDB$RELATION_NAME RDB$FIELD_DIMENSIONS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_37 + RDB$RELATION_NAME RDB$TYPES + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_38 + RDB$RELATION_NAME RDB$TRIGGERS + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_39 + RDB$RELATION_NAME RDB$ROLES + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_4 + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_40 + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_41 + RDB$RELATION_NAME RDB$INDICES + RDB$INDEX_ID 3 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_42 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 2 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_43 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$INDEX_ID 3 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_44 + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 2 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE 1 + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_45 + RDB$RELATION_NAME RDB$FILTERS + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_46 + RDB$RELATION_NAME RDB$GENERATORS + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_47 + RDB$RELATION_NAME RDB$PACKAGES + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_48 + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_49 + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_5 + RDB$RELATION_NAME RDB$INDICES + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_50 + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$INDEX_ID 3 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 2 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_51 + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$INDEX_ID 3 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 2 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_52 + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_53 + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_6 + RDB$RELATION_NAME RDB$INDEX_SEGMENTS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_7 + RDB$RELATION_NAME RDB$SECURITY_CLASSES + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_8 + RDB$RELATION_NAME RDB$TRIGGERS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_9 + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 2 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + Records affected: 54 + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_db_16_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [('RDB\\$INDEX_NAME[\\s]+RDB\\$INDEX.*', 'RDB\\$INDEX_NAME RDB\\$INDEX'), ('DECRIPTN_BLOB_ID.*', ''), ('EXPR_BLR_BLOB_ID.*', ''), ('EXPR_SRC_BLOB_ID.*', '')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + -- 28.10.2015: + -- Added blocks in subst-section in order to ignore concrete values in RBD$INDEX_** (i.e. suffixes). + -- Moved all BLOB fields at the end of output, suppress comparison of their IDs. + -- Added query to select FIELDS list of table because main check does not use asterisk + -- and we have to know if DDL of table will have any changes in future. + + set list on; + set blob all; + set count on; + + -- Query for check whether fields list of table was changed: + select rf.rdb$field_name + from rdb$relation_fields rf + where rf.rdb$relation_name = upper('rdb$indices') + order by rf.rdb$field_name; + + -- Main test query: + select + rdb$index_name + ,rdb$relation_name + ,rdb$index_id + ,rdb$unique_flag + ,rdb$segment_count + ,rdb$index_inactive + ,rdb$index_type + ,rdb$system_flag + ,rdb$statistics + ,rdb$foreign_key + ,rdb$description as decriptn_blob_id + ,rdb$expression_blr as expr_blr_blob_id + ,rdb$expression_source as expr_src_blob_id + from rdb$indices + order by rdb$index_name; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$FIELD_NAME RDB$EXPRESSION_BLR + RDB$FIELD_NAME RDB$EXPRESSION_SOURCE + RDB$FIELD_NAME RDB$FOREIGN_KEY + RDB$FIELD_NAME RDB$INDEX_ID + RDB$FIELD_NAME RDB$INDEX_INACTIVE + RDB$FIELD_NAME RDB$INDEX_NAME + RDB$FIELD_NAME RDB$INDEX_TYPE + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$FIELD_NAME RDB$SEGMENT_COUNT + RDB$FIELD_NAME RDB$STATISTICS + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$FIELD_NAME RDB$UNIQUE_FLAG + + Records affected: 13 + + + RDB$INDEX_NAME RDB$INDEX_0 + RDB$RELATION_NAME RDB$RELATIONS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_1 + RDB$RELATION_NAME RDB$RELATIONS + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_10 + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 2 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_11 + RDB$RELATION_NAME RDB$GENERATORS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_12 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_13 + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_14 + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_15 + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$INDEX_ID 3 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 2 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_16 + RDB$RELATION_NAME RDB$FORMATS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 2 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_17 + RDB$RELATION_NAME RDB$FILTERS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 2 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_18 + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 3 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_19 + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_2 + RDB$RELATION_NAME RDB$FIELDS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_20 + RDB$RELATION_NAME RDB$COLLATIONS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_21 + RDB$RELATION_NAME RDB$PROCEDURES + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 2 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_22 + RDB$RELATION_NAME RDB$PROCEDURES + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_23 + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_24 + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_25 + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_26 + RDB$RELATION_NAME RDB$COLLATIONS + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 2 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_27 + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 2 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_28 + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 3 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_29 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_3 + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_30 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_31 + RDB$RELATION_NAME RDB$INDICES + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_32 + RDB$RELATION_NAME RDB$TRANSACTIONS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_33 + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_34 + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_35 + RDB$RELATION_NAME RDB$TRIGGER_MESSAGES + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_36 + RDB$RELATION_NAME RDB$FIELD_DIMENSIONS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_37 + RDB$RELATION_NAME RDB$TYPES + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_38 + RDB$RELATION_NAME RDB$TRIGGERS + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_39 + RDB$RELATION_NAME RDB$ROLES + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_4 + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_40 + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_41 + RDB$RELATION_NAME RDB$INDICES + RDB$INDEX_ID 3 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_42 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 2 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_43 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$INDEX_ID 3 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_44 + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 2 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE 1 + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_45 + RDB$RELATION_NAME RDB$FILTERS + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_46 + RDB$RELATION_NAME RDB$GENERATORS + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_47 + RDB$RELATION_NAME RDB$PACKAGES + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_48 + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_49 + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_5 + RDB$RELATION_NAME RDB$INDICES + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_50 + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$INDEX_ID 3 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 2 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_51 + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$INDEX_ID 3 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 2 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_52 + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_53 + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_54 + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$INDEX_ID 2 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_55 + RDB$RELATION_NAME RDB$PUBLICATIONS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_56 + RDB$RELATION_NAME RDB$PUBLICATION_TABLES + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 2 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_6 + RDB$RELATION_NAME RDB$INDEX_SEGMENTS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 0 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_7 + RDB$RELATION_NAME RDB$SECURITY_CLASSES + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_8 + RDB$RELATION_NAME RDB$TRIGGERS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 1 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + RDB$INDEX_NAME RDB$INDEX_9 + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$INDEX_ID 1 + RDB$UNIQUE_FLAG 1 + RDB$SEGMENT_COUNT 2 + RDB$INDEX_INACTIVE 0 + RDB$INDEX_TYPE + RDB$SYSTEM_FLAG 1 + RDB$STATISTICS + RDB$FOREIGN_KEY + DECRIPTN_BLOB_ID + EXPR_BLR_BLOB_ID + EXPR_SRC_BLOB_ID + + + Records affected: 57 + """ + +@pytest.mark.version('>=4.0') +def test_db_16_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/functional/basic/db/test_17.py b/tests/functional/basic/db/test_17.py new file mode 100644 index 00000000..cc43230d --- /dev/null +++ b/tests/functional/basic/db/test_17.py @@ -0,0 +1,31 @@ +#coding:utf-8 +# +# id: functional.basic.db.17 +# title: Empty DB - RDB$LOG_FILES +# decription: Check for correct content of RDB$LOG_FILES in empty database. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.basic.db.db_17 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select * from RDB$LOG_FILES;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=1.0') +def test_17_1(act_1: Action): + act_1.execute() + diff --git a/tests/functional/basic/db/test_18.py b/tests/functional/basic/db/test_18.py new file mode 100644 index 00000000..49cbf5be --- /dev/null +++ b/tests/functional/basic/db/test_18.py @@ -0,0 +1,724 @@ +#coding:utf-8 +# +# id: functional.basic.db.db_18 +# title: Empty DB - RDB$PAGES +# decription: Check for correct content of RDB$PAGES in empty database. +# +# Database is created with 4K pages. We may add other RDB$PAGES tests for different page sizes. +# tracker_id: +# min_versions: [] +# versions: 3.0, 4.0 +# qmid: functional.basic.db.db_18 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- 30.10.2015. + -- 1. Removed from comparison values of RDB$PAGE_NUMBER because its value (can) differ on Win32 vs Nix64. + -- 2. Added query to select FIELDS list of table because main check does not use asterisk + -- and we have to know if DDL of table will have any changes in future. + + set blob all; + set count on; + set list on; + + -- Query for check whether fields list of table was changed: + select rf.rdb$field_name + from rdb$relation_fields rf + where rf.rdb$relation_name = upper('rdb$pages') + order by rf.rdb$field_name; + + -- Main test query: + select rdb$relation_id, rdb$page_sequence, rdb$page_type + from rdb$pages + order by 1,2,3; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$FIELD_NAME RDB$PAGE_NUMBER + RDB$FIELD_NAME RDB$PAGE_SEQUENCE + RDB$FIELD_NAME RDB$PAGE_TYPE + RDB$FIELD_NAME RDB$RELATION_ID + + Records affected: 4 + + RDB$RELATION_ID 0 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 3 + + RDB$RELATION_ID 0 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 0 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 0 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 9 + + RDB$RELATION_ID 1 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 1 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 2 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 2 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 3 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 3 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 4 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 4 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 5 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 5 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 6 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 6 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 7 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 7 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 8 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 8 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 9 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 9 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 10 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 10 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 11 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 11 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 12 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 12 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 13 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 13 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 14 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 14 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 15 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 15 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 16 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 16 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 17 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 17 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 18 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 18 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 19 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 19 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 20 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 20 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 21 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 21 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 22 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 22 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 23 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 23 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 24 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 24 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 25 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 25 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 26 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 26 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 27 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 27 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 28 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 28 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 29 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 29 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 30 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 30 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 31 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 31 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 32 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 32 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 42 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 42 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 45 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 45 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 47 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 47 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + Records affected: 74 + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_db_18_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + -- 30.10.2015. + -- 1. Removed from comparison values of RDB$PAGE_NUMBER because its value (can) differ on Win32 vs Nix64. + -- 2. Added query to select FIELDS list of table because main check does not use asterisk + -- and we have to know if DDL of table will have any changes in future. + + set blob all; + set count on; + set list on; + + -- Query for check whether fields list of table was changed: + select rf.rdb$field_name + from rdb$relation_fields rf + where rf.rdb$relation_name = upper('rdb$pages') + order by rf.rdb$field_name; + + -- Main test query: + select rdb$relation_id, rdb$page_sequence, rdb$page_type + from rdb$pages + order by 1,2,3; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + RDB$FIELD_NAME RDB$PAGE_NUMBER + RDB$FIELD_NAME RDB$PAGE_SEQUENCE + RDB$FIELD_NAME RDB$PAGE_TYPE + RDB$FIELD_NAME RDB$RELATION_ID + + Records affected: 4 + + + RDB$RELATION_ID 0 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 3 + + RDB$RELATION_ID 0 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 0 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 0 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 9 + + RDB$RELATION_ID 1 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 1 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 2 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 2 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 3 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 3 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 4 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 4 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 5 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 5 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 6 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 6 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 7 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 7 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 8 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 8 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 9 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 9 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 10 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 10 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 11 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 11 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 12 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 12 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 13 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 13 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 14 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 14 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 15 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 15 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 16 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 16 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 17 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 17 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 18 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 18 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 19 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 19 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 20 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 20 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 21 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 21 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 22 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 22 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 23 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 23 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 24 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 24 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 25 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 25 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 26 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 26 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 27 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 27 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 28 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 28 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 29 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 29 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 30 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 30 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 31 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 31 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 32 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 32 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 42 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 42 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 45 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 45 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 47 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 47 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 51 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 51 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + RDB$RELATION_ID 52 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 4 + + RDB$RELATION_ID 52 + RDB$PAGE_SEQUENCE 0 + RDB$PAGE_TYPE 6 + + Records affected: 78 + """ + +@pytest.mark.version('>=4.0') +def test_db_18_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/functional/basic/db/test_19.py b/tests/functional/basic/db/test_19.py new file mode 100644 index 00000000..2a39af6b --- /dev/null +++ b/tests/functional/basic/db/test_19.py @@ -0,0 +1,206 @@ +#coding:utf-8 +# +# id: functional.basic.db.19 +# title: New DB - RDB$PROCEDURE_PARAMETERS +# decription: +# Check for correct content of RDB$PROCEDURE_PARAMETERS in a new database. +# Checked on: +# 2.5.9.27126: OK, 0.485s. +# 3.0.5.33086: OK, 1.000s. +# 4.0.0.1378: OK, 5.078s. +# +# tracker_id: +# min_versions: [] +# versions: 3.0, 4.0 +# qmid: functional.basic.db.db_19 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + select * + from rdb$procedure_parameters + order by rdb$procedure_name,rdb$parameter_name,rdb$parameter_number; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_19_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set list on; + set count on; + select * + from rdb$procedure_parameters + order by rdb$procedure_name,rdb$parameter_name,rdb$parameter_number; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + + RDB$PARAMETER_NAME RDB$DST_OFFSET + RDB$PROCEDURE_NAME TRANSITIONS + RDB$PARAMETER_NUMBER 3 + RDB$PARAMETER_TYPE 1 + RDB$FIELD_SOURCE RDB$TIME_ZONE_OFFSET + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + RDB$DEFAULT_VALUE + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$NULL_FLAG 1 + RDB$PARAMETER_MECHANISM 0 + RDB$FIELD_NAME + RDB$RELATION_NAME + RDB$PACKAGE_NAME RDB$TIME_ZONE_UTIL + + RDB$PARAMETER_NAME RDB$EFFECTIVE_OFFSET + RDB$PROCEDURE_NAME TRANSITIONS + RDB$PARAMETER_NUMBER 4 + RDB$PARAMETER_TYPE 1 + RDB$FIELD_SOURCE RDB$TIME_ZONE_OFFSET + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + RDB$DEFAULT_VALUE + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$NULL_FLAG 1 + RDB$PARAMETER_MECHANISM 0 + RDB$FIELD_NAME + RDB$RELATION_NAME + RDB$PACKAGE_NAME RDB$TIME_ZONE_UTIL + + RDB$PARAMETER_NAME RDB$END_TIMESTAMP + RDB$PROCEDURE_NAME TRANSITIONS + RDB$PARAMETER_NUMBER 1 + RDB$PARAMETER_TYPE 1 + RDB$FIELD_SOURCE RDB$TIMESTAMP_TZ + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + RDB$DEFAULT_VALUE + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$NULL_FLAG 1 + RDB$PARAMETER_MECHANISM 0 + RDB$FIELD_NAME + RDB$RELATION_NAME + RDB$PACKAGE_NAME RDB$TIME_ZONE_UTIL + + RDB$PARAMETER_NAME RDB$FROM_TIMESTAMP + RDB$PROCEDURE_NAME TRANSITIONS + RDB$PARAMETER_NUMBER 1 + RDB$PARAMETER_TYPE 0 + RDB$FIELD_SOURCE RDB$TIMESTAMP_TZ + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + RDB$DEFAULT_VALUE + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$NULL_FLAG 1 + RDB$PARAMETER_MECHANISM 0 + RDB$FIELD_NAME + RDB$RELATION_NAME + RDB$PACKAGE_NAME RDB$TIME_ZONE_UTIL + + RDB$PARAMETER_NAME RDB$START_TIMESTAMP + RDB$PROCEDURE_NAME TRANSITIONS + RDB$PARAMETER_NUMBER 0 + RDB$PARAMETER_TYPE 1 + RDB$FIELD_SOURCE RDB$TIMESTAMP_TZ + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + RDB$DEFAULT_VALUE + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$NULL_FLAG 1 + RDB$PARAMETER_MECHANISM 0 + RDB$FIELD_NAME + RDB$RELATION_NAME + RDB$PACKAGE_NAME RDB$TIME_ZONE_UTIL + + RDB$PARAMETER_NAME RDB$TIME_ZONE_NAME + RDB$PROCEDURE_NAME TRANSITIONS + RDB$PARAMETER_NUMBER 0 + RDB$PARAMETER_TYPE 0 + RDB$FIELD_SOURCE RDB$TIME_ZONE_NAME + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + RDB$DEFAULT_VALUE + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$NULL_FLAG 1 + RDB$PARAMETER_MECHANISM 0 + RDB$FIELD_NAME + RDB$RELATION_NAME + RDB$PACKAGE_NAME RDB$TIME_ZONE_UTIL + + RDB$PARAMETER_NAME RDB$TO_TIMESTAMP + RDB$PROCEDURE_NAME TRANSITIONS + RDB$PARAMETER_NUMBER 2 + RDB$PARAMETER_TYPE 0 + RDB$FIELD_SOURCE RDB$TIMESTAMP_TZ + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + RDB$DEFAULT_VALUE + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$NULL_FLAG 1 + RDB$PARAMETER_MECHANISM 0 + RDB$FIELD_NAME + RDB$RELATION_NAME + RDB$PACKAGE_NAME RDB$TIME_ZONE_UTIL + + RDB$PARAMETER_NAME RDB$ZONE_OFFSET + RDB$PROCEDURE_NAME TRANSITIONS + RDB$PARAMETER_NUMBER 2 + RDB$PARAMETER_TYPE 1 + RDB$FIELD_SOURCE RDB$TIME_ZONE_OFFSET + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + RDB$DEFAULT_VALUE + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$NULL_FLAG 1 + RDB$PARAMETER_MECHANISM 0 + RDB$FIELD_NAME + RDB$RELATION_NAME + RDB$PACKAGE_NAME RDB$TIME_ZONE_UTIL + + Records affected: 8 + """ + +@pytest.mark.version('>=4.0') +def test_19_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/functional/basic/db/test_20.py b/tests/functional/basic/db/test_20.py new file mode 100644 index 00000000..03650788 --- /dev/null +++ b/tests/functional/basic/db/test_20.py @@ -0,0 +1,96 @@ +#coding:utf-8 +# +# id: functional.basic.db.20 +# title: New database: content of RDB$PROCEDURES +# decription: +# Check for correct content of RDB$PROCEDURES in a new database. +# 15.01.2019. Split 'firebird_version' because 4.0 now has SP in new database. +# +# tracker_id: +# min_versions: [] +# versions: 3.0, 4.0 +# qmid: functional.basic.db.db_20 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set count on; + set list on; + set blob all; + select p.* + from rdb$procedures p + order by p.rdb$procedure_id; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_20_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set count on; + set list on; + set blob all; + select p.* + from rdb$procedures p + order by p.rdb$procedure_id; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + RDB$PROCEDURE_NAME TRANSITIONS + RDB$PROCEDURE_ID 1 + RDB$PROCEDURE_INPUTS 3 + RDB$PROCEDURE_OUTPUTS 5 + RDB$DESCRIPTION + RDB$PROCEDURE_SOURCE + RDB$PROCEDURE_BLR + RDB$SECURITY_CLASS + RDB$OWNER_NAME SYSDBA + RDB$RUNTIME + RDB$SYSTEM_FLAG 1 + RDB$PROCEDURE_TYPE 1 + RDB$VALID_BLR 1 + RDB$DEBUG_INFO + RDB$ENGINE_NAME SYSTEM + RDB$ENTRYPOINT + RDB$PACKAGE_NAME RDB$TIME_ZONE_UTIL + RDB$PRIVATE_FLAG 0 + RDB$SQL_SECURITY + + Records affected: 1 + """ + +@pytest.mark.version('>=4.0') +def test_20_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/functional/basic/db/test_21.py b/tests/functional/basic/db/test_21.py new file mode 100644 index 00000000..fdf3d258 --- /dev/null +++ b/tests/functional/basic/db/test_21.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: functional.basic.db.21 +# title: Empty DB - RDB$REF_CONSTRAINTS +# decription: Check for correct content of RDB$REF_CONSTRAINTS in empty database. +# tracker_id: +# min_versions: [] +# versions: 2.5 +# qmid: functional.basic.db.db_21 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + select * from rdb$ref_constraints order by rdb$constraint_name; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ + +@pytest.mark.version('>=2.5') +def test_21_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/basic/db/test_22.py b/tests/functional/basic/db/test_22.py new file mode 100644 index 00000000..b01cdd90 --- /dev/null +++ b/tests/functional/basic/db/test_22.py @@ -0,0 +1,470 @@ +#coding:utf-8 +# +# id: functional.basic.db.db_22 +# title: Empty DB - RDB$RELATION_CONSTRAINTS +# decription: Check for correct content of RDB$RELATION_CONSTRAINTS in empty database. +# tracker_id: +# min_versions: [] +# versions: 3.0, 4.0 +# qmid: functional.basic.db.db_22 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('RDB\\$CONSTRAINT_NAME[\\s]+RDB\\$INDEX.*', 'RDB\\$CONSTRAINT_NAME RDB\\$INDEX'), ('RDB\\$INDEX_NAME[\\s]+RDB\\$INDEX.*', 'RDB\\$INDEX_NAME RDB\\$INDEX')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + select rc.* + from rdb$relation_constraints rc + order by lpad( trim(replace(rdb$constraint_name, 'RDB$INDEX_', '')),31,'0'); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$CONSTRAINT_NAME RDB$INDEX_0 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$RELATIONS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_0 + + RDB$CONSTRAINT_NAME RDB$INDEX_2 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$FIELDS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_2 + + RDB$CONSTRAINT_NAME RDB$INDEX_5 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$INDICES + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_5 + + RDB$CONSTRAINT_NAME RDB$INDEX_7 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$SECURITY_CLASSES + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_7 + + RDB$CONSTRAINT_NAME RDB$INDEX_8 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$TRIGGERS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_8 + + RDB$CONSTRAINT_NAME RDB$INDEX_9 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_9 + + RDB$CONSTRAINT_NAME RDB$INDEX_11 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$GENERATORS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_11 + + RDB$CONSTRAINT_NAME RDB$INDEX_12 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_12 + + RDB$CONSTRAINT_NAME RDB$INDEX_13 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_13 + + RDB$CONSTRAINT_NAME RDB$INDEX_15 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_15 + + RDB$CONSTRAINT_NAME RDB$INDEX_17 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$FILTERS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_17 + + RDB$CONSTRAINT_NAME RDB$INDEX_18 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_18 + + RDB$CONSTRAINT_NAME RDB$INDEX_19 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_19 + + RDB$CONSTRAINT_NAME RDB$INDEX_20 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$COLLATIONS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_20 + + RDB$CONSTRAINT_NAME RDB$INDEX_21 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$PROCEDURES + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_21 + + RDB$CONSTRAINT_NAME RDB$INDEX_22 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$PROCEDURES + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_22 + + RDB$CONSTRAINT_NAME RDB$INDEX_23 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_23 + + RDB$CONSTRAINT_NAME RDB$INDEX_24 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_24 + + RDB$CONSTRAINT_NAME RDB$INDEX_25 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_25 + + RDB$CONSTRAINT_NAME RDB$INDEX_26 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$COLLATIONS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_26 + + RDB$CONSTRAINT_NAME RDB$INDEX_32 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$TRANSACTIONS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_32 + + RDB$CONSTRAINT_NAME RDB$INDEX_39 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$ROLES + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_39 + + RDB$CONSTRAINT_NAME RDB$INDEX_44 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_44 + + RDB$CONSTRAINT_NAME RDB$INDEX_45 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$FILTERS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_45 + + RDB$CONSTRAINT_NAME RDB$INDEX_46 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$GENERATORS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_46 + + RDB$CONSTRAINT_NAME RDB$INDEX_47 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$PACKAGES + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_47 + + RDB$CONSTRAINT_NAME RDB$INDEX_53 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_53 + Records affected: 27 + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_db_22_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [('RDB\\$CONSTRAINT_NAME[\\s]+RDB\\$INDEX.*', 'RDB\\$CONSTRAINT_NAME RDB\\$INDEX'), ('RDB\\$INDEX_NAME[\\s]+RDB\\$INDEX.*', 'RDB\\$INDEX_NAME RDB\\$INDEX')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set list on; + set count on; + select rc.* + from rdb$relation_constraints rc + order by lpad( trim(replace(rdb$constraint_name, 'RDB$INDEX_', '')),31,'0'); + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + RDB$CONSTRAINT_NAME RDB$INDEX_0 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$RELATIONS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_0 + + RDB$CONSTRAINT_NAME RDB$INDEX_2 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$FIELDS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_2 + + RDB$CONSTRAINT_NAME RDB$INDEX_5 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$INDICES + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_5 + + RDB$CONSTRAINT_NAME RDB$INDEX_7 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$SECURITY_CLASSES + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_7 + + RDB$CONSTRAINT_NAME RDB$INDEX_8 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$TRIGGERS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_8 + + RDB$CONSTRAINT_NAME RDB$INDEX_9 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_9 + + RDB$CONSTRAINT_NAME RDB$INDEX_11 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$GENERATORS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_11 + + RDB$CONSTRAINT_NAME RDB$INDEX_12 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_12 + + RDB$CONSTRAINT_NAME RDB$INDEX_13 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_13 + + RDB$CONSTRAINT_NAME RDB$INDEX_15 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_15 + + RDB$CONSTRAINT_NAME RDB$INDEX_17 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$FILTERS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_17 + + RDB$CONSTRAINT_NAME RDB$INDEX_18 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_18 + + RDB$CONSTRAINT_NAME RDB$INDEX_19 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_19 + + RDB$CONSTRAINT_NAME RDB$INDEX_20 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$COLLATIONS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_20 + + RDB$CONSTRAINT_NAME RDB$INDEX_21 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$PROCEDURES + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_21 + + RDB$CONSTRAINT_NAME RDB$INDEX_22 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$PROCEDURES + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_22 + + RDB$CONSTRAINT_NAME RDB$INDEX_23 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_23 + + RDB$CONSTRAINT_NAME RDB$INDEX_24 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_24 + + RDB$CONSTRAINT_NAME RDB$INDEX_25 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_25 + + RDB$CONSTRAINT_NAME RDB$INDEX_26 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$COLLATIONS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_26 + + RDB$CONSTRAINT_NAME RDB$INDEX_32 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$TRANSACTIONS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_32 + + RDB$CONSTRAINT_NAME RDB$INDEX_39 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$ROLES + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_39 + + RDB$CONSTRAINT_NAME RDB$INDEX_44 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_44 + + RDB$CONSTRAINT_NAME RDB$INDEX_45 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$FILTERS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_45 + + RDB$CONSTRAINT_NAME RDB$INDEX_46 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$GENERATORS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_46 + + RDB$CONSTRAINT_NAME RDB$INDEX_47 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$PACKAGES + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_47 + + RDB$CONSTRAINT_NAME RDB$INDEX_53 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_53 + + RDB$CONSTRAINT_NAME RDB$INDEX_54 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_54 + + RDB$CONSTRAINT_NAME RDB$INDEX_55 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$PUBLICATIONS + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_55 + + RDB$CONSTRAINT_NAME RDB$INDEX_56 + RDB$CONSTRAINT_TYPE UNIQUE + RDB$RELATION_NAME RDB$PUBLICATION_TABLES + RDB$DEFERRABLE NO + RDB$INITIALLY_DEFERRED NO + RDB$INDEX_NAME RDB$INDEX_56 + + + Records affected: 30 + """ + +@pytest.mark.version('>=4.0') +def test_db_22_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/functional/basic/db/test_23.py b/tests/functional/basic/db/test_23.py new file mode 100644 index 00000000..6e5766f9 --- /dev/null +++ b/tests/functional/basic/db/test_23.py @@ -0,0 +1,2423 @@ +#coding:utf-8 +# +# id: functional.basic.db.db_23 +# title: Empty DB - RDB$RELATIONS +# decription: Check for correct content of RDB$RELATIONS in empty database. +# tracker_id: +# min_versions: ['2.5.7'] +# versions: 3.0, 4.0 +# qmid: functional.basic.db.db_23 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('VIEW_BLR_BLOB_ID.*', ''), ('VIEW_SRC_BLOB_ID.*', ''), ('DESCR_BLOB_ID.*', ''), ('RUNTIME_BLOB_ID.*', ''), ('EXT_DESCR_BLOB_ID.*', ''), ('RDB\\$TRIGGER_.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- 28.10.2015. + -- 1. Removed from output BLOB IDs for fields rdb$security_class and rdb$default_class - they changes very often. + -- 2. Added blocks to 'substitution' section to: + -- 2.1 Suppress possible differences when check IDs of all BLOB fields. + -- 2.2. Ignore values of IDs in lines like "trigger_name: RDB$TRIGGER_**". + -- 3. Added query to select FIELDS list of table because main check does not use asterisk + -- and we have to know if DDL of table will have any changes in future. + + set list on; + set blob all; + set count on; + + -- Query for check whether fields list of table was changed: + select rf.rdb$field_name + from rdb$relation_fields rf + where rf.rdb$relation_name = upper('rdb$relations') + order by rf.rdb$field_name; + + -- Main test query: + select + rdb$relation_id + ,rdb$relation_name + ,rdb$system_flag + ,rdb$dbkey_length + ,rdb$format + ,rdb$field_id + ,rdb$flags + ,rdb$relation_type + ,rdb$owner_name + ,rdb$external_file + ,rdb$view_blr as view_blr_blob_id + ,rdb$view_source as view_src_blob_id + ,rdb$description as descr_blob_id + ,rdb$runtime as runtime_blob_id + ,rdb$external_description as ext_descr_blob_id + --,rdb$security_class + --,rdb$default_class + from rdb$relations + order by rdb$relation_id; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + + RDB$FIELD_NAME RDB$DBKEY_LENGTH + + RDB$FIELD_NAME RDB$DEFAULT_CLASS + + RDB$FIELD_NAME RDB$DESCRIPTION + + RDB$FIELD_NAME RDB$EXTERNAL_DESCRIPTION + + RDB$FIELD_NAME RDB$EXTERNAL_FILE + + RDB$FIELD_NAME RDB$FIELD_ID + + RDB$FIELD_NAME RDB$FLAGS + + RDB$FIELD_NAME RDB$FORMAT + + RDB$FIELD_NAME RDB$OWNER_NAME + + RDB$FIELD_NAME RDB$RELATION_ID + + RDB$FIELD_NAME RDB$RELATION_NAME + + RDB$FIELD_NAME RDB$RELATION_TYPE + + RDB$FIELD_NAME RDB$RUNTIME + + RDB$FIELD_NAME RDB$SECURITY_CLASS + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + + RDB$FIELD_NAME RDB$VIEW_BLR + + RDB$FIELD_NAME RDB$VIEW_SOURCE + + + Records affected: 17 + + RDB$RELATION_ID 0 + RDB$RELATION_NAME RDB$PAGES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 4 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 1 + RDB$RELATION_NAME RDB$DATABASE + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 5 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 2 + RDB$RELATION_NAME RDB$FIELDS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 30 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID 6:1e8 + Field id: 0 + name: RDB$FIELD_NAME + Field id: 1 + name: RDB$QUERY_NAME + Field id: 2 + name: RDB$VALIDATION_BLR + Field id: 3 + name: RDB$VALIDATION_SOURCE + Field id: 4 + name: RDB$COMPUTED_BLR + Field id: 5 + name: RDB$COMPUTED_SOURCE + Field id: 6 + name: RDB$DEFAULT_VALUE + Field id: 7 + name: RDB$DEFAULT_SOURCE + Field id: 8 + name: RDB$FIELD_LENGTH + Field id: 9 + name: RDB$FIELD_SCALE + Field id: 10 + name: RDB$FIELD_TYPE + Field id: 11 + name: RDB$FIELD_SUB_TYPE + Field id: 12 + name: RDB$MISSING_VALUE + Field id: 13 + name: RDB$MISSING_SOURCE + Field id: 14 + name: RDB$DESCRIPTION + Field id: 15 + name: RDB$SYSTEM_FLAG + field_not_null + Field id: 16 + name: RDB$QUERY_HEADER + Field id: 17 + name: RDB$SEGMENT_LENGTH + Field id: 18 + name: RDB$EDIT_STRING + Field id: 19 + name: RDB$EXTERNAL_LENGTH + Field id: 20 + name: RDB$EXTERNAL_SCALE + Field id: 21 + name: RDB$EXTERNAL_TYPE + Field id: 22 + name: RDB$DIMENSIONS + Field id: 23 + name: RDB$NULL_FLAG + Field id: 24 + name: RDB$CHARACTER_LENGTH + Field id: 25 + name: RDB$COLLATION_ID + Field id: 26 + name: RDB$CHARACTER_SET_ID + Field id: 27 + name: RDB$FIELD_PRECISION + Field id: 28 + name: RDB$SECURITY_CLASS + Field id: 29 + name: RDB$OWNER_NAME + trigger_name: RDB$TRIGGER_36 + + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 3 + RDB$RELATION_NAME RDB$INDEX_SEGMENTS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 4 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID 6:1e5 + Field id: 0 + name: RDB$INDEX_NAME + Field id: 1 + name: RDB$FIELD_NAME + Field id: 2 + name: RDB$FIELD_POSITION + Field id: 3 + name: RDB$STATISTICS + trigger_name: RDB$TRIGGER_17 + trigger_name: RDB$TRIGGER_18 + + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 4 + RDB$RELATION_NAME RDB$INDICES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 13 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID 6:1e6 + Field id: 0 + name: RDB$INDEX_NAME + Field id: 1 + name: RDB$RELATION_NAME + Field id: 2 + name: RDB$INDEX_ID + Field id: 3 + name: RDB$UNIQUE_FLAG + Field id: 4 + name: RDB$DESCRIPTION + Field id: 5 + name: RDB$SEGMENT_COUNT + Field id: 6 + name: RDB$INDEX_INACTIVE + Field id: 7 + name: RDB$INDEX_TYPE + Field id: 8 + name: RDB$FOREIGN_KEY + Field id: 9 + name: RDB$SYSTEM_FLAG + field_not_null + Field id: 10 + name: RDB$EXPRESSION_BLR + Field id: 11 + name: RDB$EXPRESSION_SOURCE + Field id: 12 + name: RDB$STATISTICS + trigger_name: RDB$TRIGGER_19 + trigger_name: RDB$TRIGGER_20 + + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 5 + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 21 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID 6:1e7 + Field id: 0 + name: RDB$FIELD_NAME + Field id: 1 + name: RDB$RELATION_NAME + Field id: 2 + name: RDB$FIELD_SOURCE + Field id: 3 + name: RDB$QUERY_NAME + Field id: 4 + name: RDB$BASE_FIELD + Field id: 5 + name: RDB$EDIT_STRING + Field id: 6 + name: RDB$FIELD_POSITION + Field id: 7 + name: RDB$QUERY_HEADER + Field id: 8 + name: RDB$UPDATE_FLAG + Field id: 9 + name: RDB$FIELD_ID + Field id: 10 + name: RDB$VIEW_CONTEXT + Field id: 11 + name: RDB$DESCRIPTION + Field id: 12 + name: RDB$DEFAULT_VALUE + Field id: 13 + name: RDB$SYSTEM_FLAG + field_not_null + Field id: 14 + name: RDB$SECURITY_CLASS + Field id: 15 + name: RDB$COMPLEX_NAME + Field id: 16 + name: RDB$NULL_FLAG + Field id: 17 + name: RDB$DEFAULT_SOURCE + Field id: 18 + name: RDB$COLLATION_ID + Field id: 19 + name: RDB$GENERATOR_NAME + Field id: 20 + name: RDB$IDENTITY_TYPE + trigger_name: RDB$TRIGGER_23 + trigger_name: RDB$TRIGGER_24 + trigger_name: RDB$TRIGGER_27 + + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 6 + RDB$RELATION_NAME RDB$RELATIONS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 17 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 7 + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 6 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 8 + RDB$RELATION_NAME RDB$FORMATS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 3 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 9 + RDB$RELATION_NAME RDB$SECURITY_CLASSES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 3 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 10 + RDB$RELATION_NAME RDB$FILES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 6 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 11 + RDB$RELATION_NAME RDB$TYPES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 5 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 12 + RDB$RELATION_NAME RDB$TRIGGERS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 14 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID 6:1e1 + Field id: 0 + name: RDB$TRIGGER_NAME + Field id: 1 + name: RDB$RELATION_NAME + Field id: 2 + name: RDB$TRIGGER_SEQUENCE + Field id: 3 + name: RDB$TRIGGER_TYPE + Field id: 4 + name: RDB$TRIGGER_SOURCE + Field id: 5 + name: RDB$TRIGGER_BLR + Field id: 6 + name: RDB$DESCRIPTION + Field id: 7 + name: RDB$TRIGGER_INACTIVE + Field id: 8 + name: RDB$SYSTEM_FLAG + field_not_null + Field id: 9 + name: RDB$FLAGS + Field id: 10 + name: RDB$VALID_BLR + Field id: 11 + name: RDB$DEBUG_INFO + Field id: 12 + name: RDB$ENGINE_NAME + Field id: 13 + name: RDB$ENTRYPOINT + trigger_name: RDB$TRIGGER_2 + trigger_name: RDB$TRIGGER_21 + trigger_name: RDB$TRIGGER_22 + trigger_name: RDB$TRIGGER_3 + + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 13 + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 6 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 14 + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 20 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 15 + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 22 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 16 + RDB$RELATION_NAME RDB$FILTERS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 9 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 17 + RDB$RELATION_NAME RDB$TRIGGER_MESSAGES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 3 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 18 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 8 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID 6:1e0 + Field id: 0 + name: RDB$USER + Field id: 1 + name: RDB$GRANTOR + Field id: 2 + name: RDB$PRIVILEGE + Field id: 3 + name: RDB$GRANT_OPTION + Field id: 4 + name: RDB$RELATION_NAME + Field id: 5 + name: RDB$FIELD_NAME + Field id: 6 + name: RDB$USER_TYPE + Field id: 7 + name: RDB$OBJECT_TYPE + trigger_name: RDB$TRIGGER_1 + trigger_name: RDB$TRIGGER_31 + trigger_name: RDB$TRIGGER_32 + trigger_name: RDB$TRIGGER_33 + trigger_name: RDB$TRIGGER_8 + trigger_name: RDB$TRIGGER_9 + + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 19 + RDB$RELATION_NAME RDB$TRANSACTIONS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 4 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 20 + RDB$RELATION_NAME RDB$GENERATORS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 8 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 21 + RDB$RELATION_NAME RDB$FIELD_DIMENSIONS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 4 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 22 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 6 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID 6:1e2 + Field id: 0 + name: RDB$CONSTRAINT_NAME + Field id: 1 + name: RDB$CONSTRAINT_TYPE + Field id: 2 + name: RDB$RELATION_NAME + Field id: 3 + name: RDB$DEFERRABLE + default_value: + blr_version5, + blr_literal, blr_text2, 2,0, 2,0, 'N','O', + blr_eoc + Field id: 4 + name: RDB$INITIALLY_DEFERRED + default_value: + blr_version5, + blr_literal, blr_text2, 2,0, 2,0, 'N','O', + blr_eoc + Field id: 5 + name: RDB$INDEX_NAME + trigger_name: RDB$TRIGGER_10 + trigger_name: RDB$TRIGGER_11 + trigger_name: RDB$TRIGGER_25 + trigger_name: RDB$TRIGGER_26 + trigger_name: RDB$TRIGGER_34 + + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 23 + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 5 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID 6:1e3 + Field id: 0 + name: RDB$CONSTRAINT_NAME + Field id: 1 + name: RDB$CONST_NAME_UQ + Field id: 2 + name: RDB$MATCH_OPTION + default_value: + blr_version5, + blr_literal, blr_text2, 2,0, 4,0, 'F','U','L','L', + blr_eoc + Field id: 3 + name: RDB$UPDATE_RULE + default_value: + blr_version5, + blr_literal, blr_text2, 2,0, 8,0, 'R','E','S','T','R','I','C','T', + blr_eoc + Field id: 4 + name: RDB$DELETE_RULE + default_value: + blr_version5, + blr_literal, blr_text2, 2,0, 8,0, 'R','E','S','T','R','I','C','T', + blr_eoc + trigger_name: RDB$TRIGGER_12 + trigger_name: RDB$TRIGGER_13 + + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 24 + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 2 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID 6:1e4 + Field id: 0 + name: RDB$CONSTRAINT_NAME + Field id: 1 + name: RDB$TRIGGER_NAME + trigger_name: RDB$TRIGGER_14 + trigger_name: RDB$TRIGGER_15 + trigger_name: RDB$TRIGGER_16 + trigger_name: RDB$TRIGGER_35 + + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 25 + RDB$RELATION_NAME RDB$LOG_FILES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 6 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 26 + RDB$RELATION_NAME RDB$PROCEDURES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 18 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 27 + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 15 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 28 + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 11 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 29 + RDB$RELATION_NAME RDB$COLLATIONS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 11 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 30 + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 7 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 31 + RDB$RELATION_NAME RDB$ROLES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 5 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 32 + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 6 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 33 + RDB$RELATION_NAME MON$DATABASE + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 22 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 34 + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 20 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 35 + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 13 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 36 + RDB$RELATION_NAME MON$STATEMENTS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 8 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 37 + RDB$RELATION_NAME MON$CALL_STACK + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 10 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 38 + RDB$RELATION_NAME MON$IO_STATS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 6 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 39 + RDB$RELATION_NAME MON$RECORD_STATS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 16 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 40 + RDB$RELATION_NAME MON$CONTEXT_VARIABLES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 4 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 41 + RDB$RELATION_NAME MON$MEMORY_USAGE + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 6 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 42 + RDB$RELATION_NAME RDB$PACKAGES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 8 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 43 + RDB$RELATION_NAME SEC$USERS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 8 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 44 + RDB$RELATION_NAME SEC$USER_ATTRIBUTES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 4 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 45 + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 10 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 46 + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 8 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 47 + RDB$RELATION_NAME RDB$DB_CREATORS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 2 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 48 + RDB$RELATION_NAME SEC$DB_CREATORS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 2 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 49 + RDB$RELATION_NAME MON$TABLE_STATS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 4 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + + Records affected: 50 + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_db_23_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [('VIEW_BLR_BLOB_ID.*', ''), ('VIEW_SRC_BLOB_ID.*', ''), ('DESCR_BLOB_ID.*', ''), ('RUNTIME_BLOB_ID.*', ''), ('EXT_DESCR_BLOB_ID.*', ''), ('RDB\\$TRIGGER_.*', '')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + -- 28.10.2015. + -- 1. Removed from output BLOB IDs for fields rdb$security_class and rdb$default_class - they changes very often. + -- 2. Added blocks to 'substitution' section to: + -- 2.1 Suppress possible differences when check IDs of all BLOB fields. + -- 2.2. Ignore values of IDs in lines like "trigger_name: RDB$TRIGGER_**". + -- 3. Added query to select FIELDS list of table because main check does not use asterisk + -- and we have to know if DDL of table will have any changes in future. + + set list on; + set blob all; + set count on; + + -- Query for check whether fields list of table was changed: + select rf.rdb$field_name + from rdb$relation_fields rf + where rf.rdb$relation_name = upper('rdb$relations') + order by rf.rdb$field_name; + + -- Main test query. + -- NB: rdb$relation_name is unique column, see DDL: + -- ALTER TABLE RDB$RELATIONS ADD CONSTRAINT RDB$INDEX_0 UNIQUE (RDB$RELATION_NAME); + select + rdb$relation_id + ,rdb$relation_name + ,rdb$system_flag + ,rdb$dbkey_length + ,rdb$format + ,rdb$field_id + ,rdb$flags + ,rdb$relation_type + ,rdb$owner_name + ,rdb$external_file + ,rdb$view_blr as view_blr_blob_id + ,rdb$view_source as view_src_blob_id + ,rdb$description as descr_blob_id + ,rdb$runtime as runtime_blob_id + ,rdb$external_description as ext_descr_blob_id + --,rdb$security_class + --,rdb$default_class + from rdb$relations + order by RDB$RELATION_NAME; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + + RDB$FIELD_NAME RDB$DBKEY_LENGTH + + RDB$FIELD_NAME RDB$DEFAULT_CLASS + + RDB$FIELD_NAME RDB$DESCRIPTION + + RDB$FIELD_NAME RDB$EXTERNAL_DESCRIPTION + + RDB$FIELD_NAME RDB$EXTERNAL_FILE + + RDB$FIELD_NAME RDB$FIELD_ID + + RDB$FIELD_NAME RDB$FLAGS + + RDB$FIELD_NAME RDB$FORMAT + + RDB$FIELD_NAME RDB$OWNER_NAME + + RDB$FIELD_NAME RDB$RELATION_ID + + RDB$FIELD_NAME RDB$RELATION_NAME + + RDB$FIELD_NAME RDB$RELATION_TYPE + + RDB$FIELD_NAME RDB$RUNTIME + + RDB$FIELD_NAME RDB$SECURITY_CLASS + + RDB$FIELD_NAME RDB$SQL_SECURITY + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + + RDB$FIELD_NAME RDB$VIEW_BLR + + RDB$FIELD_NAME RDB$VIEW_SOURCE + + + Records affected: 18 + + RDB$RELATION_ID 34 + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 26 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 37 + RDB$RELATION_NAME MON$CALL_STACK + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 10 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 40 + RDB$RELATION_NAME MON$CONTEXT_VARIABLES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 4 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 33 + RDB$RELATION_NAME MON$DATABASE + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 28 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 38 + RDB$RELATION_NAME MON$IO_STATS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 6 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 41 + RDB$RELATION_NAME MON$MEMORY_USAGE + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 6 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 39 + RDB$RELATION_NAME MON$RECORD_STATS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 17 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 36 + RDB$RELATION_NAME MON$STATEMENTS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 10 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 49 + RDB$RELATION_NAME MON$TABLE_STATS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 4 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 35 + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 13 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 45 + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 10 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 32 + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 6 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 28 + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 11 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 24 + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 2 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID 6:1e4 + Field id: 0 + name: RDB$CONSTRAINT_NAME + Field id: 1 + name: RDB$TRIGGER_NAME + trigger_name: RDB$TRIGGER_14 + trigger_name: RDB$TRIGGER_15 + trigger_name: RDB$TRIGGER_35 + trigger_name: RDB$TRIGGER_16 + + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 29 + RDB$RELATION_NAME RDB$COLLATIONS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 11 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 53 + RDB$RELATION_NAME RDB$CONFIG + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 6 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 1 + RDB$RELATION_NAME RDB$DATABASE + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 6 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 47 + RDB$RELATION_NAME RDB$DB_CREATORS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 2 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 13 + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 6 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 30 + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 7 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 2 + RDB$RELATION_NAME RDB$FIELDS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 30 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID 6:1e8 + Field id: 0 + name: RDB$FIELD_NAME + Field id: 1 + name: RDB$QUERY_NAME + Field id: 2 + name: RDB$VALIDATION_BLR + Field id: 3 + name: RDB$VALIDATION_SOURCE + Field id: 4 + name: RDB$COMPUTED_BLR + Field id: 5 + name: RDB$COMPUTED_SOURCE + Field id: 6 + name: RDB$DEFAULT_VALUE + Field id: 7 + name: RDB$DEFAULT_SOURCE + Field id: 8 + name: RDB$FIELD_LENGTH + Field id: 9 + name: RDB$FIELD_SCALE + Field id: 10 + name: RDB$FIELD_TYPE + Field id: 11 + name: RDB$FIELD_SUB_TYPE + Field id: 12 + name: RDB$MISSING_VALUE + Field id: 13 + name: RDB$MISSING_SOURCE + Field id: 14 + name: RDB$DESCRIPTION + Field id: 15 + name: RDB$SYSTEM_FLAG + field_not_null + Field id: 16 + name: RDB$QUERY_HEADER + Field id: 17 + name: RDB$SEGMENT_LENGTH + Field id: 18 + name: RDB$EDIT_STRING + Field id: 19 + name: RDB$EXTERNAL_LENGTH + Field id: 20 + name: RDB$EXTERNAL_SCALE + Field id: 21 + name: RDB$EXTERNAL_TYPE + Field id: 22 + name: RDB$DIMENSIONS + Field id: 23 + name: RDB$NULL_FLAG + Field id: 24 + name: RDB$CHARACTER_LENGTH + Field id: 25 + name: RDB$COLLATION_ID + Field id: 26 + name: RDB$CHARACTER_SET_ID + Field id: 27 + name: RDB$FIELD_PRECISION + Field id: 28 + name: RDB$SECURITY_CLASS + Field id: 29 + name: RDB$OWNER_NAME + trigger_name: RDB$TRIGGER_36 + + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 21 + RDB$RELATION_NAME RDB$FIELD_DIMENSIONS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 4 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 10 + RDB$RELATION_NAME RDB$FILES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 6 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 16 + RDB$RELATION_NAME RDB$FILTERS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 9 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 8 + RDB$RELATION_NAME RDB$FORMATS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 3 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 14 + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 21 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 15 + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 22 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 20 + RDB$RELATION_NAME RDB$GENERATORS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 8 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 3 + RDB$RELATION_NAME RDB$INDEX_SEGMENTS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 4 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID 6:1e5 + Field id: 0 + name: RDB$INDEX_NAME + Field id: 1 + name: RDB$FIELD_NAME + Field id: 2 + name: RDB$FIELD_POSITION + Field id: 3 + name: RDB$STATISTICS + trigger_name: RDB$TRIGGER_17 + trigger_name: RDB$TRIGGER_18 + + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 4 + RDB$RELATION_NAME RDB$INDICES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 13 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID 6:1e6 + Field id: 0 + name: RDB$INDEX_NAME + Field id: 1 + name: RDB$RELATION_NAME + Field id: 2 + name: RDB$INDEX_ID + Field id: 3 + name: RDB$UNIQUE_FLAG + Field id: 4 + name: RDB$DESCRIPTION + Field id: 5 + name: RDB$SEGMENT_COUNT + Field id: 6 + name: RDB$INDEX_INACTIVE + Field id: 7 + name: RDB$INDEX_TYPE + Field id: 8 + name: RDB$FOREIGN_KEY + Field id: 9 + name: RDB$SYSTEM_FLAG + field_not_null + Field id: 10 + name: RDB$EXPRESSION_BLR + Field id: 11 + name: RDB$EXPRESSION_SOURCE + Field id: 12 + name: RDB$STATISTICS + trigger_name: RDB$TRIGGER_20 + trigger_name: RDB$TRIGGER_19 + + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 25 + RDB$RELATION_NAME RDB$LOG_FILES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 6 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 42 + RDB$RELATION_NAME RDB$PACKAGES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 9 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 0 + RDB$RELATION_NAME RDB$PAGES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 4 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 26 + RDB$RELATION_NAME RDB$PROCEDURES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 19 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 27 + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 15 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 51 + RDB$RELATION_NAME RDB$PUBLICATIONS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 5 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 52 + RDB$RELATION_NAME RDB$PUBLICATION_TABLES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 2 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 23 + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 5 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID 6:1e3 + Field id: 0 + name: RDB$CONSTRAINT_NAME + Field id: 1 + name: RDB$CONST_NAME_UQ + Field id: 2 + name: RDB$MATCH_OPTION + default_value: + blr_version5, + blr_literal, blr_text2, 2,0, 4,0, 'F','U','L','L', + blr_eoc + Field id: 3 + name: RDB$UPDATE_RULE + default_value: + blr_version5, + blr_literal, blr_text2, 2,0, 8,0, 'R','E','S','T','R','I','C','T', + blr_eoc + Field id: 4 + name: RDB$DELETE_RULE + default_value: + blr_version5, + blr_literal, blr_text2, 2,0, 8,0, 'R','E','S','T','R','I','C','T', + blr_eoc + trigger_name: RDB$TRIGGER_12 + trigger_name: RDB$TRIGGER_13 + + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 6 + RDB$RELATION_NAME RDB$RELATIONS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 18 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 22 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 6 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID 6:1e2 + Field id: 0 + name: RDB$CONSTRAINT_NAME + Field id: 1 + name: RDB$CONSTRAINT_TYPE + Field id: 2 + name: RDB$RELATION_NAME + Field id: 3 + name: RDB$DEFERRABLE + default_value: + blr_version5, + blr_literal, blr_text2, 2,0, 2,0, 'N','O', + blr_eoc + Field id: 4 + name: RDB$INITIALLY_DEFERRED + default_value: + blr_version5, + blr_literal, blr_text2, 2,0, 2,0, 'N','O', + blr_eoc + Field id: 5 + name: RDB$INDEX_NAME + trigger_name: RDB$TRIGGER_10 + trigger_name: RDB$TRIGGER_11 + trigger_name: RDB$TRIGGER_34 + trigger_name: RDB$TRIGGER_25 + trigger_name: RDB$TRIGGER_26 + + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 5 + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 21 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID 6:1e7 + Field id: 0 + name: RDB$FIELD_NAME + Field id: 1 + name: RDB$RELATION_NAME + Field id: 2 + name: RDB$FIELD_SOURCE + Field id: 3 + name: RDB$QUERY_NAME + Field id: 4 + name: RDB$BASE_FIELD + Field id: 5 + name: RDB$EDIT_STRING + Field id: 6 + name: RDB$FIELD_POSITION + Field id: 7 + name: RDB$QUERY_HEADER + Field id: 8 + name: RDB$UPDATE_FLAG + Field id: 9 + name: RDB$FIELD_ID + Field id: 10 + name: RDB$VIEW_CONTEXT + Field id: 11 + name: RDB$DESCRIPTION + Field id: 12 + name: RDB$DEFAULT_VALUE + Field id: 13 + name: RDB$SYSTEM_FLAG + field_not_null + Field id: 14 + name: RDB$SECURITY_CLASS + Field id: 15 + name: RDB$COMPLEX_NAME + Field id: 16 + name: RDB$NULL_FLAG + Field id: 17 + name: RDB$DEFAULT_SOURCE + Field id: 18 + name: RDB$COLLATION_ID + Field id: 19 + name: RDB$GENERATOR_NAME + Field id: 20 + name: RDB$IDENTITY_TYPE + trigger_name: RDB$TRIGGER_23 + trigger_name: RDB$TRIGGER_24 + trigger_name: RDB$TRIGGER_27 + + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 31 + RDB$RELATION_NAME RDB$ROLES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 6 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 9 + RDB$RELATION_NAME RDB$SECURITY_CLASSES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 3 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 50 + RDB$RELATION_NAME RDB$TIME_ZONES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 2 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 19 + RDB$RELATION_NAME RDB$TRANSACTIONS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 4 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 12 + RDB$RELATION_NAME RDB$TRIGGERS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 15 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID 6:1e1 + Field id: 0 + name: RDB$TRIGGER_NAME + Field id: 1 + name: RDB$RELATION_NAME + Field id: 2 + name: RDB$TRIGGER_SEQUENCE + Field id: 3 + name: RDB$TRIGGER_TYPE + Field id: 4 + name: RDB$TRIGGER_SOURCE + Field id: 5 + name: RDB$TRIGGER_BLR + Field id: 6 + name: RDB$DESCRIPTION + Field id: 7 + name: RDB$TRIGGER_INACTIVE + Field id: 8 + name: RDB$SYSTEM_FLAG + field_not_null + Field id: 9 + name: RDB$FLAGS + Field id: 10 + name: RDB$VALID_BLR + Field id: 11 + name: RDB$DEBUG_INFO + Field id: 12 + name: RDB$ENGINE_NAME + Field id: 13 + name: RDB$ENTRYPOINT + Field id: 14 + name: RDB$SQL_SECURITY + trigger_name: RDB$TRIGGER_2 + trigger_name: RDB$TRIGGER_3 + trigger_name: RDB$TRIGGER_21 + trigger_name: RDB$TRIGGER_22 + + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 17 + RDB$RELATION_NAME RDB$TRIGGER_MESSAGES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 3 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 11 + RDB$RELATION_NAME RDB$TYPES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 5 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 18 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 8 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID 6:1e0 + Field id: 0 + name: RDB$USER + Field id: 1 + name: RDB$GRANTOR + Field id: 2 + name: RDB$PRIVILEGE + Field id: 3 + name: RDB$GRANT_OPTION + Field id: 4 + name: RDB$RELATION_NAME + Field id: 5 + name: RDB$FIELD_NAME + Field id: 6 + name: RDB$USER_TYPE + Field id: 7 + name: RDB$OBJECT_TYPE + trigger_name: RDB$TRIGGER_1 + trigger_name: RDB$TRIGGER_8 + trigger_name: RDB$TRIGGER_9 + trigger_name: RDB$TRIGGER_31 + trigger_name: RDB$TRIGGER_32 + trigger_name: RDB$TRIGGER_33 + + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 7 + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 6 + RDB$FLAGS + RDB$RELATION_TYPE 0 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 48 + RDB$RELATION_NAME SEC$DB_CREATORS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 2 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 46 + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 8 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 43 + RDB$RELATION_NAME SEC$USERS + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 8 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + RDB$RELATION_ID 44 + RDB$RELATION_NAME SEC$USER_ATTRIBUTES + RDB$SYSTEM_FLAG 1 + RDB$DBKEY_LENGTH 8 + RDB$FORMAT 0 + RDB$FIELD_ID 4 + RDB$FLAGS + RDB$RELATION_TYPE 3 + RDB$OWNER_NAME SYSDBA + RDB$EXTERNAL_FILE + VIEW_BLR_BLOB_ID + VIEW_SRC_BLOB_ID + DESCR_BLOB_ID + RUNTIME_BLOB_ID + EXT_DESCR_BLOB_ID + + + Records affected: 54 + """ + +@pytest.mark.version('>=4.0') +def test_db_23_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/functional/basic/db/test_24.py b/tests/functional/basic/db/test_24.py new file mode 100644 index 00000000..4de2740c --- /dev/null +++ b/tests/functional/basic/db/test_24.py @@ -0,0 +1,21044 @@ +#coding:utf-8 +# +# id: functional.basic.db.db_24 +# title: Empty DB - RDB$RELATION_FIELDS +# decription: Check for correct content of RDB$RELATION_FIELDS in empty database. +# tracker_id: +# min_versions: ['2.5.7'] +# versions: 3.0, 4.0 +# qmid: functional.basic.db.db_24 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('RDB\\$SECURITY_CLASS[ ]+SQL\\$.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- ##################################################################################### + -- 3.0 + -- ##################################################################################### + set list on; + select * + from rdb$relation_fields rf + order by rf.rdb$field_name, rf.rdb$relation_name; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + + RDB$FIELD_NAME MON$ATTACHMENT_ID + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$ATTACHMENT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$ATTACHMENT_ID + RDB$RELATION_NAME MON$CONTEXT_VARIABLES + RDB$FIELD_SOURCE RDB$ATTACHMENT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$ATTACHMENT_ID + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_SOURCE RDB$ATTACHMENT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$ATTACHMENT_ID + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_SOURCE RDB$ATTACHMENT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$ATTACHMENT_NAME + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$FILE_NAME2 + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$AUTH_METHOD + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$AUTH_METHOD + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 18 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 18 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$AUTO_COMMIT + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$AUTO_UNDO + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 11 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 11 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$BACKUP_STATE + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$BACKUP_STATE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 18 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 18 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$BACKVERSION_READS + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 13 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 13 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$CALLER_ID + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_SOURCE RDB$CALL_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$CALL_ID + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_SOURCE RDB$CALL_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$CHARACTER_SET_ID + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$CHARACTER_SET_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$CLIENT_VERSION + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$CLIENT_VERSION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 14 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 14 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$CREATION_DATE + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$TIMESTAMP + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 15 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 15 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$CRYPT_PAGE + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 19 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 19 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$DATABASE_NAME + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$FILE_NAME2 + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$EXPLAINED_PLAN + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$FORCED_WRITES + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 13 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 13 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$FRAGMENT_READS + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 14 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 14 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$GARBAGE_COLLECTION + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 11 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 11 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$ISOLATION_MODE + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_SOURCE RDB$ISOLATION_MODE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$LOCK_TIMEOUT + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_SOURCE RDB$LOCK_TIMEOUT + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$MAX_MEMORY_ALLOCATED + RDB$RELATION_NAME MON$MEMORY_USAGE + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$MAX_MEMORY_USED + RDB$RELATION_NAME MON$MEMORY_USAGE + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$MEMORY_ALLOCATED + RDB$RELATION_NAME MON$MEMORY_USAGE + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$MEMORY_USED + RDB$RELATION_NAME MON$MEMORY_USAGE + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$NEXT_TRANSACTION + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$TRANSACTION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$OBJECT_NAME + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_SOURCE RDB$GENERIC_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$OBJECT_TYPE + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_SOURCE RDB$OBJECT_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$ODS_MAJOR + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$ODS_NUMBER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$ODS_MINOR + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$ODS_NUMBER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$OLDEST_ACTIVE + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$TRANSACTION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$OLDEST_ACTIVE + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_SOURCE RDB$TRANSACTION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$OLDEST_SNAPSHOT + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$TRANSACTION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$OLDEST_TRANSACTION + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$TRANSACTION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$OLDEST_TRANSACTION + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_SOURCE RDB$TRANSACTION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$OWNER + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 20 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 20 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$PACKAGE_NAME + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_SOURCE RDB$PACKAGE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$PAGES + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 16 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 16 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$PAGE_BUFFERS + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$PAGE_BUFFERS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$PAGE_FETCHES + RDB$RELATION_NAME MON$IO_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$PAGE_MARKS + RDB$RELATION_NAME MON$IO_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$PAGE_READS + RDB$RELATION_NAME MON$IO_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$PAGE_SIZE + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$PAGE_SIZE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$PAGE_WRITES + RDB$RELATION_NAME MON$IO_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$READ_ONLY + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 12 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 12 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$READ_ONLY + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RECORD_BACKOUTS + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RECORD_CONFLICTS + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 12 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 12 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RECORD_DELETES + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RECORD_EXPUNGES + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RECORD_IDX_READS + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RECORD_INSERTS + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RECORD_LOCKS + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RECORD_PURGES + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RECORD_RPT_READS + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 15 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 15 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RECORD_SEQ_READS + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RECORD_STAT_ID + RDB$RELATION_NAME MON$TABLE_STATS + RDB$FIELD_SOURCE RDB$STAT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RECORD_UPDATES + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RECORD_WAITS + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 11 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 11 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$REMOTE_ADDRESS + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$REMOTE_ADDRESS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$REMOTE_HOST + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$HOST_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 16 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 16 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$REMOTE_OS_USER + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$OS_USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 17 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 17 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$REMOTE_PID + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$PID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$REMOTE_PROCESS + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$FILE_NAME2 + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 12 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 12 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$REMOTE_PROTOCOL + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$REMOTE_PROTOCOL + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$REMOTE_VERSION + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$REMOTE_VERSION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 15 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 15 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RESERVE_SPACE + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 14 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 14 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$ROLE + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$SEC_DATABASE + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE MON$SEC_DATABASE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 21 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 21 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$SERVER_PID + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$PID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$SHUTDOWN_MODE + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$SHUTDOWN_MODE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$SOURCE_COLUMN + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_SOURCE RDB$SOURCE_INFO + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$SOURCE_LINE + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_SOURCE RDB$SOURCE_INFO + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$SQL_DIALECT + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$SQL_DIALECT + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$SQL_TEXT + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STATE + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$STATE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STATE + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_SOURCE RDB$STATE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STATE + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_SOURCE RDB$STATE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STATEMENT_ID + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_SOURCE RDB$STATEMENT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STATEMENT_ID + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_SOURCE RDB$STATEMENT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STAT_GROUP + RDB$RELATION_NAME MON$IO_STATS + RDB$FIELD_SOURCE RDB$STAT_GROUP + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STAT_GROUP + RDB$RELATION_NAME MON$MEMORY_USAGE + RDB$FIELD_SOURCE RDB$STAT_GROUP + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STAT_GROUP + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$STAT_GROUP + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STAT_GROUP + RDB$RELATION_NAME MON$TABLE_STATS + RDB$FIELD_SOURCE RDB$STAT_GROUP + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STAT_ID + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$STAT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 13 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 13 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STAT_ID + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_SOURCE RDB$STAT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STAT_ID + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$STAT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 17 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 17 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STAT_ID + RDB$RELATION_NAME MON$IO_STATS + RDB$FIELD_SOURCE RDB$STAT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STAT_ID + RDB$RELATION_NAME MON$MEMORY_USAGE + RDB$FIELD_SOURCE RDB$STAT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STAT_ID + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$STAT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STAT_ID + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_SOURCE RDB$STAT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STAT_ID + RDB$RELATION_NAME MON$TABLE_STATS + RDB$FIELD_SOURCE RDB$STAT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STAT_ID + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_SOURCE RDB$STAT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 12 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 12 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$SWEEP_INTERVAL + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$SWEEP_INTERVAL + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 11 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 11 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$SYSTEM_FLAG + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 19 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 19 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$TABLE_NAME + RDB$RELATION_NAME MON$TABLE_STATS + RDB$FIELD_SOURCE RDB$RELATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$TIMESTAMP + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$TIMESTAMP + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$TIMESTAMP + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_SOURCE RDB$TIMESTAMP + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$TIMESTAMP + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_SOURCE RDB$TIMESTAMP + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$TIMESTAMP + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_SOURCE RDB$TIMESTAMP + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$TOP_TRANSACTION + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_SOURCE RDB$TRANSACTION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$TRANSACTION_ID + RDB$RELATION_NAME MON$CONTEXT_VARIABLES + RDB$FIELD_SOURCE RDB$TRANSACTION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$TRANSACTION_ID + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_SOURCE RDB$TRANSACTION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$TRANSACTION_ID + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_SOURCE RDB$TRANSACTION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$USER + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$VARIABLE_NAME + RDB$RELATION_NAME MON$CONTEXT_VARIABLES + RDB$FIELD_SOURCE RDB$CONTEXT_VAR_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$VARIABLE_VALUE + RDB$RELATION_NAME MON$CONTEXT_VARIABLES + RDB$FIELD_SOURCE RDB$CONTEXT_VAR_VALUE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$ACL + RDB$RELATION_NAME RDB$SECURITY_CLASSES + RDB$FIELD_SOURCE RDB$ACL + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$ARGUMENT_MECHANISM + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$ARGUMENT_MECHANISM + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 17 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 17 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$ARGUMENT_NAME + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$ARGUMENT_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 11 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 11 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$ARGUMENT_POSITION + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$FIELD_POSITION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$BACKUP_ID + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_SOURCE RDB$BACKUP_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$BACKUP_LEVEL + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_SOURCE RDB$BACKUP_LEVEL + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$BASE_COLLATION_NAME + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_SOURCE RDB$COLLATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$BASE_FIELD + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$BYTES_PER_CHARACTER + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_SOURCE RDB$FIELD_LENGTH + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CHARACTER_LENGTH + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$FIELD_LENGTH + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 24 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 24 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CHARACTER_LENGTH + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$FIELD_LENGTH + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CHARACTER_SET_ID + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_SOURCE RDB$CHARACTER_SET_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CHARACTER_SET_ID + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_SOURCE RDB$CHARACTER_SET_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CHARACTER_SET_ID + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$CHARACTER_SET_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 26 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 26 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CHARACTER_SET_ID + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$CHARACTER_SET_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_SOURCE RDB$CHARACTER_SET_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$RELATION_NAME RDB$DATABASE + RDB$FIELD_SOURCE RDB$CHARACTER_SET_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$COLLATION_ATTRIBUTES + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_SOURCE RDB$GENERIC_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$COLLATION_ID + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_SOURCE RDB$COLLATION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$COLLATION_ID + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$COLLATION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 25 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 25 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$COLLATION_ID + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$COLLATION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 15 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 15 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$COLLATION_ID + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$COLLATION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$COLLATION_ID + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$COLLATION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 18 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 18 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$COLLATION_NAME + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_SOURCE RDB$COLLATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$COMPLEX_NAME + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 15 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 15 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$COMPUTED_BLR + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$VALUE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$COMPUTED_SOURCE + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CONSTRAINT_NAME + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$FIELD_SOURCE RDB$CONSTRAINT_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CONSTRAINT_NAME + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$FIELD_SOURCE RDB$CONSTRAINT_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CONSTRAINT_NAME + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$FIELD_SOURCE RDB$CONSTRAINT_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CONSTRAINT_TYPE + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$FIELD_SOURCE RDB$CONSTRAINT_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CONST_NAME_UQ + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$FIELD_SOURCE RDB$CONSTRAINT_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CONTEXT_NAME + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$FIELD_SOURCE RDB$CONTEXT_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CONTEXT_TYPE + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$FIELD_SOURCE RDB$VIEW_CONTEXT + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DBKEY_LENGTH + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$DBKEY_LENGTH + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEBUG_INFO + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$DEBUG_INFO + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 15 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 15 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEBUG_INFO + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$DEBUG_INFO + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 13 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 13 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEBUG_INFO + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$DEBUG_INFO + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 11 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 11 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEFAULT_CLASS + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 14 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 14 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEFAULT_COLLATE_NAME + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_SOURCE RDB$COLLATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEFAULT_SOURCE + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEFAULT_SOURCE + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 14 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 14 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEFAULT_SOURCE + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEFAULT_SOURCE + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 17 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 17 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEFAULT_VALUE + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$VALUE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEFAULT_VALUE + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$VALUE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 13 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 13 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEFAULT_VALUE + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$VALUE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEFAULT_VALUE + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$VALUE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 12 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 12 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEFERRABLE + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$FIELD_SOURCE RDB$DEFERRABLE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DELETE_RULE + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$FIELD_SOURCE RDB$RULE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEPENDED_ON_NAME + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$FIELD_SOURCE RDB$GENERIC_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEPENDED_ON_TYPE + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$FIELD_SOURCE RDB$OBJECT_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEPENDENT_NAME + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$FIELD_SOURCE RDB$GENERIC_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEPENDENT_TYPE + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$FIELD_SOURCE RDB$OBJECT_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$DATABASE + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 14 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 14 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 21 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 21 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$GENERATORS + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 11 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 11 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$ROLES + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$SECURITY_CLASSES + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$TYPES + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTOR + RDB$RELATION_NAME RDB$FORMATS + RDB$FIELD_SOURCE RDB$DESCRIPTOR + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DETERMINISTIC_FLAG + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 19 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 19 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DIMENSION + RDB$RELATION_NAME RDB$FIELD_DIMENSIONS + RDB$FIELD_SOURCE RDB$DIMENSION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DIMENSIONS + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$DIMENSIONS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 22 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 22 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$EDIT_STRING + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$EDIT_STRING + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 18 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 18 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$EDIT_STRING + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$EDIT_STRING + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$ENGINE_NAME + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$ENGINE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$ENGINE_NAME + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$ENGINE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 14 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 14 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$ENGINE_NAME + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$ENGINE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 12 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 12 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$ENTRYPOINT + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_SOURCE RDB$EXTERNAL_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$ENTRYPOINT + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$EXTERNAL_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$ENTRYPOINT + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$EXTERNAL_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 15 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 15 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$ENTRYPOINT + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$EXTERNAL_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 13 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 13 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$EXCEPTION_NAME + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$FIELD_SOURCE RDB$EXCEPTION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$EXCEPTION_NUMBER + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$FIELD_SOURCE RDB$EXCEPTION_NUMBER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$EXPRESSION_BLR + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_SOURCE RDB$VALUE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$EXPRESSION_SOURCE + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 11 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 11 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$EXTERNAL_DESCRIPTION + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$EXTERNAL_DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 12 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 12 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$EXTERNAL_FILE + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$FILE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$EXTERNAL_LENGTH + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$FIELD_LENGTH + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 19 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 19 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$EXTERNAL_SCALE + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$FIELD_SCALE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 20 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 20 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$EXTERNAL_TYPE + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$FIELD_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 21 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 21 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_ID + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$FIELD_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_ID + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$FIELD_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_LENGTH + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$FIELD_LENGTH + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_LENGTH + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$FIELD_LENGTH + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$RELATION_NAME RDB$FIELD_DIMENSIONS + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 18 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 18 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$RELATION_NAME RDB$INDEX_SEGMENTS + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 12 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 12 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$RELATION_NAME RDB$TYPES + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_POSITION + RDB$RELATION_NAME RDB$INDEX_SEGMENTS + RDB$FIELD_SOURCE RDB$FIELD_POSITION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_POSITION + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$FIELD_POSITION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_PRECISION + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$FIELD_PRECISION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 27 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 27 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_PRECISION + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$FIELD_PRECISION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_SCALE + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$FIELD_SCALE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_SCALE + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$FIELD_SCALE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_SOURCE + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 12 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 12 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_SOURCE + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_SOURCE + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_SUB_TYPE + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$FIELD_SUB_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 11 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 11 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_SUB_TYPE + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$FIELD_SUB_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$FIELD_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$FIELD_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FILE_FLAGS + RDB$RELATION_NAME RDB$FILES + RDB$FIELD_SOURCE RDB$FILE_FLAGS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FILE_FLAGS + RDB$RELATION_NAME RDB$LOG_FILES + RDB$FIELD_SOURCE RDB$FILE_FLAGS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FILE_LENGTH + RDB$RELATION_NAME RDB$FILES + RDB$FIELD_SOURCE RDB$FILE_LENGTH + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FILE_LENGTH + RDB$RELATION_NAME RDB$LOG_FILES + RDB$FIELD_SOURCE RDB$FILE_LENGTH + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FILE_NAME + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_SOURCE RDB$FILE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FILE_NAME + RDB$RELATION_NAME RDB$FILES + RDB$FIELD_SOURCE RDB$FILE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FILE_NAME + RDB$RELATION_NAME RDB$LOG_FILES + RDB$FIELD_SOURCE RDB$FILE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FILE_PARTITIONS + RDB$RELATION_NAME RDB$LOG_FILES + RDB$FIELD_SOURCE RDB$FILE_PARTITIONS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FILE_P_OFFSET + RDB$RELATION_NAME RDB$LOG_FILES + RDB$FIELD_SOURCE RDB$FILE_P_OFFSET + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FILE_SEQUENCE + RDB$RELATION_NAME RDB$FILES + RDB$FIELD_SOURCE RDB$FILE_SEQUENCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FILE_SEQUENCE + RDB$RELATION_NAME RDB$LOG_FILES + RDB$FIELD_SOURCE RDB$FILE_SEQUENCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FILE_START + RDB$RELATION_NAME RDB$FILES + RDB$FIELD_SOURCE RDB$FILE_START + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FLAGS + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 15 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 15 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FLAGS + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FOREIGN_KEY + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_SOURCE RDB$RELATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FORMAT + RDB$RELATION_NAME RDB$FORMATS + RDB$FIELD_SOURCE RDB$FORMAT + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FORMAT + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$FORMAT + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FORM_OF_USE + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_SOURCE RDB$GENERIC_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FUNCTION_BLR + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$FUNCTION_BLR + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 13 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 13 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FUNCTION_ID + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$FUNCTION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 12 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 12 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FUNCTION_NAME + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_SOURCE RDB$FUNCTION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FUNCTION_NAME + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_SOURCE RDB$FUNCTION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FUNCTION_NAME + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_SOURCE RDB$FUNCTION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FUNCTION_NAME + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$FUNCTION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FUNCTION_NAME + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$FUNCTION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FUNCTION_SOURCE + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 11 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 11 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FUNCTION_TYPE + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$FUNCTION_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$GENERATOR_ID + RDB$RELATION_NAME RDB$GENERATORS + RDB$FIELD_SOURCE RDB$GENERATOR_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$GENERATOR_INCREMENT + RDB$RELATION_NAME RDB$GENERATORS + RDB$FIELD_SOURCE RDB$GENERATOR_INCREMENT + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$GENERATOR_NAME + RDB$RELATION_NAME RDB$GENERATORS + RDB$FIELD_SOURCE RDB$GENERATOR_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$GENERATOR_NAME + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$GENERATOR_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 19 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 19 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$GRANTOR + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$GRANT_OPTION + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$GUID + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_SOURCE RDB$GUID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$IDENTITY_TYPE + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$IDENTITY_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 20 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 20 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$INDEX_ID + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_SOURCE RDB$INDEX_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$INDEX_INACTIVE + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$INDEX_NAME + RDB$RELATION_NAME RDB$INDEX_SEGMENTS + RDB$FIELD_SOURCE RDB$INDEX_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$INDEX_NAME + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_SOURCE RDB$INDEX_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$INDEX_NAME + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$FIELD_SOURCE RDB$INDEX_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$INDEX_TYPE + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$INITIALLY_DEFERRED + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$FIELD_SOURCE RDB$DEFERRABLE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$INITIAL_VALUE + RDB$RELATION_NAME RDB$GENERATORS + RDB$FIELD_SOURCE RDB$GENERATOR_VALUE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$INPUT_SUB_TYPE + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_SOURCE RDB$FIELD_SUB_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$LEGACY_FLAG + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 18 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 18 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$LINGER + RDB$RELATION_NAME RDB$DATABASE + RDB$FIELD_SOURCE RDB$LINGER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$LOWER_BOUND + RDB$RELATION_NAME RDB$FIELD_DIMENSIONS + RDB$FIELD_SOURCE RDB$BOUND + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MAP_DB + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_SOURCE RDB$MAP_DB + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MAP_FROM + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_SOURCE RDB$MAP_FROM + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MAP_FROM_TYPE + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_SOURCE RDB$MAP_FROM_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MAP_NAME + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_SOURCE RDB$MAP_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MAP_PLUGIN + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_SOURCE RDB$PLUGIN + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MAP_TO + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_SOURCE RDB$MAP_TO + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MAP_TO_TYPE + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_SOURCE RDB$OBJECT_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MAP_USING + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_SOURCE RDB$MAP_USING + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MATCH_OPTION + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$FIELD_SOURCE RDB$MATCH_OPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MECHANISM + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$MECHANISM + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MESSAGE + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$FIELD_SOURCE RDB$MESSAGE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MESSAGE + RDB$RELATION_NAME RDB$TRIGGER_MESSAGES + RDB$FIELD_SOURCE RDB$MESSAGE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MESSAGE_NUMBER + RDB$RELATION_NAME RDB$TRIGGER_MESSAGES + RDB$FIELD_SOURCE RDB$MESSAGE_NUMBER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MISSING_SOURCE + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 13 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 13 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MISSING_VALUE + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$VALUE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 12 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 12 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MODULE_NAME + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_SOURCE RDB$FILE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MODULE_NAME + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$FILE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$NULL_FLAG + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$NULL_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 23 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 23 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$NULL_FLAG + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$NULL_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 16 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 16 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$NULL_FLAG + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$NULL_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$NULL_FLAG + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$NULL_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 16 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 16 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$NUMBER_OF_CHARACTERS + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_SOURCE RDB$NUMBER_OF_CHARACTERS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$FIELD_SOURCE RDB$OBJECT_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$OUTPUT_SUB_TYPE + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_SOURCE RDB$FIELD_SUB_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$OWNER_NAME + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$OWNER_NAME + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$OWNER_NAME + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$OWNER_NAME + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 29 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 29 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$OWNER_NAME + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$OWNER_NAME + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 17 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 17 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$OWNER_NAME + RDB$RELATION_NAME RDB$GENERATORS + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$OWNER_NAME + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$OWNER_NAME + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$OWNER_NAME + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 13 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 13 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$OWNER_NAME + RDB$RELATION_NAME RDB$ROLES + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PACKAGE_BODY_SOURCE + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PACKAGE_HEADER_SOURCE + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PACKAGE_NAME + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$FIELD_SOURCE RDB$PACKAGE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PACKAGE_NAME + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$PACKAGE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PACKAGE_NAME + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$PACKAGE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PACKAGE_NAME + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_SOURCE RDB$PACKAGE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PACKAGE_NAME + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$PACKAGE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 16 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 16 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PACKAGE_NAME + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$PACKAGE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 14 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 14 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PACKAGE_NAME + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$FIELD_SOURCE RDB$PACKAGE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PAGE_NUMBER + RDB$RELATION_NAME RDB$PAGES + RDB$FIELD_SOURCE RDB$PAGE_NUMBER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PAGE_SEQUENCE + RDB$RELATION_NAME RDB$PAGES + RDB$FIELD_SOURCE RDB$PAGE_SEQUENCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PAGE_TYPE + RDB$RELATION_NAME RDB$PAGES + RDB$FIELD_SOURCE RDB$PAGE_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PARAMETER_MECHANISM + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$MECHANISM + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 11 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 11 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PARAMETER_NAME + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$PARAMETER_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PARAMETER_NUMBER + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$PARAMETER_NUMBER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PARAMETER_TYPE + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$PARAMETER_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PRIVATE_FLAG + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PRIVATE_FLAG + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 17 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 17 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PRIVILEGE + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$FIELD_SOURCE RDB$PRIVILEGE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PROCEDURE_BLR + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$PROCEDURE_BLR + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PROCEDURE_ID + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$PROCEDURE_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PROCEDURE_INPUTS + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$PROCEDURE_PARAMETERS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PROCEDURE_NAME + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$PROCEDURE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PROCEDURE_NAME + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$PROCEDURE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PROCEDURE_OUTPUTS + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$PROCEDURE_PARAMETERS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PROCEDURE_SOURCE + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PROCEDURE_TYPE + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$PROCEDURE_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 11 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 11 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$QUERY_HEADER + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$QUERY_HEADER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 16 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 16 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$QUERY_HEADER + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$QUERY_HEADER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$QUERY_NAME + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$QUERY_NAME + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$QUERY_NAME + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RELATION_ID + RDB$RELATION_NAME RDB$DATABASE + RDB$FIELD_SOURCE RDB$RELATION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RELATION_ID + RDB$RELATION_NAME RDB$FORMATS + RDB$FIELD_SOURCE RDB$RELATION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RELATION_ID + RDB$RELATION_NAME RDB$PAGES + RDB$FIELD_SOURCE RDB$RELATION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RELATION_ID + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$RELATION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$RELATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 19 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 19 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_SOURCE RDB$RELATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$RELATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 13 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 13 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$RELATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$FIELD_SOURCE RDB$RELATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$RELATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$RELATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$FIELD_SOURCE RDB$GENERIC_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$FIELD_SOURCE RDB$RELATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RELATION_TYPE + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$RELATION_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 16 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 16 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RETURN_ARGUMENT + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$FIELD_POSITION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$ROLE_NAME + RDB$RELATION_NAME RDB$ROLES + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RUNTIME + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$RUNTIME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RUNTIME + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$RUNTIME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 11 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 11 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SCN + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_SOURCE RDB$SCN + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$RELATION_NAME RDB$DATABASE + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 28 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 28 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 16 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 16 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$RELATION_NAME RDB$GENERATORS + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 14 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 14 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$RELATION_NAME RDB$ROLES + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$RELATION_NAME RDB$SECURITY_CLASSES + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SEGMENT_COUNT + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_SOURCE RDB$SEGMENT_COUNT + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SEGMENT_LENGTH + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$SEGMENT_LENGTH + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 17 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 17 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SHADOW_NUMBER + RDB$RELATION_NAME RDB$FILES + RDB$FIELD_SOURCE RDB$SHADOW_NUMBER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SPECIFIC_ATTRIBUTES + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_SOURCE RDB$SPECIFIC_ATTRIBUTES + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$STATISTICS + RDB$RELATION_NAME RDB$INDEX_SEGMENTS + RDB$FIELD_SOURCE RDB$STATISTICS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$STATISTICS + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_SOURCE RDB$STATISTICS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 12 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 12 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 15 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 15 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 20 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 20 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$GENERATORS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 13 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 13 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$ROLES + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$TYPES + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TIMESTAMP + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_SOURCE RDB$TIMESTAMP + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TIMESTAMP + RDB$RELATION_NAME RDB$TRANSACTIONS + RDB$FIELD_SOURCE RDB$TIMESTAMP + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TRANSACTION_DESCRIPTION + RDB$RELATION_NAME RDB$TRANSACTIONS + RDB$FIELD_SOURCE RDB$TRANSACTION_DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TRANSACTION_ID + RDB$RELATION_NAME RDB$TRANSACTIONS + RDB$FIELD_SOURCE RDB$TRANSACTION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TRANSACTION_STATE + RDB$RELATION_NAME RDB$TRANSACTIONS + RDB$FIELD_SOURCE RDB$TRANSACTION_STATE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TRIGGER_BLR + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$TRIGGER_BLR + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TRIGGER_INACTIVE + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TRIGGER_NAME + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$FIELD_SOURCE RDB$TRIGGER_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TRIGGER_NAME + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$TRIGGER_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TRIGGER_NAME + RDB$RELATION_NAME RDB$TRIGGER_MESSAGES + RDB$FIELD_SOURCE RDB$TRIGGER_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TRIGGER_SEQUENCE + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$TRIGGER_SEQUENCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TRIGGER_SOURCE + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TRIGGER_TYPE + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$TRIGGER_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TYPE + RDB$RELATION_NAME RDB$TYPES + RDB$FIELD_SOURCE RDB$GENERIC_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TYPE_NAME + RDB$RELATION_NAME RDB$TYPES + RDB$FIELD_SOURCE RDB$TYPE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$UNIQUE_FLAG + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$UPDATE_FLAG + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$UPDATE_RULE + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$FIELD_SOURCE RDB$RULE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$UPPER_BOUND + RDB$RELATION_NAME RDB$FIELD_DIMENSIONS + RDB$FIELD_SOURCE RDB$BOUND + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$USER + RDB$RELATION_NAME RDB$DB_CREATORS + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$USER + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$USER_TYPE + RDB$RELATION_NAME RDB$DB_CREATORS + RDB$FIELD_SOURCE RDB$OBJECT_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$USER_TYPE + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$FIELD_SOURCE RDB$OBJECT_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$VALIDATION_BLR + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$VALIDATION_BLR + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$VALIDATION_SOURCE + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$VALID_BLR + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 14 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 14 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$VALID_BLR + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 12 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 12 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$VALID_BLR + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$VALID_BODY_FLAG + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$VIEW_BLR + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$VIEW_BLR + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$VIEW_CONTEXT + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$VIEW_CONTEXT + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$VIEW_CONTEXT + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$FIELD_SOURCE RDB$VIEW_CONTEXT + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$VIEW_NAME + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$FIELD_SOURCE RDB$RELATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$VIEW_SOURCE + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$ACTIVE + RDB$RELATION_NAME SEC$USERS + RDB$FIELD_SOURCE RDB$BOOLEAN + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$ADMIN + RDB$RELATION_NAME SEC$USERS + RDB$FIELD_SOURCE RDB$BOOLEAN + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$DESCRIPTION + RDB$RELATION_NAME SEC$USERS + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$FIRST_NAME + RDB$RELATION_NAME SEC$USERS + RDB$FIELD_SOURCE SEC$NAME_PART + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$KEY + RDB$RELATION_NAME SEC$USER_ATTRIBUTES + RDB$FIELD_SOURCE SEC$KEY + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$LAST_NAME + RDB$RELATION_NAME SEC$USERS + RDB$FIELD_SOURCE SEC$NAME_PART + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$MAP_DB + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$FIELD_SOURCE RDB$MAP_DB + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$MAP_FROM + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$FIELD_SOURCE RDB$MAP_FROM + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$MAP_FROM_TYPE + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$FIELD_SOURCE RDB$MAP_FROM_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$MAP_NAME + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$FIELD_SOURCE RDB$MAP_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$MAP_PLUGIN + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$FIELD_SOURCE RDB$PLUGIN + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$MAP_TO + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$FIELD_SOURCE RDB$MAP_TO + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$MAP_TO_TYPE + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$FIELD_SOURCE RDB$OBJECT_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$MAP_USING + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$FIELD_SOURCE RDB$MAP_USING + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$MIDDLE_NAME + RDB$RELATION_NAME SEC$USERS + RDB$FIELD_SOURCE SEC$NAME_PART + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$PLUGIN + RDB$RELATION_NAME SEC$USERS + RDB$FIELD_SOURCE RDB$PLUGIN + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$PLUGIN + RDB$RELATION_NAME SEC$USER_ATTRIBUTES + RDB$FIELD_SOURCE RDB$PLUGIN + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$USER + RDB$RELATION_NAME SEC$DB_CREATORS + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$USER_NAME + RDB$RELATION_NAME SEC$USERS + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$USER_NAME + RDB$RELATION_NAME SEC$USER_ATTRIBUTES + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$USER_TYPE + RDB$RELATION_NAME SEC$DB_CREATORS + RDB$FIELD_SOURCE RDB$OBJECT_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$VALUE + RDB$RELATION_NAME SEC$USER_ATTRIBUTES + RDB$FIELD_SOURCE SEC$VALUE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_db_24_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [('RDB\\$SECURITY_CLASS[ ]+SQL\\$.*', '')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + -- ##################################################################################### + -- 4.0 + -- ##################################################################################### + set list on; + set count on; + select * + from rdb$relation_fields rf + order by rf.rdb$field_name, rf.rdb$relation_name; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + + RDB$FIELD_NAME MON$ATTACHMENT_ID + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$ATTACHMENT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$ATTACHMENT_ID + RDB$RELATION_NAME MON$CONTEXT_VARIABLES + RDB$FIELD_SOURCE RDB$ATTACHMENT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$ATTACHMENT_ID + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_SOURCE RDB$ATTACHMENT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$ATTACHMENT_ID + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_SOURCE RDB$ATTACHMENT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$ATTACHMENT_NAME + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$FILE_NAME2 + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$AUTH_METHOD + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$AUTH_METHOD + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 18 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 18 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$AUTO_COMMIT + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$AUTO_UNDO + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 11 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 11 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$BACKUP_STATE + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$BACKUP_STATE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 18 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 18 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$BACKVERSION_READS + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 13 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 13 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$CALLER_ID + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_SOURCE RDB$CALL_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$CALL_ID + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_SOURCE RDB$CALL_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$CHARACTER_SET_ID + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$CHARACTER_SET_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$CLIENT_VERSION + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$CLIENT_VERSION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 14 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 14 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$CREATION_DATE + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$TIMESTAMP_TZ + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 15 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 15 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$CRYPT_PAGE + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 19 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 19 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$CRYPT_STATE + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$CRYPT_STATE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 22 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 22 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$DATABASE_NAME + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$FILE_NAME2 + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$EXPLAINED_PLAN + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$FILE_ID + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$FILE_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 24 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 24 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$FORCED_WRITES + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 13 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 13 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$FRAGMENT_READS + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 14 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 14 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$GARBAGE_COLLECTION + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 11 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 11 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$GUID + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$GUID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 23 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 23 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$IDLE_TIMEOUT + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE MON$IDLE_TIMEOUT + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 20 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 20 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$IDLE_TIMER + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE MON$IDLE_TIMER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 21 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 21 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$ISOLATION_MODE + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_SOURCE RDB$ISOLATION_MODE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$LOCK_TIMEOUT + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_SOURCE RDB$LOCK_TIMEOUT + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$MAX_MEMORY_ALLOCATED + RDB$RELATION_NAME MON$MEMORY_USAGE + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$MAX_MEMORY_USED + RDB$RELATION_NAME MON$MEMORY_USAGE + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$MEMORY_ALLOCATED + RDB$RELATION_NAME MON$MEMORY_USAGE + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$MEMORY_USED + RDB$RELATION_NAME MON$MEMORY_USAGE + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$NEXT_ATTACHMENT + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$ATTACHMENT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 25 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 25 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$NEXT_STATEMENT + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$STATEMENT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 26 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 26 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$NEXT_TRANSACTION + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$TRANSACTION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$OBJECT_NAME + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_SOURCE RDB$GENERIC_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$OBJECT_TYPE + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_SOURCE RDB$OBJECT_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$ODS_MAJOR + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$ODS_NUMBER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$ODS_MINOR + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$ODS_NUMBER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$OLDEST_ACTIVE + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$TRANSACTION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$OLDEST_ACTIVE + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_SOURCE RDB$TRANSACTION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$OLDEST_SNAPSHOT + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$TRANSACTION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$OLDEST_TRANSACTION + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$TRANSACTION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$OLDEST_TRANSACTION + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_SOURCE RDB$TRANSACTION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$OWNER + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 20 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 20 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$PACKAGE_NAME + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_SOURCE RDB$PACKAGE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$PAGES + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 16 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 16 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$PAGE_BUFFERS + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$PAGE_BUFFERS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$PAGE_FETCHES + RDB$RELATION_NAME MON$IO_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$PAGE_MARKS + RDB$RELATION_NAME MON$IO_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$PAGE_READS + RDB$RELATION_NAME MON$IO_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$PAGE_SIZE + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$PAGE_SIZE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$PAGE_WRITES + RDB$RELATION_NAME MON$IO_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$READ_ONLY + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 12 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 12 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$READ_ONLY + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RECORD_BACKOUTS + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RECORD_CONFLICTS + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 12 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 12 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RECORD_DELETES + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RECORD_EXPUNGES + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RECORD_IDX_READS + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RECORD_IMGC + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 16 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 16 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RECORD_INSERTS + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RECORD_LOCKS + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RECORD_PURGES + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RECORD_RPT_READS + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 15 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 15 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RECORD_SEQ_READS + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RECORD_STAT_ID + RDB$RELATION_NAME MON$TABLE_STATS + RDB$FIELD_SOURCE RDB$STAT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RECORD_UPDATES + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RECORD_WAITS + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$COUNTER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 11 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 11 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$REMOTE_ADDRESS + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$REMOTE_ADDRESS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$REMOTE_HOST + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$HOST_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 16 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 16 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$REMOTE_OS_USER + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$OS_USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 17 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 17 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$REMOTE_PID + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$PID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$REMOTE_PROCESS + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$FILE_NAME2 + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 12 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 12 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$REMOTE_PROTOCOL + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$REMOTE_PROTOCOL + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$REMOTE_VERSION + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$REMOTE_VERSION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 15 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 15 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$REPLICA_MODE + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$REPLICA_MODE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 27 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 27 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$RESERVE_SPACE + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 14 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 14 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$ROLE + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$SEC_DATABASE + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE MON$SEC_DATABASE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 21 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 21 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$SERVER_PID + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$PID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$SHUTDOWN_MODE + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$SHUTDOWN_MODE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$SOURCE_COLUMN + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_SOURCE RDB$SOURCE_INFO + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$SOURCE_LINE + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_SOURCE RDB$SOURCE_INFO + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$SQL_DIALECT + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$SQL_DIALECT + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$SQL_TEXT + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STATE + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$STATE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STATE + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_SOURCE RDB$STATE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STATE + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_SOURCE RDB$STATE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STATEMENT_ID + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_SOURCE RDB$STATEMENT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STATEMENT_ID + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_SOURCE RDB$STATEMENT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STATEMENT_TIMEOUT + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE MON$STATEMENT_TIMEOUT + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 22 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 22 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STATEMENT_TIMEOUT + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_SOURCE MON$STATEMENT_TIMEOUT + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STATEMENT_TIMER + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_SOURCE MON$STATEMENT_TIMER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STAT_GROUP + RDB$RELATION_NAME MON$IO_STATS + RDB$FIELD_SOURCE RDB$STAT_GROUP + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STAT_GROUP + RDB$RELATION_NAME MON$MEMORY_USAGE + RDB$FIELD_SOURCE RDB$STAT_GROUP + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STAT_GROUP + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$STAT_GROUP + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STAT_GROUP + RDB$RELATION_NAME MON$TABLE_STATS + RDB$FIELD_SOURCE RDB$STAT_GROUP + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STAT_ID + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$STAT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 13 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 13 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STAT_ID + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_SOURCE RDB$STAT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STAT_ID + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$STAT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 17 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 17 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STAT_ID + RDB$RELATION_NAME MON$IO_STATS + RDB$FIELD_SOURCE RDB$STAT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STAT_ID + RDB$RELATION_NAME MON$MEMORY_USAGE + RDB$FIELD_SOURCE RDB$STAT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STAT_ID + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_SOURCE RDB$STAT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STAT_ID + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_SOURCE RDB$STAT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STAT_ID + RDB$RELATION_NAME MON$TABLE_STATS + RDB$FIELD_SOURCE RDB$STAT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$STAT_ID + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_SOURCE RDB$STAT_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 12 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 12 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$SWEEP_INTERVAL + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_SOURCE RDB$SWEEP_INTERVAL + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 11 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 11 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$SYSTEM_FLAG + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 19 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 19 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$TABLE_NAME + RDB$RELATION_NAME MON$TABLE_STATS + RDB$FIELD_SOURCE RDB$RELATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$TIMESTAMP + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$TIMESTAMP_TZ + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$TIMESTAMP + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_SOURCE RDB$TIMESTAMP_TZ + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$TIMESTAMP + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_SOURCE RDB$TIMESTAMP_TZ + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$TIMESTAMP + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_SOURCE RDB$TIMESTAMP_TZ + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$TOP_TRANSACTION + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_SOURCE RDB$TRANSACTION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$TRANSACTION_ID + RDB$RELATION_NAME MON$CONTEXT_VARIABLES + RDB$FIELD_SOURCE RDB$TRANSACTION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$TRANSACTION_ID + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_SOURCE RDB$TRANSACTION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$TRANSACTION_ID + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_SOURCE RDB$TRANSACTION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$USER + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$VARIABLE_NAME + RDB$RELATION_NAME MON$CONTEXT_VARIABLES + RDB$FIELD_SOURCE RDB$CONTEXT_VAR_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$VARIABLE_VALUE + RDB$RELATION_NAME MON$CONTEXT_VARIABLES + RDB$FIELD_SOURCE RDB$CONTEXT_VAR_VALUE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$WIRE_COMPRESSED + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$BOOLEAN + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 23 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 23 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$WIRE_CRYPT_PLUGIN + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE MON$WIRE_CRYPT_PLUGIN + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 25 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 25 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME MON$WIRE_ENCRYPTED + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_SOURCE RDB$BOOLEAN + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 24 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 24 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$ACL + RDB$RELATION_NAME RDB$SECURITY_CLASSES + RDB$FIELD_SOURCE RDB$ACL + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$ACTIVE_FLAG + RDB$RELATION_NAME RDB$PUBLICATIONS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$ARGUMENT_MECHANISM + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$ARGUMENT_MECHANISM + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 17 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 17 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$ARGUMENT_NAME + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$ARGUMENT_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 11 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 11 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$ARGUMENT_POSITION + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$FIELD_POSITION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$AUTO_ENABLE + RDB$RELATION_NAME RDB$PUBLICATIONS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$BACKUP_ID + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_SOURCE RDB$BACKUP_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$BACKUP_LEVEL + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_SOURCE RDB$BACKUP_LEVEL + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$BASE_COLLATION_NAME + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_SOURCE RDB$COLLATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$BASE_FIELD + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$BYTES_PER_CHARACTER + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_SOURCE RDB$FIELD_LENGTH + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CHARACTER_LENGTH + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$FIELD_LENGTH + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 24 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 24 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CHARACTER_LENGTH + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$FIELD_LENGTH + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CHARACTER_SET_ID + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_SOURCE RDB$CHARACTER_SET_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CHARACTER_SET_ID + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_SOURCE RDB$CHARACTER_SET_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CHARACTER_SET_ID + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$CHARACTER_SET_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 26 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 26 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CHARACTER_SET_ID + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$CHARACTER_SET_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_SOURCE RDB$CHARACTER_SET_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$RELATION_NAME RDB$DATABASE + RDB$FIELD_SOURCE RDB$CHARACTER_SET_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$COLLATION_ATTRIBUTES + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_SOURCE RDB$GENERIC_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$COLLATION_ID + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_SOURCE RDB$COLLATION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$COLLATION_ID + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$COLLATION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 25 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 25 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$COLLATION_ID + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$COLLATION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 15 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 15 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$COLLATION_ID + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$COLLATION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$COLLATION_ID + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$COLLATION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 18 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 18 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$COLLATION_NAME + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_SOURCE RDB$COLLATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$COMPLEX_NAME + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 15 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 15 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$COMPUTED_BLR + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$VALUE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$COMPUTED_SOURCE + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CONFIG_DEFAULT + RDB$RELATION_NAME RDB$CONFIG + RDB$FIELD_SOURCE RDB$CONFIG_VALUE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CONFIG_ID + RDB$RELATION_NAME RDB$CONFIG + RDB$FIELD_SOURCE RDB$CONFIG_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CONFIG_IS_SET + RDB$RELATION_NAME RDB$CONFIG + RDB$FIELD_SOURCE RDB$CONFIG_IS_SET + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CONFIG_NAME + RDB$RELATION_NAME RDB$CONFIG + RDB$FIELD_SOURCE RDB$CONFIG_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CONFIG_SOURCE + RDB$RELATION_NAME RDB$CONFIG + RDB$FIELD_SOURCE RDB$FILE_NAME2 + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CONFIG_VALUE + RDB$RELATION_NAME RDB$CONFIG + RDB$FIELD_SOURCE RDB$CONFIG_VALUE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CONSTRAINT_NAME + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$FIELD_SOURCE RDB$CONSTRAINT_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CONSTRAINT_NAME + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$FIELD_SOURCE RDB$CONSTRAINT_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CONSTRAINT_NAME + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$FIELD_SOURCE RDB$CONSTRAINT_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CONSTRAINT_TYPE + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$FIELD_SOURCE RDB$CONSTRAINT_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CONST_NAME_UQ + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$FIELD_SOURCE RDB$CONSTRAINT_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CONTEXT_NAME + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$FIELD_SOURCE RDB$CONTEXT_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$CONTEXT_TYPE + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$FIELD_SOURCE RDB$VIEW_CONTEXT + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DBKEY_LENGTH + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$DBKEY_LENGTH + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEBUG_INFO + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$DEBUG_INFO + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 15 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 15 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEBUG_INFO + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$DEBUG_INFO + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 13 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 13 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEBUG_INFO + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$DEBUG_INFO + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 11 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 11 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEFAULT_CLASS + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 14 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 14 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEFAULT_COLLATE_NAME + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_SOURCE RDB$COLLATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEFAULT_SOURCE + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEFAULT_SOURCE + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 14 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 14 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEFAULT_SOURCE + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEFAULT_SOURCE + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 17 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 17 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEFAULT_VALUE + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$VALUE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEFAULT_VALUE + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$VALUE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 13 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 13 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEFAULT_VALUE + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$VALUE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEFAULT_VALUE + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$VALUE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 12 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 12 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEFERRABLE + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$FIELD_SOURCE RDB$DEFERRABLE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DELETE_RULE + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$FIELD_SOURCE RDB$RULE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEPENDED_ON_NAME + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$FIELD_SOURCE RDB$GENERIC_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEPENDED_ON_TYPE + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$FIELD_SOURCE RDB$OBJECT_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEPENDENT_NAME + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$FIELD_SOURCE RDB$GENERIC_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DEPENDENT_TYPE + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$FIELD_SOURCE RDB$OBJECT_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$DATABASE + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 14 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 14 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 21 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 21 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$GENERATORS + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 11 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 11 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$ROLES + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$SECURITY_CLASSES + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTION + RDB$RELATION_NAME RDB$TYPES + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DESCRIPTOR + RDB$RELATION_NAME RDB$FORMATS + RDB$FIELD_SOURCE RDB$DESCRIPTOR + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DETERMINISTIC_FLAG + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 19 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 19 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DIMENSION + RDB$RELATION_NAME RDB$FIELD_DIMENSIONS + RDB$FIELD_SOURCE RDB$DIMENSION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$DIMENSIONS + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$DIMENSIONS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 22 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 22 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$EDIT_STRING + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$EDIT_STRING + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 18 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 18 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$EDIT_STRING + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$EDIT_STRING + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$ENGINE_NAME + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$ENGINE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$ENGINE_NAME + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$ENGINE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 14 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 14 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$ENGINE_NAME + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$ENGINE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 12 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 12 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$ENTRYPOINT + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_SOURCE RDB$EXTERNAL_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$ENTRYPOINT + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$EXTERNAL_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$ENTRYPOINT + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$EXTERNAL_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 15 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 15 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$ENTRYPOINT + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$EXTERNAL_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 13 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 13 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$EXCEPTION_NAME + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$FIELD_SOURCE RDB$EXCEPTION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$EXCEPTION_NUMBER + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$FIELD_SOURCE RDB$EXCEPTION_NUMBER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$EXPRESSION_BLR + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_SOURCE RDB$VALUE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$EXPRESSION_SOURCE + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 11 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 11 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$EXTERNAL_DESCRIPTION + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$EXTERNAL_DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 12 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 12 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$EXTERNAL_FILE + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$FILE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$EXTERNAL_LENGTH + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$FIELD_LENGTH + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 19 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 19 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$EXTERNAL_SCALE + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$FIELD_SCALE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 20 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 20 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$EXTERNAL_TYPE + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$FIELD_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 21 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 21 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_ID + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$FIELD_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_ID + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$FIELD_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_LENGTH + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$FIELD_LENGTH + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_LENGTH + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$FIELD_LENGTH + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$RELATION_NAME RDB$FIELD_DIMENSIONS + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 18 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 18 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$RELATION_NAME RDB$INDEX_SEGMENTS + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 12 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 12 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$RELATION_NAME RDB$TYPES + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_NAME + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_POSITION + RDB$RELATION_NAME RDB$INDEX_SEGMENTS + RDB$FIELD_SOURCE RDB$FIELD_POSITION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_POSITION + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$FIELD_POSITION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_PRECISION + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$FIELD_PRECISION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 27 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 27 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_PRECISION + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$FIELD_PRECISION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_SCALE + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$FIELD_SCALE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_SCALE + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$FIELD_SCALE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_SOURCE + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 12 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 12 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_SOURCE + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_SOURCE + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_SUB_TYPE + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$FIELD_SUB_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 11 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 11 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_SUB_TYPE + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$FIELD_SUB_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$FIELD_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$FIELD_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FILE_FLAGS + RDB$RELATION_NAME RDB$FILES + RDB$FIELD_SOURCE RDB$FILE_FLAGS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FILE_FLAGS + RDB$RELATION_NAME RDB$LOG_FILES + RDB$FIELD_SOURCE RDB$FILE_FLAGS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FILE_LENGTH + RDB$RELATION_NAME RDB$FILES + RDB$FIELD_SOURCE RDB$FILE_LENGTH + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FILE_LENGTH + RDB$RELATION_NAME RDB$LOG_FILES + RDB$FIELD_SOURCE RDB$FILE_LENGTH + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FILE_NAME + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_SOURCE RDB$FILE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FILE_NAME + RDB$RELATION_NAME RDB$FILES + RDB$FIELD_SOURCE RDB$FILE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FILE_NAME + RDB$RELATION_NAME RDB$LOG_FILES + RDB$FIELD_SOURCE RDB$FILE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FILE_PARTITIONS + RDB$RELATION_NAME RDB$LOG_FILES + RDB$FIELD_SOURCE RDB$FILE_PARTITIONS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FILE_P_OFFSET + RDB$RELATION_NAME RDB$LOG_FILES + RDB$FIELD_SOURCE RDB$FILE_P_OFFSET + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FILE_SEQUENCE + RDB$RELATION_NAME RDB$FILES + RDB$FIELD_SOURCE RDB$FILE_SEQUENCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FILE_SEQUENCE + RDB$RELATION_NAME RDB$LOG_FILES + RDB$FIELD_SOURCE RDB$FILE_SEQUENCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FILE_START + RDB$RELATION_NAME RDB$FILES + RDB$FIELD_SOURCE RDB$FILE_START + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FLAGS + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 15 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 15 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FLAGS + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FOREIGN_KEY + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_SOURCE RDB$RELATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FORMAT + RDB$RELATION_NAME RDB$FORMATS + RDB$FIELD_SOURCE RDB$FORMAT + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FORMAT + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$FORMAT + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FORM_OF_USE + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_SOURCE RDB$GENERIC_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FUNCTION_BLR + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$FUNCTION_BLR + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 13 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 13 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FUNCTION_ID + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$FUNCTION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 12 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 12 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FUNCTION_NAME + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_SOURCE RDB$FUNCTION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FUNCTION_NAME + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_SOURCE RDB$FUNCTION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FUNCTION_NAME + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_SOURCE RDB$FUNCTION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FUNCTION_NAME + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$FUNCTION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FUNCTION_NAME + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$FUNCTION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FUNCTION_SOURCE + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 11 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 11 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$FUNCTION_TYPE + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$FUNCTION_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$GENERATOR_ID + RDB$RELATION_NAME RDB$GENERATORS + RDB$FIELD_SOURCE RDB$GENERATOR_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$GENERATOR_INCREMENT + RDB$RELATION_NAME RDB$GENERATORS + RDB$FIELD_SOURCE RDB$GENERATOR_INCREMENT + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$GENERATOR_NAME + RDB$RELATION_NAME RDB$GENERATORS + RDB$FIELD_SOURCE RDB$GENERATOR_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$GENERATOR_NAME + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$GENERATOR_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 19 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 19 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$GRANTOR + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$GRANT_OPTION + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$GUID + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_SOURCE RDB$GUID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$IDENTITY_TYPE + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$IDENTITY_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 20 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 20 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$INDEX_ID + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_SOURCE RDB$INDEX_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$INDEX_INACTIVE + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$INDEX_NAME + RDB$RELATION_NAME RDB$INDEX_SEGMENTS + RDB$FIELD_SOURCE RDB$INDEX_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$INDEX_NAME + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_SOURCE RDB$INDEX_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$INDEX_NAME + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$FIELD_SOURCE RDB$INDEX_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$INDEX_TYPE + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$INITIALLY_DEFERRED + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$FIELD_SOURCE RDB$DEFERRABLE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$INITIAL_VALUE + RDB$RELATION_NAME RDB$GENERATORS + RDB$FIELD_SOURCE RDB$GENERATOR_VALUE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$INPUT_SUB_TYPE + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_SOURCE RDB$FIELD_SUB_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$LEGACY_FLAG + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 18 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 18 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$LINGER + RDB$RELATION_NAME RDB$DATABASE + RDB$FIELD_SOURCE RDB$LINGER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$LOWER_BOUND + RDB$RELATION_NAME RDB$FIELD_DIMENSIONS + RDB$FIELD_SOURCE RDB$BOUND + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MAP_DB + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_SOURCE RDB$MAP_DB + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MAP_FROM + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_SOURCE RDB$MAP_FROM + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MAP_FROM_TYPE + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_SOURCE RDB$MAP_FROM_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MAP_NAME + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_SOURCE RDB$MAP_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MAP_PLUGIN + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_SOURCE RDB$PLUGIN + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MAP_TO + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_SOURCE RDB$MAP_TO + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MAP_TO_TYPE + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_SOURCE RDB$OBJECT_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MAP_USING + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_SOURCE RDB$MAP_USING + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MATCH_OPTION + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$FIELD_SOURCE RDB$MATCH_OPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MECHANISM + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$MECHANISM + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MESSAGE + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$FIELD_SOURCE RDB$MESSAGE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MESSAGE + RDB$RELATION_NAME RDB$TRIGGER_MESSAGES + RDB$FIELD_SOURCE RDB$MESSAGE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MESSAGE_NUMBER + RDB$RELATION_NAME RDB$TRIGGER_MESSAGES + RDB$FIELD_SOURCE RDB$MESSAGE_NUMBER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MISSING_SOURCE + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 13 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 13 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MISSING_VALUE + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$VALUE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 12 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 12 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MODULE_NAME + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_SOURCE RDB$FILE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$MODULE_NAME + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$FILE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$NULL_FLAG + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$NULL_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 23 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 23 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$NULL_FLAG + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$NULL_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 16 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 16 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$NULL_FLAG + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$NULL_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$NULL_FLAG + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$NULL_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 16 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 16 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$NUMBER_OF_CHARACTERS + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_SOURCE RDB$NUMBER_OF_CHARACTERS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$FIELD_SOURCE RDB$OBJECT_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$OUTPUT_SUB_TYPE + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_SOURCE RDB$FIELD_SUB_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$OWNER_NAME + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$OWNER_NAME + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$OWNER_NAME + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$OWNER_NAME + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 29 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 29 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$OWNER_NAME + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$OWNER_NAME + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 17 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 17 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$OWNER_NAME + RDB$RELATION_NAME RDB$GENERATORS + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$OWNER_NAME + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$OWNER_NAME + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$OWNER_NAME + RDB$RELATION_NAME RDB$PUBLICATIONS + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$OWNER_NAME + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 13 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 13 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$OWNER_NAME + RDB$RELATION_NAME RDB$ROLES + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PACKAGE_BODY_SOURCE + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PACKAGE_HEADER_SOURCE + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PACKAGE_NAME + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$FIELD_SOURCE RDB$PACKAGE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PACKAGE_NAME + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$PACKAGE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PACKAGE_NAME + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$PACKAGE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PACKAGE_NAME + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_SOURCE RDB$PACKAGE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PACKAGE_NAME + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$PACKAGE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 16 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 16 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PACKAGE_NAME + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$PACKAGE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 14 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 14 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PACKAGE_NAME + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$FIELD_SOURCE RDB$PACKAGE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PAGE_NUMBER + RDB$RELATION_NAME RDB$PAGES + RDB$FIELD_SOURCE RDB$PAGE_NUMBER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PAGE_SEQUENCE + RDB$RELATION_NAME RDB$PAGES + RDB$FIELD_SOURCE RDB$PAGE_SEQUENCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PAGE_TYPE + RDB$RELATION_NAME RDB$PAGES + RDB$FIELD_SOURCE RDB$PAGE_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PARAMETER_MECHANISM + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$MECHANISM + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 11 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 11 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PARAMETER_NAME + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$PARAMETER_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PARAMETER_NUMBER + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$PARAMETER_NUMBER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PARAMETER_TYPE + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$PARAMETER_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PRIVATE_FLAG + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PRIVATE_FLAG + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 17 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 17 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PRIVILEGE + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$FIELD_SOURCE RDB$PRIVILEGE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PROCEDURE_BLR + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$PROCEDURE_BLR + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PROCEDURE_ID + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$PROCEDURE_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PROCEDURE_INPUTS + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$PROCEDURE_PARAMETERS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PROCEDURE_NAME + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$PROCEDURE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PROCEDURE_NAME + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$PROCEDURE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PROCEDURE_OUTPUTS + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$PROCEDURE_PARAMETERS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PROCEDURE_SOURCE + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PROCEDURE_TYPE + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$PROCEDURE_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 11 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 11 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PUBLICATION_NAME + RDB$RELATION_NAME RDB$PUBLICATIONS + RDB$FIELD_SOURCE RDB$PUBLICATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$PUBLICATION_NAME + RDB$RELATION_NAME RDB$PUBLICATION_TABLES + RDB$FIELD_SOURCE RDB$PUBLICATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$QUERY_HEADER + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$QUERY_HEADER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 16 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 16 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$QUERY_HEADER + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$QUERY_HEADER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$QUERY_NAME + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$QUERY_NAME + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$QUERY_NAME + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$FIELD_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RELATION_ID + RDB$RELATION_NAME RDB$DATABASE + RDB$FIELD_SOURCE RDB$RELATION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RELATION_ID + RDB$RELATION_NAME RDB$FORMATS + RDB$FIELD_SOURCE RDB$RELATION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RELATION_ID + RDB$RELATION_NAME RDB$PAGES + RDB$FIELD_SOURCE RDB$RELATION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RELATION_ID + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$RELATION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$RELATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 19 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 19 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_SOURCE RDB$RELATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$RELATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 13 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 13 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$RELATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$FIELD_SOURCE RDB$RELATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$RELATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$RELATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$FIELD_SOURCE RDB$GENERIC_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RELATION_NAME + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$FIELD_SOURCE RDB$RELATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RELATION_TYPE + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$RELATION_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 16 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 16 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RETURN_ARGUMENT + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$FIELD_POSITION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$ROLE_NAME + RDB$RELATION_NAME RDB$ROLES + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RUNTIME + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$RUNTIME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$RUNTIME + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$RUNTIME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 11 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 11 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SCN + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_SOURCE RDB$SCN + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$RELATION_NAME RDB$DATABASE + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 28 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 28 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 16 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 16 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$RELATION_NAME RDB$GENERATORS + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 14 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 14 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$RELATION_NAME RDB$ROLES + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SECURITY_CLASS + RDB$RELATION_NAME RDB$SECURITY_CLASSES + RDB$FIELD_SOURCE RDB$SECURITY_CLASS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SEGMENT_COUNT + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_SOURCE RDB$SEGMENT_COUNT + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SEGMENT_LENGTH + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$SEGMENT_LENGTH + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 17 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 17 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SHADOW_NUMBER + RDB$RELATION_NAME RDB$FILES + RDB$FIELD_SOURCE RDB$SHADOW_NUMBER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SPECIFIC_ATTRIBUTES + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_SOURCE RDB$SPECIFIC_ATTRIBUTES + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SQL_SECURITY + RDB$RELATION_NAME RDB$DATABASE + RDB$FIELD_SOURCE RDB$SQL_SECURITY + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SQL_SECURITY + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$SQL_SECURITY + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 20 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 20 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SQL_SECURITY + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_SOURCE RDB$SQL_SECURITY + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SQL_SECURITY + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$SQL_SECURITY + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 18 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 18 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SQL_SECURITY + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$SQL_SECURITY + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 17 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 17 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SQL_SECURITY + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$SQL_SECURITY + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 14 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 14 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$STATISTICS + RDB$RELATION_NAME RDB$INDEX_SEGMENTS + RDB$FIELD_SOURCE RDB$STATISTICS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$STATISTICS + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_SOURCE RDB$STATISTICS + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 12 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 12 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 15 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 15 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 20 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 20 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$GENERATORS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 9 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 9 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$PUBLICATIONS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 13 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 13 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$ROLES + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$RELATION_NAME RDB$TYPES + RDB$FIELD_SOURCE RDB$SYSTEM_FLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$SYSTEM_PRIVILEGES + RDB$RELATION_NAME RDB$ROLES + RDB$FIELD_SOURCE RDB$SYSTEM_PRIVILEGES + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TABLE_NAME + RDB$RELATION_NAME RDB$PUBLICATION_TABLES + RDB$FIELD_SOURCE RDB$RELATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TIMESTAMP + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_SOURCE RDB$TIMESTAMP_TZ + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TIMESTAMP + RDB$RELATION_NAME RDB$TRANSACTIONS + RDB$FIELD_SOURCE RDB$TIMESTAMP_TZ + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TIME_ZONE_ID + RDB$RELATION_NAME RDB$TIME_ZONES + RDB$FIELD_SOURCE RDB$TIME_ZONE_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TIME_ZONE_NAME + RDB$RELATION_NAME RDB$TIME_ZONES + RDB$FIELD_SOURCE RDB$TIME_ZONE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TRANSACTION_DESCRIPTION + RDB$RELATION_NAME RDB$TRANSACTIONS + RDB$FIELD_SOURCE RDB$TRANSACTION_DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TRANSACTION_ID + RDB$RELATION_NAME RDB$TRANSACTIONS + RDB$FIELD_SOURCE RDB$TRANSACTION_ID + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TRANSACTION_STATE + RDB$RELATION_NAME RDB$TRANSACTIONS + RDB$FIELD_SOURCE RDB$TRANSACTION_STATE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TRIGGER_BLR + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$TRIGGER_BLR + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TRIGGER_INACTIVE + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TRIGGER_NAME + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$FIELD_SOURCE RDB$TRIGGER_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TRIGGER_NAME + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$TRIGGER_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TRIGGER_NAME + RDB$RELATION_NAME RDB$TRIGGER_MESSAGES + RDB$FIELD_SOURCE RDB$TRIGGER_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TRIGGER_SEQUENCE + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$TRIGGER_SEQUENCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TRIGGER_SOURCE + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TRIGGER_TYPE + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$TRIGGER_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TYPE + RDB$RELATION_NAME RDB$TYPES + RDB$FIELD_SOURCE RDB$GENERIC_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$TYPE_NAME + RDB$RELATION_NAME RDB$TYPES + RDB$FIELD_SOURCE RDB$TYPE_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$UNIQUE_FLAG + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$UPDATE_FLAG + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 8 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 8 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$UPDATE_RULE + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$FIELD_SOURCE RDB$RULE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$UPPER_BOUND + RDB$RELATION_NAME RDB$FIELD_DIMENSIONS + RDB$FIELD_SOURCE RDB$BOUND + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$USER + RDB$RELATION_NAME RDB$DB_CREATORS + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$USER + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$USER_TYPE + RDB$RELATION_NAME RDB$DB_CREATORS + RDB$FIELD_SOURCE RDB$OBJECT_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$USER_TYPE + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$FIELD_SOURCE RDB$OBJECT_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$VALIDATION_BLR + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$VALIDATION_BLR + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$VALIDATION_SOURCE + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$VALID_BLR + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 14 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 14 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$VALID_BLR + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 12 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 12 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$VALID_BLR + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$VALID_BODY_FLAG + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_SOURCE RDB$SYSTEM_NULLFLAG + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$VIEW_BLR + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$VIEW_BLR + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$VIEW_CONTEXT + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_SOURCE RDB$VIEW_CONTEXT + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 10 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 10 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$VIEW_CONTEXT + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$FIELD_SOURCE RDB$VIEW_CONTEXT + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$VIEW_NAME + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$FIELD_SOURCE RDB$RELATION_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME RDB$VIEW_SOURCE + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_SOURCE RDB$SOURCE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 1 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$ACTIVE + RDB$RELATION_NAME SEC$USERS + RDB$FIELD_SOURCE RDB$BOOLEAN + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$ADMIN + RDB$RELATION_NAME SEC$USERS + RDB$FIELD_SOURCE RDB$BOOLEAN + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$DESCRIPTION + RDB$RELATION_NAME SEC$USERS + RDB$FIELD_SOURCE RDB$DESCRIPTION + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$FIRST_NAME + RDB$RELATION_NAME SEC$USERS + RDB$FIELD_SOURCE SEC$NAME_PART + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$KEY + RDB$RELATION_NAME SEC$USER_ATTRIBUTES + RDB$FIELD_SOURCE SEC$KEY + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$LAST_NAME + RDB$RELATION_NAME SEC$USERS + RDB$FIELD_SOURCE SEC$NAME_PART + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$MAP_DB + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$FIELD_SOURCE RDB$MAP_DB + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$MAP_FROM + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$FIELD_SOURCE RDB$MAP_FROM + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 5 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 5 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$MAP_FROM_TYPE + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$FIELD_SOURCE RDB$MAP_FROM_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 4 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 4 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$MAP_NAME + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$FIELD_SOURCE RDB$MAP_NAME + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$MAP_PLUGIN + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$FIELD_SOURCE RDB$PLUGIN + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$MAP_TO + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$FIELD_SOURCE RDB$MAP_TO + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$MAP_TO_TYPE + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$FIELD_SOURCE RDB$OBJECT_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 6 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 6 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$MAP_USING + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$FIELD_SOURCE RDB$MAP_USING + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$MIDDLE_NAME + RDB$RELATION_NAME SEC$USERS + RDB$FIELD_SOURCE SEC$NAME_PART + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$PLUGIN + RDB$RELATION_NAME SEC$USERS + RDB$FIELD_SOURCE RDB$PLUGIN + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 7 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 7 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$PLUGIN + RDB$RELATION_NAME SEC$USER_ATTRIBUTES + RDB$FIELD_SOURCE RDB$PLUGIN + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 3 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 3 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$USER + RDB$RELATION_NAME SEC$DB_CREATORS + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$USER_NAME + RDB$RELATION_NAME SEC$USERS + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$USER_NAME + RDB$RELATION_NAME SEC$USER_ATTRIBUTES + RDB$FIELD_SOURCE RDB$USER + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 0 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 0 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$USER_TYPE + RDB$RELATION_NAME SEC$DB_CREATORS + RDB$FIELD_SOURCE RDB$OBJECT_TYPE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 1 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 1 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + RDB$FIELD_NAME SEC$VALUE + RDB$RELATION_NAME SEC$USER_ATTRIBUTES + RDB$FIELD_SOURCE SEC$VALUE + RDB$QUERY_NAME + RDB$BASE_FIELD + RDB$EDIT_STRING + RDB$FIELD_POSITION 2 + RDB$QUERY_HEADER + RDB$UPDATE_FLAG 0 + RDB$FIELD_ID 2 + RDB$VIEW_CONTEXT + RDB$DESCRIPTION + RDB$DEFAULT_VALUE + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS + RDB$COMPLEX_NAME + RDB$NULL_FLAG + RDB$DEFAULT_SOURCE + RDB$COLLATION_ID + RDB$GENERATOR_NAME + RDB$IDENTITY_TYPE + + + Records affected: 495 + """ + +@pytest.mark.version('>=4.0') +def test_db_24_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/functional/basic/db/test_25.py b/tests/functional/basic/db/test_25.py new file mode 100644 index 00000000..f001cdbc --- /dev/null +++ b/tests/functional/basic/db/test_25.py @@ -0,0 +1,82 @@ +#coding:utf-8 +# +# id: functional.basic.db.25 +# title: Empty DB - RDB$ROLES +# decription: Check for correct content of RDB$ROLES in empty database. +# tracker_id: +# min_versions: [] +# versions: 3.0, 4.0 +# qmid: functional.basic.db.db_25 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('RDB\\$SECURITY_CLASS\\s+SQL.*', 'RDB\\$SECURITY_CLASS SQL'), ('[\t ]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + -- NB: rdb$role_name is UNIQUE column. + select * from rdb$roles order by rdb$role_name; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$ROLE_NAME RDB$ADMIN + RDB$OWNER_NAME SYSDBA + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS SQL$162 + + Records affected: 1 + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_25_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [('RDB\\$SECURITY_CLASS\\s+SQL.*', 'RDB\\$SECURITY_CLASS SQL'), ('[\t ]+', ' ')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set list on; + set count on; + -- NB: rdb$role_name is UNIQUE column. + select * from rdb$roles order by rdb$role_name; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + RDB$ROLE_NAME RDB$ADMIN + RDB$OWNER_NAME SYSDBA + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS SQL$383 + RDB$SYSTEM_PRIVILEGES FFFFFFFFFFFFFFFF + + Records affected: 1 + """ + +@pytest.mark.version('>=4.0') +def test_25_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/functional/basic/db/test_26.py b/tests/functional/basic/db/test_26.py new file mode 100644 index 00000000..cf63022a --- /dev/null +++ b/tests/functional/basic/db/test_26.py @@ -0,0 +1,7934 @@ +#coding:utf-8 +# +# id: functional.basic.db.db_26 +# title: Empty DB - RDB$SECURITY_CLASSES +# decription: Check for correct content of RDB$SECURITY_CLASSES in empty database. +# tracker_id: +# min_versions: ['2.5.7'] +# versions: 3.0, 4.0 +# qmid: functional.basic.db.db_26 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('RDB\\$ACL.*', ''), ('RDB\\$SECURITY_CLASS[\\s]+SQL\\$.*', 'RDB\\$SECURITY_CLASS SQL\\$'), ('[\t ]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- 28.10.2015 + -- Updated expected_stdout, added block to subst-section in order to ignore differences + -- in values like "SQL$****" of field RDB$SECURITY_CLASS. + + set list on; + set blob 3; + set count on; + select * + from rdb$security_classes + order by rdb$security_class; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$SECURITY_CLASS SQL$1 + RDB$ACL 9:0 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$10 + RDB$ACL 9:9 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$100 + RDB$ACL 9:63 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$101 + RDB$ACL 9:64 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$102 + RDB$ACL 9:65 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$103 + RDB$ACL 9:66 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$104 + RDB$ACL 9:67 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$105 + RDB$ACL 9:68 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$106 + RDB$ACL 9:69 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$107 + RDB$ACL 9:6a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$108 + RDB$ACL 9:6b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$109 + RDB$ACL 9:6c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$11 + RDB$ACL 9:a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$110 + RDB$ACL 9:6d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$111 + RDB$ACL 9:6e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$112 + RDB$ACL 9:6f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$113 + RDB$ACL 9:70 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$114 + RDB$ACL 9:71 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$115 + RDB$ACL 9:72 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$116 + RDB$ACL 9:73 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$117 + RDB$ACL 9:74 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$118 + RDB$ACL 9:75 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$119 + RDB$ACL 9:76 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$12 + RDB$ACL 9:b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$120 + RDB$ACL 9:77 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$121 + RDB$ACL 9:78 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$122 + RDB$ACL 9:79 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$123 + RDB$ACL 9:7a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$124 + RDB$ACL 9:7b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$125 + RDB$ACL 9:7c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$126 + RDB$ACL 9:7d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$127 + RDB$ACL 9:7e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$128 + RDB$ACL 9:7f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$129 + RDB$ACL 9:80 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$13 + RDB$ACL 9:c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$130 + RDB$ACL 9:81 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$131 + RDB$ACL 9:82 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$132 + RDB$ACL 9:83 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$133 + RDB$ACL 9:84 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$134 + RDB$ACL 9:85 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$135 + RDB$ACL 9:86 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$136 + RDB$ACL 9:87 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$137 + RDB$ACL 9:5a0 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$138 + RDB$ACL 9:5a1 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$139 + RDB$ACL 9:5a2 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$14 + RDB$ACL 9:d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$140 + RDB$ACL 9:5a3 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$141 + RDB$ACL 9:5a4 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$142 + RDB$ACL 9:5a5 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$143 + RDB$ACL 9:5a6 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$144 + RDB$ACL 9:5a7 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$145 + RDB$ACL 9:5a8 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$146 + RDB$ACL 9:5a9 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$147 + RDB$ACL 9:5aa + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$148 + RDB$ACL 9:5ab + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$149 + RDB$ACL 9:5ac + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$15 + RDB$ACL 9:e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$150 + RDB$ACL 9:5ad + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$151 + RDB$ACL 9:5ae + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$152 + RDB$ACL 9:5af + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$153 + RDB$ACL 9:5b0 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$154 + RDB$ACL 9:5b1 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$155 + RDB$ACL 9:5b2 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$156 + RDB$ACL 9:5b3 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$157 + RDB$ACL 9:5b4 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$158 + RDB$ACL 9:5b5 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$159 + RDB$ACL 9:5b6 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$16 + RDB$ACL 9:f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$160 + RDB$ACL 9:5b7 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$161 + RDB$ACL 9:5b8 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$162 + RDB$ACL 9:5b9 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$163 + RDB$ACL 9:5ba + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$164 + RDB$ACL 9:5bb + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$165 + RDB$ACL 9:5bc + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$166 + RDB$ACL 9:5bd + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$167 + RDB$ACL 9:5be + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$168 + RDB$ACL 9:5bf + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$169 + RDB$ACL 9:5c0 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$17 + RDB$ACL 9:10 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$170 + RDB$ACL 9:5c1 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$171 + RDB$ACL 9:5c2 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$172 + RDB$ACL 9:5c3 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$173 + RDB$ACL 9:5c4 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$174 + RDB$ACL 9:5c5 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$175 + RDB$ACL 9:5c6 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$176 + RDB$ACL 9:5c7 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$177 + RDB$ACL 9:5c8 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$178 + RDB$ACL 9:5c9 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$179 + RDB$ACL 9:5ca + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$18 + RDB$ACL 9:11 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$180 + RDB$ACL 9:5cb + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$181 + RDB$ACL 9:5cc + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$182 + RDB$ACL 9:5cd + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$183 + RDB$ACL 9:5ce + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$184 + RDB$ACL 9:5cf + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$185 + RDB$ACL 9:5d0 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$186 + RDB$ACL 9:5d1 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$187 + RDB$ACL 9:5d2 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$188 + RDB$ACL 9:5d3 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$189 + RDB$ACL 9:5d4 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$19 + RDB$ACL 9:12 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$190 + RDB$ACL 9:5d5 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$191 + RDB$ACL 9:5d6 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$192 + RDB$ACL 9:5d7 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$193 + RDB$ACL 9:5d8 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$194 + RDB$ACL 9:5d9 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$195 + RDB$ACL 9:5da + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$196 + RDB$ACL 9:5db + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$197 + RDB$ACL 9:5dc + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$198 + RDB$ACL 9:5dd + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$199 + RDB$ACL 9:5de + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$2 + RDB$ACL 9:1 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$20 + RDB$ACL 9:13 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$200 + RDB$ACL 9:5df + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$201 + RDB$ACL 9:5e0 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$202 + RDB$ACL 9:5e1 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$203 + RDB$ACL 9:5e2 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$204 + RDB$ACL 9:5e3 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$205 + RDB$ACL 9:5e4 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$206 + RDB$ACL 9:5e5 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$207 + RDB$ACL 9:5e6 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$208 + RDB$ACL 9:5e7 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$209 + RDB$ACL 9:5e8 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$21 + RDB$ACL 9:14 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$210 + RDB$ACL 9:5e9 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$211 + RDB$ACL 9:5ea + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$212 + RDB$ACL 9:5eb + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$213 + RDB$ACL 9:5ec + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$214 + RDB$ACL 9:5ed + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$215 + RDB$ACL 9:5ee + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$216 + RDB$ACL 9:5ef + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$217 + RDB$ACL 9:5f0 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$218 + RDB$ACL 9:5f1 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$219 + RDB$ACL 9:5f2 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$22 + RDB$ACL 9:15 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$220 + RDB$ACL 9:5f3 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$221 + RDB$ACL 9:5f4 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$222 + RDB$ACL 9:5f5 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$223 + RDB$ACL 9:5f6 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$224 + RDB$ACL 9:5f7 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$225 + RDB$ACL 9:5f8 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$226 + RDB$ACL 9:5f9 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$227 + RDB$ACL 9:5fa + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$228 + RDB$ACL 9:5fb + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$229 + RDB$ACL 9:5fc + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$23 + RDB$ACL 9:16 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$230 + RDB$ACL 9:5fd + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$231 + RDB$ACL 9:5fe + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$232 + RDB$ACL 9:5ff + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$233 + RDB$ACL 9:600 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$234 + RDB$ACL 9:601 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$235 + RDB$ACL 9:602 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$236 + RDB$ACL 9:603 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$237 + RDB$ACL 9:604 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$238 + RDB$ACL 9:605 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$239 + RDB$ACL 9:606 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$24 + RDB$ACL 9:17 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$240 + RDB$ACL 9:607 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$241 + RDB$ACL 9:608 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$242 + RDB$ACL 9:609 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$243 + RDB$ACL 9:60a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$244 + RDB$ACL 9:60b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$245 + RDB$ACL 9:60c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$246 + RDB$ACL 9:60d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$247 + RDB$ACL 9:60e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$248 + RDB$ACL 9:60f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$249 + RDB$ACL 9:610 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$25 + RDB$ACL 9:18 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$250 + RDB$ACL 9:611 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$251 + RDB$ACL 9:612 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$252 + RDB$ACL 9:613 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$253 + RDB$ACL 9:614 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$254 + RDB$ACL 9:615 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$255 + RDB$ACL 9:616 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$256 + RDB$ACL 9:617 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$257 + RDB$ACL 9:618 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$258 + RDB$ACL 9:619 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$259 + RDB$ACL 9:61a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$26 + RDB$ACL 9:19 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$260 + RDB$ACL 9:61b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$261 + RDB$ACL 9:61c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$262 + RDB$ACL 9:61d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$263 + RDB$ACL 9:61e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$264 + RDB$ACL 9:61f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$265 + RDB$ACL 9:620 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$266 + RDB$ACL 9:621 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$267 + RDB$ACL 9:622 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$268 + RDB$ACL 9:623 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$269 + RDB$ACL 9:624 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$27 + RDB$ACL 9:1a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$270 + RDB$ACL 9:625 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$271 + RDB$ACL 9:626 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$272 + RDB$ACL 9:627 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$273 + RDB$ACL 9:960 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$274 + RDB$ACL 9:961 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$275 + RDB$ACL 9:962 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$276 + RDB$ACL 9:963 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$277 + RDB$ACL 9:964 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$278 + RDB$ACL 9:965 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$279 + RDB$ACL 9:966 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$28 + RDB$ACL 9:1b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$280 + RDB$ACL 9:967 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$281 + RDB$ACL 9:968 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$282 + RDB$ACL 9:969 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$283 + RDB$ACL 9:96a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$284 + RDB$ACL 9:96b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$285 + RDB$ACL 9:96c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$286 + RDB$ACL 9:96d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$287 + RDB$ACL 9:96e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$288 + RDB$ACL 9:96f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$289 + RDB$ACL 9:970 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$29 + RDB$ACL 9:1c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$290 + RDB$ACL 9:971 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$291 + RDB$ACL 9:972 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$292 + RDB$ACL 9:973 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$293 + RDB$ACL 9:974 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$294 + RDB$ACL 9:975 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$295 + RDB$ACL 9:976 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$296 + RDB$ACL 9:977 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$297 + RDB$ACL 9:978 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$298 + RDB$ACL 9:979 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$299 + RDB$ACL 9:97a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$3 + RDB$ACL 9:2 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$30 + RDB$ACL 9:1d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$300 + RDB$ACL 9:97b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$301 + RDB$ACL 9:97c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$302 + RDB$ACL 9:97d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$303 + RDB$ACL 9:97e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$304 + RDB$ACL 9:97f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$305 + RDB$ACL 9:980 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$306 + RDB$ACL 9:981 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$307 + RDB$ACL 9:982 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$308 + RDB$ACL 9:983 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$309 + RDB$ACL 9:984 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$31 + RDB$ACL 9:1e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$310 + RDB$ACL 9:985 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$311 + RDB$ACL 9:986 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$312 + RDB$ACL 9:987 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$313 + RDB$ACL 9:988 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$314 + RDB$ACL 9:989 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$315 + RDB$ACL 9:98a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$316 + RDB$ACL 9:98b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$317 + RDB$ACL 9:98c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$318 + RDB$ACL 9:98d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$319 + RDB$ACL 9:98e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$32 + RDB$ACL 9:1f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$320 + RDB$ACL 9:98f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$321 + RDB$ACL 9:990 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$322 + RDB$ACL 9:991 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$323 + RDB$ACL 9:992 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$324 + RDB$ACL 9:993 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$325 + RDB$ACL 9:994 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$326 + RDB$ACL 9:995 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$327 + RDB$ACL 9:996 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$328 + RDB$ACL 9:997 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$329 + RDB$ACL 9:998 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$33 + RDB$ACL 9:20 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$330 + RDB$ACL 9:999 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$331 + RDB$ACL 9:99a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$332 + RDB$ACL 9:99b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$333 + RDB$ACL 9:99c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$334 + RDB$ACL 9:99d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$335 + RDB$ACL 9:99e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$336 + RDB$ACL 9:99f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$337 + RDB$ACL 9:9a0 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$338 + RDB$ACL 9:9a1 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$339 + RDB$ACL 9:9a2 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$34 + RDB$ACL 9:21 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$340 + RDB$ACL 9:9a3 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$341 + RDB$ACL 9:9a4 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$342 + RDB$ACL 9:9a5 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$343 + RDB$ACL 9:9a6 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$344 + RDB$ACL 9:9a7 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$345 + RDB$ACL 9:9a8 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$346 + RDB$ACL 9:9a9 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$347 + RDB$ACL 9:9aa + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$348 + RDB$ACL 9:9ab + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$349 + RDB$ACL 9:9ac + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$35 + RDB$ACL 9:22 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$350 + RDB$ACL 9:9ad + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$351 + RDB$ACL 9:9ae + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$352 + RDB$ACL 9:9af + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$353 + RDB$ACL 9:9b0 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$354 + RDB$ACL 9:9b1 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$355 + RDB$ACL 9:9b2 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$356 + RDB$ACL 9:9b3 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$357 + RDB$ACL 9:9b4 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$358 + RDB$ACL 9:9b5 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$359 + RDB$ACL 9:9b6 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$36 + RDB$ACL 9:23 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$360 + RDB$ACL 9:9b7 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$361 + RDB$ACL 9:9b8 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$362 + RDB$ACL 9:9b9 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$363 + RDB$ACL 9:9ba + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$364 + RDB$ACL 9:9c7 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop) + all users: (*.*), privileges: () + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$365 + RDB$ACL 9:9c8 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$366 + RDB$ACL 9:9ca + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$367 + RDB$ACL 9:9cc + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$368 + RDB$ACL 9:9ce + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$369 + RDB$ACL 9:9d0 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$37 + RDB$ACL 9:24 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$370 + RDB$ACL 9:9d2 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$371 + RDB$ACL 9:9d4 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$372 + RDB$ACL 9:9d6 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$373 + RDB$ACL 9:9d8 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$374 + RDB$ACL 9:9da + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$375 + RDB$ACL 9:9dc + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$376 + RDB$ACL 9:9de + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$377 + RDB$ACL 9:9e0 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$378 + RDB$ACL 9:9e2 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$379 + RDB$ACL 9:9e4 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$38 + RDB$ACL 9:25 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$380 + RDB$ACL 9:9e6 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$381 + RDB$ACL 9:9e8 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$382 + RDB$ACL 9:d21 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$383 + RDB$ACL 9:d23 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$384 + RDB$ACL 9:d25 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$385 + RDB$ACL 9:d27 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$386 + RDB$ACL 9:d29 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$387 + RDB$ACL 9:d2b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$388 + RDB$ACL 9:d2d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$389 + RDB$ACL 9:d2f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$39 + RDB$ACL 9:26 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$390 + RDB$ACL 9:d31 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$391 + RDB$ACL 9:d33 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$392 + RDB$ACL 9:d35 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$393 + RDB$ACL 9:d37 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$394 + RDB$ACL 9:d39 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$395 + RDB$ACL 9:d3b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$396 + RDB$ACL 9:d3d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$397 + RDB$ACL 9:d3f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$398 + RDB$ACL 9:d41 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$399 + RDB$ACL 9:d43 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$4 + RDB$ACL 9:3 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$40 + RDB$ACL 9:27 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$400 + RDB$ACL 9:d45 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$401 + RDB$ACL 9:d47 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$402 + RDB$ACL 9:d49 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$403 + RDB$ACL 9:d4b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$404 + RDB$ACL 9:d4d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$405 + RDB$ACL 9:d4f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$406 + RDB$ACL 9:d51 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$407 + RDB$ACL 9:d53 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$408 + RDB$ACL 9:d55 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$409 + RDB$ACL 9:d57 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$41 + RDB$ACL 9:28 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$410 + RDB$ACL 9:d59 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$411 + RDB$ACL 9:d5b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$412 + RDB$ACL 9:d5d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$413 + RDB$ACL 9:d5f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$414 + RDB$ACL 9:d61 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$42 + RDB$ACL 9:29 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$43 + RDB$ACL 9:2a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$44 + RDB$ACL 9:2b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$45 + RDB$ACL 9:2c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$46 + RDB$ACL 9:2d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$47 + RDB$ACL 9:2e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$48 + RDB$ACL 9:2f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$49 + RDB$ACL 9:30 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$5 + RDB$ACL 9:4 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$50 + RDB$ACL 9:31 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$51 + RDB$ACL 9:32 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$52 + RDB$ACL 9:33 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$53 + RDB$ACL 9:34 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$54 + RDB$ACL 9:35 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$55 + RDB$ACL 9:36 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$56 + RDB$ACL 9:37 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$57 + RDB$ACL 9:38 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$58 + RDB$ACL 9:39 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$59 + RDB$ACL 9:3a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$6 + RDB$ACL 9:5 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$60 + RDB$ACL 9:3b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$61 + RDB$ACL 9:3c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$62 + RDB$ACL 9:3d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$63 + RDB$ACL 9:3e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$64 + RDB$ACL 9:3f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$65 + RDB$ACL 9:40 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$66 + RDB$ACL 9:41 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$67 + RDB$ACL 9:42 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$68 + RDB$ACL 9:43 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$69 + RDB$ACL 9:44 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$7 + RDB$ACL 9:6 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$70 + RDB$ACL 9:45 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$71 + RDB$ACL 9:46 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$72 + RDB$ACL 9:47 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$73 + RDB$ACL 9:48 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$74 + RDB$ACL 9:49 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$75 + RDB$ACL 9:4a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$76 + RDB$ACL 9:4b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$77 + RDB$ACL 9:4c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$78 + RDB$ACL 9:4d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$79 + RDB$ACL 9:4e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$8 + RDB$ACL 9:7 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$80 + RDB$ACL 9:4f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$81 + RDB$ACL 9:50 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$82 + RDB$ACL 9:51 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$83 + RDB$ACL 9:52 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$84 + RDB$ACL 9:53 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$85 + RDB$ACL 9:54 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$86 + RDB$ACL 9:55 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$87 + RDB$ACL 9:56 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$88 + RDB$ACL 9:57 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$89 + RDB$ACL 9:58 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$9 + RDB$ACL 9:8 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$90 + RDB$ACL 9:59 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$91 + RDB$ACL 9:5a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$92 + RDB$ACL 9:5b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$93 + RDB$ACL 9:5c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$94 + RDB$ACL 9:5d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$95 + RDB$ACL 9:5e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$96 + RDB$ACL 9:5f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$97 + RDB$ACL 9:60 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$98 + RDB$ACL 9:61 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$99 + RDB$ACL 9:62 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$CHARSETS + RDB$ACL 9:9c4 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop) + all users: (*.*), privileges: () + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$COLLATIONS + RDB$ACL 9:9c5 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop) + all users: (*.*), privileges: () + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT1 + RDB$ACL 9:9c9 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT10 + RDB$ACL 9:9db + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT11 + RDB$ACL 9:9dd + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT12 + RDB$ACL 9:9df + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT13 + RDB$ACL 9:9e1 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT14 + RDB$ACL 9:9e3 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT15 + RDB$ACL 9:9e5 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT16 + RDB$ACL 9:9e7 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT17 + RDB$ACL 9:d20 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT18 + RDB$ACL 9:d22 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT19 + RDB$ACL 9:d24 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT2 + RDB$ACL 9:9cb + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT20 + RDB$ACL 9:d26 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT21 + RDB$ACL 9:d28 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT22 + RDB$ACL 9:d2a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT23 + RDB$ACL 9:d2c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT24 + RDB$ACL 9:d2e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT25 + RDB$ACL 9:d30 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT26 + RDB$ACL 9:d32 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT27 + RDB$ACL 9:d34 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT28 + RDB$ACL 9:d36 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT29 + RDB$ACL 9:d38 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT3 + RDB$ACL 9:9cd + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT30 + RDB$ACL 9:d3a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT31 + RDB$ACL 9:d3c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT32 + RDB$ACL 9:d3e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT33 + RDB$ACL 9:d40 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT34 + RDB$ACL 9:d42 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT35 + RDB$ACL 9:d44 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT36 + RDB$ACL 9:d46 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT37 + RDB$ACL 9:d48 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT38 + RDB$ACL 9:d4a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT39 + RDB$ACL 9:d4c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT4 + RDB$ACL 9:9cf + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT40 + RDB$ACL 9:d4e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT41 + RDB$ACL 9:d50 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT42 + RDB$ACL 9:d52 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT43 + RDB$ACL 9:d54 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT44 + RDB$ACL 9:d56 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT45 + RDB$ACL 9:d58 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT46 + RDB$ACL 9:d5a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT47 + RDB$ACL 9:d5c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT48 + RDB$ACL 9:d5e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT49 + RDB$ACL 9:d60 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT5 + RDB$ACL 9:9d1 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT50 + RDB$ACL 9:d62 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT6 + RDB$ACL 9:9d3 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT7 + RDB$ACL 9:9d5 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT8 + RDB$ACL 9:9d7 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT9 + RDB$ACL 9:9d9 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DOMAINS + RDB$ACL 9:9c1 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop) + all users: (*.*), privileges: () + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$EXCEPTIONS + RDB$ACL 9:9c2 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop) + all users: (*.*), privileges: () + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$FILTERS + RDB$ACL 9:9c6 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop) + all users: (*.*), privileges: () + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$FUNCTIONS + RDB$ACL 9:9be + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop) + all users: (*.*), privileges: () + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$GENERATORS + RDB$ACL 9:9c0 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop) + all users: (*.*), privileges: () + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$PACKAGES + RDB$ACL 9:9bf + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop) + all users: (*.*), privileges: () + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$PROCEDURES + RDB$ACL 9:9bd + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop) + all users: (*.*), privileges: () + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$ROLES + RDB$ACL 9:9c3 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop) + all users: (*.*), privileges: () + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$TABLES + RDB$ACL 9:9bb + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop) + all users: (*.*), privileges: () + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$VIEWS + RDB$ACL 9:9bc + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop) + all users: (*.*), privileges: () + + RDB$DESCRIPTION + + + Records affected: 476 + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_db_26_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [('RDB\\$ACL.*', ''), ('RDB\\$SECURITY_CLASS[\\s]+SQL\\$.*', 'RDB\\$SECURITY_CLASS SQL\\$'), ('[\t ]+', ' ')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set list on; + set blob 3; + set count on; + -- NB: 'rdb$security_class' is unique field, see DDL. + select * + from rdb$security_classes + order by rdb$security_class; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + RDB$SECURITY_CLASS SQL$1 + RDB$ACL 9:0 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$10 + RDB$ACL 9:9 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$100 + RDB$ACL 9:63 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$101 + RDB$ACL 9:64 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$102 + RDB$ACL 9:65 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$103 + RDB$ACL 9:66 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$104 + RDB$ACL 9:67 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$105 + RDB$ACL 9:68 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$106 + RDB$ACL 9:69 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$107 + RDB$ACL 9:6a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$108 + RDB$ACL 9:6b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$109 + RDB$ACL 9:6c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$11 + RDB$ACL 9:a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$110 + RDB$ACL 9:6d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$111 + RDB$ACL 9:6e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$112 + RDB$ACL 9:6f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$113 + RDB$ACL 9:70 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$114 + RDB$ACL 9:71 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$115 + RDB$ACL 9:72 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$116 + RDB$ACL 9:73 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$117 + RDB$ACL 9:74 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$118 + RDB$ACL 9:75 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$119 + RDB$ACL 9:76 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$12 + RDB$ACL 9:b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$120 + RDB$ACL 9:77 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$121 + RDB$ACL 9:78 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$122 + RDB$ACL 9:79 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$123 + RDB$ACL 9:7a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$124 + RDB$ACL 9:7b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$125 + RDB$ACL 9:7c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$126 + RDB$ACL 9:7d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$127 + RDB$ACL 9:7e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$128 + RDB$ACL 9:7f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$129 + RDB$ACL 9:80 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$13 + RDB$ACL 9:c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$130 + RDB$ACL 9:81 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$131 + RDB$ACL 9:82 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$132 + RDB$ACL 9:83 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$133 + RDB$ACL 9:84 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$134 + RDB$ACL 9:85 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$135 + RDB$ACL 9:86 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$136 + RDB$ACL 9:87 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$137 + RDB$ACL 9:5a0 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$138 + RDB$ACL 9:5a1 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$139 + RDB$ACL 9:5a2 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$14 + RDB$ACL 9:d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$140 + RDB$ACL 9:5a3 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$141 + RDB$ACL 9:5a4 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$142 + RDB$ACL 9:5a5 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$143 + RDB$ACL 9:5a6 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$144 + RDB$ACL 9:5a7 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$145 + RDB$ACL 9:5a8 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$146 + RDB$ACL 9:5a9 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$147 + RDB$ACL 9:5aa + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$148 + RDB$ACL 9:5ab + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$149 + RDB$ACL 9:5ac + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$15 + RDB$ACL 9:e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$150 + RDB$ACL 9:5ad + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$151 + RDB$ACL 9:5ae + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$152 + RDB$ACL 9:5af + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$153 + RDB$ACL 9:5b0 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$154 + RDB$ACL 9:5b1 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$155 + RDB$ACL 9:5b2 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$156 + RDB$ACL 9:5b3 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$157 + RDB$ACL 9:5b4 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$158 + RDB$ACL 9:5b5 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$159 + RDB$ACL 9:5b6 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$16 + RDB$ACL 9:f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$160 + RDB$ACL 9:5b7 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$161 + RDB$ACL 9:5b8 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$162 + RDB$ACL 9:5b9 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$163 + RDB$ACL 9:5ba + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$164 + RDB$ACL 9:5bb + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$165 + RDB$ACL 9:5bc + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$166 + RDB$ACL 9:5bd + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$167 + RDB$ACL 9:5be + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$168 + RDB$ACL 9:5bf + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$169 + RDB$ACL 9:5c0 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$17 + RDB$ACL 9:10 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$170 + RDB$ACL 9:5c1 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$171 + RDB$ACL 9:5c2 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$172 + RDB$ACL 9:5c3 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$173 + RDB$ACL 9:5c4 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$174 + RDB$ACL 9:5c5 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$175 + RDB$ACL 9:5c6 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$176 + RDB$ACL 9:5c7 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$177 + RDB$ACL 9:5c8 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$178 + RDB$ACL 9:5c9 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$179 + RDB$ACL 9:5ca + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$18 + RDB$ACL 9:11 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$180 + RDB$ACL 9:5cb + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$181 + RDB$ACL 9:5cc + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$182 + RDB$ACL 9:5cd + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$183 + RDB$ACL 9:5ce + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$184 + RDB$ACL 9:5cf + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$185 + RDB$ACL 9:5d0 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$186 + RDB$ACL 9:5d1 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$187 + RDB$ACL 9:5d2 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$188 + RDB$ACL 9:5d3 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$189 + RDB$ACL 9:5d4 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$19 + RDB$ACL 9:12 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$190 + RDB$ACL 9:5d5 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$191 + RDB$ACL 9:5d6 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$192 + RDB$ACL 9:5d7 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$193 + RDB$ACL 9:5d8 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$194 + RDB$ACL 9:5d9 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$195 + RDB$ACL 9:5da + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$196 + RDB$ACL 9:5db + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$197 + RDB$ACL 9:5dc + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$198 + RDB$ACL 9:5dd + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$199 + RDB$ACL 9:5de + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$2 + RDB$ACL 9:1 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$20 + RDB$ACL 9:13 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$200 + RDB$ACL 9:5df + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$201 + RDB$ACL 9:5e0 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$202 + RDB$ACL 9:5e1 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$203 + RDB$ACL 9:5e2 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$204 + RDB$ACL 9:5e3 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$205 + RDB$ACL 9:5e4 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$206 + RDB$ACL 9:5e5 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$207 + RDB$ACL 9:5e6 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$208 + RDB$ACL 9:5e7 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$209 + RDB$ACL 9:5e8 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$21 + RDB$ACL 9:14 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$210 + RDB$ACL 9:5e9 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$211 + RDB$ACL 9:5ea + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$212 + RDB$ACL 9:5eb + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$213 + RDB$ACL 9:5ec + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$214 + RDB$ACL 9:5ed + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$215 + RDB$ACL 9:5ee + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$216 + RDB$ACL 9:5ef + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$217 + RDB$ACL 9:5f0 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$218 + RDB$ACL 9:5f1 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$219 + RDB$ACL 9:5f2 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$22 + RDB$ACL 9:15 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$220 + RDB$ACL 9:5f3 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$221 + RDB$ACL 9:5f4 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$222 + RDB$ACL 9:5f5 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$223 + RDB$ACL 9:5f6 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$224 + RDB$ACL 9:5f7 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$225 + RDB$ACL 9:5f8 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$226 + RDB$ACL 9:5f9 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$227 + RDB$ACL 9:5fa + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$228 + RDB$ACL 9:5fb + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$229 + RDB$ACL 9:5fc + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$23 + RDB$ACL 9:16 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$230 + RDB$ACL 9:5fd + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$231 + RDB$ACL 9:5fe + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$232 + RDB$ACL 9:5ff + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$233 + RDB$ACL 9:600 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$234 + RDB$ACL 9:601 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$235 + RDB$ACL 9:602 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$236 + RDB$ACL 9:603 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$237 + RDB$ACL 9:604 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$238 + RDB$ACL 9:605 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$239 + RDB$ACL 9:606 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$24 + RDB$ACL 9:17 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$240 + RDB$ACL 9:607 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$241 + RDB$ACL 9:608 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$242 + RDB$ACL 9:609 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$243 + RDB$ACL 9:60a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$244 + RDB$ACL 9:60b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$245 + RDB$ACL 9:60c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$246 + RDB$ACL 9:60d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$247 + RDB$ACL 9:60e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$248 + RDB$ACL 9:60f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$249 + RDB$ACL 9:610 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$25 + RDB$ACL 9:18 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$250 + RDB$ACL 9:611 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$251 + RDB$ACL 9:612 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$252 + RDB$ACL 9:613 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$253 + RDB$ACL 9:614 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$254 + RDB$ACL 9:615 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$255 + RDB$ACL 9:616 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$256 + RDB$ACL 9:617 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$257 + RDB$ACL 9:618 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$258 + RDB$ACL 9:619 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$259 + RDB$ACL 9:61a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$26 + RDB$ACL 9:19 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$260 + RDB$ACL 9:61b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$261 + RDB$ACL 9:61c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$262 + RDB$ACL 9:61d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$263 + RDB$ACL 9:61e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$264 + RDB$ACL 9:61f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$265 + RDB$ACL 9:620 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$266 + RDB$ACL 9:621 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$267 + RDB$ACL 9:622 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$268 + RDB$ACL 9:623 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$269 + RDB$ACL 9:624 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$27 + RDB$ACL 9:1a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$270 + RDB$ACL 9:625 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$271 + RDB$ACL 9:626 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$272 + RDB$ACL 9:627 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$273 + RDB$ACL 9:960 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$274 + RDB$ACL 9:961 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$275 + RDB$ACL 9:962 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$276 + RDB$ACL 9:963 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$277 + RDB$ACL 9:964 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$278 + RDB$ACL 9:965 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$279 + RDB$ACL 9:966 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$28 + RDB$ACL 9:1b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$280 + RDB$ACL 9:967 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$281 + RDB$ACL 9:968 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$282 + RDB$ACL 9:969 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$283 + RDB$ACL 9:96a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$284 + RDB$ACL 9:96b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$285 + RDB$ACL 9:96c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$286 + RDB$ACL 9:96d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$287 + RDB$ACL 9:96e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$288 + RDB$ACL 9:96f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$289 + RDB$ACL 9:970 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$29 + RDB$ACL 9:1c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$290 + RDB$ACL 9:971 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$291 + RDB$ACL 9:972 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$292 + RDB$ACL 9:973 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$293 + RDB$ACL 9:974 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$294 + RDB$ACL 9:975 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$295 + RDB$ACL 9:976 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$296 + RDB$ACL 9:977 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$297 + RDB$ACL 9:978 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$298 + RDB$ACL 9:979 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$299 + RDB$ACL 9:97a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$3 + RDB$ACL 9:2 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$30 + RDB$ACL 9:1d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$300 + RDB$ACL 9:97b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$301 + RDB$ACL 9:97c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$302 + RDB$ACL 9:97d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$303 + RDB$ACL 9:97e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$304 + RDB$ACL 9:97f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$305 + RDB$ACL 9:980 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$306 + RDB$ACL 9:981 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$307 + RDB$ACL 9:982 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$308 + RDB$ACL 9:983 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$309 + RDB$ACL 9:984 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$31 + RDB$ACL 9:1e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$310 + RDB$ACL 9:985 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$311 + RDB$ACL 9:986 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$312 + RDB$ACL 9:987 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$313 + RDB$ACL 9:988 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$314 + RDB$ACL 9:989 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$315 + RDB$ACL 9:98a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$316 + RDB$ACL 9:98b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$317 + RDB$ACL 9:98c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$318 + RDB$ACL 9:98d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$319 + RDB$ACL 9:98e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$32 + RDB$ACL 9:1f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$320 + RDB$ACL 9:98f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$321 + RDB$ACL 9:990 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$322 + RDB$ACL 9:991 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$323 + RDB$ACL 9:992 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$324 + RDB$ACL 9:993 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$325 + RDB$ACL 9:994 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$326 + RDB$ACL 9:995 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$327 + RDB$ACL 9:996 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$328 + RDB$ACL 9:997 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$329 + RDB$ACL 9:998 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$33 + RDB$ACL 9:20 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$330 + RDB$ACL 9:999 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$331 + RDB$ACL 9:99a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$332 + RDB$ACL 9:99b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$333 + RDB$ACL 9:99c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$334 + RDB$ACL 9:99d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$335 + RDB$ACL 9:99e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$336 + RDB$ACL 9:99f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$337 + RDB$ACL 9:9a0 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$338 + RDB$ACL 9:9a1 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$339 + RDB$ACL 9:9a2 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$34 + RDB$ACL 9:21 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$340 + RDB$ACL 9:9a3 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$341 + RDB$ACL 9:9a4 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$342 + RDB$ACL 9:9a5 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$343 + RDB$ACL 9:9a6 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$344 + RDB$ACL 9:9a7 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$345 + RDB$ACL 9:9a8 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$346 + RDB$ACL 9:9a9 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$347 + RDB$ACL 9:9aa + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$348 + RDB$ACL 9:9ab + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$349 + RDB$ACL 9:9ac + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$35 + RDB$ACL 9:22 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$350 + RDB$ACL 9:9ad + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$351 + RDB$ACL 9:9ae + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$352 + RDB$ACL 9:9af + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$353 + RDB$ACL 9:9b0 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$354 + RDB$ACL 9:9b1 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$355 + RDB$ACL 9:9b2 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$356 + RDB$ACL 9:9b3 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$357 + RDB$ACL 9:9b4 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$358 + RDB$ACL 9:9b5 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$359 + RDB$ACL 9:9b6 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$36 + RDB$ACL 9:23 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$360 + RDB$ACL 9:9b7 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$361 + RDB$ACL 9:9b8 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$362 + RDB$ACL 9:9b9 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$363 + RDB$ACL 9:9ba + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$364 + RDB$ACL 9:9bb + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$365 + RDB$ACL 9:9bc + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$366 + RDB$ACL 9:9bd + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$367 + RDB$ACL 9:9be + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$368 + RDB$ACL 9:9bf + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$369 + RDB$ACL 9:9c0 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$37 + RDB$ACL 9:24 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$370 + RDB$ACL 9:9c1 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$371 + RDB$ACL 9:9c2 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$372 + RDB$ACL 9:9c3 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$373 + RDB$ACL 9:9c4 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$374 + RDB$ACL 9:9c5 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$375 + RDB$ACL 9:9c6 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$376 + RDB$ACL 9:9c7 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$377 + RDB$ACL 9:9c8 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$378 + RDB$ACL 9:9c9 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$379 + RDB$ACL 9:9ca + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$38 + RDB$ACL 9:25 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$380 + RDB$ACL 9:9cb + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$381 + RDB$ACL 9:9cc + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$382 + RDB$ACL 9:9cd + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$383 + RDB$ACL 9:9ce + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$384 + RDB$ACL 9:9cf + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (execute) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$385 + RDB$ACL 9:9dc + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop) + all users: (*.*), privileges: () + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$386 + RDB$ACL 9:9dd + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$387 + RDB$ACL 9:9df + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$388 + RDB$ACL 9:9e1 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$389 + RDB$ACL 9:9e3 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$39 + RDB$ACL 9:26 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$390 + RDB$ACL 9:9e5 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$391 + RDB$ACL 9:9e7 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$392 + RDB$ACL 9:d20 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$393 + RDB$ACL 9:d22 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$394 + RDB$ACL 9:d24 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$395 + RDB$ACL 9:d26 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$396 + RDB$ACL 9:d28 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$397 + RDB$ACL 9:d55 + ACL version 1 + person: SYSDBA, privileges: (alter, control, drop, insert, update, delete, select, references) + (null)3, privileges: (insert, update, delete, select, references) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$398 + RDB$ACL 9:d2c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$399 + RDB$ACL 9:d2e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$4 + RDB$ACL 9:3 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$40 + RDB$ACL 9:27 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$400 + RDB$ACL 9:d30 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$401 + RDB$ACL 9:d32 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$402 + RDB$ACL 9:d34 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$403 + RDB$ACL 9:d36 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$404 + RDB$ACL 9:d38 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$405 + RDB$ACL 9:d3a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$406 + RDB$ACL 9:d3c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$407 + RDB$ACL 9:d3e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$408 + RDB$ACL 9:d40 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$409 + RDB$ACL 9:d42 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$41 + RDB$ACL 9:28 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$410 + RDB$ACL 9:d44 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$411 + RDB$ACL 9:d46 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$412 + RDB$ACL 9:d48 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$413 + RDB$ACL 9:d4a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$414 + RDB$ACL 9:d4c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$415 + RDB$ACL 9:d4e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$416 + RDB$ACL 9:d50 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$417 + RDB$ACL 9:d52 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$418 + RDB$ACL 9:d80 + ACL version 1 + person: SYSDBA, privileges: (alter, control, drop, insert, update, delete, select, references) + (null)4, privileges: (insert, update, delete, select, references) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$419 + RDB$ACL 9:d56 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$42 + RDB$ACL 9:29 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$420 + RDB$ACL 9:d58 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$421 + RDB$ACL 9:d5a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$422 + RDB$ACL 9:d5c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$423 + RDB$ACL 9:d5e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$424 + RDB$ACL 9:d60 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$425 + RDB$ACL 9:d62 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$426 + RDB$ACL 9:d64 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$427 + RDB$ACL 9:d66 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$428 + RDB$ACL 9:d68 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$429 + RDB$ACL 9:d6a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$43 + RDB$ACL 9:2a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$430 + RDB$ACL 9:d6c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$431 + RDB$ACL 9:d6e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$432 + RDB$ACL 9:d70 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$433 + RDB$ACL 9:d2b + ACL version 1 + person: SYSDBA, privileges: (alter, control, drop, insert, update, delete, select, references) + (null)22, privileges: (insert, update, delete, select, references) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$434 + RDB$ACL 9:d74 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$435 + RDB$ACL 9:d76 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$436 + RDB$ACL 9:d78 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$437 + RDB$ACL 9:d7a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$438 + RDB$ACL 9:d7c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$439 + RDB$ACL 9:d7e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$44 + RDB$ACL 9:2b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$45 + RDB$ACL 9:2c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$46 + RDB$ACL 9:2d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$47 + RDB$ACL 9:2e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$48 + RDB$ACL 9:2f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$49 + RDB$ACL 9:30 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$5 + RDB$ACL 9:4 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$50 + RDB$ACL 9:31 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$51 + RDB$ACL 9:32 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$52 + RDB$ACL 9:33 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$53 + RDB$ACL 9:34 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$54 + RDB$ACL 9:35 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$55 + RDB$ACL 9:36 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$56 + RDB$ACL 9:37 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$57 + RDB$ACL 9:38 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$58 + RDB$ACL 9:39 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$59 + RDB$ACL 9:3a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$6 + RDB$ACL 9:5 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$60 + RDB$ACL 9:3b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$61 + RDB$ACL 9:3c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$62 + RDB$ACL 9:3d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$63 + RDB$ACL 9:3e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$64 + RDB$ACL 9:3f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$65 + RDB$ACL 9:40 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$66 + RDB$ACL 9:41 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$67 + RDB$ACL 9:42 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$68 + RDB$ACL 9:43 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$69 + RDB$ACL 9:44 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$7 + RDB$ACL 9:6 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$70 + RDB$ACL 9:45 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$71 + RDB$ACL 9:46 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$72 + RDB$ACL 9:47 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$73 + RDB$ACL 9:48 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$74 + RDB$ACL 9:49 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$75 + RDB$ACL 9:4a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$76 + RDB$ACL 9:4b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$77 + RDB$ACL 9:4c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$78 + RDB$ACL 9:4d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$79 + RDB$ACL 9:4e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$8 + RDB$ACL 9:7 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$80 + RDB$ACL 9:4f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$81 + RDB$ACL 9:50 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$82 + RDB$ACL 9:51 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$83 + RDB$ACL 9:52 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$84 + RDB$ACL 9:53 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$85 + RDB$ACL 9:54 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$86 + RDB$ACL 9:55 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$87 + RDB$ACL 9:56 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$88 + RDB$ACL 9:57 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$89 + RDB$ACL 9:58 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$9 + RDB$ACL 9:8 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$90 + RDB$ACL 9:59 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$91 + RDB$ACL 9:5a + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$92 + RDB$ACL 9:5b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$93 + RDB$ACL 9:5c + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$94 + RDB$ACL 9:5d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$95 + RDB$ACL 9:5e + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$96 + RDB$ACL 9:5f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$97 + RDB$ACL 9:60 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$98 + RDB$ACL 9:61 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$99 + RDB$ACL 9:62 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, usage) + all users: (*.*), privileges: (usage) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$CHARSETS + RDB$ACL 9:9d9 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop) + all users: (*.*), privileges: () + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$COLLATIONS + RDB$ACL 9:9da + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop) + all users: (*.*), privileges: () + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT1 + RDB$ACL 9:9de + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT10 + RDB$ACL 9:d27 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT11 + RDB$ACL 9:d29 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT12 + RDB$ACL 9:d2a + ACL version 1 + person: SYSDBA, privileges: (alter, control, drop, insert, update, delete, select, references) + (null)3, privileges: (insert, update, delete, select, references) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT13 + RDB$ACL 9:d2d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT14 + RDB$ACL 9:d2f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT15 + RDB$ACL 9:d31 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT16 + RDB$ACL 9:d33 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT17 + RDB$ACL 9:d35 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT18 + RDB$ACL 9:d37 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT19 + RDB$ACL 9:d39 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT2 + RDB$ACL 9:9e0 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT20 + RDB$ACL 9:d3b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT21 + RDB$ACL 9:d3d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT22 + RDB$ACL 9:d3f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT23 + RDB$ACL 9:d41 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT24 + RDB$ACL 9:d43 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT25 + RDB$ACL 9:d45 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT26 + RDB$ACL 9:d47 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT27 + RDB$ACL 9:d49 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT28 + RDB$ACL 9:d4b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT29 + RDB$ACL 9:d4d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT3 + RDB$ACL 9:9e2 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT30 + RDB$ACL 9:d4f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT31 + RDB$ACL 9:d51 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT32 + RDB$ACL 9:d53 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT33 + RDB$ACL 9:d54 + ACL version 1 + person: SYSDBA, privileges: (alter, control, drop, insert, update, delete, select, references) + (null)4, privileges: (insert, update, delete, select, references) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT34 + RDB$ACL 9:d57 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT35 + RDB$ACL 9:d59 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT36 + RDB$ACL 9:d5b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT37 + RDB$ACL 9:d5d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT38 + RDB$ACL 9:d5f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT39 + RDB$ACL 9:d61 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT4 + RDB$ACL 9:9e4 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT40 + RDB$ACL 9:d63 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT41 + RDB$ACL 9:d65 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT42 + RDB$ACL 9:d67 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT43 + RDB$ACL 9:d69 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT44 + RDB$ACL 9:d6b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT45 + RDB$ACL 9:d6d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT46 + RDB$ACL 9:d6f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT47 + RDB$ACL 9:d71 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT48 + RDB$ACL 9:d72 + ACL version 1 + person: SYSDBA, privileges: (alter, control, drop, insert, update, delete, select, references) + (null)22, privileges: (insert, update, delete, select, references) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT49 + RDB$ACL 9:d75 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT5 + RDB$ACL 9:9e6 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT50 + RDB$ACL 9:d77 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT51 + RDB$ACL 9:d79 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT52 + RDB$ACL 9:d7b + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT53 + RDB$ACL 9:d7d + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT54 + RDB$ACL 9:d7f + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT6 + RDB$ACL 9:9e8 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT7 + RDB$ACL 9:d21 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT8 + RDB$ACL 9:d23 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DEFAULT9 + RDB$ACL 9:d25 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop, select, insert, update, delete) + all users: (*.*), privileges: (select) + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$DOMAINS + RDB$ACL 9:9d6 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop) + all users: (*.*), privileges: () + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$EXCEPTIONS + RDB$ACL 9:9d7 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop) + all users: (*.*), privileges: () + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$FILTERS + RDB$ACL 9:9db + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop) + all users: (*.*), privileges: () + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$FUNCTIONS + RDB$ACL 9:9d3 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop) + all users: (*.*), privileges: () + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$GENERATORS + RDB$ACL 9:9d5 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop) + all users: (*.*), privileges: () + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$PACKAGES + RDB$ACL 9:9d4 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop) + all users: (*.*), privileges: () + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$PROCEDURES + RDB$ACL 9:9d2 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop) + all users: (*.*), privileges: () + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$ROLES + RDB$ACL 9:9d8 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop) + all users: (*.*), privileges: () + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$TABLES + RDB$ACL 9:9d0 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop) + all users: (*.*), privileges: () + + RDB$DESCRIPTION + + RDB$SECURITY_CLASS SQL$VIEWS + RDB$ACL 9:9d1 + ACL version 1 + person: SYSDBA, privileges: (control, alter, drop) + all users: (*.*), privileges: () + + RDB$DESCRIPTION + + + Records affected: 505 + """ + +@pytest.mark.version('>=4.0') +def test_db_26_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/functional/basic/db/test_27.py b/tests/functional/basic/db/test_27.py new file mode 100644 index 00000000..182ad872 --- /dev/null +++ b/tests/functional/basic/db/test_27.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: functional.basic.db.27 +# title: Empty DB - RDB$TRANSACTIONS +# decription: Check for correct content of RDB$TRANSACTIONS in empty database. +# tracker_id: +# min_versions: [] +# versions: 2.5 +# qmid: functional.basic.db.db_27 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + select * from rdb$transactions order by rdb$transaction_id; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ + +@pytest.mark.version('>=2.5') +def test_27_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/basic/db/test_28.py b/tests/functional/basic/db/test_28.py new file mode 100644 index 00000000..dcaa9ca2 --- /dev/null +++ b/tests/functional/basic/db/test_28.py @@ -0,0 +1,183 @@ +#coding:utf-8 +# +# id: functional.basic.db.28 +# title: Empty DB - RDB$TRIGGER_MESSAGES +# decription: Check for correct content of RDB$TRIGGER_MESSAGES in empty database. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.basic.db.db_28 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('RDB\\$TRIGGER_NAME[\\s]+RDB\\$TRIGGER.*', 'RDB\\$TRIGGER_NAME RDB\\$TRIGGER')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + set blob all; + select * from rdb$trigger_messages order by rdb$trigger_name, rdb$message_number; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + + RDB$TRIGGER_NAME RDB$TRIGGER_1 + RDB$MESSAGE_NUMBER 0 + RDB$MESSAGE existing_priv_mod + + RDB$TRIGGER_NAME RDB$TRIGGER_10 + RDB$MESSAGE_NUMBER 1 + RDB$MESSAGE primary_key_ref + + RDB$TRIGGER_NAME RDB$TRIGGER_10 + RDB$MESSAGE_NUMBER 2 + RDB$MESSAGE primary_key_notnull + + RDB$TRIGGER_NAME RDB$TRIGGER_12 + RDB$MESSAGE_NUMBER 1 + RDB$MESSAGE ref_cnstrnt_notfound + + RDB$TRIGGER_NAME RDB$TRIGGER_12 + RDB$MESSAGE_NUMBER 2 + RDB$MESSAGE foreign_key_notfound + + RDB$TRIGGER_NAME RDB$TRIGGER_13 + RDB$MESSAGE_NUMBER 1 + RDB$MESSAGE ref_cnstrnt_update + + RDB$TRIGGER_NAME RDB$TRIGGER_14 + RDB$MESSAGE_NUMBER 1 + RDB$MESSAGE check_cnstrnt_update + + RDB$TRIGGER_NAME RDB$TRIGGER_15 + RDB$MESSAGE_NUMBER 1 + RDB$MESSAGE check_cnstrnt_del + + RDB$TRIGGER_NAME RDB$TRIGGER_17 + RDB$MESSAGE_NUMBER 1 + RDB$MESSAGE integ_index_seg_del + + RDB$TRIGGER_NAME RDB$TRIGGER_18 + RDB$MESSAGE_NUMBER 1 + RDB$MESSAGE integ_index_seg_mod + + RDB$TRIGGER_NAME RDB$TRIGGER_19 + RDB$MESSAGE_NUMBER 1 + RDB$MESSAGE integ_index_del + + RDB$TRIGGER_NAME RDB$TRIGGER_2 + RDB$MESSAGE_NUMBER 0 + RDB$MESSAGE systrig_update + + RDB$TRIGGER_NAME RDB$TRIGGER_20 + RDB$MESSAGE_NUMBER 1 + RDB$MESSAGE integ_index_mod + + RDB$TRIGGER_NAME RDB$TRIGGER_20 + RDB$MESSAGE_NUMBER 2 + RDB$MESSAGE integ_index_deactivate + + RDB$TRIGGER_NAME RDB$TRIGGER_20 + RDB$MESSAGE_NUMBER 3 + RDB$MESSAGE integ_deactivate_primary + + RDB$TRIGGER_NAME RDB$TRIGGER_21 + RDB$MESSAGE_NUMBER 1 + RDB$MESSAGE check_trig_del + + RDB$TRIGGER_NAME RDB$TRIGGER_22 + RDB$MESSAGE_NUMBER 1 + RDB$MESSAGE check_trig_update + + RDB$TRIGGER_NAME RDB$TRIGGER_23 + RDB$MESSAGE_NUMBER 1 + RDB$MESSAGE cnstrnt_fld_del + + RDB$TRIGGER_NAME RDB$TRIGGER_24 + RDB$MESSAGE_NUMBER 1 + RDB$MESSAGE cnstrnt_fld_rename + + RDB$TRIGGER_NAME RDB$TRIGGER_24 + RDB$MESSAGE_NUMBER 2 + RDB$MESSAGE integ_index_seg_mod + + RDB$TRIGGER_NAME RDB$TRIGGER_25 + RDB$MESSAGE_NUMBER 1 + RDB$MESSAGE rel_cnstrnt_update + + RDB$TRIGGER_NAME RDB$TRIGGER_26 + RDB$MESSAGE_NUMBER 1 + RDB$MESSAGE constaint_on_view + + RDB$TRIGGER_NAME RDB$TRIGGER_26 + RDB$MESSAGE_NUMBER 2 + RDB$MESSAGE invld_cnstrnt_type + + RDB$TRIGGER_NAME RDB$TRIGGER_26 + RDB$MESSAGE_NUMBER 3 + RDB$MESSAGE primary_key_exists + + RDB$TRIGGER_NAME RDB$TRIGGER_3 + RDB$MESSAGE_NUMBER 0 + RDB$MESSAGE systrig_update + + RDB$TRIGGER_NAME RDB$TRIGGER_31 + RDB$MESSAGE_NUMBER 0 + RDB$MESSAGE no_write_user_priv + + RDB$TRIGGER_NAME RDB$TRIGGER_32 + RDB$MESSAGE_NUMBER 0 + RDB$MESSAGE no_write_user_priv + + RDB$TRIGGER_NAME RDB$TRIGGER_33 + RDB$MESSAGE_NUMBER 0 + RDB$MESSAGE no_write_user_priv + + RDB$TRIGGER_NAME RDB$TRIGGER_36 + RDB$MESSAGE_NUMBER 1 + RDB$MESSAGE integ_index_seg_mod + + RDB$TRIGGER_NAME RDB$TRIGGER_9 + RDB$MESSAGE_NUMBER 0 + RDB$MESSAGE grant_obj_notfound + + RDB$TRIGGER_NAME RDB$TRIGGER_9 + RDB$MESSAGE_NUMBER 1 + RDB$MESSAGE grant_fld_notfound + + RDB$TRIGGER_NAME RDB$TRIGGER_9 + RDB$MESSAGE_NUMBER 2 + RDB$MESSAGE grant_nopriv + + RDB$TRIGGER_NAME RDB$TRIGGER_9 + RDB$MESSAGE_NUMBER 3 + RDB$MESSAGE nonsql_security_rel + + RDB$TRIGGER_NAME RDB$TRIGGER_9 + RDB$MESSAGE_NUMBER 4 + RDB$MESSAGE nonsql_security_fld + + RDB$TRIGGER_NAME RDB$TRIGGER_9 + RDB$MESSAGE_NUMBER 5 + RDB$MESSAGE grant_nopriv_on_base + + + Records affected: 35 + """ + +@pytest.mark.version('>=3.0') +def test_28_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/basic/db/test_29.py b/tests/functional/basic/db/test_29.py new file mode 100644 index 00000000..c1829b4f --- /dev/null +++ b/tests/functional/basic/db/test_29.py @@ -0,0 +1,4493 @@ +#coding:utf-8 +# +# id: functional.basic.db.db_29 +# title: Empty DB - RDB$TRIGGERS +# decription: +# Verify content of RDB$TRIGGERS in empty database. +# Checked on: +# 2.5.9.27126: OK, 0.625s. +# 3.0.5.33086: OK, 1.156s. +# 4.0.0.1378: OK, 4.812s. +# +# tracker_id: +# min_versions: ['2.5.7'] +# versions: 3.0, 4.0 +# qmid: functional.basic.db.db_29 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('RDB\\$TRIGGER_BLR.*', ''), ('RDB\\$TRIGGER_NAME[\\s]+RDB\\$TRIGGER.*', 'RDB\\$TRIGGER_NAME RDB\\$TRIGGER')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set blob all; + set count on; + select * from rdb$triggers rt order by rt.rdb$trigger_name; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$TRIGGER_NAME RDB$TRIGGER_1 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 3 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:0 + blr_version5, + blr_leave, 0, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + RDB$TRIGGER_NAME RDB$TRIGGER_10 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 5 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:7 + blr_version5, + blr_begin, + blr_label, 0, + blr_begin, + blr_begin, + blr_if, + blr_or, + blr_eql, + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text2, 0,0, 11,0, 'P','R','I','M','A','R','Y',32,'K','E','Y', + blr_eql, + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text2, 0,0, 6,0, 'U','N','I','Q','U','E', + blr_begin, + blr_begin, + blr_if, + blr_any, + blr_rse, 1, + blr_relation, 19, 'R','D','B','$','R','E','F','_','C','O','N','S','T','R','A','I','N','T','S', 2, + blr_boolean, + blr_eql, + blr_field, 2, 17, 'R','D','B','$','C','O','N','S','T','_','N','A','M','E','_','U','Q', + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_end, + blr_begin, + blr_begin, + blr_leave, 1, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_if, + blr_eql, + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text2, 0,0, 11,0, 'F','O','R','E','I','G','N',32,'K','E','Y', + blr_begin, + blr_begin, + blr_for, + blr_rse, 1, + blr_relation, 19, 'R','D','B','$','R','E','F','_','C','O','N','S','T','R','A','I','N','T','S', 3, + blr_boolean, + blr_eql, + blr_field, 3, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_end, + blr_erase, 3, + blr_end, + blr_end, + blr_end, + blr_if, + blr_eql, + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text2, 0,0, 8,0, 'N','O','T',32,'N','U','L','L', + blr_begin, + blr_begin, + blr_label, 1, + blr_for, + blr_rse, 5, + blr_relation2, 21, 'R','D','B','$','C','H','E','C','K','_','C','O','N','S','T','R','A','I','N','T','S', + 9, 'C','1',32,'C','H','K','C','O','N', 4, + blr_relation2, 19, 'R','D','B','$','R','E','L','A','T','I','O','N','_','F','I','E','L','D','S', + 6, 'C','1',32,'R','F','L', 5, + blr_relation2, 10, 'R','D','B','$','F','I','E','L','D','S', + 6, 'C','1',32,'F','L','D', 6, + blr_relation2, 11, 'R','D','B','$','I','N','D','I','C','E','S', + 6, 'C','1',32,'I','N','D', 7, + blr_relation2, 18, 'R','D','B','$','I','N','D','E','X','_','S','E','G','M','E','N','T','S', + 9, 'C','1',32,'I','D','X','S','E','G', 8, + blr_boolean, + blr_and, + blr_and, + blr_and, + blr_and, + blr_and, + blr_and, + blr_and, + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_eql, + blr_field, 5, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 4, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_eql, + blr_field, 5, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 0, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_eql, + blr_field, 5, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 8, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_eql, + blr_field, 6, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 5, 16, 'R','D','B','$','F','I','E','L','D','_','S','O','U','R','C','E', + blr_or, + blr_missing, + blr_field, 6, 13, 'R','D','B','$','N','U','L','L','_','F','L','A','G', + blr_eql, + blr_field, 6, 13, 'R','D','B','$','N','U','L','L','_','F','L','A','G', + blr_literal, blr_long, 0, 0,0,0,0, + blr_eql, + blr_field, 7, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 0, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_eql, + blr_field, 7, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 8, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_end, + blr_begin, + blr_begin, + blr_begin, + blr_if, + blr_any, + blr_rse, 1, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 9, + blr_boolean, + blr_and, + blr_eql, + blr_field, 9, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_derived_expr, 1, 8, + blr_field, 8, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_eql, + blr_field, 9, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text2, 0,0, 11,0, 'P','R','I','M','A','R','Y',32,'K','E','Y', + blr_end, + blr_begin, + blr_begin, + blr_leave, 2, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + RDB$TRIGGER_NAME RDB$TRIGGER_11 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 6 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:8 + blr_version5, + blr_begin, + blr_if, + blr_or, + blr_eql, + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 11,0, 'F','O','R','E','I','G','N',32,'K','E','Y', + blr_or, + blr_eql, + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 11,0, 'P','R','I','M','A','R','Y',32,'K','E','Y', + blr_eql, + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 6,0, 'U','N','I','Q','U','E', + blr_begin, + blr_for, + blr_rse, 1, + blr_relation, 11, 'R','D','B','$','I','N','D','I','C','E','S', 3, + blr_boolean, + blr_eql, + blr_field, 0, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 3, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_end, + blr_begin, + blr_erase, 3, + blr_for, + blr_rse, 1, + blr_relation, 18, 'R','D','B','$','I','N','D','E','X','_','S','E','G','M','E','N','T','S', 4, + blr_boolean, + blr_eql, + blr_field, 4, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 3, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_end, + blr_begin, + blr_erase, 4, + blr_end, + blr_end, + blr_end, + blr_end, + blr_if, + blr_eql, + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 8,0, 'N','O','T',32,'N','U','L','L', + blr_begin, + blr_for, + blr_rse, 2, + blr_relation, 21, 'R','D','B','$','C','H','E','C','K','_','C','O','N','S','T','R','A','I','N','T','S', 5, + blr_relation, 19, 'R','D','B','$','R','E','L','A','T','I','O','N','_','F','I','E','L','D','S', 6, + blr_boolean, + blr_and, + blr_eql, + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 5, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 6, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 0, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_eql, + blr_field, 6, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 5, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_end, + blr_begin, + blr_erase, 5, + blr_modify, 6, 7, + blr_begin, + blr_assignment, + blr_literal, blr_long, 0, 0,0,0,0, + blr_field, 7, 13, 'R','D','B','$','N','U','L','L','_','F','L','A','G', + blr_end, + blr_end, + blr_end, + blr_end, + blr_if, + blr_eql, + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 5,0, 'C','H','E','C','K', + blr_begin, + blr_for, + blr_rse, 1, + blr_relation, 21, 'R','D','B','$','C','H','E','C','K','_','C','O','N','S','T','R','A','I','N','T','S', 8, + blr_boolean, + blr_eql, + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 8, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_end, + blr_begin, + blr_erase, 8, + blr_for, + blr_rse, 1, + blr_relation, 12, 'R','D','B','$','T','R','I','G','G','E','R','S', 9, + blr_boolean, + blr_and, + blr_eql, + blr_field, 9, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_field, 8, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_eql, + blr_field, 9, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 0, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_end, + blr_begin, + blr_erase, 9, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + RDB$TRIGGER_NAME RDB$TRIGGER_12 + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 1 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:9 + blr_version5, + blr_begin, + blr_if, + blr_not, + blr_any, + blr_rse, 1, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 3, + blr_boolean, + blr_and, + blr_eql, + blr_field, 3, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 1, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_eql, + blr_field, 3, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 11,0, 'F','O','R','E','I','G','N',32,'K','E','Y', + blr_end, + blr_leave, 1, + blr_end, + blr_if, + blr_not, + blr_any, + blr_rse, 1, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 4, + blr_boolean, + blr_and, + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 1, 17, 'R','D','B','$','C','O','N','S','T','_','N','A','M','E','_','U','Q', + blr_or, + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 11,0, 'P','R','I','M','A','R','Y',32,'K','E','Y', + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 6,0, 'U','N','I','Q','U','E', + blr_end, + blr_leave, 2, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + RDB$TRIGGER_NAME RDB$TRIGGER_13 + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 3 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:a + blr_version5, + blr_begin, + blr_leave, 1, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + RDB$TRIGGER_NAME RDB$TRIGGER_14 + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 3 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:b + blr_version5, + blr_begin, + blr_leave, 1, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + RDB$TRIGGER_NAME RDB$TRIGGER_15 + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 5 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:c + blr_version5, + blr_begin, + blr_if, + blr_any, + blr_rse, 1, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 3, + blr_boolean, + blr_eql, + blr_field, 3, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_end, + blr_leave, 1, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + RDB$TRIGGER_NAME RDB$TRIGGER_16 + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 6 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:d + blr_version5, + blr_begin, + blr_for, + blr_rse, 2, + blr_relation, 19, 'R','D','B','$','R','E','L','A','T','I','O','N','_','F','I','E','L','D','S', 3, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 4, + blr_boolean, + blr_and, + blr_eql, + blr_field, 3, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 4, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 8,0, 'N','O','T',32,'N','U','L','L', + blr_eql, + blr_field, 3, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 0, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_end, + blr_begin, + blr_modify, 3, 5, + blr_begin, + blr_assignment, + blr_literal, blr_long, 0, 0,0,0,0, + blr_field, 5, 13, 'R','D','B','$','N','U','L','L','_','F','L','A','G', + blr_end, + blr_end, + blr_for, + blr_rse, 2, + blr_relation, 12, 'R','D','B','$','T','R','I','G','G','E','R','S', 6, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 7, + blr_boolean, + blr_and, + blr_eql, + blr_field, 7, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 7, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 5,0, 'C','H','E','C','K', + blr_and, + blr_eql, + blr_field, 6, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 7, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_eql, + blr_field, 6, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_field, 0, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_end, + blr_begin, + blr_erase, 6, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + RDB$TRIGGER_NAME RDB$TRIGGER_17 + RDB$RELATION_NAME RDB$INDEX_SEGMENTS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 5 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:e + blr_version5, + blr_begin, + blr_if, + blr_any, + blr_rse, 1, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 3, + blr_boolean, + blr_eql, + blr_field, 3, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 0, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_end, + blr_leave, 1, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + RDB$TRIGGER_NAME RDB$TRIGGER_18 + RDB$RELATION_NAME RDB$INDEX_SEGMENTS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 3 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:3c0 + blr_version5, + blr_begin, + blr_if, + blr_any, + blr_rse, 1, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 3, + blr_boolean, + blr_eql, + blr_field, 3, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 0, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_end, + blr_if, + blr_not, + blr_and, + blr_eql, + blr_field, 0, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 1, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 0, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 1, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_eql, + blr_field, 0, 18, 'R','D','B','$','F','I','E','L','D','_','P','O','S','I','T','I','O','N', + blr_field, 1, 18, 'R','D','B','$','F','I','E','L','D','_','P','O','S','I','T','I','O','N', + blr_leave, 1, + blr_end, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + RDB$TRIGGER_NAME RDB$TRIGGER_19 + RDB$RELATION_NAME RDB$INDICES + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 5 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:3c1 + blr_version5, + blr_begin, + blr_if, + blr_any, + blr_rse, 1, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 3, + blr_boolean, + blr_eql, + blr_field, 3, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 0, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_end, + blr_leave, 1, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + RDB$TRIGGER_NAME RDB$TRIGGER_2 + RDB$RELATION_NAME RDB$TRIGGERS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 3 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:3 + blr_version5, + blr_if, + blr_eql, + blr_field, 0, 15, 'R','D','B','$','S','Y','S','T','E','M','_','F','L','A','G', + blr_literal, blr_short, 0, 1,0, + blr_leave, 0, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + RDB$TRIGGER_NAME RDB$TRIGGER_20 + RDB$RELATION_NAME RDB$INDICES + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 3 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:3c2 + blr_version5, + blr_begin, + blr_if, + blr_any, + blr_rse, 1, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 3, + blr_boolean, + blr_eql, + blr_field, 3, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 0, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_end, + blr_begin, + blr_if, + blr_not, + blr_and, + blr_eql, + blr_field, 0, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 1, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 0, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 1, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 0, 12, 'R','D','B','$','I','N','D','E','X','_','I','D', + blr_field, 1, 12, 'R','D','B','$','I','N','D','E','X','_','I','D', + blr_and, + blr_eql, + blr_field, 0, 17, 'R','D','B','$','S','E','G','M','E','N','T','_','C','O','U','N','T', + blr_field, 1, 17, 'R','D','B','$','S','E','G','M','E','N','T','_','C','O','U','N','T', + blr_eql, + blr_field, 0, 15, 'R','D','B','$','F','O','R','E','I','G','N','_','K','E','Y', + blr_field, 1, 15, 'R','D','B','$','F','O','R','E','I','G','N','_','K','E','Y', + blr_leave, 1, + blr_end, + blr_end, + blr_end, + blr_for, + blr_rse, 3, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 4, + blr_relation, 11, 'R','D','B','$','I','N','D','I','C','E','S', 5, + blr_relation, 11, 'R','D','B','$','I','N','D','I','C','E','S', 6, + blr_boolean, + blr_and, + blr_eql, + blr_field, 4, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 0, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 5, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 0, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 6, 15, 'R','D','B','$','F','O','R','E','I','G','N','_','K','E','Y', + blr_field, 0, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 1, 18, 'R','D','B','$','I','N','D','E','X','_','I','N','A','C','T','I','V','E', + blr_literal, blr_long, 0, 1,0,0,0, + blr_or, + blr_eql, + blr_field, 0, 18, 'R','D','B','$','I','N','D','E','X','_','I','N','A','C','T','I','V','E', + blr_literal, blr_long, 0, 0,0,0,0, + blr_missing, + blr_field, 0, 18, 'R','D','B','$','I','N','D','E','X','_','I','N','A','C','T','I','V','E', + blr_end, + blr_begin, + blr_leave, 2, + blr_end, + blr_if, + blr_any, + blr_rse, 1, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 7, + blr_boolean, + blr_and, + blr_eql, + blr_field, 7, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 0, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_or, + blr_eql, + blr_field, 7, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 11,0, 'P','R','I','M','A','R','Y',32,'K','E','Y', + blr_or, + blr_eql, + blr_field, 7, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 6,0, 'U','N','I','Q','U','E', + blr_eql, + blr_field, 7, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 11,0, 'F','O','R','E','I','G','N',32,'K','E','Y', + blr_end, + blr_begin, + blr_if, + blr_and, + blr_eql, + blr_field, 1, 18, 'R','D','B','$','I','N','D','E','X','_','I','N','A','C','T','I','V','E', + blr_literal, blr_long, 0, 1,0,0,0, + blr_or, + blr_eql, + blr_field, 0, 18, 'R','D','B','$','I','N','D','E','X','_','I','N','A','C','T','I','V','E', + blr_literal, blr_long, 0, 0,0,0,0, + blr_missing, + blr_field, 0, 18, 'R','D','B','$','I','N','D','E','X','_','I','N','A','C','T','I','V','E', + blr_begin, + blr_if, + blr_eql, + blr_field, 7, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 11,0, 'F','O','R','E','I','G','N',32,'K','E','Y', + blr_leave, 2, + blr_leave, 3, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + RDB$TRIGGER_NAME RDB$TRIGGER_21 + RDB$RELATION_NAME RDB$TRIGGERS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 5 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:3c3 + blr_version5, + blr_begin, + blr_for, + blr_rse, 2, + blr_relation, 21, 'R','D','B','$','C','H','E','C','K','_','C','O','N','S','T','R','A','I','N','T','S', 3, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 4, + blr_boolean, + blr_and, + blr_eql, + blr_field, 3, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_field, 0, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 3, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 5,0, 'C','H','E','C','K', + blr_end, + blr_begin, + blr_leave, 1, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + RDB$TRIGGER_NAME RDB$TRIGGER_22 + RDB$RELATION_NAME RDB$TRIGGERS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 3 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:3c4 + blr_version5, + blr_begin, + blr_for, + blr_rse, 2, + blr_relation, 21, 'R','D','B','$','C','H','E','C','K','_','C','O','N','S','T','R','A','I','N','T','S', 3, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 4, + blr_boolean, + blr_and, + blr_eql, + blr_field, 3, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_field, 0, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 3, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 5,0, 'C','H','E','C','K', + blr_end, + blr_begin, + blr_if, + blr_not, + blr_and, + blr_and, + blr_and, + blr_and, + blr_and, + blr_and, + blr_and, + blr_and, + blr_equiv, + blr_field, 0, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_field, 1, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_equiv, + blr_field, 0, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 1, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_equiv, + blr_field, 0, 20, 'R','D','B','$','T','R','I','G','G','E','R','_','S','E','Q','U','E','N','C','E', + blr_field, 1, 20, 'R','D','B','$','T','R','I','G','G','E','R','_','S','E','Q','U','E','N','C','E', + blr_equiv, + blr_field, 0, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','T','Y','P','E', + blr_field, 1, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','T','Y','P','E', + blr_equiv, + blr_field, 0, 15, 'R','D','B','$','T','R','I','G','G','E','R','_','B','L','R', + blr_field, 1, 15, 'R','D','B','$','T','R','I','G','G','E','R','_','B','L','R', + blr_equiv, + blr_field, 0, 20, 'R','D','B','$','T','R','I','G','G','E','R','_','I','N','A','C','T','I','V','E', + blr_field, 1, 20, 'R','D','B','$','T','R','I','G','G','E','R','_','I','N','A','C','T','I','V','E', + blr_equiv, + blr_field, 0, 15, 'R','D','B','$','S','Y','S','T','E','M','_','F','L','A','G', + blr_field, 1, 15, 'R','D','B','$','S','Y','S','T','E','M','_','F','L','A','G', + blr_equiv, + blr_field, 0, 9, 'R','D','B','$','F','L','A','G','S', + blr_field, 1, 9, 'R','D','B','$','F','L','A','G','S', + blr_equiv, + blr_field, 0, 14, 'R','D','B','$','D','E','B','U','G','_','I','N','F','O', + blr_field, 1, 14, 'R','D','B','$','D','E','B','U','G','_','I','N','F','O', + blr_begin, + blr_leave, 1, + blr_end, + blr_end, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + RDB$TRIGGER_NAME RDB$TRIGGER_23 + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 5 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:3c5 + blr_version5, + blr_begin, + blr_for, + blr_rse, 3, + blr_relation, 11, 'R','D','B','$','I','N','D','I','C','E','S', 3, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 4, + blr_relation, 18, 'R','D','B','$','I','N','D','E','X','_','S','E','G','M','E','N','T','S', 5, + blr_boolean, + blr_and, + blr_eql, + blr_field, 3, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 0, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 3, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 5, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 4, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 5, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_eql, + blr_field, 5, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 0, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_end, + blr_begin, + blr_if, + blr_any, + blr_rse, 1, + blr_relation, 18, 'R','D','B','$','I','N','D','E','X','_','S','E','G','M','E','N','T','S', 6, + blr_boolean, + blr_and, + blr_eql, + blr_field, 6, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 5, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_neq, + blr_field, 6, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 0, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_end, + blr_leave, 1, + blr_erase, 4, + blr_end, + blr_for, + blr_rse, 3, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 7, + blr_relation, 21, 'R','D','B','$','C','H','E','C','K','_','C','O','N','S','T','R','A','I','N','T','S', 8, + blr_relation, 16, 'R','D','B','$','D','E','P','E','N','D','E','N','C','I','E','S', 9, + blr_boolean, + blr_and, + blr_and, + blr_eql, + blr_field, 7, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 0, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 7, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 5,0, 'C','H','E','C','K', + blr_and, + blr_eql, + blr_field, 8, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_field, 9, 18, 'R','D','B','$','D','E','P','E','N','D','E','N','T','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 9, 18, 'R','D','B','$','D','E','P','E','N','D','E','N','T','_','T','Y','P','E', + blr_literal, blr_long, 0, 2,0,0,0, + blr_and, + blr_eql, + blr_field, 9, 20, 'R','D','B','$','D','E','P','E','N','D','E','D','_','O','N','_','T','Y','P','E', + blr_literal, blr_long, 0, 0,0,0,0, + blr_and, + blr_eql, + blr_field, 9, 20, 'R','D','B','$','D','E','P','E','N','D','E','D','_','O','N','_','N','A','M','E', + blr_field, 0, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_eql, + blr_field, 9, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 0, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_eql, + blr_field, 8, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 7, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_end, + blr_begin, + blr_if, + blr_any, + blr_rse, 1, + blr_relation, 16, 'R','D','B','$','D','E','P','E','N','D','E','N','C','I','E','S', 10, + blr_boolean, + blr_and, + blr_eql, + blr_field, 10, 18, 'R','D','B','$','D','E','P','E','N','D','E','N','T','_','N','A','M','E', + blr_field, 8, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 10, 18, 'R','D','B','$','D','E','P','E','N','D','E','N','T','_','T','Y','P','E', + blr_literal, blr_long, 0, 2,0,0,0, + blr_and, + blr_eql, + blr_field, 10, 20, 'R','D','B','$','D','E','P','E','N','D','E','D','_','O','N','_','T','Y','P','E', + blr_literal, blr_long, 0, 0,0,0,0, + blr_and, + blr_eql, + blr_field, 10, 20, 'R','D','B','$','D','E','P','E','N','D','E','D','_','O','N','_','N','A','M','E', + blr_field, 0, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_neq, + blr_field, 10, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 0, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_end, + blr_leave, 1, + blr_erase, 7, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + RDB$TRIGGER_NAME RDB$TRIGGER_24 + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 3 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:3c6 + blr_version5, + blr_begin, + blr_if, + blr_any, + blr_rse, 3, + blr_relation, 11, 'R','D','B','$','I','N','D','I','C','E','S', 3, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 4, + blr_relation, 18, 'R','D','B','$','I','N','D','E','X','_','S','E','G','M','E','N','T','S', 5, + blr_boolean, + blr_and, + blr_eql, + blr_field, 3, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 0, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 3, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 5, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 4, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 5, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_eql, + blr_field, 5, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 0, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_end, + blr_begin, + blr_if, + blr_neq, + blr_field, 0, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 1, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_leave, 1, + blr_end, + blr_if, + blr_not, + blr_and, + blr_eql, + blr_field, 0, 16, 'R','D','B','$','F','I','E','L','D','_','S','O','U','R','C','E', + blr_field, 1, 16, 'R','D','B','$','F','I','E','L','D','_','S','O','U','R','C','E', + blr_eql, + blr_field, 0, 16, 'R','D','B','$','C','O','L','L','A','T','I','O','N','_','I','D', + blr_field, 1, 16, 'R','D','B','$','C','O','L','L','A','T','I','O','N','_','I','D', + blr_leave, 2, + blr_end, + blr_end, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + RDB$TRIGGER_NAME RDB$TRIGGER_25 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 3 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:6 + blr_version5, + blr_begin, + blr_leave, 1, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + RDB$TRIGGER_NAME RDB$TRIGGER_26 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 1 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:5 + blr_version5, + blr_begin, + blr_if, + blr_any, + blr_rse, 1, + blr_relation, 13, 'R','D','B','$','R','E','L','A','T','I','O','N','S', 3, + blr_boolean, + blr_and, + blr_eql, + blr_field, 3, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 1, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_not, + blr_missing, + blr_field, 3, 15, 'R','D','B','$','V','I','E','W','_','S','O','U','R','C','E', + blr_end, + blr_leave, 1, + blr_end, + blr_if, + blr_not, + blr_or, + blr_eql, + blr_field, 1, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 6,0, 'U','N','I','Q','U','E', + blr_or, + blr_eql, + blr_field, 1, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 11,0, 'P','R','I','M','A','R','Y',32,'K','E','Y', + blr_or, + blr_eql, + blr_field, 1, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 11,0, 'F','O','R','E','I','G','N',32,'K','E','Y', + blr_or, + blr_eql, + blr_field, 1, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 8,0, 'N','O','T',32,'N','U','L','L', + blr_eql, + blr_field, 1, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 5,0, 'C','H','E','C','K', + blr_leave, 2, + blr_end, + blr_if, + blr_eql, + blr_field, 1, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 11,0, 'P','R','I','M','A','R','Y',32,'K','E','Y', + blr_begin, + blr_if, + blr_any, + blr_rse, 1, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 4, + blr_boolean, + blr_and, + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 11,0, 'P','R','I','M','A','R','Y',32,'K','E','Y', + blr_eql, + blr_field, 4, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 1, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_end, + blr_leave, 3, + blr_end, + blr_end, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + RDB$TRIGGER_NAME RDB$TRIGGER_27 + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 6 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:3c7 + blr_version5, + blr_begin, + blr_for, + blr_rse, 2, + blr_relation, 21, 'R','D','B','$','C','H','E','C','K','_','C','O','N','S','T','R','A','I','N','T','S', 3, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 4, + blr_boolean, + blr_and, + blr_eql, + blr_field, 0, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 3, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 3, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 0, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 4, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 8,0, 'N','O','T',32,'N','U','L','L', + blr_end, + blr_begin, + blr_erase, 4, + blr_erase, 3, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + RDB$TRIGGER_NAME RDB$TRIGGER_3 + RDB$RELATION_NAME RDB$TRIGGERS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 5 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:4 + blr_version5, + blr_if, + blr_eql, + blr_field, 0, 15, 'R','D','B','$','S','Y','S','T','E','M','_','F','L','A','G', + blr_literal, blr_short, 0, 1,0, + blr_leave, 0, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + RDB$TRIGGER_NAME RDB$TRIGGER_31 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 3 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:3c8 + blr_version5, + blr_begin, + blr_if, + blr_and, + blr_not, + blr_missing, + blr_field, 1, 11, 'R','D','B','$','G','R','A','N','T','O','R', + blr_and, + blr_neq, + blr_field, 1, 11, 'R','D','B','$','G','R','A','N','T','O','R', + blr_user_name, + blr_and, + blr_neq, + blr_user_name, + blr_literal, blr_text, 6,0, 'S','Y','S','D','B','A', + blr_and, + blr_neq, + blr_current_role, + blr_literal, blr_text, 9,0, 'R','D','B','$','A','D','M','I','N', + blr_not, + blr_any, + blr_rse, 1, + blr_relation, 13, 'R','D','B','$','R','E','L','A','T','I','O','N','S', 4, + blr_boolean, + blr_and, + blr_eql, + blr_field, 4, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_literal, blr_text, 12,0, 'R','D','B','$','D','A','T','A','B','A','S','E', + blr_eql, + blr_field, 4, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_user_name, + blr_end, + blr_begin, + blr_for, + blr_rse, 1, + blr_relation, 13, 'R','D','B','$','R','E','L','A','T','I','O','N','S', 3, + blr_boolean, + blr_eql, + blr_field, 3, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_literal, blr_text, 12,0, 'R','D','B','$','D','A','T','A','B','A','S','E', + blr_end, + blr_begin, + blr_if, + blr_or, + blr_missing, + blr_field, 3, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_neq, + blr_field, 3, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_user_name, + blr_leave, 0, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + RDB$TRIGGER_NAME RDB$TRIGGER_32 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 5 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:3c9 + blr_version5, + blr_begin, + blr_if, + blr_and, + blr_not, + blr_missing, + blr_field, 1, 11, 'R','D','B','$','G','R','A','N','T','O','R', + blr_and, + blr_neq, + blr_field, 1, 11, 'R','D','B','$','G','R','A','N','T','O','R', + blr_user_name, + blr_and, + blr_neq, + blr_user_name, + blr_literal, blr_text, 6,0, 'S','Y','S','D','B','A', + blr_and, + blr_neq, + blr_current_role, + blr_literal, blr_text, 9,0, 'R','D','B','$','A','D','M','I','N', + blr_not, + blr_any, + blr_rse, 1, + blr_relation, 13, 'R','D','B','$','R','E','L','A','T','I','O','N','S', 4, + blr_boolean, + blr_and, + blr_eql, + blr_field, 4, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_literal, blr_text, 12,0, 'R','D','B','$','D','A','T','A','B','A','S','E', + blr_eql, + blr_field, 4, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_user_name, + blr_end, + blr_begin, + blr_for, + blr_rse, 1, + blr_relation, 13, 'R','D','B','$','R','E','L','A','T','I','O','N','S', 3, + blr_boolean, + blr_eql, + blr_field, 3, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_literal, blr_text, 12,0, 'R','D','B','$','D','A','T','A','B','A','S','E', + blr_end, + blr_begin, + blr_if, + blr_or, + blr_missing, + blr_field, 3, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_neq, + blr_field, 3, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_user_name, + blr_leave, 0, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + RDB$TRIGGER_NAME RDB$TRIGGER_33 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 1 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:3ca + blr_version5, + blr_begin, + blr_if, + blr_and, + blr_not, + blr_missing, + blr_field, 1, 11, 'R','D','B','$','G','R','A','N','T','O','R', + blr_and, + blr_neq, + blr_field, 1, 11, 'R','D','B','$','G','R','A','N','T','O','R', + blr_user_name, + blr_and, + blr_neq, + blr_user_name, + blr_literal, blr_text, 6,0, 'S','Y','S','D','B','A', + blr_and, + blr_neq, + blr_current_role, + blr_literal, blr_text, 9,0, 'R','D','B','$','A','D','M','I','N', + blr_not, + blr_any, + blr_rse, 1, + blr_relation, 13, 'R','D','B','$','R','E','L','A','T','I','O','N','S', 4, + blr_boolean, + blr_and, + blr_eql, + blr_field, 4, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_literal, blr_text, 12,0, 'R','D','B','$','D','A','T','A','B','A','S','E', + blr_eql, + blr_field, 4, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_user_name, + blr_end, + blr_begin, + blr_for, + blr_rse, 1, + blr_relation, 13, 'R','D','B','$','R','E','L','A','T','I','O','N','S', 3, + blr_boolean, + blr_eql, + blr_field, 3, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_literal, blr_text, 12,0, 'R','D','B','$','D','A','T','A','B','A','S','E', + blr_end, + blr_begin, + blr_if, + blr_or, + blr_missing, + blr_field, 3, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_neq, + blr_field, 3, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_user_name, + blr_leave, 0, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + RDB$TRIGGER_NAME RDB$TRIGGER_34 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 6 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:3cb + blr_version5, + blr_begin, + blr_if, + blr_eql, + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 11,0, 'F','O','R','E','I','G','N',32,'K','E','Y', + blr_begin, + blr_for, + blr_rse, 1, + blr_relation, 21, 'R','D','B','$','C','H','E','C','K','_','C','O','N','S','T','R','A','I','N','T','S', 3, + blr_boolean, + blr_eql, + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 3, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_end, + blr_begin, + blr_erase, 3, + blr_for, + blr_rse, 1, + blr_relation, 12, 'R','D','B','$','T','R','I','G','G','E','R','S', 4, + blr_boolean, + blr_eql, + blr_field, 4, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_field, 3, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_end, + blr_begin, + blr_erase, 4, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 2 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + RDB$TRIGGER_NAME RDB$TRIGGER_35 + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 6 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:3cc + blr_version5, + blr_begin, + blr_for, + blr_rse, 2, + blr_relation, 12, 'R','D','B','$','T','R','I','G','G','E','R','S', 3, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 4, + blr_boolean, + blr_and, + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 11,0, 'F','O','R','E','I','G','N',32,'K','E','Y', + blr_eql, + blr_field, 3, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_field, 0, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_end, + blr_begin, + blr_erase, 3, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 2 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + RDB$TRIGGER_NAME RDB$TRIGGER_36 + RDB$RELATION_NAME RDB$FIELDS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 3 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:3cd + blr_version5, + blr_begin, + blr_if, + blr_not, + blr_and, + blr_eql, + blr_field, 0, 16, 'R','D','B','$','F','I','E','L','D','_','L','E','N','G','T','H', + blr_field, 1, 16, 'R','D','B','$','F','I','E','L','D','_','L','E','N','G','T','H', + blr_and, + blr_eql, + blr_field, 0, 14, 'R','D','B','$','F','I','E','L','D','_','T','Y','P','E', + blr_field, 1, 14, 'R','D','B','$','F','I','E','L','D','_','T','Y','P','E', + blr_and, + blr_eql, + blr_field, 0, 16, 'R','D','B','$','C','O','L','L','A','T','I','O','N','_','I','D', + blr_field, 1, 16, 'R','D','B','$','C','O','L','L','A','T','I','O','N','_','I','D', + blr_eql, + blr_field, 0, 20, 'R','D','B','$','C','H','A','R','A','C','T','E','R','_','S','E','T','_','I','D', + blr_field, 1, 20, 'R','D','B','$','C','H','A','R','A','C','T','E','R','_','S','E','T','_','I','D', + blr_if, + blr_any, + blr_rse, 4, + blr_relation, 11, 'R','D','B','$','I','N','D','I','C','E','S', 3, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 4, + blr_relation, 18, 'R','D','B','$','I','N','D','E','X','_','S','E','G','M','E','N','T','S', 5, + blr_relation, 19, 'R','D','B','$','R','E','L','A','T','I','O','N','_','F','I','E','L','D','S', 6, + blr_boolean, + blr_and, + blr_eql, + blr_field, 3, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 6, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 3, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 5, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 4, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 5, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 5, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 6, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_eql, + blr_field, 6, 16, 'R','D','B','$','F','I','E','L','D','_','S','O','U','R','C','E', + blr_field, 0, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_end, + blr_leave, 1, + blr_end, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + RDB$TRIGGER_NAME RDB$TRIGGER_8 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 5 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:1 + blr_version5, + blr_if, + blr_not, + blr_missing, + blr_field, 0, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_for, + blr_rse, 1, + blr_relation, 19, 'R','D','B','$','R','E','L','A','T','I','O','N','_','F','I','E','L','D','S', 3, + blr_boolean, + blr_and, + blr_eql, + blr_field, 3, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 0, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_eql, + blr_field, 3, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 0, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_end, + blr_begin, + blr_if, + blr_starting, + blr_field, 3, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_literal, blr_text, 9,0, 'S','Q','L','$','G','R','A','N','T', + blr_begin, + blr_for, + blr_rse, 1, + blr_relation, 20, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S','E','S', 4, + blr_boolean, + blr_eql, + blr_field, 4, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_field, 3, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_end, + blr_begin, + blr_erase, 4, + blr_end, + blr_modify, 3, 5, + blr_begin, + blr_assignment, + blr_null, + blr_field, 5, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + RDB$TRIGGER_NAME RDB$TRIGGER_9 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 1 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:2 + blr_version5, + blr_begin, + blr_if, + blr_missing, + blr_field, 1, 11, 'R','D','B','$','G','R','A','N','T','O','R', + blr_assignment, + blr_user_name, + blr_field, 1, 11, 'R','D','B','$','G','R','A','N','T','O','R', + blr_end, + blr_if, + blr_eql, + blr_field, 1, 15, 'R','D','B','$','O','B','J','E','C','T','_','T','Y','P','E', + blr_literal, blr_long, 0, 0,0,0,0, + blr_begin, + blr_for, + blr_rse, 1, + blr_relation, 13, 'R','D','B','$','R','E','L','A','T','I','O','N','S', 6, + blr_boolean, + blr_eql, + blr_field, 6, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 1, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_end, + blr_begin, + blr_if, + blr_or, + blr_and, + blr_eql, + blr_field, 6, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_user_name, + blr_and, + blr_eql, + blr_field, 6, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_field, 1, 11, 'R','D','B','$','G','R','A','N','T','O','R', + blr_eql, + blr_field, 6, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_field, 1, 8, 'R','D','B','$','U','S','E','R', + blr_or, + blr_eql, + blr_user_name, + blr_literal, blr_text, 6,0, 'S','Y','S','D','B','A', + blr_or, + blr_eql, + blr_current_role, + blr_literal, blr_text, 9,0, 'R','D','B','$','A','D','M','I','N', + blr_any, + blr_rse, 1, + blr_relation, 13, 'R','D','B','$','R','E','L','A','T','I','O','N','S', 28, + blr_boolean, + blr_and, + blr_eql, + blr_field, 28, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_literal, blr_text, 12,0, 'R','D','B','$','D','A','T','A','B','A','S','E', + blr_eql, + blr_field, 28, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_user_name, + blr_end, + blr_begin, + blr_end, + blr_if, + blr_neq, + blr_field, 6, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_user_name, + blr_begin, + blr_if, + blr_not, + blr_any, + blr_rse, 1, + blr_relation, 19, 'R','D','B','$','U','S','E','R','_','P','R','I','V','I','L','E','G','E','S', 7, + blr_boolean, + blr_and, + blr_eql, + blr_field, 7, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 1, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 7, 15, 'R','D','B','$','O','B','J','E','C','T','_','T','Y','P','E', + blr_literal, blr_long, 0, 0,0,0,0, + blr_and, + blr_eql, + blr_field, 7, 13, 'R','D','B','$','P','R','I','V','I','L','E','G','E', + blr_field, 1, 13, 'R','D','B','$','P','R','I','V','I','L','E','G','E', + blr_and, + blr_eql, + blr_field, 7, 8, 'R','D','B','$','U','S','E','R', + blr_field, 1, 11, 'R','D','B','$','G','R','A','N','T','O','R', + blr_and, + blr_eql, + blr_field, 7, 13, 'R','D','B','$','U','S','E','R','_','T','Y','P','E', + blr_literal, blr_long, 0, 8,0,0,0, + blr_and, + blr_neq, + blr_field, 7, 16, 'R','D','B','$','G','R','A','N','T','_','O','P','T','I','O','N', + blr_literal, blr_long, 0, 0,0,0,0, + blr_or, + blr_missing, + blr_field, 7, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_eql, + blr_field, 7, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 1, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_end, + blr_leave, 2, + blr_end, + blr_end, + blr_if, + blr_not, + blr_missing, + blr_field, 1, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_begin, + blr_for, + blr_rse, 3, + blr_relation, 19, 'R','D','B','$','R','E','L','A','T','I','O','N','_','F','I','E','L','D','S', 8, + blr_relation, 18, 'R','D','B','$','V','I','E','W','_','R','E','L','A','T','I','O','N','S', 9, + blr_relation, 13, 'R','D','B','$','R','E','L','A','T','I','O','N','S', 10, + blr_boolean, + blr_and, + blr_eql, + blr_field, 8, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 1, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 8, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 1, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_and, + blr_not, + blr_missing, + blr_field, 8, 14, 'R','D','B','$','B','A','S','E','_','F','I','E','L','D', + blr_and, + blr_eql, + blr_field, 9, 13, 'R','D','B','$','V','I','E','W','_','N','A','M','E', + blr_field, 8, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 9, 16, 'R','D','B','$','V','I','E','W','_','C','O','N','T','E','X','T', + blr_field, 8, 16, 'R','D','B','$','V','I','E','W','_','C','O','N','T','E','X','T', + blr_eql, + blr_field, 9, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 10, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_end, + blr_begin, + blr_if, + blr_and, + blr_neq, + blr_field, 10, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_field, 6, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_and, + blr_neq, + blr_user_name, + blr_literal, blr_text, 6,0, 'S','Y','S','D','B','A', + blr_and, + blr_neq, + blr_current_role, + blr_literal, blr_text, 9,0, 'R','D','B','$','A','D','M','I','N', + blr_not, + blr_any, + blr_rse, 1, + blr_relation, 13, 'R','D','B','$','R','E','L','A','T','I','O','N','S', 29, + blr_boolean, + blr_and, + blr_eql, + blr_field, 29, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_literal, blr_text, 12,0, 'R','D','B','$','D','A','T','A','B','A','S','E', + blr_eql, + blr_field, 29, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_user_name, + blr_end, + blr_begin, + blr_if, + blr_not, + blr_any, + blr_rse, 1, + blr_relation, 19, 'R','D','B','$','U','S','E','R','_','P','R','I','V','I','L','E','G','E','S', 11, + blr_boolean, + blr_and, + blr_eql, + blr_field, 11, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 10, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 11, 15, 'R','D','B','$','O','B','J','E','C','T','_','T','Y','P','E', + blr_literal, blr_long, 0, 0,0,0,0, + blr_and, + blr_eql, + blr_field, 11, 13, 'R','D','B','$','P','R','I','V','I','L','E','G','E', + blr_field, 1, 13, 'R','D','B','$','P','R','I','V','I','L','E','G','E', + blr_and, + blr_eql, + blr_field, 11, 8, 'R','D','B','$','U','S','E','R', + blr_field, 6, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 11, 13, 'R','D','B','$','U','S','E','R','_','T','Y','P','E', + blr_literal, blr_long, 0, 8,0,0,0, + blr_and, + blr_neq, + blr_field, 11, 16, 'R','D','B','$','G','R','A','N','T','_','O','P','T','I','O','N', + blr_literal, blr_long, 0, 0,0,0,0, + blr_or, + blr_missing, + blr_field, 11, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_eql, + blr_field, 11, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 8, 14, 'R','D','B','$','B','A','S','E','_','F','I','E','L','D', + blr_end, + blr_leave, 5, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_begin, + blr_for, + blr_rse, 2, + blr_relation, 18, 'R','D','B','$','V','I','E','W','_','R','E','L','A','T','I','O','N','S', 12, + blr_relation, 13, 'R','D','B','$','R','E','L','A','T','I','O','N','S', 13, + blr_boolean, + blr_and, + blr_eql, + blr_field, 12, 13, 'R','D','B','$','V','I','E','W','_','N','A','M','E', + blr_field, 1, 17, 'R','D','B','$', + 'R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_eql, + blr_field, 12, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 13, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_end, + blr_begin, + blr_if, + blr_and, + blr_neq, + blr_field, 13, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_field, 6, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_and, + blr_neq, + blr_user_name, + blr_literal, blr_text, 6,0, 'S','Y','S','D','B','A', + blr_and, + blr_neq, + blr_current_role, + blr_literal, blr_text, 9,0, 'R','D','B','$','A','D','M','I','N', + blr_not, + blr_any, + blr_rse, 1, + blr_relation, 13, 'R','D','B','$','R','E','L','A','T','I','O','N','S', 30, + blr_boolean, + blr_and, + blr_eql, + blr_field, 30, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_literal, blr_text, 12,0, 'R','D','B','$','D','A','T','A','B','A','S','E', + blr_eql, + blr_field, 30, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_user_name, + blr_end, + blr_begin, + blr_if, + blr_not, + blr_any, + blr_rse, 1, + blr_relation, 19, 'R','D','B','$','U','S','E','R','_','P','R','I','V','I','L','E','G','E','S', 14, + blr_boolean, + blr_and, + blr_eql, + blr_field, 14, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 13, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 14, 15, 'R','D','B','$','O','B','J','E','C','T','_','T','Y','P','E', + blr_literal, blr_long, 0, 0,0,0,0, + blr_and, + blr_eql, + blr_field, 14, 13, 'R','D','B','$','P','R','I','V','I','L','E','G','E', + blr_field, 1, 13, 'R','D','B','$','P','R','I','V','I','L','E','G','E', + blr_and, + blr_eql, + blr_field, 14, 8, 'R','D','B','$','U','S','E','R', + blr_field, 6, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 14, 13, 'R','D','B','$','U','S','E','R','_','T','Y','P','E', + blr_literal, blr_long, 0, 8,0,0,0, + blr_and, + blr_neq, + blr_field, 14, 16, 'R','D','B','$','G','R','A','N','T','_','O','P','T','I','O','N', + blr_literal, blr_long, 0, 0,0,0,0, + blr_missing, + blr_field, 14, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_end, + blr_leave, 5, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_if, + blr_missing, + blr_field, 6, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_modify, 6, 15, + blr_begin, + blr_assignment, + blr_cast, blr_varying2, 3,0, 31,0, + blr_concatenate, + blr_literal, blr_text2, 1,0, 4,0, 'S','Q','L','$', + blr_gen_id, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_literal, blr_long, 0, 1,0,0,0, + blr_field, 15, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_end, + blr_if, + blr_not, + blr_starting, + blr_field, 6, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_cast, blr_varying2, 3,0, 31,0, + blr_literal, blr_text2, 1,0, 4,0, 'S','Q','L','$', + blr_leave, 3, + blr_end, + blr_end, + blr_if, + blr_not, + blr_missing, + blr_field, 1, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_for, + blr_rse, 1, + blr_relation, 19, 'R','D','B','$','R','E','L','A','T','I','O','N','_','F','I','E','L','D','S', 16, + blr_boolean, + blr_and, + blr_eql, + blr_field, 16, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 1, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_eql, + blr_field, 16, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 1, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_end, + blr_begin, + blr_if, + blr_missing, + blr_field, 16, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_modify, 16, 17, + blr_begin, + blr_assignment, + blr_concatenate, + blr_literal, blr_text, 9,0, 'S','Q','L','$','G','R','A','N','T', + blr_gen_id, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_literal, blr_long, 0, 1,0,0,0, + blr_field, 17, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_end, + blr_if, + blr_not, + blr_starting, + blr_field, 16, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_literal, blr_text, 9,0, 'S','Q','L','$','G','R','A','N','T', + blr_leave, 4, + blr_end, + blr_end, + blr_end, + blr_end, + blr_if, + blr_eql, + blr_field, 1, 15, 'R','D','B','$','O','B','J','E','C','T','_','T','Y','P','E', + blr_literal, blr_long, 0, 5,0,0,0, + blr_for, + blr_rse, 1, + blr_relation, 14, 'R','D','B','$','P','R','O','C','E','D','U','R','E','S', 18, + blr_boolean, + blr_and, + blr_missing, + blr_field, 18, 16, 'R','D','B','$','P','A','C','K','A','G','E','_','N','A','M','E', + blr_eql, + blr_field, 18, 18, 'R','D','B','$','P','R','O','C','E','D','U','R','E','_','N','A','M','E', + blr_field, 1, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_end, + blr_begin, + blr_if, + blr_and, + blr_neq, + blr_field, 18, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_user_name, + blr_and, + blr_neq, + blr_user_name, + blr_literal, blr_text, 6,0, 'S','Y','S','D','B','A', + blr_and, + blr_neq, + blr_current_role, + blr_literal, blr_text, 9,0, 'R','D','B','$','A','D','M','I','N', + blr_not, + blr_any, + blr_rse, 1, + blr_relation, 13, 'R','D','B','$','R','E','L','A','T','I','O','N','S', 31, + blr_boolean, + blr_and, + blr_eql, + blr_field, 31, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_literal, blr_text, 12,0, 'R','D','B','$','D','A','T','A','B','A','S','E', + blr_eql, + blr_field, 31, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_user_name, + blr_end, + blr_if, + blr_not, + blr_any, + blr_rse, 1, + blr_relation, 19, 'R','D','B','$','U','S','E','R','_','P','R','I','V','I','L','E','G','E','S', 19, + blr_boolean, + blr_and, + blr_eql, + blr_field, 19, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 1, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 19, 15, 'R','D','B','$','O','B','J','E','C','T','_','T','Y','P','E', + blr_literal, blr_long, 0, 5,0,0,0, + blr_and, + blr_eql, + blr_field, 19, 13, 'R','D','B','$','P','R','I','V','I','L','E','G','E', + blr_field, 1, 13, 'R','D','B','$','P','R','I','V','I','L','E','G','E', + blr_and, + blr_eql, + blr_field, 19, 8, 'R','D','B','$','U','S','E','R', + blr_field, 1, 11, 'R','D','B','$','G','R','A','N','T','O','R', + blr_and, + blr_eql, + blr_field, 19, 13, 'R','D','B','$','U','S','E','R','_','T','Y','P','E', + blr_literal, blr_long, 0, 8,0,0,0, + blr_and, + blr_neq, + blr_field, 19, 16, 'R','D','B','$','G','R','A','N','T','_','O','P','T','I','O','N', + blr_literal, blr_long, 0, 0,0,0,0, + blr_or, + blr_missing, + blr_field, 19, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_eql, + blr_field, 19, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 1, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_end, + blr_leave, 2, + blr_end, + blr_end, + blr_if, + blr_missing, + blr_field, 18, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_modify, 18, 20, + blr_begin, + blr_assignment, + blr_cast, blr_varying2, 3,0, 31,0, + blr_concatenate, + blr_literal, blr_text2, 1,0, 4,0, 'S','Q','L','$', + blr_gen_id, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_literal, blr_long, 0, 1,0,0,0, + blr_field, 20, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_end, + blr_if, + blr_not, + blr_starting, + blr_field, 18, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_cast, blr_varying2, 3,0, 31,0, + blr_literal, blr_text2, 1,0, 4,0, 'S','Q','L','$', + b + lr_leave, 3, + blr_end, + blr_end, + blr_if, + blr_eql, + blr_field, 1, 15, 'R','D','B','$','O','B','J','E','C','T','_','T','Y','P','E', + blr_literal, blr_long, 0, 15,0,0,0, + blr_for, + blr_rse, 1, + blr_relation, 13, 'R','D','B','$','F','U','N','C','T','I','O','N','S', 26, + blr_boolean, + blr_and, + blr_missing, + blr_field, 26, 16, 'R','D','B','$','P','A','C','K','A','G','E','_','N','A','M','E', + blr_eql, + blr_field, 26, 17, 'R','D','B','$','F','U','N','C','T','I','O','N','_','N','A','M','E', + blr_field, 1, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_end, + blr_begin, + blr_if, + blr_and, + blr_neq, + blr_field, 26, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_user_name, + blr_and, + blr_neq, + blr_user_name, + blr_literal, blr_text, 6,0, 'S','Y','S','D','B','A', + blr_and, + blr_neq, + blr_current_role, + blr_literal, blr_text, 9,0, 'R','D','B','$','A','D','M','I','N', + blr_not, + blr_any, + blr_rse, 1, + blr_relation, 13, 'R','D','B','$','R','E','L','A','T','I','O','N','S', 32, + blr_boolean, + blr_and, + blr_eql, + blr_field, 32, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_literal, blr_text, 12,0, 'R','D','B','$','D','A','T','A','B','A','S','E', + blr_eql, + blr_field, 32, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_user_name, + blr_end, + blr_if, + blr_not, + blr_any, + blr_rse, 1, + blr_relation, 19, 'R','D','B','$','U','S','E','R','_','P','R','I','V','I','L','E','G','E','S', 27, + blr_boolean, + blr_and, + blr_eql, + blr_field, 27, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 1, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 27, 15, 'R','D','B','$','O','B','J','E','C','T','_','T','Y','P','E', + blr_literal, blr_long, 0, 5,0,0,0, + blr_and, + blr_eql, + blr_field, 27, 13, 'R','D','B','$','P','R','I','V','I','L','E','G','E', + blr_field, 1, 13, 'R','D','B','$','P','R','I','V','I','L','E','G','E', + blr_and, + blr_eql, + blr_field, 27, 8, 'R','D','B','$','U','S','E','R', + blr_field, 1, 11, 'R','D','B','$','G','R','A','N','T','O','R', + blr_and, + blr_eql, + blr_field, 27, 13, 'R','D','B','$','U','S','E','R','_','T','Y','P','E', + blr_literal, blr_long, 0, 8,0,0,0, + blr_and, + blr_neq, + blr_field, 27, 16, 'R','D','B','$','G','R','A','N','T','_','O','P','T','I','O','N', + blr_literal, blr_long, 0, 0,0,0,0, + blr_or, + blr_missing, + blr_field, 27, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_eql, + blr_field, 27, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 1, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_end, + blr_leave, 2, + blr_end, + blr_end, + blr_if, + blr_missing, + blr_field, 26, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_modify, 26, 28, + blr_begin, + blr_assignment, + blr_cast, blr_varying2, 3,0, 31,0, + blr_concatenate, + blr_literal, blr_text2, 1,0, 4,0, 'S','Q','L','$', + blr_gen_id, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_literal, blr_long, 0, 1,0,0,0, + blr_field, 28, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_end, + blr_if, + blr_not, + blr_starting, + blr_field, 26, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_cast, blr_varying2, 3,0, 31,0, + blr_literal, blr_text2, 1,0, 4,0, 'S','Q','L','$', + blr_leave, 3, + blr_end, + blr_end, + blr_if, + blr_eql, + blr_field, 1, 15, 'R','D','B','$','O','B','J','E','C','T','_','T','Y','P','E', + blr_literal, blr_long, 0, 18,0,0,0, + blr_for, + blr_rse, 1, + blr_relation, 12, 'R','D','B','$','P','A','C','K','A','G','E','S', 22, + blr_boolean, + blr_eql, + blr_field, 22, 16, 'R','D','B','$','P','A','C','K','A','G','E','_','N','A','M','E', + blr_field, 1, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_end, + blr_begin, + blr_if, + blr_and, + blr_neq, + blr_field, 22, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_user_name, + blr_and, + blr_neq, + blr_user_name, + blr_literal, blr_text, 6,0, 'S','Y','S','D','B','A', + blr_and, + blr_neq, + blr_current_role, + blr_literal, blr_text, 9,0, 'R','D','B','$','A','D','M','I','N', + blr_not, + blr_any, + blr_rse, 1, + blr_relation, 13, 'R','D','B','$','R','E','L','A','T','I','O','N','S', 33, + blr_boolean, + blr_and, + blr_eql, + blr_field, 33, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_literal, blr_text, 12,0, 'R','D','B','$','D','A','T','A','B','A','S','E', + blr_eql, + blr_field, 33, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_user_name, + blr_end, + blr_if, + blr_not, + blr_any, + blr_rse, 1, + blr_relation, 19, 'R','D','B','$','U','S','E','R','_','P','R','I','V','I','L','E','G','E','S', 24, + blr_boolean, + blr_and, + blr_eql, + blr_field, 24, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 1, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 24, 15, 'R','D','B','$','O','B','J','E','C','T','_','T','Y','P','E', + blr_literal, blr_long, 0, 18,0,0,0, + blr_and, + blr_eql, + blr_field, 24, 13, 'R','D','B','$','P','R','I','V','I','L','E','G','E', + blr_field, 1, 13, 'R','D','B','$','P','R','I','V','I','L','E','G','E', + blr_and, + blr_eql, + blr_field, 24, 8, 'R','D','B','$','U','S','E','R', + blr_field, 1, 11, 'R','D','B','$','G','R','A','N','T','O','R', + blr_and, + blr_eql, + blr_field, 24, 13, 'R','D','B','$','U','S','E','R','_','T','Y','P','E', + blr_literal, blr_long, 0, 8,0,0,0, + blr_and, + blr_neq, + blr_field, 24, 16, 'R','D','B','$','G','R','A','N','T','_','O','P','T','I','O','N', + blr_literal, blr_long, 0, 0,0,0,0, + blr_or, + blr_missing, + blr_field, 24, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_eql, + blr_field, 24, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 1, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_end, + blr_leave, 2, + blr_end, + blr_end, + blr_if, + blr_missing, + blr_field, 22, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_modify, 22, 23, + blr_begin, + blr_assignment, + blr_cast, blr_varying2, 3,0, 31,0, + blr_concatenate, + blr_literal, blr_text2, 1,0, 4,0, 'S','Q','L','$', + blr_gen_id, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_literal, blr_long, 0, 1,0,0,0, + blr_field, 23, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_end, + blr_if, + blr_not, + blr_starting, + blr_field, 22, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_cast, blr_varying2, 3,0, 31,0, + blr_literal, blr_text2, 1,0, 4,0, 'S','Q','L','$', + blr_leave, 3, + blr_end, + blr_end, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + + + Records affected: 29 + + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_db_29_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [('RDB\\$TRIGGER_BLR.*', ''), ('RDB\\$TRIGGER_NAME[\\s]+RDB\\$TRIGGER.*', 'RDB\\$TRIGGER_NAME RDB\\$TRIGGER')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set list on; + set blob all; + set count on; + select * from rdb$triggers rt order by rt.rdb$trigger_name; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + RDB$TRIGGER_NAME RDB$TRIGGER_1 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 3 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:0 + blr_version5, + blr_leave, 0, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + RDB$TRIGGER_NAME RDB$TRIGGER_10 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 5 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:7 + blr_version5, + blr_begin, + blr_label, 0, + blr_begin, + blr_begin, + blr_if, + blr_or, + blr_eql, + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text2, 0,0, 11,0, 'P','R','I','M','A','R','Y',32,'K','E','Y', + blr_eql, + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text2, 0,0, 6,0, 'U','N','I','Q','U','E', + blr_begin, + blr_begin, + blr_if, + blr_any, + blr_rse, 1, + blr_relation, 19, 'R','D','B','$','R','E','F','_','C','O','N','S','T','R','A','I','N','T','S', 2, + blr_boolean, + blr_eql, + blr_field, 2, 17, 'R','D','B','$','C','O','N','S','T','_','N','A','M','E','_','U','Q', + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_end, + blr_begin, + blr_begin, + blr_leave, 1, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_if, + blr_eql, + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text2, 0,0, 11,0, 'F','O','R','E','I','G','N',32,'K','E','Y', + blr_begin, + blr_begin, + blr_for, + blr_rse, 1, + blr_relation, 19, 'R','D','B','$','R','E','F','_','C','O','N','S','T','R','A','I','N','T','S', 3, + blr_boolean, + blr_eql, + blr_field, 3, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_end, + blr_erase, 3, + blr_end, + blr_end, + blr_end, + blr_if, + blr_eql, + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text2, 0,0, 8,0, 'N','O','T',32,'N','U','L','L', + blr_begin, + blr_begin, + blr_label, 1, + blr_for, + blr_rse, 5, + blr_relation2, 21, 'R','D','B','$','C','H','E','C','K','_','C','O','N','S','T','R','A','I','N','T','S', + 9, 'C','1',32,'C','H','K','C','O','N', 4, + blr_relation2, 19, 'R','D','B','$','R','E','L','A','T','I','O','N','_','F','I','E','L','D','S', + 6, 'C','1',32,'R','F','L', 5, + blr_relation2, 10, 'R','D','B','$','F','I','E','L','D','S', + 6, 'C','1',32,'F','L','D', 6, + blr_relation2, 11, 'R','D','B','$','I','N','D','I','C','E','S', + 6, 'C','1',32,'I','N','D', 7, + blr_relation2, 18, 'R','D','B','$','I','N','D','E','X','_','S','E','G','M','E','N','T','S', + 9, 'C','1',32,'I','D','X','S','E','G', 8, + blr_boolean, + blr_and, + blr_and, + blr_and, + blr_and, + blr_and, + blr_and, + blr_and, + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_eql, + blr_field, 5, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 4, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_eql, + blr_field, 5, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 0, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_eql, + blr_field, 5, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 8, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_eql, + blr_field, 6, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 5, 16, 'R','D','B','$','F','I','E','L','D','_','S','O','U','R','C','E', + blr_or, + blr_missing, + blr_field, 6, 13, 'R','D','B','$','N','U','L','L','_','F','L','A','G', + blr_eql, + blr_field, 6, 13, 'R','D','B','$','N','U','L','L','_','F','L','A','G', + blr_literal, blr_long, 0, 0,0,0,0, + blr_eql, + blr_field, 7, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 0, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_eql, + blr_field, 7, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 8, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_end, + blr_begin, + blr_begin, + blr_begin, + blr_if, + blr_any, + blr_rse, 1, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 9, + blr_boolean, + blr_and, + blr_eql, + blr_field, 9, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_derived_expr, 1, 8, + blr_field, 8, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_eql, + blr_field, 9, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text2, 0,0, 11,0, 'P','R','I','M','A','R','Y',32,'K','E','Y', + blr_end, + blr_begin, + blr_begin, + blr_leave, 2, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + RDB$TRIGGER_NAME RDB$TRIGGER_11 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 6 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:8 + blr_version5, + blr_begin, + blr_if, + blr_or, + blr_eql, + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 11,0, 'F','O','R','E','I','G','N',32,'K','E','Y', + blr_or, + blr_eql, + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 11,0, 'P','R','I','M','A','R','Y',32,'K','E','Y', + blr_eql, + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 6,0, 'U','N','I','Q','U','E', + blr_begin, + blr_for, + blr_rse, 1, + blr_relation, 11, 'R','D','B','$','I','N','D','I','C','E','S', 3, + blr_boolean, + blr_eql, + blr_field, 0, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 3, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_end, + blr_begin, + blr_erase, 3, + blr_for, + blr_rse, 1, + blr_relation, 18, 'R','D','B','$','I','N','D','E','X','_','S','E','G','M','E','N','T','S', 4, + blr_boolean, + blr_eql, + blr_field, 4, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 3, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_end, + blr_begin, + blr_erase, 4, + blr_end, + blr_end, + blr_end, + blr_end, + blr_if, + blr_eql, + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 8,0, 'N','O','T',32,'N','U','L','L', + blr_begin, + blr_for, + blr_rse, 2, + blr_relation, 21, 'R','D','B','$','C','H','E','C','K','_','C','O','N','S','T','R','A','I','N','T','S', 5, + blr_relation, 19, 'R','D','B','$','R','E','L','A','T','I','O','N','_','F','I','E','L','D','S', 6, + blr_boolean, + blr_and, + blr_eql, + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 5, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 6, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 0, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_eql, + blr_field, 6, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 5, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_end, + blr_begin, + blr_erase, 5, + blr_modify, 6, 7, + blr_begin, + blr_assignment, + blr_literal, blr_long, 0, 0,0,0,0, + blr_field, 7, 13, 'R','D','B','$','N','U','L','L','_','F','L','A','G', + blr_end, + blr_end, + blr_end, + blr_end, + blr_if, + blr_eql, + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 5,0, 'C','H','E','C','K', + blr_begin, + blr_for, + blr_rse, 1, + blr_relation, 21, 'R','D','B','$','C','H','E','C','K','_','C','O','N','S','T','R','A','I','N','T','S', 8, + blr_boolean, + blr_eql, + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 8, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_end, + blr_begin, + blr_erase, 8, + blr_for, + blr_rse, 1, + blr_relation, 12, 'R','D','B','$','T','R','I','G','G','E','R','S', 9, + blr_boolean, + blr_and, + blr_eql, + blr_field, 9, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_field, 8, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_eql, + blr_field, 9, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 0, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_end, + blr_begin, + blr_erase, 9, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + RDB$TRIGGER_NAME RDB$TRIGGER_12 + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 1 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:9 + blr_version5, + blr_begin, + blr_if, + blr_not, + blr_any, + blr_rse, 1, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 3, + blr_boolean, + blr_and, + blr_eql, + blr_field, 3, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 1, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_eql, + blr_field, 3, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 11,0, 'F','O','R','E','I','G','N',32,'K','E','Y', + blr_end, + blr_leave, 1, + blr_end, + blr_if, + blr_not, + blr_any, + blr_rse, 1, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 4, + blr_boolean, + blr_and, + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 1, 17, 'R','D','B','$','C','O','N','S','T','_','N','A','M','E','_','U','Q', + blr_or, + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 11,0, 'P','R','I','M','A','R','Y',32,'K','E','Y', + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 6,0, 'U','N','I','Q','U','E', + blr_end, + blr_leave, 2, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + RDB$TRIGGER_NAME RDB$TRIGGER_13 + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 3 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:a + blr_version5, + blr_begin, + blr_leave, 1, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + RDB$TRIGGER_NAME RDB$TRIGGER_14 + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 3 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:b + blr_version5, + blr_begin, + blr_if, + blr_any, + blr_rse, 1, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 3, + blr_boolean, + blr_and, + blr_not, + blr_eql, + blr_field, 3, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 8,0, 'N','O','T',32,'N','U','L','L', + blr_eql, + blr_field, 3, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_end, + blr_leave, 1, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + RDB$TRIGGER_NAME RDB$TRIGGER_15 + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 5 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:c + blr_version5, + blr_begin, + blr_if, + blr_any, + blr_rse, 1, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 3, + blr_boolean, + blr_eql, + blr_field, 3, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_end, + blr_leave, 1, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + RDB$TRIGGER_NAME RDB$TRIGGER_16 + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 6 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:d + blr_version5, + blr_begin, + blr_for, + blr_rse, 2, + blr_relation, 19, 'R','D','B','$','R','E','L','A','T','I','O','N','_','F','I','E','L','D','S', 3, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 4, + blr_boolean, + blr_and, + blr_eql, + blr_field, 3, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 4, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 8,0, 'N','O','T',32,'N','U','L','L', + blr_eql, + blr_field, 3, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 0, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_end, + blr_begin, + blr_modify, 3, 5, + blr_begin, + blr_assignment, + blr_literal, blr_long, 0, 0,0,0,0, + blr_field, 5, 13, 'R','D','B','$','N','U','L','L','_','F','L','A','G', + blr_end, + blr_end, + blr_for, + blr_rse, 2, + blr_relation, 12, 'R','D','B','$','T','R','I','G','G','E','R','S', 6, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 7, + blr_boolean, + blr_and, + blr_eql, + blr_field, 7, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 7, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 5,0, 'C','H','E','C','K', + blr_and, + blr_eql, + blr_field, 6, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 7, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_eql, + blr_field, 6, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_field, 0, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_end, + blr_begin, + blr_erase, 6, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + RDB$TRIGGER_NAME RDB$TRIGGER_17 + RDB$RELATION_NAME RDB$INDEX_SEGMENTS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 5 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:e + blr_version5, + blr_begin, + blr_if, + blr_any, + blr_rse, 1, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 3, + blr_boolean, + blr_eql, + blr_field, 3, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 0, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_end, + blr_leave, 1, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + RDB$TRIGGER_NAME RDB$TRIGGER_18 + RDB$RELATION_NAME RDB$INDEX_SEGMENTS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 3 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:f + blr_version5, + blr_begin, + blr_if, + blr_any, + blr_rse, 1, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 3, + blr_boolean, + blr_eql, + blr_field, 3, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 0, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_end, + blr_if, + blr_not, + blr_and, + blr_eql, + blr_field, 0, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 1, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 0, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 1, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_eql, + blr_field, 0, 18, 'R','D','B','$','F','I','E','L','D','_','P','O','S','I','T','I','O','N', + blr_field, 1, 18, 'R','D','B','$','F','I','E','L','D','_','P','O','S','I','T','I','O','N', + blr_leave, 1, + blr_end, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + RDB$TRIGGER_NAME RDB$TRIGGER_19 + RDB$RELATION_NAME RDB$INDICES + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 5 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:10 + blr_version5, + blr_begin, + blr_if, + blr_any, + blr_rse, 1, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 3, + blr_boolean, + blr_eql, + blr_field, 3, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 0, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_end, + blr_leave, 1, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + RDB$TRIGGER_NAME RDB$TRIGGER_2 + RDB$RELATION_NAME RDB$TRIGGERS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 3 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:3 + blr_version5, + blr_if, + blr_eql, + blr_field, 0, 15, 'R','D','B','$','S','Y','S','T','E','M','_','F','L','A','G', + blr_literal, blr_short, 0, 1,0, + blr_leave, 0, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + RDB$TRIGGER_NAME RDB$TRIGGER_20 + RDB$RELATION_NAME RDB$INDICES + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 3 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:11 + blr_version5, + blr_begin, + blr_if, + blr_any, + blr_rse, 1, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 3, + blr_boolean, + blr_eql, + blr_field, 3, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 0, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_end, + blr_begin, + blr_if, + blr_not, + blr_and, + blr_eql, + blr_field, 0, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 1, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 0, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 1, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 0, 12, 'R','D','B','$','I','N','D','E','X','_','I','D', + blr_field, 1, 12, 'R','D','B','$','I','N','D','E','X','_','I','D', + blr_and, + blr_eql, + blr_field, 0, 17, 'R','D','B','$','S','E','G','M','E','N','T','_','C','O','U','N','T', + blr_field, 1, 17, 'R','D','B','$','S','E','G','M','E','N','T','_','C','O','U','N','T', + blr_eql, + blr_field, 0, 15, 'R','D','B','$','F','O','R','E','I','G','N','_','K','E','Y', + blr_field, 1, 15, 'R','D','B','$','F','O','R','E','I','G','N','_','K','E','Y', + blr_leave, 1, + blr_end, + blr_end, + blr_end, + blr_for, + blr_rse, 3, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 4, + blr_relation, 11, 'R','D','B','$','I','N','D','I','C','E','S', 5, + blr_relation, 11, 'R','D','B','$','I','N','D','I','C','E','S', 6, + blr_boolean, + blr_and, + blr_eql, + blr_field, 4, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 0, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 5, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 0, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 6, 15, 'R','D','B','$','F','O','R','E','I','G','N','_','K','E','Y', + blr_field, 0, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 1, 18, 'R','D','B','$','I','N','D','E','X','_','I','N','A','C','T','I','V','E', + blr_literal, blr_long, 0, 1,0,0,0, + blr_or, + blr_eql, + blr_field, 0, 18, 'R','D','B','$','I','N','D','E','X','_','I','N','A','C','T','I','V','E', + blr_literal, blr_long, 0, 0,0,0,0, + blr_missing, + blr_field, 0, 18, 'R','D','B','$','I','N','D','E','X','_','I','N','A','C','T','I','V','E', + blr_end, + blr_begin, + blr_leave, 2, + blr_end, + blr_if, + blr_any, + blr_rse, 1, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 7, + blr_boolean, + blr_and, + blr_eql, + blr_field, 7, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 0, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_or, + blr_eql, + blr_field, 7, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 11,0, 'P','R','I','M','A','R','Y',32,'K','E','Y', + blr_or, + blr_eql, + blr_field, 7, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 6,0, 'U','N','I','Q','U','E', + blr_eql, + blr_field, 7, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 11,0, 'F','O','R','E','I','G','N',32,'K','E','Y', + blr_end, + blr_begin, + blr_if, + blr_and, + blr_eql, + blr_field, 1, 18, 'R','D','B','$','I','N','D','E','X','_','I','N','A','C','T','I','V','E', + blr_literal, blr_long, 0, 1,0,0,0, + blr_or, + blr_eql, + blr_field, 0, 18, 'R','D','B','$','I','N','D','E','X','_','I','N','A','C','T','I','V','E', + blr_literal, blr_long, 0, 0,0,0,0, + blr_missing, + blr_field, 0, 18, 'R','D','B','$','I','N','D','E','X','_','I','N','A','C','T','I','V','E', + blr_begin, + blr_if, + blr_eql, + blr_field, 7, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 11,0, 'F','O','R','E','I','G','N',32,'K','E','Y', + blr_leave, 2, + blr_leave, 3, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + RDB$TRIGGER_NAME RDB$TRIGGER_21 + RDB$RELATION_NAME RDB$TRIGGERS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 5 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:12 + blr_version5, + blr_begin, + blr_for, + blr_rse, 2, + blr_relation, 21, 'R','D','B','$','C','H','E','C','K','_','C','O','N','S','T','R','A','I','N','T','S', 3, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 4, + blr_boolean, + blr_and, + blr_eql, + blr_field, 3, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_field, 0, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 3, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 5,0, 'C','H','E','C','K', + blr_end, + blr_begin, + blr_leave, 1, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + RDB$TRIGGER_NAME RDB$TRIGGER_22 + RDB$RELATION_NAME RDB$TRIGGERS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 3 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:3c0 + blr_version5, + blr_begin, + blr_for, + blr_rse, 2, + blr_relation, 21, 'R','D','B','$','C','H','E','C','K','_','C','O','N','S','T','R','A','I','N','T','S', 3, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 4, + blr_boolean, + blr_and, + blr_eql, + blr_field, 3, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_field, 0, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 3, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 5,0, 'C','H','E','C','K', + blr_end, + blr_begin, + blr_if, + blr_not, + blr_and, + blr_and, + blr_and, + blr_and, + blr_and, + blr_and, + blr_and, + blr_and, + blr_equiv, + blr_field, 0, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_field, 1, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_equiv, + blr_field, 0, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 1, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_equiv, + blr_field, 0, 20, 'R','D','B','$','T','R','I','G','G','E','R','_','S','E','Q','U','E','N','C','E', + blr_field, 1, 20, 'R','D','B','$','T','R','I','G','G','E','R','_','S','E','Q','U','E','N','C','E', + blr_equiv, + blr_field, 0, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','T','Y','P','E', + blr_field, 1, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','T','Y','P','E', + blr_equiv, + blr_field, 0, 15, 'R','D','B','$','T','R','I','G','G','E','R','_','B','L','R', + blr_field, 1, 15, 'R','D','B','$','T','R','I','G','G','E','R','_','B','L','R', + blr_equiv, + blr_field, 0, 20, 'R','D','B','$','T','R','I','G','G','E','R','_','I','N','A','C','T','I','V','E', + blr_field, 1, 20, 'R','D','B','$','T','R','I','G','G','E','R','_','I','N','A','C','T','I','V','E', + blr_equiv, + blr_field, 0, 15, 'R','D','B','$','S','Y','S','T','E','M','_','F','L','A','G', + blr_field, 1, 15, 'R','D','B','$','S','Y','S','T','E','M','_','F','L','A','G', + blr_equiv, + blr_field, 0, 9, 'R','D','B','$','F','L','A','G','S', + blr_field, 1, 9, 'R','D','B','$','F','L','A','G','S', + blr_equiv, + blr_field, 0, 14, 'R','D','B','$','D','E','B','U','G','_','I','N','F','O', + blr_field, 1, 14, 'R','D','B','$','D','E','B','U','G','_','I','N','F','O', + blr_begin, + blr_leave, 1, + blr_end, + blr_end, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + RDB$TRIGGER_NAME RDB$TRIGGER_23 + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 5 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:3c1 + blr_version5, + blr_begin, + blr_for, + blr_rse, 3, + blr_relation, 11, 'R','D','B','$','I','N','D','I','C','E','S', 3, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 4, + blr_relation, 18, 'R','D','B','$','I','N','D','E','X','_','S','E','G','M','E','N','T','S', 5, + blr_boolean, + blr_and, + blr_eql, + blr_field, 3, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 0, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 3, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 5, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 4, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 5, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_eql, + blr_field, 5, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 0, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_end, + blr_begin, + blr_if, + blr_any, + blr_rse, 1, + blr_relation, 18, 'R','D','B','$','I','N','D','E','X','_','S','E','G','M','E','N','T','S', 6, + blr_boolean, + blr_and, + blr_eql, + blr_field, 6, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 5, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_neq, + blr_field, 6, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 0, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_end, + blr_leave, 1, + blr_erase, 4, + blr_end, + blr_for, + blr_rse, 3, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 7, + blr_relation, 21, 'R','D','B','$','C','H','E','C','K','_','C','O','N','S','T','R','A','I','N','T','S', 8, + blr_relation, 16, 'R','D','B','$','D','E','P','E','N','D','E','N','C','I','E','S', 9, + blr_boolean, + blr_and, + blr_and, + blr_eql, + blr_field, 7, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 0, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 7, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 5,0, 'C','H','E','C','K', + blr_and, + blr_eql, + blr_field, 8, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_field, 9, 18, 'R','D','B','$','D','E','P','E','N','D','E','N','T','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 9, 18, 'R','D','B','$','D','E','P','E','N','D','E','N','T','_','T','Y','P','E', + blr_literal, blr_long, 0, 2,0,0,0, + blr_and, + blr_eql, + blr_field, 9, 20, 'R','D','B','$','D','E','P','E','N','D','E','D','_','O','N','_','T','Y','P','E', + blr_literal, blr_long, 0, 0,0,0,0, + blr_and, + blr_eql, + blr_field, 9, 20, 'R','D','B','$','D','E','P','E','N','D','E','D','_','O','N','_','N','A','M','E', + blr_field, 0, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_eql, + blr_field, 9, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 0, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_eql, + blr_field, 8, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 7, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_end, + blr_begin, + blr_if, + blr_any, + blr_rse, 1, + blr_relation, 16, 'R','D','B','$','D','E','P','E','N','D','E','N','C','I','E','S', 10, + blr_boolean, + blr_and, + blr_eql, + blr_field, 10, 18, 'R','D','B','$','D','E','P','E','N','D','E','N','T','_','N','A','M','E', + blr_field, 8, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 10, 18, 'R','D','B','$','D','E','P','E','N','D','E','N','T','_','T','Y','P','E', + blr_literal, blr_long, 0, 2,0,0,0, + blr_and, + blr_eql, + blr_field, 10, 20, 'R','D','B','$','D','E','P','E','N','D','E','D','_','O','N','_','T','Y','P','E', + blr_literal, blr_long, 0, 0,0,0,0, + blr_and, + blr_eql, + blr_field, 10, 20, 'R','D','B','$','D','E','P','E','N','D','E','D','_','O','N','_','N','A','M','E', + blr_field, 0, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_neq, + blr_field, 10, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 0, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_end, + blr_leave, 1, + blr_erase, 7, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + RDB$TRIGGER_NAME RDB$TRIGGER_24 + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 3 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:3c2 + blr_version5, + blr_begin, + blr_if, + blr_any, + blr_rse, 3, + blr_relation, 11, 'R','D','B','$','I','N','D','I','C','E','S', 3, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 4, + blr_relation, 18, 'R','D','B','$','I','N','D','E','X','_','S','E','G','M','E','N','T','S', 5, + blr_boolean, + blr_and, + blr_eql, + blr_field, 3, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 0, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 3, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 5, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 4, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 5, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_eql, + blr_field, 5, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 0, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_end, + blr_begin, + blr_if, + blr_neq, + blr_field, 0, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 1, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_leave, 1, + blr_end, + blr_if, + blr_not, + blr_and, + blr_eql, + blr_field, 0, 16, 'R','D','B','$','F','I','E','L','D','_','S','O','U','R','C','E', + blr_field, 1, 16, 'R','D','B','$','F','I','E','L','D','_','S','O','U','R','C','E', + blr_eql, + blr_field, 0, 16, 'R','D','B','$','C','O','L','L','A','T','I','O','N','_','I','D', + blr_field, 1, 16, 'R','D','B','$','C','O','L','L','A','T','I','O','N','_','I','D', + blr_leave, 2, + blr_end, + blr_end, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + RDB$TRIGGER_NAME RDB$TRIGGER_25 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 3 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:6 + blr_version5, + blr_begin, + blr_leave, 1, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + RDB$TRIGGER_NAME RDB$TRIGGER_26 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 1 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:5 + blr_version5, + blr_begin, + blr_if, + blr_any, + blr_rse, 1, + blr_relation, 13, 'R','D','B','$','R','E','L','A','T','I','O','N','S', 3, + blr_boolean, + blr_and, + blr_eql, + blr_field, 3, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 1, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_not, + blr_missing, + blr_field, 3, 15, 'R','D','B','$','V','I','E','W','_','S','O','U','R','C','E', + blr_end, + blr_leave, 1, + blr_end, + blr_if, + blr_not, + blr_or, + blr_eql, + blr_field, 1, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 6,0, 'U','N','I','Q','U','E', + blr_or, + blr_eql, + blr_field, 1, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 11,0, 'P','R','I','M','A','R','Y',32,'K','E','Y', + blr_or, + blr_eql, + blr_field, 1, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 11,0, 'F','O','R','E','I','G','N',32,'K','E','Y', + blr_or, + blr_eql, + blr_field, 1, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 8,0, 'N','O','T',32,'N','U','L','L', + blr_eql, + blr_field, 1, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 5,0, 'C','H','E','C','K', + blr_leave, 2, + blr_end, + blr_if, + blr_eql, + blr_field, 1, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 11,0, 'P','R','I','M','A','R','Y',32,'K','E','Y', + blr_begin, + blr_if, + blr_any, + blr_rse, 1, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 4, + blr_boolean, + blr_and, + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 11,0, 'P','R','I','M','A','R','Y',32,'K','E','Y', + blr_eql, + blr_field, 4, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 1, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_end, + blr_leave, 3, + blr_end, + blr_end, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + RDB$TRIGGER_NAME RDB$TRIGGER_27 + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 6 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:3c3 + blr_version5, + blr_begin, + blr_for, + blr_rse, 2, + blr_relation, 21, 'R','D','B','$','C','H','E','C','K','_','C','O','N','S','T','R','A','I','N','T','S', 3, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 4, + blr_boolean, + blr_and, + blr_eql, + blr_field, 0, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 3, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 3, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 0, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 4, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 8,0, 'N','O','T',32,'N','U','L','L', + blr_end, + blr_begin, + blr_erase, 4, + blr_erase, 3, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + RDB$TRIGGER_NAME RDB$TRIGGER_3 + RDB$RELATION_NAME RDB$TRIGGERS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 5 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:4 + blr_version5, + blr_if, + blr_eql, + blr_field, 0, 15, 'R','D','B','$','S','Y','S','T','E','M','_','F','L','A','G', + blr_literal, blr_short, 0, 1,0, + blr_leave, 0, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + RDB$TRIGGER_NAME RDB$TRIGGER_31 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 3 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:3c4 + blr_version5, + blr_begin, + blr_if, + blr_and, + blr_not, + blr_missing, + blr_field, 1, 11, 'R','D','B','$','G','R','A','N','T','O','R', + blr_and, + blr_neq, + blr_field, 1, 11, 'R','D','B','$','G','R','A','N','T','O','R', + blr_user_name, + blr_neq, + blr_sys_function, 20, 'R','D','B','$','S','Y','S','T','E','M','_','P','R','I','V','I','L','E','G','E',1, + blr_literal, blr_short, 0, 20,0, + blr_literal, blr_bool, 1, + blr_begin, + blr_for, + blr_rse, 1, + blr_relation, 13, 'R','D','B','$','R','E','L','A','T','I','O','N','S', 3, + blr_boolean, + blr_eql, + blr_field, 3, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_literal, blr_text, 12,0, 'R','D','B','$','D','A','T','A','B','A','S','E', + blr_end, + blr_begin, + blr_if, + blr_or, + blr_missing, + blr_field, 3, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_neq, + blr_field, 3, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_user_name, + blr_leave, 0, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + RDB$TRIGGER_NAME RDB$TRIGGER_32 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 5 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:3c5 + blr_version5, + blr_begin, + blr_if, + blr_and, + blr_not, + blr_missing, + blr_field, 1, 11, 'R','D','B','$','G','R','A','N','T','O','R', + blr_and, + blr_neq, + blr_field, 1, 11, 'R','D','B','$','G','R','A','N','T','O','R', + blr_user_name, + blr_neq, + blr_sys_function, 20, 'R','D','B','$','S','Y','S','T','E','M','_','P','R','I','V','I','L','E','G','E',1, + blr_literal, blr_short, 0, 20,0, + blr_literal, blr_bool, 1, + blr_begin, + blr_for, + blr_rse, 1, + blr_relation, 13, 'R','D','B','$','R','E','L','A','T','I','O','N','S', 3, + blr_boolean, + blr_eql, + blr_field, 3, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_literal, blr_text, 12,0, 'R','D','B','$','D','A','T','A','B','A','S','E', + blr_end, + blr_begin, + blr_if, + blr_or, + blr_missing, + blr_field, 3, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_neq, + blr_field, 3, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_user_name, + blr_leave, 0, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + RDB$TRIGGER_NAME RDB$TRIGGER_33 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 1 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:3c6 + blr_version5, + blr_begin, + blr_if, + blr_and, + blr_not, + blr_missing, + blr_field, 1, 11, 'R','D','B','$','G','R','A','N','T','O','R', + blr_and, + blr_neq, + blr_field, 1, 11, 'R','D','B','$','G','R','A','N','T','O','R', + blr_user_name, + blr_neq, + blr_sys_function, 20, 'R','D','B','$','S','Y','S','T','E','M','_','P','R','I','V','I','L','E','G','E',1, + blr_literal, blr_short, 0, 20,0, + blr_literal, blr_bool, 1, + blr_begin, + blr_for, + blr_rse, 1, + blr_relation, 13, 'R','D','B','$','R','E','L','A','T','I','O','N','S', 3, + blr_boolean, + blr_eql, + blr_field, 3, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_literal, blr_text, 12,0, 'R','D','B','$','D','A','T','A','B','A','S','E', + blr_end, + blr_begin, + blr_if, + blr_or, + blr_missing, + blr_field, 3, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_neq, + blr_field, 3, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_user_name, + blr_leave, 0, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + RDB$TRIGGER_NAME RDB$TRIGGER_34 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 6 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:3c7 + blr_version5, + blr_begin, + blr_if, + blr_eql, + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 11,0, 'F','O','R','E','I','G','N',32,'K','E','Y', + blr_begin, + blr_for, + blr_rse, 1, + blr_relation, 21, 'R','D','B','$','C','H','E','C','K','_','C','O','N','S','T','R','A','I','N','T','S', 3, + blr_boolean, + blr_eql, + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 3, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_end, + blr_begin, + blr_erase, 3, + blr_for, + blr_rse, 1, + blr_relation, 12, 'R','D','B','$','T','R','I','G','G','E','R','S', 4, + blr_boolean, + blr_eql, + blr_field, 4, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_field, 3, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_end, + blr_begin, + blr_erase, 4, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 2 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + RDB$TRIGGER_NAME RDB$TRIGGER_35 + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 6 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:3c8 + blr_version5, + blr_begin, + blr_for, + blr_rse, 2, + blr_relation, 12, 'R','D','B','$','T','R','I','G','G','E','R','S', 3, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 4, + blr_boolean, + blr_and, + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_field, 0, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 4, 19, 'R','D','B','$','C','O','N','S','T','R','A','I','N','T','_','T','Y','P','E', + blr_literal, blr_text, 11,0, 'F','O','R','E','I','G','N',32,'K','E','Y', + blr_eql, + blr_field, 3, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_field, 0, 16, 'R','D','B','$','T','R','I','G','G','E','R','_','N','A','M','E', + blr_end, + blr_begin, + blr_erase, 3, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 2 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + RDB$TRIGGER_NAME RDB$TRIGGER_36 + RDB$RELATION_NAME RDB$FIELDS + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 3 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:3c9 + blr_version5, + blr_begin, + blr_if, + blr_not, + blr_and, + blr_eql, + blr_field, 0, 16, 'R','D','B','$','F','I','E','L','D','_','L','E','N','G','T','H', + blr_field, 1, 16, 'R','D','B','$','F','I','E','L','D','_','L','E','N','G','T','H', + blr_and, + blr_eql, + blr_field, 0, 14, 'R','D','B','$','F','I','E','L','D','_','T','Y','P','E', + blr_field, 1, 14, 'R','D','B','$','F','I','E','L','D','_','T','Y','P','E', + blr_and, + blr_eql, + blr_field, 0, 16, 'R','D','B','$','C','O','L','L','A','T','I','O','N','_','I','D', + blr_field, 1, 16, 'R','D','B','$','C','O','L','L','A','T','I','O','N','_','I','D', + blr_eql, + blr_field, 0, 20, 'R','D','B','$','C','H','A','R','A','C','T','E','R','_','S','E','T','_','I','D', + blr_field, 1, 20, 'R','D','B','$','C','H','A','R','A','C','T','E','R','_','S','E','T','_','I','D', + blr_if, + blr_any, + blr_rse, 4, + blr_relation, 11, 'R','D','B','$','I','N','D','I','C','E','S', 3, + blr_relation, 24, 'R','D','B','$','R','E','L','A','T','I','O','N','_','C','O','N','S','T','R','A','I','N','T','S', 4, + blr_relation, 18, 'R','D','B','$','I','N','D','E','X','_','S','E','G','M','E','N','T','S', 5, + blr_relation, 19, 'R','D','B','$','R','E','L','A','T','I','O','N','_','F','I','E','L','D','S', 6, + blr_boolean, + blr_and, + blr_eql, + blr_field, 3, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 6, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 3, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 5, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 4, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_field, 5, 14, 'R','D','B','$','I','N','D','E','X','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 5, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 6, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_eql, + blr_field, 6, 16, 'R','D','B','$','F','I','E','L','D','_','S','O','U','R','C','E', + blr_field, 0, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_end, + blr_leave, 1, + blr_end, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + RDB$TRIGGER_NAME RDB$TRIGGER_8 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 5 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:1 + blr_version5, + blr_if, + blr_not, + blr_missing, + blr_field, 0, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_for, + blr_rse, 1, + blr_relation, 19, 'R','D','B','$','R','E','L','A','T','I','O','N','_','F','I','E','L','D','S', 3, + blr_boolean, + blr_and, + blr_eql, + blr_field, 3, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 0, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_eql, + blr_field, 3, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 0, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_end, + blr_begin, + blr_if, + blr_starting, + blr_field, 3, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_literal, blr_text, 9,0, 'S','Q','L','$','G','R','A','N','T', + blr_begin, + blr_for, + blr_rse, 1, + blr_relation, 20, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S','E','S', 4, + blr_boolean, + blr_eql, + blr_field, 4, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_field, 3, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_end, + blr_begin, + blr_erase, 4, + blr_end, + blr_modify, 3, 5, + blr_begin, + blr_assignment, + blr_null, + blr_field, 5, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + RDB$TRIGGER_NAME RDB$TRIGGER_9 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$TRIGGER_SEQUENCE 0 + RDB$TRIGGER_TYPE 1 + RDB$TRIGGER_SOURCE + RDB$TRIGGER_BLR c:2 + blr_version5, + blr_begin, + blr_if, + blr_missing, + blr_field, 1, 11, 'R','D','B','$','G','R','A','N','T','O','R', + blr_assignment, + blr_user_name, + blr_field, 1, 11, 'R','D','B','$','G','R','A','N','T','O','R', + blr_end, + blr_if, + blr_eql, + blr_field, 1, 15, 'R','D','B','$','O','B','J','E','C','T','_','T','Y','P','E', + blr_literal, blr_long, 0, 0,0,0,0, + blr_begin, + blr_for, + blr_rse, 1, + blr_relation, 13, 'R','D','B','$','R','E','L','A','T','I','O','N','S', 6, + blr_boolean, + blr_eql, + blr_field, 6, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 1, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_end, + blr_begin, + blr_if, + blr_or, + blr_and, + blr_eql, + blr_field, 6, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_user_name, + blr_and, + blr_eql, + blr_field, 6, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_field, 1, 11, 'R','D','B','$','G','R','A','N','T','O','R', + blr_eql, + blr_field, 6, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_field, 1, 8, 'R','D','B','$','U','S','E','R', + blr_eql, + blr_sys_function, 20, 'R','D','B','$','S','Y','S','T','E','M','_','P','R','I','V','I','L','E','G','E',1, + blr_literal, blr_short, 0, 21,0, + blr_literal, blr_bool, 1, + blr_begin, + blr_end, + blr_if, + blr_neq, + blr_field, 6, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_user_name, + blr_begin, + blr_end, + blr_if, + blr_not, + blr_missing, + blr_field, 1, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_begin, + blr_for, + blr_rse, 3, + blr_relation, 19, 'R','D','B','$','R','E','L','A','T','I','O','N','_','F','I','E','L','D','S', 8, + blr_relation, 18, 'R','D','B','$','V','I','E','W','_','R','E','L','A','T','I','O','N','S', 9, + blr_relation, 13, 'R','D','B','$','R','E','L','A','T','I','O','N','S', 10, + blr_boolean, + blr_and, + blr_eql, + blr_field, 8, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 1, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 8, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 1, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_and, + blr_not, + blr_missing, + blr_field, 8, 14, 'R','D','B','$','B','A','S','E','_','F','I','E','L','D', + blr_and, + blr_eql, + blr_field, 9, 13, 'R','D','B','$','V','I','E','W','_','N','A','M','E', + blr_field, 8, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 9, 16, 'R','D','B','$','V','I','E','W','_','C','O','N','T','E','X','T', + blr_field, 8, 16, 'R','D','B','$','V','I','E','W','_','C','O','N','T','E','X','T', + blr_eql, + blr_field, 9, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 10, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_end, + blr_begin, + blr_if, + blr_and, + blr_neq, + blr_field, 10, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_field, 6, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_neq, + blr_sys_function, 20, 'R','D','B','$','S','Y','S','T','E','M','_','P','R','I','V','I','L','E','G','E',1, + blr_literal, blr_short, 0, 21,0, + blr_literal, blr_bool, 1, + blr_begin, + blr_if, + blr_not, + blr_any, + blr_rse, 1, + blr_relation, 19, 'R','D','B','$','U','S','E','R','_','P','R','I','V','I','L','E','G','E','S', 11, + blr_boolean, + blr_and, + blr_eql, + blr_field, 11, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 10, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 11, 15, 'R','D','B','$','O','B','J','E','C','T','_','T','Y','P','E', + blr_literal, blr_long, 0, 0,0,0,0, + blr_and, + blr_eql, + blr_field, 11, 13, 'R','D','B','$','P','R','I','V','I','L','E','G','E', + blr_field, 1, 13, 'R','D','B','$','P','R','I','V','I','L','E','G','E', + blr_and, + blr_eql, + blr_field, 11, 8, 'R','D','B','$','U','S','E','R', + blr_field, 6, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 11, 13, 'R','D','B','$','U','S','E','R','_','T','Y','P','E', + blr_literal, blr_long, 0, 8,0,0,0, + blr_and, + blr_neq, + blr_field, 11, 16, 'R','D','B','$','G','R','A','N','T','_','O','P','T','I','O','N', + blr_literal, blr_long, 0, 0,0,0,0, + blr_or, + blr_missing, + blr_field, 11, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_eql, + blr_field, 11, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 8, 14, 'R','D','B','$','B','A','S','E','_','F','I','E','L','D', + blr_end, + blr_leave, 5, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_begin, + blr_for, + blr_rse, 2, + blr_relation, 18, 'R','D','B','$','V','I','E','W','_','R','E','L','A','T','I','O','N','S', 12, + blr_relation, 13, 'R','D','B','$','R','E','L','A','T','I','O','N','S', 13, + blr_boolean, + blr_and, + blr_eql, + blr_field, 12, 13, 'R','D','B','$','V','I','E','W','_','N','A','M','E', + blr_field, 1, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_eql, + blr_field, 12, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 13, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_end, + blr_begin, + blr_if, + blr_and, + blr_neq, + blr_field, 13, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_field, 6, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_neq, + blr_sys_function, 20, 'R','D','B','$','S','Y','S','T','E','M','_','P','R','I','V','I','L','E','G','E',1, + blr_literal, blr_short, 0, 21,0, + blr_literal, blr_bool, 1, + blr_begin, + blr_if, + blr_not, + blr_any, + blr_rse, 1, + blr_relation, 19, 'R','D','B','$','U','S','E','R','_','P','R','I','V','I','L','E','G','E','S', 14, + blr_boolean, + blr_and, + blr_eql, + blr_field, 14, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 13, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 14, 15, 'R','D','B','$','O','B','J','E','C','T','_','T','Y','P','E', + blr_literal, blr_long, 0, 0,0,0,0, + blr_and, + blr_eql, + blr_field, 14, 13, 'R','D','B','$','P','R','I','V','I','L','E','G','E', + blr_field, 1, 13, 'R','D','B','$','P','R','I','V','I','L','E','G','E', + blr_and, + blr_eql, + blr_field, 14, 8, 'R','D','B','$','U','S','E','R', + blr_field, 6, 14, 'R','D','B','$','O','W','N','E','R','_','N','A','M','E', + blr_and, + blr_eql, + blr_field, 14, 13, 'R','D','B','$','U','S','E','R','_','T','Y','P','E', + blr_literal, blr_long, 0, 8,0,0,0, + blr_and, + blr_neq, + blr_field, 14, 16, 'R','D','B','$','G','R','A','N','T','_','O','P','T','I','O','N', + blr_literal, blr_long, 0, 0,0,0,0, + blr_missing, + blr_field, 14, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_end, + blr_leave, 5, + blr_end, + blr_end, + blr_end, + blr_end, + blr_end, + blr_if, + blr_missing, + blr_field, 6, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_modify, 6, 15, + blr_begin, + blr_assignment, + blr_cast, blr_varying2, 4,0, 252,0, + blr_concatenate, + blr_literal, blr_text2, 1,0, 4,0, 'S','Q','L','$', + blr_gen_id, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_literal, blr_long, 0, 1,0,0,0, + blr_field, 15, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_end, + + blr_if, + blr_not, + blr_starting, + blr_field, 6, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_cast, blr_varying2, 4,0, 252,0, + blr_literal, blr_text2, 1,0, 4,0, 'S','Q','L','$', + blr_leave, 3, + blr_end, + blr_end, + blr_if, + blr_not, + blr_missing, + blr_field, 1, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_for, + blr_rse, 1, + blr_relation, 19, 'R','D','B','$','R','E','L','A','T','I','O','N','_','F','I','E','L','D','S', 16, + blr_boolean, + blr_and, + blr_eql, + blr_field, 16, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_field, 1, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_eql, + blr_field, 16, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_field, 1, 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', + blr_end, + blr_begin, + blr_if, + blr_missing, + blr_field, 16, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_modify, 16, 17, + blr_begin, + blr_assignment, + blr_concatenate, + blr_literal, blr_text, 9,0, 'S','Q','L','$','G','R','A','N','T', + blr_gen_id, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_literal, blr_long, 0, 1,0,0,0, + blr_field, 17, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_end, + blr_if, + blr_not, + blr_starting, + blr_field, 16, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_literal, blr_text, 9,0, 'S','Q','L','$','G','R','A','N','T', + blr_leave, 4, + blr_end, + blr_end, + blr_end, + blr_end, + blr_if, + blr_eql, + blr_field, 1, 15, 'R','D','B','$','O','B','J','E','C','T','_','T','Y','P','E', + blr_literal, blr_long, 0, 5,0,0,0, + blr_for, + blr_rse, 1, + blr_relation, 14, 'R','D','B','$','P','R','O','C','E','D','U','R','E','S', 18, + blr_boolean, + blr_and, + blr_missing, + blr_field, 18, 16, 'R','D','B','$','P','A','C','K','A','G','E','_','N','A','M','E', + blr_eql, + blr_field, 18, 18, 'R','D','B','$','P','R','O','C','E','D','U','R','E','_','N','A','M','E', + blr_field, 1, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_end, + blr_begin, + blr_if, + blr_missing, + blr_field, 18, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_modify, 18, 20, + blr_begin, + blr_assignment, + blr_cast, blr_varying2, 4,0, 252,0, + blr_concatenate, + blr_literal, blr_text2, 1,0, 4,0, 'S','Q','L','$', + blr_gen_id, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_literal, blr_long, 0, 1,0,0,0, + blr_field, 20, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_end, + blr_if, + blr_not, + blr_starting, + blr_field, 18, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_cast, blr_varying2, 4,0, 252,0, + blr_literal, blr_text2, 1,0, 4,0, 'S','Q','L','$', + blr_leave, 3, + blr_end, + blr_end, + blr_if, + blr_eql, + blr_field, 1, 15, 'R','D','B','$','O','B','J','E','C','T','_','T','Y','P','E', + blr_literal, blr_long, 0, 15,0,0,0, + blr_for, + blr_rse, 1, + blr_relation, 13, 'R','D','B','$','F','U','N','C','T','I','O','N','S', 26, + blr_boolean, + blr_and, + blr_missing, + blr_field, 26, 16, 'R','D','B','$','P','A','C','K','A','G','E','_','N','A','M','E', + blr_eql, + blr_field, 26, 17, 'R','D','B','$','F','U','N','C','T','I','O','N','_','N','A','M','E', + blr_field, 1, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_end, + blr_begin, + blr_if, + blr_missing, + blr_field, 26, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_modify, 26, 28, + blr_begin, + blr_assignment, + blr_cast, blr_varying2, 4,0, 252,0, + blr_concatenate, + blr_literal, blr_text2, 1,0, 4,0, 'S','Q','L','$', + blr_gen_id, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_literal, blr_long, 0, 1,0,0,0, + blr_field, 28, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_end, + blr_if, + blr_not, + blr_starting, + blr_field, 26, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_cast, blr_varying2, 4,0, 252,0, + blr_literal, blr_text2, 1,0, 4,0, 'S','Q','L','$', + blr_leave, 3, + blr_end, + blr_end, + blr_if, + blr_eql, + blr_field, 1, 15, 'R','D','B','$','O','B','J','E','C','T','_','T','Y','P','E', + blr_literal, blr_long, 0, 18,0,0,0, + blr_for, + blr_rse, 1, + blr_relation, 12, 'R','D','B','$','P','A','C','K','A','G','E','S', 22, + blr_boolean, + blr_eql, + blr_field, 22, 16, 'R','D','B','$','P','A','C','K','A','G','E','_','N','A','M','E', + blr_field, 1, 17, 'R','D','B','$','R','E','L','A','T','I','O','N','_','N','A','M','E', + blr_end, + blr_begin, + blr_if, + blr_missing, + blr_field, 22, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_modify, 22, 23, + blr_begin, + blr_assignment, + blr_cast, blr_varying2, 4,0, 252,0, + blr_concatenate, + blr_literal, blr_text2, 1,0, 4,0, 'S','Q','L','$', + blr_gen_id, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_literal, blr_long, 0, 1,0,0,0, + blr_field, 23, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_end, + blr_if, + blr_not, + blr_starting, + blr_field, 22, 18, 'R','D','B','$','S','E','C','U','R','I','T','Y','_','C','L','A','S','S', + blr_cast, blr_varying2, 4,0, 252,0, + blr_literal, blr_text2, 1,0, 4,0, 'S','Q','L','$', + blr_leave, 3, + blr_end, + blr_end, + blr_end, + blr_end, + blr_eoc + + RDB$DESCRIPTION + RDB$TRIGGER_INACTIVE + RDB$SYSTEM_FLAG 1 + RDB$FLAGS 0 + RDB$VALID_BLR + RDB$DEBUG_INFO + RDB$ENGINE_NAME + RDB$ENTRYPOINT + RDB$SQL_SECURITY + + + Records affected: 29 + """ + +@pytest.mark.version('>=4.0') +def test_db_29_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/functional/basic/db/test_30.py b/tests/functional/basic/db/test_30.py new file mode 100644 index 00000000..cc26978b --- /dev/null +++ b/tests/functional/basic/db/test_30.py @@ -0,0 +1,3419 @@ +#coding:utf-8 +# +# id: functional.basic.db.db_30 +# title: Empty DB - RDB$TYPES +# decription: +# Check for correct content of RDB$TYPES in empty database. +# Checked on: +# 2.5.9.27126: OK, 0.562s. +# 3.0.5.33086: OK, 1.641s. +# 4.0.0.1378: OK, 5.047s. +# +# tracker_id: +# min_versions: ['2.5.7'] +# versions: 3.0, 4.0 +# qmid: functional.basic.db.db_30 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select '' as "DDL of table rdb$types:" from rdb$database; + show table rdb$types; + select count(*) "Number of rows in rdb$types:" from rdb$types; + select * from rdb$types; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DDL of table rdb$types: + + RDB$FIELD_NAME (RDB$FIELD_NAME) CHAR(31) CHARACTER SET UNICODE_FSS Nullable + RDB$TYPE (RDB$GENERIC_TYPE) SMALLINT Nullable + RDB$TYPE_NAME (RDB$TYPE_NAME) CHAR(31) CHARACTER SET UNICODE_FSS Nullable + RDB$DESCRIPTION (RDB$DESCRIPTION) BLOB segment 80, subtype TEXT CHARACTER SET UNICODE_FSS Nullable + RDB$SYSTEM_FLAG (RDB$SYSTEM_FLAG) SMALLINT Not Null + + Number of rows in rdb$types: 254 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 14 + RDB$TYPE_NAME TEXT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 7 + RDB$TYPE_NAME SHORT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 8 + RDB$TYPE_NAME LONG + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 9 + RDB$TYPE_NAME QUAD + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 10 + RDB$TYPE_NAME FLOAT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 27 + RDB$TYPE_NAME DOUBLE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 35 + RDB$TYPE_NAME TIMESTAMP + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 37 + RDB$TYPE_NAME VARYING + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 261 + RDB$TYPE_NAME BLOB + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 40 + RDB$TYPE_NAME CSTRING + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 45 + RDB$TYPE_NAME BLOB_ID + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 12 + RDB$TYPE_NAME DATE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 13 + RDB$TYPE_NAME TIME + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 16 + RDB$TYPE_NAME INT64 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 23 + RDB$TYPE_NAME BOOLEAN + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_SUB_TYPE + RDB$TYPE 0 + RDB$TYPE_NAME BINARY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_SUB_TYPE + RDB$TYPE 1 + RDB$TYPE_NAME TEXT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_SUB_TYPE + RDB$TYPE 2 + RDB$TYPE_NAME BLR + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_SUB_TYPE + RDB$TYPE 3 + RDB$TYPE_NAME ACL + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_SUB_TYPE + RDB$TYPE 4 + RDB$TYPE_NAME RANGES + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_SUB_TYPE + RDB$TYPE 5 + RDB$TYPE_NAME SUMMARY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_SUB_TYPE + RDB$TYPE 6 + RDB$TYPE_NAME FORMAT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_SUB_TYPE + RDB$TYPE 7 + RDB$TYPE_NAME TRANSACTION_DESCRIPTION + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_SUB_TYPE + RDB$TYPE 8 + RDB$TYPE_NAME EXTERNAL_FILE_DESCRIPTION + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_SUB_TYPE + RDB$TYPE 9 + RDB$TYPE_NAME DEBUG_INFORMATION + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FUNCTION_TYPE + RDB$TYPE 0 + RDB$TYPE_NAME VALUE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FUNCTION_TYPE + RDB$TYPE 1 + RDB$TYPE_NAME BOOLEAN + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$MECHANISM + RDB$TYPE 0 + RDB$TYPE_NAME BY_VALUE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$MECHANISM + RDB$TYPE 1 + RDB$TYPE_NAME BY_REFERENCE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$MECHANISM + RDB$TYPE 2 + RDB$TYPE_NAME BY_VMS_DESCRIPTOR + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$MECHANISM + RDB$TYPE 3 + RDB$TYPE_NAME BY_ISC_DESCRIPTOR + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$MECHANISM + RDB$TYPE 4 + RDB$TYPE_NAME BY_SCALAR_ARRAY_DESCRIPTOR + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$MECHANISM + RDB$TYPE 5 + RDB$TYPE_NAME BY_REFERENCE_WITH_NULL + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRIGGER_TYPE + RDB$TYPE 1 + RDB$TYPE_NAME PRE_STORE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRIGGER_TYPE + RDB$TYPE 2 + RDB$TYPE_NAME POST_STORE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRIGGER_TYPE + RDB$TYPE 3 + RDB$TYPE_NAME PRE_MODIFY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRIGGER_TYPE + RDB$TYPE 4 + RDB$TYPE_NAME POST_MODIFY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRIGGER_TYPE + RDB$TYPE 5 + RDB$TYPE_NAME PRE_ERASE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRIGGER_TYPE + RDB$TYPE 6 + RDB$TYPE_NAME POST_ERASE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRIGGER_TYPE + RDB$TYPE 8192 + RDB$TYPE_NAME CONNECT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRIGGER_TYPE + RDB$TYPE 8193 + RDB$TYPE_NAME DISCONNECT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRIGGER_TYPE + RDB$TYPE 8194 + RDB$TYPE_NAME TRANSACTION_START + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRIGGER_TYPE + RDB$TYPE 8195 + RDB$TYPE_NAME TRANSACTION_COMMIT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRIGGER_TYPE + RDB$TYPE 8196 + RDB$TYPE_NAME TRANSACTION_ROLLBACK + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 0 + RDB$TYPE_NAME RELATION + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 1 + RDB$TYPE_NAME VIEW + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 2 + RDB$TYPE_NAME TRIGGER + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 3 + RDB$TYPE_NAME COMPUTED_FIELD + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 4 + RDB$TYPE_NAME VALIDATION + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 5 + RDB$TYPE_NAME PROCEDURE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 6 + RDB$TYPE_NAME EXPRESSION_INDEX + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 7 + RDB$TYPE_NAME EXCEPTION + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 8 + RDB$TYPE_NAME USER + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 9 + RDB$TYPE_NAME FIELD + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 10 + RDB$TYPE_NAME INDEX + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 11 + RDB$TYPE_NAME CHARACTER_SET + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 12 + RDB$TYPE_NAME USER_GROUP + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 13 + RDB$TYPE_NAME ROLE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 14 + RDB$TYPE_NAME GENERATOR + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 15 + RDB$TYPE_NAME UDF + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 16 + RDB$TYPE_NAME BLOB_FILTER + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 17 + RDB$TYPE_NAME COLLATION + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 18 + RDB$TYPE_NAME PACKAGE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 19 + RDB$TYPE_NAME PACKAGE BODY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRANSACTION_STATE + RDB$TYPE 1 + RDB$TYPE_NAME LIMBO + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRANSACTION_STATE + RDB$TYPE 2 + RDB$TYPE_NAME COMMITTED + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRANSACTION_STATE + RDB$TYPE 3 + RDB$TYPE_NAME ROLLED_BACK + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$TYPE 0 + RDB$TYPE_NAME USER + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$TYPE 1 + RDB$TYPE_NAME SYSTEM + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$TYPE 2 + RDB$TYPE_NAME QLI + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$TYPE 3 + RDB$TYPE_NAME CHECK_CONSTRAINT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$TYPE 4 + RDB$TYPE_NAME REFERENTIAL_CONSTRAINT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$TYPE 5 + RDB$TYPE_NAME VIEW_CHECK + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$TYPE 6 + RDB$TYPE_NAME IDENTITY_GENERATOR + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$RELATION_TYPE + RDB$TYPE 0 + RDB$TYPE_NAME PERSISTENT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$RELATION_TYPE + RDB$TYPE 1 + RDB$TYPE_NAME VIEW + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$RELATION_TYPE + RDB$TYPE 2 + RDB$TYPE_NAME EXTERNAL + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$RELATION_TYPE + RDB$TYPE 3 + RDB$TYPE_NAME VIRTUAL + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$RELATION_TYPE + RDB$TYPE 4 + RDB$TYPE_NAME GLOBAL_TEMPORARY_PRESERVE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$RELATION_TYPE + RDB$TYPE 5 + RDB$TYPE_NAME GLOBAL_TEMPORARY_DELETE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PROCEDURE_TYPE + RDB$TYPE 0 + RDB$TYPE_NAME LEGACY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PROCEDURE_TYPE + RDB$TYPE 1 + RDB$TYPE_NAME SELECTABLE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PROCEDURE_TYPE + RDB$TYPE 2 + RDB$TYPE_NAME EXECUTABLE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PARAMETER_MECHANISM + RDB$TYPE 0 + RDB$TYPE_NAME NORMAL + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PARAMETER_MECHANISM + RDB$TYPE 1 + RDB$TYPE_NAME TYPE OF + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$STATE + RDB$TYPE 0 + RDB$TYPE_NAME IDLE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$STATE + RDB$TYPE 1 + RDB$TYPE_NAME ACTIVE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$STATE + RDB$TYPE 2 + RDB$TYPE_NAME STALLED + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$SHUTDOWN_MODE + RDB$TYPE 0 + RDB$TYPE_NAME ONLINE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$SHUTDOWN_MODE + RDB$TYPE 1 + RDB$TYPE_NAME MULTI_USER_SHUTDOWN + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$SHUTDOWN_MODE + RDB$TYPE 2 + RDB$TYPE_NAME SINGLE_USER_SHUTDOWN + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$SHUTDOWN_MODE + RDB$TYPE 3 + RDB$TYPE_NAME FULL_SHUTDOWN + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$ISOLATION_MODE + RDB$TYPE 0 + RDB$TYPE_NAME CONSISTENCY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$ISOLATION_MODE + RDB$TYPE 1 + RDB$TYPE_NAME CONCURRENCY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$ISOLATION_MODE + RDB$TYPE 2 + RDB$TYPE_NAME READ_COMMITTED_VERSION + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$ISOLATION_MODE + RDB$TYPE 3 + RDB$TYPE_NAME READ_COMMITTED_NO_VERSION + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$BACKUP_STATE + RDB$TYPE 0 + RDB$TYPE_NAME NORMAL + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$BACKUP_STATE + RDB$TYPE 1 + RDB$TYPE_NAME STALLED + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$BACKUP_STATE + RDB$TYPE 2 + RDB$TYPE_NAME MERGE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$STAT_GROUP + RDB$TYPE 0 + RDB$TYPE_NAME DATABASE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$STAT_GROUP + RDB$TYPE 1 + RDB$TYPE_NAME ATTACHMENT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$STAT_GROUP + RDB$TYPE 2 + RDB$TYPE_NAME TRANSACTION + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$STAT_GROUP + RDB$TYPE 3 + RDB$TYPE_NAME STATEMENT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$STAT_GROUP + RDB$TYPE 4 + RDB$TYPE_NAME CALL + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$IDENTITY_TYPE + RDB$TYPE 0 + RDB$TYPE_NAME ALWAYS + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$IDENTITY_TYPE + RDB$TYPE 1 + RDB$TYPE_NAME BY DEFAULT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PARAMETER_TYPE + RDB$TYPE 0 + RDB$TYPE_NAME INPUT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PARAMETER_TYPE + RDB$TYPE 1 + RDB$TYPE_NAME OUTPUT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRIGGER_INACTIVE + RDB$TYPE 0 + RDB$TYPE_NAME ACTIVE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRIGGER_INACTIVE + RDB$TYPE 1 + RDB$TYPE_NAME INACTIVE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$INDEX_INACTIVE + RDB$TYPE 0 + RDB$TYPE_NAME ACTIVE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$INDEX_INACTIVE + RDB$TYPE 1 + RDB$TYPE_NAME INACTIVE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$UNIQUE_FLAG + RDB$TYPE 0 + RDB$TYPE_NAME NON_UNIQUE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$UNIQUE_FLAG + RDB$TYPE 1 + RDB$TYPE_NAME UNIQUE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$GRANT_OPTION + RDB$TYPE 0 + RDB$TYPE_NAME NONE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$GRANT_OPTION + RDB$TYPE 1 + RDB$TYPE_NAME GRANT_OPTION + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$GRANT_OPTION + RDB$TYPE 2 + RDB$TYPE_NAME ADMIN_OPTION + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PAGE_TYPE + RDB$TYPE 1 + RDB$TYPE_NAME HEADER + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PAGE_TYPE + RDB$TYPE 2 + RDB$TYPE_NAME PAGE_INVENTORY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PAGE_TYPE + RDB$TYPE 3 + RDB$TYPE_NAME TRANSACTION_INVENTORY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PAGE_TYPE + RDB$TYPE 4 + RDB$TYPE_NAME POINTER + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PAGE_TYPE + RDB$TYPE 5 + RDB$TYPE_NAME DATA + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PAGE_TYPE + RDB$TYPE 6 + RDB$TYPE_NAME INDEX_ROOT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PAGE_TYPE + RDB$TYPE 7 + RDB$TYPE_NAME INDEX_BUCKET + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PAGE_TYPE + RDB$TYPE 8 + RDB$TYPE_NAME BLOB + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PAGE_TYPE + RDB$TYPE 9 + RDB$TYPE_NAME GENERATOR + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PAGE_TYPE + RDB$TYPE 10 + RDB$TYPE_NAME SCN_INVENTORY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PRIVATE_FLAG + RDB$TYPE 0 + RDB$TYPE_NAME PUBLIC + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PRIVATE_FLAG + RDB$TYPE 1 + RDB$TYPE_NAME PRIVATE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$LEGACY_FLAG + RDB$TYPE 0 + RDB$TYPE_NAME NEW_STYLE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$LEGACY_FLAG + RDB$TYPE 1 + RDB$TYPE_NAME LEGACY_STYLE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$DETERMINISTIC_FLAG + RDB$TYPE 0 + RDB$TYPE_NAME NON_DETERMINISTIC + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$DETERMINISTIC_FLAG + RDB$TYPE 1 + RDB$TYPE_NAME DETERMINISTIC + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$MAP_TO_TYPE + RDB$TYPE 0 + RDB$TYPE_NAME USER + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$MAP_TO_TYPE + RDB$TYPE 1 + RDB$TYPE_NAME ROLE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 0 + RDB$TYPE_NAME NONE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 1 + RDB$TYPE_NAME OCTETS + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 2 + RDB$TYPE_NAME ASCII + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 3 + RDB$TYPE_NAME UNICODE_FSS + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 4 + RDB$TYPE_NAME UTF8 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 5 + RDB$TYPE_NAME SJIS_0208 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 6 + RDB$TYPE_NAME EUCJ_0208 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 10 + RDB$TYPE_NAME DOS437 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 11 + RDB$TYPE_NAME DOS850 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 12 + RDB$TYPE_NAME DOS865 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 21 + RDB$TYPE_NAME ISO8859_1 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 22 + RDB$TYPE_NAME ISO8859_2 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 23 + RDB$TYPE_NAME ISO8859_3 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 34 + RDB$TYPE_NAME ISO8859_4 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 35 + RDB$TYPE_NAME ISO8859_5 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 36 + RDB$TYPE_NAME ISO8859_6 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 37 + RDB$TYPE_NAME ISO8859_7 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 38 + RDB$TYPE_NAME ISO8859_8 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 39 + RDB$TYPE_NAME ISO8859_9 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 40 + RDB$TYPE_NAME ISO8859_13 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 45 + RDB$TYPE_NAME DOS852 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 46 + RDB$TYPE_NAME DOS857 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 13 + RDB$TYPE_NAME DOS860 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 47 + RDB$TYPE_NAME DOS861 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 14 + RDB$TYPE_NAME DOS863 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 50 + RDB$TYPE_NAME CYRL + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 9 + RDB$TYPE_NAME DOS737 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 15 + RDB$TYPE_NAME DOS775 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 16 + RDB$TYPE_NAME DOS858 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 17 + RDB$TYPE_NAME DOS862 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 18 + RDB$TYPE_NAME DOS864 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 48 + RDB$TYPE_NAME DOS866 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 49 + RDB$TYPE_NAME DOS869 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 51 + RDB$TYPE_NAME WIN1250 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 52 + RDB$TYPE_NAME WIN1251 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 53 + RDB$TYPE_NAME WIN1252 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 54 + RDB$TYPE_NAME WIN1253 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 55 + RDB$TYPE_NAME WIN1254 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 19 + RDB$TYPE_NAME NEXT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 58 + RDB$TYPE_NAME WIN1255 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 59 + RDB$TYPE_NAME WIN1256 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 60 + RDB$TYPE_NAME WIN1257 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 44 + RDB$TYPE_NAME KSC_5601 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 56 + RDB$TYPE_NAME BIG_5 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 57 + RDB$TYPE_NAME GB_2312 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 63 + RDB$TYPE_NAME KOI8R + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 64 + RDB$TYPE_NAME KOI8U + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 65 + RDB$TYPE_NAME WIN1258 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 66 + RDB$TYPE_NAME TIS620 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 67 + RDB$TYPE_NAME GBK + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 68 + RDB$TYPE_NAME CP943C + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 69 + RDB$TYPE_NAME GB18030 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 1 + RDB$TYPE_NAME BINARY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 2 + RDB$TYPE_NAME USASCII + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 2 + RDB$TYPE_NAME ASCII7 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 3 + RDB$TYPE_NAME UTF_FSS + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 3 + RDB$TYPE_NAME SQL_TEXT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 4 + RDB$TYPE_NAME UTF-8 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 5 + RDB$TYPE_NAME SJIS + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 6 + RDB$TYPE_NAME EUCJ + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 10 + RDB$TYPE_NAME DOS_437 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 11 + RDB$TYPE_NAME DOS_850 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 12 + RDB$TYPE_NAME DOS_865 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 21 + RDB$TYPE_NAME ISO88591 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 21 + RDB$TYPE_NAME LATIN1 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 21 + RDB$TYPE_NAME ANSI + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 22 + RDB$TYPE_NAME ISO88592 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 22 + RDB$TYPE_NAME LATIN2 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 22 + RDB$TYPE_NAME ISO-8859-2 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 23 + RDB$TYPE_NAME ISO88593 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 23 + RDB$TYPE_NAME LATIN3 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 23 + RDB$TYPE_NAME ISO-8859-3 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 34 + RDB$TYPE_NAME ISO88594 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 34 + RDB$TYPE_NAME LATIN4 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 34 + RDB$TYPE_NAME ISO-8859-4 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 35 + RDB$TYPE_NAME ISO88595 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 35 + RDB$TYPE_NAME ISO-8859-5 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 36 + RDB$TYPE_NAME ISO88596 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 36 + RDB$TYPE_NAME ISO-8859-6 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 37 + RDB$TYPE_NAME ISO88597 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 37 + RDB$TYPE_NAME ISO-8859-7 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 38 + RDB$TYPE_NAME ISO88598 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 38 + RDB$TYPE_NAME ISO-8859-8 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 39 + RDB$TYPE_NAME ISO88599 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 39 + RDB$TYPE_NAME LATIN5 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 39 + RDB$TYPE_NAME ISO-8859-9 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 40 + RDB$TYPE_NAME ISO885913 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 40 + RDB$TYPE_NAME LATIN7 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 40 + RDB$TYPE_NAME ISO-8859-13 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 45 + RDB$TYPE_NAME DOS_852 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 46 + RDB$TYPE_NAME DOS_857 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 13 + RDB$TYPE_NAME DOS_860 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 47 + RDB$TYPE_NAME DOS_861 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 14 + RDB$TYPE_NAME DOS_863 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 9 + RDB$TYPE_NAME DOS_737 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 15 + RDB$TYPE_NAME DOS_775 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 16 + RDB$TYPE_NAME DOS_858 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 17 + RDB$TYPE_NAME DOS_862 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 18 + RDB$TYPE_NAME DOS_864 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 48 + RDB$TYPE_NAME DOS_866 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 49 + RDB$TYPE_NAME DOS_869 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 51 + RDB$TYPE_NAME WIN_1250 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 52 + RDB$TYPE_NAME WIN_1251 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 53 + RDB$TYPE_NAME WIN_1252 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 54 + RDB$TYPE_NAME WIN_1253 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 55 + RDB$TYPE_NAME WIN_1254 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 58 + RDB$TYPE_NAME WIN_1255 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 59 + RDB$TYPE_NAME WIN_1256 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 60 + RDB$TYPE_NAME WIN_1257 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 65 + RDB$TYPE_NAME WIN_1258 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 44 + RDB$TYPE_NAME KSC5601 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 44 + RDB$TYPE_NAME DOS_949 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 44 + RDB$TYPE_NAME WIN_949 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 56 + RDB$TYPE_NAME BIG5 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 56 + RDB$TYPE_NAME DOS_950 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 56 + RDB$TYPE_NAME WIN_950 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 57 + RDB$TYPE_NAME GB2312 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 57 + RDB$TYPE_NAME DOS_936 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 57 + RDB$TYPE_NAME WIN_936 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_db_30_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set list on; + + -- Query for check whether fields list of table was changed: + select rf.rdb$field_name + from rdb$relation_fields rf + where rf.rdb$relation_name = upper('rdb$relations') + order by rf.rdb$field_name; + + set count on; + set blob all; + select * from rdb$types order by rdb$field_name, rdb$type_name; + select iif(count(distinct rdb$field_name || rdb$type_name) = count(*), 1, 0) as "Are ordered columns unique ?" from rdb$types; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + + RDB$FIELD_NAME RDB$DBKEY_LENGTH + + RDB$FIELD_NAME RDB$DEFAULT_CLASS + + RDB$FIELD_NAME RDB$DESCRIPTION + + RDB$FIELD_NAME RDB$EXTERNAL_DESCRIPTION + + RDB$FIELD_NAME RDB$EXTERNAL_FILE + + RDB$FIELD_NAME RDB$FIELD_ID + + RDB$FIELD_NAME RDB$FLAGS + + RDB$FIELD_NAME RDB$FORMAT + + RDB$FIELD_NAME RDB$OWNER_NAME + + RDB$FIELD_NAME RDB$RELATION_ID + + RDB$FIELD_NAME RDB$RELATION_NAME + + RDB$FIELD_NAME RDB$RELATION_TYPE + + RDB$FIELD_NAME RDB$RUNTIME + + RDB$FIELD_NAME RDB$SECURITY_CLASS + + RDB$FIELD_NAME RDB$SQL_SECURITY + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + + RDB$FIELD_NAME RDB$VIEW_BLR + + RDB$FIELD_NAME RDB$VIEW_SOURCE + + + + RDB$FIELD_NAME MON$BACKUP_STATE + RDB$TYPE 2 + RDB$TYPE_NAME MERGE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$BACKUP_STATE + RDB$TYPE 0 + RDB$TYPE_NAME NORMAL + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$BACKUP_STATE + RDB$TYPE 1 + RDB$TYPE_NAME STALLED + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$CRYPT_STATE + RDB$TYPE 2 + RDB$TYPE_NAME DECRYPT IN PROGRESS + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$CRYPT_STATE + RDB$TYPE 3 + RDB$TYPE_NAME ENCRYPT IN PROGRESS + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$CRYPT_STATE + RDB$TYPE 1 + RDB$TYPE_NAME ENCRYPTED + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$CRYPT_STATE + RDB$TYPE 0 + RDB$TYPE_NAME NOT ENCRYPTED + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$ISOLATION_MODE + RDB$TYPE 1 + RDB$TYPE_NAME CONCURRENCY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$ISOLATION_MODE + RDB$TYPE 0 + RDB$TYPE_NAME CONSISTENCY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$ISOLATION_MODE + RDB$TYPE 3 + RDB$TYPE_NAME READ_COMMITTED_NO_VERSION + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$ISOLATION_MODE + RDB$TYPE 4 + RDB$TYPE_NAME READ_COMMITTED_READ_CONSISTENCY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$ISOLATION_MODE + RDB$TYPE 2 + RDB$TYPE_NAME READ_COMMITTED_VERSION + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$REPLICA_MODE + RDB$TYPE 0 + RDB$TYPE_NAME NONE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$REPLICA_MODE + RDB$TYPE 1 + RDB$TYPE_NAME READ-ONLY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$REPLICA_MODE + RDB$TYPE 2 + RDB$TYPE_NAME READ-WRITE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$SHUTDOWN_MODE + RDB$TYPE 3 + RDB$TYPE_NAME FULL_SHUTDOWN + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$SHUTDOWN_MODE + RDB$TYPE 1 + RDB$TYPE_NAME MULTI_USER_SHUTDOWN + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$SHUTDOWN_MODE + RDB$TYPE 0 + RDB$TYPE_NAME ONLINE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$SHUTDOWN_MODE + RDB$TYPE 2 + RDB$TYPE_NAME SINGLE_USER_SHUTDOWN + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$STATE + RDB$TYPE 1 + RDB$TYPE_NAME ACTIVE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$STATE + RDB$TYPE 0 + RDB$TYPE_NAME IDLE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$STATE + RDB$TYPE 2 + RDB$TYPE_NAME STALLED + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$STAT_GROUP + RDB$TYPE 1 + RDB$TYPE_NAME ATTACHMENT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$STAT_GROUP + RDB$TYPE 4 + RDB$TYPE_NAME CALL + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$STAT_GROUP + RDB$TYPE 0 + RDB$TYPE_NAME DATABASE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$STAT_GROUP + RDB$TYPE 3 + RDB$TYPE_NAME STATEMENT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME MON$STAT_GROUP + RDB$TYPE 2 + RDB$TYPE_NAME TRANSACTION + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 21 + RDB$TYPE_NAME ANSI + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 2 + RDB$TYPE_NAME ASCII + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 2 + RDB$TYPE_NAME ASCII7 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 56 + RDB$TYPE_NAME BIG5 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 56 + RDB$TYPE_NAME BIG_5 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 1 + RDB$TYPE_NAME BINARY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 68 + RDB$TYPE_NAME CP943C + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 50 + RDB$TYPE_NAME CYRL + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 10 + RDB$TYPE_NAME DOS437 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 9 + RDB$TYPE_NAME DOS737 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 15 + RDB$TYPE_NAME DOS775 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 11 + RDB$TYPE_NAME DOS850 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 45 + RDB$TYPE_NAME DOS852 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 46 + RDB$TYPE_NAME DOS857 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 16 + RDB$TYPE_NAME DOS858 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 13 + RDB$TYPE_NAME DOS860 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 47 + RDB$TYPE_NAME DOS861 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 17 + RDB$TYPE_NAME DOS862 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 14 + RDB$TYPE_NAME DOS863 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 18 + RDB$TYPE_NAME DOS864 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 12 + RDB$TYPE_NAME DOS865 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 48 + RDB$TYPE_NAME DOS866 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 49 + RDB$TYPE_NAME DOS869 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 10 + RDB$TYPE_NAME DOS_437 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 9 + RDB$TYPE_NAME DOS_737 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 15 + RDB$TYPE_NAME DOS_775 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 11 + RDB$TYPE_NAME DOS_850 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 45 + RDB$TYPE_NAME DOS_852 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 46 + RDB$TYPE_NAME DOS_857 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 16 + RDB$TYPE_NAME DOS_858 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 13 + RDB$TYPE_NAME DOS_860 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 47 + RDB$TYPE_NAME DOS_861 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 17 + RDB$TYPE_NAME DOS_862 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 14 + RDB$TYPE_NAME DOS_863 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 18 + RDB$TYPE_NAME DOS_864 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 12 + RDB$TYPE_NAME DOS_865 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 48 + RDB$TYPE_NAME DOS_866 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 49 + RDB$TYPE_NAME DOS_869 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 57 + RDB$TYPE_NAME DOS_936 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 44 + RDB$TYPE_NAME DOS_949 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 56 + RDB$TYPE_NAME DOS_950 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 6 + RDB$TYPE_NAME EUCJ + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 6 + RDB$TYPE_NAME EUCJ_0208 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 69 + RDB$TYPE_NAME GB18030 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 57 + RDB$TYPE_NAME GB2312 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 67 + RDB$TYPE_NAME GBK + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 57 + RDB$TYPE_NAME GB_2312 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 40 + RDB$TYPE_NAME ISO-8859-13 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 22 + RDB$TYPE_NAME ISO-8859-2 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 23 + RDB$TYPE_NAME ISO-8859-3 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 34 + RDB$TYPE_NAME ISO-8859-4 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 35 + RDB$TYPE_NAME ISO-8859-5 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 36 + RDB$TYPE_NAME ISO-8859-6 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 37 + RDB$TYPE_NAME ISO-8859-7 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 38 + RDB$TYPE_NAME ISO-8859-8 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 39 + RDB$TYPE_NAME ISO-8859-9 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 21 + RDB$TYPE_NAME ISO88591 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 40 + RDB$TYPE_NAME ISO885913 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 22 + RDB$TYPE_NAME ISO88592 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 23 + RDB$TYPE_NAME ISO88593 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 34 + RDB$TYPE_NAME ISO88594 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 35 + RDB$TYPE_NAME ISO88595 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 36 + RDB$TYPE_NAME ISO88596 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 37 + RDB$TYPE_NAME ISO88597 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 38 + RDB$TYPE_NAME ISO88598 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 39 + RDB$TYPE_NAME ISO88599 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 21 + RDB$TYPE_NAME ISO8859_1 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 40 + RDB$TYPE_NAME ISO8859_13 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 22 + RDB$TYPE_NAME ISO8859_2 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 23 + RDB$TYPE_NAME ISO8859_3 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 34 + RDB$TYPE_NAME ISO8859_4 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 35 + RDB$TYPE_NAME ISO8859_5 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 36 + RDB$TYPE_NAME ISO8859_6 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 37 + RDB$TYPE_NAME ISO8859_7 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 38 + RDB$TYPE_NAME ISO8859_8 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 39 + RDB$TYPE_NAME ISO8859_9 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 63 + RDB$TYPE_NAME KOI8R + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 64 + RDB$TYPE_NAME KOI8U + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 44 + RDB$TYPE_NAME KSC5601 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 44 + RDB$TYPE_NAME KSC_5601 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 21 + RDB$TYPE_NAME LATIN1 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 22 + RDB$TYPE_NAME LATIN2 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 23 + RDB$TYPE_NAME LATIN3 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 34 + RDB$TYPE_NAME LATIN4 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 39 + RDB$TYPE_NAME LATIN5 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 40 + RDB$TYPE_NAME LATIN7 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 19 + RDB$TYPE_NAME NEXT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 0 + RDB$TYPE_NAME NONE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 1 + RDB$TYPE_NAME OCTETS + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 5 + RDB$TYPE_NAME SJIS + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 5 + RDB$TYPE_NAME SJIS_0208 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 3 + RDB$TYPE_NAME SQL_TEXT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 66 + RDB$TYPE_NAME TIS620 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 3 + RDB$TYPE_NAME UNICODE_FSS + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 2 + RDB$TYPE_NAME USASCII + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 4 + RDB$TYPE_NAME UTF-8 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 4 + RDB$TYPE_NAME UTF8 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 3 + RDB$TYPE_NAME UTF_FSS + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 51 + RDB$TYPE_NAME WIN1250 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 52 + RDB$TYPE_NAME WIN1251 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 53 + RDB$TYPE_NAME WIN1252 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 54 + RDB$TYPE_NAME WIN1253 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 55 + RDB$TYPE_NAME WIN1254 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 58 + RDB$TYPE_NAME WIN1255 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 59 + RDB$TYPE_NAME WIN1256 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 60 + RDB$TYPE_NAME WIN1257 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 65 + RDB$TYPE_NAME WIN1258 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 51 + RDB$TYPE_NAME WIN_1250 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 52 + RDB$TYPE_NAME WIN_1251 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 53 + RDB$TYPE_NAME WIN_1252 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 54 + RDB$TYPE_NAME WIN_1253 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 55 + RDB$TYPE_NAME WIN_1254 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 58 + RDB$TYPE_NAME WIN_1255 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 59 + RDB$TYPE_NAME WIN_1256 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 60 + RDB$TYPE_NAME WIN_1257 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 65 + RDB$TYPE_NAME WIN_1258 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 57 + RDB$TYPE_NAME WIN_936 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 44 + RDB$TYPE_NAME WIN_949 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$CHARACTER_SET_NAME + RDB$TYPE 56 + RDB$TYPE_NAME WIN_950 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$DETERMINISTIC_FLAG + RDB$TYPE 1 + RDB$TYPE_NAME DETERMINISTIC + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$DETERMINISTIC_FLAG + RDB$TYPE 0 + RDB$TYPE_NAME NON_DETERMINISTIC + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_SUB_TYPE + RDB$TYPE 3 + RDB$TYPE_NAME ACL + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_SUB_TYPE + RDB$TYPE 0 + RDB$TYPE_NAME BINARY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_SUB_TYPE + RDB$TYPE 2 + RDB$TYPE_NAME BLR + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_SUB_TYPE + RDB$TYPE 9 + RDB$TYPE_NAME DEBUG_INFORMATION + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_SUB_TYPE + RDB$TYPE 8 + RDB$TYPE_NAME EXTERNAL_FILE_DESCRIPTION + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_SUB_TYPE + RDB$TYPE 6 + RDB$TYPE_NAME FORMAT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_SUB_TYPE + RDB$TYPE 4 + RDB$TYPE_NAME RANGES + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_SUB_TYPE + RDB$TYPE 5 + RDB$TYPE_NAME SUMMARY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_SUB_TYPE + RDB$TYPE 1 + RDB$TYPE_NAME TEXT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_SUB_TYPE + RDB$TYPE 7 + RDB$TYPE_NAME TRANSACTION_DESCRIPTION + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 261 + RDB$TYPE_NAME BLOB + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 45 + RDB$TYPE_NAME BLOB_ID + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 23 + RDB$TYPE_NAME BOOLEAN + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 40 + RDB$TYPE_NAME CSTRING + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 12 + RDB$TYPE_NAME DATE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 24 + RDB$TYPE_NAME DECFLOAT(16) + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 25 + RDB$TYPE_NAME DECFLOAT(34) + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 27 + RDB$TYPE_NAME DOUBLE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 10 + RDB$TYPE_NAME FLOAT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 26 + RDB$TYPE_NAME INT128 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 16 + RDB$TYPE_NAME INT64 + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 8 + RDB$TYPE_NAME LONG + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 9 + RDB$TYPE_NAME QUAD + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 7 + RDB$TYPE_NAME SHORT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 14 + RDB$TYPE_NAME TEXT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 13 + RDB$TYPE_NAME TIME + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 28 + RDB$TYPE_NAME TIME WITH TIMEZONE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 35 + RDB$TYPE_NAME TIMESTAMP + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 29 + RDB$TYPE_NAME TIMESTAMP WITH TIMEZONE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FIELD_TYPE + RDB$TYPE 37 + RDB$TYPE_NAME VARYING + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FUNCTION_TYPE + RDB$TYPE 1 + RDB$TYPE_NAME BOOLEAN + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$FUNCTION_TYPE + RDB$TYPE 0 + RDB$TYPE_NAME VALUE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$GRANT_OPTION + RDB$TYPE 2 + RDB$TYPE_NAME ADMIN_OPTION + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$GRANT_OPTION + RDB$TYPE 1 + RDB$TYPE_NAME GRANT_OPTION + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$GRANT_OPTION + RDB$TYPE 0 + RDB$TYPE_NAME NONE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$IDENTITY_TYPE + RDB$TYPE 0 + RDB$TYPE_NAME ALWAYS + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$IDENTITY_TYPE + RDB$TYPE 1 + RDB$TYPE_NAME BY DEFAULT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$INDEX_INACTIVE + RDB$TYPE 0 + RDB$TYPE_NAME ACTIVE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$INDEX_INACTIVE + RDB$TYPE 1 + RDB$TYPE_NAME INACTIVE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$LEGACY_FLAG + RDB$TYPE 1 + RDB$TYPE_NAME LEGACY_STYLE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$LEGACY_FLAG + RDB$TYPE 0 + RDB$TYPE_NAME NEW_STYLE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$MAP_TO_TYPE + RDB$TYPE 1 + RDB$TYPE_NAME ROLE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$MAP_TO_TYPE + RDB$TYPE 0 + RDB$TYPE_NAME USER + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$MECHANISM + RDB$TYPE 3 + RDB$TYPE_NAME BY_ISC_DESCRIPTOR + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$MECHANISM + RDB$TYPE 1 + RDB$TYPE_NAME BY_REFERENCE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$MECHANISM + RDB$TYPE 5 + RDB$TYPE_NAME BY_REFERENCE_WITH_NULL + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$MECHANISM + RDB$TYPE 4 + RDB$TYPE_NAME BY_SCALAR_ARRAY_DESCRIPTOR + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$MECHANISM + RDB$TYPE 0 + RDB$TYPE_NAME BY_VALUE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$MECHANISM + RDB$TYPE 2 + RDB$TYPE_NAME BY_VMS_DESCRIPTOR + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 16 + RDB$TYPE_NAME BLOB_FILTER + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 11 + RDB$TYPE_NAME CHARACTER_SET + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 17 + RDB$TYPE_NAME COLLATION + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 3 + RDB$TYPE_NAME COMPUTED_FIELD + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 7 + RDB$TYPE_NAME EXCEPTION + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 6 + RDB$TYPE_NAME EXPRESSION_INDEX + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 9 + RDB$TYPE_NAME FIELD + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 14 + RDB$TYPE_NAME GENERATOR + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 10 + RDB$TYPE_NAME INDEX + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 18 + RDB$TYPE_NAME PACKAGE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 19 + RDB$TYPE_NAME PACKAGE BODY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 5 + RDB$TYPE_NAME PROCEDURE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 0 + RDB$TYPE_NAME RELATION + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 13 + RDB$TYPE_NAME ROLE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 2 + RDB$TYPE_NAME TRIGGER + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 15 + RDB$TYPE_NAME UDF + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 8 + RDB$TYPE_NAME USER + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 12 + RDB$TYPE_NAME USER_GROUP + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 4 + RDB$TYPE_NAME VALIDATION + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$OBJECT_TYPE + RDB$TYPE 1 + RDB$TYPE_NAME VIEW + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PAGE_TYPE + RDB$TYPE 8 + RDB$TYPE_NAME BLOB + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PAGE_TYPE + RDB$TYPE 5 + RDB$TYPE_NAME DATA + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PAGE_TYPE + RDB$TYPE 9 + RDB$TYPE_NAME GENERATOR + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PAGE_TYPE + RDB$TYPE 1 + RDB$TYPE_NAME HEADER + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PAGE_TYPE + RDB$TYPE 7 + RDB$TYPE_NAME INDEX_BUCKET + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PAGE_TYPE + RDB$TYPE 6 + RDB$TYPE_NAME INDEX_ROOT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PAGE_TYPE + RDB$TYPE 2 + RDB$TYPE_NAME PAGE_INVENTORY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PAGE_TYPE + RDB$TYPE 4 + RDB$TYPE_NAME POINTER + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PAGE_TYPE + RDB$TYPE 10 + RDB$TYPE_NAME SCN_INVENTORY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PAGE_TYPE + RDB$TYPE 3 + RDB$TYPE_NAME TRANSACTION_INVENTORY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PARAMETER_MECHANISM + RDB$TYPE 0 + RDB$TYPE_NAME NORMAL + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PARAMETER_MECHANISM + RDB$TYPE 1 + RDB$TYPE_NAME TYPE OF + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PARAMETER_TYPE + RDB$TYPE 0 + RDB$TYPE_NAME INPUT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PARAMETER_TYPE + RDB$TYPE 1 + RDB$TYPE_NAME OUTPUT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PRIVATE_FLAG + RDB$TYPE 1 + RDB$TYPE_NAME PRIVATE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PRIVATE_FLAG + RDB$TYPE 0 + RDB$TYPE_NAME PUBLIC + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PROCEDURE_TYPE + RDB$TYPE 2 + RDB$TYPE_NAME EXECUTABLE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PROCEDURE_TYPE + RDB$TYPE 0 + RDB$TYPE_NAME LEGACY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$PROCEDURE_TYPE + RDB$TYPE 1 + RDB$TYPE_NAME SELECTABLE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$RELATION_TYPE + RDB$TYPE 2 + RDB$TYPE_NAME EXTERNAL + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$RELATION_TYPE + RDB$TYPE 5 + RDB$TYPE_NAME GLOBAL_TEMPORARY_DELETE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$RELATION_TYPE + RDB$TYPE 4 + RDB$TYPE_NAME GLOBAL_TEMPORARY_PRESERVE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$RELATION_TYPE + RDB$TYPE 0 + RDB$TYPE_NAME PERSISTENT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$RELATION_TYPE + RDB$TYPE 1 + RDB$TYPE_NAME VIEW + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$RELATION_TYPE + RDB$TYPE 3 + RDB$TYPE_NAME VIRTUAL + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$TYPE 3 + RDB$TYPE_NAME CHECK_CONSTRAINT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$TYPE 6 + RDB$TYPE_NAME IDENTITY_GENERATOR + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$TYPE 2 + RDB$TYPE_NAME QLI + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$TYPE 4 + RDB$TYPE_NAME REFERENTIAL_CONSTRAINT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$TYPE 1 + RDB$TYPE_NAME SYSTEM + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$TYPE 0 + RDB$TYPE_NAME USER + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_FLAG + RDB$TYPE 5 + RDB$TYPE_NAME VIEW_CHECK + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_PRIVILEGES + RDB$TYPE 17 + RDB$TYPE_NAME ACCESS_ANY_OBJECT_IN_DATABASE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_PRIVILEGES + RDB$TYPE 8 + RDB$TYPE_NAME ACCESS_SHUTDOWN_DATABASE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_PRIVILEGES + RDB$TYPE 15 + RDB$TYPE_NAME CHANGE_HEADER_SETTINGS + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_PRIVILEGES + RDB$TYPE 19 + RDB$TYPE_NAME CHANGE_MAPPING_RULES + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_PRIVILEGES + RDB$TYPE 5 + RDB$TYPE_NAME CHANGE_SHUTDOWN_MODE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_PRIVILEGES + RDB$TYPE 9 + RDB$TYPE_NAME CREATE_DATABASE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_PRIVILEGES + RDB$TYPE 23 + RDB$TYPE_NAME CREATE_PRIVILEGED_ROLES + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_PRIVILEGES + RDB$TYPE 3 + RDB$TYPE_NAME CREATE_USER_TYPES + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_PRIVILEGES + RDB$TYPE 10 + RDB$TYPE_NAME DROP_DATABASE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_PRIVILEGES + RDB$TYPE 24 + RDB$TYPE_NAME GET_DBCRYPT_INFO + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_PRIVILEGES + RDB$TYPE 22 + RDB$TYPE_NAME GRANT_REVOKE_ANY_DDL_RIGHT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_PRIVILEGES + RDB$TYPE 21 + RDB$TYPE_NAME GRANT_REVOKE_ON_ANY_OBJECT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_PRIVILEGES + RDB$TYPE 14 + RDB$TYPE_NAME IGNORE_DB_TRIGGERS + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_PRIVILEGES + RDB$TYPE 18 + RDB$TYPE_NAME MODIFY_ANY_OBJECT_IN_DATABASE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_PRIVILEGES + RDB$TYPE 25 + RDB$TYPE_NAME MODIFY_EXT_CONN_POOL + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_PRIVILEGES + RDB$TYPE 7 + RDB$TYPE_NAME MONITOR_ANY_ATTACHMENT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_PRIVILEGES + RDB$TYPE 2 + RDB$TYPE_NAME READ_RAW_PAGES + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_PRIVILEGES + RDB$TYPE 26 + RDB$TYPE_NAME REPLICATE_INTO_DATABASE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_PRIVILEGES + RDB$TYPE 16 + RDB$TYPE_NAME SELECT_ANY_OBJECT_IN_DATABASE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_PRIVILEGES + RDB$TYPE 6 + RDB$TYPE_NAME TRACE_ANY_ATTACHMENT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_PRIVILEGES + RDB$TYPE 1 + RDB$TYPE_NAME USER_MANAGEMENT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_PRIVILEGES + RDB$TYPE 11 + RDB$TYPE_NAME USE_GBAK_UTILITY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_PRIVILEGES + RDB$TYPE 13 + RDB$TYPE_NAME USE_GFIX_UTILITY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_PRIVILEGES + RDB$TYPE 20 + RDB$TYPE_NAME USE_GRANTED_BY_CLAUSE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_PRIVILEGES + RDB$TYPE 12 + RDB$TYPE_NAME USE_GSTAT_UTILITY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$SYSTEM_PRIVILEGES + RDB$TYPE 4 + RDB$TYPE_NAME USE_NBACKUP_UTILITY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRANSACTION_STATE + RDB$TYPE 2 + RDB$TYPE_NAME COMMITTED + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRANSACTION_STATE + RDB$TYPE 1 + RDB$TYPE_NAME LIMBO + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRANSACTION_STATE + RDB$TYPE 3 + RDB$TYPE_NAME ROLLED_BACK + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRIGGER_INACTIVE + RDB$TYPE 0 + RDB$TYPE_NAME ACTIVE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRIGGER_INACTIVE + RDB$TYPE 1 + RDB$TYPE_NAME INACTIVE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRIGGER_TYPE + RDB$TYPE 8192 + RDB$TYPE_NAME CONNECT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRIGGER_TYPE + RDB$TYPE 8193 + RDB$TYPE_NAME DISCONNECT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRIGGER_TYPE + RDB$TYPE 6 + RDB$TYPE_NAME POST_ERASE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRIGGER_TYPE + RDB$TYPE 4 + RDB$TYPE_NAME POST_MODIFY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRIGGER_TYPE + RDB$TYPE 2 + RDB$TYPE_NAME POST_STORE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRIGGER_TYPE + RDB$TYPE 5 + RDB$TYPE_NAME PRE_ERASE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRIGGER_TYPE + RDB$TYPE 3 + RDB$TYPE_NAME PRE_MODIFY + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRIGGER_TYPE + RDB$TYPE 1 + RDB$TYPE_NAME PRE_STORE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRIGGER_TYPE + RDB$TYPE 8195 + RDB$TYPE_NAME TRANSACTION_COMMIT + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRIGGER_TYPE + RDB$TYPE 8196 + RDB$TYPE_NAME TRANSACTION_ROLLBACK + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$TRIGGER_TYPE + RDB$TYPE 8194 + RDB$TYPE_NAME TRANSACTION_START + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$UNIQUE_FLAG + RDB$TYPE 0 + RDB$TYPE_NAME NON_UNIQUE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + RDB$FIELD_NAME RDB$UNIQUE_FLAG + RDB$TYPE 1 + RDB$TYPE_NAME UNIQUE + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + + + Records affected: 293 + + Are ordered columns unique ? 1 + + + Records affected: 1 + """ + +@pytest.mark.version('>=4.0') +def test_db_30_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/functional/basic/db/test_31.py b/tests/functional/basic/db/test_31.py new file mode 100644 index 00000000..788416db --- /dev/null +++ b/tests/functional/basic/db/test_31.py @@ -0,0 +1,12654 @@ +#coding:utf-8 +# +# id: functional.basic.db.db_31 +# title: Empty DB - RDB$USER_PRIVILEGES +# decription: +# Check for correct content of RDB$USER_PRIVILEGES in empty database.', +# +# tracker_id: +# min_versions: ['2.5.7'] +# versions: 3.0, 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- 30.10.2015: field rdb$grantor now contain NULLs in all records for new empty database (since build ~32134). + -- Confirmed by Alex that this is OK 30.10.2015 15:28. + set list on; + + -- Query for check whether fields list of table was changed: + select rf.rdb$field_name + from rdb$relation_fields rf + where rf.rdb$relation_name = upper('rdb$user_privileges') + order by rf.rdb$field_name; + + set count on; + + select * from rdb$user_privileges t + order by + t.rdb$user + ,coalesce(t.rdb$grantor,'[none]') + ,t.rdb$relation_name + ,t.rdb$privilege + ,t.rdb$grant_option + ,coalesce(t.rdb$field_name, '[none') + ,t.rdb$user_type + ,t.rdb$object_type + ; + + set count off; + select iif( + count(*) = + count(distinct rdb$user || coalesce(rdb$grantor,'[none]') || rdb$privilege || rdb$relation_name || rdb$privilege || rdb$grant_option || coalesce(rdb$field_name, '[none') || rdb$user_type || rdb$object_type + ) + ,1 + ,0 + ) as "Are ordered columns unique ?" from rdb$user_privileges + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + + RDB$FIELD_NAME RDB$FIELD_NAME + + RDB$FIELD_NAME RDB$GRANTOR + + RDB$FIELD_NAME RDB$GRANT_OPTION + + RDB$FIELD_NAME RDB$OBJECT_TYPE + + RDB$FIELD_NAME RDB$PRIVILEGE + + RDB$FIELD_NAME RDB$RELATION_NAME + + RDB$FIELD_NAME RDB$USER + + RDB$FIELD_NAME RDB$USER_TYPE + + + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME MON$CONTEXT_VARIABLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME MON$IO_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME MON$MEMORY_USAGE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME MON$TABLE_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$DATABASE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$FIELD_DIMENSIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$FILES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$FORMATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$GENERATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$INDEX_SEGMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$LOG_FILES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$PAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$ROLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$SECURITY_CLASSES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$TRANSACTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$TRIGGER_MESSAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$TYPES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME SEC$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME SEC$USERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME SEC$USER_ATTRIBUTES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 20 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ASCII + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ASCII + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME BIG_5 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME BIG_5 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME BS_BA + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME CP943C + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME CP943C + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME CP943C_UNICODE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME CS_CZ + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME CYRL + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME CYRL + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DA_DA + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_CSY + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_DAN865 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_DEU437 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_DEU850 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_ESP437 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_ESP850 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_FIN437 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_FRA437 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_FRA850 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_FRC850 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_FRC863 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_ITA437 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_ITA850 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_NLD437 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_NLD850 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_NOR865 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_PLK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_PTB850 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_PTG860 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_RUS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_SLO + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_SVE437 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_SVE850 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_TRK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_UK437 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_UK850 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_US437 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_US850 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DE_DE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS437 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS437 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS737 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS737 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS775 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS775 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS850 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS850 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS852 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS852 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS857 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS857 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS858 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS858 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS860 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS860 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS861 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS861 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS862 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS862 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS863 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS863 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS864 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS864 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS865 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS865 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS866 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS866 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS869 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS869 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DU_NL + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME EN_UK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME EN_US + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ES_ES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ES_ES_CI_AI + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME EUCJ_0208 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME EUCJ_0208 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME FI_FI + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME FR_CA + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME FR_CA_CI_AI + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME FR_FR + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME FR_FR_CI_AI + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME GB18030 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME GB18030 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME GB18030_UNICODE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME GBK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME GBK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME GBK_UNICODE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME GB_2312 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME GB_2312 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_1 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_1 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_13 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_13 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_2 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_2 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_3 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_3 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_4 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_4 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_5 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_5 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_6 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_6 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_7 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_7 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_8 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_8 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_9 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_9 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO_HUN + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO_PLK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME IS_IS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME IT_IT + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME KOI8R + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME KOI8R + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME KOI8R_RU + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME KOI8U + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME KOI8U + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME KOI8U_UA + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME KSC_5601 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME KSC_5601 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME KSC_DICTIONARY + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME LT_LT + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$CONTEXT_VARIABLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$CONTEXT_VARIABLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$CONTEXT_VARIABLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$CONTEXT_VARIABLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$CONTEXT_VARIABLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$IO_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$IO_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$IO_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$IO_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$IO_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$MEMORY_USAGE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$MEMORY_USAGE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$MEMORY_USAGE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$MEMORY_USAGE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$MEMORY_USAGE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$SEC_DATABASE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$TABLE_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$TABLE_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$TABLE_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$TABLE_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$TABLE_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME NEXT + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME NEXT + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME NONE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME NONE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME NO_NO + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME NXT_DEU + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME NXT_ESP + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME NXT_FRA + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME NXT_ITA + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME NXT_US + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME OCTETS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME OCTETS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PDOX_ASCII + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PDOX_CSY + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PDOX_CYRL + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PDOX_HUN + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PDOX_INTL + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PDOX_ISL + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PDOX_NORDAN4 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PDOX_PLK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PDOX_SLO + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PDOX_SWEDFIN + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PT_BR + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PT_PT + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PXW_CSY + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PXW_CYRL + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PXW_GREEK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PXW_HUN + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PXW_HUNDC + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PXW_INTL + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PXW_INTL850 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PXW_NORDAN4 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PXW_PLK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PXW_SLOV + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PXW_SPAN + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PXW_SWEDFIN + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PXW_TURK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$ACL + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$ADMIN + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 13 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$ARGUMENT_MECHANISM + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$ARGUMENT_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$ATTACHMENT_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$AUTH_METHOD + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 14 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$BACKUP_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$BACKUP_LEVEL + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$BACKUP_STATE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$BOOLEAN + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$BOUND + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CALL_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CHARACTER_SET_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CHARACTER_SET_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CLIENT_VERSION + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$COLLATION_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$COLLATION_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CONSTRAINT_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CONSTRAINT_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 14 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CONSTRAINT_TYPE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CONTEXT_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CONTEXT_VAR_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CONTEXT_VAR_VALUE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$COUNTER + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DATABASE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DATABASE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DATABASE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DATABASE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DATABASE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DBKEY_LENGTH + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DEBUG_INFO + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DEFERRABLE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DESCRIPTION + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DESCRIPTOR + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DIMENSION + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DIMENSIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$EDIT_STRING + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$ENGINE_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 14 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$EXCEPTION_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$EXCEPTION_NUMBER + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$EXTERNAL_DESCRIPTION + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$EXTERNAL_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELD_DIMENSIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELD_DIMENSIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELD_DIMENSIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELD_DIMENSIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELD_DIMENSIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELD_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELD_LENGTH + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELD_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELD_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 14 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELD_POSITION + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELD_PRECISION + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELD_SCALE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELD_SUB_TYPE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELD_TYPE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILE_FLAGS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILE_LENGTH + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILE_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILE_NAME2 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILE_PARTITIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILE_P_OFFSET + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILE_SEQUENCE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILE_START + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FORMAT + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FORMATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FORMATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FORMATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FORMATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FORMATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 14 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTION_BLR + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTION_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTION_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTION_TYPE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$GENERATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$GENERATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$GENERATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$GENERATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$GENERATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$GENERATOR_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$GENERATOR_INCREMENT + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$GENERATOR_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$GENERATOR_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 14 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$GENERATOR_VALUE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$GENERIC_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$GENERIC_TYPE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$GUID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$HOST_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$IDENTITY_TYPE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$INDEX_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$INDEX_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$INDEX_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 14 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$INDEX_SEGMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$INDEX_SEGMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$INDEX_SEGMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$INDEX_SEGMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$INDEX_SEGMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$ISOLATION_MODE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$LINGER + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$LOCK_TIMEOUT + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$LOG_FILES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$LOG_FILES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$LOG_FILES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$LOG_FILES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$LOG_FILES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$MAP_DB + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$MAP_FROM + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$MAP_FROM_TYPE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$MAP_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$MAP_TO + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$MAP_USING + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$MATCH_OPTION + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$MECHANISM + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$MESSAGE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$MESSAGE_NUMBER + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$NULL_FLAG + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$NUMBER_OF_CHARACTERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$OBJECT_TYPE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$ODS_NUMBER + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$OS_USER + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PACKAGE_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PAGE_BUFFERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PAGE_NUMBER + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PAGE_SEQUENCE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PAGE_SIZE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PAGE_TYPE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PARAMETER_MECHANISM + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PARAMETER_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PARAMETER_NUMBER + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PARAMETER_TYPE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PLAN + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PLUGIN + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PRIVILEGE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 14 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURE_BLR + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURE_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURE_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURE_TYPE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$QUERY_HEADER + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATION_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATION_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATION_TYPE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$REMOTE_ADDRESS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$REMOTE_PROTOCOL + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$REMOTE_VERSION + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$ROLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$ROLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$ROLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$ROLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$ROLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RULE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RUNTIME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SCN + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SECURITY_CLASS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SECURITY_CLASS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 14 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SECURITY_CLASSES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SECURITY_CLASSES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SECURITY_CLASSES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SECURITY_CLASSES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SECURITY_CLASSES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SEGMENT_COUNT + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SEGMENT_LENGTH + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SHADOW_NUMBER + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SHUTDOWN_MODE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SOURCE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SOURCE_INFO + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SPECIFIC_ATTRIBUTES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SQL_DIALECT + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$STATE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$STATEMENT_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$STATISTICS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$STAT_GROUP + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$STAT_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SWEEP_INTERVAL + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SYSTEM_FLAG + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SYSTEM_NULLFLAG + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TIMESTAMP + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRANSACTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRANSACTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRANSACTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRANSACTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRANSACTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRANSACTION_DESCRIPTION + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRANSACTION_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRANSACTION_STATE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGER_BLR + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGER_MESSAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGER_MESSAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGER_MESSAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGER_MESSAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGER_MESSAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGER_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGER_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 14 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGER_SEQUENCE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGER_TYPE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TYPES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TYPES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TYPES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TYPES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TYPES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TYPE_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$USER + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$VALIDATION_BLR + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$VALUE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$VIEW_BLR + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$VIEW_CONTEXT + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$KEY + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$NAME_PART + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$USERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$USERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$USERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$USERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$USERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$USER_ATTRIBUTES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$USER_ATTRIBUTES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$USER_ATTRIBUTES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$USER_ATTRIBUTES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$USER_ATTRIBUTES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$USER_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$VALUE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SJIS_0208 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SJIS_0208 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SQL$DEFAULT + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 14 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SV_SV + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME TIS620 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME TIS620 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME TIS620_UNICODE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME UCS_BASIC + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME UNICODE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME UNICODE_CI + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME UNICODE_CI_AI + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME UNICODE_FSS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME UNICODE_FSS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME UTF8 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME UTF8 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1250 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1250 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1251 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1251 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1251_UA + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1252 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1252 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1253 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1253 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1254 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1254 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1255 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1255 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1256 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1256 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1257 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1257 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1257_EE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1257_LT + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1257_LV + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1258 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1258 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN_CZ + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN_CZ_CI_AI + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN_PTBR + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + + Records affected: 664 + + Are ordered columns unique ? 1 + + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_db_31_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set list on; + + -- Query for check whether fields list of table was changed: + select rf.rdb$field_name + from rdb$relation_fields rf + where rf.rdb$relation_name = upper('rdb$user_privileges') + order by rf.rdb$field_name; + + set count on; + + select * from rdb$user_privileges t + order by + t.rdb$user + ,coalesce(t.rdb$grantor,'[none]') + ,t.rdb$relation_name + ,t.rdb$privilege + ,t.rdb$grant_option + ,coalesce(t.rdb$field_name, '[none') + ,t.rdb$user_type + ,t.rdb$object_type + ; + set count off; + select iif( + count(*) = + count(distinct rdb$user || coalesce(rdb$grantor,'[none]') || rdb$privilege || rdb$relation_name || rdb$privilege || rdb$grant_option || coalesce(rdb$field_name, '[none') || rdb$user_type || rdb$object_type + ) + ,1 + ,0 + ) as "Are ordered columns unique ?" from rdb$user_privileges + ; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + + RDB$FIELD_NAME RDB$FIELD_NAME + + RDB$FIELD_NAME RDB$GRANTOR + + RDB$FIELD_NAME RDB$GRANT_OPTION + + RDB$FIELD_NAME RDB$OBJECT_TYPE + + RDB$FIELD_NAME RDB$PRIVILEGE + + RDB$FIELD_NAME RDB$RELATION_NAME + + RDB$FIELD_NAME RDB$USER + + RDB$FIELD_NAME RDB$USER_TYPE + + + + RDB$USER 22 + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 20 + RDB$OBJECT_TYPE 0 + + RDB$USER 22 + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 20 + RDB$OBJECT_TYPE 0 + + RDB$USER 22 + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 20 + RDB$OBJECT_TYPE 0 + + RDB$USER 22 + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 20 + RDB$OBJECT_TYPE 0 + + RDB$USER 22 + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 20 + RDB$OBJECT_TYPE 0 + + RDB$USER 3 + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$TYPES + RDB$FIELD_NAME + RDB$USER_TYPE 20 + RDB$OBJECT_TYPE 0 + + RDB$USER 3 + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$TYPES + RDB$FIELD_NAME + RDB$USER_TYPE 20 + RDB$OBJECT_TYPE 0 + + RDB$USER 3 + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$TYPES + RDB$FIELD_NAME + RDB$USER_TYPE 20 + RDB$OBJECT_TYPE 0 + + RDB$USER 3 + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$TYPES + RDB$FIELD_NAME + RDB$USER_TYPE 20 + RDB$OBJECT_TYPE 0 + + RDB$USER 3 + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$TYPES + RDB$FIELD_NAME + RDB$USER_TYPE 20 + RDB$OBJECT_TYPE 0 + + RDB$USER 4 + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_NAME + RDB$USER_TYPE 20 + RDB$OBJECT_TYPE 0 + + RDB$USER 4 + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_NAME + RDB$USER_TYPE 20 + RDB$OBJECT_TYPE 0 + + RDB$USER 4 + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_NAME + RDB$USER_TYPE 20 + RDB$OBJECT_TYPE 0 + + RDB$USER 4 + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_NAME + RDB$USER_TYPE 20 + RDB$OBJECT_TYPE 0 + + RDB$USER 4 + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_NAME + RDB$USER_TYPE 20 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME MON$CONTEXT_VARIABLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME MON$IO_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME MON$MEMORY_USAGE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME MON$TABLE_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$CONFIG + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$DATABASE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$FIELD_DIMENSIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$FILES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$FORMATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$GENERATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$INDEX_SEGMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$LOG_FILES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$PAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$PUBLICATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$PUBLICATION_TABLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$ROLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$SECURITY_CLASSES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$TIME_ZONES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$TRANSACTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$TRIGGER_MESSAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$TYPES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME SEC$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME SEC$USERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER PUBLIC + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME SEC$USER_ATTRIBUTES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ASCII + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ASCII + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME BIG_5 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME BIG_5 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME BS_BA + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME CP943C + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME CP943C + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME CP943C_UNICODE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME CS_CZ + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME CYRL + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME CYRL + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DA_DA + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_CSY + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_DAN865 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_DEU437 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_DEU850 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_ESP437 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_ESP850 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_FIN437 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_FRA437 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_FRA850 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_FRC850 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_FRC863 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_ITA437 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_ITA850 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_NLD437 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_NLD850 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_NOR865 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_PLK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_PTB850 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_PTG860 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_RUS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_SLO + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_SVE437 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_SVE850 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_TRK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_UK437 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_UK850 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_US437 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DB_US850 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DE_DE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS437 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS437 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS737 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS737 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS775 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS775 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS850 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS850 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS852 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS852 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS857 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS857 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS858 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS858 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS860 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS860 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS861 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS861 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS862 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS862 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS863 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS863 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS864 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS864 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS865 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS865 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS866 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS866 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS869 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DOS869 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME DU_NL + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME EN_UK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME EN_US + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ES_ES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ES_ES_CI_AI + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME EUCJ_0208 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME EUCJ_0208 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME FI_FI + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME FR_CA + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME FR_CA_CI_AI + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME FR_FR + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME FR_FR_CI_AI + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME GB18030 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME GB18030 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME GB18030_UNICODE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME GBK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME GBK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME GBK_UNICODE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME GB_2312 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME GB_2312 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_1 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_1 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_13 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_13 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_2 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_2 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_3 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_3 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_4 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_4 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_5 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_5 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_6 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_6 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_7 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_7 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_8 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_8 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_9 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO8859_9 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO_HUN + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME ISO_PLK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME IS_IS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME IT_IT + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME KOI8R + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME KOI8R + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME KOI8R_RU + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME KOI8U + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME KOI8U + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME KOI8U_UA + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME KSC_5601 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME KSC_5601 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME KSC_DICTIONARY + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME LT_LT + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$ATTACHMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$CALL_STACK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$CONTEXT_VARIABLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$CONTEXT_VARIABLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$CONTEXT_VARIABLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$CONTEXT_VARIABLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$CONTEXT_VARIABLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$DATABASE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$IDLE_TIMEOUT + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$IDLE_TIMER + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$IO_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$IO_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$IO_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$IO_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$IO_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$MEMORY_USAGE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$MEMORY_USAGE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$MEMORY_USAGE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$MEMORY_USAGE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$MEMORY_USAGE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$RECORD_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$SEC_DATABASE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$STATEMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$STATEMENT_TIMEOUT + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$STATEMENT_TIMER + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$TABLE_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$TABLE_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$TABLE_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$TABLE_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$TABLE_STATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$TRANSACTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME MON$WIRE_CRYPT_PLUGIN + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME NEXT + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME NEXT + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME NONE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME NONE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME NO_NO + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME NXT_DEU + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME NXT_ESP + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME NXT_FRA + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME NXT_ITA + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME NXT_US + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME OCTETS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME OCTETS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PDOX_ASCII + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PDOX_CSY + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PDOX_CYRL + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PDOX_HUN + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PDOX_INTL + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PDOX_ISL + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PDOX_NORDAN4 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PDOX_PLK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PDOX_SLO + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PDOX_SWEDFIN + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PT_BR + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PT_PT + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PXW_CSY + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PXW_CYRL + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PXW_GREEK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PXW_HUN + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PXW_HUNDC + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PXW_INTL + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PXW_INTL850 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PXW_NORDAN4 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PXW_PLK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PXW_SLOV + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PXW_SPAN + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PXW_SWEDFIN + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME PXW_TURK + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$ACL + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE M + RDB$GRANT_OPTION 2 + RDB$RELATION_NAME RDB$ADMIN + RDB$FIELD_NAME D + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 13 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$ARGUMENT_MECHANISM + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$ARGUMENT_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$ATTACHMENT_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$AUTH_MAPPING + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$AUTH_METHOD + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 14 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$BACKUP_HISTORY + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$BACKUP_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$BACKUP_LEVEL + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$BACKUP_STATE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$BOOLEAN + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$BOUND + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CALL_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CHARACTER_SETS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CHARACTER_SET_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CHARACTER_SET_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CHECK_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CLIENT_VERSION + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$COLLATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$COLLATION_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$COLLATION_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CONFIG + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CONFIG + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CONFIG + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CONFIG + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CONFIG + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CONFIG_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CONFIG_IS_SET + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CONFIG_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CONFIG_VALUE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CONSTRAINT_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CONSTRAINT_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 14 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CONSTRAINT_TYPE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CONTEXT_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CONTEXT_VAR_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CONTEXT_VAR_VALUE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$COUNTER + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$CRYPT_STATE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DATABASE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DATABASE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DATABASE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DATABASE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DATABASE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DBKEY_LENGTH + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DBTZ_VERSION + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DEBUG_INFO + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DEFERRABLE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DEPENDENCIES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DESCRIPTION + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DESCRIPTOR + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DIMENSION + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$DIMENSIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$EDIT_STRING + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$ENGINE_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 14 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$EXCEPTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$EXCEPTION_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$EXCEPTION_NUMBER + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$EXTERNAL_DESCRIPTION + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$EXTERNAL_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELDS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELD_DIMENSIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELD_DIMENSIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELD_DIMENSIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELD_DIMENSIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELD_DIMENSIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELD_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELD_LENGTH + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELD_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELD_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 14 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELD_POSITION + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELD_PRECISION + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELD_SCALE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELD_SUB_TYPE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FIELD_TYPE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILE_FLAGS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILE_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILE_LENGTH + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILE_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILE_NAME2 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILE_PARTITIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILE_P_OFFSET + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILE_SEQUENCE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILE_START + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FILTERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FORMAT + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FORMATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FORMATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FORMATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FORMATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FORMATS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 14 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTION_ARGUMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTION_BLR + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTION_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTION_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$FUNCTION_TYPE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$GENERATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$GENERATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$GENERATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$GENERATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$GENERATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$GENERATOR_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$GENERATOR_INCREMENT + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$GENERATOR_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$GENERATOR_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 14 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$GENERATOR_VALUE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$GENERIC_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$GENERIC_TYPE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$GUID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$HOST_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$IDENTITY_TYPE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$INDEX_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$INDEX_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$INDEX_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 14 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$INDEX_SEGMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$INDEX_SEGMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$INDEX_SEGMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$INDEX_SEGMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$INDEX_SEGMENTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$INDICES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$ISOLATION_MODE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$LINGER + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$LOCK_TIMEOUT + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$LOG_FILES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$LOG_FILES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$LOG_FILES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$LOG_FILES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$LOG_FILES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$MAP_DB + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$MAP_FROM + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$MAP_FROM_TYPE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$MAP_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$MAP_TO + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$MAP_USING + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$MATCH_OPTION + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$MECHANISM + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$MESSAGE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$MESSAGE_NUMBER + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$NULL_FLAG + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$NUMBER_OF_CHARACTERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$OBJECT_TYPE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$ODS_NUMBER + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$OS_USER + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PACKAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PACKAGE_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PAGE_BUFFERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PAGE_NUMBER + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PAGE_SEQUENCE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PAGE_SIZE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PAGE_TYPE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PARAMETER_MECHANISM + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PARAMETER_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PARAMETER_NUMBER + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PARAMETER_TYPE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PLAN + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PLUGIN + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PRIVILEGE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 14 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURE_BLR + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURE_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURE_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURE_PARAMETERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PROCEDURE_TYPE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PUBLICATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PUBLICATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PUBLICATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PUBLICATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PUBLICATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PUBLICATION_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PUBLICATION_TABLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PUBLICATION_TABLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PUBLICATION_TABLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PUBLICATION_TABLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$PUBLICATION_TABLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$QUERY_HEADER + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$REF_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATION_CONSTRAINTS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATION_FIELDS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATION_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATION_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RELATION_TYPE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$REMOTE_ADDRESS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$REMOTE_PROTOCOL + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$REMOTE_VERSION + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$REPLICA_MODE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$ROLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$ROLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$ROLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$ROLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$ROLES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RULE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$RUNTIME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SCN + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SECURITY_CLASS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SECURITY_CLASS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 14 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SECURITY_CLASSES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SECURITY_CLASSES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SECURITY_CLASSES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SECURITY_CLASSES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SECURITY_CLASSES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SEGMENT_COUNT + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SEGMENT_LENGTH + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SHADOW_NUMBER + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SHUTDOWN_MODE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SOURCE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SOURCE_INFO + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SPECIFIC_ATTRIBUTES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SQL_DIALECT + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SQL_SECURITY + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$STATE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$STATEMENT_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$STATISTICS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$STAT_GROUP + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$STAT_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SWEEP_INTERVAL + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SYSTEM_FLAG + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SYSTEM_NULLFLAG + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$SYSTEM_PRIVILEGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TIMESTAMP + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TIMESTAMP_TZ + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TIME_ZONES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TIME_ZONES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TIME_ZONES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TIME_ZONES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TIME_ZONES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TIME_ZONE_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TIME_ZONE_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TIME_ZONE_OFFSET + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE X + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TIME_ZONE_UTIL + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 18 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRANSACTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRANSACTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRANSACTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRANSACTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRANSACTIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRANSACTION_DESCRIPTION + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRANSACTION_ID + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRANSACTION_STATE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGER_BLR + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGER_MESSAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGER_MESSAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGER_MESSAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGER_MESSAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGER_MESSAGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGER_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGER_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 14 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGER_SEQUENCE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TRIGGER_TYPE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TYPES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TYPES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TYPES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TYPES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TYPES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$TYPE_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$USER + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$USER_PRIVILEGES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$VALIDATION_BLR + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$VALUE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$VIEW_BLR + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$VIEW_CONTEXT + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME RDB$VIEW_RELATIONS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$DB_CREATORS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$GLOBAL_AUTH_MAPPING + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$KEY + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$NAME_PART + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$USERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$USERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$USERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$USERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$USERS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE D + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$USER_ATTRIBUTES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE I + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$USER_ATTRIBUTES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE R + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$USER_ATTRIBUTES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE S + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$USER_ATTRIBUTES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE U + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$USER_ATTRIBUTES + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$USER_NAME + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SEC$VALUE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 9 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SJIS_0208 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SJIS_0208 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SQL$DEFAULT + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 14 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME SV_SV + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME TIS620 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME TIS620 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME TIS620_UNICODE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME UCS_BASIC + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME UNICODE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME UNICODE_CI + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME UNICODE_CI_AI + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME UNICODE_FSS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME UNICODE_FSS + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME UTF8 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME UTF8 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1250 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1250 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1251 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1251 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1251_UA + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1252 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1252 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1253 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1253 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1254 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1254 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1255 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1255 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1256 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1256 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1257 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1257 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1257_EE + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1257_LT + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1257_LV + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1258 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 11 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN1258 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN_CZ + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN_CZ_CI_AI + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + RDB$USER SYSDBA + RDB$GRANTOR + RDB$PRIVILEGE G + RDB$GRANT_OPTION 1 + RDB$RELATION_NAME WIN_PTBR + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 17 + + + Records affected: 723 + + Are ordered columns unique ? 1 + """ + +@pytest.mark.version('>=4.0') +def test_db_31_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/functional/basic/db/test_32.py b/tests/functional/basic/db/test_32.py new file mode 100644 index 00000000..5da6a9cc --- /dev/null +++ b/tests/functional/basic/db/test_32.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: functional.basic.db.32 +# title: Empty DB - RDB$VIEW_RELATIONS +# decription: Check for correct content of RDB$VIEW_RELATIONS in empty database. +# tracker_id: +# min_versions: [] +# versions: 2.5 +# qmid: functional.basic.db.db_32 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + select * from rdb$view_relations v order by v.rdb$view_name, v.rdb$relation_name; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ + +@pytest.mark.version('>=2.5') +def test_32_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/basic/isql/__init__.py b/tests/functional/basic/isql/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/basic/isql/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/basic/isql/test_00.py b/tests/functional/basic/isql/test_00.py new file mode 100644 index 00000000..f5d3a9b5 --- /dev/null +++ b/tests/functional/basic/isql/test_00.py @@ -0,0 +1,80 @@ +#coding:utf-8 +# +# id: functional.basic.isql.isql_00 +# title: Check output of "HELP" and "HELP SET" commands +# decription: +# NB: this test can also cover issue of CORE-2432 ("Missing SHOW COLLATIONs in HELP") +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + help; + help set; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Frontend commands: + BLOBDUMP -- dump BLOB to a file + BLOBVIEW -- view BLOB in text editor + EDIT [] -- edit SQL script file and execute + EDIT -- edit current command buffer and execute + HELP -- display this menu + INput -- take input from the named SQL file + OUTput [] -- write output to named file + OUTput -- return output to stdout + SET [] -- set/unset print width to for column + All commands may be abbreviated to letters in CAPitals + """ + +@pytest.mark.version('>=3.0') +def test_isql_00_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/basic/isql/test_01.py b/tests/functional/basic/isql/test_01.py new file mode 100644 index 00000000..8bb26f9a --- /dev/null +++ b/tests/functional/basic/isql/test_01.py @@ -0,0 +1,94 @@ +#coding:utf-8 +# +# id: functional.basic.isql.isql_01 +# title: ISQL - SHOW DATABASE +# decription: Check for correct output of SHOW DATABASE on empty database. +# tracker_id: +# min_versions: [] +# versions: 3.0, 4.0 +# qmid: functional.basic.isql.isql_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('Owner.*', 'Owner'), ('PAGE_SIZE.*', 'PAGE_SIZE'), ('Number of DB pages allocated.*', 'Number of DB pages allocated'), ('Number of DB pages used.*', 'Number of DB pages used'), ('Number of DB pages free.*', 'Number of DB pages free'), ('Sweep.*', 'Sweep'), ('Forced Writes.*', 'Forced Writes'), ('Transaction -.*', ''), ('ODS.*', 'ODS'), ('Default Character.*', 'Default Character')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- 19.01.2016: added line "Database not encrypted", see http://sourceforge.net/p/firebird/code/62825 + show database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Database: localhost:c:\\job\\qa btest-repo mp unctional.basic.isql.isql_01.fdb + Owner: SYSDBA + PAGE_SIZE 8192 + Number of DB pages allocated + Number of DB pages used + Number of DB pages free + Sweep interval = 11120000 + Forced Writes are ON + Transaction - oldest = 1 + Transaction - oldest active = 2 + Transaction - oldest snapshot = 2 + Transaction - Next = 5 + ODS = 12.0 + Database not encrypted + Default Character set: NONE + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_isql_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [('Owner.*', 'Owner'), ('PAGE_SIZE.*', 'PAGE_SIZE'), ('Number of DB pages allocated.*', 'Number of DB pages allocated'), ('Number of DB pages used.*', 'Number of DB pages used'), ('Number of DB pages free.*', 'Number of DB pages free'), ('Sweep.*', 'Sweep'), ('Forced Writes.*', 'Forced Writes'), ('Transaction -.*', ''), ('ODS.*', 'ODS'), ('Wire crypt plugin.*', 'Wire crypt plugin'), ('Default Character.*', 'Default Character')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + -- Separate for FB 4.0 since 22.01.2020 + show database; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + Database: localhost:c:\\job\\qa btest-repo mp unctional.basic.isql.isql_01.fdb + Owner: SYSDBA + PAGE_SIZE 8192 + Number of DB pages allocated = 212 + Number of DB pages used = 192 + Number of DB pages free = 20 + Sweep interval = 20000 + Forced Writes are ON + Transaction - oldest = 4 + Transaction - oldest active = 5 + Transaction - oldest snapshot = 5 + Transaction - Next = 9 + ODS = 13.0 + Database not encrypted + Wire crypt plugin: + Default Character set: NONE + """ + +@pytest.mark.version('>=4.0') +def test_isql_01_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/functional/basic/isql/test_02.py b/tests/functional/basic/isql/test_02.py new file mode 100644 index 00000000..3e2f2ca0 --- /dev/null +++ b/tests/functional/basic/isql/test_02.py @@ -0,0 +1,377 @@ +#coding:utf-8 +# +# id: functional.basic.isql.isql_02 +# title: ISQL - SHOW SYSTEM TABLES +# decription: +# Check for correct output of "SHOW SYSTEM;" command on empty database. +# Checked on: +# 2.5.9.27126: OK, 0.484s. +# 3.0.5.33086: OK, 1.031s. +# 4.0.0.1378: OK, 7.547s. +# +# tracker_id: +# min_versions: [] +# versions: 3.0, 4.0 +# qmid: functional.basic.isql.isql_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """show system ;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +Tables: + MON$ATTACHMENTS MON$CALL_STACK + MON$CONTEXT_VARIABLES MON$DATABASE + MON$IO_STATS MON$MEMORY_USAGE + MON$RECORD_STATS MON$STATEMENTS + MON$TABLE_STATS MON$TRANSACTIONS + RDB$AUTH_MAPPING RDB$BACKUP_HISTORY + RDB$CHARACTER_SETS RDB$CHECK_CONSTRAINTS + RDB$COLLATIONS RDB$DATABASE + RDB$DB_CREATORS RDB$DEPENDENCIES + RDB$EXCEPTIONS RDB$FIELDS + RDB$FIELD_DIMENSIONS RDB$FILES + RDB$FILTERS RDB$FORMATS + RDB$FUNCTIONS RDB$FUNCTION_ARGUMENTS + RDB$GENERATORS RDB$INDEX_SEGMENTS + RDB$INDICES RDB$LOG_FILES + RDB$PACKAGES RDB$PAGES + RDB$PROCEDURES RDB$PROCEDURE_PARAMETERS + RDB$REF_CONSTRAINTS RDB$RELATIONS + RDB$RELATION_CONSTRAINTS RDB$RELATION_FIELDS + RDB$ROLES RDB$SECURITY_CLASSES + RDB$TRANSACTIONS RDB$TRIGGERS + RDB$TRIGGER_MESSAGES RDB$TYPES + RDB$USER_PRIVILEGES RDB$VIEW_RELATIONS + SEC$DB_CREATORS SEC$GLOBAL_AUTH_MAPPING + SEC$USERS SEC$USER_ATTRIBUTES + +Collations: + ASCII BIG_5 + BS_BA CP943C + CP943C_UNICODE CS_CZ + CYRL DA_DA + DB_CSY DB_DAN865 + DB_DEU437 DB_DEU850 + DB_ESP437 DB_ESP850 + DB_FIN437 DB_FRA437 + DB_FRA850 DB_FRC850 + DB_FRC863 DB_ITA437 + DB_ITA850 DB_NLD437 + DB_NLD850 DB_NOR865 + DB_PLK DB_PTB850 + DB_PTG860 DB_RUS + DB_SLO DB_SVE437 + DB_SVE850 DB_TRK + DB_UK437 DB_UK850 + DB_US437 DB_US850 + DE_DE DOS437 + DOS737 DOS775 + DOS850 DOS852 + DOS857 DOS858 + DOS860 DOS861 + DOS862 DOS863 + DOS864 DOS865 + DOS866 DOS869 + DU_NL EN_UK + EN_US ES_ES + ES_ES_CI_AI EUCJ_0208 + FI_FI FR_CA + FR_CA_CI_AI FR_FR + FR_FR_CI_AI GB18030 + GB18030_UNICODE GBK + GBK_UNICODE GB_2312 + ISO8859_1 ISO8859_13 + ISO8859_2 ISO8859_3 + ISO8859_4 ISO8859_5 + ISO8859_6 ISO8859_7 + ISO8859_8 ISO8859_9 + ISO_HUN ISO_PLK + IS_IS IT_IT + KOI8R KOI8R_RU + KOI8U KOI8U_UA + KSC_5601 KSC_DICTIONARY + LT_LT NEXT + NONE NO_NO + NXT_DEU NXT_ESP + NXT_FRA NXT_ITA + NXT_US OCTETS + PDOX_ASCII PDOX_CSY + PDOX_CYRL PDOX_HUN + PDOX_INTL PDOX_ISL + PDOX_NORDAN4 PDOX_PLK + PDOX_SLO PDOX_SWEDFIN + PT_BR PT_PT + PXW_CSY PXW_CYRL + PXW_GREEK PXW_HUN + PXW_HUNDC PXW_INTL + PXW_INTL850 PXW_NORDAN4 + PXW_PLK PXW_SLOV + PXW_SPAN PXW_SWEDFIN + PXW_TURK SJIS_0208 + SV_SV TIS620 + TIS620_UNICODE UCS_BASIC + UNICODE UNICODE_CI + UNICODE_CI_AI UNICODE_FSS + UTF8 WIN1250 + WIN1251 WIN1251_UA + WIN1252 WIN1253 + WIN1254 WIN1255 + WIN1256 WIN1257 + WIN1257_EE WIN1257_LT + WIN1257_LV WIN1258 + WIN_CZ WIN_CZ_CI_AI + WIN_PTBR + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_isql_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + show system; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + Tables: + MON$ATTACHMENTS + MON$CALL_STACK + MON$CONTEXT_VARIABLES + MON$DATABASE + MON$IO_STATS + MON$MEMORY_USAGE + MON$RECORD_STATS + MON$STATEMENTS + MON$TABLE_STATS + MON$TRANSACTIONS + RDB$AUTH_MAPPING + RDB$BACKUP_HISTORY + RDB$CHARACTER_SETS + RDB$CHECK_CONSTRAINTS + RDB$COLLATIONS + RDB$CONFIG + RDB$DATABASE + RDB$DB_CREATORS + RDB$DEPENDENCIES + RDB$EXCEPTIONS + RDB$FIELDS + RDB$FIELD_DIMENSIONS + RDB$FILES + RDB$FILTERS + RDB$FORMATS + RDB$FUNCTIONS + RDB$FUNCTION_ARGUMENTS + RDB$GENERATORS + RDB$INDEX_SEGMENTS + RDB$INDICES + RDB$LOG_FILES + RDB$PACKAGES + RDB$PAGES + 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$TIME_ZONES + RDB$TRANSACTIONS + RDB$TRIGGERS + RDB$TRIGGER_MESSAGES + RDB$TYPES + RDB$USER_PRIVILEGES + RDB$VIEW_RELATIONS + SEC$DB_CREATORS + SEC$GLOBAL_AUTH_MAPPING + SEC$USERS + SEC$USER_ATTRIBUTES + + Collations: + ASCII + BIG_5 + BS_BA + CP943C + CP943C_UNICODE + CS_CZ + CYRL + DA_DA + DB_CSY + DB_DAN865 + DB_DEU437 + DB_DEU850 + DB_ESP437 + DB_ESP850 + DB_FIN437 + DB_FRA437 + DB_FRA850 + DB_FRC850 + DB_FRC863 + DB_ITA437 + DB_ITA850 + DB_NLD437 + DB_NLD850 + DB_NOR865 + DB_PLK + DB_PTB850 + DB_PTG860 + DB_RUS + DB_SLO + DB_SVE437 + DB_SVE850 + DB_TRK + DB_UK437 + DB_UK850 + DB_US437 + DB_US850 + DE_DE + DOS437 + DOS737 + DOS775 + DOS850 + DOS852 + DOS857 + DOS858 + DOS860 + DOS861 + DOS862 + DOS863 + DOS864 + DOS865 + DOS866 + DOS869 + DU_NL + EN_UK + EN_US + ES_ES + ES_ES_CI_AI + EUCJ_0208 + FI_FI + FR_CA + FR_CA_CI_AI + FR_FR + FR_FR_CI_AI + GB18030 + GB18030_UNICODE + GBK + GBK_UNICODE + GB_2312 + ISO8859_1 + ISO8859_13 + ISO8859_2 + ISO8859_3 + ISO8859_4 + ISO8859_5 + ISO8859_6 + ISO8859_7 + ISO8859_8 + ISO8859_9 + ISO_HUN + ISO_PLK + IS_IS + IT_IT + KOI8R + KOI8R_RU + KOI8U + KOI8U_UA + KSC_5601 + KSC_DICTIONARY + LT_LT + NEXT + NONE + NO_NO + NXT_DEU + NXT_ESP + NXT_FRA + NXT_ITA + NXT_US + OCTETS + PDOX_ASCII + PDOX_CSY + PDOX_CYRL + PDOX_HUN + PDOX_INTL + PDOX_ISL + PDOX_NORDAN4 + PDOX_PLK + PDOX_SLO + PDOX_SWEDFIN + PT_BR + PT_PT + PXW_CSY + PXW_CYRL + PXW_GREEK + PXW_HUN + PXW_HUNDC + PXW_INTL + PXW_INTL850 + PXW_NORDAN4 + PXW_PLK + PXW_SLOV + PXW_SPAN + PXW_SWEDFIN + PXW_TURK + SJIS_0208 + SV_SV + TIS620 + TIS620_UNICODE + UCS_BASIC + UNICODE + UNICODE_CI + UNICODE_CI_AI + UNICODE_FSS + UTF8 + WIN1250 + WIN1251 + WIN1251_UA + WIN1252 + WIN1253 + WIN1254 + WIN1255 + WIN1256 + WIN1257 + WIN1257_EE + WIN1257_LT + WIN1257_LV + WIN1258 + WIN_CZ + WIN_CZ_CI_AI + WIN_PTBR + + Roles: + RDB$ADMIN + """ + +@pytest.mark.version('>=4.0') +def test_isql_02_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/functional/basic/isql/test_03.py b/tests/functional/basic/isql/test_03.py new file mode 100644 index 00000000..f7a47baa --- /dev/null +++ b/tests/functional/basic/isql/test_03.py @@ -0,0 +1,444 @@ +#coding:utf-8 +# +# id: functional.basic.isql.isql_03 +# title: SHOW SYSTEM parameters +# decription: Extend ISQL SHOW SYSTEM command to accept parameters TABLES, COLLATIONS and FUNCTIONS +# tracker_id: CORE-978 +# min_versions: [] +# versions: 3.0, 4.0 +# qmid: functional.basic.isql.isql_14 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [("'COLL-VERSION=\\d+\\.\\d+\\.\\d+\\.\\d+', ", ''), ("'COLL-VERSION=\\d+\\.\\d+', ", '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SHOW SYSTEM TABLES; +SHOW SYSTEM COLLATIONS; +SHOW SYSTEM FUNCTIONS; + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MON$ATTACHMENTS MON$CALL_STACK + MON$CONTEXT_VARIABLES MON$DATABASE + MON$IO_STATS MON$MEMORY_USAGE + MON$RECORD_STATS MON$STATEMENTS + MON$TABLE_STATS MON$TRANSACTIONS + RDB$AUTH_MAPPING RDB$BACKUP_HISTORY + RDB$CHARACTER_SETS RDB$CHECK_CONSTRAINTS + RDB$COLLATIONS RDB$DATABASE + RDB$DB_CREATORS RDB$DEPENDENCIES + RDB$EXCEPTIONS RDB$FIELDS + RDB$FIELD_DIMENSIONS RDB$FILES + RDB$FILTERS RDB$FORMATS + RDB$FUNCTIONS RDB$FUNCTION_ARGUMENTS + RDB$GENERATORS RDB$INDEX_SEGMENTS + RDB$INDICES RDB$LOG_FILES + RDB$PACKAGES RDB$PAGES + RDB$PROCEDURES RDB$PROCEDURE_PARAMETERS + RDB$REF_CONSTRAINTS RDB$RELATIONS + RDB$RELATION_CONSTRAINTS RDB$RELATION_FIELDS + RDB$ROLES RDB$SECURITY_CLASSES + RDB$TRANSACTIONS RDB$TRIGGERS + RDB$TRIGGER_MESSAGES RDB$TYPES + RDB$USER_PRIVILEGES RDB$VIEW_RELATIONS + SEC$DB_CREATORS SEC$GLOBAL_AUTH_MAPPING + SEC$USERS SEC$USER_ATTRIBUTES + +ASCII, CHARACTER SET ASCII, PAD SPACE, SYSTEM +BIG_5, CHARACTER SET BIG_5, PAD SPACE, SYSTEM +BS_BA, CHARACTER SET WIN1250, PAD SPACE, SYSTEM +CP943C, CHARACTER SET CP943C, PAD SPACE, SYSTEM +CP943C_UNICODE, CHARACTER SET CP943C, PAD SPACE, SYSTEM +CS_CZ, CHARACTER SET ISO8859_2, PAD SPACE, SYSTEM +CYRL, CHARACTER SET CYRL, PAD SPACE, SYSTEM +DA_DA, CHARACTER SET ISO8859_1, PAD SPACE, SYSTEM +DB_CSY, CHARACTER SET DOS852, PAD SPACE, SYSTEM +DB_DAN865, CHARACTER SET DOS865, PAD SPACE, SYSTEM +DB_DEU437, CHARACTER SET DOS437, PAD SPACE, SYSTEM +DB_DEU850, CHARACTER SET DOS850, PAD SPACE, SYSTEM +DB_ESP437, CHARACTER SET DOS437, PAD SPACE, SYSTEM +DB_ESP850, CHARACTER SET DOS850, PAD SPACE, SYSTEM +DB_FIN437, CHARACTER SET DOS437, PAD SPACE, SYSTEM +DB_FRA437, CHARACTER SET DOS437, PAD SPACE, SYSTEM +DB_FRA850, CHARACTER SET DOS850, PAD SPACE, SYSTEM +DB_FRC850, CHARACTER SET DOS850, PAD SPACE, SYSTEM +DB_FRC863, CHARACTER SET DOS863, PAD SPACE, SYSTEM +DB_ITA437, CHARACTER SET DOS437, PAD SPACE, SYSTEM +DB_ITA850, CHARACTER SET DOS850, PAD SPACE, SYSTEM +DB_NLD437, CHARACTER SET DOS437, PAD SPACE, SYSTEM +DB_NLD850, CHARACTER SET DOS850, PAD SPACE, SYSTEM +DB_NOR865, CHARACTER SET DOS865, PAD SPACE, SYSTEM +DB_PLK, CHARACTER SET DOS852, PAD SPACE, SYSTEM +DB_PTB850, CHARACTER SET DOS850, PAD SPACE, SYSTEM +DB_PTG860, CHARACTER SET DOS860, PAD SPACE, SYSTEM +DB_RUS, CHARACTER SET CYRL, PAD SPACE, SYSTEM +DB_SLO, CHARACTER SET DOS852, PAD SPACE, SYSTEM +DB_SVE437, CHARACTER SET DOS437, PAD SPACE, SYSTEM +DB_SVE850, CHARACTER SET DOS850, PAD SPACE, SYSTEM +DB_TRK, CHARACTER SET DOS857, PAD SPACE, SYSTEM +DB_UK437, CHARACTER SET DOS437, PAD SPACE, SYSTEM +DB_UK850, CHARACTER SET DOS850, PAD SPACE, SYSTEM +DB_US437, CHARACTER SET DOS437, PAD SPACE, SYSTEM +DB_US850, CHARACTER SET DOS850, PAD SPACE, SYSTEM +DE_DE, CHARACTER SET ISO8859_1, PAD SPACE, SYSTEM +DOS437, CHARACTER SET DOS437, PAD SPACE, SYSTEM +DOS737, CHARACTER SET DOS737, PAD SPACE, SYSTEM +DOS775, CHARACTER SET DOS775, PAD SPACE, SYSTEM +DOS850, CHARACTER SET DOS850, PAD SPACE, SYSTEM +DOS852, CHARACTER SET DOS852, PAD SPACE, SYSTEM +DOS857, CHARACTER SET DOS857, PAD SPACE, SYSTEM +DOS858, CHARACTER SET DOS858, PAD SPACE, SYSTEM +DOS860, CHARACTER SET DOS860, PAD SPACE, SYSTEM +DOS861, CHARACTER SET DOS861, PAD SPACE, SYSTEM +DOS862, CHARACTER SET DOS862, PAD SPACE, SYSTEM +DOS863, CHARACTER SET DOS863, PAD SPACE, SYSTEM +DOS864, CHARACTER SET DOS864, PAD SPACE, SYSTEM +DOS865, CHARACTER SET DOS865, PAD SPACE, SYSTEM +DOS866, CHARACTER SET DOS866, PAD SPACE, SYSTEM +DOS869, CHARACTER SET DOS869, PAD SPACE, SYSTEM +DU_NL, CHARACTER SET ISO8859_1, PAD SPACE, SYSTEM +EN_UK, CHARACTER SET ISO8859_1, PAD SPACE, SYSTEM +EN_US, CHARACTER SET ISO8859_1, PAD SPACE, SYSTEM +ES_ES, CHARACTER SET ISO8859_1, PAD SPACE, 'DISABLE-COMPRESSIONS=1;SPECIALS-FIRST=1', SYSTEM +ES_ES_CI_AI, CHARACTER SET ISO8859_1, PAD SPACE, CASE INSENSITIVE, ACCENT INSENSITIVE, 'DISABLE-COMPRESSIONS=1;SPECIALS-FIRST=1', SYSTEM +EUCJ_0208, CHARACTER SET EUCJ_0208, PAD SPACE, SYSTEM +FI_FI, CHARACTER SET ISO8859_1, PAD SPACE, SYSTEM +FR_CA, CHARACTER SET ISO8859_1, PAD SPACE, SYSTEM +FR_CA_CI_AI, CHARACTER SET ISO8859_1, FROM EXTERNAL ('FR_CA'), PAD SPACE, CASE INSENSITIVE, ACCENT INSENSITIVE, 'SPECIALS-FIRST=1', SYSTEM +FR_FR, CHARACTER SET ISO8859_1, PAD SPACE, SYSTEM +FR_FR_CI_AI, CHARACTER SET ISO8859_1, FROM EXTERNAL ('FR_FR'), PAD SPACE, CASE INSENSITIVE, ACCENT INSENSITIVE, 'SPECIALS-FIRST=1', SYSTEM +GB18030, CHARACTER SET GB18030, PAD SPACE, SYSTEM +GB18030_UNICODE, CHARACTER SET GB18030, PAD SPACE, SYSTEM +GBK, CHARACTER SET GBK, PAD SPACE, SYSTEM +GBK_UNICODE, CHARACTER SET GBK, PAD SPACE, SYSTEM +GB_2312, CHARACTER SET GB_2312, PAD SPACE, SYSTEM +ISO8859_1, CHARACTER SET ISO8859_1, PAD SPACE, SYSTEM +ISO8859_13, CHARACTER SET ISO8859_13, PAD SPACE, SYSTEM +ISO8859_2, CHARACTER SET ISO8859_2, PAD SPACE, SYSTEM +ISO8859_3, CHARACTER SET ISO8859_3, PAD SPACE, SYSTEM +ISO8859_4, CHARACTER SET ISO8859_4, PAD SPACE, SYSTEM +ISO8859_5, CHARACTER SET ISO8859_5, PAD SPACE, SYSTEM +ISO8859_6, CHARACTER SET ISO8859_6, PAD SPACE, SYSTEM +ISO8859_7, CHARACTER SET ISO8859_7, PAD SPACE, SYSTEM +ISO8859_8, CHARACTER SET ISO8859_8, PAD SPACE, SYSTEM +ISO8859_9, CHARACTER SET ISO8859_9, PAD SPACE, SYSTEM +ISO_HUN, CHARACTER SET ISO8859_2, PAD SPACE, SYSTEM +ISO_PLK, CHARACTER SET ISO8859_2, PAD SPACE, SYSTEM +IS_IS, CHARACTER SET ISO8859_1, PAD SPACE, SYSTEM +IT_IT, CHARACTER SET ISO8859_1, PAD SPACE, SYSTEM +KOI8R, CHARACTER SET KOI8R, PAD SPACE, SYSTEM +KOI8R_RU, CHARACTER SET KOI8R, PAD SPACE, SYSTEM +KOI8U, CHARACTER SET KOI8U, PAD SPACE, SYSTEM +KOI8U_UA, CHARACTER SET KOI8U, PAD SPACE, SYSTEM +KSC_5601, CHARACTER SET KSC_5601, PAD SPACE, SYSTEM +KSC_DICTIONARY, CHARACTER SET KSC_5601, PAD SPACE, SYSTEM +LT_LT, CHARACTER SET ISO8859_13, PAD SPACE, SYSTEM +NEXT, CHARACTER SET NEXT, PAD SPACE, SYSTEM +NONE, CHARACTER SET NONE, PAD SPACE, SYSTEM +NO_NO, CHARACTER SET ISO8859_1, PAD SPACE, SYSTEM +NXT_DEU, CHARACTER SET NEXT, PAD SPACE, SYSTEM +NXT_ESP, CHARACTER SET NEXT, PAD SPACE, SYSTEM +NXT_FRA, CHARACTER SET NEXT, PAD SPACE, SYSTEM +NXT_ITA, CHARACTER SET NEXT, PAD SPACE, SYSTEM +NXT_US, CHARACTER SET NEXT, PAD SPACE, SYSTEM +OCTETS, CHARACTER SET OCTETS, PAD SPACE, SYSTEM +PDOX_ASCII, CHARACTER SET DOS437, PAD SPACE, SYSTEM +PDOX_CSY, CHARACTER SET DOS852, PAD SPACE, SYSTEM +PDOX_CYRL, CHARACTER SET CYRL, PAD SPACE, SYSTEM +PDOX_HUN, CHARACTER SET DOS852, PAD SPACE, SYSTEM +PDOX_INTL, CHARACTER SET DOS437, PAD SPACE, SYSTEM +PDOX_ISL, CHARACTER SET DOS861, PAD SPACE, SYSTEM +PDOX_NORDAN4, CHARACTER SET DOS865, PAD SPACE, SYSTEM +PDOX_PLK, CHARACTER SET DOS852, PAD SPACE, SYSTEM +PDOX_SLO, CHARACTER SET DOS852, PAD SPACE, SYSTEM +PDOX_SWEDFIN, CHARACTER SET DOS437, PAD SPACE, SYSTEM +PT_BR, CHARACTER SET ISO8859_1, PAD SPACE, CASE INSENSITIVE, ACCENT INSENSITIVE, SYSTEM +PT_PT, CHARACTER SET ISO8859_1, PAD SPACE, SYSTEM +PXW_CSY, CHARACTER SET WIN1250, PAD SPACE, SYSTEM +PXW_CYRL, CHARACTER SET WIN1251, PAD SPACE, SYSTEM +PXW_GREEK, CHARACTER SET WIN1253, PAD SPACE, SYSTEM +PXW_HUN, CHARACTER SET WIN1250, PAD SPACE, SYSTEM +PXW_HUNDC, CHARACTER SET WIN1250, PAD SPACE, SYSTEM +PXW_INTL, CHARACTER SET WIN1252, PAD SPACE, SYSTEM +PXW_INTL850, CHARACTER SET WIN1252, PAD SPACE, SYSTEM +PXW_NORDAN4, CHARACTER SET WIN1252, PAD SPACE, SYSTEM +PXW_PLK, CHARACTER SET WIN1250, PAD SPACE, SYSTEM +PXW_SLOV, CHARACTER SET WIN1250, PAD SPACE, SYSTEM +PXW_SPAN, CHARACTER SET WIN1252, PAD SPACE, SYSTEM +PXW_SWEDFIN, CHARACTER SET WIN1252, PAD SPACE, SYSTEM +PXW_TURK, CHARACTER SET WIN1254, PAD SPACE, SYSTEM +SJIS_0208, CHARACTER SET SJIS_0208, PAD SPACE, SYSTEM +SV_SV, CHARACTER SET ISO8859_1, PAD SPACE, SYSTEM +TIS620, CHARACTER SET TIS620, PAD SPACE, SYSTEM +TIS620_UNICODE, CHARACTER SET TIS620, PAD SPACE, SYSTEM +UCS_BASIC, CHARACTER SET UTF8, PAD SPACE, SYSTEM +UNICODE, CHARACTER SET UTF8, PAD SPACE, SYSTEM +UNICODE_CI, CHARACTER SET UTF8, FROM EXTERNAL ('UNICODE'), PAD SPACE, CASE INSENSITIVE, SYSTEM +UNICODE_CI_AI, CHARACTER SET UTF8, FROM EXTERNAL ('UNICODE'), PAD SPACE, CASE INSENSITIVE, ACCENT INSENSITIVE, SYSTEM +UNICODE_FSS, CHARACTER SET UNICODE_FSS, PAD SPACE, SYSTEM +UTF8, CHARACTER SET UTF8, PAD SPACE, SYSTEM +WIN1250, CHARACTER SET WIN1250, PAD SPACE, SYSTEM +WIN1251, CHARACTER SET WIN1251, PAD SPACE, SYSTEM +WIN1251_UA, CHARACTER SET WIN1251, PAD SPACE, SYSTEM +WIN1252, CHARACTER SET WIN1252, PAD SPACE, SYSTEM +WIN1253, CHARACTER SET WIN1253, PAD SPACE, SYSTEM +WIN1254, CHARACTER SET WIN1254, PAD SPACE, SYSTEM +WIN1255, CHARACTER SET WIN1255, PAD SPACE, SYSTEM +WIN1256, CHARACTER SET WIN1256, PAD SPACE, SYSTEM +WIN1257, CHARACTER SET WIN1257, PAD SPACE, SYSTEM +WIN1257_EE, CHARACTER SET WIN1257, PAD SPACE, SYSTEM +WIN1257_LT, CHARACTER SET WIN1257, PAD SPACE, SYSTEM +WIN1257_LV, CHARACTER SET WIN1257, PAD SPACE, SYSTEM +WIN1258, CHARACTER SET WIN1258, PAD SPACE, SYSTEM +WIN_CZ, CHARACTER SET WIN1250, PAD SPACE, CASE INSENSITIVE, SYSTEM +WIN_CZ_CI_AI, CHARACTER SET WIN1250, PAD SPACE, CASE INSENSITIVE, ACCENT INSENSITIVE, SYSTEM +WIN_PTBR, CHARACTER SET WIN1252, PAD SPACE, CASE INSENSITIVE, ACCENT INSENSITIVE, SYSTEM + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_isql_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [("'COLL-VERSION=\\d+\\.\\d+\\.\\d+\\.\\d+', ", ''), ("'COLL-VERSION=\\d+\\.\\d+', ", '')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + SHOW SYSTEM TABLES; + SHOW SYSTEM COLLATIONS; + SHOW SYSTEM FUNCTIONS; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + MON$ATTACHMENTS + MON$CALL_STACK + MON$CONTEXT_VARIABLES + MON$DATABASE + MON$IO_STATS + MON$MEMORY_USAGE + MON$RECORD_STATS + MON$STATEMENTS + MON$TABLE_STATS + MON$TRANSACTIONS + RDB$AUTH_MAPPING + RDB$BACKUP_HISTORY + RDB$CHARACTER_SETS + RDB$CHECK_CONSTRAINTS + RDB$COLLATIONS + RDB$CONFIG + RDB$DATABASE + RDB$DB_CREATORS + RDB$DEPENDENCIES + RDB$EXCEPTIONS + RDB$FIELDS + RDB$FIELD_DIMENSIONS + RDB$FILES + RDB$FILTERS + RDB$FORMATS + RDB$FUNCTIONS + RDB$FUNCTION_ARGUMENTS + RDB$GENERATORS + RDB$INDEX_SEGMENTS + RDB$INDICES + RDB$LOG_FILES + RDB$PACKAGES + RDB$PAGES + 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$TIME_ZONES + RDB$TRANSACTIONS + RDB$TRIGGERS + RDB$TRIGGER_MESSAGES + RDB$TYPES + RDB$USER_PRIVILEGES + RDB$VIEW_RELATIONS + SEC$DB_CREATORS + SEC$GLOBAL_AUTH_MAPPING + SEC$USERS + SEC$USER_ATTRIBUTES + + ASCII, CHARACTER SET ASCII, PAD SPACE, SYSTEM + BIG_5, CHARACTER SET BIG_5, PAD SPACE, SYSTEM + BS_BA, CHARACTER SET WIN1250, PAD SPACE, SYSTEM + CP943C, CHARACTER SET CP943C, PAD SPACE, SYSTEM + CP943C_UNICODE, CHARACTER SET CP943C, PAD SPACE, 'COLL-VERSION=153.88', SYSTEM + CS_CZ, CHARACTER SET ISO8859_2, PAD SPACE, SYSTEM + CYRL, CHARACTER SET CYRL, PAD SPACE, SYSTEM + DA_DA, CHARACTER SET ISO8859_1, PAD SPACE, SYSTEM + DB_CSY, CHARACTER SET DOS852, PAD SPACE, SYSTEM + DB_DAN865, CHARACTER SET DOS865, PAD SPACE, SYSTEM + DB_DEU437, CHARACTER SET DOS437, PAD SPACE, SYSTEM + DB_DEU850, CHARACTER SET DOS850, PAD SPACE, SYSTEM + DB_ESP437, CHARACTER SET DOS437, PAD SPACE, SYSTEM + DB_ESP850, CHARACTER SET DOS850, PAD SPACE, SYSTEM + DB_FIN437, CHARACTER SET DOS437, PAD SPACE, SYSTEM + DB_FRA437, CHARACTER SET DOS437, PAD SPACE, SYSTEM + DB_FRA850, CHARACTER SET DOS850, PAD SPACE, SYSTEM + DB_FRC850, CHARACTER SET DOS850, PAD SPACE, SYSTEM + DB_FRC863, CHARACTER SET DOS863, PAD SPACE, SYSTEM + DB_ITA437, CHARACTER SET DOS437, PAD SPACE, SYSTEM + DB_ITA850, CHARACTER SET DOS850, PAD SPACE, SYSTEM + DB_NLD437, CHARACTER SET DOS437, PAD SPACE, SYSTEM + DB_NLD850, CHARACTER SET DOS850, PAD SPACE, SYSTEM + DB_NOR865, CHARACTER SET DOS865, PAD SPACE, SYSTEM + DB_PLK, CHARACTER SET DOS852, PAD SPACE, SYSTEM + DB_PTB850, CHARACTER SET DOS850, PAD SPACE, SYSTEM + DB_PTG860, CHARACTER SET DOS860, PAD SPACE, SYSTEM + DB_RUS, CHARACTER SET CYRL, PAD SPACE, SYSTEM + DB_SLO, CHARACTER SET DOS852, PAD SPACE, SYSTEM + DB_SVE437, CHARACTER SET DOS437, PAD SPACE, SYSTEM + DB_SVE850, CHARACTER SET DOS850, PAD SPACE, SYSTEM + DB_TRK, CHARACTER SET DOS857, PAD SPACE, SYSTEM + DB_UK437, CHARACTER SET DOS437, PAD SPACE, SYSTEM + DB_UK850, CHARACTER SET DOS850, PAD SPACE, SYSTEM + DB_US437, CHARACTER SET DOS437, PAD SPACE, SYSTEM + DB_US850, CHARACTER SET DOS850, PAD SPACE, SYSTEM + DE_DE, CHARACTER SET ISO8859_1, PAD SPACE, SYSTEM + DOS437, CHARACTER SET DOS437, PAD SPACE, SYSTEM + DOS737, CHARACTER SET DOS737, PAD SPACE, SYSTEM + DOS775, CHARACTER SET DOS775, PAD SPACE, SYSTEM + DOS850, CHARACTER SET DOS850, PAD SPACE, SYSTEM + DOS852, CHARACTER SET DOS852, PAD SPACE, SYSTEM + DOS857, CHARACTER SET DOS857, PAD SPACE, SYSTEM + DOS858, CHARACTER SET DOS858, PAD SPACE, SYSTEM + DOS860, CHARACTER SET DOS860, PAD SPACE, SYSTEM + DOS861, CHARACTER SET DOS861, PAD SPACE, SYSTEM + DOS862, CHARACTER SET DOS862, PAD SPACE, SYSTEM + DOS863, CHARACTER SET DOS863, PAD SPACE, SYSTEM + DOS864, CHARACTER SET DOS864, PAD SPACE, SYSTEM + DOS865, CHARACTER SET DOS865, PAD SPACE, SYSTEM + DOS866, CHARACTER SET DOS866, PAD SPACE, SYSTEM + DOS869, CHARACTER SET DOS869, PAD SPACE, SYSTEM + DU_NL, CHARACTER SET ISO8859_1, PAD SPACE, SYSTEM + EN_UK, CHARACTER SET ISO8859_1, PAD SPACE, SYSTEM + EN_US, CHARACTER SET ISO8859_1, PAD SPACE, SYSTEM + ES_ES, CHARACTER SET ISO8859_1, PAD SPACE, 'DISABLE-COMPRESSIONS=1;SPECIALS-FIRST=1', SYSTEM + ES_ES_CI_AI, CHARACTER SET ISO8859_1, PAD SPACE, CASE INSENSITIVE, ACCENT INSENSITIVE, 'DISABLE-COMPRESSIONS=1;SPECIALS-FIRST=1', SYSTEM + EUCJ_0208, CHARACTER SET EUCJ_0208, PAD SPACE, SYSTEM + FI_FI, CHARACTER SET ISO8859_1, PAD SPACE, SYSTEM + FR_CA, CHARACTER SET ISO8859_1, PAD SPACE, SYSTEM + FR_CA_CI_AI, CHARACTER SET ISO8859_1, FROM EXTERNAL ('FR_CA'), PAD SPACE, CASE INSENSITIVE, ACCENT INSENSITIVE, 'SPECIALS-FIRST=1', SYSTEM + FR_FR, CHARACTER SET ISO8859_1, PAD SPACE, SYSTEM + FR_FR_CI_AI, CHARACTER SET ISO8859_1, FROM EXTERNAL ('FR_FR'), PAD SPACE, CASE INSENSITIVE, ACCENT INSENSITIVE, 'SPECIALS-FIRST=1', SYSTEM + GB18030, CHARACTER SET GB18030, PAD SPACE, SYSTEM + GB18030_UNICODE, CHARACTER SET GB18030, PAD SPACE, 'COLL-VERSION=153.88', SYSTEM + GBK, CHARACTER SET GBK, PAD SPACE, SYSTEM + GBK_UNICODE, CHARACTER SET GBK, PAD SPACE, 'COLL-VERSION=153.88', SYSTEM + GB_2312, CHARACTER SET GB_2312, PAD SPACE, SYSTEM + ISO8859_1, CHARACTER SET ISO8859_1, PAD SPACE, SYSTEM + ISO8859_13, CHARACTER SET ISO8859_13, PAD SPACE, SYSTEM + ISO8859_2, CHARACTER SET ISO8859_2, PAD SPACE, SYSTEM + ISO8859_3, CHARACTER SET ISO8859_3, PAD SPACE, SYSTEM + ISO8859_4, CHARACTER SET ISO8859_4, PAD SPACE, SYSTEM + ISO8859_5, CHARACTER SET ISO8859_5, PAD SPACE, SYSTEM + ISO8859_6, CHARACTER SET ISO8859_6, PAD SPACE, SYSTEM + ISO8859_7, CHARACTER SET ISO8859_7, PAD SPACE, SYSTEM + ISO8859_8, CHARACTER SET ISO8859_8, PAD SPACE, SYSTEM + ISO8859_9, CHARACTER SET ISO8859_9, PAD SPACE, SYSTEM + ISO_HUN, CHARACTER SET ISO8859_2, PAD SPACE, SYSTEM + ISO_PLK, CHARACTER SET ISO8859_2, PAD SPACE, SYSTEM + IS_IS, CHARACTER SET ISO8859_1, PAD SPACE, SYSTEM + IT_IT, CHARACTER SET ISO8859_1, PAD SPACE, SYSTEM + KOI8R, CHARACTER SET KOI8R, PAD SPACE, SYSTEM + KOI8R_RU, CHARACTER SET KOI8R, PAD SPACE, SYSTEM + KOI8U, CHARACTER SET KOI8U, PAD SPACE, SYSTEM + KOI8U_UA, CHARACTER SET KOI8U, PAD SPACE, SYSTEM + KSC_5601, CHARACTER SET KSC_5601, PAD SPACE, SYSTEM + KSC_DICTIONARY, CHARACTER SET KSC_5601, PAD SPACE, SYSTEM + LT_LT, CHARACTER SET ISO8859_13, PAD SPACE, SYSTEM + NEXT, CHARACTER SET NEXT, PAD SPACE, SYSTEM + NONE, CHARACTER SET NONE, PAD SPACE, SYSTEM + NO_NO, CHARACTER SET ISO8859_1, PAD SPACE, SYSTEM + NXT_DEU, CHARACTER SET NEXT, PAD SPACE, SYSTEM + NXT_ESP, CHARACTER SET NEXT, PAD SPACE, SYSTEM + NXT_FRA, CHARACTER SET NEXT, PAD SPACE, SYSTEM + NXT_ITA, CHARACTER SET NEXT, PAD SPACE, SYSTEM + NXT_US, CHARACTER SET NEXT, PAD SPACE, SYSTEM + OCTETS, CHARACTER SET OCTETS, PAD SPACE, SYSTEM + PDOX_ASCII, CHARACTER SET DOS437, PAD SPACE, SYSTEM + PDOX_CSY, CHARACTER SET DOS852, PAD SPACE, SYSTEM + PDOX_CYRL, CHARACTER SET CYRL, PAD SPACE, SYSTEM + PDOX_HUN, CHARACTER SET DOS852, PAD SPACE, SYSTEM + PDOX_INTL, CHARACTER SET DOS437, PAD SPACE, SYSTEM + PDOX_ISL, CHARACTER SET DOS861, PAD SPACE, SYSTEM + PDOX_NORDAN4, CHARACTER SET DOS865, PAD SPACE, SYSTEM + PDOX_PLK, CHARACTER SET DOS852, PAD SPACE, SYSTEM + PDOX_SLO, CHARACTER SET DOS852, PAD SPACE, SYSTEM + PDOX_SWEDFIN, CHARACTER SET DOS437, PAD SPACE, SYSTEM + PT_BR, CHARACTER SET ISO8859_1, PAD SPACE, CASE INSENSITIVE, ACCENT INSENSITIVE, SYSTEM + PT_PT, CHARACTER SET ISO8859_1, PAD SPACE, SYSTEM + PXW_CSY, CHARACTER SET WIN1250, PAD SPACE, SYSTEM + PXW_CYRL, CHARACTER SET WIN1251, PAD SPACE, SYSTEM + PXW_GREEK, CHARACTER SET WIN1253, PAD SPACE, SYSTEM + PXW_HUN, CHARACTER SET WIN1250, PAD SPACE, SYSTEM + PXW_HUNDC, CHARACTER SET WIN1250, PAD SPACE, SYSTEM + PXW_INTL, CHARACTER SET WIN1252, PAD SPACE, SYSTEM + PXW_INTL850, CHARACTER SET WIN1252, PAD SPACE, SYSTEM + PXW_NORDAN4, CHARACTER SET WIN1252, PAD SPACE, SYSTEM + PXW_PLK, CHARACTER SET WIN1250, PAD SPACE, SYSTEM + PXW_SLOV, CHARACTER SET WIN1250, PAD SPACE, SYSTEM + PXW_SPAN, CHARACTER SET WIN1252, PAD SPACE, SYSTEM + PXW_SWEDFIN, CHARACTER SET WIN1252, PAD SPACE, SYSTEM + PXW_TURK, CHARACTER SET WIN1254, PAD SPACE, SYSTEM + SJIS_0208, CHARACTER SET SJIS_0208, PAD SPACE, SYSTEM + SV_SV, CHARACTER SET ISO8859_1, PAD SPACE, SYSTEM + TIS620, CHARACTER SET TIS620, PAD SPACE, SYSTEM + TIS620_UNICODE, CHARACTER SET TIS620, PAD SPACE, 'COLL-VERSION=153.88', SYSTEM + UCS_BASIC, CHARACTER SET UTF8, PAD SPACE, SYSTEM + UNICODE, CHARACTER SET UTF8, PAD SPACE, 'COLL-VERSION=153.88', SYSTEM + UNICODE_CI, CHARACTER SET UTF8, FROM EXTERNAL ('UNICODE'), PAD SPACE, CASE INSENSITIVE, 'COLL-VERSION=153.88', SYSTEM + UNICODE_CI_AI, CHARACTER SET UTF8, FROM EXTERNAL ('UNICODE'), PAD SPACE, CASE INSENSITIVE, ACCENT INSENSITIVE, 'COLL-VERSION=153.88', SYSTEM + UNICODE_FSS, CHARACTER SET UNICODE_FSS, PAD SPACE, SYSTEM + UTF8, CHARACTER SET UTF8, PAD SPACE, SYSTEM + WIN1250, CHARACTER SET WIN1250, PAD SPACE, SYSTEM + WIN1251, CHARACTER SET WIN1251, PAD SPACE, SYSTEM + WIN1251_UA, CHARACTER SET WIN1251, PAD SPACE, SYSTEM + WIN1252, CHARACTER SET WIN1252, PAD SPACE, SYSTEM + WIN1253, CHARACTER SET WIN1253, PAD SPACE, SYSTEM + WIN1254, CHARACTER SET WIN1254, PAD SPACE, SYSTEM + WIN1255, CHARACTER SET WIN1255, PAD SPACE, SYSTEM + WIN1256, CHARACTER SET WIN1256, PAD SPACE, SYSTEM + WIN1257, CHARACTER SET WIN1257, PAD SPACE, SYSTEM + WIN1257_EE, CHARACTER SET WIN1257, PAD SPACE, SYSTEM + WIN1257_LT, CHARACTER SET WIN1257, PAD SPACE, SYSTEM + WIN1257_LV, CHARACTER SET WIN1257, PAD SPACE, SYSTEM + WIN1258, CHARACTER SET WIN1258, PAD SPACE, SYSTEM + WIN_CZ, CHARACTER SET WIN1250, PAD SPACE, CASE INSENSITIVE, SYSTEM + WIN_CZ_CI_AI, CHARACTER SET WIN1250, PAD SPACE, CASE INSENSITIVE, ACCENT INSENSITIVE, SYSTEM + WIN_PTBR, CHARACTER SET WIN1252, PAD SPACE, CASE INSENSITIVE, ACCENT INSENSITIVE, SYSTEM + """ + +@pytest.mark.version('>=4.0') +def test_isql_03_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/functional/basic/isql/test_05.py b/tests/functional/basic/isql/test_05.py new file mode 100644 index 00000000..2145b26b --- /dev/null +++ b/tests/functional/basic/isql/test_05.py @@ -0,0 +1,76 @@ +#coding:utf-8 +# +# id: functional.basic.isql.isql_05 +# title: ISQL should be able to process single statement with length up to 10*1024*1024 chars +# decription: +# Source sample see in CORE-5382 ("Incorrect processing (truncation) of SQL statement with length 10MB+1"). +# Test prepares script with two SELECT statements: +# One of them has length EXACTLY equal to 10*1024*1024 chars (excluding final ';'), another length = 10Mb + 1. +# First statement should be executed OK, second should fail. +# Checked on WI-V3.0.2.32625, WI-T4.0.0.440 +# +# PS. Best place of this test in functional/basic/isql/ folder rather than in 'bugs' one. +# +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('After line .*', ''), ('-At line.*', ''), ('At line.*', '')] + +init_script_1 = """ + recreate table dua(i int); + insert into dua(i) values(1); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import subprocess +# import fdb +# +# db_conn.close() +# +# dml_pref='select /*' +# dml_suff='*/ %s i from rdb$database;' +# +# # prepare DB for testing: create lot of tables: +# ############################################### +# f_work_sql=open( os.path.join(context['temp_directory'],'tmp_work_5382.sql'), 'w') +# f_work_sql.write('set list on;' + os.linesep) +# f_work_sql.write( (dml_pref.ljust(10485729,'-') + dml_suff) % (10485760) ) +# f_work_sql.write( (dml_pref.ljust(10485730,'-') + dml_suff) % (10485761) ) +# f_work_sql.close() +# +# runProgram('isql',[dsn,'-user',user_name,'-pas',user_password,'-i',f_work_sql.name]) +# os.remove(f_work_sql.name) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + I 10485760 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 54000 + Dynamic SQL Error + -SQL error code = -902 + -Implementation limit exceeded + -SQL statement is too long. Maximum size is 10485760 bytes. + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_isql_05_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/database/__init__.py b/tests/functional/database/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/database/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/database/alter/test_01.py b/tests/functional/database/alter/test_01.py new file mode 100644 index 00000000..a5301ca6 --- /dev/null +++ b/tests/functional/database/alter/test_01.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: functional.database.alter_01 +# title: Alter database: adding a secondary file +# decription: Adding a secondary file to the database +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [('^.*TEST.G', 'TEST.G'), ('[ ]+', '\t')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# cursor=db_conn.cursor() +# cursor.execute("ALTER DATABASE ADD FILE '$(DATABASE_LOCATION)TEST.G00' STARTING 10000") +# db_conn.commit() +# cursor=db_conn.cursor() +# cursor.execute("SELECT cast(RDB$FILE_NAME as varchar(150)),RDB$FILE_SEQUENCE,RDB$FILE_START,RDB$FILE_LENGTH FROM RDB$FILES") +# printData(cursor) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """CAST RDB$FILE_SEQUENCE RDB$FILE_START RDB$FILE_LENGTH +------------------------------------------------------------------------------------------------------------------------------------------------------ ----------------- -------------- --------------- +C:\\JOB\\QA\\FBTEST\\TMP\\TEST.G00 1 10000 0 +""" + +@pytest.mark.version('>=1.0') +@pytest.mark.xfail +def test_alter_01_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/database/alter/test_02.py b/tests/functional/database/alter/test_02.py new file mode 100644 index 00000000..94eaed28 --- /dev/null +++ b/tests/functional/database/alter/test_02.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: functional.database.alter_02 +# title: ALter database: adding secondary file with alternate keyword +# decription: Adding secondary file with alternate keyword for database. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [('^.*TEST.G', 'TEST.G'), ('[ ]+', '\t')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# cursor=db_conn.cursor() +# cursor.execute("ALTER SCHEMA ADD FILE '$(DATABASE_LOCATION)TEST.G00' STARTING 10000") +# db_conn.commit() +# cursor.execute("SELECT cast(RDB$FILE_NAME as varchar(150)),RDB$FILE_SEQUENCE,RDB$FILE_START,RDB$FILE_LENGTH FROM RDB$FILES") +# printData(cursor) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """CAST RDB$FILE_SEQUENCE RDB$FILE_START RDB$FILE_LENGTH +------------------------------------------------------------------------------------------------------------------------------------------------------ ----------------- -------------- --------------- +C:\\JOB\\QA\\FBTEST\\TMP\\TEST.G00 1 10000 0 +""" + +@pytest.mark.version('>=1.0') +@pytest.mark.xfail +def test_alter_02_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/database/alter/test_03.py b/tests/functional/database/alter/test_03.py new file mode 100644 index 00000000..6ec1aebe --- /dev/null +++ b/tests/functional/database/alter/test_03.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: functional.database.alter_03 +# title: Alter database: add file with name of this database or previously added files must fail +# decription: Add same file twice must fail +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# cursor=db_conn.cursor() +# cursor.execute("ALTER DATABASE ADD FILE '$(DATABASE_LOCATION)TEST.G00' STARTING 10000") +# db_conn.commit() +# try: +# cursor=db_conn.cursor() +# cursor.execute("ALTER DATABASE ADD FILE '$(DATABASE_LOCATION)TEST.G00' STARTING 20000") +# db_conn.commit() +# except kdb.DatabaseError, e: +# print (e[0]) +# except: +# print ("Unexpected exception",sys.exc_info()[0]) +# print ("Arguments",sys.exc_info()[1]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Error while executing SQL statement: + - SQLCODE: -607 + - unsuccessful metadata update + - ALTER DATABASE failed + - Cannot add file with the same name as the database or added files + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_alter_03_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/database/create/__init__.py b/tests/functional/database/create/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/database/create/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/database/create/test_01.py b/tests/functional/database/create/test_01.py new file mode 100644 index 00000000..9fca5e0f --- /dev/null +++ b/tests/functional/database/create/test_01.py @@ -0,0 +1,77 @@ +#coding:utf-8 +# +# id: functional.database.create_01 +# title: +# Check ability to specify SET NAMES and DEFAULT CHARACTER SET within one statement. +# Checked on: +# 4.0.0.1740 SS: 1.157s. +# 3.0.6.33236 SS: 0.808s. +# 2.5.9.27149 SC: 0.508s. +# NOTE: name of client charset must be enclosed in apostrophes, i.e.: create database ... set names 'win1251' ... +# +# decription: +# tracker_id: +# min_versions: ['2.5'] +# versions: 2.5.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import fdb +# +# +# test_db="".join([context[db_path_property], "tmp_create_db_01.fdb"]) +# if os.path.isfile(test_db): +# os.remove(test_db) +# +# db_conn.close() +# +# sql_ddl = "create database 'localhost:%(test_db)s' user '%(user_name)s' password '%(user_password)s' set names 'win1251' default character set utf8" % dict(globals(), **locals()) +# +# con = fdb.create_database( sql_ddl ) +# +# cur = con.cursor() +# sql=''' +# 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 +# ''' +# +# cur.execute(sql); +# +# hdr=cur.description +# for r in cur: +# for i in range(0,len(hdr)): +# print( hdr[i][0],':', r[i] ) +# +# con.commit() +# con.drop_database() +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CLIENT_CHAR_SET : WIN1251 + DB_CHAR_SET : UTF8 + """ + +@pytest.mark.version('>=2.5.0') +@pytest.mark.xfail +def test_create_01_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/database/create/test_02.py b/tests/functional/database/create/test_02.py new file mode 100644 index 00000000..518c6006 --- /dev/null +++ b/tests/functional/database/create/test_02.py @@ -0,0 +1,73 @@ +#coding:utf-8 +# +# id: functional.database.create_02 +# title: CREATE DATABASE - non sysdba user +# decription: +# tracker_id: +# min_versions: ['2.1.7'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set wng off; + set bail on; + create or alter user ozzy password 'osb' revoke admin role; + commit; + revoke all on all from ozzy; + commit; + + -- ::: 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; + + drop database; + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; + revoke create database from user ozzy; + revoke drop database from user ozzy; + drop user ozzy; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Who am I ? OZZY + Am I on just created DB ? YES + """ + +@pytest.mark.version('>=3.0') +def test_create_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/database/create/test_03.py b/tests/functional/database/create/test_03.py new file mode 100644 index 00000000..873296c7 --- /dev/null +++ b/tests/functional/database/create/test_03.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: functional.database.create_03 +# title: CREATE DATABASE - PAGE SIZE 1024 +# decription: +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!PAGE_SIZE).)*$', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=1024, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select mon$page_size as page_size from mon$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PAGE_SIZE 4096 + """ + +@pytest.mark.version('>=3.0') +def test_create_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/database/create/test_04.py b/tests/functional/database/create/test_04.py new file mode 100644 index 00000000..5c4a1cbd --- /dev/null +++ b/tests/functional/database/create/test_04.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: functional.database.create_04 +# title: CREATE DATABASE - PAGE SIZE 2048 +# decription: +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!PAGE_SIZE).)*$', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=2048, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select mon$page_size as page_size from mon$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PAGE_SIZE 4096 + """ + +@pytest.mark.version('>=3.0') +def test_create_04_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/database/create/test_05.py b/tests/functional/database/create/test_05.py new file mode 100644 index 00000000..6153e8c5 --- /dev/null +++ b/tests/functional/database/create/test_05.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: functional.database.create_05 +# title: CREATE DATABASE - PAGE SIZE 4096 +# decription: +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!PAGE_SIZE).)*$', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select mon$page_size as page_size from mon$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PAGE_SIZE 4096 + """ + +@pytest.mark.version('>=3.0') +def test_create_05_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/database/create/test_06.py b/tests/functional/database/create/test_06.py new file mode 100644 index 00000000..d50cf07d --- /dev/null +++ b/tests/functional/database/create/test_06.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: functional.database.create_06 +# title: CREATE DATABASE - PAGE SIZE 8192 +# decription: +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!PAGE_SIZE).)*$', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=8192, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select mon$page_size as page_size from mon$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PAGE_SIZE 8192 + """ + +@pytest.mark.version('>=3.0') +def test_create_06_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/database/create/test_07.py b/tests/functional/database/create/test_07.py new file mode 100644 index 00000000..27b3509d --- /dev/null +++ b/tests/functional/database/create/test_07.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: functional.database.create_07 +# title: CREATE DATABASE - PAGE SIZE 16384 +# decription: +# tracker_id: +# min_versions: [] +# versions: 3.0, 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^((?!PAGE_SIZE).)*$', '')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=16384, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select mon$page_size as page_size from mon$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PAGE_SIZE 16384 + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_create_07_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [('^((?!PAGE_SIZE).)*$', '')] + +init_script_2 = """""" + +db_2 = db_factory(page_size=32768, sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set list on; + select mon$page_size as page_size from mon$database; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + PAGE_SIZE 32768 + """ + +@pytest.mark.version('>=4.0') +def test_create_07_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/functional/database/create/test_08.py b/tests/functional/database/create/test_08.py new file mode 100644 index 00000000..043174e6 --- /dev/null +++ b/tests/functional/database/create/test_08.py @@ -0,0 +1,68 @@ +#coding:utf-8 +# +# id: functional.database.create_08 +# title: +# CREATE DATABASE - Multi file DB +# Checked on: +# 2.5.9.27126: OK, 0.750s. +# 3.0.5.33086: OK, 2.078s. +# 4.0.0.1378: OK, 8.500s. +# +# decription: +# tracker_id: +# min_versions: ['2.5'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('^.*TMP_CREATE_DB_08.F00', 'TMP_CREATE_DB_08.F00'), ('[ ]+', '\t')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# dsn = "".join([context["server_location"], +# context[db_path_property], +# "TMP_CREATE_DB_08.FDB"]) +# +# file1 = "".join([context[db_path_property], "TMP_CREATE_DB_08.F00"]) +# +# createCommand = "CREATE DATABASE '%s' LENGTH 300 USER '%s' PASSWORD '%s' FILE '%s' LENGTH 300" % (dsn, user_name, user_password, file1) +# +# db_conn= kdb.create_database(createCommand, int(sql_dialect)) +# +# sql=''' +# set list on; +# select +# cast(rdb$file_name as varchar(60)) db_file +# ,rdb$file_sequence +# ,rdb$file_start +# ,rdb$file_length +# from rdb$files +# ; +# ''' +# runProgram('isql',[dsn,'-user',user_name,'-pas',user_password],sql) +# db_conn.drop_database() +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TMP_CREATE_DB_08.F00 + RDB$FILE_SEQUENCE 1 + RDB$FILE_START 301 + RDB$FILE_LENGTH 300 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_create_08_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/database/create/test_09.py b/tests/functional/database/create/test_09.py new file mode 100644 index 00000000..f925ba8e --- /dev/null +++ b/tests/functional/database/create/test_09.py @@ -0,0 +1,83 @@ +#coding:utf-8 +# +# id: functional.database.create_09 +# title: CREATE DATABASE - Multi file DB +# decription: +# Create database with four files. +# Checked on: +# 2.5.9.27126: OK, 0.875s. +# 3.0.5.33086: OK, 5.797s. +# 4.0.0.1378: OK, 8.468s. +# +# tracker_id: +# min_versions: ['2.5'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('^.*TMP_CREATE_DB_09.F0', 'TMP_CREATE_DB_09.F0'), ('[ ]+', '\t')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# dsn = "".join([context["server_location"], +# context[db_path_property], +# "TMP_CREATE_DB_09.FDB"]) +# +# DB_FILE1 = "".join([context[db_path_property], "TMP_CREATE_DB_09.F00"]) +# DB_FILE2 = "".join([context[db_path_property], "TMP_CREATE_DB_09.F01"]) +# DB_FILE3 = "".join([context[db_path_property], "TMP_CREATE_DB_09.F02"]) +# +# DB_USER=user_name +# DB_PSWD=user_password +# DB_FILE_LEN=300 +# +# createCommand = "CREATE DATABASE '%s' LENGTH 300 USER '%s' PASSWORD '%s' FILE '%s' LENGTH 300 FILE '%s' LENGTH 300 FILE '%s' LENGTH 300" % (dsn, user_name, user_password, DB_FILE1, DB_FILE2, DB_FILE3 ) +# db_conn= kdb.create_database(createCommand, int(sql_dialect)) +# +# sql=''' +# set list on; +# select +# cast(rdb$file_name as varchar(60)) db_file +# ,rdb$file_sequence +# ,rdb$file_start +# ,rdb$file_length +# from rdb$files +# ; +# ''' +# runProgram('isql',[dsn,'-user',user_name,'-pas',user_password],sql) +# +# db_conn.drop_database() +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TMP_CREATE_DB_09.F00 + RDB$FILE_SEQUENCE 1 + RDB$FILE_START 301 + RDB$FILE_LENGTH 300 + TMP_CREATE_DB_09.F01 + RDB$FILE_SEQUENCE 2 + RDB$FILE_START 601 + RDB$FILE_LENGTH 300 + TMP_CREATE_DB_09.F02 + RDB$FILE_SEQUENCE 3 + RDB$FILE_START 901 + RDB$FILE_LENGTH 300 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_create_09_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/database/create/test_10.py b/tests/functional/database/create/test_10.py new file mode 100644 index 00000000..424573d2 --- /dev/null +++ b/tests/functional/database/create/test_10.py @@ -0,0 +1,139 @@ +#coding:utf-8 +# +# id: functional.database.create_10 +# title: CREATE DATABASE - Multi file DB - starting +# decription: +# Database with four files. Additional files specified by STARTING AT. +# Checked on: +# 2.5.9.27126: OK, 1.610s. +# 3.0.5.33086: OK, 2.047s. +# 4.0.0.1378: OK, 7.266s. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 3.0, 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('^.*TMP_CREATE_DB_10.F0', 'TMP_CREATE_DB_10.F0'), ('[ ]+', '\t')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# dsn = "".join([context["server_location"], +# context[db_path_property], +# "TMP_CREATE_DB_10.FDB"]) +# +# file1 = "".join([context[db_path_property], "TMP_CREATE_DB_10.F00"]) +# file2 = "".join([context[db_path_property], "TMP_CREATE_DB_10.F01"]) +# file3 = "".join([context[db_path_property], "TMP_CREATE_DB_10.F02"]) +# +# createCommand = "CREATE DATABASE '%s' USER '%s' PASSWORD '%s' FILE '%s' STARTING AT PAGE 201 FILE '%s' STARTING AT PAGE 601 FILE '%s' STARTING AT PAGE 1001" % (dsn, user_name, user_password, file1, file2, file3) +# +# db_conn= kdb.create_database(createCommand, int(sql_dialect)) +# +# sql=''' +# set list on; +# select +# cast(rdb$file_name as varchar(60)) db_file +# ,rdb$file_sequence +# ,rdb$file_start +# ,rdb$file_length +# from rdb$files +# ; +# ''' +# runProgram('isql',[dsn,'-user',user_name,'-pas',user_password],sql) +# +# db_conn.drop_database() +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TMP_CREATE_DB_10.F00 + RDB$FILE_SEQUENCE 1 + RDB$FILE_START 201 + RDB$FILE_LENGTH 400 + TMP_CREATE_DB_10.F01 + RDB$FILE_SEQUENCE 2 + RDB$FILE_START 601 + RDB$FILE_LENGTH 400 + TMP_CREATE_DB_10.F02 + RDB$FILE_SEQUENCE 3 + RDB$FILE_START 1001 + RDB$FILE_LENGTH 0 + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_create_10_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + +# version: 4.0 +# resources: None + +substitutions_2 = [('^.*TMP_CREATE_DB_10.F0', 'TMP_CREATE_DB_10.F0'), ('[ ]+', '\t')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +# test_script_2 +#--- +# dsn = "".join([context["server_location"], +# context[db_path_property], +# "TMP_CREATE_DB_10.FDB"]) +# +# file1 = "".join([context[db_path_property], "TMP_CREATE_DB_10.F00"]) +# file2 = "".join([context[db_path_property], "TMP_CREATE_DB_10.F01"]) +# file3 = "".join([context[db_path_property], "TMP_CREATE_DB_10.F02"]) +# +# createCommand = "CREATE DATABASE '%s' USER '%s' PASSWORD '%s' FILE '%s' STARTING AT PAGE 301 FILE '%s' STARTING AT PAGE 801 FILE '%s' STARTING AT PAGE 1301" % (dsn, user_name, user_password, file1, file2, file3) +# +# db_conn= kdb.create_database(createCommand, int(sql_dialect)) +# +# sql=''' +# set list on; +# select +# cast(rdb$file_name as varchar(60)) db_file +# ,rdb$file_sequence +# ,rdb$file_start +# ,rdb$file_length +# from rdb$files +# ; +# ''' +# runProgram('isql',[dsn,'-user',user_name,'-pas',user_password],sql) +# +# db_conn.drop_database() +#--- +#act_2 = python_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + TMP_CREATE_DB_10.F00 + RDB$FILE_SEQUENCE 1 + RDB$FILE_START 301 + RDB$FILE_LENGTH 500 + TMP_CREATE_DB_10.F01 + RDB$FILE_SEQUENCE 2 + RDB$FILE_START 801 + RDB$FILE_LENGTH 500 + TMP_CREATE_DB_10.F02 + RDB$FILE_SEQUENCE 3 + RDB$FILE_START 1301 + RDB$FILE_LENGTH 0 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_create_10_2(db_2): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/database/create/test_11.py b/tests/functional/database/create/test_11.py new file mode 100644 index 00000000..473ee992 --- /dev/null +++ b/tests/functional/database/create/test_11.py @@ -0,0 +1,37 @@ +#coding:utf-8 +# +# id: functional.database.create.11 +# title: CREATE DATABASE - Default char set NONE +# decription: This test should be implemented for all char sets. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT RDB$CHARACTER_SET_NAME FROM rdb$Database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$CHARACTER_SET_NAME + NONE + """ + +@pytest.mark.version('>=2.0') +def test_11_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/datatypes/__init__.py b/tests/functional/datatypes/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/datatypes/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/datatypes/test_decfloat_binding_to_legacy.py b/tests/functional/datatypes/test_decfloat_binding_to_legacy.py new file mode 100644 index 00000000..424a3fbe --- /dev/null +++ b/tests/functional/datatypes/test_decfloat_binding_to_legacy.py @@ -0,0 +1,132 @@ +#coding:utf-8 +# +# id: functional.datatypes.decfloat_binding_to_legacy +# title: Test ability for DECFLOAT values to be represented as other data types using LEGACY keyword. +# decription: +# We check here that values from DECFLOAT will be actually converted to legacy datatypes +# according to following table from sql.extensions\\README.set_bind.md: +# ---------------------------------------------------------- +# | Native datatype | Legacy datatype | +# |--------------------------|-----------------------------| +# | BOOLEAN | CHAR(5) | +# | DECFLOAT | DOUBLE PRECISION | +# | NUMERIC(38) | NUMERIC(18) | +# | TIME WITH TIME ZONE | TIME WITHOUT TIME ZONE | +# | TIMESTAMP WITH TIME ZONE | TIMESTAMP WITHOUT TIME ZONE | +# ---------------------------------------------------------- +# SQLDA must contain the same datatypes when we use either explicit rule or LEGACY keyword. +# Checked on 4.0.0.1691 SS: 1.113s. +# +# WARNING, 11.03.2020. +# Test verifies binding of TIME WITH TIMEZONE data and uses America/Los_Angeles timezone. +# But there is daylight saving time in the USA, they change clock at the begining of March. +# +# For this reason query like: "select time '10:00 America/Los_Angeles' from ..." will return +# different values depending on current date. For example, if we are in Moscow timezone then +# returned value will be either 20:00 in February or 21:00 in March. +# Result for other timezone (e.g. Tokyo) will be differ, etc. +# For this reason, special replacement will be done in 'substitution' section: we replace +# value of hours with '??' because it is no matter what's the time there, we have to ensure +# only the ability to work with such time using SET BIND clause. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [(' \\d{2}:00:00.0000', ' ??:00:00.0000'), ('charset.*', ''), ('.*alias:.*', ''), ('^((?!(sqltype|check_bind_)).)*$', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + --set bail on; + --set echo on; + set sqlda_display on; + + -- Legacy, explicit and implicit: + set bind of boolean to char(5); + select not false and true as "check_bind_bool_to_char" from rdb$database; + + set bind of boolean to legacy; + select not false and true as "check_bind_bool_to_legacy" from rdb$database; + + + set bind of decfloat to double precision; + select 3.141592653589793238462643383279502884197169399375105820974944592307816406286 as "check_bind_decfloat_to_double" from rdb$database; + + set bind of decfloat to legacy; + select 3.141592653589793238462643383279502884197169399375105820974944592307816406286 as "check_bind_decfloat_to_legacy" from rdb$database; + + + set bind of numeric(38) to numeric(18); -- this is mentioned in http://tracker.firebirdsql.org/browse/CORE-6057 + select 3.141592653589793238462643383279502884197169399375105820974944592307816406286 as "check_bind_n38_to_n18" from rdb$database; + + set bind of numeric(38) to legacy; + select 3.141592653589793238462643383279502884197169399375105820974944592307816406286 as "check_bind_n38_to_legacy" from rdb$database; + + + set bind of time with time zone to time without time zone; + select time '10:00 America/Los_Angeles' as "check_bind_time_with_zone_to_time" from rdb$database; + + set bind of time with time zone to legacy; + select time '10:00 America/Los_Angeles' as "check_bind_time_with_zone_to_legacy" from rdb$database; + + + set bind of timestamp with time zone to timestamp without time zone; + select timestamp '2018-01-01 12:00 GMT' as "check_bind_timestamp_with_zone_to_timestamp" from rdb$database; + + set bind of timestamp with time zone to legacy; + select timestamp '2018-01-01 12:00 GMT' as "check_bind_timestamp_with_zone_to_legacy" from rdb$database; + + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 01: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 5 + check_bind_bool_to_char TRUE + + 01: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 5 + check_bind_bool_to_legacy TRUE + + 01: sqltype: 480 DOUBLE scale: 0 subtype: 0 len: 8 + check_bind_decfloat_to_double 3.141592653589793 + + 01: sqltype: 480 DOUBLE scale: 0 subtype: 0 len: 8 + check_bind_decfloat_to_legacy 3.141592653589793 + + 01: sqltype: 480 DOUBLE scale: 0 subtype: 0 len: 8 + check_bind_n38_to_n18 3.141592653589793 + + 01: sqltype: 480 DOUBLE scale: 0 subtype: 0 len: 8 + check_bind_n38_to_legacy 3.141592653589793 + + 01: sqltype: 560 TIME scale: 0 subtype: 0 len: 4 + check_bind_time_with_zone_to_time ??:00:00.0000 + + 01: sqltype: 560 TIME scale: 0 subtype: 0 len: 4 + check_bind_time_with_zone_to_legacy ??:00:00.0000 + + 01: sqltype: 510 TIMESTAMP scale: 0 subtype: 0 len: 8 + check_bind_timestamp_with_zone_to_timestamp 2018-01-01 ??:00:00.0000 + + 01: sqltype: 510 TIMESTAMP scale: 0 subtype: 0 len: 8 + check_bind_timestamp_with_zone_to_legacy 2018-01-01 ??:00:00.0000 + """ + +@pytest.mark.version('>=4.0') +def test_decfloat_binding_to_legacy_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/datatypes/test_decfloat_binding_to_other_types.py b/tests/functional/datatypes/test_decfloat_binding_to_other_types.py new file mode 100644 index 00000000..76f9ab57 --- /dev/null +++ b/tests/functional/datatypes/test_decfloat_binding_to_other_types.py @@ -0,0 +1,125 @@ +#coding:utf-8 +# +# id: functional.datatypes.decfloat_binding_to_other_types +# title: Test ability for DECFLOAT values to be represented as other data types (char, double, bigint). +# decription: +# See CORE-5535 and doc\\sql.extensions\\README.data_types: +# --- +# SET DECFLOAT BIND - controls how are DECFLOAT values represented in outer +# world (i.e. in messages or in XSQLDA). Valid binding types are: NATIVE (use IEEE754 +# binary representation), CHAR/CHARACTER (use ASCII string), DOUBLE PRECISION (use +# 8-byte FP representation - same as used for DOUBLE PRECISION fields) or BIGINT +# with possible comma-separated SCALE clause (i.e. 'BIGINT, 3'). +# --- +# FB40SS, build 4.0.0.651: OK, 0.921s. +# +# ::: NB :::: +# Temply deferred check of "set decfloat bind bigint, 3" when value has at least one digit in floating part. +# Also, one need to check case when we try to bind to BIGINT value that is too big for it (say, more than 19 digits). +# Waiting for reply from Alex, letters 25.05.2017 21:12 & 21:22. +# +# +# 10.12.2019. Updated syntax for SET BIND command because it was changed in 11-nov-2019. +# Replaced 'bigint,3' with numeric(18,3) - can not specify scale using comma delimiter, i.e. ",3" +# Checked on: WI-T4.0.0.1685. +# +# 27.12.2019. Updated expected_stdout after discuss with Alex: subtype now must be zero in all cases. +# Checked on: WI-T4.0.0.1710. +# +# 25.06.2020, 4.0.0.2076: changed types in SQLDA from numeric to int128 // after discuss with Alex about CORE-6342. +# 01.07.2020, 4.0.0.2084: adjusted expected output ('subtype' values). Added SET BIND from decfloat to INT128. +# Removed unnecessary lines from output and added substitution section for result to be properly filtered. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('^((?!sqltype|DECFLOAT_TO_).)*$', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set sqlda_display on; + + -- set decfloat bind char; + set bind of decfloat to char; + select 123456789012345678901234567890.1234 as decfloat_to_char + from rdb$database; + + -- set decfloat bind double precision; + set bind of decfloat to double precision; + select 123456789012345678901234567890.1234 as decfloat_to_double + from rdb$database; + + -- set decfloat bind bigint; + set bind of decfloat to bigint; + select 1234567890123456789.1234 as decfloat_to_bigint + from rdb$database; + + -- set decfloat bind bigint, 0; + set bind of decfloat to numeric(18,0); + select 1234567890123456789.1234 as decfloat_to_bigint_0 + from rdb$database; + + + -- Alex' samples, letter 25.05.2017 21:56 + -- set decfloat bind bigint, 3; + set bind of decfloat to numeric(18,3); + select cast(1234.5678 as decfloat(16)) as decfloat_to_bigint_3 + from rdb$database; -- 1234.568 + + + -- set decfloat bind bigint, 8; + set bind of decfloat to numeric(18,8); + select cast(1234.5678 as decfloat(16)) as decfloat_to_bigint_9 + from rdb$database; -- 1234.56780000 + + set bind of decfloat to int128; + -- -170141183460469231731687303715884105728 ; 170141183460469231731687303715884105727 + select cast( 1701411834604692317316873037158841.05727 as decfloat(34)) as decfloat_to_int128 + from rdb$database; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 01: sqltype: 32752 INT128 scale: -4 subtype: 0 len: 16 + : name: CONSTANT alias: DECFLOAT_TO_CHAR + DECFLOAT_TO_CHAR 123456789012345678901234567890.1234 + 01: sqltype: 32752 INT128 scale: -4 subtype: 0 len: 16 + : name: CONSTANT alias: DECFLOAT_TO_DOUBLE + DECFLOAT_TO_DOUBLE 123456789012345678901234567890.1234 + 01: sqltype: 32752 INT128 scale: -4 subtype: 0 len: 16 + : name: CONSTANT alias: DECFLOAT_TO_BIGINT + DECFLOAT_TO_BIGINT 1234567890123456789.1234 + 01: sqltype: 32752 INT128 scale: -4 subtype: 0 len: 16 + : name: CONSTANT alias: DECFLOAT_TO_BIGINT_0 + DECFLOAT_TO_BIGINT_0 1234567890123456789.1234 + 01: sqltype: 580 INT64 scale: -3 subtype: 1 len: 8 + : name: CAST alias: DECFLOAT_TO_BIGINT_3 + DECFLOAT_TO_BIGINT_3 1234.568 + 01: sqltype: 580 INT64 scale: -8 subtype: 1 len: 8 + : name: CAST alias: DECFLOAT_TO_BIGINT_9 + DECFLOAT_TO_BIGINT_9 1234.56780000 + 01: sqltype: 32752 INT128 scale: 0 subtype: 0 len: 16 + : name: CAST alias: DECFLOAT_TO_INT128 + DECFLOAT_TO_INT128 1701411834604692317316873037158841 + """ + +@pytest.mark.version('>=4.0') +def test_decfloat_binding_to_other_types_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/datatypes/test_decfloat_boundary_values.py b/tests/functional/datatypes/test_decfloat_boundary_values.py new file mode 100644 index 00000000..ec554292 --- /dev/null +++ b/tests/functional/datatypes/test_decfloat_boundary_values.py @@ -0,0 +1,88 @@ +#coding:utf-8 +# +# id: functional.datatypes.decfloat_boundary_values +# title: Check BOUNDARY values that are defined for DECFLOAT datatype. +# decription: +# See CORE-5535 and doc\\sql.extensions\\README.data_types +# FB40CS, build 4.0.0.651: OK, 1.906ss +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[\\s]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + with + c as ( + select + cast(-9.999999999999999E384 as decfloat(16)) as min_df16_for_neg_scope + ,cast(-1.0E-383 as decfloat(16)) as max_df16_for_neg_scope + ,cast(1.0E-383 as decfloat(16)) as min_df16_for_pos_scope + ,cast( 9.999999999999999E384 as decfloat(16)) as max_df16_for_pos_scope + ,cast(-9.999999999999999999999999999999999E6144 as decfloat(34)) as min_df34_for_neg_scope + ,cast(-1.0E-6143 as decfloat(34)) as max_df34_for_neg_scope + ,cast(1.0E-6143 as decfloat(34)) as min_df34_for_pos_scope + ,cast( 9.999999999999999999999999999999999E6144 as decfloat(34)) as max_df34_for_pos_scope + from rdb$database + ) + select + c.min_df16_for_neg_scope + ,c.max_df16_for_neg_scope + ,c.min_df16_for_pos_scope + ,c.max_df16_for_pos_scope + ,c.min_df34_for_neg_scope + ,c.max_df34_for_neg_scope + ,c.min_df34_for_pos_scope + ,c.max_df34_for_pos_scope + ,c.min_df16_for_neg_scope - c.min_df16_for_neg_scope as zero_min_df16_for_neg + ,c.max_df16_for_neg_scope - c.max_df16_for_neg_scope as zero_max_df16_for_neg + ,c.min_df16_for_pos_scope - c.min_df16_for_pos_scope as zero_min_df16_for_pos + ,c.max_df16_for_pos_scope - c.max_df16_for_pos_scope as zero_max_df16_for_pos + ,c.min_df34_for_neg_scope - c.min_df34_for_neg_scope as zero_min_df34_for_neg + ,c.max_df34_for_neg_scope - c.max_df34_for_neg_scope as zero_max_df34_for_neg + ,c.min_df34_for_pos_scope - c.min_df34_for_pos_scope as zero_min_df34_for_pos + ,c.max_df34_for_pos_scope - c.max_df34_for_pos_scope as zero_max_df34_for_pos + from c + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MIN_DF16_FOR_NEG_SCOPE -9.999999999999999E+384 + MAX_DF16_FOR_NEG_SCOPE -1.0E-383 + MIN_DF16_FOR_POS_SCOPE 1.0E-383 + MAX_DF16_FOR_POS_SCOPE 9.999999999999999E+384 + MIN_DF34_FOR_NEG_SCOPE -9.999999999999999999999999999999999E+6144 + MAX_DF34_FOR_NEG_SCOPE -1.0E-6143 + MIN_DF34_FOR_POS_SCOPE 1.0E-6143 + MAX_DF34_FOR_POS_SCOPE 9.999999999999999999999999999999999E+6144 + ZERO_MIN_DF16_FOR_NEG 0E+369 + ZERO_MAX_DF16_FOR_NEG 0E-384 + ZERO_MIN_DF16_FOR_POS 0E-384 + ZERO_MAX_DF16_FOR_POS 0E+369 + ZERO_MIN_DF34_FOR_NEG 0E+6111 + ZERO_MAX_DF34_FOR_NEG 0E-6144 + ZERO_MIN_DF34_FOR_POS 0E-6144 + ZERO_MAX_DF34_FOR_POS 0E+6111 + """ + +@pytest.mark.version('>=4.0') +def test_decfloat_boundary_values_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/datatypes/test_decfloat_columns_handlng.py b/tests/functional/datatypes/test_decfloat_columns_handlng.py new file mode 100644 index 00000000..f4c3c669 --- /dev/null +++ b/tests/functional/datatypes/test_decfloat_columns_handlng.py @@ -0,0 +1,144 @@ +#coding:utf-8 +# +# id: functional.datatypes.decfloat_columns_handlng +# title: Check ability of misc. actions against table column for DECFLOAT datatype. +# decription: +# See CORE-5535 and doc\\sql.extensions\\README.data_types +# FB40CS, build 4.0.0.651: OK, 2.203ss. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + recreate table test(id int, x decfloat(16)); + commit; + + set term ^; + execute block as + begin + begin + execute statement 'drop domain dm_df16'; + when any do begin end + end + begin + execute statement 'drop domain dm_df34'; + when any do begin end + end + end + ^ + set term ;^ + commit; + + create domain dm_df16 as decfloat(16) default -9.999999999999999E384; + create domain dm_df34 as decfloat(34) default -9.999999999999999999999999999999999E6144; + commit; + + -- check ability to alter column of a table when initially datatype was numeric or double precision: + recreate table test( + id bigint default 9223372036854775807 + ,n numeric(18,2) + ,x double precision + ); + + recreate table test2( + id bigint + ,n dm_df16 + ,x dm_df34 + ); + + + recreate table test3( + id dm_df16 + ,n dm_df34 + ,x dm_df16 + ); + + commit; + + + alter table test + alter column n type dm_df34, + alter column x type dm_df16; + commit; + + + -- Should FAIL with: + -- - Conversion from base type DECFLOAT(34) to DECFLOAT(16) is not supported. + alter table test alter n type decfloat(16); + + commit; + + + -- Check that one may insert default values: + insert into test default values returning id, n, x; + commit; + + set count on; + --set echo on; + + --insert into test2 select * from test; + --show table test; + --show table test3; + + insert into test2 select * from test; -- should FAIL + + insert into test3 + select + cast(id as decfloat(16))*id*id*id*id*id*id*id*id*id*id*id*id*id*id*id*id*id*id*id, + -n, + -x + from test; -- should PASS + + set count off; + select * from test3; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 9223372036854775807 + N -9.999999999999999999999999999999999E+6144 + X -9.999999999999999E+384 + + Records affected: 0 + Records affected: 1 + + ID 1.985155524189834E+379 + N 9.999999999999999999999999999999999E+6144 + X 9.999999999999999E+384 + + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER TABLE TEST failed + -Cannot change datatype for N. Conversion from base type DECFLOAT(34) to DECFLOAT(16) is not supported. + + Statement failed, SQLSTATE = 22003 + Decimal float overflow. The exponent of a result is greater than the magnitude allowed. + """ + +@pytest.mark.version('>=4.0') +def test_decfloat_columns_handlng_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/datatypes/test_decfloat_ddl_indices.py b/tests/functional/datatypes/test_decfloat_ddl_indices.py new file mode 100644 index 00000000..d84e85f0 --- /dev/null +++ b/tests/functional/datatypes/test_decfloat_ddl_indices.py @@ -0,0 +1,151 @@ +#coding:utf-8 +# +# id: functional.datatypes.decfloat_ddl_indices +# title: Check ability to create table with 16 fields of type decfloat(34), plus create indices and add data. +# decription: +# See CORE-5535 and doc\\sql.extensions\\README.data_types +# FB40SS, build 4.0.0.688: OK, 1.156s. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set list on; + recreate table test( + f1 decfloat(34) + default 1239999999999999999999955599999999789999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999919 + ,f2 decfloat(34) + default -123999999999999999999995559999999978999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999998 + ,f3 decfloat(34) + default 123999999999999999999995559999999978999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999998 + ,f4 decfloat(34) + default -123999999999999999999995559999999978999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999998 + ,f5 decfloat(34) + default 123999999999999999999995559999999978999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999998 + ,f6 decfloat(34) + default -123999999999999999999995559999999978999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999998 + ,f7 decfloat(34) + default 123999999999999999999995559999999978999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999998 + ,f8 decfloat(34) + default -123999999999999999999995559999999978999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999998 + ,f9 decfloat(34) + default 123999999999999999999995559999999978999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999998 + ,f10 decfloat(34) + default -123999999999999999999995559999999978999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999998 + ,f11 decfloat(34) + default 123999999999999999999995559999999978999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999998 + ,f12 decfloat(34) + default -123999999999999999999995559999999978999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999998 + ,f13 decfloat(34) + default 123999999999999999999995559999999978999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999998 + ,f14 decfloat(34) + default -123999999999999999999995559999999978999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999998 + ,f15 decfloat(34) + default 123999999999999999999995559999999978999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999998 + ,f16 decfloat(34) + default -123999999999999999999995559999999978999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999998 + ); + alter table test add fff computed by ( + f1 + + f2 + + f3 + + f4 + + f5 + + f6 + + f7 + + f8 + + f9 + + f10 + + f11 + + f12 + + f13 + + f14 + + f15 + + f16 + ); + create index test_compound on test( + f1 + ,f2 + ,f3 + ,f4 + ,f5 + ,f6 + ,f7 + ,f8 + ,f9 + ,f10 + ,f11 + ,f12 + ,f13 + ,f14 + ,f15 + ,f16 + ); + create index test_computed1 on test computed by ( + f1 + + f2 + + f3 + + f4 + + f5 + + f6 + + f7 + + f8 + + f9 + + f10 + + f11 + + f12 + + f13 + + f14 + + f15 + + f16 + ); + create index test_computed2 on test computed by (fff); + commit; + + insert into test default values; + select * from test where fff > 0; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F1 1.239999999999999999999955600000000E+1023 + F2 -1.239999999999999999999955600000000E+1022 + F3 1.239999999999999999999955600000000E+1022 + F4 -1.239999999999999999999955600000000E+1022 + F5 1.239999999999999999999955600000000E+1022 + F6 -1.239999999999999999999955600000000E+1022 + F7 1.239999999999999999999955600000000E+1022 + F8 -1.239999999999999999999955600000000E+1022 + F9 1.239999999999999999999955600000000E+1022 + F10 -1.239999999999999999999955600000000E+1022 + F11 1.239999999999999999999955600000000E+1022 + F12 -1.239999999999999999999955600000000E+1022 + F13 1.239999999999999999999955600000000E+1022 + F14 -1.239999999999999999999955600000000E+1022 + F15 1.239999999999999999999955600000000E+1022 + F16 -1.239999999999999999999955600000000E+1022 + FFF 1.115999999999999999999960040000000E+1023 + """ + +@pytest.mark.version('>=4.0') +def test_decfloat_ddl_indices_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/datatypes/test_decfloat_df16_alignment.py b/tests/functional/datatypes/test_decfloat_df16_alignment.py new file mode 100644 index 00000000..c0bd72c1 --- /dev/null +++ b/tests/functional/datatypes/test_decfloat_df16_alignment.py @@ -0,0 +1,60 @@ +#coding:utf-8 +# +# id: functional.datatypes.decfloat_df16_alignment +# title: Check proper alignment of decfloat(16) value if it is shown in ISQL when SET LIST ON. +# decription: +# See CORE-5535 and doc\\sql.extensions\\README.data_types +# Test is based on letter to Alex, 02.05.2017, 9:38: +# For ISQL 'SET LIST ON' there was auxiliary ("wrong") space character between column name +# for decfloat(16) and its value comparing with decfloat(34). +# FB40CS, build 4.0.0.651: OK, 1.406ss. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + recreate table test( + a varchar(1) default '|' + ,x34 decfloat(34) default -9.999999999999999999999999999999999E6144 + ,y16 decfloat(16) default -9.999999999999999E384 + ,u34 decfloat(34) default 9.999999999999999999999999999999999E6144 + ,v16 decfloat(16) default 9.999999999999999E384 + ,w varchar(1) default '|' + ); + commit; + insert into test default values returning a,x34,y16,u34,v16,w; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A | + X34 -9.999999999999999999999999999999999E+6144 + Y16 -9.999999999999999E+384 + U34 9.999999999999999999999999999999999E+6144 + V16 9.999999999999999E+384 + W | + """ + +@pytest.mark.version('>=4.0') +def test_decfloat_df16_alignment_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/datatypes/test_decfloat_exceptions_trapping.py b/tests/functional/datatypes/test_decfloat_exceptions_trapping.py new file mode 100644 index 00000000..a987c3b7 --- /dev/null +++ b/tests/functional/datatypes/test_decfloat_exceptions_trapping.py @@ -0,0 +1,141 @@ +#coding:utf-8 +# +# id: functional.datatypes.decfloat_exceptions_trapping +# title: Test exception trapping for result of DECFLOAT operations. +# decription: +# See CORE-5535 and doc\\sql.extensions\\README.data_types: +# --- +# SET DECFLOAT TRAPS TO - controls which +# exceptional conditions cause a trap. Valid traps are: Division_by_zero, Inexact, +# Invalid_operation, Overflow and Underflow. By default traps are set to: +# Division_by_zero, Invalid_operation, Overflow, Underflow. +# --- +# FB40SS, build 4.0.0.651: OK, 0.782s. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + ------------------------- check: empty vs Division_by_zero ------------------------ + set decfloat traps to; + -- Should issue: Infinity + select 1/1e-9999 zero_div_when_df_trap_empty + from rdb$database; + + + set decfloat traps to Division_by_zero; + -- Statement failed, SQLSTATE = 22012 + -- Decimal float divide by zero. The code attempted to divide a DECFLOAT value by zero. + select 1/1e-9999 zero_div_when_df_trap_zd + from rdb$database; + + ------------------------- check: empty vs Overflow ------------------------ + set decfloat traps to; + -- Should issue: Infinity + select 1e9999 huge_when_df_trap_empty + from rdb$database; + + set decfloat traps to Overflow; + -- Statement failed, SQLSTATE = 22003 + -- Decimal float overflow. The exponent of a result is greater than the magnitude allowed. + select 1e9999 huge_when_df_trap_overflow + from rdb$database; + + ------------------------- check: empty vs Underflow ------------------------ + + set decfloat traps to; + -- Issues: 0E-6176 + select 1e-9999 about_zero_when_df_trap_empty + from rdb$database; + + set decfloat traps to Underflow; + -- Statement failed, SQLSTATE = 22003 + -- Decimal float overflow. The exponent of a result is greater than the magnitude allowed. + select 1e-9999 about_zero_when_df_trap_overflow + from rdb$database; + + + + ------------------------- check: empty vs Inexact ------------------------ + + set decfloat traps to; + + -- Should issue: Infinity + select 1e9999 + 1e9999 as add_huges_when_df_trap_empty + from rdb$database; + + set decfloat traps to Inexact; + + -- Statement failed, SQLSTATE = 22000 + -- Decimal float inexact result. The result of an operation cannot be represented as a decimal fraction. + select 1e9999 + 1e9999 add_huges_when_df_trap_inexact + from rdb$database; + + + ------------------------- check: empty vs Invalid_operation ------------------------ + + -- Sample by Alex, letter 25.05.2017 20:30 + + set decfloat traps to; + -- Should issue: NaN + select cast('34ffd' as decfloat(16)) nan_when_df_trap_empty + from rdb$database; + + set decfloat traps to Invalid_operation; + -- Statement failed, SQLSTATE = 22000 + -- Decimal float invalid operation. An indeterminant error occurred during an operation. + select cast('34ffd' as decfloat(16)) nan_when_df_trap_inv_op + from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ZERO_DIV_WHEN_DF_TRAP_EMPTY Infinity + HUGE_WHEN_DF_TRAP_EMPTY Infinity + ABOUT_ZERO_WHEN_DF_TRAP_EMPTY 0E-6176 + ADD_HUGES_WHEN_DF_TRAP_EMPTY Infinity + NAN_WHEN_DF_TRAP_EMPTY NaN + + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22012 + Decimal float divide by zero. The code attempted to divide a DECFLOAT value by zero. + + Statement failed, SQLSTATE = 22003 + Decimal float overflow. The exponent of a result is greater than the magnitude allowed. + + Statement failed, SQLSTATE = 22003 + Decimal float underflow. The exponent of a result is less than the magnitude allowed. + + Statement failed, SQLSTATE = 22000 + Decimal float inexact result. The result of an operation cannot be represented as a decimal fraction. + + Statement failed, SQLSTATE = 22000 + Decimal float invalid operation. An indeterminant error occurred during an operation. + """ + +@pytest.mark.version('>=4.0') +def test_decfloat_exceptions_trapping_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/datatypes/test_decfloat_literal_interpr.py b/tests/functional/datatypes/test_decfloat_literal_interpr.py new file mode 100644 index 00000000..e3e354f0 --- /dev/null +++ b/tests/functional/datatypes/test_decfloat_literal_interpr.py @@ -0,0 +1,75 @@ +#coding:utf-8 +# +# id: functional.datatypes.decfloat_literal_interpr +# title: Test interpretation of numeric literals. +# decription: +# When literal can not be fit in any of "pre-4.0" then DECFLOAT should be considered as DECFLOAT(34). +# See CORE-5535 and doc\\sql.extensions\\README.data_types +# See also letter from Alex, 24.05.2017 19:28. +# +# Checked on: FB40CS, build 4.0.0.651: OK, 1.375s +# ::: NB ::: +# Currently only double precision form of literals is checked. +# Literals with value out bigint scope are not checked - waiting for reply from Alex, letter 24.05.2017 21:16 +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set sqlda_display on; + + select + 1e-308 as almost_zero_double_precision + from rdb$database; -- ==> 9.999999999999999e-309 -- this is still DP + + select + 1e-309 as almost_zero_decfloat_34 + from rdb$database; -- ==> FAILS on 3.0; must be interpreted as DECFLOAT(34) on 4.0.0 + + /* + --- todo later! waiting for reply from Alex, letter 24.05.2017 21:16 + select + -9223372036854775809 as behind_bigint_max + ,9223372036854775808 as behind_bigint_min + from rdb$database; -- ==> FAILS on 3.0; must be interpreted as DECFLOAT(34) on 4.0.0 + */ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + INPUT message field count: 0 + OUTPUT message field count: 1 + 01: sqltype: 480 DOUBLE scale: 0 subtype: 0 len: 8 + : name: CONSTANT alias: ALMOST_ZERO_DOUBLE_PRECISION + : table: owner: + ALMOST_ZERO_DOUBLE_PRECISION 9.999999999999999e-309 + INPUT message field count: 0 + OUTPUT message field count: 1 + 01: sqltype: 32762 DECFLOAT(34) scale: 0 subtype: 0 len: 16 + : name: CONSTANT alias: ALMOST_ZERO_DECFLOAT_34 + : table: owner: + ALMOST_ZERO_DECFLOAT_34 1E-309 + """ + +@pytest.mark.version('>=4.0') +def test_decfloat_literal_interpr_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/datatypes/test_decfloat_literal_length.py b/tests/functional/datatypes/test_decfloat_literal_length.py new file mode 100644 index 00000000..b8081ce8 --- /dev/null +++ b/tests/functional/datatypes/test_decfloat_literal_length.py @@ -0,0 +1,219 @@ +#coding:utf-8 +# +# id: functional.datatypes.decfloat_literal_length +# title: Literal length currently is limited with 1024 characters (including decimal separator and minus sign if any) +# decription: +# See CORE-5535 and doc\\sql.extensions\\README.data_types: +# === +# Although length of DECFLOAT(34) literal can exceed 6000 bytes (0.000<6000 zeros>00123) +# implementation limit exists - length of such literal should not exceed 1024 bytes. +# === +# FB40SS, build 4.0.0.651: OK, 1.047s +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set sqlda_display on; + + -- All of these should PASS (they all have length=1024 bytes): + -- ########################################################### + + select + 0.10000000000000000000055500000000789000000000000000000000000000000000000000000000000000000000000099900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 + from rdb$database + ; + + select + -0.1000000000000000000005550000000078900000000000000000000000000000000000000000000000000000000000009990000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 + from rdb$database + ; + + select + 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054321 + from rdb$database + ; + + select + -0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054321 + from rdb$database + ; + + + select + 1230000000000000000000055500000000789000000000000000000000000000000000000000000000000000000000000099900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 + from rdb$database + ; + + + select + -123000000000000000000005550000000078900000000000000000000000000000000000000000000000000000000000009990000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 + from rdb$database + ; + + + -- All of these should FAIL (they all have length=1025 bytes): + -- ########################################################### + + select + 0.100000000000000000000555000000007890000000000000000000000000000000000000000000000000000000000000999000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010 + from rdb$database + ; + + select + -0.10000000000000000000055500000000789000000000000000000000000000000000000000000000000000000000000099900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010 + from rdb$database + ; + + select + 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000543210 + from rdb$database + ; + + select + -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000543210 + from rdb$database + ; + + + select + 12300000000000000000000555000000007890000000000000000000000000000000000000000000000000000000000000999000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010 + from rdb$database + ; + + + select + -1230000000000000000000055500000000789000000000000000000000000000000000000000000000000000000000000099900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010 + from rdb$database + ; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + INPUT message field count: 0 + + OUTPUT message field count: 1 + 01: sqltype: 32762 DECFLOAT(34) scale: 0 subtype: 0 len: 16 + : name: CONSTANT alias: CONSTANT + : table: owner: + + CONSTANT 0.1000000000000000000005550000000079 + + + + INPUT message field count: 0 + + OUTPUT message field count: 1 + 01: sqltype: 32762 DECFLOAT(34) scale: 0 subtype: 0 len: 16 + : name: CONSTANT alias: CONSTANT + : table: owner: + + CONSTANT -0.1000000000000000000005550000000079 + + + + INPUT message field count: 0 + + OUTPUT message field count: 1 + 01: sqltype: 32762 DECFLOAT(34) scale: 0 subtype: 0 len: 16 + : name: CONSTANT alias: CONSTANT + : table: owner: + + CONSTANT 5.4321E-1018 + + + + INPUT message field count: 0 + + OUTPUT message field count: 1 + 01: sqltype: 32762 DECFLOAT(34) scale: 0 subtype: 0 len: 16 + : name: CONSTANT alias: CONSTANT + : table: owner: + + CONSTANT -5.4321E-1017 + + + + INPUT message field count: 0 + + OUTPUT message field count: 1 + 01: sqltype: 32762 DECFLOAT(34) scale: 0 subtype: 0 len: 16 + : name: CONSTANT alias: CONSTANT + : table: owner: + + CONSTANT 1.230000000000000000000055500000001E+1023 + + + + INPUT message field count: 0 + + OUTPUT message field count: 1 + 01: sqltype: 32762 DECFLOAT(34) scale: 0 subtype: 0 len: 16 + : name: CONSTANT alias: CONSTANT + : table: owner: + + CONSTANT -1.230000000000000000000055500000001E+1022 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22001 + arithmetic exception, numeric overflow, or string truncation + -string right truncation + -Implementation limit exceeded + -expected length 1024, actual 1025 + + Statement failed, SQLSTATE = 22001 + arithmetic exception, numeric overflow, or string truncation + -string right truncation + -Implementation limit exceeded + -expected length 1024, actual 1025 + + Statement failed, SQLSTATE = 22001 + arithmetic exception, numeric overflow, or string truncation + -string right truncation + -Implementation limit exceeded + -expected length 1024, actual 1025 + + Statement failed, SQLSTATE = 22001 + arithmetic exception, numeric overflow, or string truncation + -string right truncation + -Implementation limit exceeded + -expected length 1024, actual 1025 + + Statement failed, SQLSTATE = 22001 + arithmetic exception, numeric overflow, or string truncation + -string right truncation + -Implementation limit exceeded + -expected length 1024, actual 1025 + + Statement failed, SQLSTATE = 22001 + arithmetic exception, numeric overflow, or string truncation + -string right truncation + -Implementation limit exceeded + -expected length 1024, actual 1025 + """ + +@pytest.mark.version('>=4.0') +def test_decfloat_literal_length_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/datatypes/test_decfloat_loose_accuracy.py b/tests/functional/datatypes/test_decfloat_loose_accuracy.py new file mode 100644 index 00000000..94badd60 --- /dev/null +++ b/tests/functional/datatypes/test_decfloat_loose_accuracy.py @@ -0,0 +1,57 @@ +#coding:utf-8 +# +# id: functional.datatypes.decfloat_loose_accuracy +# title: Test for preseving accuracy when evaluate sum of values with huge dfference in magnitude. +# decription: +# Wide range of terms can lead to wrong result of sum. +# https://en.wikipedia.org/wiki/Decimal_floating_point +# https://en.wikipedia.org/wiki/Kahan_summation_algorithm +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select + 1 + +cast(1e33 as decfloat) + -cast(1e33 as decfloat) + as addition_with_e33 + from rdb$database; + + select + 1 + +cast(1e34 as decfloat) + -cast(1e34 as decfloat) + as addition_with_e34 + from rdb$database; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ADDITION_WITH_E33 1 + ADDITION_WITH_E34 0E+1 + """ + +@pytest.mark.version('>=4.0') +def test_decfloat_loose_accuracy_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/datatypes/test_decfloat_min_distinguish.py b/tests/functional/datatypes/test_decfloat_min_distinguish.py new file mode 100644 index 00000000..a50867da --- /dev/null +++ b/tests/functional/datatypes/test_decfloat_min_distinguish.py @@ -0,0 +1,10321 @@ +#coding:utf-8 +# +# id: functional.datatypes.decfloat_min_distinguish +# title: List of all values starting from 1.0 divided by 2, until previous and current become equal +# decription: +# Checked on 4.0.0.1740 (both Windows and POSIX give the same result). +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[\\s]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + set term ^; + execute block returns(i int, x decfloat, y decfloat) as + begin + i = 0; + x = cast(1.0 as decfloat); + y = cast(0.5 as decfloat); + while ( i < 20000 ) do + begin + suspend; + i = i+1; + x = y/2; + y = y/4; + if ( x<= y ) then + begin + suspend; + leave; + end + end + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 0 1.0 0.5 + 1 0.25 0.125 + 2 0.0625 0.03125 + 3 0.015625 0.0078125 + 4 0.00390625 0.001953125 + 5 0.0009765625 0.00048828125 + 6 0.000244140625 0.0001220703125 + 7 0.00006103515625 0.000030517578125 + 8 0.0000152587890625 0.00000762939453125 + 9 0.000003814697265625 0.0000019073486328125 + 10 9.5367431640625E-7 4.76837158203125E-7 + 11 2.384185791015625E-7 1.1920928955078125E-7 + 12 5.9604644775390625E-8 2.98023223876953125E-8 + 13 1.490116119384765625E-8 7.450580596923828125E-9 + 14 3.7252902984619140625E-9 1.86264514923095703125E-9 + 15 9.31322574615478515625E-10 4.656612873077392578125E-10 + 16 2.3283064365386962890625E-10 1.16415321826934814453125E-10 + 17 5.82076609134674072265625E-11 2.910383045673370361328125E-11 + 18 1.4551915228366851806640625E-11 7.2759576141834259033203125E-12 + 19 3.63797880709171295166015625E-12 1.818989403545856475830078125E-12 + 20 9.094947017729282379150390625E-13 4.5474735088646411895751953125E-13 + 21 2.27373675443232059478759765625E-13 1.136868377216160297393798828125E-13 + 22 5.684341886080801486968994140625E-14 2.8421709430404007434844970703125E-14 + 23 1.42108547152020037174224853515625E-14 7.10542735760100185871124267578125E-15 + 24 3.552713678800500929355621337890625E-15 1.776356839400250464677810668945313E-15 + 25 8.881784197001252323389053344726565E-16 4.440892098500626161694526672363283E-16 + 26 2.220446049250313080847263336181642E-16 1.110223024625156540423631668090821E-16 + 27 5.551115123125782702118158340454105E-17 2.775557561562891351059079170227053E-17 + 28 1.387778780781445675529539585113527E-17 6.938893903907228377647697925567633E-18 + 29 3.469446951953614188823848962783817E-18 1.734723475976807094411924481391908E-18 + 30 8.67361737988403547205962240695954E-19 4.33680868994201773602981120347977E-19 + 31 2.168404344971008868014905601739885E-19 1.084202172485504434007452800869943E-19 + 32 5.421010862427522170037264004349715E-20 2.710505431213761085018632002174858E-20 + 33 1.355252715606880542509316001087429E-20 6.776263578034402712546580005437145E-21 + 34 3.388131789017201356273290002718573E-21 1.694065894508600678136645001359286E-21 + 35 8.47032947254300339068322500679643E-22 4.235164736271501695341612503398215E-22 + 36 2.117582368135750847670806251699108E-22 1.058791184067875423835403125849554E-22 + 37 5.29395592033937711917701562924777E-23 2.646977960169688559588507814623885E-23 + 38 1.323488980084844279794253907311943E-23 6.617444900424221398971269536559713E-24 + 39 3.308722450212110699485634768279857E-24 1.654361225106055349742817384139928E-24 + 40 8.27180612553027674871408692069964E-25 4.13590306276513837435704346034982E-25 + 41 2.06795153138256918717852173017491E-25 1.033975765691284593589260865087455E-25 + 42 5.169878828456422967946304325437275E-26 2.584939414228211483973152162718638E-26 + 43 1.292469707114105741986576081359319E-26 6.462348535570528709932880406796595E-27 + 44 3.231174267785264354966440203398298E-27 1.615587133892632177483220101699149E-27 + 45 8.077935669463160887416100508495745E-28 4.038967834731580443708050254247873E-28 + 46 2.019483917365790221854025127123937E-28 1.009741958682895110927012563561968E-28 + 47 5.04870979341447555463506281780984E-29 2.52435489670723777731753140890492E-29 + 48 1.26217744835361888865876570445246E-29 6.3108872417680944432938285222623E-30 + 49 3.15544362088404722164691426113115E-30 1.577721810442023610823457130565575E-30 + 50 7.888609052210118054117285652827875E-31 3.944304526105059027058642826413938E-31 + 51 1.972152263052529513529321413206969E-31 9.860761315262647567646607066034845E-32 + 52 4.930380657631323783823303533017423E-32 2.465190328815661891911651766508711E-32 + 53 1.232595164407830945955825883254356E-32 6.162975822039154729779129416271778E-33 + 54 3.081487911019577364889564708135889E-33 1.540743955509788682444782354067945E-33 + 55 7.703719777548943412223911770339725E-34 3.851859888774471706111955885169863E-34 + 56 1.925929944387235853055977942584932E-34 9.629649721936179265279889712924658E-35 + 57 4.814824860968089632639944856462329E-35 2.407412430484044816319972428231165E-35 + 58 1.203706215242022408159986214115583E-35 6.018531076210112040799931070577913E-36 + 59 3.009265538105056020399965535288957E-36 1.504632769052528010199982767644478E-36 + 60 7.52316384526264005099991383822239E-37 3.761581922631320025499956919111195E-37 + 61 1.880790961315660012749978459555598E-37 9.403954806578300063749892297777988E-38 + 62 4.701977403289150031874946148888994E-38 2.350988701644575015937473074444497E-38 + 63 1.175494350822287507968736537222249E-38 5.877471754111437539843682686111243E-39 + 64 2.938735877055718769921841343055622E-39 1.469367938527859384960920671527811E-39 + 65 7.346839692639296924804603357639055E-40 3.673419846319648462402301678819528E-40 + 66 1.836709923159824231201150839409764E-40 9.18354961579912115600575419704882E-41 + 67 4.59177480789956057800287709852441E-41 2.295887403949780289001438549262205E-41 + 68 1.147943701974890144500719274631103E-41 5.739718509874450722503596373155513E-42 + 69 2.869859254937225361251798186577757E-42 1.434929627468612680625899093288878E-42 + 70 7.17464813734306340312949546644439E-43 3.587324068671531701564747733222195E-43 + 71 1.793662034335765850782373866611098E-43 8.968310171678829253911869333055488E-44 + 72 4.484155085839414626955934666527744E-44 2.242077542919707313477967333263872E-44 + 73 1.121038771459853656738983666631936E-44 5.60519385729926828369491833315968E-45 + 74 2.80259692864963414184745916657984E-45 1.40129846432481707092372958328992E-45 + 75 7.0064923216240853546186479164496E-46 3.5032461608120426773093239582248E-46 + 76 1.7516230804060213386546619791124E-46 8.758115402030106693273309895562E-47 + 77 4.379057701015053346636654947781E-47 2.1895288505075266733183274738905E-47 + 78 1.09476442525376333665916373694525E-47 5.47382212626881668329581868472625E-48 + 79 2.736911063134408341647909342363125E-48 1.368455531567204170823954671181563E-48 + 80 6.842277657836020854119773355907815E-49 3.421138828918010427059886677953908E-49 + 81 1.710569414459005213529943338976954E-49 8.55284707229502606764971669488477E-50 + 82 4.276423536147513033824858347442385E-50 2.138211768073756516912429173721193E-50 + 83 1.069105884036878258456214586860597E-50 5.345529420184391292281072934302983E-51 + 84 2.672764710092195646140536467151492E-51 1.336382355046097823070268233575746E-51 + 85 6.68191177523048911535134116787873E-52 3.340955887615244557675670583939365E-52 + 86 1.670477943807622278837835291969683E-52 8.352389719038111394189176459848413E-53 + 87 4.176194859519055697094588229924207E-53 2.088097429759527848547294114962103E-53 + 88 1.044048714879763924273647057481052E-53 5.220243574398819621368235287405258E-54 + 89 2.610121787199409810684117643702629E-54 1.305060893599704905342058821851315E-54 + 90 6.525304467998524526710294109256575E-55 3.262652233999262263355147054628288E-55 + 91 1.631326116999631131677573527314144E-55 8.15663058499815565838786763657072E-56 + 92 4.07831529249907782919393381828536E-56 2.03915764624953891459696690914268E-56 + 93 1.01957882312476945729848345457134E-56 5.0978941156238472864924172728567E-57 + 94 2.54894705781192364324620863642835E-57 1.274473528905961821623104318214175E-57 + 95 6.372367644529809108115521591070875E-58 3.186183822264904554057760795535438E-58 + 96 1.593091911132452277028880397767719E-58 7.965459555662261385144401988838595E-59 + 97 3.982729777831130692572200994419298E-59 1.991364888915565346286100497209649E-59 + 98 9.956824444577826731430502486048245E-60 4.978412222288913365715251243024123E-60 + 99 2.489206111144456682857625621512062E-60 1.244603055572228341428812810756031E-60 + 100 6.223015277861141707144064053780155E-61 3.111507638930570853572032026890078E-61 + 101 1.555753819465285426786016013445039E-61 7.778769097326427133930080067225195E-62 + 102 3.889384548663213566965040033612598E-62 1.944692274331606783482520016806299E-62 + 103 9.723461371658033917412600084031495E-63 4.861730685829016958706300042015748E-63 + 104 2.430865342914508479353150021007874E-63 1.215432671457254239676575010503937E-63 + 105 6.077163357286271198382875052519685E-64 3.038581678643135599191437526259843E-64 + 106 1.519290839321567799595718763129922E-64 7.596454196607838997978593815649608E-65 + 107 3.798227098303919498989296907824804E-65 1.899113549151959749494648453912402E-65 + 108 9.49556774575979874747324226956201E-66 4.747783872879899373736621134781005E-66 + 109 2.373891936439949686868310567390503E-66 1.186945968219974843434155283695251E-66 + 110 5.934729841099874217170776418476255E-67 2.967364920549937108585388209238128E-67 + 111 1.483682460274968554292694104619064E-67 7.41841230137484277146347052309532E-68 + 112 3.70920615068742138573173526154766E-68 1.85460307534371069286586763077383E-68 + 113 9.27301537671855346432933815386915E-69 4.636507688359276732164669076934575E-69 + 114 2.318253844179638366082334538467288E-69 1.159126922089819183041167269233644E-69 + 115 5.79563461044909591520583634616822E-70 2.89781730522454795760291817308411E-70 + 116 1.448908652612273978801459086542055E-70 7.244543263061369894007295432710275E-71 + 117 3.622271631530684947003647716355138E-71 1.811135815765342473501823858177569E-71 + 118 9.055679078826712367509119290887845E-72 4.527839539413356183754559645443923E-72 + 119 2.263919769706678091877279822721962E-72 1.131959884853339045938639911360981E-72 + 120 5.659799424266695229693199556804905E-73 2.829899712133347614846599778402453E-73 + 121 1.414949856066673807423299889201227E-73 7.074749280333369037116499446006133E-74 + 122 3.537374640166684518558249723003067E-74 1.768687320083342259279124861501533E-74 + 123 8.843436600416711296395624307507665E-75 4.421718300208355648197812153753833E-75 + 124 2.210859150104177824098906076876917E-75 1.105429575052088912049453038438458E-75 + 125 5.52714787526044456024726519219229E-76 2.763573937630222280123632596096145E-76 + 126 1.381786968815111140061816298048073E-76 6.908934844075555700309081490240363E-77 + 127 3.454467422037777850154540745120182E-77 1.727233711018888925077270372560091E-77 + 128 8.636168555094444625386351862800455E-78 4.318084277547222312693175931400228E-78 + 129 2.159042138773611156346587965700114E-78 1.079521069386805578173293982850057E-78 + 130 5.397605346934027890866469914250285E-79 2.698802673467013945433234957125143E-79 + 131 1.349401336733506972716617478562572E-79 6.747006683667534863583087392812858E-80 + 132 3.373503341833767431791543696406429E-80 1.686751670916883715895771848203215E-80 + 133 8.433758354584418579478859241016075E-81 4.216879177292209289739429620508038E-81 + 134 2.108439588646104644869714810254019E-81 1.054219794323052322434857405127010E-81 + 135 5.27109897161526161217428702563505E-82 2.635549485807630806087143512817525E-82 + 136 1.317774742903815403043571756408763E-82 6.588873714519077015217858782043813E-83 + 137 3.294436857259538507608929391021907E-83 1.647218428629769253804464695510953E-83 + 138 8.236092143148846269022323477554765E-84 4.118046071574423134511161738777383E-84 + 139 2.059023035787211567255580869388692E-84 1.029511517893605783627790434694346E-84 + 140 5.14755758946802891813895217347173E-85 2.573778794734014459069476086735865E-85 + 141 1.286889397367007229534738043367933E-85 6.434446986835036147673690216839663E-86 + 142 3.217223493417518073836845108419832E-86 1.608611746708759036918422554209916E-86 + 143 8.04305873354379518459211277104958E-87 4.02152936677189759229605638552479E-87 + 144 2.010764683385948796148028192762395E-87 1.005382341692974398074014096381198E-87 + 145 5.02691170846487199037007048190599E-88 2.513455854232435995185035240952995E-88 + 146 1.256727927116217997592517620476498E-88 6.283639635581089987962588102382488E-89 + 147 3.141819817790544993981294051191244E-89 1.570909908895272496990647025595622E-89 + 148 7.85454954447636248495323512797811E-90 3.927274772238181242476617563989055E-90 + 149 1.963637386119090621238308781994528E-90 9.818186930595453106191543909972638E-91 + 150 4.909093465297726553095771954986319E-91 2.454546732648863276547885977493160E-91 + 151 1.227273366324431638273942988746580E-91 6.13636683162215819136971494373290E-92 + 152 3.06818341581107909568485747186645E-92 1.534091707905539547842428735933225E-92 + 153 7.670458539527697739212143679666125E-93 3.835229269763848869606071839833063E-93 + 154 1.917614634881924434803035919916532E-93 9.588073174409622174015179599582658E-94 + 155 4.794036587204811087007589799791329E-94 2.397018293602405543503794899895665E-94 + 156 1.198509146801202771751897449947833E-94 5.992545734006013858759487249739163E-95 + 157 2.996272867003006929379743624869582E-95 1.498136433501503464689871812434791E-95 + 158 7.490682167507517323449359062173955E-96 3.745341083753758661724679531086978E-96 + 159 1.872670541876879330862339765543489E-96 9.363352709384396654311698827717445E-97 + 160 4.681676354692198327155849413858723E-97 2.340838177346099163577924706929361E-97 + 161 1.170419088673049581788962353464681E-97 5.852095443365247908944811767323403E-98 + 162 2.926047721682623954472405883661702E-98 1.463023860841311977236202941830851E-98 + 163 7.315119304206559886181014709154255E-99 3.657559652103279943090507354577128E-99 + 164 1.828779826051639971545253677288564E-99 9.14389913025819985772626838644282E-100 + 165 4.57194956512909992886313419322141E-100 2.285974782564549964431567096610705E-100 + 166 1.142987391282274982215783548305353E-100 5.714936956411374911078917741526763E-101 + 167 2.857468478205687455539458870763382E-101 1.428734239102843727769729435381691E-101 + 168 7.143671195514218638848647176908455E-102 3.571835597757109319424323588454228E-102 + 169 1.785917798878554659712161794227114E-102 8.92958899439277329856080897113557E-103 + 170 4.464794497196386649280404485567785E-103 2.232397248598193324640202242783893E-103 + 171 1.116198624299096662320101121391947E-103 5.580993121495483311600505606959733E-104 + 172 2.790496560747741655800252803479867E-104 1.395248280373870827900126401739933E-104 + 173 6.976241401869354139500632008699665E-105 3.488120700934677069750316004349833E-105 + 174 1.744060350467338534875158002174917E-105 8.720301752336692674375790010874583E-106 + 175 4.360150876168346337187895005437292E-106 2.180075438084173168593947502718646E-106 + 176 1.090037719042086584296973751359323E-106 5.450188595210432921484868756796615E-107 + 177 2.725094297605216460742434378398308E-107 1.362547148802608230371217189199154E-107 + 178 6.81273574401304115185608594599577E-108 3.406367872006520575928042972997885E-108 + 179 1.703183936003260287964021486498943E-108 8.515919680016301439820107432494713E-109 + 180 4.257959840008150719910053716247357E-109 2.128979920004075359955026858123678E-109 + 181 1.064489960002037679977513429061839E-109 5.322449800010188399887567145309195E-110 + 182 2.661224900005094199943783572654598E-110 1.330612450002547099971891786327299E-110 + 183 6.653062250012735499859458931636495E-111 3.326531125006367749929729465818248E-111 + 184 1.663265562503183874964864732909124E-111 8.31632781251591937482432366454562E-112 + 185 4.15816390625795968741216183227281E-112 2.079081953128979843706080916136405E-112 + 186 1.039540976564489921853040458068203E-112 5.197704882822449609265202290341013E-113 + 187 2.598852441411224804632601145170507E-113 1.299426220705612402316300572585253E-113 + 188 6.497131103528062011581502862926265E-114 3.248565551764031005790751431463133E-114 + 189 1.624282775882015502895375715731567E-114 8.121413879410077514476878578657833E-115 + 190 4.060706939705038757238439289328917E-115 2.030353469852519378619219644664458E-115 + 191 1.015176734926259689309609822332229E-115 5.075883674631298446548049111661145E-116 + 192 2.537941837315649223274024555830573E-116 1.268970918657824611637012277915286E-116 + 193 6.34485459328912305818506138957643E-117 3.172427296644561529092530694788215E-117 + 194 1.586213648322280764546265347394108E-117 7.931068241611403822731326736970538E-118 + 195 3.965534120805701911365663368485269E-118 1.982767060402850955682831684242635E-118 + 196 9.913835302014254778414158421213175E-119 4.956917651007127389207079210606588E-119 + 197 2.478458825503563694603539605303294E-119 1.239229412751781847301769802651647E-119 + 198 6.196147063758909236508849013258235E-120 3.098073531879454618254424506629118E-120 + 199 1.549036765939727309127212253314559E-120 7.745183829698636545636061266572795E-121 + 200 3.872591914849318272818030633286398E-121 1.936295957424659136409015316643199E-121 + 201 9.681479787123295682045076583215995E-122 4.840739893561647841022538291607998E-122 + 202 2.420369946780823920511269145803999E-122 1.210184973390411960255634572902000E-122 + 203 6.05092486695205980127817286451000E-123 3.02546243347602990063908643225500E-123 + 204 1.51273121673801495031954321612750E-123 7.5636560836900747515977160806375E-124 + 205 3.78182804184503737579885804031875E-124 1.890914020922518687899429020159375E-124 + 206 9.454570104612593439497145100796875E-125 4.727285052306296719748572550398438E-125 + 207 2.363642526153148359874286275199219E-125 1.181821263076574179937143137599610E-125 + 208 5.90910631538287089968571568799805E-126 2.954553157691435449842857843999025E-126 + 209 1.477276578845717724921428921999513E-126 7.386382894228588624607144609997563E-127 + 210 3.693191447114294312303572304998782E-127 1.846595723557147156151786152499391E-127 + 211 9.232978617785735780758930762496955E-128 4.616489308892867890379465381248478E-128 + 212 2.308244654446433945189732690624239E-128 1.154122327223216972594866345312120E-128 + 213 5.77061163611608486297433172656060E-129 2.88530581805804243148716586328030E-129 + 214 1.44265290902902121574358293164015E-129 7.21326454514510607871791465820075E-130 + 215 3.606632272572553039358957329100375E-130 1.803316136286276519679478664550188E-130 + 216 9.01658068143138259839739332275094E-131 4.50829034071569129919869666137547E-131 + 217 2.254145170357845649599348330687735E-131 1.127072585178922824799674165343868E-131 + 218 5.63536292589461412399837082671934E-132 2.81768146294730706199918541335967E-132 + 219 1.408840731473653530999592706679835E-132 7.044203657368267654997963533399175E-133 + 220 3.522101828684133827498981766699588E-133 1.761050914342066913749490883349794E-133 + 221 8.80525457171033456874745441674897E-134 4.402627285855167284373727208374485E-134 + 222 2.201313642927583642186863604187243E-134 1.100656821463791821093431802093621E-134 + 223 5.503284107318959105467159010468105E-135 2.751642053659479552733579505234053E-135 + 224 1.375821026829739776366789752617027E-135 6.879105134148698881833948763085133E-136 + 225 3.439552567074349440916974381542567E-136 1.719776283537174720458487190771283E-136 + 226 8.598881417685873602292435953856415E-137 4.299440708842936801146217976928208E-137 + 227 2.149720354421468400573108988464104E-137 1.074860177210734200286554494232052E-137 + 228 5.37430088605367100143277247116026E-138 2.68715044302683550071638623558013E-138 + 229 1.343575221513417750358193117790065E-138 6.717876107567088751790965588950325E-139 + 230 3.358938053783544375895482794475163E-139 1.679469026891772187947741397237581E-139 + 231 8.397345134458860939738706986187905E-140 4.198672567229430469869353493093953E-140 + 232 2.099336283614715234934676746546977E-140 1.049668141807357617467338373273488E-140 + 233 5.24834070903678808733669186636744E-141 2.62417035451839404366834593318372E-141 + 234 1.31208517725919702183417296659186E-141 6.5604258862959851091708648329593E-142 + 235 3.28021294314799255458543241647965E-142 1.640106471573996277292716208239825E-142 + 236 8.200532357869981386463581041199125E-143 4.100266178934990693231790520599563E-143 + 237 2.050133089467495346615895260299782E-143 1.025066544733747673307947630149891E-143 + 238 5.125332723668738366539738150749455E-144 2.562666361834369183269869075374728E-144 + 239 1.281333180917184591634934537687364E-144 6.40666590458592295817467268843682E-145 + 240 3.20333295229296147908733634421841E-145 1.601666476146480739543668172109205E-145 + 241 8.008332380732403697718340860546025E-146 4.004166190366201848859170430273013E-146 + 242 2.002083095183100924429585215136507E-146 1.001041547591550462214792607568253E-146 + 243 5.005207737957752311073963037841265E-147 2.502603868978876155536981518920633E-147 + 244 1.251301934489438077768490759460317E-147 6.256509672447190388842453797301583E-148 + 245 3.128254836223595194421226898650792E-148 1.564127418111797597210613449325396E-148 + 246 7.82063709055898798605306724662698E-149 3.91031854527949399302653362331349E-149 + 247 1.955159272639746996513266811656745E-149 9.775796363198734982566334058283725E-150 + 248 4.887898181599367491283167029141863E-150 2.443949090799683745641583514570931E-150 + 249 1.221974545399841872820791757285466E-150 6.109872726999209364103958786427328E-151 + 250 3.054936363499604682051979393213664E-151 1.527468181749802341025989696606832E-151 + 251 7.63734090874901170512994848303416E-152 3.81867045437450585256497424151708E-152 + 252 1.90933522718725292628248712075854E-152 9.5466761359362646314124356037927E-153 + 253 4.77333806796813231570621780189635E-153 2.386669033984066157853108900948175E-153 + 254 1.193334516992033078926554450474088E-153 5.966672584960165394632772252370438E-154 + 255 2.983336292480082697316386126185219E-154 1.491668146240041348658193063092610E-154 + 256 7.45834073120020674329096531546305E-155 3.729170365600103371645482657731525E-155 + 257 1.864585182800051685822741328865763E-155 9.322925914000258429113706644328813E-156 + 258 4.661462957000129214556853322164407E-156 2.330731478500064607278426661082203E-156 + 259 1.165365739250032303639213330541102E-156 5.826828696250161518196066652705508E-157 + 260 2.913414348125080759098033326352754E-157 1.456707174062540379549016663176377E-157 + 261 7.283535870312701897745083315881885E-158 3.641767935156350948872541657940943E-158 + 262 1.820883967578175474436270828970472E-158 9.104419837890877372181354144852358E-159 + 263 4.552209918945438686090677072426179E-159 2.276104959472719343045338536213090E-159 + 264 1.138052479736359671522669268106545E-159 5.690262398681798357613346340532725E-160 + 265 2.845131199340899178806673170266363E-160 1.422565599670449589403336585133181E-160 + 266 7.112827998352247947016682925665905E-161 3.556413999176123973508341462832953E-161 + 267 1.778206999588061986754170731416477E-161 8.891034997940309933770853657082383E-162 + 268 4.445517498970154966885426828541192E-162 2.222758749485077483442713414270596E-162 + 269 1.111379374742538741721356707135298E-162 5.55689687371269370860678353567649E-163 + 270 2.778448436856346854303391767838245E-163 1.389224218428173427151695883919123E-163 + 271 6.946121092140867135758479419595615E-164 3.473060546070433567879239709797808E-164 + 272 1.736530273035216783939619854898904E-164 8.68265136517608391969809927449452E-165 + 273 4.34132568258804195984904963724726E-165 2.17066284129402097992452481862363E-165 + 274 1.085331420647010489962262409311815E-165 5.426657103235052449811312046559075E-166 + 275 2.713328551617526224905656023279538E-166 1.356664275808763112452828011639769E-166 + 276 6.783321379043815562264140058198845E-167 3.391660689521907781132070029099423E-167 + 277 1.695830344760953890566035014549712E-167 8.479151723804769452830175072748558E-168 + 278 4.239575861902384726415087536374279E-168 2.119787930951192363207543768187140E-168 + 279 1.059893965475596181603771884093570E-168 5.29946982737798090801885942046785E-169 + 280 2.649734913688990454009429710233925E-169 1.324867456844495227004714855116963E-169 + 281 6.624337284222476135023574275584815E-170 3.312168642111238067511787137792408E-170 + 282 1.656084321055619033755893568896204E-170 8.28042160527809516877946784448102E-171 + 283 4.14021080263904758438973392224051E-171 2.070105401319523792194866961120255E-171 + 284 1.035052700659761896097433480560128E-171 5.175263503298809480487167402800638E-172 + 285 2.587631751649404740243583701400319E-172 1.293815875824702370121791850700160E-172 + 286 6.46907937912351185060895925350080E-173 3.23453968956175592530447962675040E-173 + 287 1.61726984478087796265223981337520E-173 8.0863492239043898132611990668760E-174 + 288 4.0431746119521949066305995334380E-174 2.0215873059760974533152997667190E-174 + 289 1.0107936529880487266576498833595E-174 5.0539682649402436332882494167975E-175 + 290 2.52698413247012181664412470839875E-175 1.263492066235060908322062354199375E-175 + 291 6.317460331175304541610311770996875E-176 3.158730165587652270805155885498438E-176 + 292 1.579365082793826135402577942749219E-176 7.896825413969130677012889713746095E-177 + 293 3.948412706984565338506444856873048E-177 1.974206353492282669253222428436524E-177 + 294 9.87103176746141334626611214218262E-178 4.93551588373070667313305607109131E-178 + 295 2.467757941865353336566528035545655E-178 1.233878970932676668283264017772828E-178 + 296 6.16939485466338334141632008886414E-179 3.08469742733169167070816004443207E-179 + 297 1.542348713665845835354080022216035E-179 7.711743568329229176770400111080175E-180 + 298 3.855871784164614588385200055540088E-180 1.927935892082307294192600027770044E-180 + 299 9.63967946041153647096300013885022E-181 4.81983973020576823548150006942511E-181 + 300 2.409919865102884117740750034712555E-181 1.204959932551442058870375017356278E-181 + 301 6.02479966275721029435187508678139E-182 3.012399831378605147175937543390695E-182 + 302 1.506199915689302573587968771695348E-182 7.530999578446512867939843858476738E-183 + 303 3.765499789223256433969921929238369E-183 1.882749894611628216984960964619185E-183 + 304 9.413749473058141084924804823095925E-184 4.706874736529070542462402411547963E-184 + 305 2.353437368264535271231201205773982E-184 1.176718684132267635615600602886991E-184 + 306 5.883593420661338178078003014434955E-185 2.941796710330669089039001507217478E-185 + 307 1.470898355165334544519500753608739E-185 7.354491775826672722597503768043695E-186 + 308 3.677245887913336361298751884021848E-186 1.838622943956668180649375942010924E-186 + 309 9.19311471978334090324687971005462E-187 4.59655735989167045162343985502731E-187 + 310 2.298278679945835225811719927513655E-187 1.149139339972917612905859963756828E-187 + 311 5.74569669986458806452929981878414E-188 2.87284834993229403226464990939207E-188 + 312 1.436424174966147016132324954696035E-188 7.182120874830735080661624773480175E-189 + 313 3.591060437415367540330812386740088E-189 1.795530218707683770165406193370044E-189 + 314 8.97765109353841885082703096685022E-190 4.48882554676920942541351548342511E-190 + 315 2.244412773384604712706757741712555E-190 1.122206386692302356353378870856278E-190 + 316 5.61103193346151178176689435428139E-191 2.805515966730755890883447177140695E-191 + 317 1.402757983365377945441723588570348E-191 7.013789916826889727208617942851738E-192 + 318 3.506894958413444863604308971425869E-192 1.753447479206722431802154485712935E-192 + 319 8.767237396033612159010772428564675E-193 4.383618698016806079505386214282338E-193 + 320 2.191809349008403039752693107141169E-193 1.095904674504201519876346553570585E-193 + 321 5.479523372521007599381732767852925E-194 2.739761686260503799690866383926463E-194 + 322 1.369880843130251899845433191963232E-194 6.849404215651259499227165959816158E-195 + 323 3.424702107825629749613582979908079E-195 1.712351053912814874806791489954040E-195 + 324 8.56175526956407437403395744977020E-196 4.28087763478203718701697872488510E-196 + 325 2.14043881739101859350848936244255E-196 1.070219408695509296754244681221275E-196 + 326 5.351097043477546483771223406106375E-197 2.675548521738773241885611703053188E-197 + 327 1.337774260869386620942805851526594E-197 6.68887130434693310471402925763297E-198 + 328 3.344435652173466552357014628816485E-198 1.672217826086733276178507314408243E-198 + 329 8.361089130433666380892536572041215E-199 4.180544565216833190446268286020608E-199 + 330 2.090272282608416595223134143010304E-199 1.045136141304208297611567071505152E-199 + 331 5.22568070652104148805783535752576E-200 2.61284035326052074402891767876288E-200 + 332 1.30642017663026037201445883938144E-200 6.5321008831513018600722941969072E-201 + 333 3.2660504415756509300361470984536E-201 1.6330252207878254650180735492268E-201 + 334 8.165126103939127325090367746134E-202 4.082563051969563662545183873067E-202 + 335 2.0412815259847818312725919365335E-202 1.02064076299239091563629596826675E-202 + 336 5.10320381496195457818147984133375E-203 2.551601907480977289090739920666875E-203 + 337 1.275800953740488644545369960333438E-203 6.379004768702443222726849801667188E-204 + 338 3.189502384351221611363424900833594E-204 1.594751192175610805681712450416797E-204 + 339 7.973755960878054028408562252083985E-205 3.986877980439027014204281126041993E-205 + 340 1.993438990219513507102140563020997E-205 9.967194951097567535510702815104983E-206 + 341 4.983597475548783767755351407552492E-206 2.491798737774391883877675703776246E-206 + 342 1.245899368887195941938837851888123E-206 6.229496844435979709694189259440615E-207 + 343 3.114748422217989854847094629720308E-207 1.557374211108994927423547314860154E-207 + 344 7.78687105554497463711773657430077E-208 3.893435527772487318558868287150385E-208 + 345 1.946717763886243659279434143575193E-208 9.733588819431218296397170717875963E-209 + 346 4.866794409715609148198585358937982E-209 2.433397204857804574099292679468991E-209 + 347 1.216698602428902287049646339734496E-209 6.083493012144511435248231698672478E-210 + 348 3.041746506072255717624115849336239E-210 1.520873253036127858812057924668120E-210 + 349 7.60436626518063929406028962334060E-211 3.80218313259031964703014481167030E-211 + 350 1.90109156629515982351507240583515E-211 9.50545783147579911757536202917575E-212 + 351 4.752728915737899558787681014587875E-212 2.376364457868949779393840507293938E-212 + 352 1.188182228934474889696920253646969E-212 5.940911144672374448484601268234845E-213 + 353 2.970455572336187224242300634117423E-213 1.485227786168093612121150317058711E-213 + 354 7.426138930840468060605751585293555E-214 3.713069465420234030302875792646778E-214 + 355 1.856534732710117015151437896323389E-214 9.282673663550585075757189481616945E-215 + 356 4.641336831775292537878594740808473E-215 2.320668415887646268939297370404236E-215 + 357 1.160334207943823134469648685202118E-215 5.80167103971911567234824342601059E-216 + 358 2.900835519859557836174121713005295E-216 1.450417759929778918087060856502648E-216 + 359 7.25208879964889459043530428251324E-217 3.62604439982444729521765214125662E-217 + 360 1.81302219991222364760882607062831E-217 9.06511099956111823804413035314155E-218 + 361 4.532555499780559119022065176570775E-218 2.266277749890279559511032588285388E-218 + 362 1.133138874945139779755516294142694E-218 5.66569437472569889877758147071347E-219 + 363 2.832847187362849449388790735356735E-219 1.416423593681424724694395367678368E-219 + 364 7.08211796840712362347197683839184E-220 3.54105898420356181173598841919592E-220 + 365 1.77052949210178090586799420959796E-220 8.8526474605089045293399710479898E-221 + 366 4.4263237302544522646699855239949E-221 2.21316186512722613233499276199745E-221 + 367 1.106580932563613066167496380998725E-221 5.532904662818065330837481904993625E-222 + 368 2.766452331409032665418740952496813E-222 1.383226165704516332709370476248406E-222 + 369 6.91613082852258166354685238124203E-223 3.458065414261290831773426190621015E-223 + 370 1.729032707130645415886713095310508E-223 8.645163535653227079433565476552538E-224 + 371 4.322581767826613539716782738276269E-224 2.161290883913306769858391369138135E-224 + 372 1.080645441956653384929195684569068E-224 5.403227209783266924645978422845338E-225 + 373 2.701613604891633462322989211422669E-225 1.350806802445816731161494605711335E-225 + 374 6.754034012229083655807473028556675E-226 3.377017006114541827903736514278338E-226 + 375 1.688508503057270913951868257139169E-226 8.442542515286354569759341285695845E-227 + 376 4.221271257643177284879670642847923E-227 2.110635628821588642439835321423961E-227 + 377 1.055317814410794321219917660711981E-227 5.276589072053971606099588303559903E-228 + 378 2.638294536026985803049794151779952E-228 1.319147268013492901524897075889976E-228 + 379 6.59573634006746450762448537944988E-229 3.29786817003373225381224268972494E-229 + 380 1.64893408501686612690612134486247E-229 8.24467042508433063453060672431235E-230 + 381 4.122335212542165317265303362156175E-230 2.061167606271082658632651681078088E-230 + 382 1.030583803135541329316325840539044E-230 5.15291901567770664658162920269522E-231 + 383 2.57645950783885332329081460134761E-231 1.288229753919426661645407300673805E-231 + 384 6.441148769597133308227036503369025E-232 3.220574384798566654113518251684513E-232 + 385 1.610287192399283327056759125842257E-232 8.051435961996416635283795629211283E-233 + 386 4.025717980998208317641897814605642E-233 2.012858990499104158820948907302821E-233 + 387 1.006429495249552079410474453651411E-233 5.032147476247760397052372268257053E-234 + 388 2.516073738123880198526186134128527E-234 1.258036869061940099263093067064263E-234 + 389 6.290184345309700496315465335321315E-235 3.145092172654850248157732667660658E-235 + 390 1.572546086327425124078866333830329E-235 7.862730431637125620394331669151645E-236 + 391 3.931365215818562810197165834575823E-236 1.965682607909281405098582917287911E-236 + 392 9.828413039546407025492914586439555E-237 4.914206519773203512746457293219778E-237 + 393 2.457103259886601756373228646609889E-237 1.228551629943300878186614323304945E-237 + 394 6.142758149716504390933071616524725E-238 3.071379074858252195466535808262363E-238 + 395 1.535689537429126097733267904131182E-238 7.678447687145630488666339520655908E-239 + 396 3.839223843572815244333169760327954E-239 1.919611921786407622166584880163977E-239 + 397 9.598059608932038110832924400819885E-240 4.799029804466019055416462200409943E-240 + 398 2.399514902233009527708231100204972E-240 1.199757451116504763854115550102486E-240 + 399 5.99878725558252381927057775051243E-241 2.999393627791261909635288875256215E-241 + 400 1.499696813895630954817644437628108E-241 7.498484069478154774088222188140538E-242 + 401 3.749242034739077387044111094070269E-242 1.874621017369538693522055547035135E-242 + 402 9.373105086847693467610277735175675E-243 4.686552543423846733805138867587838E-243 + 403 2.343276271711923366902569433793919E-243 1.171638135855961683451284716896960E-243 + 404 5.85819067927980841725642358448480E-244 2.92909533963990420862821179224240E-244 + 405 1.46454766981995210431410589612120E-244 7.3227383490997605215705294806060E-245 + 406 3.6613691745498802607852647403030E-245 1.8306845872749401303926323701515E-245 + 407 9.1534229363747006519631618507575E-246 4.57671146818735032598158092537875E-246 + 408 2.288355734093675162990790462689375E-246 1.144177867046837581495395231344688E-246 + 409 5.72088933523418790747697615672344E-247 2.86044466761709395373848807836172E-247 + 410 1.43022233380854697686924403918086E-247 7.1511116690427348843462201959043E-248 + 411 3.57555583452136744217311009795215E-248 1.787777917260683721086555048976075E-248 + 412 8.938889586303418605432775244880375E-249 4.469444793151709302716387622440188E-249 + 413 2.234722396575854651358193811220094E-249 1.117361198287927325679096905610047E-249 + 414 5.586805991439636628395484528050235E-250 2.793402995719818314197742264025118E-250 + 415 1.396701497859909157098871132012559E-250 6.983507489299545785494355660062795E-251 + 416 3.491753744649772892747177830031398E-251 1.745876872324886446373588915015699E-251 + 417 8.729384361624432231867944575078495E-252 4.364692180812216115933972287539248E-252 + 418 2.182346090406108057966986143769624E-252 1.091173045203054028983493071884812E-252 + 419 5.45586522601527014491746535942406E-253 2.72793261300763507245873267971203E-253 + 420 1.363966306503817536229366339856015E-253 6.819831532519087681146831699280075E-254 + 421 3.409915766259543840573415849640038E-254 1.704957883129771920286707924820019E-254 + 422 8.524789415648859601433539624100095E-255 4.262394707824429800716769812050048E-255 + 423 2.131197353912214900358384906025024E-255 1.065598676956107450179192453012512E-255 + 424 5.32799338478053725089596226506256E-256 2.66399669239026862544798113253128E-256 + 425 1.33199834619513431272399056626564E-256 6.6599917309756715636199528313282E-257 + 426 3.3299958654878357818099764156641E-257 1.66499793274391789090498820783205E-257 + 427 8.32498966371958945452494103916025E-258 4.162494831859794727262470519580125E-258 + 428 2.081247415929897363631235259790063E-258 1.040623707964948681815617629895031E-258 + 429 5.203118539824743409078088149475155E-259 2.601559269912371704539044074737578E-259 + 430 1.300779634956185852269522037368789E-259 6.503898174780929261347610186843945E-260 + 431 3.251949087390464630673805093421973E-260 1.625974543695232315336902546710986E-260 + 432 8.12987271847616157668451273355493E-261 4.064936359238080788342256366777465E-261 + 433 2.032468179619040394171128183388733E-261 1.016234089809520197085564091694366E-261 + 434 5.08117044904760098542782045847183E-262 2.540585224523800492713910229235915E-262 + 435 1.270292612261900246356955114617958E-262 6.351463061309501231784775573089788E-263 + 436 3.175731530654750615892387786544894E-263 1.587865765327375307946193893272447E-263 + 437 7.939328826636876539730969466362235E-264 3.969664413318438269865484733181118E-264 + 438 1.984832206659219134932742366590559E-264 9.924161033296095674663711832952795E-265 + 439 4.962080516648047837331855916476398E-265 2.481040258324023918665927958238199E-265 + 440 1.240520129162011959332963979119100E-265 6.202600645810059796664819895595498E-266 + 441 3.101300322905029898332409947797749E-266 1.550650161452514949166204973898875E-266 + 442 7.753250807262574745831024869494375E-267 3.876625403631287372915512434747188E-267 + 443 1.938312701815643686457756217373594E-267 9.69156350907821843228878108686797E-268 + 444 4.845781754539109216144390543433985E-268 2.422890877269554608072195271716993E-268 + 445 1.211445438634777304036097635858497E-268 6.057227193173886520180488179292483E-269 + 446 3.028613596586943260090244089646242E-269 1.514306798293471630045122044823121E-269 + 447 7.571533991467358150225610224115605E-270 3.785766995733679075112805112057803E-270 + 448 1.892883497866839537556402556028902E-270 9.464417489334197687782012780144508E-271 + 449 4.732208744667098843891006390072254E-271 2.366104372333549421945503195036127E-271 + 450 1.183052186166774710972751597518064E-271 5.915260930833873554863757987590318E-272 + 451 2.957630465416936777431878993795159E-272 1.478815232708468388715939496897580E-272 + 452 7.39407616354234194357969748448790E-273 3.69703808177117097178984874224395E-273 + 453 1.848519040885585485894924371121975E-273 9.242595204427927429474621855609875E-274 + 454 4.621297602213963714737310927804938E-274 2.310648801106981857368655463902469E-274 + 455 1.155324400553490928684327731951235E-274 5.776622002767454643421638659756173E-275 + 456 2.888311001383727321710819329878087E-275 1.444155500691863660855409664939043E-275 + 457 7.220777503459318304277048324695215E-276 3.610388751729659152138524162347608E-276 + 458 1.805194375864829576069262081173804E-276 9.02597187932414788034631040586902E-277 + 459 4.51298593966207394017315520293451E-277 2.256492969831036970086577601467255E-277 + 460 1.128246484915518485043288800733628E-277 5.641232424577592425216444003668138E-278 + 461 2.820616212288796212608222001834069E-278 1.410308106144398106304111000917035E-278 + 462 7.051540530721990531520555004585175E-279 3.525770265360995265760277502292588E-279 + 463 1.762885132680497632880138751146294E-279 8.81442566340248816440069375573147E-280 + 464 4.407212831701244082200346877865735E-280 2.203606415850622041100173438932868E-280 + 465 1.101803207925311020550086719466434E-280 5.50901603962655510275043359733217E-281 + 466 2.754508019813277551375216798666085E-281 1.377254009906638775687608399333043E-281 + 467 6.886270049533193878438041996665215E-282 3.443135024766596939219020998332608E-282 + 468 1.721567512383298469609510499166304E-282 8.60783756191649234804755249583152E-283 + 469 4.30391878095824617402377624791576E-283 2.15195939047912308701188812395788E-283 + 470 1.07597969523956154350594406197894E-283 5.3798984761978077175297203098947E-284 + 471 2.68994923809890385876486015494735E-284 1.344974619049451929382430077473675E-284 + 472 6.724873095247259646912150387368375E-285 3.362436547623629823456075193684188E-285 + 473 1.681218273811814911728037596842094E-285 8.40609136905907455864018798421047E-286 + 474 4.203045684529537279320093992105235E-286 2.101522842264768639660046996052618E-286 + 475 1.050761421132384319830023498026309E-286 5.253807105661921599150117490131545E-287 + 476 2.626903552830960799575058745065773E-287 1.313451776415480399787529372532886E-287 + 477 6.56725888207740199893764686266443E-288 3.283629441038700999468823431332215E-288 + 478 1.641814720519350499734411715666108E-288 8.209073602596752498672058578330538E-289 + 479 4.104536801298376249336029289165269E-289 2.052268400649188124668014644582635E-289 + 480 1.026134200324594062334007322291318E-289 5.130671001622970311670036611456588E-290 + 481 2.565335500811485155835018305728294E-290 1.282667750405742577917509152864147E-290 + 482 6.413338752028712889587545764320735E-291 3.206669376014356444793772882160368E-291 + 483 1.603334688007178222396886441080184E-291 8.01667344003589111198443220540092E-292 + 484 4.00833672001794555599221610270046E-292 2.00416836000897277799610805135023E-292 + 485 1.002084180004486388998054025675115E-292 5.010420900022431944990270128375575E-293 + 486 2.505210450011215972495135064187788E-293 1.252605225005607986247567532093894E-293 + 487 6.26302612502803993123783766046947E-294 3.131513062514019965618918830234735E-294 + 488 1.565756531257009982809459415117368E-294 7.828782656285049914047297075586838E-295 + 489 3.914391328142524957023648537793419E-295 1.957195664071262478511824268896710E-295 + 490 9.78597832035631239255912134448355E-296 4.892989160178156196279560672241775E-296 + 491 2.446494580089078098139780336120888E-296 1.223247290044539049069890168060444E-296 + 492 6.11623645022269524534945084030222E-297 3.05811822511134762267472542015111E-297 + 493 1.529059112555673811337362710075555E-297 7.645295562778369056686813550377775E-298 + 494 3.822647781389184528343406775188888E-298 1.911323890694592264171703387594444E-298 + 495 9.55661945347296132085851693797222E-299 4.77830972673648066042925846898611E-299 + 496 2.389154863368240330214629234493055E-299 1.194577431684120165107314617246528E-299 + 497 5.97288715842060082553657308623264E-300 2.98644357921030041276828654311632E-300 + 498 1.49322178960515020638414327155816E-300 7.4661089480257510319207163577908E-301 + 499 3.7330544740128755159603581788954E-301 1.8665272370064377579801790894477E-301 + 500 9.3326361850321887899008954472385E-302 4.66631809251609439495044772361925E-302 + 501 2.333159046258047197475223861809625E-302 1.166579523129023598737611930904813E-302 + 502 5.832897615645117993688059654524065E-303 2.916448807822558996844029827262033E-303 + 503 1.458224403911279498422014913631017E-303 7.291122019556397492110074568155083E-304 + 504 3.645561009778198746055037284077542E-304 1.822780504889099373027518642038771E-304 + 505 9.113902524445496865137593210193855E-305 4.556951262222748432568796605096928E-305 + 506 2.278475631111374216284398302548464E-305 1.139237815555687108142199151274232E-305 + 507 5.69618907777843554071099575637116E-306 2.84809453888921777035549787818558E-306 + 508 1.42404726944460888517774893909279E-306 7.12023634722304442588874469546395E-307 + 509 3.560118173611522212944372347731975E-307 1.780059086805761106472186173865988E-307 + 510 8.90029543402880553236093086932994E-308 4.45014771701440276618046543466497E-308 + 511 2.225073858507201383090232717332485E-308 1.112536929253600691545116358666243E-308 + 512 5.562684646268003457725581793331215E-309 2.781342323134001728862790896665608E-309 + 513 1.390671161567000864431395448332804E-309 6.95335580783500432215697724166402E-310 + 514 3.47667790391750216107848862083201E-310 1.738338951958751080539244310416005E-310 + 515 8.691694759793755402696221552080025E-311 4.345847379896877701348110776040013E-311 + 516 2.172923689948438850674055388020007E-311 1.086461844974219425337027694010003E-311 + 517 5.432309224871097126685138470050015E-312 2.716154612435548563342569235025008E-312 + 518 1.358077306217774281671284617512504E-312 6.79038653108887140835642308756252E-313 + 519 3.39519326554443570417821154378126E-313 1.69759663277221785208910577189063E-313 + 520 8.48798316386108926044552885945315E-314 4.243991581930544630222764429726575E-314 + 521 2.121995790965272315111382214863288E-314 1.060997895482636157555691107431644E-314 + 522 5.30498947741318078777845553715822E-315 2.65249473870659039388922776857911E-315 + 523 1.326247369353295196944613884289555E-315 6.631236846766475984723069421447775E-316 + 524 3.315618423383237992361534710723888E-316 1.657809211691618996180767355361944E-316 + 525 8.28904605845809498090383677680972E-317 4.14452302922904749045191838840486E-317 + 526 2.07226151461452374522595919420243E-317 1.036130757307261872612979597101215E-317 + 527 5.180653786536309363064897985506075E-318 2.590326893268154681532448992753038E-318 + 528 1.295163446634077340766224496376519E-318 6.475817233170386703831122481882595E-319 + 529 3.237908616585193351915561240941298E-319 1.618954308292596675957780620470649E-319 + 530 8.094771541462983379788903102353245E-320 4.047385770731491689894451551176623E-320 + 531 2.023692885365745844947225775588312E-320 1.011846442682872922473612887794156E-320 + 532 5.05923221341436461236806443897078E-321 2.52961610670718230618403221948539E-321 + 533 1.264808053353591153092016109742695E-321 6.324040266767955765460080548713475E-322 + 534 3.162020133383977882730040274356738E-322 1.581010066691988941365020137178369E-322 + 535 7.905050333459944706825100685891845E-323 3.952525166729972353412550342945923E-323 + 536 1.976262583364986176706275171472962E-323 9.881312916824930883531375857364808E-324 + 537 4.940656458412465441765687928682404E-324 2.470328229206232720882843964341202E-324 + 538 1.235164114603116360441421982170601E-324 6.175820573015581802207109910853005E-325 + 539 3.087910286507790901103554955426503E-325 1.543955143253895450551777477713251E-325 + 540 7.719775716269477252758887388566255E-326 3.859887858134738626379443694283128E-326 + 541 1.929943929067369313189721847141564E-326 9.64971964533684656594860923570782E-327 + 542 4.82485982266842328297430461785391E-327 2.412429911334211641487152308926955E-327 + 543 1.206214955667105820743576154463478E-327 6.031074778335529103717880772317388E-328 + 544 3.015537389167764551858940386158694E-328 1.507768694583882275929470193079347E-328 + 545 7.538843472919411379647350965396735E-329 3.769421736459705689823675482698368E-329 + 546 1.884710868229852844911837741349184E-329 9.42355434114926422455918870674592E-330 + 547 4.71177717057463211227959435337296E-330 2.35588858528731605613979717668648E-330 + 548 1.17794429264365802806989858834324E-330 5.8897214632182901403494929417162E-331 + 549 2.9448607316091450701747464708581E-331 1.47243036580457253508737323542905E-331 + 550 7.36215182902286267543686617714525E-332 3.681075914511431337718433088572625E-332 + 551 1.840537957255715668859216544286313E-332 9.202689786278578344296082721431563E-333 + 552 4.601344893139289172148041360715782E-333 2.300672446569644586074020680357891E-333 + 553 1.150336223284822293037010340178946E-333 5.751681116424111465185051700894728E-334 + 554 2.875840558212055732592525850447364E-334 1.437920279106027866296262925223682E-334 + 555 7.18960139553013933148131462611841E-335 3.594800697765069665740657313059205E-335 + 556 1.797400348882534832870328656529603E-335 8.987001744412674164351643282648013E-336 + 557 4.493500872206337082175821641324007E-336 2.246750436103168541087910820662003E-336 + 558 1.123375218051584270543955410331002E-336 5.616876090257921352719777051655008E-337 + 559 2.808438045128960676359888525827504E-337 1.404219022564480338179944262913752E-337 + 560 7.02109511282240169089972131456876E-338 3.51054755641120084544986065728438E-338 + 561 1.75527377820560042272493032864219E-338 8.77636889102800211362465164321095E-339 + 562 4.388184445514001056812325821605475E-339 2.194092222757000528406162910802738E-339 + 563 1.097046111378500264203081455401369E-339 5.485230556892501321015407277006845E-340 + 564 2.742615278446250660507703638503423E-340 1.371307639223125330253851819251711E-340 + 565 6.856538196115626651269259096258555E-341 3.428269098057813325634629548129278E-341 + 566 1.714134549028906662817314774064639E-341 8.570672745144533314086573870323195E-342 + 567 4.285336372572266657043286935161598E-342 2.142668186286133328521643467580799E-342 + 568 1.071334093143066664260821733790400E-342 5.356670465715333321304108668951998E-343 + 569 2.678335232857666660652054334475999E-343 1.339167616428833330326027167238000E-343 + 570 6.69583808214416665163013583619000E-344 3.34791904107208332581506791809500E-344 + 571 1.67395952053604166290753395904750E-344 8.3697976026802083145376697952375E-345 + 572 4.18489880134010415726883489761875E-345 2.092449400670052078634417448809375E-345 + 573 1.046224700335026039317208724404688E-345 5.231123501675130196586043622023438E-346 + 574 2.615561750837565098293021811011719E-346 1.307780875418782549146510905505860E-346 + 575 6.53890437709391274573255452752930E-347 3.26945218854695637286627726376465E-347 + 576 1.634726094273478186433138631882325E-347 8.173630471367390932165693159411625E-348 + 577 4.086815235683695466082846579705813E-348 2.043407617841847733041423289852906E-348 + 578 1.021703808920923866520711644926453E-348 5.108519044604619332603558224632265E-349 + 579 2.554259522302309666301779112316133E-349 1.277129761151154833150889556158066E-349 + 580 6.38564880575577416575444778079033E-350 3.192824402877887082877223890395165E-350 + 581 1.596412201438943541438611945197583E-350 7.982061007194717707193059725987913E-351 + 582 3.991030503597358853596529862993957E-351 1.995515251798679426798264931496978E-351 + 583 9.97757625899339713399132465748489E-352 4.988788129496698566995662328742445E-352 + 584 2.494394064748349283497831164371223E-352 1.247197032374174641748915582185611E-352 + 585 6.235985161870873208744577910928055E-353 3.117992580935436604372288955464028E-353 + 586 1.558996290467718302186144477732014E-353 7.79498145233859151093072238866007E-354 + 587 3.897490726169295755465361194330035E-354 1.948745363084647877732680597165018E-354 + 588 9.74372681542323938866340298582509E-355 4.871863407711619694331701492912545E-355 + 589 2.435931703855809847165850746456273E-355 1.217965851927904923582925373228136E-355 + 590 6.08982925963952461791462686614068E-356 3.04491462981976230895731343307034E-356 + 591 1.52245731490988115447865671653517E-356 7.61228657454940577239328358267585E-357 + 592 3.806143287274702886196641791337925E-357 1.903071643637351443098320895668963E-357 + 593 9.515358218186757215491604478344815E-358 4.757679109093378607745802239172408E-358 + 594 2.378839554546689303872901119586204E-358 1.189419777273344651936450559793102E-358 + 595 5.94709888636672325968225279896551E-359 2.973549443183361629841126399482755E-359 + 596 1.486774721591680814920563199741378E-359 7.433873607958404074602815998706888E-360 + 597 3.716936803979202037301407999353444E-360 1.858468401989601018650703999676722E-360 + 598 9.29234200994800509325351999838361E-361 4.646171004974002546626759999191805E-361 + 599 2.323085502487001273313379999595903E-361 1.161542751243500636656689999797951E-361 + 600 5.807713756217503183283449998989755E-362 2.903856878108751591641724999494878E-362 + 601 1.451928439054375795820862499747439E-362 7.259642195271878979104312498737195E-363 + 602 3.629821097635939489552156249368598E-363 1.814910548817969744776078124684299E-363 + 603 9.074552744089848723880390623421495E-364 4.537276372044924361940195311710748E-364 + 604 2.268638186022462180970097655855374E-364 1.134319093011231090485048827927687E-364 + 605 5.671595465056155452425244139638435E-365 2.835797732528077726212622069819218E-365 + 606 1.417898866264038863106311034909609E-365 7.089494331320194315531555174548045E-366 + 607 3.544747165660097157765777587274023E-366 1.772373582830048578882888793637011E-366 + 608 8.861867914150242894414443968185055E-367 4.430933957075121447207221984092528E-367 + 609 2.215466978537560723603610992046264E-367 1.107733489268780361801805496023132E-367 + 610 5.53866744634390180900902748011566E-368 2.76933372317195090450451374005783E-368 + 611 1.384666861585975452252256870028915E-368 6.923334307929877261261284350144575E-369 + 612 3.461667153964938630630642175072288E-369 1.730833576982469315315321087536144E-369 + 613 8.65416788491234657657660543768072E-370 4.32708394245617328828830271884036E-370 + 614 2.16354197122808664414415135942018E-370 1.08177098561404332207207567971009E-370 + 615 5.40885492807021661036037839855045E-371 2.704427464035108305180189199275225E-371 + 616 1.352213732017554152590094599637613E-371 6.761068660087770762950472998188063E-372 + 617 3.380534330043885381475236499094032E-372 1.690267165021942690737618249547016E-372 + 618 8.45133582510971345368809124773508E-373 4.22566791255485672684404562386754E-373 + 619 2.11283395627742836342202281193377E-373 1.056416978138714181711011405966885E-373 + 620 5.282084890693570908555057029834425E-374 2.641042445346785454277528514917213E-374 + 621 1.320521222673392727138764257458607E-374 6.602606113366963635693821287293033E-375 + 622 3.301303056683481817846910643646517E-375 1.650651528341740908923455321823258E-375 + 623 8.25325764170870454461727660911629E-376 4.126628820854352272308638304558145E-376 + 624 2.063314410427176136154319152279073E-376 1.031657205213588068077159576139536E-376 + 625 5.15828602606794034038579788069768E-377 2.57914301303397017019289894034884E-377 + 626 1.28957150651698508509644947017442E-377 6.4478575325849254254822473508721E-378 + 627 3.22392876629246271274112367543605E-378 1.611964383146231356370561837718025E-378 + 628 8.059821915731156781852809188590125E-379 4.029910957865578390926404594295063E-379 + 629 2.014955478932789195463202297147532E-379 1.007477739466394597731601148573766E-379 + 630 5.03738869733197298865800574286883E-380 2.518694348665986494329002871434415E-380 + 631 1.259347174332993247164501435717208E-380 6.296735871664966235822507178586038E-381 + 632 3.148367935832483117911253589293019E-381 1.574183967916241558955626794646510E-381 + 633 7.87091983958120779477813397323255E-382 3.935459919790603897389066986616275E-382 + 634 1.967729959895301948694533493308138E-382 9.838649799476509743472667466540688E-383 + 635 4.919324899738254871736333733270344E-383 2.459662449869127435868166866635172E-383 + 636 1.229831224934563717934083433317586E-383 6.14915612467281858967041716658793E-384 + 637 3.074578062336409294835208583293965E-384 1.537289031168204647417604291646983E-384 + 638 7.686445155841023237088021458234915E-385 3.843222577920511618544010729117458E-385 + 639 1.921611288960255809272005364558729E-385 9.608056444801279046360026822793645E-386 + 640 4.804028222400639523180013411396823E-386 2.402014111200319761590006705698411E-386 + 641 1.201007055600159880795003352849206E-386 6.005035278000799403975016764246028E-387 + 642 3.002517639000399701987508382123014E-387 1.501258819500199850993754191061507E-387 + 643 7.506294097500999254968770955307535E-388 3.753147048750499627484385477653768E-388 + 644 1.876573524375249813742192738826884E-388 9.38286762187624906871096369413442E-389 + 645 4.69143381093812453435548184706721E-389 2.345716905469062267177740923533605E-389 + 646 1.172858452734531133588870461766803E-389 5.864292263672655667944352308834013E-390 + 647 2.932146131836327833972176154417007E-390 1.466073065918163916986088077208503E-390 + 648 7.330365329590819584930440386042515E-391 3.665182664795409792465220193021258E-391 + 649 1.832591332397704896232610096510629E-391 9.162956661988524481163050482553145E-392 + 650 4.581478330994262240581525241276573E-392 2.290739165497131120290762620638286E-392 + 651 1.145369582748565560145381310319143E-392 5.726847913742827800726906551595715E-393 + 652 2.863423956871413900363453275797858E-393 1.431711978435706950181726637898929E-393 + 653 7.158559892178534750908633189494645E-394 3.579279946089267375454316594747323E-394 + 654 1.789639973044633687727158297373662E-394 8.948199865223168438635791486868308E-395 + 655 4.474099932611584219317895743434154E-395 2.237049966305792109658947871717077E-395 + 656 1.118524983152896054829473935858539E-395 5.592624915764480274147369679292693E-396 + 657 2.796312457882240137073684839646347E-396 1.398156228941120068536842419823173E-396 + 658 6.990781144705600342684212099115865E-397 3.495390572352800171342106049557933E-397 + 659 1.747695286176400085671053024778967E-397 8.738476430882000428355265123894833E-398 + 660 4.369238215441000214177632561947417E-398 2.184619107720500107088816280973708E-398 + 661 1.092309553860250053544408140486854E-398 5.46154776930125026772204070243427E-399 + 662 2.730773884650625133861020351217135E-399 1.365386942325312566930510175608568E-399 + 663 6.82693471162656283465255087804284E-400 3.41346735581328141732627543902142E-400 + 664 1.70673367790664070866313771951071E-400 8.53366838953320354331568859755355E-401 + 665 4.266834194766601771657844298776775E-401 2.133417097383300885828922149388388E-401 + 666 1.066708548691650442914461074694194E-401 5.33354274345825221457230537347097E-402 + 667 2.666771371729126107286152686735485E-402 1.333385685864563053643076343367743E-402 + 668 6.666928429322815268215381716838715E-403 3.333464214661407634107690858419358E-403 + 669 1.666732107330703817053845429209679E-403 8.333660536653519085269227146048395E-404 + 670 4.166830268326759542634613573024198E-404 2.083415134163379771317306786512099E-404 + 671 1.041707567081689885658653393256050E-404 5.208537835408449428293266966280248E-405 + 672 2.604268917704224714146633483140124E-405 1.302134458852112357073316741570062E-405 + 673 6.51067229426056178536658370785031E-406 3.255336147130280892683291853925155E-406 + 674 1.627668073565140446341645926962578E-406 8.138340367825702231708229634812888E-407 + 675 4.069170183912851115854114817406444E-407 2.034585091956425557927057408703222E-407 + 676 1.017292545978212778963528704351611E-407 5.086462729891063894817643521758055E-408 + 677 2.543231364945531947408821760879028E-408 1.271615682472765973704410880439514E-408 + 678 6.35807841236382986852205440219757E-409 3.179039206181914934261027201098785E-409 + 679 1.589519603090957467130513600549393E-409 7.947598015454787335652568002746963E-410 + 680 3.973799007727393667826284001373482E-410 1.986899503863696833913142000686741E-410 + 681 9.934497519318484169565710003433705E-411 4.967248759659242084782855001716853E-411 + 682 2.483624379829621042391427500858427E-411 1.241812189914810521195713750429213E-411 + 683 6.209060949574052605978568752146065E-412 3.104530474787026302989284376073033E-412 + 684 1.552265237393513151494642188036517E-412 7.761326186967565757473210940182583E-413 + 685 3.880663093483782878736605470091292E-413 1.940331546741891439368302735045646E-413 + 686 9.70165773370945719684151367522823E-414 4.850828866854728598420756837614115E-414 + 687 2.425414433427364299210378418807058E-414 1.212707216713682149605189209403529E-414 + 688 6.063536083568410748025946047017645E-415 3.031768041784205374012973023508823E-415 + 689 1.515884020892102687006486511754412E-415 7.579420104460513435032432558772058E-416 + 690 3.789710052230256717516216279386029E-416 1.894855026115128358758108139693015E-416 + 691 9.474275130575641793790540698465075E-417 4.737137565287820896895270349232538E-417 + 692 2.368568782643910448447635174616269E-417 1.184284391321955224223817587308135E-417 + 693 5.921421956609776121119087936540675E-418 2.960710978304888060559543968270338E-418 + 694 1.480355489152444030279771984135169E-418 7.401777445762220151398859920675845E-419 + 695 3.700888722881110075699429960337923E-419 1.850444361440555037849714980168961E-419 + 696 9.252221807202775189248574900844805E-420 4.626110903601387594624287450422403E-420 + 697 2.313055451800693797312143725211202E-420 1.156527725900346898656071862605601E-420 + 698 5.782638629501734493280359313028005E-421 2.891319314750867246640179656514003E-421 + 699 1.445659657375433623320089828257002E-421 7.228298286877168116600449141285008E-422 + 700 3.614149143438584058300224570642504E-422 1.807074571719292029150112285321252E-422 + 701 9.03537285859646014575056142660626E-423 4.51768642929823007287528071330313E-423 + 702 2.258843214649115036437640356651565E-423 1.129421607324557518218820178325783E-423 + 703 5.647108036622787591094100891628915E-424 2.823554018311393795547050445814458E-424 + 704 1.411777009155696897773525222907229E-424 7.058885045778484488867626114536145E-425 + 705 3.529442522889242244433813057268073E-425 1.764721261444621122216906528634036E-425 + 706 8.82360630722310561108453264317018E-426 4.41180315361155280554226632158509E-426 + 707 2.205901576805776402771133160792545E-426 1.102950788402888201385566580396273E-426 + 708 5.514753942014441006927832901981365E-427 2.757376971007220503463916450990683E-427 + 709 1.378688485503610251731958225495342E-427 6.893442427518051258659791127476708E-428 + 710 3.446721213759025629329895563738354E-428 1.723360606879512814664947781869177E-428 + 711 8.616803034397564073324738909345885E-429 4.308401517198782036662369454672943E-429 + 712 2.154200758599391018331184727336472E-429 1.077100379299695509165592363668236E-429 + 713 5.38550189649847754582796181834118E-430 2.69275094824923877291398090917059E-430 + 714 1.346375474124619386456990454585295E-430 6.731877370623096932284952272926475E-431 + 715 3.365938685311548466142476136463238E-431 1.682969342655774233071238068231619E-431 + 716 8.414846713278871165356190341158095E-432 4.207423356639435582678095170579048E-432 + 717 2.103711678319717791339047585289524E-432 1.051855839159858895669523792644762E-432 + 718 5.25927919579929447834761896322381E-433 2.629639597899647239173809481611905E-433 + 719 1.314819798949823619586904740805953E-433 6.574098994749118097934523704029763E-434 + 720 3.287049497374559048967261852014882E-434 1.643524748687279524483630926007441E-434 + 721 8.217623743436397622418154630037205E-435 4.108811871718198811209077315018603E-435 + 722 2.054405935859099405604538657509302E-435 1.027202967929549702802269328754651E-435 + 723 5.136014839647748514011346643773255E-436 2.568007419823874257005673321886628E-436 + 724 1.284003709911937128502836660943314E-436 6.42001854955968564251418330471657E-437 + 725 3.210009274779842821257091652358285E-437 1.605004637389921410628545826179143E-437 + 726 8.025023186949607053142729130895715E-438 4.012511593474803526571364565447858E-438 + 727 2.006255796737401763285682282723929E-438 1.003127898368700881642841141361965E-438 + 728 5.015639491843504408214205706809825E-439 2.507819745921752204107102853404913E-439 + 729 1.253909872960876102053551426702457E-439 6.269549364804380510267757133512283E-440 + 730 3.134774682402190255133878566756142E-440 1.567387341201095127566939283378071E-440 + 731 7.836936706005475637834696416890355E-441 3.918468353002737818917348208445178E-441 + 732 1.959234176501368909458674104222589E-441 9.796170882506844547293370521112945E-442 + 733 4.898085441253422273646685260556473E-442 2.449042720626711136823342630278236E-442 + 734 1.224521360313355568411671315139118E-442 6.12260680156677784205835657569559E-443 + 735 3.061303400783388921029178287847795E-443 1.530651700391694460514589143923898E-443 + 736 7.65325850195847230257294571961949E-444 3.826629250979236151286472859809745E-444 + 737 1.913314625489618075643236429904873E-444 9.566573127448090378216182149524363E-445 + 738 4.783286563724045189108091074762182E-445 2.391643281862022594554045537381091E-445 + 739 1.195821640931011297277022768690546E-445 5.979108204655056486385113843452728E-446 + 740 2.989554102327528243192556921726364E-446 1.494777051163764121596278460863182E-446 + 741 7.47388525581882060798139230431591E-447 3.736942627909410303990696152157955E-447 + 742 1.868471313954705151995348076078978E-447 9.342356569773525759976740380394888E-448 + 743 4.671178284886762879988370190197444E-448 2.335589142443381439994185095098722E-448 + 744 1.167794571221690719997092547549361E-448 5.838972856108453599985462737746805E-449 + 745 2.919486428054226799992731368873403E-449 1.459743214027113399996365684436701E-449 + 746 7.298716070135566999981828422183505E-450 3.649358035067783499990914211091753E-450 + 747 1.824679017533891749995457105545877E-450 9.123395087669458749977285527729383E-451 + 748 4.561697543834729374988642763864692E-451 2.280848771917364687494321381932346E-451 + 749 1.140424385958682343747160690966173E-451 5.702121929793411718735803454830865E-452 + 750 2.851060964896705859367901727415433E-452 1.425530482448352929683950863707716E-452 + 751 7.12765241224176464841975431853858E-453 3.56382620612088232420987715926929E-453 + 752 1.781913103060441162104938579634645E-453 8.909565515302205810524692898173225E-454 + 753 4.454782757651102905262346449086613E-454 2.227391378825551452631173224543306E-454 + 754 1.113695689412775726315586612271653E-454 5.568478447063878631577933061358265E-455 + 755 2.784239223531939315788966530679133E-455 1.392119611765969657894483265339566E-455 + 756 6.96059805882984828947241632669783E-456 3.480299029414924144736208163348915E-456 + 757 1.740149514707462072368104081674458E-456 8.700747573537310361840520408372288E-457 + 758 4.350373786768655180920260204186144E-457 2.175186893384327590460130102093072E-457 + 759 1.087593446692163795230065051046536E-457 5.43796723346081897615032525523268E-458 + 760 2.71898361673040948807516262761634E-458 1.35949180836520474403758131380817E-458 + 761 6.79745904182602372018790656904085E-459 3.398729520913011860093953284520425E-459 + 762 1.699364760456505930046976642260213E-459 8.496823802282529650234883211301063E-460 + 763 4.248411901141264825117441605650532E-460 2.124205950570632412558720802825266E-460 + 764 1.062102975285316206279360401412633E-460 5.310514876426581031396802007063165E-461 + 765 2.655257438213290515698401003531583E-461 1.327628719106645257849200501765791E-461 + 766 6.638143595533226289246002508828955E-462 3.319071797766613144623001254414478E-462 + 767 1.659535898883306572311500627207239E-462 8.297679494416532861557503136036195E-463 + 768 4.148839747208266430778751568018098E-463 2.074419873604133215389375784009049E-463 + 769 1.037209936802066607694687892004525E-463 5.186049684010333038473439460022623E-464 + 770 2.593024842005166519236719730011312E-464 1.296512421002583259618359865005656E-464 + 771 6.48256210501291629809179932502828E-465 3.24128105250645814904589966251414E-465 + 772 1.62064052625322907452294983125707E-465 8.10320263126614537261474915628535E-466 + 773 4.051601315633072686307374578142675E-466 2.025800657816536343153687289071338E-466 + 774 1.012900328908268171576843644535669E-466 5.064501644541340857884218222678345E-467 + 775 2.532250822270670428942109111339173E-467 1.266125411135335214471054555669586E-467 + 776 6.33062705567667607235527277834793E-468 3.165313527838338036177636389173965E-468 + 777 1.582656763919169018088818194586983E-468 7.913283819595845090444090972934913E-469 + 778 3.956641909797922545222045486467457E-469 1.978320954898961272611022743233728E-469 + 779 9.89160477449480636305511371616864E-470 4.94580238724740318152755685808432E-470 + 780 2.47290119362370159076377842904216E-470 1.23645059681185079538188921452108E-470 + 781 6.1822529840592539769094460726054E-471 3.0911264920296269884547230363027E-471 + 782 1.54556324601481349422736151815135E-471 7.72781623007406747113680759075675E-472 + 783 3.863908115037033735568403795378375E-472 1.931954057518516867784201897689188E-472 + 784 9.65977028759258433892100948844594E-473 4.82988514379629216946050474422297E-473 + 785 2.414942571898146084730252372111485E-473 1.207471285949073042365126186055743E-473 + 786 6.037356429745365211825630930278715E-474 3.018678214872682605912815465139358E-474 + 787 1.509339107436341302956407732569679E-474 7.546695537181706514782038662848395E-475 + 788 3.773347768590853257391019331424198E-475 1.886673884295426628695509665712099E-475 + 789 9.433369421477133143477548328560495E-476 4.716684710738566571738774164280248E-476 + 790 2.358342355369283285869387082140124E-476 1.179171177684641642934693541070062E-476 + 791 5.89585588842320821467346770535031E-477 2.947927944211604107336733852675155E-477 + 792 1.473963972105802053668366926337578E-477 7.369819860529010268341834631687888E-478 + 793 3.684909930264505134170917315843944E-478 1.842454965132252567085458657921972E-478 + 794 9.21227482566126283542729328960986E-479 4.60613741283063141771364664480493E-479 + 795 2.303068706415315708856823322402465E-479 1.151534353207657854428411661201233E-479 + 796 5.757671766038289272142058306006165E-480 2.878835883019144636071029153003083E-480 + 797 1.439417941509572318035514576501542E-480 7.197089707547861590177572882507708E-481 + 798 3.598544853773930795088786441253854E-481 1.799272426886965397544393220626927E-481 + 799 8.996362134434826987721966103134635E-482 4.498181067217413493860983051567318E-482 + 800 2.249090533608706746930491525783659E-482 1.124545266804353373465245762891830E-482 + 801 5.62272633402176686732622881445915E-483 2.811363167010883433663114407229575E-483 + 802 1.405681583505441716831557203614788E-483 7.028407917527208584157786018073938E-484 + 803 3.514203958763604292078893009036969E-484 1.757101979381802146039446504518485E-484 + 804 8.785509896909010730197232522592425E-485 4.392754948454505365098616261296213E-485 + 805 2.196377474227252682549308130648107E-485 1.098188737113626341274654065324053E-485 + 806 5.490943685568131706373270326620265E-486 2.745471842784065853186635163310133E-486 + 807 1.372735921392032926593317581655067E-486 6.863679606960164632966587908275333E-487 + 808 3.431839803480082316483293954137667E-487 1.715919901740041158241646977068833E-487 + 809 8.579599508700205791208234885344165E-488 4.289799754350102895604117442672083E-488 + 810 2.144899877175051447802058721336042E-488 1.072449938587525723901029360668021E-488 + 811 5.362249692937628619505146803340105E-489 2.681124846468814309752573401670053E-489 + 812 1.340562423234407154876286700835027E-489 6.702812116172035774381433504175133E-490 + 813 3.351406058086017887190716752087567E-490 1.675703029043008943595358376043783E-490 + 814 8.378515145215044717976791880218915E-491 4.189257572607522358988395940109458E-491 + 815 2.094628786303761179494197970054729E-491 1.047314393151880589747098985027365E-491 + 816 5.236571965759402948735494925136825E-492 2.618285982879701474367747462568413E-492 + 817 1.309142991439850737183873731284207E-492 6.545714957199253685919368656421033E-493 + 818 3.272857478599626842959684328210517E-493 1.636428739299813421479842164105258E-493 + 819 8.18214369649906710739921082052629E-494 4.091071848249533553699605410263145E-494 + 820 2.045535924124766776849802705131573E-494 1.022767962062383388424901352565786E-494 + 821 5.11383981031191694212450676282893E-495 2.556919905155958471062253381414465E-495 + 822 1.278459952577979235531126690707233E-495 6.392299762889896177655633453536163E-496 + 823 3.196149881444948088827816726768082E-496 1.598074940722474044413908363384041E-496 + 824 7.990374703612370222069541816920205E-497 3.995187351806185111034770908460103E-497 + 825 1.997593675903092555517385454230052E-497 9.987968379515462777586927271150258E-498 + 826 4.993984189757731388793463635575129E-498 2.496992094878865694396731817787565E-498 + 827 1.248496047439432847198365908893783E-498 6.242480237197164235991829544468913E-499 + 828 3.121240118598582117995914772234457E-499 1.560620059299291058997957386117228E-499 + 829 7.80310029649645529498978693058614E-500 3.90155014824822764749489346529307E-500 + 830 1.950775074124113823747446732646535E-500 9.753875370620569118737233663232675E-501 + 831 4.876937685310284559368616831616338E-501 2.438468842655142279684308415808169E-501 + 832 1.219234421327571139842154207904085E-501 6.096172106637855699210771039520423E-502 + 833 3.048086053318927849605385519760212E-502 1.524043026659463924802692759880106E-502 + 834 7.62021513329731962401346379940053E-503 3.810107566648659812006731899700265E-503 + 835 1.905053783324329906003365949850133E-503 9.525268916621649530016829749250663E-504 + 836 4.762634458310824765008414874625332E-504 2.381317229155412382504207437312666E-504 + 837 1.190658614577706191252103718656333E-504 5.953293072888530956260518593281665E-505 + 838 2.976646536444265478130259296640833E-505 1.488323268222132739065129648320416E-505 + 839 7.44161634111066369532564824160208E-506 3.72080817055533184766282412080104E-506 + 840 1.86040408527766592383141206040052E-506 9.3020204263883296191570603020026E-507 + 841 4.6510102131941648095785301510013E-507 2.32550510659708240478926507550065E-507 + 842 1.162752553298541202394632537750325E-507 5.813762766492706011973162688751625E-508 + 843 2.906881383246353005986581344375813E-508 1.453440691623176502993290672187906E-508 + 844 7.26720345811588251496645336093953E-509 3.633601729057941257483226680469765E-509 + 845 1.816800864528970628741613340234883E-509 9.084004322644853143708066701174413E-510 + 846 4.542002161322426571854033350587207E-510 2.271001080661213285927016675293603E-510 + 847 1.135500540330606642963508337646802E-510 5.677502701653033214817541688234008E-511 + 848 2.838751350826516607408770844117004E-511 1.419375675413258303704385422058502E-511 + 849 7.09687837706629151852192711029251E-512 3.548439188533145759260963555146255E-512 + 850 1.774219594266572879630481777573128E-512 8.871097971332864398152408887865638E-513 + 851 4.435548985666432199076204443932819E-513 2.217774492833216099538102221966410E-513 + 852 1.108887246416608049769051110983205E-513 5.544436232083040248845255554916025E-514 + 853 2.772218116041520124422627777458013E-514 1.386109058020760062211313888729006E-514 + 854 6.93054529010380031105656944364503E-515 3.465272645051900155528284721822515E-515 + 855 1.732636322525950077764142360911258E-515 8.663181612629750388820711804556288E-516 + 856 4.331590806314875194410355902278144E-516 2.165795403157437597205177951139072E-516 + 857 1.082897701578718798602588975569536E-516 5.41448850789359399301294487784768E-517 + 858 2.70724425394679699650647243892384E-517 1.35362212697339849825323621946192E-517 + 859 6.7681106348669924912661810973096E-518 3.3840553174334962456330905486548E-518 + 860 1.6920276587167481228165452743274E-518 8.460138293583740614082726371637E-519 + 861 4.2300691467918703070413631858185E-519 2.11503457339593515352068159290925E-519 + 862 1.057517286697967576760340796454625E-519 5.287586433489837883801703982273125E-520 + 863 2.643793216744918941900851991136563E-520 1.321896608372459470950425995568281E-520 + 864 6.609483041862297354752129977841405E-521 3.304741520931148677376064988920703E-521 + 865 1.652370760465574338688032494460352E-521 8.261853802327871693440162472301758E-522 + 866 4.130926901163935846720081236150879E-522 2.065463450581967923360040618075440E-522 + 867 1.032731725290983961680020309037720E-522 5.16365862645491980840010154518860E-523 + 868 2.58182931322745990420005077259430E-523 1.29091465661372995210002538629715E-523 + 869 6.45457328306864976050012693148575E-524 3.227286641534324880250063465742875E-524 + 870 1.613643320767162440125031732871438E-524 8.068216603835812200625158664357188E-525 + 871 4.034108301917906100312579332178594E-525 2.017054150958953050156289666089297E-525 + 872 1.008527075479476525078144833044649E-525 5.042635377397382625390724165223243E-526 + 873 2.521317688698691312695362082611622E-526 1.260658844349345656347681041305811E-526 + 874 6.303294221746728281738405206529055E-527 3.151647110873364140869202603264528E-527 + 875 1.575823555436682070434601301632264E-527 7.87911777718341035217300650816132E-528 + 876 3.93955888859170517608650325408066E-528 1.96977944429585258804325162704033E-528 + 877 9.84889722147926294021625813520165E-529 4.924448610739631470108129067600825E-529 + 878 2.462224305369815735054064533800413E-529 1.231112152684907867527032266900206E-529 + 879 6.15556076342453933763516133450103E-530 3.077780381712269668817580667250515E-530 + 880 1.538890190856134834408790333625258E-530 7.694450954280674172043951668126288E-531 + 881 3.847225477140337086021975834063144E-531 1.923612738570168543010987917031572E-531 + 882 9.61806369285084271505493958515786E-532 4.80903184642542135752746979257893E-532 + 883 2.404515923212710678763734896289465E-532 1.202257961606355339381867448144733E-532 + 884 6.011289808031776696909337240723665E-533 3.005644904015888348454668620361833E-533 + 885 1.502822452007944174227334310180917E-533 7.514112260039720871136671550904583E-534 + 886 3.757056130019860435568335775452292E-534 1.878528065009930217784167887726146E-534 + 887 9.39264032504965108892083943863073E-535 4.696320162524825544460419719315365E-535 + 888 2.348160081262412772230209859657683E-535 1.174080040631206386115104929828841E-535 + 889 5.870400203156031930575524649144205E-536 2.935200101578015965287762324572103E-536 + 890 1.467600050789007982643881162286052E-536 7.338000253945039913219405811430258E-537 + 891 3.669000126972519956609702905715129E-537 1.834500063486259978304851452857565E-537 + 892 9.172500317431299891524257264287825E-538 4.586250158715649945762128632143913E-538 + 893 2.293125079357824972881064316071957E-538 1.146562539678912486440532158035978E-538 + 894 5.73281269839456243220266079017989E-539 2.866406349197281216101330395089945E-539 + 895 1.433203174598640608050665197544973E-539 7.166015872993203040253325987724863E-540 + 896 3.583007936496601520126662993862432E-540 1.791503968248300760063331496931216E-540 + 897 8.95751984124150380031665748465608E-541 4.47875992062075190015832874232804E-541 + 898 2.23937996031037595007916437116402E-541 1.11968998015518797503958218558201E-541 + 899 5.59844990077593987519791092791005E-542 2.799224950387969937598955463955025E-542 + 900 1.399612475193984968799477731977513E-542 6.998062375969924843997388659887563E-543 + 901 3.499031187984962421998694329943782E-543 1.749515593992481210999347164971891E-543 + 902 8.747577969962406054996735824859455E-544 4.373788984981203027498367912429728E-544 + 903 2.186894492490601513749183956214864E-544 1.093447246245300756874591978107432E-544 + 904 5.46723623122650378437295989053716E-545 2.73361811561325189218647994526858E-545 + 905 1.36680905780662594609323997263429E-545 6.83404528903312973046619986317145E-546 + 906 3.417022644516564865233099931585725E-546 1.708511322258282432616549965792863E-546 + 907 8.542556611291412163082749828964315E-547 4.271278305645706081541374914482158E-547 + 908 2.135639152822853040770687457241079E-547 1.067819576411426520385343728620540E-547 + 909 5.33909788205713260192671864310270E-548 2.66954894102856630096335932155135E-548 + 910 1.334774470514283150481679660775675E-548 6.673872352571415752408398303878375E-549 + 911 3.336936176285707876204199151939188E-549 1.668468088142853938102099575969594E-549 + 912 8.34234044071426969051049787984797E-550 4.171170220357134845255248939923985E-550 + 913 2.085585110178567422627624469961993E-550 1.042792555089283711313812234980996E-550 + 914 5.21396277544641855656906117490498E-551 2.60698138772320927828453058745249E-551 + 915 1.303490693861604639142265293726245E-551 6.517453469308023195711326468631225E-552 + 916 3.258726734654011597855663234315613E-552 1.629363367327005798927831617157806E-552 + 917 8.14681683663502899463915808578903E-553 4.073408418317514497319579042894515E-553 + 918 2.036704209158757248659789521447258E-553 1.018352104579378624329894760723629E-553 + 919 5.091760522896893121649473803618145E-554 2.545880261448446560824736901809073E-554 + 920 1.272940130724223280412368450904537E-554 6.364700653621116402061842254522683E-555 + 921 3.182350326810558201030921127261342E-555 1.591175163405279100515460563630671E-555 + 922 7.955875817026395502577302818153355E-556 3.977937908513197751288651409076678E-556 + 923 1.988968954256598875644325704538339E-556 9.944844771282994378221628522691695E-557 + 924 4.972422385641497189110814261345848E-557 2.486211192820748594555407130672924E-557 + 925 1.243105596410374297277703565336462E-557 6.21552798205187148638851782668231E-558 + 926 3.107763991025935743194258913341155E-558 1.553881995512967871597129456670578E-558 + 927 7.76940997756483935798564728335289E-559 3.884704988782419678992823641676445E-559 + 928 1.942352494391209839496411820838223E-559 9.711762471956049197482059104191113E-560 + 929 4.855881235978024598741029552095557E-560 2.427940617989012299370514776047778E-560 + 930 1.213970308994506149685257388023889E-560 6.069851544972530748426286940119445E-561 + 931 3.034925772486265374213143470059723E-561 1.517462886243132687106571735029861E-561 + 932 7.587314431215663435532858675149305E-562 3.793657215607831717766429337574653E-562 + 933 1.896828607803915858883214668787327E-562 9.484143039019579294416073343936633E-563 + 934 4.742071519509789647208036671968317E-563 2.371035759754894823604018335984158E-563 + 935 1.185517879877447411802009167992079E-563 5.927589399387237059010045839960395E-564 + 936 2.963794699693618529505022919980198E-564 1.481897349846809264752511459990099E-564 + 937 7.409486749234046323762557299950495E-565 3.704743374617023161881278649975248E-565 + 938 1.852371687308511580940639324987624E-565 9.26185843654255790470319662493812E-566 + 939 4.63092921827127895235159831246906E-566 2.31546460913563947617579915623453E-566 + 940 1.157732304567819738087899578117265E-566 5.788661522839098690439497890586325E-567 + 941 2.894330761419549345219748945293163E-567 1.447165380709774672609874472646581E-567 + 942 7.235826903548873363049372363232905E-568 3.617913451774436681524686181616453E-568 + 943 1.808956725887218340762343090808227E-568 9.044783629436091703811715454041133E-569 + 944 4.522391814718045851905857727020567E-569 2.261195907359022925952928863510283E-569 + 945 1.130597953679511462976464431755142E-569 5.652989768397557314882322158775708E-570 + 946 2.826494884198778657441161079387854E-570 1.413247442099389328720580539693927E-570 + 947 7.066237210496946643602902698469635E-571 3.533118605248473321801451349234818E-571 + 948 1.766559302624236660900725674617409E-571 8.832796513121183304503628373087045E-572 + 949 4.416398256560591652251814186543523E-572 2.208199128280295826125907093271761E-572 + 950 1.104099564140147913062953546635881E-572 5.520497820700739565314767733179403E-573 + 951 2.760248910350369782657383866589702E-573 1.380124455175184891328691933294851E-573 + 952 6.900622275875924456643459666474255E-574 3.450311137937962228321729833237128E-574 + 953 1.725155568968981114160864916618564E-574 8.62577784484490557080432458309282E-575 + 954 4.31288892242245278540216229154641E-575 2.156444461211226392701081145773205E-575 + 955 1.078222230605613196350540572886603E-575 5.391111153028065981752702864433013E-576 + 956 2.695555576514032990876351432216507E-576 1.347777788257016495438175716108253E-576 + 957 6.738888941285082477190878580541265E-577 3.369444470642541238595439290270633E-577 + 958 1.684722235321270619297719645135317E-577 8.423611176606353096488598225676583E-578 + 959 4.211805588303176548244299112838292E-578 2.105902794151588274122149556419146E-578 + 960 1.052951397075794137061074778209573E-578 5.264756985378970685305373891047865E-579 + 961 2.632378492689485342652686945523933E-579 1.316189246344742671326343472761966E-579 + 962 6.58094623172371335663171736380983E-580 3.290473115861856678315858681904915E-580 + 963 1.645236557930928339157929340952458E-580 8.226182789654641695789646704762288E-581 + 964 4.113091394827320847894823352381144E-581 2.056545697413660423947411676190572E-581 + 965 1.028272848706830211973705838095286E-581 5.14136424353415105986852919047643E-582 + 966 2.570682121767075529934264595238215E-582 1.285341060883537764967132297619108E-582 + 967 6.42670530441768882483566148809554E-583 3.21335265220884441241783074404777E-583 + 968 1.606676326104422206208915372023885E-583 8.033381630522111031044576860119425E-584 + 969 4.016690815261055515522288430059713E-584 2.008345407630527757761144215029856E-584 + 970 1.004172703815263878880572107514928E-584 5.02086351907631939440286053757464E-585 + 971 2.51043175953815969720143026878732E-585 1.25521587976907984860071513439366E-585 + 972 6.2760793988453992430035756719683E-586 3.13803969942269962150178783598415E-586 + 973 1.569019849711349810750893917992075E-586 7.845099248556749053754469589960375E-587 + 974 3.922549624278374526877234794980188E-587 1.961274812139187263438617397490094E-587 + 975 9.80637406069593631719308698745047E-588 4.903187030347968158596543493725235E-588 + 976 2.451593515173984079298271746862618E-588 1.225796757586992039649135873431309E-588 + 977 6.128983787934960198245679367156545E-589 3.064491893967480099122839683578273E-589 + 978 1.532245946983740049561419841789137E-589 7.661229734918700247807099208945683E-590 + 979 3.830614867459350123903549604472842E-590 1.915307433729675061951774802236421E-590 + 980 9.576537168648375309758874011182105E-591 4.788268584324187654879437005591053E-591 + 981 2.394134292162093827439718502795527E-591 1.197067146081046913719859251397763E-591 + 982 5.985335730405234568599296256988815E-592 2.992667865202617284299648128494408E-592 + 983 1.496333932601308642149824064247204E-592 7.48166966300654321074912032123602E-593 + 984 3.74083483150327160537456016061801E-593 1.870417415751635802687280080309005E-593 + 985 9.352087078758179013436400401545025E-594 4.676043539379089506718200200772513E-594 + 986 2.338021769689544753359100100386257E-594 1.169010884844772376679550050193128E-594 + 987 5.84505442422386188339775025096564E-595 2.92252721211193094169887512548282E-595 + 988 1.46126360605596547084943756274141E-595 7.30631803027982735424718781370705E-596 + 989 3.653159015139913677123593906853525E-596 1.826579507569956838561796953426763E-596 + 990 9.132897537849784192808984767133815E-597 4.566448768924892096404492383566908E-597 + 991 2.283224384462446048202246191783454E-597 1.141612192231223024101123095891727E-597 + 992 5.708060961156115120505615479458635E-598 2.854030480578057560252807739729318E-598 + 993 1.427015240289028780126403869864659E-598 7.135076201445143900632019349323295E-599 + 994 3.567538100722571950316009674661648E-599 1.783769050361285975158004837330824E-599 + 995 8.91884525180642987579002418665412E-600 4.45942262590321493789501209332706E-600 + 996 2.22971131295160746894750604666353E-600 1.114855656475803734473753023331765E-600 + 997 5.574278282379018672368765116658825E-601 2.787139141189509336184382558329413E-601 + 998 1.393569570594754668092191279164707E-601 6.967847852973773340460956395823533E-602 + 999 3.483923926486886670230478197911767E-602 1.741961963243443335115239098955883E-602 + 1000 8.709809816217216675576195494779415E-603 4.354904908108608337788097747389708E-603 + 1001 2.177452454054304168894048873694854E-603 1.088726227027152084447024436847427E-603 + 1002 5.443631135135760422235122184237135E-604 2.721815567567880211117561092118568E-604 + 1003 1.360907783783940105558780546059284E-604 6.80453891891970052779390273029642E-605 + 1004 3.40226945945985026389695136514821E-605 1.701134729729925131948475682574105E-605 + 1005 8.505673648649625659742378412870525E-606 4.252836824324812829871189206435263E-606 + 1006 2.126418412162406414935594603217632E-606 1.063209206081203207467797301608816E-606 + 1007 5.31604603040601603733898650804408E-607 2.65802301520300801866949325402204E-607 + 1008 1.32901150760150400933474662701102E-607 6.6450575380075200466737331350551E-608 + 1009 3.32252876900376002333686656752755E-608 1.661264384501880011668433283763775E-608 + 1010 8.306321922509400058342166418818875E-609 4.153160961254700029171083209409438E-609 + 1011 2.076580480627350014585541604704719E-609 1.038290240313675007292770802352360E-609 + 1012 5.19145120156837503646385401176180E-610 2.59572560078418751823192700588090E-610 + 1013 1.29786280039209375911596350294045E-610 6.48931400196046879557981751470225E-611 + 1014 3.244657000980234397789908757351125E-611 1.622328500490117198894954378675563E-611 + 1015 8.111642502450585994474771893377815E-612 4.055821251225292997237385946688908E-612 + 1016 2.027910625612646498618692973344454E-612 1.013955312806323249309346486672227E-612 + 1017 5.069776564031616246546732433361135E-613 2.534888282015808123273366216680568E-613 + 1018 1.267444141007904061636683108340284E-613 6.33722070503952030818341554170142E-614 + 1019 3.16861035251976015409170777085071E-614 1.584305176259880077045853885425355E-614 + 1020 7.921525881299400385229269427126775E-615 3.960762940649700192614634713563388E-615 + 1021 1.980381470324850096307317356781694E-615 9.90190735162425048153658678390847E-616 + 1022 4.950953675812125240768293391954235E-616 2.475476837906062620384146695977118E-616 + 1023 1.237738418953031310192073347988559E-616 6.188692094765156550960366739942795E-617 + 1024 3.094346047382578275480183369971398E-617 1.547173023691289137740091684985699E-617 + 1025 7.735865118456445688700458424928495E-618 3.867932559228222844350229212464248E-618 + 1026 1.933966279614111422175114606232124E-618 9.66983139807055711087557303116062E-619 + 1027 4.83491569903527855543778651558031E-619 2.417457849517639277718893257790155E-619 + 1028 1.208728924758819638859446628895078E-619 6.043644623794098194297233144475388E-620 + 1029 3.021822311897049097148616572237694E-620 1.510911155948524548574308286118847E-620 + 1030 7.554555779742622742871541430594235E-621 3.777277889871311371435770715297118E-621 + 1031 1.888638944935655685717885357648559E-621 9.443194724678278428589426788242795E-622 + 1032 4.721597362339139214294713394121398E-622 2.360798681169569607147356697060699E-622 + 1033 1.180399340584784803573678348530350E-622 5.901996702923924017868391742651748E-623 + 1034 2.950998351461962008934195871325874E-623 1.475499175730981004467097935662937E-623 + 1035 7.377495878654905022335489678314685E-624 3.688747939327452511167744839157343E-624 + 1036 1.844373969663726255583872419578672E-624 9.221869848318631277919362097893358E-625 + 1037 4.610934924159315638959681048946679E-625 2.305467462079657819479840524473340E-625 + 1038 1.152733731039828909739920262236670E-625 5.76366865519914454869960131118335E-626 + 1039 2.881834327599572274349800655591675E-626 1.440917163799786137174900327795838E-626 + 1040 7.20458581899893068587450163897919E-627 3.602292909499465342937250819489595E-627 + 1041 1.801146454749732671468625409744798E-627 9.005732273748663357343127048723988E-628 + 1042 4.502866136874331678671563524361994E-628 2.251433068437165839335781762180997E-628 + 1043 1.125716534218582919667890881090499E-628 5.628582671092914598339454405452493E-629 + 1044 2.814291335546457299169727202726247E-629 1.407145667773228649584863601363123E-629 + 1045 7.035728338866143247924318006815615E-630 3.517864169433071623962159003407808E-630 + 1046 1.758932084716535811981079501703904E-630 8.79466042358267905990539750851952E-631 + 1047 4.39733021179133952995269875425976E-631 2.19866510589566976497634937712988E-631 + 1048 1.09933255294783488248817468856494E-631 5.4966627647391744124408734428247E-632 + 1049 2.74833138236958720622043672141235E-632 1.374165691184793603110218360706175E-632 + 1050 6.870828455923968015551091803530875E-633 3.435414227961984007775545901765438E-633 + 1051 1.717707113980992003887772950882719E-633 8.588535569904960019438864754413595E-634 + 1052 4.294267784952480009719432377206798E-634 2.147133892476240004859716188603399E-634 + 1053 1.073566946238120002429858094301700E-634 5.367834731190600012149290471508498E-635 + 1054 2.683917365595300006074645235754249E-635 1.341958682797650003037322617877125E-635 + 1055 6.709793413988250015186613089385625E-636 3.354896706994125007593306544692813E-636 + 1056 1.677448353497062503796653272346407E-636 8.387241767485312518983266361732033E-637 + 1057 4.193620883742656259491633180866017E-637 2.096810441871328129745816590433008E-637 + 1058 1.048405220935664064872908295216504E-637 5.24202610467832032436454147608252E-638 + 1059 2.62101305233916016218227073804126E-638 1.31050652616958008109113536902063E-638 + 1060 6.55253263084790040545567684510315E-639 3.276266315423950202727838422551575E-639 + 1061 1.638133157711975101363919211275788E-639 8.190665788559875506819596056378938E-640 + 1062 4.095332894279937753409798028189469E-640 2.047666447139968876704899014094735E-640 + 1063 1.023833223569984438352449507047368E-640 5.119166117849922191762247535236838E-641 + 1064 2.559583058924961095881123767618419E-641 1.279791529462480547940561883809210E-641 + 1065 6.39895764731240273970280941904605E-642 3.199478823656201369851404709523025E-642 + 1066 1.599739411828100684925702354761513E-642 7.998697059140503424628511773807563E-643 + 1067 3.999348529570251712314255886903782E-643 1.999674264785125856157127943451891E-643 + 1068 9.998371323925629280785639717259455E-644 4.999185661962814640392819858629728E-644 + 1069 2.499592830981407320196409929314864E-644 1.249796415490703660098204964657432E-644 + 1070 6.24898207745351830049102482328716E-645 3.12449103872675915024551241164358E-645 + 1071 1.56224551936337957512275620582179E-645 7.81122759681689787561378102910895E-646 + 1072 3.905613798408448937806890514554475E-646 1.952806899204224468903445257277238E-646 + 1073 9.76403449602112234451722628638619E-647 4.882017248010561172258613143193095E-647 + 1074 2.441008624005280586129306571596548E-647 1.220504312002640293064653285798274E-647 + 1075 6.10252156001320146532326642899137E-648 3.051260780006600732661633214495685E-648 + 1076 1.525630390003300366330816607247843E-648 7.628151950016501831654083036239213E-649 + 1077 3.814075975008250915827041518119607E-649 1.907037987504125457913520759059803E-649 + 1078 9.535189937520627289567603795299015E-650 4.767594968760313644783801897649508E-650 + 1079 2.383797484380156822391900948824754E-650 1.191898742190078411195950474412377E-650 + 1080 5.959493710950392055979752372061885E-651 2.979746855475196027989876186030943E-651 + 1081 1.489873427737598013994938093015472E-651 7.449367138687990069974690465077358E-652 + 1082 3.724683569343995034987345232538679E-652 1.862341784671997517493672616269340E-652 + 1083 9.31170892335998758746836308134670E-653 4.65585446167999379373418154067335E-653 + 1084 2.327927230839996896867090770336675E-653 1.163963615419998448433545385168338E-653 + 1085 5.81981807709999224216772692584169E-654 2.909909038549996121083863462920845E-654 + 1086 1.454954519274998060541931731460423E-654 7.274772596374990302709658657302113E-655 + 1087 3.637386298187495151354829328651057E-655 1.818693149093747575677414664325528E-655 + 1088 9.09346574546873787838707332162764E-656 4.54673287273436893919353666081382E-656 + 1089 2.27336643636718446959676833040691E-656 1.136683218183592234798384165203455E-656 + 1090 5.683416090917961173991920826017275E-657 2.841708045458980586995960413008638E-657 + 1091 1.420854022729490293497980206504319E-657 7.104270113647451467489901032521595E-658 + 1092 3.552135056823725733744950516260798E-658 1.776067528411862866872475258130399E-658 + 1093 8.880337642059314334362376290651995E-659 4.440168821029657167181188145325998E-659 + 1094 2.220084410514828583590594072662999E-659 1.110042205257414291795297036331500E-659 + 1095 5.55021102628707145897648518165750E-660 2.77510551314353572948824259082875E-660 + 1096 1.387552756571767864744121295414375E-660 6.937763782858839323720606477071875E-661 + 1097 3.468881891429419661860303238535938E-661 1.734440945714709830930151619267969E-661 + 1098 8.672204728573549154650758096339845E-662 4.336102364286774577325379048169923E-662 + 1099 2.168051182143387288662689524084962E-662 1.084025591071693644331344762042481E-662 + 1100 5.420127955358468221656723810212405E-663 2.710063977679234110828361905106203E-663 + 1101 1.355031988839617055414180952553102E-663 6.775159944198085277070904762765508E-664 + 1102 3.387579972099042638535452381382754E-664 1.693789986049521319267726190691377E-664 + 1103 8.468949930247606596338630953456885E-665 4.234474965123803298169315476728443E-665 + 1104 2.117237482561901649084657738364222E-665 1.058618741280950824542328869182111E-665 + 1105 5.293093706404754122711644345910555E-666 2.646546853202377061355822172955278E-666 + 1106 1.323273426601188530677911086477639E-666 6.616367133005942653389555432388195E-667 + 1107 3.308183566502971326694777716194098E-667 1.654091783251485663347388858097049E-667 + 1108 8.270458916257428316736944290485245E-668 4.135229458128714158368472145242623E-668 + 1109 2.067614729064357079184236072621312E-668 1.033807364532178539592118036310656E-668 + 1110 5.16903682266089269796059018155328E-669 2.58451841133044634898029509077664E-669 + 1111 1.29225920566522317449014754538832E-669 6.4612960283261158724507377269416E-670 + 1112 3.2306480141630579362253688634708E-670 1.6153240070815289681126844317354E-670 + 1113 8.076620035407644840563422158677E-671 4.0383100177038224202817110793385E-671 + 1114 2.01915500885191121014085553966925E-671 1.009577504425955605070427769834625E-671 + 1115 5.047887522129778025352138849173125E-672 2.523943761064889012676069424586563E-672 + 1116 1.261971880532444506338034712293282E-672 6.309859402662222531690173561466408E-673 + 1117 3.154929701331111265845086780733204E-673 1.577464850665555632922543390366602E-673 + 1118 7.88732425332777816461271695183301E-674 3.943662126663889082306358475916505E-674 + 1119 1.971831063331944541153179237958253E-674 9.859155316659722705765896189791263E-675 + 1120 4.929577658329861352882948094895632E-675 2.464788829164930676441474047447816E-675 + 1121 1.232394414582465338220737023723908E-675 6.16197207291232669110368511861954E-676 + 1122 3.08098603645616334555184255930977E-676 1.540493018228081672775921279654885E-676 + 1123 7.702465091140408363879606398274425E-677 3.851232545570204181939803199137213E-677 + 1124 1.925616272785102090969901599568607E-677 9.628081363925510454849507997843033E-678 + 1125 4.814040681962755227424753998921517E-678 2.407020340981377613712376999460758E-678 + 1126 1.203510170490688806856188499730379E-678 6.017550852453444034280942498651895E-679 + 1127 3.008775426226722017140471249325948E-679 1.504387713113361008570235624662974E-679 + 1128 7.52193856556680504285117812331487E-680 3.760969282783402521425589061657435E-680 + 1129 1.880484641391701260712794530828718E-680 9.402423206958506303563972654143588E-681 + 1130 4.701211603479253151781986327071794E-681 2.350605801739626575890993163535897E-681 + 1131 1.175302900869813287945496581767949E-681 5.876514504349066439727482908839743E-682 + 1132 2.938257252174533219863741454419872E-682 1.469128626087266609931870727209936E-682 + 1133 7.34564313043633304965935363604968E-683 3.67282156521816652482967681802484E-683 + 1134 1.83641078260908326241483840901242E-683 9.1820539130454163120741920450621E-684 + 1135 4.59102695652270815603709602253105E-684 2.295513478261354078018548011265525E-684 + 1136 1.147756739130677039009274005632763E-684 5.738783695653385195046370028163813E-685 + 1137 2.869391847826692597523185014081907E-685 1.434695923913346298761592507040953E-685 + 1138 7.173479619566731493807962535204765E-686 3.586739809783365746903981267602383E-686 + 1139 1.793369904891682873451990633801192E-686 8.966849524458414367259953169005958E-687 + 1140 4.483424762229207183629976584502979E-687 2.241712381114603591814988292251490E-687 + 1141 1.120856190557301795907494146125745E-687 5.604280952786508979537470730628725E-688 + 1142 2.802140476393254489768735365314363E-688 1.401070238196627244884367682657181E-688 + 1143 7.005351190983136224421838413285905E-689 3.502675595491568112210919206642953E-689 + 1144 1.751337797745784056105459603321477E-689 8.756688988728920280527298016607383E-690 + 1145 4.378344494364460140263649008303692E-690 2.189172247182230070131824504151846E-690 + 1146 1.094586123591115035065912252075923E-690 5.472930617955575175329561260379615E-691 + 1147 2.736465308977787587664780630189808E-691 1.368232654488893793832390315094904E-691 + 1148 6.84116327244446896916195157547452E-692 3.42058163622223448458097578773726E-692 + 1149 1.71029081811111724229048789386863E-692 8.55145409055558621145243946934315E-693 + 1150 4.275727045277793105726219734671575E-693 2.137863522638896552863109867335788E-693 + 1151 1.068931761319448276431554933667894E-693 5.34465880659724138215777466833947E-694 + 1152 2.672329403298620691078887334169735E-694 1.336164701649310345539443667084868E-694 + 1153 6.68082350824655172769721833542434E-695 3.34041175412327586384860916771217E-695 + 1154 1.670205877061637931924304583856085E-695 8.351029385308189659621522919280425E-696 + 1155 4.175514692654094829810761459640213E-696 2.087757346327047414905380729820106E-696 + 1156 1.043878673163523707452690364910053E-696 5.219393365817618537263451824550265E-697 + 1157 2.609696682908809268631725912275133E-697 1.304848341454404634315862956137566E-697 + 1158 6.52424170727202317157931478068783E-698 3.262120853636011585789657390343915E-698 + 1159 1.631060426818005792894828695171958E-698 8.155302134090028964474143475859788E-699 + 1160 4.077651067045014482237071737929894E-699 2.038825533522507241118535868964947E-699 + 1161 1.019412766761253620559267934482474E-699 5.097063833806268102796339672412368E-700 + 1162 2.548531916903134051398169836206184E-700 1.274265958451567025699084918103092E-700 + 1163 6.37132979225783512849542459051546E-701 3.18566489612891756424771229525773E-701 + 1164 1.592832448064458782123856147628865E-701 7.964162240322293910619280738144325E-702 + 1165 3.982081120161146955309640369072163E-702 1.991040560080573477654820184536081E-702 + 1166 9.955202800402867388274100922680405E-703 4.977601400201433694137050461340203E-703 + 1167 2.488800700100716847068525230670102E-703 1.244400350050358423534262615335051E-703 + 1168 6.222001750251792117671313076675255E-704 3.111000875125896058835656538337628E-704 + 1169 1.555500437562948029417828269168814E-704 7.77750218781474014708914134584407E-705 + 1170 3.888751093907370073544570672922035E-705 1.944375546953685036772285336461018E-705 + 1171 9.72187773476842518386142668230509E-706 4.860938867384212591930713341152545E-706 + 1172 2.430469433692106295965356670576273E-706 1.215234716846053147982678335288136E-706 + 1173 6.07617358423026573991339167644068E-707 3.03808679211513286995669583822034E-707 + 1174 1.51904339605756643497834791911017E-707 7.59521698028783217489173959555085E-708 + 1175 3.797608490143916087445869797775425E-708 1.898804245071958043722934898887713E-708 + 1176 9.494021225359790218614674494438565E-709 4.747010612679895109307337247219283E-709 + 1177 2.373505306339947554653668623609642E-709 1.186752653169973777326834311804821E-709 + 1178 5.933763265849868886634171559024105E-710 2.966881632924934443317085779512053E-710 + 1179 1.483440816462467221658542889756027E-710 7.417204082312336108292714448780133E-711 + 1180 3.708602041156168054146357224390067E-711 1.854301020578084027073178612195033E-711 + 1181 9.271505102890420135365893060975165E-712 4.635752551445210067682946530487583E-712 + 1182 2.317876275722605033841473265243792E-712 1.158938137861302516920736632621896E-712 + 1183 5.79469068930651258460368316310948E-713 2.89734534465325629230184158155474E-713 + 1184 1.44867267232662814615092079077737E-713 7.24336336163314073075460395388685E-714 + 1185 3.621681680816570365377301976943425E-714 1.810840840408285182688650988471713E-714 + 1186 9.054204202041425913443254942358565E-715 4.527102101020712956721627471179283E-715 + 1187 2.263551050510356478360813735589642E-715 1.131775525255178239180406867794821E-715 + 1188 5.658877626275891195902034338974105E-716 2.829438813137945597951017169487053E-716 + 1189 1.414719406568972798975508584743527E-716 7.073597032844863994877542923717633E-717 + 1190 3.536798516422431997438771461858817E-717 1.768399258211215998719385730929408E-717 + 1191 8.84199629105607999359692865464704E-718 4.42099814552803999679846432732352E-718 + 1192 2.21049907276401999839923216366176E-718 1.10524953638200999919961608183088E-718 + 1193 5.5262476819100499959980804091544E-719 2.7631238409550249979990402045772E-719 + 1194 1.3815619204775124989995201022886E-719 6.907809602387562494997600511443E-720 + 1195 3.4539048011937812474988002557215E-720 1.72695240059689062374940012786075E-720 + 1196 8.63476200298445311874700063930375E-721 4.317381001492226559373500319651875E-721 + 1197 2.158690500746113279686750159825938E-721 1.079345250373056639843375079912969E-721 + 1198 5.396726251865283199216875399564845E-722 2.698363125932641599608437699782423E-722 + 1199 1.349181562966320799804218849891212E-722 6.745907814831603999021094249456058E-723 + 1200 3.372953907415801999510547124728029E-723 1.686476953707900999755273562364015E-723 + 1201 8.432384768539504998776367811820075E-724 4.216192384269752499388183905910038E-724 + 1202 2.108096192134876249694091952955019E-724 1.054048096067438124847045976477510E-724 + 1203 5.27024048033719062423522988238755E-725 2.635120240168595312117614941193775E-725 + 1204 1.317560120084297656058807470596888E-725 6.587800600421488280294037352984438E-726 + 1205 3.293900300210744140147018676492219E-726 1.646950150105372070073509338246110E-726 + 1206 8.23475075052686035036754669123055E-727 4.117375375263430175183773345615275E-727 + 1207 2.058687687631715087591886672807638E-727 1.029343843815857543795943336403819E-727 + 1208 5.146719219079287718979716682019095E-728 2.573359609539643859489858341009548E-728 + 1209 1.286679804769821929744929170504774E-728 6.43339902384910964872464585252387E-729 + 1210 3.216699511924554824362322926261935E-729 1.608349755962277412181161463130968E-729 + 1211 8.04174877981138706090580731565484E-730 4.02087438990569353045290365782742E-730 + 1212 2.01043719495284676522645182891371E-730 1.005218597476423382613225914456855E-730 + 1213 5.026092987382116913066129572284275E-731 2.513046493691058456533064786142138E-731 + 1214 1.256523246845529228266532393071069E-731 6.282616234227646141332661965355345E-732 + 1215 3.141308117113823070666330982677673E-732 1.570654058556911535333165491338836E-732 + 1216 7.85327029278455767666582745669418E-733 3.92663514639227883833291372834709E-733 + 1217 1.963317573196139419166456864173545E-733 9.816587865980697095832284320867725E-734 + 1218 4.908293932990348547916142160433863E-734 2.454146966495174273958071080216931E-734 + 1219 1.227073483247587136979035540108466E-734 6.135367416237935684895177700542328E-735 + 1220 3.067683708118967842447588850271164E-735 1.533841854059483921223794425135582E-735 + 1221 7.66920927029741960611897212567791E-736 3.834604635148709803059486062838955E-736 + 1222 1.917302317574354901529743031419478E-736 9.586511587871774507648715157097388E-737 + 1223 4.793255793935887253824357578548694E-737 2.396627896967943626912178789274347E-737 + 1224 1.198313948483971813456089394637174E-737 5.991569742419859067280446973185868E-738 + 1225 2.995784871209929533640223486592934E-738 1.497892435604964766820111743296467E-738 + 1226 7.489462178024823834100558716482335E-739 3.744731089012411917050279358241168E-739 + 1227 1.872365544506205958525139679120584E-739 9.36182772253102979262569839560292E-740 + 1228 4.68091386126551489631284919780146E-740 2.34045693063275744815642459890073E-740 + 1229 1.170228465316378724078212299450365E-740 5.851142326581893620391061497251825E-741 + 1230 2.925571163290946810195530748625913E-741 1.462785581645473405097765374312956E-741 + 1231 7.31392790822736702548882687156478E-742 3.65696395411368351274441343578239E-742 + 1232 1.828481977056841756372206717891195E-742 9.142409885284208781861033589455975E-743 + 1233 4.571204942642104390930516794727988E-743 2.285602471321052195465258397363994E-743 + 1234 1.142801235660526097732629198681997E-743 5.714006178302630488663145993409985E-744 + 1235 2.857003089151315244331572996704993E-744 1.428501544575657622165786498352496E-744 + 1236 7.14250772287828811082893249176248E-745 3.57125386143914405541446624588124E-745 + 1237 1.78562693071957202770723312294062E-745 8.9281346535978601385361656147031E-746 + 1238 4.46406732679893006926808280735155E-746 2.232033663399465034634041403675775E-746 + 1239 1.116016831699732517317020701837888E-746 5.580084158498662586585103509189438E-747 + 1240 2.790042079249331293292551754594719E-747 1.395021039624665646646275877297360E-747 + 1241 6.97510519812332823323137938648680E-748 3.48755259906166411661568969324340E-748 + 1242 1.74377629953083205830784484662170E-748 8.7188814976541602915392242331085E-749 + 1243 4.35944074882708014576961211655425E-749 2.179720374413540072884806058277125E-749 + 1244 1.089860187206770036442403029138563E-749 5.449300936033850182212015145692813E-750 + 1245 2.724650468016925091106007572846407E-750 1.362325234008462545553003786423203E-750 + 1246 6.811626170042312727765018932116015E-751 3.405813085021156363882509466058008E-751 + 1247 1.702906542510578181941254733029004E-751 8.51453271255289090970627366514502E-752 + 1248 4.25726635627644545485313683257251E-752 2.128633178138222727426568416286255E-752 + 1249 1.064316589069111363713284208143128E-752 5.321582945345556818566421040715638E-753 + 1250 2.660791472672778409283210520357819E-753 1.330395736336389204641605260178910E-753 + 1251 6.65197868168194602320802630089455E-754 3.325989340840973011604013150447275E-754 + 1252 1.662994670420486505802006575223638E-754 8.314973352102432529010032876118188E-755 + 1253 4.157486676051216264505016438059094E-755 2.078743338025608132252508219029547E-755 + 1254 1.039371669012804066126254109514774E-755 5.196858345064020330631270547573868E-756 + 1255 2.598429172532010165315635273786934E-756 1.299214586266005082657817636893467E-756 + 1256 6.496072931330025413289088184467335E-757 3.248036465665012706644544092233668E-757 + 1257 1.624018232832506353322272046116834E-757 8.12009116416253176661136023058417E-758 + 1258 4.060045582081265883305680115292085E-758 2.030022791040632941652840057646043E-758 + 1259 1.015011395520316470826420028823022E-758 5.075056977601582354132100144115108E-759 + 1260 2.537528488800791177066050072057554E-759 1.268764244400395588533025036028777E-759 + 1261 6.343821222001977942665125180143885E-760 3.171910611000988971332562590071943E-760 + 1262 1.585955305500494485666281295035972E-760 7.929776527502472428331406475179858E-761 + 1263 3.964888263751236214165703237589929E-761 1.982444131875618107082851618794965E-761 + 1264 9.912220659378090535414258093974825E-762 4.956110329689045267707129046987413E-762 + 1265 2.478055164844522633853564523493707E-762 1.239027582422261316926782261746853E-762 + 1266 6.195137912111306584633911308734265E-763 3.097568956055653292316955654367133E-763 + 1267 1.548784478027826646158477827183567E-763 7.743922390139133230792389135917833E-764 + 1268 3.871961195069566615396194567958917E-764 1.935980597534783307698097283979458E-764 + 1269 9.67990298767391653849048641989729E-765 4.839951493836958269245243209948645E-765 + 1270 2.419975746918479134622621604974323E-765 1.209987873459239567311310802487161E-765 + 1271 6.049939367296197836556554012435805E-766 3.024969683648098918278277006217903E-766 + 1272 1.512484841824049459139138503108952E-766 7.562424209120247295695692515544758E-767 + 1273 3.781212104560123647847846257772379E-767 1.890606052280061823923923128886190E-767 + 1274 9.45303026140030911961961564443095E-768 4.726515130700154559809807822215475E-768 + 1275 2.363257565350077279904903911107738E-768 1.181628782675038639952451955553869E-768 + 1276 5.908143913375193199762259777769345E-769 2.954071956687596599881129888884673E-769 + 1277 1.477035978343798299940564944442337E-769 7.385179891718991499702824722211683E-770 + 1278 3.692589945859495749851412361105842E-770 1.846294972929747874925706180552921E-770 + 1279 9.231474864648739374628530902764605E-771 4.615737432324369687314265451382303E-771 + 1280 2.307868716162184843657132725691152E-771 1.153934358081092421828566362845576E-771 + 1281 5.76967179040546210914283181422788E-772 2.88483589520273105457141590711394E-772 + 1282 1.44241794760136552728570795355697E-772 7.21208973800682763642853976778485E-773 + 1283 3.606044869003413818214269883892425E-773 1.803022434501706909107134941946213E-773 + 1284 9.015112172508534545535674709731065E-774 4.507556086254267272767837354865533E-774 + 1285 2.253778043127133636383918677432767E-774 1.126889021563566818191959338716383E-774 + 1286 5.634445107817834090959796693581915E-775 2.817222553908917045479898346790958E-775 + 1287 1.408611276954458522739949173395479E-775 7.043056384772292613699745866977395E-776 + 1288 3.521528192386146306849872933488698E-776 1.760764096193073153424936466744349E-776 + 1289 8.803820480965365767124682333721745E-777 4.401910240482682883562341166860873E-777 + 1290 2.200955120241341441781170583430437E-777 1.100477560120670720890585291715218E-777 + 1291 5.50238780060335360445292645857609E-778 2.751193900301676802226463229288045E-778 + 1292 1.375596950150838401113231614644023E-778 6.877984750754192005566158073220113E-779 + 1293 3.438992375377096002783079036610057E-779 1.719496187688548001391539518305028E-779 + 1294 8.59748093844274000695769759152514E-780 4.29874046922137000347884879576257E-780 + 1295 2.149370234610685001739424397881285E-780 1.074685117305342500869712198940643E-780 + 1296 5.373425586526712504348560994703215E-781 2.686712793263356252174280497351608E-781 + 1297 1.343356396631678126087140248675804E-781 6.71678198315839063043570124337902E-782 + 1298 3.35839099157919531521785062168951E-782 1.679195495789597657608925310844755E-782 + 1299 8.395977478947988288044626554223775E-783 4.197988739473994144022313277111888E-783 + 1300 2.098994369736997072011156638555944E-783 1.049497184868498536005578319277972E-783 + 1301 5.24748592434249268002789159638986E-784 2.62374296217124634001394579819493E-784 + 1302 1.311871481085623170006972899097465E-784 6.559357405428115850034864495487325E-785 + 1303 3.279678702714057925017432247743663E-785 1.639839351357028962508716123871831E-785 + 1304 8.199196756785144812543580619359155E-786 4.099598378392572406271790309679578E-786 + 1305 2.049799189196286203135895154839789E-786 1.024899594598143101567947577419895E-786 + 1306 5.124497972990715507839737887099475E-787 2.562248986495357753919868943549738E-787 + 1307 1.281124493247678876959934471774869E-787 6.405622466238394384799672358874345E-788 + 1308 3.202811233119197192399836179437173E-788 1.601405616559598596199918089718586E-788 + 1309 8.00702808279799298099959044859293E-789 4.003514041398996490499795224296465E-789 + 1310 2.001757020699498245249897612148233E-789 1.000878510349749122624948806074116E-789 + 1311 5.00439255174874561312474403037058E-790 2.50219627587437280656237201518529E-790 + 1312 1.251098137937186403281186007592645E-790 6.255490689685932016405930037963225E-791 + 1313 3.127745344842966008202965018981613E-791 1.563872672421483004101482509490806E-791 + 1314 7.81936336210741502050741254745403E-792 3.909681681053707510253706273727015E-792 + 1315 1.954840840526853755126853136863508E-792 9.774204202634268775634265684317538E-793 + 1316 4.887102101317134387817132842158769E-793 2.443551050658567193908566421079385E-793 + 1317 1.221775525329283596954283210539693E-793 6.108877626646417984771416052698463E-794 + 1318 3.054438813323208992385708026349232E-794 1.527219406661604496192854013174616E-794 + 1319 7.63609703330802248096427006587308E-795 3.81804851665401124048213503293654E-795 + 1320 1.90902425832700562024106751646827E-795 9.54512129163502810120533758234135E-796 + 1321 4.772560645817514050602668791170675E-796 2.386280322908757025301334395585338E-796 + 1322 1.193140161454378512650667197792669E-796 5.965700807271892563253335988963345E-797 + 1323 2.982850403635946281626667994481673E-797 1.491425201817973140813333997240836E-797 + 1324 7.45712600908986570406666998620418E-798 3.72856300454493285203333499310209E-798 + 1325 1.864281502272466426016667496551045E-798 9.321407511362332130083337482755225E-799 + 1326 4.660703755681166065041668741377613E-799 2.330351877840583032520834370688806E-799 + 1327 1.165175938920291516260417185344403E-799 5.825879694601457581302085926722015E-800 + 1328 2.912939847300728790651042963361008E-800 1.456469923650364395325521481680504E-800 + 1329 7.28234961825182197662760740840252E-801 3.64117480912591098831380370420126E-801 + 1330 1.82058740456295549415690185210063E-801 9.10293702281477747078450926050315E-802 + 1331 4.551468511407388735392254630251575E-802 2.275734255703694367696127315125788E-802 + 1332 1.137867127851847183848063657562894E-802 5.68933563925923591924031828781447E-803 + 1333 2.844667819629617959620159143907235E-803 1.422333909814808979810079571953618E-803 + 1334 7.11166954907404489905039785976809E-804 3.555834774537022449525198929884045E-804 + 1335 1.777917387268511224762599464942023E-804 8.889586936342556123812997324710113E-805 + 1336 4.444793468171278061906498662355057E-805 2.222396734085639030953249331177528E-805 + 1337 1.111198367042819515476624665588764E-805 5.55599183521409757738312332794382E-806 + 1338 2.77799591760704878869156166397191E-806 1.388997958803524394345780831985955E-806 + 1339 6.944989794017621971728904159929775E-807 3.472494897008810985864452079964888E-807 + 1340 1.736247448504405492932226039982444E-807 8.68123724252202746466113019991222E-808 + 1341 4.34061862126101373233056509995611E-808 2.170309310630506866165282549978055E-808 + 1342 1.085154655315253433082641274989028E-808 5.425773276576267165413206374945138E-809 + 1343 2.712886638288133582706603187472569E-809 1.356443319144066791353301593736285E-809 + 1344 6.782216595720333956766507968681425E-810 3.391108297860166978383253984340713E-810 + 1345 1.695554148930083489191626992170357E-810 8.477770744650417445958134960851783E-811 + 1346 4.238885372325208722979067480425892E-811 2.119442686162604361489533740212946E-811 + 1347 1.059721343081302180744766870106473E-811 5.298606715406510903723834350532365E-812 + 1348 2.649303357703255451861917175266183E-812 1.324651678851627725930958587633091E-812 + 1349 6.623258394258138629654792938165455E-813 3.311629197129069314827396469082728E-813 + 1350 1.655814598564534657413698234541364E-813 8.27907299282267328706849117270682E-814 + 1351 4.13953649641133664353424558635341E-814 2.069768248205668321767122793176705E-814 + 1352 1.034884124102834160883561396588353E-814 5.174420620514170804417806982941763E-815 + 1353 2.587210310257085402208903491470882E-815 1.293605155128542701104451745735441E-815 + 1354 6.468025775642713505522258728677205E-816 3.234012887821356752761129364338603E-816 + 1355 1.617006443910678376380564682169302E-816 8.085032219553391881902823410846508E-817 + 1356 4.042516109776695940951411705423254E-817 2.021258054888347970475705852711627E-817 + 1357 1.010629027444173985237852926355814E-817 5.053145137220869926189264631779068E-818 + 1358 2.526572568610434963094632315889534E-818 1.263286284305217481547316157944767E-818 + 1359 6.316431421526087407736580789723835E-819 3.158215710763043703868290394861918E-819 + 1360 1.579107855381521851934145197430959E-819 7.895539276907609259670725987154795E-820 + 1361 3.947769638453804629835362993577398E-820 1.973884819226902314917681496788699E-820 + 1362 9.869424096134511574588407483943495E-821 4.934712048067255787294203741971748E-821 + 1363 2.467356024033627893647101870985874E-821 1.233678012016813946823550935492937E-821 + 1364 6.168390060084069734117754677464685E-822 3.084195030042034867058877338732343E-822 + 1365 1.542097515021017433529438669366172E-822 7.710487575105087167647193346830858E-823 + 1366 3.855243787552543583823596673415429E-823 1.927621893776271791911798336707715E-823 + 1367 9.638109468881358959558991683538575E-824 4.819054734440679479779495841769288E-824 + 1368 2.409527367220339739889747920884644E-824 1.204763683610169869944873960442322E-824 + 1369 6.02381841805084934972436980221161E-825 3.011909209025424674862184901105805E-825 + 1370 1.505954604512712337431092450552903E-825 7.529773022563561687155462252764513E-826 + 1371 3.764886511281780843577731126382257E-826 1.882443255640890421788865563191128E-826 + 1372 9.41221627820445210894432781595564E-827 4.70610813910222605447216390797782E-827 + 1373 2.35305406955111302723608195398891E-827 1.176527034775556513618040976994455E-827 + 1374 5.882635173877782568090204884972275E-828 2.941317586938891284045102442486138E-828 + 1375 1.470658793469445642022551221243069E-828 7.353293967347228210112756106215345E-829 + 1376 3.676646983673614105056378053107673E-829 1.838323491836807052528189026553836E-829 + 1377 9.19161745918403526264094513276918E-830 4.59580872959201763132047256638459E-830 + 1378 2.297904364796008815660236283192295E-830 1.148952182398004407830118141596148E-830 + 1379 5.74476091199002203915059070798074E-831 2.87238045599501101957529535399037E-831 + 1380 1.436190227997505509787647676995185E-831 7.180951139987527548938238384975925E-832 + 1381 3.590475569993763774469119192487963E-832 1.795237784996881887234559596243981E-832 + 1382 8.976188924984409436172797981219905E-833 4.488094462492204718086398990609953E-833 + 1383 2.244047231246102359043199495304977E-833 1.122023615623051179521599747652488E-833 + 1384 5.61011807811525589760799873826244E-834 2.80505903905762794880399936913122E-834 + 1385 1.40252951952881397440199968456561E-834 7.01264759764406987200999842282805E-835 + 1386 3.506323798822034936004999211414025E-835 1.753161899411017468002499605707013E-835 + 1387 8.765809497055087340012498028535065E-836 4.382904748527543670006249014267533E-836 + 1388 2.191452374263771835003124507133767E-836 1.095726187131885917501562253566883E-836 + 1389 5.478630935659429587507811267834415E-837 2.739315467829714793753905633917208E-837 + 1390 1.369657733914857396876952816958604E-837 6.84828866957428698438476408479302E-838 + 1391 3.42414433478714349219238204239651E-838 1.712072167393571746096191021198255E-838 + 1392 8.560360836967858730480955105991275E-839 4.280180418483929365240477552995638E-839 + 1393 2.140090209241964682620238776497819E-839 1.070045104620982341310119388248910E-839 + 1394 5.35022552310491170655059694124455E-840 2.675112761552455853275298470622275E-840 + 1395 1.337556380776227926637649235311138E-840 6.687781903881139633188246176555688E-841 + 1396 3.343890951940569816594123088277844E-841 1.671945475970284908297061544138922E-841 + 1397 8.35972737985142454148530772069461E-842 4.179863689925712270742653860347305E-842 + 1398 2.089931844962856135371326930173653E-842 1.044965922481428067685663465086826E-842 + 1399 5.22482961240714033842831732543413E-843 2.612414806203570169214158662717065E-843 + 1400 1.306207403101785084607079331358533E-843 6.531037015508925423035396656792663E-844 + 1401 3.265518507754462711517698328396332E-844 1.632759253877231355758849164198166E-844 + 1402 8.16379626938615677879424582099083E-845 4.081898134693078389397122910495415E-845 + 1403 2.040949067346539194698561455247708E-845 1.020474533673269597349280727623854E-845 + 1404 5.10237266836634798674640363811927E-846 2.551186334183173993373201819059635E-846 + 1405 1.275593167091586996686600909529818E-846 6.377965835457934983433004547649088E-847 + 1406 3.188982917728967491716502273824544E-847 1.594491458864483745858251136912272E-847 + 1407 7.97245729432241872929125568456136E-848 3.98622864716120936464562784228068E-848 + 1408 1.99311432358060468232281392114034E-848 9.9655716179030234116140696057017E-849 + 1409 4.98278580895151170580703480285085E-849 2.491392904475755852903517401425425E-849 + 1410 1.245696452237877926451758700712713E-849 6.228482261189389632258793503563563E-850 + 1411 3.114241130594694816129396751781782E-850 1.557120565297347408064698375890891E-850 + 1412 7.785602826486737040323491879454455E-851 3.892801413243368520161745939727228E-851 + 1413 1.946400706621684260080872969863614E-851 9.73200353310842130040436484931807E-852 + 1414 4.866001766554210650202182424659035E-852 2.433000883277105325101091212329518E-852 + 1415 1.216500441638552662550545606164759E-852 6.082502208192763312752728030823795E-853 + 1416 3.041251104096381656376364015411898E-853 1.520625552048190828188182007705949E-853 + 1417 7.603127760240954140940910038529745E-854 3.801563880120477070470455019264873E-854 + 1418 1.900781940060238535235227509632437E-854 9.503909700301192676176137548162183E-855 + 1419 4.751954850150596338088068774081092E-855 2.375977425075298169044034387040546E-855 + 1420 1.187988712537649084522017193520273E-855 5.939943562688245422610085967601365E-856 + 1421 2.969971781344122711305042983800683E-856 1.484985890672061355652521491900341E-856 + 1422 7.424929453360306778262607459501705E-857 3.712464726680153389131303729750853E-857 + 1423 1.856232363340076694565651864875427E-857 9.281161816700383472828259324377133E-858 + 1424 4.640580908350191736414129662188567E-858 2.320290454175095868207064831094283E-858 + 1425 1.160145227087547934103532415547142E-858 5.800726135437739670517662077735708E-859 + 1426 2.900363067718869835258831038867854E-859 1.450181533859434917629415519433927E-859 + 1427 7.250907669297174588147077597169635E-860 3.625453834648587294073538798584818E-860 + 1428 1.812726917324293647036769399292409E-860 9.063634586621468235183846996462045E-861 + 1429 4.531817293310734117591923498231023E-861 2.265908646655367058795961749115511E-861 + 1430 1.132954323327683529397980874557756E-861 5.664771616638417646989904372788778E-862 + 1431 2.832385808319208823494952186394389E-862 1.416192904159604411747476093197195E-862 + 1432 7.080964520798022058737380465985975E-863 3.540482260399011029368690232992988E-863 + 1433 1.770241130199505514684345116496494E-863 8.85120565099752757342172558248247E-864 + 1434 4.425602825498763786710862791241235E-864 2.212801412749381893355431395620618E-864 + 1435 1.106400706374690946677715697810309E-864 5.532003531873454733388578489051545E-865 + 1436 2.766001765936727366694289244525773E-865 1.383000882968363683347144622262886E-865 + 1437 6.91500441484181841673572311131443E-866 3.457502207420909208367861555657215E-866 + 1438 1.728751103710454604183930777828608E-866 8.643755518552273020919653889143038E-867 + 1439 4.321877759276136510459826944571519E-867 2.160938879638068255229913472285760E-867 + 1440 1.080469439819034127614956736142880E-867 5.40234719909517063807478368071440E-868 + 1441 2.70117359954758531903739184035720E-868 1.35058679977379265951869592017860E-868 + 1442 6.7529339988689632975934796008930E-869 3.3764669994344816487967398004465E-869 + 1443 1.68823349971724082439836990022325E-869 8.44116749858620412199184950111625E-870 + 1444 4.220583749293102060995924750558125E-870 2.110291874646551030497962375279063E-870 + 1445 1.055145937323275515248981187639532E-870 5.275729686616377576244905938197658E-871 + 1446 2.637864843308188788122452969098829E-871 1.318932421654094394061226484549415E-871 + 1447 6.594662108270471970306132422747075E-872 3.297331054135235985153066211373538E-872 + 1448 1.648665527067617992576533105686769E-872 8.243327635338089962882665528433845E-873 + 1449 4.121663817669044981441332764216923E-873 2.060831908834522490720666382108461E-873 + 1450 1.030415954417261245360333191054231E-873 5.152079772086306226801665955271153E-874 + 1451 2.576039886043153113400832977635577E-874 1.288019943021576556700416488817788E-874 + 1452 6.44009971510788278350208244408894E-875 3.22004985755394139175104122204447E-875 + 1453 1.610024928776970695875520611022235E-875 8.050124643884853479377603055111175E-876 + 1454 4.025062321942426739688801527555588E-876 2.012531160971213369844400763777794E-876 + 1455 1.006265580485606684922200381888897E-876 5.031327902428033424611001909444485E-877 + 1456 2.515663951214016712305500954722243E-877 1.257831975607008356152750477361121E-877 + 1457 6.289159878035041780763752386805605E-878 3.144579939017520890381876193402803E-878 + 1458 1.572289969508760445190938096701402E-878 7.861449847543802225954690483507008E-879 + 1459 3.930724923771901112977345241753504E-879 1.965362461885950556488672620876752E-879 + 1460 9.82681230942975278244336310438376E-880 4.91340615471487639122168155219188E-880 + 1461 2.45670307735743819561084077609594E-880 1.22835153867871909780542038804797E-880 + 1462 6.14175769339359548902710194023985E-881 3.070878846696797744513550970119925E-881 + 1463 1.535439423348398872256775485059963E-881 7.677197116741994361283877425299813E-882 + 1464 3.838598558370997180641938712649907E-882 1.919299279185498590320969356324953E-882 + 1465 9.596496395927492951604846781624765E-883 4.798248197963746475802423390812383E-883 + 1466 2.399124098981873237901211695406192E-883 1.199562049490936618950605847703096E-883 + 1467 5.99781024745468309475302923851548E-884 2.99890512372734154737651461925774E-884 + 1468 1.49945256186367077368825730962887E-884 7.49726280931835386844128654814435E-885 + 1469 3.748631404659176934220643274072175E-885 1.874315702329588467110321637036088E-885 + 1470 9.37157851164794233555160818518044E-886 4.68578925582397116777580409259022E-886 + 1471 2.34289462791198558388790204629511E-886 1.171447313955992791943951023147555E-886 + 1472 5.857236569779963959719755115737775E-887 2.928618284889981979859877557868888E-887 + 1473 1.464309142444990989929938778934444E-887 7.32154571222495494964969389467222E-888 + 1474 3.66077285611247747482484694733611E-888 1.830386428056238737412423473668055E-888 + 1475 9.151932140281193687062117368340275E-889 4.575966070140596843531058684170138E-889 + 1476 2.287983035070298421765529342085069E-889 1.143991517535149210882764671042535E-889 + 1477 5.719957587675746054413823355212675E-890 2.859978793837873027206911677606338E-890 + 1478 1.429989396918936513603455838803169E-890 7.149946984594682568017279194015845E-891 + 1479 3.574973492297341284008639597007923E-891 1.787486746148670642004319798503961E-891 + 1480 8.937433730743353210021598992519805E-892 4.468716865371676605010799496259903E-892 + 1481 2.234358432685838302505399748129952E-892 1.117179216342919151252699874064976E-892 + 1482 5.58589608171459575626349937032488E-893 2.79294804085729787813174968516244E-893 + 1483 1.39647402042864893906587484258122E-893 6.9823701021432446953293742129061E-894 + 1484 3.49118505107162234766468710645305E-894 1.745592525535811173832343553226525E-894 + 1485 8.727962627679055869161717766132625E-895 4.363981313839527934580858883066313E-895 + 1486 2.181990656919763967290429441533157E-895 1.090995328459881983645214720766578E-895 + 1487 5.45497664229940991822607360383289E-896 2.727488321149704959113036801916445E-896 + 1488 1.363744160574852479556518400958223E-896 6.818720802874262397782592004791113E-897 + 1489 3.409360401437131198891296002395557E-897 1.704680200718565599445648001197778E-897 + 1490 8.52340100359282799722824000598889E-898 4.261700501796413998614120002994445E-898 + 1491 2.130850250898206999307060001497223E-898 1.065425125449103499653530000748611E-898 + 1492 5.327125627245517498267650003743055E-899 2.663562813622758749133825001871528E-899 + 1493 1.331781406811379374566912500935764E-899 6.65890703405689687283456250467882E-900 + 1494 3.32945351702844843641728125233941E-900 1.664726758514224218208640626169705E-900 + 1495 8.323633792571121091043203130848525E-901 4.161816896285560545521601565424263E-901 + 1496 2.080908448142780272760800782712132E-901 1.040454224071390136380400391356066E-901 + 1497 5.20227112035695068190200195678033E-902 2.601135560178475340951000978390165E-902 + 1498 1.300567780089237670475500489195083E-902 6.502838900446188352377502445975413E-903 + 1499 3.251419450223094176188751222987707E-903 1.625709725111547088094375611493853E-903 + 1500 8.128548625557735440471878057469265E-904 4.064274312778867720235939028734633E-904 + 1501 2.032137156389433860117969514367317E-904 1.016068578194716930058984757183658E-904 + 1502 5.08034289097358465029492378591829E-905 2.540171445486792325147461892959145E-905 + 1503 1.270085722743396162573730946479573E-905 6.350428613716980812868654732397863E-906 + 1504 3.175214306858490406434327366198932E-906 1.587607153429245203217163683099466E-906 + 1505 7.93803576714622601608581841549733E-907 3.969017883573113008042909207748665E-907 + 1506 1.984508941786556504021454603874333E-907 9.922544708932782520107273019371663E-908 + 1507 4.961272354466391260053636509685832E-908 2.480636177233195630026818254842916E-908 + 1508 1.240318088616597815013409127421458E-908 6.20159044308298907506704563710729E-909 + 1509 3.100795221541494537533522818553645E-909 1.550397610770747268766761409276823E-909 + 1510 7.751988053853736343833807046384115E-910 3.875994026926868171916903523192058E-910 + 1511 1.937997013463434085958451761596029E-910 9.689985067317170429792258807980145E-911 + 1512 4.844992533658585214896129403990073E-911 2.422496266829292607448064701995036E-911 + 1513 1.211248133414646303724032350997518E-911 6.05624066707323151862016175498759E-912 + 1514 3.028120333536615759310080877493795E-912 1.514060166768307879655040438746898E-912 + 1515 7.57030083384153939827520219373449E-913 3.785150416920769699137601096867245E-913 + 1516 1.892575208460384849568800548433623E-913 9.462876042301924247844002742168113E-914 + 1517 4.731438021150962123922001371084057E-914 2.365719010575481061961000685542028E-914 + 1518 1.182859505287740530980500342771014E-914 5.91429752643870265490250171385507E-915 + 1519 2.957148763219351327451250856927535E-915 1.478574381609675663725625428463768E-915 + 1520 7.39287190804837831862812714231884E-916 3.69643595402418915931406357115942E-916 + 1521 1.84821797701209457965703178557971E-916 9.24108988506047289828515892789855E-917 + 1522 4.620544942530236449142579463949275E-917 2.310272471265118224571289731974638E-917 + 1523 1.155136235632559112285644865987319E-917 5.775681178162795561428224329936595E-918 + 1524 2.887840589081397780714112164968298E-918 1.443920294540698890357056082484149E-918 + 1525 7.219601472703494451785280412420745E-919 3.609800736351747225892640206210373E-919 + 1526 1.804900368175873612946320103105187E-919 9.024501840879368064731600515525933E-920 + 1527 4.512250920439684032365800257762967E-920 2.256125460219842016182900128881483E-920 + 1528 1.128062730109921008091450064440742E-920 5.640313650549605040457250322203708E-921 + 1529 2.820156825274802520228625161101854E-921 1.410078412637401260114312580550927E-921 + 1530 7.050392063187006300571562902754635E-922 3.525196031593503150285781451377318E-922 + 1531 1.762598015796751575142890725688659E-922 8.812990078983757875714453628443295E-923 + 1532 4.406495039491878937857226814221648E-923 2.203247519745939468928613407110824E-923 + 1533 1.101623759872969734464306703555412E-923 5.50811879936484867232153351777706E-924 + 1534 2.75405939968242433616076675888853E-924 1.377029699841212168080383379444265E-924 + 1535 6.885148499206060840401916897221325E-925 3.442574249603030420200958448610663E-925 + 1536 1.721287124801515210100479224305332E-925 8.606435624007576050502396121526658E-926 + 1537 4.303217812003788025251198060763329E-926 2.151608906001894012625599030381665E-926 + 1538 1.075804453000947006312799515190833E-926 5.379022265004735031563997575954163E-927 + 1539 2.689511132502367515781998787977082E-927 1.344755566251183757890999393988541E-927 + 1540 6.723777831255918789454996969942705E-928 3.361888915627959394727498484971353E-928 + 1541 1.680944457813979697363749242485677E-928 8.404722289069898486818746212428383E-929 + 1542 4.202361144534949243409373106214192E-929 2.101180572267474621704686553107096E-929 + 1543 1.050590286133737310852343276553548E-929 5.25295143066868655426171638276774E-930 + 1544 2.62647571533434327713085819138387E-930 1.313237857667171638565429095691935E-930 + 1545 6.566189288335858192827145478459675E-931 3.283094644167929096413572739229838E-931 + 1546 1.641547322083964548206786369614919E-931 8.207736610419822741033931848074595E-932 + 1547 4.103868305209911370516965924037298E-932 2.051934152604955685258482962018649E-932 + 1548 1.025967076302477842629241481009325E-932 5.129835381512389213146207405046623E-933 + 1549 2.564917690756194606573103702523312E-933 1.282458845378097303286551851261656E-933 + 1550 6.41229422689048651643275925630828E-934 3.20614711344524325821637962815414E-934 + 1551 1.60307355672262162910818981407707E-934 8.01536778361310814554094907038535E-935 + 1552 4.007683891806554072770474535192675E-935 2.003841945903277036385237267596338E-935 + 1553 1.001920972951638518192618633798169E-935 5.009604864758192590963093168990845E-936 + 1554 2.504802432379096295481546584495423E-936 1.252401216189548147740773292247711E-936 + 1555 6.262006080947740738703866461238555E-937 3.131003040473870369351933230619278E-937 + 1556 1.565501520236935184675966615309639E-937 7.827507601184675923379833076548195E-938 + 1557 3.913753800592337961689916538274098E-938 1.956876900296168980844958269137049E-938 + 1558 9.784384501480844904224791345685245E-939 4.892192250740422452112395672842623E-939 + 1559 2.446096125370211226056197836421312E-939 1.223048062685105613028098918210656E-939 + 1560 6.11524031342552806514049459105328E-940 3.05762015671276403257024729552664E-940 + 1561 1.52881007835638201628512364776332E-940 7.6440503917819100814256182388166E-941 + 1562 3.8220251958909550407128091194083E-941 1.91101259794547752035640455970415E-941 + 1563 9.55506298972738760178202279852075E-942 4.777531494863693800891011399260375E-942 + 1564 2.388765747431846900445505699630188E-942 1.194382873715923450222752849815094E-942 + 1565 5.97191436857961725111376424907547E-943 2.985957184289808625556882124537735E-943 + 1566 1.492978592144904312778441062268868E-943 7.464892960724521563892205311344338E-944 + 1567 3.732446480362260781946102655672169E-944 1.866223240181130390973051327836085E-944 + 1568 9.331116200905651954865256639180425E-945 4.665558100452825977432628319590213E-945 + 1569 2.332779050226412988716314159795107E-945 1.166389525113206494358157079897553E-945 + 1570 5.831947625566032471790785399487765E-946 2.915973812783016235895392699743883E-946 + 1571 1.457986906391508117947696349871942E-946 7.289934531957540589738481749359708E-947 + 1572 3.644967265978770294869240874679854E-947 1.822483632989385147434620437339927E-947 + 1573 9.112418164946925737173102186699635E-948 4.556209082473462868586551093349818E-948 + 1574 2.278104541236731434293275546674909E-948 1.139052270618365717146637773337455E-948 + 1575 5.695261353091828585733188866687275E-949 2.847630676545914292866594433343638E-949 + 1576 1.423815338272957146433297216671819E-949 7.119076691364785732166486083359095E-950 + 1577 3.559538345682392866083243041679548E-950 1.779769172841196433041621520839774E-950 + 1578 8.89884586420598216520810760419887E-951 4.449422932102991082604053802099435E-951 + 1579 2.224711466051495541302026901049718E-951 1.112355733025747770651013450524859E-951 + 1580 5.561778665128738853255067252624295E-952 2.780889332564369426627533626312148E-952 + 1581 1.390444666282184713313766813156074E-952 6.95222333141092356656883406578037E-953 + 1582 3.476111665705461783284417032890185E-953 1.738055832852730891642208516445093E-953 + 1583 8.690279164263654458211042582225465E-954 4.345139582131827229105521291112733E-954 + 1584 2.172569791065913614552760645556367E-954 1.086284895532956807276380322778183E-954 + 1585 5.431424477664784036381901613890915E-955 2.715712238832392018190950806945458E-955 + 1586 1.357856119416196009095475403472729E-955 6.789280597080980045477377017363645E-956 + 1587 3.394640298540490022738688508681823E-956 1.697320149270245011369344254340911E-956 + 1588 8.486600746351225056846721271704555E-957 4.243300373175612528423360635852278E-957 + 1589 2.121650186587806264211680317926139E-957 1.060825093293903132105840158963070E-957 + 1590 5.30412546646951566052920079481535E-958 2.652062733234757830264600397407675E-958 + 1591 1.326031366617378915132300198703838E-958 6.630156833086894575661500993519188E-959 + 1592 3.315078416543447287830750496759594E-959 1.657539208271723643915375248379797E-959 + 1593 8.287696041358618219576876241898985E-960 4.143848020679309109788438120949493E-960 + 1594 2.071924010339654554894219060474747E-960 1.035962005169827277447109530237373E-960 + 1595 5.179810025849136387235547651186865E-961 2.589905012924568193617773825593433E-961 + 1596 1.294952506462284096808886912796717E-961 6.474762532311420484044434563983583E-962 + 1597 3.237381266155710242022217281991792E-962 1.618690633077855121011108640995896E-962 + 1598 8.09345316538927560505554320497948E-963 4.04672658269463780252777160248974E-963 + 1599 2.02336329134731890126388580124487E-963 1.011681645673659450631942900622435E-963 + 1600 5.058408228368297253159714503112175E-964 2.529204114184148626579857251556088E-964 + 1601 1.264602057092074313289928625778044E-964 6.32301028546037156644964312889022E-965 + 1602 3.16150514273018578322482156444511E-965 1.580752571365092891612410782222555E-965 + 1603 7.903762856825464458062053911112775E-966 3.951881428412732229031026955556388E-966 + 1604 1.975940714206366114515513477778194E-966 9.87970357103183057257756738889097E-967 + 1605 4.939851785515915286288783694445485E-967 2.469925892757957643144391847222743E-967 + 1606 1.234962946378978821572195923611372E-967 6.174814731894894107860979618056858E-968 + 1607 3.087407365947447053930489809028429E-968 1.543703682973723526965244904514215E-968 + 1608 7.718518414868617634826224522571075E-969 3.859259207434308817413112261285538E-969 + 1609 1.929629603717154408706556130642769E-969 9.648148018585772043532780653213845E-970 + 1610 4.824074009292886021766390326606923E-970 2.412037004646443010883195163303461E-970 + 1611 1.206018502323221505441597581651731E-970 6.030092511616107527207987908258653E-971 + 1612 3.015046255808053763603993954129327E-971 1.507523127904026881801996977064663E-971 + 1613 7.537615639520134409009984885323315E-972 3.768807819760067204504992442661658E-972 + 1614 1.884403909880033602252496221330829E-972 9.422019549400168011262481106654145E-973 + 1615 4.711009774700084005631240553327073E-973 2.355504887350042002815620276663536E-973 + 1616 1.177752443675021001407810138331768E-973 5.88876221837510500703905069165884E-974 + 1617 2.94438110918755250351952534582942E-974 1.47219055459377625175976267291471E-974 + 1618 7.36095277296888125879881336457355E-975 3.680476386484440629399406682286775E-975 + 1619 1.840238193242220314699703341143388E-975 9.201190966211101573498516705716938E-976 + 1620 4.600595483105550786749258352858469E-976 2.300297741552775393374629176429235E-976 + 1621 1.150148870776387696687314588214618E-976 5.750744353881938483436572941073088E-977 + 1622 2.875372176940969241718286470536544E-977 1.437686088470484620859143235268272E-977 + 1623 7.18843044235242310429571617634136E-978 3.59421522117621155214785808817068E-978 + 1624 1.79710761058810577607392904408534E-978 8.9855380529405288803696452204267E-979 + 1625 4.49276902647026444018482261021335E-979 2.246384513235132220092411305106675E-979 + 1626 1.123192256617566110046205652553338E-979 5.615961283087830550231028262766688E-980 + 1627 2.807980641543915275115514131383344E-980 1.403990320771957637557757065691672E-980 + 1628 7.01995160385978818778878532845836E-981 3.50997580192989409389439266422918E-981 + 1629 1.75498790096494704694719633211459E-981 8.77493950482473523473598166057295E-982 + 1630 4.387469752412367617367990830286475E-982 2.193734876206183808683995415143238E-982 + 1631 1.096867438103091904341997707571619E-982 5.484337190515459521709988537858095E-983 + 1632 2.742168595257729760854994268929048E-983 1.371084297628864880427497134464524E-983 + 1633 6.85542148814432440213748567232262E-984 3.42771074407216220106874283616131E-984 + 1634 1.713855372036081100534371418080655E-984 8.569276860180405502671857090403275E-985 + 1635 4.284638430090202751335928545201638E-985 2.142319215045101375667964272600819E-985 + 1636 1.071159607522550687833982136300410E-985 5.355798037612753439169910681502048E-986 + 1637 2.677899018806376719584955340751024E-986 1.338949509403188359792477670375512E-986 + 1638 6.69474754701594179896238835187756E-987 3.34737377350797089948119417593878E-987 + 1639 1.67368688675398544974059708796939E-987 8.36843443376992724870298543984695E-988 + 1640 4.184217216884963624351492719923475E-988 2.092108608442481812175746359961738E-988 + 1641 1.046054304221240906087873179980869E-988 5.230271521106204530439365899904345E-989 + 1642 2.615135760553102265219682949952173E-989 1.307567880276551132609841474976086E-989 + 1643 6.53783940138275566304920737488043E-990 3.268919700691377831524603687440215E-990 + 1644 1.634459850345688915762301843720108E-990 8.172299251728444578811509218600538E-991 + 1645 4.086149625864222289405754609300269E-991 2.043074812932111144702877304650135E-991 + 1646 1.021537406466055572351438652325068E-991 5.107687032330277861757193261625338E-992 + 1647 2.553843516165138930878596630812669E-992 1.276921758082569465439298315406335E-992 + 1648 6.384608790412847327196491577031675E-993 3.192304395206423663598245788515838E-993 + 1649 1.596152197603211831799122894257919E-993 7.980760988016059158995614471289595E-994 + 1650 3.990380494008029579497807235644798E-994 1.995190247004014789748903617822399E-994 + 1651 9.975951235020073948744518089111995E-995 4.987975617510036974372259044555998E-995 + 1652 2.493987808755018487186129522277999E-995 1.246993904377509243593064761139000E-995 + 1653 6.23496952188754621796532380569500E-996 3.11748476094377310898266190284750E-996 + 1654 1.55874238047188655449133095142375E-996 7.79371190235943277245665475711875E-997 + 1655 3.896855951179716386228327378559375E-997 1.948427975589858193114163689279688E-997 + 1656 9.74213987794929096557081844639844E-998 4.87106993897464548278540922319922E-998 + 1657 2.43553496948732274139270461159961E-998 1.217767484743661370696352305799805E-998 + 1658 6.088837423718306853481761528999025E-999 3.044418711859153426740880764499513E-999 + 1659 1.522209355929576713370440382249757E-999 7.611046779647883566852201911248783E-1000 + 1660 3.805523389823941783426100955624392E-1000 1.902761694911970891713050477812196E-1000 + 1661 9.51380847455985445856525238906098E-1001 4.75690423727992722928262619453049E-1001 + 1662 2.378452118639963614641313097265245E-1001 1.189226059319981807320656548632623E-1001 + 1663 5.946130296599909036603282743163115E-1002 2.973065148299954518301641371581558E-1002 + 1664 1.486532574149977259150820685790779E-1002 7.432662870749886295754103428953895E-1003 + 1665 3.716331435374943147877051714476948E-1003 1.858165717687471573938525857238474E-1003 + 1666 9.29082858843735786969262928619237E-1004 4.645414294218678934846314643096185E-1004 + 1667 2.322707147109339467423157321548093E-1004 1.161353573554669733711578660774046E-1004 + 1668 5.80676786777334866855789330387023E-1005 2.903383933886674334278946651935115E-1005 + 1669 1.451691966943337167139473325967558E-1005 7.258459834716685835697366629837788E-1006 + 1670 3.629229917358342917848683314918894E-1006 1.814614958679171458924341657459447E-1006 + 1671 9.073074793395857294621708287297235E-1007 4.536537396697928647310854143648618E-1007 + 1672 2.268268698348964323655427071824309E-1007 1.134134349174482161827713535912155E-1007 + 1673 5.670671745872410809138567679560775E-1008 2.835335872936205404569283839780388E-1008 + 1674 1.417667936468102702284641919890194E-1008 7.08833968234051351142320959945097E-1009 + 1675 3.544169841170256755711604799725485E-1009 1.772084920585128377855802399862743E-1009 + 1676 8.860424602925641889279011999313715E-1010 4.430212301462820944639505999656858E-1010 + 1677 2.215106150731410472319752999828429E-1010 1.107553075365705236159876499914215E-1010 + 1678 5.537765376828526180799382499571075E-1011 2.768882688414263090399691249785538E-1011 + 1679 1.384441344207131545199845624892769E-1011 6.922206721035657725999228124463845E-1012 + 1680 3.461103360517828862999614062231923E-1012 1.730551680258914431499807031115961E-1012 + 1681 8.652758401294572157499035155579805E-1013 4.326379200647286078749517577789903E-1013 + 1682 2.163189600323643039374758788894952E-1013 1.081594800161821519687379394447476E-1013 + 1683 5.40797400080910759843689697223738E-1014 2.70398700040455379921844848611869E-1014 + 1684 1.351993500202276899609224243059345E-1014 6.759967501011384498046121215296725E-1015 + 1685 3.379983750505692249023060607648363E-1015 1.689991875252846124511530303824181E-1015 + 1686 8.449959376264230622557651519120905E-1016 4.224979688132115311278825759560453E-1016 + 1687 2.112489844066057655639412879780227E-1016 1.056244922033028827819706439890113E-1016 + 1688 5.281224610165144139098532199450565E-1017 2.640612305082572069549266099725283E-1017 + 1689 1.320306152541286034774633049862642E-1017 6.601530762706430173873165249313208E-1018 + 1690 3.300765381353215086936582624656604E-1018 1.650382690676607543468291312328302E-1018 + 1691 8.25191345338303771734145656164151E-1019 4.125956726691518858670728280820755E-1019 + 1692 2.062978363345759429335364140410378E-1019 1.031489181672879714667682070205189E-1019 + 1693 5.157445908364398573338410351025945E-1020 2.578722954182199286669205175512973E-1020 + 1694 1.289361477091099643334602587756487E-1020 6.446807385455498216673012938782433E-1021 + 1695 3.223403692727749108336506469391217E-1021 1.611701846363874554168253234695608E-1021 + 1696 8.05850923181937277084126617347804E-1022 4.02925461590968638542063308673902E-1022 + 1697 2.01462730795484319271031654336951E-1022 1.007313653977421596355158271684755E-1022 + 1698 5.036568269887107981775791358423775E-1023 2.518284134943553990887895679211888E-1023 + 1699 1.259142067471776995443947839605944E-1023 6.29571033735888497721973919802972E-1024 + 1700 3.14785516867944248860986959901486E-1024 1.57392758433972124430493479950743E-1024 + 1701 7.86963792169860622152467399753715E-1025 3.934818960849303110762336998768575E-1025 + 1702 1.967409480424651555381168499384288E-1025 9.837047402123257776905842496921438E-1026 + 1703 4.918523701061628888452921248460719E-1026 2.459261850530814444226460624230360E-1026 + 1704 1.229630925265407222113230312115180E-1026 6.14815462632703611056615156057590E-1027 + 1705 3.07407731316351805528307578028795E-1027 1.537038656581759027641537890143975E-1027 + 1706 7.685193282908795138207689450719875E-1028 3.842596641454397569103844725359938E-1028 + 1707 1.921298320727198784551922362679969E-1028 9.606491603635993922759611813399845E-1029 + 1708 4.803245801817996961379805906699923E-1029 2.401622900908998480689902953349961E-1029 + 1709 1.200811450454499240344951476674981E-1029 6.004057252272496201724757383374903E-1030 + 1710 3.002028626136248100862378691687452E-1030 1.501014313068124050431189345843726E-1030 + 1711 7.50507156534062025215594672921863E-1031 3.752535782670310126077973364609315E-1031 + 1712 1.876267891335155063038986682304658E-1031 9.381339456675775315194933411523288E-1032 + 1713 4.690669728337887657597466705761644E-1032 2.345334864168943828798733352880822E-1032 + 1714 1.172667432084471914399366676440411E-1032 5.863337160422359571996833382202055E-1033 + 1715 2.931668580211179785998416691101028E-1033 1.465834290105589892999208345550514E-1033 + 1716 7.32917145052794946499604172775257E-1034 3.664585725263974732498020863876285E-1034 + 1717 1.832292862631987366249010431938143E-1034 9.161464313159936831245052159690713E-1035 + 1718 4.580732156579968415622526079845357E-1035 2.290366078289984207811263039922678E-1035 + 1719 1.145183039144992103905631519961339E-1035 5.725915195724960519528157599806695E-1036 + 1720 2.862957597862480259764078799903348E-1036 1.431478798931240129882039399951674E-1036 + 1721 7.15739399465620064941019699975837E-1037 3.578696997328100324705098499879185E-1037 + 1722 1.789348498664050162352549249939593E-1037 8.946742493320250811762746249697963E-1038 + 1723 4.473371246660125405881373124848982E-1038 2.236685623330062702940686562424491E-1038 + 1724 1.118342811665031351470343281212246E-1038 5.591714058325156757351716406061228E-1039 + 1725 2.795857029162578378675858203030614E-1039 1.397928514581289189337929101515307E-1039 + 1726 6.989642572906445946689645507576535E-1040 3.494821286453222973344822753788268E-1040 + 1727 1.747410643226611486672411376894134E-1040 8.73705321613305743336205688447067E-1041 + 1728 4.368526608066528716681028442235335E-1041 2.184263304033264358340514221117668E-1041 + 1729 1.092131652016632179170257110558834E-1041 5.46065826008316089585128555279417E-1042 + 1730 2.730329130041580447925642776397085E-1042 1.365164565020790223962821388198543E-1042 + 1731 6.825822825103951119814106940992715E-1043 3.412911412551975559907053470496358E-1043 + 1732 1.706455706275987779953526735248179E-1043 8.532278531379938899767633676240895E-1044 + 1733 4.266139265689969449883816838120448E-1044 2.133069632844984724941908419060224E-1044 + 1734 1.066534816422492362470954209530112E-1044 5.33267408211246181235477104765056E-1045 + 1735 2.66633704105623090617738552382528E-1045 1.33316852052811545308869276191264E-1045 + 1736 6.6658426026405772654434638095632E-1046 3.3329213013202886327217319047816E-1046 + 1737 1.6664606506601443163608659523908E-1046 8.332303253300721581804329761954E-1047 + 1738 4.166151626650360790902164880977E-1047 2.0830758133251803954510824404885E-1047 + 1739 1.04153790666259019772554122024425E-1047 5.20768953331295098862770610122125E-1048 + 1740 2.603844766656475494313853050610625E-1048 1.301922383328237747156926525305313E-1048 + 1741 6.509611916641188735784632626526565E-1049 3.254805958320594367892316313263283E-1049 + 1742 1.627402979160297183946158156631642E-1049 8.137014895801485919730790783158208E-1050 + 1743 4.068507447900742959865395391579104E-1050 2.034253723950371479932697695789552E-1050 + 1744 1.017126861975185739966348847894776E-1050 5.08563430987592869983174423947388E-1051 + 1745 2.54281715493796434991587211973694E-1051 1.27140857746898217495793605986847E-1051 + 1746 6.35704288734491087478968029934235E-1052 3.178521443672455437394840149671175E-1052 + 1747 1.589260721836227718697420074835588E-1052 7.946303609181138593487100374177938E-1053 + 1748 3.973151804590569296743550187088969E-1053 1.986575902295284648371775093544485E-1053 + 1749 9.932879511476423241858875467722425E-1054 4.966439755738211620929437733861213E-1054 + 1750 2.483219877869105810464718866930607E-1054 1.241609938934552905232359433465303E-1054 + 1751 6.208049694672764526161797167326515E-1055 3.104024847336382263080898583663258E-1055 + 1752 1.552012423668191131540449291831629E-1055 7.760062118340955657702246459158145E-1056 + 1753 3.880031059170477828851123229579073E-1056 1.940015529585238914425561614789536E-1056 + 1754 9.70007764792619457212780807394768E-1057 4.85003882396309728606390403697384E-1057 + 1755 2.42501941198154864303195201848692E-1057 1.21250970599077432151597600924346E-1057 + 1756 6.0625485299538716075798800462173E-1058 3.03127426497693580378994002310865E-1058 + 1757 1.515637132488467901894970011554325E-1058 7.578185662442339509474850057771625E-1059 + 1758 3.789092831221169754737425028885813E-1059 1.894546415610584877368712514442906E-1059 + 1759 9.47273207805292438684356257221453E-1060 4.736366039026462193421781286107265E-1060 + 1760 2.368183019513231096710890643053633E-1060 1.184091509756615548355445321526816E-1060 + 1761 5.92045754878307774177722660763408E-1061 2.96022877439153887088861330381704E-1061 + 1762 1.48011438719576943544430665190852E-1061 7.4005719359788471772215332595426E-1062 + 1763 3.7002859679894235886107666297713E-1062 1.85014298399471179430538331488565E-1062 + 1764 9.25071491997355897152691657442825E-1063 4.625357459986779485763458287214125E-1063 + 1765 2.312678729993389742881729143607063E-1063 1.156339364996694871440864571803531E-1063 + 1766 5.781696824983474357204322859017655E-1064 2.890848412491737178602161429508828E-1064 + 1767 1.445424206245868589301080714754414E-1064 7.22712103122934294650540357377207E-1065 + 1768 3.613560515614671473252701786886035E-1065 1.806780257807335736626350893443018E-1065 + 1769 9.03390128903667868313175446721509E-1066 4.516950644518339341565877233607545E-1066 + 1770 2.258475322259169670782938616803773E-1066 1.129237661129584835391469308401886E-1066 + 1771 5.64618830564792417695734654200943E-1067 2.823094152823962088478673271004715E-1067 + 1772 1.411547076411981044239336635502358E-1067 7.057735382059905221196683177511788E-1068 + 1773 3.528867691029952610598341588755894E-1068 1.764433845514976305299170794377947E-1068 + 1774 8.822169227574881526495853971889735E-1069 4.411084613787440763247926985944868E-1069 + 1775 2.205542306893720381623963492972434E-1069 1.102771153446860190811981746486217E-1069 + 1776 5.513855767234300954059908732431085E-1070 2.756927883617150477029954366215543E-1070 + 1777 1.378463941808575238514977183107772E-1070 6.892319709042876192574885915538858E-1071 + 1778 3.446159854521438096287442957769429E-1071 1.723079927260719048143721478884715E-1071 + 1779 8.615399636303595240718607394423575E-1072 4.307699818151797620359303697211788E-1072 + 1780 2.153849909075898810179651848605894E-1072 1.076924954537949405089825924302947E-1072 + 1781 5.384624772689747025449129621514735E-1073 2.692312386344873512724564810757368E-1073 + 1782 1.346156193172436756362282405378684E-1073 6.73078096586218378181141202689342E-1074 + 1783 3.36539048293109189090570601344671E-1074 1.682695241465545945452853006723355E-1074 + 1784 8.413476207327729727264265033616775E-1075 4.206738103663864863632132516808388E-1075 + 1785 2.103369051831932431816066258404194E-1075 1.051684525915966215908033129202097E-1075 + 1786 5.258422629579831079540165646010485E-1076 2.629211314789915539770082823005243E-1076 + 1787 1.314605657394957769885041411502622E-1076 6.573028286974788849425207057513108E-1077 + 1788 3.286514143487394424712603528756554E-1077 1.643257071743697212356301764378277E-1077 + 1789 8.216285358718486061781508821891385E-1078 4.108142679359243030890754410945693E-1078 + 1790 2.054071339679621515445377205472847E-1078 1.027035669839810757722688602736423E-1078 + 1791 5.135178349199053788613443013682115E-1079 2.567589174599526894306721506841058E-1079 + 1792 1.283794587299763447153360753420529E-1079 6.418972936498817235766803767102645E-1080 + 1793 3.209486468249408617883401883551323E-1080 1.604743234124704308941700941775661E-1080 + 1794 8.023716170623521544708504708878305E-1081 4.011858085311760772354252354439153E-1081 + 1795 2.005929042655880386177126177219577E-1081 1.002964521327940193088563088609788E-1081 + 1796 5.01482260663970096544281544304894E-1082 2.50741130331985048272140772152447E-1082 + 1797 1.253705651659925241360703860762235E-1082 6.268528258299626206803519303811175E-1083 + 1798 3.134264129149813103401759651905588E-1083 1.567132064574906551700879825952794E-1083 + 1799 7.83566032287453275850439912976397E-1084 3.917830161437266379252199564881985E-1084 + 1800 1.958915080718633189626099782440993E-1084 9.794575403593165948130498912204963E-1085 + 1801 4.897287701796582974065249456102482E-1085 2.448643850898291487032624728051241E-1085 + 1802 1.224321925449145743516312364025621E-1085 6.121609627245728717581561820128103E-1086 + 1803 3.060804813622864358790780910064052E-1086 1.530402406811432179395390455032026E-1086 + 1804 7.65201203405716089697695227516013E-1087 3.826006017028580448488476137580065E-1087 + 1805 1.913003008514290224244238068790033E-1087 9.565015042571451121221190343950163E-1088 + 1806 4.782507521285725560610595171975082E-1088 2.391253760642862780305297585987541E-1088 + 1807 1.195626880321431390152648792993771E-1088 5.978134401607156950763243964968853E-1089 + 1808 2.989067200803578475381621982484427E-1089 1.494533600401789237690810991242213E-1089 + 1809 7.472668002008946188454054956211065E-1090 3.736334001004473094227027478105533E-1090 + 1810 1.868167000502236547113513739052767E-1090 9.340835002511182735567568695263833E-1091 + 1811 4.670417501255591367783784347631917E-1091 2.335208750627795683891892173815958E-1091 + 1812 1.167604375313897841945946086907979E-1091 5.838021876569489209729730434539895E-1092 + 1813 2.919010938284744604864865217269948E-1092 1.459505469142372302432432608634974E-1092 + 1814 7.29752734571186151216216304317487E-1093 3.648763672855930756081081521587435E-1093 + 1815 1.824381836427965378040540760793718E-1093 9.121909182139826890202703803968588E-1094 + 1816 4.560954591069913445101351901984294E-1094 2.280477295534956722550675950992147E-1094 + 1817 1.140238647767478361275337975496074E-1094 5.701193238837391806376689877480368E-1095 + 1818 2.850596619418695903188344938740184E-1095 1.425298309709347951594172469370092E-1095 + 1819 7.12649154854673975797086234685046E-1096 3.56324577427336987898543117342523E-1096 + 1820 1.781622887136684939492715586712615E-1096 8.908114435683424697463577933563075E-1097 + 1821 4.454057217841712348731788966781538E-1097 2.227028608920856174365894483390769E-1097 + 1822 1.113514304460428087182947241695385E-1097 5.567571522302140435914736208476923E-1098 + 1823 2.783785761151070217957368104238462E-1098 1.391892880575535108978684052119231E-1098 + 1824 6.959464402877675544893420260596155E-1099 3.479732201438837772446710130298078E-1099 + 1825 1.739866100719418886223355065149039E-1099 8.699330503597094431116775325745195E-1100 + 1826 4.349665251798547215558387662872598E-1100 2.174832625899273607779193831436299E-1100 + 1827 1.087416312949636803889596915718150E-1100 5.437081564748184019447984578590748E-1101 + 1828 2.718540782374092009723992289295374E-1101 1.359270391187046004861996144647687E-1101 + 1829 6.796351955935230024309980723238435E-1102 3.398175977967615012154990361619218E-1102 + 1830 1.699087988983807506077495180809609E-1102 8.495439944919037530387475904048045E-1103 + 1831 4.247719972459518765193737952024023E-1103 2.123859986229759382596868976012011E-1103 + 1832 1.061929993114879691298434488006006E-1103 5.309649965574398456492172440030028E-1104 + 1833 2.654824982787199228246086220015014E-1104 1.327412491393599614123043110007507E-1104 + 1834 6.637062456967998070615215550037535E-1105 3.318531228483999035307607775018768E-1105 + 1835 1.659265614241999517653803887509384E-1105 8.29632807120999758826901943754692E-1106 + 1836 4.14816403560499879413450971877346E-1106 2.07408201780249939706725485938673E-1106 + 1837 1.037041008901249698533627429693365E-1106 5.185205044506248492668137148466825E-1107 + 1838 2.592602522253124246334068574233413E-1107 1.296301261126562123167034287116706E-1107 + 1839 6.48150630563281061583517143558353E-1108 3.240753152816405307917585717791765E-1108 + 1840 1.620376576408202653958792858895883E-1108 8.101882882041013269793964294479413E-1109 + 1841 4.050941441020506634896982147239707E-1109 2.025470720510253317448491073619853E-1109 + 1842 1.012735360255126658724245536809927E-1109 5.063676801275633293621227684049633E-1110 + 1843 2.531838400637816646810613842024817E-1110 1.265919200318908323405306921012408E-1110 + 1844 6.32959600159454161702653460506204E-1111 3.16479800079727080851326730253102E-1111 + 1845 1.58239900039863540425663365126551E-1111 7.91199500199317702128316825632755E-1112 + 1846 3.955997500996588510641584128163775E-1112 1.977998750498294255320792064081888E-1112 + 1847 9.88999375249147127660396032040944E-1113 4.94499687624573563830198016020472E-1113 + 1848 2.47249843812286781915099008010236E-1113 1.23624921906143390957549504005118E-1113 + 1849 6.1812460953071695478774752002559E-1114 3.09062304765358477393873760012795E-1114 + 1850 1.545311523826792386969368800063975E-1114 7.726557619133961934846844000319875E-1115 + 1851 3.863278809566980967423422000159938E-1115 1.931639404783490483711711000079969E-1115 + 1852 9.658197023917452418558555000399845E-1116 4.829098511958726209279277500199923E-1116 + 1853 2.414549255979363104639638750099962E-1116 1.207274627989681552319819375049981E-1116 + 1854 6.036373139948407761599096875249905E-1117 3.018186569974203880799548437624953E-1117 + 1855 1.509093284987101940399774218812477E-1117 7.545466424935509701998871094062383E-1118 + 1856 3.772733212467754850999435547031192E-1118 1.886366606233877425499717773515596E-1118 + 1857 9.43183303116938712749858886757798E-1119 4.71591651558469356374929443378899E-1119 + 1858 2.357958257792346781874647216894495E-1119 1.178979128896173390937323608447248E-1119 + 1859 5.89489564448086695468661804223624E-1120 2.94744782224043347734330902111812E-1120 + 1860 1.47372391112021673867165451055906E-1120 7.3686195556010836933582725527953E-1121 + 1861 3.68430977780054184667913627639765E-1121 1.842154888900270923339568138198825E-1121 + 1862 9.210774444501354616697840690994125E-1122 4.605387222250677308348920345497063E-1122 + 1863 2.302693611125338654174460172748532E-1122 1.151346805562669327087230086374266E-1122 + 1864 5.75673402781334663543615043187133E-1123 2.878367013906673317718075215935665E-1123 + 1865 1.439183506953336658859037607967833E-1123 7.195917534766683294295188039839163E-1124 + 1866 3.597958767383341647147594019919582E-1124 1.798979383691670823573797009959791E-1124 + 1867 8.994896918458354117868985049798955E-1125 4.497448459229177058934492524899478E-1125 + 1868 2.248724229614588529467246262449739E-1125 1.124362114807294264733623131224870E-1125 + 1869 5.62181057403647132366811565612435E-1126 2.810905287018235661834057828062175E-1126 + 1870 1.405452643509117830917028914031088E-1126 7.027263217545589154585144570155438E-1127 + 1871 3.513631608772794577292572285077719E-1127 1.756815804386397288646286142538860E-1127 + 1872 8.78407902193198644323143071269430E-1128 4.39203951096599322161571535634715E-1128 + 1873 2.196019755482996610807857678173575E-1128 1.098009877741498305403928839086788E-1128 + 1874 5.49004938870749152701964419543394E-1129 2.74502469435374576350982209771697E-1129 + 1875 1.372512347176872881754911048858485E-1129 6.862561735884364408774555244292425E-1130 + 1876 3.431280867942182204387277622146213E-1130 1.715640433971091102193638811073106E-1130 + 1877 8.57820216985545551096819405536553E-1131 4.289101084927727755484097027682765E-1131 + 1878 2.144550542463863877742048513841383E-1131 1.072275271231931938871024256920691E-1131 + 1879 5.361376356159659694355121284603455E-1132 2.680688178079829847177560642301728E-1132 + 1880 1.340344089039914923588780321150864E-1132 6.70172044519957461794390160575432E-1133 + 1881 3.35086022259978730897195080287716E-1133 1.67543011129989365448597540143858E-1133 + 1882 8.3771505564994682724298770071929E-1134 4.18857527824973413621493850359645E-1134 + 1883 2.094287639124867068107469251798225E-1134 1.047143819562433534053734625899113E-1134 + 1884 5.235719097812167670268673129495565E-1135 2.617859548906083835134336564747783E-1135 + 1885 1.308929774453041917567168282373892E-1135 6.544648872265209587835841411869458E-1136 + 1886 3.272324436132604793917920705934729E-1136 1.636162218066302396958960352967365E-1136 + 1887 8.180811090331511984794801764836825E-1137 4.090405545165755992397400882418413E-1137 + 1888 2.045202772582877996198700441209207E-1137 1.022601386291438998099350220604603E-1137 + 1889 5.113006931457194990496751103023015E-1138 2.556503465728597495248375551511508E-1138 + 1890 1.278251732864298747624187775755754E-1138 6.39125866432149373812093887877877E-1139 + 1891 3.195629332160746869060469439389385E-1139 1.597814666080373434530234719694693E-1139 + 1892 7.989073330401867172651173598473465E-1140 3.994536665200933586325586799236733E-1140 + 1893 1.997268332600466793162793399618367E-1140 9.986341663002333965813966998091833E-1141 + 1894 4.993170831501166982906983499045917E-1141 2.496585415750583491453491749522958E-1141 + 1895 1.248292707875291745726745874761479E-1141 6.241463539376458728633729373807395E-1142 + 1896 3.120731769688229364316864686903698E-1142 1.560365884844114682158432343451849E-1142 + 1897 7.801829424220573410792161717259245E-1143 3.900914712110286705396080858629623E-1143 + 1898 1.950457356055143352698040429314812E-1143 9.752286780275716763490202146574058E-1144 + 1899 4.876143390137858381745101073287029E-1144 2.438071695068929190872550536643515E-1144 + 1900 1.219035847534464595436275268321758E-1144 6.095179237672322977181376341608788E-1145 + 1901 3.047589618836161488590688170804394E-1145 1.523794809418080744295344085402197E-1145 + 1902 7.618974047090403721476720427010985E-1146 3.809487023545201860738360213505493E-1146 + 1903 1.904743511772600930369180106752747E-1146 9.523717558863004651845900533763733E-1147 + 1904 4.761858779431502325922950266881867E-1147 2.380929389715751162961475133440933E-1147 + 1905 1.190464694857875581480737566720467E-1147 5.952323474289377907403687833602333E-1148 + 1906 2.976161737144688953701843916801167E-1148 1.488080868572344476850921958400583E-1148 + 1907 7.440404342861722384254609792002915E-1149 3.720202171430861192127304896001458E-1149 + 1908 1.860101085715430596063652448000729E-1149 9.300505428577152980318262240003645E-1150 + 1909 4.650252714288576490159131120001823E-1150 2.325126357144288245079565560000911E-1150 + 1910 1.162563178572144122539782780000456E-1150 5.812815892860720612698913900002278E-1151 + 1911 2.906407946430360306349456950001139E-1151 1.453203973215180153174728475000570E-1151 + 1912 7.26601986607590076587364237500285E-1152 3.633009933037950382936821187501425E-1152 + 1913 1.816504966518975191468410593750713E-1152 9.082524832594875957342052968753563E-1153 + 1914 4.541262416297437978671026484376782E-1153 2.270631208148718989335513242188391E-1153 + 1915 1.135315604074359494667756621094196E-1153 5.676578020371797473338783105470978E-1154 + 1916 2.838289010185898736669391552735489E-1154 1.419144505092949368334695776367745E-1154 + 1917 7.095722525464746841673478881838725E-1155 3.547861262732373420836739440919363E-1155 + 1918 1.773930631366186710418369720459682E-1155 8.869653156830933552091848602298408E-1156 + 1919 4.434826578415466776045924301149204E-1156 2.217413289207733388022962150574602E-1156 + 1920 1.108706644603866694011481075287301E-1156 5.543533223019333470057405376436505E-1157 + 1921 2.771766611509666735028702688218253E-1157 1.385883305754833367514351344109126E-1157 + 1922 6.92941652877416683757175672054563E-1158 3.464708264387083418785878360272815E-1158 + 1923 1.732354132193541709392939180136408E-1158 8.661770660967708546964695900682038E-1159 + 1924 4.330885330483854273482347950341019E-1159 2.165442665241927136741173975170510E-1159 + 1925 1.082721332620963568370586987585255E-1159 5.413606663104817841852934937926275E-1160 + 1926 2.706803331552408920926467468963138E-1160 1.353401665776204460463233734481569E-1160 + 1927 6.767008328881022302316168672407845E-1161 3.383504164440511151158084336203923E-1161 + 1928 1.691752082220255575579042168101962E-1161 8.458760411101277877895210840509808E-1162 + 1929 4.229380205550638938947605420254904E-1162 2.114690102775319469473802710127452E-1162 + 1930 1.057345051387659734736901355063726E-1162 5.28672525693829867368450677531863E-1163 + 1931 2.643362628469149336842253387659315E-1163 1.321681314234574668421126693829658E-1163 + 1932 6.60840657117287334210563346914829E-1164 3.304203285586436671052816734574145E-1164 + 1933 1.652101642793218335526408367287073E-1164 8.260508213966091677632041836435363E-1165 + 1934 4.130254106983045838816020918217682E-1165 2.065127053491522919408010459108841E-1165 + 1935 1.032563526745761459704005229554421E-1165 5.162817633728807298520026147772103E-1166 + 1936 2.581408816864403649260013073886052E-1166 1.290704408432201824630006536943026E-1166 + 1937 6.45352204216100912315003268471513E-1167 3.226761021080504561575016342357565E-1167 + 1938 1.613380510540252280787508171178783E-1167 8.066902552701261403937540855893913E-1168 + 1939 4.033451276350630701968770427946957E-1168 2.016725638175315350984385213973478E-1168 + 1940 1.008362819087657675492192606986739E-1168 5.041814095438288377460963034933695E-1169 + 1941 2.520907047719144188730481517466848E-1169 1.260453523859572094365240758733424E-1169 + 1942 6.30226761929786047182620379366712E-1170 3.15113380964893023591310189683356E-1170 + 1943 1.57556690482446511795655094841678E-1170 7.8778345241223255897827547420839E-1171 + 1944 3.93891726206116279489137737104195E-1171 1.969458631030581397445688685520975E-1171 + 1945 9.847293155152906987228443427604875E-1172 4.923646577576453493614221713802438E-1172 + 1946 2.461823288788226746807110856901219E-1172 1.230911644394113373403555428450610E-1172 + 1947 6.15455822197056686701777714225305E-1173 3.077279110985283433508888571126525E-1173 + 1948 1.538639555492641716754444285563263E-1173 7.693197777463208583772221427816313E-1174 + 1949 3.846598888731604291886110713908157E-1174 1.923299444365802145943055356954078E-1174 + 1950 9.61649722182901072971527678477039E-1175 4.808248610914505364857638392385195E-1175 + 1951 2.404124305457252682428819196192598E-1175 1.202062152728626341214409598096299E-1175 + 1952 6.010310763643131706072047990481495E-1176 3.005155381821565853036023995240748E-1176 + 1953 1.502577690910782926518011997620374E-1176 7.51288845455391463259005998810187E-1177 + 1954 3.756444227276957316295029994050935E-1177 1.878222113638478658147514997025468E-1177 + 1955 9.39111056819239329073757498512734E-1178 4.69555528409619664536878749256367E-1178 + 1956 2.347777642048098322684393746281835E-1178 1.173888821024049161342196873140918E-1178 + 1957 5.86944410512024580671098436570459E-1179 2.934722052560122903355492182852295E-1179 + 1958 1.467361026280061451677746091426148E-1179 7.336805131400307258388730457130738E-1180 + 1959 3.668402565700153629194365228565369E-1180 1.834201282850076814597182614282685E-1180 + 1960 9.171006414250384072985913071413425E-1181 4.585503207125192036492956535706713E-1181 + 1961 2.292751603562596018246478267853357E-1181 1.146375801781298009123239133926678E-1181 + 1962 5.73187900890649004561619566963339E-1182 2.865939504453245022808097834816695E-1182 + 1963 1.432969752226622511404048917408348E-1182 7.164848761133112557020244587041738E-1183 + 1964 3.582424380566556278510122293520869E-1183 1.791212190283278139255061146760435E-1183 + 1965 8.956060951416390696275305733802175E-1184 4.478030475708195348137652866901088E-1184 + 1966 2.239015237854097674068826433450544E-1184 1.119507618927048837034413216725272E-1184 + 1967 5.59753809463524418517206608362636E-1185 2.79876904731762209258603304181318E-1185 + 1968 1.39938452365881104629301652090659E-1185 6.99692261829405523146508260453295E-1186 + 1969 3.498461309147027615732541302266475E-1186 1.749230654573513807866270651133238E-1186 + 1970 8.74615327286756903933135325566619E-1187 4.373076636433784519665676627833095E-1187 + 1971 2.186538318216892259832838313916548E-1187 1.093269159108446129916419156958274E-1187 + 1972 5.46634579554223064958209578479137E-1188 2.733172897771115324791047892395685E-1188 + 1973 1.366586448885557662395523946197843E-1188 6.832932244427788311977619730989213E-1189 + 1974 3.416466122213894155988809865494607E-1189 1.708233061106947077994404932747303E-1189 + 1975 8.541165305534735389972024663736515E-1190 4.270582652767367694986012331868258E-1190 + 1976 2.135291326383683847493006165934129E-1190 1.067645663191841923746503082967065E-1190 + 1977 5.338228315959209618732515414835325E-1191 2.669114157979604809366257707417663E-1191 + 1978 1.334557078989802404683128853708832E-1191 6.672785394949012023415644268544158E-1192 + 1979 3.336392697474506011707822134272079E-1192 1.668196348737253005853911067136040E-1192 + 1980 8.34098174368626502926955533568020E-1193 4.17049087184313251463477766784010E-1193 + 1981 2.08524543592156625731738883392005E-1193 1.042622717960783128658694416960025E-1193 + 1982 5.213113589803915643293472084800125E-1194 2.606556794901957821646736042400063E-1194 + 1983 1.303278397450978910823368021200032E-1194 6.516391987254894554116840106000158E-1195 + 1984 3.258195993627447277058420053000079E-1195 1.629097996813723638529210026500040E-1195 + 1985 8.14548998406861819264605013250020E-1196 4.07274499203430909632302506625010E-1196 + 1986 2.03637249601715454816151253312505E-1196 1.018186248008577274080756266562525E-1196 + 1987 5.090931240042886370403781332812625E-1197 2.545465620021443185201890666406313E-1197 + 1988 1.272732810010721592600945333203157E-1197 6.363664050053607963004726666015783E-1198 + 1989 3.181832025026803981502363333007892E-1198 1.590916012513401990751181666503946E-1198 + 1990 7.95458006256700995375590833251973E-1199 3.977290031283504976877954166259865E-1199 + 1991 1.988645015641752488438977083129933E-1199 9.943225078208762442194885415649663E-1200 + 1992 4.971612539104381221097442707824832E-1200 2.485806269552190610548721353912416E-1200 + 1993 1.242903134776095305274360676956208E-1200 6.21451567388047652637180338478104E-1201 + 1994 3.10725783694023826318590169239052E-1201 1.55362891847011913159295084619526E-1201 + 1995 7.7681445923505956579647542309763E-1202 3.88407229617529782898237711548815E-1202 + 1996 1.942036148087648914491188557744075E-1202 9.710180740438244572455942788720375E-1203 + 1997 4.855090370219122286227971394360188E-1203 2.427545185109561143113985697180094E-1203 + 1998 1.213772592554780571556992848590047E-1203 6.068862962773902857784964242950235E-1204 + 1999 3.034431481386951428892482121475118E-1204 1.517215740693475714446241060737559E-1204 + 2000 7.586078703467378572231205303687795E-1205 3.793039351733689286115602651843898E-1205 + 2001 1.896519675866844643057801325921949E-1205 9.482598379334223215289006629609745E-1206 + 2002 4.741299189667111607644503314804873E-1206 2.370649594833555803822251657402436E-1206 + 2003 1.185324797416777901911125828701218E-1206 5.92662398708388950955562914350609E-1207 + 2004 2.963311993541944754777814571753045E-1207 1.481655996770972377388907285876523E-1207 + 2005 7.408279983854861886944536429382615E-1208 3.704139991927430943472268214691308E-1208 + 2006 1.852069995963715471736134107345654E-1208 9.26034997981857735868067053672827E-1209 + 2007 4.630174989909288679340335268364135E-1209 2.315087494954644339670167634182068E-1209 + 2008 1.157543747477322169835083817091034E-1209 5.78771873738661084917541908545517E-1210 + 2009 2.893859368693305424587709542727585E-1210 1.446929684346652712293854771363793E-1210 + 2010 7.234648421733263561469273856818965E-1211 3.617324210866631780734636928409483E-1211 + 2011 1.808662105433315890367318464204742E-1211 9.043310527166579451836592321023708E-1212 + 2012 4.521655263583289725918296160511854E-1212 2.260827631791644862959148080255927E-1212 + 2013 1.130413815895822431479574040127964E-1212 5.652069079479112157397870200639818E-1213 + 2014 2.826034539739556078698935100319909E-1213 1.413017269869778039349467550159955E-1213 + 2015 7.065086349348890196747337750799775E-1214 3.532543174674445098373668875399888E-1214 + 2016 1.766271587337222549186834437699944E-1214 8.83135793668611274593417218849972E-1215 + 2017 4.41567896834305637296708609424986E-1215 2.20783948417152818648354304712493E-1215 + 2018 1.103919742085764093241771523562465E-1215 5.519598710428820466208857617812325E-1216 + 2019 2.759799355214410233104428808906163E-1216 1.379899677607205116552214404453081E-1216 + 2020 6.899498388036025582761072022265405E-1217 3.449749194018012791380536011132703E-1217 + 2021 1.724874597009006395690268005566352E-1217 8.624372985045031978451340027831758E-1218 + 2022 4.312186492522515989225670013915879E-1218 2.156093246261257994612835006957940E-1218 + 2023 1.078046623130628997306417503478970E-1218 5.39023311565314498653208751739485E-1219 + 2024 2.695116557826572493266043758697425E-1219 1.347558278913286246633021879348713E-1219 + 2025 6.737791394566431233165109396743565E-1220 3.368895697283215616582554698371783E-1220 + 2026 1.684447848641607808291277349185892E-1220 8.422239243208039041456386745929458E-1221 + 2027 4.211119621604019520728193372964729E-1221 2.105559810802009760364096686482365E-1221 + 2028 1.052779905401004880182048343241183E-1221 5.263899527005024400910241716205913E-1222 + 2029 2.631949763502512200455120858102957E-1222 1.315974881751256100227560429051478E-1222 + 2030 6.57987440875628050113780214525739E-1223 3.289937204378140250568901072628695E-1223 + 2031 1.644968602189070125284450536314348E-1223 8.224843010945350626422252681571738E-1224 + 2032 4.112421505472675313211126340785869E-1224 2.056210752736337656605563170392935E-1224 + 2033 1.028105376368168828302781585196468E-1224 5.140526881840844141513907925982338E-1225 + 2034 2.570263440920422070756953962991169E-1225 1.285131720460211035378476981495585E-1225 + 2035 6.425658602301055176892384907477925E-1226 3.212829301150527588446192453738963E-1226 + 2036 1.606414650575263794223096226869482E-1226 8.032073252876318971115481134347408E-1227 + 2037 4.016036626438159485557740567173704E-1227 2.008018313219079742778870283586852E-1227 + 2038 1.004009156609539871389435141793426E-1227 5.02004578304769935694717570896713E-1228 + 2039 2.510022891523849678473587854483565E-1228 1.255011445761924839236793927241783E-1228 + 2040 6.275057228809624196183969636208915E-1229 3.137528614404812098091984818104458E-1229 + 2041 1.568764307202406049045992409052229E-1229 7.843821536012030245229962045261145E-1230 + 2042 3.921910768006015122614981022630573E-1230 1.960955384003007561307490511315286E-1230 + 2043 9.80477692001503780653745255657643E-1231 4.902388460007518903268726278288215E-1231 + 2044 2.451194230003759451634363139144108E-1231 1.225597115001879725817181569572054E-1231 + 2045 6.12798557500939862908590784786027E-1232 3.063992787504699314542953923930135E-1232 + 2046 1.531996393752349657271476961965068E-1232 7.659981968761748286357384809825338E-1233 + 2047 3.829990984380874143178692404912669E-1233 1.914995492190437071589346202456335E-1233 + 2048 9.574977460952185357946731012281675E-1234 4.787488730476092678973365506140838E-1234 + 2049 2.393744365238046339486682753070419E-1234 1.196872182619023169743341376535210E-1234 + 2050 5.98436091309511584871670688267605E-1235 2.992180456547557924358353441338025E-1235 + 2051 1.496090228273778962179176720669013E-1235 7.480451141368894810895883603345063E-1236 + 2052 3.740225570684447405447941801672532E-1236 1.870112785342223702723970900836266E-1236 + 2053 9.35056392671111851361985450418133E-1237 4.675281963355559256809927252090665E-1237 + 2054 2.337640981677779628404963626045333E-1237 1.168820490838889814202481813022666E-1237 + 2055 5.84410245419444907101240906511333E-1238 2.922051227097224535506204532556665E-1238 + 2056 1.461025613548612267753102266278333E-1238 7.305128067743061338765511331391663E-1239 + 2057 3.652564033871530669382755665695832E-1239 1.826282016935765334691377832847916E-1239 + 2058 9.13141008467882667345688916423958E-1240 4.56570504233941333672844458211979E-1240 + 2059 2.282852521169706668364222291059895E-1240 1.141426260584853334182111145529948E-1240 + 2060 5.70713130292426667091055572764974E-1241 2.85356565146213333545527786382487E-1241 + 2061 1.426782825731066667727638931912435E-1241 7.133914128655333338638194659562175E-1242 + 2062 3.566957064327666669319097329781088E-1242 1.783478532163833334659548664890544E-1242 + 2063 8.91739266081916667329774332445272E-1243 4.45869633040958333664887166222636E-1243 + 2064 2.22934816520479166832443583111318E-1243 1.11467408260239583416221791555659E-1243 + 2065 5.57337041301197917081108957778295E-1244 2.786685206505989585405544788891475E-1244 + 2066 1.393342603252994792702772394445738E-1244 6.966713016264973963513861972228688E-1245 + 2067 3.483356508132486981756930986114344E-1245 1.741678254066243490878465493057172E-1245 + 2068 8.70839127033121745439232746528586E-1246 4.35419563516560872719616373264293E-1246 + 2069 2.177097817582804363598081866321465E-1246 1.088548908791402181799040933160733E-1246 + 2070 5.442744543957010908995204665803665E-1247 2.721372271978505454497602332901833E-1247 + 2071 1.360686135989252727248801166450917E-1247 6.803430679946263636244005832254583E-1248 + 2072 3.401715339973131818122002916127292E-1248 1.700857669986565909061001458063646E-1248 + 2073 8.50428834993282954530500729031823E-1249 4.252144174966414772652503645159115E-1249 + 2074 2.126072087483207386326251822579558E-1249 1.063036043741603693163125911289779E-1249 + 2075 5.315180218708018465815629556448895E-1250 2.657590109354009232907814778224448E-1250 + 2076 1.328795054677004616453907389112224E-1250 6.64397527338502308226953694556112E-1251 + 2077 3.32198763669251154113476847278056E-1251 1.66099381834625577056738423639028E-1251 + 2078 8.3049690917312788528369211819514E-1252 4.1524845458656394264184605909757E-1252 + 2079 2.07624227293281971320923029548785E-1252 1.038121136466409856604615147743925E-1252 + 2080 5.190605682332049283023075738719625E-1253 2.595302841166024641511537869359813E-1253 + 2081 1.297651420583012320755768934679907E-1253 6.488257102915061603778844673399533E-1254 + 2082 3.244128551457530801889422336699767E-1254 1.622064275728765400944711168349883E-1254 + 2083 8.110321378643827004723555841749415E-1255 4.055160689321913502361777920874708E-1255 + 2084 2.027580344660956751180888960437354E-1255 1.013790172330478375590444480218677E-1255 + 2085 5.068950861652391877952222401093385E-1256 2.534475430826195938976111200546693E-1256 + 2086 1.267237715413097969488055600273347E-1256 6.336188577065489847440278001366733E-1257 + 2087 3.168094288532744923720139000683367E-1257 1.584047144266372461860069500341683E-1257 + 2088 7.920235721331862309300347501708415E-1258 3.960117860665931154650173750854208E-1258 + 2089 1.980058930332965577325086875427104E-1258 9.90029465166482788662543437713552E-1259 + 2090 4.95014732583241394331271718856776E-1259 2.47507366291620697165635859428388E-1259 + 2091 1.23753683145810348582817929714194E-1259 6.1876841572905174291408964857097E-1260 + 2092 3.09384207864525871457044824285485E-1260 1.546921039322629357285224121427425E-1260 + 2093 7.734605196613146786426120607137125E-1261 3.867302598306573393213060303568563E-1261 + 2094 1.933651299153286696606530151784282E-1261 9.668256495766433483032650758921408E-1262 + 2095 4.834128247883216741516325379460704E-1262 2.417064123941608370758162689730352E-1262 + 2096 1.208532061970804185379081344865176E-1262 6.04266030985402092689540672432588E-1263 + 2097 3.02133015492701046344770336216294E-1263 1.51066507746350523172385168108147E-1263 + 2098 7.55332538731752615861925840540735E-1264 3.776662693658763079309629202703675E-1264 + 2099 1.888331346829381539654814601351838E-1264 9.441656734146907698274073006759188E-1265 + 2100 4.720828367073453849137036503379594E-1265 2.360414183536726924568518251689797E-1265 + 2101 1.180207091768363462284259125844899E-1265 5.901035458841817311421295629224493E-1266 + 2102 2.950517729420908655710647814612247E-1266 1.475258864710454327855323907306123E-1266 + 2103 7.376294323552271639276619536530615E-1267 3.688147161776135819638309768265308E-1267 + 2104 1.844073580888067909819154884132654E-1267 9.22036790444033954909577442066327E-1268 + 2105 4.610183952220169774547887210331635E-1268 2.305091976110084887273943605165818E-1268 + 2106 1.152545988055042443636971802582909E-1268 5.762729940275212218184859012914545E-1269 + 2107 2.881364970137606109092429506457273E-1269 1.440682485068803054546214753228636E-1269 + 2108 7.20341242534401527273107376614318E-1270 3.60170621267200763636553688307159E-1270 + 2109 1.800853106336003818182768441535795E-1270 9.004265531680019090913842207678975E-1271 + 2110 4.502132765840009545456921103839488E-1271 2.251066382920004772728460551919744E-1271 + 2111 1.125533191460002386364230275959872E-1271 5.62766595730001193182115137979936E-1272 + 2112 2.81383297865000596591057568989968E-1272 1.40691648932500298295528784494984E-1272 + 2113 7.0345824466250149147764392247492E-1273 3.5172912233125074573882196123746E-1273 + 2114 1.7586456116562537286941098061873E-1273 8.7932280582812686434705490309365E-1274 + 2115 4.39661402914063432173527451546825E-1274 2.198307014570317160867637257734125E-1274 + 2116 1.099153507285158580433818628867063E-1274 5.495767536425792902169093144335313E-1275 + 2117 2.747883768212896451084546572167657E-1275 1.373941884106448225542273286083828E-1275 + 2118 6.86970942053224112771136643041914E-1276 3.43485471026612056385568321520957E-1276 + 2119 1.717427355133060281927841607604785E-1276 8.587136775665301409639208038023925E-1277 + 2120 4.293568387832650704819604019011963E-1277 2.146784193916325352409802009505981E-1277 + 2121 1.073392096958162676204901004752991E-1277 5.366960484790813381024505023764953E-1278 + 2122 2.683480242395406690512252511882477E-1278 1.341740121197703345256126255941238E-1278 + 2123 6.70870060598851672628063127970619E-1279 3.354350302994258363140315639853095E-1279 + 2124 1.677175151497129181570157819926548E-1279 8.385875757485645907850789099632738E-1280 + 2125 4.192937878742822953925394549816369E-1280 2.096468939371411476962697274908185E-1280 + 2126 1.048234469685705738481348637454093E-1280 5.241172348428528692406743187270463E-1281 + 2127 2.620586174214264346203371593635232E-1281 1.310293087107132173101685796817616E-1281 + 2128 6.55146543553566086550842898408808E-1282 3.27573271776783043275421449204404E-1282 + 2129 1.63786635888391521637710724602202E-1282 8.1893317944195760818855362301101E-1283 + 2130 4.09466589720978804094276811505505E-1283 2.047332948604894020471384057527525E-1283 + 2131 1.023666474302447010235692028763763E-1283 5.118332371512235051178460143818813E-1284 + 2132 2.559166185756117525589230071909407E-1284 1.279583092878058762794615035954703E-1284 + 2133 6.397915464390293813973075179773515E-1285 3.198957732195146906986537589886758E-1285 + 2134 1.599478866097573453493268794943379E-1285 7.997394330487867267466343974716895E-1286 + 2135 3.998697165243933633733171987358448E-1286 1.999348582621966816866585993679224E-1286 + 2136 9.99674291310983408433292996839612E-1287 4.99837145655491704216646498419806E-1287 + 2137 2.49918572827745852108323249209903E-1287 1.249592864138729260541616246049515E-1287 + 2138 6.247964320693646302708081230247575E-1288 3.123982160346823151354040615123788E-1288 + 2139 1.561991080173411575677020307561894E-1288 7.80995540086705787838510153780947E-1289 + 2140 3.904977700433528939192550768904735E-1289 1.952488850216764469596275384452368E-1289 + 2141 9.76244425108382234798137692226184E-1290 4.88122212554191117399068846113092E-1290 + 2142 2.44061106277095558699534423056546E-1290 1.22030553138547779349767211528273E-1290 + 2143 6.10152765692738896748836057641365E-1291 3.050763828463694483744180288206825E-1291 + 2144 1.525381914231847241872090144103413E-1291 7.626909571159236209360450720517063E-1292 + 2145 3.813454785579618104680225360258532E-1292 1.906727392789809052340112680129266E-1292 + 2146 9.53363696394904526170056340064633E-1293 4.766818481974522630850281700323165E-1293 + 2147 2.383409240987261315425140850161583E-1293 1.191704620493630657712570425080791E-1293 + 2148 5.958523102468153288562852125403955E-1294 2.979261551234076644281426062701978E-1294 + 2149 1.489630775617038322140713031350989E-1294 7.448153878085191610703565156754945E-1295 + 2150 3.724076939042595805351782578377473E-1295 1.862038469521297902675891289188736E-1295 + 2151 9.31019234760648951337945644594368E-1296 4.65509617380324475668972822297184E-1296 + 2152 2.32754808690162237834486411148592E-1296 1.16377404345081118917243205574296E-1296 + 2153 5.8188702172540559458621602787148E-1297 2.9094351086270279729310801393574E-1297 + 2154 1.4547175543135139864655400696787E-1297 7.2735877715675699323277003483935E-1298 + 2155 3.63679388578378496616385017419675E-1298 1.818396942891892483081925087098375E-1298 + 2156 9.091984714459462415409625435491875E-1299 4.545992357229731207704812717745938E-1299 + 2157 2.272996178614865603852406358872969E-1299 1.136498089307432801926203179436485E-1299 + 2158 5.682490446537164009631015897182425E-1300 2.841245223268582004815507948591213E-1300 + 2159 1.420622611634291002407753974295607E-1300 7.103113058171455012038769871478033E-1301 + 2160 3.551556529085727506019384935739017E-1301 1.775778264542863753009692467869508E-1301 + 2161 8.87889132271431876504846233934754E-1302 4.43944566135715938252423116967377E-1302 + 2162 2.219722830678579691262115584836885E-1302 1.109861415339289845631057792418443E-1302 + 2163 5.549307076696449228155288962092215E-1303 2.774653538348224614077644481046108E-1303 + 2164 1.387326769174112307038822240523054E-1303 6.93663384587056153519411120261527E-1304 + 2165 3.468316922935280767597055601307635E-1304 1.734158461467640383798527800653818E-1304 + 2166 8.67079230733820191899263900326909E-1305 4.335396153669100959496319501634545E-1305 + 2167 2.167698076834550479748159750817273E-1305 1.083849038417275239874079875408636E-1305 + 2168 5.41924519208637619937039937704318E-1306 2.70962259604318809968519968852159E-1306 + 2169 1.354811298021594049842599844260795E-1306 6.774056490107970249212999221303975E-1307 + 2170 3.387028245053985124606499610651988E-1307 1.693514122526992562303249805325994E-1307 + 2171 8.46757061263496281151624902662997E-1308 4.233785306317481405758124513314985E-1308 + 2172 2.116892653158740702879062256657493E-1308 1.058446326579370351439531128328746E-1308 + 2173 5.29223163289685175719765564164373E-1309 2.646115816448425878598827820821865E-1309 + 2174 1.323057908224212939299413910410933E-1309 6.615289541121064696497069552054663E-1310 + 2175 3.307644770560532348248534776027332E-1310 1.653822385280266174124267388013666E-1310 + 2176 8.26911192640133087062133694006833E-1311 4.134555963200665435310668470034165E-1311 + 2177 2.067277981600332717655334235017083E-1311 1.033638990800166358827667117508541E-1311 + 2178 5.168194954000831794138335587542705E-1312 2.584097477000415897069167793771353E-1312 + 2179 1.292048738500207948534583896885677E-1312 6.460243692501039742672919484428383E-1313 + 2180 3.230121846250519871336459742214192E-1313 1.615060923125259935668229871107096E-1313 + 2181 8.07530461562629967834114935553548E-1314 4.03765230781314983917057467776774E-1314 + 2182 2.01882615390657491958528733888387E-1314 1.009413076953287459792643669441935E-1314 + 2183 5.047065384766437298963218347209675E-1315 2.523532692383218649481609173604838E-1315 + 2184 1.261766346191609324740804586802419E-1315 6.308831730958046623704022934012095E-1316 + 2185 3.154415865479023311852011467006048E-1316 1.577207932739511655926005733503024E-1316 + 2186 7.88603966369755827963002866751512E-1317 3.94301983184877913981501433375756E-1317 + 2187 1.97150991592438956990750716687878E-1317 9.8575495796219478495375358343939E-1318 + 2188 4.92877478981097392476876791719695E-1318 2.464387394905486962384383958598475E-1318 + 2189 1.232193697452743481192191979299238E-1318 6.160968487263717405960959896496188E-1319 + 2190 3.080484243631858702980479948248094E-1319 1.540242121815929351490239974124047E-1319 + 2191 7.701210609079646757451199870620235E-1320 3.850605304539823378725599935310118E-1320 + 2192 1.925302652269911689362799967655059E-1320 9.626513261349558446813999838275295E-1321 + 2193 4.813256630674779223406999919137648E-1321 2.406628315337389611703499959568824E-1321 + 2194 1.203314157668694805851749979784412E-1321 6.01657078834347402925874989892206E-1322 + 2195 3.00828539417173701462937494946103E-1322 1.504142697085868507314687474730515E-1322 + 2196 7.520713485429342536573437373652575E-1323 3.760356742714671268286718686826288E-1323 + 2197 1.880178371357335634143359343413144E-1323 9.40089185678667817071679671706572E-1324 + 2198 4.70044592839333908535839835853286E-1324 2.35022296419666954267919917926643E-1324 + 2199 1.175111482098334771339599589633215E-1324 5.875557410491673856697997948166075E-1325 + 2200 2.937778705245836928348998974083038E-1325 1.468889352622918464174499487041519E-1325 + 2201 7.344446763114592320872497435207595E-1326 3.672223381557296160436248717603798E-1326 + 2202 1.836111690778648080218124358801899E-1326 9.180558453893240401090621794009495E-1327 + 2203 4.590279226946620200545310897004748E-1327 2.295139613473310100272655448502374E-1327 + 2204 1.147569806736655050136327724251187E-1327 5.737849033683275250681638621255935E-1328 + 2205 2.868924516841637625340819310627968E-1328 1.434462258420818812670409655313984E-1328 + 2206 7.17231129210409406335204827656992E-1329 3.58615564605204703167602413828496E-1329 + 2207 1.79307782302602351583801206914248E-1329 8.9653891151301175791900603457124E-1330 + 2208 4.4826945575650587895950301728562E-1330 2.2413472787825293947975150864281E-1330 + 2209 1.12067363939126469739875754321405E-1330 5.60336819695632348699378771607025E-1331 + 2210 2.801684098478161743496893858035125E-1331 1.400842049239080871748446929017563E-1331 + 2211 7.004210246195404358742234645087815E-1332 3.502105123097702179371117322543908E-1332 + 2212 1.751052561548851089685558661271954E-1332 8.75526280774425544842779330635977E-1333 + 2213 4.377631403872127724213896653179885E-1333 2.188815701936063862106948326589943E-1333 + 2214 1.094407850968031931053474163294972E-1333 5.472039254840159655267370816474858E-1334 + 2215 2.736019627420079827633685408237429E-1334 1.368009813710039913816842704118715E-1334 + 2216 6.840049068550199569084213520593575E-1335 3.420024534275099784542106760296788E-1335 + 2217 1.710012267137549892271053380148394E-1335 8.55006133568774946135526690074197E-1336 + 2218 4.275030667843874730677633450370985E-1336 2.137515333921937365338816725185493E-1336 + 2219 1.068757666960968682669408362592747E-1336 5.343788334804843413347041812963733E-1337 + 2220 2.671894167402421706673520906481867E-1337 1.335947083701210853336760453240933E-1337 + 2221 6.679735418506054266683802266204665E-1338 3.339867709253027133341901133102333E-1338 + 2222 1.669933854626513566670950566551167E-1338 8.349669273132567833354752832755833E-1339 + 2223 4.174834636566283916677376416377917E-1339 2.087417318283141958338688208188958E-1339 + 2224 1.043708659141570979169344104094479E-1339 5.218543295707854895846720520472395E-1340 + 2225 2.609271647853927447923360260236198E-1340 1.304635823926963723961680130118099E-1340 + 2226 6.523179119634818619808400650590495E-1341 3.261589559817409309904200325295248E-1341 + 2227 1.630794779908704654952100162647624E-1341 8.15397389954352327476050081323812E-1342 + 2228 4.07698694977176163738025040661906E-1342 2.03849347488588081869012520330953E-1342 + 2229 1.019246737442940409345062601654765E-1342 5.096233687214702046725313008273825E-1343 + 2230 2.548116843607351023362656504136913E-1343 1.274058421803675511681328252068456E-1343 + 2231 6.37029210901837755840664126034228E-1344 3.18514605450918877920332063017114E-1344 + 2232 1.59257302725459438960166031508557E-1344 7.96286513627297194800830157542785E-1345 + 2233 3.981432568136485974004150787713925E-1345 1.990716284068242987002075393856963E-1345 + 2234 9.953581420341214935010376969284815E-1346 4.976790710170607467505188484642408E-1346 + 2235 2.488395355085303733752594242321204E-1346 1.244197677542651866876297121160602E-1346 + 2236 6.22098838771325933438148560580301E-1347 3.110494193856629667190742802901505E-1347 + 2237 1.555247096928314833595371401450753E-1347 7.776235484641574167976857007253763E-1348 + 2238 3.888117742320787083988428503626882E-1348 1.944058871160393541994214251813441E-1348 + 2239 9.720294355801967709971071259067205E-1349 4.860147177900983854985535629533603E-1349 + 2240 2.430073588950491927492767814766802E-1349 1.215036794475245963746383907383401E-1349 + 2241 6.075183972376229818731919536917005E-1350 3.037591986188114909365959768458503E-1350 + 2242 1.518795993094057454682979884229252E-1350 7.593979965470287273414899421146258E-1351 + 2243 3.796989982735143636707449710573129E-1351 1.898494991367571818353724855286565E-1351 + 2244 9.492474956837859091768624276432825E-1352 4.746237478418929545884312138216413E-1352 + 2245 2.373118739209464772942156069108207E-1352 1.186559369604732386471078034554103E-1352 + 2246 5.932796848023661932355390172770515E-1353 2.966398424011830966177695086385258E-1353 + 2247 1.483199212005915483088847543192629E-1353 7.415996060029577415444237715963145E-1354 + 2248 3.707998030014788707722118857981573E-1354 1.853999015007394353861059428990786E-1354 + 2249 9.26999507503697176930529714495393E-1355 4.634997537518485884652648572476965E-1355 + 2250 2.317498768759242942326324286238483E-1355 1.158749384379621471163162143119241E-1355 + 2251 5.793746921898107355815810715596205E-1356 2.896873460949053677907905357798103E-1356 + 2252 1.448436730474526838953952678899052E-1356 7.242183652372634194769763394495258E-1357 + 2253 3.621091826186317097384881697247629E-1357 1.810545913093158548692440848623815E-1357 + 2254 9.052729565465792743462204243119075E-1358 4.526364782732896371731102121559538E-1358 + 2255 2.263182391366448185865551060779769E-1358 1.131591195683224092932775530389885E-1358 + 2256 5.657955978416120464663877651949425E-1359 2.828977989208060232331938825974713E-1359 + 2257 1.414488994604030116165969412987357E-1359 7.072444973020150580829847064936783E-1360 + 2258 3.536222486510075290414923532468392E-1360 1.768111243255037645207461766234196E-1360 + 2259 8.84055621627518822603730883117098E-1361 4.42027810813759411301865441558549E-1361 + 2260 2.210139054068797056509327207792745E-1361 1.105069527034398528254663603896373E-1361 + 2261 5.525347635171992641273318019481865E-1362 2.762673817585996320636659009740933E-1362 + 2262 1.381336908792998160318329504870467E-1362 6.906684543964990801591647524352333E-1363 + 2263 3.453342271982495400795823762176167E-1363 1.726671135991247700397911881088083E-1363 + 2264 8.633355679956238501989559405440415E-1364 4.316677839978119250994779702720208E-1364 + 2265 2.158338919989059625497389851360104E-1364 1.079169459994529812748694925680052E-1364 + 2266 5.39584729997264906374347462840026E-1365 2.69792364998632453187173731420013E-1365 + 2267 1.348961824993162265935868657100065E-1365 6.744809124965811329679343285500325E-1366 + 2268 3.372404562482905664839671642750163E-1366 1.686202281241452832419835821375081E-1366 + 2269 8.431011406207264162099179106875405E-1367 4.215505703103632081049589553437703E-1367 + 2270 2.107752851551816040524794776718852E-1367 1.053876425775908020262397388359426E-1367 + 2271 5.26938212887954010131198694179713E-1368 2.634691064439770050655993470898565E-1368 + 2272 1.317345532219885025327996735449283E-1368 6.586727661099425126639983677246413E-1369 + 2273 3.293363830549712563319991838623207E-1369 1.646681915274856281659995919311603E-1369 + 2274 8.233409576374281408299979596558015E-1370 4.116704788187140704149989798279008E-1370 + 2275 2.058352394093570352074994899139504E-1370 1.029176197046785176037497449569752E-1370 + 2276 5.14588098523392588018748724784876E-1371 2.57294049261696294009374362392438E-1371 + 2277 1.28647024630848147004687181196219E-1371 6.43235123154240735023435905981095E-1372 + 2278 3.216175615771203675117179529905475E-1372 1.608087807885601837558589764952738E-1372 + 2279 8.04043903942800918779294882476369E-1373 4.020219519714004593896474412381845E-1373 + 2280 2.010109759857002296948237206190923E-1373 1.005054879928501148474118603095461E-1373 + 2281 5.025274399642505742370593015477305E-1374 2.512637199821252871185296507738653E-1374 + 2282 1.256318599910626435592648253869327E-1374 6.281592999553132177963241269346633E-1375 + 2283 3.140796499776566088981620634673317E-1375 1.570398249888283044490810317336658E-1375 + 2284 7.85199124944141522245405158668329E-1376 3.925995624720707611227025793341645E-1376 + 2285 1.962997812360353805613512896670823E-1376 9.814989061801769028067564483354113E-1377 + 2286 4.907494530900884514033782241677057E-1377 2.453747265450442257016891120838528E-1377 + 2287 1.226873632725221128508445560419264E-1377 6.13436816362610564254222780209632E-1378 + 2288 3.06718408181305282127111390104816E-1378 1.53359204090652641063555695052408E-1378 + 2289 7.6679602045326320531777847526204E-1379 3.8339801022663160265888923763102E-1379 + 2290 1.9169900511331580132944461881551E-1379 9.5849502556657900664722309407755E-1380 + 2291 4.79247512783289503323611547038775E-1380 2.396237563916447516618057735193875E-1380 + 2292 1.198118781958223758309028867596938E-1380 5.990593909791118791545144337984688E-1381 + 2293 2.995296954895559395772572168992344E-1381 1.497648477447779697886286084496172E-1381 + 2294 7.48824238723889848943143042248086E-1382 3.74412119361944924471571521124043E-1382 + 2295 1.872060596809724622357857605620215E-1382 9.360302984048623111789288028101075E-1383 + 2296 4.680151492024311555894644014050538E-1383 2.340075746012155777947322007025269E-1383 + 2297 1.170037873006077888973661003512635E-1383 5.850189365030389444868305017563173E-1384 + 2298 2.925094682515194722434152508781587E-1384 1.462547341257597361217076254390793E-1384 + 2299 7.312736706287986806085381271953965E-1385 3.656368353143993403042690635976983E-1385 + 2300 1.828184176571996701521345317988492E-1385 9.140920882859983507606726589942458E-1386 + 2301 4.570460441429991753803363294971229E-1386 2.285230220714995876901681647485615E-1386 + 2302 1.142615110357497938450840823742808E-1386 5.713075551787489692254204118714038E-1387 + 2303 2.856537775893744846127102059357019E-1387 1.428268887946872423063551029678510E-1387 + 2304 7.14134443973436211531775514839255E-1388 3.570672219867181057658877574196275E-1388 + 2305 1.785336109933590528829438787098138E-1388 8.926680549667952644147193935490688E-1389 + 2306 4.463340274833976322073596967745344E-1389 2.231670137416988161036798483872672E-1389 + 2307 1.115835068708494080518399241936336E-1389 5.57917534354247040259199620968168E-1390 + 2308 2.78958767177123520129599810484084E-1390 1.39479383588561760064799905242042E-1390 + 2309 6.9739691794280880032399952621021E-1391 3.48698458971404400161999763105105E-1391 + 2310 1.743492294857022000809998815525525E-1391 8.717461474285110004049994077627625E-1392 + 2311 4.358730737142555002024997038813813E-1392 2.179365368571277501012498519406906E-1392 + 2312 1.089682684285638750506249259703453E-1392 5.448413421428193752531246298517265E-1393 + 2313 2.724206710714096876265623149258633E-1393 1.362103355357048438132811574629316E-1393 + 2314 6.81051677678524219066405787314658E-1394 3.40525838839262109533202893657329E-1394 + 2315 1.702629194196310547666014468286645E-1394 8.513145970981552738330072341433225E-1395 + 2316 4.256572985490776369165036170716613E-1395 2.128286492745388184582518085358306E-1395 + 2317 1.064143246372694092291259042679153E-1395 5.320716231863470461456295213395765E-1396 + 2318 2.660358115931735230728147606697883E-1396 1.330179057965867615364073803348941E-1396 + 2319 6.650895289829338076820369016744705E-1397 3.325447644914669038410184508372353E-1397 + 2320 1.662723822457334519205092254186177E-1397 8.313619112286672596025461270930883E-1398 + 2321 4.156809556143336298012730635465442E-1398 2.078404778071668149006365317732721E-1398 + 2322 1.039202389035834074503182658866361E-1398 5.196011945179170372515913294331803E-1399 + 2323 2.598005972589585186257956647165902E-1399 1.299002986294792593128978323582951E-1399 + 2324 6.495014931473962965644891617914755E-1400 3.247507465736981482822445808957378E-1400 + 2325 1.623753732868490741411222904478689E-1400 8.118768664342453707056114522393445E-1401 + 2326 4.059384332171226853528057261196723E-1401 2.029692166085613426764028630598361E-1401 + 2327 1.014846083042806713382014315299181E-1401 5.074230415214033566910071576495903E-1402 + 2328 2.537115207607016783455035788247952E-1402 1.268557603803508391727517894123976E-1402 + 2329 6.34278801901754195863758947061988E-1403 3.17139400950877097931879473530994E-1403 + 2330 1.58569700475438548965939736765497E-1403 7.92848502377192744829698683827485E-1404 + 2331 3.964242511885963724148493419137425E-1404 1.982121255942981862074246709568713E-1404 + 2332 9.910606279714909310371233547843565E-1405 4.955303139857454655185616773921783E-1405 + 2333 2.477651569928727327592808386960892E-1405 1.238825784964363663796404193480446E-1405 + 2334 6.19412892482181831898202096740223E-1406 3.097064462410909159491010483701115E-1406 + 2335 1.548532231205454579745505241850558E-1406 7.742661156027272898727526209252788E-1407 + 2336 3.871330578013636449363763104626394E-1407 1.935665289006818224681881552313197E-1407 + 2337 9.678326445034091123409407761565985E-1408 4.839163222517045561704703880782993E-1408 + 2338 2.419581611258522780852351940391497E-1408 1.209790805629261390426175970195748E-1408 + 2339 6.04895402814630695213087985097874E-1409 3.02447701407315347606543992548937E-1409 + 2340 1.512238507036576738032719962744685E-1409 7.561192535182883690163599813723425E-1410 + 2341 3.780596267591441845081799906861713E-1410 1.890298133795720922540899953430856E-1410 + 2342 9.45149066897860461270449976715428E-1411 4.72574533448930230635224988357714E-1411 + 2343 2.36287266724465115317612494178857E-1411 1.181436333622325576588062470894285E-1411 + 2344 5.907181668111627882940312354471425E-1412 2.953590834055813941470156177235713E-1412 + 2345 1.476795417027906970735078088617857E-1412 7.383977085139534853675390443089283E-1413 + 2346 3.691988542569767426837695221544642E-1413 1.845994271284883713418847610772321E-1413 + 2347 9.229971356424418567094238053861605E-1414 4.614985678212209283547119026930803E-1414 + 2348 2.307492839106104641773559513465402E-1414 1.153746419553052320886779756732701E-1414 + 2349 5.768732097765261604433898783663505E-1415 2.884366048882630802216949391831753E-1415 + 2350 1.442183024441315401108474695915877E-1415 7.210915122206577005542373479579383E-1416 + 2351 3.605457561103288502771186739789692E-1416 1.802728780551644251385593369894846E-1416 + 2352 9.01364390275822125692796684947423E-1417 4.506821951379110628463983424737115E-1417 + 2353 2.253410975689555314231991712368558E-1417 1.126705487844777657115995856184279E-1417 + 2354 5.633527439223888285579979280921395E-1418 2.816763719611944142789989640460698E-1418 + 2355 1.408381859805972071394994820230349E-1418 7.041909299029860356974974101151745E-1419 + 2356 3.520954649514930178487487050575873E-1419 1.760477324757465089243743525287936E-1419 + 2357 8.80238662378732544621871762643968E-1420 4.40119331189366272310935881321984E-1420 + 2358 2.20059665594683136155467940660992E-1420 1.10029832797341568077733970330496E-1420 + 2359 5.5014916398670784038866985165248E-1421 2.7507458199335392019433492582624E-1421 + 2360 1.3753729099667696009716746291312E-1421 6.876864549833848004858373145656E-1422 + 2361 3.438432274916924002429186572828E-1422 1.719216137458462001214593286414E-1422 + 2362 8.59608068729231000607296643207E-1423 4.298040343646155003036483216035E-1423 + 2363 2.1490201718230775015182416080175E-1423 1.07451008591153875075912080400875E-1423 + 2364 5.37255042955769375379560402004375E-1424 2.686275214778846876897802010021875E-1424 + 2365 1.343137607389423438448901005010938E-1424 6.715688036947117192244505025054688E-1425 + 2366 3.357844018473558596122252512527344E-1425 1.678922009236779298061126256263672E-1425 + 2367 8.39461004618389649030563128131836E-1426 4.19730502309194824515281564065918E-1426 + 2368 2.09865251154597412257640782032959E-1426 1.049326255772987061288203910164795E-1426 + 2369 5.246631278864935306441019550823975E-1427 2.623315639432467653220509775411988E-1427 + 2370 1.311657819716233826610254887705994E-1427 6.55828909858116913305127443852997E-1428 + 2371 3.279144549290584566525637219264985E-1428 1.639572274645292283262818609632493E-1428 + 2372 8.197861373226461416314093048162465E-1429 4.098930686613230708157046524081233E-1429 + 2373 2.049465343306615354078523262040617E-1429 1.024732671653307677039261631020308E-1429 + 2374 5.12366335826653838519630815510154E-1430 2.56183167913326919259815407755077E-1430 + 2375 1.280915839566634596299077038775385E-1430 6.404579197833172981495385193876925E-1431 + 2376 3.202289598916586490747692596938463E-1431 1.601144799458293245373846298469231E-1431 + 2377 8.005723997291466226869231492346155E-1432 4.002861998645733113434615746173078E-1432 + 2378 2.001430999322866556717307873086539E-1432 1.000715499661433278358653936543270E-1432 + 2379 5.00357749830716639179326968271635E-1433 2.501788749153583195896634841358175E-1433 + 2380 1.250894374576791597948317420679088E-1433 6.254471872883957989741587103395438E-1434 + 2381 3.127235936441978994870793551697719E-1434 1.563617968220989497435396775848860E-1434 + 2382 7.81808984110494748717698387924430E-1435 3.90904492055247374358849193962215E-1435 + 2383 1.954522460276236871794245969811075E-1435 9.772612301381184358971229849055375E-1436 + 2384 4.886306150690592179485614924527688E-1436 2.443153075345296089742807462263844E-1436 + 2385 1.221576537672648044871403731131922E-1436 6.10788268836324022435701865565961E-1437 + 2386 3.053941344181620112178509327829805E-1437 1.526970672090810056089254663914903E-1437 + 2387 7.634853360454050280446273319574515E-1438 3.817426680227025140223136659787258E-1438 + 2388 1.908713340113512570111568329893629E-1438 9.543566700567562850557841649468145E-1439 + 2389 4.771783350283781425278920824734073E-1439 2.385891675141890712639460412367036E-1439 + 2390 1.192945837570945356319730206183518E-1439 5.96472918785472678159865103091759E-1440 + 2391 2.982364593927363390799325515458795E-1440 1.491182296963681695399662757729398E-1440 + 2392 7.45591148481840847699831378864699E-1441 3.727955742409204238499156894323495E-1441 + 2393 1.863977871204602119249578447161748E-1441 9.319889356023010596247892235808738E-1442 + 2394 4.659944678011505298123946117904369E-1442 2.329972339005752649061973058952185E-1442 + 2395 1.164986169502876324530986529476093E-1442 5.824930847514381622654932647380463E-1443 + 2396 2.912465423757190811327466323690232E-1443 1.456232711878595405663733161845116E-1443 + 2397 7.28116355939297702831866580922558E-1444 3.64058177969648851415933290461279E-1444 + 2398 1.820290889848244257079666452306395E-1444 9.101454449241221285398332261531975E-1445 + 2399 4.550727224620610642699166130765988E-1445 2.275363612310305321349583065382994E-1445 + 2400 1.137681806155152660674791532691497E-1445 5.688409030775763303373957663457485E-1446 + 2401 2.844204515387881651686978831728743E-1446 1.422102257693940825843489415864371E-1446 + 2402 7.110511288469704129217447079321855E-1447 3.555255644234852064608723539660928E-1447 + 2403 1.777627822117426032304361769830464E-1447 8.88813911058713016152180884915232E-1448 + 2404 4.44406955529356508076090442457616E-1448 2.22203477764678254038045221228808E-1448 + 2405 1.11101738882339127019022610614404E-1448 5.5550869441169563509511305307202E-1449 + 2406 2.7775434720584781754755652653601E-1449 1.38877173602923908773778263268005E-1449 + 2407 6.94385868014619543868891316340025E-1450 3.471929340073097719344456581700125E-1450 + 2408 1.735964670036548859672228290850063E-1450 8.679823350182744298361141454250313E-1451 + 2409 4.339911675091372149180570727125157E-1451 2.169955837545686074590285363562578E-1451 + 2410 1.084977918772843037295142681781289E-1451 5.424889593864215186475713408906445E-1452 + 2411 2.712444796932107593237856704453223E-1452 1.356222398466053796618928352226611E-1452 + 2412 6.781111992330268983094641761133055E-1453 3.390555996165134491547320880566528E-1453 + 2413 1.695277998082567245773660440283264E-1453 8.47638999041283622886830220141632E-1454 + 2414 4.23819499520641811443415110070816E-1454 2.11909749760320905721707555035408E-1454 + 2415 1.05954874880160452860853777517704E-1454 5.2977437440080226430426888758852E-1455 + 2416 2.6488718720040113215213444379426E-1455 1.3244359360020056607606722189713E-1455 + 2417 6.6221796800100283038033610948565E-1456 3.31108984000501415190168054742825E-1456 + 2418 1.655544920002507075950840273714125E-1456 8.277724600012535379754201368570625E-1457 + 2419 4.138862300006267689877100684285313E-1457 2.069431150003133844938550342142656E-1457 + 2420 1.034715575001566922469275171071328E-1457 5.17357787500783461234637585535664E-1458 + 2421 2.58678893750391730617318792767832E-1458 1.29339446875195865308659396383916E-1458 + 2422 6.4669723437597932654329698191958E-1459 3.2334861718798966327164849095979E-1459 + 2423 1.61674308593994831635824245479895E-1459 8.08371542969974158179121227399475E-1460 + 2424 4.041857714849870790895606136997375E-1460 2.020928857424935395447803068498688E-1460 + 2425 1.010464428712467697723901534249344E-1460 5.05232214356233848861950767124672E-1461 + 2426 2.52616107178116924430975383562336E-1461 1.26308053589058462215487691781168E-1461 + 2427 6.3154026794529231107743845890584E-1462 3.1577013397264615553871922945292E-1462 + 2428 1.5788506698632307776935961472646E-1462 7.894253349316153888467980736323E-1463 + 2429 3.9471266746580769442339903681615E-1463 1.97356333732903847211699518408075E-1463 + 2430 9.86781668664519236058497592040375E-1464 4.933908343322596180292487960201875E-1464 + 2431 2.466954171661298090146243980100938E-1464 1.233477085830649045073121990050469E-1464 + 2432 6.167385429153245225365609950252345E-1465 3.083692714576622612682804975126173E-1465 + 2433 1.541846357288311306341402487563087E-1465 7.709231786441556531707012437815433E-1466 + 2434 3.854615893220778265853506218907717E-1466 1.927307946610389132926753109453858E-1466 + 2435 9.63653973305194566463376554726929E-1467 4.818269866525972832316882773634645E-1467 + 2436 2.409134933262986416158441386817323E-1467 1.204567466631493208079220693408661E-1467 + 2437 6.022837333157466040396103467043305E-1468 3.011418666578733020198051733521653E-1468 + 2438 1.505709333289366510099025866760827E-1468 7.528546666446832550495129333804133E-1469 + 2439 3.764273333223416275247564666902067E-1469 1.882136666611708137623782333451033E-1469 + 2440 9.410683333058540688118911667255165E-1470 4.705341666529270344059455833627583E-1470 + 2441 2.352670833264635172029727916813792E-1470 1.176335416632317586014863958406896E-1470 + 2442 5.88167708316158793007431979203448E-1471 2.94083854158079396503715989601724E-1471 + 2443 1.47041927079039698251857994800862E-1471 7.3520963539519849125928997400431E-1472 + 2444 3.67604817697599245629644987002155E-1472 1.838024088487996228148224935010775E-1472 + 2445 9.190120442439981140741124675053875E-1473 4.595060221219990570370562337526938E-1473 + 2446 2.297530110609995285185281168763469E-1473 1.148765055304997642592640584381735E-1473 + 2447 5.743825276524988212963202921908675E-1474 2.871912638262494106481601460954338E-1474 + 2448 1.435956319131247053240800730477169E-1474 7.179781595656235266204003652385845E-1475 + 2449 3.589890797828117633102001826192923E-1475 1.794945398914058816551000913096461E-1475 + 2450 8.974726994570294082755004565482305E-1476 4.487363497285147041377502282741153E-1476 + 2451 2.243681748642573520688751141370577E-1476 1.121840874321286760344375570685288E-1476 + 2452 5.60920437160643380172187785342644E-1477 2.80460218580321690086093892671322E-1477 + 2453 1.40230109290160845043046946335661E-1477 7.01150546450804225215234731678305E-1478 + 2454 3.505752732254021126076173658391525E-1478 1.752876366127010563038086829195763E-1478 + 2455 8.764381830635052815190434145978815E-1479 4.382190915317526407595217072989408E-1479 + 2456 2.191095457658763203797608536494704E-1479 1.095547728829381601898804268247352E-1479 + 2457 5.47773864414690800949402134123676E-1480 2.73886932207345400474701067061838E-1480 + 2458 1.36943466103672700237350533530919E-1480 6.84717330518363501186752667654595E-1481 + 2459 3.423586652591817505933763338272975E-1481 1.711793326295908752966881669136488E-1481 + 2460 8.55896663147954376483440834568244E-1482 4.27948331573977188241720417284122E-1482 + 2461 2.13974165786988594120860208642061E-1482 1.069870828934942970604301043210305E-1482 + 2462 5.349354144674714853021505216051525E-1483 2.674677072337357426510752608025763E-1483 + 2463 1.337338536168678713255376304012882E-1483 6.686692680843393566276881520064408E-1484 + 2464 3.343346340421696783138440760032204E-1484 1.671673170210848391569220380016102E-1484 + 2465 8.35836585105424195784610190008051E-1485 4.179182925527120978923050950040255E-1485 + 2466 2.089591462763560489461525475020128E-1485 1.044795731381780244730762737510064E-1485 + 2467 5.22397865690890122365381368755032E-1486 2.61198932845445061182690684377516E-1486 + 2468 1.30599466422722530591345342188758E-1486 6.5299733211361265295672671094379E-1487 + 2469 3.26498666056806326478363355471895E-1487 1.632493330284031632391816777359475E-1487 + 2470 8.162466651420158161959083886797375E-1488 4.081233325710079080979541943398688E-1488 + 2471 2.040616662855039540489770971699344E-1488 1.020308331427519770244885485849672E-1488 + 2472 5.10154165713759885122442742924836E-1489 2.55077082856879942561221371462418E-1489 + 2473 1.27538541428439971280610685731209E-1489 6.37692707142199856403053428656045E-1490 + 2474 3.188463535710999282015267143280225E-1490 1.594231767855499641007633571640113E-1490 + 2475 7.971158839277498205038167858200565E-1491 3.985579419638749102519083929100283E-1491 + 2476 1.992789709819374551259541964550142E-1491 9.963948549096872756297709822750708E-1492 + 2477 4.981974274548436378148854911375354E-1492 2.490987137274218189074427455687677E-1492 + 2478 1.245493568637109094537213727843839E-1492 6.227467843185545472686068639219193E-1493 + 2479 3.113733921592772736343034319609597E-1493 1.556866960796386368171517159804798E-1493 + 2480 7.78433480398193184085758579902399E-1494 3.892167401990965920428792899511995E-1494 + 2481 1.946083700995482960214396449755998E-1494 9.730418504977414801071982248779988E-1495 + 2482 4.865209252488707400535991124389994E-1495 2.432604626244353700267995562194997E-1495 + 2483 1.216302313122176850133997781097499E-1495 6.081511565610884250669988905487493E-1496 + 2484 3.040755782805442125334994452743747E-1496 1.520377891402721062667497226371873E-1496 + 2485 7.601889457013605313337486131859365E-1497 3.800944728506802656668743065929683E-1497 + 2486 1.900472364253401328334371532964842E-1497 9.502361821267006641671857664824208E-1498 + 2487 4.751180910633503320835928832412104E-1498 2.375590455316751660417964416206052E-1498 + 2488 1.187795227658375830208982208103026E-1498 5.93897613829187915104491104051513E-1499 + 2489 2.969488069145939575522455520257565E-1499 1.484744034572969787761227760128783E-1499 + 2490 7.423720172864848938806138800643915E-1500 3.711860086432424469403069400321958E-1500 + 2491 1.855930043216212234701534700160979E-1500 9.279650216081061173507673500804895E-1501 + 2492 4.639825108040530586753836750402448E-1501 2.319912554020265293376918375201224E-1501 + 2493 1.159956277010132646688459187600612E-1501 5.79978138505066323344229593800306E-1502 + 2494 2.89989069252533161672114796900153E-1502 1.449945346262665808360573984500765E-1502 + 2495 7.249726731313329041802869922503825E-1503 3.624863365656664520901434961251913E-1503 + 2496 1.812431682828332260450717480625957E-1503 9.062158414141661302253587403129783E-1504 + 2497 4.531079207070830651126793701564892E-1504 2.265539603535415325563396850782446E-1504 + 2498 1.132769801767707662781698425391223E-1504 5.663849008838538313908492126956115E-1505 + 2499 2.831924504419269156954246063478058E-1505 1.415962252209634578477123031739029E-1505 + 2500 7.079811261048172892385615158695145E-1506 3.539905630524086446192807579347573E-1506 + 2501 1.769952815262043223096403789673787E-1506 8.849764076310216115482018948368933E-1507 + 2502 4.424882038155108057741009474184467E-1507 2.212441019077554028870504737092233E-1507 + 2503 1.106220509538777014435252368546117E-1507 5.531102547693885072176261842730583E-1508 + 2504 2.765551273846942536088130921365292E-1508 1.382775636923471268044065460682646E-1508 + 2505 6.91387818461735634022032730341323E-1509 3.456939092308678170110163651706615E-1509 + 2506 1.728469546154339085055081825853308E-1509 8.642347730771695425275409129266538E-1510 + 2507 4.321173865385847712637704564633269E-1510 2.160586932692923856318852282316635E-1510 + 2508 1.080293466346461928159426141158318E-1510 5.401467331732309640797130705791588E-1511 + 2509 2.700733665866154820398565352895794E-1511 1.350366832933077410199282676447897E-1511 + 2510 6.751834164665387050996413382239485E-1512 3.375917082332693525498206691119743E-1512 + 2511 1.687958541166346762749103345559872E-1512 8.439792705831733813745516727799358E-1513 + 2512 4.219896352915866906872758363899679E-1513 2.109948176457933453436379181949840E-1513 + 2513 1.054974088228966726718189590974920E-1513 5.27487044114483363359094795487460E-1514 + 2514 2.63743522057241681679547397743730E-1514 1.31871761028620840839773698871865E-1514 + 2515 6.59358805143104204198868494359325E-1515 3.296794025715521020994342471796625E-1515 + 2516 1.648397012857760510497171235898313E-1515 8.241985064288802552485856179491563E-1516 + 2517 4.120992532144401276242928089745782E-1516 2.060496266072200638121464044872891E-1516 + 2518 1.030248133036100319060732022436446E-1516 5.151240665180501595303660112182228E-1517 + 2519 2.575620332590250797651830056091114E-1517 1.287810166295125398825915028045557E-1517 + 2520 6.439050831475626994129575140227785E-1518 3.219525415737813497064787570113893E-1518 + 2521 1.609762707868906748532393785056947E-1518 8.048813539344533742661968925284733E-1519 + 2522 4.024406769672266871330984462642367E-1519 2.012203384836133435665492231321183E-1519 + 2523 1.006101692418066717832746115660592E-1519 5.030508462090333589163730578302958E-1520 + 2524 2.515254231045166794581865289151479E-1520 1.257627115522583397290932644575740E-1520 + 2525 6.28813557761291698645466322287870E-1521 3.14406778880645849322733161143935E-1521 + 2526 1.572033894403229246613665805719675E-1521 7.860169472016146233068329028598375E-1522 + 2527 3.930084736008073116534164514299188E-1522 1.965042368004036558267082257149594E-1522 + 2528 9.82521184002018279133541128574797E-1523 4.912605920010091395667705642873985E-1523 + 2529 2.456302960005045697833852821436993E-1523 1.228151480002522848916926410718496E-1523 + 2530 6.14075740001261424458463205359248E-1524 3.07037870000630712229231602679624E-1524 + 2531 1.53518935000315356114615801339812E-1524 7.6759467500157678057307900669906E-1525 + 2532 3.8379733750078839028653950334953E-1525 1.91898668750394195143269751674765E-1525 + 2533 9.59493343751970975716348758373825E-1526 4.797466718759854878581743791869125E-1526 + 2534 2.398733359379927439290871895934563E-1526 1.199366679689963719645435947967281E-1526 + 2535 5.996833398449818598227179739836405E-1527 2.998416699224909299113589869918203E-1527 + 2536 1.499208349612454649556794934959102E-1527 7.496041748062273247783974674795508E-1528 + 2537 3.748020874031136623891987337397754E-1528 1.874010437015568311945993668698877E-1528 + 2538 9.370052185077841559729968343494385E-1529 4.685026092538920779864984171747193E-1529 + 2539 2.342513046269460389932492085873597E-1529 1.171256523134730194966246042936798E-1529 + 2540 5.85628261567365097483123021468399E-1530 2.928141307836825487415615107341995E-1530 + 2541 1.464070653918412743707807553670998E-1530 7.320353269592063718539037768354988E-1531 + 2542 3.660176634796031859269518884177494E-1531 1.830088317398015929634759442088747E-1531 + 2543 9.150441586990079648173797210443735E-1532 4.575220793495039824086898605221868E-1532 + 2544 2.287610396747519912043449302610934E-1532 1.143805198373759956021724651305467E-1532 + 2545 5.719025991868799780108623256527335E-1533 2.859512995934399890054311628263668E-1533 + 2546 1.429756497967199945027155814131834E-1533 7.14878248983599972513577907065917E-1534 + 2547 3.574391244917999862567889535329585E-1534 1.787195622458999931283944767664793E-1534 + 2548 8.935978112294999656419723838323965E-1535 4.467989056147499828209861919161983E-1535 + 2549 2.233994528073749914104930959580992E-1535 1.116997264036874957052465479790496E-1535 + 2550 5.58498632018437478526232739895248E-1536 2.79249316009218739263116369947624E-1536 + 2551 1.39624658004609369631558184973812E-1536 6.9812329002304684815779092486906E-1537 + 2552 3.4906164501152342407889546243453E-1537 1.74530822505761712039447731217265E-1537 + 2553 8.72654112528808560197238656086325E-1538 4.363270562644042800986193280431625E-1538 + 2554 2.181635281322021400493096640215813E-1538 1.090817640661010700246548320107906E-1538 + 2555 5.45408820330505350123274160053953E-1539 2.727044101652526750616370800269765E-1539 + 2556 1.363522050826263375308185400134883E-1539 6.817610254131316876540927000674413E-1540 + 2557 3.408805127065658438270463500337207E-1540 1.704402563532829219135231750168603E-1540 + 2558 8.522012817664146095676158750843015E-1541 4.261006408832073047838079375421508E-1541 + 2559 2.130503204416036523919039687710754E-1541 1.065251602208018261959519843855377E-1541 + 2560 5.326258011040091309797599219276885E-1542 2.663129005520045654898799609638443E-1542 + 2561 1.331564502760022827449399804819222E-1542 6.657822513800114137246999024096108E-1543 + 2562 3.328911256900057068623499512048054E-1543 1.664455628450028534311749756024027E-1543 + 2563 8.322278142250142671558748780120135E-1544 4.161139071125071335779374390060068E-1544 + 2564 2.080569535562535667889687195030034E-1544 1.040284767781267833944843597515017E-1544 + 2565 5.201423838906339169724217987575085E-1545 2.600711919453169584862108993787543E-1545 + 2566 1.300355959726584792431054496893772E-1545 6.501779798632923962155272484468858E-1546 + 2567 3.250889899316461981077636242234429E-1546 1.625444949658230990538818121117215E-1546 + 2568 8.127224748291154952694090605586075E-1547 4.063612374145577476347045302793038E-1547 + 2569 2.031806187072788738173522651396519E-1547 1.015903093536394369086761325698260E-1547 + 2570 5.07951546768197184543380662849130E-1548 2.53975773384098592271690331424565E-1548 + 2571 1.269878866920492961358451657122825E-1548 6.349394334602464806792258285614125E-1549 + 2572 3.174697167301232403396129142807063E-1549 1.587348583650616201698064571403531E-1549 + 2573 7.936742918253081008490322857017655E-1550 3.968371459126540504245161428508828E-1550 + 2574 1.984185729563270252122580714254414E-1550 9.92092864781635126061290357127207E-1551 + 2575 4.960464323908175630306451785636035E-1551 2.480232161954087815153225892818018E-1551 + 2576 1.240116080977043907576612946409009E-1551 6.200580404885219537883064732045045E-1552 + 2577 3.100290202442609768941532366022523E-1552 1.550145101221304884470766183011261E-1552 + 2578 7.750725506106524422353830915056305E-1553 3.875362753053262211176915457528153E-1553 + 2579 1.937681376526631105588457728764077E-1553 9.688406882633155527942288643820383E-1554 + 2580 4.844203441316577763971144321910192E-1554 2.422101720658288881985572160955096E-1554 + 2581 1.211050860329144440992786080477548E-1554 6.05525430164572220496393040238774E-1555 + 2582 3.02762715082286110248196520119387E-1555 1.513813575411430551240982600596935E-1555 + 2583 7.569067877057152756204913002984675E-1556 3.784533938528576378102456501492338E-1556 + 2584 1.892266969264288189051228250746169E-1556 9.461334846321440945256141253730845E-1557 + 2585 4.730667423160720472628070626865423E-1557 2.365333711580360236314035313432711E-1557 + 2586 1.182666855790180118157017656716356E-1557 5.913334278950900590785088283581778E-1558 + 2587 2.956667139475450295392544141790889E-1558 1.478333569737725147696272070895445E-1558 + 2588 7.391667848688625738481360354477225E-1559 3.695833924344312869240680177238613E-1559 + 2589 1.847916962172156434620340088619307E-1559 9.239584810860782173101700443096533E-1560 + 2590 4.619792405430391086550850221548267E-1560 2.309896202715195543275425110774133E-1560 + 2591 1.154948101357597771637712555387067E-1560 5.774740506787988858188562776935333E-1561 + 2592 2.887370253393994429094281388467667E-1561 1.443685126696997214547140694233833E-1561 + 2593 7.218425633484986072735703471169165E-1562 3.609212816742493036367851735584583E-1562 + 2594 1.804606408371246518183925867792292E-1562 9.023032041856232590919629338961458E-1563 + 2595 4.511516020928116295459814669480729E-1563 2.255758010464058147729907334740365E-1563 + 2596 1.127879005232029073864953667370183E-1563 5.639395026160145369324768336850913E-1564 + 2597 2.819697513080072684662384168425457E-1564 1.409848756540036342331192084212728E-1564 + 2598 7.04924378270018171165596042106364E-1565 3.52462189135009085582798021053182E-1565 + 2599 1.76231094567504542791399010526591E-1565 8.81155472837522713956995052632955E-1566 + 2600 4.405777364187613569784975263164775E-1566 2.202888682093806784892487631582388E-1566 + 2601 1.101444341046903392446243815791194E-1566 5.50722170523451696223121907895597E-1567 + 2602 2.753610852617258481115609539477985E-1567 1.376805426308629240557804769738993E-1567 + 2603 6.884027131543146202789023848694965E-1568 3.442013565771573101394511924347483E-1568 + 2604 1.721006782885786550697255962173742E-1568 8.605033914428932753486279810868708E-1569 + 2605 4.302516957214466376743139905434354E-1569 2.151258478607233188371569952717177E-1569 + 2606 1.075629239303616594185784976358589E-1569 5.378146196518082970928924881792943E-1570 + 2607 2.689073098259041485464462440896472E-1570 1.344536549129520742732231220448236E-1570 + 2608 6.72268274564760371366115610224118E-1571 3.36134137282380185683057805112059E-1571 + 2609 1.680670686411900928415289025560295E-1571 8.403353432059504642076445127801475E-1572 + 2610 4.201676716029752321038222563900738E-1572 2.100838358014876160519111281950369E-1572 + 2611 1.050419179007438080259555640975185E-1572 5.252095895037190401297778204875923E-1573 + 2612 2.626047947518595200648889102437962E-1573 1.313023973759297600324444551218981E-1573 + 2613 6.565119868796488001622222756094905E-1574 3.282559934398244000811111378047453E-1574 + 2614 1.641279967199122000405555689023727E-1574 8.206399835995610002027778445118633E-1575 + 2615 4.103199917997805001013889222559317E-1575 2.051599958998902500506944611279658E-1575 + 2616 1.025799979499451250253472305639829E-1575 5.128999897497256251267361528199145E-1576 + 2617 2.564499948748628125633680764099573E-1576 1.282249974374314062816840382049786E-1576 + 2618 6.41124987187157031408420191024893E-1577 3.205624935935785157042100955124465E-1577 + 2619 1.602812467967892578521050477562233E-1577 8.014062339839462892605252387811163E-1578 + 2620 4.007031169919731446302626193905582E-1578 2.003515584959865723151313096952791E-1578 + 2621 1.001757792479932861575656548476396E-1578 5.008788962399664307878282742381978E-1579 + 2622 2.504394481199832153939141371190989E-1579 1.252197240599916076969570685595495E-1579 + 2623 6.260986202999580384847853427977475E-1580 3.130493101499790192423926713988738E-1580 + 2624 1.565246550749895096211963356994369E-1580 7.826232753749475481059816784971845E-1581 + 2625 3.913116376874737740529908392485923E-1581 1.956558188437368870264954196242961E-1581 + 2626 9.782790942186844351324770981214805E-1582 4.891395471093422175662385490607403E-1582 + 2627 2.445697735546711087831192745303702E-1582 1.222848867773355543915596372651851E-1582 + 2628 6.114244338866777719577981863259255E-1583 3.057122169433388859788990931629628E-1583 + 2629 1.528561084716694429894495465814814E-1583 7.64280542358347214947247732907407E-1584 + 2630 3.821402711791736074736238664537035E-1584 1.910701355895868037368119332268518E-1584 + 2631 9.55350677947934018684059666134259E-1585 4.776753389739670093420298330671295E-1585 + 2632 2.388376694869835046710149165335648E-1585 1.194188347434917523355074582667824E-1585 + 2633 5.97094173717458761677537291333912E-1586 2.98547086858729380838768645666956E-1586 + 2634 1.49273543429364690419384322833478E-1586 7.4636771714682345209692161416739E-1587 + 2635 3.73183858573411726048460807083695E-1587 1.865919292867058630242304035418475E-1587 + 2636 9.329596464335293151211520177092375E-1588 4.664798232167646575605760088546188E-1588 + 2637 2.332399116083823287802880044273094E-1588 1.166199558041911643901440022136547E-1588 + 2638 5.830997790209558219507200110682735E-1589 2.915498895104779109753600055341368E-1589 + 2639 1.457749447552389554876800027670684E-1589 7.28874723776194777438400013835342E-1590 + 2640 3.64437361888097388719200006917671E-1590 1.822186809440486943596000034588355E-1590 + 2641 9.110934047202434717980000172941775E-1591 4.555467023601217358990000086470888E-1591 + 2642 2.277733511800608679495000043235444E-1591 1.138866755900304339747500021617722E-1591 + 2643 5.69433377950152169873750010808861E-1592 2.847166889750760849368750054044305E-1592 + 2644 1.423583444875380424684375027022153E-1592 7.117917224376902123421875135110763E-1593 + 2645 3.558958612188451061710937567555382E-1593 1.779479306094225530855468783777691E-1593 + 2646 8.897396530471127654277343918888455E-1594 4.448698265235563827138671959444228E-1594 + 2647 2.224349132617781913569335979722114E-1594 1.112174566308890956784667989861057E-1594 + 2648 5.560872831544454783923339949305285E-1595 2.780436415772227391961669974652643E-1595 + 2649 1.390218207886113695980834987326322E-1595 6.951091039430568479904174936631608E-1596 + 2650 3.475545519715284239952087468315804E-1596 1.737772759857642119976043734157902E-1596 + 2651 8.68886379928821059988021867078951E-1597 4.344431899644105299940109335394755E-1597 + 2652 2.172215949822052649970054667697378E-1597 1.086107974911026324985027333848689E-1597 + 2653 5.430539874555131624925136669243445E-1598 2.715269937277565812462568334621723E-1598 + 2654 1.357634968638782906231284167310862E-1598 6.788174843193914531156420836554308E-1599 + 2655 3.394087421596957265578210418277154E-1599 1.697043710798478632789105209138577E-1599 + 2656 8.485218553992393163945526045692885E-1600 4.242609276996196581972763022846443E-1600 + 2657 2.121304638498098290986381511423222E-1600 1.060652319249049145493190755711611E-1600 + 2658 5.303261596245245727465953778558055E-1601 2.651630798122622863732976889279028E-1601 + 2659 1.325815399061311431866488444639514E-1601 6.62907699530655715933244222319757E-1602 + 2660 3.314538497653278579666221111598785E-1602 1.657269248826639289833110555799393E-1602 + 2661 8.286346244133196449165552778996965E-1603 4.143173122066598224582776389498483E-1603 + 2662 2.071586561033299112291388194749242E-1603 1.035793280516649556145694097374621E-1603 + 2663 5.178966402583247780728470486873105E-1604 2.589483201291623890364235243436553E-1604 + 2664 1.294741600645811945182117621718277E-1604 6.473708003229059725910588108591383E-1605 + 2665 3.236854001614529862955294054295692E-1605 1.618427000807264931477647027147846E-1605 + 2666 8.09213500403632465738823513573923E-1606 4.046067502018162328694117567869615E-1606 + 2667 2.023033751009081164347058783934808E-1606 1.011516875504540582173529391967404E-1606 + 2668 5.05758437752270291086764695983702E-1607 2.52879218876135145543382347991851E-1607 + 2669 1.264396094380675727716911739959255E-1607 6.321980471903378638584558699796275E-1608 + 2670 3.160990235951689319292279349898138E-1608 1.580495117975844659646139674949069E-1608 + 2671 7.902475589879223298230698374745345E-1609 3.951237794939611649115349187372673E-1609 + 2672 1.975618897469805824557674593686337E-1609 9.878094487349029122788372968431683E-1610 + 2673 4.939047243674514561394186484215842E-1610 2.469523621837257280697093242107921E-1610 + 2674 1.234761810918628640348546621053961E-1610 6.173809054593143201742733105269803E-1611 + 2675 3.086904527296571600871366552634902E-1611 1.543452263648285800435683276317451E-1611 + 2676 7.717261318241429002178416381587255E-1612 3.858630659120714501089208190793628E-1612 + 2677 1.929315329560357250544604095396814E-1612 9.64657664780178625272302047698407E-1613 + 2678 4.823288323900893126361510238492035E-1613 2.411644161950446563180755119246018E-1613 + 2679 1.205822080975223281590377559623009E-1613 6.029110404876116407951887798115045E-1614 + 2680 3.014555202438058203975943899057523E-1614 1.507277601219029101987971949528761E-1614 + 2681 7.536388006095145509939859747643805E-1615 3.768194003047572754969929873821903E-1615 + 2682 1.884097001523786377484964936910952E-1615 9.420485007618931887424824684554758E-1616 + 2683 4.710242503809465943712412342277379E-1616 2.355121251904732971856206171138690E-1616 + 2684 1.177560625952366485928103085569345E-1616 5.887803129761832429640515427846725E-1617 + 2685 2.943901564880916214820257713923363E-1617 1.471950782440458107410128856961681E-1617 + 2686 7.359753912202290537050644284808405E-1618 3.679876956101145268525322142404203E-1618 + 2687 1.839938478050572634262661071202102E-1618 9.199692390252863171313305356010508E-1619 + 2688 4.599846195126431585656652678005254E-1619 2.299923097563215792828326339002627E-1619 + 2689 1.149961548781607896414163169501314E-1619 5.749807743908039482070815847506568E-1620 + 2690 2.874903871954019741035407923753284E-1620 1.437451935977009870517703961876642E-1620 + 2691 7.18725967988504935258851980938321E-1621 3.593629839942524676294259904691605E-1621 + 2692 1.796814919971262338147129952345803E-1621 8.984074599856311690735649761729013E-1622 + 2693 4.492037299928155845367824880864507E-1622 2.246018649964077922683912440432253E-1622 + 2694 1.123009324982038961341956220216127E-1622 5.615046624910194806709781101080633E-1623 + 2695 2.807523312455097403354890550540317E-1623 1.403761656227548701677445275270158E-1623 + 2696 7.01880828113774350838722637635079E-1624 3.509404140568871754193613188175395E-1624 + 2697 1.754702070284435877096806594087698E-1624 8.773510351422179385484032970438488E-1625 + 2698 4.386755175711089692742016485219244E-1625 2.193377587855544846371008242609622E-1625 + 2699 1.096688793927772423185504121304811E-1625 5.483443969638862115927520606524055E-1626 + 2700 2.741721984819431057963760303262028E-1626 1.370860992409715528981880151631014E-1626 + 2701 6.85430496204857764490940075815507E-1627 3.427152481024288822454700379077535E-1627 + 2702 1.713576240512144411227350189538768E-1627 8.567881202560722056136750947693838E-1628 + 2703 4.283940601280361028068375473846919E-1628 2.141970300640180514034187736923460E-1628 + 2704 1.070985150320090257017093868461730E-1628 5.35492575160045128508546934230865E-1629 + 2705 2.677462875800225642542734671154325E-1629 1.338731437900112821271367335577163E-1629 + 2706 6.693657189500564106356836677885815E-1630 3.346828594750282053178418338942908E-1630 + 2707 1.673414297375141026589209169471454E-1630 8.36707148687570513294604584735727E-1631 + 2708 4.183535743437852566473022923678635E-1631 2.091767871718926283236511461839318E-1631 + 2709 1.045883935859463141618255730919659E-1631 5.229419679297315708091278654598295E-1632 + 2710 2.614709839648657854045639327299148E-1632 1.307354919824328927022819663649574E-1632 + 2711 6.53677459912164463511409831824787E-1633 3.268387299560822317557049159123935E-1633 + 2712 1.634193649780411158778524579561968E-1633 8.170968248902055793892622897809838E-1634 + 2713 4.085484124451027896946311448904919E-1634 2.042742062225513948473155724452460E-1634 + 2714 1.021371031112756974236577862226230E-1634 5.10685515556378487118288931113115E-1635 + 2715 2.553427577781892435591444655565575E-1635 1.276713788890946217795722327782788E-1635 + 2716 6.38356894445473108897861163891394E-1636 3.19178447222736554448930581945697E-1636 + 2717 1.595892236113682772244652909728485E-1636 7.979461180568413861223264548642425E-1637 + 2718 3.989730590284206930611632274321213E-1637 1.994865295142103465305816137160606E-1637 + 2719 9.97432647571051732652908068580303E-1638 4.987163237855258663264540342901515E-1638 + 2720 2.493581618927629331632270171450758E-1638 1.246790809463814665816135085725379E-1638 + 2721 6.233954047319073329080675428626895E-1639 3.116977023659536664540337714313448E-1639 + 2722 1.558488511829768332270168857156724E-1639 7.79244255914884166135084428578362E-1640 + 2723 3.89622127957442083067542214289181E-1640 1.948110639787210415337711071445905E-1640 + 2724 9.740553198936052076688555357229525E-1641 4.870276599468026038344277678614763E-1641 + 2725 2.435138299734013019172138839307382E-1641 1.217569149867006509586069419653691E-1641 + 2726 6.087845749335032547930347098268455E-1642 3.043922874667516273965173549134228E-1642 + 2727 1.521961437333758136982586774567114E-1642 7.60980718666879068491293387283557E-1643 + 2728 3.804903593334395342456466936417785E-1643 1.902451796667197671228233468208893E-1643 + 2729 9.512258983335988356141167341044465E-1644 4.756129491667994178070583670522233E-1644 + 2730 2.378064745833997089035291835261117E-1644 1.189032372916998544517645917630558E-1644 + 2731 5.94516186458499272258822958815279E-1645 2.972580932292496361294114794076395E-1645 + 2732 1.486290466146248180647057397038198E-1645 7.431452330731240903235286985190988E-1646 + 2733 3.715726165365620451617643492595494E-1646 1.857863082682810225808821746297747E-1646 + 2734 9.289315413414051129044108731488735E-1647 4.644657706707025564522054365744368E-1647 + 2735 2.322328853353512782261027182872184E-1647 1.161164426676756391130513591436092E-1647 + 2736 5.80582213338378195565256795718046E-1648 2.90291106669189097782628397859023E-1648 + 2737 1.451455533345945488913141989295115E-1648 7.257277666729727444565709946475575E-1649 + 2738 3.628638833364863722282854973237788E-1649 1.814319416682431861141427486618894E-1649 + 2739 9.07159708341215930570713743309447E-1650 4.535798541706079652853568716547235E-1650 + 2740 2.267899270853039826426784358273618E-1650 1.133949635426519913213392179136809E-1650 + 2741 5.669748177132599566066960895684045E-1651 2.834874088566299783033480447842023E-1651 + 2742 1.417437044283149891516740223921012E-1651 7.087185221415749457583701119605058E-1652 + 2743 3.543592610707874728791850559802529E-1652 1.771796305353937364395925279901265E-1652 + 2744 8.858981526769686821979626399506325E-1653 4.429490763384843410989813199753163E-1653 + 2745 2.214745381692421705494906599876582E-1653 1.107372690846210852747453299938291E-1653 + 2746 5.536863454231054263737266499691455E-1654 2.768431727115527131868633249845728E-1654 + 2747 1.384215863557763565934316624922864E-1654 6.92107931778881782967158312461432E-1655 + 2748 3.46053965889440891483579156230716E-1655 1.73026982944720445741789578115358E-1655 + 2749 8.6513491472360222870894789057679E-1656 4.32567457361801114354473945288395E-1656 + 2750 2.162837286809005571772369726441975E-1656 1.081418643404502785886184863220988E-1656 + 2751 5.40709321702251392943092431610494E-1657 2.70354660851125696471546215805247E-1657 + 2752 1.351773304255628482357731079026235E-1657 6.758866521278142411788655395131175E-1658 + 2753 3.379433260639071205894327697565588E-1658 1.689716630319535602947163848782794E-1658 + 2754 8.44858315159767801473581924391397E-1659 4.224291575798839007367909621956985E-1659 + 2755 2.112145787899419503683954810978493E-1659 1.056072893949709751841977405489246E-1659 + 2756 5.28036446974854875920988702744623E-1660 2.640182234874274379604943513723115E-1660 + 2757 1.320091117437137189802471756861558E-1660 6.600455587185685949012358784307788E-1661 + 2758 3.300227793592842974506179392153894E-1661 1.650113896796421487253089696076947E-1661 + 2759 8.250569483982107436265448480384735E-1662 4.125284741991053718132724240192368E-1662 + 2760 2.062642370995526859066362120096184E-1662 1.031321185497763429533181060048092E-1662 + 2761 5.15660592748881714766590530024046E-1663 2.57830296374440857383295265012023E-1663 + 2762 1.289151481872204286916476325060115E-1663 6.445757409361021434582381625300575E-1664 + 2763 3.222878704680510717291190812650288E-1664 1.611439352340255358645595406325144E-1664 + 2764 8.05719676170127679322797703162572E-1665 4.02859838085063839661398851581286E-1665 + 2765 2.01429919042531919830699425790643E-1665 1.007149595212659599153497128953215E-1665 + 2766 5.035747976063297995767485644766075E-1666 2.517873988031648997883742822383038E-1666 + 2767 1.258936994015824498941871411191519E-1666 6.294684970079122494709357055957595E-1667 + 2768 3.147342485039561247354678527978798E-1667 1.573671242519780623677339263989399E-1667 + 2769 7.868356212598903118386696319946995E-1668 3.934178106299451559193348159973498E-1668 + 2770 1.967089053149725779596674079986749E-1668 9.835445265748628897983370399933745E-1669 + 2771 4.917722632874314448991685199966873E-1669 2.458861316437157224495842599983436E-1669 + 2772 1.229430658218578612247921299991718E-1669 6.14715329109289306123960649995859E-1670 + 2773 3.073576645546446530619803249979295E-1670 1.536788322773223265309901624989648E-1670 + 2774 7.68394161386611632654950812494824E-1671 3.84197080693305816327475406247412E-1671 + 2775 1.92098540346652908163737703123706E-1671 9.6049270173326454081868851561853E-1672 + 2776 4.80246350866632270409344257809265E-1672 2.401231754333161352046721289046325E-1672 + 2777 1.200615877166580676023360644523163E-1672 6.003079385832903380116803222615813E-1673 + 2778 3.001539692916451690058401611307907E-1673 1.500769846458225845029200805653953E-1673 + 2779 7.503849232291129225146004028269765E-1674 3.751924616145564612573002014134883E-1674 + 2780 1.875962308072782306286501007067442E-1674 9.379811540363911531432505035337208E-1675 + 2781 4.689905770181955765716252517668604E-1675 2.344952885090977882858126258834302E-1675 + 2782 1.172476442545488941429063129417151E-1675 5.862382212727444707145315647085755E-1676 + 2783 2.931191106363722353572657823542878E-1676 1.465595553181861176786328911771439E-1676 + 2784 7.327977765909305883931644558857195E-1677 3.663988882954652941965822279428598E-1677 + 2785 1.831994441477326470982911139714299E-1677 9.159972207386632354914555698571495E-1678 + 2786 4.579986103693316177457277849285748E-1678 2.289993051846658088728638924642874E-1678 + 2787 1.144996525923329044364319462321437E-1678 5.724982629616645221821597311607185E-1679 + 2788 2.862491314808322610910798655803593E-1679 1.431245657404161305455399327901796E-1679 + 2789 7.15622828702080652727699663950898E-1680 3.57811414351040326363849831975449E-1680 + 2790 1.789057071755201631819249159877245E-1680 8.945285358776008159096245799386225E-1681 + 2791 4.472642679388004079548122899693113E-1681 2.236321339694002039774061449846556E-1681 + 2792 1.118160669847001019887030724923278E-1681 5.59080334923500509943515362461639E-1682 + 2793 2.795401674617502549717576812308195E-1682 1.397700837308751274858788406154098E-1682 + 2794 6.98850418654375637429394203077049E-1683 3.494252093271878187146971015385245E-1683 + 2795 1.747126046635939093573485507692623E-1683 8.735630233179695467867427538463113E-1684 + 2796 4.367815116589847733933713769231557E-1684 2.183907558294923866966856884615778E-1684 + 2797 1.091953779147461933483428442307889E-1684 5.459768895737309667417142211539445E-1685 + 2798 2.729884447868654833708571105769723E-1685 1.364942223934327416854285552884861E-1685 + 2799 6.824711119671637084271427764424305E-1686 3.412355559835818542135713882212153E-1686 + 2800 1.706177779917909271067856941106077E-1686 8.530888899589546355339284705530383E-1687 + 2801 4.265444449794773177669642352765192E-1687 2.132722224897386588834821176382596E-1687 + 2802 1.066361112448693294417410588191298E-1687 5.33180556224346647208705294095649E-1688 + 2803 2.665902781121733236043526470478245E-1688 1.332951390560866618021763235239123E-1688 + 2804 6.664756952804333090108816176195615E-1689 3.332378476402166545054408088097808E-1689 + 2805 1.666189238201083272527204044048904E-1689 8.33094619100541636263602022024452E-1690 + 2806 4.16547309550270818131801011012226E-1690 2.08273654775135409065900505506113E-1690 + 2807 1.041368273875677045329502527530565E-1690 5.206841369378385226647512637652825E-1691 + 2808 2.603420684689192613323756318826413E-1691 1.301710342344596306661878159413206E-1691 + 2809 6.50855171172298153330939079706603E-1692 3.254275855861490766654695398533015E-1692 + 2810 1.627137927930745383327347699266508E-1692 8.135689639653726916636738496332538E-1693 + 2811 4.067844819826863458318369248166269E-1693 2.033922409913431729159184624083135E-1693 + 2812 1.016961204956715864579592312041568E-1693 5.084806024783579322897961560207838E-1694 + 2813 2.542403012391789661448980780103919E-1694 1.271201506195894830724490390051960E-1694 + 2814 6.35600753097947415362245195025980E-1695 3.17800376548973707681122597512990E-1695 + 2815 1.58900188274486853840561298756495E-1695 7.94500941372434269202806493782475E-1696 + 2816 3.972504706862171346014032468912375E-1696 1.986252353431085673007016234456188E-1696 + 2817 9.93126176715542836503508117228094E-1697 4.96563088357771418251754058614047E-1697 + 2818 2.482815441788857091258770293070235E-1697 1.241407720894428545629385146535118E-1697 + 2819 6.20703860447214272814692573267559E-1698 3.103519302236071364073462866337795E-1698 + 2820 1.551759651118035682036731433168898E-1698 7.758798255590178410183657165844488E-1699 + 2821 3.879399127795089205091828582922244E-1699 1.939699563897544602545914291461122E-1699 + 2822 9.69849781948772301272957145730561E-1700 4.849248909743861506364785728652805E-1700 + 2823 2.424624454871930753182392864326403E-1700 1.212312227435965376591196432163201E-1700 + 2824 6.061561137179826882955982160816005E-1701 3.030780568589913441477991080408003E-1701 + 2825 1.515390284294956720738995540204002E-1701 7.576951421474783603694977701020008E-1702 + 2826 3.788475710737391801847488850510004E-1702 1.894237855368695900923744425255002E-1702 + 2827 9.47118927684347950461872212627501E-1703 4.735594638421739752309361063137505E-1703 + 2828 2.367797319210869876154680531568753E-1703 1.183898659605434938077340265784376E-1703 + 2829 5.91949329802717469038670132892188E-1704 2.95974664901358734519335066446094E-1704 + 2830 1.47987332450679367259667533223047E-1704 7.39936662253396836298337666115235E-1705 + 2831 3.699683311266984181491688330576175E-1705 1.849841655633492090745844165288088E-1705 + 2832 9.24920827816746045372922082644044E-1706 4.62460413908373022686461041322022E-1706 + 2833 2.31230206954186511343230520661011E-1706 1.156151034770932556716152603305055E-1706 + 2834 5.780755173854662783580763016525275E-1707 2.890377586927331391790381508262638E-1707 + 2835 1.445188793463665695895190754131319E-1707 7.225943967318328479475953770656595E-1708 + 2836 3.612971983659164239737976885328298E-1708 1.806485991829582119868988442664149E-1708 + 2837 9.032429959147910599344942213320745E-1709 4.516214979573955299672471106660373E-1709 + 2838 2.258107489786977649836235553330187E-1709 1.129053744893488824918117776665093E-1709 + 2839 5.645268724467444124590588883325465E-1710 2.822634362233722062295294441662733E-1710 + 2840 1.411317181116861031147647220831367E-1710 7.056585905584305155738236104156833E-1711 + 2841 3.528292952792152577869118052078417E-1711 1.764146476396076288934559026039208E-1711 + 2842 8.82073238198038144467279513019604E-1712 4.41036619099019072233639756509802E-1712 + 2843 2.20518309549509536116819878254901E-1712 1.102591547747547680584099391274505E-1712 + 2844 5.512957738737738402920496956372525E-1713 2.756478869368869201460248478186263E-1713 + 2845 1.378239434684434600730124239093132E-1713 6.891197173422173003650621195465658E-1714 + 2846 3.445598586711086501825310597732829E-1714 1.722799293355543250912655298866415E-1714 + 2847 8.613996466777716254563276494332075E-1715 4.306998233388858127281638247166038E-1715 + 2848 2.153499116694429063640819123583019E-1715 1.076749558347214531820409561791510E-1715 + 2849 5.38374779173607265910204780895755E-1716 2.691873895868036329551023904478775E-1716 + 2850 1.345936947934018164775511952239388E-1716 6.729684739670090823877559761196938E-1717 + 2851 3.364842369835045411938779880598469E-1717 1.682421184917522705969389940299235E-1717 + 2852 8.412105924587613529846949701496175E-1718 4.206052962293806764923474850748088E-1718 + 2853 2.103026481146903382461737425374044E-1718 1.051513240573451691230868712687022E-1718 + 2854 5.25756620286725845615434356343511E-1719 2.628783101433629228077171781717555E-1719 + 2855 1.314391550716814614038585890858778E-1719 6.571957753584073070192929454293888E-1720 + 2856 3.285978876792036535096464727146944E-1720 1.642989438396018267548232363573472E-1720 + 2857 8.21494719198009133774116181786736E-1721 4.10747359599004566887058090893368E-1721 + 2858 2.05373679799502283443529045446684E-1721 1.02686839899751141721764522723342E-1721 + 2859 5.1343419949875570860882261361671E-1722 2.56717099749377854304411306808355E-1722 + 2860 1.283585498746889271522056534041775E-1722 6.417927493734446357610282670208875E-1723 + 2861 3.208963746867223178805141335104438E-1723 1.604481873433611589402570667552219E-1723 + 2862 8.022409367168057947012853337761095E-1724 4.011204683584028973506426668880548E-1724 + 2863 2.005602341792014486753213334440274E-1724 1.002801170896007243376606667220137E-1724 + 2864 5.014005854480036216883033336100685E-1725 2.507002927240018108441516668050343E-1725 + 2865 1.253501463620009054220758334025172E-1725 6.267507318100045271103791670125858E-1726 + 2866 3.133753659050022635551895835062929E-1726 1.566876829525011317775947917531465E-1726 + 2867 7.834384147625056588879739587657325E-1727 3.917192073812528294439869793828663E-1727 + 2868 1.958596036906264147219934896914332E-1727 9.792980184531320736099674484571658E-1728 + 2869 4.896490092265660368049837242285829E-1728 2.448245046132830184024918621142915E-1728 + 2870 1.224122523066415092012459310571458E-1728 6.120612615332075460062296552857288E-1729 + 2871 3.060306307666037730031148276428644E-1729 1.530153153833018865015574138214322E-1729 + 2872 7.65076576916509432507787069107161E-1730 3.825382884582547162538935345535805E-1730 + 2873 1.912691442291273581269467672767903E-1730 9.563457211456367906347338363839513E-1731 + 2874 4.781728605728183953173669181919757E-1731 2.390864302864091976586834590959878E-1731 + 2875 1.195432151432045988293417295479939E-1731 5.977160757160229941467086477399695E-1732 + 2876 2.988580378580114970733543238699848E-1732 1.494290189290057485366771619349924E-1732 + 2877 7.47145094645028742683385809674962E-1733 3.73572547322514371341692904837481E-1733 + 2878 1.867862736612571856708464524187405E-1733 9.339313683062859283542322620937025E-1734 + 2879 4.669656841531429641771161310468513E-1734 2.334828420765714820885580655234256E-1734 + 2880 1.167414210382857410442790327617128E-1734 5.83707105191428705221395163808564E-1735 + 2881 2.91853552595714352610697581904282E-1735 1.45926776297857176305348790952141E-1735 + 2882 7.29633881489285881526743954760705E-1736 3.648169407446429407633719773803525E-1736 + 2883 1.824084703723214703816859886901763E-1736 9.120423518616073519084299434508813E-1737 + 2884 4.560211759308036759542149717254407E-1737 2.280105879654018379771074858627203E-1737 + 2885 1.140052939827009189885537429313602E-1737 5.700264699135045949427687146568008E-1738 + 2886 2.850132349567522974713843573284004E-1738 1.425066174783761487356921786642002E-1738 + 2887 7.12533087391880743678460893321001E-1739 3.562665436959403718392304466605005E-1739 + 2888 1.781332718479701859196152233302503E-1739 8.906663592398509295980761166512513E-1740 + 2889 4.453331796199254647990380583256257E-1740 2.226665898099627323995190291628128E-1740 + 2890 1.113332949049813661997595145814064E-1740 5.56666474524906830998797572907032E-1741 + 2891 2.78333237262453415499398786453516E-1741 1.39166618631226707749699393226758E-1741 + 2892 6.9583309315613353874849696613379E-1742 3.47916546578066769374248483066895E-1742 + 2893 1.739582732890333846871242415334475E-1742 8.697913664451669234356212076672375E-1743 + 2894 4.348956832225834617178106038336188E-1743 2.174478416112917308589053019168094E-1743 + 2895 1.087239208056458654294526509584047E-1743 5.436196040282293271472632547920235E-1744 + 2896 2.718098020141146635736316273960118E-1744 1.359049010070573317868158136980059E-1744 + 2897 6.795245050352866589340790684900295E-1745 3.397622525176433294670395342450148E-1745 + 2898 1.698811262588216647335197671225074E-1745 8.49405631294108323667598835612537E-1746 + 2899 4.247028156470541618337994178062685E-1746 2.123514078235270809168997089031343E-1746 + 2900 1.061757039117635404584498544515672E-1746 5.308785195588177022922492722578358E-1747 + 2901 2.654392597794088511461246361289179E-1747 1.327196298897044255730623180644590E-1747 + 2902 6.63598149448522127865311590322295E-1748 3.317990747242610639326557951611475E-1748 + 2903 1.658995373621305319663278975805738E-1748 8.294976868106526598316394879028688E-1749 + 2904 4.147488434053263299158197439514344E-1749 2.073744217026631649579098719757172E-1749 + 2905 1.036872108513315824789549359878586E-1749 5.18436054256657912394774679939293E-1750 + 2906 2.592180271283289561973873399696465E-1750 1.296090135641644780986936699848233E-1750 + 2907 6.480450678208223904934683499241165E-1751 3.240225339104111952467341749620583E-1751 + 2908 1.620112669552055976233670874810292E-1751 8.100563347760279881168354374051458E-1752 + 2909 4.050281673880139940584177187025729E-1752 2.025140836940069970292088593512865E-1752 + 2910 1.012570418470034985146044296756433E-1752 5.062852092350174925730221483782163E-1753 + 2911 2.531426046175087462865110741891082E-1753 1.265713023087543731432555370945541E-1753 + 2912 6.328565115437718657162776854727705E-1754 3.164282557718859328581388427363853E-1754 + 2913 1.582141278859429664290694213681927E-1754 7.910706394297148321453471068409633E-1755 + 2914 3.955353197148574160726735534204817E-1755 1.977676598574287080363367767102408E-1755 + 2915 9.88838299287143540181683883551204E-1756 4.94419149643571770090841941775602E-1756 + 2916 2.47209574821785885045420970887801E-1756 1.236047874108929425227104854439005E-1756 + 2917 6.180239370544647126135524272195025E-1757 3.090119685272323563067762136097513E-1757 + 2918 1.545059842636161781533881068048757E-1757 7.725299213180808907669405340243783E-1758 + 2919 3.862649606590404453834702670121892E-1758 1.931324803295202226917351335060946E-1758 + 2920 9.65662401647601113458675667530473E-1759 4.828312008238005567293378337652365E-1759 + 2921 2.414156004119002783646689168826183E-1759 1.207078002059501391823344584413091E-1759 + 2922 6.035390010297506959116722922065455E-1760 3.017695005148753479558361461032728E-1760 + 2923 1.508847502574376739779180730516364E-1760 7.54423751287188369889590365258182E-1761 + 2924 3.77211875643594184944795182629091E-1761 1.886059378217970924723975913145455E-1761 + 2925 9.430296891089854623619879565727275E-1762 4.715148445544927311809939782863638E-1762 + 2926 2.357574222772463655904969891431819E-1762 1.178787111386231827952484945715910E-1762 + 2927 5.89393555693115913976242472857955E-1763 2.946967778465579569881212364289775E-1763 + 2928 1.473483889232789784940606182144888E-1763 7.367419446163948924703030910724438E-1764 + 2929 3.683709723081974462351515455362219E-1764 1.841854861540987231175757727681110E-1764 + 2930 9.20927430770493615587878863840555E-1765 4.604637153852468077939394319202775E-1765 + 2931 2.302318576926234038969697159601388E-1765 1.151159288463117019484848579800694E-1765 + 2932 5.75579644231558509742424289900347E-1766 2.877898221157792548712121449501735E-1766 + 2933 1.438949110578896274356060724750868E-1766 7.194745552894481371780303623754338E-1767 + 2934 3.597372776447240685890151811877169E-1767 1.798686388223620342945075905938585E-1767 + 2935 8.993431941118101714725379529692925E-1768 4.496715970559050857362689764846463E-1768 + 2936 2.248357985279525428681344882423232E-1768 1.124178992639762714340672441211616E-1768 + 2937 5.62089496319881357170336220605808E-1769 2.81044748159940678585168110302904E-1769 + 2938 1.40522374079970339292584055151452E-1769 7.0261187039985169646292027575726E-1770 + 2939 3.5130593519992584823146013787863E-1770 1.75652967599962924115730068939315E-1770 + 2940 8.78264837999814620578650344696575E-1771 4.391324189999073102893251723482875E-1771 + 2941 2.195662094999536551446625861741438E-1771 1.097831047499768275723312930870719E-1771 + 2942 5.489155237498841378616564654353595E-1772 2.744577618749420689308282327176798E-1772 + 2943 1.372288809374710344654141163588399E-1772 6.861444046873551723270705817941995E-1773 + 2944 3.430722023436775861635352908970998E-1773 1.715361011718387930817676454485499E-1773 + 2945 8.576805058591939654088382272427495E-1774 4.288402529295969827044191136213748E-1774 + 2946 2.144201264647984913522095568106874E-1774 1.072100632323992456761047784053437E-1774 + 2947 5.360503161619962283805238920267185E-1775 2.680251580809981141902619460133593E-1775 + 2948 1.340125790404990570951309730066797E-1775 6.700628952024952854756548650333983E-1776 + 2949 3.350314476012476427378274325166992E-1776 1.675157238006238213689137162583496E-1776 + 2950 8.37578619003119106844568581291748E-1777 4.18789309501559553422284290645874E-1777 + 2951 2.09394654750779776711142145322937E-1777 1.046973273753898883555710726614685E-1777 + 2952 5.234866368769494417778553633073425E-1778 2.617433184384747208889276816536713E-1778 + 2953 1.308716592192373604444638408268357E-1778 6.543582960961868022223192041341783E-1779 + 2954 3.271791480480934011111596020670892E-1779 1.635895740240467005555798010335446E-1779 + 2955 8.17947870120233502777899005167723E-1780 4.089739350601167513889495025838615E-1780 + 2956 2.044869675300583756944747512919308E-1780 1.022434837650291878472373756459654E-1780 + 2957 5.11217418825145939236186878229827E-1781 2.556087094125729696180934391149135E-1781 + 2958 1.278043547062864848090467195574568E-1781 6.390217735314324240452335977872838E-1782 + 2959 3.195108867657162120226167988936419E-1782 1.597554433828581060113083994468210E-1782 + 2960 7.98777216914290530056541997234105E-1783 3.993886084571452650282709986170525E-1783 + 2961 1.996943042285726325141354993085263E-1783 9.984715211428631625706774965426313E-1784 + 2962 4.992357605714315812853387482713157E-1784 2.496178802857157906426693741356578E-1784 + 2963 1.248089401428578953213346870678289E-1784 6.240447007142894766066734353391445E-1785 + 2964 3.120223503571447383033367176695723E-1785 1.560111751785723691516683588347861E-1785 + 2965 7.800558758928618457583417941739305E-1786 3.900279379464309228791708970869653E-1786 + 2966 1.950139689732154614395854485434827E-1786 9.750698448660773071979272427174133E-1787 + 2967 4.875349224330386535989636213587067E-1787 2.437674612165193267994818106793533E-1787 + 2968 1.218837306082596633997409053396767E-1787 6.094186530412983169987045266983833E-1788 + 2969 3.047093265206491584993522633491917E-1788 1.523546632603245792496761316745958E-1788 + 2970 7.61773316301622896248380658372979E-1789 3.808866581508114481241903291864895E-1789 + 2971 1.904433290754057240620951645932448E-1789 9.522166453770286203104758229662238E-1790 + 2972 4.761083226885143101552379114831119E-1790 2.380541613442571550776189557415560E-1790 + 2973 1.190270806721285775388094778707780E-1790 5.95135403360642887694047389353890E-1791 + 2974 2.97567701680321443847023694676945E-1791 1.487838508401607219235118473384725E-1791 + 2975 7.439192542008036096175592366923625E-1792 3.719596271004018048087796183461813E-1792 + 2976 1.859798135502009024043898091730907E-1792 9.298990677510045120219490458654533E-1793 + 2977 4.649495338755022560109745229327267E-1793 2.324747669377511280054872614663633E-1793 + 2978 1.162373834688755640027436307331817E-1793 5.811869173443778200137181536659083E-1794 + 2979 2.905934586721889100068590768329542E-1794 1.452967293360944550034295384164771E-1794 + 2980 7.264836466804722750171476920823855E-1795 3.632418233402361375085738460411928E-1795 + 2981 1.816209116701180687542869230205964E-1795 9.08104558350590343771434615102982E-1796 + 2982 4.54052279175295171885717307551491E-1796 2.270261395876475859428586537757455E-1796 + 2983 1.135130697938237929714293268878728E-1796 5.675653489691189648571466344393638E-1797 + 2984 2.837826744845594824285733172196819E-1797 1.418913372422797412142866586098410E-1797 + 2985 7.09456686211398706071433293049205E-1798 3.547283431056993530357166465246025E-1798 + 2986 1.773641715528496765178583232623013E-1798 8.868208577642483825892916163115063E-1799 + 2987 4.434104288821241912946458081557532E-1799 2.217052144410620956473229040778766E-1799 + 2988 1.108526072205310478236614520389383E-1799 5.542630361026552391183072601946915E-1800 + 2989 2.771315180513276195591536300973458E-1800 1.385657590256638097795768150486729E-1800 + 2990 6.928287951283190488978840752433645E-1801 3.464143975641595244489420376216823E-1801 + 2991 1.732071987820797622244710188108412E-1801 8.660359939103988111223550940542058E-1802 + 2992 4.330179969551994055611775470271029E-1802 2.165089984775997027805887735135515E-1802 + 2993 1.082544992387998513902943867567758E-1802 5.412724961939992569514719337838788E-1803 + 2994 2.706362480969996284757359668919394E-1803 1.353181240484998142378679834459697E-1803 + 2995 6.765906202424990711893399172298485E-1804 3.382953101212495355946699586149243E-1804 + 2996 1.691476550606247677973349793074622E-1804 8.457382753031238389866748965373108E-1805 + 2997 4.228691376515619194933374482686554E-1805 2.114345688257809597466687241343277E-1805 + 2998 1.057172844128904798733343620671639E-1805 5.285864220644523993666718103358193E-1806 + 2999 2.642932110322261996833359051679097E-1806 1.321466055161130998416679525839548E-1806 + 3000 6.60733027580565499208339762919774E-1807 3.30366513790282749604169881459887E-1807 + 3001 1.651832568951413748020849407299435E-1807 8.259162844757068740104247036497175E-1808 + 3002 4.129581422378534370052123518248588E-1808 2.064790711189267185026061759124294E-1808 + 3003 1.032395355594633592513030879562147E-1808 5.161976777973167962565154397810735E-1809 + 3004 2.580988388986583981282577198905368E-1809 1.290494194493291990641288599452684E-1809 + 3005 6.45247097246645995320644299726342E-1810 3.22623548623322997660322149863171E-1810 + 3006 1.613117743116614988301610749315855E-1810 8.065588715583074941508053746579275E-1811 + 3007 4.032794357791537470754026873289638E-1811 2.016397178895768735377013436644819E-1811 + 3008 1.008198589447884367688506718322410E-1811 5.040992947239421838442533591612048E-1812 + 3009 2.520496473619710919221266795806024E-1812 1.260248236809855459610633397903012E-1812 + 3010 6.30124118404927729805316698951506E-1813 3.15062059202463864902658349475753E-1813 + 3011 1.575310296012319324513291747378765E-1813 7.876551480061596622566458736893825E-1814 + 3012 3.938275740030798311283229368446913E-1814 1.969137870015399155641614684223456E-1814 + 3013 9.84568935007699577820807342111728E-1815 4.92284467503849788910403671055864E-1815 + 3014 2.46142233751924894455201835527932E-1815 1.23071116875962447227600917763966E-1815 + 3015 6.1535558437981223613800458881983E-1816 3.07677792189906118069002294409915E-1816 + 3016 1.538388960949530590345011472049575E-1816 7.691944804747652951725057360247875E-1817 + 3017 3.845972402373826475862528680123938E-1817 1.922986201186913237931264340061969E-1817 + 3018 9.614931005934566189656321700309845E-1818 4.807465502967283094828160850154923E-1818 + 3019 2.403732751483641547414080425077462E-1818 1.201866375741820773707040212538731E-1818 + 3020 6.009331878709103868535201062693655E-1819 3.004665939354551934267600531346828E-1819 + 3021 1.502332969677275967133800265673414E-1819 7.51166484838637983566900132836707E-1820 + 3022 3.755832424193189917834500664183535E-1820 1.877916212096594958917250332091768E-1820 + 3023 9.38958106048297479458625166045884E-1821 4.69479053024148739729312583022942E-1821 + 3024 2.34739526512074369864656291511471E-1821 1.173697632560371849323281457557355E-1821 + 3025 5.868488162801859246616407287786775E-1822 2.934244081400929623308203643893388E-1822 + 3026 1.467122040700464811654101821946694E-1822 7.33561020350232405827050910973347E-1823 + 3027 3.667805101751162029135254554866735E-1823 1.833902550875581014567627277433368E-1823 + 3028 9.16951275437790507283813638716684E-1824 4.58475637718895253641906819358342E-1824 + 3029 2.29237818859447626820953409679171E-1824 1.146189094297238134104767048395855E-1824 + 3030 5.730945471486190670523835241979275E-1825 2.865472735743095335261917620989638E-1825 + 3031 1.432736367871547667630958810494819E-1825 7.163681839357738338154794052474095E-1826 + 3032 3.581840919678869169077397026237048E-1826 1.790920459839434584538698513118524E-1826 + 3033 8.95460229919717292269349256559262E-1827 4.47730114959858646134674628279631E-1827 + 3034 2.238650574799293230673373141398155E-1827 1.119325287399646615336686570699078E-1827 + 3035 5.59662643699823307668343285349539E-1828 2.798313218499116538341716426747695E-1828 + 3036 1.399156609249558269170858213373848E-1828 6.995783046247791345854291066869238E-1829 + 3037 3.497891523123895672927145533434619E-1829 1.748945761561947836463572766717310E-1829 + 3038 8.74472880780973918231786383358655E-1830 4.372364403904869591158931916793275E-1830 + 3039 2.186182201952434795579465958396638E-1830 1.093091100976217397789732979198319E-1830 + 3040 5.465455504881086988948664895991595E-1831 2.732727752440543494474332447995798E-1831 + 3041 1.366363876220271747237166223997899E-1831 6.831819381101358736185831119989495E-1832 + 3042 3.415909690550679368092915559994748E-1832 1.707954845275339684046457779997374E-1832 + 3043 8.53977422637669842023228889998687E-1833 4.269887113188349210116144449993435E-1833 + 3044 2.134943556594174605058072224996718E-1833 1.067471778297087302529036112498359E-1833 + 3045 5.337358891485436512645180562491795E-1834 2.668679445742718256322590281245898E-1834 + 3046 1.334339722871359128161295140622949E-1834 6.671698614356795640806475703114745E-1835 + 3047 3.335849307178397820403237851557373E-1835 1.667924653589198910201618925778686E-1835 + 3048 8.33962326794599455100809462889343E-1836 4.169811633972997275504047314446715E-1836 + 3049 2.084905816986498637752023657223358E-1836 1.042452908493249318876011828611679E-1836 + 3050 5.212264542466246594380059143058395E-1837 2.606132271233123297190029571529198E-1837 + 3051 1.303066135616561648595014785764599E-1837 6.515330678082808242975073928822995E-1838 + 3052 3.257665339041404121487536964411498E-1838 1.628832669520702060743768482205749E-1838 + 3053 8.144163347603510303718842411028745E-1839 4.072081673801755151859421205514373E-1839 + 3054 2.036040836900877575929710602757187E-1839 1.018020418450438787964855301378593E-1839 + 3055 5.090102092252193939824276506892965E-1840 2.545051046126096969912138253446483E-1840 + 3056 1.272525523063048484956069126723242E-1840 6.362627615315242424780345633616208E-1841 + 3057 3.181313807657621212390172816808104E-1841 1.590656903828810606195086408404052E-1841 + 3058 7.95328451914405303097543204202026E-1842 3.97664225957202651548771602101013E-1842 + 3059 1.988321129786013257743858010505065E-1842 9.941605648930066288719290052525325E-1843 + 3060 4.970802824465033144359645026262663E-1843 2.485401412232516572179822513131331E-1843 + 3061 1.242700706116258286089911256565666E-1843 6.213503530581291430449556282828328E-1844 + 3062 3.106751765290645715224778141414164E-1844 1.553375882645322857612389070707082E-1844 + 3063 7.76687941322661428806194535353541E-1845 3.883439706613307144030972676767705E-1845 + 3064 1.941719853306653572015486338383853E-1845 9.708599266533267860077431691919263E-1846 + 3065 4.854299633266633930038715845959632E-1846 2.427149816633316965019357922979816E-1846 + 3066 1.213574908316658482509678961489908E-1846 6.06787454158329241254839480744954E-1847 + 3067 3.03393727079164620627419740372477E-1847 1.516968635395823103137098701862385E-1847 + 3068 7.584843176979115515685493509311925E-1848 3.792421588489557757842746754655963E-1848 + 3069 1.896210794244778878921373377327982E-1848 9.481053971223894394606866886639908E-1849 + 3070 4.740526985611947197303433443319954E-1849 2.370263492805973598651716721659977E-1849 + 3071 1.185131746402986799325858360829989E-1849 5.925658732014933996629291804149943E-1850 + 3072 2.962829366007466998314645902074972E-1850 1.481414683003733499157322951037486E-1850 + 3073 7.40707341501866749578661475518743E-1851 3.703536707509333747893307377593715E-1851 + 3074 1.851768353754666873946653688796858E-1851 9.258841768773334369733268443984288E-1852 + 3075 4.629420884386667184866634221992144E-1852 2.314710442193333592433317110996072E-1852 + 3076 1.157355221096666796216658555498036E-1852 5.78677610548333398108329277749018E-1853 + 3077 2.89338805274166699054164638874509E-1853 1.446694026370833495270823194372545E-1853 + 3078 7.233470131854167476354115971862725E-1854 3.616735065927083738177057985931363E-1854 + 3079 1.808367532963541869088528992965682E-1854 9.041837664817709345442644964828408E-1855 + 3080 4.520918832408854672721322482414204E-1855 2.260459416204427336360661241207102E-1855 + 3081 1.130229708102213668180330620603551E-1855 5.651148540511068340901653103017755E-1856 + 3082 2.825574270255534170450826551508878E-1856 1.412787135127767085225413275754439E-1856 + 3083 7.063935675638835426127066378772195E-1857 3.531967837819417713063533189386098E-1857 + 3084 1.765983918909708856531766594693049E-1857 8.829919594548544282658832973465245E-1858 + 3085 4.414959797274272141329416486732623E-1858 2.207479898637136070664708243366311E-1858 + 3086 1.103739949318568035332354121683156E-1858 5.518699746592840176661770608415778E-1859 + 3087 2.759349873296420088330885304207889E-1859 1.379674936648210044165442652103945E-1859 + 3088 6.898374683241050220827213260519725E-1860 3.449187341620525110413606630259863E-1860 + 3089 1.724593670810262555206803315129932E-1860 8.622968354051312776034016575649658E-1861 + 3090 4.311484177025656388017008287824829E-1861 2.155742088512828194008504143912415E-1861 + 3091 1.077871044256414097004252071956208E-1861 5.389355221282070485021260359781038E-1862 + 3092 2.694677610641035242510630179890519E-1862 1.347338805320517621255315089945260E-1862 + 3093 6.73669402660258810627657544972630E-1863 3.36834701330129405313828772486315E-1863 + 3094 1.684173506650647026569143862431575E-1863 8.420867533253235132845719312157875E-1864 + 3095 4.210433766626617566422859656078938E-1864 2.105216883313308783211429828039469E-1864 + 3096 1.052608441656654391605714914019735E-1864 5.263042208283271958028574570098673E-1865 + 3097 2.631521104141635979014287285049337E-1865 1.315760552070817989507143642524668E-1865 + 3098 6.57880276035408994753571821262334E-1866 3.28940138017704497376785910631167E-1866 + 3099 1.644700690088522486883929553155835E-1866 8.223503450442612434419647765779175E-1867 + 3100 4.111751725221306217209823882889588E-1867 2.055875862610653108604911941444794E-1867 + 3101 1.027937931305326554302455970722397E-1867 5.139689656526632771512279853611985E-1868 + 3102 2.569844828263316385756139926805993E-1868 1.284922414131658192878069963402996E-1868 + 3103 6.42461207065829096439034981701498E-1869 3.21230603532914548219517490850749E-1869 + 3104 1.606153017664572741097587454253745E-1869 8.030765088322863705487937271268725E-1870 + 3105 4.015382544161431852743968635634363E-1870 2.007691272080715926371984317817181E-1870 + 3106 1.003845636040357963185992158908591E-1870 5.019228180201789815929960794542953E-1871 + 3107 2.509614090100894907964980397271477E-1871 1.254807045050447453982490198635738E-1871 + 3108 6.27403522525223726991245099317869E-1872 3.137017612626118634956225496589345E-1872 + 3109 1.568508806313059317478112748294673E-1872 7.842544031565296587390563741473363E-1873 + 3110 3.921272015782648293695281870736682E-1873 1.960636007891324146847640935368341E-1873 + 3111 9.803180039456620734238204676841705E-1874 4.901590019728310367119102338420853E-1874 + 3112 2.450795009864155183559551169210427E-1874 1.225397504932077591779775584605213E-1874 + 3113 6.126987524660387958898877923026065E-1875 3.063493762330193979449438961513033E-1875 + 3114 1.531746881165096989724719480756517E-1875 7.658734405825484948623597403782583E-1876 + 3115 3.829367202912742474311798701891292E-1876 1.914683601456371237155899350945646E-1876 + 3116 9.57341800728185618577949675472823E-1877 4.786709003640928092889748377364115E-1877 + 3117 2.393354501820464046444874188682058E-1877 1.196677250910232023222437094341029E-1877 + 3118 5.983386254551160116112185471705145E-1878 2.991693127275580058056092735852573E-1878 + 3119 1.495846563637790029028046367926287E-1878 7.479232818188950145140231839631433E-1879 + 3120 3.739616409094475072570115919815717E-1879 1.869808204547237536285057959907858E-1879 + 3121 9.34904102273618768142528979953929E-1880 4.674520511368093840712644899769645E-1880 + 3122 2.337260255684046920356322449884823E-1880 1.168630127842023460178161224942411E-1880 + 3123 5.843150639210117300890806124712055E-1881 2.921575319605058650445403062356028E-1881 + 3124 1.460787659802529325222701531178014E-1881 7.30393829901264662611350765589007E-1882 + 3125 3.651969149506323313056753827945035E-1882 1.825984574753161656528376913972518E-1882 + 3126 9.12992287376580828264188456986259E-1883 4.564961436882904141320942284931295E-1883 + 3127 2.282480718441452070660471142465648E-1883 1.141240359220726035330235571232824E-1883 + 3128 5.70620179610363017665117785616412E-1884 2.85310089805181508832558892808206E-1884 + 3129 1.42655044902590754416279446404103E-1884 7.13275224512953772081397232020515E-1885 + 3130 3.566376122564768860406986160102575E-1885 1.783188061282384430203493080051288E-1885 + 3131 8.91594030641192215101746540025644E-1886 4.45797015320596107550873270012822E-1886 + 3132 2.22898507660298053775436635006411E-1886 1.114492538301490268877183175032055E-1886 + 3133 5.572462691507451344385915875160275E-1887 2.786231345753725672192957937580138E-1887 + 3134 1.393115672876862836096478968790069E-1887 6.965578364384314180482394843950345E-1888 + 3135 3.482789182192157090241197421975173E-1888 1.741394591096078545120598710987586E-1888 + 3136 8.70697295548039272560299355493793E-1889 4.353486477740196362801496777468965E-1889 + 3137 2.176743238870098181400748388734483E-1889 1.088371619435049090700374194367241E-1889 + 3138 5.441858097175245453501870971836205E-1890 2.720929048587622726750935485918103E-1890 + 3139 1.360464524293811363375467742959052E-1890 6.802322621469056816877338714795258E-1891 + 3140 3.401161310734528408438669357397629E-1891 1.700580655367264204219334678698815E-1891 + 3141 8.502903276836321021096673393494075E-1892 4.251451638418160510548336696747038E-1892 + 3142 2.125725819209080255274168348373519E-1892 1.062862909604540127637084174186760E-1892 + 3143 5.31431454802270063818542087093380E-1893 2.65715727401135031909271043546690E-1893 + 3144 1.32857863700567515954635521773345E-1893 6.64289318502837579773177608866725E-1894 + 3145 3.321446592514187898865888044333625E-1894 1.660723296257093949432944022166813E-1894 + 3146 8.303616481285469747164720110834065E-1895 4.151808240642734873582360055417033E-1895 + 3147 2.075904120321367436791180027708517E-1895 1.037952060160683718395590013854258E-1895 + 3148 5.18976030080341859197795006927129E-1896 2.594880150401709295988975034635645E-1896 + 3149 1.297440075200854647994487517317823E-1896 6.487200376004273239972437586589113E-1897 + 3150 3.243600188002136619986218793294557E-1897 1.621800094001068309993109396647278E-1897 + 3151 8.10900047000534154996554698323639E-1898 4.054500235002670774982773491618195E-1898 + 3152 2.027250117501335387491386745809098E-1898 1.013625058750667693745693372904549E-1898 + 3153 5.068125293753338468728466864522745E-1899 2.534062646876669234364233432261373E-1899 + 3154 1.267031323438334617182116716130687E-1899 6.335156617191673085910583580653433E-1900 + 3155 3.167578308595836542955291790326717E-1900 1.583789154297918271477645895163358E-1900 + 3156 7.91894577148959135738822947581679E-1901 3.959472885744795678694114737908395E-1901 + 3157 1.979736442872397839347057368954198E-1901 9.898682214361989196735286844770988E-1902 + 3158 4.949341107180994598367643422385494E-1902 2.474670553590497299183821711192747E-1902 + 3159 1.237335276795248649591910855596374E-1902 6.186676383976243247959554277981868E-1903 + 3160 3.093338191988121623979777138990934E-1903 1.546669095994060811989888569495467E-1903 + 3161 7.733345479970304059949442847477335E-1904 3.866672739985152029974721423738668E-1904 + 3162 1.933336369992576014987360711869334E-1904 9.66668184996288007493680355934667E-1905 + 3163 4.833340924981440037468401779673335E-1905 2.416670462490720018734200889836668E-1905 + 3164 1.208335231245360009367100444918334E-1905 6.04167615622680004683550222459167E-1906 + 3165 3.020838078113400023417751112295835E-1906 1.510419039056700011708875556147918E-1906 + 3166 7.55209519528350005854437778073959E-1907 3.776047597641750029272188890369795E-1907 + 3167 1.888023798820875014636094445184898E-1907 9.440118994104375073180472225924488E-1908 + 3168 4.720059497052187536590236112962244E-1908 2.360029748526093768295118056481122E-1908 + 3169 1.180014874263046884147559028240561E-1908 5.900074371315234420737795141202805E-1909 + 3170 2.950037185657617210368897570601403E-1909 1.475018592828808605184448785300701E-1909 + 3171 7.375092964144043025922243926503505E-1910 3.687546482072021512961121963251753E-1910 + 3172 1.843773241036010756480560981625877E-1910 9.218866205180053782402804908129383E-1911 + 3173 4.609433102590026891201402454064692E-1911 2.304716551295013445600701227032346E-1911 + 3174 1.152358275647506722800350613516173E-1911 5.761791378237533614001753067580865E-1912 + 3175 2.880895689118766807000876533790433E-1912 1.440447844559383403500438266895216E-1912 + 3176 7.20223922279691701750219133447608E-1913 3.60111961139845850875109566723804E-1913 + 3177 1.80055980569922925437554783361902E-1913 9.0027990284961462718777391680951E-1914 + 3178 4.50139951424807313593886958404755E-1914 2.250699757124036567969434792023775E-1914 + 3179 1.125349878562018283984717396011888E-1914 5.626749392810091419923586980059438E-1915 + 3180 2.813374696405045709961793490029719E-1915 1.406687348202522854980896745014860E-1915 + 3181 7.03343674101261427490448372507430E-1916 3.51671837050630713745224186253715E-1916 + 3182 1.758359185253153568726120931268575E-1916 8.791795926265767843630604656342875E-1917 + 3183 4.395897963132883921815302328171438E-1917 2.197948981566441960907651164085719E-1917 + 3184 1.098974490783220980453825582042860E-1917 5.494872453916104902269127910214298E-1918 + 3185 2.747436226958052451134563955107149E-1918 1.373718113479026225567281977553575E-1918 + 3186 6.868590567395131127836409887767875E-1919 3.434295283697565563918204943883938E-1919 + 3187 1.717147641848782781959102471941969E-1919 8.585738209243913909795512359709845E-1920 + 3188 4.292869104621956954897756179854923E-1920 2.146434552310978477448878089927461E-1920 + 3189 1.073217276155489238724439044963731E-1920 5.366086380777446193622195224818653E-1921 + 3190 2.683043190388723096811097612409327E-1921 1.341521595194361548405548806204663E-1921 + 3191 6.707607975971807742027744031023315E-1922 3.353803987985903871013872015511658E-1922 + 3192 1.676901993992951935506936007755829E-1922 8.384509969964759677534680038779145E-1923 + 3193 4.192254984982379838767340019389573E-1923 2.096127492491189919383670009694786E-1923 + 3194 1.048063746245594959691835004847393E-1923 5.240318731227974798459175024236965E-1924 + 3195 2.620159365613987399229587512118483E-1924 1.310079682806993699614793756059241E-1924 + 3196 6.550398414034968498073968780296205E-1925 3.275199207017484249036984390148103E-1925 + 3197 1.637599603508742124518492195074052E-1925 8.187998017543710622592460975370258E-1926 + 3198 4.093999008771855311296230487685129E-1926 2.046999504385927655648115243842565E-1926 + 3199 1.023499752192963827824057621921283E-1926 5.117498760964819139120288109606413E-1927 + 3200 2.558749380482409569560144054803207E-1927 1.279374690241204784780072027401603E-1927 + 3201 6.396873451206023923900360137008015E-1928 3.198436725603011961950180068504008E-1928 + 3202 1.599218362801505980975090034252004E-1928 7.99609181400752990487545017126002E-1929 + 3203 3.99804590700376495243772508563001E-1929 1.999022953501882476218862542815005E-1929 + 3204 9.995114767509412381094312714075025E-1930 4.997557383754706190547156357037513E-1930 + 3205 2.498778691877353095273578178518757E-1930 1.249389345938676547636789089259378E-1930 + 3206 6.24694672969338273818394544629689E-1931 3.123473364846691369091972723148445E-1931 + 3207 1.561736682423345684545986361574223E-1931 7.808683412116728422729931807871113E-1932 + 3208 3.904341706058364211364965903935557E-1932 1.952170853029182105682482951967778E-1932 + 3209 9.76085426514591052841241475983889E-1933 4.880427132572955264206207379919445E-1933 + 3210 2.440213566286477632103103689959723E-1933 1.220106783143238816051551844979861E-1933 + 3211 6.100533915716194080257759224899305E-1934 3.050266957858097040128879612449653E-1934 + 3212 1.525133478929048520064439806224827E-1934 7.625667394645242600322199031124133E-1935 + 3213 3.812833697322621300161099515562067E-1935 1.906416848661310650080549757781033E-1935 + 3214 9.532084243306553250402748788905165E-1936 4.766042121653276625201374394452583E-1936 + 3215 2.383021060826638312600687197226292E-1936 1.191510530413319156300343598613146E-1936 + 3216 5.95755265206659578150171799306573E-1937 2.978776326033297890750858996532865E-1937 + 3217 1.489388163016648945375429498266433E-1937 7.446940815083244726877147491332163E-1938 + 3218 3.723470407541622363438573745666082E-1938 1.861735203770811181719286872833041E-1938 + 3219 9.308676018854055908596434364165205E-1939 4.654338009427027954298217182082603E-1939 + 3220 2.327169004713513977149108591041302E-1939 1.163584502356756988574554295520651E-1939 + 3221 5.817922511783784942872771477603255E-1940 2.908961255891892471436385738801628E-1940 + 3222 1.454480627945946235718192869400814E-1940 7.27240313972973117859096434700407E-1941 + 3223 3.636201569864865589295482173502035E-1941 1.818100784932432794647741086751018E-1941 + 3224 9.09050392466216397323870543375509E-1942 4.545251962331081986619352716877545E-1942 + 3225 2.272625981165540993309676358438773E-1942 1.136312990582770496654838179219386E-1942 + 3226 5.68156495291385248327419089609693E-1943 2.840782476456926241637095448048465E-1943 + 3227 1.420391238228463120818547724024233E-1943 7.101956191142315604092738620121163E-1944 + 3228 3.550978095571157802046369310060582E-1944 1.775489047785578901023184655030291E-1944 + 3229 8.877445238927894505115923275151455E-1945 4.438722619463947252557961637575728E-1945 + 3230 2.219361309731973626278980818787864E-1945 1.109680654865986813139490409393932E-1945 + 3231 5.54840327432993406569745204696966E-1946 2.77420163716496703284872602348483E-1946 + 3232 1.387100818582483516424363011742415E-1946 6.935504092912417582121815058712075E-1947 + 3233 3.467752046456208791060907529356038E-1947 1.733876023228104395530453764678019E-1947 + 3234 8.669380116140521977652268823390095E-1948 4.334690058070260988826134411695048E-1948 + 3235 2.167345029035130494413067205847524E-1948 1.083672514517565247206533602923762E-1948 + 3236 5.41836257258782623603266801461881E-1949 2.709181286293913118016334007309405E-1949 + 3237 1.354590643146956559008167003654703E-1949 6.772953215734782795040835018273513E-1950 + 3238 3.386476607867391397520417509136757E-1950 1.693238303933695698760208754568378E-1950 + 3239 8.46619151966847849380104377284189E-1951 4.233095759834239246900521886420945E-1951 + 3240 2.116547879917119623450260943210473E-1951 1.058273939958559811725130471605236E-1951 + 3241 5.29136969979279905862565235802618E-1952 2.64568484989639952931282617901309E-1952 + 3242 1.322842424948199764656413089506545E-1952 6.614212124740998823282065447532725E-1953 + 3243 3.307106062370499411641032723766363E-1953 1.653553031185249705820516361883181E-1953 + 3244 8.267765155926248529102581809415905E-1954 4.133882577963124264551290904707953E-1954 + 3245 2.066941288981562132275645452353977E-1954 1.033470644490781066137822726176988E-1954 + 3246 5.16735322245390533068911363088494E-1955 2.58367661122695266534455681544247E-1955 + 3247 1.291838305613476332672278407721235E-1955 6.459191528067381663361392038606175E-1956 + 3248 3.229595764033690831680696019303088E-1956 1.614797882016845415840348009651544E-1956 + 3249 8.07398941008422707920174004825772E-1957 4.03699470504211353960087002412886E-1957 + 3250 2.01849735252105676980043501206443E-1957 1.009248676260528384900217506032215E-1957 + 3251 5.046243381302641924501087530161075E-1958 2.523121690651320962250543765080538E-1958 + 3252 1.261560845325660481125271882540269E-1958 6.307804226628302405626359412701345E-1959 + 3253 3.153902113314151202813179706350673E-1959 1.576951056657075601406589853175336E-1959 + 3254 7.88475528328537800703294926587668E-1960 3.94237764164268900351647463293834E-1960 + 3255 1.97118882082134450175823731646917E-1960 9.85594410410672250879118658234585E-1961 + 3256 4.927972052053361254395593291172925E-1961 2.463986026026680627197796645586463E-1961 + 3257 1.231993013013340313598898322793232E-1961 6.159965065066701567994491613966158E-1962 + 3258 3.079982532533350783997245806983079E-1962 1.539991266266675391998622903491540E-1962 + 3259 7.69995633133337695999311451745770E-1963 3.84997816566668847999655725872885E-1963 + 3260 1.924989082833344239998278629364425E-1963 9.624945414166721199991393146822125E-1964 + 3261 4.812472707083360599995696573411063E-1964 2.406236353541680299997848286705531E-1964 + 3262 1.203118176770840149998924143352766E-1964 6.015590883854200749994620716763828E-1965 + 3263 3.007795441927100374997310358381914E-1965 1.503897720963550187498655179190957E-1965 + 3264 7.519488604817750937493275895954785E-1966 3.759744302408875468746637947977393E-1966 + 3265 1.879872151204437734373318973988697E-1966 9.399360756022188671866594869943483E-1967 + 3266 4.699680378011094335933297434971742E-1967 2.349840189005547167966648717485871E-1967 + 3267 1.174920094502773583983324358742936E-1967 5.874600472513867919916621793714678E-1968 + 3268 2.937300236256933959958310896857339E-1968 1.468650118128466979979155448428670E-1968 + 3269 7.34325059064233489989577724214335E-1969 3.671625295321167449947888621071675E-1969 + 3270 1.835812647660583724973944310535838E-1969 9.179063238302918624869721552679188E-1970 + 3271 4.589531619151459312434860776339594E-1970 2.294765809575729656217430388169797E-1970 + 3272 1.147382904787864828108715194084899E-1970 5.736914523939324140543575970424493E-1971 + 3273 2.868457261969662070271787985212247E-1971 1.434228630984831035135893992606123E-1971 + 3274 7.171143154924155175679469963030615E-1972 3.585571577462077587839734981515308E-1972 + 3275 1.792785788731038793919867490757654E-1972 8.96392894365519396959933745378827E-1973 + 3276 4.481964471827596984799668726894135E-1973 2.240982235913798492399834363447068E-1973 + 3277 1.120491117956899246199917181723534E-1973 5.60245558978449623099958590861767E-1974 + 3278 2.801227794892248115499792954308835E-1974 1.400613897446124057749896477154418E-1974 + 3279 7.00306948723062028874948238577209E-1975 3.501534743615310144374741192886045E-1975 + 3280 1.750767371807655072187370596443023E-1975 8.753836859038275360936852982215113E-1976 + 3281 4.376918429519137680468426491107557E-1976 2.188459214759568840234213245553778E-1976 + 3282 1.094229607379784420117106622776889E-1976 5.471148036898922100585533113884445E-1977 + 3283 2.735574018449461050292766556942223E-1977 1.367787009224730525146383278471111E-1977 + 3284 6.838935046123652625731916392355555E-1978 3.419467523061826312865958196177778E-1978 + 3285 1.709733761530913156432979098088889E-1978 8.548668807654565782164895490444445E-1979 + 3286 4.274334403827282891082447745222223E-1979 2.137167201913641445541223872611111E-1979 + 3287 1.068583600956820722770611936305556E-1979 5.342918004784103613853059681527778E-1980 + 3288 2.671459002392051806926529840763889E-1980 1.335729501196025903463264920381945E-1980 + 3289 6.678647505980129517316324601909725E-1981 3.339323752990064758658162300954863E-1981 + 3290 1.669661876495032379329081150477432E-1981 8.348309382475161896645405752387158E-1982 + 3291 4.174154691237580948322702876193579E-1982 2.087077345618790474161351438096790E-1982 + 3292 1.043538672809395237080675719048395E-1982 5.217693364046976185403378595241975E-1983 + 3293 2.608846682023488092701689297620988E-1983 1.304423341011744046350844648810494E-1983 + 3294 6.52211670505872023175422324405247E-1984 3.261058352529360115877111622026235E-1984 + 3295 1.630529176264680057938555811013118E-1984 8.152645881323400289692779055065588E-1985 + 3296 4.076322940661700144846389527532794E-1985 2.038161470330850072423194763766397E-1985 + 3297 1.019080735165425036211597381883199E-1985 5.095403675827125181057986909415993E-1986 + 3298 2.547701837913562590528993454707997E-1986 1.273850918956781295264496727353998E-1986 + 3299 6.36925459478390647632248363676999E-1987 3.184627297391953238161241818384995E-1987 + 3300 1.592313648695976619080620909192498E-1987 7.961568243479883095403104545962488E-1988 + 3301 3.980784121739941547701552272981244E-1988 1.990392060869970773850776136490622E-1988 + 3302 9.95196030434985386925388068245311E-1989 4.975980152174926934626940341226555E-1989 + 3303 2.487990076087463467313470170613278E-1989 1.243995038043731733656735085306639E-1989 + 3304 6.219975190218658668283675426533195E-1990 3.109987595109329334141837713266598E-1990 + 3305 1.554993797554664667070918856633299E-1990 7.774968987773323335354594283166495E-1991 + 3306 3.887484493886661667677297141583248E-1991 1.943742246943330833838648570791624E-1991 + 3307 9.71871123471665416919324285395812E-1992 4.85935561735832708459662142697906E-1992 + 3308 2.42967780867916354229831071348953E-1992 1.214838904339581771149155356744765E-1992 + 3309 6.074194521697908855745776783723825E-1993 3.037097260848954427872888391861913E-1993 + 3310 1.518548630424477213936444195930957E-1993 7.592743152122386069682220979654783E-1994 + 3311 3.796371576061193034841110489827392E-1994 1.898185788030596517420555244913696E-1994 + 3312 9.49092894015298258710277622456848E-1995 4.74546447007649129355138811228424E-1995 + 3313 2.37273223503824564677569405614212E-1995 1.18636611751912282338784702807106E-1995 + 3314 5.9318305875956141169392351403553E-1996 2.96591529379780705846961757017765E-1996 + 3315 1.482957646898903529234808785088825E-1996 7.414788234494517646174043925444125E-1997 + 3316 3.707394117247258823087021962722063E-1997 1.853697058623629411543510981361031E-1997 + 3317 9.268485293118147057717554906805155E-1998 4.634242646559073528858777453402578E-1998 + 3318 2.317121323279536764429388726701289E-1998 1.158560661639768382214694363350645E-1998 + 3319 5.792803308198841911073471816753225E-1999 2.896401654099420955536735908376613E-1999 + 3320 1.448200827049710477768367954188307E-1999 7.241004135248552388841839770941533E-2000 + 3321 3.620502067624276194420919885470767E-2000 1.810251033812138097210459942735383E-2000 + 3322 9.051255169060690486052299713676915E-2001 4.525627584530345243026149856838458E-2001 + 3323 2.262813792265172621513074928419229E-2001 1.131406896132586310756537464209615E-2001 + 3324 5.657034480662931553782687321048075E-2002 2.828517240331465776891343660524038E-2002 + 3325 1.414258620165732888445671830262019E-2002 7.071293100828664442228359151310095E-2003 + 3326 3.535646550414332221114179575655048E-2003 1.767823275207166110557089787827524E-2003 + 3327 8.83911637603583055278544893913762E-2004 4.41955818801791527639272446956881E-2004 + 3328 2.209779094008957638196362234784405E-2004 1.104889547004478819098181117392203E-2004 + 3329 5.524447735022394095490905586961015E-2005 2.762223867511197047745452793480508E-2005 + 3330 1.381111933755598523872726396740254E-2005 6.90555966877799261936363198370127E-2006 + 3331 3.452779834388996309681815991850635E-2006 1.726389917194498154840907995925318E-2006 + 3332 8.63194958597249077420453997962659E-2007 4.315974792986245387102269989813295E-2007 + 3333 2.157987396493122693551134994906648E-2007 1.078993698246561346775567497453324E-2007 + 3334 5.39496849123280673387783748726662E-2008 2.69748424561640336693891874363331E-2008 + 3335 1.348742122808201683469459371816655E-2008 6.743710614041008417347296859083275E-2009 + 3336 3.371855307020504208673648429541638E-2009 1.685927653510252104336824214770819E-2009 + 3337 8.429638267551260521684121073854095E-2010 4.214819133775630260842060536927048E-2010 + 3338 2.107409566887815130421030268463524E-2010 1.053704783443907565210515134231762E-2010 + 3339 5.26852391721953782605257567115881E-2011 2.634261958609768913026287835579405E-2011 + 3340 1.317130979304884456513143917789703E-2011 6.585654896524422282565719588948513E-2012 + 3341 3.292827448262211141282859794474257E-2012 1.646413724131105570641429897237128E-2012 + 3342 8.23206862065552785320714948618564E-2013 4.11603431032776392660357474309282E-2013 + 3343 2.05801715516388196330178737154641E-2013 1.029008577581940981650893685773205E-2013 + 3344 5.145042887909704908254468428866025E-2014 2.572521443954852454127234214433013E-2014 + 3345 1.286260721977426227063617107216507E-2014 6.431303609887131135318085536082533E-2015 + 3346 3.215651804943565567659042768041267E-2015 1.607825902471782783829521384020633E-2015 + 3347 8.039129512358913919147606920103165E-2016 4.019564756179456959573803460051583E-2016 + 3348 2.009782378089728479786901730025792E-2016 1.004891189044864239893450865012896E-2016 + 3349 5.02445594522432119946725432506448E-2017 2.51222797261216059973362716253224E-2017 + 3350 1.25611398630608029986681358126612E-2017 6.2805699315304014993340679063306E-2018 + 3351 3.1402849657652007496670339531653E-2018 1.57014248288260037483351697658265E-2018 + 3352 7.85071241441300187416758488291325E-2019 3.925356207206500937083792441456625E-2019 + 3353 1.962678103603250468541896220728313E-2019 9.813390518016252342709481103641563E-2020 + 3354 4.906695259008126171354740551820782E-2020 2.453347629504063085677370275910391E-2020 + 3355 1.226673814752031542838685137955196E-2020 6.133369073760157714193425689775978E-2021 + 3356 3.066684536880078857096712844887989E-2021 1.533342268440039428548356422443995E-2021 + 3357 7.666711342200197142741782112219975E-2022 3.833355671100098571370891056109988E-2022 + 3358 1.916677835550049285685445528054994E-2022 9.58338917775024642842722764027497E-2023 + 3359 4.791694588875123214213613820137485E-2023 2.395847294437561607106806910068743E-2023 + 3360 1.197923647218780803553403455034372E-2023 5.989618236093904017767017275171858E-2024 + 3361 2.994809118046952008883508637585929E-2024 1.497404559023476004441754318792965E-2024 + 3362 7.487022795117380022208771593964825E-2025 3.743511397558690011104385796982413E-2025 + 3363 1.871755698779345005552192898491207E-2025 9.358778493896725027760964492456033E-2026 + 3364 4.679389246948362513880482246228017E-2026 2.339694623474181256940241123114008E-2026 + 3365 1.169847311737090628470120561557004E-2026 5.84923655868545314235060280778502E-2027 + 3366 2.92461827934272657117530140389251E-2027 1.462309139671363285587650701946255E-2027 + 3367 7.311545698356816427938253509731275E-2028 3.655772849178408213969126754865638E-2028 + 3368 1.827886424589204106984563377432819E-2028 9.139432122946020534922816887164095E-2029 + 3369 4.569716061473010267461408443582048E-2029 2.284858030736505133730704221791024E-2029 + 3370 1.142429015368252566865352110895512E-2029 5.71214507684126283432676055447756E-2030 + 3371 2.85607253842063141716338027723878E-2030 1.42803626921031570858169013861939E-2030 + 3372 7.14018134605157854290845069309695E-2031 3.570090673025789271454225346548475E-2031 + 3373 1.785045336512894635727112673274238E-2031 8.925226682564473178635563366371188E-2032 + 3374 4.462613341282236589317781683185594E-2032 2.231306670641118294658890841592797E-2032 + 3375 1.115653335320559147329445420796399E-2032 5.578266676602795736647227103981993E-2033 + 3376 2.789133338301397868323613551990997E-2033 1.394566669150698934161806775995498E-2033 + 3377 6.97283334575349467080903387997749E-2034 3.486416672876747335404516939988745E-2034 + 3378 1.743208336438373667702258469994373E-2034 8.716041682191868338511292349971863E-2035 + 3379 4.358020841095934169255646174985932E-2035 2.179010420547967084627823087492966E-2035 + 3380 1.089505210273983542313911543746483E-2035 5.447526051369917711569557718732415E-2036 + 3381 2.723763025684958855784778859366208E-2036 1.361881512842479427892389429683104E-2036 + 3382 6.80940756421239713946194714841552E-2037 3.40470378210619856973097357420776E-2037 + 3383 1.70235189105309928486548678710388E-2037 8.5117594552654964243274339355194E-2038 + 3384 4.2558797276327482121637169677597E-2038 2.12793986381637410608185848387985E-2038 + 3385 1.063969931908187053040929241939925E-2038 5.319849659540935265204646209699625E-2039 + 3386 2.659924829770467632602323104849813E-2039 1.329962414885233816301161552424906E-2039 + 3387 6.64981207442616908150580776212453E-2040 3.324906037213084540752903881062265E-2040 + 3388 1.662453018606542270376451940531133E-2040 8.312265093032711351882259702655663E-2041 + 3389 4.156132546516355675941129851327832E-2041 2.078066273258177837970564925663916E-2041 + 3390 1.039033136629088918985282462831958E-2041 5.19516568314544459492641231415979E-2042 + 3391 2.597582841572722297463206157079895E-2042 1.298791420786361148731603078539948E-2042 + 3392 6.49395710393180574365801539269974E-2043 3.24697855196590287182900769634987E-2043 + 3393 1.623489275982951435914503848174935E-2043 8.117446379914757179572519240874675E-2044 + 3394 4.058723189957378589786259620437338E-2044 2.029361594978689294893129810218669E-2044 + 3395 1.014680797489344647446564905109335E-2044 5.073403987446723237232824525546673E-2045 + 3396 2.536701993723361618616412262773337E-2045 1.268350996861680809308206131386668E-2045 + 3397 6.34175498430840404654103065693334E-2046 3.17087749215420202327051532846667E-2046 + 3398 1.585438746077101011635257664233335E-2046 7.927193730385505058176288321166675E-2047 + 3399 3.963596865192752529088144160583338E-2047 1.981798432596376264544072080291669E-2047 + 3400 9.908992162981881322720360401458345E-2048 4.954496081490940661360180200729173E-2048 + 3401 2.477248040745470330680090100364587E-2048 1.238624020372735165340045050182293E-2048 + 3402 6.193120101863675826700225250911465E-2049 3.096560050931837913350112625455733E-2049 + 3403 1.548280025465918956675056312727867E-2049 7.741400127329594783375281563639333E-2050 + 3404 3.870700063664797391687640781819667E-2050 1.935350031832398695843820390909833E-2050 + 3405 9.676750159161993479219101954549165E-2051 4.838375079580996739609550977274583E-2051 + 3406 2.419187539790498369804775488637292E-2051 1.209593769895249184902387744318646E-2051 + 3407 6.04796884947624592451193872159323E-2052 3.023984424738122962255969360796615E-2052 + 3408 1.511992212369061481127984680398308E-2052 7.559961061845307405639923401991538E-2053 + 3409 3.779980530922653702819961700995769E-2053 1.889990265461326851409980850497885E-2053 + 3410 9.449951327306634257049904252489425E-2054 4.724975663653317128524952126244713E-2054 + 3411 2.362487831826658564262476063122357E-2054 1.181243915913329282131238031561178E-2054 + 3412 5.90621957956664641065619015780589E-2055 2.953109789783323205328095078902945E-2055 + 3413 1.476554894891661602664047539451473E-2055 7.382774474458308013320237697257363E-2056 + 3414 3.691387237229154006660118848628682E-2056 1.845693618614577003330059424314341E-2056 + 3415 9.228468093072885016650297121571705E-2057 4.614234046536442508325148560785853E-2057 + 3416 2.307117023268221254162574280392927E-2057 1.153558511634110627081287140196463E-2057 + 3417 5.767792558170553135406435700982315E-2058 2.883896279085276567703217850491158E-2058 + 3418 1.441948139542638283851608925245579E-2058 7.209740697713191419258044626227895E-2059 + 3419 3.604870348856595709629022313113948E-2059 1.802435174428297854814511156556974E-2059 + 3420 9.01217587214148927407255578278487E-2060 4.506087936070744637036277891392435E-2060 + 3421 2.253043968035372318518138945696218E-2060 1.126521984017686159259069472848109E-2060 + 3422 5.632609920088430796295347364240545E-2061 2.816304960044215398147673682120273E-2061 + 3423 1.408152480022107699073836841060137E-2061 7.040762400110538495369184205300683E-2062 + 3424 3.520381200055269247684592102650342E-2062 1.760190600027634623842296051325171E-2062 + 3425 8.800953000138173119211480256625855E-2063 4.400476500069086559605740128312928E-2063 + 3426 2.200238250034543279802870064156464E-2063 1.100119125017271639901435032078232E-2063 + 3427 5.50059562508635819950717516039116E-2064 2.75029781254317909975358758019558E-2064 + 3428 1.37514890627158954987679379009779E-2064 6.87574453135794774938396895048895E-2065 + 3429 3.437872265678973874691984475244475E-2065 1.718936132839486937345992237622238E-2065 + 3430 8.59468066419743468672996118811119E-2066 4.297340332098717343364980594055595E-2066 + 3431 2.148670166049358671682490297027798E-2066 1.074335083024679335841245148513899E-2066 + 3432 5.371675415123396679206225742569495E-2067 2.685837707561698339603112871284748E-2067 + 3433 1.342918853780849169801556435642374E-2067 6.71459426890424584900778217821187E-2068 + 3434 3.357297134452122924503891089105935E-2068 1.678648567226061462251945544552968E-2068 + 3435 8.39324283613030731125972772276484E-2069 4.19662141806515365562986386138242E-2069 + 3436 2.09831070903257682781493193069121E-2069 1.049155354516288413907465965345605E-2069 + 3437 5.245776772581442069537329826728025E-2070 2.622888386290721034768664913364013E-2070 + 3438 1.311444193145360517384332456682007E-2070 6.557220965726802586921662283410033E-2071 + 3439 3.278610482863401293460831141705017E-2071 1.639305241431700646730415570852508E-2071 + 3440 8.19652620715850323365207785426254E-2072 4.09826310357925161682603892713127E-2072 + 3441 2.049131551789625808413019463565635E-2072 1.024565775894812904206509731782818E-2072 + 3442 5.12282887947406452103254865891409E-2073 2.561414439737032260516274329457045E-2073 + 3443 1.280707219868516130258137164728523E-2073 6.403536099342580651290685823642613E-2074 + 3444 3.201768049671290325645342911821307E-2074 1.600884024835645162822671455910653E-2074 + 3445 8.004420124178225814113357279553265E-2075 4.002210062089112907056678639776633E-2075 + 3446 2.001105031044556453528339319888317E-2075 1.000552515522278226764169659944158E-2075 + 3447 5.00276257761139113382084829972079E-2076 2.501381288805695566910424149860395E-2076 + 3448 1.250690644402847783455212074930198E-2076 6.253453222014238917276060374650988E-2077 + 3449 3.126726611007119458638030187325494E-2077 1.563363305503559729319015093662747E-2077 + 3450 7.816816527517798646595075468313735E-2078 3.908408263758899323297537734156868E-2078 + 3451 1.954204131879449661648768867078434E-2078 9.77102065939724830824384433539217E-2079 + 3452 4.885510329698624154121922167696085E-2079 2.442755164849312077060961083848043E-2079 + 3453 1.221377582424656038530480541924022E-2079 6.106887912123280192652402709620108E-2080 + 3454 3.053443956061640096326201354810054E-2080 1.526721978030820048163100677405027E-2080 + 3455 7.633609890154100240815503387025135E-2081 3.816804945077050120407751693512568E-2081 + 3456 1.908402472538525060203875846756284E-2081 9.54201236269262530101937923378142E-2082 + 3457 4.77100618134631265050968961689071E-2082 2.385503090673156325254844808445355E-2082 + 3458 1.192751545336578162627422404222678E-2082 5.963757726682890813137112021113388E-2083 + 3459 2.981878863341445406568556010556694E-2083 1.490939431670722703284278005278347E-2083 + 3460 7.454697158353613516421390026391735E-2084 3.727348579176806758210695013195868E-2084 + 3461 1.863674289588403379105347506597934E-2084 9.31837144794201689552673753298967E-2085 + 3462 4.659185723971008447763368766494835E-2085 2.329592861985504223881684383247418E-2085 + 3463 1.164796430992752111940842191623709E-2085 5.823982154963760559704210958118545E-2086 + 3464 2.911991077481880279852105479059273E-2086 1.455995538740940139926052739529636E-2086 + 3465 7.27997769370470069963026369764818E-2087 3.63998884685235034981513184882409E-2087 + 3466 1.819994423426175174907565924412045E-2087 9.099972117130875874537829622060225E-2088 + 3467 4.549986058565437937268914811030113E-2088 2.274993029282718968634457405515056E-2088 + 3468 1.137496514641359484317228702757528E-2088 5.68748257320679742158614351378764E-2089 + 3469 2.84374128660339871079307175689382E-2089 1.42187064330169935539653587844691E-2089 + 3470 7.10935321650849677698267939223455E-2090 3.554676608254248388491339696117275E-2090 + 3471 1.777338304127124194245669848058638E-2090 8.886691520635620971228349240293188E-2091 + 3472 4.443345760317810485614174620146594E-2091 2.221672880158905242807087310073297E-2091 + 3473 1.110836440079452621403543655036649E-2091 5.554182200397263107017718275183243E-2092 + 3474 2.777091100198631553508859137591622E-2092 1.388545550099315776754429568795811E-2092 + 3475 6.942727750496578883772147843979055E-2093 3.471363875248289441886073921989528E-2093 + 3476 1.735681937624144720943036960994764E-2093 8.67840968812072360471518480497382E-2094 + 3477 4.33920484406036180235759240248691E-2094 2.169602422030180901178796201243455E-2094 + 3478 1.084801211015090450589398100621728E-2094 5.424006055075452252946990503108638E-2095 + 3479 2.712003027537726126473495251554319E-2095 1.356001513768863063236747625777160E-2095 + 3480 6.78000756884431531618373812888580E-2096 3.39000378442215765809186906444290E-2096 + 3481 1.69500189221107882904593453222145E-2096 8.47500946105539414522967266110725E-2097 + 3482 4.237504730527697072614836330553625E-2097 2.118752365263848536307418165276813E-2097 + 3483 1.059376182631924268153709082638407E-2097 5.296880913159621340768545413192033E-2098 + 3484 2.648440456579810670384272706596017E-2098 1.324220228289905335192136353298008E-2098 + 3485 6.62110114144952667596068176649004E-2099 3.31055057072476333798034088324502E-2099 + 3486 1.65527528536238166899017044162251E-2099 8.27637642681190834495085220811255E-2100 + 3487 4.138188213405954172475426104056275E-2100 2.069094106702977086237713052028138E-2100 + 3488 1.034547053351488543118856526014069E-2100 5.172735266757442715594282630070345E-2101 + 3489 2.586367633378721357797141315035173E-2101 1.293183816689360678898570657517586E-2101 + 3490 6.46591908344680339449285328758793E-2102 3.232959541723401697246426643793965E-2102 + 3491 1.616479770861700848623213321896983E-2102 8.082398854308504243116066609484913E-2103 + 3492 4.041199427154252121558033304742457E-2103 2.020599713577126060779016652371228E-2103 + 3493 1.010299856788563030389508326185614E-2103 5.05149928394281515194754163092807E-2104 + 3494 2.525749641971407575973770815464035E-2104 1.262874820985703787986885407732018E-2104 + 3495 6.31437410492851893993442703866009E-2105 3.157187052464259469967213519330045E-2105 + 3496 1.578593526232129734983606759665023E-2105 7.892967631160648674918033798325113E-2106 + 3497 3.946483815580324337459016899162557E-2106 1.973241907790162168729508449581278E-2106 + 3498 9.86620953895081084364754224790639E-2107 4.933104769475405421823771123953195E-2107 + 3499 2.466552384737702710911885561976598E-2107 1.233276192368851355455942780988299E-2107 + 3500 6.166380961844256777279713904941495E-2108 3.083190480922128388639856952470748E-2108 + 3501 1.541595240461064194319928476235374E-2108 7.70797620230532097159964238117687E-2109 + 3502 3.853988101152660485799821190588435E-2109 1.926994050576330242899910595294218E-2109 + 3503 9.63497025288165121449955297647109E-2110 4.817485126440825607249776488235545E-2110 + 3504 2.408742563220412803624888244117773E-2110 1.204371281610206401812444122058886E-2110 + 3505 6.02185640805103200906222061029443E-2111 3.010928204025516004531110305147215E-2111 + 3506 1.505464102012758002265555152573608E-2111 7.527320510063790011327775762868038E-2112 + 3507 3.763660255031895005663887881434019E-2112 1.881830127515947502831943940717010E-2112 + 3508 9.40915063757973751415971970358505E-2113 4.704575318789868757079859851792525E-2113 + 3509 2.352287659394934378539929925896263E-2113 1.176143829697467189269964962948131E-2113 + 3510 5.880719148487335946349824814740655E-2114 2.940359574243667973174912407370328E-2114 + 3511 1.470179787121833986587456203685164E-2114 7.35089893560916993293728101842582E-2115 + 3512 3.67544946780458496646864050921291E-2115 1.837724733902292483234320254606455E-2115 + 3513 9.188623669511462416171601273032275E-2116 4.594311834755731208085800636516138E-2116 + 3514 2.297155917377865604042900318258069E-2116 1.148577958688932802021450159129035E-2116 + 3515 5.742889793444664010107250795645175E-2117 2.871444896722332005053625397822588E-2117 + 3516 1.435722448361166002526812698911294E-2117 7.17861224180583001263406349455647E-2118 + 3517 3.589306120902915006317031747278235E-2118 1.794653060451457503158515873639118E-2118 + 3518 8.97326530225728751579257936819559E-2119 4.486632651128643757896289684097795E-2119 + 3519 2.243316325564321878948144842048898E-2119 1.121658162782160939474072421024449E-2119 + 3520 5.608290813910804697370362105122245E-2120 2.804145406955402348685181052561123E-2120 + 3521 1.402072703477701174342590526280562E-2120 7.010363517388505871712952631402808E-2121 + 3522 3.505181758694252935856476315701404E-2121 1.752590879347126467928238157850702E-2121 + 3523 8.76295439673563233964119078925351E-2122 4.381477198367816169820595394626755E-2122 + 3524 2.190738599183908084910297697313378E-2122 1.095369299591954042455148848656689E-2122 + 3525 5.476846497959770212275744243283445E-2123 2.738423248979885106137872121641723E-2123 + 3526 1.369211624489942553068936060820862E-2123 6.846058122449712765344680304104308E-2124 + 3527 3.423029061224856382672340152052154E-2124 1.711514530612428191336170076026077E-2124 + 3528 8.557572653062140956680850380130385E-2125 4.278786326531070478340425190065193E-2125 + 3529 2.139393163265535239170212595032597E-2125 1.069696581632767619585106297516298E-2125 + 3530 5.34848290816383809792553148758149E-2126 2.674241454081919048962765743790745E-2126 + 3531 1.337120727040959524481382871895373E-2126 6.685603635204797622406914359476863E-2127 + 3532 3.342801817602398811203457179738432E-2127 1.671400908801199405601728589869216E-2127 + 3533 8.35700454400599702800864294934608E-2128 4.17850227200299851400432147467304E-2128 + 3534 2.08925113600149925700216073733652E-2128 1.04462556800074962850108036866826E-2128 + 3535 5.2231278400037481425054018433413E-2129 2.61156392000187407125270092167065E-2129 + 3536 1.305781960000937035626350460835325E-2129 6.528909800004685178131752304176625E-2130 + 3537 3.264454900002342589065876152088313E-2130 1.632227450001171294532938076044156E-2130 + 3538 8.16113725000585647266469038022078E-2131 4.08056862500292823633234519011039E-2131 + 3539 2.040284312501464118166172595055195E-2131 1.020142156250732059083086297527598E-2131 + 3540 5.10071078125366029541543148763799E-2132 2.550355390626830147707715743818995E-2132 + 3541 1.275177695313415073853857871909498E-2132 6.375888476567075369269289359547488E-2133 + 3542 3.187944238283537684634644679773744E-2133 1.593972119141768842317322339886872E-2133 + 3543 7.96986059570884421158661169943436E-2134 3.98493029785442210579330584971718E-2134 + 3544 1.99246514892721105289665292485859E-2134 9.96232574463605526448326462429295E-2135 + 3545 4.981162872318027632241632312146475E-2135 2.490581436159013816120816156073238E-2135 + 3546 1.245290718079506908060408078036619E-2135 6.226453590397534540302040390183095E-2136 + 3547 3.113226795198767270151020195091548E-2136 1.556613397599383635075510097545774E-2136 + 3548 7.78306698799691817537755048772887E-2137 3.891533493998459087688775243864435E-2137 + 3549 1.945766746999229543844387621932218E-2137 9.728833734996147719221938109661088E-2138 + 3550 4.864416867498073859610969054830544E-2138 2.432208433749036929805484527415272E-2138 + 3551 1.216104216874518464902742263707636E-2138 6.08052108437259232451371131853818E-2139 + 3552 3.04026054218629616225685565926909E-2139 1.520130271093148081128427829634545E-2139 + 3553 7.600651355465740405642139148172725E-2140 3.800325677732870202821069574086363E-2140 + 3554 1.900162838866435101410534787043182E-2140 9.500814194332175507052673935215908E-2141 + 3555 4.750407097166087753526336967607954E-2141 2.375203548583043876763168483803977E-2141 + 3556 1.187601774291521938381584241901989E-2141 5.938008871457609691907921209509943E-2142 + 3557 2.969004435728804845953960604754972E-2142 1.484502217864402422976980302377486E-2142 + 3558 7.42251108932201211488490151188743E-2143 3.711255544661006057442450755943715E-2143 + 3559 1.855627772330503028721225377971858E-2143 9.278138861652515143606126889859288E-2144 + 3560 4.639069430826257571803063444929644E-2144 2.319534715413128785901531722464822E-2144 + 3561 1.159767357706564392950765861232411E-2144 5.798836788532821964753829306162055E-2145 + 3562 2.899418394266410982376914653081028E-2145 1.449709197133205491188457326540514E-2145 + 3563 7.24854598566602745594228663270257E-2146 3.624272992833013727971143316351285E-2146 + 3564 1.812136496416506863985571658175643E-2146 9.060682482082534319927858290878213E-2147 + 3565 4.530341241041267159963929145439107E-2147 2.265170620520633579981964572719553E-2147 + 3566 1.132585310260316789990982286359777E-2147 5.662926551301583949954911431798883E-2148 + 3567 2.831463275650791974977455715899442E-2148 1.415731637825395987488727857949721E-2148 + 3568 7.078658189126979937443639289748605E-2149 3.539329094563489968721819644874303E-2149 + 3569 1.769664547281744984360909822437152E-2149 8.848322736408724921804549112185758E-2150 + 3570 4.424161368204362460902274556092879E-2150 2.212080684102181230451137278046440E-2150 + 3571 1.106040342051090615225568639023220E-2150 5.53020171025545307612784319511610E-2151 + 3572 2.76510085512772653806392159755805E-2151 1.382550427563863269031960798779025E-2151 + 3573 6.912752137819316345159803993895125E-2152 3.456376068909658172579901996947563E-2152 + 3574 1.728188034454829086289950998473782E-2152 8.640940172274145431449754992368908E-2153 + 3575 4.320470086137072715724877496184454E-2153 2.160235043068536357862438748092227E-2153 + 3576 1.080117521534268178931219374046114E-2153 5.400587607671340894656096870230568E-2154 + 3577 2.700293803835670447328048435115284E-2154 1.350146901917835223664024217557642E-2154 + 3578 6.75073450958917611832012108778821E-2155 3.375367254794588059160060543894105E-2155 + 3579 1.687683627397294029580030271947053E-2155 8.438418136986470147900151359735263E-2156 + 3580 4.219209068493235073950075679867632E-2156 2.109604534246617536975037839933816E-2156 + 3581 1.054802267123308768487518919966908E-2156 5.27401133561654384243759459983454E-2157 + 3582 2.63700566780827192121879729991727E-2157 1.318502833904135960609398649958635E-2157 + 3583 6.592514169520679803046993249793175E-2158 3.296257084760339901523496624896588E-2158 + 3584 1.648128542380169950761748312448294E-2158 8.24064271190084975380874156224147E-2159 + 3585 4.120321355950424876904370781120735E-2159 2.060160677975212438452185390560368E-2159 + 3586 1.030080338987606219226092695280184E-2159 5.15040169493803109613046347640092E-2160 + 3587 2.57520084746901554806523173820046E-2160 1.28760042373450777403261586910023E-2160 + 3588 6.43800211867253887016307934550115E-2161 3.219001059336269435081539672750575E-2161 + 3589 1.609500529668134717540769836375288E-2161 8.047502648340673587703849181876438E-2162 + 3590 4.023751324170336793851924590938219E-2162 2.011875662085168396925962295469110E-2162 + 3591 1.005937831042584198462981147734555E-2162 5.029689155212920992314905738672775E-2163 + 3592 2.514844577606460496157452869336388E-2163 1.257422288803230248078726434668194E-2163 + 3593 6.28711144401615124039363217334097E-2164 3.143555722008075620196816086670485E-2164 + 3594 1.571777861004037810098408043335243E-2164 7.858889305020189050492040216676213E-2165 + 3595 3.929444652510094525246020108338107E-2165 1.964722326255047262623010054169053E-2165 + 3596 9.823611631275236313115050270845265E-2166 4.911805815637618156557525135422633E-2166 + 3597 2.455902907818809078278762567711317E-2166 1.227951453909404539139381283855658E-2166 + 3598 6.13975726954702269569690641927829E-2167 3.069878634773511347848453209639145E-2167 + 3599 1.534939317386755673924226604819573E-2167 7.674696586933778369621133024097863E-2168 + 3600 3.837348293466889184810566512048932E-2168 1.918674146733444592405283256024466E-2168 + 3601 9.59337073366722296202641628012233E-2169 4.796685366833611481013208140061165E-2169 + 3602 2.398342683416805740506604070030583E-2169 1.199171341708402870253302035015291E-2169 + 3603 5.995856708542014351266510175076455E-2170 2.997928354271007175633255087538228E-2170 + 3604 1.498964177135503587816627543769114E-2170 7.49482088567751793908313771884557E-2171 + 3605 3.747410442838758969541568859422785E-2171 1.873705221419379484770784429711393E-2171 + 3606 9.368526107096897423853922148556965E-2172 4.684263053548448711926961074278483E-2172 + 3607 2.342131526774224355963480537139242E-2172 1.171065763387112177981740268569621E-2172 + 3608 5.855328816935560889908701342848105E-2173 2.927664408467780444954350671424053E-2173 + 3609 1.463832204233890222477175335712027E-2173 7.319161021169451112385876678560133E-2174 + 3610 3.659580510584725556192938339280067E-2174 1.829790255292362778096469169640033E-2174 + 3611 9.148951276461813890482345848200165E-2175 4.574475638230906945241172924100083E-2175 + 3612 2.287237819115453472620586462050042E-2175 1.143618909557726736310293231025021E-2175 + 3613 5.718094547788633681551466155125105E-2176 2.859047273894316840775733077562553E-2176 + 3614 1.429523636947158420387866538781277E-2176 7.147618184735792101939332693906383E-2177 + 3615 3.573809092367896050969666346953192E-2177 1.786904546183948025484833173476596E-2177 + 3616 8.93452273091974012742416586738298E-2178 4.46726136545987006371208293369149E-2178 + 3617 2.233630682729935031856041466845745E-2178 1.116815341364967515928020733422873E-2178 + 3618 5.584076706824837579640103667114365E-2179 2.792038353412418789820051833557183E-2179 + 3619 1.396019176706209394910025916778592E-2179 6.980095883531046974550129583892958E-2180 + 3620 3.490047941765523487275064791946479E-2180 1.745023970882761743637532395973240E-2180 + 3621 8.72511985441380871818766197986620E-2181 4.36255992720690435909383098993310E-2181 + 3622 2.18127996360345217954691549496655E-2181 1.090639981801726089773457747483275E-2181 + 3623 5.453199909008630448867288737416375E-2182 2.726599954504315224433644368708188E-2182 + 3624 1.363299977252157612216822184354094E-2182 6.81649988626078806108411092177047E-2183 + 3625 3.408249943130394030542055460885235E-2183 1.704124971565197015271027730442618E-2183 + 3626 8.52062485782598507635513865221309E-2184 4.260312428912992538177569326106545E-2184 + 3627 2.130156214456496269088784663053273E-2184 1.065078107228248134544392331526636E-2184 + 3628 5.32539053614124067272196165763318E-2185 2.66269526807062033636098082881659E-2185 + 3629 1.331347634035310168180490414408295E-2185 6.656738170176550840902452072041475E-2186 + 3630 3.328369085088275420451226036020738E-2186 1.664184542544137710225613018010369E-2186 + 3631 8.320922712720688551128065090051845E-2187 4.160461356360344275564032545025923E-2187 + 3632 2.080230678180172137782016272512962E-2187 1.040115339090086068891008136256481E-2187 + 3633 5.200576695450430344455040681282405E-2188 2.600288347725215172227520340641203E-2188 + 3634 1.300144173862607586113760170320602E-2188 6.500720869313037930568800851603008E-2189 + 3635 3.250360434656518965284400425801504E-2189 1.625180217328259482642200212900752E-2189 + 3636 8.12590108664129741321100106450376E-2190 4.06295054332064870660550053225188E-2190 + 3637 2.03147527166032435330275026612594E-2190 1.01573763583016217665137513306297E-2190 + 3638 5.07868817915081088325687566531485E-2191 2.539344089575405441628437832657425E-2191 + 3639 1.269672044787702720814218916328713E-2191 6.348360223938513604071094581643563E-2192 + 3640 3.174180111969256802035547290821782E-2192 1.587090055984628401017773645410891E-2192 + 3641 7.935450279923142005088868227054455E-2193 3.967725139961571002544434113527228E-2193 + 3642 1.983862569980785501272217056763614E-2193 9.91931284990392750636108528381807E-2194 + 3643 4.959656424951963753180542641909035E-2194 2.479828212475981876590271320954518E-2194 + 3644 1.239914106237990938295135660477259E-2194 6.199570531189954691475678302386295E-2195 + 3645 3.099785265594977345737839151193148E-2195 1.549892632797488672868919575596574E-2195 + 3646 7.74946316398744336434459787798287E-2196 3.874731581993721682172298938991435E-2196 + 3647 1.937365790996860841086149469495718E-2196 9.686828954984304205430747347478588E-2197 + 3648 4.843414477492152102715373673739294E-2197 2.421707238746076051357686836869647E-2197 + 3649 1.210853619373038025678843418434824E-2197 6.054268096865190128394217092174118E-2198 + 3650 3.027134048432595064197108546087059E-2198 1.513567024216297532098554273043530E-2198 + 3651 7.56783512108148766049277136521765E-2199 3.783917560540743830246385682608825E-2199 + 3652 1.891958780270371915123192841304413E-2199 9.459793901351859575615964206522063E-2200 + 3653 4.729896950675929787807982103261032E-2200 2.364948475337964893903991051630516E-2200 + 3654 1.182474237668982446951995525815258E-2200 5.91237118834491223475997762907629E-2201 + 3655 2.956185594172456117379988814538145E-2201 1.478092797086228058689994407269073E-2201 + 3656 7.390463985431140293449972036345365E-2202 3.695231992715570146724986018172683E-2202 + 3657 1.847615996357785073362493009086342E-2202 9.238079981788925366812465045431708E-2203 + 3658 4.619039990894462683406232522715854E-2203 2.309519995447231341703116261357927E-2203 + 3659 1.154759997723615670851558130678964E-2203 5.773799988618078354257790653394818E-2204 + 3660 2.886899994309039177128895326697409E-2204 1.443449997154519588564447663348705E-2204 + 3661 7.217249985772597942822238316743525E-2205 3.608624992886298971411119158371763E-2205 + 3662 1.804312496443149485705559579185882E-2205 9.021562482215747428527797895929408E-2206 + 3663 4.510781241107873714263898947964704E-2206 2.255390620553936857131949473982352E-2206 + 3664 1.127695310276968428565974736991176E-2206 5.63847655138484214282987368495588E-2207 + 3665 2.81923827569242107141493684247794E-2207 1.40961913784621053570746842123897E-2207 + 3666 7.04809568923105267853734210619485E-2208 3.524047844615526339268671053097425E-2208 + 3667 1.762023922307763169634335526548713E-2208 8.810119611538815848171677632743563E-2209 + 3668 4.405059805769407924085838816371782E-2209 2.202529902884703962042919408185891E-2209 + 3669 1.101264951442351981021459704092946E-2209 5.506324757211759905107298520464728E-2210 + 3670 2.753162378605879952553649260232364E-2210 1.376581189302939976276824630116182E-2210 + 3671 6.88290594651469988138412315058091E-2211 3.441452973257349940692061575290455E-2211 + 3672 1.720726486628674970346030787645228E-2211 8.603632433143374851730153938226138E-2212 + 3673 4.301816216571687425865076969113069E-2212 2.150908108285843712932538484556535E-2212 + 3674 1.075454054142921856466269242278268E-2212 5.377270270714609282331346211391338E-2213 + 3675 2.688635135357304641165673105695669E-2213 1.344317567678652320582836552847835E-2213 + 3676 6.721587838393261602914182764239175E-2214 3.360793919196630801457091382119588E-2214 + 3677 1.680396959598315400728545691059794E-2214 8.40198479799157700364272845529897E-2215 + 3678 4.200992398995788501821364227649485E-2215 2.100496199497894250910682113824743E-2215 + 3679 1.050248099748947125455341056912372E-2215 5.251240498744735627276705284561858E-2216 + 3680 2.625620249372367813638352642280929E-2216 1.312810124686183906819176321140465E-2216 + 3681 6.564050623430919534095881605702325E-2217 3.282025311715459767047940802851163E-2217 + 3682 1.641012655857729883523970401425582E-2217 8.205063279288649417619852007127908E-2218 + 3683 4.102531639644324708809926003563954E-2218 2.051265819822162354404963001781977E-2218 + 3684 1.025632909911081177202481500890989E-2218 5.128164549555405886012407504454943E-2219 + 3685 2.564082274777702943006203752227472E-2219 1.282041137388851471503101876113736E-2219 + 3686 6.41020568694425735751550938056868E-2220 3.20510284347212867875775469028434E-2220 + 3687 1.60255142173606433937887734514217E-2220 8.01275710868032169689438672571085E-2221 + 3688 4.006378554340160848447193362855425E-2221 2.003189277170080424223596681427713E-2221 + 3689 1.001594638585040212111798340713857E-2221 5.007973192925201060558991703569283E-2222 + 3690 2.503986596462600530279495851784642E-2222 1.251993298231300265139747925892321E-2222 + 3691 6.259966491156501325698739629461605E-2223 3.129983245578250662849369814730803E-2223 + 3692 1.564991622789125331424684907365402E-2223 7.824958113945626657123424536827008E-2224 + 3693 3.912479056972813328561712268413504E-2224 1.956239528486406664280856134206752E-2224 + 3694 9.78119764243203332140428067103376E-2225 4.89059882121601666070214033551688E-2225 + 3695 2.44529941060800833035107016775844E-2225 1.22264970530400416517553508387922E-2225 + 3696 6.1132485265200208258776754193961E-2226 3.05662426326001041293883770969805E-2226 + 3697 1.528312131630005206469418854849025E-2226 7.641560658150026032347094274245125E-2227 + 3698 3.820780329075013016173547137122563E-2227 1.910390164537506508086773568561281E-2227 + 3699 9.551950822687532540433867842806405E-2228 4.775975411343766270216933921403203E-2228 + 3700 2.387987705671883135108466960701602E-2228 1.193993852835941567554233480350801E-2228 + 3701 5.969969264179707837771167401754005E-2229 2.984984632089853918885583700877003E-2229 + 3702 1.492492316044926959442791850438502E-2229 7.462461580224634797213959252192508E-2230 + 3703 3.731230790112317398606979626096254E-2230 1.865615395056158699303489813048127E-2230 + 3704 9.328076975280793496517449065240635E-2231 4.664038487640396748258724532620318E-2231 + 3705 2.332019243820198374129362266310159E-2231 1.166009621910099187064681133155080E-2231 + 3706 5.83004810955049593532340566577540E-2232 2.91502405477524796766170283288770E-2232 + 3707 1.45751202738762398383085141644385E-2232 7.28756013693811991915425708221925E-2233 + 3708 3.643780068469059959577128541109625E-2233 1.821890034234529979788564270554813E-2233 + 3709 9.109450171172649898942821352774065E-2234 4.554725085586324949471410676387033E-2234 + 3710 2.277362542793162474735705338193517E-2234 1.138681271396581237367852669096758E-2234 + 3711 5.69340635698290618683926334548379E-2235 2.846703178491453093419631672741895E-2235 + 3712 1.423351589245726546709815836370948E-2235 7.116757946228632733549079181854738E-2236 + 3713 3.558378973114316366774539590927369E-2236 1.779189486557158183387269795463685E-2236 + 3714 8.895947432785790916936348977318425E-2237 4.447973716392895458468174488659213E-2237 + 3715 2.223986858196447729234087244329607E-2237 1.111993429098223864617043622164803E-2237 + 3716 5.559967145491119323085218110824015E-2238 2.779983572745559661542609055412008E-2238 + 3717 1.389991786372779830771304527706004E-2238 6.94995893186389915385652263853002E-2239 + 3718 3.47497946593194957692826131926501E-2239 1.737489732965974788464130659632505E-2239 + 3719 8.687448664829873942320653298162525E-2240 4.343724332414936971160326649081263E-2240 + 3720 2.171862166207468485580163324540632E-2240 1.085931083103734242790081662270316E-2240 + 3721 5.42965541551867121395040831135158E-2241 2.71482770775933560697520415567579E-2241 + 3722 1.357413853879667803487602077837895E-2241 6.787069269398339017438010389189475E-2242 + 3723 3.393534634699169508719005194594738E-2242 1.696767317349584754359502597297369E-2242 + 3724 8.483836586747923771797512986486845E-2243 4.241918293373961885898756493243423E-2243 + 3725 2.120959146686980942949378246621712E-2243 1.060479573343490471474689123310856E-2243 + 3726 5.30239786671745235737344561655428E-2244 2.65119893335872617868672280827714E-2244 + 3727 1.32559946667936308934336140413857E-2244 6.62799733339681544671680702069285E-2245 + 3728 3.313998666698407723358403510346425E-2245 1.656999333349203861679201755173213E-2245 + 3729 8.284996666746019308396008775866065E-2246 4.142498333373009654198004387933033E-2246 + 3730 2.071249166686504827099002193966517E-2246 1.035624583343252413549501096983258E-2246 + 3731 5.17812291671626206774750548491629E-2247 2.589061458358131033873752742458145E-2247 + 3732 1.294530729179065516936876371229073E-2247 6.472653645895327584684381856145363E-2248 + 3733 3.236326822947663792342190928072682E-2248 1.618163411473831896171095464036341E-2248 + 3734 8.090817057369159480855477320181705E-2249 4.045408528684579740427738660090853E-2249 + 3735 2.022704264342289870213869330045427E-2249 1.011352132171144935106934665022713E-2249 + 3736 5.056760660855724675534673325113565E-2250 2.528380330427862337767336662556783E-2250 + 3737 1.264190165213931168883668331278392E-2250 6.320950826069655844418341656391958E-2251 + 3738 3.160475413034827922209170828195979E-2251 1.580237706517413961104585414097990E-2251 + 3739 7.90118853258706980552292707048995E-2252 3.950594266293534902761463535244975E-2252 + 3740 1.975297133146767451380731767622488E-2252 9.876485665733837256903658838112438E-2253 + 3741 4.938242832866918628451829419056219E-2253 2.469121416433459314225914709528110E-2253 + 3742 1.234560708216729657112957354764055E-2253 6.172803541083648285564786773820275E-2254 + 3743 3.086401770541824142782393386910138E-2254 1.543200885270912071391196693455069E-2254 + 3744 7.716004426354560356955983467275345E-2255 3.858002213177280178477991733637673E-2255 + 3745 1.929001106588640089238995866818837E-2255 9.645005532943200446194979334094183E-2256 + 3746 4.822502766471600223097489667047092E-2256 2.411251383235800111548744833523546E-2256 + 3747 1.205625691617900055774372416761773E-2256 6.028128458089500278871862083808865E-2257 + 3748 3.014064229044750139435931041904433E-2257 1.507032114522375069717965520952216E-2257 + 3749 7.53516057261187534858982760476108E-2258 3.76758028630593767429491380238054E-2258 + 3750 1.88379014315296883714745690119027E-2258 9.41895071576484418573728450595135E-2259 + 3751 4.709475357882422092868642252975675E-2259 2.354737678941211046434321126487838E-2259 + 3752 1.177368839470605523217160563243919E-2259 5.886844197353027616085802816219595E-2260 + 3753 2.943422098676513808042901408109798E-2260 1.471711049338256904021450704054899E-2260 + 3754 7.358555246691284520107253520274495E-2261 3.679277623345642260053626760137248E-2261 + 3755 1.839638811672821130026813380068624E-2261 9.19819405836410565013406690034312E-2262 + 3756 4.59909702918205282506703345017156E-2262 2.29954851459102641253351672508578E-2262 + 3757 1.14977425729551320626675836254289E-2262 5.74887128647756603133379181271445E-2263 + 3758 2.874435643238783015666895906357225E-2263 1.437217821619391507833447953178613E-2263 + 3759 7.186089108096957539167239765893065E-2264 3.593044554048478769583619882946533E-2264 + 3760 1.796522277024239384791809941473267E-2264 8.982611385121196923959049707366333E-2265 + 3761 4.491305692560598461979524853683167E-2265 2.245652846280299230989762426841583E-2265 + 3762 1.122826423140149615494881213420792E-2265 5.614132115700748077474406067103958E-2266 + 3763 2.807066057850374038737203033551979E-2266 1.403533028925187019368601516775990E-2266 + 3764 7.01766514462593509684300758387995E-2267 3.508832572312967548421503791939975E-2267 + 3765 1.754416286156483774210751895969988E-2267 8.772081430782418871053759479849938E-2268 + 3766 4.386040715391209435526879739924969E-2268 2.193020357695604717763439869962485E-2268 + 3767 1.096510178847802358881719934981243E-2268 5.482550894239011794408599674906213E-2269 + 3768 2.741275447119505897204299837453107E-2269 1.370637723559752948602149918726553E-2269 + 3769 6.853188617798764743010749593632765E-2270 3.426594308899382371505374796816383E-2270 + 3770 1.713297154449691185752687398408192E-2270 8.566485772248455928763436992040958E-2271 + 3771 4.283242886124227964381718496020479E-2271 2.141621443062113982190859248010240E-2271 + 3772 1.070810721531056991095429624005120E-2271 5.35405360765528495547714812002560E-2272 + 3773 2.67702680382764247773857406001280E-2272 1.33851340191382123886928703000640E-2272 + 3774 6.6925670095691061943464351500320E-2273 3.3462835047845530971732175750160E-2273 + 3775 1.6731417523922765485866087875080E-2273 8.365708761961382742933043937540E-2274 + 3776 4.182854380980691371466521968770E-2274 2.091427190490345685733260984385E-2274 + 3777 1.0457135952451728428666304921925E-2274 5.2285679762258642143331524609625E-2275 + 3778 2.61428398811293210716657623048125E-2275 1.307141994056466053583288115240625E-2275 + 3779 6.535709970282330267916440576203125E-2276 3.267854985141165133958220288101563E-2276 + 3780 1.633927492570582566979110144050782E-2276 8.169637462852912834895550720253908E-2277 + 3781 4.084818731426456417447775360126954E-2277 2.042409365713228208723887680063477E-2277 + 3782 1.021204682856614104361943840031739E-2277 5.106023414283070521809719200158693E-2278 + 3783 2.553011707141535260904859600079347E-2278 1.276505853570767630452429800039673E-2278 + 3784 6.382529267853838152262149000198365E-2279 3.191264633926919076131074500099183E-2279 + 3785 1.595632316963459538065537250049592E-2279 7.978161584817297690327686250247958E-2280 + 3786 3.989080792408648845163843125123979E-2280 1.994540396204324422581921562561990E-2280 + 3787 9.97270198102162211290960781280995E-2281 4.986350990510811056454803906404975E-2281 + 3788 2.493175495255405528227401953202488E-2281 1.246587747627702764113700976601244E-2281 + 3789 6.23293873813851382056850488300622E-2282 3.11646936906925691028425244150311E-2282 + 3790 1.558234684534628455142126220751555E-2282 7.791173422673142275710631103757775E-2283 + 3791 3.895586711336571137855315551878888E-2283 1.947793355668285568927657775939444E-2283 + 3792 9.73896677834142784463828887969722E-2284 4.86948338917071392231914443984861E-2284 + 3793 2.434741694585356961159572219924305E-2284 1.217370847292678480579786109962153E-2284 + 3794 6.086854236463392402898930549810765E-2285 3.043427118231696201449465274905383E-2285 + 3795 1.521713559115848100724732637452692E-2285 7.608567795579240503623663187263458E-2286 + 3796 3.804283897789620251811831593631729E-2286 1.902141948894810125905915796815865E-2286 + 3797 9.510709744474050629529578984079325E-2287 4.755354872237025314764789492039663E-2287 + 3798 2.377677436118512657382394746019832E-2287 1.188838718059256328691197373009916E-2287 + 3799 5.94419359029628164345598686504958E-2288 2.97209679514814082172799343252479E-2288 + 3800 1.486048397574070410863996716262395E-2288 7.430241987870352054319983581311975E-2289 + 3801 3.715120993935176027159991790655988E-2289 1.857560496967588013579995895327994E-2289 + 3802 9.28780248483794006789997947663997E-2290 4.643901242418970033949989738319985E-2290 + 3803 2.321950621209485016974994869159993E-2290 1.160975310604742508487497434579996E-2290 + 3804 5.80487655302371254243748717289998E-2291 2.90243827651185627121874358644999E-2291 + 3805 1.451219138255928135609371793224995E-2291 7.256095691279640678046858966124975E-2292 + 3806 3.628047845639820339023429483062488E-2292 1.814023922819910169511714741531244E-2292 + 3807 9.07011961409955084755857370765622E-2293 4.53505980704977542377928685382811E-2293 + 3808 2.267529903524887711889643426914055E-2293 1.133764951762443855944821713457028E-2293 + 3809 5.66882475881221927972410856728514E-2294 2.83441237940610963986205428364257E-2294 + 3810 1.417206189703054819931027141821285E-2294 7.086030948515274099655135709106425E-2295 + 3811 3.543015474257637049827567854553213E-2295 1.771507737128818524913783927276606E-2295 + 3812 8.85753868564409262456891963638303E-2296 4.428769342822046312284459818191515E-2296 + 3813 2.214384671411023156142229909095758E-2296 1.107192335705511578071114954547879E-2296 + 3814 5.535961678527557890355574772739395E-2297 2.767980839263778945177787386369698E-2297 + 3815 1.383990419631889472588893693184849E-2297 6.919952098159447362944468465924245E-2298 + 3816 3.459976049079723681472234232962123E-2298 1.729988024539861840736117116481061E-2298 + 3817 8.649940122699309203680585582405305E-2299 4.324970061349654601840292791202653E-2299 + 3818 2.162485030674827300920146395601327E-2299 1.081242515337413650460073197800663E-2299 + 3819 5.406212576687068252300365989003315E-2300 2.703106288343534126150182994501658E-2300 + 3820 1.351553144171767063075091497250829E-2300 6.757765720858835315375457486254145E-2301 + 3821 3.378882860429417657687728743127073E-2301 1.689441430214708828843864371563536E-2301 + 3822 8.44720715107354414421932185781768E-2302 4.22360357553677207210966092890884E-2302 + 3823 2.11180178776838603605483046445442E-2302 1.05590089388419301802741523222721E-2302 + 3824 5.27950446942096509013707616113605E-2303 2.639752234710482545068538080568025E-2303 + 3825 1.319876117355241272534269040284013E-2303 6.599380586776206362671345201420063E-2304 + 3826 3.299690293388103181335672600710032E-2304 1.649845146694051590667836300355016E-2304 + 3827 8.24922573347025795333918150177508E-2305 4.12461286673512897666959075088754E-2305 + 3828 2.06230643336756448833479537544377E-2305 1.031153216683782244167397687721885E-2305 + 3829 5.155766083418911220836988438609425E-2306 2.577883041709455610418494219304713E-2306 + 3830 1.288941520854727805209247109652357E-2306 6.444707604273639026046235548261783E-2307 + 3831 3.222353802136819513023117774130892E-2307 1.611176901068409756511558887065446E-2307 + 3832 8.05588450534204878255779443532723E-2308 4.027942252671024391278897217663615E-2308 + 3833 2.013971126335512195639448608831808E-2308 1.006985563167756097819724304415904E-2308 + 3834 5.03492781583878048909862152207952E-2309 2.51746390791939024454931076103976E-2309 + 3835 1.25873195395969512227465538051988E-2309 6.2936597697984756113732769025994E-2310 + 3836 3.1468298848992378056866384512997E-2310 1.57341494244961890284331922564985E-2310 + 3837 7.86707471224809451421659612824925E-2311 3.933537356124047257108298064124625E-2311 + 3838 1.966768678062023628554149032062313E-2311 9.833843390310118142770745160311563E-2312 + 3839 4.916921695155059071385372580155782E-2312 2.458460847577529535692686290077891E-2312 + 3840 1.229230423788764767846343145038946E-2312 6.146152118943823839231715725194728E-2313 + 3841 3.073076059471911919615857862597364E-2313 1.536538029735955959807928931298682E-2313 + 3842 7.68269014867977979903964465649341E-2314 3.841345074339889899519822328246705E-2314 + 3843 1.920672537169944949759911164123353E-2314 9.603362685849724748799555820616763E-2315 + 3844 4.801681342924862374399777910308382E-2315 2.400840671462431187199888955154191E-2315 + 3845 1.200420335731215593599944477577096E-2315 6.002101678656077967999722387885478E-2316 + 3846 3.001050839328038983999861193942739E-2316 1.500525419664019491999930596971370E-2316 + 3847 7.50262709832009745999965298485685E-2317 3.751313549160048729999826492428425E-2317 + 3848 1.875656774580024364999913246214213E-2317 9.378283872900121824999566231071063E-2318 + 3849 4.689141936450060912499783115535532E-2318 2.344570968225030456249891557767766E-2318 + 3850 1.172285484112515228124945778883883E-2318 5.861427420562576140624728894419415E-2319 + 3851 2.930713710281288070312364447209708E-2319 1.465356855140644035156182223604854E-2319 + 3852 7.32678427570322017578091111802427E-2320 3.663392137851610087890455559012135E-2320 + 3853 1.831696068925805043945227779506068E-2320 9.158480344629025219726138897530338E-2321 + 3854 4.579240172314512609863069448765169E-2321 2.289620086157256304931534724382585E-2321 + 3855 1.144810043078628152465767362191293E-2321 5.724050215393140762328836810956463E-2322 + 3856 2.862025107696570381164418405478232E-2322 1.431012553848285190582209202739116E-2322 + 3857 7.15506276924142595291104601369558E-2323 3.57753138462071297645552300684779E-2323 + 3858 1.788765692310356488227761503423895E-2323 8.943828461551782441138807517119475E-2324 + 3859 4.471914230775891220569403758559738E-2324 2.235957115387945610284701879279869E-2324 + 3860 1.117978557693972805142350939639935E-2324 5.589892788469864025711754698199673E-2325 + 3861 2.794946394234932012855877349099837E-2325 1.397473197117466006427938674549918E-2325 + 3862 6.98736598558733003213969337274959E-2326 3.493682992793665016069846686374795E-2326 + 3863 1.746841496396832508034923343187398E-2326 8.734207481984162540174616715936988E-2327 + 3864 4.367103740992081270087308357968494E-2327 2.183551870496040635043654178984247E-2327 + 3865 1.091775935248020317521827089492124E-2327 5.458879676240101587609135447460618E-2328 + 3866 2.729439838120050793804567723730309E-2328 1.364719919060025396902283861865155E-2328 + 3867 6.823599595300126984511419309325775E-2329 3.411799797650063492255709654662888E-2329 + 3868 1.705899898825031746127854827331444E-2329 8.52949949412515873063927413665722E-2330 + 3869 4.26474974706257936531963706832861E-2330 2.132374873531289682659818534164305E-2330 + 3870 1.066187436765644841329909267082153E-2330 5.330937183828224206649546335410763E-2331 + 3871 2.665468591914112103324773167705382E-2331 1.332734295957056051662386583852691E-2331 + 3872 6.663671479785280258311932919263455E-2332 3.331835739892640129155966459631728E-2332 + 3873 1.665917869946320064577983229815864E-2332 8.32958934973160032288991614907932E-2333 + 3874 4.16479467486580016144495807453966E-2333 2.08239733743290008072247903726983E-2333 + 3875 1.041198668716450040361239518634915E-2333 5.205993343582250201806197593174575E-2334 + 3876 2.602996671791125100903098796587288E-2334 1.301498335895562550451549398293644E-2334 + 3877 6.50749167947781275225774699146822E-2335 3.25374583973890637612887349573411E-2335 + 3878 1.626872919869453188064436747867055E-2335 8.134364599347265940322183739335275E-2336 + 3879 4.067182299673632970161091869667638E-2336 2.033591149836816485080545934833819E-2336 + 3880 1.016795574918408242540272967416910E-2336 5.083977874592041212701364837084548E-2337 + 3881 2.541988937296020606350682418542274E-2337 1.270994468648010303175341209271137E-2337 + 3882 6.354972343240051515876706046355685E-2338 3.177486171620025757938353023177843E-2338 + 3883 1.588743085810012878969176511588922E-2338 7.943715429050064394845882557944608E-2339 + 3884 3.971857714525032197422941278972304E-2339 1.985928857262516098711470639486152E-2339 + 3885 9.92964428631258049355735319743076E-2340 4.96482214315629024677867659871538E-2340 + 3886 2.48241107157814512338933829935769E-2340 1.241205535789072561694669149678845E-2340 + 3887 6.206027678945362808473345748394225E-2341 3.103013839472681404236672874197113E-2341 + 3888 1.551506919736340702118336437098557E-2341 7.757534598681703510591682185492783E-2342 + 3889 3.878767299340851755295841092746392E-2342 1.939383649670425877647920546373196E-2342 + 3890 9.69691824835212938823960273186598E-2343 4.84845912417606469411980136593299E-2343 + 3891 2.424229562088032347059900682966495E-2343 1.212114781044016173529950341483248E-2343 + 3892 6.06057390522008086764975170741624E-2344 3.03028695261004043382487585370812E-2344 + 3893 1.51514347630502021691243792685406E-2344 7.5757173815251010845621896342703E-2345 + 3894 3.78785869076255054228109481713515E-2345 1.893929345381275271140547408567575E-2345 + 3895 9.469646726906376355702737042837875E-2346 4.734823363453188177851368521418938E-2346 + 3896 2.367411681726594088925684260709469E-2346 1.183705840863297044462842130354735E-2346 + 3897 5.918529204316485222314210651773675E-2347 2.959264602158242611157105325886838E-2347 + 3898 1.479632301079121305578552662943419E-2347 7.398161505395606527892763314717095E-2348 + 3899 3.699080752697803263946381657358548E-2348 1.849540376348901631973190828679274E-2348 + 3900 9.24770188174450815986595414339637E-2349 4.623850940872254079932977071698185E-2349 + 3901 2.311925470436127039966488535849093E-2349 1.155962735218063519983244267924546E-2349 + 3902 5.77981367609031759991622133962273E-2350 2.889906838045158799958110669811365E-2350 + 3903 1.444953419022579399979055334905683E-2350 7.224767095112896999895276674528413E-2351 + 3904 3.612383547556448499947638337264207E-2351 1.806191773778224249973819168632103E-2351 + 3905 9.030958868891121249869095843160515E-2352 4.515479434445560624934547921580258E-2352 + 3906 2.257739717222780312467273960790129E-2352 1.128869858611390156233636980395065E-2352 + 3907 5.644349293056950781168184901975325E-2353 2.822174646528475390584092450987663E-2353 + 3908 1.411087323264237695292046225493832E-2353 7.055436616321188476460231127469158E-2354 + 3909 3.527718308160594238230115563734579E-2354 1.763859154080297119115057781867290E-2354 + 3910 8.81929577040148559557528890933645E-2355 4.409647885200742797787644454668225E-2355 + 3911 2.204823942600371398893822227334113E-2355 1.102411971300185699446911113667056E-2355 + 3912 5.51205985650092849723455556833528E-2356 2.75602992825046424861727778416764E-2356 + 3913 1.37801496412523212430863889208382E-2356 6.8900748206261606215431944604191E-2357 + 3914 3.44503741031308031077159723020955E-2357 1.722518705156540155385798615104775E-2357 + 3915 8.612593525782700776928993075523875E-2358 4.306296762891350388464496537761938E-2358 + 3916 2.153148381445675194232248268880969E-2358 1.076574190722837597116124134440485E-2358 + 3917 5.382870953614187985580620672202425E-2359 2.691435476807093992790310336101213E-2359 + 3918 1.345717738403546996395155168050607E-2359 6.728588692017734981975775840253033E-2360 + 3919 3.364294346008867490987887920126517E-2360 1.682147173004433745493943960063258E-2360 + 3920 8.41073586502216872746971980031629E-2361 4.205367932511084363734859900158145E-2361 + 3921 2.102683966255542181867429950079073E-2361 1.051341983127771090933714975039536E-2361 + 3922 5.25670991563885545466857487519768E-2362 2.62835495781942772733428743759884E-2362 + 3923 1.31417747890971386366714371879942E-2362 6.5708873945485693183357185939971E-2363 + 3924 3.28544369727428465916785929699855E-2363 1.642721848637142329583929648499275E-2363 + 3925 8.213609243185711647919648242496375E-2364 4.106804621592855823959824121248188E-2364 + 3926 2.053402310796427911979912060624094E-2364 1.026701155398213955989956030312047E-2364 + 3927 5.133505776991069779949780151560235E-2365 2.566752888495534889974890075780118E-2365 + 3928 1.283376444247767444987445037890059E-2365 6.416882221238837224937225189450295E-2366 + 3929 3.208441110619418612468612594725148E-2366 1.604220555309709306234306297362574E-2366 + 3930 8.02110277654854653117153148681287E-2367 4.010551388274273265585765743406435E-2367 + 3931 2.005275694137136632792882871703218E-2367 1.002637847068568316396441435851609E-2367 + 3932 5.013189235342841581982207179258045E-2368 2.506594617671420790991103589629023E-2368 + 3933 1.253297308835710395495551794814512E-2368 6.266486544178551977477758974072558E-2369 + 3934 3.133243272089275988738879487036279E-2369 1.566621636044637994369439743518140E-2369 + 3935 7.83310818022318997184719871759070E-2370 3.91655409011159498592359935879535E-2370 + 3936 1.958277045055797492961799679397675E-2370 9.791385225278987464808998396988375E-2371 + 3937 4.895692612639493732404499198494188E-2371 2.447846306319746866202249599247094E-2371 + 3938 1.223923153159873433101124799623547E-2371 6.119615765799367165505623998117735E-2372 + 3939 3.059807882899683582752811999058868E-2372 1.529903941449841791376405999529434E-2372 + 3940 7.64951970724920895688202999764717E-2373 3.824759853624604478441014998823585E-2373 + 3941 1.912379926812302239220507499411793E-2373 9.561899634061511196102537497058963E-2374 + 3942 4.780949817030755598051268748529482E-2374 2.390474908515377799025634374264741E-2374 + 3943 1.195237454257688899512817187132371E-2374 5.976187271288444497564085935661853E-2375 + 3944 2.988093635644222248782042967830927E-2375 1.494046817822111124391021483915463E-2375 + 3945 7.470234089110555621955107419577315E-2376 3.735117044555277810977553709788658E-2376 + 3946 1.867558522277638905488776854894329E-2376 9.337792611388194527443884274471645E-2377 + 3947 4.668896305694097263721942137235823E-2377 2.334448152847048631860971068617911E-2377 + 3948 1.167224076423524315930485534308956E-2377 5.836120382117621579652427671544778E-2378 + 3949 2.918060191058810789826213835772389E-2378 1.459030095529405394913106917886195E-2378 + 3950 7.295150477647026974565534589430975E-2379 3.647575238823513487282767294715488E-2379 + 3951 1.823787619411756743641383647357744E-2379 9.11893809705878371820691823678872E-2380 + 3952 4.55946904852939185910345911839436E-2380 2.27973452426469592955172955919718E-2380 + 3953 1.13986726213234796477586477959859E-2380 5.69933631066173982387932389799295E-2381 + 3954 2.849668155330869911939661948996475E-2381 1.424834077665434955969830974498238E-2381 + 3955 7.12417038832717477984915487249119E-2382 3.562085194163587389924577436245595E-2382 + 3956 1.781042597081793694962288718122798E-2382 8.905212985408968474811443590613988E-2383 + 3957 4.452606492704484237405721795306994E-2383 2.226303246352242118702860897653497E-2383 + 3958 1.113151623176121059351430448826749E-2383 5.565758115880605296757152244133743E-2384 + 3959 2.782879057940302648378576122066872E-2384 1.391439528970151324189288061033436E-2384 + 3960 6.95719764485075662094644030516718E-2385 3.47859882242537831047322015258359E-2385 + 3961 1.739299411212689155236610076291795E-2385 8.696497056063445776183050381458975E-2386 + 3962 4.348248528031722888091525190729488E-2386 2.174124264015861444045762595364744E-2386 + 3963 1.087062132007930722022881297682372E-2386 5.43531066003965361011440648841186E-2387 + 3964 2.71765533001982680505720324420593E-2387 1.358827665009913402528601622102965E-2387 + 3965 6.794138325049567012643008110514825E-2388 3.397069162524783506321504055257413E-2388 + 3966 1.698534581262391753160752027628707E-2388 8.492672906311958765803760138143533E-2389 + 3967 4.246336453155979382901880069071767E-2389 2.123168226577989691450940034535883E-2389 + 3968 1.061584113288994845725470017267942E-2389 5.307920566444974228627350086339708E-2390 + 3969 2.653960283222487114313675043169854E-2390 1.326980141611243557156837521584927E-2390 + 3970 6.634900708056217785784187607924635E-2391 3.317450354028108892892093803962318E-2391 + 3971 1.658725177014054446446046901981159E-2391 8.293625885070272232230234509905795E-2392 + 3972 4.146812942535136116115117254952898E-2392 2.073406471267568058057558627476449E-2392 + 3973 1.036703235633784029028779313738225E-2392 5.183516178168920145143896568691123E-2393 + 3974 2.591758089084460072571948284345562E-2393 1.295879044542230036285974142172781E-2393 + 3975 6.479395222711150181429870710863905E-2394 3.239697611355575090714935355431953E-2394 + 3976 1.619848805677787545357467677715977E-2394 8.099244028388937726787338388579883E-2395 + 3977 4.049622014194468863393669194289942E-2395 2.024811007097234431696834597144971E-2395 + 3978 1.012405503548617215848417298572486E-2395 5.062027517743086079242086492862428E-2396 + 3979 2.531013758871543039621043246431214E-2396 1.265506879435771519810521623215607E-2396 + 3980 6.327534397178857599052608116078035E-2397 3.163767198589428799526304058039018E-2397 + 3981 1.581883599294714399763152029019509E-2397 7.909417996473571998815760145097545E-2398 + 3982 3.954708998236785999407880072548773E-2398 1.977354499118392999703940036274386E-2398 + 3983 9.88677249559196499851970018137193E-2399 4.943386247795982499259850090685965E-2399 + 3984 2.471693123897991249629925045342983E-2399 1.235846561948995624814962522671491E-2399 + 3985 6.179232809744978124074812613357455E-2400 3.089616404872489062037406306678728E-2400 + 3986 1.544808202436244531018703153339364E-2400 7.72404101218122265509351576669682E-2401 + 3987 3.86202050609061132754675788334841E-2401 1.931010253045305663773378941674205E-2401 + 3988 9.655051265226528318866894708371025E-2402 4.827525632613264159433447354185513E-2402 + 3989 2.413762816306632079716723677092757E-2402 1.206881408153316039858361838546378E-2402 + 3990 6.03440704076658019929180919273189E-2403 3.017203520383290099645904596365945E-2403 + 3991 1.508601760191645049822952298182973E-2403 7.543008800958225249114761490914863E-2404 + 3992 3.771504400479112624557380745457432E-2404 1.885752200239556312278690372728716E-2404 + 3993 9.42876100119778156139345186364358E-2405 4.71438050059889078069672593182179E-2405 + 3994 2.357190250299445390348362965910895E-2405 1.178595125149722695174181482955448E-2405 + 3995 5.89297562574861347587090741477724E-2406 2.94648781287430673793545370738862E-2406 + 3996 1.47324390643715336896772685369431E-2406 7.36621953218576684483863426847155E-2407 + 3997 3.683109766092883422419317134235775E-2407 1.841554883046441711209658567117888E-2407 + 3998 9.20777441523220855604829283558944E-2408 4.60388720761610427802414641779472E-2408 + 3999 2.30194360380805213901207320889736E-2408 1.15097180190402606950603660444868E-2408 + 4000 5.7548590095201303475301830222434E-2409 2.8774295047600651737650915111217E-2409 + 4001 1.43871475238003258688254575556085E-2409 7.19357376190016293441272877780425E-2410 + 4002 3.596786880950081467206364388902125E-2410 1.798393440475040733603182194451063E-2410 + 4003 8.991967202375203668015910972255315E-2411 4.495983601187601834007955486127658E-2411 + 4004 2.247991800593800917003977743063829E-2411 1.123995900296900458501988871531915E-2411 + 4005 5.619979501484502292509944357659575E-2412 2.809989750742251146254972178829788E-2412 + 4006 1.404994875371125573127486089414894E-2412 7.02497437685562786563743044707447E-2413 + 4007 3.512487188427813932818715223537235E-2413 1.756243594213906966409357611768618E-2413 + 4008 8.78121797106953483204678805884309E-2414 4.390608985534767416023394029421545E-2414 + 4009 2.195304492767383708011697014710773E-2414 1.097652246383691854005848507355386E-2414 + 4010 5.48826123191845927002924253677693E-2415 2.744130615959229635014621268388465E-2415 + 4011 1.372065307979614817507310634194233E-2415 6.860326539898074087536553170971163E-2416 + 4012 3.430163269949037043768276585485582E-2416 1.715081634974518521884138292742791E-2416 + 4013 8.575408174872592609420691463713955E-2417 4.287704087436296304710345731856978E-2417 + 4014 2.143852043718148152355172865928489E-2417 1.071926021859074076177586432964245E-2417 + 4015 5.359630109295370380887932164821225E-2418 2.679815054647685190443966082410613E-2418 + 4016 1.339907527323842595221983041205307E-2418 6.699537636619212976109915206026533E-2419 + 4017 3.349768818309606488054957603013267E-2419 1.674884409154803244027478801506633E-2419 + 4018 8.374422045774016220137394007533165E-2420 4.187211022887008110068697003766583E-2420 + 4019 2.093605511443504055034348501883292E-2420 1.046802755721752027517174250941646E-2420 + 4020 5.23401377860876013758587125470823E-2421 2.617006889304380068792935627354115E-2421 + 4021 1.308503444652190034396467813677058E-2421 6.542517223260950171982339068385288E-2422 + 4022 3.271258611630475085991169534192644E-2422 1.635629305815237542995584767096322E-2422 + 4023 8.17814652907618771497792383548161E-2423 4.089073264538093857488961917740805E-2423 + 4024 2.044536632269046928744480958870403E-2423 1.022268316134523464372240479435201E-2423 + 4025 5.111341580672617321861202397176005E-2424 2.555670790336308660930601198588003E-2424 + 4026 1.277835395168154330465300599294002E-2424 6.389176975840771652326502996470008E-2425 + 4027 3.194588487920385826163251498235004E-2425 1.597294243960192913081625749117502E-2425 + 4028 7.98647121980096456540812874558751E-2426 3.993235609900482282704064372793755E-2426 + 4029 1.996617804950241141352032186396878E-2426 9.983089024751205706760160931984388E-2427 + 4030 4.991544512375602853380080465992194E-2427 2.495772256187801426690040232996097E-2427 + 4031 1.247886128093900713345020116498049E-2427 6.239430640469503566725100582490243E-2428 + 4032 3.119715320234751783362550291245122E-2428 1.559857660117375891681275145622561E-2428 + 4033 7.799288300586879458406375728112805E-2429 3.899644150293439729203187864056403E-2429 + 4034 1.949822075146719864601593932028202E-2429 9.749110375733599323007969660141008E-2430 + 4035 4.874555187866799661503984830070504E-2430 2.437277593933399830751992415035252E-2430 + 4036 1.218638796966699915375996207517626E-2430 6.09319398483349957687998103758813E-2431 + 4037 3.046596992416749788439990518794065E-2431 1.523298496208374894219995259397033E-2431 + 4038 7.616492481041874471099976296985165E-2432 3.808246240520937235549988148492583E-2432 + 4039 1.904123120260468617774994074246292E-2432 9.520615601302343088874970371231458E-2433 + 4040 4.760307800651171544437485185615729E-2433 2.380153900325585772218742592807865E-2433 + 4041 1.190076950162792886109371296403933E-2433 5.950384750813964430546856482019663E-2434 + 4042 2.975192375406982215273428241009832E-2434 1.487596187703491107636714120504916E-2434 + 4043 7.43798093851745553818357060252458E-2435 3.71899046925872776909178530126229E-2435 + 4044 1.859495234629363884545892650631145E-2435 9.297476173146819422729463253155725E-2436 + 4045 4.648738086573409711364731626577863E-2436 2.324369043286704855682365813288931E-2436 + 4046 1.162184521643352427841182906644466E-2436 5.810922608216762139205914533222328E-2437 + 4047 2.905461304108381069602957266611164E-2437 1.452730652054190534801478633305582E-2437 + 4048 7.26365326027095267400739316652791E-2438 3.631826630135476337003696583263955E-2438 + 4049 1.815913315067738168501848291631978E-2438 9.079566575338690842509241458159888E-2439 + 4050 4.539783287669345421254620729079944E-2439 2.269891643834672710627310364539972E-2439 + 4051 1.134945821917336355313655182269986E-2439 5.67472910958668177656827591134993E-2440 + 4052 2.837364554793340888284137955674965E-2440 1.418682277396670444142068977837483E-2440 + 4053 7.093411386983352220710344889187415E-2441 3.546705693491676110355172444593708E-2441 + 4054 1.773352846745838055177586222296854E-2441 8.86676423372919027588793111148427E-2442 + 4055 4.433382116864595137943965555742135E-2442 2.216691058432297568971982777871068E-2442 + 4056 1.108345529216148784485991388935534E-2442 5.54172764608074392242995694467767E-2443 + 4057 2.770863823040371961214978472338835E-2443 1.385431911520185980607489236169418E-2443 + 4058 6.92715955760092990303744618084709E-2444 3.463579778800464951518723090423545E-2444 + 4059 1.731789889400232475759361545211773E-2444 8.658949447001162378796807726058863E-2445 + 4060 4.329474723500581189398403863029432E-2445 2.164737361750290594699201931514716E-2445 + 4061 1.082368680875145297349600965757358E-2445 5.41184340437572648674800482878679E-2446 + 4062 2.705921702187863243374002414393395E-2446 1.352960851093931621687001207196698E-2446 + 4063 6.76480425546965810843500603598349E-2447 3.382402127734829054217503017991745E-2447 + 4064 1.691201063867414527108751508995873E-2447 8.456005319337072635543757544979363E-2448 + 4065 4.228002659668536317771878772489682E-2448 2.114001329834268158885939386244841E-2448 + 4066 1.057000664917134079442969693122421E-2448 5.285003324585670397214848465612103E-2449 + 4067 2.642501662292835198607424232806052E-2449 1.321250831146417599303712116403026E-2449 + 4068 6.60625415573208799651856058201513E-2450 3.303127077866043998259280291007565E-2450 + 4069 1.651563538933021999129640145503783E-2450 8.257817694665109995648200727518913E-2451 + 4070 4.128908847332554997824100363759457E-2451 2.064454423666277498912050181879728E-2451 + 4071 1.032227211833138749456025090939864E-2451 5.16113605916569374728012545469932E-2452 + 4072 2.58056802958284687364006272734966E-2452 1.29028401479142343682003136367483E-2452 + 4073 6.45142007395711718410015681837415E-2453 3.225710036978558592050078409187075E-2453 + 4074 1.612855018489279296025039204593538E-2453 8.064275092446396480125196022967688E-2454 + 4075 4.032137546223198240062598011483844E-2454 2.016068773111599120031299005741922E-2454 + 4076 1.008034386555799560015649502870961E-2454 5.040171932778997800078247514354805E-2455 + 4077 2.520085966389498900039123757177403E-2455 1.260042983194749450019561878588701E-2455 + 4078 6.300214915973747250097809392943505E-2456 3.150107457986873625048904696471753E-2456 + 4079 1.575053728993436812524452348235877E-2456 7.875268644967184062622261741179383E-2457 + 4080 3.937634322483592031311130870589692E-2457 1.968817161241796015655565435294846E-2457 + 4081 9.84408580620898007827782717647423E-2458 4.922042903104490039138913588237115E-2458 + 4082 2.461021451552245019569456794118558E-2458 1.230510725776122509784728397059279E-2458 + 4083 6.152553628880612548923641985296395E-2459 3.076276814440306274461820992648198E-2459 + 4084 1.538138407220153137230910496324099E-2459 7.690692036100765686154552481620495E-2460 + 4085 3.845346018050382843077276240810248E-2460 1.922673009025191421538638120405124E-2460 + 4086 9.61336504512595710769319060202562E-2461 4.80668252256297855384659530101281E-2461 + 4087 2.403341261281489276923297650506405E-2461 1.201670630640744638461648825253203E-2461 + 4088 6.008353153203723192308244126266015E-2462 3.004176576601861596154122063133008E-2462 + 4089 1.502088288300930798077061031566504E-2462 7.51044144150465399038530515783252E-2463 + 4090 3.75522072075232699519265257891626E-2463 1.87761036037616349759632628945813E-2463 + 4091 9.38805180188081748798163144729065E-2464 4.694025900940408743990815723645325E-2464 + 4092 2.347012950470204371995407861822663E-2464 1.173506475235102185997703930911331E-2464 + 4093 5.867532376175510929988519654556655E-2465 2.933766188087755464994259827278328E-2465 + 4094 1.466883094043877732497129913639164E-2465 7.33441547021938866248564956819582E-2466 + 4095 3.66720773510969433124282478409791E-2466 1.833603867554847165621412392048955E-2466 + 4096 9.168019337774235828107061960244775E-2467 4.584009668887117914053530980122388E-2467 + 4097 2.292004834443558957026765490061194E-2467 1.146002417221779478513382745030597E-2467 + 4098 5.730012086108897392566913725152985E-2468 2.865006043054448696283456862576493E-2468 + 4099 1.432503021527224348141728431288247E-2468 7.162515107636121740708642156441233E-2469 + 4100 3.581257553818060870354321078220617E-2469 1.790628776909030435177160539110308E-2469 + 4101 8.95314388454515217588580269555154E-2470 4.47657194227257608794290134777577E-2470 + 4102 2.238285971136288043971450673887885E-2470 1.119142985568144021985725336943943E-2470 + 4103 5.595714927840720109928626684719715E-2471 2.797857463920360054964313342359858E-2471 + 4104 1.398928731960180027482156671179929E-2471 6.994643659800900137410783355899645E-2472 + 4105 3.497321829900450068705391677949823E-2472 1.748660914950225034352695838974911E-2472 + 4106 8.743304574751125171763479194874555E-2473 4.371652287375562585881739597437278E-2473 + 4107 2.185826143687781292940869798718639E-2473 1.092913071843890646470434899359320E-2473 + 4108 5.46456535921945323235217449679660E-2474 2.73228267960972661617608724839830E-2474 + 4109 1.36614133980486330808804362419915E-2474 6.83070669902431654044021812099575E-2475 + 4110 3.415353349512158270220109060497875E-2475 1.707676674756079135110054530248938E-2475 + 4111 8.53838337378039567555027265124469E-2476 4.269191686890197837775136325622345E-2476 + 4112 2.134595843445098918887568162811173E-2476 1.067297921722549459443784081405586E-2476 + 4113 5.33648960861274729721892040702793E-2477 2.668244804306373648609460203513965E-2477 + 4114 1.334122402153186824304730101756983E-2477 6.670612010765934121523650508784913E-2478 + 4115 3.335306005382967060761825254392457E-2478 1.667653002691483530380912627196228E-2478 + 4116 8.33826501345741765190456313598114E-2479 4.16913250672870882595228156799057E-2479 + 4117 2.084566253364354412976140783995285E-2479 1.042283126682177206488070391997643E-2479 + 4118 5.211415633410886032440351959988215E-2480 2.605707816705443016220175979994108E-2480 + 4119 1.302853908352721508110087989997054E-2480 6.51426954176360754055043994998527E-2481 + 4120 3.257134770881803770275219974992635E-2481 1.628567385440901885137609987496318E-2481 + 4121 8.14283692720450942568804993748159E-2482 4.071418463602254712844024968740795E-2482 + 4122 2.035709231801127356422012484370398E-2482 1.017854615900563678211006242185199E-2482 + 4123 5.089273079502818391055031210925995E-2483 2.544636539751409195527515605462998E-2483 + 4124 1.272318269875704597763757802731499E-2483 6.361591349378522988818789013657495E-2484 + 4125 3.180795674689261494409394506828748E-2484 1.590397837344630747204697253414374E-2484 + 4126 7.95198918672315373602348626707187E-2485 3.975994593361576868011743133535935E-2485 + 4127 1.987997296680788434005871566767968E-2485 9.939986483403942170029357833839838E-2486 + 4128 4.969993241701971085014678916919919E-2486 2.484996620850985542507339458459960E-2486 + 4129 1.242498310425492771253669729229980E-2486 6.21249155212746385626834864614990E-2487 + 4130 3.10624577606373192813417432307495E-2487 1.553122888031865964067087161537475E-2487 + 4131 7.765614440159329820335435807687375E-2488 3.882807220079664910167717903843688E-2488 + 4132 1.941403610039832455083858951921844E-2488 9.70701805019916227541929475960922E-2489 + 4133 4.85350902509958113770964737980461E-2489 2.426754512549790568854823689902305E-2489 + 4134 1.213377256274895284427411844951153E-2489 6.066886281374476422137059224755763E-2490 + 4135 3.033443140687238211068529612377882E-2490 1.516721570343619105534264806188941E-2490 + 4136 7.583607851718095527671324030944705E-2491 3.791803925859047763835662015472353E-2491 + 4137 1.895901962929523881917831007736177E-2491 9.479509814647619409589155038680883E-2492 + 4138 4.739754907323809704794577519340442E-2492 2.369877453661904852397288759670221E-2492 + 4139 1.184938726830952426198644379835111E-2492 5.924693634154762130993221899175553E-2493 + 4140 2.962346817077381065496610949587777E-2493 1.481173408538690532748305474793888E-2493 + 4141 7.40586704269345266374152737396944E-2494 3.70293352134672633187076368698472E-2494 + 4142 1.85146676067336316593538184349236E-2494 9.2573338033668158296769092174618E-2495 + 4143 4.6286669016834079148384546087309E-2495 2.31433345084170395741922730436545E-2495 + 4144 1.157166725420851978709613652182725E-2495 5.785833627104259893548068260913625E-2496 + 4145 2.892916813552129946774034130456813E-2496 1.446458406776064973387017065228406E-2496 + 4146 7.23229203388032486693508532614203E-2497 3.616146016940162433467542663071015E-2497 + 4147 1.808073008470081216733771331535508E-2497 9.040365042350406083668856657677538E-2498 + 4148 4.520182521175203041834428328838769E-2498 2.260091260587601520917214164419385E-2498 + 4149 1.130045630293800760458607082209693E-2498 5.650228151469003802293035411048463E-2499 + 4150 2.825114075734501901146517705524232E-2499 1.412557037867250950573258852762116E-2499 + 4151 7.06278518933625475286629426381058E-2500 3.53139259466812737643314713190529E-2500 + 4152 1.765696297334063688216573565952645E-2500 8.828481486670318441082867829763225E-2501 + 4153 4.414240743335159220541433914881613E-2501 2.207120371667579610270716957440806E-2501 + 4154 1.103560185833789805135358478720403E-2501 5.517800929168949025676792393602015E-2502 + 4155 2.758900464584474512838396196801008E-2502 1.379450232292237256419198098400504E-2502 + 4156 6.89725116146118628209599049200252E-2503 3.44862558073059314104799524600126E-2503 + 4157 1.72431279036529657052399762300063E-2503 8.62156395182648285261998811500315E-2504 + 4158 4.310781975913241426309994057501575E-2504 2.155390987956620713154997028750788E-2504 + 4159 1.077695493978310356577498514375394E-2504 5.38847746989155178288749257187697E-2505 + 4160 2.694238734945775891443746285938485E-2505 1.347119367472887945721873142969243E-2505 + 4161 6.735596837364439728609365714846215E-2506 3.367798418682219864304682857423108E-2506 + 4162 1.683899209341109932152341428711554E-2506 8.41949604670554966076170714355777E-2507 + 4163 4.209748023352774830380853571778885E-2507 2.104874011676387415190426785889443E-2507 + 4164 1.052437005838193707595213392944722E-2507 5.262185029190968537976066964723608E-2508 + 4165 2.631092514595484268988033482361804E-2508 1.315546257297742134494016741180902E-2508 + 4166 6.57773128648871067247008370590451E-2509 3.288865643244355336235041852952255E-2509 + 4167 1.644432821622177668117520926476128E-2509 8.222164108110888340587604632380638E-2510 + 4168 4.111082054055444170293802316190319E-2510 2.055541027027722085146901158095160E-2510 + 4169 1.027770513513861042573450579047580E-2510 5.13885256756930521286725289523790E-2511 + 4170 2.56942628378465260643362644761895E-2511 1.284713141892326303216813223809475E-2511 + 4171 6.423565709461631516084066119047375E-2512 3.211782854730815758042033059523688E-2512 + 4172 1.605891427365407879021016529761844E-2512 8.02945713682703939510508264880922E-2513 + 4173 4.01472856841351969755254132440461E-2513 2.007364284206759848776270662202305E-2513 + 4174 1.003682142103379924388135331101153E-2513 5.018410710516899621940676655505763E-2514 + 4175 2.509205355258449810970338327752882E-2514 1.254602677629224905485169163876441E-2514 + 4176 6.273013388146124527425845819382205E-2515 3.136506694073062263712922909691103E-2515 + 4177 1.568253347036531131856461454845552E-2515 7.841266735182655659282307274227758E-2516 + 4178 3.920633367591327829641153637113879E-2516 1.960316683795663914820576818556940E-2516 + 4179 9.80158341897831957410288409278470E-2517 4.90079170948915978705144204639235E-2517 + 4180 2.450395854744579893525721023196175E-2517 1.225197927372289946762860511598088E-2517 + 4181 6.12598963686144973381430255799044E-2518 3.06299481843072486690715127899522E-2518 + 4182 1.53149740921536243345357563949761E-2518 7.65748704607681216726787819748805E-2519 + 4183 3.828743523038406083633939098744025E-2519 1.914371761519203041816969549372013E-2519 + 4184 9.571858807596015209084847746860065E-2520 4.785929403798007604542423873430033E-2520 + 4185 2.392964701899003802271211936715017E-2520 1.196482350949501901135605968357508E-2520 + 4186 5.98241175474750950567802984178754E-2521 2.99120587737375475283901492089377E-2521 + 4187 1.495602938686877376419507460446885E-2521 7.478014693434386882097537302234425E-2522 + 4188 3.739007346717193441048768651117213E-2522 1.869503673358596720524384325558606E-2522 + 4189 9.34751836679298360262192162779303E-2523 4.673759183396491801310960813896515E-2523 + 4190 2.336879591698245900655480406948258E-2523 1.168439795849122950327740203474129E-2523 + 4191 5.842198979245614751638701017370645E-2524 2.921099489622807375819350508685323E-2524 + 4192 1.460549744811403687909675254342662E-2524 7.302748724057018439548376271713308E-2525 + 4193 3.651374362028509219774188135856654E-2525 1.825687181014254609887094067928327E-2525 + 4194 9.128435905071273049435470339641635E-2526 4.564217952535636524717735169820818E-2526 + 4195 2.282108976267818262358867584910409E-2526 1.141054488133909131179433792455205E-2526 + 4196 5.705272440669545655897168962276025E-2527 2.852636220334772827948584481138013E-2527 + 4197 1.426318110167386413974292240569007E-2527 7.131590550836932069871461202845033E-2528 + 4198 3.565795275418466034935730601422517E-2528 1.782897637709233017467865300711258E-2528 + 4199 8.91448818854616508733932650355629E-2529 4.457244094273082543669663251778145E-2529 + 4200 2.228622047136541271834831625889073E-2529 1.114311023568270635917415812944536E-2529 + 4201 5.57155511784135317958707906472268E-2530 2.78577755892067658979353953236134E-2530 + 4202 1.39288877946033829489676976618067E-2530 6.96444389730169147448384883090335E-2531 + 4203 3.482221948650845737241924415451675E-2531 1.741110974325422868620962207725838E-2531 + 4204 8.70555487162711434310481103862919E-2532 4.352777435813557171552405519314595E-2532 + 4205 2.176388717906778585776202759657298E-2532 1.088194358953389292888101379828649E-2532 + 4206 5.440971794766946464440506899143245E-2533 2.720485897383473232220253449571623E-2533 + 4207 1.360242948691736616110126724785812E-2533 6.801214743458683080550633623929058E-2534 + 4208 3.400607371729341540275316811964529E-2534 1.700303685864670770137658405982265E-2534 + 4209 8.501518429323353850688292029911325E-2535 4.250759214661676925344146014955663E-2535 + 4210 2.125379607330838462672073007477832E-2535 1.062689803665419231336036503738916E-2535 + 4211 5.31344901832709615668018251869458E-2536 2.65672450916354807834009125934729E-2536 + 4212 1.328362254581774039170045629673645E-2536 6.641811272908870195850228148368225E-2537 + 4213 3.320905636454435097925114074184113E-2537 1.660452818227217548962557037092056E-2537 + 4214 8.30226409113608774481278518546028E-2538 4.15113204556804387240639259273014E-2538 + 4215 2.07556602278402193620319629636507E-2538 1.037783011392010968101598148182535E-2538 + 4216 5.188915056960054840507990740912675E-2539 2.594457528480027420253995370456338E-2539 + 4217 1.297228764240013710126997685228169E-2539 6.486143821200068550634988426140845E-2540 + 4218 3.243071910600034275317494213070423E-2540 1.621535955300017137658747106535211E-2540 + 4219 8.107679776500085688293735532676055E-2541 4.053839888250042844146867766338028E-2541 + 4220 2.026919944125021422073433883169014E-2541 1.013459972062510711036716941584507E-2541 + 4221 5.067299860312553555183584707922535E-2542 2.533649930156276777591792353961268E-2542 + 4222 1.266824965078138388795896176980634E-2542 6.33412482539069194397948088490317E-2543 + 4223 3.167062412695345971989740442451585E-2543 1.583531206347672985994870221225793E-2543 + 4224 7.917656031738364929974351106128965E-2544 3.958828015869182464987175553064483E-2544 + 4225 1.979414007934591232493587776532242E-2544 9.897070039672956162467938882661208E-2545 + 4226 4.948535019836478081233969441330604E-2545 2.474267509918239040616984720665302E-2545 + 4227 1.237133754959119520308492360332651E-2545 6.185668774795597601542461801663255E-2546 + 4228 3.092834387397798800771230900831628E-2546 1.546417193698899400385615450415814E-2546 + 4229 7.73208596849449700192807725207907E-2547 3.866042984247248500964038626039535E-2547 + 4230 1.933021492123624250482019313019768E-2547 9.665107460618121252410096565098838E-2548 + 4231 4.832553730309060626205048282549419E-2548 2.416276865154530313102524141274710E-2548 + 4232 1.208138432577265156551262070637355E-2548 6.040692162886325782756310353186775E-2549 + 4233 3.020346081443162891378155176593388E-2549 1.510173040721581445689077588296694E-2549 + 4234 7.55086520360790722844538794148347E-2550 3.775432601803953614222693970741735E-2550 + 4235 1.887716300901976807111346985370868E-2550 9.438581504509884035556734926854338E-2551 + 4236 4.719290752254942017778367463427169E-2551 2.359645376127471008889183731713585E-2551 + 4237 1.179822688063735504444591865856793E-2551 5.899113440318677522222959329283963E-2552 + 4238 2.949556720159338761111479664641982E-2552 1.474778360079669380555739832320991E-2552 + 4239 7.373891800398346902778699161604955E-2553 3.686945900199173451389349580802478E-2553 + 4240 1.843472950099586725694674790401239E-2553 9.217364750497933628473373952006195E-2554 + 4241 4.608682375248966814236686976003098E-2554 2.304341187624483407118343488001549E-2554 + 4242 1.152170593812241703559171744000775E-2554 5.760852969061208517795858720003873E-2555 + 4243 2.880426484530604258897929360001937E-2555 1.440213242265302129448964680000968E-2555 + 4244 7.20106621132651064724482340000484E-2556 3.60053310566325532362241170000242E-2556 + 4245 1.80026655283162766181120585000121E-2556 9.00133276415813830905602925000605E-2557 + 4246 4.500666382079069154528014625003025E-2557 2.250333191039534577264007312501513E-2557 + 4247 1.125166595519767288632003656250757E-2557 5.625832977598836443160018281253783E-2558 + 4248 2.812916488799418221580009140626892E-2558 1.406458244399709110790004570313446E-2558 + 4249 7.03229122199854555395002285156723E-2559 3.516145610999272776975011425783615E-2559 + 4250 1.758072805499636388487505712891808E-2559 8.790364027498181942437528564459038E-2560 + 4251 4.395182013749090971218764282229519E-2560 2.197591006874545485609382141114760E-2560 + 4252 1.098795503437272742804691070557380E-2560 5.49397751718636371402345535278690E-2561 + 4253 2.74698875859318185701172767639345E-2561 1.373494379296590928505863838196725E-2561 + 4254 6.867471896482954642529319190983625E-2562 3.433735948241477321264659595491813E-2562 + 4255 1.716867974120738660632329797745907E-2562 8.584339870603693303161648988729533E-2563 + 4256 4.292169935301846651580824494364767E-2563 2.146084967650923325790412247182383E-2563 + 4257 1.073042483825461662895206123591192E-2563 5.365212419127308314476030617955958E-2564 + 4258 2.682606209563654157238015308977979E-2564 1.341303104781827078619007654488990E-2564 + 4259 6.70651552390913539309503827244495E-2565 3.353257761954567696547519136222475E-2565 + 4260 1.676628880977283848273759568111238E-2565 8.383144404886419241368797840556188E-2566 + 4261 4.191572202443209620684398920278094E-2566 2.095786101221604810342199460139047E-2566 + 4262 1.047893050610802405171099730069524E-2566 5.239465253054012025855498650347618E-2567 + 4263 2.619732626527006012927749325173809E-2567 1.309866313263503006463874662586905E-2567 + 4264 6.549331566317515032319373312934525E-2568 3.274665783158757516159686656467263E-2568 + 4265 1.637332891579378758079843328233632E-2568 8.186664457896893790399216641168158E-2569 + 4266 4.093332228948446895199608320584079E-2569 2.046666114474223447599804160292040E-2569 + 4267 1.023333057237111723799902080146020E-2569 5.11666528618555861899951040073010E-2570 + 4268 2.55833264309277930949975520036505E-2570 1.279166321546389654749877600182525E-2570 + 4269 6.395831607731948273749388000912625E-2571 3.197915803865974136874694000456313E-2571 + 4270 1.598957901932987068437347000228157E-2571 7.994789509664935342186735001140783E-2572 + 4271 3.997394754832467671093367500570392E-2572 1.998697377416233835546683750285196E-2572 + 4272 9.99348688708116917773341875142598E-2573 4.99674344354058458886670937571299E-2573 + 4273 2.498371721770292294433354687856495E-2573 1.249185860885146147216677343928248E-2573 + 4274 6.24592930442573073608338671964124E-2574 3.12296465221286536804169335982062E-2574 + 4275 1.56148232610643268402084667991031E-2574 7.80741163053216342010423339955155E-2575 + 4276 3.903705815266081710052116699775775E-2575 1.951852907633040855026058349887888E-2575 + 4277 9.75926453816520427513029174943944E-2576 4.87963226908260213756514587471972E-2576 + 4278 2.43981613454130106878257293735986E-2576 1.21990806727065053439128646867993E-2576 + 4279 6.09954033635325267195643234339965E-2577 3.049770168176626335978216171699825E-2577 + 4280 1.524885084088313167989108085849913E-2577 7.624425420441565839945540429249563E-2578 + 4281 3.812212710220782919972770214624782E-2578 1.906106355110391459986385107312391E-2578 + 4282 9.530531775551957299931925536561955E-2579 4.765265887775978649965962768280978E-2579 + 4283 2.382632943887989324982981384140489E-2579 1.191316471943994662491490692070245E-2579 + 4284 5.956582359719973312457453460351225E-2580 2.978291179859986656228726730175613E-2580 + 4285 1.489145589929993328114363365087807E-2580 7.445727949649966640571816825439033E-2581 + 4286 3.722863974824983320285908412719517E-2581 1.861431987412491660142954206359758E-2581 + 4287 9.30715993706245830071477103179879E-2582 4.653579968531229150357385515899395E-2582 + 4288 2.326789984265614575178692757949698E-2582 1.163394992132807287589346378974849E-2582 + 4289 5.816974960664036437946731894874245E-2583 2.908487480332018218973365947437123E-2583 + 4290 1.454243740166009109486682973718562E-2583 7.271218700830045547433414868592808E-2584 + 4291 3.635609350415022773716707434296404E-2584 1.817804675207511386858353717148202E-2584 + 4292 9.08902337603755693429176858574101E-2585 4.544511688018778467145884292870505E-2585 + 4293 2.272255844009389233572942146435253E-2585 1.136127922004694616786471073217626E-2585 + 4294 5.68063961002347308393235536608813E-2586 2.840319805011736541966177683044065E-2586 + 4295 1.420159902505868270983088841522033E-2586 7.100799512529341354915444207610163E-2587 + 4296 3.550399756264670677457722103805082E-2587 1.775199878132335338728861051902541E-2587 + 4297 8.875999390661676693644305259512705E-2588 4.437999695330838346822152629756353E-2588 + 4298 2.218999847665419173411076314878177E-2588 1.109499923832709586705538157439088E-2588 + 4299 5.54749961916354793352769078719544E-2589 2.77374980958177396676384539359772E-2589 + 4300 1.38687490479088698338192269679886E-2589 6.9343745239544349169096134839943E-2590 + 4301 3.46718726197721745845480674199715E-2590 1.733593630988608729227403370998575E-2590 + 4302 8.667968154943043646137016854992875E-2591 4.333984077471521823068508427496438E-2591 + 4303 2.166992038735760911534254213748219E-2591 1.083496019367880455767127106874110E-2591 + 4304 5.41748009683940227883563553437055E-2592 2.708740048419701139417817767185275E-2592 + 4305 1.354370024209850569708908883592638E-2592 6.771850121049252848544544417963188E-2593 + 4306 3.385925060524626424272272208981594E-2593 1.692962530262313212136136104490797E-2593 + 4307 8.464812651311566060680680522453985E-2594 4.232406325655783030340340261226993E-2594 + 4308 2.116203162827891515170170130613497E-2594 1.058101581413945757585085065306748E-2594 + 4309 5.29050790706972878792542532653374E-2595 2.64525395353486439396271266326687E-2595 + 4310 1.322626976767432196981356331633435E-2595 6.613134883837160984906781658167175E-2596 + 4311 3.306567441918580492453390829083588E-2596 1.653283720959290246226695414541794E-2596 + 4312 8.26641860479645123113347707270897E-2597 4.133209302398225615566738536354485E-2597 + 4313 2.066604651199112807783369268177243E-2597 1.033302325599556403891684634088621E-2597 + 4314 5.166511627997782019458423170443105E-2598 2.583255813998891009729211585221553E-2598 + 4315 1.291627906999445504864605792610777E-2598 6.458139534997227524323028963053883E-2599 + 4316 3.229069767498613762161514481526942E-2599 1.614534883749306881080757240763471E-2599 + 4317 8.072674418746534405403786203817355E-2600 4.036337209373267202701893101908678E-2600 + 4318 2.018168604686633601350946550954339E-2600 1.009084302343316800675473275477170E-2600 + 4319 5.04542151171658400337736637738585E-2601 2.522710755858292001688683188692925E-2601 + 4320 1.261355377929146000844341594346463E-2601 6.306776889645730004221707971732313E-2602 + 4321 3.153388444822865002110853985866157E-2602 1.576694222411432501055426992933078E-2602 + 4322 7.88347111205716250527713496466539E-2603 3.941735556028581252638567482332695E-2603 + 4323 1.970867778014290626319283741166348E-2603 9.854338890071453131596418705831738E-2604 + 4324 4.927169445035726565798209352915869E-2604 2.463584722517863282899104676457935E-2604 + 4325 1.231792361258931641449552338228968E-2604 6.158961806294658207247761691144838E-2605 + 4326 3.079480903147329103623880845572419E-2605 1.539740451573664551811940422786210E-2605 + 4327 7.69870225786832275905970211393105E-2606 3.849351128934161379529851056965525E-2606 + 4328 1.924675564467080689764925528482763E-2606 9.623377822335403448824627642413813E-2607 + 4329 4.811688911167701724412313821206907E-2607 2.405844455583850862206156910603453E-2607 + 4330 1.202922227791925431103078455301727E-2607 6.014611138959627155515392276508633E-2608 + 4331 3.007305569479813577757696138254317E-2608 1.503652784739906788878848069127158E-2608 + 4332 7.51826392369953394439424034563579E-2609 3.759131961849766972197120172817895E-2609 + 4333 1.879565980924883486098560086408948E-2609 9.397829904624417430492800432044738E-2610 + 4334 4.698914952312208715246400216022369E-2610 2.349457476156104357623200108011185E-2610 + 4335 1.174728738078052178811600054005593E-2610 5.873643690390260894058000270027963E-2611 + 4336 2.936821845195130447029000135013982E-2611 1.468410922597565223514500067506991E-2611 + 4337 7.342054612987826117572500337534955E-2612 3.671027306493913058786250168767478E-2612 + 4338 1.835513653246956529393125084383739E-2612 9.177568266234782646965625421918695E-2613 + 4339 4.588784133117391323482812710959348E-2613 2.294392066558695661741406355479674E-2613 + 4340 1.147196033279347830870703177739837E-2613 5.735980166396739154353515888699185E-2614 + 4341 2.867990083198369577176757944349593E-2614 1.433995041599184788588378972174796E-2614 + 4342 7.16997520799592394294189486087398E-2615 3.58498760399796197147094743043699E-2615 + 4343 1.792493801998980985735473715218495E-2615 8.962469009994904928677368576092475E-2616 + 4344 4.481234504997452464338684288046238E-2616 2.240617252498726232169342144023119E-2616 + 4345 1.120308626249363116084671072011560E-2616 5.601543131246815580423355360057798E-2617 + 4346 2.800771565623407790211677680028899E-2617 1.400385782811703895105838840014450E-2617 + 4347 7.00192891405851947552919420007225E-2618 3.500964457029259737764597100036125E-2618 + 4348 1.750482228514629868882298550018063E-2618 8.752411142573149344411492750090313E-2619 + 4349 4.376205571286574672205746375045157E-2619 2.188102785643287336102873187522578E-2619 + 4350 1.094051392821643668051436593761289E-2619 5.470256964108218340257182968806445E-2620 + 4351 2.735128482054109170128591484403223E-2620 1.367564241027054585064295742201611E-2620 + 4352 6.837821205135272925321478711008055E-2621 3.418910602567636462660739355504028E-2621 + 4353 1.709455301283818231330369677752014E-2621 8.54727650641909115665184838876007E-2622 + 4354 4.273638253209545578325924194380035E-2622 2.136819126604772789162962097190018E-2622 + 4355 1.068409563302386394581481048595009E-2622 5.342047816511931972907405242975045E-2623 + 4356 2.671023908255965986453702621487523E-2623 1.335511954127982993226851310743761E-2623 + 4357 6.677559770639914966134256553718805E-2624 3.338779885319957483067128276859403E-2624 + 4358 1.669389942659978741533564138429702E-2624 8.346949713299893707667820692148508E-2625 + 4359 4.173474856649946853833910346074254E-2625 2.086737428324973426916955173037127E-2625 + 4360 1.043368714162486713458477586518564E-2625 5.216843570812433567292387932592818E-2626 + 4361 2.608421785406216783646193966296409E-2626 1.304210892703108391823096983148205E-2626 + 4362 6.521054463515541959115484915741025E-2627 3.260527231757770979557742457870513E-2627 + 4363 1.630263615878885489778871228935257E-2627 8.151318079394427448894356144676283E-2628 + 4364 4.075659039697213724447178072338142E-2628 2.037829519848606862223589036169071E-2628 + 4365 1.018914759924303431111794518084536E-2628 5.094573799621517155558972590422678E-2629 + 4366 2.547286899810758577779486295211339E-2629 1.273643449905379288889743147605670E-2629 + 4367 6.36821724952689644444871573802835E-2630 3.184108624763448222224357869014175E-2630 + 4368 1.592054312381724111112178934507088E-2630 7.960271561908620555560894672535438E-2631 + 4369 3.980135780954310277780447336267719E-2631 1.990067890477155138890223668133860E-2631 + 4370 9.95033945238577569445111834066930E-2632 4.97516972619288784722555917033465E-2632 + 4371 2.487584863096443923612779585167325E-2632 1.243792431548221961806389792583663E-2632 + 4372 6.218962157741109809031948962918315E-2633 3.109481078870554904515974481459158E-2633 + 4373 1.554740539435277452257987240729579E-2633 7.773702697176387261289936203647895E-2634 + 4374 3.886851348588193630644968101823948E-2634 1.943425674294096815322484050911974E-2634 + 4375 9.71712837147048407661242025455987E-2635 4.858564185735242038306210127279935E-2635 + 4376 2.429282092867621019153105063639968E-2635 1.214641046433810509576552531819984E-2635 + 4377 6.07320523216905254788276265909992E-2636 3.03660261608452627394138132954996E-2636 + 4378 1.51830130804226313697069066477498E-2636 7.5915065402113156848534533238749E-2637 + 4379 3.79575327010565784242672666193745E-2637 1.897876635052828921213363330968725E-2637 + 4380 9.489383175264144606066816654843625E-2638 4.744691587632072303033408327421813E-2638 + 4381 2.372345793816036151516704163710907E-2638 1.186172896908018075758352081855453E-2638 + 4382 5.930864484540090378791760409277265E-2639 2.965432242270045189395880204638633E-2639 + 4383 1.482716121135022594697940102319317E-2639 7.413580605675112973489700511596583E-2640 + 4384 3.706790302837556486744850255798292E-2640 1.853395151418778243372425127899146E-2640 + 4385 9.26697575709389121686212563949573E-2641 4.633487878546945608431062819747865E-2641 + 4386 2.316743939273472804215531409873933E-2641 1.158371969636736402107765704936966E-2641 + 4387 5.79185984818368201053882852468483E-2642 2.895929924091841005269414262342415E-2642 + 4388 1.447964962045920502634707131171208E-2642 7.239824810229602513173535655856038E-2643 + 4389 3.619912405114801256586767827928019E-2643 1.809956202557400628293383913964010E-2643 + 4390 9.04978101278700314146691956982005E-2644 4.524890506393501570733459784910025E-2644 + 4391 2.262445253196750785366729892455013E-2644 1.131222626598375392683364946227506E-2644 + 4392 5.65611313299187696341682473113753E-2645 2.828056566495938481708412365568765E-2645 + 4393 1.414028283247969240854206182784383E-2645 7.070141416239846204271030913921913E-2646 + 4394 3.535070708119923102135515456960957E-2646 1.767535354059961551067757728480478E-2646 + 4395 8.83767677029980775533878864240239E-2647 4.418838385149903877669394321201195E-2647 + 4396 2.209419192574951938834697160600598E-2647 1.104709596287475969417348580300299E-2647 + 4397 5.523547981437379847086742901501495E-2648 2.761773990718689923543371450750748E-2648 + 4398 1.380886995359344961771685725375374E-2648 6.90443497679672480885842862687687E-2649 + 4399 3.452217488398362404429214313438435E-2649 1.726108744199181202214607156719218E-2649 + 4400 8.63054372099590601107303578359609E-2650 4.315271860497953005536517891798045E-2650 + 4401 2.157635930248976502768258945899023E-2650 1.078817965124488251384129472949511E-2650 + 4402 5.394089825622441256920647364747555E-2651 2.697044912811220628460323682373778E-2651 + 4403 1.348522456405610314230161841186889E-2651 6.742612282028051571150809205934445E-2652 + 4404 3.371306141014025785575404602967223E-2652 1.685653070507012892787702301483611E-2652 + 4405 8.428265352535064463938511507418055E-2653 4.214132676267532231969255753709028E-2653 + 4406 2.107066338133766115984627876854514E-2653 1.053533169066883057992313938427257E-2653 + 4407 5.267665845334415289961569692136285E-2654 2.633832922667207644980784846068143E-2654 + 4408 1.316916461333603822490392423034072E-2654 6.584582306668019112451962115170358E-2655 + 4409 3.292291153334009556225981057585179E-2655 1.646145576667004778112990528792590E-2655 + 4410 8.23072788333502389056495264396295E-2656 4.115363941667511945282476321981475E-2656 + 4411 2.057681970833755972641238160990738E-2656 1.028840985416877986320619080495369E-2656 + 4412 5.144204927084389931603095402476845E-2657 2.572102463542194965801547701238423E-2657 + 4413 1.286051231771097482900773850619212E-2657 6.430256158855487414503869253096058E-2658 + 4414 3.215128079427743707251934626548029E-2658 1.607564039713871853625967313274015E-2658 + 4415 8.037820198569359268129836566370075E-2659 4.018910099284679634064918283185038E-2659 + 4416 2.009455049642339817032459141592519E-2659 1.004727524821169908516229570796260E-2659 + 4417 5.02363762410584954258114785398130E-2660 2.51181881205292477129057392699065E-2660 + 4418 1.255909406026462385645286963495325E-2660 6.279547030132311928226434817476625E-2661 + 4419 3.139773515066155964113217408738313E-2661 1.569886757533077982056608704369156E-2661 + 4420 7.84943378766538991028304352184578E-2662 3.92471689383269495514152176092289E-2662 + 4421 1.962358446916347477570760880461445E-2662 9.811792234581737387853804402307225E-2663 + 4422 4.905896117290868693926902201153613E-2663 2.452948058645434346963451100576806E-2663 + 4423 1.226474029322717173481725550288403E-2663 6.132370146613585867408627751442015E-2664 + 4424 3.066185073306792933704313875721008E-2664 1.533092536653396466852156937860504E-2664 + 4425 7.66546268326698233426078468930252E-2665 3.83273134163349116713039234465126E-2665 + 4426 1.91636567081674558356519617232563E-2665 9.58182835408372791782598086162815E-2666 + 4427 4.790914177041863958912990430814075E-2666 2.395457088520931979456495215407038E-2666 + 4428 1.197728544260465989728247607703519E-2666 5.988642721302329948641238038517595E-2667 + 4429 2.994321360651164974320619019258798E-2667 1.497160680325582487160309509629399E-2667 + 4430 7.485803401627912435801547548146995E-2668 3.742901700813956217900773774073498E-2668 + 4431 1.871450850406978108950386887036749E-2668 9.357254252034890544751934435183745E-2669 + 4432 4.678627126017445272375967217591873E-2669 2.339313563008722636187983608795936E-2669 + 4433 1.169656781504361318093991804397968E-2669 5.84828390752180659046995902198984E-2670 + 4434 2.92414195376090329523497951099492E-2670 1.46207097688045164761748975549746E-2670 + 4435 7.3103548844022582380874487774873E-2671 3.65517744220112911904372438874365E-2671 + 4436 1.827588721100564559521862194371825E-2671 9.137943605502822797609310971859125E-2672 + 4437 4.568971802751411398804655485929563E-2672 2.284485901375705699402327742964781E-2672 + 4438 1.142242950687852849701163871482391E-2672 5.711214753439264248505819357411953E-2673 + 4439 2.855607376719632124252909678705977E-2673 1.427803688359816062126454839352988E-2673 + 4440 7.13901844179908031063227419676494E-2674 3.56950922089954015531613709838247E-2674 + 4441 1.784754610449770077658068549191235E-2674 8.923773052248850388290342745956175E-2675 + 4442 4.461886526124425194145171372978088E-2675 2.230943263062212597072585686489044E-2675 + 4443 1.115471631531106298536292843244522E-2675 5.57735815765553149268146421622261E-2676 + 4444 2.788679078827765746340732108111305E-2676 1.394339539413882873170366054055653E-2676 + 4445 6.971697697069414365851830270278265E-2677 3.485848848534707182925915135139133E-2677 + 4446 1.742924424267353591462957567569567E-2677 8.714622121336767957314787837847833E-2678 + 4447 4.357311060668383978657393918923917E-2678 2.178655530334191989328696959461958E-2678 + 4448 1.089327765167095994664348479730979E-2678 5.446638825835479973321742398654895E-2679 + 4449 2.723319412917739986660871199327448E-2679 1.361659706458869993330435599663724E-2679 + 4450 6.80829853229434996665217799831862E-2680 3.40414926614717498332608899915931E-2680 + 4451 1.702074633073587491663044499579655E-2680 8.510373165367937458315222497898275E-2681 + 4452 4.255186582683968729157611248949138E-2681 2.127593291341984364578805624474569E-2681 + 4453 1.063796645670992182289402812237285E-2681 5.318983228354960911447014061186423E-2682 + 4454 2.659491614177480455723507030593212E-2682 1.329745807088740227861753515296606E-2682 + 4455 6.64872903544370113930876757648303E-2683 3.324364517721850569654383788241515E-2683 + 4456 1.662182258860925284827191894120758E-2683 8.310911294304626424135959470603788E-2684 + 4457 4.155455647152313212067979735301894E-2684 2.077727823576156606033989867650947E-2684 + 4458 1.038863911788078303016994933825474E-2684 5.194319558940391515084974669127368E-2685 + 4459 2.597159779470195757542487334563684E-2685 1.298579889735097878771243667281842E-2685 + 4460 6.49289944867548939385621833640921E-2686 3.246449724337744696928109168204605E-2686 + 4461 1.623224862168872348464054584102303E-2686 8.116124310844361742320272920511513E-2687 + 4462 4.058062155422180871160136460255757E-2687 2.029031077711090435580068230127878E-2687 + 4463 1.014515538855545217790034115063939E-2687 5.072577694277726088950170575319695E-2688 + 4464 2.536288847138863044475085287659848E-2688 1.268144423569431522237542643829924E-2688 + 4465 6.34072211784715761118771321914962E-2689 3.17036105892357880559385660957481E-2689 + 4466 1.585180529461789402796928304787405E-2689 7.925902647308947013984641523937025E-2690 + 4467 3.962951323654473506992320761968513E-2690 1.981475661827236753496160380984256E-2690 + 4468 9.90737830913618376748080190492128E-2691 4.95368915456809188374040095246064E-2691 + 4469 2.47684457728404594187020047623032E-2691 1.23842228864202297093510023811516E-2691 + 4470 6.1921114432101148546755011905758E-2692 3.0960557216050574273377505952879E-2692 + 4471 1.54802786080252871366887529764395E-2692 7.74013930401264356834437648821975E-2693 + 4472 3.870069652006321784172188244109875E-2693 1.935034826003160892086094122054938E-2693 + 4473 9.67517413001580446043047061027469E-2694 4.837587065007902230215235305137345E-2694 + 4474 2.418793532503951115107617652568673E-2694 1.209396766251975557553808826284336E-2694 + 4475 6.04698383125987778776904413142168E-2695 3.02349191562993889388452206571084E-2695 + 4476 1.51174595781496944694226103285542E-2695 7.5587297890748472347113051642771E-2696 + 4477 3.77936489453742361735565258213855E-2696 1.889682447268711808677826291069275E-2696 + 4478 9.448412236343559043389131455346375E-2697 4.724206118171779521694565727673188E-2697 + 4479 2.362103059085889760847282863836594E-2697 1.181051529542944880423641431918297E-2697 + 4480 5.905257647714724402118207159591485E-2698 2.952628823857362201059103579795743E-2698 + 4481 1.476314411928681100529551789897872E-2698 7.381572059643405502647758949489358E-2699 + 4482 3.690786029821702751323879474744679E-2699 1.845393014910851375661939737372340E-2699 + 4483 9.22696507455425687830969868686170E-2700 4.61348253727712843915484934343085E-2700 + 4484 2.306741268638564219577424671715425E-2700 1.153370634319282109788712335857713E-2700 + 4485 5.766853171596410548943561679288565E-2701 2.883426585798205274471780839644283E-2701 + 4486 1.441713292899102637235890419822142E-2701 7.208566464495513186179452099110708E-2702 + 4487 3.604283232247756593089726049555354E-2702 1.802141616123878296544863024777677E-2702 + 4488 9.010708080619391482724315123888385E-2703 4.505354040309695741362157561944193E-2703 + 4489 2.252677020154847870681078780972097E-2703 1.126338510077423935340539390486048E-2703 + 4490 5.63169255038711967670269695243024E-2704 2.81584627519355983835134847621512E-2704 + 4491 1.40792313759677991917567423810756E-2704 7.0396156879838995958783711905378E-2705 + 4492 3.5198078439919497979391855952689E-2705 1.75990392199597489896959279763445E-2705 + 4493 8.79951960997987449484796398817225E-2706 4.399759804989937247423981994086125E-2706 + 4494 2.199879902494968623711990997043063E-2706 1.099939951247484311855995498521531E-2706 + 4495 5.499699756237421559279977492607655E-2707 2.749849878118710779639988746303828E-2707 + 4496 1.374924939059355389819994373151914E-2707 6.87462469529677694909997186575957E-2708 + 4497 3.437312347648388474549985932879785E-2708 1.718656173824194237274992966439893E-2708 + 4498 8.593280869120971186374964832199465E-2709 4.296640434560485593187482416099733E-2709 + 4499 2.148320217280242796593741208049867E-2709 1.074160108640121398296870604024933E-2709 + 4500 5.370800543200606991484353020124665E-2710 2.685400271600303495742176510062333E-2710 + 4501 1.342700135800151747871088255031167E-2710 6.713500679000758739355441275155833E-2711 + 4502 3.356750339500379369677720637577917E-2711 1.678375169750189684838860318788958E-2711 + 4503 8.39187584875094842419430159394479E-2712 4.195937924375474212097150796972395E-2712 + 4504 2.097968962187737106048575398486198E-2712 1.048984481093868553024287699243099E-2712 + 4505 5.244922405469342765121438496215495E-2713 2.622461202734671382560719248107748E-2713 + 4506 1.311230601367335691280359624053874E-2713 6.55615300683667845640179812026937E-2714 + 4507 3.278076503418339228200899060134685E-2714 1.639038251709169614100449530067343E-2714 + 4508 8.195191258545848070502247650336715E-2715 4.097595629272924035251123825168358E-2715 + 4509 2.048797814636462017625561912584179E-2715 1.024398907318231008812780956292090E-2715 + 4510 5.12199453659115504406390478146045E-2716 2.560997268295577522031952390730225E-2716 + 4511 1.280498634147788761015976195365113E-2716 6.402493170738943805079880976825563E-2717 + 4512 3.201246585369471902539940488412782E-2717 1.600623292684735951269970244206391E-2717 + 4513 8.003116463423679756349851221031955E-2718 4.001558231711839878174925610515978E-2718 + 4514 2.000779115855919939087462805257989E-2718 1.000389557927959969543731402628995E-2718 + 4515 5.001947789639799847718657013144975E-2719 2.500973894819899923859328506572488E-2719 + 4516 1.250486947409949961929664253286244E-2719 6.25243473704974980964832126643122E-2720 + 4517 3.12621736852487490482416063321561E-2720 1.563108684262437452412080316607805E-2720 + 4518 7.815543421312187262060401583039025E-2721 3.907771710656093631030200791519513E-2721 + 4519 1.953885855328046815515100395759757E-2721 9.769429276640234077575501978798783E-2722 + 4520 4.884714638320117038787750989399392E-2722 2.442357319160058519393875494699696E-2722 + 4521 1.221178659580029259696937747349848E-2722 6.10589329790014629848468873674924E-2723 + 4522 3.05294664895007314924234436837462E-2723 1.52647332447503657462117218418731E-2723 + 4523 7.63236662237518287310586092093655E-2724 3.816183311187591436552930460468275E-2724 + 4524 1.908091655593795718276465230234138E-2724 9.540458277968978591382326151170688E-2725 + 4525 4.770229138984489295691163075585344E-2725 2.385114569492244647845581537792672E-2725 + 4526 1.192557284746122323922790768896336E-2725 5.96278642373061161961395384448168E-2726 + 4527 2.98139321186530580980697692224084E-2726 1.49069660593265290490348846112042E-2726 + 4528 7.4534830296632645245174423056021E-2727 3.72674151483163226225872115280105E-2727 + 4529 1.863370757415816131129360576400525E-2727 9.316853787079080655646802882002625E-2728 + 4530 4.658426893539540327823401441001313E-2728 2.329213446769770163911700720500656E-2728 + 4531 1.164606723384885081955850360250328E-2728 5.82303361692442540977925180125164E-2729 + 4532 2.91151680846221270488962590062582E-2729 1.45575840423110635244481295031291E-2729 + 4533 7.27879202115553176222406475156455E-2730 3.639396010577765881112032375782275E-2730 + 4534 1.819698005288882940556016187891138E-2730 9.098490026444414702780080939455688E-2731 + 4535 4.549245013222207351390040469727844E-2731 2.274622506611103675695020234863922E-2731 + 4536 1.137311253305551837847510117431961E-2731 5.686556266527759189237550587159805E-2732 + 4537 2.843278133263879594618775293579903E-2732 1.421639066631939797309387646789951E-2732 + 4538 7.108195333159698986546938233949755E-2733 3.554097666579849493273469116974878E-2733 + 4539 1.777048833289924746636734558487439E-2733 8.885244166449623733183672792437195E-2734 + 4540 4.442622083224811866591836396218598E-2734 2.221311041612405933295918198109299E-2734 + 4541 1.110655520806202966647959099054650E-2734 5.553277604031014833239795495273248E-2735 + 4542 2.776638802015507416619897747636624E-2735 1.388319401007753708309948873818312E-2735 + 4543 6.94159700503876854154974436909156E-2736 3.47079850251938427077487218454578E-2736 + 4544 1.73539925125969213538743609227289E-2736 8.67699625629846067693718046136445E-2737 + 4545 4.338498128149230338468590230682225E-2737 2.169249064074615169234295115341113E-2737 + 4546 1.084624532037307584617147557670557E-2737 5.423122660186537923085737788352783E-2738 + 4547 2.711561330093268961542868894176392E-2738 1.355780665046634480771434447088196E-2738 + 4548 6.77890332523317240385717223544098E-2739 3.38945166261658620192858611772049E-2739 + 4549 1.694725831308293100964293058860245E-2739 8.473629156541465504821465294301225E-2740 + 4550 4.236814578270732752410732647150613E-2740 2.118407289135366376205366323575306E-2740 + 4551 1.059203644567683188102683161787653E-2740 5.296018222838415940513415808938265E-2741 + 4552 2.648009111419207970256707904469133E-2741 1.324004555709603985128353952234566E-2741 + 4553 6.62002277854801992564176976117283E-2742 3.310011389274009962820884880586415E-2742 + 4554 1.655005694637004981410442440293208E-2742 8.275028473185024907052212201466038E-2743 + 4555 4.137514236592512453526106100733019E-2743 2.068757118296256226763053050366510E-2743 + 4556 1.034378559148128113381526525183255E-2743 5.171892795740640566907632625916275E-2744 + 4557 2.585946397870320283453816312958138E-2744 1.292973198935160141726908156479069E-2744 + 4558 6.464865994675800708634540782395345E-2745 3.232432997337900354317270391197673E-2745 + 4559 1.616216498668950177158635195598837E-2745 8.081082493344750885793175977994183E-2746 + 4560 4.040541246672375442896587988997092E-2746 2.020270623336187721448293994498546E-2746 + 4561 1.010135311668093860724146997249273E-2746 5.050676558340469303620734986246365E-2747 + 4562 2.525338279170234651810367493123183E-2747 1.262669139585117325905183746561591E-2747 + 4563 6.313345697925586629525918732807955E-2748 3.156672848962793314762959366403978E-2748 + 4564 1.578336424481396657381479683201989E-2748 7.891682122406983286907398416009945E-2749 + 4565 3.945841061203491643453699208004973E-2749 1.972920530601745821726849604002486E-2749 + 4566 9.86460265300872910863424802001243E-2750 4.932301326504364554317124010006215E-2750 + 4567 2.466150663252182277158562005003108E-2750 1.233075331626091138579281002501554E-2750 + 4568 6.16537665813045569289640501250777E-2751 3.082688329065227846448202506253885E-2751 + 4569 1.541344164532613923224101253126943E-2751 7.706720822663069616120506265634713E-2752 + 4570 3.853360411331534808060253132817357E-2752 1.926680205665767404030126566408678E-2752 + 4571 9.63340102832883702015063283204339E-2753 4.816700514164418510075316416021695E-2753 + 4572 2.408350257082209255037658208010848E-2753 1.204175128541104627518829104005424E-2753 + 4573 6.02087564270552313759414552002712E-2754 3.01043782135276156879707276001356E-2754 + 4574 1.50521891067638078439853638000678E-2754 7.5260945533819039219926819000339E-2755 + 4575 3.76304727669095196099634095001695E-2755 1.881523638345475980498170475008475E-2755 + 4576 9.407618191727379902490852375042375E-2756 4.703809095863689951245426187521188E-2756 + 4577 2.351904547931844975622713093760594E-2756 1.175952273965922487811356546880297E-2756 + 4578 5.879761369829612439056782734401485E-2757 2.939880684914806219528391367200743E-2757 + 4579 1.469940342457403109764195683600372E-2757 7.349701712287015548820978418001858E-2758 + 4580 3.674850856143507774410489209000929E-2758 1.837425428071753887205244604500465E-2758 + 4581 9.187127140358769436026223022502325E-2759 4.593563570179384718013111511251163E-2759 + 4582 2.296781785089692359006555755625582E-2759 1.148390892544846179503277877812791E-2759 + 4583 5.741954462724230897516389389063955E-2760 2.870977231362115448758194694531978E-2760 + 4584 1.435488615681057724379097347265989E-2760 7.177443078405288621895486736329945E-2761 + 4585 3.588721539202644310947743368164973E-2761 1.794360769601322155473871684082486E-2761 + 4586 8.97180384800661077736935842041243E-2762 4.485901924003305388684679210206215E-2762 + 4587 2.242950962001652694342339605103108E-2762 1.121475481000826347171169802551554E-2762 + 4588 5.60737740500413173585584901275777E-2763 2.803688702502065867927924506378885E-2763 + 4589 1.401844351251032933963962253189443E-2763 7.009221756255164669819811265947213E-2764 + 4590 3.504610878127582334909905632973607E-2764 1.752305439063791167454952816486803E-2764 + 4591 8.761527195318955837274764082434015E-2765 4.380763597659477918637382041217008E-2765 + 4592 2.190381798829738959318691020608504E-2765 1.095190899414869479659345510304252E-2765 + 4593 5.47595449707434739829672755152126E-2766 2.73797724853717369914836377576063E-2766 + 4594 1.368988624268586849574181887880315E-2766 6.844943121342934247870909439401575E-2767 + 4595 3.422471560671467123935454719700788E-2767 1.711235780335733561967727359850394E-2767 + 4596 8.55617890167866780983863679925197E-2768 4.278089450839333904919318399625985E-2768 + 4597 2.139044725419666952459659199812993E-2768 1.069522362709833476229829599906496E-2768 + 4598 5.34761181354916738114914799953248E-2769 2.67380590677458369057457399976624E-2769 + 4599 1.33690295338729184528728699988312E-2769 6.6845147669364592264364349994156E-2770 + 4600 3.3422573834682296132182174997078E-2770 1.6711286917341148066091087498539E-2770 + 4601 8.3556434586705740330455437492695E-2771 4.17782172933528701652277187463475E-2771 + 4602 2.088910864667643508261385937317375E-2771 1.044455432333821754130692968658688E-2771 + 4603 5.22227716166910877065346484329344E-2772 2.61113858083455438532673242164672E-2772 + 4604 1.30556929041727719266336621082336E-2772 6.5278464520863859633168310541168E-2773 + 4605 3.2639232260431929816584155270584E-2773 1.6319616130215964908292077635292E-2773 + 4606 8.159808065107982454146038817646E-2774 4.079904032553991227073019408823E-2774 + 4607 2.0399520162769956135365097044115E-2774 1.01997600813849780676825485220575E-2774 + 4608 5.09988004069248903384127426102875E-2775 2.549940020346244516920637130514375E-2775 + 4609 1.274970010173122258460318565257188E-2775 6.374850050865611292301592826285938E-2776 + 4610 3.187425025432805646150796413142969E-2776 1.593712512716402823075398206571485E-2776 + 4611 7.968562563582014115376991032857425E-2777 3.984281281791007057688495516428713E-2777 + 4612 1.992140640895503528844247758214357E-2777 9.960703204477517644221238791071783E-2778 + 4613 4.980351602238758822110619395535892E-2778 2.490175801119379411055309697767946E-2778 + 4614 1.245087900559689705527654848883973E-2778 6.225439502798448527638274244419865E-2779 + 4615 3.112719751399224263819137122209933E-2779 1.556359875699612131909568561104966E-2779 + 4616 7.78179937849806065954784280552483E-2780 3.890899689249030329773921402762415E-2780 + 4617 1.945449844624515164886960701381208E-2780 9.727249223122575824434803506906038E-2781 + 4618 4.863624611561287912217401753453019E-2781 2.431812305780643956108700876726510E-2781 + 4619 1.215906152890321978054350438363255E-2781 6.079530764451609890271752191816275E-2782 + 4620 3.039765382225804945135876095908138E-2782 1.519882691112902472567938047954069E-2782 + 4621 7.599413455564512362839690239770345E-2783 3.799706727782256181419845119885173E-2783 + 4622 1.899853363891128090709922559942587E-2783 9.499266819455640453549612799712933E-2784 + 4623 4.749633409727820226774806399856467E-2784 2.374816704863910113387403199928233E-2784 + 4624 1.187408352431955056693701599964117E-2784 5.937041762159775283468507999820583E-2785 + 4625 2.968520881079887641734253999910292E-2785 1.484260440539943820867126999955146E-2785 + 4626 7.42130220269971910433563499977573E-2786 3.710651101349859552167817499887865E-2786 + 4627 1.855325550674929776083908749943933E-2786 9.276627753374648880419543749719663E-2787 + 4628 4.638313876687324440209771874859832E-2787 2.319156938343662220104885937429916E-2787 + 4629 1.159578469171831110052442968714958E-2787 5.79789234585915555026221484357479E-2788 + 4630 2.898946172929577775131107421787395E-2788 1.449473086464788887565553710893698E-2788 + 4631 7.24736543232394443782776855446849E-2789 3.623682716161972218913884277234245E-2789 + 4632 1.811841358080986109456942138617123E-2789 9.059206790404930547284710693085613E-2790 + 4633 4.529603395202465273642355346542807E-2790 2.264801697601232636821177673271403E-2790 + 4634 1.132400848800616318410588836635702E-2790 5.662004244003081592052944183178508E-2791 + 4635 2.831002122001540796026472091589254E-2791 1.415501061000770398013236045794627E-2791 + 4636 7.077505305003851990066180228973135E-2792 3.538752652501925995033090114486568E-2792 + 4637 1.769376326250962997516545057243284E-2792 8.84688163125481498758272528621642E-2793 + 4638 4.42344081562740749379136264310821E-2793 2.211720407813703746895681321554105E-2793 + 4639 1.105860203906851873447840660777053E-2793 5.529301019534259367239203303885263E-2794 + 4640 2.764650509767129683619601651942632E-2794 1.382325254883564841809800825971316E-2794 + 4641 6.91162627441782420904900412985658E-2795 3.45581313720891210452450206492829E-2795 + 4642 1.727906568604456052262251032464145E-2795 8.639532843022280261311255162320725E-2796 + 4643 4.319766421511140130655627581160363E-2796 2.159883210755570065327813790580181E-2796 + 4644 1.079941605377785032663906895290091E-2796 5.399708026888925163319534476450453E-2797 + 4645 2.699854013444462581659767238225227E-2797 1.349927006722231290829883619112613E-2797 + 4646 6.749635033611156454149418095563065E-2798 3.374817516805578227074709047781533E-2798 + 4647 1.687408758402789113537354523890767E-2798 8.437043792013945567686772619453833E-2799 + 4648 4.218521896006972783843386309726917E-2799 2.109260948003486391921693154863458E-2799 + 4649 1.054630474001743195960846577431729E-2799 5.273152370008715979804232887158645E-2800 + 4650 2.636576185004357989902116443579323E-2800 1.318288092502178994951058221789661E-2800 + 4651 6.591440462510894974755291108948305E-2801 3.295720231255447487377645554474153E-2801 + 4652 1.647860115627723743688822777237077E-2801 8.239300578138618718444113886185383E-2802 + 4653 4.119650289069309359222056943092692E-2802 2.059825144534654679611028471546346E-2802 + 4654 1.029912572267327339805514235773173E-2802 5.149562861336636699027571178865865E-2803 + 4655 2.574781430668318349513785589432933E-2803 1.287390715334159174756892794716466E-2803 + 4656 6.43695357667079587378446397358233E-2804 3.218476788335397936892231986791165E-2804 + 4657 1.609238394167698968446115993395583E-2804 8.046191970838494842230579966977913E-2805 + 4658 4.023095985419247421115289983488957E-2805 2.011547992709623710557644991744478E-2805 + 4659 1.005773996354811855278822495872239E-2805 5.028869981774059276394112479361195E-2806 + 4660 2.514434990887029638197056239680598E-2806 1.257217495443514819098528119840299E-2806 + 4661 6.286087477217574095492640599201495E-2807 3.143043738608787047746320299600748E-2807 + 4662 1.571521869304393523873160149800374E-2807 7.85760934652196761936580074900187E-2808 + 4663 3.928804673260983809682900374500935E-2808 1.964402336630491904841450187250468E-2808 + 4664 9.82201168315245952420725093625234E-2809 4.91100584157622976210362546812617E-2809 + 4665 2.455502920788114881051812734063085E-2809 1.227751460394057440525906367031543E-2809 + 4666 6.138757301970287202629531835157715E-2810 3.069378650985143601314765917578858E-2810 + 4667 1.534689325492571800657382958789429E-2810 7.673446627462859003286914793947145E-2811 + 4668 3.836723313731429501643457396973573E-2811 1.918361656865714750821728698486786E-2811 + 4669 9.59180828432857375410864349243393E-2812 4.795904142164286877054321746216965E-2812 + 4670 2.397952071082143438527160873108483E-2812 1.198976035541071719263580436554241E-2812 + 4671 5.994880177705358596317902182771205E-2813 2.997440088852679298158951091385603E-2813 + 4672 1.498720044426339649079475545692802E-2813 7.493600222131698245397377728464008E-2814 + 4673 3.746800111065849122698688864232004E-2814 1.873400055532924561349344432116002E-2814 + 4674 9.36700027766462280674672216058001E-2815 4.683500138832311403373361080290005E-2815 + 4675 2.341750069416155701686680540145003E-2815 1.170875034708077850843340270072501E-2815 + 4676 5.854375173540389254216701350362505E-2816 2.927187586770194627108350675181253E-2816 + 4677 1.463593793385097313554175337590627E-2816 7.317968966925486567770876687953133E-2817 + 4678 3.658984483462743283885438343976567E-2817 1.829492241731371641942719171988283E-2817 + 4679 9.147461208656858209713595859941415E-2818 4.573730604328429104856797929970708E-2818 + 4680 2.286865302164214552428398964985354E-2818 1.143432651082107276214199482492677E-2818 + 4681 5.717163255410536381070997412463385E-2819 2.858581627705268190535498706231693E-2819 + 4682 1.429290813852634095267749353115847E-2819 7.146454069263170476338746765579233E-2820 + 4683 3.573227034631585238169373382789617E-2820 1.786613517315792619084686691394808E-2820 + 4684 8.93306758657896309542343345697404E-2821 4.46653379328948154771171672848702E-2821 + 4685 2.23326689664474077385585836424351E-2821 1.116633448322370386927929182121755E-2821 + 4686 5.583167241611851934639645910608775E-2822 2.791583620805925967319822955304388E-2822 + 4687 1.395791810402962983659911477652194E-2822 6.97895905201481491829955738826097E-2823 + 4688 3.489479526007407459149778694130485E-2823 1.744739763003703729574889347065243E-2823 + 4689 8.723698815018518647874446735326215E-2824 4.361849407509259323937223367663108E-2824 + 4690 2.180924703754629661968611683831554E-2824 1.090462351877314830984305841915777E-2824 + 4691 5.452311759386574154921529209578885E-2825 2.726155879693287077460764604789443E-2825 + 4692 1.363077939846643538730382302394722E-2825 6.815389699233217693651911511973608E-2826 + 4693 3.407694849616608846825955755986804E-2826 1.703847424808304423412977877993402E-2826 + 4694 8.51923712404152211706488938996701E-2827 4.259618562020761058532444694983505E-2827 + 4695 2.129809281010380529266222347491753E-2827 1.064904640505190264633111173745876E-2827 + 4696 5.32452320252595132316555586872938E-2828 2.66226160126297566158277793436469E-2828 + 4697 1.331130800631487830791388967182345E-2828 6.655654003157439153956944835911725E-2829 + 4698 3.327827001578719576978472417955863E-2829 1.663913500789359788489236208977931E-2829 + 4699 8.319567503946798942446181044889655E-2830 4.159783751973399471223090522444828E-2830 + 4700 2.079891875986699735611545261222414E-2830 1.039945937993349867805772630611207E-2830 + 4701 5.199729689966749339028863153056035E-2831 2.599864844983374669514431576528018E-2831 + 4702 1.299932422491687334757215788264009E-2831 6.499662112458436673786078941320045E-2832 + 4703 3.249831056229218336893039470660023E-2832 1.624915528114609168446519735330011E-2832 + 4704 8.124577640573045842232598676650055E-2833 4.062288820286522921116299338325028E-2833 + 4705 2.031144410143261460558149669162514E-2833 1.015572205071630730279074834581257E-2833 + 4706 5.077861025358153651395374172906285E-2834 2.538930512679076825697687086453143E-2834 + 4707 1.269465256339538412848843543226572E-2834 6.347326281697692064244217716132858E-2835 + 4708 3.173663140848846032122108858066429E-2835 1.586831570424423016061054429033215E-2835 + 4709 7.934157852122115080305272145166075E-2836 3.967078926061057540152636072583038E-2836 + 4710 1.983539463030528770076318036291519E-2836 9.917697315152643850381590181457595E-2837 + 4711 4.958848657576321925190795090728798E-2837 2.479424328788160962595397545364399E-2837 + 4712 1.239712164394080481297698772682200E-2837 6.198560821970402406488493863410998E-2838 + 4713 3.099280410985201203244246931705499E-2838 1.549640205492600601622123465852750E-2838 + 4714 7.74820102746300300811061732926375E-2839 3.874100513731501504055308664631875E-2839 + 4715 1.937050256865750752027654332315938E-2839 9.685251284328753760138271661579688E-2840 + 4716 4.842625642164376880069135830789844E-2840 2.421312821082188440034567915394922E-2840 + 4717 1.210656410541094220017283957697461E-2840 6.053282052705471100086419788487305E-2841 + 4718 3.026641026352735550043209894243653E-2841 1.513320513176367775021604947121826E-2841 + 4719 7.56660256588183887510802473560913E-2842 3.783301282940919437554012367804565E-2842 + 4720 1.891650641470459718777006183902283E-2842 9.458253207352298593885030919511413E-2843 + 4721 4.729126603676149296942515459755707E-2843 2.364563301838074648471257729877853E-2843 + 4722 1.182281650919037324235628864938927E-2843 5.911408254595186621178144324694633E-2844 + 4723 2.955704127297593310589072162347317E-2844 1.477852063648796655294536081173658E-2844 + 4724 7.38926031824398327647268040586829E-2845 3.694630159121991638236340202934145E-2845 + 4725 1.847315079560995819118170101467073E-2845 9.236575397804979095590850507335363E-2846 + 4726 4.618287698902489547795425253667682E-2846 2.309143849451244773897712626833841E-2846 + 4727 1.154571924725622386948856313416921E-2846 5.772859623628111934744281567084603E-2847 + 4728 2.886429811814055967372140783542302E-2847 1.443214905907027983686070391771151E-2847 + 4729 7.216074529535139918430351958855755E-2848 3.608037264767569959215175979427878E-2848 + 4730 1.804018632383784979607587989713939E-2848 9.020093161918924898037939948569695E-2849 + 4731 4.510046580959462449018969974284848E-2849 2.255023290479731224509484987142424E-2849 + 4732 1.127511645239865612254742493571212E-2849 5.63755822619932806127371246785606E-2850 + 4733 2.81877911309966403063685623392803E-2850 1.409389556549832015318428116964015E-2850 + 4734 7.046947782749160076592140584820075E-2851 3.523473891374580038296070292410038E-2851 + 4735 1.761736945687290019148035146205019E-2851 8.808684728436450095740175731025095E-2852 + 4736 4.404342364218225047870087865512548E-2852 2.202171182109112523935043932756274E-2852 + 4737 1.101085591054556261967521966378137E-2852 5.505427955272781309837609831890685E-2853 + 4738 2.752713977636390654918804915945343E-2853 1.376356988818195327459402457972671E-2853 + 4739 6.881784944090976637297012289863355E-2854 3.440892472045488318648506144931678E-2854 + 4740 1.720446236022744159324253072465839E-2854 8.602231180113720796621265362329195E-2855 + 4741 4.301115590056860398310632681164598E-2855 2.150557795028430199155316340582299E-2855 + 4742 1.075278897514215099577658170291150E-2855 5.376394487571075497888290851455748E-2856 + 4743 2.688197243785537748944145425727874E-2856 1.344098621892768874472072712863937E-2856 + 4744 6.720493109463844372360363564319685E-2857 3.360246554731922186180181782159843E-2857 + 4745 1.680123277365961093090090891079922E-2857 8.400616386829805465450454455399608E-2858 + 4746 4.200308193414902732725227227699804E-2858 2.100154096707451366362613613849902E-2858 + 4747 1.050077048353725683181306806924951E-2858 5.250385241768628415906534034624755E-2859 + 4748 2.625192620884314207953267017312378E-2859 1.312596310442157103976633508656189E-2859 + 4749 6.562981552210785519883167543280945E-2860 3.281490776105392759941583771640473E-2860 + 4750 1.640745388052696379970791885820237E-2860 8.203726940263481899853959429101183E-2861 + 4751 4.101863470131740949926979714550592E-2861 2.050931735065870474963489857275296E-2861 + 4752 1.025465867532935237481744928637648E-2861 5.12732933766467618740872464318824E-2862 + 4753 2.56366466883233809370436232159412E-2862 1.28183233441616904685218116079706E-2862 + 4754 6.4091616720808452342609058039853E-2863 3.20458083604042261713045290199265E-2863 + 4755 1.602290418020211308565226450996325E-2863 8.011452090101056542826132254981625E-2864 + 4756 4.005726045050528271413066127490813E-2864 2.002863022525264135706533063745406E-2864 + 4757 1.001431511262632067853266531872703E-2864 5.007157556313160339266332659363515E-2865 + 4758 2.503578778156580169633166329681758E-2865 1.251789389078290084816583164840879E-2865 + 4759 6.258946945391450424082915824204395E-2866 3.129473472695725212041457912102198E-2866 + 4760 1.564736736347862606020728956051099E-2866 7.823683681739313030103644780255495E-2867 + 4761 3.911841840869656515051822390127748E-2867 1.955920920434828257525911195063874E-2867 + 4762 9.77960460217414128762955597531937E-2868 4.889802301087070643814777987659685E-2868 + 4763 2.444901150543535321907388993829843E-2868 1.222450575271767660953694496914921E-2868 + 4764 6.112252876358838304768472484574605E-2869 3.056126438179419152384236242287303E-2869 + 4765 1.528063219089709576192118121143652E-2869 7.640316095448547880960590605718258E-2870 + 4766 3.820158047724273940480295302859129E-2870 1.910079023862136970240147651429565E-2870 + 4767 9.550395119310684851200738257147825E-2871 4.775197559655342425600369128573913E-2871 + 4768 2.387598779827671212800184564286957E-2871 1.193799389913835606400092282143478E-2871 + 4769 5.96899694956917803200046141071739E-2872 2.984498474784589016000230705358695E-2872 + 4770 1.492249237392294508000115352679348E-2872 7.461246186961472540000576763396738E-2873 + 4771 3.730623093480736270000288381698369E-2873 1.865311546740368135000144190849185E-2873 + 4772 9.326557733701840675000720954245925E-2874 4.663278866850920337500360477122963E-2874 + 4773 2.331639433425460168750180238561482E-2874 1.165819716712730084375090119280741E-2874 + 4774 5.829098583563650421875450596403705E-2875 2.914549291781825210937725298201853E-2875 + 4775 1.457274645890912605468862649100927E-2875 7.286373229454563027344313245504633E-2876 + 4776 3.643186614727281513672156622752317E-2876 1.821593307363640756836078311376158E-2876 + 4777 9.10796653681820378418039155688079E-2877 4.553983268409101892090195778440395E-2877 + 4778 2.276991634204550946045097889220198E-2877 1.138495817102275473022548944610099E-2877 + 4779 5.692479085511377365112744723050495E-2878 2.846239542755688682556372361525248E-2878 + 4780 1.423119771377844341278186180762624E-2878 7.11559885688922170639093090381312E-2879 + 4781 3.55779942844461085319546545190656E-2879 1.77889971422230542659773272595328E-2879 + 4782 8.8944985711115271329886636297664E-2880 4.4472492855557635664943318148832E-2880 + 4783 2.2236246427778817832471659074416E-2880 1.1118123213889408916235829537208E-2880 + 4784 5.559061606944704458117914768604E-2881 2.779530803472352229058957384302E-2881 + 4785 1.389765401736176114529478692151E-2881 6.948827008680880572647393460755E-2882 + 4786 3.4744135043404402863236967303775E-2882 1.73720675217022014316184836518875E-2882 + 4787 8.68603376085110071580924182594375E-2883 4.343016880425550357904620912971875E-2883 + 4788 2.171508440212775178952310456485938E-2883 1.085754220106387589476155228242969E-2883 + 4789 5.428771100531937947380776141214845E-2884 2.714385550265968973690388070607423E-2884 + 4790 1.357192775132984486845194035303712E-2884 6.785963875664922434225970176518558E-2885 + 4791 3.392981937832461217112985088259279E-2885 1.696490968916230608556492544129640E-2885 + 4792 8.48245484458115304278246272064820E-2886 4.24122742229057652139123136032410E-2886 + 4793 2.12061371114528826069561568016205E-2886 1.060306855572644130347807840081025E-2886 + 4794 5.301534277863220651739039200405125E-2887 2.650767138931610325869519600202563E-2887 + 4795 1.325383569465805162934759800101282E-2887 6.626917847329025814673799000506408E-2888 + 4796 3.313458923664512907336899500253204E-2888 1.656729461832256453668449750126602E-2888 + 4797 8.28364730916128226834224875063301E-2889 4.141823654580641134171124375316505E-2889 + 4798 2.070911827290320567085562187658253E-2889 1.035455913645160283542781093829126E-2889 + 4799 5.17727956822580141771390546914563E-2890 2.588639784112900708856952734572815E-2890 + 4800 1.294319892056450354428476367286408E-2890 6.471599460282251772142381836432038E-2891 + 4801 3.235799730141125886071190918216019E-2891 1.617899865070562943035595459108010E-2891 + 4802 8.08949932535281471517797729554005E-2892 4.044749662676407357588988647770025E-2892 + 4803 2.022374831338203678794494323885013E-2892 1.011187415669101839397247161942506E-2892 + 4804 5.05593707834550919698623580971253E-2893 2.527968539172754598493117904856265E-2893 + 4805 1.263984269586377299246558952428133E-2893 6.319921347931886496232794762140663E-2894 + 4806 3.159960673965943248116397381070332E-2894 1.579980336982971624058198690535166E-2894 + 4807 7.89990168491485812029099345267583E-2895 3.949950842457429060145496726337915E-2895 + 4808 1.974975421228714530072748363168958E-2895 9.874877106143572650363741815844788E-2896 + 4809 4.937438553071786325181870907922394E-2896 2.468719276535893162590935453961197E-2896 + 4810 1.234359638267946581295467726980599E-2896 6.171798191339732906477338634902993E-2897 + 4811 3.085899095669866453238669317451497E-2897 1.542949547834933226619334658725748E-2897 + 4812 7.71474773917466613309667329362874E-2898 3.85737386958733306654833664681437E-2898 + 4813 1.928686934793666533274168323407185E-2898 9.643434673968332666370841617035925E-2899 + 4814 4.821717336984166333185420808517963E-2899 2.410858668492083166592710404258981E-2899 + 4815 1.205429334246041583296355202129491E-2899 6.027146671230207916481776010647453E-2900 + 4816 3.013573335615103958240888005323727E-2900 1.506786667807551979120444002661863E-2900 + 4817 7.533933339037759895602220013309315E-2901 3.766966669518879947801110006654658E-2901 + 4818 1.883483334759439973900555003327329E-2901 9.417416673797199869502775016636645E-2902 + 4819 4.708708336898599934751387508318323E-2902 2.354354168449299967375693754159161E-2902 + 4820 1.177177084224649983687846877079581E-2902 5.885885421123249918439234385397903E-2903 + 4821 2.942942710561624959219617192698952E-2903 1.471471355280812479609808596349476E-2903 + 4822 7.35735677640406239804904298174738E-2904 3.67867838820203119902452149087369E-2904 + 4823 1.839339194101015599512260745436845E-2904 9.196695970505077997561303727184225E-2905 + 4824 4.598347985252538998780651863592113E-2905 2.299173992626269499390325931796056E-2905 + 4825 1.149586996313134749695162965898028E-2905 5.74793498156567374847581482949014E-2906 + 4826 2.87396749078283687423790741474507E-2906 1.436983745391418437118953707372535E-2906 + 4827 7.184918726957092185594768536862675E-2907 3.592459363478546092797384268431338E-2907 + 4828 1.796229681739273046398692134215669E-2907 8.981148408696365231993460671078345E-2908 + 4829 4.490574204348182615996730335539173E-2908 2.245287102174091307998365167769586E-2908 + 4830 1.122643551087045653999182583884793E-2908 5.613217755435228269995912919423965E-2909 + 4831 2.806608877717614134997956459711983E-2909 1.403304438858807067498978229855991E-2909 + 4832 7.016522194294035337494891149279955E-2910 3.508261097147017668747445574639978E-2910 + 4833 1.754130548573508834373722787319989E-2910 8.770652742867544171868613936599945E-2911 + 4834 4.385326371433772085934306968299973E-2911 2.192663185716886042967153484149986E-2911 + 4835 1.096331592858443021483576742074993E-2911 5.481657964292215107417883710374965E-2912 + 4836 2.740828982146107553708941855187483E-2912 1.370414491073053776854470927593741E-2912 + 4837 6.852072455365268884272354637968705E-2913 3.426036227682634442136177318984353E-2913 + 4838 1.713018113841317221068088659492177E-2913 8.565090569206586105340443297460883E-2914 + 4839 4.282545284603293052670221648730442E-2914 2.141272642301646526335110824365221E-2914 + 4840 1.070636321150823263167555412182611E-2914 5.353181605754116315837777060913053E-2915 + 4841 2.676590802877058157918888530456527E-2915 1.338295401438529078959444265228263E-2915 + 4842 6.691477007192645394797221326141315E-2916 3.345738503596322697398610663070658E-2916 + 4843 1.672869251798161348699305331535329E-2916 8.364346258990806743496526657676645E-2917 + 4844 4.182173129495403371748263328838323E-2917 2.091086564747701685874131664419161E-2917 + 4845 1.045543282373850842937065832209581E-2917 5.227716411869254214685329161047903E-2918 + 4846 2.613858205934627107342664580523952E-2918 1.306929102967313553671332290261976E-2918 + 4847 6.53464551483656776835666145130988E-2919 3.26732275741828388417833072565494E-2919 + 4848 1.63366137870914194208916536282747E-2919 8.16830689354570971044582681413735E-2920 + 4849 4.084153446772854855222913407068675E-2920 2.042076723386427427611456703534338E-2920 + 4850 1.021038361693213713805728351767169E-2920 5.105191808466068569028641758835845E-2921 + 4851 2.552595904233034284514320879417923E-2921 1.276297952116517142257160439708961E-2921 + 4852 6.381489760582585711285802198544805E-2922 3.190744880291292855642901099272403E-2922 + 4853 1.595372440145646427821450549636202E-2922 7.976862200728232139107252748181008E-2923 + 4854 3.988431100364116069553626374090504E-2923 1.994215550182058034776813187045252E-2923 + 4855 9.97107775091029017388406593522626E-2924 4.98553887545514508694203296761313E-2924 + 4856 2.492769437727572543471016483806565E-2924 1.246384718863786271735508241903283E-2924 + 4857 6.231923594318931358677541209516415E-2925 3.115961797159465679338770604758208E-2925 + 4858 1.557980898579732839669385302379104E-2925 7.78990449289866419834692651189552E-2926 + 4859 3.89495224644933209917346325594776E-2926 1.94747612322466604958673162797388E-2926 + 4860 9.7373806161233302479336581398694E-2927 4.8686903080616651239668290699347E-2927 + 4861 2.43434515403083256198341453496735E-2927 1.217172577015416280991707267483675E-2927 + 4862 6.085862885077081404958536337418375E-2928 3.042931442538540702479268168709188E-2928 + 4863 1.521465721269270351239634084354594E-2928 7.60732860634635175619817042177297E-2929 + 4864 3.803664303173175878099085210886485E-2929 1.901832151586587939049542605443243E-2929 + 4865 9.509160757932939695247713027216215E-2930 4.754580378966469847623856513608108E-2930 + 4866 2.377290189483234923811928256804054E-2930 1.188645094741617461905964128402027E-2930 + 4867 5.943225473708087309529820642010135E-2931 2.971612736854043654764910321005068E-2931 + 4868 1.485806368427021827382455160502534E-2931 7.42903184213510913691227580251267E-2932 + 4869 3.714515921067554568456137901256335E-2932 1.857257960533777284228068950628168E-2932 + 4870 9.28628980266888642114034475314084E-2933 4.64314490133444321057017237657042E-2933 + 4871 2.32157245066722160528508618828521E-2933 1.160786225333610802642543094142605E-2933 + 4872 5.803931126668054013212715470713025E-2934 2.901965563334027006606357735356513E-2934 + 4873 1.450982781667013503303178867678257E-2934 7.254913908335067516515894338391283E-2935 + 4874 3.627456954167533758257947169195642E-2935 1.813728477083766879128973584597821E-2935 + 4875 9.068642385418834395644867922989105E-2936 4.534321192709417197822433961494553E-2936 + 4876 2.267160596354708598911216980747277E-2936 1.133580298177354299455608490373638E-2936 + 4877 5.66790149088677149727804245186819E-2937 2.833950745443385748639021225934095E-2937 + 4878 1.416975372721692874319510612967048E-2937 7.084876863608464371597553064835238E-2938 + 4879 3.542438431804232185798776532417619E-2938 1.771219215902116092899388266208810E-2938 + 4880 8.85609607951058046449694133104405E-2939 4.428048039755290232248470665522025E-2939 + 4881 2.214024019877645116124235332761013E-2939 1.107012009938822558062117666380506E-2939 + 4882 5.53506004969411279031058833190253E-2940 2.767530024847056395155294165951265E-2940 + 4883 1.383765012423528197577647082975633E-2940 6.918825062117640987888235414878163E-2941 + 4884 3.459412531058820493944117707439082E-2941 1.729706265529410246972058853719541E-2941 + 4885 8.648531327647051234860294268597705E-2942 4.324265663823525617430147134298853E-2942 + 4886 2.162132831911762808715073567149427E-2942 1.081066415955881404357536783574713E-2942 + 4887 5.405332079779407021787683917873565E-2943 2.702666039889703510893841958936783E-2943 + 4888 1.351333019944851755446920979468392E-2943 6.756665099724258777234604897341958E-2944 + 4889 3.378332549862129388617302448670979E-2944 1.689166274931064694308651224335490E-2944 + 4890 8.44583137465532347154325612167745E-2945 4.222915687327661735771628060838725E-2945 + 4891 2.111457843663830867885814030419363E-2945 1.055728921831915433942907015209681E-2945 + 4892 5.278644609159577169714535076048405E-2946 2.639322304579788584857267538024203E-2946 + 4893 1.319661152289894292428633769012102E-2946 6.598305761449471462143168845060508E-2947 + 4894 3.299152880724735731071584422530254E-2947 1.649576440362367865535792211265127E-2947 + 4895 8.247882201811839327678961056325635E-2948 4.123941100905919663839480528162818E-2948 + 4896 2.061970550452959831919740264081409E-2948 1.030985275226479915959870132040705E-2948 + 4897 5.154926376132399579799350660203525E-2949 2.577463188066199789899675330101763E-2949 + 4898 1.288731594033099894949837665050882E-2949 6.443657970165499474749188325254408E-2950 + 4899 3.221828985082749737374594162627204E-2950 1.610914492541374868687297081313602E-2950 + 4900 8.05457246270687434343648540656801E-2951 4.027286231353437171718242703284005E-2951 + 4901 2.013643115676718585859121351642003E-2951 1.006821557838359292929560675821001E-2951 + 4902 5.034107789191796464647803379105005E-2952 2.517053894595898232323901689552503E-2952 + 4903 1.258526947297949116161950844776252E-2952 6.292634736489745580809754223881258E-2953 + 4904 3.146317368244872790404877111940629E-2953 1.573158684122436395202438555970315E-2953 + 4905 7.865793420612181976012192779851575E-2954 3.932896710306090988006096389925788E-2954 + 4906 1.966448355153045494003048194962894E-2954 9.83224177576522747001524097481447E-2955 + 4907 4.916120887882613735007620487407235E-2955 2.458060443941306867503810243703618E-2955 + 4908 1.229030221970653433751905121851809E-2955 6.145151109853267168759525609259045E-2956 + 4909 3.072575554926633584379762804629523E-2956 1.536287777463316792189881402314761E-2956 + 4910 7.681438887316583960949407011573805E-2957 3.840719443658291980474703505786903E-2957 + 4911 1.920359721829145990237351752893452E-2957 9.601798609145729951186758764467258E-2958 + 4912 4.800899304572864975593379382233629E-2958 2.400449652286432487796689691116815E-2958 + 4913 1.200224826143216243898344845558408E-2958 6.001124130716081219491724227792038E-2959 + 4914 3.000562065358040609745862113896019E-2959 1.500281032679020304872931056948010E-2959 + 4915 7.50140516339510152436465528474005E-2960 3.750702581697550762182327642370025E-2960 + 4916 1.875351290848775381091163821185013E-2960 9.376756454243876905455819105925063E-2961 + 4917 4.688378227121938452727909552962532E-2961 2.344189113560969226363954776481266E-2961 + 4918 1.172094556780484613181977388240633E-2961 5.860472783902423065909886941203165E-2962 + 4919 2.930236391951211532954943470601583E-2962 1.465118195975605766477471735300791E-2962 + 4920 7.325590979878028832387358676503955E-2963 3.662795489939014416193679338251978E-2963 + 4921 1.831397744969507208096839669125989E-2963 9.156988724847536040484198345629945E-2964 + 4922 4.578494362423768020242099172814973E-2964 2.289247181211884010121049586407486E-2964 + 4923 1.144623590605942005060524793203743E-2964 5.723117953029710025302623966018715E-2965 + 4924 2.861558976514855012651311983009358E-2965 1.430779488257427506325655991504679E-2965 + 4925 7.153897441287137531628279957523395E-2966 3.576948720643568765814139978761698E-2966 + 4926 1.788474360321784382907069989380849E-2966 8.942371801608921914535349946904245E-2967 + 4927 4.471185900804460957267674973452123E-2967 2.235592950402230478633837486726061E-2967 + 4928 1.117796475201115239316918743363031E-2967 5.588982376005576196584593716815153E-2968 + 4929 2.794491188002788098292296858407577E-2968 1.397245594001394049146148429203788E-2968 + 4930 6.98622797000697024573074214601894E-2969 3.49311398500348512286537107300947E-2969 + 4931 1.746556992501742561432685536504735E-2969 8.732784962508712807163427682523675E-2970 + 4932 4.366392481254356403581713841261838E-2970 2.183196240627178201790856920630919E-2970 + 4933 1.091598120313589100895428460315460E-2970 5.457990601567945504477142301577298E-2971 + 4934 2.728995300783972752238571150788649E-2971 1.364497650391986376119285575394325E-2971 + 4935 6.822488251959931880596427876971625E-2972 3.411244125979965940298213938485813E-2972 + 4936 1.705622062989982970149106969242907E-2972 8.528110314949914850745534846214533E-2973 + 4937 4.264055157474957425372767423107267E-2973 2.132027578737478712686383711553633E-2973 + 4938 1.066013789368739356343191855776817E-2973 5.330068946843696781715959278884083E-2974 + 4939 2.665034473421848390857979639442042E-2974 1.332517236710924195428989819721021E-2974 + 4940 6.662586183554620977144949098605105E-2975 3.331293091777310488572474549302553E-2975 + 4941 1.665646545888655244286237274651277E-2975 8.328232729443276221431186373256383E-2976 + 4942 4.164116364721638110715593186628192E-2976 2.082058182360819055357796593314096E-2976 + 4943 1.041029091180409527678898296657048E-2976 5.20514545590204763839449148328524E-2977 + 4944 2.60257272795102381919724574164262E-2977 1.30128636397551190959862287082131E-2977 + 4945 6.50643181987755954799311435410655E-2978 3.253215909938779773996557177053275E-2978 + 4946 1.626607954969389886998278588526638E-2978 8.133039774846949434991392942633188E-2979 + 4947 4.066519887423474717495696471316594E-2979 2.033259943711737358747848235658297E-2979 + 4948 1.016629971855868679373924117829149E-2979 5.083149859279343396869620589145743E-2980 + 4949 2.541574929639671698434810294572872E-2980 1.270787464819835849217405147286436E-2980 + 4950 6.35393732409917924608702573643218E-2981 3.17696866204958962304351286821609E-2981 + 4951 1.588484331024794811521756434108045E-2981 7.942421655123974057608782170540225E-2982 + 4952 3.971210827561987028804391085270113E-2982 1.985605413780993514402195542635056E-2982 + 4953 9.92802706890496757201097771317528E-2983 4.96401353445248378600548885658764E-2983 + 4954 2.48200676722624189300274442829382E-2983 1.24100338361312094650137221414691E-2983 + 4955 6.20501691806560473250686107073455E-2984 3.102508459032802366253430535367275E-2984 + 4956 1.551254229516401183126715267683638E-2984 7.756271147582005915633576338418188E-2985 + 4957 3.878135573791002957816788169209094E-2985 1.939067786895501478908394084604547E-2985 + 4958 9.695338934477507394541970423022735E-2986 4.847669467238753697270985211511368E-2986 + 4959 2.423834733619376848635492605755684E-2986 1.211917366809688424317746302877842E-2986 + 4960 6.05958683404844212158873151438921E-2987 3.029793417024221060794365757194605E-2987 + 4961 1.514896708512110530397182878597303E-2987 7.574483542560552651985914392986513E-2988 + 4962 3.787241771280276325992957196493257E-2988 1.893620885640138162996478598246628E-2988 + 4963 9.46810442820069081498239299123314E-2989 4.73405221410034540749119649561657E-2989 + 4964 2.367026107050172703745598247808285E-2989 1.183513053525086351872799123904143E-2989 + 4965 5.917565267625431759363995619520715E-2990 2.958782633812715879681997809760358E-2990 + 4966 1.479391316906357939840998904880179E-2990 7.396956584531789699204994524400895E-2991 + 4967 3.698478292265894849602497262200448E-2991 1.849239146132947424801248631100224E-2991 + 4968 9.24619573066473712400624315550112E-2992 4.62309786533236856200312157775056E-2992 + 4969 2.31154893266618428100156078887528E-2992 1.15577446633309214050078039443764E-2992 + 4970 5.7788723316654607025039019721882E-2993 2.8894361658327303512519509860941E-2993 + 4971 1.44471808291636517562597549304705E-2993 7.22359041458182587812987746523525E-2994 + 4972 3.611795207290912939064938732617625E-2994 1.805897603645456469532469366308813E-2994 + 4973 9.029488018227282347662346831544065E-2995 4.514744009113641173831173415772033E-2995 + 4974 2.257372004556820586915586707886017E-2995 1.128686002278410293457793353943008E-2995 + 4975 5.64343001139205146728896676971504E-2996 2.82171500569602573364448338485752E-2996 + 4976 1.41085750284801286682224169242876E-2996 7.0542875142400643341112084621438E-2997 + 4977 3.5271437571200321670556042310719E-2997 1.76357187856001608352780211553595E-2997 + 4978 8.81785939280008041763901057767975E-2998 4.408929696400040208819505288839875E-2998 + 4979 2.204464848200020104409752644419938E-2998 1.102232424100010052204876322209969E-2998 + 4980 5.511162120500050261024381611049845E-2999 2.755581060250025130512190805524923E-2999 + 4981 1.377790530125012565256095402762462E-2999 6.888952650625062826280477013812308E-3000 + 4982 3.444476325312531413140238506906154E-3000 1.722238162656265706570119253453077E-3000 + 4983 8.611190813281328532850596267265385E-3001 4.305595406640664266425298133632693E-3001 + 4984 2.152797703320332133212649066816347E-3001 1.076398851660166066606324533408173E-3001 + 4985 5.381994258300830333031622667040865E-3002 2.690997129150415166515811333520433E-3002 + 4986 1.345498564575207583257905666760217E-3002 6.727492822876037916289528333801083E-3003 + 4987 3.363746411438018958144764166900542E-3003 1.681873205719009479072382083450271E-3003 + 4988 8.409366028595047395361910417251355E-3004 4.204683014297523697680955208625678E-3004 + 4989 2.102341507148761848840477604312839E-3004 1.051170753574380924420238802156420E-3004 + 4990 5.25585376787190462210119401078210E-3005 2.62792688393595231105059700539105E-3005 + 4991 1.313963441967976155525298502695525E-3005 6.569817209839880777626492513477625E-3006 + 4992 3.284908604919940388813246256738813E-3006 1.642454302459970194406623128369406E-3006 + 4993 8.21227151229985097203311564184703E-3007 4.106135756149925486016557820923515E-3007 + 4994 2.053067878074962743008278910461758E-3007 1.026533939037481371504139455230879E-3007 + 4995 5.132669695187406857520697276154395E-3008 2.566334847593703428760348638077198E-3008 + 4996 1.283167423796851714380174319038599E-3008 6.415837118984258571900871595192995E-3009 + 4997 3.207918559492129285950435797596498E-3009 1.603959279746064642975217898798249E-3009 + 4998 8.019796398730323214876089493991245E-3010 4.009898199365161607438044746995623E-3010 + 4999 2.004949099682580803719022373497812E-3010 1.002474549841290401859511186748906E-3010 + 5000 5.01237274920645200929755593374453E-3011 2.506186374603226004648777966872265E-3011 + 5001 1.253093187301613002324388983436133E-3011 6.265465936508065011621944917180663E-3012 + 5002 3.132732968254032505810972458590332E-3012 1.566366484127016252905486229295166E-3012 + 5003 7.83183242063508126452743114647583E-3013 3.915916210317540632263715573237915E-3013 + 5004 1.957958105158770316131857786618958E-3013 9.789790525793851580659288933094788E-3014 + 5005 4.894895262896925790329644466547394E-3014 2.447447631448462895164822233273697E-3014 + 5006 1.223723815724231447582411116636849E-3014 6.118619078621157237912055583184243E-3015 + 5007 3.059309539310578618956027791592122E-3015 1.529654769655289309478013895796061E-3015 + 5008 7.648273848276446547390069478980305E-3016 3.824136924138223273695034739490153E-3016 + 5009 1.912068462069111636847517369745077E-3016 9.560342310345558184237586848725383E-3017 + 5010 4.780171155172779092118793424362692E-3017 2.390085577586389546059396712181346E-3017 + 5011 1.195042788793194773029698356090673E-3017 5.975213943965973865148491780453365E-3018 + 5012 2.987606971982986932574245890226683E-3018 1.493803485991493466287122945113341E-3018 + 5013 7.469017429957467331435614725566705E-3019 3.734508714978733665717807362783353E-3019 + 5014 1.867254357489366832858903681391677E-3019 9.336271787446834164294518406958383E-3020 + 5015 4.668135893723417082147259203479192E-3020 2.334067946861708541073629601739596E-3020 + 5016 1.167033973430854270536814800869798E-3020 5.83516986715427135268407400434899E-3021 + 5017 2.917584933577135676342037002174495E-3021 1.458792466788567838171018501087248E-3021 + 5018 7.29396233394283919085509250543624E-3022 3.64698116697141959542754625271812E-3022 + 5019 1.82349058348570979771377312635906E-3022 9.1174529174285489885688656317953E-3023 + 5020 4.55872645871427449428443281589765E-3023 2.279363229357137247142216407948825E-3023 + 5021 1.139681614678568623571108203974413E-3023 5.698408073392843117855541019872063E-3024 + 5022 2.849204036696421558927770509936032E-3024 1.424602018348210779463885254968016E-3024 + 5023 7.12301009174105389731942627484008E-3025 3.56150504587052694865971313742004E-3025 + 5024 1.78075252293526347432985656871002E-3025 8.9037626146763173716492828435501E-3026 + 5025 4.45188130733815868582464142177505E-3026 2.225940653669079342912320710887525E-3026 + 5026 1.112970326834539671456160355443763E-3026 5.564851634172698357280801777218813E-3027 + 5027 2.782425817086349178640400888609407E-3027 1.391212908543174589320200444304703E-3027 + 5028 6.956064542715872946601002221523515E-3028 3.478032271357936473300501110761758E-3028 + 5029 1.739016135678968236650250555380879E-3028 8.695080678394841183251252776904395E-3029 + 5030 4.347540339197420591625626388452198E-3029 2.173770169598710295812813194226099E-3029 + 5031 1.086885084799355147906406597113050E-3029 5.434425423996775739532032985565248E-3030 + 5032 2.717212711998387869766016492782624E-3030 1.358606355999193934883008246391312E-3030 + 5033 6.79303177999596967441504123195656E-3031 3.39651588999798483720752061597828E-3031 + 5034 1.69825794499899241860376030798914E-3031 8.4912897249949620930188015399457E-3032 + 5035 4.24564486249748104650940076997285E-3032 2.122822431248740523254700384986425E-3032 + 5036 1.061411215624370261627350192493213E-3032 5.307056078121851308136750962466063E-3033 + 5037 2.653528039060925654068375481233032E-3033 1.326764019530462827034187740616516E-3033 + 5038 6.63382009765231413517093870308258E-3034 3.31691004882615706758546935154129E-3034 + 5039 1.658455024413078533792734675770645E-3034 8.292275122065392668963673378853225E-3035 + 5040 4.146137561032696334481836689426613E-3035 2.073068780516348167240918344713306E-3035 + 5041 1.036534390258174083620459172356653E-3035 5.182671951290870418102295861783265E-3036 + 5042 2.591335975645435209051147930891633E-3036 1.295667987822717604525573965445816E-3036 + 5043 6.47833993911358802262786982722908E-3037 3.23916996955679401131393491361454E-3037 + 5044 1.61958498477839700565696745680727E-3037 8.09792492389198502828483728403635E-3038 + 5045 4.048962461945992514142418642018175E-3038 2.024481230972996257071209321009088E-3038 + 5046 1.012240615486498128535604660504544E-3038 5.06120307743249064267802330252272E-3039 + 5047 2.53060153871624532133901165126136E-3039 1.26530076935812266066950582563068E-3039 + 5048 6.3265038467906133033475291281534E-3040 3.1632519233953066516737645640767E-3040 + 5049 1.58162596169765332583688228203835E-3040 7.90812980848826662918441141019175E-3041 + 5050 3.954064904244133314592205705095875E-3041 1.977032452122066657296102852547938E-3041 + 5051 9.88516226061033328648051426273969E-3042 4.942581130305166643240257131369845E-3042 + 5052 2.471290565152583321620128565684923E-3042 1.235645282576291660810064282842461E-3042 + 5053 6.178226412881458304050321414212305E-3043 3.089113206440729152025160707106153E-3043 + 5054 1.544556603220364576012580353553077E-3043 7.722783016101822880062901767765383E-3044 + 5055 3.861391508050911440031450883882692E-3044 1.930695754025455720015725441941346E-3044 + 5056 9.65347877012727860007862720970673E-3045 4.826739385063639300039313604853365E-3045 + 5057 2.413369692531819650019656802426683E-3045 1.206684846265909825009828401213341E-3045 + 5058 6.033424231329549125049142006066705E-3046 3.016712115664774562524571003033353E-3046 + 5059 1.508356057832387281262285501516677E-3046 7.541780289161936406311427507583383E-3047 + 5060 3.770890144580968203155713753791692E-3047 1.885445072290484101577856876895846E-3047 + 5061 9.42722536145242050788928438447923E-3048 4.713612680726210253944642192239615E-3048 + 5062 2.356806340363105126972321096119808E-3048 1.178403170181552563486160548059904E-3048 + 5063 5.89201585090776281743080274029952E-3049 2.94600792545388140871540137014976E-3049 + 5064 1.47300396272694070435770068507488E-3049 7.3650198136347035217885034253744E-3050 + 5065 3.6825099068173517608942517126872E-3050 1.8412549534086758804471258563436E-3050 + 5066 9.206274767043379402235629281718E-3051 4.603137383521689701117814640859E-3051 + 5067 2.3015686917608448505589073204295E-3051 1.15078434588042242527945366021475E-3051 + 5068 5.75392172940211212639726830107375E-3052 2.876960864701056063198634150536875E-3052 + 5069 1.438480432350528031599317075268438E-3052 7.192402161752640157996585376342188E-3053 + 5070 3.596201080876320078998292688171094E-3053 1.798100540438160039499146344085547E-3053 + 5071 8.990502702190800197495731720427735E-3054 4.495251351095400098747865860213868E-3054 + 5072 2.247625675547700049373932930106934E-3054 1.123812837773850024686966465053467E-3054 + 5073 5.619064188869250123434832325267335E-3055 2.809532094434625061717416162633668E-3055 + 5074 1.404766047217312530858708081316834E-3055 7.02383023608656265429354040658417E-3056 + 5075 3.511915118043281327146770203292085E-3056 1.755957559021640663573385101646043E-3056 + 5076 8.779787795108203317866925508230215E-3057 4.389893897554101658933462754115108E-3057 + 5077 2.194946948777050829466731377057554E-3057 1.097473474388525414733365688528777E-3057 + 5078 5.487367371942627073666828442643885E-3058 2.743683685971313536833414221321943E-3058 + 5079 1.371841842985656768416707110660972E-3058 6.859209214928283842083535553304858E-3059 + 5080 3.429604607464141921041767776652429E-3059 1.714802303732070960520883888326215E-3059 + 5081 8.574011518660354802604419441631075E-3060 4.287005759330177401302209720815538E-3060 + 5082 2.143502879665088700651104860407769E-3060 1.071751439832544350325552430203885E-3060 + 5083 5.358757199162721751627762151019425E-3061 2.679378599581360875813881075509713E-3061 + 5084 1.339689299790680437906940537754857E-3061 6.698446498953402189534702688774283E-3062 + 5085 3.349223249476701094767351344387142E-3062 1.674611624738350547383675672193571E-3062 + 5086 8.373058123691752736918378360967855E-3063 4.186529061845876368459189180483928E-3063 + 5087 2.093264530922938184229594590241964E-3063 1.046632265461469092114797295120982E-3063 + 5088 5.23316132730734546057398647560491E-3064 2.616580663653672730286993237802455E-3064 + 5089 1.308290331826836365143496618901228E-3064 6.541451659134181825717483094506138E-3065 + 5090 3.270725829567090912858741547253069E-3065 1.635362914783545456429370773626535E-3065 + 5091 8.176814573917727282146853868132675E-3066 4.088407286958863641073426934066338E-3066 + 5092 2.044203643479431820536713467033169E-3066 1.022101821739715910268356733516585E-3066 + 5093 5.110509108698579551341783667582925E-3067 2.555254554349289775670891833791463E-3067 + 5094 1.277627277174644887835445916895732E-3067 6.388136385873224439177229584478658E-3068 + 5095 3.194068192936612219588614792239329E-3068 1.597034096468306109794307396119665E-3068 + 5096 7.985170482341530548971536980598325E-3069 3.992585241170765274485768490299163E-3069 + 5097 1.996292620585382637242884245149582E-3069 9.981463102926913186214421225747908E-3070 + 5098 4.990731551463456593107210612873954E-3070 2.495365775731728296553605306436977E-3070 + 5099 1.247682887865864148276802653218489E-3070 6.238414439329320741384013266092443E-3071 + 5100 3.119207219664660370692006633046222E-3071 1.559603609832330185346003316523111E-3071 + 5101 7.798018049161650926730016582615555E-3072 3.899009024580825463365008291307778E-3072 + 5102 1.949504512290412731682504145653889E-3072 9.747522561452063658412520728269445E-3073 + 5103 4.873761280726031829206260364134723E-3073 2.436880640363015914603130182067361E-3073 + 5104 1.218440320181507957301565091033681E-3073 6.092201600907539786507825455168403E-3074 + 5105 3.046100800453769893253912727584202E-3074 1.523050400226884946626956363792101E-3074 + 5106 7.615252001134424733134781818960505E-3075 3.807626000567212366567390909480253E-3075 + 5107 1.903813000283606183283695454740127E-3075 9.519065001418030916418477273700633E-3076 + 5108 4.759532500709015458209238636850317E-3076 2.379766250354507729104619318425158E-3076 + 5109 1.189883125177253864552309659212579E-3076 5.949415625886269322761548296062895E-3077 + 5110 2.974707812943134661380774148031448E-3077 1.487353906471567330690387074015724E-3077 + 5111 7.43676953235783665345193537007862E-3078 3.71838476617891832672596768503931E-3078 + 5112 1.859192383089459163362983842519655E-3078 9.295961915447295816814919212598275E-3079 + 5113 4.647980957723647908407459606299138E-3079 2.323990478861823954203729803149569E-3079 + 5114 1.161995239430911977101864901574785E-3079 5.809976197154559885509324507873923E-3080 + 5115 2.904988098577279942754662253936962E-3080 1.452494049288639971377331126968481E-3080 + 5116 7.262470246443199856886655634842405E-3081 3.631235123221599928443327817421203E-3081 + 5117 1.815617561610799964221663908710602E-3081 9.078087808053999821108319543553008E-3082 + 5118 4.539043904026999910554159771776504E-3082 2.269521952013499955277079885888252E-3082 + 5119 1.134760976006749977638539942944126E-3082 5.67380488003374988819269971472063E-3083 + 5120 2.836902440016874944096349857360315E-3083 1.418451220008437472048174928680158E-3083 + 5121 7.09225610004218736024087464340079E-3084 3.546128050021093680120437321700395E-3084 + 5122 1.773064025010546840060218660850198E-3084 8.865320125052734200301093304250988E-3085 + 5123 4.432660062526367100150546652125494E-3085 2.216330031263183550075273326062747E-3085 + 5124 1.108165015631591775037636663031374E-3085 5.540825078157958875188183315156868E-3086 + 5125 2.770412539078979437594091657578434E-3086 1.385206269539489718797045828789217E-3086 + 5126 6.926031347697448593985229143946085E-3087 3.463015673848724296992614571973043E-3087 + 5127 1.731507836924362148496307285986522E-3087 8.657539184621810742481536429932608E-3088 + 5128 4.328769592310905371240768214966304E-3088 2.164384796155452685620384107483152E-3088 + 5129 1.082192398077726342810192053741576E-3088 5.41096199038863171405096026870788E-3089 + 5130 2.70548099519431585702548013435394E-3089 1.35274049759715792851274006717697E-3089 + 5131 6.76370248798578964256370033588485E-3090 3.381851243992894821281850167942425E-3090 + 5132 1.690925621996447410640925083971213E-3090 8.454628109982237053204625419856063E-3091 + 5133 4.227314054991118526602312709928032E-3091 2.113657027495559263301156354964016E-3091 + 5134 1.056828513747779631650578177482008E-3091 5.28414256873889815825289088741004E-3092 + 5135 2.64207128436944907912644544370502E-3092 1.32103564218472453956322272185251E-3092 + 5136 6.60517821092362269781611360926255E-3093 3.302589105461811348908056804631275E-3093 + 5137 1.651294552730905674454028402315638E-3093 8.256472763654528372270142011578188E-3094 + 5138 4.128236381827264186135071005789094E-3094 2.064118190913632093067535502894547E-3094 + 5139 1.032059095456816046533767751447274E-3094 5.160295477284080232668838757236368E-3095 + 5140 2.580147738642040116334419378618184E-3095 1.290073869321020058167209689309092E-3095 + 5141 6.45036934660510029083604844654546E-3096 3.22518467330255014541802422327273E-3096 + 5142 1.612592336651275072709012111636365E-3096 8.062961683256375363545060558181825E-3097 + 5143 4.031480841628187681772530279090913E-3097 2.015740420814093840886265139545456E-3097 + 5144 1.007870210407046920443132569772728E-3097 5.03935105203523460221566284886364E-3098 + 5145 2.51967552601761730110783142443182E-3098 1.25983776300880865055391571221591E-3098 + 5146 6.29918881504404325276957856107955E-3099 3.149594407522021626384789280539775E-3099 + 5147 1.574797203761010813192394640269888E-3099 7.873986018805054065961973201349438E-3100 + 5148 3.936993009402527032980986600674719E-3100 1.968496504701263516490493300337360E-3100 + 5149 9.84248252350631758245246650168680E-3101 4.92124126175315879122623325084340E-3101 + 5150 2.46062063087657939561311662542170E-3101 1.23031031543828969780655831271085E-3101 + 5151 6.15155157719144848903279156355425E-3102 3.075775788595724244516395781777125E-3102 + 5152 1.537887894297862122258197890888563E-3102 7.689439471489310611290989454442813E-3103 + 5153 3.844719735744655305645494727221407E-3103 1.922359867872327652822747363610703E-3103 + 5154 9.611799339361638264113736818053515E-3104 4.805899669680819132056868409026758E-3104 + 5155 2.402949834840409566028434204513379E-3104 1.201474917420204783014217102256690E-3104 + 5156 6.00737458710102391507108551128345E-3105 3.003687293550511957535542755641725E-3105 + 5157 1.501843646775255978767771377820863E-3105 7.509218233876279893838856889104313E-3106 + 5158 3.754609116938139946919428444552157E-3106 1.877304558469069973459714222276078E-3106 + 5159 9.38652279234534986729857111138039E-3107 4.693261396172674933649285555690195E-3107 + 5160 2.346630698086337466824642777845098E-3107 1.173315349043168733412321388922549E-3107 + 5161 5.866576745215843667061606944612745E-3108 2.933288372607921833530803472306373E-3108 + 5162 1.466644186303960916765401736153187E-3108 7.333220931519804583827008680765933E-3109 + 5163 3.666610465759902291913504340382967E-3109 1.833305232879951145956752170191483E-3109 + 5164 9.166526164399755729783760850957415E-3110 4.583263082199877864891880425478708E-3110 + 5165 2.291631541099938932445940212739354E-3110 1.145815770549969466222970106369677E-3110 + 5166 5.729078852749847331114850531848385E-3111 2.864539426374923665557425265924193E-3111 + 5167 1.432269713187461832778712632962097E-3111 7.161348565937309163893563164810483E-3112 + 5168 3.580674282968654581946781582405242E-3112 1.790337141484327290973390791202621E-3112 + 5169 8.951685707421636454866953956013105E-3113 4.475842853710818227433476978006553E-3113 + 5170 2.237921426855409113716738489003277E-3113 1.118960713427704556858369244501638E-3113 + 5171 5.59480356713852278429184622250819E-3114 2.797401783569261392145923111254095E-3114 + 5172 1.398700891784630696072961555627048E-3114 6.993504458923153480364807778135238E-3115 + 5173 3.496752229461576740182403889067619E-3115 1.748376114730788370091201944533810E-3115 + 5174 8.74188057365394185045600972266905E-3116 4.370940286826970925228004861334525E-3116 + 5175 2.185470143413485462614002430667263E-3116 1.092735071706742731307001215333631E-3116 + 5176 5.463675358533713656535006076668155E-3117 2.731837679266856828267503038334078E-3117 + 5177 1.365918839633428414133751519167039E-3117 6.829594198167142070668757595835195E-3118 + 5178 3.414797099083571035334378797917598E-3118 1.707398549541785517667189398958799E-3118 + 5179 8.536992747708927588335946994793995E-3119 4.268496373854463794167973497396998E-3119 + 5180 2.134248186927231897083986748698499E-3119 1.067124093463615948541993374349250E-3119 + 5181 5.33562046731807974270996687174625E-3120 2.667810233659039871354983435873125E-3120 + 5182 1.333905116829519935677491717936563E-3120 6.669525584147599678387458589682813E-3121 + 5183 3.334762792073799839193729294841407E-3121 1.667381396036899919596864647420703E-3121 + 5184 8.336906980184499597984323237103515E-3122 4.168453490092249798992161618551758E-3122 + 5185 2.084226745046124899496080809275879E-3122 1.042113372523062449748040404637940E-3122 + 5186 5.21056686261531224874020202318970E-3123 2.60528343130765612437010101159485E-3123 + 5187 1.302641715653828062185050505797425E-3123 6.513208578269140310925252528987125E-3124 + 5188 3.256604289134570155462626264493563E-3124 1.628302144567285077731313132246781E-3124 + 5189 8.141510722836425388656565661233905E-3125 4.070755361418212694328282830616953E-3125 + 5190 2.035377680709106347164141415308477E-3125 1.017688840354553173582070707654238E-3125 + 5191 5.08844420177276586791035353827119E-3126 2.544222100886382933955176769135595E-3126 + 5192 1.272111050443191466977588384567798E-3126 6.360555252215957334887941922838988E-3127 + 5193 3.180277626107978667443970961419494E-3127 1.590138813053989333721985480709747E-3127 + 5194 7.950694065269946668609927403548735E-3128 3.975347032634973334304963701774368E-3128 + 5195 1.987673516317486667152481850887184E-3128 9.93836758158743333576240925443592E-3129 + 5196 4.96918379079371666788120462721796E-3129 2.48459189539685833394060231360898E-3129 + 5197 1.24229594769842916697030115680449E-3129 6.21147973849214583485150578402245E-3130 + 5198 3.105739869246072917425752892011225E-3130 1.552869934623036458712876446005613E-3130 + 5199 7.764349673115182293564382230028065E-3131 3.882174836557591146782191115014033E-3131 + 5200 1.941087418278795573391095557507017E-3131 9.705437091393977866955477787535083E-3132 + 5201 4.852718545696988933477738893767542E-3132 2.426359272848494466738869446883771E-3132 + 5202 1.213179636424247233369434723441886E-3132 6.065898182121236166847173617209428E-3133 + 5203 3.032949091060618083423586808604714E-3133 1.516474545530309041711793404302357E-3133 + 5204 7.582372727651545208558967021511785E-3134 3.791186363825772604279483510755893E-3134 + 5205 1.895593181912886302139741755377947E-3134 9.477965909564431510698708776889733E-3135 + 5206 4.738982954782215755349354388444867E-3135 2.369491477391107877674677194222433E-3135 + 5207 1.184745738695553938837338597111217E-3135 5.923728693477769694186692985556083E-3136 + 5208 2.961864346738884847093346492778042E-3136 1.480932173369442423546673246389021E-3136 + 5209 7.404660866847212117733366231945105E-3137 3.702330433423606058866683115972553E-3137 + 5210 1.851165216711803029433341557986277E-3137 9.255826083559015147166707789931383E-3138 + 5211 4.627913041779507573583353894965692E-3138 2.313956520889753786791676947482846E-3138 + 5212 1.156978260444876893395838473741423E-3138 5.784891302224384466979192368707115E-3139 + 5213 2.892445651112192233489596184353558E-3139 1.446222825556096116744798092176779E-3139 + 5214 7.231114127780480583723990460883895E-3140 3.615557063890240291861995230441948E-3140 + 5215 1.807778531945120145930997615220974E-3140 9.03889265972560072965498807610487E-3141 + 5216 4.519446329862800364827494038052435E-3141 2.259723164931400182413747019026218E-3141 + 5217 1.129861582465700091206873509513109E-3141 5.649307912328500456034367547565545E-3142 + 5218 2.824653956164250228017183773782773E-3142 1.412326978082125114008591886891386E-3142 + 5219 7.06163489041062557004295943445693E-3143 3.530817445205312785021479717228465E-3143 + 5220 1.765408722602656392510739858614233E-3143 8.827043613013281962553699293071163E-3144 + 5221 4.413521806506640981276849646535582E-3144 2.206760903253320490638424823267791E-3144 + 5222 1.103380451626660245319212411633896E-3144 5.516902258133301226596062058169478E-3145 + 5223 2.758451129066650613298031029084739E-3145 1.379225564533325306649015514542370E-3145 + 5224 6.89612782266662653324507757271185E-3146 3.448063911333313266622538786355925E-3146 + 5225 1.724031955666656633311269393177963E-3146 8.620159778333283166556346965889813E-3147 + 5226 4.310079889166641583278173482944907E-3147 2.155039944583320791639086741472453E-3147 + 5227 1.077519972291660395819543370736227E-3147 5.387599861458301979097716853681133E-3148 + 5228 2.693799930729150989548858426840567E-3148 1.346899965364575494774429213420283E-3148 + 5229 6.734499826822877473872146067101415E-3149 3.367249913411438736936073033550708E-3149 + 5230 1.683624956705719368468036516775354E-3149 8.41812478352859684234018258387677E-3150 + 5231 4.209062391764298421170091291938385E-3150 2.104531195882149210585045645969193E-3150 + 5232 1.052265597941074605292522822984597E-3150 5.261327989705373026462614114922983E-3151 + 5233 2.630663994852686513231307057461492E-3151 1.315331997426343256615653528730746E-3151 + 5234 6.57665998713171628307826764365373E-3152 3.288329993565858141539133821826865E-3152 + 5235 1.644164996782929070769566910913433E-3152 8.220824983914645353847834554567163E-3153 + 5236 4.110412491957322676923917277283582E-3153 2.055206245978661338461958638641791E-3153 + 5237 1.027603122989330669230979319320896E-3153 5.138015614946653346154896596604478E-3154 + 5238 2.569007807473326673077448298302239E-3154 1.284503903736663336538724149151120E-3154 + 5239 6.42251951868331668269362074575560E-3155 3.21125975934165834134681037287780E-3155 + 5240 1.60562987967082917067340518643890E-3155 8.0281493983541458533670259321945E-3156 + 5241 4.01407469917707292668351296609725E-3156 2.007037349588536463341756483048625E-3156 + 5242 1.003518674794268231670878241524313E-3156 5.017593373971341158354391207621563E-3157 + 5243 2.508796686985670579177195603810782E-3157 1.254398343492835289588597801905391E-3157 + 5244 6.271991717464176447942989009526955E-3158 3.135995858732088223971494504763478E-3158 + 5245 1.567997929366044111985747252381739E-3158 7.839989646830220559928736261908695E-3159 + 5246 3.919994823415110279964368130954348E-3159 1.959997411707555139982184065477174E-3159 + 5247 9.79998705853777569991092032738587E-3160 4.899993529268887849955460163692935E-3160 + 5248 2.449996764634443924977730081846468E-3160 1.224998382317221962488865040923234E-3160 + 5249 6.12499191158610981244432520461617E-3161 3.062495955793054906222162602308085E-3161 + 5250 1.531247977896527453111081301154043E-3161 7.656239889482637265555406505770213E-3162 + 5251 3.828119944741318632777703252885107E-3162 1.914059972370659316388851626442553E-3162 + 5252 9.570299861853296581944258132212765E-3163 4.785149930926648290972129066106383E-3163 + 5253 2.392574965463324145486064533053192E-3163 1.196287482731662072743032266526596E-3163 + 5254 5.98143741365831036371516133263298E-3164 2.99071870682915518185758066631649E-3164 + 5255 1.495359353414577590928790333158245E-3164 7.476796767072887954643951665791225E-3165 + 5256 3.738398383536443977321975832895613E-3165 1.869199191768221988660987916447806E-3165 + 5257 9.34599595884110994330493958223903E-3166 4.672997979420554971652469791119515E-3166 + 5258 2.336498989710277485826234895559758E-3166 1.168249494855138742913117447779879E-3166 + 5259 5.841247474275693714565587238899395E-3167 2.920623737137846857282793619449698E-3167 + 5260 1.460311868568923428641396809724849E-3167 7.301559342844617143206984048624245E-3168 + 5261 3.650779671422308571603492024312123E-3168 1.825389835711154285801746012156061E-3168 + 5262 9.126949178555771429008730060780305E-3169 4.563474589277885714504365030390153E-3169 + 5263 2.281737294638942857252182515195077E-3169 1.140868647319471428626091257597538E-3169 + 5264 5.70434323659735714313045628798769E-3170 2.852171618298678571565228143993845E-3170 + 5265 1.426085809149339285782614071996923E-3170 7.130429045746696428913070359984613E-3171 + 5266 3.565214522873348214456535179992307E-3171 1.782607261436674107228267589996153E-3171 + 5267 8.913036307183370536141337949980765E-3172 4.456518153591685268070668974990383E-3172 + 5268 2.228259076795842634035334487495192E-3172 1.114129538397921317017667243747596E-3172 + 5269 5.57064769198960658508833621873798E-3173 2.78532384599480329254416810936899E-3173 + 5270 1.392661922997401646272084054684495E-3173 6.963309614987008231360420273422475E-3174 + 5271 3.481654807493504115680210136711238E-3174 1.740827403746752057840105068355619E-3174 + 5272 8.704137018733760289200525341778095E-3175 4.352068509366880144600262670889048E-3175 + 5273 2.176034254683440072300131335444524E-3175 1.088017127341720036150065667722262E-3175 + 5274 5.44008563670860018075032833861131E-3176 2.720042818354300090375164169305655E-3176 + 5275 1.360021409177150045187582084652828E-3176 6.800107045885750225937910423264138E-3177 + 5276 3.400053522942875112968955211632069E-3177 1.700026761471437556484477605816035E-3177 + 5277 8.500133807357187782422388029080175E-3178 4.250066903678593891211194014540088E-3178 + 5278 2.125033451839296945605597007270044E-3178 1.062516725919648472802798503635022E-3178 + 5279 5.31258362959824236401399251817511E-3179 2.656291814799121182006996259087555E-3179 + 5280 1.328145907399560591003498129543778E-3179 6.640729536997802955017490647718888E-3180 + 5281 3.320364768498901477508745323859444E-3180 1.660182384249450738754372661929722E-3180 + 5282 8.30091192124725369377186330964861E-3181 4.150455960623626846885931654824305E-3181 + 5283 2.075227980311813423442965827412153E-3181 1.037613990155906711721482913706076E-3181 + 5284 5.18806995077953355860741456853038E-3182 2.59403497538976677930370728426519E-3182 + 5285 1.297017487694883389651853642132595E-3182 6.485087438474416948259268210662975E-3183 + 5286 3.242543719237208474129634105331488E-3183 1.621271859618604237064817052665744E-3183 + 5287 8.10635929809302118532408526332872E-3184 4.05317964904651059266204263166436E-3184 + 5288 2.02658982452325529633102131583218E-3184 1.01329491226162764816551065791609E-3184 + 5289 5.06647456130813824082755328958045E-3185 2.533237280654069120413776644790225E-3185 + 5290 1.266618640327034560206888322395113E-3185 6.333093201635172801034441611975563E-3186 + 5291 3.166546600817586400517220805987782E-3186 1.583273300408793200258610402993891E-3186 + 5292 7.916366502043966001293052014969455E-3187 3.958183251021983000646526007484728E-3187 + 5293 1.979091625510991500323263003742364E-3187 9.89545812755495750161631501871182E-3188 + 5294 4.94772906377747875080815750935591E-3188 2.473864531888739375404078754677955E-3188 + 5295 1.236932265944369687702039377338978E-3188 6.184661329721848438510196886694888E-3189 + 5296 3.092330664860924219255098443347444E-3189 1.546165332430462109627549221673722E-3189 + 5297 7.73082666215231054813774610836861E-3190 3.865413331076155274068873054184305E-3190 + 5298 1.932706665538077637034436527092153E-3190 9.663533327690388185172182635460763E-3191 + 5299 4.831766663845194092586091317730382E-3191 2.415883331922597046293045658865191E-3191 + 5300 1.207941665961298523146522829432596E-3191 6.039708329806492615732614147162978E-3192 + 5301 3.019854164903246307866307073581489E-3192 1.509927082451623153933153536790745E-3192 + 5302 7.549635412258115769665767683953725E-3193 3.774817706129057884832883841976863E-3193 + 5303 1.887408853064528942416441920988432E-3193 9.437044265322644712082209604942158E-3194 + 5304 4.718522132661322356041104802471079E-3194 2.359261066330661178020552401235540E-3194 + 5305 1.179630533165330589010276200617770E-3194 5.89815266582665294505138100308885E-3195 + 5306 2.949076332913326472525690501544425E-3195 1.474538166456663236262845250772213E-3195 + 5307 7.372690832283316181314226253861065E-3196 3.686345416141658090657113126930533E-3196 + 5308 1.843172708070829045328556563465267E-3196 9.215863540354145226642782817326333E-3197 + 5309 4.607931770177072613321391408663167E-3197 2.303965885088536306660695704331583E-3197 + 5310 1.151982942544268153330347852165792E-3197 5.759914712721340766651739260828958E-3198 + 5311 2.879957356360670383325869630414479E-3198 1.439978678180335191662934815207240E-3198 + 5312 7.19989339090167595831467407603620E-3199 3.59994669545083797915733703801810E-3199 + 5313 1.79997334772541898957866851900905E-3199 8.99986673862709494789334259504525E-3200 + 5314 4.499933369313547473946671297522625E-3200 2.249966684656773736973335648761313E-3200 + 5315 1.124983342328386868486667824380657E-3200 5.624916711641934342433339121903283E-3201 + 5316 2.812458355820967171216669560951642E-3201 1.406229177910483585608334780475821E-3201 + 5317 7.031145889552417928041673902379105E-3202 3.515572944776208964020836951189553E-3202 + 5318 1.757786472388104482010418475594777E-3202 8.788932361940522410052092377973883E-3203 + 5319 4.394466180970261205026046188986942E-3203 2.197233090485130602513023094493471E-3203 + 5320 1.098616545242565301256511547246736E-3203 5.493082726212826506282557736233678E-3204 + 5321 2.746541363106413253141278868116839E-3204 1.373270681553206626570639434058420E-3204 + 5322 6.86635340776603313285319717029210E-3205 3.43317670388301656642659858514605E-3205 + 5323 1.716588351941508283213299292573025E-3205 8.582941759707541416066496462865125E-3206 + 5324 4.291470879853770708033248231432563E-3206 2.145735439926885354016624115716281E-3206 + 5325 1.072867719963442677008312057858141E-3206 5.364338599817213385041560289290703E-3207 + 5326 2.682169299908606692520780144645352E-3207 1.341084649954303346260390072322676E-3207 + 5327 6.70542324977151673130195036161338E-3208 3.35271162488575836565097518080669E-3208 + 5328 1.676355812442879182825487590403345E-3208 8.381779062214395914127437952016725E-3209 + 5329 4.190889531107197957063718976008363E-3209 2.095444765553598978531859488004181E-3209 + 5330 1.047722382776799489265929744002091E-3209 5.238611913883997446329648720010453E-3210 + 5331 2.619305956941998723164824360005227E-3210 1.309652978470999361582412180002613E-3210 + 5332 6.548264892354996807912060900013065E-3211 3.274132446177498403956030450006533E-3211 + 5333 1.637066223088749201978015225003267E-3211 8.185331115443746009890076125016333E-3212 + 5334 4.092665557721873004945038062508167E-3212 2.046332778860936502472519031254083E-3212 + 5335 1.023166389430468251236259515627042E-3212 5.115831947152341256181297578135208E-3213 + 5336 2.557915973576170628090648789067604E-3213 1.278957986788085314045324394533802E-3213 + 5337 6.39478993394042657022662197266901E-3214 3.197394966970213285113310986334505E-3214 + 5338 1.598697483485106642556655493167253E-3214 7.993487417425533212783277465836263E-3215 + 5339 3.996743708712766606391638732918132E-3215 1.998371854356383303195819366459066E-3215 + 5340 9.99185927178191651597909683229533E-3216 4.995929635890958257989548416147665E-3216 + 5341 2.497964817945479128994774208073833E-3216 1.248982408972739564497387104036916E-3216 + 5342 6.24491204486369782248693552018458E-3217 3.12245602243184891124346776009229E-3217 + 5343 1.561228011215924455621733880046145E-3217 7.806140056079622278108669400230725E-3218 + 5344 3.903070028039811139054334700115363E-3218 1.951535014019905569527167350057681E-3218 + 5345 9.757675070099527847635836750288405E-3219 4.878837535049763923817918375144203E-3219 + 5346 2.439418767524881961908959187572102E-3219 1.219709383762440980954479593786051E-3219 + 5347 6.098546918812204904772397968930255E-3220 3.049273459406102452386198984465128E-3220 + 5348 1.524636729703051226193099492232564E-3220 7.62318364851525613096549746116282E-3221 + 5349 3.81159182425762806548274873058141E-3221 1.905795912128814032741374365290705E-3221 + 5350 9.528979560644070163706871826453525E-3222 4.764489780322035081853435913226763E-3222 + 5351 2.382244890161017540926717956613382E-3222 1.191122445080508770463358978306691E-3222 + 5352 5.955612225402543852316794891533455E-3223 2.977806112701271926158397445766728E-3223 + 5353 1.488903056350635963079198722883364E-3223 7.44451528175317981539599361441682E-3224 + 5354 3.72225764087658990769799680720841E-3224 1.861128820438294953848998403604205E-3224 + 5355 9.305644102191474769244992018021025E-3225 4.652822051095737384622496009010513E-3225 + 5356 2.326411025547868692311248004505257E-3225 1.163205512773934346155624002252628E-3225 + 5357 5.81602756386967173077812001126314E-3226 2.90801378193483586538906000563157E-3226 + 5358 1.454006890967417932694530002815785E-3226 7.270034454837089663472650014078925E-3227 + 5359 3.635017227418544831736325007039463E-3227 1.817508613709272415868162503519731E-3227 + 5360 9.087543068546362079340812517598655E-3228 4.543771534273181039670406258799328E-3228 + 5361 2.271885767136590519835203129399664E-3228 1.135942883568295259917601564699832E-3228 + 5362 5.67971441784147629958800782349916E-3229 2.83985720892073814979400391174958E-3229 + 5363 1.41992860446036907489700195587479E-3229 7.09964302230184537448500977937395E-3230 + 5364 3.549821511150922687242504889686975E-3230 1.774910755575461343621252444843488E-3230 + 5365 8.87455377787730671810626222421744E-3231 4.43727688893865335905313111210872E-3231 + 5366 2.21863844446932667952656555605436E-3231 1.10931922223466333976328277802718E-3231 + 5367 5.5465961111733166988164138901359E-3232 2.77329805558665834940820694506795E-3232 + 5368 1.386649027793329174704103472533975E-3232 6.933245138966645873520517362669875E-3233 + 5369 3.466622569483322936760258681334938E-3233 1.733311284741661468380129340667469E-3233 + 5370 8.666556423708307341900646703337345E-3234 4.333278211854153670950323351668673E-3234 + 5371 2.166639105927076835475161675834337E-3234 1.083319552963538417737580837917168E-3234 + 5372 5.41659776481769208868790418958584E-3235 2.70829888240884604434395209479292E-3235 + 5373 1.35414944120442302217197604739646E-3235 6.7707472060221151108598802369823E-3236 + 5374 3.38537360301105755542994011849115E-3236 1.692686801505528777714970059245575E-3236 + 5375 8.463434007527643888574850296227875E-3237 4.231717003763821944287425148113938E-3237 + 5376 2.115858501881910972143712574056969E-3237 1.057929250940955486071856287028485E-3237 + 5377 5.289646254704777430359281435142425E-3238 2.644823127352388715179640717571213E-3238 + 5378 1.322411563676194357589820358785607E-3238 6.612057818380971787949101793928033E-3239 + 5379 3.306028909190485893974550896964017E-3239 1.653014454595242946987275448482008E-3239 + 5380 8.26507227297621473493637724241004E-3240 4.13253613648810736746818862120502E-3240 + 5381 2.06626806824405368373409431060251E-3240 1.033134034122026841867047155301255E-3240 + 5382 5.165670170610134209335235776506275E-3241 2.582835085305067104667617888253138E-3241 + 5383 1.291417542652533552333808944126569E-3241 6.457087713262667761669044720632845E-3242 + 5384 3.228543856631333880834522360316423E-3242 1.614271928315666940417261180158211E-3242 + 5385 8.071359641578334702086305900791055E-3243 4.035679820789167351043152950395528E-3243 + 5386 2.017839910394583675521576475197764E-3243 1.008919955197291837760788237598882E-3243 + 5387 5.04459977598645918880394118799441E-3244 2.522299887993229594401970593997205E-3244 + 5388 1.261149943996614797200985296998603E-3244 6.305749719983073986004926484993013E-3245 + 5389 3.152874859991536993002463242496507E-3245 1.576437429995768496501231621248253E-3245 + 5390 7.882187149978842482506158106241265E-3246 3.941093574989421241253079053120633E-3246 + 5391 1.970546787494710620626539526560317E-3246 9.852733937473553103132697632801583E-3247 + 5392 4.926366968736776551566348816400792E-3247 2.463183484368388275783174408200396E-3247 + 5393 1.231591742184194137891587204100198E-3247 6.15795871092097068945793602050099E-3248 + 5394 3.078979355460485344728968010250495E-3248 1.539489677730242672364484005125248E-3248 + 5395 7.69744838865121336182242002562624E-3249 3.84872419432560668091121001281312E-3249 + 5396 1.92436209716280334045560500640656E-3249 9.6218104858140167022780250320328E-3250 + 5397 4.8109052429070083511390125160164E-3250 2.4054526214535041755695062580082E-3250 + 5398 1.2027263107267520877847531290041E-3250 6.0136315536337604389237656450205E-3251 + 5399 3.00681577681688021946188282251025E-3251 1.503407888408440109730941411255125E-3251 + 5400 7.517039442042200548654707056275625E-3252 3.758519721021100274327353528137813E-3252 + 5401 1.879259860510550137163676764068907E-3252 9.396299302552750685818383820344533E-3253 + 5402 4.698149651276375342909191910172267E-3253 2.349074825638187671454595955086133E-3253 + 5403 1.174537412819093835727297977543067E-3253 5.872687064095469178636489887715333E-3254 + 5404 2.936343532047734589318244943857667E-3254 1.468171766023867294659122471928833E-3254 + 5405 7.340858830119336473295612359644165E-3255 3.670429415059668236647806179822083E-3255 + 5406 1.835214707529834118323903089911042E-3255 9.176073537649170591619515449555208E-3256 + 5407 4.588036768824585295809757724777604E-3256 2.294018384412292647904878862388802E-3256 + 5408 1.147009192206146323952439431194401E-3256 5.735045961030731619762197155972005E-3257 + 5409 2.867522980515365809881098577986003E-3257 1.433761490257682904940549288993001E-3257 + 5410 7.168807451288414524702746444965005E-3258 3.584403725644207262351373222482503E-3258 + 5411 1.792201862822103631175686611241252E-3258 8.961009314110518155878433056206258E-3259 + 5412 4.480504657055259077939216528103129E-3259 2.240252328527629538969608264051565E-3259 + 5413 1.120126164263814769484804132025783E-3259 5.600630821319073847424020660128913E-3260 + 5414 2.800315410659536923712010330064457E-3260 1.400157705329768461856005165032228E-3260 + 5415 7.00078852664884230928002582516114E-3261 3.50039426332442115464001291258057E-3261 + 5416 1.750197131662210577320006456290285E-3261 8.750985658311052886600032281451425E-3262 + 5417 4.375492829155526443300016140725713E-3262 2.187746414577763221650008070362856E-3262 + 5418 1.093873207288881610825004035181428E-3262 5.46936603644440805412502017590714E-3263 + 5419 2.73468301822220402706251008795357E-3263 1.367341509111102013531255043976785E-3263 + 5420 6.836707545555510067656275219883925E-3264 3.418353772777755033828137609941963E-3264 + 5421 1.709176886388877516914068804970982E-3264 8.545884431944387584570344024854908E-3265 + 5422 4.272942215972193792285172012427454E-3265 2.136471107986096896142586006213727E-3265 + 5423 1.068235553993048448071293003106864E-3265 5.341177769965242240356465015534318E-3266 + 5424 2.670588884982621120178232507767159E-3266 1.335294442491310560089116253883580E-3266 + 5425 6.67647221245655280044558126941790E-3267 3.33823610622827640022279063470895E-3267 + 5426 1.669118053114138200111395317354475E-3267 8.345590265570691000556976586772375E-3268 + 5427 4.172795132785345500278488293386188E-3268 2.086397566392672750139244146693094E-3268 + 5428 1.043198783196336375069622073346547E-3268 5.215993915981681875348110366732735E-3269 + 5429 2.607996957990840937674055183366368E-3269 1.303998478995420468837027591683184E-3269 + 5430 6.51999239497710234418513795841592E-3270 3.25999619748855117209256897920796E-3270 + 5431 1.62999809874427558604628448960398E-3270 8.1499904937213779302314224480199E-3271 + 5432 4.07499524686068896511571122400995E-3271 2.037497623430344482557855612004975E-3271 + 5433 1.018748811715172241278927806002488E-3271 5.093744058575861206394639030012438E-3272 + 5434 2.546872029287930603197319515006219E-3272 1.273436014643965301598659757503110E-3272 + 5435 6.36718007321982650799329878751555E-3273 3.183590036609913253996649393757775E-3273 + 5436 1.591795018304956626998324696878888E-3273 7.958975091524783134991623484394438E-3274 + 5437 3.979487545762391567495811742197219E-3274 1.989743772881195783747905871098610E-3274 + 5438 9.94871886440597891873952935549305E-3275 4.974359432202989459369764677746525E-3275 + 5439 2.487179716101494729684882338873263E-3275 1.243589858050747364842441169436631E-3275 + 5440 6.217949290253736824212205847183155E-3276 3.108974645126868412106102923591578E-3276 + 5441 1.554487322563434206053051461795789E-3276 7.772436612817171030265257308978945E-3277 + 5442 3.886218306408585515132628654489473E-3277 1.943109153204292757566314327244736E-3277 + 5443 9.71554576602146378783157163622368E-3278 4.85777288301073189391578581811184E-3278 + 5444 2.42888644150536594695789290905592E-3278 1.21444322075268297347894645452796E-3278 + 5445 6.0722161037634148673947322726398E-3279 3.0361080518817074336973661363199E-3279 + 5446 1.51805402594085371684868306815995E-3279 7.59027012970426858424341534079975E-3280 + 5447 3.795135064852134292121707670399875E-3280 1.897567532426067146060853835199938E-3280 + 5448 9.48783766213033573030426917599969E-3281 4.743918831065167865152134587999845E-3281 + 5449 2.371959415532583932576067293999923E-3281 1.185979707766291966288033646999961E-3281 + 5450 5.929898538831459831440168234999805E-3282 2.964949269415729915720084117499903E-3282 + 5451 1.482474634707864957860042058749952E-3282 7.412373173539324789300210293749758E-3283 + 5452 3.706186586769662394650105146874879E-3283 1.853093293384831197325052573437440E-3283 + 5453 9.26546646692415598662526286718720E-3284 4.63273323346207799331263143359360E-3284 + 5454 2.31636661673103899665631571679680E-3284 1.15818330836551949832815785839840E-3284 + 5455 5.7909165418275974916407892919920E-3285 2.8954582709137987458203946459960E-3285 + 5456 1.4477291354568993729101973229980E-3285 7.238645677284496864550986614990E-3286 + 5457 3.619322838642248432275493307495E-3286 1.8096614193211242161377466537475E-3286 + 5458 9.0483070966056210806887332687375E-3287 4.52415354830281054034436663436875E-3287 + 5459 2.262076774151405270172183317184375E-3287 1.131038387075702635086091658592188E-3287 + 5460 5.65519193537851317543045829296094E-3288 2.82759596768925658771522914648047E-3288 + 5461 1.413797983844628293857614573240235E-3288 7.068989919223141469288072866201175E-3289 + 5462 3.534494959611570734644036433100588E-3289 1.767247479805785367322018216550294E-3289 + 5463 8.83623739902892683661009108275147E-3290 4.418118699514463418305045541375735E-3290 + 5464 2.209059349757231709152522770687868E-3290 1.104529674878615854576261385343934E-3290 + 5465 5.52264837439307927288130692671967E-3291 2.761324187196539636440653463359835E-3291 + 5466 1.380662093598269818220326731679918E-3291 6.903310467991349091101633658399588E-3292 + 5467 3.451655233995674545550816829199794E-3292 1.725827616997837272775408414599897E-3292 + 5468 8.629138084989186363877042072999485E-3293 4.314569042494593181938521036499743E-3293 + 5469 2.157284521247296590969260518249872E-3293 1.078642260623648295484630259124936E-3293 + 5470 5.39321130311824147742315129562468E-3294 2.69660565155912073871157564781234E-3294 + 5471 1.34830282577956036935578782390617E-3294 6.74151412889780184677893911953085E-3295 + 5472 3.370757064448900923389469559765425E-3295 1.685378532224450461694734779882713E-3295 + 5473 8.426892661122252308473673899413565E-3296 4.213446330561126154236836949706783E-3296 + 5474 2.106723165280563077118418474853392E-3296 1.053361582640281538559209237426696E-3296 + 5475 5.26680791320140769279604618713348E-3297 2.63340395660070384639802309356674E-3297 + 5476 1.31670197830035192319901154678337E-3297 6.58350989150175961599505773391685E-3298 + 5477 3.291754945750879807997528866958425E-3298 1.645877472875439903998764433479213E-3298 + 5478 8.229387364377199519993822167396065E-3299 4.114693682188599759996911083698033E-3299 + 5479 2.057346841094299879998455541849017E-3299 1.028673420547149939999227770924508E-3299 + 5480 5.14336710273574969999613885462254E-3300 2.57168355136787484999806942731127E-3300 + 5481 1.285841775683937424999034713655635E-3300 6.429208878419687124995173568278175E-3301 + 5482 3.214604439209843562497586784139088E-3301 1.607302219604921781248793392069544E-3301 + 5483 8.03651109802460890624396696034772E-3302 4.01825554901230445312198348017386E-3302 + 5484 2.00912777450615222656099174008693E-3302 1.004563887253076113280495870043465E-3302 + 5485 5.022819436265380566402479350217325E-3303 2.511409718132690283201239675108663E-3303 + 5486 1.255704859066345141600619837554332E-3303 6.278524295331725708003099187771658E-3304 + 5487 3.139262147665862854001549593885829E-3304 1.569631073832931427000774796942915E-3304 + 5488 7.848155369164657135003873984714575E-3305 3.924077684582328567501936992357288E-3305 + 5489 1.962038842291164283750968496178644E-3305 9.81019421145582141875484248089322E-3306 + 5490 4.90509710572791070937742124044661E-3306 2.452548552863955354688710620223305E-3306 + 5491 1.226274276431977677344355310111653E-3306 6.131371382159888386721776550558263E-3307 + 5492 3.065685691079944193360888275279132E-3307 1.532842845539972096680444137639566E-3307 + 5493 7.66421422769986048340222068819783E-3308 3.832107113849930241701110344098915E-3308 + 5494 1.916053556924965120850555172049458E-3308 9.580267784624825604252775860247288E-3309 + 5495 4.790133892312412802126387930123644E-3309 2.395066946156206401063193965061822E-3309 + 5496 1.197533473078103200531596982530911E-3309 5.987667365390516002657984912654555E-3310 + 5497 2.993833682695258001328992456327278E-3310 1.496916841347629000664496228163639E-3310 + 5498 7.484584206738145003322481140818195E-3311 3.742292103369072501661240570409098E-3311 + 5499 1.871146051684536250830620285204549E-3311 9.355730258422681254153101426022745E-3312 + 5500 4.677865129211340627076550713011373E-3312 2.338932564605670313538275356505686E-3312 + 5501 1.169466282302835156769137678252843E-3312 5.847331411514175783845688391264215E-3313 + 5502 2.923665705757087891922844195632108E-3313 1.461832852878543945961422097816054E-3313 + 5503 7.30916426439271972980711048908027E-3314 3.654582132196359864903555244540135E-3314 + 5504 1.827291066098179932451777622270068E-3314 9.136455330490899662258888111350338E-3315 + 5505 4.568227665245449831129444055675169E-3315 2.284113832622724915564722027837585E-3315 + 5506 1.142056916311362457782361013918793E-3315 5.710284581556812288911805069593963E-3316 + 5507 2.855142290778406144455902534796982E-3316 1.427571145389203072227951267398491E-3316 + 5508 7.137855726946015361139756336992455E-3317 3.568927863473007680569878168496228E-3317 + 5509 1.784463931736503840284939084248114E-3317 8.92231965868251920142469542124057E-3318 + 5510 4.461159829341259600712347710620285E-3318 2.230579914670629800356173855310143E-3318 + 5511 1.115289957335314900178086927655072E-3318 5.576449786676574500890434638275358E-3319 + 5512 2.788224893338287250445217319137679E-3319 1.394112446669143625222608659568840E-3319 + 5513 6.97056223334571812611304329784420E-3320 3.48528111667285906305652164892210E-3320 + 5514 1.74264055833642953152826082446105E-3320 8.71320279168214765764130412230525E-3321 + 5515 4.356601395841073828820652061152625E-3321 2.178300697920536914410326030576313E-3321 + 5516 1.089150348960268457205163015288157E-3321 5.445751744801342286025815076440783E-3322 + 5517 2.722875872400671143012907538220392E-3322 1.361437936200335571506453769110196E-3322 + 5518 6.80718968100167785753226884555098E-3323 3.40359484050083892876613442277549E-3323 + 5519 1.701797420250419464383067211387745E-3323 8.508987101252097321915336056938725E-3324 + 5520 4.254493550626048660957668028469363E-3324 2.127246775313024330478834014234681E-3324 + 5521 1.063623387656512165239417007117341E-3324 5.318116938282560826197085035586703E-3325 + 5522 2.659058469141280413098542517793352E-3325 1.329529234570640206549271258896676E-3325 + 5523 6.64764617285320103274635629448338E-3326 3.32382308642660051637317814724169E-3326 + 5524 1.661911543213300258186589073620845E-3326 8.309557716066501290932945368104225E-3327 + 5525 4.154778858033250645466472684052113E-3327 2.077389429016625322733236342026056E-3327 + 5526 1.038694714508312661366618171013028E-3327 5.19347357254156330683309085506514E-3328 + 5527 2.59673678627078165341654542753257E-3328 1.298368393135390826708272713766285E-3328 + 5528 6.491841965676954133541363568831425E-3329 3.245920982838477066770681784415713E-3329 + 5529 1.622960491419238533385340892207857E-3329 8.114802457096192666926704461039283E-3330 + 5530 4.057401228548096333463352230519642E-3330 2.028700614274048166731676115259821E-3330 + 5531 1.014350307137024083365838057629911E-3330 5.071751535685120416829190288149553E-3331 + 5532 2.535875767842560208414595144074777E-3331 1.267937883921280104207297572037388E-3331 + 5533 6.33968941960640052103648786018694E-3332 3.16984470980320026051824393009347E-3332 + 5534 1.584922354901600130259121965046735E-3332 7.924611774508000651295609825233675E-3333 + 5535 3.962305887254000325647804912616838E-3333 1.981152943627000162823902456308419E-3333 + 5536 9.905764718135000814119512281542095E-3334 4.952882359067500407059756140771048E-3334 + 5537 2.476441179533750203529878070385524E-3334 1.238220589766875101764939035192762E-3334 + 5538 6.19110294883437550882469517596381E-3335 3.095551474417187754412347587981905E-3335 + 5539 1.547775737208593877206173793990953E-3335 7.738878686042969386030868969954763E-3336 + 5540 3.869439343021484693015434484977382E-3336 1.934719671510742346507717242488691E-3336 + 5541 9.673598357553711732538586212443455E-3337 4.836799178776855866269293106221728E-3337 + 5542 2.418399589388427933134646553110864E-3337 1.209199794694213966567323276555432E-3337 + 5543 6.04599897347106983283661638277716E-3338 3.02299948673553491641830819138858E-3338 + 5544 1.51149974336776745820915409569429E-3338 7.55749871683883729104577047847145E-3339 + 5545 3.778749358419418645522885239235725E-3339 1.889374679209709322761442619617863E-3339 + 5546 9.446873396048546613807213098089315E-3340 4.723436698024273306903606549044658E-3340 + 5547 2.361718349012136653451803274522329E-3340 1.180859174506068326725901637261165E-3340 + 5548 5.904295872530341633629508186305825E-3341 2.952147936265170816814754093152913E-3341 + 5549 1.476073968132585408407377046576457E-3341 7.380369840662927042036885232882283E-3342 + 5550 3.690184920331463521018442616441142E-3342 1.845092460165731760509221308220571E-3342 + 5551 9.225462300828658802546106541102855E-3343 4.612731150414329401273053270551428E-3343 + 5552 2.306365575207164700636526635275714E-3343 1.153182787603582350318263317637857E-3343 + 5553 5.765913938017911751591316588189285E-3344 2.882956969008955875795658294094643E-3344 + 5554 1.441478484504477937897829147047322E-3344 7.207392422522389689489145735236608E-3345 + 5555 3.603696211261194844744572867618304E-3345 1.801848105630597422372286433809152E-3345 + 5556 9.00924052815298711186143216904576E-3346 4.50462026407649355593071608452288E-3346 + 5557 2.25231013203824677796535804226144E-3346 1.12615506601912338898267902113072E-3346 + 5558 5.6307753300956169449133951056536E-3347 2.8153876650478084724566975528268E-3347 + 5559 1.4076938325239042362283487764134E-3347 7.038469162619521181141743882067E-3348 + 5560 3.5192345813097605905708719410335E-3348 1.75961729065488029528543597051675E-3348 + 5561 8.79808645327440147642717985258375E-3349 4.399043226637200738213589926291875E-3349 + 5562 2.199521613318600369106794963145938E-3349 1.099760806659300184553397481572969E-3349 + 5563 5.498804033296500922766987407864845E-3350 2.749402016648250461383493703932423E-3350 + 5564 1.374701008324125230691746851966212E-3350 6.873505041620626153458734259831058E-3351 + 5565 3.436752520810313076729367129915529E-3351 1.718376260405156538364683564957765E-3351 + 5566 8.591881302025782691823417824788825E-3352 4.295940651012891345911708912394413E-3352 + 5567 2.147970325506445672955854456197207E-3352 1.073985162753222836477927228098603E-3352 + 5568 5.369925813766114182389636140493015E-3353 2.684962906883057091194818070246508E-3353 + 5569 1.342481453441528545597409035123254E-3353 6.71240726720764272798704517561627E-3354 + 5570 3.356203633603821363993522587808135E-3354 1.678101816801910681996761293904068E-3354 + 5571 8.39050908400955340998380646952034E-3355 4.19525454200477670499190323476017E-3355 + 5572 2.097627271002388352495951617380085E-3355 1.048813635501194176247975808690043E-3355 + 5573 5.244068177505970881239879043450215E-3356 2.622034088752985440619939521725108E-3356 + 5574 1.311017044376492720309969760862554E-3356 6.55508522188246360154984880431277E-3357 + 5575 3.277542610941231800774924402156385E-3357 1.638771305470615900387462201078193E-3357 + 5576 8.193856527353079501937311005390965E-3358 4.096928263676539750968655502695483E-3358 + 5577 2.048464131838269875484327751347742E-3358 1.024232065919134937742163875673871E-3358 + 5578 5.121160329595674688710819378369355E-3359 2.560580164797837344355409689184678E-3359 + 5579 1.280290082398918672177704844592339E-3359 6.401450411994593360888524222961695E-3360 + 5580 3.200725205997296680444262111480848E-3360 1.600362602998648340222131055740424E-3360 + 5581 8.00181301499324170111065527870212E-3361 4.00090650749662085055532763935106E-3361 + 5582 2.00045325374831042527766381967553E-3361 1.000226626874155212638831909837765E-3361 + 5583 5.001133134370776063194159549188825E-3362 2.500566567185388031597079774594413E-3362 + 5584 1.250283283592694015798539887297207E-3362 6.251416417963470078992699436486033E-3363 + 5585 3.125708208981735039496349718243017E-3363 1.562854104490867519748174859121508E-3363 + 5586 7.81427052245433759874087429560754E-3364 3.90713526122716879937043714780377E-3364 + 5587 1.953567630613584399685218573901885E-3364 9.767838153067921998426092869509425E-3365 + 5588 4.883919076533960999213046434754713E-3365 2.441959538266980499606523217377356E-3365 + 5589 1.220979769133490249803261608688678E-3365 6.10489884566745124901630804344339E-3366 + 5590 3.052449422833725624508154021721695E-3366 1.526224711416862812254077010860848E-3366 + 5591 7.63112355708431406127038505430424E-3367 3.81556177854215703063519252715212E-3367 + 5592 1.90778088927107851531759626357606E-3367 9.5389044463553925765879813178803E-3368 + 5593 4.76945222317769628829399065894015E-3368 2.384726111588848144146995329470075E-3368 + 5594 1.192363055794424072073497664735038E-3368 5.961815278972120360367488323675188E-3369 + 5595 2.980907639486060180183744161837594E-3369 1.490453819743030090091872080918797E-3369 + 5596 7.452269098715150450459360404593985E-3370 3.726134549357575225229680202296993E-3370 + 5597 1.863067274678787612614840101148497E-3370 9.315336373393938063074200505742483E-3371 + 5598 4.657668186696969031537100252871242E-3371 2.328834093348484515768550126435621E-3371 + 5599 1.164417046674242257884275063217811E-3371 5.822085233371211289421375316089053E-3372 + 5600 2.911042616685605644710687658044527E-3372 1.455521308342802822355343829022263E-3372 + 5601 7.277606541714014111776719145111315E-3373 3.638803270857007055888359572555658E-3373 + 5602 1.819401635428503527944179786277829E-3373 9.097008177142517639720898931389145E-3374 + 5603 4.548504088571258819860449465694573E-3374 2.274252044285629409930224732847286E-3374 + 5604 1.137126022142814704965112366423643E-3374 5.685630110714073524825561832118215E-3375 + 5605 2.842815055357036762412780916059108E-3375 1.421407527678518381206390458029554E-3375 + 5606 7.10703763839259190603195229014777E-3376 3.553518819196295953015976145073885E-3376 + 5607 1.776759409598147976507988072536943E-3376 8.883797047990739882539940362684713E-3377 + 5608 4.441898523995369941269970181342357E-3377 2.220949261997684970634985090671178E-3377 + 5609 1.110474630998842485317492545335589E-3377 5.552373154994212426587462726677945E-3378 + 5610 2.776186577497106213293731363338973E-3378 1.388093288748553106646865681669486E-3378 + 5611 6.94046644374276553323432840834743E-3379 3.470233221871382766617164204173715E-3379 + 5612 1.735116610935691383308582102086858E-3379 8.675583054678456916542910510434288E-3380 + 5613 4.337791527339228458271455255217144E-3380 2.168895763669614229135727627608572E-3380 + 5614 1.084447881834807114567863813804286E-3380 5.42223940917403557283931906902143E-3381 + 5615 2.711119704587017786419659534510715E-3381 1.355559852293508893209829767255358E-3381 + 5616 6.77779926146754446604914883627679E-3382 3.388899630733772233024574418138395E-3382 + 5617 1.694449815366886116512287209069198E-3382 8.472249076834430582561436045345988E-3383 + 5618 4.236124538417215291280718022672994E-3383 2.118062269208607645640359011336497E-3383 + 5619 1.059031134604303822820179505668249E-3383 5.295155673021519114100897528341243E-3384 + 5620 2.647577836510759557050448764170622E-3384 1.323788918255379778525224382085311E-3384 + 5621 6.618944591276898892626121910426555E-3385 3.309472295638449446313060955213278E-3385 + 5622 1.654736147819224723156530477606639E-3385 8.273680739096123615782652388033195E-3386 + 5623 4.136840369548061807891326194016598E-3386 2.068420184774030903945663097008299E-3386 + 5624 1.034210092387015451972831548504150E-3386 5.171050461935077259864157742520748E-3387 + 5625 2.585525230967538629932078871260374E-3387 1.292762615483769314966039435630187E-3387 + 5626 6.463813077418846574830197178150935E-3388 3.231906538709423287415098589075468E-3388 + 5627 1.615953269354711643707549294537734E-3388 8.07976634677355821853774647268867E-3389 + 5628 4.039883173386779109268873236344335E-3389 2.019941586693389554634436618172168E-3389 + 5629 1.009970793346694777317218309086084E-3389 5.04985396673347388658609154543042E-3390 + 5630 2.52492698336673694329304577271521E-3390 1.262463491683368471646522886357605E-3390 + 5631 6.312317458416842358232614431788025E-3391 3.156158729208421179116307215894013E-3391 + 5632 1.578079364604210589558153607947007E-3391 7.890396823021052947790768039735033E-3392 + 5633 3.945198411510526473895384019867517E-3392 1.972599205755263236947692009933758E-3392 + 5634 9.86299602877631618473846004966879E-3393 4.931498014388158092369230024834395E-3393 + 5635 2.465749007194079046184615012417198E-3393 1.232874503597039523092307506208599E-3393 + 5636 6.164372517985197615461537531042995E-3394 3.082186258992598807730768765521498E-3394 + 5637 1.541093129496299403865384382760749E-3394 7.705465647481497019326921913803745E-3395 + 5638 3.852732823740748509663460956901873E-3395 1.926366411870374254831730478450936E-3395 + 5639 9.63183205935187127415865239225468E-3396 4.81591602967593563707932619612734E-3396 + 5640 2.40795801483796781853966309806367E-3396 1.203979007418983909269831549031835E-3396 + 5641 6.019895037094919546349157745159175E-3397 3.009947518547459773174578872579588E-3397 + 5642 1.504973759273729886587289436289794E-3397 7.52486879636864943293644718144897E-3398 + 5643 3.762434398184324716468223590724485E-3398 1.881217199092162358234111795362243E-3398 + 5644 9.406085995460811791170558976811215E-3399 4.703042997730405895585279488405608E-3399 + 5645 2.351521498865202947792639744202804E-3399 1.175760749432601473896319872101402E-3399 + 5646 5.87880374716300736948159936050701E-3400 2.939401873581503684740799680253505E-3400 + 5647 1.469700936790751842370399840126753E-3400 7.348504683953759211851999200633763E-3401 + 5648 3.674252341976879605925999600316882E-3401 1.837126170988439802962999800158441E-3401 + 5649 9.185630854942199014814999000792205E-3402 4.592815427471099507407499500396103E-3402 + 5650 2.296407713735549753703749750198052E-3402 1.148203856867774876851874875099026E-3402 + 5651 5.74101928433887438425937437549513E-3403 2.870509642169437192129687187747565E-3403 + 5652 1.435254821084718596064843593873783E-3403 7.176274105423592980324217969368913E-3404 + 5653 3.588137052711796490162108984684457E-3404 1.794068526355898245081054492342228E-3404 + 5654 8.97034263177949122540527246171114E-3405 4.48517131588974561270263623085557E-3405 + 5655 2.242585657944872806351318115427785E-3405 1.121292828972436403175659057713893E-3405 + 5656 5.606464144862182015878295288569465E-3406 2.803232072431091007939147644284733E-3406 + 5657 1.401616036215545503969573822142367E-3406 7.008080181077727519847869110711833E-3407 + 5658 3.504040090538863759923934555355917E-3407 1.752020045269431879961967277677958E-3407 + 5659 8.76010022634715939980983638838979E-3408 4.380050113173579699904918194194895E-3408 + 5660 2.190025056586789849952459097097448E-3408 1.095012528293394924976229548548724E-3408 + 5661 5.47506264146697462488114774274362E-3409 2.73753132073348731244057387137181E-3409 + 5662 1.368765660366743656220286935685905E-3409 6.843828301833718281101434678429525E-3410 + 5663 3.421914150916859140550717339214763E-3410 1.710957075458429570275358669607381E-3410 + 5664 8.554785377292147851376793348036905E-3411 4.277392688646073925688396674018453E-3411 + 5665 2.138696344323036962844198337009227E-3411 1.069348172161518481422099168504613E-3411 + 5666 5.346740860807592407110495842523065E-3412 2.673370430403796203555247921261533E-3412 + 5667 1.336685215201898101777623960630767E-3412 6.683426076009490508888119803153833E-3413 + 5668 3.341713038004745254444059901576917E-3413 1.670856519002372627222029950788458E-3413 + 5669 8.35428259501186313611014975394229E-3414 4.177141297505931568055074876971145E-3414 + 5670 2.088570648752965784027537438485573E-3414 1.044285324376482892013768719242786E-3414 + 5671 5.22142662188241446006884359621393E-3415 2.610713310941207230034421798106965E-3415 + 5672 1.305356655470603615017210899053483E-3415 6.526783277353018075086054495267413E-3416 + 5673 3.263391638676509037543027247633707E-3416 1.631695819338254518771513623816853E-3416 + 5674 8.158479096691272593857568119084265E-3417 4.079239548345636296928784059542133E-3417 + 5675 2.039619774172818148464392029771067E-3417 1.019809887086409074232196014885533E-3417 + 5676 5.099049435432045371160980074427665E-3418 2.549524717716022685580490037213833E-3418 + 5677 1.274762358858011342790245018606917E-3418 6.373811794290056713951225093034583E-3419 + 5678 3.186905897145028356975612546517292E-3419 1.593452948572514178487806273258646E-3419 + 5679 7.96726474286257089243903136629323E-3420 3.983632371431285446219515683146615E-3420 + 5680 1.991816185715642723109757841573308E-3420 9.959080928578213615548789207866538E-3421 + 5681 4.979540464289106807774394603933269E-3421 2.489770232144553403887197301966635E-3421 + 5682 1.244885116072276701943598650983318E-3421 6.224425580361383509717993254916588E-3422 + 5683 3.112212790180691754858996627458294E-3422 1.556106395090345877429498313729147E-3422 + 5684 7.780531975451729387147491568645735E-3423 3.890265987725864693573745784322868E-3423 + 5685 1.945132993862932346786872892161434E-3423 9.72566496931466173393436446080717E-3424 + 5686 4.862832484657330866967182230403585E-3424 2.431416242328665433483591115201793E-3424 + 5687 1.215708121164332716741795557600897E-3424 6.078540605821663583708977788004483E-3425 + 5688 3.039270302910831791854488894002242E-3425 1.519635151455415895927244447001121E-3425 + 5689 7.598175757277079479636222235005605E-3426 3.799087878638539739818111117502803E-3426 + 5690 1.899543939319269869909055558751402E-3426 9.497719696596349349545277793757008E-3427 + 5691 4.748859848298174674772638896878504E-3427 2.374429924149087337386319448439252E-3427 + 5692 1.187214962074543668693159724219626E-3427 5.93607481037271834346579862109813E-3428 + 5693 2.968037405186359171732899310549065E-3428 1.484018702593179585866449655274533E-3428 + 5694 7.420093512965897929332248276372665E-3429 3.710046756482948964666124138186333E-3429 + 5695 1.855023378241474482333062069093167E-3429 9.275116891207372411665310345465833E-3430 + 5696 4.637558445603686205832655172732917E-3430 2.318779222801843102916327586366458E-3430 + 5697 1.159389611400921551458163793183229E-3430 5.796948057004607757290818965916145E-3431 + 5698 2.898474028502303878645409482958073E-3431 1.449237014251151939322704741479036E-3431 + 5699 7.24618507125575969661352370739518E-3432 3.62309253562787984830676185369759E-3432 + 5700 1.811546267813939924153380926848795E-3432 9.057731339069699620766904634243975E-3433 + 5701 4.528865669534849810383452317121988E-3433 2.264432834767424905191726158560994E-3433 + 5702 1.132216417383712452595863079280497E-3433 5.661082086918562262979315396402485E-3434 + 5703 2.830541043459281131489657698201243E-3434 1.415270521729640565744828849100621E-3434 + 5704 7.076352608648202828724144245503105E-3435 3.538176304324101414362072122751553E-3435 + 5705 1.769088152162050707181036061375777E-3435 8.845440760810253535905180306878883E-3436 + 5706 4.422720380405126767952590153439442E-3436 2.211360190202563383976295076719721E-3436 + 5707 1.105680095101281691988147538359861E-3436 5.528400475506408459940737691799303E-3437 + 5708 2.764200237753204229970368845899652E-3437 1.382100118876602114985184422949826E-3437 + 5709 6.91050059438301057492592211474913E-3438 3.455250297191505287462961057374565E-3438 + 5710 1.727625148595752643731480528687283E-3438 8.638125742978763218657402643436413E-3439 + 5711 4.319062871489381609328701321718207E-3439 2.159531435744690804664350660859103E-3439 + 5712 1.079765717872345402332175330429552E-3439 5.398828589361727011660876652147758E-3440 + 5713 2.699414294680863505830438326073879E-3440 1.349707147340431752915219163036940E-3440 + 5714 6.74853573670215876457609581518470E-3441 3.37426786835107938228804790759235E-3441 + 5715 1.687133934175539691144023953796175E-3441 8.435669670877698455720119768980875E-3442 + 5716 4.217834835438849227860059884490438E-3442 2.108917417719424613930029942245219E-3442 + 5717 1.054458708859712306965014971122610E-3442 5.272293544298561534825074855613048E-3443 + 5718 2.636146772149280767412537427806524E-3443 1.318073386074640383706268713903262E-3443 + 5719 6.59036693037320191853134356951631E-3444 3.295183465186600959265671784758155E-3444 + 5720 1.647591732593300479632835892379078E-3444 8.237958662966502398164179461895388E-3445 + 5721 4.118979331483251199082089730947694E-3445 2.059489665741625599541044865473847E-3445 + 5722 1.029744832870812799770522432736924E-3445 5.148724164354063998852612163684618E-3446 + 5723 2.574362082177031999426306081842309E-3446 1.287181041088515999713153040921155E-3446 + 5724 6.435905205442579998565765204605775E-3447 3.217952602721289999282882602302888E-3447 + 5725 1.608976301360644999641441301151444E-3447 8.04488150680322499820720650575722E-3448 + 5726 4.02244075340161249910360325287861E-3448 2.011220376700806249551801626439305E-3448 + 5727 1.005610188350403124775900813219653E-3448 5.028050941752015623879504066098263E-3449 + 5728 2.514025470876007811939752033049132E-3449 1.257012735438003905969876016524566E-3449 + 5729 6.28506367719001952984938008262283E-3450 3.142531838595009764924690041311415E-3450 + 5730 1.571265919297504882462345020655708E-3450 7.856329596487524412311725103278538E-3451 + 5731 3.928164798243762206155862551639269E-3451 1.964082399121881103077931275819635E-3451 + 5732 9.820411995609405515389656379098175E-3452 4.910205997804702757694828189549088E-3452 + 5733 2.455102998902351378847414094774544E-3452 1.227551499451175689423707047387272E-3452 + 5734 6.13775749725587844711853523693636E-3453 3.06887874862793922355926761846818E-3453 + 5735 1.53443937431396961177963380923409E-3453 7.67219687156984805889816904617045E-3454 + 5736 3.836098435784924029449084523085225E-3454 1.918049217892462014724542261542613E-3454 + 5737 9.590246089462310073622711307713065E-3455 4.795123044731155036811355653856533E-3455 + 5738 2.397561522365577518405677826928267E-3455 1.198780761182788759202838913464133E-3455 + 5739 5.993903805913943796014194567320665E-3456 2.996951902956971898007097283660333E-3456 + 5740 1.498475951478485949003548641830167E-3456 7.492379757392429745017743209150833E-3457 + 5741 3.746189878696214872508871604575417E-3457 1.873094939348107436254435802287708E-3457 + 5742 9.36547469674053718127217901143854E-3458 4.68273734837026859063608950571927E-3458 + 5743 2.341368674185134295318044752859635E-3458 1.170684337092567147659022376429818E-3458 + 5744 5.85342168546283573829511188214909E-3459 2.926710842731417869147555941074545E-3459 + 5745 1.463355421365708934573777970537273E-3459 7.316777106828544672868889852686363E-3460 + 5746 3.658388553414272336434444926343182E-3460 1.829194276707136168217222463171591E-3460 + 5747 9.145971383535680841086112315857955E-3461 4.572985691767840420543056157928978E-3461 + 5748 2.286492845883920210271528078964489E-3461 1.143246422941960105135764039482245E-3461 + 5749 5.716232114709800525678820197411225E-3462 2.858116057354900262839410098705613E-3462 + 5750 1.429058028677450131419705049352807E-3462 7.145290143387250657098525246764033E-3463 + 5751 3.572645071693625328549262623382017E-3463 1.786322535846812664274631311691008E-3463 + 5752 8.93161267923406332137315655845504E-3464 4.46580633961703166068657827922752E-3464 + 5753 2.23290316980851583034328913961376E-3464 1.11645158490425791517164456980688E-3464 + 5754 5.5822579245212895758582228490344E-3465 2.7911289622606447879291114245172E-3465 + 5755 1.3955644811303223939645557122586E-3465 6.977822405651611969822778561293E-3466 + 5756 3.4889112028258059849113892806465E-3466 1.74445560141290299245569464032325E-3466 + 5757 8.72227800706451496227847320161625E-3467 4.361139003532257481139236600808125E-3467 + 5758 2.180569501766128740569618300404063E-3467 1.090284750883064370284809150202031E-3467 + 5759 5.451423754415321851424045751010155E-3468 2.725711877207660925712022875505078E-3468 + 5760 1.362855938603830462856011437752539E-3468 6.814279693019152314280057188762695E-3469 + 5761 3.407139846509576157140028594381348E-3469 1.703569923254788078570014297190674E-3469 + 5762 8.51784961627394039285007148595337E-3470 4.258924808136970196425035742976685E-3470 + 5763 2.129462404068485098212517871488343E-3470 1.064731202034242549106258935744171E-3470 + 5764 5.323656010171212745531294678720855E-3471 2.661828005085606372765647339360428E-3471 + 5765 1.330914002542803186382823669680214E-3471 6.65457001271401593191411834840107E-3472 + 5766 3.327285006357007965957059174200535E-3472 1.663642503178503982978529587100268E-3472 + 5767 8.31821251589251991489264793550134E-3473 4.15910625794625995744632396775067E-3473 + 5768 2.079553128973129978723161983875335E-3473 1.039776564486564989361580991937668E-3473 + 5769 5.19888282243282494680790495968834E-3474 2.59944141121641247340395247984417E-3474 + 5770 1.299720705608206236701976239922085E-3474 6.498603528041031183509881199610425E-3475 + 5771 3.249301764020515591754940599805213E-3475 1.624650882010257795877470299902606E-3475 + 5772 8.12325441005128897938735149951303E-3476 4.061627205025644489693675749756515E-3476 + 5773 2.030813602512822244846837874878258E-3476 1.015406801256411122423418937439129E-3476 + 5774 5.077034006282055612117094687195645E-3477 2.538517003141027806058547343597823E-3477 + 5775 1.269258501570513903029273671798912E-3477 6.346292507852569515146368358994558E-3478 + 5776 3.173146253926284757573184179497279E-3478 1.586573126963142378786592089748640E-3478 + 5777 7.93286563481571189393296044874320E-3479 3.96643281740785594696648022437160E-3479 + 5778 1.98321640870392797348324011218580E-3479 9.9160820435196398674162005609290E-3480 + 5779 4.9580410217598199337081002804645E-3480 2.47902051087990996685405014023225E-3480 + 5780 1.239510255439954983427025070116125E-3480 6.197551277199774917135125350580625E-3481 + 5781 3.098775638599887458567562675290313E-3481 1.549387819299943729283781337645156E-3481 + 5782 7.74693909649971864641890668822578E-3482 3.87346954824985932320945334411289E-3482 + 5783 1.936734774124929661604726672056445E-3482 9.683673870624648308023633360282225E-3483 + 5784 4.841836935312324154011816680141113E-3483 2.420918467656162077005908340070556E-3483 + 5785 1.210459233828081038502954170035278E-3483 6.05229616914040519251477085017639E-3484 + 5786 3.026148084570202596257385425088195E-3484 1.513074042285101298128692712544098E-3484 + 5787 7.56537021142550649064346356272049E-3485 3.782685105712753245321731781360245E-3485 + 5788 1.891342552856376622660865890680123E-3485 9.456712764281883113304329453400613E-3486 + 5789 4.728356382140941556652164726700307E-3486 2.364178191070470778326082363350153E-3486 + 5790 1.182089095535235389163041181675077E-3486 5.910445477676176945815205908375383E-3487 + 5791 2.955222738838088472907602954187692E-3487 1.477611369419044236453801477093846E-3487 + 5792 7.38805684709522118226900738546923E-3488 3.694028423547610591134503692734615E-3488 + 5793 1.847014211773805295567251846367308E-3488 9.235071058869026477836259231836538E-3489 + 5794 4.617535529434513238918129615918269E-3489 2.308767764717256619459064807959135E-3489 + 5795 1.154383882358628309729532403979568E-3489 5.771919411793141548647662019897838E-3490 + 5796 2.885959705896570774323831009948919E-3490 1.442979852948285387161915504974460E-3490 + 5797 7.21489926474142693580957752487230E-3491 3.60744963237071346790478876243615E-3491 + 5798 1.803724816185356733952394381218075E-3491 9.018624080926783669761971906090375E-3492 + 5799 4.509312040463391834880985953045188E-3492 2.254656020231695917440492976522594E-3492 + 5800 1.127328010115847958720246488261297E-3492 5.636640050579239793601232441306485E-3493 + 5801 2.818320025289619896800616220653243E-3493 1.409160012644809948400308110326621E-3493 + 5802 7.045800063224049742001540551633105E-3494 3.522900031612024871000770275816553E-3494 + 5803 1.761450015806012435500385137908277E-3494 8.807250079030062177501925689541383E-3495 + 5804 4.403625039515031088750962844770692E-3495 2.201812519757515544375481422385346E-3495 + 5805 1.100906259878757772187740711192673E-3495 5.504531299393788860938703555963365E-3496 + 5806 2.752265649696894430469351777981683E-3496 1.376132824848447215234675888990841E-3496 + 5807 6.880664124242236076173379444954205E-3497 3.440332062121118038086689722477103E-3497 + 5808 1.720166031060559019043344861238552E-3497 8.600830155302795095216724306192758E-3498 + 5809 4.300415077651397547608362153096379E-3498 2.150207538825698773804181076548190E-3498 + 5810 1.075103769412849386902090538274095E-3498 5.375518847064246934510452691370475E-3499 + 5811 2.687759423532123467255226345685238E-3499 1.343879711766061733627613172842619E-3499 + 5812 6.719398558830308668138065864213095E-3500 3.359699279415154334069032932106548E-3500 + 5813 1.679849639707577167034516466053274E-3500 8.39924819853788583517258233026637E-3501 + 5814 4.199624099268942917586291165133185E-3501 2.099812049634471458793145582566593E-3501 + 5815 1.049906024817235729396572791283297E-3501 5.249530124086178646982863956416483E-3502 + 5816 2.624765062043089323491431978208242E-3502 1.312382531021544661745715989104121E-3502 + 5817 6.561912655107723308728579945520605E-3503 3.280956327553861654364289972760303E-3503 + 5818 1.640478163776930827182144986380152E-3503 8.202390818884654135910724931900758E-3504 + 5819 4.101195409442327067955362465950379E-3504 2.050597704721163533977681232975190E-3504 + 5820 1.025298852360581766988840616487595E-3504 5.126494261802908834944203082437975E-3505 + 5821 2.563247130901454417472101541218988E-3505 1.281623565450727208736050770609494E-3505 + 5822 6.40811782725363604368025385304747E-3506 3.204058913626818021840126926523735E-3506 + 5823 1.602029456813409010920063463261868E-3506 8.010147284067045054600317316309338E-3507 + 5824 4.005073642033522527300158658154669E-3507 2.002536821016761263650079329077335E-3507 + 5825 1.001268410508380631825039664538668E-3507 5.006342052541903159125198322693338E-3508 + 5826 2.503171026270951579562599161346669E-3508 1.251585513135475789781299580673335E-3508 + 5827 6.257927565677378948906497903366675E-3509 3.128963782838689474453248951683338E-3509 + 5828 1.564481891419344737226624475841669E-3509 7.822409457096723686133122379208345E-3510 + 5829 3.911204728548361843066561189604173E-3510 1.955602364274180921533280594802086E-3510 + 5830 9.77801182137090460766640297401043E-3511 4.889005910685452303833201487005215E-3511 + 5831 2.444502955342726151916600743502608E-3511 1.222251477671363075958300371751304E-3511 + 5832 6.11125738835681537979150185875652E-3512 3.05562869417840768989575092937826E-3512 + 5833 1.52781434708920384494787546468913E-3512 7.63907173544601922473937732344565E-3513 + 5834 3.819535867723009612369688661722825E-3513 1.909767933861504806184844330861413E-3513 + 5835 9.548839669307524030924221654307065E-3514 4.774419834653762015462110827153533E-3514 + 5836 2.387209917326881007731055413576767E-3514 1.193604958663440503865527706788383E-3514 + 5837 5.968024793317202519327638533941915E-3515 2.984012396658601259663819266970958E-3515 + 5838 1.492006198329300629831909633485479E-3515 7.460030991646503149159548167427395E-3516 + 5839 3.730015495823251574579774083713698E-3516 1.865007747911625787289887041856849E-3516 + 5840 9.325038739558128936449435209284245E-3517 4.662519369779064468224717604642123E-3517 + 5841 2.331259684889532234112358802321062E-3517 1.165629842444766117056179401160531E-3517 + 5842 5.828149212223830585280897005802655E-3518 2.914074606111915292640448502901328E-3518 + 5843 1.457037303055957646320224251450664E-3518 7.28518651527978823160112125725332E-3519 + 5844 3.64259325763989411580056062862666E-3519 1.82129662881994705790028031431333E-3519 + 5845 9.10648314409973528950140157156665E-3520 4.553241572049867644750700785783325E-3520 + 5846 2.276620786024933822375350392891663E-3520 1.138310393012466911187675196445831E-3520 + 5847 5.691551965062334555938375982229155E-3521 2.845775982531167277969187991114578E-3521 + 5848 1.422887991265583638984593995557289E-3521 7.114439956327918194922969977786445E-3522 + 5849 3.557219978163959097461484988893223E-3522 1.778609989081979548730742494446611E-3522 + 5850 8.893049945409897743653712472233055E-3523 4.446524972704948871826856236116528E-3523 + 5851 2.223262486352474435913428118058264E-3523 1.111631243176237217956714059029132E-3523 + 5852 5.55815621588118608978357029514566E-3524 2.77907810794059304489178514757283E-3524 + 5853 1.389539053970296522445892573786415E-3524 6.947695269851482612229462868932075E-3525 + 5854 3.473847634925741306114731434466038E-3525 1.736923817462870653057365717233019E-3525 + 5855 8.684619087314353265286828586165095E-3526 4.342309543657176632643414293082548E-3526 + 5856 2.171154771828588316321707146541274E-3526 1.085577385914294158160853573270637E-3526 + 5857 5.427886929571470790804267866353185E-3527 2.713943464785735395402133933176593E-3527 + 5858 1.356971732392867697701066966588297E-3527 6.784858661964338488505334832941483E-3528 + 5859 3.392429330982169244252667416470742E-3528 1.696214665491084622126333708235371E-3528 + 5860 8.481073327455423110631668541176855E-3529 4.240536663727711555315834270588428E-3529 + 5861 2.120268331863855777657917135294214E-3529 1.060134165931927888828958567647107E-3529 + 5862 5.300670829659639444144792838235535E-3530 2.650335414829819722072396419117768E-3530 + 5863 1.325167707414909861036198209558884E-3530 6.62583853707454930518099104779442E-3531 + 5864 3.31291926853727465259049552389721E-3531 1.656459634268637326295247761948605E-3531 + 5865 8.282298171343186631476238809743025E-3532 4.141149085671593315738119404871513E-3532 + 5866 2.070574542835796657869059702435757E-3532 1.035287271417898328934529851217878E-3532 + 5867 5.17643635708949164467264925608939E-3533 2.588218178544745822336324628044695E-3533 + 5868 1.294109089272372911168162314022348E-3533 6.470545446361864555840811570111738E-3534 + 5869 3.235272723180932277920405785055869E-3534 1.617636361590466138960202892527935E-3534 + 5870 8.088181807952330694801014462639675E-3535 4.044090903976165347400507231319838E-3535 + 5871 2.022045451988082673700253615659919E-3535 1.011022725994041336850126807829960E-3535 + 5872 5.05511362997020668425063403914980E-3536 2.52755681498510334212531701957490E-3536 + 5873 1.26377840749255167106265850978745E-3536 6.31889203746275835531329254893725E-3537 + 5874 3.159446018731379177656646274468625E-3537 1.579723009365689588828323137234313E-3537 + 5875 7.898615046828447944141615686171565E-3538 3.949307523414223972070807843085783E-3538 + 5876 1.974653761707111986035403921542892E-3538 9.873268808535559930177019607714458E-3539 + 5877 4.936634404267779965088509803857229E-3539 2.468317202133889982544254901928615E-3539 + 5878 1.234158601066944991272127450964308E-3539 6.170793005334724956360637254821538E-3540 + 5879 3.085396502667362478180318627410769E-3540 1.542698251333681239090159313705385E-3540 + 5880 7.713491256668406195450796568526925E-3541 3.856745628334203097725398284263463E-3541 + 5881 1.928372814167101548862699142131732E-3541 9.641864070835507744313495710658658E-3542 + 5882 4.820932035417753872156747855329329E-3542 2.410466017708876936078373927664665E-3542 + 5883 1.205233008854438468039186963832333E-3542 6.026165044272192340195934819161663E-3543 + 5884 3.013082522136096170097967409580832E-3543 1.506541261068048085048983704790416E-3543 + 5885 7.53270630534024042524491852395208E-3544 3.76635315267012021262245926197604E-3544 + 5886 1.88317657633506010631122963098802E-3544 9.4158828816753005315561481549401E-3545 + 5887 4.70794144083765026577807407747005E-3545 2.353970720418825132889037038735025E-3545 + 5888 1.176985360209412566444518519367513E-3545 5.884926801047062832222592596837563E-3546 + 5889 2.942463400523531416111296298418782E-3546 1.471231700261765708055648149209391E-3546 + 5890 7.356158501308828540278240746046955E-3547 3.678079250654414270139120373023478E-3547 + 5891 1.839039625327207135069560186511739E-3547 9.195198126636035675347800932558695E-3548 + 5892 4.597599063318017837673900466279348E-3548 2.298799531659008918836950233139674E-3548 + 5893 1.149399765829504459418475116569837E-3548 5.746998829147522297092375582849185E-3549 + 5894 2.873499414573761148546187791424593E-3549 1.436749707286880574273093895712296E-3549 + 5895 7.18374853643440287136546947856148E-3550 3.59187426821720143568273473928074E-3550 + 5896 1.79593713410860071784136736964037E-3550 8.97968567054300358920683684820185E-3551 + 5897 4.489842835271501794603418424100925E-3551 2.244921417635750897301709212050463E-3551 + 5898 1.122460708817875448650854606025232E-3551 5.612303544089377243254273030126158E-3552 + 5899 2.806151772044688621627136515063079E-3552 1.403075886022344310813568257531540E-3552 + 5900 7.01537943011172155406784128765770E-3553 3.50768971505586077703392064382885E-3553 + 5901 1.753844857527930388516960321914425E-3553 8.769224287639651942584801609572125E-3554 + 5902 4.384612143819825971292400804786063E-3554 2.192306071909912985646200402393031E-3554 + 5903 1.096153035954956492823100201196516E-3554 5.480765179774782464115501005982578E-3555 + 5904 2.740382589887391232057750502991289E-3555 1.370191294943695616028875251495645E-3555 + 5905 6.850956474718478080144376257478225E-3556 3.425478237359239040072188128739113E-3556 + 5906 1.712739118679619520036094064369557E-3556 8.563695593398097600180470321847783E-3557 + 5907 4.281847796699048800090235160923892E-3557 2.140923898349524400045117580461946E-3557 + 5908 1.070461949174762200022558790230973E-3557 5.352309745873811000112793951154865E-3558 + 5909 2.676154872936905500056396975577433E-3558 1.338077436468452750028198487788716E-3558 + 5910 6.69038718234226375014099243894358E-3559 3.34519359117113187507049621947179E-3559 + 5911 1.672596795585565937535248109735895E-3559 8.362983977927829687676240548679475E-3560 + 5912 4.181491988963914843838120274339738E-3560 2.090745994481957421919060137169869E-3560 + 5913 1.045372997240978710959530068584935E-3560 5.226864986204893554797650342924673E-3561 + 5914 2.613432493102446777398825171462337E-3561 1.306716246551223388699412585731168E-3561 + 5915 6.53358123275611694349706292865584E-3562 3.26679061637805847174853146432792E-3562 + 5916 1.63339530818902923587426573216396E-3562 8.1669765409451461793713286608198E-3563 + 5917 4.0834882704725730896856643304099E-3563 2.04174413523628654484283216520495E-3563 + 5918 1.020872067618143272421416082602475E-3563 5.104360338090716362107080413012375E-3564 + 5919 2.552180169045358181053540206506188E-3564 1.276090084522679090526770103253094E-3564 + 5920 6.38045042261339545263385051626547E-3565 3.190225211306697726316925258132735E-3565 + 5921 1.595112605653348863158462629066368E-3565 7.975563028266744315792313145331838E-3566 + 5922 3.987781514133372157896156572665919E-3566 1.993890757066686078948078286332960E-3566 + 5923 9.96945378533343039474039143166480E-3567 4.98472689266671519737019571583240E-3567 + 5924 2.49236344633335759868509785791620E-3567 1.24618172316667879934254892895810E-3567 + 5925 6.2309086158333939967127446447905E-3568 3.11545430791669699835637232239525E-3568 + 5926 1.557727153958348499178186161197625E-3568 7.788635769791742495890930805988125E-3569 + 5927 3.894317884895871247945465402994063E-3569 1.947158942447935623972732701497031E-3569 + 5928 9.735794712239678119863663507485155E-3570 4.867897356119839059931831753742578E-3570 + 5929 2.433948678059919529965915876871289E-3570 1.216974339029959764982957938435645E-3570 + 5930 6.084871695149798824914789692178225E-3571 3.042435847574899412457394846089113E-3571 + 5931 1.521217923787449706228697423044557E-3571 7.606089618937248531143487115222783E-3572 + 5932 3.803044809468624265571743557611392E-3572 1.901522404734312132785871778805696E-3572 + 5933 9.50761202367156066392935889402848E-3573 4.75380601183578033196467944701424E-3573 + 5934 2.37690300591789016598233972350712E-3573 1.18845150295894508299116986175356E-3573 + 5935 5.9422575147947254149558493087678E-3574 2.9711287573973627074779246543839E-3574 + 5936 1.48556437869868135373896232719195E-3574 7.42782189349340676869481163595975E-3575 + 5937 3.713910946746703384347405817979875E-3575 1.856955473373351692173702908989938E-3575 + 5938 9.28477736686675846086851454494969E-3576 4.642388683433379230434257272474845E-3576 + 5939 2.321194341716689615217128636237423E-3576 1.160597170858344807608564318118711E-3576 + 5940 5.802985854291724038042821590593555E-3577 2.901492927145862019021410795296778E-3577 + 5941 1.450746463572931009510705397648389E-3577 7.253732317864655047553526988241945E-3578 + 5942 3.626866158932327523776763494120973E-3578 1.813433079466163761888381747060486E-3578 + 5943 9.06716539733081880944190873530243E-3579 4.533582698665409404720954367651215E-3579 + 5944 2.266791349332704702360477183825608E-3579 1.133395674666352351180238591912804E-3579 + 5945 5.66697837333176175590119295956402E-3580 2.83348918666588087795059647978201E-3580 + 5946 1.416744593332940438975298239891005E-3580 7.083722966664702194876491199455025E-3581 + 5947 3.541861483332351097438245599727513E-3581 1.770930741666175548719122799863756E-3581 + 5948 8.85465370833087774359561399931878E-3582 4.42732685416543887179780699965939E-3582 + 5949 2.213663427082719435898903499829695E-3582 1.106831713541359717949451749914848E-3582 + 5950 5.53415856770679858974725874957424E-3583 2.76707928385339929487362937478712E-3583 + 5951 1.38353964192669964743681468739356E-3583 6.9176982096334982371840734369678E-3584 + 5952 3.4588491048167491185920367184839E-3584 1.72942455240837455929601835924195E-3584 + 5953 8.64712276204187279648009179620975E-3585 4.323561381020936398240045898104875E-3585 + 5954 2.161780690510468199120022949052438E-3585 1.080890345255234099560011474526219E-3585 + 5955 5.404451726276170497800057372631095E-3586 2.702225863138085248900028686315548E-3586 + 5956 1.351112931569042624450014343157774E-3586 6.75556465784521312225007171578887E-3587 + 5957 3.377782328922606561125035857894435E-3587 1.688891164461303280562517928947218E-3587 + 5958 8.44445582230651640281258964473609E-3588 4.222227911153258201406294822368045E-3588 + 5959 2.111113955576629100703147411184023E-3588 1.055556977788314550351573705592011E-3588 + 5960 5.277784888941572751757868527960055E-3589 2.638892444470786375878934263980028E-3589 + 5961 1.319446222235393187939467131990014E-3589 6.59723111117696593969733565995007E-3590 + 5962 3.298615555588482969848667829975035E-3590 1.649307777794241484924333914987518E-3590 + 5963 8.24653888897120742462166957493759E-3591 4.123269444485603712310834787468795E-3591 + 5964 2.061634722242801856155417393734398E-3591 1.030817361121400928077708696867199E-3591 + 5965 5.154086805607004640388543484335995E-3592 2.577043402803502320194271742167998E-3592 + 5966 1.288521701401751160097135871083999E-3592 6.442608507008755800485679355419995E-3593 + 5967 3.221304253504377900242839677709998E-3593 1.610652126752188950121419838854999E-3593 + 5968 8.053260633760944750607099194274995E-3594 4.026630316880472375303549597137498E-3594 + 5969 2.013315158440236187651774798568749E-3594 1.006657579220118093825887399284375E-3594 + 5970 5.033287896100590469129436996421875E-3595 2.516643948050295234564718498210938E-3595 + 5971 1.258321974025147617282359249105469E-3595 6.291609870125738086411796245527345E-3596 + 5972 3.145804935062869043205898122763673E-3596 1.572902467531434521602949061381836E-3596 + 5973 7.86451233765717260801474530690918E-3597 3.93225616882858630400737265345459E-3597 + 5974 1.966128084414293152003686326727295E-3597 9.830640422071465760018431633636475E-3598 + 5975 4.915320211035732880009215816818238E-3598 2.457660105517866440004607908409119E-3598 + 5976 1.228830052758933220002303954204560E-3598 6.144150263794666100011519771022798E-3599 + 5977 3.072075131897333050005759885511399E-3599 1.536037565948666525002879942755700E-3599 + 5978 7.68018782974333262501439971377850E-3600 3.84009391487166631250719985688925E-3600 + 5979 1.920046957435833156253599928444625E-3600 9.600234787179165781267999642223125E-3601 + 5980 4.800117393589582890633999821111563E-3601 2.400058696794791445316999910555781E-3601 + 5981 1.200029348397395722658499955277891E-3601 6.000146741986978613292499776389453E-3602 + 5982 3.000073370993489306646249888194727E-3602 1.500036685496744653323124944097363E-3602 + 5983 7.500183427483723266615624720486815E-3603 3.750091713741861633307812360243408E-3603 + 5984 1.875045856870930816653906180121704E-3603 9.37522928435465408326953090060852E-3604 + 5985 4.68761464217732704163476545030426E-3604 2.34380732108866352081738272515213E-3604 + 5986 1.171903660544331760408691362576065E-3604 5.859518302721658802043456812880325E-3605 + 5987 2.929759151360829401021728406440163E-3605 1.464879575680414700510864203220081E-3605 + 5988 7.324397878402073502554321016100405E-3606 3.662198939201036751277160508050203E-3606 + 5989 1.831099469600518375638580254025102E-3606 9.155497348002591878192901270125508E-3607 + 5990 4.577748674001295939096450635062754E-3607 2.288874337000647969548225317531377E-3607 + 5991 1.144437168500323984774112658765689E-3607 5.722185842501619923870563293828443E-3608 + 5992 2.861092921250809961935281646914222E-3608 1.430546460625404980967640823457111E-3608 + 5993 7.152732303127024904838204117285555E-3609 3.576366151563512452419102058642778E-3609 + 5994 1.788183075781756226209551029321389E-3609 8.940915378908781131047755146606945E-3610 + 5995 4.470457689454390565523877573303473E-3610 2.235228844727195282761938786651736E-3610 + 5996 1.117614422363597641380969393325868E-3610 5.58807211181798820690484696662934E-3611 + 5997 2.79403605590899410345242348331467E-3611 1.397018027954497051726211741657335E-3611 + 5998 6.985090139772485258631058708286675E-3612 3.492545069886242629315529354143338E-3612 + 5999 1.746272534943121314657764677071669E-3612 8.731362674715606573288823385358345E-3613 + 6000 4.365681337357803286644411692679173E-3613 2.182840668678901643322205846339586E-3613 + 6001 1.091420334339450821661102923169793E-3613 5.457101671697254108305514615848965E-3614 + 6002 2.728550835848627054152757307924483E-3614 1.364275417924313527076378653962241E-3614 + 6003 6.821377089621567635381893269811205E-3615 3.410688544810783817690946634905603E-3615 + 6004 1.705344272405391908845473317452802E-3615 8.526721362026959544227366587264008E-3616 + 6005 4.263360681013479772113683293632004E-3616 2.131680340506739886056841646816002E-3616 + 6006 1.065840170253369943028420823408001E-3616 5.329200851266849715142104117040005E-3617 + 6007 2.664600425633424857571052058520003E-3617 1.332300212816712428785526029260001E-3617 + 6008 6.661501064083562143927630146300005E-3618 3.330750532041781071963815073150003E-3618 + 6009 1.665375266020890535981907536575002E-3618 8.326876330104452679909537682875008E-3619 + 6010 4.163438165052226339954768841437504E-3619 2.081719082526113169977384420718752E-3619 + 6011 1.040859541263056584988692210359376E-3619 5.20429770631528292494346105179688E-3620 + 6012 2.60214885315764146247173052589844E-3620 1.30107442657882073123586526294922E-3620 + 6013 6.5053721328941036561793263147461E-3621 3.25268606644705182808966315737305E-3621 + 6014 1.626343033223525914044831578686525E-3621 8.131715166117629570224157893432625E-3622 + 6015 4.065857583058814785112078946716313E-3622 2.032928791529407392556039473358156E-3622 + 6016 1.016464395764703696278019736679078E-3622 5.08232197882351848139009868339539E-3623 + 6017 2.541160989411759240695049341697695E-3623 1.270580494705879620347524670848848E-3623 + 6018 6.35290247352939810173762335424424E-3624 3.17645123676469905086881167712212E-3624 + 6019 1.58822561838234952543440583856106E-3624 7.9411280919117476271720291928053E-3625 + 6020 3.97056404595587381358601459640265E-3625 1.985282022977936906793007298201325E-3625 + 6021 9.926410114889684533965036491006625E-3626 4.963205057444842266982518245503313E-3626 + 6022 2.481602528722421133491259122751657E-3626 1.240801264361210566745629561375828E-3626 + 6023 6.20400632180605283372814780687914E-3627 3.10200316090302641686407390343957E-3627 + 6024 1.551001580451513208432036951719785E-3627 7.755007902257566042160184758598925E-3628 + 6025 3.877503951128783021080092379299463E-3628 1.938751975564391510540046189649731E-3628 + 6026 9.693759877821957552700230948248655E-3629 4.846879938910978776350115474124328E-3629 + 6027 2.423439969455489388175057737062164E-3629 1.211719984727744694087528868531082E-3629 + 6028 6.05859992363872347043764434265541E-3630 3.029299961819361735218822171327705E-3630 + 6029 1.514649980909680867609411085663853E-3630 7.573249904548404338047055428319263E-3631 + 6030 3.786624952274202169023527714159632E-3631 1.893312476137101084511763857079816E-3631 + 6031 9.46656238068550542255881928539908E-3632 4.73328119034275271127940964269954E-3632 + 6032 2.36664059517137635563970482134977E-3632 1.183320297585688177819852410674885E-3632 + 6033 5.916601487928440889099262053374425E-3633 2.958300743964220444549631026687213E-3633 + 6034 1.479150371982110222274815513343607E-3633 7.395751859910551111374077566718033E-3634 + 6035 3.697875929955275555687038783359017E-3634 1.848937964977637777843519391679508E-3634 + 6036 9.24468982488818888921759695839754E-3635 4.62234491244409444460879847919877E-3635 + 6037 2.311172456222047222304399239599385E-3635 1.155586228111023611152199619799693E-3635 + 6038 5.777931140555118055760998098998465E-3636 2.888965570277559027880499049499233E-3636 + 6039 1.444482785138779513940249524749617E-3636 7.222413925693897569701247623748083E-3637 + 6040 3.611206962846948784850623811874042E-3637 1.805603481423474392425311905937021E-3637 + 6041 9.028017407117371962126559529685105E-3638 4.514008703558685981063279764842553E-3638 + 6042 2.257004351779342990531639882421277E-3638 1.128502175889671495265819941210638E-3638 + 6043 5.64251087944835747632909970605319E-3639 2.821255439724178738164549853026595E-3639 + 6044 1.410627719862089369082274926513298E-3639 7.053138599310446845411374632566488E-3640 + 6045 3.526569299655223422705687316283244E-3640 1.763284649827611711352843658141622E-3640 + 6046 8.81642324913805855676421829070811E-3641 4.408211624569029278382109145354055E-3641 + 6047 2.204105812284514639191054572677028E-3641 1.102052906142257319595527286338514E-3641 + 6048 5.51026453071128659797763643169257E-3642 2.755132265355643298988818215846285E-3642 + 6049 1.377566132677821649494409107923143E-3642 6.887830663389108247472045539615713E-3643 + 6050 3.443915331694554123736022769807857E-3643 1.721957665847277061868011384903928E-3643 + 6051 8.60978832923638530934005692451964E-3644 4.30489416461819265467002846225982E-3644 + 6052 2.15244708230909632733501423112991E-3644 1.076223541154548163667507115564955E-3644 + 6053 5.381117705772740818337535577824775E-3645 2.690558852886370409168767788912388E-3645 + 6054 1.345279426443185204584383894456194E-3645 6.72639713221592602292191947228097E-3646 + 6055 3.363198566107963011460959736140485E-3646 1.681599283053981505730479868070243E-3646 + 6056 8.407996415269907528652399340351215E-3647 4.203998207634953764326199670175608E-3647 + 6057 2.101999103817476882163099835087804E-3647 1.050999551908738441081549917543902E-3647 + 6058 5.25499775954369220540774958771951E-3648 2.627498879771846102703874793859755E-3648 + 6059 1.313749439885923051351937396929878E-3648 6.568747199429615256759686984649388E-3649 + 6060 3.284373599714807628379843492324694E-3649 1.642186799857403814189921746162347E-3649 + 6061 8.210933999287019070949608730811735E-3650 4.105466999643509535474804365405868E-3650 + 6062 2.052733499821754767737402182702934E-3650 1.026366749910877383868701091351467E-3650 + 6063 5.131833749554386919343505456757335E-3651 2.565916874777193459671752728378668E-3651 + 6064 1.282958437388596729835876364189334E-3651 6.41479218694298364917938182094667E-3652 + 6065 3.207396093471491824589690910473335E-3652 1.603698046735745912294845455236668E-3652 + 6066 8.01849023367872956147422727618334E-3653 4.00924511683936478073711363809167E-3653 + 6067 2.004622558419682390368556819045835E-3653 1.002311279209841195184278409522918E-3653 + 6068 5.01155639604920597592139204761459E-3654 2.505778198024602987960696023807295E-3654 + 6069 1.252889099012301493980348011903648E-3654 6.264445495061507469901740059518238E-3655 + 6070 3.132222747530753734950870029759119E-3655 1.566111373765376867475435014879560E-3655 + 6071 7.83055686882688433737717507439780E-3656 3.91527843441344216868858753719890E-3656 + 6072 1.95763921720672108434429376859945E-3656 9.78819608603360542172146884299725E-3657 + 6073 4.894098043016802710860734421498625E-3657 2.447049021508401355430367210749313E-3657 + 6074 1.223524510754200677715183605374657E-3657 6.117622553771003388575918026873283E-3658 + 6075 3.058811276885501694287959013436642E-3658 1.529405638442750847143979506718321E-3658 + 6076 7.647028192213754235719897533591605E-3659 3.823514096106877117859948766795803E-3659 + 6077 1.911757048053438558929974383397902E-3659 9.558785240267192794649871916989508E-3660 + 6078 4.779392620133596397324935958494754E-3660 2.389696310066798198662467979247377E-3660 + 6079 1.194848155033399099331233989623689E-3660 5.974240775166995496656169948118443E-3661 + 6080 2.987120387583497748328084974059222E-3661 1.493560193791748874164042487029611E-3661 + 6081 7.467800968958744370820212435148055E-3662 3.733900484479372185410106217574028E-3662 + 6082 1.866950242239686092705053108787014E-3662 9.33475121119843046352526554393507E-3663 + 6083 4.667375605599215231762632771967535E-3663 2.333687802799607615881316385983768E-3663 + 6084 1.166843901399803807940658192991884E-3663 5.83421950699901903970329096495942E-3664 + 6085 2.91710975349950951985164548247971E-3664 1.458554876749754759925822741239855E-3664 + 6086 7.292774383748773799629113706199275E-3665 3.646387191874386899814556853099638E-3665 + 6087 1.823193595937193449907278426549819E-3665 9.115967979685967249536392132749095E-3666 + 6088 4.557983989842983624768196066374548E-3666 2.278991994921491812384098033187274E-3666 + 6089 1.139495997460745906192049016593637E-3666 5.697479987303729530960245082968185E-3667 + 6090 2.848739993651864765480122541484093E-3667 1.424369996825932382740061270742046E-3667 + 6091 7.12184998412966191370030635371023E-3668 3.560924992064830956850153176855115E-3668 + 6092 1.780462496032415478425076588427558E-3668 8.902312480162077392125382942137788E-3669 + 6093 4.451156240081038696062691471068894E-3669 2.225578120040519348031345735534447E-3669 + 6094 1.112789060020259674015672867767224E-3669 5.563945300101298370078364338836118E-3670 + 6095 2.781972650050649185039182169418059E-3670 1.390986325025324592519591084709030E-3670 + 6096 6.95493162512662296259795542354515E-3671 3.477465812563311481298977711772575E-3671 + 6097 1.738732906281655740649488855886288E-3671 8.693664531408278703247444279431438E-3672 + 6098 4.346832265704139351623722139715719E-3672 2.173416132852069675811861069857860E-3672 + 6099 1.086708066426034837905930534928930E-3672 5.43354033213017418952965267464465E-3673 + 6100 2.716770166065087094764826337322325E-3673 1.358385083032543547382413168661163E-3673 + 6101 6.791925415162717736912065843305815E-3674 3.395962707581358868456032921652908E-3674 + 6102 1.697981353790679434228016460826454E-3674 8.48990676895339717114008230413227E-3675 + 6103 4.244953384476698585570041152066135E-3675 2.122476692238349292785020576033068E-3675 + 6104 1.061238346119174646392510288016534E-3675 5.30619173059587323196255144008267E-3676 + 6105 2.653095865297936615981275720041335E-3676 1.326547932648968307990637860020668E-3676 + 6106 6.63273966324484153995318930010334E-3677 3.31636983162242076997659465005167E-3677 + 6107 1.658184915811210384988297325025835E-3677 8.290924579056051924941486625129175E-3678 + 6108 4.145462289528025962470743312564588E-3678 2.072731144764012981235371656282294E-3678 + 6109 1.036365572382006490617685828141147E-3678 5.181827861910032453088429140705735E-3679 + 6110 2.590913930955016226544214570352868E-3679 1.295456965477508113272107285176434E-3679 + 6111 6.47728482738754056636053642588217E-3680 3.238642413693770283180268212941085E-3680 + 6112 1.619321206846885141590134106470543E-3680 8.096606034234425707950670532352713E-3681 + 6113 4.048303017117212853975335266176357E-3681 2.024151508558606426987667633088178E-3681 + 6114 1.012075754279303213493833816544089E-3681 5.060378771396516067469169082720445E-3682 + 6115 2.530189385698258033734584541360223E-3682 1.265094692849129016867292270680111E-3682 + 6116 6.325473464245645084336461353400555E-3683 3.162736732122822542168230676700278E-3683 + 6117 1.581368366061411271084115338350139E-3683 7.906841830307056355420576691750695E-3684 + 6118 3.953420915153528177710288345875348E-3684 1.976710457576764088855144172937674E-3684 + 6119 9.88355228788382044427572086468837E-3685 4.941776143941910222137860432344185E-3685 + 6120 2.470888071970955111068930216172093E-3685 1.235444035985477555534465108086046E-3685 + 6121 6.17722017992738777767232554043023E-3686 3.088610089963693888836162770215115E-3686 + 6122 1.544305044981846944418081385107558E-3686 7.721525224909234722090406925537788E-3687 + 6123 3.860762612454617361045203462768894E-3687 1.930381306227308680522601731384447E-3687 + 6124 9.651906531136543402613008656922235E-3688 4.825953265568271701306504328461118E-3688 + 6125 2.412976632784135850653252164230559E-3688 1.206488316392067925326626082115280E-3688 + 6126 6.03244158196033962663313041057640E-3689 3.01622079098016981331656520528820E-3689 + 6127 1.50811039549008490665828260264410E-3689 7.5405519774504245332914130132205E-3690 + 6128 3.77027598872521226664570650661025E-3690 1.885137994362606133322853253305125E-3690 + 6129 9.425689971813030666614266266525625E-3691 4.712844985906515333307133133262813E-3691 + 6130 2.356422492953257666653566566631407E-3691 1.178211246476628833326783283315703E-3691 + 6131 5.891056232383144166633916416578515E-3692 2.945528116191572083316958208289258E-3692 + 6132 1.472764058095786041658479104144629E-3692 7.363820290478930208292395520723145E-3693 + 6133 3.681910145239465104146197760361573E-3693 1.840955072619732552073098880180786E-3693 + 6134 9.20477536309866276036549440090393E-3694 4.602387681549331380182747200451965E-3694 + 6135 2.301193840774665690091373600225983E-3694 1.150596920387332845045686800112991E-3694 + 6136 5.752984601936664225228434000564955E-3695 2.876492300968332112614217000282478E-3695 + 6137 1.438246150484166056307108500141239E-3695 7.191230752420830281535542500706195E-3696 + 6138 3.595615376210415140767771250353098E-3696 1.797807688105207570383885625176549E-3696 + 6139 8.989038440526037851919428125882745E-3697 4.494519220263018925959714062941373E-3697 + 6140 2.247259610131509462979857031470687E-3697 1.123629805065754731489928515735343E-3697 + 6141 5.618149025328773657449642578676715E-3698 2.809074512664386828724821289338358E-3698 + 6142 1.404537256332193414362410644669179E-3698 7.022686281660967071812053223345895E-3699 + 6143 3.511343140830483535906026611672948E-3699 1.755671570415241767953013305836474E-3699 + 6144 8.77835785207620883976506652918237E-3700 4.389178926038104419882533264591185E-3700 + 6145 2.194589463019052209941266632295593E-3700 1.097294731509526104970633316147796E-3700 + 6146 5.48647365754763052485316658073898E-3701 2.74323682877381526242658329036949E-3701 + 6147 1.371618414386907631213291645184745E-3701 6.858092071934538156066458225923725E-3702 + 6148 3.429046035967269078033229112961863E-3702 1.714523017983634539016614556480931E-3702 + 6149 8.572615089918172695083072782404655E-3703 4.286307544959086347541536391202328E-3703 + 6150 2.143153772479543173770768195601164E-3703 1.071576886239771586885384097800582E-3703 + 6151 5.35788443119885793442692048900291E-3704 2.678942215599428967213460244501455E-3704 + 6152 1.339471107799714483606730122250728E-3704 6.697355538998572418033650611253638E-3705 + 6153 3.348677769499286209016825305626819E-3705 1.674338884749643104508412652813410E-3705 + 6154 8.37169442374821552254206326406705E-3706 4.185847211874107761271031632033525E-3706 + 6155 2.092923605937053880635515816016763E-3706 1.046461802968526940317757908008381E-3706 + 6156 5.232309014842634701588789540041905E-3707 2.616154507421317350794394770020953E-3707 + 6157 1.308077253710658675397197385010477E-3707 6.540386268553293376985986925052383E-3708 + 6158 3.270193134276646688492993462526192E-3708 1.635096567138323344246496731263096E-3708 + 6159 8.17548283569161672123248365631548E-3709 4.08774141784580836061624182815774E-3709 + 6160 2.04387070892290418030812091407887E-3709 1.021935354461452090154060457039435E-3709 + 6161 5.109676772307260450770302285197175E-3710 2.554838386153630225385151142598588E-3710 + 6162 1.277419193076815112692575571299294E-3710 6.38709596538407556346287785649647E-3711 + 6163 3.193547982692037781731438928248235E-3711 1.596773991346018890865719464124118E-3711 + 6164 7.98386995673009445432859732062059E-3712 3.991934978365047227164298660310295E-3712 + 6165 1.995967489182523613582149330155148E-3712 9.979837445912618067910746650775738E-3713 + 6166 4.989918722956309033955373325387869E-3713 2.494959361478154516977686662693935E-3713 + 6167 1.247479680739077258488843331346968E-3713 6.237398403695386292444216656734838E-3714 + 6168 3.118699201847693146222108328367419E-3714 1.559349600923846573111054164183710E-3714 + 6169 7.79674800461923286555527082091855E-3715 3.898374002309616432777635410459275E-3715 + 6170 1.949187001154808216388817705229638E-3715 9.745935005774041081944088526148188E-3716 + 6171 4.872967502887020540972044263074094E-3716 2.436483751443510270486022131537047E-3716 + 6172 1.218241875721755135243011065768524E-3716 6.091209378608775676215055328842618E-3717 + 6173 3.045604689304387838107527664421309E-3717 1.522802344652193919053763832210655E-3717 + 6174 7.614011723260969595268819161053275E-3718 3.807005861630484797634409580526638E-3718 + 6175 1.903502930815242398817204790263319E-3718 9.517514654076211994086023951316595E-3719 + 6176 4.758757327038105997043011975658298E-3719 2.379378663519052998521505987829149E-3719 + 6177 1.189689331759526499260752993914575E-3719 5.948446658797632496303764969572873E-3720 + 6178 2.974223329398816248151882484786437E-3720 1.487111664699408124075941242393218E-3720 + 6179 7.43555832349704062037970621196609E-3721 3.717779161748520310189853105983045E-3721 + 6180 1.858889580874260155094926552991523E-3721 9.294447904371300775474632764957613E-3722 + 6181 4.647223952185650387737316382478807E-3722 2.323611976092825193868658191239403E-3722 + 6182 1.161805988046412596934329095619702E-3722 5.809029940232062984671645478098508E-3723 + 6183 2.904514970116031492335822739049254E-3723 1.452257485058015746167911369524627E-3723 + 6184 7.261287425290078730839556847623135E-3724 3.630643712645039365419778423811568E-3724 + 6185 1.815321856322519682709889211905784E-3724 9.07660928161259841354944605952892E-3725 + 6186 4.53830464080629920677472302976446E-3725 2.26915232040314960338736151488223E-3725 + 6187 1.134576160201574801693680757441115E-3725 5.672880801007874008468403787205575E-3726 + 6188 2.836440400503937004234201893602788E-3726 1.418220200251968502117100946801394E-3726 + 6189 7.09110100125984251058550473400697E-3727 3.545550500629921255292752367003485E-3727 + 6190 1.772775250314960627646376183501743E-3727 8.863876251574803138231880917508713E-3728 + 6191 4.431938125787401569115940458754357E-3728 2.215969062893700784557970229377178E-3728 + 6192 1.107984531446850392278985114688589E-3728 5.539922657234251961394925573442945E-3729 + 6193 2.769961328617125980697462786721473E-3729 1.384980664308562990348731393360736E-3729 + 6194 6.92490332154281495174365696680368E-3730 3.46245166077140747587182848340184E-3730 + 6195 1.73122583038570373793591424170092E-3730 8.6561291519285186896795712085046E-3731 + 6196 4.3280645759642593448397856042523E-3731 2.16403228798212967241989280212615E-3731 + 6197 1.082016143991064836209946401063075E-3731 5.410080719955324181049732005315375E-3732 + 6198 2.705040359977662090524866002657688E-3732 1.352520179988831045262433001328844E-3732 + 6199 6.76260089994415522631216500664422E-3733 3.38130044997207761315608250332211E-3733 + 6200 1.690650224986038806578041251661055E-3733 8.453251124930194032890206258305275E-3734 + 6201 4.226625562465097016445103129152638E-3734 2.113312781232548508222551564576319E-3734 + 6202 1.056656390616274254111275782288160E-3734 5.283281953081371270556378911440798E-3735 + 6203 2.641640976540685635278189455720399E-3735 1.320820488270342817639094727860200E-3735 + 6204 6.60410244135171408819547363930100E-3736 3.30205122067585704409773681965050E-3736 + 6205 1.65102561033792852204886840982525E-3736 8.25512805168964261024434204912625E-3737 + 6206 4.127564025844821305122171024563125E-3737 2.063782012922410652561085512281563E-3737 + 6207 1.031891006461205326280542756140782E-3737 5.159455032306026631402713780703908E-3738 + 6208 2.579727516153013315701356890351954E-3738 1.289863758076506657850678445175977E-3738 + 6209 6.449318790382533289253392225879885E-3739 3.224659395191266644626696112939943E-3739 + 6210 1.612329697595633322313348056469972E-3739 8.061648487978166611566740282349858E-3740 + 6211 4.030824243989083305783370141174929E-3740 2.015412121994541652891685070587465E-3740 + 6212 1.007706060997270826445842535293733E-3740 5.038530304986354132229212676468663E-3741 + 6213 2.519265152493177066114606338234332E-3741 1.259632576246588533057303169117166E-3741 + 6214 6.29816288123294266528651584558583E-3742 3.149081440616471332643257922792915E-3742 + 6215 1.574540720308235666321628961396458E-3742 7.872703601541178331608144806982288E-3743 + 6216 3.936351800770589165804072403491144E-3743 1.968175900385294582902036201745572E-3743 + 6217 9.84087950192647291451018100872786E-3744 4.92043975096323645725509050436393E-3744 + 6218 2.460219875481618228627545252181965E-3744 1.230109937740809114313772626090983E-3744 + 6219 6.150549688704045571568863130454915E-3745 3.075274844352022785784431565227458E-3745 + 6220 1.537637422176011392892215782613729E-3745 7.688187110880056964461078913068645E-3746 + 6221 3.844093555440028482230539456534323E-3746 1.922046777720014241115269728267161E-3746 + 6222 9.610233888600071205576348641335805E-3747 4.805116944300035602788174320667903E-3747 + 6223 2.402558472150017801394087160333952E-3747 1.201279236075008900697043580166976E-3747 + 6224 6.00639618037504450348521790083488E-3748 3.00319809018752225174260895041744E-3748 + 6225 1.50159904509376112587130447520872E-3748 7.5079952254688056293565223760436E-3749 + 6226 3.7539976127344028146782611880218E-3749 1.8769988063672014073391305940109E-3749 + 6227 9.3849940318360070366956529700545E-3750 4.69249701591800351834782648502725E-3750 + 6228 2.346248507959001759173913242513625E-3750 1.173124253979500879586956621256813E-3750 + 6229 5.865621269897504397934783106284065E-3751 2.932810634948752198967391553142033E-3751 + 6230 1.466405317474376099483695776571017E-3751 7.332026587371880497418478882855083E-3752 + 6231 3.666013293685940248709239441427542E-3752 1.833006646842970124354619720713771E-3752 + 6232 9.165033234214850621773098603568855E-3753 4.582516617107425310886549301784428E-3753 + 6233 2.291258308553712655443274650892214E-3753 1.145629154276856327721637325446107E-3753 + 6234 5.728145771384281638608186627230535E-3754 2.864072885692140819304093313615268E-3754 + 6235 1.432036442846070409652046656807634E-3754 7.16018221423035204826023328403817E-3755 + 6236 3.580091107115176024130116642019085E-3755 1.790045553557588012065058321009543E-3755 + 6237 8.950227767787940060325291605047715E-3756 4.475113883893970030162645802523858E-3756 + 6238 2.237556941946985015081322901261929E-3756 1.118778470973492507540661450630965E-3756 + 6239 5.593892354867462537703307253154825E-3757 2.796946177433731268851653626577413E-3757 + 6240 1.398473088716865634425826813288707E-3757 6.992365443584328172129134066443533E-3758 + 6241 3.496182721792164086064567033221767E-3758 1.748091360896082043032283516610883E-3758 + 6242 8.740456804480410215161417583054415E-3759 4.370228402240205107580708791527208E-3759 + 6243 2.185114201120102553790354395763604E-3759 1.092557100560051276895177197881802E-3759 + 6244 5.46278550280025638447588598940901E-3760 2.731392751400128192237942994704505E-3760 + 6245 1.365696375700064096118971497352253E-3760 6.828481878500320480594857486761263E-3761 + 6246 3.414240939250160240297428743380632E-3761 1.707120469625080120148714371690316E-3761 + 6247 8.53560234812540060074357185845158E-3762 4.26780117406270030037178592922579E-3762 + 6248 2.133900587031350150185892964612895E-3762 1.066950293515675075092946482306448E-3762 + 6249 5.33475146757837537546473241153224E-3763 2.66737573378918768773236620576612E-3763 + 6250 1.33368786689459384386618310288306E-3763 6.6684393344729692193309155144153E-3764 + 6251 3.33421966723648460966545775720765E-3764 1.667109833618242304832728878603825E-3764 + 6252 8.335549168091211524163644393019125E-3765 4.167774584045605762081822196509563E-3765 + 6253 2.083887292022802881040911098254782E-3765 1.041943646011401440520455549127391E-3765 + 6254 5.209718230057007202602277745636955E-3766 2.604859115028503601301138872818478E-3766 + 6255 1.302429557514251800650569436409239E-3766 6.512147787571259003252847182046195E-3767 + 6256 3.256073893785629501626423591023098E-3767 1.628036946892814750813211795511549E-3767 + 6257 8.140184734464073754066058977557745E-3768 4.070092367232036877033029488778873E-3768 + 6258 2.035046183616018438516514744389437E-3768 1.017523091808009219258257372194718E-3768 + 6259 5.08761545904004609629128686097359E-3769 2.543807729520023048145643430486795E-3769 + 6260 1.271903864760011524072821715243398E-3769 6.359519323800057620364108576216988E-3770 + 6261 3.179759661900028810182054288108494E-3770 1.589879830950014405091027144054247E-3770 + 6262 7.949399154750072025455135720271235E-3771 3.974699577375036012727567860135618E-3771 + 6263 1.987349788687518006363783930067809E-3771 9.936748943437590031818919650339045E-3772 + 6264 4.968374471718795015909459825169523E-3772 2.484187235859397507954729912584761E-3772 + 6265 1.242093617929698753977364956292381E-3772 6.210468089648493769886824781461903E-3773 + 6266 3.105234044824246884943412390730952E-3773 1.552617022412123442471706195365476E-3773 + 6267 7.76308511206061721235853097682738E-3774 3.88154255603030860617926548841369E-3774 + 6268 1.940771278015154303089632744206845E-3774 9.703856390075771515448163721034225E-3775 + 6269 4.851928195037885757724081860517113E-3775 2.425964097518942878862040930258556E-3775 + 6270 1.212982048759471439431020465129278E-3775 6.06491024379735719715510232564639E-3776 + 6271 3.032455121898678598577551162823195E-3776 1.516227560949339299288775581411598E-3776 + 6272 7.58113780474669649644387790705799E-3777 3.790568902373348248221938953528995E-3777 + 6273 1.895284451186674124110969476764498E-3777 9.476422255933370620554847383822488E-3778 + 6274 4.738211127966685310277423691911244E-3778 2.369105563983342655138711845955622E-3778 + 6275 1.184552781991671327569355922977811E-3778 5.922763909958356637846779614889055E-3779 + 6276 2.961381954979178318923389807444528E-3779 1.480690977489589159461694903722264E-3779 + 6277 7.40345488744794579730847451861132E-3780 3.70172744372397289865423725930566E-3780 + 6278 1.85086372186198644932711862965283E-3780 9.25431860930993224663559314826415E-3781 + 6279 4.627159304654966123317796574132075E-3781 2.313579652327483061658898287066038E-3781 + 6280 1.156789826163741530829449143533019E-3781 5.783949130818707654147245717665095E-3782 + 6281 2.891974565409353827073622858832548E-3782 1.445987282704676913536811429416274E-3782 + 6282 7.22993641352338456768405714708137E-3783 3.614968206761692283842028573540685E-3783 + 6283 1.807484103380846141921014286770343E-3783 9.037420516904230709605071433851713E-3784 + 6284 4.518710258452115354802535716925857E-3784 2.259355129226057677401267858462928E-3784 + 6285 1.129677564613028838700633929231464E-3784 5.64838782306514419350316964615732E-3785 + 6286 2.82419391153257209675158482307866E-3785 1.41209695576628604837579241153933E-3785 + 6287 7.06048477883143024187896205769665E-3786 3.530242389415715120939481028848325E-3786 + 6288 1.765121194707857560469740514424163E-3786 8.825605973539287802348702572120813E-3787 + 6289 4.412802986769643901174351286060407E-3787 2.206401493384821950587175643030203E-3787 + 6290 1.103200746692410975293587821515102E-3787 5.516003733462054876467939107575508E-3788 + 6291 2.758001866731027438233969553787754E-3788 1.379000933365513719116984776893877E-3788 + 6292 6.895004666827568595584923884469385E-3789 3.447502333413784297792461942234693E-3789 + 6293 1.723751166706892148896230971117347E-3789 8.618755833534460744481154855586733E-3790 + 6294 4.309377916767230372240577427793367E-3790 2.154688958383615186120288713896683E-3790 + 6295 1.077344479191807593060144356948342E-3790 5.386722395959037965300721784741708E-3791 + 6296 2.693361197979518982650360892370854E-3791 1.346680598989759491325180446185427E-3791 + 6297 6.733402994948797456625902230927135E-3792 3.366701497474398728312951115463568E-3792 + 6298 1.683350748737199364156475557731784E-3792 8.41675374368599682078237778865892E-3793 + 6299 4.20837687184299841039118889432946E-3793 2.10418843592149920519559444716473E-3793 + 6300 1.052094217960749602597797223582365E-3793 5.260471089803748012988986117911825E-3794 + 6301 2.630235544901874006494493058955913E-3794 1.315117772450937003247246529477956E-3794 + 6302 6.57558886225468501623623264738978E-3795 3.28779443112734250811811632369489E-3795 + 6303 1.643897215563671254059058161847445E-3795 8.219486077818356270295290809237225E-3796 + 6304 4.109743038909178135147645404618613E-3796 2.054871519454589067573822702309306E-3796 + 6305 1.027435759727294533786911351154653E-3796 5.137178798636472668934556755773265E-3797 + 6306 2.568589399318236334467278377886633E-3797 1.284294699659118167233639188943316E-3797 + 6307 6.42147349829559083616819594471658E-3798 3.21073674914779541808409797235829E-3798 + 6308 1.605368374573897709042048986179145E-3798 8.026841872869488545210244930895725E-3799 + 6309 4.013420936434744272605122465447863E-3799 2.006710468217372136302561232723931E-3799 + 6310 1.003355234108686068151280616361966E-3799 5.016776170543430340756403081809828E-3800 + 6311 2.508388085271715170378201540904914E-3800 1.254194042635857585189100770452457E-3800 + 6312 6.270970213179287925945503852262285E-3801 3.135485106589643962972751926131143E-3801 + 6313 1.567742553294821981486375963065572E-3801 7.838712766474109907431879815327858E-3802 + 6314 3.919356383237054953715939907663929E-3802 1.959678191618527476857969953831965E-3802 + 6315 9.798390958092637384289849769159825E-3803 4.899195479046318692144924884579913E-3803 + 6316 2.449597739523159346072462442289957E-3803 1.224798869761579673036231221144978E-3803 + 6317 6.12399434880789836518115610572489E-3804 3.061997174403949182590578052862445E-3804 + 6318 1.530998587201974591295289026431223E-3804 7.654992936009872956476445132156113E-3805 + 6319 3.827496468004936478238222566078057E-3805 1.913748234002468239119111283039028E-3805 + 6320 9.56874117001234119559555641519514E-3806 4.78437058500617059779777820759757E-3806 + 6321 2.392185292503085298898889103798785E-3806 1.196092646251542649449444551899393E-3806 + 6322 5.980463231257713247247222759496965E-3807 2.990231615628856623623611379748483E-3807 + 6323 1.495115807814428311811805689874242E-3807 7.475579039072141559059028449371208E-3808 + 6324 3.737789519536070779529514224685604E-3808 1.868894759768035389764757112342802E-3808 + 6325 9.34447379884017694882378556171401E-3809 4.672236899420088474411892780857005E-3809 + 6326 2.336118449710044237205946390428503E-3809 1.168059224855022118602973195214251E-3809 + 6327 5.840296124275110593014865976071255E-3810 2.920148062137555296507432988035628E-3810 + 6328 1.460074031068777648253716494017814E-3810 7.30037015534388824126858247008907E-3811 + 6329 3.650185077671944120634291235044535E-3811 1.825092538835972060317145617522268E-3811 + 6330 9.12546269417986030158572808761134E-3812 4.56273134708993015079286404380567E-3812 + 6331 2.281365673544965075396432021902835E-3812 1.140682836772482537698216010951418E-3812 + 6332 5.70341418386241268849108005475709E-3813 2.851707091931206344245540027378545E-3813 + 6333 1.425853545965603172122770013689273E-3813 7.129267729828015860613850068446363E-3814 + 6334 3.564633864914007930306925034223182E-3814 1.782316932457003965153462517111591E-3814 + 6335 8.911584662285019825767312585557955E-3815 4.455792331142509912883656292778978E-3815 + 6336 2.227896165571254956441828146389489E-3815 1.113948082785627478220914073194745E-3815 + 6337 5.569740413928137391104570365973725E-3816 2.784870206964068695552285182986863E-3816 + 6338 1.392435103482034347776142591493432E-3816 6.962175517410171738880712957467158E-3817 + 6339 3.481087758705085869440356478733579E-3817 1.740543879352542934720178239366790E-3817 + 6340 8.70271939676271467360089119683395E-3818 4.351359698381357336800445598416975E-3818 + 6341 2.175679849190678668400222799208488E-3818 1.087839924595339334200111399604244E-3818 + 6342 5.43919962297669667100055699802122E-3819 2.71959981148834833550027849901061E-3819 + 6343 1.359799905744174167750139249505305E-3819 6.798999528720870838750696247526525E-3820 + 6344 3.399499764360435419375348123763263E-3820 1.699749882180217709687674061881631E-3820 + 6345 8.498749410901088548438370309408155E-3821 4.249374705450544274219185154704078E-3821 + 6346 2.124687352725272137109592577352039E-3821 1.062343676362636068554796288676020E-3821 + 6347 5.31171838181318034277398144338010E-3822 2.65585919090659017138699072169005E-3822 + 6348 1.327929595453295085693495360845025E-3822 6.639647977266475428467476804225125E-3823 + 6349 3.319823988633237714233738402112563E-3823 1.659911994316618857116869201056281E-3823 + 6350 8.299559971583094285584346005281405E-3824 4.149779985791547142792173002640703E-3824 + 6351 2.074889992895773571396086501320352E-3824 1.037444996447886785698043250660176E-3824 + 6352 5.18722498223943392849021625330088E-3825 2.59361249111971696424510812665044E-3825 + 6353 1.29680624555985848212255406332522E-3825 6.4840312277992924106127703166261E-3826 + 6354 3.24201561389964620530638515831305E-3826 1.621007806949823102653192579156525E-3826 + 6355 8.105039034749115513265962895782625E-3827 4.052519517374557756632981447891313E-3827 + 6356 2.026259758687278878316490723945657E-3827 1.013129879343639439158245361972828E-3827 + 6357 5.06564939671819719579122680986414E-3828 2.53282469835909859789561340493207E-3828 + 6358 1.266412349179549298947806702466035E-3828 6.332061745897746494739033512330175E-3829 + 6359 3.166030872948873247369516756165088E-3829 1.583015436474436623684758378082544E-3829 + 6360 7.91507718237218311842379189041272E-3830 3.95753859118609155921189594520636E-3830 + 6361 1.97876929559304577960594797260318E-3830 9.8938464779652288980297398630159E-3831 + 6362 4.94692323898261444901486993150795E-3831 2.473461619491307224507434965753975E-3831 + 6363 1.236730809745653612253717482876988E-3831 6.183654048728268061268587414384938E-3832 + 6364 3.091827024364134030634293707192469E-3832 1.545913512182067015317146853596235E-3832 + 6365 7.729567560910335076585734267981175E-3833 3.864783780455167538292867133990588E-3833 + 6366 1.932391890227583769146433566995294E-3833 9.66195945113791884573216783497647E-3834 + 6367 4.830979725568959422866083917488235E-3834 2.415489862784479711433041958744118E-3834 + 6368 1.207744931392239855716520979372059E-3834 6.038724656961199278582604896860295E-3835 + 6369 3.019362328480599639291302448430148E-3835 1.509681164240299819645651224215074E-3835 + 6370 7.54840582120149909822825612107537E-3836 3.774202910600749549114128060537685E-3836 + 6371 1.887101455300374774557064030268843E-3836 9.435507276501873872785320151344213E-3837 + 6372 4.717753638250936936392660075672107E-3837 2.358876819125468468196330037836053E-3837 + 6373 1.179438409562734234098165018918027E-3837 5.897192047813671170490825094590133E-3838 + 6374 2.948596023906835585245412547295067E-3838 1.474298011953417792622706273647533E-3838 + 6375 7.371490059767088963113531368237665E-3839 3.685745029883544481556765684118833E-3839 + 6376 1.842872514941772240778382842059417E-3839 9.214362574708861203891914210297083E-3840 + 6377 4.607181287354430601945957105148542E-3840 2.303590643677215300972978552574271E-3840 + 6378 1.151795321838607650486489276287136E-3840 5.758976609193038252432446381435678E-3841 + 6379 2.879488304596519126216223190717839E-3841 1.439744152298259563108111595358920E-3841 + 6380 7.19872076149129781554055797679460E-3842 3.59936038074564890777027898839730E-3842 + 6381 1.79968019037282445388513949419865E-3842 8.99840095186412226942569747099325E-3843 + 6382 4.499200475932061134712848735496625E-3843 2.249600237966030567356424367748313E-3843 + 6383 1.124800118983015283678212183874157E-3843 5.624000594915076418391060919370783E-3844 + 6384 2.812000297457538209195530459685392E-3844 1.406000148728769104597765229842696E-3844 + 6385 7.03000074364384552298882614921348E-3845 3.51500037182192276149441307460674E-3845 + 6386 1.75750018591096138074720653730337E-3845 8.78750092955480690373603268651685E-3846 + 6387 4.393750464777403451868016343258425E-3846 2.196875232388701725934008171629213E-3846 + 6388 1.098437616194350862967004085814607E-3846 5.492188080971754314835020429073033E-3847 + 6389 2.746094040485877157417510214536517E-3847 1.373047020242938578708755107268258E-3847 + 6390 6.86523510121469289354377553634129E-3848 3.432617550607346446771887768170645E-3848 + 6391 1.716308775303673223385943884085323E-3848 8.581543876518366116929719420426613E-3849 + 6392 4.290771938259183058464859710213307E-3849 2.145385969129591529232429855106653E-3849 + 6393 1.072692984564795764616214927553327E-3849 5.363464922823978823081074637766633E-3850 + 6394 2.681732461411989411540537318883317E-3850 1.340866230705994705770268659441658E-3850 + 6395 6.70433115352997352885134329720829E-3851 3.352165576764986764425671648604145E-3851 + 6396 1.676082788382493382212835824302073E-3851 8.380413941912466911064179121510363E-3852 + 6397 4.190206970956233455532089560755182E-3852 2.095103485478116727766044780377591E-3852 + 6398 1.047551742739058363883022390188796E-3852 5.237758713695291819415111950943978E-3853 + 6399 2.618879356847645909707555975471989E-3853 1.309439678423822954853777987735995E-3853 + 6400 6.547198392119114774268889938679975E-3854 3.273599196059557387134444969339988E-3854 + 6401 1.636799598029778693567222484669994E-3854 8.18399799014889346783611242334997E-3855 + 6402 4.091998995074446733918056211674985E-3855 2.045999497537223366959028105837493E-3855 + 6403 1.022999748768611683479514052918747E-3855 5.114998743843058417397570264593733E-3856 + 6404 2.557499371921529208698785132296867E-3856 1.278749685960764604349392566148433E-3856 + 6405 6.393748429803823021746962830742165E-3857 3.196874214901911510873481415371083E-3857 + 6406 1.598437107450955755436740707685542E-3857 7.992185537254778777183703538427708E-3858 + 6407 3.996092768627389388591851769213854E-3858 1.998046384313694694295925884606927E-3858 + 6408 9.990231921568473471479629423034635E-3859 4.995115960784236735739814711517318E-3859 + 6409 2.497557980392118367869907355758659E-3859 1.248778990196059183934953677879330E-3859 + 6410 6.24389495098029591967476838939665E-3860 3.121947475490147959837384194698325E-3860 + 6411 1.560973737745073979918692097349163E-3860 7.804868688725369899593460486745813E-3861 + 6412 3.902434344362684949796730243372907E-3861 1.951217172181342474898365121686453E-3861 + 6413 9.756085860906712374491825608432265E-3862 4.878042930453356187245912804216133E-3862 + 6414 2.439021465226678093622956402108067E-3862 1.219510732613339046811478201054033E-3862 + 6415 6.097553663066695234057391005270165E-3863 3.048776831533347617028695502635083E-3863 + 6416 1.524388415766673808514347751317542E-3863 7.621942078833369042571738756587708E-3864 + 6417 3.810971039416684521285869378293854E-3864 1.905485519708342260642934689146927E-3864 + 6418 9.527427598541711303214673445734635E-3865 4.763713799270855651607336722867318E-3865 + 6419 2.381856899635427825803668361433659E-3865 1.190928449817713912901834180716830E-3865 + 6420 5.95464224908856956450917090358415E-3866 2.977321124544284782254585451792075E-3866 + 6421 1.488660562272142391127292725896038E-3866 7.443302811360711955636463629480188E-3867 + 6422 3.721651405680355977818231814740094E-3867 1.860825702840177988909115907370047E-3867 + 6423 9.304128514200889944545579536850235E-3868 4.652064257100444972272789768425118E-3868 + 6424 2.326032128550222486136394884212559E-3868 1.163016064275111243068197442106280E-3868 + 6425 5.81508032137555621534098721053140E-3869 2.90754016068777810767049360526570E-3869 + 6426 1.45377008034388905383524680263285E-3869 7.26885040171944526917623401316425E-3870 + 6427 3.634425200859722634588117006582125E-3870 1.817212600429861317294058503291063E-3870 + 6428 9.086063002149306586470292516455315E-3871 4.543031501074653293235146258227658E-3871 + 6429 2.271515750537326646617573129113829E-3871 1.135757875268663323308786564556915E-3871 + 6430 5.678789376343316616543932822784575E-3872 2.839394688171658308271966411392288E-3872 + 6431 1.419697344085829154135983205696144E-3872 7.09848672042914577067991602848072E-3873 + 6432 3.54924336021457288533995801424036E-3873 1.77462168010728644266997900712018E-3873 + 6433 8.8731084005364322133498950356009E-3874 4.43655420026821610667494751780045E-3874 + 6434 2.218277100134108053337473758900225E-3874 1.109138550067054026668736879450113E-3874 + 6435 5.545692750335270133343684397250565E-3875 2.772846375167635066671842198625283E-3875 + 6436 1.386423187583817533335921099312642E-3875 6.932115937919087666679605496563208E-3876 + 6437 3.466057968959543833339802748281604E-3876 1.733028984479771916669901374140802E-3876 + 6438 8.66514492239885958334950687070401E-3877 4.332572461199429791674753435352005E-3877 + 6439 2.166286230599714895837376717676003E-3877 1.083143115299857447918688358838001E-3877 + 6440 5.415715576499287239593441794190005E-3878 2.707857788249643619796720897095003E-3878 + 6441 1.353928894124821809898360448547502E-3878 6.769644470624109049491802242737508E-3879 + 6442 3.384822235312054524745901121368754E-3879 1.692411117656027262372950560684377E-3879 + 6443 8.462055588280136311864752803421885E-3880 4.231027794140068155932376401710943E-3880 + 6444 2.115513897070034077966188200855472E-3880 1.057756948535017038983094100427736E-3880 + 6445 5.28878474267508519491547050213868E-3881 2.64439237133754259745773525106934E-3881 + 6446 1.32219618566877129872886762553467E-3881 6.61098092834385649364433812767335E-3882 + 6447 3.305490464171928246822169063836675E-3882 1.652745232085964123411084531918338E-3882 + 6448 8.26372616042982061705542265959169E-3883 4.131863080214910308527711329795845E-3883 + 6449 2.065931540107455154263855664897923E-3883 1.032965770053727577131927832448961E-3883 + 6450 5.164828850268637885659639162244805E-3884 2.582414425134318942829819581122403E-3884 + 6451 1.291207212567159471414909790561202E-3884 6.456036062835797357074548952806008E-3885 + 6452 3.228018031417898678537274476403004E-3885 1.614009015708949339268637238201502E-3885 + 6453 8.07004507854474669634318619100751E-3886 4.035022539272373348171593095503755E-3886 + 6454 2.017511269636186674085796547751878E-3886 1.008755634818093337042898273875939E-3886 + 6455 5.043778174090466685214491369379695E-3887 2.521889087045233342607245684689848E-3887 + 6456 1.260944543522616671303622842344924E-3887 6.30472271761308335651811421172462E-3888 + 6457 3.15236135880654167825905710586231E-3888 1.576180679403270839129528552931155E-3888 + 6458 7.880903397016354195647642764655775E-3889 3.940451698508177097823821382327888E-3889 + 6459 1.970225849254088548911910691163944E-3889 9.85112924627044274455955345581972E-3890 + 6460 4.92556462313522137227977672790986E-3890 2.46278231156761068613988836395493E-3890 + 6461 1.231391155783805343069944181977465E-3890 6.156955778919026715349720909887325E-3891 + 6462 3.078477889459513357674860454943663E-3891 1.539238944729756678837430227471831E-3891 + 6463 7.696194723648783394187151137359155E-3892 3.848097361824391697093575568679578E-3892 + 6464 1.924048680912195848546787784339789E-3892 9.620243404560979242733938921698945E-3893 + 6465 4.810121702280489621366969460849473E-3893 2.405060851140244810683484730424736E-3893 + 6466 1.202530425570122405341742365212368E-3893 6.01265212785061202670871182606184E-3894 + 6467 3.00632606392530601335435591303092E-3894 1.50316303196265300667717795651546E-3894 + 6468 7.5158151598132650333858897825773E-3895 3.75790757990663251669294489128865E-3895 + 6469 1.878953789953316258346472445644325E-3895 9.394768949766581291732362228221625E-3896 + 6470 4.697384474883290645866181114110813E-3896 2.348692237441645322933090557055406E-3896 + 6471 1.174346118720822661466545278527703E-3896 5.871730593604113307332726392638515E-3897 + 6472 2.935865296802056653666363196319258E-3897 1.467932648401028326833181598159629E-3897 + 6473 7.339663242005141634165907990798145E-3898 3.669831621002570817082953995399073E-3898 + 6474 1.834915810501285408541476997699537E-3898 9.174579052506427042707384988497683E-3899 + 6475 4.587289526253213521353692494248842E-3899 2.293644763126606760676846247124421E-3899 + 6476 1.146822381563303380338423123562211E-3899 5.734111907816516901692115617811053E-3900 + 6477 2.867055953908258450846057808905527E-3900 1.433527976954129225423028904452763E-3900 + 6478 7.167639884770646127115144522263815E-3901 3.583819942385323063557572261131908E-3901 + 6479 1.791909971192661531778786130565954E-3901 8.95954985596330765889393065282977E-3902 + 6480 4.479774927981653829446965326414885E-3902 2.239887463990826914723482663207443E-3902 + 6481 1.119943731995413457361741331603722E-3902 5.599718659977067286808706658018608E-3903 + 6482 2.799859329988533643404353329009304E-3903 1.399929664994266821702176664504652E-3903 + 6483 6.99964832497133410851088332252326E-3904 3.49982416248566705425544166126163E-3904 + 6484 1.749912081242833527127720830630815E-3904 8.749560406214167635638604153154075E-3905 + 6485 4.374780203107083817819302076577038E-3905 2.187390101553541908909651038288519E-3905 + 6486 1.093695050776770954454825519144260E-3905 5.468475253883854772274127595721298E-3906 + 6487 2.734237626941927386137063797860649E-3906 1.367118813470963693068531898930325E-3906 + 6488 6.835594067354818465342659494651625E-3907 3.417797033677409232671329747325813E-3907 + 6489 1.708898516838704616335664873662907E-3907 8.544492584193523081678324368314533E-3908 + 6490 4.272246292096761540839162184157267E-3908 2.136123146048380770419581092078633E-3908 + 6491 1.068061573024190385209790546039317E-3908 5.340307865120951926048952730196583E-3909 + 6492 2.670153932560475963024476365098292E-3909 1.335076966280237981512238182549146E-3909 + 6493 6.67538483140118990756119091274573E-3910 3.337692415700594953780595456372865E-3910 + 6494 1.668846207850297476890297728186433E-3910 8.344231039251487384451488640932163E-3911 + 6495 4.172115519625743692225744320466082E-3911 2.086057759812871846112872160233041E-3911 + 6496 1.043028879906435923056436080116521E-3911 5.215144399532179615282180400582603E-3912 + 6497 2.607572199766089807641090200291302E-3912 1.303786099883044903820545100145651E-3912 + 6498 6.518930499415224519102725500728255E-3913 3.259465249707612259551362750364128E-3913 + 6499 1.629732624853806129775681375182064E-3913 8.14866312426903064887840687591032E-3914 + 6500 4.07433156213451532443920343795516E-3914 2.03716578106725766221960171897758E-3914 + 6501 1.01858289053362883110980085948879E-3914 5.09291445266814415554900429744395E-3915 + 6502 2.546457226334072077774502148721975E-3915 1.273228613167036038887251074360988E-3915 + 6503 6.36614306583518019443625537180494E-3916 3.18307153291759009721812768590247E-3916 + 6504 1.591535766458795048609063842951235E-3916 7.957678832293975243045319214756175E-3917 + 6505 3.978839416146987621522659607378088E-3917 1.989419708073493810761329803689044E-3917 + 6506 9.94709854036746905380664901844522E-3918 4.97354927018373452690332450922261E-3918 + 6507 2.486774635091867263451662254611305E-3918 1.243387317545933631725831127305653E-3918 + 6508 6.216936587729668158629155636528265E-3919 3.108468293864834079314577818264133E-3919 + 6509 1.554234146932417039657288909132067E-3919 7.771170734662085198286444545660333E-3920 + 6510 3.885585367331042599143222272830167E-3920 1.942792683665521299571611136415083E-3920 + 6511 9.713963418327606497858055682075415E-3921 4.856981709163803248929027841037708E-3921 + 6512 2.428490854581901624464513920518854E-3921 1.214245427290950812232256960259427E-3921 + 6513 6.071227136454754061161284801297135E-3922 3.035613568227377030580642400648568E-3922 + 6514 1.517806784113688515290321200324284E-3922 7.58903392056844257645160600162142E-3923 + 6515 3.79451696028422128822580300081071E-3923 1.897258480142110644112901500405355E-3923 + 6516 9.486292400710553220564507502026775E-3924 4.743146200355276610282253751013388E-3924 + 6517 2.371573100177638305141126875506694E-3924 1.185786550088819152570563437753347E-3924 + 6518 5.928932750444095762852817188766735E-3925 2.964466375222047881426408594383368E-3925 + 6519 1.482233187611023940713204297191684E-3925 7.41116593805511970356602148595842E-3926 + 6520 3.70558296902755985178301074297921E-3926 1.852791484513779925891505371489605E-3926 + 6521 9.263957422568899629457526857448025E-3927 4.631978711284449814728763428724013E-3927 + 6522 2.315989355642224907364381714362007E-3927 1.157994677821112453682190857181003E-3927 + 6523 5.789973389105562268410954285905015E-3928 2.894986694552781134205477142952508E-3928 + 6524 1.447493347276390567102738571476254E-3928 7.23746673638195283551369285738127E-3929 + 6525 3.618733368190976417756846428690635E-3929 1.809366684095488208878423214345318E-3929 + 6526 9.04683342047744104439211607172659E-3930 4.523416710238720522196058035863295E-3930 + 6527 2.261708355119360261098029017931648E-3930 1.130854177559680130549014508965824E-3930 + 6528 5.65427088779840065274507254482912E-3931 2.82713544389920032637253627241456E-3931 + 6529 1.41356772194960016318626813620728E-3931 7.0678386097480008159313406810364E-3932 + 6530 3.5339193048740004079656703405182E-3932 1.7669596524370002039828351702591E-3932 + 6531 8.8347982621850010199141758512955E-3933 4.41739913109250050995708792564775E-3933 + 6532 2.208699565546250254978543962823875E-3933 1.104349782773125127489271981411938E-3933 + 6533 5.52174891386562563744635990705969E-3934 2.760874456932812818723179953529845E-3934 + 6534 1.380437228466406409361589976764923E-3934 6.902186142332032046807949883824613E-3935 + 6535 3.451093071166016023403974941912307E-3935 1.725546535583008011701987470956153E-3935 + 6536 8.627732677915040058509937354780765E-3936 4.313866338957520029254968677390383E-3936 + 6537 2.156933169478760014627484338695192E-3936 1.078466584739380007313742169347596E-3936 + 6538 5.39233292369690003656871084673798E-3937 2.69616646184845001828435542336899E-3937 + 6539 1.348083230924225009142177711684495E-3937 6.740416154621125045710888558422475E-3938 + 6540 3.370208077310562522855444279211238E-3938 1.685104038655281261427722139605619E-3938 + 6541 8.425520193276406307138610698028095E-3939 4.212760096638203153569305349014048E-3939 + 6542 2.106380048319101576784652674507024E-3939 1.053190024159550788392326337253512E-3939 + 6543 5.26595012079775394196163168626756E-3940 2.63297506039887697098081584313378E-3940 + 6544 1.31648753019943848549040792156689E-3940 6.58243765099719242745203960783445E-3941 + 6545 3.291218825498596213726019803917225E-3941 1.645609412749298106863009901958613E-3941 + 6546 8.228047063746490534315049509793065E-3942 4.114023531873245267157524754896533E-3942 + 6547 2.057011765936622633578762377448267E-3942 1.028505882968311316789381188724133E-3942 + 6548 5.142529414841556583946905943620665E-3943 2.571264707420778291973452971810333E-3943 + 6549 1.285632353710389145986726485905167E-3943 6.428161768551945729933632429525833E-3944 + 6550 3.214080884275972864966816214762917E-3944 1.607040442137986432483408107381458E-3944 + 6551 8.03520221068993216241704053690729E-3945 4.017601105344966081208520268453645E-3945 + 6552 2.008800552672483040604260134226823E-3945 1.004400276336241520302130067113411E-3945 + 6553 5.022001381681207601510650335567055E-3946 2.511000690840603800755325167783528E-3946 + 6554 1.255500345420301900377662583891764E-3946 6.27750172710150950188831291945882E-3947 + 6555 3.13875086355075475094415645972941E-3947 1.569375431775377375472078229864705E-3947 + 6556 7.846877158876886877360391149323525E-3948 3.923438579438443438680195574661763E-3948 + 6557 1.961719289719221719340097787330882E-3948 9.808596448596108596700488936654408E-3949 + 6558 4.904298224298054298350244468327204E-3949 2.452149112149027149175122234163602E-3949 + 6559 1.226074556074513574587561117081801E-3949 6.130372780372567872937805585409005E-3950 + 6560 3.065186390186283936468902792704503E-3950 1.532593195093141968234451396352251E-3950 + 6561 7.662965975465709841172256981761255E-3951 3.831482987732854920586128490880628E-3951 + 6562 1.915741493866427460293064245440314E-3951 9.57870746933213730146532122720157E-3952 + 6563 4.789353734666068650732660613600785E-3952 2.394676867333034325366330306800393E-3952 + 6564 1.197338433666517162683165153400197E-3952 5.986692168332585813415825767000983E-3953 + 6565 2.993346084166292906707912883500492E-3953 1.496673042083146453353956441750246E-3953 + 6566 7.48336521041573226676978220875123E-3954 3.741682605207866133384891104375615E-3954 + 6567 1.870841302603933066692445552187808E-3954 9.354206513019665333462227760939038E-3955 + 6568 4.677103256509832666731113880469519E-3955 2.338551628254916333365556940234760E-3955 + 6569 1.169275814127458166682778470117380E-3955 5.84637907063729083341389235058690E-3956 + 6570 2.92318953531864541670694617529345E-3956 1.461594767659322708353473087646725E-3956 + 6571 7.307973838296613541767365438233625E-3957 3.653986919148306770883682719116813E-3957 + 6572 1.826993459574153385441841359558407E-3957 9.134967297870766927209206797792033E-3958 + 6573 4.567483648935383463604603398896017E-3958 2.283741824467691731802301699448008E-3958 + 6574 1.141870912233845865901150849724004E-3958 5.70935456116922932950575424862002E-3959 + 6575 2.85467728058461466475287712431001E-3959 1.427338640292307332376438562155005E-3959 + 6576 7.136693201461536661882192810775025E-3960 3.568346600730768330941096405387513E-3960 + 6577 1.784173300365384165470548202693757E-3960 8.920866501826920827352741013468783E-3961 + 6578 4.460433250913460413676370506734392E-3961 2.230216625456730206838185253367196E-3961 + 6579 1.115108312728365103419092626683598E-3961 5.57554156364182551709546313341799E-3962 + 6580 2.787770781820912758547731566708995E-3962 1.393885390910456379273865783354498E-3962 + 6581 6.96942695455228189636932891677249E-3963 3.484713477276140948184664458386245E-3963 + 6582 1.742356738638070474092332229193123E-3963 8.711783693190352370461661145965613E-3964 + 6583 4.355891846595176185230830572982807E-3964 2.177945923297588092615415286491403E-3964 + 6584 1.088972961648794046307707643245702E-3964 5.444864808243970231538538216228508E-3965 + 6585 2.722432404121985115769269108114254E-3965 1.361216202060992557884634554057127E-3965 + 6586 6.806081010304962789423172770285635E-3966 3.403040505152481394711586385142818E-3966 + 6587 1.701520252576240697355793192571409E-3966 8.507601262881203486778965962857045E-3967 + 6588 4.253800631440601743389482981428523E-3967 2.126900315720300871694741490714261E-3967 + 6589 1.063450157860150435847370745357131E-3967 5.317250789300752179236853726785653E-3968 + 6590 2.658625394650376089618426863392827E-3968 1.329312697325188044809213431696413E-3968 + 6591 6.646563486625940224046067158482065E-3969 3.323281743312970112023033579241033E-3969 + 6592 1.661640871656485056011516789620517E-3969 8.308204358282425280057583948102583E-3970 + 6593 4.154102179141212640028791974051292E-3970 2.077051089570606320014395987025646E-3970 + 6594 1.038525544785303160007197993512823E-3970 5.192627723926515800035989967564115E-3971 + 6595 2.596313861963257900017994983782058E-3971 1.298156930981628950008997491891029E-3971 + 6596 6.490784654908144750044987459455145E-3972 3.245392327454072375022493729727573E-3972 + 6597 1.622696163727036187511246864863787E-3972 8.113480818635180937556234324318933E-3973 + 6598 4.056740409317590468778117162159467E-3973 2.028370204658795234389058581079733E-3973 + 6599 1.014185102329397617194529290539867E-3973 5.070925511646988085972646452699333E-3974 + 6600 2.535462755823494042986323226349667E-3974 1.267731377911747021493161613174833E-3974 + 6601 6.338656889558735107465808065874165E-3975 3.169328444779367553732904032937083E-3975 + 6602 1.584664222389683776866452016468542E-3975 7.923321111948418884332260082342708E-3976 + 6603 3.961660555974209442166130041171354E-3976 1.980830277987104721083065020585677E-3976 + 6604 9.904151389935523605415325102928385E-3977 4.952075694967761802707662551464193E-3977 + 6605 2.476037847483880901353831275732097E-3977 1.238018923741940450676915637866048E-3977 + 6606 6.19009461870970225338457818933024E-3978 3.09504730935485112669228909466512E-3978 + 6607 1.54752365467742556334614454733256E-3978 7.7376182733871278167307227366628E-3979 + 6608 3.8688091366935639083653613683314E-3979 1.9344045683467819541826806841657E-3979 + 6609 9.6720228417339097709134034208285E-3980 4.83601142086695488545670171041425E-3980 + 6610 2.418005710433477442728350855207125E-3980 1.209002855216738721364175427603563E-3980 + 6611 6.045014276083693606820877138017815E-3981 3.022507138041846803410438569008908E-3981 + 6612 1.511253569020923401705219284504454E-3981 7.55626784510461700852609642252227E-3982 + 6613 3.778133922552308504263048211261135E-3982 1.889066961276154252131524105630568E-3982 + 6614 9.44533480638077126065762052815284E-3983 4.72266740319038563032881026407642E-3983 + 6615 2.36133370159519281516440513203821E-3983 1.180666850797596407582202566019105E-3983 + 6616 5.903334253987982037911012830095525E-3984 2.951667126993991018955506415047763E-3984 + 6617 1.475833563496995509477753207523882E-3984 7.379167817484977547388766037619408E-3985 + 6618 3.689583908742488773694383018809704E-3985 1.844791954371244386847191509404852E-3985 + 6619 9.22395977185622193423595754702426E-3986 4.61197988592811096711797877351213E-3986 + 6620 2.305989942964055483558989386756065E-3986 1.152994971482027741779494693378033E-3986 + 6621 5.764974857410138708897473466890165E-3987 2.882487428705069354448736733445083E-3987 + 6622 1.441243714352534677224368366722542E-3987 7.206218571762673386121841833612708E-3988 + 6623 3.603109285881336693060920916806354E-3988 1.801554642940668346530460458403177E-3988 + 6624 9.007773214703341732652302292015885E-3989 4.503886607351670866326151146007943E-3989 + 6625 2.251943303675835433163075573003972E-3989 1.125971651837917716581537786501986E-3989 + 6626 5.62985825918958858290768893250993E-3990 2.814929129594794291453844466254965E-3990 + 6627 1.407464564797397145726922233127483E-3990 7.037322823986985728634611165637413E-3991 + 6628 3.518661411993492864317305582818707E-3991 1.759330705996746432158652791409353E-3991 + 6629 8.796653529983732160793263957046765E-3992 4.398326764991866080396631978523383E-3992 + 6630 2.199163382495933040198315989261692E-3992 1.099581691247966520099157994630846E-3992 + 6631 5.49790845623983260049578997315423E-3993 2.748954228119916300247894986577115E-3993 + 6632 1.374477114059958150123947493288558E-3993 6.872385570299790750619737466442788E-3994 + 6633 3.436192785149895375309868733221394E-3994 1.718096392574947687654934366610697E-3994 + 6634 8.590481962874738438274671833053485E-3995 4.295240981437369219137335916526743E-3995 + 6635 2.147620490718684609568667958263372E-3995 1.073810245359342304784333979131686E-3995 + 6636 5.36905122679671152392166989565843E-3996 2.684525613398355761960834947829215E-3996 + 6637 1.342262806699177880980417473914608E-3996 6.711314033495889404902087369573038E-3997 + 6638 3.355657016747944702451043684786519E-3997 1.677828508373972351225521842393260E-3997 + 6639 8.38914254186986175612760921196630E-3998 4.19457127093493087806380460598315E-3998 + 6640 2.097285635467465439031902302991575E-3998 1.048642817733732719515951151495788E-3998 + 6641 5.24321408866866359757975575747894E-3999 2.62160704433433179878987787873947E-3999 + 6642 1.310803522167165899394938939369735E-3999 6.554017610835829496974694696848675E-4000 + 6643 3.277008805417914748487347348424338E-4000 1.638504402708957374243673674212169E-4000 + 6644 8.192522013544786871218368371060845E-4001 4.096261006772393435609184185530423E-4001 + 6645 2.048130503386196717804592092765212E-4001 1.024065251693098358902296046382606E-4001 + 6646 5.12032625846549179451148023191303E-4002 2.560163129232745897255740115956515E-4002 + 6647 1.280081564616372948627870057978258E-4002 6.400407823081864743139350289891288E-4003 + 6648 3.200203911540932371569675144945644E-4003 1.600101955770466185784837572472822E-4003 + 6649 8.00050977885233092892418786236411E-4004 4.000254889426165464462093931182055E-4004 + 6650 2.000127444713082732231046965591028E-4004 1.000063722356541366115523482795514E-4004 + 6651 5.00031861178270683057761741397757E-4005 2.500159305891353415288808706988785E-4005 + 6652 1.250079652945676707644404353494393E-4005 6.250398264728383538222021767471963E-4006 + 6653 3.125199132364191769111010883735982E-4006 1.562599566182095884555505441867991E-4006 + 6654 7.812997830910479422777527209339955E-4007 3.906498915455239711388763604669978E-4007 + 6655 1.953249457727619855694381802334989E-4007 9.766247288638099278471909011674945E-4008 + 6656 4.883123644319049639235954505837473E-4008 2.441561822159524819617977252918736E-4008 + 6657 1.220780911079762409808988626459368E-4008 6.10390455539881204904494313229684E-4009 + 6658 3.05195227769940602452247156614842E-4009 1.52597613884970301226123578307421E-4009 + 6659 7.62988069424851506130617891537105E-4010 3.814940347124257530653089457685525E-4010 + 6660 1.907470173562128765326544728842763E-4010 9.537350867810643826632723644213813E-4011 + 6661 4.768675433905321913316361822106907E-4011 2.384337716952660956658180911053453E-4011 + 6662 1.192168858476330478329090455526727E-4011 5.960844292381652391645452277633633E-4012 + 6663 2.980422146190826195822726138816817E-4012 1.490211073095413097911363069408408E-4012 + 6664 7.45105536547706548955681534704204E-4013 3.72552768273853274477840767352102E-4013 + 6665 1.86276384136926637238920383676051E-4013 9.31381920684633186194601918380255E-4014 + 6666 4.656909603423165930973009591901275E-4014 2.328454801711582965486504795950638E-4014 + 6667 1.164227400855791482743252397975319E-4014 5.821137004278957413716261989876595E-4015 + 6668 2.910568502139478706858130994938298E-4015 1.455284251069739353429065497469149E-4015 + 6669 7.276421255348696767145327487345745E-4016 3.638210627674348383572663743672873E-4016 + 6670 1.819105313837174191786331871836437E-4016 9.095526569185870958931659359182183E-4017 + 6671 4.547763284592935479465829679591092E-4017 2.273881642296467739732914839795546E-4017 + 6672 1.136940821148233869866457419897773E-4017 5.684704105741169349332287099488865E-4018 + 6673 2.842352052870584674666143549744433E-4018 1.421176026435292337333071774872216E-4018 + 6674 7.10588013217646168666535887436108E-4019 3.55294006608823084333267943718054E-4019 + 6675 1.77647003304411542166633971859027E-4019 8.88235016522057710833169859295135E-4020 + 6676 4.441175082610288554165849296475675E-4020 2.220587541305144277082924648237838E-4020 + 6677 1.110293770652572138541462324118919E-4020 5.551468853262860692707311620594595E-4021 + 6678 2.775734426631430346353655810297298E-4021 1.387867213315715173176827905148649E-4021 + 6679 6.939336066578575865884139525743245E-4022 3.469668033289287932942069762871623E-4022 + 6680 1.734834016644643966471034881435812E-4022 8.674170083223219832355174407179058E-4023 + 6681 4.337085041611609916177587203589529E-4023 2.168542520805804958088793601794765E-4023 + 6682 1.084271260402902479044396800897383E-4023 5.421356302014512395221984004486913E-4024 + 6683 2.710678151007256197610992002243457E-4024 1.355339075503628098805496001121728E-4024 + 6684 6.77669537751814049402748000560864E-4025 3.38834768875907024701374000280432E-4025 + 6685 1.69417384437953512350687000140216E-4025 8.4708692218976756175343500070108E-4026 + 6686 4.2354346109488378087671750035054E-4026 2.1177173054744189043835875017527E-4026 + 6687 1.05885865273720945219179375087635E-4026 5.29429326368604726095896875438175E-4027 + 6688 2.647146631843023630479484377190875E-4027 1.323573315921511815239742188595438E-4027 + 6689 6.61786657960755907619871094297719E-4028 3.308933289803779538099355471488595E-4028 + 6690 1.654466644901889769049677735744298E-4028 8.272333224509448845248388678721488E-4029 + 6691 4.136166612254724422624194339360744E-4029 2.068083306127362211312097169680372E-4029 + 6692 1.034041653063681105656048584840186E-4029 5.17020826531840552828024292420093E-4030 + 6693 2.585104132659202764140121462100465E-4030 1.292552066329601382070060731050233E-4030 + 6694 6.462760331648006910350303655251165E-4031 3.231380165824003455175151827625583E-4031 + 6695 1.615690082912001727587575913812792E-4031 8.078450414560008637937879569063958E-4032 + 6696 4.039225207280004318968939784531979E-4032 2.019612603640002159484469892265990E-4032 + 6697 1.009806301820001079742234946132995E-4032 5.049031509100005398711174730664975E-4033 + 6698 2.524515754550002699355587365332488E-4033 1.262257877275001349677793682666244E-4033 + 6699 6.31128938637500674838896841333122E-4034 3.15564469318750337419448420666561E-4034 + 6700 1.577822346593751687097242103332805E-4034 7.889111732968758435486210516664025E-4035 + 6701 3.944555866484379217743105258332013E-4035 1.972277933242189608871552629166006E-4035 + 6702 9.86138966621094804435776314583003E-4036 4.930694833105474022178881572915015E-4036 + 6703 2.465347416552737011089440786457508E-4036 1.232673708276368505544720393228754E-4036 + 6704 6.16336854138184252772360196614377E-4037 3.081684270690921263861800983071885E-4037 + 6705 1.540842135345460631930900491535943E-4037 7.704210676727303159654502457679713E-4038 + 6706 3.852105338363651579827251228839857E-4038 1.926052669181825789913625614419928E-4038 + 6707 9.63026334590912894956812807209964E-4039 4.81513167295456447478406403604982E-4039 + 6708 2.40756583647728223739203201802491E-4039 1.203782918238641118696016009012455E-4039 + 6709 6.018914591193205593480080045062275E-4040 3.009457295596602796740040022531138E-4040 + 6710 1.504728647798301398370020011265569E-4040 7.523643238991506991850100056327845E-4041 + 6711 3.761821619495753495925050028163923E-4041 1.880910809747876747962525014081961E-4041 + 6712 9.404554048739383739812625070409805E-4042 4.702277024369691869906312535204903E-4042 + 6713 2.351138512184845934953156267602452E-4042 1.175569256092422967476578133801226E-4042 + 6714 5.87784628046211483738289066900613E-4043 2.938923140231057418691445334503065E-4043 + 6715 1.469461570115528709345722667251533E-4043 7.347307850577643546728613336257663E-4044 + 6716 3.673653925288821773364306668128832E-4044 1.836826962644410886682153334064416E-4044 + 6717 9.18413481322205443341076667032208E-4045 4.59206740661102721670538333516104E-4045 + 6718 2.29603370330551360835269166758052E-4045 1.14801685165275680417634583379026E-4045 + 6719 5.7400842582637840208817291689513E-4046 2.87004212913189201044086458447565E-4046 + 6720 1.435021064565946005220432292237825E-4046 7.175105322829730026102161461189125E-4047 + 6721 3.587552661414865013051080730594563E-4047 1.793776330707432506525540365297281E-4047 + 6722 8.968881653537162532627701826486405E-4048 4.484440826768581266313850913243203E-4048 + 6723 2.242220413384290633156925456621602E-4048 1.121110206692145316578462728310801E-4048 + 6724 5.605551033460726582892313641554005E-4049 2.802775516730363291446156820777003E-4049 + 6725 1.401387758365181645723078410388502E-4049 7.006938791825908228615392051942508E-4050 + 6726 3.503469395912954114307696025971254E-4050 1.751734697956477057153848012985627E-4050 + 6727 8.758673489782385285769240064928135E-4051 4.379336744891192642884620032464068E-4051 + 6728 2.189668372445596321442310016232034E-4051 1.094834186222798160721155008116017E-4051 + 6729 5.474170931113990803605775040580085E-4052 2.737085465556995401802887520290043E-4052 + 6730 1.368542732778497700901443760145022E-4052 6.842713663892488504507218800725108E-4053 + 6731 3.421356831946244252253609400362554E-4053 1.710678415973122126126804700181277E-4053 + 6732 8.553392079865610630634023500906385E-4054 4.276696039932805315317011750453193E-4054 + 6733 2.138348019966402657658505875226597E-4054 1.069174009983201328829252937613298E-4054 + 6734 5.34587004991600664414626468806649E-4055 2.672935024958003322073132344033245E-4055 + 6735 1.336467512479001661036566172016623E-4055 6.682337562395008305182830860083113E-4056 + 6736 3.341168781197504152591415430041557E-4056 1.670584390598752076295707715020778E-4056 + 6737 8.35292195299376038147853857510389E-4057 4.176460976496880190739269287551945E-4057 + 6738 2.088230488248440095369634643775973E-4057 1.044115244124220047684817321887986E-4057 + 6739 5.22057622062110023842408660943993E-4058 2.610288110310550119212043304719965E-4058 + 6740 1.305144055155275059606021652359983E-4058 6.525720275776375298030108261799913E-4059 + 6741 3.262860137888187649015054130899957E-4059 1.631430068944093824507527065449978E-4059 + 6742 8.15715034472046912253763532724989E-4060 4.078575172360234561268817663624945E-4060 + 6743 2.039287586180117280634408831812473E-4060 1.019643793090058640317204415906236E-4060 + 6744 5.09821896545029320158602207953118E-4061 2.54910948272514660079301103976559E-4061 + 6745 1.274554741362573300396505519882795E-4061 6.372773706812866501982527599413975E-4062 + 6746 3.186386853406433250991263799706988E-4062 1.593193426703216625495631899853494E-4062 + 6747 7.96596713351608312747815949926747E-4063 3.982983566758041563739079749633735E-4063 + 6748 1.991491783379020781869539874816868E-4063 9.957458916895103909347699374084338E-4064 + 6749 4.978729458447551954673849687042169E-4064 2.489364729223775977336924843521085E-4064 + 6750 1.244682364611887988668462421760543E-4064 6.223411823059439943342312108802713E-4065 + 6751 3.111705911529719971671156054401357E-4065 1.555852955764859985835578027200678E-4065 + 6752 7.77926477882429992917789013600339E-4066 3.889632389412149964588945068001695E-4066 + 6753 1.944816194706074982294472534000848E-4066 9.724080973530374911472362670004238E-4067 + 6754 4.862040486765187455736181335002119E-4067 2.431020243382593727868090667501060E-4067 + 6755 1.215510121691296863934045333750530E-4067 6.07755060845648431967022666875265E-4068 + 6756 3.038775304228242159835113334376325E-4068 1.519387652114121079917556667188163E-4068 + 6757 7.596938260570605399587783335940815E-4069 3.798469130285302699793891667970408E-4069 + 6758 1.899234565142651349896945833985204E-4069 9.49617282571325674948472916992602E-4070 + 6759 4.74808641285662837474236458496301E-4070 2.374043206428314187371182292481505E-4070 + 6760 1.187021603214157093685591146240753E-4070 5.935108016070785468427955731203763E-4071 + 6761 2.967554008035392734213977865601882E-4071 1.483777004017696367106988932800941E-4071 + 6762 7.418885020088481835534944664004705E-4072 3.709442510044240917767472332002353E-4072 + 6763 1.854721255022120458883736166001177E-4072 9.273606275110602294418680830005883E-4073 + 6764 4.636803137555301147209340415002942E-4073 2.318401568777650573604670207501471E-4073 + 6765 1.159200784388825286802335103750736E-4073 5.796003921944126434011675518753678E-4074 + 6766 2.898001960972063217005837759376839E-4074 1.449000980486031608502918879688420E-4074 + 6767 7.24500490243015804251459439844210E-4075 3.62250245121507902125729719922105E-4075 + 6768 1.811251225607539510628648599610525E-4075 9.056256128037697553143242998052625E-4076 + 6769 4.528128064018848776571621499026313E-4076 2.264064032009424388285810749513156E-4076 + 6770 1.132032016004712194142905374756578E-4076 5.66016008002356097071452687378289E-4077 + 6771 2.830080040011780485357263436891445E-4077 1.415040020005890242678631718445723E-4077 + 6772 7.075200100029451213393158592228615E-4078 3.537600050014725606696579296114308E-4078 + 6773 1.768800025007362803348289648057154E-4078 8.84400012503681401674144824028577E-4079 + 6774 4.422000062518407008370724120142885E-4079 2.211000031259203504185362060071443E-4079 + 6775 1.105500015629601752092681030035722E-4079 5.527500078148008760463405150178608E-4080 + 6776 2.763750039074004380231702575089304E-4080 1.381875019537002190115851287544652E-4080 + 6777 6.90937509768501095057925643772326E-4081 3.45468754884250547528962821886163E-4081 + 6778 1.727343774421252737644814109430815E-4081 8.636718872106263688224070547154075E-4082 + 6779 4.318359436053131844112035273577038E-4082 2.159179718026565922056017636788519E-4082 + 6780 1.079589859013282961028008818394260E-4082 5.397949295066414805140044091971298E-4083 + 6781 2.698974647533207402570022045985649E-4083 1.349487323766603701285011022992825E-4083 + 6782 6.747436618833018506425055114964125E-4084 3.373718309416509253212527557482063E-4084 + 6783 1.686859154708254626606263778741032E-4084 8.434295773541273133031318893705158E-4085 + 6784 4.217147886770636566515659446852579E-4085 2.108573943385318283257829723426290E-4085 + 6785 1.054286971692659141628914861713145E-4085 5.271434858463295708144574308565725E-4086 + 6786 2.635717429231647854072287154282863E-4086 1.317858714615823927036143577141431E-4086 + 6787 6.589293573079119635180717885707155E-4087 3.294646786539559817590358942853578E-4087 + 6788 1.647323393269779908795179471426789E-4087 8.236616966348899543975897357133945E-4088 + 6789 4.118308483174449771987948678566973E-4088 2.059154241587224885993974339283486E-4088 + 6790 1.029577120793612442996987169641743E-4088 5.147885603968062214984935848208715E-4089 + 6791 2.573942801984031107492467924104358E-4089 1.286971400992015553746233962052179E-4089 + 6792 6.434857004960077768731169810260895E-4090 3.217428502480038884365584905130448E-4090 + 6793 1.608714251240019442182792452565224E-4090 8.04357125620009721091396226282612E-4091 + 6794 4.02178562810004860545698113141306E-4091 2.01089281405002430272849056570653E-4091 + 6795 1.005446407025012151364245282853265E-4091 5.027232035125060756821226414266325E-4092 + 6796 2.513616017562530378410613207133163E-4092 1.256808008781265189205306603566581E-4092 + 6797 6.284040043906325946026533017832905E-4093 3.142020021953162973013266508916453E-4093 + 6798 1.571010010976581486506633254458227E-4093 7.855050054882907432533166272291133E-4094 + 6799 3.927525027441453716266583136145567E-4094 1.963762513720726858133291568072783E-4094 + 6800 9.818812568603634290666457840363915E-4095 4.909406284301817145333228920181958E-4095 + 6801 2.454703142150908572666614460090979E-4095 1.227351571075454286333307230045490E-4095 + 6802 6.13675785537727143166653615022745E-4096 3.068378927688635715833268075113725E-4096 + 6803 1.534189463844317857916634037556863E-4096 7.670947319221589289583170187784313E-4097 + 6804 3.835473659610794644791585093892157E-4097 1.917736829805397322395792546946078E-4097 + 6805 9.58868414902698661197896273473039E-4098 4.794342074513493305989481367365195E-4098 + 6806 2.397171037256746652994740683682598E-4098 1.198585518628373326497370341841299E-4098 + 6807 5.992927593141866632486851709206495E-4099 2.996463796570933316243425854603248E-4099 + 6808 1.498231898285466658121712927301624E-4099 7.49115949142733329060856463650812E-4100 + 6809 3.74557974571366664530428231825406E-4100 1.87278987285683332265214115912703E-4100 + 6810 9.36394936428416661326070579563515E-4101 4.681974682142083306630352897817575E-4101 + 6811 2.340987341071041653315176448908788E-4101 1.170493670535520826657588224454394E-4101 + 6812 5.85246835267760413328794112227197E-4102 2.926234176338802066643970561135985E-4102 + 6813 1.463117088169401033321985280567993E-4102 7.315585440847005166609926402839963E-4103 + 6814 3.657792720423502583304963201419982E-4103 1.828896360211751291652481600709991E-4103 + 6815 9.144481801058756458262408003549955E-4104 4.572240900529378229131204001774978E-4104 + 6816 2.286120450264689114565602000887489E-4104 1.143060225132344557282801000443745E-4104 + 6817 5.715301125661722786414005002218725E-4105 2.857650562830861393207002501109363E-4105 + 6818 1.428825281415430696603501250554682E-4105 7.144126407077153483017506252773408E-4106 + 6819 3.572063203538576741508753126386704E-4106 1.786031601769288370754376563193352E-4106 + 6820 8.93015800884644185377188281596676E-4107 4.46507900442322092688594140798338E-4107 + 6821 2.23253950221161046344297070399169E-4107 1.116269751105805231721485351995845E-4107 + 6822 5.581348755529026158607426759979225E-4108 2.790674377764513079303713379989613E-4108 + 6823 1.395337188882256539651856689994807E-4108 6.976685944411282698259283449974033E-4109 + 6824 3.488342972205641349129641724987017E-4109 1.744171486102820674564820862493508E-4109 + 6825 8.72085743051410337282410431246754E-4110 4.36042871525705168641205215623377E-4110 + 6826 2.180214357628525843206026078116885E-4110 1.090107178814262921603013039058443E-4110 + 6827 5.450535894071314608015065195292215E-4111 2.725267947035657304007532597646108E-4111 + 6828 1.362633973517828652003766298823054E-4111 6.81316986758914326001883149411527E-4112 + 6829 3.406584933794571630009415747057635E-4112 1.703292466897285815004707873528818E-4112 + 6830 8.51646233448642907502353936764409E-4113 4.258231167243214537511769683822045E-4113 + 6831 2.129115583621607268755884841911023E-4113 1.064557791810803634377942420955511E-4113 + 6832 5.322788959054018171889712104777555E-4114 2.661394479527009085944856052388778E-4114 + 6833 1.330697239763504542972428026194389E-4114 6.653486198817522714862140130971945E-4115 + 6834 3.326743099408761357431070065485973E-4115 1.663371549704380678715535032742986E-4115 + 6835 8.31685774852190339357767516371493E-4116 4.158428874260951696788837581857465E-4116 + 6836 2.079214437130475848394418790928733E-4116 1.039607218565237924197209395464366E-4116 + 6837 5.19803609282618962098604697732183E-4117 2.599018046413094810493023488660915E-4117 + 6838 1.299509023206547405246511744330458E-4117 6.497545116032737026232558721652288E-4118 + 6839 3.248772558016368513116279360826144E-4118 1.624386279008184256558139680413072E-4118 + 6840 8.12193139504092128279069840206536E-4119 4.06096569752046064139534920103268E-4119 + 6841 2.03048284876023032069767460051634E-4119 1.01524142438011516034883730025817E-4119 + 6842 5.07620712190057580174418650129085E-4120 2.538103560950287900872093250645425E-4120 + 6843 1.269051780475143950436046625322713E-4120 6.345258902375719752180233126613563E-4121 + 6844 3.172629451187859876090116563306782E-4121 1.586314725593929938045058281653391E-4121 + 6845 7.931573627969649690225291408266955E-4122 3.965786813984824845112645704133478E-4122 + 6846 1.982893406992412422556322852066739E-4122 9.914467034962062112781614260333695E-4123 + 6847 4.957233517481031056390807130166848E-4123 2.478616758740515528195403565083424E-4123 + 6848 1.239308379370257764097701782541712E-4123 6.19654189685128882048850891270856E-4124 + 6849 3.09827094842564441024425445635428E-4124 1.54913547421282220512212722817714E-4124 + 6850 7.7456773710641110256106361408857E-4125 3.87283868553205551280531807044285E-4125 + 6851 1.936419342766027756402659035221425E-4125 9.682096713830138782013295176107125E-4126 + 6852 4.841048356915069391006647588053563E-4126 2.420524178457534695503323794026781E-4126 + 6853 1.210262089228767347751661897013391E-4126 6.051310446143836738758309485066953E-4127 + 6854 3.025655223071918369379154742533477E-4127 1.512827611535959184689577371266738E-4127 + 6855 7.56413805767979592344788685633369E-4128 3.782069028839897961723943428166845E-4128 + 6856 1.891034514419948980861971714083423E-4128 9.455172572099744904309858570417113E-4129 + 6857 4.727586286049872452154929285208557E-4129 2.363793143024936226077464642604278E-4129 + 6858 1.181896571512468113038732321302139E-4129 5.909482857562340565193661606510695E-4130 + 6859 2.954741428781170282596830803255348E-4130 1.477370714390585141298415401627674E-4130 + 6860 7.38685357195292570649207700813837E-4131 3.693426785976462853246038504069185E-4131 + 6861 1.846713392988231426623019252034593E-4131 9.233566964941157133115096260172963E-4132 + 6862 4.616783482470578566557548130086482E-4132 2.308391741235289283278774065043241E-4132 + 6863 1.154195870617644641639387032521621E-4132 5.770979353088223208196935162608103E-4133 + 6864 2.885489676544111604098467581304052E-4133 1.442744838272055802049233790652026E-4133 + 6865 7.21372419136027901024616895326013E-4134 3.606862095680139505123084476630065E-4134 + 6866 1.803431047840069752561542238315033E-4134 9.017155239200348762807711191575163E-4135 + 6867 4.508577619600174381403855595787582E-4135 2.254288809800087190701927797893791E-4135 + 6868 1.127144404900043595350963898946896E-4135 5.635722024500217976754819494734478E-4136 + 6869 2.817861012250108988377409747367239E-4136 1.408930506125054494188704873683620E-4136 + 6870 7.04465253062527247094352436841810E-4137 3.52232626531263623547176218420905E-4137 + 6871 1.761163132656318117735881092104525E-4137 8.805815663281590588679405460522625E-4138 + 6872 4.402907831640795294339702730261313E-4138 2.201453915820397647169851365130656E-4138 + 6873 1.100726957910198823584925682565328E-4138 5.50363478955099411792462841282664E-4139 + 6874 2.75181739477549705896231420641332E-4139 1.37590869738774852948115710320666E-4139 + 6875 6.8795434869387426474057855160333E-4140 3.43977174346937132370289275801665E-4140 + 6876 1.719885871734685661851446379008325E-4140 8.599429358673428309257231895041625E-4141 + 6877 4.299714679336714154628615947520813E-4141 2.149857339668357077314307973760406E-4141 + 6878 1.074928669834178538657153986880203E-4141 5.374643349170892693285769934401015E-4142 + 6879 2.687321674585446346642884967200508E-4142 1.343660837292723173321442483600254E-4142 + 6880 6.71830418646361586660721241800127E-4143 3.359152093231807933303606209000635E-4143 + 6881 1.679576046615903966651803104500318E-4143 8.397880233079519833259015522501588E-4144 + 6882 4.198940116539759916629507761250794E-4144 2.099470058269879958314753880625397E-4144 + 6883 1.049735029134939979157376940312699E-4144 5.248675145674699895786884701563493E-4145 + 6884 2.624337572837349947893442350781747E-4145 1.312168786418674973946721175390873E-4145 + 6885 6.560843932093374869733605876954365E-4146 3.280421966046687434866802938477183E-4146 + 6886 1.640210983023343717433401469238592E-4146 8.201054915116718587167007346192958E-4147 + 6887 4.100527457558359293583503673096479E-4147 2.050263728779179646791751836548240E-4147 + 6888 1.025131864389589823395875918274120E-4147 5.12565932194794911697937959137060E-4148 + 6889 2.56282966097397455848968979568530E-4148 1.28141483048698727924484489784265E-4148 + 6890 6.40707415243493639622422448921325E-4149 3.203537076217468198112112244606625E-4149 + 6891 1.601768538108734099056056122303313E-4149 8.008842690543670495280280611516563E-4150 + 6892 4.004421345271835247640140305758282E-4150 2.002210672635917623820070152879141E-4150 + 6893 1.001105336317958811910035076439571E-4150 5.005526681589794059550175382197853E-4151 + 6894 2.502763340794897029775087691098927E-4151 1.251381670397448514887543845549463E-4151 + 6895 6.256908351987242574437719227747315E-4152 3.128454175993621287218859613873658E-4152 + 6896 1.564227087996810643609429806936829E-4152 7.821135439984053218047149034684145E-4153 + 6897 3.910567719992026609023574517342073E-4153 1.955283859996013304511787258671036E-4153 + 6898 9.77641929998006652255893629335518E-4154 4.88820964999003326127946814667759E-4154 + 6899 2.444104824995016630639734073338795E-4154 1.222052412497508315319867036669398E-4154 + 6900 6.11026206248754157659933518334699E-4155 3.055131031243770788299667591673495E-4155 + 6901 1.527565515621885394149833795836748E-4155 7.637827578109426970749168979183738E-4156 + 6902 3.818913789054713485374584489591869E-4156 1.909456894527356742687292244795935E-4156 + 6903 9.547284472636783713436461223979675E-4157 4.773642236318391856718230611989838E-4157 + 6904 2.386821118159195928359115305994919E-4157 1.193410559079597964179557652997460E-4157 + 6905 5.96705279539798982089778826498730E-4158 2.98352639769899491044889413249365E-4158 + 6906 1.491763198849497455224447066246825E-4158 7.458815994247487276122235331234125E-4159 + 6907 3.729407997123743638061117665617063E-4159 1.864703998561871819030558832808531E-4159 + 6908 9.323519992809359095152794164042655E-4160 4.661759996404679547576397082021328E-4160 + 6909 2.330879998202339773788198541010664E-4160 1.165439999101169886894099270505332E-4160 + 6910 5.82719999550584943447049635252666E-4161 2.91359999775292471723524817626333E-4161 + 6911 1.456799998876462358617624088131665E-4161 7.283999994382311793088120440658325E-4162 + 6912 3.641999997191155896544060220329163E-4162 1.820999998595577948272030110164581E-4162 + 6913 9.104999992977889741360150550822905E-4163 4.552499996488944870680075275411453E-4163 + 6914 2.276249998244472435340037637705727E-4163 1.138124999122236217670018818852863E-4163 + 6915 5.690624995611181088350094094264315E-4164 2.845312497805590544175047047132158E-4164 + 6916 1.422656248902795272087523523566079E-4164 7.113281244513976360437617617830395E-4165 + 6917 3.556640622256988180218808808915198E-4165 1.778320311128494090109404404457599E-4165 + 6918 8.891601555642470450547022022287995E-4166 4.445800777821235225273511011143998E-4166 + 6919 2.222900388910617612636755505571999E-4166 1.111450194455308806318377752786000E-4166 + 6920 5.55725097227654403159188876393000E-4167 2.77862548613827201579594438196500E-4167 + 6921 1.38931274306913600789797219098250E-4167 6.9465637153456800394898609549125E-4168 + 6922 3.47328185767284001974493047745625E-4168 1.736640928836420009872465238728125E-4168 + 6923 8.683204644182100049362326193640625E-4169 4.341602322091050024681163096820313E-4169 + 6924 2.170801161045525012340581548410157E-4169 1.085400580522762506170290774205078E-4169 + 6925 5.42700290261381253085145387102539E-4170 2.713501451306906265425726935512695E-4170 + 6926 1.356750725653453132712863467756348E-4170 6.783753628267265663564317338781738E-4171 + 6927 3.391876814133632831782158669390869E-4171 1.695938407066816415891079334695435E-4171 + 6928 8.479692035334082079455396673477175E-4172 4.239846017667041039727698336738588E-4172 + 6929 2.119923008833520519863849168369294E-4172 1.059961504416760259931924584184647E-4172 + 6930 5.299807522083801299659622920923235E-4173 2.649903761041900649829811460461618E-4173 + 6931 1.324951880520950324914905730230809E-4173 6.624759402604751624574528651154045E-4174 + 6932 3.312379701302375812287264325577023E-4174 1.656189850651187906143632162788511E-4174 + 6933 8.280949253255939530718160813942555E-4175 4.140474626627969765359080406971278E-4175 + 6934 2.070237313313984882679540203485639E-4175 1.035118656656992441339770101742820E-4175 + 6935 5.17559328328496220669885050871410E-4176 2.58779664164248110334942525435705E-4176 + 6936 1.293898320821240551674712627178525E-4176 6.469491604106202758373563135892625E-4177 + 6937 3.234745802053101379186781567946313E-4177 1.617372901026550689593390783973156E-4177 + 6938 8.08686450513275344796695391986578E-4178 4.04343225256637672398347695993289E-4178 + 6939 2.021716126283188361991738479966445E-4178 1.010858063141594180995869239983223E-4178 + 6940 5.054290315707970904979346199916115E-4179 2.527145157853985452489673099958058E-4179 + 6941 1.263572578926992726244836549979029E-4179 6.317862894634963631224182749895145E-4180 + 6942 3.158931447317481815612091374947573E-4180 1.579465723658740907806045687473786E-4180 + 6943 7.89732861829370453903022843736893E-4181 3.948664309146852269515114218684465E-4181 + 6944 1.974332154573426134757557109342233E-4181 9.871660772867130673787785546711163E-4182 + 6945 4.935830386433565336893892773355582E-4182 2.467915193216782668446946386677791E-4182 + 6946 1.233957596608391334223473193338896E-4182 6.169787983041956671117365966694478E-4183 + 6947 3.084893991520978335558682983347239E-4183 1.542446995760489167779341491673620E-4183 + 6948 7.71223497880244583889670745836810E-4184 3.85611748940122291944835372918405E-4184 + 6949 1.928058744700611459724176864592025E-4184 9.640293723503057298620884322960125E-4185 + 6950 4.820146861751528649310442161480063E-4185 2.410073430875764324655221080740031E-4185 + 6951 1.205036715437882162327610540370016E-4185 6.025183577189410811638052701850078E-4186 + 6952 3.012591788594705405819026350925039E-4186 1.506295894297352702909513175462520E-4186 + 6953 7.53147947148676351454756587731260E-4187 3.76573973574338175727378293865630E-4187 + 6954 1.88286986787169087863689146932815E-4187 9.41434933935845439318445734664075E-4188 + 6955 4.707174669679227196592228673320375E-4188 2.353587334839613598296114336660188E-4188 + 6956 1.176793667419806799148057168330094E-4188 5.88396833709903399574028584165047E-4189 + 6957 2.941984168549516997870142920825235E-4189 1.470992084274758498935071460412618E-4189 + 6958 7.35496042137379249467535730206309E-4190 3.677480210686896247337678651031545E-4190 + 6959 1.838740105343448123668839325515773E-4190 9.193700526717240618344196627578863E-4191 + 6960 4.596850263358620309172098313789432E-4191 2.298425131679310154586049156894716E-4191 + 6961 1.149212565839655077293024578447358E-4191 5.74606282919827538646512289223679E-4192 + 6962 2.873031414599137693232561446118395E-4192 1.436515707299568846616280723059198E-4192 + 6963 7.18257853649784423308140361529599E-4193 3.591289268248922116540701807647995E-4193 + 6964 1.795644634124461058270350903823998E-4193 8.978223170622305291351754519119988E-4194 + 6965 4.489111585311152645675877259559994E-4194 2.244555792655576322837938629779997E-4194 + 6966 1.122277896327788161418969314889999E-4194 5.611389481638940807094846574449993E-4195 + 6967 2.805694740819470403547423287224997E-4195 1.402847370409735201773711643612498E-4195 + 6968 7.01423685204867600886855821806249E-4196 3.507118426024338004434279109031245E-4196 + 6969 1.753559213012169002217139554515623E-4196 8.767796065060845011085697772578113E-4197 + 6970 4.383898032530422505542848886289057E-4197 2.191949016265211252771424443144528E-4197 + 6971 1.095974508132605626385712221572264E-4197 5.47987254066302813192856110786132E-4198 + 6972 2.73993627033151406596428055393066E-4198 1.36996813516575703298214027696533E-4198 + 6973 6.84984067582878516491070138482665E-4199 3.424920337914392582455350692413325E-4199 + 6974 1.712460168957196291227675346206663E-4199 8.562300844785981456138376731033313E-4200 + 6975 4.281150422392990728069188365516657E-4200 2.140575211196495364034594182758328E-4200 + 6976 1.070287605598247682017297091379164E-4200 5.35143802799123841008648545689582E-4201 + 6977 2.67571901399561920504324272844791E-4201 1.337859506997809602521621364223955E-4201 + 6978 6.689297534989048012608106821119775E-4202 3.344648767494524006304053410559888E-4202 + 6979 1.672324383747262003152026705279944E-4202 8.36162191873631001576013352639972E-4203 + 6980 4.18081095936815500788006676319986E-4203 2.09040547968407750394003338159993E-4203 + 6981 1.045202739842038751970016690799965E-4203 5.226013699210193759850083453999825E-4204 + 6982 2.613006849605096879925041726999913E-4204 1.306503424802548439962520863499956E-4204 + 6983 6.53251712401274219981260431749978E-4205 3.26625856200637109990630215874989E-4205 + 6984 1.633129281003185549953151079374945E-4205 8.165646405015927749765755396874725E-4206 + 6985 4.082823202507963874882877698437363E-4206 2.041411601253981937441438849218681E-4206 + 6986 1.020705800626990968720719424609341E-4206 5.103529003134954843603597123046703E-4207 + 6987 2.551764501567477421801798561523352E-4207 1.275882250783738710900899280761676E-4207 + 6988 6.37941125391869355450449640380838E-4208 3.18970562695934677725224820190419E-4208 + 6989 1.594852813479673388626124100952095E-4208 7.974264067398366943130620504760475E-4209 + 6990 3.987132033699183471565310252380238E-4209 1.993566016849591735782655126190119E-4209 + 6991 9.967830084247958678913275630950595E-4210 4.983915042123979339456637815475298E-4210 + 6992 2.491957521061989669728318907737649E-4210 1.245978760530994834864159453868825E-4210 + 6993 6.229893802654974174320797269344125E-4211 3.114946901327487087160398634672063E-4211 + 6994 1.557473450663743543580199317336032E-4211 7.787367253318717717900996586680158E-4212 + 6995 3.893683626659358858950498293340079E-4212 1.946841813329679429475249146670040E-4212 + 6996 9.73420906664839714737624573335020E-4213 4.86710453332419857368812286667510E-4213 + 6997 2.43355226666209928684406143333755E-4213 1.216776133331049643422030716668775E-4213 + 6998 6.083880666655248217110153583343875E-4214 3.041940333327624108555076791671938E-4214 + 6999 1.520970166663812054277538395835969E-4214 7.604850833319060271387691979179845E-4215 + 7000 3.802425416659530135693845989589923E-4215 1.901212708329765067846922994794961E-4215 + 7001 9.506063541648825339234614973974805E-4216 4.753031770824412669617307486987403E-4216 + 7002 2.376515885412206334808653743493702E-4216 1.188257942706103167404326871746851E-4216 + 7003 5.941289713530515837021634358734255E-4217 2.970644856765257918510817179367128E-4217 + 7004 1.485322428382628959255408589683564E-4217 7.42661214191314479627704294841782E-4218 + 7005 3.71330607095657239813852147420891E-4218 1.856653035478286199069260737104455E-4218 + 7006 9.283265177391430995346303685522275E-4219 4.641632588695715497673151842761138E-4219 + 7007 2.320816294347857748836575921380569E-4219 1.160408147173928874418287960690285E-4219 + 7008 5.802040735869644372091439803451425E-4220 2.901020367934822186045719901725713E-4220 + 7009 1.450510183967411093022859950862857E-4220 7.252550919837055465114299754314283E-4221 + 7010 3.626275459918527732557149877157142E-4221 1.813137729959263866278574938578571E-4221 + 7011 9.065688649796319331392874692892855E-4222 4.532844324898159665696437346446428E-4222 + 7012 2.266422162449079832848218673223214E-4222 1.133211081224539916424109336611607E-4222 + 7013 5.666055406122699582120546683058035E-4223 2.833027703061349791060273341529018E-4223 + 7014 1.416513851530674895530136670764509E-4223 7.082569257653374477650683353822545E-4224 + 7015 3.541284628826687238825341676911273E-4224 1.770642314413343619412670838455636E-4224 + 7016 8.85321157206671809706335419227818E-4225 4.42660578603335904853167709613909E-4225 + 7017 2.213302893016679524265838548069545E-4225 1.106651446508339762132919274034773E-4225 + 7018 5.533257232541698810664596370173865E-4226 2.766628616270849405332298185086933E-4226 + 7019 1.383314308135424702666149092543467E-4226 6.916571540677123513330745462717333E-4227 + 7020 3.458285770338561756665372731358667E-4227 1.729142885169280878332686365679333E-4227 + 7021 8.645714425846404391663431828396665E-4228 4.322857212923202195831715914198333E-4228 + 7022 2.161428606461601097915857957099167E-4228 1.080714303230800548957928978549583E-4228 + 7023 5.403571516154002744789644892747915E-4229 2.701785758077001372394822446373958E-4229 + 7024 1.350892879038500686197411223186979E-4229 6.754464395192503430987056115934895E-4230 + 7025 3.377232197596251715493528057967448E-4230 1.688616098798125857746764028983724E-4230 + 7026 8.44308049399062928873382014491862E-4231 4.22154024699531464436691007245931E-4231 + 7027 2.110770123497657322183455036229655E-4231 1.055385061748828661091727518114828E-4231 + 7028 5.27692530874414330545863759057414E-4232 2.63846265437207165272931879528707E-4232 + 7029 1.319231327186035826364659397643535E-4232 6.596156635930179131823296988217675E-4233 + 7030 3.298078317965089565911648494108838E-4233 1.649039158982544782955824247054419E-4233 + 7031 8.245195794912723914779121235272095E-4234 4.122597897456361957389560617636048E-4234 + 7032 2.061298948728180978694780308818024E-4234 1.030649474364090489347390154409012E-4234 + 7033 5.15324737182045244673695077204506E-4235 2.57662368591022622336847538602253E-4235 + 7034 1.288311842955113111684237693011265E-4235 6.441559214775565558421188465056325E-4236 + 7035 3.220779607387782779210594232528163E-4236 1.610389803693891389605297116264081E-4236 + 7036 8.051949018469456948026485581320405E-4237 4.025974509234728474013242790660203E-4237 + 7037 2.012987254617364237006621395330102E-4237 1.006493627308682118503310697665051E-4237 + 7038 5.032468136543410592516553488325255E-4238 2.516234068271705296258276744162628E-4238 + 7039 1.258117034135852648129138372081314E-4238 6.29058517067926324064569186040657E-4239 + 7040 3.145292585339631620322845930203285E-4239 1.572646292669815810161422965101643E-4239 + 7041 7.863231463349079050807114825508215E-4240 3.931615731674539525403557412754108E-4240 + 7042 1.965807865837269762701778706377054E-4240 9.82903932918634881350889353188527E-4241 + 7043 4.914519664593174406754446765942635E-4241 2.457259832296587203377223382971318E-4241 + 7044 1.228629916148293601688611691485659E-4241 6.143149580741468008443058457428295E-4242 + 7045 3.071574790370734004221529228714148E-4242 1.535787395185367002110764614357074E-4242 + 7046 7.67893697592683501055382307178537E-4243 3.839468487963417505276911535892685E-4243 + 7047 1.919734243981708752638455767946343E-4243 9.598671219908543763192278839731713E-4244 + 7048 4.799335609954271881596139419865857E-4244 2.399667804977135940798069709932928E-4244 + 7049 1.199833902488567970399034854966464E-4244 5.99916951244283985199517427483232E-4245 + 7050 2.99958475622141992599758713741616E-4245 1.49979237811070996299879356870808E-4245 + 7051 7.4989618905535498149939678435404E-4246 3.7494809452767749074969839217702E-4246 + 7052 1.8747404726383874537484919608851E-4246 9.3737023631919372687424598044255E-4247 + 7053 4.68685118159596863437122990221275E-4247 2.343425590797984317185614951106375E-4247 + 7054 1.171712795398992158592807475553188E-4247 5.858563976994960792964037377765938E-4248 + 7055 2.929281988497480396482018688882969E-4248 1.464640994248740198241009344441485E-4248 + 7056 7.323204971243700991205046722207425E-4249 3.661602485621850495602523361103713E-4249 + 7057 1.830801242810925247801261680551857E-4249 9.154006214054626239006308402759283E-4250 + 7058 4.577003107027313119503154201379642E-4250 2.288501553513656559751577100689821E-4250 + 7059 1.144250776756828279875788550344911E-4250 5.721253883784141399378942751724553E-4251 + 7060 2.860626941892070699689471375862277E-4251 1.430313470946035349844735687931138E-4251 + 7061 7.15156735473017674922367843965569E-4252 3.575783677365088374611839219827845E-4252 + 7062 1.787891838682544187305919609913923E-4252 8.939459193412720936529598049569613E-4253 + 7063 4.469729596706360468264799024784807E-4253 2.234864798353180234132399512392403E-4253 + 7064 1.117432399176590117066199756196202E-4253 5.587161995882950585330998780981008E-4254 + 7065 2.793580997941475292665499390490504E-4254 1.396790498970737646332749695245252E-4254 + 7066 6.98395249485368823166374847622626E-4255 3.49197624742684411583187423811313E-4255 + 7067 1.745988123713422057915937119056565E-4255 8.729940618567110289579685595282825E-4256 + 7068 4.364970309283555144789842797641413E-4256 2.182485154641777572394921398820706E-4256 + 7069 1.091242577320888786197460699410353E-4256 5.456212886604443930987303497051765E-4257 + 7070 2.728106443302221965493651748525883E-4257 1.364053221651110982746825874262941E-4257 + 7071 6.820266108255554913734129371314705E-4258 3.410133054127777456867064685657353E-4258 + 7072 1.705066527063888728433532342828677E-4258 8.525332635319443642167661714143383E-4259 + 7073 4.262666317659721821083830857071692E-4259 2.131333158829860910541915428535846E-4259 + 7074 1.065666579414930455270957714267923E-4259 5.328332897074652276354788571339615E-4260 + 7075 2.664166448537326138177394285669808E-4260 1.332083224268663069088697142834904E-4260 + 7076 6.66041612134331534544348571417452E-4261 3.33020806067165767272174285708726E-4261 + 7077 1.66510403033582883636087142854363E-4261 8.32552015167914418180435714271815E-4262 + 7078 4.162760075839572090902178571359075E-4262 2.081380037919786045451089285679538E-4262 + 7079 1.040690018959893022725544642839769E-4262 5.203450094799465113627723214198845E-4263 + 7080 2.601725047399732556813861607099423E-4263 1.300862523699866278406930803549711E-4263 + 7081 6.504312618499331392034654017748555E-4264 3.252156309249665696017327008874278E-4264 + 7082 1.626078154624832848008663504437139E-4264 8.130390773124164240043317522185695E-4265 + 7083 4.065195386562082120021658761092848E-4265 2.032597693281041060010829380546424E-4265 + 7084 1.016298846640520530005414690273212E-4265 5.08149423320260265002707345136606E-4266 + 7085 2.54074711660130132501353672568303E-4266 1.270373558300650662506768362841515E-4266 + 7086 6.351867791503253312533841814207575E-4267 3.175933895751626656266920907103788E-4267 + 7087 1.587966947875813328133460453551894E-4267 7.93983473937906664066730226775947E-4268 + 7088 3.969917369689533320333651133879735E-4268 1.984958684844766660166825566939868E-4268 + 7089 9.92479342422383330083412783469934E-4269 4.96239671211191665041706391734967E-4269 + 7090 2.481198356055958325208531958674835E-4269 1.240599178027979162604265979337418E-4269 + 7091 6.20299589013989581302132989668709E-4270 3.101497945069947906510664948343545E-4270 + 7092 1.550748972534973953255332474171773E-4270 7.753744862674869766276662370858863E-4271 + 7093 3.876872431337434883138331185429432E-4271 1.938436215668717441569165592714716E-4271 + 7094 9.69218107834358720784582796357358E-4272 4.84609053917179360392291398178679E-4272 + 7095 2.423045269585896801961456990893395E-4272 1.211522634792948400980728495446698E-4272 + 7096 6.05761317396474200490364247723349E-4273 3.028806586982371002451821238616745E-4273 + 7097 1.514403293491185501225910619308373E-4273 7.572016467455927506129553096541863E-4274 + 7098 3.786008233727963753064776548270932E-4274 1.893004116863981876532388274135466E-4274 + 7099 9.46502058431990938266194137067733E-4275 4.732510292159954691330970685338665E-4275 + 7100 2.366255146079977345665485342669333E-4275 1.183127573039988672832742671334666E-4275 + 7101 5.91563786519994336416371335667333E-4276 2.957818932599971682081856678336665E-4276 + 7102 1.478909466299985841040928339168333E-4276 7.394547331499929205204641695841663E-4277 + 7103 3.697273665749964602602320847920832E-4277 1.848636832874982301301160423960416E-4277 + 7104 9.24318416437491150650580211980208E-4278 4.62159208218745575325290105990104E-4278 + 7105 2.31079604109372787662645052995052E-4278 1.15539802054686393831322526497526E-4278 + 7106 5.7769901027343196915661263248763E-4279 2.88849505136715984578306316243815E-4279 + 7107 1.444247525683579922891531581219075E-4279 7.221237628417899614457657906095375E-4280 + 7108 3.610618814208949807228828953047688E-4280 1.805309407104474903614414476523844E-4280 + 7109 9.02654703552237451807207238261922E-4281 4.51327351776118725903603619130961E-4281 + 7110 2.256636758880593629518018095654805E-4281 1.128318379440296814759009047827403E-4281 + 7111 5.641591897201484073795045239137015E-4282 2.820795948600742036897522619568508E-4282 + 7112 1.410397974300371018448761309784254E-4282 7.05198987150185509224380654892127E-4283 + 7113 3.525994935750927546121903274460635E-4283 1.762997467875463773060951637230318E-4283 + 7114 8.81498733937731886530475818615159E-4284 4.407493669688659432652379093075795E-4284 + 7115 2.203746834844329716326189546537898E-4284 1.101873417422164858163094773268949E-4284 + 7116 5.509367087110824290815473866344745E-4285 2.754683543555412145407736933172373E-4285 + 7117 1.377341771777706072703868466586187E-4285 6.886708858888530363519342332930933E-4286 + 7118 3.443354429444265181759671166465467E-4286 1.721677214722132590879835583232733E-4286 + 7119 8.608386073610662954399177916163665E-4287 4.304193036805331477199588958081833E-4287 + 7120 2.152096518402665738599794479040917E-4287 1.076048259201332869299897239520458E-4287 + 7121 5.38024129600666434649948619760229E-4288 2.690120648003332173249743098801145E-4288 + 7122 1.345060324001666086624871549400573E-4288 6.725301620008330433124357747002863E-4289 + 7123 3.362650810004165216562178873501432E-4289 1.681325405002082608281089436750716E-4289 + 7124 8.40662702501041304140544718375358E-4290 4.20331351250520652070272359187679E-4290 + 7125 2.101656756252603260351361795938395E-4290 1.050828378126301630175680897969198E-4290 + 7126 5.25414189063150815087840448984599E-4291 2.627070945315754075439202244922995E-4291 + 7127 1.313535472657877037719601122461498E-4291 6.567677363289385188598005612307488E-4292 + 7128 3.283838681644692594299002806153744E-4292 1.641919340822346297149501403076872E-4292 + 7129 8.20959670411173148574750701538436E-4293 4.10479835205586574287375350769218E-4293 + 7130 2.05239917602793287143687675384609E-4293 1.026199588013966435718438376923045E-4293 + 7131 5.130997940069832178592191884615225E-4294 2.565498970034916089296095942307613E-4294 + 7132 1.282749485017458044648047971153807E-4294 6.413747425087290223240239855769033E-4295 + 7133 3.206873712543645111620119927884517E-4295 1.603436856271822555810059963942258E-4295 + 7134 8.01718428135911277905029981971129E-4296 4.008592140679556389525149909855645E-4296 + 7135 2.004296070339778194762574954927823E-4296 1.002148035169889097381287477463911E-4296 + 7136 5.010740175849445486906437387319555E-4297 2.505370087924722743453218693659778E-4297 + 7137 1.252685043962361371726609346829889E-4297 6.263425219811806858633046734149445E-4298 + 7138 3.131712609905903429316523367074723E-4298 1.565856304952951714658261683537361E-4298 + 7139 7.829281524764758573291308417686805E-4299 3.914640762382379286645654208843403E-4299 + 7140 1.957320381191189643322827104421702E-4299 9.786601905955948216614135522108508E-4300 + 7141 4.893300952977974108307067761054254E-4300 2.446650476488987054153533880527127E-4300 + 7142 1.223325238244493527076766940263564E-4300 6.116626191222467635383834701317818E-4301 + 7143 3.058313095611233817691917350658909E-4301 1.529156547805616908845958675329455E-4301 + 7144 7.645782739028084544229793376647275E-4302 3.822891369514042272114896688323638E-4302 + 7145 1.911445684757021136057448344161819E-4302 9.557228423785105680287241720809095E-4303 + 7146 4.778614211892552840143620860404548E-4303 2.389307105946276420071810430202274E-4303 + 7147 1.194653552973138210035905215101137E-4303 5.973267764865691050179526075505685E-4304 + 7148 2.986633882432845525089763037752843E-4304 1.493316941216422762544881518876421E-4304 + 7149 7.466584706082113812724407594382105E-4305 3.733292353041056906362203797191053E-4305 + 7150 1.866646176520528453181101898595527E-4305 9.333230882602642265905509492977633E-4306 + 7151 4.666615441301321132952754746488817E-4306 2.333307720650660566476377373244408E-4306 + 7152 1.166653860325330283238188686622204E-4306 5.83326930162665141619094343311102E-4307 + 7153 2.91663465081332570809547171655551E-4307 1.458317325406662854047735858277755E-4307 + 7154 7.291586627033314270238679291388775E-4308 3.645793313516657135119339645694388E-4308 + 7155 1.822896656758328567559669822847194E-4308 9.11448328379164283779834911423597E-4309 + 7156 4.557241641895821418899174557117985E-4309 2.278620820947910709449587278558993E-4309 + 7157 1.139310410473955354724793639279497E-4309 5.696552052369776773623968196397483E-4310 + 7158 2.848276026184888386811984098198742E-4310 1.424138013092444193405992049099371E-4310 + 7159 7.120690065462220967029960245496855E-4311 3.560345032731110483514980122748428E-4311 + 7160 1.780172516365555241757490061374214E-4311 8.90086258182777620878745030687107E-4312 + 7161 4.450431290913888104393725153435535E-4312 2.225215645456944052196862576717768E-4312 + 7162 1.112607822728472026098431288358884E-4312 5.56303911364236013049215644179442E-4313 + 7163 2.78151955682118006524607822089721E-4313 1.390759778410590032623039110448605E-4313 + 7164 6.953798892052950163115195552243025E-4314 3.476899446026475081557597776121513E-4314 + 7165 1.738449723013237540778798888060757E-4314 8.692248615066187703893994440303783E-4315 + 7166 4.346124307533093851946997220151892E-4315 2.173062153766546925973498610075946E-4315 + 7167 1.086531076883273462986749305037973E-4315 5.432655384416367314933746525189865E-4316 + 7168 2.716327692208183657466873262594933E-4316 1.358163846104091828733436631297466E-4316 + 7169 6.79081923052045914366718315648733E-4317 3.395409615260229571833591578243665E-4317 + 7170 1.697704807630114785916795789121833E-4317 8.488524038150573929583978945609163E-4318 + 7171 4.244262019075286964791989472804582E-4318 2.122131009537643482395994736402291E-4318 + 7172 1.061065504768821741197997368201146E-4318 5.305327523844108705989986841005728E-4319 + 7173 2.652663761922054352994993420502864E-4319 1.326331880961027176497496710251432E-4319 + 7174 6.63165940480513588248748355125716E-4320 3.31582970240256794124374177562858E-4320 + 7175 1.65791485120128397062187088781429E-4320 8.28957425600641985310935443907145E-4321 + 7176 4.144787128003209926554677219535725E-4321 2.072393564001604963277338609767863E-4321 + 7177 1.036196782000802481638669304883932E-4321 5.180983910004012408193346524419658E-4322 + 7178 2.590491955002006204096673262209829E-4322 1.295245977501003102048336631104915E-4322 + 7179 6.476229887505015510241683155524575E-4323 3.238114943752507755120841577762288E-4323 + 7180 1.619057471876253877560420788881144E-4323 8.09528735938126938780210394440572E-4324 + 7181 4.04764367969063469390105197220286E-4324 2.02382183984531734695052598610143E-4324 + 7182 1.011910919922658673475262993050715E-4324 5.059554599613293367376314965253575E-4325 + 7183 2.529777299806646683688157482626788E-4325 1.264888649903323341844078741313394E-4325 + 7184 6.32444324951661670922039370656697E-4326 3.162221624758308354610196853283485E-4326 + 7185 1.581110812379154177305098426641743E-4326 7.905554061895770886525492133208713E-4327 + 7186 3.952777030947885443262746066604357E-4327 1.976388515473942721631373033302178E-4327 + 7187 9.88194257736971360815686516651089E-4328 4.940971288684856804078432583255445E-4328 + 7188 2.470485644342428402039216291627723E-4328 1.235242822171214201019608145813861E-4328 + 7189 6.176214110856071005098040729069305E-4329 3.088107055428035502549020364534653E-4329 + 7190 1.544053527714017751274510182267327E-4329 7.720267638570088756372550911336633E-4330 + 7191 3.860133819285044378186275455668317E-4330 1.930066909642522189093137727834158E-4330 + 7192 9.65033454821261094546568863917079E-4331 4.825167274106305472732844319585395E-4331 + 7193 2.412583637053152736366422159792698E-4331 1.206291818526576368183211079896349E-4331 + 7194 6.031459092632881840916055399481745E-4332 3.015729546316440920458027699740873E-4332 + 7195 1.507864773158220460229013849870437E-4332 7.539323865791102301145069249352183E-4333 + 7196 3.769661932895551150572534624676092E-4333 1.884830966447775575286267312338046E-4333 + 7197 9.42415483223887787643133656169023E-4334 4.712077416119438938215668280845115E-4334 + 7198 2.356038708059719469107834140422558E-4334 1.178019354029859734553917070211279E-4334 + 7199 5.890096770149298672769585351056395E-4335 2.945048385074649336384792675528198E-4335 + 7200 1.472524192537324668192396337764099E-4335 7.362620962686623340961981688820495E-4336 + 7201 3.681310481343311670480990844410248E-4336 1.840655240671655835240495422205124E-4336 + 7202 9.20327620335827917620247711102562E-4337 4.60163810167913958810123855551281E-4337 + 7203 2.300819050839569794050619277756405E-4337 1.150409525419784897025309638878203E-4337 + 7204 5.752047627098924485126548194391015E-4338 2.876023813549462242563274097195508E-4338 + 7205 1.438011906774731121281637048597754E-4338 7.19005953387365560640818524298877E-4339 + 7206 3.595029766936827803204092621494385E-4339 1.797514883468413901602046310747193E-4339 + 7207 8.987574417342069508010231553735965E-4340 4.493787208671034754005115776867983E-4340 + 7208 2.246893604335517377002557888433992E-4340 1.123446802167758688501278944216996E-4340 + 7209 5.61723401083879344250639472108498E-4341 2.80861700541939672125319736054249E-4341 + 7210 1.404308502709698360626598680271245E-4341 7.021542513548491803132993401356225E-4342 + 7211 3.510771256774245901566496700678113E-4342 1.755385628387122950783248350339056E-4342 + 7212 8.77692814193561475391624175169528E-4343 4.38846407096780737695812087584764E-4343 + 7213 2.19423203548390368847906043792382E-4343 1.09711601774195184423953021896191E-4343 + 7214 5.48558008870975922119765109480955E-4344 2.742790044354879610598825547404775E-4344 + 7215 1.371395022177439805299412773702388E-4344 6.856975110887199026497063868511938E-4345 + 7216 3.428487555443599513248531934255969E-4345 1.714243777721799756624265967127985E-4345 + 7217 8.571218888608998783121329835639925E-4346 4.285609444304499391560664917819963E-4346 + 7218 2.142804722152249695780332458909982E-4346 1.071402361076124847890166229454991E-4346 + 7219 5.357011805380624239450831147274955E-4347 2.678505902690312119725415573637478E-4347 + 7220 1.339252951345156059862707786818739E-4347 6.696264756725780299313538934093695E-4348 + 7221 3.348132378362890149656769467046848E-4348 1.674066189181445074828384733523424E-4348 + 7222 8.37033094590722537414192366761712E-4349 4.18516547295361268707096183380856E-4349 + 7223 2.09258273647680634353548091690428E-4349 1.04629136823840317176774045845214E-4349 + 7224 5.2314568411920158588387022922607E-4350 2.61572842059600792941935114613035E-4350 + 7225 1.307864210298003964709675573065175E-4350 6.539321051490019823548377865325875E-4351 + 7226 3.269660525745009911774188932662938E-4351 1.634830262872504955887094466331469E-4351 + 7227 8.174151314362524779435472331657345E-4352 4.087075657181262389717736165828673E-4352 + 7228 2.043537828590631194858868082914337E-4352 1.021768914295315597429434041457168E-4352 + 7229 5.10884457147657798714717020728584E-4353 2.55442228573828899357358510364292E-4353 + 7230 1.27721114286914449678679255182146E-4353 6.3860557143457224839339627591073E-4354 + 7231 3.19302785717286124196698137955365E-4354 1.596513928586430620983490689776825E-4354 + 7232 7.982569642932153104917453448884125E-4355 3.991284821466076552458726724442063E-4355 + 7233 1.995642410733038276229363362221032E-4355 9.978212053665191381146816811105158E-4356 + 7234 4.989106026832595690573408405552579E-4356 2.494553013416297845286704202776290E-4356 + 7235 1.247276506708148922643352101388145E-4356 6.236382533540744613216760506940725E-4357 + 7236 3.118191266770372306608380253470363E-4357 1.559095633385186153304190126735181E-4357 + 7237 7.795478166925930766520950633675905E-4358 3.897739083462965383260475316837953E-4358 + 7238 1.948869541731482691630237658418977E-4358 9.744347708657413458151188292094883E-4359 + 7239 4.872173854328706729075594146047442E-4359 2.436086927164353364537797073023721E-4359 + 7240 1.218043463582176682268898536511861E-4359 6.090217317910883411344492682559303E-4360 + 7241 3.045108658955441705672246341279652E-4360 1.522554329477720852836123170639826E-4360 + 7242 7.61277164738860426418061585319913E-4361 3.806385823694302132090307926599565E-4361 + 7243 1.903192911847151066045153963299783E-4361 9.515964559235755330225769816498913E-4362 + 7244 4.757982279617877665112884908249457E-4362 2.378991139808938832556442454124728E-4362 + 7245 1.189495569904469416278221227062364E-4362 5.94747784952234708139110613531182E-4363 + 7246 2.97373892476117354069555306765591E-4363 1.486869462380586770347776533827955E-4363 + 7247 7.434347311902933851738882669139775E-4364 3.717173655951466925869441334569888E-4364 + 7248 1.858586827975733462934720667284944E-4364 9.29293413987866731467360333642472E-4365 + 7249 4.64646706993933365733680166821236E-4365 2.32323353496966682866840083410618E-4365 + 7250 1.16161676748483341433420041705309E-4365 5.80808383742416707167100208526545E-4366 + 7251 2.904041918712083535835501042632725E-4366 1.452020959356041767917750521316363E-4366 + 7252 7.260104796780208839588752606581815E-4367 3.630052398390104419794376303290908E-4367 + 7253 1.815026199195052209897188151645454E-4367 9.07513099597526104948594075822727E-4368 + 7254 4.537565497987630524742970379113635E-4368 2.268782748993815262371485189556818E-4368 + 7255 1.134391374496907631185742594778409E-4368 5.671956872484538155928712973892045E-4369 + 7256 2.835978436242269077964356486946023E-4369 1.417989218121134538982178243473011E-4369 + 7257 7.089946090605672694910891217365055E-4370 3.544973045302836347455445608682528E-4370 + 7258 1.772486522651418173727722804341264E-4370 8.86243261325709086863861402170632E-4371 + 7259 4.43121630662854543431930701085316E-4371 2.21560815331427271715965350542658E-4371 + 7260 1.10780407665713635857982675271329E-4371 5.53902038328568179289913376356645E-4372 + 7261 2.769510191642840896449566881783225E-4372 1.384755095821420448224783440891613E-4372 + 7262 6.923775479107102241123917204458065E-4373 3.461887739553551120561958602229033E-4373 + 7263 1.730943869776775560280979301114517E-4373 8.654719348883877801404896505572583E-4374 + 7264 4.327359674441938900702448252786292E-4374 2.163679837220969450351224126393146E-4374 + 7265 1.081839918610484725175612063196573E-4374 5.409199593052423625878060315982865E-4375 + 7266 2.704599796526211812939030157991433E-4375 1.352299898263105906469515078995716E-4375 + 7267 6.76149949131552953234757539497858E-4376 3.38074974565776476617378769748929E-4376 + 7268 1.690374872828882383086893848744645E-4376 8.451874364144411915434469243723225E-4377 + 7269 4.225937182072205957717234621861613E-4377 2.112968591036102978858617310930806E-4377 + 7270 1.056484295518051489429308655465403E-4377 5.282421477590257447146543277327015E-4378 + 7271 2.641210738795128723573271638663508E-4378 1.320605369397564361786635819331754E-4378 + 7272 6.60302684698782180893317909665877E-4379 3.301513423493910904466589548329385E-4379 + 7273 1.650756711746955452233294774164693E-4379 8.253783558734777261166473870823463E-4380 + 7274 4.126891779367388630583236935411732E-4380 2.063445889683694315291618467705866E-4380 + 7275 1.031722944841847157645809233852933E-4380 5.158614724209235788229046169264665E-4381 + 7276 2.579307362104617894114523084632333E-4381 1.289653681052308947057261542316166E-4381 + 7277 6.44826840526154473528630771158083E-4382 3.224134202630772367643153855790415E-4382 + 7278 1.612067101315386183821576927895208E-4382 8.060335506576930919107884639476038E-4383 + 7279 4.030167753288465459553942319738019E-4383 2.015083876644232729776971159869010E-4383 + 7280 1.007541938322116364888485579934505E-4383 5.037709691610581824442427899672525E-4384 + 7281 2.518854845805290912221213949836263E-4384 1.259427422902645456110606974918131E-4384 + 7282 6.297137114513227280553034874590655E-4385 3.148568557256613640276517437295328E-4385 + 7283 1.574284278628306820138258718647664E-4385 7.87142139314153410069129359323832E-4386 + 7284 3.93571069657076705034564679661916E-4386 1.96785534828538352517282339830958E-4386 + 7285 9.8392767414269176258641169915479E-4387 4.91963837071345881293205849577395E-4387 + 7286 2.459819185356729406466029247886975E-4387 1.229909592678364703233014623943488E-4387 + 7287 6.14954796339182351616507311971744E-4388 3.07477398169591175808253655985872E-4388 + 7288 1.53738699084795587904126827992936E-4388 7.6869349542397793952063413996468E-4389 + 7289 3.8434674771198896976031706998234E-4389 1.9217337385599448488015853499117E-4389 + 7290 9.6086686927997242440079267495585E-4390 4.80433434639986212200396337477925E-4390 + 7291 2.402167173199931061001981687389625E-4390 1.201083586599965530500990843694813E-4390 + 7292 6.005417932999827652504954218474065E-4391 3.002708966499913826252477109237033E-4391 + 7293 1.501354483249956913126238554618517E-4391 7.506772416249784565631192773092583E-4392 + 7294 3.753386208124892282815596386546292E-4392 1.876693104062446141407798193273146E-4392 + 7295 9.38346552031223070703899096636573E-4393 4.691732760156115353519495483182865E-4393 + 7296 2.345866380078057676759747741591433E-4393 1.172933190039028838379873870795716E-4393 + 7297 5.86466595019514419189936935397858E-4394 2.93233297509757209594968467698929E-4394 + 7298 1.466166487548786047974842338494645E-4394 7.330832437743930239874211692473225E-4395 + 7299 3.665416218871965119937105846236613E-4395 1.832708109435982559968552923118306E-4395 + 7300 9.16354054717991279984276461559153E-4396 4.581770273589956399921382307795765E-4396 + 7301 2.290885136794978199960691153897883E-4396 1.145442568397489099980345576948941E-4396 + 7302 5.727212841987445499901727884744705E-4397 2.863606420993722749950863942372353E-4397 + 7303 1.431803210496861374975431971186177E-4397 7.159016052484306874877159855930883E-4398 + 7304 3.579508026242153437438579927965442E-4398 1.789754013121076718719289963982721E-4398 + 7305 8.948770065605383593596449819913605E-4399 4.474385032802691796798224909956803E-4399 + 7306 2.237192516401345898399112454978402E-4399 1.118596258200672949199556227489201E-4399 + 7307 5.592981291003364745997781137446005E-4400 2.796490645501682372998890568723003E-4400 + 7308 1.398245322750841186499445284361502E-4400 6.991226613754205932497226421807508E-4401 + 7309 3.495613306877102966248613210903754E-4401 1.747806653438551483124306605451877E-4401 + 7310 8.739033267192757415621533027259385E-4402 4.369516633596378707810766513629693E-4402 + 7311 2.184758316798189353905383256814847E-4402 1.092379158399094676952691628407423E-4402 + 7312 5.461895791995473384763458142037115E-4403 2.730947895997736692381729071018558E-4403 + 7313 1.365473947998868346190864535509279E-4403 6.827369739994341730954322677546395E-4404 + 7314 3.413684869997170865477161338773198E-4404 1.706842434998585432738580669386599E-4404 + 7315 8.534212174992927163692903346932995E-4405 4.267106087496463581846451673466498E-4405 + 7316 2.133553043748231790923225836733249E-4405 1.066776521874115895461612918366625E-4405 + 7317 5.333882609370579477308064591833125E-4406 2.666941304685289738654032295916563E-4406 + 7318 1.333470652342644869327016147958282E-4406 6.667353261713224346635080739791408E-4407 + 7319 3.333676630856612173317540369895704E-4407 1.666838315428306086658770184947852E-4407 + 7320 8.33419157714153043329385092473926E-4408 4.16709578857076521664692546236963E-4408 + 7321 2.083547894285382608323462731184815E-4408 1.041773947142691304161731365592408E-4408 + 7322 5.20886973571345652080865682796204E-4409 2.60443486785672826040432841398102E-4409 + 7323 1.30221743392836413020216420699051E-4409 6.51108716964182065101082103495255E-4410 + 7324 3.255543584820910325505410517476275E-4410 1.627771792410455162752705258738138E-4410 + 7325 8.13885896205227581376352629369069E-4411 4.069429481026137906881763146845345E-4411 + 7326 2.034714740513068953440881573422673E-4411 1.017357370256534476720440786711336E-4411 + 7327 5.08678685128267238360220393355668E-4412 2.54339342564133619180110196677834E-4412 + 7328 1.27169671282066809590055098338917E-4412 6.35848356410334047950275491694585E-4413 + 7329 3.179241782051670239751377458472925E-4413 1.589620891025835119875688729236463E-4413 + 7330 7.948104455129175599378443646182315E-4414 3.974052227564587799689221823091158E-4414 + 7331 1.987026113782293899844610911545579E-4414 9.935130568911469499223054557727895E-4415 + 7332 4.967565284455734749611527278863948E-4415 2.483782642227867374805763639431974E-4415 + 7333 1.241891321113933687402881819715987E-4415 6.209456605569668437014409098579935E-4416 + 7334 3.104728302784834218507204549289968E-4416 1.552364151392417109253602274644984E-4416 + 7335 7.76182075696208554626801137322492E-4417 3.88091037848104277313400568661246E-4417 + 7336 1.94045518924052138656700284330623E-4417 9.70227594620260693283501421653115E-4418 + 7337 4.851137973101303466417507108265575E-4418 2.425568986550651733208753554132788E-4418 + 7338 1.212784493275325866604376777066394E-4418 6.06392246637662933302188388533197E-4419 + 7339 3.031961233188314666510941942665985E-4419 1.515980616594157333255470971332993E-4419 + 7340 7.579903082970786666277354856664965E-4420 3.789951541485393333138677428332483E-4420 + 7341 1.894975770742696666569338714166242E-4420 9.474878853713483332846693570831208E-4421 + 7342 4.737439426856741666423346785415604E-4421 2.368719713428370833211673392707802E-4421 + 7343 1.184359856714185416605836696353901E-4421 5.921799283570927083029183481769505E-4422 + 7344 2.960899641785463541514591740884753E-4422 1.480449820892731770757295870442376E-4422 + 7345 7.40224910446365885378647935221188E-4423 3.70112455223182942689323967610594E-4423 + 7346 1.85056227611591471344661983805297E-4423 9.25281138057957356723309919026485E-4424 + 7347 4.626405690289786783616549595132425E-4424 2.313202845144893391808274797566213E-4424 + 7348 1.156601422572446695904137398783107E-4424 5.783007112862233479520686993915533E-4425 + 7349 2.891503556431116739760343496957767E-4425 1.445751778215558369880171748478883E-4425 + 7350 7.228758891077791849400858742394415E-4426 3.614379445538895924700429371197208E-4426 + 7351 1.807189722769447962350214685598604E-4426 9.03594861384723981175107342799302E-4427 + 7352 4.51797430692361990587553671399651E-4427 2.258987153461809952937768356998255E-4427 + 7353 1.129493576730904976468884178499128E-4427 5.647467883654524882344420892495638E-4428 + 7354 2.823733941827262441172210446247819E-4428 1.411866970913631220586105223123910E-4428 + 7355 7.05933485456815610293052611561955E-4429 3.529667427284078051465263057809775E-4429 + 7356 1.764833713642039025732631528904888E-4429 8.824168568210195128663157644524438E-4430 + 7357 4.412084284105097564331578822262219E-4430 2.206042142052548782165789411131110E-4430 + 7358 1.103021071026274391082894705565555E-4430 5.515105355131371955414473527827775E-4431 + 7359 2.757552677565685977707236763913888E-4431 1.378776338782842988853618381956944E-4431 + 7360 6.89388169391421494426809190978472E-4432 3.44694084695710747213404595489236E-4432 + 7361 1.72347042347855373606702297744618E-4432 8.6173521173927686803351148872309E-4433 + 7362 4.30867605869638434016755744361545E-4433 2.154338029348192170083778721807725E-4433 + 7363 1.077169014674096085041889360903863E-4433 5.385845073370480425209446804519313E-4434 + 7364 2.692922536685240212604723402259657E-4434 1.346461268342620106302361701129828E-4434 + 7365 6.73230634171310053151180850564914E-4435 3.36615317085655026575590425282457E-4435 + 7366 1.683076585428275132877952126412285E-4435 8.415382927141375664389760632061425E-4436 + 7367 4.207691463570687832194880316030713E-4436 2.103845731785343916097440158015356E-4436 + 7368 1.051922865892671958048720079007678E-4436 5.25961432946335979024360039503839E-4437 + 7369 2.629807164731679895121800197519195E-4437 1.314903582365839947560900098759598E-4437 + 7370 6.57451791182919973780450049379799E-4438 3.287258955914599868902250246898995E-4438 + 7371 1.643629477957299934451125123449498E-4438 8.218147389786499672255625617247488E-4439 + 7372 4.109073694893249836127812808623744E-4439 2.054536847446624918063906404311872E-4439 + 7373 1.027268423723312459031953202155936E-4439 5.13634211861656229515976601077968E-4440 + 7374 2.56817105930828114757988300538984E-4440 1.28408552965414057378994150269492E-4440 + 7375 6.4204276482707028689497075134746E-4441 3.2102138241353514344748537567373E-4441 + 7376 1.60510691206767571723742687836865E-4441 8.02553456033837858618713439184325E-4442 + 7377 4.012767280169189293093567195921625E-4442 2.006383640084594646546783597960813E-4442 + 7378 1.003191820042297323273391798980407E-4442 5.015959100211486616366958994902033E-4443 + 7379 2.507979550105743308183479497451017E-4443 1.253989775052871654091739748725508E-4443 + 7380 6.26994887526435827045869874362754E-4444 3.13497443763217913522934937181377E-4444 + 7381 1.567487218816089567614674685906885E-4444 7.837436094080447838073373429534425E-4445 + 7382 3.918718047040223919036686714767213E-4445 1.959359023520111959518343357383606E-4445 + 7383 9.79679511760055979759171678691803E-4446 4.898397558800279898795858393459015E-4446 + 7384 2.449198779400139949397929196729508E-4446 1.224599389700069974698964598364754E-4446 + 7385 6.12299694850034987349482299182377E-4447 3.061498474250174936747411495911885E-4447 + 7386 1.530749237125087468373705747955943E-4447 7.653746185625437341868528739779713E-4448 + 7387 3.826873092812718670934264369889857E-4448 1.913436546406359335467132184944928E-4448 + 7388 9.56718273203179667733566092472464E-4449 4.78359136601589833866783046236232E-4449 + 7389 2.39179568300794916933391523118116E-4449 1.19589784150397458466695761559058E-4449 + 7390 5.9794892075198729233347880779529E-4450 2.98974460375993646166739403897645E-4450 + 7391 1.494872301879968230833697019488225E-4450 7.474361509399841154168485097441125E-4451 + 7392 3.737180754699920577084242548720563E-4451 1.868590377349960288542121274360281E-4451 + 7393 9.342951886749801442710606371801405E-4452 4.671475943374900721355303185900703E-4452 + 7394 2.335737971687450360677651592950352E-4452 1.167868985843725180338825796475176E-4452 + 7395 5.83934492921862590169412898237588E-4453 2.91967246460931295084706449118794E-4453 + 7396 1.45983623230465647542353224559397E-4453 7.29918116152328237711766122796985E-4454 + 7397 3.649590580761641188558830613984925E-4454 1.824795290380820594279415306992463E-4454 + 7398 9.123976451904102971397076534962315E-4455 4.561988225952051485698538267481158E-4455 + 7399 2.280994112976025742849269133740579E-4455 1.140497056488012871424634566870290E-4455 + 7400 5.70248528244006435712317283435145E-4456 2.851242641220032178561586417175725E-4456 + 7401 1.425621320610016089280793208587863E-4456 7.128106603050080446403966042939313E-4457 + 7402 3.564053301525040223201983021469657E-4457 1.782026650762520111600991510734828E-4457 + 7403 8.91013325381260055800495755367414E-4458 4.45506662690630027900247877683707E-4458 + 7404 2.227533313453150139501239388418535E-4458 1.113766656726575069750619694209268E-4458 + 7405 5.56883328363287534875309847104634E-4459 2.78441664181643767437654923552317E-4459 + 7406 1.392208320908218837188274617761585E-4459 6.961041604541094185941373088807925E-4460 + 7407 3.480520802270547092970686544403963E-4460 1.740260401135273546485343272201981E-4460 + 7408 8.701302005676367732426716361009905E-4461 4.350651002838183866213358180504953E-4461 + 7409 2.175325501419091933106679090252477E-4461 1.087662750709545966553339545126238E-4461 + 7410 5.43831375354772983276669772563119E-4462 2.719156876773864916383348862815595E-4462 + 7411 1.359578438386932458191674431407798E-4462 6.797892191934662290958372157038988E-4463 + 7412 3.398946095967331145479186078519494E-4463 1.699473047983665572739593039259747E-4463 + 7413 8.497365239918327863697965196298735E-4464 4.248682619959163931848982598149368E-4464 + 7414 2.124341309979581965924491299074684E-4464 1.062170654989790982962245649537342E-4464 + 7415 5.31085327494895491481122824768671E-4465 2.655426637474477457405614123843355E-4465 + 7416 1.327713318737238728702807061921678E-4465 6.638566593686193643514035309608388E-4466 + 7417 3.319283296843096821757017654804194E-4466 1.659641648421548410878508827402097E-4466 + 7418 8.298208242107742054392544137010485E-4467 4.149104121053871027196272068505243E-4467 + 7419 2.074552060526935513598136034252622E-4467 1.037276030263467756799068017126311E-4467 + 7420 5.186380151317338783995340085631555E-4468 2.593190075658669391997670042815778E-4468 + 7421 1.296595037829334695998835021407889E-4468 6.482975189146673479994175107039445E-4469 + 7422 3.241487594573336739997087553519723E-4469 1.620743797286668369998543776759861E-4469 + 7423 8.103718986433341849992718883799305E-4470 4.051859493216670924996359441899653E-4470 + 7424 2.025929746608335462498179720949827E-4470 1.012964873304167731249089860474913E-4470 + 7425 5.064824366520838656245449302374565E-4471 2.532412183260419328122724651187283E-4471 + 7426 1.266206091630209664061362325593642E-4471 6.331030458151048320306811627968208E-4472 + 7427 3.165515229075524160153405813984104E-4472 1.582757614537762080076702906992052E-4472 + 7428 7.91378807268881040038351453496026E-4473 3.95689403634440520019175726748013E-4473 + 7429 1.978447018172202600095878633740065E-4473 9.892235090861013000479393168700325E-4474 + 7430 4.946117545430506500239696584350163E-4474 2.473058772715253250119848292175081E-4474 + 7431 1.236529386357626625059924146087541E-4474 6.182646931788133125299620730437703E-4475 + 7432 3.091323465894066562649810365218852E-4475 1.545661732947033281324905182609426E-4475 + 7433 7.72830866473516640662452591304713E-4476 3.864154332367583203312262956523565E-4476 + 7434 1.932077166183791601656131478261783E-4476 9.660385830918958008280657391308913E-4477 + 7435 4.830192915459479004140328695654457E-4477 2.415096457729739502070164347827228E-4477 + 7436 1.207548228864869751035082173913614E-4477 6.03774114432434875517541086956807E-4478 + 7437 3.018870572162174377587705434784035E-4478 1.509435286081087188793852717392018E-4478 + 7438 7.54717643040543594396926358696009E-4479 3.773588215202717971984631793480045E-4479 + 7439 1.886794107601358985992315896740023E-4479 9.433970538006794929961579483700113E-4480 + 7440 4.716985269003397464980789741850057E-4480 2.358492634501698732490394870925028E-4480 + 7441 1.179246317250849366245197435462514E-4480 5.89623158625424683122598717731257E-4481 + 7442 2.948115793127123415612993588656285E-4481 1.474057896563561707806496794328143E-4481 + 7443 7.370289482817808539032483971640715E-4482 3.685144741408904269516241985820358E-4482 + 7444 1.842572370704452134758120992910179E-4482 9.212861853522260673790604964550895E-4483 + 7445 4.606430926761130336895302482275448E-4483 2.303215463380565168447651241137724E-4483 + 7446 1.151607731690282584223825620568862E-4483 5.75803865845141292111912810284431E-4484 + 7447 2.879019329225706460559564051422155E-4484 1.439509664612853230279782025711078E-4484 + 7448 7.19754832306426615139891012855539E-4485 3.598774161532133075699455064277695E-4485 + 7449 1.799387080766066537849727532138848E-4485 8.996935403830332689248637660694238E-4486 + 7450 4.498467701915166344624318830347119E-4486 2.249233850957583172312159415173560E-4486 + 7451 1.124616925478791586156079707586780E-4486 5.62308462739395793078039853793390E-4487 + 7452 2.81154231369697896539019926896695E-4487 1.405771156848489482695099634483475E-4487 + 7453 7.028855784242447413475498172417375E-4488 3.514427892121223706737749086208688E-4488 + 7454 1.757213946060611853368874543104344E-4488 8.78606973030305926684437271552172E-4489 + 7455 4.39303486515152963342218635776086E-4489 2.19651743257576481671109317888043E-4489 + 7456 1.098258716287882408355546589440215E-4489 5.491293581439412041777732947201075E-4490 + 7457 2.745646790719706020888866473600538E-4490 1.372823395359853010444433236800269E-4490 + 7458 6.864116976799265052222166184001345E-4491 3.432058488399632526111083092000673E-4491 + 7459 1.716029244199816263055541546000337E-4491 8.580146220999081315277707730001683E-4492 + 7460 4.290073110499540657638853865000842E-4492 2.145036555249770328819426932500421E-4492 + 7461 1.072518277624885164409713466250211E-4492 5.362591388124425822048567331251053E-4493 + 7462 2.681295694062212911024283665625527E-4493 1.340647847031106455512141832812763E-4493 + 7463 6.703239235155532277560709164063815E-4494 3.351619617577766138780354582031908E-4494 + 7464 1.675809808788883069390177291015954E-4494 8.37904904394441534695088645507977E-4495 + 7465 4.189524521972207673475443227539885E-4495 2.094762260986103836737721613769943E-4495 + 7466 1.047381130493051918368860806884972E-4495 5.236905652465259591844304034424858E-4496 + 7467 2.618452826232629795922152017212429E-4496 1.309226413116314897961076008606215E-4496 + 7468 6.546132065581574489805380043031075E-4497 3.273066032790787244902690021515538E-4497 + 7469 1.636533016395393622451345010757769E-4497 8.182665081976968112256725053788845E-4498 + 7470 4.091332540988484056128362526894423E-4498 2.045666270494242028064181263447211E-4498 + 7471 1.022833135247121014032090631723606E-4498 5.114165676235605070160453158618028E-4499 + 7472 2.557082838117802535080226579309014E-4499 1.278541419058901267540113289654507E-4499 + 7473 6.392707095294506337700566448272535E-4500 3.196353547647253168850283224136268E-4500 + 7474 1.598176773823626584425141612068134E-4500 7.99088386911813292212570806034067E-4501 + 7475 3.995441934559066461062854030170335E-4501 1.997720967279533230531427015085168E-4501 + 7476 9.98860483639766615265713507542584E-4502 4.99430241819883307632856753771292E-4502 + 7477 2.49715120909941653816428376885646E-4502 1.24857560454970826908214188442823E-4502 + 7478 6.24287802274854134541070942214115E-4503 3.121439011374270672705354711070575E-4503 + 7479 1.560719505687135336352677355535288E-4503 7.803597528435676681763386777676438E-4504 + 7480 3.901798764217838340881693388838219E-4504 1.950899382108919170440846694419110E-4504 + 7481 9.75449691054459585220423347209555E-4505 4.877248455272297926102116736047775E-4505 + 7482 2.438624227636148963051058368023888E-4505 1.219312113818074481525529184011944E-4505 + 7483 6.09656056909037240762764592005972E-4506 3.04828028454518620381382296002986E-4506 + 7484 1.52414014227259310190691148001493E-4506 7.62070071136296550953455740007465E-4507 + 7485 3.810350355681482754767278700037325E-4507 1.905175177840741377383639350018663E-4507 + 7486 9.525875889203706886918196750093315E-4508 4.762937944601853443459098375046658E-4508 + 7487 2.381468972300926721729549187523329E-4508 1.190734486150463360864774593761665E-4508 + 7488 5.953672430752316804323872968808325E-4509 2.976836215376158402161936484404163E-4509 + 7489 1.488418107688079201080968242202082E-4509 7.442090538440396005404841211010408E-4510 + 7490 3.721045269220198002702420605505204E-4510 1.860522634610099001351210302752602E-4510 + 7491 9.30261317305049500675605151376301E-4511 4.651306586525247503378025756881505E-4511 + 7492 2.325653293262623751689012878440753E-4511 1.162826646631311875844506439220376E-4511 + 7493 5.81413323315655937922253219610188E-4512 2.90706661657827968961126609805094E-4512 + 7494 1.45353330828913984480563304902547E-4512 7.26766654144569922402816524512735E-4513 + 7495 3.633833270722849612014082622563675E-4513 1.816916635361424806007041311281838E-4513 + 7496 9.08458317680712403003520655640919E-4514 4.542291588403562015017603278204595E-4514 + 7497 2.271145794201781007508801639102298E-4514 1.135572897100890503754400819551149E-4514 + 7498 5.677864485504452518772004097755745E-4515 2.838932242752226259386002048877873E-4515 + 7499 1.419466121376113129693001024438937E-4515 7.097330606880565648465005122194683E-4516 + 7500 3.548665303440282824232502561097342E-4516 1.774332651720141412116251280548671E-4516 + 7501 8.871663258600707060581256402743355E-4517 4.435831629300353530290628201371678E-4517 + 7502 2.217915814650176765145314100685839E-4517 1.108957907325088382572657050342920E-4517 + 7503 5.54478953662544191286328525171460E-4518 2.77239476831272095643164262585730E-4518 + 7504 1.38619738415636047821582131292865E-4518 6.93098692078180239107910656464325E-4519 + 7505 3.465493460390901195539553282321625E-4519 1.732746730195450597769776641160813E-4519 + 7506 8.663733650977252988848883205804065E-4520 4.331866825488626494424441602902033E-4520 + 7507 2.165933412744313247212220801451017E-4520 1.082966706372156623606110400725508E-4520 + 7508 5.41483353186078311803055200362754E-4521 2.70741676593039155901527600181377E-4521 + 7509 1.353708382965195779507638000906885E-4521 6.768541914825978897538190004534425E-4522 + 7510 3.384270957412989448769095002267213E-4522 1.692135478706494724384547501133606E-4522 + 7511 8.46067739353247362192273750566803E-4523 4.230338696766236810961368752834015E-4523 + 7512 2.115169348383118405480684376417008E-4523 1.057584674191559202740342188208504E-4523 + 7513 5.28792337095779601370171094104252E-4524 2.64396168547889800685085547052126E-4524 + 7514 1.32198084273944900342542773526063E-4524 6.60990421369724501712713867630315E-4525 + 7515 3.304952106848622508563569338151575E-4525 1.652476053424311254281784669075788E-4525 + 7516 8.26238026712155627140892334537894E-4526 4.13119013356077813570446167268947E-4526 + 7517 2.065595066780389067852230836344735E-4526 1.032797533390194533926115418172368E-4526 + 7518 5.16398766695097266963057709086184E-4527 2.58199383347548633481528854543092E-4527 + 7519 1.29099691673774316740764427271546E-4527 6.4549845836887158370382213635773E-4528 + 7520 3.22749229184435791851911068178865E-4528 1.613746145922178959259555340894325E-4528 + 7521 8.068730729610894796297776704471625E-4529 4.034365364805447398148888352235813E-4529 + 7522 2.017182682402723699074444176117907E-4529 1.008591341201361849537222088058953E-4529 + 7523 5.042956706006809247686110440294765E-4530 2.521478353003404623843055220147383E-4530 + 7524 1.260739176501702311921527610073692E-4530 6.303695882508511559607638050368458E-4531 + 7525 3.151847941254255779803819025184229E-4531 1.575923970627127889901909512592115E-4531 + 7526 7.879619853135639449509547562960575E-4532 3.939809926567819724754773781480288E-4532 + 7527 1.969904963283909862377386890740144E-4532 9.84952481641954931188693445370072E-4533 + 7528 4.92476240820977465594346722685036E-4533 2.46238120410488732797173361342518E-4533 + 7529 1.23119060205244366398586680671259E-4533 6.15595301026221831992933403356295E-4534 + 7530 3.077976505131109159964667016781475E-4534 1.538988252565554579982333508390738E-4534 + 7531 7.69494126282777289991166754195369E-4535 3.847470631413886449955833770976845E-4535 + 7532 1.923735315706943224977916885488423E-4535 9.618676578534716124889584427442113E-4536 + 7533 4.809338289267358062444792213721057E-4536 2.404669144633679031222396106860528E-4536 + 7534 1.202334572316839515611198053430264E-4536 6.01167286158419757805599026715132E-4537 + 7535 3.00583643079209878902799513357566E-4537 1.50291821539604939451399756678783E-4537 + 7536 7.51459107698024697256998783393915E-4538 3.757295538490123486284993916969575E-4538 + 7537 1.878647769245061743142496958484788E-4538 9.393238846225308715712484792423938E-4539 + 7538 4.696619423112654357856242396211969E-4539 2.348309711556327178928121198105985E-4539 + 7539 1.174154855778163589464060599052993E-4539 5.870774278890817947320302995264963E-4540 + 7540 2.935387139445408973660151497632482E-4540 1.467693569722704486830075748816241E-4540 + 7541 7.338467848613522434150378744081205E-4541 3.669233924306761217075189372040603E-4541 + 7542 1.834616962153380608537594686020302E-4541 9.173084810766903042687973430101508E-4542 + 7543 4.586542405383451521343986715050754E-4542 2.293271202691725760671993357525377E-4542 + 7544 1.146635601345862880335996678762689E-4542 5.733178006729314401679983393813443E-4543 + 7545 2.866589003364657200839991696906722E-4543 1.433294501682328600419995848453361E-4543 + 7546 7.166472508411643002099979242266805E-4544 3.583236254205821501049989621133403E-4544 + 7547 1.791618127102910750524994810566702E-4544 8.958090635514553752624974052833508E-4545 + 7548 4.479045317757276876312487026416754E-4545 2.239522658878638438156243513208377E-4545 + 7549 1.119761329439319219078121756604189E-4545 5.598806647196596095390608783020943E-4546 + 7550 2.799403323598298047695304391510472E-4546 1.399701661799149023847652195755236E-4546 + 7551 6.99850830899574511923826097877618E-4547 3.49925415449787255961913048938809E-4547 + 7552 1.749627077248936279809565244694045E-4547 8.748135386244681399047826223470225E-4548 + 7553 4.374067693122340699523913111735113E-4548 2.187033846561170349761956555867556E-4548 + 7554 1.093516923280585174880978277933778E-4548 5.46758461640292587440489138966889E-4549 + 7555 2.733792308201462937202445694834445E-4549 1.366896154100731468601222847417223E-4549 + 7556 6.834480770503657343006114237086115E-4550 3.417240385251828671503057118543058E-4550 + 7557 1.708620192625914335751528559271529E-4550 8.543100963129571678757642796357645E-4551 + 7558 4.271550481564785839378821398178823E-4551 2.135775240782392919689410699089411E-4551 + 7559 1.067887620391196459844705349544706E-4551 5.339438101955982299223526747723528E-4552 + 7560 2.669719050977991149611763373861764E-4552 1.334859525488995574805881686930882E-4552 + 7561 6.67429762744497787402940843465441E-4553 3.337148813722488937014704217327205E-4553 + 7562 1.668574406861244468507352108663603E-4553 8.342872034306222342536760543318013E-4554 + 7563 4.171436017153111171268380271659007E-4554 2.085718008576555585634190135829503E-4554 + 7564 1.042859004288277792817095067914752E-4554 5.214295021441388964085475339573758E-4555 + 7565 2.607147510720694482042737669786879E-4555 1.303573755360347241021368834893440E-4555 + 7566 6.51786877680173620510684417446720E-4556 3.25893438840086810255342208723360E-4556 + 7567 1.62946719420043405127671104361680E-4556 8.1473359710021702563835552180840E-4557 + 7568 4.0736679855010851281917776090420E-4557 2.0368339927505425640958888045210E-4557 + 7569 1.0184169963752712820479444022605E-4557 5.0920849818763564102397220113025E-4558 + 7570 2.54604249093817820511986100565125E-4558 1.273021245469089102559930502825625E-4558 + 7571 6.365106227345445512799652514128125E-4559 3.182553113672722756399826257064063E-4559 + 7572 1.591276556836361378199913128532032E-4559 7.956382784181806890999565642660158E-4560 + 7573 3.978191392090903445499782821330079E-4560 1.989095696045451722749891410665040E-4560 + 7574 9.94547848022725861374945705332520E-4561 4.97273924011362930687472852666260E-4561 + 7575 2.48636962005681465343736426333130E-4561 1.24318481002840732671868213166565E-4561 + 7576 6.21592405014203663359341065832825E-4562 3.107962025071018316796705329164125E-4562 + 7577 1.553981012535509158398352664582063E-4562 7.769905062677545791991763322910313E-4563 + 7578 3.884952531338772895995881661455157E-4563 1.942476265669386447997940830727578E-4563 + 7579 9.71238132834693223998970415363789E-4564 4.856190664173466119994852076818945E-4564 + 7580 2.428095332086733059997426038409473E-4564 1.214047666043366529998713019204736E-4564 + 7581 6.07023833021683264999356509602368E-4565 3.03511916510841632499678254801184E-4565 + 7582 1.51755958255420816249839127400592E-4565 7.5877979127710408124919563700296E-4566 + 7583 3.7938989563855204062459781850148E-4566 1.8969494781927602031229890925074E-4566 + 7584 9.484747390963801015614945462537E-4567 4.7423736954819005078074727312685E-4567 + 7585 2.37118684774095025390373636563425E-4567 1.185593423870475126951868182817125E-4567 + 7586 5.927967119352375634759340914085625E-4568 2.963983559676187817379670457042813E-4568 + 7587 1.481991779838093908689835228521407E-4568 7.409958899190469543449176142607033E-4569 + 7588 3.704979449595234771724588071303517E-4569 1.852489724797617385862294035651758E-4569 + 7589 9.26244862398808692931147017825879E-4570 4.631224311994043464655735089129395E-4570 + 7590 2.315612155997021732327867544564698E-4570 1.157806077998510866163933772282349E-4570 + 7591 5.789030389992554330819668861411745E-4571 2.894515194996277165409834430705873E-4571 + 7592 1.447257597498138582704917215352937E-4571 7.236287987490692913524586076764683E-4572 + 7593 3.618143993745346456762293038382342E-4572 1.809071996872673228381146519191171E-4572 + 7594 9.045359984363366141905732595955855E-4573 4.522679992181683070952866297977928E-4573 + 7595 2.261339996090841535476433148988964E-4573 1.130669998045420767738216574494482E-4573 + 7596 5.65334999022710383869108287247241E-4574 2.826674995113551919345541436236205E-4574 + 7597 1.413337497556775959672770718118103E-4574 7.066687487783879798363853590590513E-4575 + 7598 3.533343743891939899181926795295257E-4575 1.766671871945969949590963397647628E-4575 + 7599 8.83335935972984974795481698823814E-4576 4.41667967986492487397740849411907E-4576 + 7600 2.208339839932462436988704247059535E-4576 1.104169919966231218494352123529768E-4576 + 7601 5.52084959983115609247176061764884E-4577 2.76042479991557804623588030882442E-4577 + 7602 1.38021239995778902311794015441221E-4577 6.90106199978894511558970077206105E-4578 + 7603 3.450530999894472557794850386030525E-4578 1.725265499947236278897425193015263E-4578 + 7604 8.626327499736181394487125965076315E-4579 4.313163749868090697243562982538158E-4579 + 7605 2.156581874934045348621781491269079E-4579 1.078290937467022674310890745634540E-4579 + 7606 5.39145468733511337155445372817270E-4580 2.69572734366755668577722686408635E-4580 + 7607 1.347863671833778342888613432043175E-4580 6.739318359168891714443067160215875E-4581 + 7608 3.369659179584445857221533580107938E-4581 1.684829589792222928610766790053969E-4581 + 7609 8.424147948961114643053833950269845E-4582 4.212073974480557321526916975134923E-4582 + 7610 2.106036987240278660763458487567462E-4582 1.053018493620139330381729243783731E-4582 + 7611 5.265092468100696651908646218918655E-4583 2.632546234050348325954323109459328E-4583 + 7612 1.316273117025174162977161554729664E-4583 6.58136558512587081488580777364832E-4584 + 7613 3.29068279256293540744290388682416E-4584 1.64534139628146770372145194341208E-4584 + 7614 8.2267069814073385186072597170604E-4585 4.1133534907036692593036298585302E-4585 + 7615 2.0566767453518346296518149292651E-4585 1.02833837267591731482590746463255E-4585 + 7616 5.14169186337958657412953732316275E-4586 2.570845931689793287064768661581375E-4586 + 7617 1.285422965844896643532384330790688E-4586 6.427114829224483217661921653953438E-4587 + 7618 3.213557414612241608830960826976719E-4587 1.606778707306120804415480413488360E-4587 + 7619 8.03389353653060402207740206744180E-4588 4.01694676826530201103870103372090E-4588 + 7620 2.00847338413265100551935051686045E-4588 1.004236692066325502759675258430225E-4588 + 7621 5.021183460331627513798376292151125E-4589 2.510591730165813756899188146075563E-4589 + 7622 1.255295865082906878449594073037782E-4589 6.276479325414534392247970365188908E-4590 + 7623 3.138239662707267196123985182594454E-4590 1.569119831353633598061992591297227E-4590 + 7624 7.845599156768167990309962956486135E-4591 3.922799578384083995154981478243068E-4591 + 7625 1.961399789192041997577490739121534E-4591 9.80699894596020998788745369560767E-4592 + 7626 4.903499472980104993943726847803835E-4592 2.451749736490052496971863423901918E-4592 + 7627 1.225874868245026248485931711950959E-4592 6.129374341225131242429658559754795E-4593 + 7628 3.064687170612565621214829279877398E-4593 1.532343585306282810607414639938699E-4593 + 7629 7.661717926531414053037073199693495E-4594 3.830858963265707026518536599846748E-4594 + 7630 1.915429481632853513259268299923374E-4594 9.57714740816426756629634149961687E-4595 + 7631 4.788573704082133783148170749808435E-4595 2.394286852041066891574085374904218E-4595 + 7632 1.197143426020533445787042687452109E-4595 5.985717130102667228935213437260545E-4596 + 7633 2.992858565051333614467606718630273E-4596 1.496429282525666807233803359315136E-4596 + 7634 7.48214641262833403616901679657568E-4597 3.74107320631416701808450839828784E-4597 + 7635 1.87053660315708350904225419914392E-4597 9.3526830157854175452112709957196E-4598 + 7636 4.6763415078927087726056354978598E-4598 2.3381707539463543863028177489299E-4598 + 7637 1.16908537697317719315140887446495E-4598 5.84542688486588596575704437232475E-4599 + 7638 2.922713442432942982878522186162375E-4599 1.461356721216471491439261093081188E-4599 + 7639 7.30678360608235745719630546540594E-4600 3.65339180304117872859815273270297E-4600 + 7640 1.826695901520589364299076366351485E-4600 9.133479507602946821495381831757425E-4601 + 7641 4.566739753801473410747690915878713E-4601 2.283369876900736705373845457939356E-4601 + 7642 1.141684938450368352686922728969678E-4601 5.70842469225184176343461364484839E-4602 + 7643 2.854212346125920881717306822424195E-4602 1.427106173062960440858653411212098E-4602 + 7644 7.13553086531480220429326705606049E-4603 3.567765432657401102146633528030245E-4603 + 7645 1.783882716328700551073316764015123E-4603 8.919413581643502755366583820075613E-4604 + 7646 4.459706790821751377683291910037807E-4604 2.229853395410875688841645955018903E-4604 + 7647 1.114926697705437844420822977509452E-4604 5.574633488527189222104114887547258E-4605 + 7648 2.787316744263594611052057443773629E-4605 1.393658372131797305526028721886815E-4605 + 7649 6.968291860658986527630143609434075E-4606 3.484145930329493263815071804717038E-4606 + 7650 1.742072965164746631907535902358519E-4606 8.710364825823733159537679511792595E-4607 + 7651 4.355182412911866579768839755896298E-4607 2.177591206455933289884419877948149E-4607 + 7652 1.088795603227966644942209938974075E-4607 5.443978016139833224711049694870373E-4608 + 7653 2.721989008069916612355524847435187E-4608 1.360994504034958306177762423717593E-4608 + 7654 6.804972520174791530888812118587965E-4609 3.402486260087395765444406059293983E-4609 + 7655 1.701243130043697882722203029646992E-4609 8.506215650218489413611015148234958E-4610 + 7656 4.253107825109244706805507574117479E-4610 2.126553912554622353402753787058740E-4610 + 7657 1.063276956277311176701376893529370E-4610 5.31638478138655588350688446764685E-4611 + 7658 2.658192390693277941753442233823425E-4611 1.329096195346638970876721116911713E-4611 + 7659 6.645480976733194854383605584558565E-4612 3.322740488366597427191802792279283E-4612 + 7660 1.661370244183298713595901396139642E-4612 8.306851220916493567979506980698208E-4613 + 7661 4.153425610458246783989753490349104E-4613 2.076712805229123391994876745174552E-4613 + 7662 1.038356402614561695997438372587276E-4613 5.19178201307280847998719186293638E-4614 + 7663 2.59589100653640423999359593146819E-4614 1.297945503268202119996797965734095E-4614 + 7664 6.489727516341010599983989828670475E-4615 3.244863758170505299991994914335238E-4615 + 7665 1.622431879085252649995997457167619E-4615 8.112159395426263249979987285838095E-4616 + 7666 4.056079697713131624989993642919048E-4616 2.028039848856565812494996821459524E-4616 + 7667 1.014019924428282906247498410729762E-4616 5.07009962214141453123749205364881E-4617 + 7668 2.535049811070707265618746026824405E-4617 1.267524905535353632809373013412203E-4617 + 7669 6.337624527676768164046865067061015E-4618 3.168812263838384082023432533530508E-4618 + 7670 1.584406131919192041011716266765254E-4618 7.92203065959596020505858133382627E-4619 + 7671 3.961015329797980102529290666913135E-4619 1.980507664898990051264645333456568E-4619 + 7672 9.90253832449495025632322666728284E-4620 4.95126916224747512816161333364142E-4620 + 7673 2.47563458112373756408080666682071E-4620 1.237817290561868782040403333410355E-4620 + 7674 6.189086452809343910202016667051775E-4621 3.094543226404671955101008333525888E-4621 + 7675 1.547271613202335977550504166762944E-4621 7.73635806601167988775252083381472E-4622 + 7676 3.86817903300583994387626041690736E-4622 1.93408951650291997193813020845368E-4622 + 7677 9.6704475825145998596906510422684E-4623 4.8352237912572999298453255211342E-4623 + 7678 2.4176118956286499649226627605671E-4623 1.20880594781432498246133138028355E-4623 + 7679 6.04402973907162491230665690141775E-4624 3.022014869535812456153328450708875E-4624 + 7680 1.511007434767906228076664225354438E-4624 7.555037173839531140383321126772188E-4625 + 7681 3.777518586919765570191660563386094E-4625 1.888759293459882785095830281693047E-4625 + 7682 9.443796467299413925479151408465235E-4626 4.721898233649706962739575704232618E-4626 + 7683 2.360949116824853481369787852116309E-4626 1.180474558412426740684893926058155E-4626 + 7684 5.902372792062133703424469630290775E-4627 2.951186396031066851712234815145388E-4627 + 7685 1.475593198015533425856117407572694E-4627 7.37796599007766712928058703786347E-4628 + 7686 3.688982995038833564640293518931735E-4628 1.844491497519416782320146759465868E-4628 + 7687 9.22245748759708391160073379732934E-4629 4.61122874379854195580036689866467E-4629 + 7688 2.305614371899270977900183449332335E-4629 1.152807185949635488950091724666168E-4629 + 7689 5.76403592974817744475045862333084E-4630 2.88201796487408872237522931166542E-4630 + 7690 1.44100898243704436118761465583271E-4630 7.20504491218522180593807327916355E-4631 + 7691 3.602522456092610902969036639581775E-4631 1.801261228046305451484518319790888E-4631 + 7692 9.00630614023152725742259159895444E-4632 4.50315307011576362871129579947722E-4632 + 7693 2.25157653505788181435564789973861E-4632 1.125788267528940907177823949869305E-4632 + 7694 5.628941337644704535889119749346525E-4633 2.814470668822352267944559874673263E-4633 + 7695 1.407235334411176133972279937336632E-4633 7.036176672055880669861399686683158E-4634 + 7696 3.518088336027940334930699843341579E-4634 1.759044168013970167465349921670790E-4634 + 7697 8.79522084006985083732674960835395E-4635 4.397610420034925418663374804176975E-4635 + 7698 2.198805210017462709331687402088488E-4635 1.099402605008731354665843701044244E-4635 + 7699 5.49701302504365677332921850522122E-4636 2.74850651252182838666460925261061E-4636 + 7700 1.374253256260914193332304626305305E-4636 6.871266281304570966661523131526525E-4637 + 7701 3.435633140652285483330761565763263E-4637 1.717816570326142741665380782881631E-4637 + 7702 8.589082851630713708326903914408155E-4638 4.294541425815356854163451957204078E-4638 + 7703 2.147270712907678427081725978602039E-4638 1.073635356453839213540862989301020E-4638 + 7704 5.36817678226919606770431494650510E-4639 2.68408839113459803385215747325255E-4639 + 7705 1.342044195567299016926078736626275E-4639 6.710220977836495084630393683131375E-4640 + 7706 3.355110488918247542315196841565688E-4640 1.677555244459123771157598420782844E-4640 + 7707 8.38777622229561885578799210391422E-4641 4.19388811114780942789399605195711E-4641 + 7708 2.096944055573904713946998025978555E-4641 1.048472027786952356973499012989278E-4641 + 7709 5.24236013893476178486749506494639E-4642 2.621180069467380892433747532473195E-4642 + 7710 1.310590034733690446216873766236598E-4642 6.552950173668452231084368831182988E-4643 + 7711 3.276475086834226115542184415591494E-4643 1.638237543417113057771092207795747E-4643 + 7712 8.191187717085565288855461038978735E-4644 4.095593858542782644427730519489368E-4644 + 7713 2.047796929271391322213865259744684E-4644 1.023898464635695661106932629872342E-4644 + 7714 5.11949232317847830553466314936171E-4645 2.559746161589239152767331574680855E-4645 + 7715 1.279873080794619576383665787340428E-4645 6.399365403973097881918328936702138E-4646 + 7716 3.199682701986548940959164468351069E-4646 1.599841350993274470479582234175535E-4646 + 7717 7.999206754966372352397911170877675E-4647 3.999603377483186176198955585438838E-4647 + 7718 1.999801688741593088099477792719419E-4647 9.999008443707965440497388963597095E-4648 + 7719 4.999504221853982720248694481798548E-4648 2.499752110926991360124347240899274E-4648 + 7720 1.249876055463495680062173620449637E-4648 6.249380277317478400310868102248185E-4649 + 7721 3.124690138658739200155434051124093E-4649 1.562345069329369600077717025562046E-4649 + 7722 7.81172534664684800038858512781023E-4650 3.905862673323424000194292563905115E-4650 + 7723 1.952931336661712000097146281952558E-4650 9.764656683308560000485731409762788E-4651 + 7724 4.882328341654280000242865704881394E-4651 2.441164170827140000121432852440697E-4651 + 7725 1.220582085413570000060716426220349E-4651 6.102910427067850000303582131101743E-4652 + 7726 3.051455213533925000151791065550872E-4652 1.525727606766962500075895532775436E-4652 + 7727 7.62863803383481250037947766387718E-4653 3.81431901691740625018973883193859E-4653 + 7728 1.907159508458703125094869415969295E-4653 9.535797542293515625474347079846475E-4654 + 7729 4.767898771146757812737173539923238E-4654 2.383949385573378906368586769961619E-4654 + 7730 1.191974692786689453184293384980810E-4654 5.959873463933447265921466924904048E-4655 + 7731 2.979936731966723632960733462452024E-4655 1.489968365983361816480366731226012E-4655 + 7732 7.44984182991680908240183365613006E-4656 3.72492091495840454120091682806503E-4656 + 7733 1.862460457479202270600458414032515E-4656 9.312302287396011353002292070162575E-4657 + 7734 4.656151143698005676501146035081288E-4657 2.328075571849002838250573017540644E-4657 + 7735 1.164037785924501419125286508770322E-4657 5.82018892962250709562643254385161E-4658 + 7736 2.910094464811253547813216271925805E-4658 1.455047232405626773906608135962903E-4658 + 7737 7.275236162028133869533040679814515E-4659 3.637618081014066934766520339907258E-4659 + 7738 1.818809040507033467383260169953629E-4659 9.094045202535167336916300849768145E-4660 + 7739 4.547022601267583668458150424884073E-4660 2.273511300633791834229075212442036E-4660 + 7740 1.136755650316895917114537606221018E-4660 5.68377825158447958557268803110509E-4661 + 7741 2.841889125792239792786344015552545E-4661 1.420944562896119896393172007776273E-4661 + 7742 7.104722814480599481965860038881365E-4662 3.552361407240299740982930019440683E-4662 + 7743 1.776180703620149870491465009720342E-4662 8.880903518100749352457325048601708E-4663 + 7744 4.440451759050374676228662524300854E-4663 2.220225879525187338114331262150427E-4663 + 7745 1.110112939762593669057165631075214E-4663 5.550564698812968345285828155376068E-4664 + 7746 2.775282349406484172642914077688034E-4664 1.387641174703242086321457038844017E-4664 + 7747 6.938205873516210431607285194220085E-4665 3.469102936758105215803642597110043E-4665 + 7748 1.734551468379052607901821298555022E-4665 8.672757341895263039509106492775108E-4666 + 7749 4.336378670947631519754553246387554E-4666 2.168189335473815759877276623193777E-4666 + 7750 1.084094667736907879938638311596889E-4666 5.420473338684539399693191557984443E-4667 + 7751 2.710236669342269699846595778992222E-4667 1.355118334671134849923297889496111E-4667 + 7752 6.775591673355674249616489447480555E-4668 3.387795836677837124808244723740278E-4668 + 7753 1.693897918338918562404122361870139E-4668 8.469489591694592812020611809350695E-4669 + 7754 4.234744795847296406010305904675348E-4669 2.117372397923648203005152952337674E-4669 + 7755 1.058686198961824101502576476168837E-4669 5.293430994809120507512882380844185E-4670 + 7756 2.646715497404560253756441190422093E-4670 1.323357748702280126878220595211046E-4670 + 7757 6.61678874351140063439110297605523E-4671 3.308394371755700317195551488027615E-4671 + 7758 1.654197185877850158597775744013808E-4671 8.270985929389250792988878720069038E-4672 + 7759 4.135492964694625396494439360034519E-4672 2.067746482347312698247219680017260E-4672 + 7760 1.033873241173656349123609840008630E-4672 5.16936620586828174561804920004315E-4673 + 7761 2.584683102934140872809024600021575E-4673 1.292341551467070436404512300010788E-4673 + 7762 6.46170775733535218202256150005394E-4674 3.23085387866767609101128075002697E-4674 + 7763 1.615426939333838045505640375013485E-4674 8.077134696669190227528201875067425E-4675 + 7764 4.038567348334595113764100937533713E-4675 2.019283674167297556882050468766856E-4675 + 7765 1.009641837083648778441025234383428E-4675 5.04820918541824389220512617191714E-4676 + 7766 2.52410459270912194610256308595857E-4676 1.262052296354560973051281542979285E-4676 + 7767 6.310261481772804865256407714896425E-4677 3.155130740886402432628203857448213E-4677 + 7768 1.577565370443201216314101928724107E-4677 7.887826852216006081570509643620533E-4678 + 7769 3.943913426108003040785254821810267E-4678 1.971956713054001520392627410905133E-4678 + 7770 9.859783565270007601963137054525665E-4679 4.929891782635003800981568527262833E-4679 + 7771 2.464945891317501900490784263631417E-4679 1.232472945658750950245392131815708E-4679 + 7772 6.16236472829375475122696065907854E-4680 3.08118236414687737561348032953927E-4680 + 7773 1.540591182073438687806740164769635E-4680 7.702955910367193439033700823848175E-4681 + 7774 3.851477955183596719516850411924088E-4681 1.925738977591798359758425205962044E-4681 + 7775 9.62869488795899179879212602981022E-4682 4.81434744397949589939606301490511E-4682 + 7776 2.407173721989747949698031507452555E-4682 1.203586860994873974849015753726278E-4682 + 7777 6.01793430497436987424507876863139E-4683 3.008967152487184937122539384315695E-4683 + 7778 1.504483576243592468561269692157848E-4683 7.522417881217962342806348460789238E-4684 + 7779 3.761208940608981171403174230394619E-4684 1.880604470304490585701587115197310E-4684 + 7780 9.40302235152245292850793557598655E-4685 4.701511175761226464253967787993275E-4685 + 7781 2.350755587880613232126983893996638E-4685 1.175377793940306616063491946998319E-4685 + 7782 5.876888969701533080317459734991595E-4686 2.938444484850766540158729867495798E-4686 + 7783 1.469222242425383270079364933747899E-4686 7.346111212126916350396824668739495E-4687 + 7784 3.673055606063458175198412334369748E-4687 1.836527803031729087599206167184874E-4687 + 7785 9.18263901515864543799603083592437E-4688 4.591319507579322718998015417962185E-4688 + 7786 2.295659753789661359499007708981093E-4688 1.147829876894830679749503854490546E-4688 + 7787 5.73914938447415339874751927245273E-4689 2.869574692237076699373759636226365E-4689 + 7788 1.434787346118538349686879818113183E-4689 7.173936730592691748434399090565913E-4690 + 7789 3.586968365296345874217199545282957E-4690 1.793484182648172937108599772641478E-4690 + 7790 8.96742091324086468554299886320739E-4691 4.483710456620432342771499431603695E-4691 + 7791 2.241855228310216171385749715801848E-4691 1.120927614155108085692874857900924E-4691 + 7792 5.60463807077554042846437428950462E-4692 2.80231903538777021423218714475231E-4692 + 7793 1.401159517693885107116093572376155E-4692 7.005797588469425535580467861880775E-4693 + 7794 3.502898794234712767790233930940388E-4693 1.751449397117356383895116965470194E-4693 + 7795 8.75724698558678191947558482735097E-4694 4.378623492793390959737792413675485E-4694 + 7796 2.189311746396695479868896206837743E-4694 1.094655873198347739934448103418871E-4694 + 7797 5.473279365991738699672240517094355E-4695 2.736639682995869349836120258547178E-4695 + 7798 1.368319841497934674918060129273589E-4695 6.841599207489673374590300646367945E-4696 + 7799 3.420799603744836687295150323183973E-4696 1.710399801872418343647575161591986E-4696 + 7800 8.55199900936209171823787580795993E-4697 4.275999504681045859118937903979965E-4697 + 7801 2.137999752340522929559468951989983E-4697 1.068999876170261464779734475994991E-4697 + 7802 5.344999380851307323898672379974955E-4698 2.672499690425653661949336189987478E-4698 + 7803 1.336249845212826830974668094993739E-4698 6.681249226064134154873340474968695E-4699 + 7804 3.340624613032067077436670237484348E-4699 1.670312306516033538718335118742174E-4699 + 7805 8.35156153258016769359167559371087E-4700 4.175780766290083846795837796855435E-4700 + 7806 2.087890383145041923397918898427718E-4700 1.043945191572520961698959449213859E-4700 + 7807 5.219725957862604808494797246069295E-4701 2.609862978931302404247398623034648E-4701 + 7808 1.304931489465651202123699311517324E-4701 6.52465744732825601061849655758662E-4702 + 7809 3.26232872366412800530924827879331E-4702 1.631164361832064002654624139396655E-4702 + 7810 8.155821809160320013273120696983275E-4703 4.077910904580160006636560348491638E-4703 + 7811 2.038955452290080003318280174245819E-4703 1.019477726145040001659140087122910E-4703 + 7812 5.09738863072520000829570043561455E-4704 2.548694315362600004147850217807275E-4704 + 7813 1.274347157681300002073925108903638E-4704 6.371735788406500010369625544518188E-4705 + 7814 3.185867894203250005184812772259094E-4705 1.592933947101625002592406386129547E-4705 + 7815 7.964669735508125012962031930647735E-4706 3.982334867754062506481015965323868E-4706 + 7816 1.991167433877031253240507982661934E-4706 9.95583716938515626620253991330967E-4707 + 7817 4.977918584692578133101269956654835E-4707 2.488959292346289066550634978327418E-4707 + 7818 1.244479646173144533275317489163709E-4707 6.222398230865722666376587445818545E-4708 + 7819 3.111199115432861333188293722909273E-4708 1.555599557716430666594146861454636E-4708 + 7820 7.77799778858215333297073430727318E-4709 3.88899889429107666648536715363659E-4709 + 7821 1.944499447145538333242683576818295E-4709 9.722497235727691666213417884091475E-4710 + 7822 4.861248617863845833106708942045738E-4710 2.430624308931922916553354471022869E-4710 + 7823 1.215312154465961458276677235511435E-4710 6.076560772329807291383386177557173E-4711 + 7824 3.038280386164903645691693088778587E-4711 1.519140193082451822845846544389293E-4711 + 7825 7.595700965412259114229232721946465E-4712 3.797850482706129557114616360973233E-4712 + 7826 1.898925241353064778557308180486617E-4712 9.494626206765323892786540902433083E-4713 + 7827 4.747313103382661946393270451216542E-4713 2.373656551691330973196635225608271E-4713 + 7828 1.186828275845665486598317612804136E-4713 5.934141379228327432991588064020678E-4714 + 7829 2.967070689614163716495794032010339E-4714 1.483535344807081858247897016005170E-4714 + 7830 7.41767672403540929123948508002585E-4715 3.708838362017704645619742540012925E-4715 + 7831 1.854419181008852322809871270006463E-4715 9.272095905044261614049356350032313E-4716 + 7832 4.636047952522130807024678175016157E-4716 2.318023976261065403512339087508078E-4716 + 7833 1.159011988130532701756169543754039E-4716 5.795059940652663508780847718770195E-4717 + 7834 2.897529970326331754390423859385098E-4717 1.448764985163165877195211929692549E-4717 + 7835 7.243824925815829385976059648462745E-4718 3.621912462907914692988029824231373E-4718 + 7836 1.810956231453957346494014912115687E-4718 9.054781157269786732470074560578433E-4719 + 7837 4.527390578634893366235037280289217E-4719 2.263695289317446683117518640144608E-4719 + 7838 1.131847644658723341558759320072304E-4719 5.65923822329361670779379660036152E-4720 + 7839 2.82961911164680835389689830018076E-4720 1.41480955582340417694844915009038E-4720 + 7840 7.0740477791170208847422457504519E-4721 3.53702388955851044237112287522595E-4721 + 7841 1.768511944779255221185561437612975E-4721 8.842559723896276105927807188064875E-4722 + 7842 4.421279861948138052963903594032438E-4722 2.210639930974069026481951797016219E-4722 + 7843 1.105319965487034513240975898508110E-4722 5.526599827435172566204879492540548E-4723 + 7844 2.763299913717586283102439746270274E-4723 1.381649956858793141551219873135137E-4723 + 7845 6.908249784293965707756099365675685E-4724 3.454124892146982853878049682837843E-4724 + 7846 1.727062446073491426939024841418922E-4724 8.635312230367457134695124207094608E-4725 + 7847 4.317656115183728567347562103547304E-4725 2.158828057591864283673781051773652E-4725 + 7848 1.079414028795932141836890525886826E-4725 5.39707014397966070918445262943413E-4726 + 7849 2.698535071989830354592226314717065E-4726 1.349267535994915177296113157358533E-4726 + 7850 6.746337679974575886480565786792665E-4727 3.373168839987287943240282893396333E-4727 + 7851 1.686584419993643971620141446698167E-4727 8.432922099968219858100707233490833E-4728 + 7852 4.216461049984109929050353616745417E-4728 2.108230524992054964525176808372708E-4728 + 7853 1.054115262496027482262588404186354E-4728 5.27057631248013741131294202093177E-4729 + 7854 2.635288156240068705656471010465885E-4729 1.317644078120034352828235505232943E-4729 + 7855 6.588220390600171764141177526164715E-4730 3.294110195300085882070588763082358E-4730 + 7856 1.647055097650042941035294381541179E-4730 8.235275488250214705176471907705895E-4731 + 7857 4.117637744125107352588235953852948E-4731 2.058818872062553676294117976926474E-4731 + 7858 1.029409436031276838147058988463237E-4731 5.147047180156384190735294942316185E-4732 + 7859 2.573523590078192095367647471158093E-4732 1.286761795039096047683823735579046E-4732 + 7860 6.43380897519548023841911867789523E-4733 3.216904487597740119209559338947615E-4733 + 7861 1.608452243798870059604779669473808E-4733 8.042261218994350298023898347369038E-4734 + 7862 4.021130609497175149011949173684519E-4734 2.010565304748587574505974586842260E-4734 + 7863 1.005282652374293787252987293421130E-4734 5.02641326187146893626493646710565E-4735 + 7864 2.513206630935734468132468233552825E-4735 1.256603315467867234066234116776413E-4735 + 7865 6.283016577339336170331170583882065E-4736 3.141508288669668085165585291941033E-4736 + 7866 1.570754144334834042582792645970517E-4736 7.853770721674170212913963229852583E-4737 + 7867 3.926885360837085106456981614926292E-4737 1.963442680418542553228490807463146E-4737 + 7868 9.81721340209271276614245403731573E-4738 4.908606701046356383071227018657865E-4738 + 7869 2.454303350523178191535613509328933E-4738 1.227151675261589095767806754664466E-4738 + 7870 6.13575837630794547883903377332233E-4739 3.067879188153972739419516886661165E-4739 + 7871 1.533939594076986369709758443330583E-4739 7.669697970384931848548792216652913E-4740 + 7872 3.834848985192465924274396108326457E-4740 1.917424492596232962137198054163228E-4740 + 7873 9.58712246298116481068599027081614E-4741 4.79356123149058240534299513540807E-4741 + 7874 2.396780615745291202671497567704035E-4741 1.198390307872645601335748783852018E-4741 + 7875 5.99195153936322800667874391926009E-4742 2.995975769681614003339371959630045E-4742 + 7876 1.497987884840807001669685979815023E-4742 7.489939424204035008348429899075113E-4743 + 7877 3.744969712102017504174214949537557E-4743 1.872484856051008752087107474768778E-4743 + 7878 9.36242428025504376043553737384389E-4744 4.681212140127521880217768686921945E-4744 + 7879 2.340606070063760940108884343460973E-4744 1.170303035031880470054442171730486E-4744 + 7880 5.85151517515940235027221085865243E-4745 2.925757587579701175136105429326215E-4745 + 7881 1.462878793789850587568052714663108E-4745 7.314393968949252937840263573315538E-4746 + 7882 3.657196984474626468920131786657769E-4746 1.828598492237313234460065893328885E-4746 + 7883 9.142992461186566172300329466644425E-4747 4.571496230593283086150164733322213E-4747 + 7884 2.285748115296641543075082366661107E-4747 1.142874057648320771537541183330553E-4747 + 7885 5.714370288241603857687705916652765E-4748 2.857185144120801928843852958326383E-4748 + 7886 1.428592572060400964421926479163192E-4748 7.142962860302004822109632395815958E-4749 + 7887 3.571481430151002411054816197907979E-4749 1.785740715075501205527408098953990E-4749 + 7888 8.92870357537750602763704049476995E-4750 4.464351787688753013818520247384975E-4750 + 7889 2.232175893844376506909260123692488E-4750 1.116087946922188253454630061846244E-4750 + 7890 5.58043973461094126727315030923122E-4751 2.79021986730547063363657515461561E-4751 + 7891 1.395109933652735316818287577307805E-4751 6.975549668263676584091437886539025E-4752 + 7892 3.487774834131838292045718943269513E-4752 1.743887417065919146022859471634756E-4752 + 7893 8.71943708532959573011429735817378E-4753 4.35971854266479786505714867908689E-4753 + 7894 2.179859271332398932528574339543445E-4753 1.089929635666199466264287169771723E-4753 + 7895 5.449648178330997331321435848858615E-4754 2.724824089165498665660717924429308E-4754 + 7896 1.362412044582749332830358962214654E-4754 6.81206022291374666415179481107327E-4755 + 7897 3.406030111456873332075897405536635E-4755 1.703015055728436666037948702768318E-4755 + 7898 8.51507527864218333018974351384159E-4756 4.257537639321091665094871756920795E-4756 + 7899 2.128768819660545832547435878460398E-4756 1.064384409830272916273717939230199E-4756 + 7900 5.321922049151364581368589696150995E-4757 2.660961024575682290684294848075498E-4757 + 7901 1.330480512287841145342147424037749E-4757 6.652402561439205726710737120188745E-4758 + 7902 3.326201280719602863355368560094373E-4758 1.663100640359801431677684280047186E-4758 + 7903 8.31550320179900715838842140023593E-4759 4.157751600899503579194210700117965E-4759 + 7904 2.078875800449751789597105350058983E-4759 1.039437900224875894798552675029491E-4759 + 7905 5.197189501124379473992763375147455E-4760 2.598594750562189736996381687573728E-4760 + 7906 1.299297375281094868498190843786864E-4760 6.49648687640547434249095421893432E-4761 + 7907 3.24824343820273717124547710946716E-4761 1.62412171910136858562273855473358E-4761 + 7908 8.1206085955068429281136927736679E-4762 4.06030429775342146405684638683395E-4762 + 7909 2.030152148876710732028423193416975E-4762 1.015076074438355366014211596708488E-4762 + 7910 5.07538037219177683007105798354244E-4763 2.53769018609588841503552899177122E-4763 + 7911 1.26884509304794420751776449588561E-4763 6.34422546523972103758882247942805E-4764 + 7912 3.172112732619860518794411239714025E-4764 1.586056366309930259397205619857013E-4764 + 7913 7.930281831549651296986028099285065E-4765 3.965140915774825648493014049642533E-4765 + 7914 1.982570457887412824246507024821267E-4765 9.912852289437064121232535124106333E-4766 + 7915 4.956426144718532060616267562053167E-4766 2.478213072359266030308133781026583E-4766 + 7916 1.239106536179633015154066890513292E-4766 6.195532680898165075770334452566458E-4767 + 7917 3.097766340449082537885167226283229E-4767 1.548883170224541268942583613141615E-4767 + 7918 7.744415851122706344712918065708075E-4768 3.872207925561353172356459032854038E-4768 + 7919 1.936103962780676586178229516427019E-4768 9.680519813903382930891147582135095E-4769 + 7920 4.840259906951691465445573791067548E-4769 2.420129953475845732722786895533774E-4769 + 7921 1.210064976737922866361393447766887E-4769 6.050324883689614331806967238834435E-4770 + 7922 3.025162441844807165903483619417218E-4770 1.512581220922403582951741809708609E-4770 + 7923 7.562906104612017914758709048543045E-4771 3.781453052306008957379354524271523E-4771 + 7924 1.890726526153004478689677262135762E-4771 9.453632630765022393448386310678808E-4772 + 7925 4.726816315382511196724193155339404E-4772 2.363408157691255598362096577669702E-4772 + 7926 1.181704078845627799181048288834851E-4772 5.908520394228138995905241444174255E-4773 + 7927 2.954260197114069497952620722087128E-4773 1.477130098557034748976310361043564E-4773 + 7928 7.38565049278517374488155180521782E-4774 3.69282524639258687244077590260891E-4774 + 7929 1.846412623196293436220387951304455E-4774 9.232063115981467181101939756522275E-4775 + 7930 4.616031557990733590550969878261138E-4775 2.308015778995366795275484939130569E-4775 + 7931 1.154007889497683397637742469565285E-4775 5.770039447488416988188712347826423E-4776 + 7932 2.885019723744208494094356173913212E-4776 1.442509861872104247047178086956606E-4776 + 7933 7.21254930936052123523589043478303E-4777 3.606274654680260617617945217391515E-4777 + 7934 1.803137327340130308808972608695758E-4777 9.015686636700651544044863043478788E-4778 + 7935 4.507843318350325772022431521739394E-4778 2.253921659175162886011215760869697E-4778 + 7936 1.126960829587581443005607880434849E-4778 5.634804147937907215028039402174243E-4779 + 7937 2.817402073968953607514019701087122E-4779 1.408701036984476803757009850543561E-4779 + 7938 7.043505184922384018785049252717805E-4780 3.521752592461192009392524626358903E-4780 + 7939 1.760876296230596004696262313179452E-4780 8.804381481152980023481311565897258E-4781 + 7940 4.402190740576490011740655782948629E-4781 2.201095370288245005870327891474315E-4781 + 7941 1.100547685144122502935163945737158E-4781 5.502738425720612514675819728685788E-4782 + 7942 2.751369212860306257337909864342894E-4782 1.375684606430153128668954932171447E-4782 + 7943 6.878423032150765643344774660857235E-4783 3.439211516075382821672387330428618E-4783 + 7944 1.719605758037691410836193665214309E-4783 8.598028790188457054180968326071545E-4784 + 7945 4.299014395094228527090484163035773E-4784 2.149507197547114263545242081517886E-4784 + 7946 1.074753598773557131772621040758943E-4784 5.373767993867785658863105203794715E-4785 + 7947 2.686883996933892829431552601897358E-4785 1.343441998466946414715776300948679E-4785 + 7948 6.717209992334732073578881504743395E-4786 3.358604996167366036789440752371698E-4786 + 7949 1.679302498083683018394720376185849E-4786 8.396512490418415091973601880929245E-4787 + 7950 4.198256245209207545986800940464623E-4787 2.099128122604603772993400470232311E-4787 + 7951 1.049564061302301886496700235116156E-4787 5.247820306511509432483501175580778E-4788 + 7952 2.623910153255754716241750587790389E-4788 1.311955076627877358120875293895195E-4788 + 7953 6.559775383139386790604376469475975E-4789 3.279887691569693395302188234737988E-4789 + 7954 1.639943845784846697651094117368994E-4789 8.19971922892423348825547058684497E-4790 + 7955 4.099859614462116744127735293422485E-4790 2.049929807231058372063867646711243E-4790 + 7956 1.024964903615529186031933823355622E-4790 5.124824518077645930159669116778108E-4791 + 7957 2.562412259038822965079834558389054E-4791 1.281206129519411482539917279194527E-4791 + 7958 6.406030647597057412699586395972635E-4792 3.203015323798528706349793197986318E-4792 + 7959 1.601507661899264353174896598993159E-4792 8.007538309496321765874482994965795E-4793 + 7960 4.003769154748160882937241497482898E-4793 2.001884577374080441468620748741449E-4793 + 7961 1.000942288687040220734310374370725E-4793 5.004711443435201103671551871853623E-4794 + 7962 2.502355721717600551835775935926812E-4794 1.251177860858800275917887967963406E-4794 + 7963 6.25588930429400137958943983981703E-4795 3.127944652147000689794719919908515E-4795 + 7964 1.563972326073500344897359959954258E-4795 7.819861630367501724486799799771288E-4796 + 7965 3.909930815183750862243399899885644E-4796 1.954965407591875431121699949942822E-4796 + 7966 9.77482703795937715560849974971411E-4797 4.887413518979688577804249874857055E-4797 + 7967 2.443706759489844288902124937428528E-4797 1.221853379744922144451062468714264E-4797 + 7968 6.10926689872461072225531234357132E-4798 3.05463344936230536112765617178566E-4798 + 7969 1.52731672468115268056382808589283E-4798 7.63658362340576340281914042946415E-4799 + 7970 3.818291811702881701409570214732075E-4799 1.909145905851440850704785107366038E-4799 + 7971 9.54572952925720425352392553683019E-4800 4.772864764628602126761962768415095E-4800 + 7972 2.386432382314301063380981384207548E-4800 1.193216191157150531690490692103774E-4800 + 7973 5.96608095578575265845245346051887E-4801 2.983040477892876329226226730259435E-4801 + 7974 1.491520238946438164613113365129718E-4801 7.457601194732190823065566825648588E-4802 + 7975 3.728800597366095411532783412824294E-4802 1.864400298683047705766391706412147E-4802 + 7976 9.322001493415238528831958532060735E-4803 4.661000746707619264415979266030368E-4803 + 7977 2.330500373353809632207989633015184E-4803 1.165250186676904816103994816507592E-4803 + 7978 5.82625093338452408051997408253796E-4804 2.91312546669226204025998704126898E-4804 + 7979 1.45656273334613102012999352063449E-4804 7.28281366673065510064996760317245E-4805 + 7980 3.641406833365327550324983801586225E-4805 1.820703416682663775162491900793113E-4805 + 7981 9.103517083413318875812459503965565E-4806 4.551758541706659437906229751982783E-4806 + 7982 2.275879270853329718953114875991392E-4806 1.137939635426664859476557437995696E-4806 + 7983 5.68969817713332429738278718997848E-4807 2.84484908856666214869139359498924E-4807 + 7984 1.42242454428333107434569679749462E-4807 7.1121227214166553717284839874731E-4808 + 7985 3.55606136070832768586424199373655E-4808 1.778030680354163842932120996868275E-4808 + 7986 8.890153401770819214660604984341375E-4809 4.445076700885409607330302492170688E-4809 + 7987 2.222538350442704803665151246085344E-4809 1.111269175221352401832575623042672E-4809 + 7988 5.55634587610676200916287811521336E-4810 2.77817293805338100458143905760668E-4810 + 7989 1.38908646902669050229071952880334E-4810 6.9454323451334525114535976440167E-4811 + 7990 3.47271617256672625572679882200835E-4811 1.736358086283363127863399411004175E-4811 + 7991 8.681790431416815639316997055020875E-4812 4.340895215708407819658498527510438E-4812 + 7992 2.170447607854203909829249263755219E-4812 1.085223803927101954914624631877610E-4812 + 7993 5.42611901963550977457312315938805E-4813 2.713059509817754887286561579694025E-4813 + 7994 1.356529754908877443643280789847013E-4813 6.782648774544387218216403949235063E-4814 + 7995 3.391324387272193609108201974617532E-4814 1.695662193636096804554100987308766E-4814 + 7996 8.47831096818048402277050493654383E-4815 4.239155484090242011385252468271915E-4815 + 7997 2.119577742045121005692626234135958E-4815 1.059788871022560502846313117067979E-4815 + 7998 5.298944355112802514231565585339895E-4816 2.649472177556401257115782792669948E-4816 + 7999 1.324736088778200628557891396334974E-4816 6.62368044389100314278945698167487E-4817 + 8000 3.311840221945501571394728490837435E-4817 1.655920110972750785697364245418718E-4817 + 8001 8.27960055486375392848682122709359E-4818 4.139800277431876964243410613546795E-4818 + 8002 2.069900138715938482121705306773398E-4818 1.034950069357969241060852653386699E-4818 + 8003 5.174750346789846205304263266933495E-4819 2.587375173394923102652131633466748E-4819 + 8004 1.293687586697461551326065816733374E-4819 6.46843793348730775663032908366687E-4820 + 8005 3.234218966743653878315164541833435E-4820 1.617109483371826939157582270916718E-4820 + 8006 8.08554741685913469578791135458359E-4821 4.042773708429567347893955677291795E-4821 + 8007 2.021386854214783673946977838645898E-4821 1.010693427107391836973488919322949E-4821 + 8008 5.053467135536959184867444596614745E-4822 2.526733567768479592433722298307373E-4822 + 8009 1.263366783884239796216861149153687E-4822 6.316833919421198981084305745768433E-4823 + 8010 3.158416959710599490542152872884217E-4823 1.579208479855299745271076436442108E-4823 + 8011 7.89604239927649872635538218221054E-4824 3.94802119963824936317769109110527E-4824 + 8012 1.974010599819124681588845545552635E-4824 9.870052999095623407944227727763175E-4825 + 8013 4.935026499547811703972113863881588E-4825 2.467513249773905851986056931940794E-4825 + 8014 1.233756624886952925993028465970397E-4825 6.168783124434764629965142329851985E-4826 + 8015 3.084391562217382314982571164925993E-4826 1.542195781108691157491285582462996E-4826 + 8016 7.71097890554345578745642791231498E-4827 3.85548945277172789372821395615749E-4827 + 8017 1.927744726385863946864106978078745E-4827 9.638723631929319734320534890393725E-4828 + 8018 4.819361815964659867160267445196863E-4828 2.409680907982329933580133722598431E-4828 + 8019 1.204840453991164966790066861299216E-4828 6.024202269955824833950334306496078E-4829 + 8020 3.012101134977912416975167153248039E-4829 1.506050567488956208487583576624020E-4829 + 8021 7.53025283744478104243791788312010E-4830 3.76512641872239052121895894156005E-4830 + 8022 1.882563209361195260609479470780025E-4830 9.412816046805976303047397353900125E-4831 + 8023 4.706408023402988151523698676950063E-4831 2.353204011701494075761849338475031E-4831 + 8024 1.176602005850747037880924669237516E-4831 5.883010029253735189404623346187578E-4832 + 8025 2.941505014626867594702311673093789E-4832 1.470752507313433797351155836546895E-4832 + 8026 7.353762536567168986755779182734475E-4833 3.676881268283584493377889591367238E-4833 + 8027 1.838440634141792246688944795683619E-4833 9.192203170708961233444723978418095E-4834 + 8028 4.596101585354480616722361989209048E-4834 2.298050792677240308361180994604524E-4834 + 8029 1.149025396338620154180590497302262E-4834 5.74512698169310077090295248651131E-4835 + 8030 2.872563490846550385451476243255655E-4835 1.436281745423275192725738121627828E-4835 + 8031 7.18140872711637596362869060813914E-4836 3.59070436355818798181434530406957E-4836 + 8032 1.795352181779093990907172652034785E-4836 8.976760908895469954535863260173925E-4837 + 8033 4.488380454447734977267931630086963E-4837 2.244190227223867488633965815043481E-4837 + 8034 1.122095113611933744316982907521741E-4837 5.610475568059668721584914537608703E-4838 + 8035 2.805237784029834360792457268804352E-4838 1.402618892014917180396228634402176E-4838 + 8036 7.01309446007458590198114317201088E-4839 3.50654723003729295099057158600544E-4839 + 8037 1.75327361501864647549528579300272E-4839 8.7663680750932323774764289650136E-4840 + 8038 4.3831840375466161887382144825068E-4840 2.1915920187733080943691072412534E-4840 + 8039 1.0957960093866540471845536206267E-4840 5.4789800469332702359227681031335E-4841 + 8040 2.73949002346663511796138405156675E-4841 1.369745011733317558980692025783375E-4841 + 8041 6.848725058666587794903460128916875E-4842 3.424362529333293897451730064458438E-4842 + 8042 1.712181264666646948725865032229219E-4842 8.560906323333234743629325161146095E-4843 + 8043 4.280453161666617371814662580573048E-4843 2.140226580833308685907331290286524E-4843 + 8044 1.070113290416654342953665645143262E-4843 5.35056645208327171476832822571631E-4844 + 8045 2.675283226041635857384164112858155E-4844 1.337641613020817928692082056429078E-4844 + 8046 6.68820806510408964346041028214539E-4845 3.344104032552044821730205141072695E-4845 + 8047 1.672052016276022410865102570536348E-4845 8.360260081380112054325512852681738E-4846 + 8048 4.180130040690056027162756426340869E-4846 2.090065020345028013581378213170435E-4846 + 8049 1.045032510172514006790689106585218E-4846 5.225162550862570033953445532926088E-4847 + 8050 2.612581275431285016976722766463044E-4847 1.306290637715642508488361383231522E-4847 + 8051 6.53145318857821254244180691615761E-4848 3.265726594289106271220903458078805E-4848 + 8052 1.632863297144553135610451729039403E-4848 8.164316485722765678052258645197013E-4849 + 8053 4.082158242861382839026129322598507E-4849 2.041079121430691419513064661299253E-4849 + 8054 1.020539560715345709756532330649627E-4849 5.102697803576728548782661653248133E-4850 + 8055 2.551348901788364274391330826624067E-4850 1.275674450894182137195665413312033E-4850 + 8056 6.378372254470910685978327066560165E-4851 3.189186127235455342989163533280083E-4851 + 8057 1.594593063617727671494581766640042E-4851 7.972965318088638357472908833200208E-4852 + 8058 3.986482659044319178736454416600104E-4852 1.993241329522159589368227208300052E-4852 + 8059 9.96620664761079794684113604150026E-4853 4.98310332380539897342056802075013E-4853 + 8060 2.491551661902699486710284010375065E-4853 1.245775830951349743355142005187533E-4853 + 8061 6.228879154756748716775710025937665E-4854 3.114439577378374358387855012968833E-4854 + 8062 1.557219788689187179193927506484417E-4854 7.786098943445935895969637532422083E-4855 + 8063 3.893049471722967947984818766211042E-4855 1.946524735861483973992409383105521E-4855 + 8064 9.732623679307419869962046915527605E-4856 4.866311839653709934981023457763803E-4856 + 8065 2.433155919826854967490511728881902E-4856 1.216577959913427483745255864440951E-4856 + 8066 6.082889799567137418726279322204755E-4857 3.041444899783568709363139661102378E-4857 + 8067 1.520722449891784354681569830551189E-4857 7.603612249458921773407849152755945E-4858 + 8068 3.801806124729460886703924576377973E-4858 1.900903062364730443351962288188986E-4858 + 8069 9.50451531182365221675981144094493E-4859 4.752257655911826108379905720472465E-4859 + 8070 2.376128827955913054189952860236233E-4859 1.188064413977956527094976430118116E-4859 + 8071 5.94032206988978263547488215059058E-4860 2.97016103494489131773744107529529E-4860 + 8072 1.485080517472445658868720537647645E-4860 7.425402587362228294343602688238225E-4861 + 8073 3.712701293681114147171801344119113E-4861 1.856350646840557073585900672059556E-4861 + 8074 9.28175323420278536792950336029778E-4862 4.64087661710139268396475168014889E-4862 + 8075 2.320438308550696341982375840074445E-4862 1.160219154275348170991187920037223E-4862 + 8076 5.801095771376740854955939600186115E-4863 2.900547885688370427477969800093058E-4863 + 8077 1.450273942844185213738984900046529E-4863 7.251369714220926068694924500232645E-4864 + 8078 3.625684857110463034347462250116323E-4864 1.812842428555231517173731125058161E-4864 + 8079 9.064212142776157585868655625290805E-4865 4.532106071388078792934327812645403E-4865 + 8080 2.266053035694039396467163906322702E-4865 1.133026517847019698233581953161351E-4865 + 8081 5.665132589235098491167909765806755E-4866 2.832566294617549245583954882903378E-4866 + 8082 1.416283147308774622791977441451689E-4866 7.081415736543873113959887207258445E-4867 + 8083 3.540707868271936556979943603629223E-4867 1.770353934135968278489971801814611E-4867 + 8084 8.851769670679841392449859009073055E-4868 4.425884835339920696224929504536528E-4868 + 8085 2.212942417669960348112464752268264E-4868 1.106471208834980174056232376134132E-4868 + 8086 5.53235604417490087028116188067066E-4869 2.76617802208745043514058094033533E-4869 + 8087 1.383089011043725217570290470167665E-4869 6.915445055218626087851452350838325E-4870 + 8088 3.457722527609313043925726175419163E-4870 1.728861263804656521962863087709581E-4870 + 8089 8.644306319023282609814315438547905E-4871 4.322153159511641304907157719273953E-4871 + 8090 2.161076579755820652453578859636977E-4871 1.080538289877910326226789429818488E-4871 + 8091 5.40269144938955163113394714909244E-4872 2.70134572469477581556697357454622E-4872 + 8092 1.35067286234738790778348678727311E-4872 6.75336431173693953891743393636555E-4873 + 8093 3.376682155868469769458716968182775E-4873 1.688341077934234884729358484091388E-4873 + 8094 8.44170538967117442364679242045694E-4874 4.22085269483558721182339621022847E-4874 + 8095 2.110426347417793605911698105114235E-4874 1.055213173708896802955849052557118E-4874 + 8096 5.27606586854448401477924526278559E-4875 2.638032934272242007389622631392795E-4875 + 8097 1.319016467136121003694811315696398E-4875 6.595082335680605018474056578481988E-4876 + 8098 3.297541167840302509237028289240994E-4876 1.648770583920151254618514144620497E-4876 + 8099 8.243852919600756273092570723102485E-4877 4.121926459800378136546285361551243E-4877 + 8100 2.060963229900189068273142680775622E-4877 1.030481614950094534136571340387811E-4877 + 8101 5.152408074750472670682856701939055E-4878 2.576204037375236335341428350969528E-4878 + 8102 1.288102018687618167670714175484764E-4878 6.44051009343809083835357087742382E-4879 + 8103 3.22025504671904541917678543871191E-4879 1.610127523359522709588392719355955E-4879 + 8104 8.050637616797613547941963596779775E-4880 4.025318808398806773970981798389888E-4880 + 8105 2.012659404199403386985490899194944E-4880 1.006329702099701693492745449597472E-4880 + 8106 5.03164851049850846746372724798736E-4881 2.51582425524925423373186362399368E-4881 + 8107 1.25791212762462711686593181199684E-4881 6.2895606381231355843296590599842E-4882 + 8108 3.1447803190615677921648295299921E-4882 1.57239015953078389608241476499605E-4882 + 8109 7.86195079765391948041207382498025E-4883 3.930975398826959740206036912490125E-4883 + 8110 1.965487699413479870103018456245063E-4883 9.827438497067399350515092281225313E-4884 + 8111 4.913719248533699675257546140612657E-4884 2.456859624266849837628773070306328E-4884 + 8112 1.228429812133424918814386535153164E-4884 6.14214906066712459407193267576582E-4885 + 8113 3.07107453033356229703596633788291E-4885 1.535537265166781148517983168941455E-4885 + 8114 7.677686325833905742589915844707275E-4886 3.838843162916952871294957922353638E-4886 + 8115 1.919421581458476435647478961176819E-4886 9.597107907292382178237394805884095E-4887 + 8116 4.798553953646191089118697402942048E-4887 2.399276976823095544559348701471024E-4887 + 8117 1.199638488411547772279674350735512E-4887 5.99819244205773886139837175367756E-4888 + 8118 2.99909622102886943069918587683878E-4888 1.49954811051443471534959293841939E-4888 + 8119 7.49774055257217357674796469209695E-4889 3.748870276286086788373982346048475E-4889 + 8120 1.874435138143043394186991173024238E-4889 9.372175690715216970934955865121188E-4890 + 8121 4.686087845357608485467477932560594E-4890 2.343043922678804242733738966280297E-4890 + 8122 1.171521961339402121366869483140149E-4890 5.857609806697010606834347415700743E-4891 + 8123 2.928804903348505303417173707850372E-4891 1.464402451674252651708586853925186E-4891 + 8124 7.32201225837126325854293426962593E-4892 3.661006129185631629271467134812965E-4892 + 8125 1.830503064592815814635733567406483E-4892 9.152515322964079073178667837032413E-4893 + 8126 4.576257661482039536589333918516207E-4893 2.288128830741019768294666959258103E-4893 + 8127 1.144064415370509884147333479629052E-4893 5.720322076852549420736667398145258E-4894 + 8128 2.860161038426274710368333699072629E-4894 1.430080519213137355184166849536315E-4894 + 8129 7.150402596065686775920834247681575E-4895 3.575201298032843387960417123840788E-4895 + 8130 1.787600649016421693980208561920394E-4895 8.93800324508210846990104280960197E-4896 + 8131 4.469001622541054234950521404800985E-4896 2.234500811270527117475260702400493E-4896 + 8132 1.117250405635263558737630351200247E-4896 5.586252028176317793688151756001233E-4897 + 8133 2.793126014088158896844075878000617E-4897 1.396563007044079448422037939000308E-4897 + 8134 6.98281503522039724211018969500154E-4898 3.49140751761019862105509484750077E-4898 + 8135 1.745703758805099310527547423750385E-4898 8.728518794025496552637737118751925E-4899 + 8136 4.364259397012748276318868559375963E-4899 2.182129698506374138159434279687981E-4899 + 8137 1.091064849253187069079717139843991E-4899 5.455324246265935345398585699219953E-4900 + 8138 2.727662123132967672699292849609977E-4900 1.363831061566483836349646424804988E-4900 + 8139 6.81915530783241918174823212402494E-4901 3.40957765391620959087411606201247E-4901 + 8140 1.704788826958104795437058031006235E-4901 8.523944134790523977185290155031175E-4902 + 8141 4.261972067395261988592645077515588E-4902 2.130986033697630994296322538757794E-4902 + 8142 1.065493016848815497148161269378897E-4902 5.327465084244077485740806346894485E-4903 + 8143 2.663732542122038742870403173447243E-4903 1.331866271061019371435201586723621E-4903 + 8144 6.659331355305096857176007933618105E-4904 3.329665677652548428588003966809053E-4904 + 8145 1.664832838826274214294001983404527E-4904 8.324164194131371071470009917022633E-4905 + 8146 4.162082097065685535735004958511317E-4905 2.081041048532842767867502479255658E-4905 + 8147 1.040520524266421383933751239627829E-4905 5.202602621332106919668756198139145E-4906 + 8148 2.601301310666053459834378099069573E-4906 1.300650655333026729917189049534786E-4906 + 8149 6.50325327666513364958594524767393E-4907 3.251626638332566824792972623836965E-4907 + 8150 1.625813319166283412396486311918483E-4907 8.129066595831417061982431559592413E-4908 + 8151 4.064533297915708530991215779796207E-4908 2.032266648957854265495607889898103E-4908 + 8152 1.016133324478927132747803944949052E-4908 5.080666622394635663739019724745258E-4909 + 8153 2.540333311197317831869509862372629E-4909 1.270166655598658915934754931186315E-4909 + 8154 6.350833277993294579673774655931575E-4910 3.175416638996647289836887327965788E-4910 + 8155 1.587708319498323644918443663982894E-4910 7.93854159749161822459221831991447E-4911 + 8156 3.969270798745809112296109159957235E-4911 1.984635399372904556148054579978618E-4911 + 8157 9.92317699686452278074027289989309E-4912 4.961588498432261390370136449946545E-4912 + 8158 2.480794249216130695185068224973273E-4912 1.240397124608065347592534112486636E-4912 + 8159 6.20198562304032673796267056243318E-4913 3.10099281152016336898133528121659E-4913 + 8160 1.550496405760081684490667640608295E-4913 7.752482028800408422453338203041475E-4914 + 8161 3.876241014400204211226669101520738E-4914 1.938120507200102105613334550760369E-4914 + 8162 9.690602536000510528066672753801845E-4915 4.845301268000255264033336376900923E-4915 + 8163 2.422650634000127632016668188450462E-4915 1.211325317000063816008334094225231E-4915 + 8164 6.056626585000319080041670471126155E-4916 3.028313292500159540020835235563078E-4916 + 8165 1.514156646250079770010417617781539E-4916 7.570783231250398850052088088907695E-4917 + 8166 3.785391615625199425026044044453848E-4917 1.892695807812599712513022022226924E-4917 + 8167 9.46347903906299856256511011113462E-4918 4.73173951953149928128255505556731E-4918 + 8168 2.365869759765749640641277527783655E-4918 1.182934879882874820320638763891828E-4918 + 8169 5.91467439941437410160319381945914E-4919 2.95733719970718705080159690972957E-4919 + 8170 1.478668599853593525400798454864785E-4919 7.393342999267967627003992274323925E-4920 + 8171 3.696671499633983813501996137161963E-4920 1.848335749816991906750998068580981E-4920 + 8172 9.241678749084959533754990342904905E-4921 4.620839374542479766877495171452453E-4921 + 8173 2.310419687271239883438747585726227E-4921 1.155209843635619941719373792863113E-4921 + 8174 5.776049218178099708596868964315565E-4922 2.888024609089049854298434482157783E-4922 + 8175 1.444012304544524927149217241078892E-4922 7.220061522722624635746086205394458E-4923 + 8176 3.610030761361312317873043102697229E-4923 1.805015380680656158936521551348615E-4923 + 8177 9.025076903403280794682607756743075E-4924 4.512538451701640397341303878371538E-4924 + 8178 2.256269225850820198670651939185769E-4924 1.128134612925410099335325969592885E-4924 + 8179 5.640673064627050496676629847964425E-4925 2.820336532313525248338314923982213E-4925 + 8180 1.410168266156762624169157461991107E-4925 7.050841330783813120845787309955533E-4926 + 8181 3.525420665391906560422893654977767E-4926 1.762710332695953280211446827488883E-4926 + 8182 8.813551663479766401057234137444415E-4927 4.406775831739883200528617068722208E-4927 + 8183 2.203387915869941600264308534361104E-4927 1.101693957934970800132154267180552E-4927 + 8184 5.50846978967485400066077133590276E-4928 2.75423489483742700033038566795138E-4928 + 8185 1.37711744741871350016519283397569E-4928 6.88558723709356750082596416987845E-4929 + 8186 3.442793618546783750412982084939225E-4929 1.721396809273391875206491042469613E-4929 + 8187 8.606984046366959376032455212348065E-4930 4.303492023183479688016227606174033E-4930 + 8188 2.151746011591739844008113803087017E-4930 1.075873005795869922004056901543508E-4930 + 8189 5.37936502897934961002028450771754E-4931 2.68968251448967480501014225385877E-4931 + 8190 1.344841257244837402505071126929385E-4931 6.724206286224187012525355634646925E-4932 + 8191 3.362103143112093506262677817323463E-4932 1.681051571556046753131338908661731E-4932 + 8192 8.405257857780233765656694543308655E-4933 4.202628928890116882828347271654328E-4933 + 8193 2.101314464445058441414173635827164E-4933 1.050657232222529220707086817913582E-4933 + 8194 5.25328616111264610353543408956791E-4934 2.626643080556323051767717044783955E-4934 + 8195 1.313321540278161525883858522391978E-4934 6.566607701390807629419292611959888E-4935 + 8196 3.283303850695403814709646305979944E-4935 1.641651925347701907354823152989972E-4935 + 8197 8.20825962673850953677411576494986E-4936 4.10412981336925476838705788247493E-4936 + 8198 2.052064906684627384193528941237465E-4936 1.026032453342313692096764470618733E-4936 + 8199 5.130162266711568460483822353093665E-4937 2.565081133355784230241911176546833E-4937 + 8200 1.282540566677892115120955588273417E-4937 6.412702833389460575604777941367083E-4938 + 8201 3.206351416694730287802388970683542E-4938 1.603175708347365143901194485341771E-4938 + 8202 8.015878541736825719505972426708855E-4939 4.007939270868412859752986213354428E-4939 + 8203 2.003969635434206429876493106677214E-4939 1.001984817717103214938246553338607E-4939 + 8204 5.009924088585516074691232766693035E-4940 2.504962044292758037345616383346518E-4940 + 8205 1.252481022146379018672808191673259E-4940 6.262405110731895093364040958366295E-4941 + 8206 3.131202555365947546682020479183148E-4941 1.565601277682973773341010239591574E-4941 + 8207 7.82800638841486886670505119795787E-4942 3.914003194207434433352525598978935E-4942 + 8208 1.957001597103717216676262799489468E-4942 9.785007985518586083381313997447338E-4943 + 8209 4.892503992759293041690656998723669E-4943 2.446251996379646520845328499361835E-4943 + 8210 1.223125998189823260422664249680918E-4943 6.115629990949116302113321248404588E-4944 + 8211 3.057814995474558151056660624202294E-4944 1.528907497737279075528330312101147E-4944 + 8212 7.644537488686395377641651560505735E-4945 3.822268744343197688820825780252868E-4945 + 8213 1.911134372171598844410412890126434E-4945 9.55567186085799422205206445063217E-4946 + 8214 4.777835930428997111026032225316085E-4946 2.388917965214498555513016112658043E-4946 + 8215 1.194458982607249277756508056329022E-4946 5.972294913036246388782540281645108E-4947 + 8216 2.986147456518123194391270140822554E-4947 1.493073728259061597195635070411277E-4947 + 8217 7.465368641295307985978175352056385E-4948 3.732684320647653992989087676028193E-4948 + 8218 1.866342160323826996494543838014097E-4948 9.331710801619134982472719190070483E-4949 + 8219 4.665855400809567491236359595035242E-4949 2.332927700404783745618179797517621E-4949 + 8220 1.166463850202391872809089898758811E-4949 5.832319251011959364045449493794053E-4950 + 8221 2.916159625505979682022724746897027E-4950 1.458079812752989841011362373448513E-4950 + 8222 7.290399063764949205056811867242565E-4951 3.645199531882474602528405933621283E-4951 + 8223 1.822599765941237301264202966810642E-4951 9.112998829706186506321014834053208E-4952 + 8224 4.556499414853093253160507417026604E-4952 2.278249707426546626580253708513302E-4952 + 8225 1.139124853713273313290126854256651E-4952 5.695624268566366566450634271283255E-4953 + 8226 2.847812134283183283225317135641628E-4953 1.423906067141591641612658567820814E-4953 + 8227 7.11953033570795820806329283910407E-4954 3.559765167853979104031646419552035E-4954 + 8228 1.779882583926989552015823209776018E-4954 8.899412919634947760079116048880088E-4955 + 8229 4.449706459817473880039558024440044E-4955 2.224853229908736940019779012220022E-4955 + 8230 1.112426614954368470009889506110011E-4955 5.562133074771842350049447530550055E-4956 + 8231 2.781066537385921175024723765275028E-4956 1.390533268692960587512361882637514E-4956 + 8232 6.95266634346480293756180941318757E-4957 3.476333171732401468780904706593785E-4957 + 8233 1.738166585866200734390452353296893E-4957 8.690832929331003671952261766484463E-4958 + 8234 4.345416464665501835976130883242232E-4958 2.172708232332750917988065441621116E-4958 + 8235 1.086354116166375458994032720810558E-4958 5.43177058083187729497016360405279E-4959 + 8236 2.715885290415938647485081802026395E-4959 1.357942645207969323742540901013198E-4959 + 8237 6.78971322603984661871270450506599E-4960 3.394856613019923309356352252532995E-4960 + 8238 1.697428306509961654678176126266498E-4960 8.487141532549808273390880631332488E-4961 + 8239 4.243570766274904136695440315666244E-4961 2.121785383137452068347720157833122E-4961 + 8240 1.060892691568726034173860078916561E-4961 5.304463457843630170869300394582805E-4962 + 8241 2.652231728921815085434650197291403E-4962 1.326115864460907542717325098645701E-4962 + 8242 6.630579322304537713586625493228505E-4963 3.315289661152268856793312746614253E-4963 + 8243 1.657644830576134428396656373307127E-4963 8.288224152880672141983281866535633E-4964 + 8244 4.144112076440336070991640933267817E-4964 2.072056038220168035495820466633908E-4964 + 8245 1.036028019110084017747910233316954E-4964 5.18014009555042008873955116658477E-4965 + 8246 2.590070047775210044369775583292385E-4965 1.295035023887605022184887791646193E-4965 + 8247 6.475175119438025110924438958230965E-4966 3.237587559719012555462219479115483E-4966 + 8248 1.618793779859506277731109739557742E-4966 8.093968899297531388655548697788708E-4967 + 8249 4.046984449648765694327774348894354E-4967 2.023492224824382847163887174447177E-4967 + 8250 1.011746112412191423581943587223589E-4967 5.058730562060957117909717936117943E-4968 + 8251 2.529365281030478558954858968058972E-4968 1.264682640515239279477429484029486E-4968 + 8252 6.32341320257619639738714742014743E-4969 3.161706601288098198693573710073715E-4969 + 8253 1.580853300644049099346786855036858E-4969 7.904266503220245496733934275184288E-4970 + 8254 3.952133251610122748366967137592144E-4970 1.976066625805061374183483568796072E-4970 + 8255 9.88033312902530687091741784398036E-4971 4.94016656451265343545870892199018E-4971 + 8256 2.47008328225632671772935446099509E-4971 1.235041641128163358864677230497545E-4971 + 8257 6.175208205640816794323386152487725E-4972 3.087604102820408397161693076243863E-4972 + 8258 1.543802051410204198580846538121932E-4972 7.719010257051020992904232690609658E-4973 + 8259 3.859505128525510496452116345304829E-4973 1.929752564262755248226058172652415E-4973 + 8260 9.648762821313776241130290863262075E-4974 4.824381410656888120565145431631038E-4974 + 8261 2.412190705328444060282572715815519E-4974 1.206095352664222030141286357907760E-4974 + 8262 6.03047676332111015070643178953880E-4975 3.01523838166055507535321589476940E-4975 + 8263 1.50761919083027753767660794738470E-4975 7.5380959541513876883830397369235E-4976 + 8264 3.76904797707569384419151986846175E-4976 1.884523988537846922095759934230875E-4976 + 8265 9.422619942689234610478799671154375E-4977 4.711309971344617305239399835577188E-4977 + 8266 2.355654985672308652619699917788594E-4977 1.177827492836154326309849958894297E-4977 + 8267 5.889137464180771631549249794471485E-4978 2.944568732090385815774624897235743E-4978 + 8268 1.472284366045192907887312448617872E-4978 7.361421830225964539436562243089358E-4979 + 8269 3.680710915112982269718281121544679E-4979 1.840355457556491134859140560772340E-4979 + 8270 9.20177728778245567429570280386170E-4980 4.60088864389122783714785140193085E-4980 + 8271 2.300444321945613918573925700965425E-4980 1.150222160972806959286962850482713E-4980 + 8272 5.751110804864034796434814252413565E-4981 2.875555402432017398217407126206783E-4981 + 8273 1.437777701216008699108703563103392E-4981 7.188888506080043495543517815516958E-4982 + 8274 3.594444253040021747771758907758479E-4982 1.797222126520010873885879453879240E-4982 + 8275 8.98611063260005436942939726939620E-4983 4.49305531630002718471469863469810E-4983 + 8276 2.24652765815001359235734931734905E-4983 1.123263829075006796178674658674525E-4983 + 8277 5.616319145375033980893373293372625E-4984 2.808159572687516990446686646686313E-4984 + 8278 1.404079786343758495223343323343157E-4984 7.020398931718792476116716616715783E-4985 + 8279 3.510199465859396238058358308357892E-4985 1.755099732929698119029179154178946E-4985 + 8280 8.77549866464849059514589577089473E-4986 4.387749332324245297572947885447365E-4986 + 8281 2.193874666162122648786473942723683E-4986 1.096937333081061324393236971361841E-4986 + 8282 5.484686665405306621966184856809205E-4987 2.742343332702653310983092428404603E-4987 + 8283 1.371171666351326655491546214202302E-4987 6.855858331756633277457731071011508E-4988 + 8284 3.427929165878316638728865535505754E-4988 1.713964582939158319364432767752877E-4988 + 8285 8.569822914695791596822163838764385E-4989 4.284911457347895798411081919382193E-4989 + 8286 2.142455728673947899205540959691097E-4989 1.071227864336973949602770479845548E-4989 + 8287 5.35613932168486974801385239922774E-4990 2.67806966084243487400692619961387E-4990 + 8288 1.339034830421217437003463099806935E-4990 6.695174152106087185017315499034675E-4991 + 8289 3.347587076053043592508657749517338E-4991 1.673793538026521796254328874758669E-4991 + 8290 8.368967690132608981271644373793345E-4992 4.184483845066304490635822186896673E-4992 + 8291 2.092241922533152245317911093448337E-4992 1.046120961266576122658955546724168E-4992 + 8292 5.23060480633288061329477773362084E-4993 2.61530240316644030664738886681042E-4993 + 8293 1.30765120158322015332369443340521E-4993 6.53825600791610076661847216702605E-4994 + 8294 3.269128003958050383309236083513025E-4994 1.634564001979025191654618041756513E-4994 + 8295 8.172820009895125958273090208782565E-4995 4.086410004947562979136545104391283E-4995 + 8296 2.043205002473781489568272552195642E-4995 1.021602501236890744784136276097821E-4995 + 8297 5.108012506184453723920681380489105E-4996 2.554006253092226861960340690244553E-4996 + 8298 1.277003126546113430980170345122277E-4996 6.385015632730567154900851725611383E-4997 + 8299 3.192507816365283577450425862805692E-4997 1.596253908182641788725212931402846E-4997 + 8300 7.98126954091320894362606465701423E-4998 3.990634770456604471813032328507115E-4998 + 8301 1.995317385228302235906516164253558E-4998 9.976586926141511179532580821267788E-4999 + 8302 4.988293463070755589766290410633894E-4999 2.494146731535377794883145205316947E-4999 + 8303 1.247073365767688897441572602658474E-4999 6.235366828838444487207863013292368E-5000 + 8304 3.117683414419222243603931506646184E-5000 1.558841707209611121801965753323092E-5000 + 8305 7.79420853604805560900982876661546E-5001 3.89710426802402780450491438330773E-5001 + 8306 1.948552134012013902252457191653865E-5001 9.742760670060069511262285958269325E-5002 + 8307 4.871380335030034755631142979134663E-5002 2.435690167515017377815571489567331E-5002 + 8308 1.217845083757508688907785744783666E-5002 6.089225418787543444538928723918328E-5003 + 8309 3.044612709393771722269464361959164E-5003 1.522306354696885861134732180979582E-5003 + 8310 7.61153177348442930567366090489791E-5004 3.805765886742214652836830452448955E-5004 + 8311 1.902882943371107326418415226224478E-5004 9.514414716855536632092076131122388E-5005 + 8312 4.757207358427768316046038065561194E-5005 2.378603679213884158023019032780597E-5005 + 8313 1.189301839606942079011509516390299E-5005 5.946509198034710395057547581951493E-5006 + 8314 2.973254599017355197528773790975747E-5006 1.486627299508677598764386895487873E-5006 + 8315 7.433136497543387993821934477439365E-5007 3.716568248771693996910967238719683E-5007 + 8316 1.858284124385846998455483619359842E-5007 9.291420621929234992277418096799208E-5008 + 8317 4.645710310964617496138709048399604E-5008 2.322855155482308748069354524199802E-5008 + 8318 1.161427577741154374034677262099901E-5008 5.807137888705771870173386310499505E-5009 + 8319 2.903568944352885935086693155249753E-5009 1.451784472176442967543346577624876E-5009 + 8320 7.25892236088221483771673288812438E-5010 3.62946118044110741885836644406219E-5010 + 8321 1.814730590220553709429183222031095E-5010 9.073652951102768547145916110155475E-5011 + 8322 4.536826475551384273572958055077738E-5011 2.268413237775692136786479027538869E-5011 + 8323 1.134206618887846068393239513769435E-5011 5.671033094439230341966197568847173E-5012 + 8324 2.835516547219615170983098784423587E-5012 1.417758273609807585491549392211793E-5012 + 8325 7.088791368049037927457746961058965E-5013 3.544395684024518963728873480529483E-5013 + 8326 1.772197842012259481864436740264742E-5013 8.860989210061297409322183701323708E-5014 + 8327 4.430494605030648704661091850661854E-5014 2.215247302515324352330545925330927E-5014 + 8328 1.107623651257662176165272962665464E-5014 5.538118256288310880826364813327318E-5015 + 8329 2.769059128144155440413182406663659E-5015 1.384529564072077720206591203331830E-5015 + 8330 6.92264782036038860103295601665915E-5016 3.461323910180194300516478008329575E-5016 + 8331 1.730661955090097150258239004164788E-5016 8.653309775450485751291195020823938E-5017 + 8332 4.326654887725242875645597510411969E-5017 2.163327443862621437822798755205985E-5017 + 8333 1.081663721931310718911399377602993E-5017 5.408318609656553594556996888014963E-5018 + 8334 2.704159304828276797278498444007482E-5018 1.352079652414138398639249222003741E-5018 + 8335 6.760398262070691993196246110018705E-5019 3.380199131035345996598123055009353E-5019 + 8336 1.690099565517672998299061527504677E-5019 8.450497827588364991495307637523383E-5020 + 8337 4.225248913794182495747653818761692E-5020 2.112624456897091247873826909380846E-5020 + 8338 1.056312228448545623936913454690423E-5020 5.281561142242728119684567273452115E-5021 + 8339 2.640780571121364059842283636726058E-5021 1.320390285560682029921141818363029E-5021 + 8340 6.601951427803410149605709091815145E-5022 3.300975713901705074802854545907573E-5022 + 8341 1.650487856950852537401427272953787E-5022 8.252439284754262687007136364768933E-5023 + 8342 4.126219642377131343503568182384467E-5023 2.063109821188565671751784091192233E-5023 + 8343 1.031554910594282835875892045596117E-5023 5.157774552971414179379460227980583E-5024 + 8344 2.578887276485707089689730113990292E-5024 1.289443638242853544844865056995146E-5024 + 8345 6.44721819121426772422432528497573E-5025 3.223609095607133862112162642487865E-5025 + 8346 1.611804547803566931056081321243933E-5025 8.059022739017834655280406606219663E-5026 + 8347 4.029511369508917327640203303109832E-5026 2.014755684754458663820101651554916E-5026 + 8348 1.007377842377229331910050825777458E-5026 5.03688921188614665955025412888729E-5027 + 8349 2.518444605943073329775127064443645E-5027 1.259222302971536664887563532221823E-5027 + 8350 6.296111514857683324437817661109115E-5028 3.148055757428841662218908830554558E-5028 + 8351 1.574027878714420831109454415277279E-5028 7.870139393572104155547272076386395E-5029 + 8352 3.935069696786052077773636038193198E-5029 1.967534848393026038886818019096599E-5029 + 8353 9.837674241965130194434090095482995E-5030 4.918837120982565097217045047741498E-5030 + 8354 2.459418560491282548608522523870749E-5030 1.229709280245641274304261261935375E-5030 + 8355 6.148546401228206371521306309676875E-5031 3.074273200614103185760653154838438E-5031 + 8356 1.537136600307051592880326577419219E-5031 7.685683001535257964401632887096095E-5032 + 8357 3.842841500767628982200816443548048E-5032 1.921420750383814491100408221774024E-5032 + 8358 9.60710375191907245550204110887012E-5033 4.80355187595953622775102055443506E-5033 + 8359 2.40177593797976811387551027721753E-5033 1.200887968989884056937755138608765E-5033 + 8360 6.004439844949420284688775693043825E-5034 3.002219922474710142344387846521913E-5034 + 8361 1.501109961237355071172193923260957E-5034 7.505549806186775355860969616304783E-5035 + 8362 3.752774903093387677930484808152392E-5035 1.876387451546693838965242404076196E-5035 + 8363 9.38193725773346919482621202038098E-5036 4.69096862886673459741310601019049E-5036 + 8364 2.345484314433367298706553005095245E-5036 1.172742157216683649353276502547623E-5036 + 8365 5.863710786083418246766382512738115E-5037 2.931855393041709123383191256369058E-5037 + 8366 1.465927696520854561691595628184529E-5037 7.329638482604272808457978140922645E-5038 + 8367 3.664819241302136404228989070461323E-5038 1.832409620651068202114494535230661E-5038 + 8368 9.162048103255341010572472676153305E-5039 4.581024051627670505286236338076653E-5039 + 8369 2.290512025813835252643118169038327E-5039 1.145256012906917626321559084519163E-5039 + 8370 5.726280064534588131607795422595815E-5040 2.863140032267294065803897711297908E-5040 + 8371 1.431570016133647032901948855648954E-5040 7.15785008066823516450974427824477E-5041 + 8372 3.578925040334117582254872139122385E-5041 1.789462520167058791127436069561193E-5041 + 8373 8.947312600835293955637180347805965E-5042 4.473656300417646977818590173902983E-5042 + 8374 2.236828150208823488909295086951492E-5042 1.118414075104411744454647543475746E-5042 + 8375 5.59207037552205872227323771737873E-5043 2.796035187761029361136618858689365E-5043 + 8376 1.398017593880514680568309429344683E-5043 6.990087969402573402841547146723413E-5044 + 8377 3.495043984701286701420773573361707E-5044 1.747521992350643350710386786680853E-5044 + 8378 8.737609961753216753551933933404265E-5045 4.368804980876608376775966966702133E-5045 + 8379 2.184402490438304188387983483351067E-5045 1.092201245219152094193991741675533E-5045 + 8380 5.461006226095760470969958708377665E-5046 2.730503113047880235484979354188833E-5046 + 8381 1.365251556523940117742489677094417E-5046 6.826257782619700588712448385472083E-5047 + 8382 3.413128891309850294356224192736042E-5047 1.706564445654925147178112096368021E-5047 + 8383 8.532822228274625735890560481840105E-5048 4.266411114137312867945280240920053E-5048 + 8384 2.133205557068656433972640120460027E-5048 1.066602778534328216986320060230013E-5048 + 8385 5.333013892671641084931600301150065E-5049 2.666506946335820542465800150575033E-5049 + 8386 1.333253473167910271232900075287517E-5049 6.666267365839551356164500376437583E-5050 + 8387 3.333133682919775678082250188218792E-5050 1.666566841459887839041125094109396E-5050 + 8388 8.33283420729943919520562547054698E-5051 4.16641710364971959760281273527349E-5051 + 8389 2.083208551824859798801406367636745E-5051 1.041604275912429899400703183818373E-5051 + 8390 5.208021379562149497003515919091865E-5052 2.604010689781074748501757959545933E-5052 + 8391 1.302005344890537374250878979772967E-5052 6.510026724452686871254394898864833E-5053 + 8392 3.255013362226343435627197449432417E-5053 1.627506681113171717813598724716208E-5053 + 8393 8.13753340556585858906799362358104E-5054 4.06876670278292929453399681179052E-5054 + 8394 2.03438335139146464726699840589526E-5054 1.01719167569573232363349920294763E-5054 + 8395 5.08595837847866161816749601473815E-5055 2.542979189239330809083748007369075E-5055 + 8396 1.271489594619665404541874003684538E-5055 6.357447973098327022709370018422688E-5056 + 8397 3.178723986549163511354685009211344E-5056 1.589361993274581755677342504605672E-5056 + 8398 7.94680996637290877838671252302836E-5057 3.97340498318645438919335626151418E-5057 + 8399 1.98670249159322719459667813075709E-5057 9.93351245796613597298339065378545E-5058 + 8400 4.966756228983067986491695326892725E-5058 2.483378114491533993245847663446363E-5058 + 8401 1.241689057245766996622923831723182E-5058 6.208445286228834983114619158615908E-5059 + 8402 3.104222643114417491557309579307954E-5059 1.552111321557208745778654789653977E-5059 + 8403 7.760556607786043728893273948269885E-5060 3.880278303893021864446636974134943E-5060 + 8404 1.940139151946510932223318487067472E-5060 9.700695759732554661116592435337358E-5061 + 8405 4.850347879866277330558296217668679E-5061 2.425173939933138665279148108834340E-5061 + 8406 1.212586969966569332639574054417170E-5061 6.06293484983284666319787027208585E-5062 + 8407 3.031467424916423331598935136042925E-5062 1.515733712458211665799467568021463E-5062 + 8408 7.578668562291058328997337840107315E-5063 3.789334281145529164498668920053658E-5063 + 8409 1.894667140572764582249334460026829E-5063 9.473335702863822911246672300134145E-5064 + 8410 4.736667851431911455623336150067073E-5064 2.368333925715955727811668075033536E-5064 + 8411 1.184166962857977863905834037516768E-5064 5.92083481428988931952917018758384E-5065 + 8412 2.96041740714494465976458509379192E-5065 1.48020870357247232988229254689596E-5065 + 8413 7.4010435178623616494114627344798E-5066 3.7005217589311808247057313672399E-5066 + 8414 1.85026087946559041235286568361995E-5066 9.25130439732795206176432841809975E-5067 + 8415 4.625652198663976030882164209049875E-5067 2.312826099331988015441082104524938E-5067 + 8416 1.156413049665994007720541052262469E-5067 5.782065248329970038602705261312345E-5068 + 8417 2.891032624164985019301352630656173E-5068 1.445516312082492509650676315328086E-5068 + 8418 7.22758156041246254825338157664043E-5069 3.613790780206231274126690788320215E-5069 + 8419 1.806895390103115637063345394160108E-5069 9.034476950515578185316726970800538E-5070 + 8420 4.517238475257789092658363485400269E-5070 2.258619237628894546329181742700135E-5070 + 8421 1.129309618814447273164590871350068E-5070 5.646548094072236365822954356750338E-5071 + 8422 2.823274047036118182911477178375169E-5071 1.411637023518059091455738589187585E-5071 + 8423 7.058185117590295457278692945937925E-5072 3.529092558795147728639346472968963E-5072 + 8424 1.764546279397573864319673236484482E-5072 8.822731396987869321598366182422408E-5073 + 8425 4.411365698493934660799183091211204E-5073 2.205682849246967330399591545605602E-5073 + 8426 1.102841424623483665199795772802801E-5073 5.514207123117418325998978864014005E-5074 + 8427 2.757103561558709162999489432007003E-5074 1.378551780779354581499744716003501E-5074 + 8428 6.892758903896772907498723580017505E-5075 3.446379451948386453749361790008753E-5075 + 8429 1.723189725974193226874680895004377E-5075 8.615948629870966134373404475021883E-5076 + 8430 4.307974314935483067186702237510942E-5076 2.153987157467741533593351118755471E-5076 + 8431 1.076993578733870766796675559377736E-5076 5.384967893669353833983377796888678E-5077 + 8432 2.692483946834676916991688898444339E-5077 1.346241973417338458495844449222170E-5077 + 8433 6.73120986708669229247922224611085E-5078 3.365604933543346146239611123055425E-5078 + 8434 1.682802466771673073119805561527713E-5078 8.414012333858365365599027807638563E-5079 + 8435 4.207006166929182682799513903819282E-5079 2.103503083464591341399756951909641E-5079 + 8436 1.051751541732295670699878475954821E-5079 5.258757708661478353499392379774103E-5080 + 8437 2.629378854330739176749696189887052E-5080 1.314689427165369588374848094943526E-5080 + 8438 6.57344713582684794187424047471763E-5081 3.286723567913423970937120237358815E-5081 + 8439 1.643361783956711985468560118679408E-5081 8.216808919783559927342800593397038E-5082 + 8440 4.108404459891779963671400296698519E-5082 2.054202229945889981835700148349260E-5082 + 8441 1.027101114972944990917850074174630E-5082 5.13550557486472495458925037087315E-5083 + 8442 2.567752787432362477294625185436575E-5083 1.283876393716181238647312592718288E-5083 + 8443 6.41938196858090619323656296359144E-5084 3.20969098429045309661828148179572E-5084 + 8444 1.60484549214522654830914074089786E-5084 8.0242274607261327415457037044893E-5085 + 8445 4.01211373036306637077285185224465E-5085 2.006056865181533185386425926122325E-5085 + 8446 1.003028432590766592693212963061163E-5085 5.015142162953832963466064815305813E-5086 + 8447 2.507571081476916481733032407652907E-5086 1.253785540738458240866516203826453E-5086 + 8448 6.268927703692291204332581019132265E-5087 3.134463851846145602166290509566133E-5087 + 8449 1.567231925923072801083145254783067E-5087 7.836159629615364005415726273915333E-5088 + 8450 3.918079814807682002707863136957667E-5088 1.959039907403841001353931568478833E-5088 + 8451 9.795199537019205006769657842394165E-5089 4.897599768509602503384828921197083E-5089 + 8452 2.448799884254801251692414460598542E-5089 1.224399942127400625846207230299271E-5089 + 8453 6.121999710637003129231036151496355E-5090 3.060999855318501564615518075748178E-5090 + 8454 1.530499927659250782307759037874089E-5090 7.652499638296253911538795189370445E-5091 + 8455 3.826249819148126955769397594685223E-5091 1.913124909574063477884698797342611E-5091 + 8456 9.565624547870317389423493986713055E-5092 4.782812273935158694711746993356528E-5092 + 8457 2.391406136967579347355873496678264E-5092 1.195703068483789673677936748339132E-5092 + 8458 5.97851534241894836838968374169566E-5093 2.98925767120947418419484187084783E-5093 + 8459 1.494628835604737092097420935423915E-5093 7.473144178023685460487104677119575E-5094 + 8460 3.736572089011842730243552338559788E-5094 1.868286044505921365121776169279894E-5094 + 8461 9.34143022252960682560888084639947E-5095 4.670715111264803412804440423199735E-5095 + 8462 2.335357555632401706402220211599868E-5095 1.167678777816200853201110105799934E-5095 + 8463 5.83839388908100426600555052899967E-5096 2.919196944540502133002775264499835E-5096 + 8464 1.459598472270251066501387632249918E-5096 7.297992361351255332506938161249588E-5097 + 8465 3.648996180675627666253469080624794E-5097 1.824498090337813833126734540312397E-5097 + 8466 9.122490451689069165633672701561985E-5098 4.561245225844534582816836350780993E-5098 + 8467 2.280622612922267291408418175390497E-5098 1.140311306461133645704209087695248E-5098 + 8468 5.70155653230566822852104543847624E-5099 2.85077826615283411426052271923812E-5099 + 8469 1.42538913307641705713026135961906E-5099 7.1269456653820852856513067980953E-5100 + 8470 3.56347283269104264282565339904765E-5100 1.781736416345521321412826699523825E-5100 + 8471 8.908682081727606607064133497619125E-5101 4.454341040863803303532066748809563E-5101 + 8472 2.227170520431901651766033374404782E-5101 1.113585260215950825883016687202391E-5101 + 8473 5.567926301079754129415083436011955E-5102 2.783963150539877064707541718005978E-5102 + 8474 1.391981575269938532353770859002989E-5102 6.959907876349692661768854295014945E-5103 + 8475 3.479953938174846330884427147507473E-5103 1.739976969087423165442213573753736E-5103 + 8476 8.69988484543711582721106786876868E-5104 4.34994242271855791360553393438434E-5104 + 8477 2.17497121135927895680276696719217E-5104 1.087485605679639478401383483596085E-5104 + 8478 5.437428028398197392006917417980425E-5105 2.718714014199098696003458708990213E-5105 + 8479 1.359357007099549348001729354495107E-5105 6.796785035497746740008646772475533E-5106 + 8480 3.398392517748873370004323386237767E-5106 1.699196258874436685002161693118883E-5106 + 8481 8.495981294372183425010808465594415E-5107 4.247990647186091712505404232797208E-5107 + 8482 2.123995323593045856252702116398604E-5107 1.061997661796522928126351058199302E-5107 + 8483 5.30998830898261464063175529099651E-5108 2.654994154491307320315877645498255E-5108 + 8484 1.327497077245653660157938822749128E-5108 6.637485386228268300789694113745638E-5109 + 8485 3.318742693114134150394847056872819E-5109 1.659371346557067075197423528436410E-5109 + 8486 8.29685673278533537598711764218205E-5110 4.148428366392667687993558821091025E-5110 + 8487 2.074214183196333843996779410545513E-5110 1.037107091598166921998389705272756E-5110 + 8488 5.18553545799083460999194852636378E-5111 2.59276772899541730499597426318189E-5111 + 8489 1.296383864497708652497987131590945E-5111 6.481919322488543262489935657954725E-5112 + 8490 3.240959661244271631244967828977363E-5112 1.620479830622135815622483914488681E-5112 + 8491 8.102399153110679078112419572443405E-5113 4.051199576555339539056209786221703E-5113 + 8492 2.025599788277669769528104893110852E-5113 1.012799894138834884764052446555426E-5113 + 8493 5.06399947069417442382026223277713E-5114 2.531999735347087211910131116388565E-5114 + 8494 1.265999867673543605955065558194283E-5114 6.329999338367718029775327790971413E-5115 + 8495 3.164999669183859014887663895485707E-5115 1.582499834591929507443831947742853E-5115 + 8496 7.912499172959647537219159738714265E-5116 3.956249586479823768609579869357133E-5116 + 8497 1.978124793239911884304789934678567E-5116 9.890623966199559421523949673392833E-5117 + 8498 4.945311983099779710761974836696417E-5117 2.472655991549889855380987418348208E-5117 + 8499 1.236327995774944927690493709174104E-5117 6.18163997887472463845246854587052E-5118 + 8500 3.09081998943736231922623427293526E-5118 1.54540999471868115961311713646763E-5118 + 8501 7.72704997359340579806558568233815E-5119 3.863524986796702899032792841169075E-5119 + 8502 1.931762493398351449516396420584538E-5119 9.658812466991757247581982102922688E-5120 + 8503 4.829406233495878623790991051461344E-5120 2.414703116747939311895495525730672E-5120 + 8504 1.207351558373969655947747762865336E-5120 6.03675779186984827973873881432668E-5121 + 8505 3.01837889593492413986936940716334E-5121 1.50918944796746206993468470358167E-5121 + 8506 7.54594723983731034967342351790835E-5122 3.772973619918655174836711758954175E-5122 + 8507 1.886486809959327587418355879477088E-5122 9.432434049796637937091779397385438E-5123 + 8508 4.716217024898318968545889698692719E-5123 2.358108512449159484272944849346360E-5123 + 8509 1.179054256224579742136472424673180E-5123 5.89527128112289871068236212336590E-5124 + 8510 2.94763564056144935534118106168295E-5124 1.473817820280724677670590530841475E-5124 + 8511 7.369089101403623388352952654207375E-5125 3.684544550701811694176476327103688E-5125 + 8512 1.842272275350905847088238163551844E-5125 9.21136137675452923544119081775922E-5126 + 8513 4.60568068837726461772059540887961E-5126 2.302840344188632308860297704439805E-5126 + 8514 1.151420172094316154430148852219903E-5126 5.757100860471580772150744261099513E-5127 + 8515 2.878550430235790386075372130549757E-5127 1.439275215117895193037686065274878E-5127 + 8516 7.19637607558947596518843032637439E-5128 3.598188037794737982594215163187195E-5128 + 8517 1.799094018897368991297107581593598E-5128 8.995470094486844956485537907967988E-5129 + 8518 4.497735047243422478242768953983994E-5129 2.248867523621711239121384476991997E-5129 + 8519 1.124433761810855619560692238495999E-5129 5.622168809054278097803461192479993E-5130 + 8520 2.811084404527139048901730596239997E-5130 1.405542202263569524450865298119998E-5130 + 8521 7.02771101131784762225432649059999E-5131 3.513855505658923811127163245299995E-5131 + 8522 1.756927752829461905563581622649998E-5131 8.784638764147309527817908113249988E-5132 + 8523 4.392319382073654763908954056624994E-5132 2.196159691036827381954477028312497E-5132 + 8524 1.098079845518413690977238514156249E-5132 5.490399227592068454886192570781243E-5133 + 8525 2.745199613796034227443096285390622E-5133 1.372599806898017113721548142695311E-5133 + 8526 6.862999034490085568607740713476555E-5134 3.431499517245042784303870356738278E-5134 + 8527 1.715749758622521392151935178369139E-5134 8.578748793112606960759675891845695E-5135 + 8528 4.289374396556303480379837945922848E-5135 2.144687198278151740189918972961424E-5135 + 8529 1.072343599139075870094959486480712E-5135 5.36171799569537935047479743240356E-5136 + 8530 2.68085899784768967523739871620178E-5136 1.34042949892384483761869935810089E-5136 + 8531 6.70214749461922418809349679050445E-5137 3.351073747309612094046748395252225E-5137 + 8532 1.675536873654806047023374197626113E-5137 8.377684368274030235116870988130563E-5138 + 8533 4.188842184137015117558435494065282E-5138 2.094421092068507558779217747032641E-5138 + 8534 1.047210546034253779389608873516321E-5138 5.236052730171268896948044367581603E-5139 + 8535 2.618026365085634448474022183790802E-5139 1.309013182542817224237011091895401E-5139 + 8536 6.545065912714086121185055459477005E-5140 3.272532956357043060592527729738503E-5140 + 8537 1.636266478178521530296263864869252E-5140 8.181332390892607651481319324346258E-5141 + 8538 4.090666195446303825740659662173129E-5141 2.045333097723151912870329831086565E-5141 + 8539 1.022666548861575956435164915543283E-5141 5.113332744307879782175824577716413E-5142 + 8540 2.556666372153939891087912288858207E-5142 1.278333186076969945543956144429103E-5142 + 8541 6.391665930384849727719780722145515E-5143 3.195832965192424863859890361072758E-5143 + 8542 1.597916482596212431929945180536379E-5143 7.989582412981062159649725902681895E-5144 + 8543 3.994791206490531079824862951340948E-5144 1.997395603245265539912431475670474E-5144 + 8544 9.98697801622632769956215737835237E-5145 4.993489008113163849781078689176185E-5145 + 8545 2.496744504056581924890539344588093E-5145 1.248372252028290962445269672294046E-5145 + 8546 6.24186126014145481222634836147023E-5146 3.120930630070727406113174180735115E-5146 + 8547 1.560465315035363703056587090367558E-5146 7.802326575176818515282935451837788E-5147 + 8548 3.901163287588409257641467725918894E-5147 1.950581643794204628820733862959447E-5147 + 8549 9.752908218971023144103669314797235E-5148 4.876454109485511572051834657398618E-5148 + 8550 2.438227054742755786025917328699309E-5148 1.219113527371377893012958664349655E-5148 + 8551 6.095567636856889465064793321748275E-5149 3.047783818428444732532396660874138E-5149 + 8552 1.523891909214222366266198330437069E-5149 7.619459546071111831330991652185345E-5150 + 8553 3.809729773035555915665495826092673E-5150 1.904864886517777957832747913046336E-5150 + 8554 9.52432443258888978916373956523168E-5151 4.76216221629444489458186978261584E-5151 + 8555 2.38108110814722244729093489130792E-5151 1.19054055407361122364546744565396E-5151 + 8556 5.9527027703680561182273372282698E-5152 2.9763513851840280591136686141349E-5152 + 8557 1.48817569259201402955683430706745E-5152 7.44087846296007014778417153533725E-5153 + 8558 3.720439231480035073892085767668625E-5153 1.860219615740017536946042883834313E-5153 + 8559 9.301098078700087684730214419171565E-5154 4.650549039350043842365107209585783E-5154 + 8560 2.325274519675021921182553604792892E-5154 1.162637259837510960591276802396446E-5154 + 8561 5.81318629918755480295638401198223E-5155 2.906593149593777401478192005991115E-5155 + 8562 1.453296574796888700739096002995558E-5155 7.266482873984443503695480014977788E-5156 + 8563 3.633241436992221751847740007488894E-5156 1.816620718496110875923870003744447E-5156 + 8564 9.083103592480554379619350018722235E-5157 4.541551796240277189809675009361118E-5157 + 8565 2.270775898120138594904837504680559E-5157 1.135387949060069297452418752340280E-5157 + 8566 5.67693974530034648726209376170140E-5158 2.83846987265017324363104688085070E-5158 + 8567 1.41923493632508662181552344042535E-5158 7.09617468162543310907761720212675E-5159 + 8568 3.548087340812716554538808601063375E-5159 1.774043670406358277269404300531688E-5159 + 8569 8.87021835203179138634702150265844E-5160 4.43510917601589569317351075132922E-5160 + 8570 2.21755458800794784658675537566461E-5160 1.108777294003973923293377687832305E-5160 + 8571 5.543886470019869616466888439161525E-5161 2.771943235009934808233444219580763E-5161 + 8572 1.385971617504967404116722109790382E-5161 6.929858087524837020583610548951908E-5162 + 8573 3.464929043762418510291805274475954E-5162 1.732464521881209255145902637237977E-5162 + 8574 8.662322609406046275729513186189885E-5163 4.331161304703023137864756593094943E-5163 + 8575 2.165580652351511568932378296547472E-5163 1.082790326175755784466189148273736E-5163 + 8576 5.41395163087877892233094574136868E-5164 2.70697581543938946116547287068434E-5164 + 8577 1.35348790771969473058273643534217E-5164 6.76743953859847365291368217671085E-5165 + 8578 3.383719769299236826456841088355425E-5165 1.691859884649618413228420544177713E-5165 + 8579 8.459299423248092066142102720888565E-5166 4.229649711624046033071051360444283E-5166 + 8580 2.114824855812023016535525680222142E-5166 1.057412427906011508267762840111071E-5166 + 8581 5.287062139530057541338814200555355E-5167 2.643531069765028770669407100277678E-5167 + 8582 1.321765534882514385334703550138839E-5167 6.608827674412571926673517750694195E-5168 + 8583 3.304413837206285963336758875347098E-5168 1.652206918603142981668379437673549E-5168 + 8584 8.261034593015714908341897188367745E-5169 4.130517296507857454170948594183873E-5169 + 8585 2.065258648253928727085474297091937E-5169 1.032629324126964363542737148545968E-5169 + 8586 5.16314662063482181771368574272984E-5170 2.58157331031741090885684287136492E-5170 + 8587 1.29078665515870545442842143568246E-5170 6.4539332757935272721421071784123E-5171 + 8588 3.22696663789676363607105358920615E-5171 1.613483318948381818035526794603075E-5171 + 8589 8.067416594741909090177633973015375E-5172 4.033708297370954545088816986507688E-5172 + 8590 2.016854148685477272544408493253844E-5172 1.008427074342738636272204246626922E-5172 + 8591 5.04213537171369318136102123313461E-5173 2.521067685856846590680510616567305E-5173 + 8592 1.260533842928423295340255308283653E-5173 6.302669214642116476701276541418263E-5174 + 8593 3.151334607321058238350638270709132E-5174 1.575667303660529119175319135354566E-5174 + 8594 7.87833651830264559587659567677283E-5175 3.939168259151322797938297838386415E-5175 + 8595 1.969584129575661398969148919193208E-5175 9.847920647878306994845744595966038E-5176 + 8596 4.923960323939153497422872297983019E-5176 2.461980161969576748711436148991510E-5176 + 8597 1.230990080984788374355718074495755E-5176 6.154950404923941871778590372478775E-5177 + 8598 3.077475202461970935889295186239388E-5177 1.538737601230985467944647593119694E-5177 + 8599 7.69368800615492733972323796559847E-5178 3.846844003077463669861618982799235E-5178 + 8600 1.923422001538731834930809491399618E-5178 9.617110007693659174654047456998088E-5179 + 8601 4.808555003846829587327023728499044E-5179 2.404277501923414793663511864249522E-5179 + 8602 1.202138750961707396831755932124761E-5179 6.010693754808536984158779660623805E-5180 + 8603 3.005346877404268492079389830311903E-5180 1.502673438702134246039694915155951E-5180 + 8604 7.513367193510671230198474575779755E-5181 3.756683596755335615099237287889878E-5181 + 8605 1.878341798377667807549618643944939E-5181 9.391708991888339037748093219724695E-5182 + 8606 4.695854495944169518874046609862348E-5182 2.347927247972084759437023304931174E-5182 + 8607 1.173963623986042379718511652465587E-5182 5.869818119930211898592558262327935E-5183 + 8608 2.934909059965105949296279131163968E-5183 1.467454529982552974648139565581984E-5183 + 8609 7.33727264991276487324069782790992E-5184 3.66863632495638243662034891395496E-5184 + 8610 1.83431816247819121831017445697748E-5184 9.1715908123909560915508722848874E-5185 + 8611 4.5857954061954780457754361424437E-5185 2.29289770309773902288771807122185E-5185 + 8612 1.146448851548869511443859035610925E-5185 5.732244257744347557219295178054625E-5186 + 8613 2.866122128872173778609647589027313E-5186 1.433061064436086889304823794513656E-5186 + 8614 7.16530532218043444652411897256828E-5187 3.58265266109021722326205948628414E-5187 + 8615 1.79132633054510861163102974314207E-5187 8.95663165272554305815514871571035E-5188 + 8616 4.478315826362771529077574357855175E-5188 2.239157913181385764538787178927588E-5188 + 8617 1.119578956590692882269393589463794E-5188 5.59789478295346441134696794731897E-5189 + 8618 2.798947391476732205673483973659485E-5189 1.399473695738366102836741986829743E-5189 + 8619 6.997368478691830514183709934148715E-5190 3.498684239345915257091854967074358E-5190 + 8620 1.749342119672957628545927483537179E-5190 8.746710598364788142729637417685895E-5191 + 8621 4.373355299182394071364818708842948E-5191 2.186677649591197035682409354421474E-5191 + 8622 1.093338824795598517841204677210737E-5191 5.466694123977992589206023386053685E-5192 + 8623 2.733347061988996294603011693026843E-5192 1.366673530994498147301505846513421E-5192 + 8624 6.833367654972490736507529232567105E-5193 3.416683827486245368253764616283553E-5193 + 8625 1.708341913743122684126882308141777E-5193 8.541709568715613420634411540708883E-5194 + 8626 4.270854784357806710317205770354442E-5194 2.135427392178903355158602885177221E-5194 + 8627 1.067713696089451677579301442588611E-5194 5.338568480447258387896507212943053E-5195 + 8628 2.669284240223629193948253606471527E-5195 1.334642120111814596974126803235763E-5195 + 8629 6.673210600559072984870634016178815E-5196 3.336605300279536492435317008089408E-5196 + 8630 1.668302650139768246217658504044704E-5196 8.34151325069884123108829252022352E-5197 + 8631 4.17075662534942061554414626011176E-5197 2.08537831267471030777207313005588E-5197 + 8632 1.04268915633735515388603656502794E-5197 5.2134457816867757694301828251397E-5198 + 8633 2.60672289084338788471509141256985E-5198 1.303361445421693942357545706284925E-5198 + 8634 6.516807227108469711787728531424625E-5199 3.258403613554234855893864265712313E-5199 + 8635 1.629201806777117427946932132856157E-5199 8.146009033885587139734660664280783E-5200 + 8636 4.073004516942793569867330332140392E-5200 2.036502258471396784933665166070196E-5200 + 8637 1.018251129235698392466832583035098E-5200 5.09125564617849196233416291517549E-5201 + 8638 2.545627823089245981167081457587745E-5201 1.272813911544622990583540728793873E-5201 + 8639 6.364069557723114952917703643969365E-5202 3.182034778861557476458851821984683E-5202 + 8640 1.591017389430778738229425910992342E-5202 7.955086947153893691147129554961708E-5203 + 8641 3.977543473576946845573564777480854E-5203 1.988771736788473422786782388740427E-5203 + 8642 9.943858683942367113933911943702135E-5204 4.971929341971183556966955971851068E-5204 + 8643 2.485964670985591778483477985925534E-5204 1.242982335492795889241738992962767E-5204 + 8644 6.214911677463979446208694964813835E-5205 3.107455838731989723104347482406918E-5205 + 8645 1.553727919365994861552173741203459E-5205 7.768639596829974307760868706017295E-5206 + 8646 3.884319798414987153880434353008648E-5206 1.942159899207493576940217176504324E-5206 + 8647 9.71079949603746788470108588252162E-5207 4.85539974801873394235054294126081E-5207 + 8648 2.427699874009366971175271470630405E-5207 1.213849937004683485587635735315203E-5207 + 8649 6.069249685023417427938178676576015E-5208 3.034624842511708713969089338288008E-5208 + 8650 1.517312421255854356984544669144004E-5208 7.58656210627927178492272334572002E-5209 + 8651 3.79328105313963589246136167286001E-5209 1.896640526569817946230680836430005E-5209 + 8652 9.483202632849089731153404182150025E-5210 4.741601316424544865576702091075013E-5210 + 8653 2.370800658212272432788351045537507E-5210 1.185400329106136216394175522768753E-5210 + 8654 5.927001645530681081970877613843765E-5211 2.963500822765340540985438806921883E-5211 + 8655 1.481750411382670270492719403460942E-5211 7.408752056913351352463597017304708E-5212 + 8656 3.704376028456675676231798508652354E-5212 1.852188014228337838115899254326177E-5212 + 8657 9.260940071141689190579496271630885E-5213 4.630470035570844595289748135815443E-5213 + 8658 2.315235017785422297644874067907722E-5213 1.157617508892711148822437033953861E-5213 + 8659 5.788087544463555744112185169769305E-5214 2.894043772231777872056092584884653E-5214 + 8660 1.447021886115888936028046292442327E-5214 7.235109430579444680140231462211633E-5215 + 8661 3.617554715289722340070115731105817E-5215 1.808777357644861170035057865552908E-5215 + 8662 9.04388678822430585017528932776454E-5216 4.52194339411215292508764466388227E-5216 + 8663 2.260971697056076462543822331941135E-5216 1.130485848528038231271911165970568E-5216 + 8664 5.65242924264019115635955582985284E-5217 2.82621462132009557817977791492642E-5217 + 8665 1.41310731066004778908988895746321E-5217 7.06553655330023894544944478731605E-5218 + 8666 3.532768276650119472724722393658025E-5218 1.766384138325059736362361196829013E-5218 + 8667 8.831920691625298681811805984145065E-5219 4.415960345812649340905902992072533E-5219 + 8668 2.207980172906324670452951496036267E-5219 1.103990086453162335226475748018133E-5219 + 8669 5.519950432265811676132378740090665E-5220 2.759975216132905838066189370045333E-5220 + 8670 1.379987608066452919033094685022667E-5220 6.899938040332264595165473425113333E-5221 + 8671 3.449969020166132297582736712556667E-5221 1.724984510083066148791368356278333E-5221 + 8672 8.624922550415330743956841781391665E-5222 4.312461275207665371978420890695833E-5222 + 8673 2.156230637603832685989210445347917E-5222 1.078115318801916342994605222673958E-5222 + 8674 5.39057659400958171497302611336979E-5223 2.695288297004790857486513056684895E-5223 + 8675 1.347644148502395428743256528342448E-5223 6.738220742511977143716282641712238E-5224 + 8676 3.369110371255988571858141320856119E-5224 1.684555185627994285929070660428060E-5224 + 8677 8.42277592813997142964535330214030E-5225 4.21138796406998571482267665107015E-5225 + 8678 2.105693982034992857411338325535075E-5225 1.052846991017496428705669162767538E-5225 + 8679 5.26423495508748214352834581383769E-5226 2.632117477543741071764172906918845E-5226 + 8680 1.316058738771870535882086453459423E-5226 6.580293693859352679410432267297113E-5227 + 8681 3.290146846929676339705216133648557E-5227 1.645073423464838169852608066824278E-5227 + 8682 8.22536711732419084926304033412139E-5228 4.112683558662095424631520167060695E-5228 + 8683 2.056341779331047712315760083530348E-5228 1.028170889665523856157880041765174E-5228 + 8684 5.14085444832761928078940020882587E-5229 2.570427224163809640394700104412935E-5229 + 8685 1.285213612081904820197350052206468E-5229 6.426068060409524100986750261032338E-5230 + 8686 3.213034030204762050493375130516169E-5230 1.606517015102381025246687565258085E-5230 + 8687 8.032585075511905126233437826290425E-5231 4.016292537755952563116718913145213E-5231 + 8688 2.008146268877976281558359456572607E-5231 1.004073134438988140779179728286303E-5231 + 8689 5.020365672194940703895898641431515E-5232 2.510182836097470351947949320715758E-5232 + 8690 1.255091418048735175973974660357879E-5232 6.275457090243675879869873301789395E-5233 + 8691 3.137728545121837939934936650894698E-5233 1.568864272560918969967468325447349E-5233 + 8692 7.844321362804594849837341627236745E-5234 3.922160681402297424918670813618373E-5234 + 8693 1.961080340701148712459335406809187E-5234 9.805401703505743562296677034045933E-5235 + 8694 4.902700851752871781148338517022967E-5235 2.451350425876435890574169258511483E-5235 + 8695 1.225675212938217945287084629255742E-5235 6.128376064691089726435423146278708E-5236 + 8696 3.064188032345544863217711573139354E-5236 1.532094016172772431608855786569677E-5236 + 8697 7.660470080863862158044278932848385E-5237 3.830235040431931079022139466424193E-5237 + 8698 1.915117520215965539511069733212097E-5237 9.575587601079827697555348666060483E-5238 + 8699 4.787793800539913848777674333030242E-5238 2.393896900269956924388837166515121E-5238 + 8700 1.196948450134978462194418583257561E-5238 5.984742250674892310972092916287803E-5239 + 8701 2.992371125337446155486046458143902E-5239 1.496185562668723077743023229071951E-5239 + 8702 7.480927813343615388715116145359755E-5240 3.740463906671807694357558072679878E-5240 + 8703 1.870231953335903847178779036339939E-5240 9.351159766679519235893895181699695E-5241 + 8704 4.675579883339759617946947590849848E-5241 2.337789941669879808973473795424924E-5241 + 8705 1.168894970834939904486736897712462E-5241 5.84447485417469952243368448856231E-5242 + 8706 2.922237427087349761216842244281155E-5242 1.461118713543674880608421122140578E-5242 + 8707 7.30559356771837440304210561070289E-5243 3.652796783859187201521052805351445E-5243 + 8708 1.826398391929593600760526402675723E-5243 9.131991959647968003802632013378613E-5244 + 8709 4.565995979823984001901316006689307E-5244 2.282997989911992000950658003344653E-5244 + 8710 1.141498994955996000475329001672327E-5244 5.707494974779980002376645008361633E-5245 + 8711 2.853747487389990001188322504180817E-5245 1.426873743694995000594161252090408E-5245 + 8712 7.13436871847497500297080626045204E-5246 3.56718435923748750148540313022602E-5246 + 8713 1.78359217961874375074270156511301E-5246 8.91796089809371875371350782556505E-5247 + 8714 4.458980449046859376856753912782525E-5247 2.229490224523429688428376956391263E-5247 + 8715 1.114745112261714844214188478195632E-5247 5.573725561308574221070942390978158E-5248 + 8716 2.786862780654287110535471195489079E-5248 1.393431390327143555267735597744540E-5248 + 8717 6.96715695163571777633867798872270E-5249 3.48357847581785888816933899436135E-5249 + 8718 1.741789237908929444084669497180675E-5249 8.708946189544647220423347485903375E-5250 + 8719 4.354473094772323610211673742951688E-5250 2.177236547386161805105836871475844E-5250 + 8720 1.088618273693080902552918435737922E-5250 5.44309136846540451276459217868961E-5251 + 8721 2.721545684232702256382296089344805E-5251 1.360772842116351128191148044672403E-5251 + 8722 6.803864210581755640955740223362015E-5252 3.401932105290877820477870111681008E-5252 + 8723 1.700966052645438910238935055840504E-5252 8.50483026322719455119467527920252E-5253 + 8724 4.25241513161359727559733763960126E-5253 2.12620756580679863779866881980063E-5253 + 8725 1.063103782903399318899334409900315E-5253 5.315518914516996594496672049501575E-5254 + 8726 2.657759457258498297248336024750788E-5254 1.328879728629249148624168012375394E-5254 + 8727 6.64439864314624574312084006187697E-5255 3.322199321573122871560420030938485E-5255 + 8728 1.661099660786561435780210015469243E-5255 8.305498303932807178901050077346213E-5256 + 8729 4.152749151966403589450525038673107E-5256 2.076374575983201794725262519336553E-5256 + 8730 1.038187287991600897362631259668277E-5256 5.190936439958004486813156298341383E-5257 + 8731 2.595468219979002243406578149170692E-5257 1.297734109989501121703289074585346E-5257 + 8732 6.48867054994750560851644537292673E-5258 3.244335274973752804258222686463365E-5258 + 8733 1.622167637486876402129111343231683E-5258 8.110838187434382010645556716158413E-5259 + 8734 4.055419093717191005322778358079207E-5259 2.027709546858595502661389179039603E-5259 + 8735 1.013854773429297751330694589519802E-5259 5.069273867146488756653472947599008E-5260 + 8736 2.534636933573244378326736473799504E-5260 1.267318466786622189163368236899752E-5260 + 8737 6.33659233393311094581684118449876E-5261 3.16829616696655547290842059224938E-5261 + 8738 1.58414808348327773645421029612469E-5261 7.92074041741638868227105148062345E-5262 + 8739 3.960370208708194341135525740311725E-5262 1.980185104354097170567762870155863E-5262 + 8740 9.900925521770485852838814350779315E-5263 4.950462760885242926419407175389658E-5263 + 8741 2.475231380442621463209703587694829E-5263 1.237615690221310731604851793847415E-5263 + 8742 6.188078451106553658024258969237075E-5264 3.094039225553276829012129484618538E-5264 + 8743 1.547019612776638414506064742309269E-5264 7.735098063883192072530323711546345E-5265 + 8744 3.867549031941596036265161855773173E-5265 1.933774515970798018132580927886586E-5265 + 8745 9.66887257985399009066290463943293E-5266 4.834436289926995045331452319716465E-5266 + 8746 2.417218144963497522665726159858233E-5266 1.208609072481748761332863079929116E-5266 + 8747 6.04304536240874380666431539964558E-5267 3.02152268120437190333215769982279E-5267 + 8748 1.510761340602185951666078849911395E-5267 7.553806703010929758330394249556975E-5268 + 8749 3.776903351505464879165197124778488E-5268 1.888451675752732439582598562389244E-5268 + 8750 9.44225837876366219791299281194622E-5269 4.72112918938183109895649640597311E-5269 + 8751 2.360564594690915549478248202986555E-5269 1.180282297345457774739124101493278E-5269 + 8752 5.90141148672728887369562050746639E-5270 2.950705743363644436847810253733195E-5270 + 8753 1.475352871681822218423905126866598E-5270 7.376764358409111092119525634332988E-5271 + 8754 3.688382179204555546059762817166494E-5271 1.844191089602277773029881408583247E-5271 + 8755 9.220955448011388865149407042916235E-5272 4.610477724005694432574703521458118E-5272 + 8756 2.305238862002847216287351760729059E-5272 1.152619431001423608143675880364530E-5272 + 8757 5.76309715500711804071837940182265E-5273 2.881548577503559020359189700911325E-5273 + 8758 1.440774288751779510179594850455663E-5273 7.203871443758897550897974252278313E-5274 + 8759 3.601935721879448775448987126139157E-5274 1.800967860939724387724493563069578E-5274 + 8760 9.00483930469862193862246781534789E-5275 4.502419652349310969311233907673945E-5275 + 8761 2.251209826174655484655616953836973E-5275 1.125604913087327742327808476918486E-5275 + 8762 5.62802456543663871163904238459243E-5276 2.814012282718319355819521192296215E-5276 + 8763 1.407006141359159677909760596148108E-5276 7.035030706795798389548802980740538E-5277 + 8764 3.517515353397899194774401490370269E-5277 1.758757676698949597387200745185135E-5277 + 8765 8.793788383494747986936003725925675E-5278 4.396894191747373993468001862962838E-5278 + 8766 2.198447095873686996734000931481419E-5278 1.099223547936843498367000465740710E-5278 + 8767 5.49611773968421749183500232870355E-5279 2.748058869842108745917501164351775E-5279 + 8768 1.374029434921054372958750582175888E-5279 6.870147174605271864793752910879438E-5280 + 8769 3.435073587302635932396876455439719E-5280 1.717536793651317966198438227719860E-5280 + 8770 8.58768396825658983099219113859930E-5281 4.29384198412829491549609556929965E-5281 + 8771 2.146920992064147457748047784649825E-5281 1.073460496032073728874023892324913E-5281 + 8772 5.367302480160368644370119461624565E-5282 2.683651240080184322185059730812283E-5282 + 8773 1.341825620040092161092529865406142E-5282 6.709128100200460805462649327030708E-5283 + 8774 3.354564050100230402731324663515354E-5283 1.677282025050115201365662331757677E-5283 + 8775 8.386410125250576006828311658788385E-5284 4.193205062625288003414155829394193E-5284 + 8776 2.096602531312644001707077914697097E-5284 1.048301265656322000853538957348548E-5284 + 8777 5.24150632828161000426769478674274E-5285 2.62075316414080500213384739337137E-5285 + 8778 1.310376582070402501066923696685685E-5285 6.551882910352012505334618483428425E-5286 + 8779 3.275941455176006252667309241714213E-5286 1.637970727588003126333654620857106E-5286 + 8780 8.18985363794001563166827310428553E-5287 4.094926818970007815834136552142765E-5287 + 8781 2.047463409485003907917068276071383E-5287 1.023731704742501953958534138035691E-5287 + 8782 5.118658523712509769792670690178455E-5288 2.559329261856254884896335345089228E-5288 + 8783 1.279664630928127442448167672544614E-5288 6.39832315464063721224083836272307E-5289 + 8784 3.199161577320318606120419181361535E-5289 1.599580788660159303060209590680768E-5289 + 8785 7.99790394330079651530104795340384E-5290 3.99895197165039825765052397670192E-5290 + 8786 1.99947598582519912882526198835096E-5290 9.9973799291259956441263099417548E-5291 + 8787 4.9986899645629978220631549708774E-5291 2.4993449822814989110315774854387E-5291 + 8788 1.24967249114074945551578874271935E-5291 6.24836245570374727757894371359675E-5292 + 8789 3.124181227851873638789471856798375E-5292 1.562090613925936819394735928399188E-5292 + 8790 7.81045306962968409697367964199594E-5293 3.90522653481484204848683982099797E-5293 + 8791 1.952613267407421024243419910498985E-5293 9.763066337037105121217099552494925E-5294 + 8792 4.881533168518552560608549776247463E-5294 2.440766584259276280304274888123731E-5294 + 8793 1.220383292129638140152137444061866E-5294 6.101916460648190700760687220309328E-5295 + 8794 3.050958230324095350380343610154664E-5295 1.525479115162047675190171805077332E-5295 + 8795 7.62739557581023837595085902538666E-5296 3.81369778790511918797542951269333E-5296 + 8796 1.906848893952559593987714756346665E-5296 9.534244469762797969938573781733325E-5297 + 8797 4.767122234881398984969286890866663E-5297 2.383561117440699492484643445433331E-5297 + 8798 1.191780558720349746242321722716666E-5297 5.958902793601748731211608613583328E-5298 + 8799 2.979451396800874365605804306791664E-5298 1.489725698400437182802902153395832E-5298 + 8800 7.44862849200218591401451076697916E-5299 3.72431424600109295700725538348958E-5299 + 8801 1.86215712300054647850362769174479E-5299 9.31078561500273239251813845872395E-5300 + 8802 4.655392807501366196259069229361975E-5300 2.327696403750683098129534614680988E-5300 + 8803 1.163848201875341549064767307340494E-5300 5.81924100937670774532383653670247E-5301 + 8804 2.909620504688353872661918268351235E-5301 1.454810252344176936330959134175618E-5301 + 8805 7.27405126172088468165479567087809E-5302 3.637025630860442340827397835439045E-5302 + 8806 1.818512815430221170413698917719523E-5302 9.092564077151105852068494588597613E-5303 + 8807 4.546282038575552926034247294298807E-5303 2.273141019287776463017123647149403E-5303 + 8808 1.136570509643888231508561823574702E-5303 5.682852548219441157542809117873508E-5304 + 8809 2.841426274109720578771404558936754E-5304 1.420713137054860289385702279468377E-5304 + 8810 7.103565685274301446928511397341885E-5305 3.551782842637150723464255698670943E-5305 + 8811 1.775891421318575361732127849335472E-5305 8.879457106592876808660639246677358E-5306 + 8812 4.439728553296438404330319623338679E-5306 2.219864276648219202165159811669340E-5306 + 8813 1.109932138324109601082579905834670E-5306 5.54966069162054800541289952917335E-5307 + 8814 2.774830345810274002706449764586675E-5307 1.387415172905137001353224882293338E-5307 + 8815 6.93707586452568500676612441146669E-5308 3.468537932262842503383062205733345E-5308 + 8816 1.734268966131421251691531102866673E-5308 8.671344830657106258457655514333363E-5309 + 8817 4.335672415328553129228827757166682E-5309 2.167836207664276564614413878583341E-5309 + 8818 1.083918103832138282307206939291671E-5309 5.419590519160691411536034696458353E-5310 + 8819 2.709795259580345705768017348229177E-5310 1.354897629790172852884008674114588E-5310 + 8820 6.77448814895086426442004337057294E-5311 3.38724407447543213221002168528647E-5311 + 8821 1.693622037237716066105010842643235E-5311 8.468110186188580330525054213216175E-5312 + 8822 4.234055093094290165262527106608088E-5312 2.117027546547145082631263553304044E-5312 + 8823 1.058513773273572541315631776652022E-5312 5.29256886636786270657815888326011E-5313 + 8824 2.646284433183931353289079441630055E-5313 1.323142216591965676644539720815028E-5313 + 8825 6.61571108295982838322269860407514E-5314 3.30785554147991419161134930203757E-5314 + 8826 1.653927770739957095805674651018785E-5314 8.269638853699785479028373255093925E-5315 + 8827 4.134819426849892739514186627546963E-5315 2.067409713424946369757093313773481E-5315 + 8828 1.033704856712473184878546656886741E-5315 5.168524283562365924392733284433703E-5316 + 8829 2.584262141781182962196366642216852E-5316 1.292131070890591481098183321108426E-5316 + 8830 6.46065535445295740549091660554213E-5317 3.230327677226478702745458302771065E-5317 + 8831 1.615163838613239351372729151385533E-5317 8.075819193066196756863645756927663E-5318 + 8832 4.037909596533098378431822878463832E-5318 2.018954798266549189215911439231916E-5318 + 8833 1.009477399133274594607955719615958E-5318 5.04738699566637297303977859807979E-5319 + 8834 2.523693497833186486519889299039895E-5319 1.261846748916593243259944649519948E-5319 + 8835 6.30923374458296621629972324759974E-5320 3.15461687229148310814986162379987E-5320 + 8836 1.577308436145741554074930811899935E-5320 7.886542180728707770374654059499675E-5321 + 8837 3.943271090364353885187327029749838E-5321 1.971635545182176942593663514874919E-5321 + 8838 9.858177725910884712968317574374595E-5322 4.929088862955442356484158787187298E-5322 + 8839 2.464544431477721178242079393593649E-5322 1.232272215738860589121039696796825E-5322 + 8840 6.161361078694302945605198483984125E-5323 3.080680539347151472802599241992063E-5323 + 8841 1.540340269673575736401299620996032E-5323 7.701701348367878682006498104980158E-5324 + 8842 3.850850674183939341003249052490079E-5324 1.925425337091969670501624526245040E-5324 + 8843 9.62712668545984835250812263122520E-5325 4.81356334272992417625406131561260E-5325 + 8844 2.40678167136496208812703065780630E-5325 1.20339083568248104406351532890315E-5325 + 8845 6.01695417841240522031757664451575E-5326 3.008477089206202610158788322257875E-5326 + 8846 1.504238544603101305079394161128938E-5326 7.521192723015506525396970805644688E-5327 + 8847 3.760596361507753262698485402822344E-5327 1.880298180753876631349242701411172E-5327 + 8848 9.40149090376938315674621350705586E-5328 4.70074545188469157837310675352793E-5328 + 8849 2.350372725942345789186553376763965E-5328 1.175186362971172894593276688381983E-5328 + 8850 5.875931814855864472966383441909915E-5329 2.937965907427932236483191720954958E-5329 + 8851 1.468982953713966118241595860477479E-5329 7.344914768569830591207979302387395E-5330 + 8852 3.672457384284915295603989651193698E-5330 1.836228692142457647801994825596849E-5330 + 8853 9.181143460712288239009974127984245E-5331 4.590571730356144119504987063992123E-5331 + 8854 2.295285865178072059752493531996062E-5331 1.147642932589036029876246765998031E-5331 + 8855 5.738214662945180149381233829990155E-5332 2.869107331472590074690616914995078E-5332 + 8856 1.434553665736295037345308457497539E-5332 7.172768328681475186726542287487695E-5333 + 8857 3.586384164340737593363271143743848E-5333 1.793192082170368796681635571871924E-5333 + 8858 8.96596041085184398340817785935962E-5334 4.48298020542592199170408892967981E-5334 + 8859 2.241490102712960995852044464839905E-5334 1.120745051356480497926022232419953E-5334 + 8860 5.603725256782402489630111162099765E-5335 2.801862628391201244815055581049883E-5335 + 8861 1.400931314195600622407527790524942E-5335 7.004656570978003112037638952624708E-5336 + 8862 3.502328285489001556018819476312354E-5336 1.751164142744500778009409738156177E-5336 + 8863 8.755820713722503890047048690780885E-5337 4.377910356861251945023524345390443E-5337 + 8864 2.188955178430625972511762172695222E-5337 1.094477589215312986255881086347611E-5337 + 8865 5.472387946076564931279405431738055E-5338 2.736193973038282465639702715869028E-5338 + 8866 1.368096986519141232819851357934514E-5338 6.84048493259570616409925678967257E-5339 + 8867 3.420242466297853082049628394836285E-5339 1.710121233148926541024814197418143E-5339 + 8868 8.550606165744632705124070987090715E-5340 4.275303082872316352562035493545358E-5340 + 8869 2.137651541436158176281017746772679E-5340 1.068825770718079088140508873386340E-5340 + 8870 5.34412885359039544070254436693170E-5341 2.67206442679519772035127218346585E-5341 + 8871 1.336032213397598860175636091732925E-5341 6.680161066987994300878180458664625E-5342 + 8872 3.340080533493997150439090229332313E-5342 1.670040266746998575219545114666156E-5342 + 8873 8.35020133373499287609772557333078E-5343 4.17510066686749643804886278666539E-5343 + 8874 2.087550333433748219024431393332695E-5343 1.043775166716874109512215696666348E-5343 + 8875 5.21887583358437054756107848333174E-5344 2.60943791679218527378053924166587E-5344 + 8876 1.304718958396092636890269620832935E-5344 6.523594791980463184451348104164675E-5345 + 8877 3.261797395990231592225674052082338E-5345 1.630898697995115796112837026041169E-5345 + 8878 8.154493489975578980564185130205845E-5346 4.077246744987789490282092565102923E-5346 + 8879 2.038623372493894745141046282551462E-5346 1.019311686246947372570523141275731E-5346 + 8880 5.096558431234736862852615706378655E-5347 2.548279215617368431426307853189328E-5347 + 8881 1.274139607808684215713153926594664E-5347 6.37069803904342107856576963297332E-5348 + 8882 3.18534901952171053928288481648666E-5348 1.59267450976085526964144240824333E-5348 + 8883 7.96337254880427634820721204121665E-5349 3.981686274402138174103606020608325E-5349 + 8884 1.990843137201069087051803010304163E-5349 9.954215686005345435259015051520813E-5350 + 8885 4.977107843002672717629507525760407E-5350 2.488553921501336358814753762880203E-5350 + 8886 1.244276960750668179407376881440102E-5350 6.221384803753340897036884407200508E-5351 + 8887 3.110692401876670448518442203600254E-5351 1.555346200938335224259221101800127E-5351 + 8888 7.776731004691676121296105509000635E-5352 3.888365502345838060648052754500318E-5352 + 8889 1.944182751172919030324026377250159E-5352 9.720913755864595151620131886250795E-5353 + 8890 4.860456877932297575810065943125398E-5353 2.430228438966148787905032971562699E-5353 + 8891 1.215114219483074393952516485781350E-5353 6.075571097415371969762582428906748E-5354 + 8892 3.037785548707685984881291214453374E-5354 1.518892774353842992440645607226687E-5354 + 8893 7.594463871769214962203228036133435E-5355 3.797231935884607481101614018066718E-5355 + 8894 1.898615967942303740550807009033359E-5355 9.493079839711518702754035045166795E-5356 + 8895 4.746539919855759351377017522583398E-5356 2.373269959927879675688508761291699E-5356 + 8896 1.186634979963939837844254380645850E-5356 5.933174899819699189221271903229248E-5357 + 8897 2.966587449909849594610635951614624E-5357 1.483293724954924797305317975807312E-5357 + 8898 7.41646862477462398652658987903656E-5358 3.70823431238731199326329493951828E-5358 + 8899 1.85411715619365599663164746975914E-5358 9.2705857809682799831582373487957E-5359 + 8900 4.63529289048413999157911867439785E-5359 2.317646445242069995789559337198925E-5359 + 8901 1.158823222621034997894779668599463E-5359 5.794116113105174989473898342997313E-5360 + 8902 2.897058056552587494736949171498657E-5360 1.448529028276293747368474585749328E-5360 + 8903 7.24264514138146873684237292874664E-5361 3.62132257069073436842118646437332E-5361 + 8904 1.81066128534536718421059323218666E-5361 9.0533064267268359210529661609333E-5362 + 8905 4.52665321336341796052648308046665E-5362 2.263326606681708980263241540233325E-5362 + 8906 1.131663303340854490131620770116663E-5362 5.658316516704272450658103850583313E-5363 + 8907 2.829158258352136225329051925291657E-5363 1.414579129176068112664525962645828E-5363 + 8908 7.07289564588034056332262981322914E-5364 3.53644782294017028166131490661457E-5364 + 8909 1.768223911470085140830657453307285E-5364 8.841119557350425704153287266536425E-5365 + 8910 4.420559778675212852076643633268213E-5365 2.210279889337606426038321816634106E-5365 + 8911 1.105139944668803213019160908317053E-5365 5.525699723344016065095804541585265E-5366 + 8912 2.762849861672008032547902270792633E-5366 1.381424930836004016273951135396316E-5366 + 8913 6.90712465418002008136975567698158E-5367 3.45356232709001004068487783849079E-5367 + 8914 1.726781163545005020342438919245395E-5367 8.633905817725025101712194596226975E-5368 + 8915 4.316952908862512550856097298113488E-5368 2.158476454431256275428048649056744E-5368 + 8916 1.079238227215628137714024324528372E-5368 5.39619113607814068857012162264186E-5369 + 8917 2.69809556803907034428506081132093E-5369 1.349047784019535172142530405660465E-5369 + 8918 6.745238920097675860712652028302325E-5370 3.372619460048837930356326014151163E-5370 + 8919 1.686309730024418965178163007075582E-5370 8.431548650122094825890815035377908E-5371 + 8920 4.215774325061047412945407517688954E-5371 2.107887162530523706472703758844477E-5371 + 8921 1.053943581265261853236351879422239E-5371 5.269717906326309266181759397111193E-5372 + 8922 2.634858953163154633090879698555597E-5372 1.317429476581577316545439849277798E-5372 + 8923 6.58714738290788658272719924638899E-5373 3.293573691453943291363599623194495E-5373 + 8924 1.646786845726971645681799811597248E-5373 8.233934228634858228408999057986238E-5374 + 8925 4.116967114317429114204499528993119E-5374 2.058483557158714557102249764496560E-5374 + 8926 1.029241778579357278551124882248280E-5374 5.14620889289678639275562441124140E-5375 + 8927 2.57310444644839319637781220562070E-5375 1.28655222322419659818890610281035E-5375 + 8928 6.43276111612098299094453051405175E-5376 3.216380558060491495472265257025875E-5376 + 8929 1.608190279030245747736132628512938E-5376 8.040951395151228738680663142564688E-5377 + 8930 4.020475697575614369340331571282344E-5377 2.010237848787807184670165785641172E-5377 + 8931 1.005118924393903592335082892820586E-5377 5.02559462196951796167541446410293E-5378 + 8932 2.512797310984758980837707232051465E-5378 1.256398655492379490418853616025733E-5378 + 8933 6.281993277461897452094268080128665E-5379 3.140996638730948726047134040064333E-5379 + 8934 1.570498319365474363023567020032167E-5379 7.852491596827371815117835100160833E-5380 + 8935 3.926245798413685907558917550080417E-5380 1.963122899206842953779458775040208E-5380 + 8936 9.81561449603421476889729387520104E-5381 4.90780724801710738444864693760052E-5381 + 8937 2.45390362400855369222432346880026E-5381 1.22695181200427684611216173440013E-5381 + 8938 6.13475906002138423056080867200065E-5382 3.067379530010692115280404336000325E-5382 + 8939 1.533689765005346057640202168000163E-5382 7.668448825026730288201010840000813E-5383 + 8940 3.834224412513365144100505420000407E-5383 1.917112206256682572050252710000203E-5383 + 8941 9.585561031283412860251263550001015E-5384 4.792780515641706430125631775000508E-5384 + 8942 2.396390257820853215062815887500254E-5384 1.198195128910426607531407943750127E-5384 + 8943 5.990975644552133037657039718750635E-5385 2.995487822276066518828519859375318E-5385 + 8944 1.497743911138033259414259929687659E-5385 7.488719555690166297071299648438295E-5386 + 8945 3.744359777845083148535649824219148E-5386 1.872179888922541574267824912109574E-5386 + 8946 9.36089944461270787133912456054787E-5387 4.680449722306353935669562280273935E-5387 + 8947 2.340224861153176967834781140136968E-5387 1.170112430576588483917390570068484E-5387 + 8948 5.85056215288294241958695285034242E-5388 2.92528107644147120979347642517121E-5388 + 8949 1.462640538220735604896738212585605E-5388 7.313202691103678024483691062928025E-5389 + 8950 3.656601345551839012241845531464013E-5389 1.828300672775919506120922765732006E-5389 + 8951 9.14150336387959753060461382866003E-5390 4.570751681939798765302306914330015E-5390 + 8952 2.285375840969899382651153457165008E-5390 1.142687920484949691325576728582504E-5390 + 8953 5.71343960242474845662788364291252E-5391 2.85671980121237422831394182145626E-5391 + 8954 1.42835990060618711415697091072813E-5391 7.14179950303093557078485455364065E-5392 + 8955 3.570899751515467785392427276820325E-5392 1.785449875757733892696213638410163E-5392 + 8956 8.927249378788669463481068192050815E-5393 4.463624689394334731740534096025408E-5393 + 8957 2.231812344697167365870267048012704E-5393 1.115906172348583682935133524006352E-5393 + 8958 5.57953086174291841467566762003176E-5394 2.78976543087145920733783381001588E-5394 + 8959 1.39488271543572960366891690500794E-5394 6.9744135771786480183445845250397E-5395 + 8960 3.48720678858932400917229226251985E-5395 1.743603394294662004586146131259925E-5395 + 8961 8.718016971473310022930730656299625E-5396 4.359008485736655011465365328149813E-5396 + 8962 2.179504242868327505732682664074907E-5396 1.089752121434163752866341332037453E-5396 + 8963 5.448760607170818764331706660187265E-5397 2.724380303585409382165853330093633E-5397 + 8964 1.362190151792704691082926665046817E-5397 6.810950758963523455414633325234083E-5398 + 8965 3.405475379481761727707316662617042E-5398 1.702737689740880863853658331308521E-5398 + 8966 8.513688448704404319268291656542605E-5399 4.256844224352202159634145828271303E-5399 + 8967 2.128422112176101079817072914135652E-5399 1.064211056088050539908536457067826E-5399 + 8968 5.32105528044025269954268228533913E-5400 2.660527640220126349771341142669565E-5400 + 8969 1.330263820110063174885670571334783E-5400 6.651319100550315874428352856673913E-5401 + 8970 3.325659550275157937214176428336957E-5401 1.662829775137578968607088214168478E-5401 + 8971 8.31414887568789484303544107084239E-5402 4.157074437843947421517720535421195E-5402 + 8972 2.078537218921973710758860267710598E-5402 1.039268609460986855379430133855299E-5402 + 8973 5.196343047304934276897150669276495E-5403 2.598171523652467138448575334638248E-5403 + 8974 1.299085761826233569224287667319124E-5403 6.49542880913116784612143833659562E-5404 + 8975 3.24771440456558392306071916829781E-5404 1.623857202282791961530359584148905E-5404 + 8976 8.119286011413959807651797920744525E-5405 4.059643005706979903825898960372263E-5405 + 8977 2.029821502853489951912949480186132E-5405 1.014910751426744975956474740093066E-5405 + 8978 5.07455375713372487978237370046533E-5406 2.537276878566862439891186850232665E-5406 + 8979 1.268638439283431219945593425116333E-5406 6.343192196417156099727967125581663E-5407 + 8980 3.171596098208578049863983562790832E-5407 1.585798049104289024931991781395416E-5407 + 8981 7.92899024552144512465995890697708E-5408 3.96449512276072256232997945348854E-5408 + 8982 1.98224756138036128116498972674427E-5408 9.91123780690180640582494863372135E-5409 + 8983 4.955618903450903202912474316860675E-5409 2.477809451725451601456237158430338E-5409 + 8984 1.238904725862725800728118579215169E-5409 6.194523629313629003640592896075845E-5410 + 8985 3.097261814656814501820296448037923E-5410 1.548630907328407250910148224018961E-5410 + 8986 7.743154536642036254550741120094805E-5411 3.871577268321018127275370560047403E-5411 + 8987 1.935788634160509063637685280023702E-5411 9.678943170802545318188426400118508E-5412 + 8988 4.839471585401272659094213200059254E-5412 2.419735792700636329547106600029627E-5412 + 8989 1.209867896350318164773553300014814E-5412 6.049339481751590823867766500074068E-5413 + 8990 3.024669740875795411933883250037034E-5413 1.512334870437897705966941625018517E-5413 + 8991 7.561674352189488529834708125092585E-5414 3.780837176094744264917354062546293E-5414 + 8992 1.890418588047372132458677031273147E-5414 9.452092940236860662293385156365733E-5415 + 8993 4.726046470118430331146692578182867E-5415 2.363023235059215165573346289091433E-5415 + 8994 1.181511617529607582786673144545717E-5415 5.907558087648037913933365722728583E-5416 + 8995 2.953779043824018956966682861364292E-5416 1.476889521912009478483341430682146E-5416 + 8996 7.38444760956004739241670715341073E-5417 3.692223804780023696208353576705365E-5417 + 8997 1.846111902390011848104176788352683E-5417 9.230559511950059240520883941763413E-5418 + 8998 4.615279755975029620260441970881707E-5418 2.307639877987514810130220985440853E-5418 + 8999 1.153819938993757405065110492720427E-5418 5.769099694968787025325552463602133E-5419 + 9000 2.884549847484393512662776231801067E-5419 1.442274923742196756331388115900533E-5419 + 9001 7.211374618710983781656940579502665E-5420 3.605687309355491890828470289751333E-5420 + 9002 1.802843654677745945414235144875667E-5420 9.014218273388729727071175724378333E-5421 + 9003 4.507109136694364863535587862189167E-5421 2.253554568347182431767793931094583E-5421 + 9004 1.126777284173591215883896965547292E-5421 5.633886420867956079419484827736458E-5422 + 9005 2.816943210433978039709742413868229E-5422 1.408471605216989019854871206934115E-5422 + 9006 7.042358026084945099274356034670575E-5423 3.521179013042472549637178017335288E-5423 + 9007 1.760589506521236274818589008667644E-5423 8.80294753260618137409294504333822E-5424 + 9008 4.40147376630309068704647252166911E-5424 2.200736883151545343523236260834555E-5424 + 9009 1.100368441575772671761618130417278E-5424 5.501842207878863358808090652086388E-5425 + 9010 2.750921103939431679404045326043194E-5425 1.375460551969715839702022663021597E-5425 + 9011 6.877302759848579198510113315107985E-5426 3.438651379924289599255056657553993E-5426 + 9012 1.719325689962144799627528328776997E-5426 8.596628449810723998137641643884983E-5427 + 9013 4.298314224905361999068820821942492E-5427 2.149157112452680999534410410971246E-5427 + 9014 1.074578556226340499767205205485623E-5427 5.372892781131702498836026027428115E-5428 + 9015 2.686446390565851249418013013714058E-5428 1.343223195282925624709006506857029E-5428 + 9016 6.716115976414628123545032534285145E-5429 3.358057988207314061772516267142573E-5429 + 9017 1.679028994103657030886258133571287E-5429 8.395144970518285154431290667856433E-5430 + 9018 4.197572485259142577215645333928217E-5430 2.098786242629571288607822666964108E-5430 + 9019 1.049393121314785644303911333482054E-5430 5.24696560657392822151955666741027E-5431 + 9020 2.623482803286964110759778333705135E-5431 1.311741401643482055379889166852568E-5431 + 9021 6.55870700821741027689944583426284E-5432 3.27935350410870513844972291713142E-5432 + 9022 1.63967675205435256922486145856571E-5432 8.19838376027176284612430729282855E-5433 + 9023 4.099191880135881423062153646414275E-5433 2.049595940067940711531076823207138E-5433 + 9024 1.024797970033970355765538411603569E-5433 5.123989850169851778827692058017845E-5434 + 9025 2.561994925084925889413846029008923E-5434 1.280997462542462944706923014504461E-5434 + 9026 6.404987312712314723534615072522305E-5435 3.202493656356157361767307536261153E-5435 + 9027 1.601246828178078680883653768130577E-5435 8.006234140890393404418268840652883E-5436 + 9028 4.003117070445196702209134420326442E-5436 2.001558535222598351104567210163221E-5436 + 9029 1.000779267611299175552283605081611E-5436 5.003896338056495877761418025408053E-5437 + 9030 2.501948169028247938880709012704027E-5437 1.250974084514123969440354506352013E-5437 + 9031 6.254870422570619847201772531760065E-5438 3.127435211285309923600886265880033E-5438 + 9032 1.563717605642654961800443132940017E-5438 7.818588028213274809002215664700083E-5439 + 9033 3.909294014106637404501107832350042E-5439 1.954647007053318702250553916175021E-5439 + 9034 9.773235035266593511252769580875105E-5440 4.886617517633296755626384790437553E-5440 + 9035 2.443308758816648377813192395218777E-5440 1.221654379408324188906596197609388E-5440 + 9036 6.10827189704162094453298098804694E-5441 3.05413594852081047226649049402347E-5441 + 9037 1.527067974260405236133245247011735E-5441 7.635339871302026180666226235058675E-5442 + 9038 3.817669935651013090333113117529338E-5442 1.908834967825506545166556558764669E-5442 + 9039 9.544174839127532725832782793823345E-5443 4.772087419563766362916391396911673E-5443 + 9040 2.386043709781883181458195698455837E-5443 1.193021854890941590729097849227918E-5443 + 9041 5.96510927445470795364548924613959E-5444 2.982554637227353976822744623069795E-5444 + 9042 1.491277318613676988411372311534898E-5444 7.456386593068384942056861557674488E-5445 + 9043 3.728193296534192471028430778837244E-5445 1.864096648267096235514215389418622E-5445 + 9044 9.32048324133548117757107694709311E-5446 4.660241620667740588785538473546555E-5446 + 9045 2.330120810333870294392769236773278E-5446 1.165060405166935147196384618386639E-5446 + 9046 5.825302025834675735981923091933195E-5447 2.912651012917337867990961545966598E-5447 + 9047 1.456325506458668933995480772983299E-5447 7.281627532293344669977403864916495E-5448 + 9048 3.640813766146672334988701932458248E-5448 1.820406883073336167494350966229124E-5448 + 9049 9.10203441536668083747175483114562E-5449 4.55101720768334041873587741557281E-5449 + 9050 2.275508603841670209367938707786405E-5449 1.137754301920835104683969353893203E-5449 + 9051 5.688771509604175523419846769466015E-5450 2.844385754802087761709923384733008E-5450 + 9052 1.422192877401043880854961692366504E-5450 7.11096438700521940427480846183252E-5451 + 9053 3.55548219350260970213740423091626E-5451 1.77774109675130485106870211545813E-5451 + 9054 8.88870548375652425534351057729065E-5452 4.444352741878262127671755288645325E-5452 + 9055 2.222176370939131063835877644322663E-5452 1.111088185469565531917938822161331E-5452 + 9056 5.555440927347827659589694110806655E-5453 2.777720463673913829794847055403328E-5453 + 9057 1.388860231836956914897423527701664E-5453 6.94430115918478457448711763850832E-5454 + 9058 3.47215057959239228724355881925416E-5454 1.73607528979619614362177940962708E-5454 + 9059 8.6803764489809807181088970481354E-5455 4.3401882244904903590544485240677E-5455 + 9060 2.17009411224524517952722426203385E-5455 1.085047056122622589763612131016925E-5455 + 9061 5.425235280613112948818060655084625E-5456 2.712617640306556474409030327542313E-5456 + 9062 1.356308820153278237204515163771157E-5456 6.781544100766391186022575818855783E-5457 + 9063 3.390772050383195593011287909427892E-5457 1.695386025191597796505643954713946E-5457 + 9064 8.47693012595798898252821977356973E-5458 4.238465062978994491264109886784865E-5458 + 9065 2.119232531489497245632054943392433E-5458 1.059616265744748622816027471696216E-5458 + 9066 5.29808132872374311408013735848108E-5459 2.64904066436187155704006867924054E-5459 + 9067 1.32452033218093577852003433962027E-5459 6.62260166090467889260017169810135E-5460 + 9068 3.311300830452339446300085849050675E-5460 1.655650415226169723150042924525338E-5460 + 9069 8.27825207613084861575021462262669E-5461 4.139126038065424307875107311313345E-5461 + 9070 2.069563019032712153937553655656673E-5461 1.034781509516356076968776827828336E-5461 + 9071 5.17390754758178038484388413914168E-5462 2.58695377379089019242194206957084E-5462 + 9072 1.29347688689544509621097103478542E-5462 6.4673844344772254810548551739271E-5463 + 9073 3.23369221723861274052742758696355E-5463 1.616846108619306370263713793481775E-5463 + 9074 8.084230543096531851318568967408875E-5464 4.042115271548265925659284483704438E-5464 + 9075 2.021057635774132962829642241852219E-5464 1.010528817887066481414821120926110E-5464 + 9076 5.05264408943533240707410560463055E-5465 2.526322044717666203537052802315275E-5465 + 9077 1.263161022358833101768526401157638E-5465 6.315805111794165508842632005788188E-5466 + 9078 3.157902555897082754421316002894094E-5466 1.578951277948541377210658001447047E-5466 + 9079 7.894756389742706886053290007235235E-5467 3.947378194871353443026645003617618E-5467 + 9080 1.973689097435676721513322501808809E-5467 9.868445487178383607566612509044045E-5468 + 9081 4.934222743589191803783306254522023E-5468 2.467111371794595901891653127261011E-5468 + 9082 1.233555685897297950945826563630506E-5468 6.167778429486489754729132818152528E-5469 + 9083 3.083889214743244877364566409076264E-5469 1.541944607371622438682283204538132E-5469 + 9084 7.70972303685811219341141602269066E-5470 3.85486151842905609670570801134533E-5470 + 9085 1.927430759214528048352854005672665E-5470 9.637153796072640241764270028363325E-5471 + 9086 4.818576898036320120882135014181663E-5471 2.409288449018160060441067507090831E-5471 + 9087 1.204644224509080030220533753545416E-5471 6.023221122545400151102668767727078E-5472 + 9088 3.011610561272700075551334383863539E-5472 1.505805280636350037775667191931770E-5472 + 9089 7.52902640318175018887833595965885E-5473 3.764513201590875094439167979829425E-5473 + 9090 1.882256600795437547219583989914713E-5473 9.411283003977187736097919949573563E-5474 + 9091 4.705641501988593868048959974786782E-5474 2.352820750994296934024479987393391E-5474 + 9092 1.176410375497148467012239993696696E-5474 5.882051877485742335061199968483478E-5475 + 9093 2.941025938742871167530599984241739E-5475 1.470512969371435583765299992120870E-5475 + 9094 7.35256484685717791882649996060435E-5476 3.676282423428588959413249980302175E-5476 + 9095 1.838141211714294479706624990151088E-5476 9.190706058571472398533124950755438E-5477 + 9096 4.595353029285736199266562475377719E-5477 2.297676514642868099633281237688860E-5477 + 9097 1.148838257321434049816640618844430E-5477 5.74419128660717024908320309422215E-5478 + 9098 2.872095643303585124541601547111075E-5478 1.436047821651792562270800773555538E-5478 + 9099 7.18023910825896281135400386777769E-5479 3.590119554129481405677001933888845E-5479 + 9100 1.795059777064740702838500966944423E-5479 8.975298885323703514192504834722113E-5480 + 9101 4.487649442661851757096252417361057E-5480 2.243824721330925878548126208680528E-5480 + 9102 1.121912360665462939274063104340264E-5480 5.60956180332731469637031552170132E-5481 + 9103 2.80478090166365734818515776085066E-5481 1.40239045083182867409257888042533E-5481 + 9104 7.01195225415914337046289440212665E-5482 3.505976127079571685231447201063325E-5482 + 9105 1.752988063539785842615723600531663E-5482 8.764940317698929213078618002658313E-5483 + 9106 4.382470158849464606539309001329157E-5483 2.191235079424732303269654500664578E-5483 + 9107 1.095617539712366151634827250332289E-5483 5.478087698561830758174136251661445E-5484 + 9108 2.739043849280915379087068125830723E-5484 1.369521924640457689543534062915361E-5484 + 9109 6.847609623202288447717670314576805E-5485 3.423804811601144223858835157288403E-5485 + 9110 1.711902405800572111929417578644202E-5485 8.559512029002860559647087893221008E-5486 + 9111 4.279756014501430279823543946610504E-5486 2.139878007250715139911771973305252E-5486 + 9112 1.069939003625357569955885986652626E-5486 5.34969501812678784977942993326313E-5487 + 9113 2.674847509063393924889714966631565E-5487 1.337423754531696962444857483315783E-5487 + 9114 6.687118772658484812224287416578915E-5488 3.343559386329242406112143708289458E-5488 + 9115 1.671779693164621203056071854144729E-5488 8.358898465823106015280359270723645E-5489 + 9116 4.179449232911553007640179635361823E-5489 2.089724616455776503820089817680911E-5489 + 9117 1.044862308227888251910044908840456E-5489 5.224311541139441259550224544202278E-5490 + 9118 2.612155770569720629775112272101139E-5490 1.306077885284860314887556136050570E-5490 + 9119 6.53038942642430157443778068025285E-5491 3.265194713212150787218890340126425E-5491 + 9120 1.632597356606075393609445170063213E-5491 8.162986783030376968047225850316063E-5492 + 9121 4.081493391515188484023612925158032E-5492 2.040746695757594242011806462579016E-5492 + 9122 1.020373347878797121005903231289508E-5492 5.10186673939398560502951615644754E-5493 + 9123 2.55093336969699280251475807822377E-5493 1.275466684848496401257379039111885E-5493 + 9124 6.377333424242482006286895195559425E-5494 3.188666712121241003143447597779713E-5494 + 9125 1.594333356060620501571723798889857E-5494 7.971666780303102507858618994449283E-5495 + 9126 3.985833390151551253929309497224642E-5495 1.992916695075775626964654748612321E-5495 + 9127 9.964583475378878134823273743061605E-5496 4.982291737689439067411636871530803E-5496 + 9128 2.491145868844719533705818435765402E-5496 1.245572934422359766852909217882701E-5496 + 9129 6.227864672111798834264546089413505E-5497 3.113932336055899417132273044706753E-5497 + 9130 1.556966168027949708566136522353377E-5497 7.784830840139748542830682611766883E-5498 + 9131 3.892415420069874271415341305883442E-5498 1.946207710034937135707670652941721E-5498 + 9132 9.731038550174685678538353264708605E-5499 4.865519275087342839269176632354303E-5499 + 9133 2.432759637543671419634588316177152E-5499 1.216379818771835709817294158088576E-5499 + 9134 6.08189909385917854908647079044288E-5500 3.04094954692958927454323539522144E-5500 + 9135 1.52047477346479463727161769761072E-5500 7.6023738673239731863580884880536E-5501 + 9136 3.8011869336619865931790442440268E-5501 1.9005934668309932965895221220134E-5501 + 9137 9.502967334154966482947610610067E-5502 4.7514836670774832414738053050335E-5502 + 9138 2.37574183353874162073690265251675E-5502 1.187870916769370810368451326258375E-5502 + 9139 5.939354583846854051842256631291875E-5503 2.969677291923427025921128315645938E-5503 + 9140 1.484838645961713512960564157822969E-5503 7.424193229808567564802820789114845E-5504 + 9141 3.712096614904283782401410394557423E-5504 1.856048307452141891200705197278711E-5504 + 9142 9.280241537260709456003525986393555E-5505 4.640120768630354728001762993196778E-5505 + 9143 2.320060384315177364000881496598389E-5505 1.160030192157588682000440748299195E-5505 + 9144 5.800150960787943410002203741495975E-5506 2.900075480393971705001101870747988E-5506 + 9145 1.450037740196985852500550935373994E-5506 7.25018870098492926250275467686997E-5507 + 9146 3.625094350492464631251377338434985E-5507 1.812547175246232315625688669217493E-5507 + 9147 9.062735876231161578128443346087465E-5508 4.531367938115580789064221673043733E-5508 + 9148 2.265683969057790394532110836521867E-5508 1.132841984528895197266055418260933E-5508 + 9149 5.664209922644475986330277091304665E-5509 2.832104961322237993165138545652333E-5509 + 9150 1.416052480661118996582569272826167E-5509 7.080262403305594982912846364130833E-5510 + 9151 3.540131201652797491456423182065417E-5510 1.770065600826398745728211591032708E-5510 + 9152 8.85032800413199372864105795516354E-5511 4.42516400206599686432052897758177E-5511 + 9153 2.212582001032998432160264488790885E-5511 1.106291000516499216080132244395443E-5511 + 9154 5.531455002582496080400661221977215E-5512 2.765727501291248040200330610988608E-5512 + 9155 1.382863750645624020100165305494304E-5512 6.91431875322812010050082652747152E-5513 + 9156 3.45715937661406005025041326373576E-5513 1.72857968830703002512520663186788E-5513 + 9157 8.6428984415351501256260331593394E-5514 4.3214492207675750628130165796697E-5514 + 9158 2.16072461038378753140650828983485E-5514 1.080362305191893765703254144917425E-5514 + 9159 5.401811525959468828516270724587125E-5515 2.700905762979734414258135362293563E-5515 + 9160 1.350452881489867207129067681146782E-5515 6.752264407449336035645338405733908E-5516 + 9161 3.376132203724668017822669202866954E-5516 1.688066101862334008911334601433477E-5516 + 9162 8.440330509311670044556673007167385E-5517 4.220165254655835022278336503583693E-5517 + 9163 2.110082627327917511139168251791847E-5517 1.055041313663958755569584125895923E-5517 + 9164 5.275206568319793777847920629479615E-5518 2.637603284159896888923960314739808E-5518 + 9165 1.318801642079948444461980157369904E-5518 6.59400821039974222230990078684952E-5519 + 9166 3.29700410519987111115495039342476E-5519 1.64850205259993555557747519671238E-5519 + 9167 8.2425102629996777778873759835619E-5520 4.12125513149983888894368799178095E-5520 + 9168 2.060627565749919444471843995890475E-5520 1.030313782874959722235921997945238E-5520 + 9169 5.15156891437479861117960998972619E-5521 2.575784457187399305589804994863095E-5521 + 9170 1.287892228593699652794902497431548E-5521 6.439461142968498263974512487157738E-5522 + 9171 3.219730571484249131987256243578869E-5522 1.609865285742124565993628121789435E-5522 + 9172 8.049326428710622829968140608947175E-5523 4.024663214355311414984070304473588E-5523 + 9173 2.012331607177655707492035152236794E-5523 1.006165803588827853746017576118397E-5523 + 9174 5.030829017944139268730087880591985E-5524 2.515414508972069634365043940295993E-5524 + 9175 1.257707254486034817182521970147997E-5524 6.288536272430174085912609850739983E-5525 + 9176 3.144268136215087042956304925369992E-5525 1.572134068107543521478152462684996E-5525 + 9177 7.86067034053771760739076231342498E-5526 3.93033517026885880369538115671249E-5526 + 9178 1.965167585134429401847690578356245E-5526 9.825837925672147009238452891781225E-5527 + 9179 4.912918962836073504619226445890613E-5527 2.456459481418036752309613222945306E-5527 + 9180 1.228229740709018376154806611472653E-5527 6.141148703545091880774033057363265E-5528 + 9181 3.070574351772545940387016528681633E-5528 1.535287175886272970193508264340816E-5528 + 9182 7.67643587943136485096754132170408E-5529 3.83821793971568242548377066085204E-5529 + 9183 1.91910896985784121274188533042602E-5529 9.5955448492892060637094266521301E-5530 + 9184 4.79777242464460303185471332606505E-5530 2.398886212322301515927356663032525E-5530 + 9185 1.199443106161150757963678331516263E-5530 5.997215530805753789818391657581313E-5531 + 9186 2.998607765402876894909195828790657E-5531 1.499303882701438447454597914395328E-5531 + 9187 7.49651941350719223727298957197664E-5532 3.74825970675359611863649478598832E-5532 + 9188 1.87412985337679805931824739299416E-5532 9.3706492668839902965912369649708E-5533 + 9189 4.6853246334419951482956184824854E-5533 2.3426623167209975741478092412427E-5533 + 9190 1.17133115836049878707390462062135E-5533 5.85665579180249393536952310310675E-5534 + 9191 2.928327895901246967684761551553375E-5534 1.464163947950623483842380775776688E-5534 + 9192 7.32081973975311741921190387888344E-5535 3.66040986987655870960595193944172E-5535 + 9193 1.83020493493827935480297596972086E-5535 9.1510246746913967740148798486043E-5536 + 9194 4.57551233734569838700743992430215E-5536 2.287756168672849193503719962151075E-5536 + 9195 1.143878084336424596751859981075538E-5536 5.719390421682122983759299905377688E-5537 + 9196 2.859695210841061491879649952688844E-5537 1.429847605420530745939824976344422E-5537 + 9197 7.14923802710265372969912488172211E-5538 3.574619013551326864849562440861055E-5538 + 9198 1.787309506775663432424781220430528E-5538 8.936547533878317162123906102152638E-5539 + 9199 4.468273766939158581061953051076319E-5539 2.234136883469579290530976525538160E-5539 + 9200 1.117068441734789645265488262769080E-5539 5.58534220867394822632744131384540E-5540 + 9201 2.79267110433697411316372065692270E-5540 1.39633555216848705658186032846135E-5540 + 9202 6.98167776084243528290930164230675E-5541 3.490838880421217641454650821153375E-5541 + 9203 1.745419440210608820727325410576688E-5541 8.727097201053044103636627052883438E-5542 + 9204 4.363548600526522051818313526441719E-5542 2.181774300263261025909156763220860E-5542 + 9205 1.090887150131630512954578381610430E-5542 5.45443575065815256477289190805215E-5543 + 9206 2.727217875329076282386445954026075E-5543 1.363608937664538141193222977013038E-5543 + 9207 6.81804468832269070596611488506519E-5544 3.409022344161345352983057442532595E-5544 + 9208 1.704511172080672676491528721266298E-5544 8.522555860403363382457643606331488E-5545 + 9209 4.261277930201681691228821803165744E-5545 2.130638965100840845614410901582872E-5545 + 9210 1.065319482550420422807205450791436E-5545 5.32659741275210211403602725395718E-5546 + 9211 2.66329870637605105701801362697859E-5546 1.331649353188025528509006813489295E-5546 + 9212 6.658246765940127642545034067446475E-5547 3.329123382970063821272517033723238E-5547 + 9213 1.664561691485031910636258516861619E-5547 8.322808457425159553181292584308095E-5548 + 9214 4.161404228712579776590646292154048E-5548 2.080702114356289888295323146077024E-5548 + 9215 1.040351057178144944147661573038512E-5548 5.20175528589072472073830786519256E-5549 + 9216 2.60087764294536236036915393259628E-5549 1.30043882147268118018457696629814E-5549 + 9217 6.5021941073634059009228848314907E-5550 3.25109705368170295046144241574535E-5550 + 9218 1.625548526840851475230721207872675E-5550 8.127742634204257376153606039363375E-5551 + 9219 4.063871317102128688076803019681688E-5551 2.031935658551064344038401509840844E-5551 + 9220 1.015967829275532172019200754920422E-5551 5.07983914637766086009600377460211E-5552 + 9221 2.539919573188830430048001887301055E-5552 1.269959786594415215024000943650528E-5552 + 9222 6.34979893297207607512000471825264E-5553 3.17489946648603803756000235912632E-5553 + 9223 1.58744973324301901878000117956316E-5553 7.9372486662150950939000058978158E-5554 + 9224 3.9686243331075475469500029489079E-5554 1.98431216655377377347500147445395E-5554 + 9225 9.92156083276886886737500737226975E-5555 4.960780416384434433687503686134875E-5555 + 9226 2.480390208192217216843751843067438E-5555 1.240195104096108608421875921533719E-5555 + 9227 6.200975520480543042109379607668595E-5556 3.100487760240271521054689803834298E-5556 + 9228 1.550243880120135760527344901917149E-5556 7.751219400600678802636724509585745E-5557 + 9229 3.875609700300339401318362254792873E-5557 1.937804850150169700659181127396436E-5557 + 9230 9.68902425075084850329590563698218E-5558 4.84451212537542425164795281849109E-5558 + 9231 2.422256062687712125823976409245545E-5558 1.211128031343856062911988204622773E-5558 + 9232 6.055640156719280314559941023113865E-5559 3.027820078359640157279970511556933E-5559 + 9233 1.513910039179820078639985255778467E-5559 7.569550195899100393199926278892333E-5560 + 9234 3.784775097949550196599963139446167E-5560 1.892387548974775098299981569723083E-5560 + 9235 9.461937744873875491499907848615415E-5561 4.730968872436937745749953924307708E-5561 + 9236 2.365484436218468872874976962153854E-5561 1.182742218109234436437488481076927E-5561 + 9237 5.913711090546172182187442405384635E-5562 2.956855545273086091093721202692318E-5562 + 9238 1.478427772636543045546860601346159E-5562 7.392138863182715227734303006730795E-5563 + 9239 3.696069431591357613867151503365398E-5563 1.848034715795678806933575751682699E-5563 + 9240 9.240173578978394034667878758413495E-5564 4.620086789489197017333939379206748E-5564 + 9241 2.310043394744598508666969689603374E-5564 1.155021697372299254333484844801687E-5564 + 9242 5.775108486861496271667424224008435E-5565 2.887554243430748135833712112004218E-5565 + 9243 1.443777121715374067916856056002109E-5565 7.218885608576870339584280280010545E-5566 + 9244 3.609442804288435169792140140005273E-5566 1.804721402144217584896070070002636E-5566 + 9245 9.02360701072108792448035035001318E-5567 4.51180350536054396224017517500659E-5567 + 9246 2.255901752680271981120087587503295E-5567 1.127950876340135990560043793751648E-5567 + 9247 5.63975438170067995280021896875824E-5568 2.81987719085033997640010948437912E-5568 + 9248 1.40993859542516998820005474218956E-5568 7.0496929771258499410002737109478E-5569 + 9249 3.5248464885629249705001368554739E-5569 1.76242324428146248525006842773695E-5569 + 9250 8.81211622140731242625034213868475E-5570 4.406058110703656213125171069342375E-5570 + 9251 2.203029055351828106562585534671188E-5570 1.101514527675914053281292767335594E-5570 + 9252 5.50757263837957026640646383667797E-5571 2.753786319189785133203231918338985E-5571 + 9253 1.376893159594892566601615959169493E-5571 6.884465797974462833008079795847463E-5572 + 9254 3.442232898987231416504039897923732E-5572 1.721116449493615708252019948961866E-5572 + 9255 8.60558224746807854126009974480933E-5573 4.302791123734039270630049872404665E-5573 + 9256 2.151395561867019635315024936202333E-5573 1.075697780933509817657512468101166E-5573 + 9257 5.37848890466754908828756234050583E-5574 2.689244452333774544143781170252915E-5574 + 9258 1.344622226166887272071890585126458E-5574 6.723111130834436360359452925632288E-5575 + 9259 3.361555565417218180179726462816144E-5575 1.680777782708609090089863231408072E-5575 + 9260 8.40388891354304545044931615704036E-5576 4.20194445677152272522465807852018E-5576 + 9261 2.10097222838576136261232903926009E-5576 1.050486114192880681306164519630045E-5576 + 9262 5.252430570964403406530822598150225E-5577 2.626215285482201703265411299075113E-5577 + 9263 1.313107642741100851632705649537557E-5577 6.565538213705504258163528247687783E-5578 + 9264 3.282769106852752129081764123843892E-5578 1.641384553426376064540882061921946E-5578 + 9265 8.20692276713188032270441030960973E-5579 4.103461383565940161352205154804865E-5579 + 9266 2.051730691782970080676102577402433E-5579 1.025865345891485040338051288701216E-5579 + 9267 5.12932672945742520169025644350608E-5580 2.56466336472871260084512822175304E-5580 + 9268 1.28233168236435630042256411087652E-5580 6.4116584118217815021128205543826E-5581 + 9269 3.2058292059108907510564102771913E-5581 1.60291460295544537552820513859565E-5581 + 9270 8.01457301477722687764102569297825E-5582 4.007286507388613438820512846489125E-5582 + 9271 2.003643253694306719410256423244563E-5582 1.001821626847153359705128211622281E-5582 + 9272 5.009108134235766798525641058111405E-5583 2.504554067117883399262820529055703E-5583 + 9273 1.252277033558941699631410264527852E-5583 6.261385167794708498157051322639258E-5584 + 9274 3.130692583897354249078525661319629E-5584 1.565346291948677124539262830659815E-5584 + 9275 7.826731459743385622696314153299075E-5585 3.913365729871692811348157076649538E-5585 + 9276 1.956682864935846405674078538324769E-5585 9.783414324679232028370392691623845E-5586 + 9277 4.891707162339616014185196345811923E-5586 2.445853581169808007092598172905961E-5586 + 9278 1.222926790584904003546299086452981E-5586 6.114633952924520017731495432264903E-5587 + 9279 3.057316976462260008865747716132452E-5587 1.528658488231130004432873858066226E-5587 + 9280 7.64329244115565002216436929033113E-5588 3.821646220577825011082184645165565E-5588 + 9281 1.910823110288912505541092322582783E-5588 9.554115551444562527705461612913913E-5589 + 9282 4.777057775722281263852730806456957E-5589 2.388528887861140631926365403228478E-5589 + 9283 1.194264443930570315963182701614239E-5589 5.971322219652851579815913508071195E-5590 + 9284 2.985661109826425789907956754035598E-5590 1.492830554913212894953978377017799E-5590 + 9285 7.464152774566064474769891885088995E-5591 3.732076387283032237384945942544498E-5591 + 9286 1.866038193641516118692472971272249E-5591 9.330190968207580593462364856361245E-5592 + 9287 4.665095484103790296731182428180623E-5592 2.332547742051895148365591214090311E-5592 + 9288 1.166273871025947574182795607045156E-5592 5.831369355129737870913978035225778E-5593 + 9289 2.915684677564868935456989017612889E-5593 1.457842338782434467728494508806445E-5593 + 9290 7.289211693912172338642472544032225E-5594 3.644605846956086169321236272016113E-5594 + 9291 1.822302923478043084660618136008057E-5594 9.111514617390215423303090680040283E-5595 + 9292 4.555757308695107711651545340020142E-5595 2.277878654347553855825772670010071E-5595 + 9293 1.138939327173776927912886335005036E-5595 5.694696635868884639564431675025178E-5596 + 9294 2.847348317934442319782215837512589E-5596 1.423674158967221159891107918756295E-5596 + 9295 7.118370794836105799455539593781475E-5597 3.559185397418052899727769796890738E-5597 + 9296 1.779592698709026449863884898445369E-5597 8.897963493545132249319424492226845E-5598 + 9297 4.448981746772566124659712246113423E-5598 2.224490873386283062329856123056711E-5598 + 9298 1.112245436693141531164928061528356E-5598 5.561227183465707655824640307641778E-5599 + 9299 2.780613591732853827912320153820889E-5599 1.390306795866426913956160076910445E-5599 + 9300 6.951533979332134569780800384552225E-5600 3.475766989666067284890400192276113E-5600 + 9301 1.737883494833033642445200096138057E-5600 8.689417474165168212226000480690283E-5601 + 9302 4.344708737082584106113000240345142E-5601 2.172354368541292053056500120172571E-5601 + 9303 1.086177184270646026528250060086286E-5601 5.430885921353230132641250300431428E-5602 + 9304 2.715442960676615066320625150215714E-5602 1.357721480338307533160312575107857E-5602 + 9305 6.788607401691537665801562875539285E-5603 3.394303700845768832900781437769643E-5603 + 9306 1.697151850422884416450390718884822E-5603 8.485759252114422082251953594424108E-5604 + 9307 4.242879626057211041125976797212054E-5604 2.121439813028605520562988398606027E-5604 + 9308 1.060719906514302760281494199303014E-5604 5.303599532571513801407470996515068E-5605 + 9309 2.651799766285756900703735498257534E-5605 1.325899883142878450351867749128767E-5605 + 9310 6.629499415714392251759338745643835E-5606 3.314749707857196125879669372821918E-5606 + 9311 1.657374853928598062939834686410959E-5606 8.286874269642990314699173432054795E-5607 + 9312 4.143437134821495157349586716027398E-5607 2.071718567410747578674793358013699E-5607 + 9313 1.035859283705373789337396679006850E-5607 5.179296418526868946686983395034248E-5608 + 9314 2.589648209263434473343491697517124E-5608 1.294824104631717236671745848758562E-5608 + 9315 6.47412052315858618335872924379281E-5609 3.237060261579293091679364621896405E-5609 + 9316 1.618530130789646545839682310948203E-5609 8.092650653948232729198411554741013E-5610 + 9317 4.046325326974116364599205777370507E-5610 2.023162663487058182299602888685253E-5610 + 9318 1.011581331743529091149801444342627E-5610 5.057906658717645455749007221713133E-5611 + 9319 2.528953329358822727874503610856567E-5611 1.264476664679411363937251805428283E-5611 + 9320 6.322383323397056819686259027141415E-5612 3.161191661698528409843129513570708E-5612 + 9321 1.580595830849264204921564756785354E-5612 7.90297915424632102460782378392677E-5613 + 9322 3.951489577123160512303911891963385E-5613 1.975744788561580256151955945981693E-5613 + 9323 9.878723942807901280759779729908465E-5614 4.939361971403950640379889864954233E-5614 + 9324 2.469680985701975320189944932477117E-5614 1.234840492850987660094972466238558E-5614 + 9325 6.17420246425493830047486233119279E-5615 3.087101232127469150237431165596395E-5615 + 9326 1.543550616063734575118715582798198E-5615 7.717753080318672875593577913990988E-5616 + 9327 3.858876540159336437796788956995494E-5616 1.929438270079668218898394478497747E-5616 + 9328 9.647191350398341094491972392488735E-5617 4.823595675199170547245986196244368E-5617 + 9329 2.411797837599585273622993098122184E-5617 1.205898918799792636811496549061092E-5617 + 9330 6.02949459399896318405748274530546E-5618 3.01474729699948159202874137265273E-5618 + 9331 1.507373648499740796014370686326365E-5618 7.536868242498703980071853431631825E-5619 + 9332 3.768434121249351990035926715815913E-5619 1.884217060624675995017963357907956E-5619 + 9333 9.42108530312337997508981678953978E-5620 4.71054265156168998754490839476989E-5620 + 9334 2.355271325780844993772454197384945E-5620 1.177635662890422496886227098692473E-5620 + 9335 5.888178314452112484431135493462365E-5621 2.944089157226056242215567746731183E-5621 + 9336 1.472044578613028121107783873365592E-5621 7.360222893065140605538919366827958E-5622 + 9337 3.680111446532570302769459683413979E-5622 1.840055723266285151384729841706990E-5622 + 9338 9.20027861633142575692364920853495E-5623 4.600139308165712878461824604267475E-5623 + 9339 2.300069654082856439230912302133738E-5623 1.150034827041428219615456151066869E-5623 + 9340 5.750174135207141098077280755334345E-5624 2.875087067603570549038640377667173E-5624 + 9341 1.437543533801785274519320188833587E-5624 7.187717669008926372596600944167933E-5625 + 9342 3.593858834504463186298300472083967E-5625 1.796929417252231593149150236041983E-5625 + 9343 8.984647086261157965745751180209915E-5626 4.492323543130578982872875590104958E-5626 + 9344 2.246161771565289491436437795052479E-5626 1.123080885782644745718218897526240E-5626 + 9345 5.61540442891322372859109448763120E-5627 2.80770221445661186429554724381560E-5627 + 9346 1.40385110722830593214777362190780E-5627 7.0192555361415296607388681095390E-5628 + 9347 3.5096277680707648303694340547695E-5628 1.75481388403538241518471702738475E-5628 + 9348 8.77406942017691207592358513692375E-5629 4.387034710088456037961792568461875E-5629 + 9349 2.193517355044228018980896284230938E-5629 1.096758677522114009490448142115469E-5629 + 9350 5.483793387610570047452240710577345E-5630 2.741896693805285023726120355288673E-5630 + 9351 1.370948346902642511863060177644337E-5630 6.854741734513212559315300888221683E-5631 + 9352 3.427370867256606279657650444110842E-5631 1.713685433628303139828825222055421E-5631 + 9353 8.568427168141515699144126110277105E-5632 4.284213584070757849572063055138553E-5632 + 9354 2.142106792035378924786031527569277E-5632 1.071053396017689462393015763784638E-5632 + 9355 5.35526698008844731196507881892319E-5633 2.677633490044223655982539409461595E-5633 + 9356 1.338816745022111827991269704730798E-5633 6.694083725110559139956348523653988E-5634 + 9357 3.347041862555279569978174261826994E-5634 1.673520931277639784989087130913497E-5634 + 9358 8.367604656388198924945435654567485E-5635 4.183802328194099462472717827283743E-5635 + 9359 2.091901164097049731236358913641872E-5635 1.045950582048524865618179456820936E-5635 + 9360 5.22975291024262432809089728410468E-5636 2.61487645512131216404544864205234E-5636 + 9361 1.30743822756065608202272432102617E-5636 6.53719113780328041011362160513085E-5637 + 9362 3.268595568901640205056810802565425E-5637 1.634297784450820102528405401282713E-5637 + 9363 8.171488922254100512642027006413565E-5638 4.085744461127050256321013503206783E-5638 + 9364 2.042872230563525128160506751603392E-5638 1.021436115281762564080253375801696E-5638 + 9365 5.10718057640881282040126687900848E-5639 2.55359028820440641020063343950424E-5639 + 9366 1.27679514410220320510031671975212E-5639 6.3839757205110160255015835987606E-5640 + 9367 3.1919878602555080127507917993803E-5640 1.59599393012775400637539589969015E-5640 + 9368 7.97996965063877003187697949845075E-5641 3.989984825319385015938489749225375E-5641 + 9369 1.994992412659692507969244874612688E-5641 9.974962063298462539846224373063438E-5642 + 9370 4.987481031649231269923112186531719E-5642 2.493740515824615634961556093265860E-5642 + 9371 1.246870257912307817480778046632930E-5642 6.23435128956153908740389023316465E-5643 + 9372 3.117175644780769543701945116582325E-5643 1.558587822390384771850972558291163E-5643 + 9373 7.792939111951923859254862791455815E-5644 3.896469555975961929627431395727908E-5644 + 9374 1.948234777987980964813715697863954E-5644 9.74117388993990482406857848931977E-5645 + 9375 4.870586944969952412034289244659885E-5645 2.435293472484976206017144622329943E-5645 + 9376 1.217646736242488103008572311164972E-5645 6.088233681212440515042861555824858E-5646 + 9377 3.044116840606220257521430777912429E-5646 1.522058420303110128760715388956215E-5646 + 9378 7.610292101515550643803576944781075E-5647 3.805146050757775321901788472390538E-5647 + 9379 1.902573025378887660950894236195269E-5647 9.512865126894438304754471180976345E-5648 + 9380 4.756432563447219152377235590488173E-5648 2.378216281723609576188617795244086E-5648 + 9381 1.189108140861804788094308897622043E-5648 5.945540704309023940471544488110215E-5649 + 9382 2.972770352154511970235772244055108E-5649 1.486385176077255985117886122027554E-5649 + 9383 7.43192588038627992558943061013777E-5650 3.715962940193139962794715305068885E-5650 + 9384 1.857981470096569981397357652534443E-5650 9.289907350482849906986788262672213E-5651 + 9385 4.644953675241424953493394131336107E-5651 2.322476837620712476746697065668053E-5651 + 9386 1.161238418810356238373348532834027E-5651 5.806192094051781191866742664170133E-5652 + 9387 2.903096047025890595933371332085067E-5652 1.451548023512945297966685666042533E-5652 + 9388 7.257740117564726489833428330212665E-5653 3.628870058782363244916714165106333E-5653 + 9389 1.814435029391181622458357082553167E-5653 9.072175146955908112291785412765833E-5654 + 9390 4.536087573477954056145892706382917E-5654 2.268043786738977028072946353191458E-5654 + 9391 1.134021893369488514036473176595729E-5654 5.670109466847442570182365882978645E-5655 + 9392 2.835054733423721285091182941489323E-5655 1.417527366711860642545591470744661E-5655 + 9393 7.087636833559303212727957353723305E-5656 3.543818416779651606363978676861653E-5656 + 9394 1.771909208389825803181989338430827E-5656 8.859546041949129015909946692154133E-5657 + 9395 4.429773020974564507954973346077067E-5657 2.214886510487282253977486673038533E-5657 + 9396 1.107443255243641126988743336519267E-5657 5.537216276218205634943716682596333E-5658 + 9397 2.768608138109102817471858341298167E-5658 1.384304069054551408735929170649083E-5658 + 9398 6.921520345272757043679645853245415E-5659 3.460760172636378521839822926622708E-5659 + 9399 1.730380086318189260919911463311354E-5659 8.65190043159094630459955731655677E-5660 + 9400 4.325950215795473152299778658278385E-5660 2.162975107897736576149889329139193E-5660 + 9401 1.081487553948868288074944664569597E-5660 5.407437769744341440374723322847983E-5661 + 9402 2.703718884872170720187361661423992E-5661 1.351859442436085360093680830711996E-5661 + 9403 6.75929721218042680046840415355998E-5662 3.37964860609021340023420207677999E-5662 + 9404 1.689824303045106700117101038389995E-5662 8.449121515225533500585505191949975E-5663 + 9405 4.224560757612766750292752595974988E-5663 2.112280378806383375146376297987494E-5663 + 9406 1.056140189403191687573188148993747E-5663 5.280700947015958437865940744968735E-5664 + 9407 2.640350473507979218932970372484368E-5664 1.320175236753989609466485186242184E-5664 + 9408 6.60087618376994804733242593121092E-5665 3.30043809188497402366621296560546E-5665 + 9409 1.65021904594248701183310648280273E-5665 8.25109522971243505916553241401365E-5666 + 9410 4.125547614856217529582766207006825E-5666 2.062773807428108764791383103503413E-5666 + 9411 1.031386903714054382395691551751707E-5666 5.156934518570271911978457758758533E-5667 + 9412 2.578467259285135955989228879379267E-5667 1.289233629642567977994614439689633E-5667 + 9413 6.446168148212839889973072198448165E-5668 3.223084074106419944986536099224083E-5668 + 9414 1.611542037053209972493268049612042E-5668 8.057710185266049862466340248060208E-5669 + 9415 4.028855092633024931233170124030104E-5669 2.014427546316512465616585062015052E-5669 + 9416 1.007213773158256232808292531007526E-5669 5.03606886579128116404146265503763E-5670 + 9417 2.518034432895640582020731327518815E-5670 1.259017216447820291010365663759408E-5670 + 9418 6.29508608223910145505182831879704E-5671 3.14754304111955072752591415939852E-5671 + 9419 1.57377152055977536376295707969926E-5671 7.8688576027988768188147853984963E-5672 + 9420 3.93442880139943840940739269924815E-5672 1.967214400699719204703696349624075E-5672 + 9421 9.836072003498596023518481748120375E-5673 4.918036001749298011759240874060188E-5673 + 9422 2.459018000874649005879620437030094E-5673 1.229509000437324502939810218515047E-5673 + 9423 6.147545002186622514699051092575235E-5674 3.073772501093311257349525546287618E-5674 + 9424 1.536886250546655628674762773143809E-5674 7.684431252733278143373813865719045E-5675 + 9425 3.842215626366639071686906932859523E-5675 1.921107813183319535843453466429761E-5675 + 9426 9.605539065916597679217267332148805E-5676 4.802769532958298839608633666074403E-5676 + 9427 2.401384766479149419804316833037202E-5676 1.200692383239574709902158416518601E-5676 + 9428 6.003461916197873549510792082593005E-5677 3.001730958098936774755396041296503E-5677 + 9429 1.500865479049468387377698020648252E-5677 7.504327395247341936888490103241258E-5678 + 9430 3.752163697623670968444245051620629E-5678 1.876081848811835484222122525810315E-5678 + 9431 9.380409244059177421110612629051575E-5679 4.690204622029588710555306314525788E-5679 + 9432 2.345102311014794355277653157262894E-5679 1.172551155507397177638826578631447E-5679 + 9433 5.862755777536985888194132893157235E-5680 2.931377888768492944097066446578618E-5680 + 9434 1.465688944384246472048533223289309E-5680 7.328444721921232360242666116446545E-5681 + 9435 3.664222360960616180121333058223273E-5681 1.832111180480308090060666529111636E-5681 + 9436 9.16055590240154045030333264555818E-5682 4.58027795120077022515166632277909E-5682 + 9437 2.290138975600385112575833161389545E-5682 1.145069487800192556287916580694773E-5682 + 9438 5.725347439000962781439582903473865E-5683 2.862673719500481390719791451736933E-5683 + 9439 1.431336859750240695359895725868467E-5683 7.156684298751203476799478629342333E-5684 + 9440 3.578342149375601738399739314671167E-5684 1.789171074687800869199869657335583E-5684 + 9441 8.945855373439004345999348286677915E-5685 4.472927686719502172999674143338958E-5685 + 9442 2.236463843359751086499837071669479E-5685 1.118231921679875543249918535834740E-5685 + 9443 5.59115960839937771624959267917370E-5686 2.79557980419968885812479633958685E-5686 + 9444 1.397789902099844429062398169793425E-5686 6.988949510499222145311990848967125E-5687 + 9445 3.494474755249611072655995424483563E-5687 1.747237377624805536327997712241781E-5687 + 9446 8.736186888124027681639988561208905E-5688 4.368093444062013840819994280604453E-5688 + 9447 2.184046722031006920409997140302227E-5688 1.092023361015503460204998570151113E-5688 + 9448 5.460116805077517301024992850755565E-5689 2.730058402538758650512496425377783E-5689 + 9449 1.365029201269379325256248212688892E-5689 6.825146006346896626281241063444458E-5690 + 9450 3.412573003173448313140620531722229E-5690 1.706286501586724156570310265861115E-5690 + 9451 8.531432507933620782851551329305575E-5691 4.265716253966810391425775664652788E-5691 + 9452 2.132858126983405195712887832326394E-5691 1.066429063491702597856443916163197E-5691 + 9453 5.332145317458512989282219580815985E-5692 2.666072658729256494641109790407993E-5692 + 9454 1.333036329364628247320554895203997E-5692 6.665181646823141236602774476019983E-5693 + 9455 3.332590823411570618301387238009992E-5693 1.666295411705785309150693619004996E-5693 + 9456 8.33147705852892654575346809502498E-5694 4.16573852926446327287673404751249E-5694 + 9457 2.082869264632231636438367023756245E-5694 1.041434632316115818219183511878123E-5694 + 9458 5.207173161580579091095917559390615E-5695 2.603586580790289545547958779695308E-5695 + 9459 1.301793290395144772773979389847654E-5695 6.50896645197572386386989694923827E-5696 + 9460 3.254483225987861931934948474619135E-5696 1.627241612993930965967474237309568E-5696 + 9461 8.13620806496965482983737118654784E-5697 4.06810403248482741491868559327392E-5697 + 9462 2.03405201624241370745934279663696E-5697 1.01702600812120685372967139831848E-5697 + 9463 5.0851300406060342686483569915924E-5698 2.5425650203030171343241784957962E-5698 + 9464 1.2712825101515085671620892478981E-5698 6.3564125507575428358104462394905E-5699 + 9465 3.17820627537877141790522311974525E-5699 1.589103137689385708952611559872625E-5699 + 9466 7.945515688446928544763057799363125E-5700 3.972757844223464272381528899681563E-5700 + 9467 1.986378922111732136190764449840782E-5700 9.931894610558660680953822249203908E-5701 + 9468 4.965947305279330340476911124601954E-5701 2.482973652639665170238455562300977E-5701 + 9469 1.241486826319832585119227781150489E-5701 6.207434131599162925596138905752443E-5702 + 9470 3.103717065799581462798069452876222E-5702 1.551858532899790731399034726438111E-5702 + 9471 7.759292664498953656995173632190555E-5703 3.879646332249476828497586816095278E-5703 + 9472 1.939823166124738414248793408047639E-5703 9.699115830623692071243967040238195E-5704 + 9473 4.849557915311846035621983520119098E-5704 2.424778957655923017810991760059549E-5704 + 9474 1.212389478827961508905495880029775E-5704 6.061947394139807544527479400148873E-5705 + 9475 3.030973697069903772263739700074437E-5705 1.515486848534951886131869850037218E-5705 + 9476 7.57743424267475943065934925018609E-5706 3.788717121337379715329674625093045E-5706 + 9477 1.894358560668689857664837312546523E-5706 9.471792803343449288324186562732613E-5707 + 9478 4.735896401671724644162093281366307E-5707 2.367948200835862322081046640683153E-5707 + 9479 1.183974100417931161040523320341577E-5707 5.919870502089655805202616601707883E-5708 + 9480 2.959935251044827902601308300853942E-5708 1.479967625522413951300654150426971E-5708 + 9481 7.399838127612069756503270752134855E-5709 3.699919063806034878251635376067428E-5709 + 9482 1.849959531903017439125817688033714E-5709 9.24979765951508719562908844016857E-5710 + 9483 4.624898829757543597814544220084285E-5710 2.312449414878771798907272110042143E-5710 + 9484 1.156224707439385899453636055021072E-5710 5.781123537196929497268180275105358E-5711 + 9485 2.890561768598464748634090137552679E-5711 1.445280884299232374317045068776340E-5711 + 9486 7.22640442149616187158522534388170E-5712 3.61320221074808093579261267194085E-5712 + 9487 1.806601105374040467896306335970425E-5712 9.033005526870202339481531679852125E-5713 + 9488 4.516502763435101169740765839926063E-5713 2.258251381717550584870382919963031E-5713 + 9489 1.129125690858775292435191459981516E-5713 5.645628454293876462175957299907578E-5714 + 9490 2.822814227146938231087978649953789E-5714 1.411407113573469115543989324976895E-5714 + 9491 7.057035567867345577719946624884475E-5715 3.528517783933672788859973312442238E-5715 + 9492 1.764258891966836394429986656221119E-5715 8.821294459834181972149933281105595E-5716 + 9493 4.410647229917090986074966640552798E-5716 2.205323614958545493037483320276399E-5716 + 9494 1.102661807479272746518741660138200E-5716 5.513309037396363732593708300690998E-5717 + 9495 2.756654518698181866296854150345499E-5717 1.378327259349090933148427075172750E-5717 + 9496 6.89163629674545466574213537586375E-5718 3.445818148372727332871067687931875E-5718 + 9497 1.722909074186363666435533843965938E-5718 8.614545370931818332177669219829688E-5719 + 9498 4.307272685465909166088834609914844E-5719 2.153636342732954583044417304957422E-5719 + 9499 1.076818171366477291522208652478711E-5719 5.384090856832386457611043262393555E-5720 + 9500 2.692045428416193228805521631196778E-5720 1.346022714208096614402760815598389E-5720 + 9501 6.730113571040483072013804077991945E-5721 3.365056785520241536006902038995973E-5721 + 9502 1.682528392760120768003451019497987E-5721 8.412641963800603840017255097489933E-5722 + 9503 4.206320981900301920008627548744967E-5722 2.103160490950150960004313774372483E-5722 + 9504 1.051580245475075480002156887186242E-5722 5.257901227375377400010784435931208E-5723 + 9505 2.628950613687688700005392217965604E-5723 1.314475306843844350002696108982802E-5723 + 9506 6.57237653421922175001348054491401E-5724 3.286188267109610875006740272457005E-5724 + 9507 1.643094133554805437503370136228503E-5724 8.215470667774027187516850681142513E-5725 + 9508 4.107735333887013593758425340571257E-5725 2.053867666943506796879212670285628E-5725 + 9509 1.026933833471753398439606335142814E-5725 5.13466916735876699219803167571407E-5726 + 9510 2.567334583679383496099015837857035E-5726 1.283667291839691748049507918928518E-5726 + 9511 6.41833645919845874024753959464259E-5727 3.209168229599229370123769797321295E-5727 + 9512 1.604584114799614685061884898660648E-5727 8.022920573998073425309424493303238E-5728 + 9513 4.011460286999036712654712246651619E-5728 2.005730143499518356327356123325810E-5728 + 9514 1.002865071749759178163678061662905E-5728 5.014325358748795890818390308314525E-5729 + 9515 2.507162679374397945409195154157263E-5729 1.253581339687198972704597577078631E-5729 + 9516 6.267906698435994863522987885393155E-5730 3.133953349217997431761493942696578E-5730 + 9517 1.566976674608998715880746971348289E-5730 7.834883373044993579403734856741445E-5731 + 9518 3.917441686522496789701867428370723E-5731 1.958720843261248394850933714185361E-5731 + 9519 9.793604216306241974254668570926805E-5732 4.896802108153120987127334285463403E-5732 + 9520 2.448401054076560493563667142731702E-5732 1.224200527038280246781833571365851E-5732 + 9521 6.121002635191401233909167856829255E-5733 3.060501317595700616954583928414628E-5733 + 9522 1.530250658797850308477291964207314E-5733 7.65125329398925154238645982103657E-5734 + 9523 3.825626646994625771193229910518285E-5734 1.912813323497312885596614955259143E-5734 + 9524 9.564066617486564427983074776295715E-5735 4.782033308743282213991537388147858E-5735 + 9525 2.391016654371641106995768694073929E-5735 1.195508327185820553497884347036965E-5735 + 9526 5.977541635929102767489421735184825E-5736 2.988770817964551383744710867592413E-5736 + 9527 1.494385408982275691872355433796207E-5736 7.471927044911378459361777168981033E-5737 + 9528 3.735963522455689229680888584490517E-5737 1.867981761227844614840444292245258E-5737 + 9529 9.33990880613922307420222146122629E-5738 4.669954403069611537101110730613145E-5738 + 9530 2.334977201534805768550555365306573E-5738 1.167488600767402884275277682653286E-5738 + 9531 5.83744300383701442137638841326643E-5739 2.918721501918507210688194206633215E-5739 + 9532 1.459360750959253605344097103316608E-5739 7.296803754796268026720485516583038E-5740 + 9533 3.648401877398134013360242758291519E-5740 1.824200938699067006680121379145760E-5740 + 9534 9.12100469349533503340060689572880E-5741 4.56050234674766751670030344786440E-5741 + 9535 2.28025117337383375835015172393220E-5741 1.14012558668691687917507586196610E-5741 + 9536 5.7006279334345843958753793098305E-5742 2.85031396671729219793768965491525E-5742 + 9537 1.425156983358646098968844827457625E-5742 7.125784916793230494844224137288125E-5743 + 9538 3.562892458396615247422112068644063E-5743 1.781446229198307623711056034322031E-5743 + 9539 8.907231145991538118555280171610155E-5744 4.453615572995769059277640085805078E-5744 + 9540 2.226807786497884529638820042902539E-5744 1.113403893248942264819410021451270E-5744 + 9541 5.56701946624471132409705010725635E-5745 2.783509733122355662048525053628175E-5745 + 9542 1.391754866561177831024262526814088E-5745 6.958774332805889155121312634070438E-5746 + 9543 3.479387166402944577560656317035219E-5746 1.739693583201472288780328158517610E-5746 + 9544 8.69846791600736144390164079258805E-5747 4.349233958003680721950820396294025E-5747 + 9545 2.174616979001840360975410198147013E-5747 1.087308489500920180487705099073506E-5747 + 9546 5.43654244750460090243852549536753E-5748 2.718271223752300451219262747683765E-5748 + 9547 1.359135611876150225609631373841883E-5748 6.795678059380751128048156869209413E-5749 + 9548 3.397839029690375564024078434604707E-5749 1.698919514845187782012039217302353E-5749 + 9549 8.494597574225938910060196086511765E-5750 4.247298787112969455030098043255883E-5750 + 9550 2.123649393556484727515049021627942E-5750 1.061824696778242363757524510813971E-5750 + 9551 5.309123483891211818787622554069855E-5751 2.654561741945605909393811277034928E-5751 + 9552 1.327280870972802954696905638517464E-5751 6.63640435486401477348452819258732E-5752 + 9553 3.31820217743200738674226409629366E-5752 1.65910108871600369337113204814683E-5752 + 9554 8.29550544358001846685566024073415E-5753 4.147752721790009233427830120367075E-5753 + 9555 2.073876360895004616713915060183538E-5753 1.036938180447502308356957530091769E-5753 + 9556 5.184690902237511541784787650458845E-5754 2.592345451118755770892393825229423E-5754 + 9557 1.296172725559377885446196912614712E-5754 6.480863627796889427230984563073558E-5755 + 9558 3.240431813898444713615492281536779E-5755 1.620215906949222356807746140768390E-5755 + 9559 8.10107953474611178403873070384195E-5756 4.050539767373055892019365351920975E-5756 + 9560 2.025269883686527946009682675960488E-5756 1.012634941843263973004841337980244E-5756 + 9561 5.06317470921631986502420668990122E-5757 2.53158735460815993251210334495061E-5757 + 9562 1.265793677304079966256051672475305E-5757 6.328968386520399831280258362376525E-5758 + 9563 3.164484193260199915640129181188263E-5758 1.582242096630099957820064590594131E-5758 + 9564 7.911210483150499789100322952970655E-5759 3.955605241575249894550161476485328E-5759 + 9565 1.977802620787624947275080738242664E-5759 9.88901310393812473637540369121332E-5760 + 9566 4.94450655196906236818770184560666E-5760 2.47225327598453118409385092280333E-5760 + 9567 1.236126637992265592046925461401665E-5760 6.180633189961327960234627307008325E-5761 + 9568 3.090316594980663980117313653504163E-5761 1.545158297490331990058656826752081E-5761 + 9569 7.725791487451659950293284133760405E-5762 3.862895743725829975146642066880203E-5762 + 9570 1.931447871862914987573321033440102E-5762 9.657239359314574937866605167200508E-5763 + 9571 4.828619679657287468933302583600254E-5763 2.414309839828643734466651291800127E-5763 + 9572 1.207154919914321867233325645900064E-5763 6.035774599571609336166628229500318E-5764 + 9573 3.017887299785804668083314114750159E-5764 1.508943649892902334041657057375080E-5764 + 9574 7.54471824946451167020828528687540E-5765 3.77235912473225583510414264343770E-5765 + 9575 1.88617956236612791755207132171885E-5765 9.43089781183063958776035660859425E-5766 + 9576 4.715448905915319793880178304297125E-5766 2.357724452957659896940089152148563E-5766 + 9577 1.178862226478829948470044576074282E-5766 5.894311132394149742350222880371408E-5767 + 9578 2.947155566197074871175111440185704E-5767 1.473577783098537435587555720092852E-5767 + 9579 7.36788891549268717793777860046426E-5768 3.68394445774634358896888930023213E-5768 + 9580 1.841972228873171794484444650116065E-5768 9.209861144365858972422223250580325E-5769 + 9581 4.604930572182929486211111625290163E-5769 2.302465286091464743105555812645081E-5769 + 9582 1.151232643045732371552777906322541E-5769 5.756163215228661857763889531612703E-5770 + 9583 2.878081607614330928881944765806352E-5770 1.439040803807165464440972382903176E-5770 + 9584 7.19520401903582732220486191451588E-5771 3.59760200951791366110243095725794E-5771 + 9585 1.79880100475895683055121547862897E-5771 8.99400502379478415275607739314485E-5772 + 9586 4.497002511897392076378038696572425E-5772 2.248501255948696038189019348286213E-5772 + 9587 1.124250627974348019094509674143107E-5772 5.621253139871740095472548370715533E-5773 + 9588 2.810626569935870047736274185357767E-5773 1.405313284967935023868137092678883E-5773 + 9589 7.026566424839675119340685463394415E-5774 3.513283212419837559670342731697208E-5774 + 9590 1.756641606209918779835171365848604E-5774 8.78320803104959389917585682924302E-5775 + 9591 4.39160401552479694958792841462151E-5775 2.195802007762398474793964207310755E-5775 + 9592 1.097901003881199237396982103655378E-5775 5.489505019405996186984910518276888E-5776 + 9593 2.744752509702998093492455259138444E-5776 1.372376254851499046746227629569222E-5776 + 9594 6.86188127425749523373113814784611E-5777 3.430940637128747616865569073923055E-5777 + 9595 1.715470318564373808432784536961528E-5777 8.577351592821869042163922684807638E-5778 + 9596 4.288675796410934521081961342403819E-5778 2.144337898205467260540980671201910E-5778 + 9597 1.072168949102733630270490335600955E-5778 5.360844745513668151352451678004775E-5779 + 9598 2.680422372756834075676225839002388E-5779 1.340211186378417037838112919501194E-5779 + 9599 6.70105593189208518919056459750597E-5780 3.350527965946042594595282298752985E-5780 + 9600 1.675263982973021297297641149376493E-5780 8.376319914865106486488205746882463E-5781 + 9601 4.188159957432553243244102873441232E-5781 2.094079978716276621622051436720616E-5781 + 9602 1.047039989358138310811025718360308E-5781 5.23519994679069155405512859180154E-5782 + 9603 2.61759997339534577702756429590077E-5782 1.308799986697672888513782147950385E-5782 + 9604 6.543999933488364442568910739751925E-5783 3.271999966744182221284455369875963E-5783 + 9605 1.635999983372091110642227684937982E-5783 8.179999916860455553211138424689908E-5784 + 9606 4.089999958430227776605569212344954E-5784 2.044999979215113888302784606172477E-5784 + 9607 1.022499989607556944151392303086239E-5784 5.112499948037784720756961515431193E-5785 + 9608 2.556249974018892360378480757715597E-5785 1.278124987009446180189240378857798E-5785 + 9609 6.39062493504723090094620189428899E-5786 3.195312467523615450473100947144495E-5786 + 9610 1.597656233761807725236550473572248E-5786 7.988281168809038626182752367861238E-5787 + 9611 3.994140584404519313091376183930619E-5787 1.997070292202259656545688091965310E-5787 + 9612 9.98535146101129828272844045982655E-5788 4.992675730505649141364220229913275E-5788 + 9613 2.496337865252824570682110114956638E-5788 1.248168932626412285341055057478319E-5788 + 9614 6.240844663132061426705275287391595E-5789 3.120422331566030713352637643695798E-5789 + 9615 1.560211165783015356676318821847899E-5789 7.801055828915076783381594109239495E-5790 + 9616 3.900527914457538391690797054619748E-5790 1.950263957228769195845398527309874E-5790 + 9617 9.75131978614384597922699263654937E-5791 4.875659893071922989613496318274685E-5791 + 9618 2.437829946535961494806748159137343E-5791 1.218914973267980747403374079568671E-5791 + 9619 6.094574866339903737016870397843355E-5792 3.047287433169951868508435198921678E-5792 + 9620 1.523643716584975934254217599460839E-5792 7.618218582924879671271087997304195E-5793 + 9621 3.809109291462439835635543998652098E-5793 1.904554645731219917817771999326049E-5793 + 9622 9.522773228656099589088859996630245E-5794 4.761386614328049794544429998315123E-5794 + 9623 2.380693307164024897272214999157562E-5794 1.190346653582012448636107499578781E-5794 + 9624 5.951733267910062243180537497893905E-5795 2.975866633955031121590268748946953E-5795 + 9625 1.487933316977515560795134374473477E-5795 7.439666584887577803975671872367383E-5796 + 9626 3.719833292443788901987835936183692E-5796 1.859916646221894450993917968091846E-5796 + 9627 9.29958323110947225496958984045923E-5797 4.649791615554736127484794920229615E-5797 + 9628 2.324895807777368063742397460114808E-5797 1.162447903888684031871198730057404E-5797 + 9629 5.81223951944342015935599365028702E-5798 2.90611975972171007967799682514351E-5798 + 9630 1.453059879860855039838998412571755E-5798 7.265299399304275199194992062858775E-5799 + 9631 3.632649699652137599597496031429388E-5799 1.816324849826068799798748015714694E-5799 + 9632 9.08162424913034399899374007857347E-5800 4.540812124565171999496870039286735E-5800 + 9633 2.270406062282585999748435019643368E-5800 1.135203031141292999874217509821684E-5800 + 9634 5.67601515570646499937108754910842E-5801 2.83800757785323249968554377455421E-5801 + 9635 1.419003788926616249842771887277105E-5801 7.095018944633081249213859436385525E-5802 + 9636 3.547509472316540624606929718192763E-5802 1.773754736158270312303464859096381E-5802 + 9637 8.868773680791351561517324295481905E-5803 4.434386840395675780758662147740953E-5803 + 9638 2.217193420197837890379331073870477E-5803 1.108596710098918945189665536935238E-5803 + 9639 5.54298355049459472594832768467619E-5804 2.771491775247297362974163842338095E-5804 + 9640 1.385745887623648681487081921169048E-5804 6.928729438118243407435409605845238E-5805 + 9641 3.464364719059121703717704802922619E-5805 1.732182359529560851858852401461310E-5805 + 9642 8.66091179764780425929426200730655E-5806 4.330455898823902129647131003653275E-5806 + 9643 2.165227949411951064823565501826638E-5806 1.082613974705975532411782750913319E-5806 + 9644 5.413069873529877662058913754566595E-5807 2.706534936764938831029456877283298E-5807 + 9645 1.353267468382469415514728438641649E-5807 6.766337341912347077573642193208245E-5808 + 9646 3.383168670956173538786821096604123E-5808 1.691584335478086769393410548302061E-5808 + 9647 8.457921677390433846967052741510305E-5809 4.228960838695216923483526370755153E-5809 + 9648 2.114480419347608461741763185377577E-5809 1.057240209673804230870881592688788E-5809 + 9649 5.28620104836902115435440796344394E-5810 2.64310052418451057717720398172197E-5810 + 9650 1.321550262092255288588601990860985E-5810 6.607751310461276442943009954304925E-5811 + 9651 3.303875655230638221471504977152463E-5811 1.651937827615319110735752488576231E-5811 + 9652 8.259689138076595553678762442881155E-5812 4.129844569038297776839381221440578E-5812 + 9653 2.064922284519148888419690610720289E-5812 1.032461142259574444209845305360145E-5812 + 9654 5.162305711297872221049226526800725E-5813 2.581152855648936110524613263400363E-5813 + 9655 1.290576427824468055262306631700182E-5813 6.452882139122340276311533158500908E-5814 + 9656 3.226441069561170138155766579250454E-5814 1.613220534780585069077883289625227E-5814 + 9657 8.066102673902925345389416448126135E-5815 4.033051336951462672694708224063068E-5815 + 9658 2.016525668475731336347354112031534E-5815 1.008262834237865668173677056015767E-5815 + 9659 5.041314171189328340868385280078835E-5816 2.520657085594664170434192640039418E-5816 + 9660 1.260328542797332085217096320019709E-5816 6.301642713986660426085481600098545E-5817 + 9661 3.150821356993330213042740800049273E-5817 1.575410678496665106521370400024636E-5817 + 9662 7.87705339248332553260685200012318E-5818 3.93852669624166276630342600006159E-5818 + 9663 1.969263348120831383151713000030795E-5818 9.846316740604156915758565000153975E-5819 + 9664 4.923158370302078457879282500076988E-5819 2.461579185151039228939641250038494E-5819 + 9665 1.230789592575519614469820625019247E-5819 6.153947962877598072349103125096235E-5820 + 9666 3.076973981438799036174551562548118E-5820 1.538486990719399518087275781274059E-5820 + 9667 7.692434953596997590436378906370295E-5821 3.846217476798498795218189453185148E-5821 + 9668 1.923108738399249397609094726592574E-5821 9.61554369199624698804547363296287E-5822 + 9669 4.807771845998123494022736816481435E-5822 2.403885922999061747011368408240718E-5822 + 9670 1.201942961499530873505684204120359E-5822 6.009714807497654367528421020601795E-5823 + 9671 3.004857403748827183764210510300898E-5823 1.502428701874413591882105255150449E-5823 + 9672 7.512143509372067959410526275752245E-5824 3.756071754686033979705263137876123E-5824 + 9673 1.878035877343016989852631568938062E-5824 9.390179386715084949263157844690308E-5825 + 9674 4.695089693357542474631578922345154E-5825 2.347544846678771237315789461172577E-5825 + 9675 1.173772423339385618657894730586289E-5825 5.868862116696928093289473652931443E-5826 + 9676 2.934431058348464046644736826465722E-5826 1.467215529174232023322368413232861E-5826 + 9677 7.336077645871160116611842066164305E-5827 3.668038822935580058305921033082153E-5827 + 9678 1.834019411467790029152960516541077E-5827 9.170097057338950145764802582705383E-5828 + 9679 4.585048528669475072882401291352692E-5828 2.292524264334737536441200645676346E-5828 + 9680 1.146262132167368768220600322838173E-5828 5.731310660836843841103001614190865E-5829 + 9681 2.865655330418421920551500807095433E-5829 1.432827665209210960275750403547716E-5829 + 9682 7.16413832604605480137875201773858E-5830 3.58206916302302740068937600886929E-5830 + 9683 1.791034581511513700344688004434645E-5830 8.955172907557568501723440022173225E-5831 + 9684 4.477586453778784250861720011086613E-5831 2.238793226889392125430860005543306E-5831 + 9685 1.119396613444696062715430002771653E-5831 5.596983067223480313577150013858265E-5832 + 9686 2.798491533611740156788575006929133E-5832 1.399245766805870078394287503464566E-5832 + 9687 6.99622883402935039197143751732283E-5833 3.498114417014675195985718758661415E-5833 + 9688 1.749057208507337597992859379330708E-5833 8.745286042536687989964296896653538E-5834 + 9689 4.372643021268343994982148448326769E-5834 2.186321510634171997491074224163385E-5834 + 9690 1.093160755317085998745537112081693E-5834 5.465803776585429993727685560408463E-5835 + 9691 2.732901888292714996863842780204232E-5835 1.366450944146357498431921390102116E-5835 + 9692 6.83225472073178749215960695051058E-5836 3.41612736036589374607980347525529E-5836 + 9693 1.708063680182946873039901737627645E-5836 8.540318400914734365199508688138225E-5837 + 9694 4.270159200457367182599754344069113E-5837 2.135079600228683591299877172034556E-5837 + 9695 1.067539800114341795649938586017278E-5837 5.33769900057170897824969293008639E-5838 + 9696 2.668849500285854489124846465043195E-5838 1.334424750142927244562423232521598E-5838 + 9697 6.67212375071463622281211616260799E-5839 3.336061875357318111406058081303995E-5839 + 9698 1.668030937678659055703029040651998E-5839 8.340154688393295278515145203259988E-5840 + 9699 4.170077344196647639257572601629994E-5840 2.085038672098323819628786300814997E-5840 + 9700 1.042519336049161909814393150407499E-5840 5.212596680245809549071965752037493E-5841 + 9701 2.606298340122904774535982876018747E-5841 1.303149170061452387267991438009373E-5841 + 9702 6.515745850307261936339957190046865E-5842 3.257872925153630968169978595023433E-5842 + 9703 1.628936462576815484084989297511717E-5842 8.144682312884077420424946487558583E-5843 + 9704 4.072341156442038710212473243779292E-5843 2.036170578221019355106236621889646E-5843 + 9705 1.018085289110509677553118310944823E-5843 5.090426445552548387765591554724115E-5844 + 9706 2.545213222776274193882795777362058E-5844 1.272606611388137096941397888681029E-5844 + 9707 6.363033056940685484706989443405145E-5845 3.181516528470342742353494721702573E-5845 + 9708 1.590758264235171371176747360851287E-5845 7.953791321175856855883736804256433E-5846 + 9709 3.976895660587928427941868402128217E-5846 1.988447830293964213970934201064108E-5846 + 9710 9.94223915146982106985467100532054E-5847 4.97111957573491053492733550266027E-5847 + 9711 2.485559787867455267463667751330135E-5847 1.242779893933727633731833875665068E-5847 + 9712 6.21389946966863816865916937832534E-5848 3.10694973483431908432958468916267E-5848 + 9713 1.553474867417159542164792344581335E-5848 7.767374337085797710823961722906675E-5849 + 9714 3.883687168542898855411980861453338E-5849 1.941843584271449427705990430726669E-5849 + 9715 9.709217921357247138529952153633345E-5850 4.854608960678623569264976076816673E-5850 + 9716 2.427304480339311784632488038408337E-5850 1.213652240169655892316244019204168E-5850 + 9717 6.06826120084827946158122009602084E-5851 3.03413060042413973079061004801042E-5851 + 9718 1.51706530021206986539530502400521E-5851 7.58532650106034932697652512002605E-5852 + 9719 3.792663250530174663488262560013025E-5852 1.896331625265087331744131280006513E-5852 + 9720 9.481658126325436658720656400032565E-5853 4.740829063162718329360328200016283E-5853 + 9721 2.370414531581359164680164100008142E-5853 1.185207265790679582340082050004071E-5853 + 9722 5.926036328953397911700410250020355E-5854 2.963018164476698955850205125010178E-5854 + 9723 1.481509082238349477925102562505089E-5854 7.407545411191747389625512812525445E-5855 + 9724 3.703772705595873694812756406262723E-5855 1.851886352797936847406378203131361E-5855 + 9725 9.259431763989684237031891015656805E-5856 4.629715881994842118515945507828403E-5856 + 9726 2.314857940997421059257972753914202E-5856 1.157428970498710529628986376957101E-5856 + 9727 5.787144852493552648144931884785505E-5857 2.893572426246776324072465942392753E-5857 + 9728 1.446786213123388162036232971196377E-5857 7.233931065616940810181164855981883E-5858 + 9729 3.616965532808470405090582427990942E-5858 1.808482766404235202545291213995471E-5858 + 9730 9.042413832021176012726456069977355E-5859 4.521206916010588006363228034988678E-5859 + 9731 2.260603458005294003181614017494339E-5859 1.130301729002647001590807008747170E-5859 + 9732 5.65150864501323500795403504373585E-5860 2.825754322506617503977017521867925E-5860 + 9733 1.412877161253308751988508760933963E-5860 7.064385806266543759942543804669813E-5861 + 9734 3.532192903133271879971271902334907E-5861 1.766096451566635939985635951167453E-5861 + 9735 8.830482257833179699928179755837265E-5862 4.415241128916589849964089877918633E-5862 + 9736 2.207620564458294924982044938959317E-5862 1.103810282229147462491022469479658E-5862 + 9737 5.51905141114573731245511234739829E-5863 2.759525705572868656227556173699145E-5863 + 9738 1.379762852786434328113778086849573E-5863 6.898814263932171640568890434247863E-5864 + 9739 3.449407131966085820284445217123932E-5864 1.724703565983042910142222608561966E-5864 + 9740 8.62351782991521455071111304280983E-5865 4.311758914957607275355556521404915E-5865 + 9741 2.155879457478803637677778260702458E-5865 1.077939728739401818838889130351229E-5865 + 9742 5.389698643697009094194445651756145E-5866 2.694849321848504547097222825878073E-5866 + 9743 1.347424660924252273548611412939037E-5866 6.737123304621261367743057064695183E-5867 + 9744 3.368561652310630683871528532347592E-5867 1.684280826155315341935764266173796E-5867 + 9745 8.42140413077657670967882133086898E-5868 4.21070206538828835483941066543449E-5868 + 9746 2.105351032694144177419705332717245E-5868 1.052675516347072088709852666358623E-5868 + 9747 5.263377581735360443549263331793115E-5869 2.631688790867680221774631665896558E-5869 + 9748 1.315844395433840110887315832948279E-5869 6.579221977169200554436579164741395E-5870 + 9749 3.289610988584600277218289582370698E-5870 1.644805494292300138609144791185349E-5870 + 9750 8.224027471461500693045723955926745E-5871 4.112013735730750346522861977963373E-5871 + 9751 2.056006867865375173261430988981687E-5871 1.028003433932687586630715494490843E-5871 + 9752 5.140017169663437933153577472454215E-5872 2.570008584831718966576788736227108E-5872 + 9753 1.285004292415859483288394368113554E-5872 6.42502146207929741644197184056777E-5873 + 9754 3.212510731039648708220985920283885E-5873 1.606255365519824354110492960141943E-5873 + 9755 8.031276827599121770552464800709715E-5874 4.015638413799560885276232400354858E-5874 + 9756 2.007819206899780442638116200177429E-5874 1.003909603449890221319058100088715E-5874 + 9757 5.019548017249451106595290500443575E-5875 2.509774008624725553297645250221788E-5875 + 9758 1.254887004312362776648822625110894E-5875 6.27443502156181388324411312555447E-5876 + 9759 3.137217510780906941622056562777235E-5876 1.568608755390453470811028281388618E-5876 + 9760 7.84304377695226735405514140694309E-5877 3.921521888476133677027570703471545E-5877 + 9761 1.960760944238066838513785351735773E-5877 9.803804721190334192568926758678863E-5878 + 9762 4.901902360595167096284463379339432E-5878 2.450951180297583548142231689669716E-5878 + 9763 1.225475590148791774071115844834858E-5878 6.12737795074395887035557922417429E-5879 + 9764 3.063688975371979435177789612087145E-5879 1.531844487685989717588894806043573E-5879 + 9765 7.659222438429948587944474030217865E-5880 3.829611219214974293972237015108933E-5880 + 9766 1.914805609607487146986118507554467E-5880 9.574028048037435734930592537772333E-5881 + 9767 4.787014024018717867465296268886167E-5881 2.393507012009358933732648134443083E-5881 + 9768 1.196753506004679466866324067221542E-5881 5.983767530023397334331620336107708E-5882 + 9769 2.991883765011698667165810168053854E-5882 1.495941882505849333582905084026927E-5882 + 9770 7.479709412529246667914525420134635E-5883 3.739854706264623333957262710067318E-5883 + 9771 1.869927353132311666978631355033659E-5883 9.349636765661558334893156775168295E-5884 + 9772 4.674818382830779167446578387584148E-5884 2.337409191415389583723289193792074E-5884 + 9773 1.168704595707694791861644596896037E-5884 5.843522978538473959308222984480185E-5885 + 9774 2.921761489269236979654111492240093E-5885 1.460880744634618489827055746120046E-5885 + 9775 7.30440372317309244913527873060023E-5886 3.652201861586546224567639365300115E-5886 + 9776 1.826100930793273112283819682650058E-5886 9.130504653966365561419098413250288E-5887 + 9777 4.565252326983182780709549206625144E-5887 2.282626163491591390354774603312572E-5887 + 9778 1.141313081745795695177387301656286E-5887 5.70656540872897847588693650828143E-5888 + 9779 2.853282704364489237943468254140715E-5888 1.426641352182244618971734127070358E-5888 + 9780 7.13320676091122309485867063535179E-5889 3.566603380455611547429335317675895E-5889 + 9781 1.783301690227805773714667658837948E-5889 8.916508451139028868573338294189738E-5890 + 9782 4.458254225569514434286669147094869E-5890 2.229127112784757217143334573547435E-5890 + 9783 1.114563556392378608571667286773718E-5890 5.572817781961893042858336433868588E-5891 + 9784 2.786408890980946521429168216934294E-5891 1.393204445490473260714584108467147E-5891 + 9785 6.966022227452366303572920542335735E-5892 3.483011113726183151786460271167868E-5892 + 9786 1.741505556863091575893230135583934E-5892 8.70752778431545787946615067791967E-5893 + 9787 4.353763892157728939733075338959835E-5893 2.176881946078864469866537669479918E-5893 + 9788 1.088440973039432234933268834739959E-5893 5.442204865197161174666344173699795E-5894 + 9789 2.721102432598580587333172086849898E-5894 1.360551216299290293666586043424949E-5894 + 9790 6.802756081496451468332930217124745E-5895 3.401378040748225734166465108562373E-5895 + 9791 1.700689020374112867083232554281187E-5895 8.503445101870564335416162771405933E-5896 + 9792 4.251722550935282167708081385702967E-5896 2.125861275467641083854040692851483E-5896 + 9793 1.062930637733820541927020346425742E-5896 5.314653188669102709635101732128708E-5897 + 9794 2.657326594334551354817550866064354E-5897 1.328663297167275677408775433032177E-5897 + 9795 6.643316485836378387043877165160885E-5898 3.321658242918189193521938582580443E-5898 + 9796 1.660829121459094596760969291290222E-5898 8.304145607295472983804846456451108E-5899 + 9797 4.152072803647736491902423228225554E-5899 2.076036401823868245951211614112777E-5899 + 9798 1.038018200911934122975605807056389E-5899 5.190091004559670614878029035281943E-5900 + 9799 2.595045502279835307439014517640972E-5900 1.297522751139917653719507258820486E-5900 + 9800 6.48761375569958826859753629410243E-5901 3.243806877849794134298768147051215E-5901 + 9801 1.621903438924897067149384073525608E-5901 8.109517194624485335746920367628038E-5902 + 9802 4.054758597312242667873460183814019E-5902 2.027379298656121333936730091907010E-5902 + 9803 1.013689649328060666968365045953505E-5902 5.068448246640303334841825229767525E-5903 + 9804 2.534224123320151667420912614883763E-5903 1.267112061660075833710456307441881E-5903 + 9805 6.335560308300379168552281537209405E-5904 3.167780154150189584276140768604703E-5904 + 9806 1.583890077075094792138070384302352E-5904 7.919450385375473960690351921511758E-5905 + 9807 3.959725192687736980345175960755879E-5905 1.979862596343868490172587980377940E-5905 + 9808 9.89931298171934245086293990188970E-5906 4.94965649085967122543146995094485E-5906 + 9809 2.474828245429835612715734975472425E-5906 1.237414122714917806357867487736213E-5906 + 9810 6.187070613574589031789337438681065E-5907 3.093535306787294515894668719340533E-5907 + 9811 1.546767653393647257947334359670267E-5907 7.733838266968236289736671798351333E-5908 + 9812 3.866919133484118144868335899175667E-5908 1.933459566742059072434167949587833E-5908 + 9813 9.667297833710295362170839747939165E-5909 4.833648916855147681085419873969583E-5909 + 9814 2.416824458427573840542709936984792E-5909 1.208412229213786920271354968492396E-5909 + 9815 6.04206114606893460135677484246198E-5910 3.02103057303446730067838742123099E-5910 + 9816 1.510515286517233650339193710615495E-5910 7.552576432586168251695968553077475E-5911 + 9817 3.776288216293084125847984276538738E-5911 1.888144108146542062923992138269369E-5911 + 9818 9.440720540732710314619960691346845E-5912 4.720360270366355157309980345673423E-5912 + 9819 2.360180135183177578654990172836712E-5912 1.180090067591588789327495086418356E-5912 + 9820 5.90045033795794394663747543209178E-5913 2.95022516897897197331873771604589E-5913 + 9821 1.475112584489485986659368858022945E-5913 7.375562922447429933296844290114725E-5914 + 9822 3.687781461223714966648422145057363E-5914 1.843890730611857483324211072528681E-5914 + 9823 9.219453653059287416621055362643405E-5915 4.609726826529643708310527681321703E-5915 + 9824 2.304863413264821854155263840660852E-5915 1.152431706632410927077631920330426E-5915 + 9825 5.76215853316205463538815960165213E-5916 2.881079266581027317694079800826065E-5916 + 9826 1.440539633290513658847039900413033E-5916 7.202698166452568294235199502065163E-5917 + 9827 3.601349083226284147117599751032582E-5917 1.800674541613142073558799875516291E-5917 + 9828 9.003372708065710367793999377581455E-5918 4.501686354032855183896999688790728E-5918 + 9829 2.250843177016427591948499844395364E-5918 1.125421588508213795974249922197682E-5918 + 9830 5.62710794254106897987124961098841E-5919 2.813553971270534489935624805494205E-5919 + 9831 1.406776985635267244967812402747103E-5919 7.033884928176336224839062013735513E-5920 + 9832 3.516942464088168112419531006867757E-5920 1.758471232044084056209765503433878E-5920 + 9833 8.79235616022042028104882751716939E-5921 4.396178080110210140524413758584695E-5921 + 9834 2.198089040055105070262206879292348E-5921 1.099044520027552535131103439646174E-5921 + 9835 5.49522260013776267565551719823087E-5922 2.747611300068881337827758599115435E-5922 + 9836 1.373805650034440668913879299557718E-5922 6.869028250172203344569396497788588E-5923 + 9837 3.434514125086101672284698248894294E-5923 1.717257062543050836142349124447147E-5923 + 9838 8.586285312715254180711745622235735E-5924 4.293142656357627090355872811117868E-5924 + 9839 2.146571328178813545177936405558934E-5924 1.073285664089406772588968202779467E-5924 + 9840 5.366428320447033862944841013897335E-5925 2.683214160223516931472420506948668E-5925 + 9841 1.341607080111758465736210253474334E-5925 6.70803540055879232868105126737167E-5926 + 9842 3.354017700279396164340525633685835E-5926 1.677008850139698082170262816842918E-5926 + 9843 8.38504425069849041085131408421459E-5927 4.192522125349245205425657042107295E-5927 + 9844 2.096261062674622602712828521053648E-5927 1.048130531337311301356414260526824E-5927 + 9845 5.24065265668655650678207130263412E-5928 2.62032632834327825339103565131706E-5928 + 9846 1.31016316417163912669551782565853E-5928 6.55081582085819563347758912829265E-5929 + 9847 3.275407910429097816738794564146325E-5929 1.637703955214548908369397282073163E-5929 + 9848 8.188519776072744541846986410365815E-5930 4.094259888036372270923493205182908E-5930 + 9849 2.047129944018186135461746602591454E-5930 1.023564972009093067730873301295727E-5930 + 9850 5.117824860045465338654366506478635E-5931 2.558912430022732669327183253239318E-5931 + 9851 1.279456215011366334663591626619659E-5931 6.397281075056831673317958133098295E-5932 + 9852 3.198640537528415836658979066549148E-5932 1.599320268764207918329489533274574E-5932 + 9853 7.99660134382103959164744766637287E-5933 3.998300671910519795823723833186435E-5933 + 9854 1.999150335955259897911861916593218E-5933 9.995751679776299489559309582966088E-5934 + 9855 4.997875839888149744779654791483044E-5934 2.498937919944074872389827395741522E-5934 + 9856 1.249468959972037436194913697870761E-5934 6.247344799860187180974568489353805E-5935 + 9857 3.123672399930093590487284244676903E-5935 1.561836199965046795243642122338451E-5935 + 9858 7.809180999825233976218210611692255E-5936 3.904590499912616988109105305846128E-5936 + 9859 1.952295249956308494054552652923064E-5936 9.76147624978154247027276326461532E-5937 + 9860 4.88073812489077123513638163230766E-5937 2.44036906244538561756819081615383E-5937 + 9861 1.220184531222692808784095408076915E-5937 6.100922656113464043920477040384575E-5938 + 9862 3.050461328056732021960238520192288E-5938 1.525230664028366010980119260096144E-5938 + 9863 7.62615332014183005490059630048072E-5939 3.81307666007091502745029815024036E-5939 + 9864 1.90653833003545751372514907512018E-5939 9.5326916501772875686257453756009E-5940 + 9865 4.76634582508864378431287268780045E-5940 2.383172912544321892156436343900225E-5940 + 9866 1.191586456272160946078218171950113E-5940 5.957932281360804730391090859750563E-5941 + 9867 2.978966140680402365195545429875282E-5941 1.489483070340201182597772714937641E-5941 + 9868 7.447415351701005912988863574688205E-5942 3.723707675850502956494431787344103E-5942 + 9869 1.861853837925251478247215893672052E-5942 9.309269189626257391236079468360258E-5943 + 9870 4.654634594813128695618039734180129E-5943 2.327317297406564347809019867090065E-5943 + 9871 1.163658648703282173904509933545033E-5943 5.818293243516410869522549667725163E-5944 + 9872 2.909146621758205434761274833862582E-5944 1.454573310879102717380637416931291E-5944 + 9873 7.272866554395513586903187084656455E-5945 3.636433277197756793451593542328228E-5945 + 9874 1.818216638598878396725796771164114E-5945 9.09108319299439198362898385582057E-5946 + 9875 4.545541596497195991814491927910285E-5946 2.272770798248597995907245963955143E-5946 + 9876 1.136385399124298997953622981977572E-5946 5.681926995621494989768114909887858E-5947 + 9877 2.840963497810747494884057454943929E-5947 1.420481748905373747442028727471965E-5947 + 9878 7.102408744526868737210143637359825E-5948 3.551204372263434368605071818679913E-5948 + 9879 1.775602186131717184302535909339957E-5948 8.878010930658585921512679546699783E-5949 + 9880 4.439005465329292960756339773349892E-5949 2.219502732664646480378169886674946E-5949 + 9881 1.109751366332323240189084943337473E-5949 5.548756831661616200945424716687365E-5950 + 9882 2.774378415830808100472712358343683E-5950 1.387189207915404050236356179171841E-5950 + 9883 6.935946039577020251181780895859205E-5951 3.467973019788510125590890447929603E-5951 + 9884 1.733986509894255062795445223964802E-5951 8.669932549471275313977226119824008E-5952 + 9885 4.334966274735637656988613059912004E-5952 2.167483137367818828494306529956002E-5952 + 9886 1.083741568683909414247153264978001E-5952 5.418707843419547071235766324890005E-5953 + 9887 2.709353921709773535617883162445003E-5953 1.354676960854886767808941581222501E-5953 + 9888 6.773384804274433839044707906112505E-5954 3.386692402137216919522353953056253E-5954 + 9889 1.693346201068608459761176976528127E-5954 8.466731005343042298805884882640633E-5955 + 9890 4.233365502671521149402942441320317E-5955 2.116682751335760574701471220660158E-5955 + 9891 1.058341375667880287350735610330079E-5955 5.291706878339401436753678051650395E-5956 + 9892 2.645853439169700718376839025825198E-5956 1.322926719584850359188419512912599E-5956 + 9893 6.614633597924251795942097564562995E-5957 3.307316798962125897971048782281498E-5957 + 9894 1.653658399481062948985524391140749E-5957 8.268291997405314744927621955703745E-5958 + 9895 4.134145998702657372463810977851873E-5958 2.067072999351328686231905488925936E-5958 + 9896 1.033536499675664343115952744462968E-5958 5.16768249837832171557976372231484E-5959 + 9897 2.58384124918916085778988186115742E-5959 1.29192062459458042889494093057871E-5959 + 9898 6.45960312297290214447470465289355E-5960 3.229801561486451072237352326446775E-5960 + 9899 1.614900780743225536118676163223388E-5960 8.074503903716127680593380816116938E-5961 + 9900 4.037251951858063840296690408058469E-5961 2.018625975929031920148345204029235E-5961 + 9901 1.009312987964515960074172602014618E-5961 5.046564939822579800370863010073088E-5962 + 9902 2.523282469911289900185431505036544E-5962 1.261641234955644950092715752518272E-5962 + 9903 6.30820617477822475046357876259136E-5963 3.15410308738911237523178938129568E-5963 + 9904 1.57705154369455618761589469064784E-5963 7.8852577184727809380794734532392E-5964 + 9905 3.9426288592363904690397367266196E-5964 1.9713144296181952345198683633098E-5964 + 9906 9.856572148090976172599341816549E-5965 4.9282860740454880862996709082745E-5965 + 9907 2.46414303702274404314983545413725E-5965 1.232071518511372021574917727068625E-5965 + 9908 6.160357592556860107874588635343125E-5966 3.080178796278430053937294317671563E-5966 + 9909 1.540089398139215026968647158835782E-5966 7.700446990696075134843235794178908E-5967 + 9910 3.850223495348037567421617897089454E-5967 1.925111747674018783710808948544727E-5967 + 9911 9.625558738370093918554044742723635E-5968 4.812779369185046959277022371361818E-5968 + 9912 2.406389684592523479638511185680909E-5968 1.203194842296261739819255592840455E-5968 + 9913 6.015974211481308699096277964202275E-5969 3.007987105740654349548138982101138E-5969 + 9914 1.503993552870327174774069491050569E-5969 7.519967764351635873870347455252845E-5970 + 9915 3.759983882175817936935173727626423E-5970 1.879991941087908968467586863813211E-5970 + 9916 9.399959705439544842337934319066055E-5971 4.699979852719772421168967159533028E-5971 + 9917 2.349989926359886210584483579766514E-5971 1.174994963179943105292241789883257E-5971 + 9918 5.874974815899715526461208949416285E-5972 2.937487407949857763230604474708143E-5972 + 9919 1.468743703974928881615302237354072E-5972 7.343718519874644408076511186770358E-5973 + 9920 3.671859259937322204038255593385179E-5973 1.835929629968661102019127796692590E-5973 + 9921 9.17964814984330551009563898346295E-5974 4.589824074921652755047819491731475E-5974 + 9922 2.294912037460826377523909745865738E-5974 1.147456018730413188761954872932869E-5974 + 9923 5.737280093652065943809774364664345E-5975 2.868640046826032971904887182332173E-5975 + 9924 1.434320023413016485952443591166087E-5975 7.171600117065082429762217955830433E-5976 + 9925 3.585800058532541214881108977915217E-5976 1.792900029266270607440554488957608E-5976 + 9926 8.96450014633135303720277244478804E-5977 4.48225007316567651860138622239402E-5977 + 9927 2.24112503658283825930069311119701E-5977 1.120562518291419129650346555598505E-5977 + 9928 5.602812591457095648251732777992525E-5978 2.801406295728547824125866388996263E-5978 + 9929 1.400703147864273912062933194498132E-5978 7.003515739321369560314665972490658E-5979 + 9930 3.501757869660684780157332986245329E-5979 1.750878934830342390078666493122665E-5979 + 9931 8.754394674151711950393332465613325E-5980 4.377197337075855975196666232806663E-5980 + 9932 2.188598668537927987598333116403332E-5980 1.094299334268963993799166558201666E-5980 + 9933 5.47149667134481996899583279100833E-5981 2.735748335672409984497916395504165E-5981 + 9934 1.367874167836204992248958197752083E-5981 6.839370839181024961244790988760413E-5982 + 9935 3.419685419590512480622395494380207E-5982 1.709842709795256240311197747190103E-5982 + 9936 8.549213548976281201555988735950515E-5983 4.274606774488140600777994367975258E-5983 + 9937 2.137303387244070300388997183987629E-5983 1.068651693622035150194498591993815E-5983 + 9938 5.343258468110175750972492959969075E-5984 2.671629234055087875486246479984538E-5984 + 9939 1.335814617027543937743123239992269E-5984 6.679073085137719688715616199961345E-5985 + 9940 3.339536542568859844357808099980673E-5985 1.669768271284429922178904049990336E-5985 + 9941 8.34884135642214961089452024995168E-5986 4.17442067821107480544726012497584E-5986 + 9942 2.08721033910553740272363006248792E-5986 1.04360516955276870136181503124396E-5986 + 9943 5.2180258477638435068090751562198E-5987 2.6090129238819217534045375781099E-5987 + 9944 1.30450646194096087670226878905495E-5987 6.52253230970480438351134394527475E-5988 + 9945 3.261266154852402191755671972637375E-5988 1.630633077426201095877835986318688E-5988 + 9946 8.15316538713100547938917993159344E-5989 4.07658269356550273969458996579672E-5989 + 9947 2.03829134678275136984729498289836E-5989 1.01914567339137568492364749144918E-5989 + 9948 5.0957283669568784246182374572459E-5990 2.54786418347843921230911872862295E-5990 + 9949 1.273932091739219606154559364311475E-5990 6.369660458696098030772796821557375E-5991 + 9950 3.184830229348049015386398410778688E-5991 1.592415114674024507693199205389344E-5991 + 9951 7.96207557337012253846599602694672E-5992 3.98103778668506126923299801347336E-5992 + 9952 1.99051889334253063461649900673668E-5992 9.9525944667126531730824950336834E-5993 + 9953 4.9762972333563265865412475168417E-5993 2.48814861667816329327062375842085E-5993 + 9954 1.244074308339081646635311879210425E-5993 6.220371541695408233176559396052125E-5994 + 9955 3.110185770847704116588279698026063E-5994 1.555092885423852058294139849013031E-5994 + 9956 7.775464427119260291470699245065155E-5995 3.887732213559630145735349622532578E-5995 + 9957 1.943866106779815072867674811266289E-5995 9.719330533899075364338374056331445E-5996 + 9958 4.859665266949537682169187028165723E-5996 2.429832633474768841084593514082861E-5996 + 9959 1.214916316737384420542296757041431E-5996 6.074581583686922102711483785207153E-5997 + 9960 3.037290791843461051355741892603577E-5997 1.518645395921730525677870946301788E-5997 + 9961 7.59322697960865262838935473150894E-5998 3.79661348980432631419467736575447E-5998 + 9962 1.898306744902163157097338682877235E-5998 9.491533724510815785486693414386175E-5999 + 9963 4.745766862255407892743346707193088E-5999 2.372883431127703946371673353596544E-5999 + 9964 1.186441715563851973185836676798272E-5999 5.93220857781925986592918338399136E-6000 + 9965 2.96610428890962993296459169199568E-6000 1.48305214445481496648229584599784E-6000 + 9966 7.4152607222740748324114792299892E-6001 3.7076303611370374162057396149946E-6001 + 9967 1.8538151805685187081028698074973E-6001 9.2690759028425935405143490374865E-6002 + 9968 4.63453795142129677025717451874325E-6002 2.317268975710648385128587259371625E-6002 + 9969 1.158634487855324192564293629685813E-6002 5.793172439276620962821468148429063E-6003 + 9970 2.896586219638310481410734074214532E-6003 1.448293109819155240705367037107266E-6003 + 9971 7.24146554909577620352683518553633E-6004 3.620732774547888101763417592768165E-6004 + 9972 1.810366387273944050881708796384083E-6004 9.051831936369720254408543981920413E-6005 + 9973 4.525915968184860127204271990960207E-6005 2.262957984092430063602135995480103E-6005 + 9974 1.131478992046215031801067997740052E-6005 5.657394960231075159005339988700258E-6006 + 9975 2.828697480115537579502669994350129E-6006 1.414348740057768789751334997175065E-6006 + 9976 7.071743700288843948756674985875325E-6007 3.535871850144421974378337492937663E-6007 + 9977 1.767935925072210987189168746468832E-6007 8.839679625361054935945843732344158E-6008 + 9978 4.419839812680527467972921866172079E-6008 2.209919906340263733986460933086040E-6008 + 9979 1.104959953170131866993230466543020E-6008 5.52479976585065933496615233271510E-6009 + 9980 2.76239988292532966748307616635755E-6009 1.381199941462664833741538083178775E-6009 + 9981 6.905999707313324168707690415893875E-6010 3.452999853656662084353845207946938E-6010 + 9982 1.726499926828331042176922603973469E-6010 8.632499634141655210884613019867345E-6011 + 9983 4.316249817070827605442306509933673E-6011 2.158124908535413802721153254966836E-6011 + 9984 1.079062454267706901360576627483418E-6011 5.39531227133853450680288313741709E-6012 + 9985 2.697656135669267253401441568708545E-6012 1.348828067834633626700720784354273E-6012 + 9986 6.744140339173168133503603921771365E-6013 3.372070169586584066751801960885683E-6013 + 9987 1.686035084793292033375900980442842E-6013 8.430175423966460166879504902214208E-6014 + 9988 4.215087711983230083439752451107104E-6014 2.107543855991615041719876225553552E-6014 + 9989 1.053771927995807520859938112776776E-6014 5.26885963997903760429969056388388E-6015 + 9990 2.63442981998951880214984528194194E-6015 1.31721490999475940107492264097097E-6015 + 9991 6.58607454997379700537461320485485E-6016 3.293037274986898502687306602427425E-6016 + 9992 1.646518637493449251343653301213713E-6016 8.232593187467246256718266506068563E-6017 + 9993 4.116296593733623128359133253034282E-6017 2.058148296866811564179566626517141E-6017 + 9994 1.029074148433405782089783313258571E-6017 5.145370742167028910448916566292853E-6018 + 9995 2.572685371083514455224458283146427E-6018 1.286342685541757227612229141573213E-6018 + 9996 6.431713427708786138061145707866065E-6019 3.215856713854393069030572853933033E-6019 + 9997 1.607928356927196534515286426966517E-6019 8.039641784635982672576432134832583E-6020 + 9998 4.019820892317991336288216067416292E-6020 2.009910446158995668144108033708146E-6020 + 9999 1.004955223079497834072054016854073E-6020 5.024776115397489170360270084270365E-6021 + 10000 2.512388057698744585180135042135183E-6021 1.256194028849372292590067521067591E-6021 + 10001 6.280970144246861462950337605337955E-6022 3.140485072123430731475168802668978E-6022 + 10002 1.570242536061715365737584401334489E-6022 7.851212680308576828687922006672445E-6023 + 10003 3.925606340154288414343961003336223E-6023 1.962803170077144207171980501668111E-6023 + 10004 9.814015850385721035859902508340555E-6024 4.907007925192860517929951254170278E-6024 + 10005 2.453503962596430258964975627085139E-6024 1.226751981298215129482487813542570E-6024 + 10006 6.13375990649107564741243906771285E-6025 3.066879953245537823706219533856425E-6025 + 10007 1.533439976622768911853109766928213E-6025 7.667199883113844559265548834641063E-6026 + 10008 3.833599941556922279632774417320532E-6026 1.916799970778461139816387208660266E-6026 + 10009 9.58399985389230569908193604330133E-6027 4.791999926946152849540968021650665E-6027 + 10010 2.395999963473076424770484010825333E-6027 1.197999981736538212385242005412666E-6027 + 10011 5.98999990868269106192621002706333E-6028 2.994999954341345530963105013531665E-6028 + 10012 1.497499977170672765481552506765833E-6028 7.487499885853363827407762533829163E-6029 + 10013 3.743749942926681913703881266914582E-6029 1.871874971463340956851940633457291E-6029 + 10014 9.359374857316704784259703167286455E-6030 4.679687428658352392129851583643228E-6030 + 10015 2.339843714329176196064925791821614E-6030 1.169921857164588098032462895910807E-6030 + 10016 5.849609285822940490162314479554035E-6031 2.924804642911470245081157239777018E-6031 + 10017 1.462402321455735122540578619888509E-6031 7.312011607278675612702893099442545E-6032 + 10018 3.656005803639337806351446549721273E-6032 1.828002901819668903175723274860636E-6032 + 10019 9.14001450909834451587861637430318E-6033 4.57000725454917225793930818715159E-6033 + 10020 2.285003627274586128969654093575795E-6033 1.142501813637293064484827046787898E-6033 + 10021 5.71250906818646532242413523393949E-6034 2.856254534093232661212067616969745E-6034 + 10022 1.428127267046616330606033808484873E-6034 7.140636335233081653030169042424363E-6035 + 10023 3.570318167616540826515084521212182E-6035 1.785159083808270413257542260606091E-6035 + 10024 8.925795419041352066287711303030455E-6036 4.462897709520676033143855651515228E-6036 + 10025 2.231448854760338016571927825757614E-6036 1.115724427380169008285963912878807E-6036 + 10026 5.578622136900845041429819564394035E-6037 2.789311068450422520714909782197018E-6037 + 10027 1.394655534225211260357454891098509E-6037 6.973277671126056301787274455492545E-6038 + 10028 3.486638835563028150893637227746273E-6038 1.743319417781514075446818613873136E-6038 + 10029 8.71659708890757037723409306936568E-6039 4.35829854445378518861704653468284E-6039 + 10030 2.17914927222689259430852326734142E-6039 1.08957463611344629715426163367071E-6039 + 10031 5.44787318056723148577130816835355E-6040 2.723936590283615742885654084176775E-6040 + 10032 1.361968295141807871442827042088388E-6040 6.809841475709039357214135210441938E-6041 + 10033 3.404920737854519678607067605220969E-6041 1.702460368927259839303533802610485E-6041 + 10034 8.512301844636299196517669013052425E-6042 4.256150922318149598258834506526213E-6042 + 10035 2.128075461159074799129417253263107E-6042 1.064037730579537399564708626631553E-6042 + 10036 5.320188652897686997823543133157765E-6043 2.660094326448843498911771566578883E-6043 + 10037 1.330047163224421749455885783289442E-6043 6.650235816122108747279428916447208E-6044 + 10038 3.325117908061054373639714458223604E-6044 1.662558954030527186819857229111802E-6044 + 10039 8.31279477015263593409928614555901E-6045 4.156397385076317967049643072779505E-6045 + 10040 2.078198692538158983524821536389753E-6045 1.039099346269079491762410768194876E-6045 + 10041 5.19549673134539745881205384097438E-6046 2.59774836567269872940602692048719E-6046 + 10042 1.298874182836349364703013460243595E-6046 6.494370914181746823515067301217975E-6047 + 10043 3.247185457090873411757533650608988E-6047 1.623592728545436705878766825304494E-6047 + 10044 8.11796364272718352939383412652247E-6048 4.058981821363591764696917063261235E-6048 + 10045 2.029490910681795882348458531630618E-6048 1.014745455340897941174229265815309E-6048 + 10046 5.073727276704489705871146329076545E-6049 2.536863638352244852935573164538273E-6049 + 10047 1.268431819176122426467786582269137E-6049 6.342159095880612132338932911345683E-6050 + 10048 3.171079547940306066169466455672842E-6050 1.585539773970153033084733227836421E-6050 + 10049 7.927698869850765165423666139182105E-6051 3.963849434925382582711833069591053E-6051 + 10050 1.981924717462691291355916534795527E-6051 9.909623587313456456779582673977633E-6052 + 10051 4.954811793656728228389791336988817E-6052 2.477405896828364114194895668494408E-6052 + 10052 1.238702948414182057097447834247204E-6052 6.19351474207091028548723917123602E-6053 + 10053 3.09675737103545514274361958561801E-6053 1.548378685517727571371809792809005E-6053 + 10054 7.741893427588637856859048964045025E-6054 3.870946713794318928429524482022513E-6054 + 10055 1.935473356897159464214762241011257E-6054 9.677366784485797321073811205056283E-6055 + 10056 4.838683392242898660536905602528142E-6055 2.419341696121449330268452801264071E-6055 + 10057 1.209670848060724665134226400632036E-6055 6.048354240303623325671132003160178E-6056 + 10058 3.024177120151811662835566001580089E-6056 1.512088560075905831417783000790045E-6056 + 10059 7.560442800379529157088915003950225E-6057 3.780221400189764578544457501975113E-6057 + 10060 1.890110700094882289272228750987557E-6057 9.450553500474411446361143754937783E-6058 + 10061 4.725276750237205723180571877468892E-6058 2.362638375118602861590285938734446E-6058 + 10062 1.181319187559301430795142969367223E-6058 5.906595937796507153975714846836115E-6059 + 10063 2.953297968898253576987857423418058E-6059 1.476648984449126788493928711709029E-6059 + 10064 7.383244922245633942469643558545145E-6060 3.691622461122816971234821779272573E-6060 + 10065 1.845811230561408485617410889636287E-6060 9.229056152807042428087054448181433E-6061 + 10066 4.614528076403521214043527224090717E-6061 2.307264038201760607021763612045358E-6061 + 10067 1.153632019100880303510881806022679E-6061 5.768160095504401517554409030113395E-6062 + 10068 2.884080047752200758777204515056698E-6062 1.442040023876100379388602257528349E-6062 + 10069 7.210200119380501896943011287641745E-6063 3.605100059690250948471505643820873E-6063 + 10070 1.802550029845125474235752821910437E-6063 9.012750149225627371178764109552183E-6064 + 10071 4.506375074612813685589382054776092E-6064 2.253187537306406842794691027388046E-6064 + 10072 1.126593768653203421397345513694023E-6064 5.632968843266017106986727568470115E-6065 + 10073 2.816484421633008553493363784235058E-6065 1.408242210816504276746681892117529E-6065 + 10074 7.041211054082521383733409460587645E-6066 3.520605527041260691866704730293823E-6066 + 10075 1.760302763520630345933352365146912E-6066 8.801513817603151729666761825734558E-6067 + 10076 4.400756908801575864833380912867279E-6067 2.200378454400787932416690456433640E-6067 + 10077 1.100189227200393966208345228216820E-6067 5.50094613600196983104172614108410E-6068 + 10078 2.75047306800098491552086307054205E-6068 1.375236534000492457760431535271025E-6068 + 10079 6.876182670002462288802157676355125E-6069 3.438091335001231144401078838177563E-6069 + 10080 1.719045667500615572200539419088782E-6069 8.595228337503077861002697095443908E-6070 + 10081 4.297614168751538930501348547721954E-6070 2.148807084375769465250674273860977E-6070 + 10082 1.074403542187884732625337136930489E-6070 5.372017710939423663126685684652443E-6071 + 10083 2.686008855469711831563342842326222E-6071 1.343004427734855915781671421163111E-6071 + 10084 6.715022138674279578908357105815555E-6072 3.357511069337139789454178552907778E-6072 + 10085 1.678755534668569894727089276453889E-6072 8.393777673342849473635446382269445E-6073 + 10086 4.196888836671424736817723191134723E-6073 2.098444418335712368408861595567361E-6073 + 10087 1.049222209167856184204430797783681E-6073 5.246111045839280921022153988918403E-6074 + 10088 2.623055522919640460511076994459202E-6074 1.311527761459820230255538497229601E-6074 + 10089 6.557638807299101151277692486148005E-6075 3.278819403649550575638846243074003E-6075 + 10090 1.639409701824775287819423121537002E-6075 8.197048509123876439097115607685008E-6076 + 10091 4.098524254561938219548557803842504E-6076 2.049262127280969109774278901921252E-6076 + 10092 1.024631063640484554887139450960626E-6076 5.12315531820242277443569725480313E-6077 + 10093 2.561577659101211387217848627401565E-6077 1.280788829550605693608924313700783E-6077 + 10094 6.403944147753028468044621568503915E-6078 3.201972073876514234022310784251958E-6078 + 10095 1.600986036938257117011155392125979E-6078 8.004930184691285585055776960629895E-6079 + 10096 4.002465092345642792527888480314948E-6079 2.001232546172821396263944240157474E-6079 + 10097 1.000616273086410698131972120078737E-6079 5.003081365432053490659860600393685E-6080 + 10098 2.501540682716026745329930300196843E-6080 1.250770341358013372664965150098421E-6080 + 10099 6.253851706790066863324825750492105E-6081 3.126925853395033431662412875246053E-6081 + 10100 1.563462926697516715831206437623027E-6081 7.817314633487583579156032188115133E-6082 + 10101 3.908657316743791789578016094057567E-6082 1.954328658371895894789008047028783E-6082 + 10102 9.771643291859479473945040235143915E-6083 4.885821645929739736972520117571958E-6083 + 10103 2.442910822964869868486260058785979E-6083 1.221455411482434934243130029392990E-6083 + 10104 6.10727705741217467121565014696495E-6084 3.053638528706087335607825073482475E-6084 + 10105 1.526819264353043667803912536741238E-6084 7.634096321765218339019562683706188E-6085 + 10106 3.817048160882609169509781341853094E-6085 1.908524080441304584754890670926547E-6085 + 10107 9.542620402206522923774453354632735E-6086 4.771310201103261461887226677316368E-6086 + 10108 2.385655100551630730943613338658184E-6086 1.192827550275815365471806669329092E-6086 + 10109 5.96413775137907682735903334664546E-6087 2.98206887568953841367951667332273E-6087 + 10110 1.491034437844769206839758336661365E-6087 7.455172189223846034198791683306825E-6088 + 10111 3.727586094611923017099395841653413E-6088 1.863793047305961508549697920826706E-6088 + 10112 9.31896523652980754274848960413353E-6089 4.659482618264903771374244802066765E-6089 + 10113 2.329741309132451885687122401033383E-6089 1.164870654566225942843561200516691E-6089 + 10114 5.824353272831129714217806002583455E-6090 2.912176636415564857108903001291728E-6090 + 10115 1.456088318207782428554451500645864E-6090 7.28044159103891214277225750322932E-6091 + 10116 3.64022079551945607138612875161466E-6091 1.82011039775972803569306437580733E-6091 + 10117 9.10055198879864017846532187903665E-6092 4.550275994399320089232660939518325E-6092 + 10118 2.275137997199660044616330469759163E-6092 1.137568998599830022308165234879581E-6092 + 10119 5.687844992999150111540826174397905E-6093 2.843922496499575055770413087198953E-6093 + 10120 1.421961248249787527885206543599477E-6093 7.109806241248937639426032717997383E-6094 + 10121 3.554903120624468819713016358998692E-6094 1.777451560312234409856508179499346E-6094 + 10122 8.88725780156117204928254089749673E-6095 4.443628900780586024641270448748365E-6095 + 10123 2.221814450390293012320635224374183E-6095 1.110907225195146506160317612187091E-6095 + 10124 5.554536125975732530801588060935455E-6096 2.777268062987866265400794030467728E-6096 + 10125 1.388634031493933132700397015233864E-6096 6.94317015746966566350198507616932E-6097 + 10126 3.47158507873483283175099253808466E-6097 1.73579253936741641587549626904233E-6097 + 10127 8.67896269683708207937748134521165E-6098 4.339481348418541039688740672605825E-6098 + 10128 2.169740674209270519844370336302913E-6098 1.084870337104635259922185168151456E-6098 + 10129 5.42435168552317629961092584075728E-6099 2.71217584276158814980546292037864E-6099 + 10130 1.35608792138079407490273146018932E-6099 6.7804396069039703745136573009466E-6100 + 10131 3.3902198034519851872568286504733E-6100 1.69510990172599259362841432523665E-6100 + 10132 8.47554950862996296814207162618325E-6101 4.237774754314981484071035813091625E-6101 + 10133 2.118887377157490742035517906545813E-6101 1.059443688578745371017758953272906E-6101 + 10134 5.29721844289372685508879476636453E-6102 2.648609221446863427544397383182265E-6102 + 10135 1.324304610723431713772198691591133E-6102 6.621523053617158568860993457955663E-6103 + 10136 3.310761526808579284430496728977832E-6103 1.655380763404289642215248364488916E-6103 + 10137 8.27690381702144821107624182244458E-6104 4.13845190851072410553812091122229E-6104 + 10138 2.069225954255362052769060455611145E-6104 1.034612977127681026384530227805573E-6104 + 10139 5.173064885638405131922651139027865E-6105 2.586532442819202565961325569513933E-6105 + 10140 1.293266221409601282980662784756967E-6105 6.466331107048006414903313923784833E-6106 + 10141 3.233165553524003207451656961892417E-6106 1.616582776762001603725828480946208E-6106 + 10142 8.08291388381000801862914240473104E-6107 4.04145694190500400931457120236552E-6107 + 10143 2.02072847095250200465728560118276E-6107 1.01036423547625100232864280059138E-6107 + 10144 5.0518211773812550116432140029569E-6108 2.52591058869062750582160700147845E-6108 + 10145 1.262955294345313752910803500739225E-6108 6.314776471726568764554017503696125E-6109 + 10146 3.157388235863284382277008751848063E-6109 1.578694117931642191138504375924031E-6109 + 10147 7.893470589658210955692521879620155E-6110 3.946735294829105477846260939810078E-6110 + 10148 1.973367647414552738923130469905039E-6110 9.866838237072763694615652349525195E-6111 + 10149 4.933419118536381847307826174762598E-6111 2.466709559268190923653913087381299E-6111 + 10150 1.233354779634095461826956543690650E-6111 6.166773898170477309134782718453248E-6112 + 10151 3.083386949085238654567391359226624E-6112 1.541693474542619327283695679613312E-6112 + 10152 7.70846737271309663641847839806656E-6113 3.85423368635654831820923919903328E-6113 + 10153 1.92711684317827415910461959951664E-6113 9.6355842158913707955230979975832E-6114 + 10154 4.8177921079456853977615489987916E-6114 2.4088960539728426988807744993958E-6114 + 10155 1.2044480269864213494403872496979E-6114 6.0222401349321067472019362484895E-6115 + 10156 3.01112006746605337360096812424475E-6115 1.505560033733026686800484062122375E-6115 + 10157 7.527800168665133434002420310611875E-6116 3.763900084332566717001210155305938E-6116 + 10158 1.881950042166283358500605077652969E-6116 9.409750210831416792503025388264845E-6117 + 10159 4.704875105415708396251512694132423E-6117 2.352437552707854198125756347066211E-6117 + 10160 1.176218776353927099062878173533106E-6117 5.881093881769635495314390867665528E-6118 + 10161 2.940546940884817747657195433832764E-6118 1.470273470442408873828597716916382E-6118 + 10162 7.35136735221204436914298858458191E-6119 3.675683676106022184571494292290955E-6119 + 10163 1.837841838053011092285747146145478E-6119 9.189209190265055461428735730727388E-6120 + 10164 4.594604595132527730714367865363694E-6120 2.297302297566263865357183932681847E-6120 + 10165 1.148651148783131932678591966340924E-6120 5.743255743915659663392959831704618E-6121 + 10166 2.871627871957829831696479915852309E-6121 1.435813935978914915848239957926155E-6121 + 10167 7.179069679894574579241199789630775E-6122 3.589534839947287289620599894815388E-6122 + 10168 1.794767419973643644810299947407694E-6122 8.97383709986821822405149973703847E-6123 + 10169 4.486918549934109112025749868519235E-6123 2.243459274967054556012874934259618E-6123 + 10170 1.121729637483527278006437467129809E-6123 5.608648187417636390032187335649045E-6124 + 10171 2.804324093708818195016093667824523E-6124 1.402162046854409097508046833912261E-6124 + 10172 7.010810234272045487540234169561305E-6125 3.505405117136022743770117084780653E-6125 + 10173 1.752702558568011371885058542390327E-6125 8.763512792840056859425292711951633E-6126 + 10174 4.381756396420028429712646355975817E-6126 2.190878198210014214856323177987908E-6126 + 10175 1.095439099105007107428161588993954E-6126 5.47719549552503553714080794496977E-6127 + 10176 2.738597747762517768570403972484885E-6127 1.369298873881258884285201986242443E-6127 + 10177 6.846494369406294421426009931212215E-6128 3.423247184703147210713004965606108E-6128 + 10178 1.711623592351573605356502482803054E-6128 8.55811796175786802678251241401527E-6129 + 10179 4.279058980878934013391256207007635E-6129 2.139529490439467006695628103503818E-6129 + 10180 1.069764745219733503347814051751909E-6129 5.348823726098667516739070258759545E-6130 + 10181 2.674411863049333758369535129379773E-6130 1.337205931524666879184767564689886E-6130 + 10182 6.68602965762333439592383782344943E-6131 3.343014828811667197961918911724715E-6131 + 10183 1.671507414405833598980959455862358E-6131 8.357537072029167994904797279311788E-6132 + 10184 4.178768536014583997452398639655894E-6132 2.089384268007291998726199319827947E-6132 + 10185 1.044692134003645999363099659913974E-6132 5.223460670018229996815498299569868E-6133 + 10186 2.611730335009114998407749149784934E-6133 1.305865167504557499203874574892467E-6133 + 10187 6.529325837522787496019372874462335E-6134 3.264662918761393748009686437231168E-6134 + 10188 1.632331459380696874004843218615584E-6134 8.16165729690348437002421609307792E-6135 + 10189 4.08082864845174218501210804653896E-6135 2.04041432422587109250605402326948E-6135 + 10190 1.02020716211293554625302701163474E-6135 5.1010358105646777312651350581737E-6136 + 10191 2.55051790528233886563256752908685E-6136 1.275258952641169432816283764543425E-6136 + 10192 6.376294763205847164081418822717125E-6137 3.188147381602923582040709411358563E-6137 + 10193 1.594073690801461791020354705679282E-6137 7.970368454007308955101773528396408E-6138 + 10194 3.985184227003654477550886764198204E-6138 1.992592113501827238775443382099102E-6138 + 10195 9.96296056750913619387721691049551E-6139 4.981480283754568096938608455247755E-6139 + 10196 2.490740141877284048469304227623878E-6139 1.245370070938642024234652113811939E-6139 + 10197 6.226850354693210121173260569059695E-6140 3.113425177346605060586630284529848E-6140 + 10198 1.556712588673302530293315142264924E-6140 7.78356294336651265146657571132462E-6141 + 10199 3.89178147168325632573328785566231E-6141 1.945890735841628162866643927831155E-6141 + 10200 9.729453679208140814333219639155775E-6142 4.864726839604070407166609819577888E-6142 + 10201 2.432363419802035203583304909788944E-6142 1.216181709901017601791652454894472E-6142 + 10202 6.08090854950508800895826227447236E-6143 3.04045427475254400447913113723618E-6143 + 10203 1.52022713737627200223956556861809E-6143 7.60113568688136001119782784309045E-6144 + 10204 3.80056784344068000559891392154523E-6144 1.90028392172034000279945696077261E-6144 + 10205 9.5014196086017000139972848038631E-6145 4.7507098043008500069986424019315E-6145 + 10206 2.3753549021504250034993212009658E-6145 1.1876774510752125017496606004829E-6145 + 10207 5.938387255376062508748303002415E-6146 2.969193627688031254374151501207E-6146 + 10208 1.484596813844015627187075750604E-6146 7.42298406922007813593537875302E-6147 + 10209 3.71149203461003906796768937651E-6147 1.85574601730501953398384468826E-6147 + 10210 9.2787300865250976699192234413E-6148 4.6393650432625488349596117207E-6148 + 10211 2.3196825216312744174798058604E-6148 1.1598412608156372087399029302E-6148 + 10212 5.799206304078186043699514651E-6149 2.899603152039093021849757326E-6149 + 10213 1.449801576019546510924878663E-6149 7.24900788009773255462439332E-6150 + 10214 3.62450394004886627731219666E-6150 1.81225197002443313865609833E-6150 + 10215 9.0612598501221656932804917E-6151 4.5306299250610828466402458E-6151 + 10216 2.2653149625305414233201229E-6151 1.1326574812652707116600615E-6151 + 10217 5.663287406326353558300308E-6152 2.831643703163176779150154E-6152 + 10218 1.415821851581588389575077E-6152 7.07910925790794194787539E-6153 + 10219 3.53955462895397097393770E-6153 1.76977731447698548696885E-6153 + 10220 8.8488865723849274348443E-6154 4.4244432861924637174221E-6154 + 10221 2.2122216430962318587111E-6154 1.1061108215481159293555E-6154 + 10222 5.530554107740579646778E-6155 2.765277053870289823389E-6155 + 10223 1.382638526935144911695E-6155 6.91319263467572455847E-6156 + 10224 3.45659631733786227924E-6156 1.72829815866893113962E-6156 + 10225 8.6414907933446556981E-6157 4.3207453966723278491E-6157 + 10226 2.1603726983361639246E-6157 1.0801863491680819623E-6157 + 10227 5.400931745840409812E-6158 2.700465872920204906E-6158 + 10228 1.350232936460102453E-6158 6.75116468230051227E-6159 + 10229 3.37558234115025614E-6159 1.68779117057512807E-6159 + 10230 8.4389558528756404E-6160 4.2194779264378202E-6160 + 10231 2.1097389632189101E-6160 1.0548694816094551E-6160 + 10232 5.274347408047276E-6161 2.637173704023638E-6161 + 10233 1.318586852011819E-6161 6.59293426005910E-6162 + 10234 3.29646713002955E-6162 1.64823356501478E-6162 + 10235 8.2411678250739E-6163 4.1205839125370E-6163 + 10236 2.0602919562685E-6163 1.0301459781343E-6163 + 10237 5.150729890672E-6164 2.575364945336E-6164 + 10238 1.287682472668E-6164 6.43841236334E-6165 + 10239 3.21920618167E-6165 1.60960309084E-6165 + 10240 8.0480154542E-6166 4.0240077271E-6166 + 10241 2.0120038636E-6166 1.0060019318E-6166 + 10242 5.030009659E-6167 2.515004830E-6167 + 10243 1.257502415E-6167 6.28751208E-6168 + 10244 3.14375604E-6168 1.57187802E-6168 + 10245 7.8593901E-6169 3.9296951E-6169 + 10246 1.9648476E-6169 9.824238E-6170 + 10247 4.912119E-6170 2.456060E-6170 + 10248 1.228030E-6170 6.14015E-6171 + 10249 3.07008E-6171 1.53504E-6171 + 10250 7.6752E-6172 3.8376E-6172 + 10251 1.9188E-6172 9.594E-6173 + 10252 4.797E-6173 2.399E-6173 + 10253 1.200E-6173 6.00E-6174 + 10254 3.00E-6174 1.50E-6174 + 10255 7.5E-6175 3.8E-6175 + 10256 1.9E-6175 1.0E-6175 + 10257 5E-6176 3E-6176 + 10258 2E-6176 1E-6176 + 10259 1E-6176 0E-6176 + 10260 0E-6176 0E-6176 + """ + +@pytest.mark.version('>=4.0') +def test_decfloat_min_distinguish_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/datatypes/test_decfloat_nan_and_infinity_comparison.py b/tests/functional/datatypes/test_decfloat_nan_and_infinity_comparison.py new file mode 100644 index 00000000..28ddab6c --- /dev/null +++ b/tests/functional/datatypes/test_decfloat_nan_and_infinity_comparison.py @@ -0,0 +1,66 @@ +#coding:utf-8 +# +# id: functional.datatypes.decfloat_nan_and_infinity_comparison +# title: DECFLOAT should not throw exceptions when +/-NaN, +/-sNaN and +/-Infinity is used in comparisons +# decription: +# Checked on 4.0.0.920. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[\\s]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- NB: need to set decfloat traps to , otherwise get: + -- Statement failed, SQLSTATE = 22012 + -- Decimal float divide by zero. The code attempted to divide a DECFLOAT value by zero. + set decfloat traps to; + set list on; + set count on; + select + i + ,n + ,i < i+i as is_infinity_less_then_itself_plus_same_infinity + ,i = i-i is_infinity_equal_to_itself_reduced_by_any_value + ,n < n + i is_nan_less_than_nan_plus_infinity + ,n = n - 1 is_nan_equal_to_nan_minus_a_number + ,n = n+1 is_nan_equal_to_nan_plus_a_number + ,n > n - i is_nan_more_than_nan_minus_infinity + from ( + select 1/1e-9999 as i, cast('34ffd' as decfloat(16)) as n from rdb$database + ); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + I Infinity + N NaN + IS_INFINITY_LESS_THEN_ITSELF_PLUS_SAME_INFINITY + IS_INFINITY_EQUAL_TO_ITSELF_REDUCED_BY_ANY_VALUE + IS_NAN_LESS_THAN_NAN_PLUS_INFINITY + IS_NAN_EQUAL_TO_NAN_MINUS_A_NUMBER + IS_NAN_EQUAL_TO_NAN_PLUS_A_NUMBER + IS_NAN_MORE_THAN_NAN_MINUS_INFINITY + + Records affected: 1 + """ + +@pytest.mark.version('>=4.0') +def test_decfloat_nan_and_infinity_comparison_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/datatypes/test_decfloat_parsing_scaled_integers_and_bigint_max_min.py b/tests/functional/datatypes/test_decfloat_parsing_scaled_integers_and_bigint_max_min.py new file mode 100644 index 00000000..df90a391 --- /dev/null +++ b/tests/functional/datatypes/test_decfloat_parsing_scaled_integers_and_bigint_max_min.py @@ -0,0 +1,94 @@ +#coding:utf-8 +# +# id: functional.datatypes.decfloat_parsing_scaled_integers_and_bigint_max_min +# title: Interpretation of DECFLOAT values as BIGINT +# decription: +# Check commit: "Fixed parsing of scaled integers and MAX/MIN INT64", 2017-05-28 +# See: github.com/FirebirdSQL/firebird/commit/1278d0692b535f69c7f9e208aad9682980ed9c59 +# 40SS, build 4.0.0.680: OK, 1.047s; build 4.0.0.651: FAILED. +# +# 10.12.2019. Updated syntax for SET BIND command because it was changed in 11-nov-2019. +# Checked on: WI-T4.0.0.1685. +# +# 30.12.2019. Updated code and expected_stdout - get it from Alex, see letter 30.12.2019 16:15. +# Checked on: 4.0.0.1712: OK, 1.188s +# +# 25.06.2020, 4.0.0.2076: changed types in SQLDA from numeric to int128 // after discuss with Alex about CORE-6342. +# 01.07.2020, 4.0.0.2084: adjusted expected output ('subtype' values). +# Removed unnecessary lines from output and added substitution section for result to be properly filtered. +# +# ::: NOTE ::: +# Found a problem with interpreting values +# 170141183460469231731687303715884105727 and -170141183460469231731687303715884105728 +# Sent letter to Alex (01.07.2020 13:55), waiting for fix. Check of bind DECFLOAT to INT128 was deferred. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('^((?!sqltype|BEHIND_BIGINT_|BIGINT_|DROB1).)*$', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set sqlda_display on; + + recreate view v_test as + select + -9223372036854775809 as behind_bigint_min + ,9223372036854775808 as behind_bigint_max + ,-9223372036854775808 as bigint_min + ,9223372036854775807 as bigint_max + ,0.0123456789123456789 as drob1 + from rdb$database; + + select * from v_test; + + set bind of bigint to double precision; + set sqlda_display off; + + select * from v_test; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 01: sqltype: 32752 INT128 Nullable scale: 0 subtype: 0 len: 16 + : name: BEHIND_BIGINT_MIN alias: BEHIND_BIGINT_MIN + 02: sqltype: 32752 INT128 Nullable scale: 0 subtype: 0 len: 16 + : name: BEHIND_BIGINT_MAX alias: BEHIND_BIGINT_MAX + 03: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: BIGINT_MIN alias: BIGINT_MIN + 04: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: BIGINT_MAX alias: BIGINT_MAX + 05: sqltype: 580 INT64 Nullable scale: -19 subtype: 0 len: 8 + : name: DROB1 alias: DROB1 + BEHIND_BIGINT_MIN -9223372036854775809 + BEHIND_BIGINT_MAX 9223372036854775808 + BIGINT_MIN -9223372036854775808 + BIGINT_MAX 9223372036854775807 + DROB1 0.0123456789123456789 + BEHIND_BIGINT_MIN -9223372036854775809 + BEHIND_BIGINT_MAX 9223372036854775808 + BIGINT_MIN -9.223372036854776e+18 + BIGINT_MAX 9.223372036854776e+18 + DROB1 0.01234567891234568 + """ + +@pytest.mark.version('>=4.0') +def test_decfloat_parsing_scaled_integers_and_bigint_max_min_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/datatypes/test_decfloat_round_modes.py b/tests/functional/datatypes/test_decfloat_round_modes.py new file mode 100644 index 00000000..95c6263a --- /dev/null +++ b/tests/functional/datatypes/test_decfloat_round_modes.py @@ -0,0 +1,187 @@ +#coding:utf-8 +# +# id: functional.datatypes.decfloat_round_modes +# title: Check validity of different ROUNDING modes that are defined for DECFLOAT datatype. +# decription: +# See CORE-5535 and doc\\sql.extensions\\README.data_types +# +# Sample with results of diff. rounding modes: ibm.com/developerworks/ru/library/dm-0801chainani/ +# Sample for round(1608.90*5/100, 2): sql.ru/forum/actualutils.aspx?action=gotomsg&tid=729836&msg=8243077 +# +# Results (24.05.2017): +# FB40CS, build 4.0.0.651: OK, 2.640ss +# FB40SC, build 4.0.0.651: OK, 1.469ss +# FB40SS, build 4.0.0.651: OK, 1.312ss +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ ]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + /****** + 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_test2 as select 1 id from rdb$database; + commit; + + recreate table test2( + v1 decfloat(16) + ,v2 decfloat(16) + ,v3 decfloat(16) + ,v4 decfloat(16) + ,v5 decfloat(16) + ,v6 decfloat(16) + ,vc decfloat(16) + ,vp decfloat(16) + ,vd decfloat(16) + ,vx computed by (vc * vp / vd) + ,vy computed by (vc * vp / vd) + ) + ; + commit; + + insert into test2( 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_test2 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 test2; + commit; + + set decfloat round ceiling; + select 'ceiling' as round_mode, v.* from v_test2 v; -- +80.45; -80.44 + + set decfloat round up; + select 'up' as round_mode, v.* from v_test2 v; -- +80.45; -80.45 + + set decfloat round half_up; + select 'half_up' as round_mode, v.* from v_test2 v; -- +80.45; -80.45 + + set decfloat round half_even; + select 'half_even' as round_mode, v.* from v_test2 v; -- +80.44; -80.44 + + set decfloat round half_down; + select 'half_down' as round_mode, v.* from v_test2 v; -- +80.44; -80.44 + + set decfloat round down; + select 'down' as round_mode, v.* from v_test2 v; -- +80.44; -80.44 + + set decfloat round floor; + select 'floor' as round_mode, v.* from v_test2 v;-- +80.44; -80.45 + + set decfloat round reround; + select 'reround' as round_mode, v.* from v_test2 v; -- +80.44; -80.44 + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ROUND_MODE 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 + ROUND_MODE 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 + ROUND_MODE 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 + ROUND_MODE 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 + ROUND_MODE 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 + ROUND_MODE 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 + ROUND_MODE 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 + ROUND_MODE 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 + """ + +@pytest.mark.version('>=4.0') +def test_decfloat_round_modes_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/datatypes/test_decfloat_scalar_functions.py b/tests/functional/datatypes/test_decfloat_scalar_functions.py new file mode 100644 index 00000000..914f69bb --- /dev/null +++ b/tests/functional/datatypes/test_decfloat_scalar_functions.py @@ -0,0 +1,118 @@ +#coding:utf-8 +# +# id: functional.datatypes.decfloat_scalar_functions +# title: Test common math functions that should work with DECFLOAT datatype. +# decription: +# See CORE-5535 and doc\\sql.extensions\\README.data_types: +# --- +# A number of standard functions can be used with DECFLOAT datatype. It is: +# ABS, CEILING, EXP, FLOOR, LN, LOG, LOG10, POWER, SIGN, SQRT. +# --- +# Checked on: +# 4.0.0.680: OK, 0.891s. +# 4.0.0.651: FAILED on SIGN() with: +# Statement failed, SQLSTATE = 22003 +# Decimal float overflow. The exponent of a result is greater than the magnitude allowed. +# +# 31.10.2019: adjusted output to recent FB version. Checked on 4.0.0.1635 SS: 0.917s. +# 26.06.2020: adjusted output to recent FB version. Checked on 4.0.0.2079, intermediate snapshot with timestamp = 26.06.2020 14:34. +# 21.08.2020: put literal numeric values into a table with DECFLOAT table; replaced UNIONED-code with separate statements. Checked on 4.0.0.2173 +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + recreate table test(n1 decfloat); + insert into test(n1) values (-123456789012345678901234567890.123); + commit; + select abs(n1) as abs_x from test; + select ceiling(n1) as ceiling_x from test; + select floor(n1) as floor_x from test; + select ceiling(abs(n1)) as ceil_abs_x from test; + select floor(abs(n1)) as floor_abs_x from test; + commit; + ------------------------------------------------------------------- + delete from test; + insert into test(n1) values ( + 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 + ); + select ln(n1) as ln_1e1024 from test; + select exp(ln(n1)) as exp_1e1024 from test; + select log10(n1) as log10_1e1024 from test; + select power(n1,-1.0000000000/log10(n1)) as power_x from test; + select sqrt(n1) as sqrt_1e1024 from test; + select sign(-n1) as sign_1e1024 from test; + commit; + ------------------------------------------------------------------- + recreate table test(power_2_127_dec_1 decfloat, power_2_127_exact decfloat); + insert into test(power_2_127_dec_1, power_2_127_exact) values ( + 170141183460469231731687303715884105727 + ,170141183460469231731687303715884105728 + ); + select ln(power_2_127_dec_1) as ln1, ln(power_2_127_exact) as ln2 from test; + + select exp(ln(power_2_127_dec_1)) as exp1, exp(ln(power_2_127_dec_1)) as exp2 from test; + + select log10(power_2_127_dec_1) as log10a, log10(power_2_127_exact) as log10b from test; + + select power(power_2_127_dec_1,-1.0000000000 / log10(power_2_127_dec_1)) as power_a + ,power(power_2_127_exact,-1.0000000000/log10(power_2_127_exact)) as power_b + from test; + + select sqrt(power_2_127_dec_1) as sqrt_a, sqrt(power_2_127_exact) as sqrt_b from test; + + select sign(-power_2_127_dec_1) as sign_a, sign(-power_2_127_exact) as sign_b from test; + + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ABS_X 123456789012345678901234567890.123 + CEILING_X -123456789012345678901234567890 + FLOOR_X -123456789012345678901234567891 + CEIL_ABS_X 123456789012345678901234567891 + FLOOR_ABS_X 123456789012345678901234567890 + LN_1E1024 2357.847135225902780434423249596789 + EXP_1E1024 9.999999999999999999999999999996197E+1023 + LOG10_1E1024 1024 + POWER_X 0.1000000000000000000000000000000000 + SQRT_1E1024 1.00000000000000000E+512 + SIGN_1E1024 -1 + LN1 88.02969193111305429598847942518842 + LN2 88.02969193111305429598847942518842 + EXP1 1.701411834604692317316873037158807E+38 + EXP2 1.701411834604692317316873037158807E+38 + LOG10A 38.23080944932561179214483963001061 + LOG10B 38.23080944932561179214483963001061 + POWER_A 0.09999999999999999999999999999999995 + POWER_B 0.09999999999999999999999999999999995 + SQRT_A 13043817825332782212.34957180625251 + SQRT_B 13043817825332782212.34957180625251 + SIGN_A -1 + SIGN_B -1 + """ + +@pytest.mark.version('>=4.0') +def test_decfloat_scalar_functions_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/datatypes/test_decfloat_single_bit_in_representation.py b/tests/functional/datatypes/test_decfloat_single_bit_in_representation.py new file mode 100644 index 00000000..f90a10a2 --- /dev/null +++ b/tests/functional/datatypes/test_decfloat_single_bit_in_representation.py @@ -0,0 +1,70 @@ +#coding:utf-8 +# +# id: functional.datatypes.decfloat_single_bit_in_representation +# title: DECFLOAT: check result of EXP() which can be represented only by one ("last") significant bit +# decription: +# Get minimal distinguish from zero value for DEFCFLOAT datatype using EXP() function. +# Check some trivial arithmetic results for this value and pair of other values which are closest to it. +# See also: https://en.wikipedia.org/wiki/Decimal_floating_point +# Checked on 4.0.0.1714 +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ ]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select + df0 as decfloat_near_zero + ,df1 as min_decfloat_distinguish_from_zero + ,df2 as max_decfloat_non_distinct_from_zero + ,df0/df1 as division_result_1a + ,df1/df0 as division_result_1b + ,df0-df1 as subtract_result_1a + ,df1-df0 as subtract_result_1b + ,df0+df2 = df1 as sum_cmp_result_2 + ,df1 / df1 division_result_2 + ,df1+df2 = df1 sum_and_cmp_result_2 + 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 + ); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DECFLOAT_NEAR_ZERO 1E-6176 + MIN_DECFLOAT_DISTINGUISH_FROM_ZERO 1E-6176 + MAX_DECFLOAT_NON_DISTINCT_FROM_ZERO 0E-6176 + DIVISION_RESULT_1A 1 + DIVISION_RESULT_1B 1 + SUBTRACT_RESULT_1A 0E-6176 + SUBTRACT_RESULT_1B 0E-6176 + SUM_CMP_RESULT_2 + DIVISION_RESULT_2 1 + SUM_AND_CMP_RESULT_2 + """ + +@pytest.mark.version('>=4.0') +def test_decfloat_single_bit_in_representation_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/datatypes/test_decfloat_special_functions.py b/tests/functional/datatypes/test_decfloat_special_functions.py new file mode 100644 index 00000000..3a2fb3e2 --- /dev/null +++ b/tests/functional/datatypes/test_decfloat_special_functions.py @@ -0,0 +1,434 @@ +#coding:utf-8 +# +# id: functional.datatypes.decfloat_special_functions +# title: Test functions that are designed specially for DECFLOAT handling. +# decription: +# See CORE-5535 and doc\\sql.extensions\\README.data_types: +# COMPARE_DECFLOAT; NORMALIZE_DECFLOAT; QUANTIZE; TOTALORDER +# Checked on: +# FB40 CS, build 4.0.0.651: OK, 1.922s +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + ---------------------------------------- NORMALIZE_DECFLOAT() ------------------------------------ + + select 'Test of NORMALIZE_DECFLOAT()' as msg from rdb$database; + select + normalize_decfloat(n1) ndf1 + ,normalize_decfloat(n2) ndf2 + ,normalize_decfloat(n3) ndf3 + ,normalize_decfloat(n4) ndf4 + ,normalize_decfloat(n5) ndf5 + ,normalize_decfloat(n6) ndf6 + from ( + select + 0.10000000000000000000055500000000789000000000000000000000000000000000000000000000000000000000000099900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 n1 + ,-0.1000000000000000000005550000000078900000000000000000000000000000000000000000000000000000000000009990000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 n2 + ,0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054321 n3 + ,-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054321 n4 + ,1230000000000000000000055500000000789000000000000000000000000000000000000000000000000000000000000099900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 n5 + ,-123000000000000000000005550000000078900000000000000000000000000000000000000000000000000000000000009990000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 n6 + from rdb$database + ) + ; + + + ---------------------------------------- COMPARE_DECFLOAT() ------------------------------------ + + -- https://www.ibm.com/support/knowledgecenter/SSEPGG_9.7.0/com.ibm.db2.luw.sql.ref.doc/doc/r0050507.html + + set list on; + select 'Test of COMPARE_DECFLOAT()' as msg from rdb$database; + select + n1 as val1 + ,n2 as val2 + ,octet_length(cast(n1 as varchar(1024))) len1 + ,octet_length(cast(n2 as varchar(1024))) len1 + ,'val1 is ' || decode(compare_decfloat(n1, n2), 0,'equal to', 1,'less than', 2,'greater than') || ' val2' compare_result + from ( + + select + 0.1 n1 + , + 0.10 n2 + from rdb$database + union all + + select + 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 n1 + , + 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010 n2 + from rdb$database + union all + + select + 10.1 n1 + , + 10.10 n2 + from rdb$database + union all + + select + 9876543211.0 n1 + , + 9876543211.00 n2 + from rdb$database + + union all + + select + 98765432100000000000000001234321.0 n1 + , + 98765432100000000000000001234321.00 n2 + from rdb$database + union all + + select + 987654321000000000000000001234321.0 n1 + , + 987654321000000000000000001234321.00 n2 + from rdb$database + union all + + + select + 9876543210000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001234321.0 n1 + , + 9876543210000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001234321.00 n2 + from rdb$database + + ) + ; + + ---------------------------------------- TOTALORDER() ------------------------------------ + + select 'Test of TOTALORDER()' as msg from rdb$database; + select + n1 as val1 + ,n2 as val2 + ,octet_length(cast(n1 as varchar(1024))) len1 + ,octet_length(cast(n2 as varchar(1024))) len1 + ,'val1 is ' || decode(totalorder(n1, n2), -1,'less than', 0,'equal to', 1,'greater than') || ' val2' total_order_result + from ( + + select + 0.1 n1 + , + 0.10 n2 + from rdb$database + union all + + select + 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 n1 + , + 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010 n2 + from rdb$database + union all + + select + 10.1 n1 + , + 10.10 n2 + from rdb$database + union all + + select + 9876543211.0 n1 + , + 9876543211.00 n2 + from rdb$database + + union all + + select + 98765432100000000000000001234321.0 n1 + , + 98765432100000000000000001234321.00 n2 + from rdb$database + union all + + select + 987654321000000000000000001234321.0 n1 + , + 987654321000000000000000001234321.00 n2 + from rdb$database + union all + + + select + 9876543210000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001234321.0 n1 + , + 9876543210000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001234321.00 n2 + from rdb$database + + ) + ; + + + + + ---------------------------------------- QUANTIZE() ------------------------------------ + + + select 'Test of QUANTIZE()' as msg from rdb$database; + select + n1 as val1 + ,octet_length(cast(n1 as varchar(1024))) len1 + ,quantize(n1, p1) qdf1 + from ( + select + 0.10000000000000000000055500000000789000000000000000000000000000000000000000000000000000000000000099900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 n1 + , + 9.99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 p1 + from rdb$database + union all + + select + -0.1000000000000000000005550000000078900000000000000000000000000000000000000000000000000000000000009990000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 + , + 9.99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 + from rdb$database + union all + + select + 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054321 + , + 9.99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 + from rdb$database + union all + + select + -0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054321 + , + 9.99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 + from rdb$database + union all + + select + 1230000000000000000000055500000000789000000000000000000000000000000000000000000000000000000000000099900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 + , + 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 + from rdb$database + union all + + select + -123000000000000000000005550000000078900000000000000000000000000000000000000000000000000000000000009990000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 + , + 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 + from rdb$database + union all + + select + 1234567890123456789012345678901234 + , + 9999999999999999999999999999999999 + from rdb$database + union all + + + select + -1234567890123456789012345678901234 + , + 99999999999999999999999999999999999 + from rdb$database + union all + + select + 1234567890123456789012345678901234.0 + , + 999999999999999999999999999999999999 + from rdb$database + union all + + + select + 1234567890123456789012345678901234.5 + , + 999999999999999999999999999999999999 + from rdb$database + union all + + select + 1234567890123456789012345678901234.56 + , + 9999999999999999999999999999999999999 + from rdb$database + + ) + ; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG Test of NORMALIZE_DECFLOAT() + NDF1 0.1000000000000000000005550000000079 + NDF2 -0.1000000000000000000005550000000079 + NDF3 5.4321E-1018 + NDF4 -5.4321E-1017 + NDF5 1.230000000000000000000055500000001E+1023 + NDF6 -1.230000000000000000000055500000001E+1022 + + + + MSG Test of COMPARE_DECFLOAT() + VAL1 0.1 + VAL2 0.10 + LEN1 3 + LEN1 4 + COMPARE_RESULT val1 is greater than val2 + + VAL1 1E-1021 + VAL2 1.0E-1021 + LEN1 7 + LEN1 9 + COMPARE_RESULT val1 is greater than val2 + + VAL1 10.1 + VAL2 10.10 + LEN1 4 + LEN1 5 + COMPARE_RESULT val1 is greater than val2 + + VAL1 9876543211.0 + VAL2 9876543211.00 + LEN1 12 + LEN1 13 + COMPARE_RESULT val1 is greater than val2 + + VAL1 98765432100000000000000001234321.0 + VAL2 98765432100000000000000001234321.00 + LEN1 34 + LEN1 35 + COMPARE_RESULT val1 is greater than val2 + + VAL1 987654321000000000000000001234321.0 + VAL2 987654321000000000000000001234321.0 + LEN1 35 + LEN1 35 + COMPARE_RESULT val1 is equal to val2 + + VAL1 9.876543210000000000000000000000000E+1020 + VAL2 9.876543210000000000000000000000000E+1020 + LEN1 41 + LEN1 41 + COMPARE_RESULT val1 is equal to val2 + + + MSG Test of TOTALORDER() + VAL1 0.1 + VAL2 0.10 + LEN1 3 + LEN1 4 + TOTAL_ORDER_RESULT val1 is greater than val2 + + VAL1 1E-1021 + VAL2 1.0E-1021 + LEN1 7 + LEN1 9 + TOTAL_ORDER_RESULT val1 is greater than val2 + + VAL1 10.1 + VAL2 10.10 + LEN1 4 + LEN1 5 + TOTAL_ORDER_RESULT val1 is greater than val2 + + VAL1 9876543211.0 + VAL2 9876543211.00 + LEN1 12 + LEN1 13 + TOTAL_ORDER_RESULT val1 is greater than val2 + + VAL1 98765432100000000000000001234321.0 + VAL2 98765432100000000000000001234321.00 + LEN1 34 + LEN1 35 + TOTAL_ORDER_RESULT val1 is greater than val2 + + VAL1 987654321000000000000000001234321.0 + VAL2 987654321000000000000000001234321.0 + LEN1 35 + LEN1 35 + TOTAL_ORDER_RESULT val1 is equal to val2 + + VAL1 9.876543210000000000000000000000000E+1020 + VAL2 9.876543210000000000000000000000000E+1020 + LEN1 41 + LEN1 41 + TOTAL_ORDER_RESULT val1 is equal to val2 + + + MSG Test of QUANTIZE() + VAL1 0.1000000000000000000005550000000079 + LEN1 36 + QDF1 0.10000000000000000000055500000001 + + VAL1 -0.1000000000000000000005550000000079 + LEN1 37 + QDF1 -0.10000000000000000000055500000001 + + VAL1 5.4321E-1018 + LEN1 12 + QDF1 0E-32 + + VAL1 -5.4321E-1017 + LEN1 13 + QDF1 -0E-32 + + VAL1 1.230000000000000000000055500000001E+1023 + LEN1 41 + QDF1 1.23000000000000000000005550000000E+1023 + + VAL1 -1.230000000000000000000055500000001E+1022 + LEN1 42 + QDF1 -1.2300000000000000000000555000000E+1022 + + VAL1 1234567890123456789012345678901234 + LEN1 34 + QDF1 1234567890123456789012345678901234 + + VAL1 -1234567890123456789012345678901234 + LEN1 35 + QDF1 -1.2345678901234567890123456789012E+33 + + VAL1 1234567890123456789012345678901234 + LEN1 34 + QDF1 1.234567890123456789012345678901E+33 + + VAL1 1234567890123456789012345678901235 + LEN1 34 + QDF1 1.234567890123456789012345678901E+33 + + VAL1 1234567890123456789012345678901235 + LEN1 34 + QDF1 1.23456789012345678901234567890E+33 + + + """ + +@pytest.mark.version('>=4.0') +def test_decfloat_special_functions_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/datatypes/test_decimal_declared_scale.py b/tests/functional/datatypes/test_decimal_declared_scale.py new file mode 100644 index 00000000..d54f1a84 --- /dev/null +++ b/tests/functional/datatypes/test_decimal_declared_scale.py @@ -0,0 +1,67 @@ +#coding:utf-8 +# +# id: functional.datatypes.decimal_declared_scale +# title: Declared scale does not act as a constraint, it just defines the accuracy of the storage +# decription: +# Samples are from CORE-3556 and CORE-5723. +# Checked on: +# FB25SC, build 2.5.8.27090: OK, 0.453s. +# FB30SS, build 3.0.3.32897: OK, 1.047s. +# FB40SS, build 4.0.0.872: OK, 1.313s. +# +# tracker_id: +# min_versions: ['2.5.8'] +# versions: 2.5.8 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.8 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + recreate table test ( id int, b numeric(18,5) ); + insert into test(id, b) values (1, 1.0000199); + insert into test(id, b) values (2, (select round(min(b),5) from test) ); + commit; + + select id, b, iif(b = 1.00002, 'true', 'false') c from test order by id; + commit; + + recreate table test(id int, a decimal(18,18), b decimal(3,3) ); + commit; + + insert into test(id, a, b) values( 1, '9.123456789012345678', '999999.999' ); + select * from test order by id; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + B 1.00002 + C true + + ID 2 + B 1.00002 + C true + + ID 1 + A 9.123456789012345678 + B 999999.999 + """ + +@pytest.mark.version('>=2.5.8') +def test_decimal_declared_scale_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/datatypes/test_dp_single_bit_in_representation.py b/tests/functional/datatypes/test_dp_single_bit_in_representation.py new file mode 100644 index 00000000..2f0e92a0 --- /dev/null +++ b/tests/functional/datatypes/test_dp_single_bit_in_representation.py @@ -0,0 +1,55 @@ +#coding:utf-8 +# +# id: functional.datatypes.dp_single_bit_in_representation +# title: Check result of EXP() which can be represented only by one ("last") significant bit +# decription: +# build 2.5.8.27067: OK, 0.640s. +# build 3.0.3.32794: OK, 0.844s. +# build 4.0.0.700: OK, 0.922s. +# (2.5.8 was checked bot on Win32 and POSIX amd64; all others - only on Win32) +# +# tracker_id: +# min_versions: ['2.5.8'] +# versions: 2.5.8 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.8 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select iif(exp(-745.1332191)=0.0, 0, 1) as still_has_bits from rdb$database; + select iif(exp(-745.1332192)=0.0, 0, 1) as still_has_bits from rdb$database; + select e1,e2, iif(e1=e2, 'equals', 'differs') as e1_equ_e2, e1/e2 as e1_div_e2, e2/e1 as e2_div_e2 + from ( + select exp(-744.0346068132731393) as e1, exp(-745.1332191019410399) as e2 from rdb$database + ); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + STILL_HAS_BITS 1 + STILL_HAS_BITS 0 + E1 4.940656458412465e-324 + E2 4.940656458412465e-324 + E1_EQU_E2 equals + E1_DIV_E2 1.000000000000000 + E2_DIV_E2 1.000000000000000 + """ + +@pytest.mark.version('>=2.5.8') +def test_dp_single_bit_in_representation_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/datatypes/test_int128_binary_operations.py b/tests/functional/datatypes/test_int128_binary_operations.py new file mode 100644 index 00000000..37e59243 --- /dev/null +++ b/tests/functional/datatypes/test_int128_binary_operations.py @@ -0,0 +1,74 @@ +#coding:utf-8 +# +# id: functional.datatypes.int128_binary_operations +# title: Basic test for binary functions against INT128 datatype +# decription: +# Test verifies https://github.com/FirebirdSQL/firebird/commit/137c3a96e51b8bc34cb74732687067e96c971226 +# (Postfix for CORE-6342: enable support of int128 in bin_* family of functions). +# Checked on 4.0.0.2083 (intermediate build 30.06.2020 16:38). +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + recreate table test_i128(bi_least int128, bi_great int128); + commit; + + insert into test_i128(bi_least, bi_great) values(-170141183460469231731687303715884105728, 170141183460469231731687303715884105727); + + + -- All subsequent expressions before 4.0.0.2083 raised: + -- Statement failed, SQLSTATE = 22003 + -- arithmetic exception, numeric overflow, or string truncation + -- -Integer overflow. The result of an integer operation caused the most significant bit of the result to carry. + + select bin_and(bi_least,bi_great) from test_i128; -- expected: 0 + select bin_not(bi_least) from test_i128; -- expected: 170141183460469231731687303715884105727 + select bin_not(bi_great) from test_i128; -- expected: -170141183460469231731687303715884105728 + select bin_or(bi_least, bi_great) from test_i128; -- expected: -1 + select bin_shr(bi_least,127) from test_i128; -- expected: 1 + select bin_shr(bi_great,127) from test_i128; -- expected: 0 + select bin_shl(bi_least,127) from test_i128; -- expected: 0 + select bin_and( bin_shl(bi_great,127), bi_least) from test_i128; -- expected: -170141183460469231731687303715884105728 + select bin_xor(bi_least, bi_great) from test_i128; -- expected: -1 + select bin_xor(bi_least, bi_great) from test_i128; -- expected: -1 + select bin_xor(bi_least, bin_xor(bi_least, bi_great)) from test_i128; -- expected: 170141183460469231731687303715884105727 + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 0 + 170141183460469231731687303715884105727 + -170141183460469231731687303715884105728 + -1 + 1 + 0 + 0 + -170141183460469231731687303715884105728 + -1 + -1 + 170141183460469231731687303715884105727 + """ + +@pytest.mark.version('>=4.0') +def test_int128_binary_operations_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/datatypes/test_int128_math_functions.py b/tests/functional/datatypes/test_int128_math_functions.py new file mode 100644 index 00000000..e5f9b872 --- /dev/null +++ b/tests/functional/datatypes/test_int128_math_functions.py @@ -0,0 +1,153 @@ +#coding:utf-8 +# +# id: functional.datatypes.int128_math_functions +# title: Basic test for math functions against INT128 datatype +# decription: +# Test verifies https://github.com/FirebirdSQL/firebird/commit/57551c3bc0f348306ac10917cb4cc862886c88c5 +# (Postfix for CORE-6344 - fixed ROUND() & TRUNC()). +# +# Also it checks result of all other math functions that can be applied to boundary values of INT128 datatype. +# This .fbt is used instead of separate test for CORE-6344 in order to verify all math-functions to in one file. +# +# ::: NB ::: +# +# Some expression still can not be evaluated and produce errors - they are commented (see "deferred" here). +# See notes in http://tracker.firebirdsql.org/browse/CORE-6344 +# +# Checked on 4.0.0.2089, intermediate snapshot with timestamp: 06-jun-2020 14:05. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + recreate table test(i128_least int128 , i128_great int128); + insert into test(i128_least, i128_great) values(-170141183460469231731687303715884105728, 170141183460469231731687303715884105727); + + select i128_least / i128_great as math_division from test; + + select i128_least + i128_great as math_addition from test; + + select mod(i128_least, i128_great) as math_mod_a from test; + + select mod(i128_great, i128_least) as math_mod_b from test; + + select abs(i128_great) as math_abs from test; + + select ceil(i128_least) as math_ceil_a from test; + select ceil(i128_great) as math_ceil_b from test; + + select floor(i128_least) as math_floor_a from test; + select floor(i128_great) as math_floor_b from test; + + select log(2,i128_great) as math_log_base2 from test; -- expected: 127 (approx) + + -- wolfram: 88.02969193111305429598847942518842414558263959199830583578... + select ln(i128_great) as math_ln from test; + + + -- wolfram: 38.2308094493256117921448396300106143995575623921374319229378881916007690214721499090149518611002670672485111597704... + select log10(i128_great) as math_log_base10 from test; + + select round(i128_least,0) as math_round_a from test; + + select round(i128_great,0) as math_round_b from test; + + -- deferred, currently fails: select round(i128_least,-128) as math_round_a from test; + + select round(i128_least,-127) as math_round_c from test; + + -- deferred, currently fails: select round(i128_great, 1) as math_round_d from test; + + select round(170141183460469231731687303715884105727,0) from rdb$database; + + /* + deferred: currently these all fail: + select round(170141183460469231731687303715884105727,1) from rdb$database; + select round(-170141183460469231731687303715884105728,0) from rdb$database; + select round(-170141183460469231731687303715884105728,1) from rdb$database; + */ + + select sign(i128_least) as math_sign_a from test; + + select sign(i128_great) as math_sign_b from test; + + select sqrt(i128_great) as math_sqrt from test; + + -- fails: select trunc(i128_least, -128) from test; + select trunc(i128_least, -127) as math_trunc_a from test; + + select trunc(i128_great, 127) as math_trunc_b from test; + + -- value from wolfram: 88.7228391116729996054057115466466007136581397263585610899071975324682723837318043612609801346001720877892090831370... + select acosh(i128_great) as math_acosh from test; + + select asinh(i128_great) as math_asinh from test; + + -- wolfram: 1.570796326794896619231321691639751442092707227933441472947 + select atan(i128_great) as math_atan from test; + + -- wolfram: -0.78539816339744830961566084581987572105223108572083217401... + select atan2(i128_least, i128_great) as math_atan2 from test; + + -- wolfram: 0.947031103791698176468465227552673769940449295269499764416... + -- RETURNS WRONG RESULT! >>> select cos(i128_great) from test; + + -- 88.0296919311130542959884794251884241455826395919983058357865175229748787617621182818236719020483787865990704025160... + -- 1.7014118346046923071280032718565510658506726293419382...*10E38 -- value for exp(88.02969193111305429) in wolfram + select cast( exp(88.02969193111305429) as int128 ) as math_exp_cast_to_int128 from test; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MATH_DIVISION -1 + MATH_ADDITION -1 + MATH_MOD_A -1 + MATH_MOD_B 170141183460469231731687303715884105727 + MATH_ABS 170141183460469231731687303715884105727 + MATH_CEIL_A -170141183460469231731687303715884105728 + MATH_CEIL_B 170141183460469231731687303715884105727 + MATH_FLOOR_A -170141183460469231731687303715884105728 + MATH_FLOOR_B 170141183460469231731687303715884105727 + MATH_LOG_BASE2 127.0000000000000000000000000000000 + MATH_LN 88.02969193111305429598847942518842 + MATH_LOG_BASE10 38.23080944932561179214483963001061 + MATH_ROUND_A -170141183460469231731687303715884105728 + MATH_ROUND_B 170141183460469231731687303715884105727 + MATH_ROUND_C 0 + ROUND 170141183460469231731687303715884105727 + MATH_SIGN_A -1 + MATH_SIGN_B 1 + MATH_SQRT 13043817825332782212.34957180625251 + MATH_TRUNC_A 0 + MATH_TRUNC_B 170141183460469231731687303715884105727 + MATH_ACOSH 88.72283911167300 + MATH_ASINH 88.72283911167300 + MATH_ATAN 1.570796326794897 + MATH_ATAN2 -0.7853981633974483 + MATH_EXP_CAST_TO_INT128 170141183460468400595186318658326495232 + """ + +@pytest.mark.version('>=4.0') +def test_int128_math_functions_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/dml/__init__.py b/tests/functional/dml/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/dml/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/dml/cte/test_01.py b/tests/functional/dml/cte/test_01.py new file mode 100644 index 00000000..c46b602a --- /dev/null +++ b/tests/functional/dml/cte/test_01.py @@ -0,0 +1,87 @@ +#coding:utf-8 +# +# id: functional.dml.cte_01 +# title: test for Non-Recursive CTEs +# decription: +# --Rules for Non-Recursive CTEs : +# --Multiple table expressions can be defined in one query +# --Any clause legal in a SELECT specification is legal in table expressions +# --Table expressions can reference one another +# --References between expressions should not have loops +# --Table expressions can be used within any part of the main query or another table expression +# --The same table expression can be used more than once in the main query +# --Table expressions (as subqueries) can be used in INSERT, UPDATE and DELETE statements +# --Table expressions are legal in PSQL code +# --WITH statements can not be nested +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.dml.cte.cte_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + CREATE TABLE employee( id_employee INTEGER , prenom VARCHAR(20) ,id_department INTEGER,age INTEGER , PRIMARY KEY(id_employee)); + + CREATE TABLE department(id_department INTEGER, name VARCHAR(20)); + + INSERT INTO department(id_department, name) values(1,'service compta'); + INSERT INTO department(id_department, name) values(2,'production'); + INSERT INTO employee(id_employee, prenom,id_department,age) VALUES (1,'benoit',1 , 30 ); + INSERT INTO employee(id_employee, prenom,id_department,age) VALUES (2,'ludivine',1 , 30 ); + INSERT INTO employee(id_employee, prenom,id_department,age) VALUES (3,'michel',1 , 27 ); + INSERT INTO employee(id_employee, prenom,id_department,age) VALUES (4,'Gilbert',1 , 42 ); + INSERT INTO employee(id_employee, prenom,id_department,age) VALUES (5,'tom',2 ,23); + INSERT INTO employee(id_employee, prenom,id_department,age) VALUES (6,'jacque',2,44 ); + INSERT INTO employee(id_employee, prenom,id_department,age) VALUES (7,'justine',2,30 ); + INSERT INTO employee(id_employee, prenom,id_department,age) VALUES (8,'martine',2,31 ); +INSERT INTO employee(id_employee, prenom,id_department,age) VALUES (9,'noemie',2,39 ); + +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """WITH + repartition_by_age AS ( +SELECT age/10 as trancheage , id_department, + COUNT(1) AS nombre + FROM employee + GROUP BY age/10, id_department +) +select d.name , jeune.nombre as jeune , trentenaire.nombre as trentenaire, quarentenaire.nombre as quantenaire +from department d +left join repartition_by_age jeune +on d.id_department = jeune.id_department +and jeune.trancheage = 2 +left join repartition_by_age trentenaire +on d.id_department = trentenaire.id_department +and trentenaire.trancheage = 3 +left join repartition_by_age quarentenaire +on d.id_department = quarentenaire.id_department +and quarentenaire.trancheage = 4 ; + + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +NAME JEUNE TRENTENAIRE QUANTENAIRE +==================== ===================== ===================== ===================== +service compta 1 2 1 +production 1 3 1 + +""" + +@pytest.mark.version('>=3.0') +def test_cte_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/dml/cte/test_02.py b/tests/functional/dml/cte/test_02.py new file mode 100644 index 00000000..5a2286d7 --- /dev/null +++ b/tests/functional/dml/cte/test_02.py @@ -0,0 +1,103 @@ +#coding:utf-8 +# +# id: functional.dml.cte_02 +# title: test for Recursive CTEs +# decription: Rules for Recursive CTEs +# A recursive CTE is self-referencing (has a reference to itself) +# A recursive CTE is a UNION of recursive and non-recursive members: +# At least one non-recursive member (anchor) must be present +# Non-recursive members are placed first in the UNION +# Recursive members are separated from anchor members and from one another with UNION ALL clauses, i.e., +# non-recursive member (anchor) +# UNION [ALL | DISTINCT] +# non-recursive member (anchor) +# UNION [ALL | DISTINCT] +# non-recursive member (anchor) +# UNION ALL +# recursive member +# UNION ALL +# recursive member +# +# References between CTEs should not have loops +# Aggregates (DISTINCT, GROUP BY, HAVING) and aggregate functions (SUM, COUNT, MAX etc) are not allowed in recursive members +# A recursive member can have only one reference to itself and only in a FROM clause +# A recursive reference cannot participate in an outer join +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.dml.cte.cte_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ CREATE TABLE product( id_product INTEGER , name VARCHAR(20) ,id_type_product INTEGER, PRIMARY KEY(id_product)); + CREATE TABLE type_product(id_type_product INTEGER, name VARCHAR(20),id_sub_type INTEGER); + INSERT INTO type_product(id_type_product,name,id_sub_type) values(1,'DVD',NULL); + INSERT INTO type_product(id_type_product,name,id_sub_type) values(2,'BOOK',NULL); + INSERT INTO type_product(id_type_product,name,id_sub_type) values(3,'FILM SF',1); + INSERT INTO type_product(id_type_product,name,id_sub_type) values(4,'FILM ACTION',1); + INSERT INTO type_product(id_type_product,name,id_sub_type) values(5,'FILM ROMANCE',1); + INSERT INTO product(id_product, name,id_type_product) VALUES (1,'Harry Potter 8',3 ); + INSERT INTO product(id_product, name,id_type_product) VALUES (2,'Total Recall',3 ); + INSERT INTO product(id_product, name,id_type_product) VALUES (3,'Kingdom of Heaven',3 ); + INSERT INTO product(id_product, name,id_type_product) VALUES (4,'Desperate Housewives',5 ); + INSERT INTO product(id_product, name,id_type_product) VALUES (5,'Reign over me',5 ); + INSERT INTO product(id_product, name,id_type_product) VALUES (6,'Prison Break',4 ); + +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """WITH RECURSIVE +TYPE_PRODUCT_RECUR (id_type_product,name,father) AS +( +SELECT id_type_product ,'+ ' || name as name , id_type_product as father +FROM type_product +WHERE type_product.id_sub_type is null +UNION ALL +SELECT T.id_type_product ,' - ' || T.name , TR.id_type_product as father +FROM type_product T +JOIN TYPE_PRODUCT_RECUR TR on TR.id_type_product = T.id_sub_type +), +COUNT_BY_TYPE AS +( +SELECT P.ID_TYPE_PRODUCT,count(ID_PRODUCT) as count_p from PRODUCT P +group by P.ID_TYPE_PRODUCT +union +SELECT TP.FATHER,count(ID_PRODUCT) as count_p from +TYPE_PRODUCT_RECUR TP , PRODUCT P +where TP.ID_TYPE_PRODUCT = P.id_type_product +group by TP.FATHER +) +SELECT T.id_type_product , T.name ,C.count_p +FROM TYPE_PRODUCT_RECUR T +left join COUNT_BY_TYPE C +on C.ID_TYPE_PRODUCT = T.id_type_product; + + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +ID_TYPE_PRODUCT NAME COUNT_P +=============== ====================== ===================== + 1 + DVD 6 + 3 - FILM SF 3 + 4 - FILM ACTION 1 + 5 - FILM ROMANCE 2 + 2 + BOOK + +""" + +@pytest.mark.version('>=3.0') +def test_cte_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/dml/delete/__init__.py b/tests/functional/dml/delete/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/dml/delete/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/dml/delete/test_01.py b/tests/functional/dml/delete/test_01.py new file mode 100644 index 00000000..3982bced --- /dev/null +++ b/tests/functional/dml/delete/test_01.py @@ -0,0 +1,34 @@ +#coding:utf-8 +# +# id: functional.dml.delete.01 +# title: DELETE +# decription: +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.dml.delete.delete_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE tb(id INT); +INSERT INTO tb VALUES(10); +COMMIT;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """DELETE FROM tb; +SELECT * FROM tb;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=1.0') +def test_01_1(act_1: Action): + act_1.execute() + diff --git a/tests/functional/dml/delete/test_02.py b/tests/functional/dml/delete/test_02.py new file mode 100644 index 00000000..3e3dba08 --- /dev/null +++ b/tests/functional/dml/delete/test_02.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: functional.dml.delete.02 +# title: DELETE with WHERE +# decription: +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.dml.delete.delete_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE tb(id INT); +INSERT INTO tb VALUES(10); +INSERT INTO tb VALUES(10); +INSERT INTO tb VALUES(20); +COMMIT;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """DELETE FROM tb WHERE id>10; +SELECT * FROM tb;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ ID +============ + + 10 + 10""" + +@pytest.mark.version('>=1.0') +def test_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/dml/delete/test_03.py b/tests/functional/dml/delete/test_03.py new file mode 100644 index 00000000..8c76cd07 --- /dev/null +++ b/tests/functional/dml/delete/test_03.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: functional.dml.delete.03 +# title: DELETE from VIEW +# decription: +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.dml.delete.delete_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE tb(id INT); +CREATE VIEW test (id) AS SELECT id FROM tb; +INSERT INTO tb VALUES(10); +INSERT INTO tb VALUES(10); +INSERT INTO tb VALUES(null); +COMMIT;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """DELETE FROM test WHERE id=10; +SELECT * FROM tb;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ ID +============ + + """ + +@pytest.mark.version('>=1.0') +def test_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/dml/insert/__init__.py b/tests/functional/dml/insert/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/dml/insert/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/dml/insert/test_01.py b/tests/functional/dml/insert/test_01.py new file mode 100644 index 00000000..715a552e --- /dev/null +++ b/tests/functional/dml/insert/test_01.py @@ -0,0 +1,58 @@ +#coding:utf-8 +# +# id: functional.dml.insert.01 +# title: INSERT with Defaults +# decription: INSERT INTO
+# DEFAULT VALUES +# [RETURNING ] +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.dml.insert.insert_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE employee( prenom VARCHAR(20) default 'anonymous' , sex CHAR(1) default 'M' );""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """insert into employee DEFAULT VALUES; +commit; +SELECT * FROM EMPLOYEE; +insert into employee DEFAULT VALUES RETURNING prenom,sex; +SELECT * FROM EMPLOYEE; + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +PRENOM SEX +==================== ====== +anonymous M + + +PRENOM SEX +==================== ====== +anonymous M + + +PRENOM SEX +==================== ====== +anonymous M +anonymous M + +""" + +@pytest.mark.version('>=2.1') +def test_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/dml/join/__init__.py b/tests/functional/dml/join/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/dml/join/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/dml/join/test_01.py b/tests/functional/dml/join/test_01.py new file mode 100644 index 00000000..09ab6359 --- /dev/null +++ b/tests/functional/dml/join/test_01.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: functional.dml.join.01 +# title: NAMED COLUMNS join +# decription: ::= +#
JOIN
+# USING ( ) +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.dml.join.join_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE employee( id_employee INTEGER , prenom VARCHAR(20) ,id_department INTEGER, PRIMARY KEY(id_employee)); +CREATE TABLE department(id_department INTEGER, name VARCHAR(20)); +INSERT INTO department(id_department, name) values(1,'somme'); +INSERT INTO department(id_department, name) values(2,'pas de calais'); +INSERT INTO employee(id_employee, prenom,id_department) VALUES (1,'benoit',1 ); +INSERT INTO employee(id_employee, prenom,id_department) VALUES (2,'tom',2 );""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select employee.prenom , department.name from employee join department using (id_department);""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +PRENOM NAME +==================== ==================== +benoit somme +tom pas de calais + +""" + +@pytest.mark.version('>=2.1') +def test_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/dml/join/test_02.py b/tests/functional/dml/join/test_02.py new file mode 100644 index 00000000..bbaf6038 --- /dev/null +++ b/tests/functional/dml/join/test_02.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: functional.dml.join.02 +# title: NATURAL join +# decription: ::= +#
NATURAL JOIN
+# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.dml.join.join_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE employee( id_employee INTEGER , prenom VARCHAR(20) ,id_department INTEGER, PRIMARY KEY(id_employee)); +CREATE TABLE department(id_department INTEGER, name VARCHAR(20)); +INSERT INTO department(id_department, name) values(1,'somme'); +INSERT INTO department(id_department, name) values(2,'pas de calais'); +INSERT INTO employee(id_employee, prenom,id_department) VALUES (1,'benoit',1 ); +INSERT INTO employee(id_employee, prenom,id_department) VALUES (2,'tom',2 );""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select employee.prenom , department.name from employee natural join department;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +PRENOM NAME +==================== ==================== +benoit somme +tom pas de calais + +""" + +@pytest.mark.version('>=2.1') +def test_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/dml/merge/__init__.py b/tests/functional/dml/merge/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/dml/merge/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/dml/merge/test_01.py b/tests/functional/dml/merge/test_01.py new file mode 100644 index 00000000..53018518 --- /dev/null +++ b/tests/functional/dml/merge/test_01.py @@ -0,0 +1,62 @@ +#coding:utf-8 +# +# id: functional.dml.merge.01 +# title: Merge +# decription: +# tracker_id: CORE-815 +# min_versions: [] +# versions: 2.1 +# qmid: functional.dml.merge.merge_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE T1 (ID integer, NAME char(10), PRIMARY KEY(id)); +CREATE TABLE T2 ( ID integer, NAME char(10), PRIMARY KEY(id)); +COMMIT; +INSERT INTO T1 (ID,NAME) VALUES (1,'1NOMT1'); +INSERT INTO T1 (ID,NAME) VALUES (2,'2NOMT1'); +INSERT INTO T2 (ID,NAME) VALUES (1,'1NOMT2'); +INSERT INTO T2 (ID,NAME) VALUES (2,'2NOMT2'); +INSERT INTO T2 (ID,NAME) VALUES (3,'3NOMT2'); +COMMIT; + +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """MERGE + INTO T1 + USING (SELECT * FROM T2 WHERE id > 1) cd + ON (T1.id = cd.id) + WHEN MATCHED THEN + UPDATE SET + name = cd.name + WHEN NOT MATCHED THEN + INSERT (id, name) + VALUES (cd.id, cd.name); +COMMIT; +SELECT ID, NAME FROM T1;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID NAME +============ ========== + 1 1NOMT1 + 2 2NOMT2 + 3 3NOMT2 + +""" + +@pytest.mark.version('>=2.1') +def test_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/dml/merge/test_02.py b/tests/functional/dml/merge/test_02.py new file mode 100644 index 00000000..46df012d --- /dev/null +++ b/tests/functional/dml/merge/test_02.py @@ -0,0 +1,72 @@ +#coding:utf-8 +# +# id: functional.dml.merge.02 +# title: merge STATEMENT can have only one RETURNING after all WHEN sub-statements. +# decription: +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('-Token unknown .*', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + recreate table ta(id int primary key, x int, y int); + recreate table tb(id int primary key, x int, y int); + commit; + + -- [ 1 ] must PASS: + merge into tb t + using ta s on s.id = t.id + when NOT matched then insert values(1,2,3) ---------------- (a) + when matched then delete returning old.id, old.x, old.y --- (b) + ; + rollback; + + -- [ 2 ] must FAIL with + -- Statement failed, SQLSTATE = 42000 / ... / -Token unknown / -when + + merge into tb t + using ta s on s.id = t.id + when matched then delete returning old.id, old.x, old.y --- (b) + when NOT matched then insert values(1,2,3) ---------------- (a) + ; + + rollback; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID + X + Y + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Token unknown - line 4, column 5 + -when + """ + +@pytest.mark.version('>=3.0') +def test_02_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/dml/merge/test_03.py b/tests/functional/dml/merge/test_03.py new file mode 100644 index 00000000..bb603c53 --- /dev/null +++ b/tests/functional/dml/merge/test_03.py @@ -0,0 +1,93 @@ +#coding:utf-8 +# +# id: functional.dml.merge.03 +# title: MERGE ... RETURNING must refer either ALIAS of the table (if it is defined) or context variables OLD and NEW +# decription: +# Checked on 4.0.0.2240 +# +# tracker_id: +# min_versions: [] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('-At line .*', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + recreate table test_a(id int primary key, x int); + recreate table test_b(id int primary key, x int); + commit; + insert into test_a(id, x) values(1, 100); + insert into test_b(id, x) values(1, 100); + commit; + + --set echo on; + + -- [ 1 ] must FAIL with "SQLSTATE = 42S22 / ... / -Column unknown -TEST_B.ID" + merge into test_b t + using test_a s on s.id = t.id + when matched then + delete returning test_b.id, test_b.x + ; + + rollback; + + -- [ 2 ] must PASS: + merge into test_b t + using test_a s on s.id = t.id + when matched then + delete + returning old.id as old_id, t.x as old_t_x + ; + + rollback; + + -- [ 3 ] must PASS: + merge into test_b t + using test_a s on s.id = t.id + when matched then + update set t.id = -s.id - 1, t.x = - s.x - 1 + returning old.id as old_id, old.x as old_x, new.id as new_id, t.x as new_x + ; + + rollback; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + OLD_ID 1 + OLD_T_X 100 + + OLD_ID 1 + OLD_X 100 + NEW_ID -2 + NEW_X -101 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42S22 + Dynamic SQL Error + -SQL error code = -206 + -Column unknown + -TEST_B.ID + """ + +@pytest.mark.version('>=4.0') +def test_03_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/dml/update_or_insert/__init__.py b/tests/functional/dml/update_or_insert/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/dml/update_or_insert/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/dml/update_or_insert/test_01.py b/tests/functional/dml/update_or_insert/test_01.py new file mode 100644 index 00000000..23bf57eb --- /dev/null +++ b/tests/functional/dml/update_or_insert/test_01.py @@ -0,0 +1,48 @@ +#coding:utf-8 +# +# id: functional.dml.update_or_insert.01 +# title: UPDATE OR INSERT +# decription: Simple UPDATE OR INSERT +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.dml.update_or_insert.update_or_insert_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE TMPTEST( id INTEGER , name VARCHAR(20) , PRIMARY KEY(id));""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """UPDATE OR INSERT INTO TMPTEST(id, name) VALUES (1,'bob' ); +select name from TMPTEST where id =1; +UPDATE OR INSERT INTO TMPTEST(id, name) VALUES (1,'ivan' ); +select name from TMPTEST where id =1; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +NAME +==================== +bob + + +NAME +==================== +ivan + +""" + +@pytest.mark.version('>=2.1') +def test_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/dml/update_or_insert/test_02.py b/tests/functional/dml/update_or_insert/test_02.py new file mode 100644 index 00000000..93ef2f95 --- /dev/null +++ b/tests/functional/dml/update_or_insert/test_02.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: functional.dml.update_or_insert.02 +# title: UPDATE OR INSERT +# decription: WITH RETURNING Clause +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.dml.update_or_insert.update_or_insert_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE TMPTEST( id INTEGER , name VARCHAR(20) , PRIMARY KEY(id));""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET TERM ^ ; + +EXECUTE BLOCK +RETURNS (V integer) +AS + + BEGIN + UPDATE OR INSERT INTO TMPTEST(id, name) VALUES (1,'ivan' ) + RETURNING id INTO :V; + SUSPEND; + + END^ + + +SET TERM ; ^ +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + V +============ + 1 + +""" + +@pytest.mark.version('>=2.1') +def test_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/dml/update_or_insert/test_03.py b/tests/functional/dml/update_or_insert/test_03.py new file mode 100644 index 00000000..ddd4e8c4 --- /dev/null +++ b/tests/functional/dml/update_or_insert/test_03.py @@ -0,0 +1,60 @@ +#coding:utf-8 +# +# id: functional.dml.update_or_insert.03 +# title: UPDATE OR INSERT +# decription: MATCHING Clause +# tracker_id: +# min_versions: [] +# versions: 2.5.0 +# qmid: functional.dml.update_or_insert.update_or_insert_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE TMPTEST_NOKEY ( id INTEGER , name VARCHAR(20));""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """UPDATE OR INSERT INTO TMPTEST_NOKEY(id, name) VALUES (1,'ivan' ) +MATCHING (id); + +select name from TMPTEST_NOKEY where id =1; + +UPDATE OR INSERT INTO TMPTEST_NOKEY(id, name) VALUES (1,'bob' ) +MATCHING (id); + +select name from TMPTEST_NOKEY where id =1; + +UPDATE OR INSERT INTO TMPTEST_NOKEY(id, name) VALUES (1,'ivan' );""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +NAME +==================== +ivan + + +NAME +==================== +bob + +""" +expected_stderr_1 = """Statement failed, SQLSTATE = 22000 +Dynamic SQL Error +-Primary key required on table TMPTEST_NOKEY +""" + +@pytest.mark.version('>=2.5.0') +def test_03_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/__init__.py b/tests/functional/domain/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/domain/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/domain/alter/__init__.py b/tests/functional/domain/alter/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/domain/alter/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/domain/alter/test_01.py b/tests/functional/domain/alter/test_01.py new file mode 100644 index 00000000..38bfb278 --- /dev/null +++ b/tests/functional/domain/alter/test_01.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: functional.domain.alter_01 +# title: ALTER DOMAIN - SET DEFAULT +# decription: +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.domain.alter.alter_domain_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [('RDB\\$DEFAULT_SOURCE.*', '')] + +init_script_1 = """ + create domain test varchar(63); + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + alter domain test set default 'test string'; + commit; + set list on; + set blob all; + select rdb$field_name, rdb$default_source + from rdb$fields where rdb$field_name=upper('test'); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$FIELD_NAME TEST + RDB$DEFAULT_SOURCE 2:1e1 + default 'test string' + """ + +@pytest.mark.version('>=2.0') +def test_alter_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/alter/test_02.py b/tests/functional/domain/alter/test_02.py new file mode 100644 index 00000000..3e411dbb --- /dev/null +++ b/tests/functional/domain/alter/test_02.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: functional.domain.alter.02 +# title: ALTER DOMAIN - DROP DEFAULT +# decription: +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.domain.alter.alter_domain_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create domain test varchar(63) default 'test string'; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + alter domain test drop default; + commit; + set list on; + select rdb$field_name, rdb$default_source + from rdb$fields + where rdb$field_name = upper('test'); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$FIELD_NAME TEST + RDB$DEFAULT_SOURCE + """ + +@pytest.mark.version('>=2.0') +def test_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/alter/test_03.py b/tests/functional/domain/alter/test_03.py new file mode 100644 index 00000000..643fa4f2 --- /dev/null +++ b/tests/functional/domain/alter/test_03.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: functional.domain.alter_03 +# title: ALTER DOMAIN - ADD CONSTRAINT +# decription: +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.domain.alter.alter_domain_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [('RDB\\$VALIDATION_SOURCE.*', '')] + +init_script_1 = """ + create domain test varchar(63); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + alter domain test add constraint check (value like 'te%'); + commit; + set list on; + set blob all; + select rdb$field_name, rdb$validation_source from rdb$fields where rdb$field_name=upper('test'); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$FIELD_NAME TEST + check (value like 'te%') + """ + +@pytest.mark.version('>=2.0') +def test_alter_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/alter/test_04.py b/tests/functional/domain/alter/test_04.py new file mode 100644 index 00000000..0069ce75 --- /dev/null +++ b/tests/functional/domain/alter/test_04.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: functional.domain.alter.04 +# title: ALTER DOMAIN - DROP CONSTRAINT +# decription: +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.domain.alter.alter_domain_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create domain test varchar(63) check(value like 'te%'); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + alter domain test drop constraint; + commit; + select rdb$field_name, rdb$validation_source + from rdb$fields + where rdb$field_name = upper('test'); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$FIELD_NAME TEST + RDB$VALIDATION_SOURCE + """ + +@pytest.mark.version('>=2.0') +def test_04_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/alter/test_05.py b/tests/functional/domain/alter/test_05.py new file mode 100644 index 00000000..54c64c42 --- /dev/null +++ b/tests/functional/domain/alter/test_05.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: functional.domain.alter_05 +# title: ALTER DOMAIN - Alter domain that doesn't exists +# decription: +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.domain.alter.alter_domain_05 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE DOMAIN test VARCHAR(63);""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ALTER DOMAIN notexists DROP CONSTRAINT;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42000 +unsuccessful metadata update +-ALTER DOMAIN NOTEXISTS failed +-Domain not found + +""" + +@pytest.mark.version('>=3.0') +def test_alter_05_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/domain/create/__init__.py b/tests/functional/domain/create/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/domain/create/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/domain/create/test_01.py b/tests/functional/domain/create/test_01.py new file mode 100644 index 00000000..085f61fa --- /dev/null +++ b/tests/functional/domain/create/test_01.py @@ -0,0 +1,37 @@ +#coding:utf-8 +# +# id: functional.domain.create.01 +# title: CREATE DOMAIN - SMALLINT +# decription: Simple domain creation based SMALLINT datatype. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test SMALLINT; +SHOW DOMAIN test; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST SMALLINT Nullable +""" + +@pytest.mark.version('>=1.0') +def test_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_02.py b/tests/functional/domain/create/test_02.py new file mode 100644 index 00000000..430f5369 --- /dev/null +++ b/tests/functional/domain/create/test_02.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: functional.domain.create.02 +# title: Simple domain creation based INTEGER datatype. +# decription: Simple domain creation based INTEGER datatype. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test INTEGER; +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST INTEGER Nullable +""" + +@pytest.mark.version('>=1.0') +def test_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_03.py b/tests/functional/domain/create/test_03.py new file mode 100644 index 00000000..bcbb659a --- /dev/null +++ b/tests/functional/domain/create/test_03.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: functional.domain.create.03 +# title: CREATE DOMAIN - INT +# decription: Simple domain creation based INT datatype. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test INT; +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST INTEGER Nullable +""" + +@pytest.mark.version('>=1.0') +def test_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_04.py b/tests/functional/domain/create/test_04.py new file mode 100644 index 00000000..7eb7102a --- /dev/null +++ b/tests/functional/domain/create/test_04.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: functional.domain.create.04 +# title: CREATE DOMAIN - FLOAT +# decription: Simple domain creation based FLOAT datatype. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test FLOAT; +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST FLOAT Nullable +""" + +@pytest.mark.version('>=1.0') +def test_04_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_05.py b/tests/functional/domain/create/test_05.py new file mode 100644 index 00000000..f7645536 --- /dev/null +++ b/tests/functional/domain/create/test_05.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: functional.domain.create.05 +# title: CREATE DOMAIN - DOUBLE PRECISION +# decription: Simple domain creation based DOUBLE PRECISION datatype. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_05 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test DOUBLE PRECISION; +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST DOUBLE PRECISION Nullable +""" + +@pytest.mark.version('>=1.0') +def test_05_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_06.py b/tests/functional/domain/create/test_06.py new file mode 100644 index 00000000..ff64738f --- /dev/null +++ b/tests/functional/domain/create/test_06.py @@ -0,0 +1,37 @@ +#coding:utf-8 +# +# id: functional.domain.create.06 +# title: CREATE DOMAIN - DOUBLE PRECISION - ARRAY +# decription: Array domain creation based DOUBLE PRECISION datatype. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.domain.create.create_domain_06 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test DOUBLE PRECISION[7]; +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST ARRAY OF [7] + DOUBLE PRECISION Nullable +""" + +@pytest.mark.version('>=2.0') +def test_06_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_07.py b/tests/functional/domain/create/test_07.py new file mode 100644 index 00000000..c4059817 --- /dev/null +++ b/tests/functional/domain/create/test_07.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: functional.domain.create.07 +# title: CREATE DOMAIN - DATE +# decription: Simple domain creation based DATE datatype. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_07 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test DATE; +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST DATE Nullable +""" + +@pytest.mark.version('>=1.0') +def test_07_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_08.py b/tests/functional/domain/create/test_08.py new file mode 100644 index 00000000..2f293c75 --- /dev/null +++ b/tests/functional/domain/create/test_08.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: functional.domain.create.08 +# title: CREATE DOMAIN - TIME +# decription: Simple domain creation based TIME datatype. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_08 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test TIME; +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST TIME Nullable +""" + +@pytest.mark.version('>=1.0') +def test_08_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_09.py b/tests/functional/domain/create/test_09.py new file mode 100644 index 00000000..5f41a3d1 --- /dev/null +++ b/tests/functional/domain/create/test_09.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: functional.domain.create.09 +# title: CREATE DOMAIN - TIMESTAMP +# decription: Simple domain creation based TIMESTAMP datatype. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_09 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test TIMESTAMP; +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST TIMESTAMP Nullable +""" + +@pytest.mark.version('>=1.0') +def test_09_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_10.py b/tests/functional/domain/create/test_10.py new file mode 100644 index 00000000..38ed29c3 --- /dev/null +++ b/tests/functional/domain/create/test_10.py @@ -0,0 +1,37 @@ +#coding:utf-8 +# +# id: functional.domain.create.10 +# title: CREATE DOMAIN - TIMESTAMP ARRAY +# decription: Array domain creation based TIMESTAMP datatype. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.domain.create.create_domain_10 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test TIMESTAMP [1024]; +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST ARRAY OF [1024] + TIMESTAMP Nullable +""" + +@pytest.mark.version('>=2.0') +def test_10_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_11.py b/tests/functional/domain/create/test_11.py new file mode 100644 index 00000000..38f89b21 --- /dev/null +++ b/tests/functional/domain/create/test_11.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: functional.domain.create.11 +# title: CREATE DOMAIN - DECIMAL +# decription: Simple domain creation based DECIMAL datatype. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_11 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test DECIMAL(18,4); +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST DECIMAL(18, 4) Nullable +""" + +@pytest.mark.version('>=1.0') +def test_11_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_12.py b/tests/functional/domain/create/test_12.py new file mode 100644 index 00000000..66ba776e --- /dev/null +++ b/tests/functional/domain/create/test_12.py @@ -0,0 +1,37 @@ +#coding:utf-8 +# +# id: functional.domain.create.12 +# title: CREATE DOMAIN - DECIMAL ARRAY +# decription: Array domain creation based DECIMAL datatype. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.domain.create.create_domain_12 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test DECIMAL(18,18)[32768]; +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST ARRAY OF [32768] + DECIMAL(18, 18) Nullable +""" + +@pytest.mark.version('>=2.0') +def test_12_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_13.py b/tests/functional/domain/create/test_13.py new file mode 100644 index 00000000..9aba84f2 --- /dev/null +++ b/tests/functional/domain/create/test_13.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: functional.domain.create.13 +# title: CREATE DOMAIN - NUMERIC +# decription: Simple domain creation based on NUMERIC datatype. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_13 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test NUMERIC(18,18); +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST NUMERIC(18, 18) Nullable +""" + +@pytest.mark.version('>=1.0') +def test_13_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_14.py b/tests/functional/domain/create/test_14.py new file mode 100644 index 00000000..fc1e1a4e --- /dev/null +++ b/tests/functional/domain/create/test_14.py @@ -0,0 +1,37 @@ +#coding:utf-8 +# +# id: functional.domain.create.14 +# title: CREATE DOMAIN - NUMERIC ARRAY +# decription: Array domain creation based on NUMERIC datatype. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.domain.create.create_domain_14 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test NUMERIC(18,18)[32768]; +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST ARRAY OF [32768] + NUMERIC(18, 18) Nullable +""" + +@pytest.mark.version('>=2.0') +def test_14_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_15.py b/tests/functional/domain/create/test_15.py new file mode 100644 index 00000000..5a88e5ad --- /dev/null +++ b/tests/functional/domain/create/test_15.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: functional.domain.create.15 +# title: CREATE DOMAIN - CHAR +# decription: Simple domain creation based CHAR datatype. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_15 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test CHAR(300); +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST CHAR(300) Nullable +""" + +@pytest.mark.version('>=1.0') +def test_15_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_16.py b/tests/functional/domain/create/test_16.py new file mode 100644 index 00000000..172f4d41 --- /dev/null +++ b/tests/functional/domain/create/test_16.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: functional.domain.create.16 +# title: CREATE DOMAIN - CHARACTER +# decription: Simple domain creation based CHARACTER datatype. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_16 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test CHARACTER(32767); +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST CHAR(32767) Nullable +""" + +@pytest.mark.version('>=1.0') +def test_16_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_17.py b/tests/functional/domain/create/test_17.py new file mode 100644 index 00000000..dddbd238 --- /dev/null +++ b/tests/functional/domain/create/test_17.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: functional.domain.create.17 +# title: CREATE DOMAIN - CHARACTER VARYING +# decription: Simple domain creation based CHARACTER VARYING datatype. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_17 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test CHARACTER VARYING(1); +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST VARCHAR(1) Nullable +""" + +@pytest.mark.version('>=1.0') +def test_17_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_18.py b/tests/functional/domain/create/test_18.py new file mode 100644 index 00000000..18622db8 --- /dev/null +++ b/tests/functional/domain/create/test_18.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: functional.domain.create.18 +# title: CREATE DOMAIN - VARCHAR +# decription: Simple domain creation based VARCHAR datatype. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_18 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test VARCHAR(32765); +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST VARCHAR(32765) Nullable +""" + +@pytest.mark.version('>=1.0') +def test_18_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_19.py b/tests/functional/domain/create/test_19.py new file mode 100644 index 00000000..f0f05ad5 --- /dev/null +++ b/tests/functional/domain/create/test_19.py @@ -0,0 +1,37 @@ +#coding:utf-8 +# +# id: functional.domain.create.19 +# title: CREATE DOMAIN - VARCHAR - ARRAY +# decription: Array domain creation based on VARCHAR datatype. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.domain.create.create_domain_19 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test VARCHAR(32765)[40000]; +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST ARRAY OF [40000] + VARCHAR(32765) Nullable +""" + +@pytest.mark.version('>=2.0') +def test_19_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_20.py b/tests/functional/domain/create/test_20.py new file mode 100644 index 00000000..b8ff05fc --- /dev/null +++ b/tests/functional/domain/create/test_20.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: functional.domain.create.20 +# title: CREATE DOMAIN - VARCHAR CHARACTER SET +# decription: Domain creation based on VARCHAR datatype with CHARACTER SET specification. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_20 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test VARCHAR(32765) CHARACTER SET ASCII; +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST VARCHAR(32765) CHARACTER SET ASCII Nullable +""" + +@pytest.mark.version('>=1.0') +def test_20_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_21.py b/tests/functional/domain/create/test_21.py new file mode 100644 index 00000000..c7b61b83 --- /dev/null +++ b/tests/functional/domain/create/test_21.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: functional.domain.create.21 +# title: CREATE DOMAIN - NCHAR +# decription: Simple domain creation based on NCHAR datatype. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_21 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test NCHAR(32767); +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST CHAR(32767) CHARACTER SET ISO8859_1 Nullable +""" + +@pytest.mark.version('>=1.0') +def test_21_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_22.py b/tests/functional/domain/create/test_22.py new file mode 100644 index 00000000..03a90103 --- /dev/null +++ b/tests/functional/domain/create/test_22.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: functional.domain.create.22 +# title: CREATE DOMAIN - NATIONAL CHARACTER +# decription: Simple domain creation based on NATIONAL CHARACTER datatype. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_22 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test NATIONAL CHARACTER(32767); +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST CHAR(32767) CHARACTER SET ISO8859_1 Nullable +""" + +@pytest.mark.version('>=1.0') +def test_22_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_23.py b/tests/functional/domain/create/test_23.py new file mode 100644 index 00000000..7ddac09c --- /dev/null +++ b/tests/functional/domain/create/test_23.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: functional.domain.create.23 +# title: CREATE DOMAIN - NATIONAL CHAR +# decription: Simple domain creation based on NATIONAL CHAR datatype. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_23 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test NATIONAL CHAR(32767); +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST CHAR(32767) CHARACTER SET ISO8859_1 Nullable +""" + +@pytest.mark.version('>=1.0') +def test_23_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_24.py b/tests/functional/domain/create/test_24.py new file mode 100644 index 00000000..e0227521 --- /dev/null +++ b/tests/functional/domain/create/test_24.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: functional.domain.create.24 +# title: CREATE DOMAIN - NATIONAL CHAR VARYING +# decription: Simple domain creation based on NATIONAL CHAR VARYING datatype. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_24 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test NATIONAL CHAR VARYING(32765); +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST VARCHAR(32765) CHARACTER SET ISO8859_1 Nullable +""" + +@pytest.mark.version('>=1.0') +def test_24_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_25.py b/tests/functional/domain/create/test_25.py new file mode 100644 index 00000000..ec3f8bf0 --- /dev/null +++ b/tests/functional/domain/create/test_25.py @@ -0,0 +1,37 @@ +#coding:utf-8 +# +# id: functional.domain.create.25 +# title: CREATE DOMAIN - NATIONAL CHAR VARYING ARRAY +# decription: Array domain creation based on NATIONAL CHAR VARYING datatype. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.domain.create.create_domain_25 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test NATIONAL CHAR VARYING(32765) [30,30,30]; +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST ARRAY OF [30, 30, 30] + VARCHAR(32765) CHARACTER SET ISO8859_1 Nullable +""" + +@pytest.mark.version('>=2.0') +def test_25_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_26.py b/tests/functional/domain/create/test_26.py new file mode 100644 index 00000000..21daac9b --- /dev/null +++ b/tests/functional/domain/create/test_26.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: functional.domain.create.26 +# title: CREATE DOMAIN - BLOB +# decription: Simple domain creation based on BLOB datatype. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.domain.create.create_domain_26 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test BLOB; +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST BLOB segment 80, subtype BINARY Nullable +""" + +@pytest.mark.version('>=2.0') +def test_26_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_27.py b/tests/functional/domain/create/test_27.py new file mode 100644 index 00000000..97bce7da --- /dev/null +++ b/tests/functional/domain/create/test_27.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: functional.domain.create.27 +# title: CREATE DOMAIN - BLOB SUB TYPE +# decription: Domain creation based on BLOB datatype with SUBTYPE specification. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_27 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test BLOB SUB_TYPE 1; +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST BLOB segment 80, subtype TEXT Nullable +""" + +@pytest.mark.version('>=1.0') +def test_27_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_28.py b/tests/functional/domain/create/test_28.py new file mode 100644 index 00000000..9f0f5288 --- /dev/null +++ b/tests/functional/domain/create/test_28.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: functional.domain.create.28 +# title: CREATE DOMAIN - BLOB SUB TYPE TEXT +# decription: Domain creation based on BLOB datatype with SUBTYPE TEXT specification. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_28 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test BLOB SUB_TYPE TEXT; +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST BLOB segment 80, subtype TEXT Nullable +""" + +@pytest.mark.version('>=1.0') +def test_28_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_29.py b/tests/functional/domain/create/test_29.py new file mode 100644 index 00000000..33a05eb9 --- /dev/null +++ b/tests/functional/domain/create/test_29.py @@ -0,0 +1,35 @@ +#coding:utf-8 +# +# id: functional.domain.create.29 +# title: CREATE DOMAIN - BLOB SEGMENT SIZE +# decription: Domain creation based on BLOB datatype with SEGMENT SIZE specification. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.domain.create.create_domain_29 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test BLOB SEGMENT SIZE 244; +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST BLOB segment 244, subtype BINARY Nullable""" + +@pytest.mark.version('>=2.0') +def test_29_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_30.py b/tests/functional/domain/create/test_30.py new file mode 100644 index 00000000..d10db6b0 --- /dev/null +++ b/tests/functional/domain/create/test_30.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: functional.domain.create.30 +# title: CREATE DOMAIN - BLOB SUB_TYPE CHARACTER SET +# decription: Domain creation based on BLOB datatype with SUBTYPE TEXT and CHARACTER SET specification. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_30 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test BLOB SUB_TYPE 1 CHARACTER SET BIG_5; +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST BLOB segment 80, subtype TEXT CHARACTER SET BIG_5 Nullable +""" + +@pytest.mark.version('>=1.0') +def test_30_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_31.py b/tests/functional/domain/create/test_31.py new file mode 100644 index 00000000..afaec201 --- /dev/null +++ b/tests/functional/domain/create/test_31.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: functional.domain.create.31 +# title: CREATE DOMAIN - BLOB (seglen,subtype) +# decription: Domain creation based on BLOB datatype with seglen-subtype specification. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_31 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test BLOB(349,1); +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST BLOB segment 349, subtype TEXT Nullable +""" + +@pytest.mark.version('>=1.0') +def test_31_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_32.py b/tests/functional/domain/create/test_32.py new file mode 100644 index 00000000..25220606 --- /dev/null +++ b/tests/functional/domain/create/test_32.py @@ -0,0 +1,37 @@ +#coding:utf-8 +# +# id: functional.domain.create.32 +# title: CREATE DOMAIN - DEFAULT literal +# decription: Domain creation based on VARCHAR datatype with literal DEFAULT specification. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_32 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test VARCHAR(32) DEFAULT 'def_value'; +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST VARCHAR(32) Nullable + DEFAULT 'def_value' +""" + +@pytest.mark.version('>=1.0') +def test_32_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_33.py b/tests/functional/domain/create/test_33.py new file mode 100644 index 00000000..772f73bf --- /dev/null +++ b/tests/functional/domain/create/test_33.py @@ -0,0 +1,37 @@ +#coding:utf-8 +# +# id: functional.domain.create.33 +# title: CREATE DOMAIN - DEFAULT NULL +# decription: Domain creation based on VARCHAR datatype with NULL DEFAULT specification. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_33 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test VARCHAR(32) DEFAULT NULL; +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST VARCHAR(32) Nullable + DEFAULT NULL +""" + +@pytest.mark.version('>=1.0') +def test_33_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_34.py b/tests/functional/domain/create/test_34.py new file mode 100644 index 00000000..0911d16e --- /dev/null +++ b/tests/functional/domain/create/test_34.py @@ -0,0 +1,37 @@ +#coding:utf-8 +# +# id: functional.domain.create.34 +# title: CREATE DOMAIN - DEFAULT USER +# decription: Domain creation based on VARCHAR datatype with USER DEFAULT specification. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_34 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test VARCHAR(32) DEFAULT USER; +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST VARCHAR(32) Nullable + DEFAULT USER +""" + +@pytest.mark.version('>=1.0') +def test_34_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_35.py b/tests/functional/domain/create/test_35.py new file mode 100644 index 00000000..796ea714 --- /dev/null +++ b/tests/functional/domain/create/test_35.py @@ -0,0 +1,37 @@ +#coding:utf-8 +# +# id: functional.domain.create.35 +# title: CREATE DOMAIN - DEFAULT CURRENT_USER +# decription: Domain creation based on VARCHAR datatype with CURRENT_USER DEFAULT specification. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_35 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test VARCHAR(32) DEFAULT CURRENT_USER; +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST VARCHAR(32) Nullable + DEFAULT CURRENT_USER +""" + +@pytest.mark.version('>=1.0') +def test_35_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_36.py b/tests/functional/domain/create/test_36.py new file mode 100644 index 00000000..7e08682d --- /dev/null +++ b/tests/functional/domain/create/test_36.py @@ -0,0 +1,37 @@ +#coding:utf-8 +# +# id: functional.domain.create.36 +# title: CREATE DOMAIN - DEFAULT CURRENT_ROLE +# decription: Domain creation based on VARCHAR datatype with CURRENT_ROLE DEFAULT specification. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_36 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test VARCHAR(32) DEFAULT CURRENT_ROLE; +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST VARCHAR(32) Nullable + DEFAULT CURRENT_ROLE +""" + +@pytest.mark.version('>=1.0') +def test_36_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_37.py b/tests/functional/domain/create/test_37.py new file mode 100644 index 00000000..63750890 --- /dev/null +++ b/tests/functional/domain/create/test_37.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: functional.domain.create.37 +# title: CREATE DOMAIN - NOT NULL +# decription: Domain creation based on VARCHAR datatype with NOT NULL specification. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_37 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test VARCHAR(32) NOT NULL; +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST VARCHAR(32) Not Null +""" + +@pytest.mark.version('>=1.0') +def test_37_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_38.py b/tests/functional/domain/create/test_38.py new file mode 100644 index 00000000..2290a848 --- /dev/null +++ b/tests/functional/domain/create/test_38.py @@ -0,0 +1,37 @@ +#coding:utf-8 +# +# id: functional.domain.create.38 +# title: CREATE DOMAIN - CHECK +# decription: Domain creation based on VARCHAR datatype with CHECK specification. +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.create.create_domain_38 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test VARCHAR(32) CHECK(VALUE LIKE 'ER%'); +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST VARCHAR(32) Nullable + CHECK(VALUE LIKE 'ER%') +""" + +@pytest.mark.version('>=1.0') +def test_38_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_39.py b/tests/functional/domain/create/test_39.py new file mode 100644 index 00000000..64b7a71c --- /dev/null +++ b/tests/functional/domain/create/test_39.py @@ -0,0 +1,36 @@ +#coding:utf-8 +# +# id: functional.domain.create.39 +# title: CREATE DOMAIN - COLLATE +# decription: Domain creation based on VARCHAR datatype with COLLATE specification. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.domain.create.create_domain_39 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test VARCHAR(32) CHARACTER SET DOS437 COLLATE DB_ITA437; +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST VARCHAR(32) CHARACTER SET DOS437 Nullable + COLLATE DB_ITA437""" + +@pytest.mark.version('>=2.0') +def test_39_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_40.py b/tests/functional/domain/create/test_40.py new file mode 100644 index 00000000..dce448a4 --- /dev/null +++ b/tests/functional/domain/create/test_40.py @@ -0,0 +1,38 @@ +#coding:utf-8 +# +# id: functional.domain.create.40 +# title: CREATE DOMAIN - all options +# decription: Domain creation based on VARCHAR datatype with all possible options. +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.domain.create.create_domain_40 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test AS VARCHAR(32) CHARACTER SET DOS437 DEFAULT USER NOT NULL CHECK(VALUE LIKE 'ER%') COLLATE DB_ITA437; +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST VARCHAR(32) CHARACTER SET DOS437 Not Null + DEFAULT USER + CHECK(VALUE LIKE 'ER%') + COLLATE DB_ITA437""" + +@pytest.mark.version('>=2.0') +def test_40_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/create/test_41.py b/tests/functional/domain/create/test_41.py new file mode 100644 index 00000000..50cd6283 --- /dev/null +++ b/tests/functional/domain/create/test_41.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: functional.domain.create_41 +# title: CREATE DOMAIN - create two domain with same name +# decription: The creation of already existing domain must fail (SQLCODE -607). +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.domain.create.create_domain_41 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE DOMAIN test AS INTEGER;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN test AS VARCHAR(32);""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 23000 +unsuccessful metadata update +-CREATE DOMAIN TEST failed +-violation of PRIMARY or UNIQUE KEY constraint "RDB$INDEX_2" on table "RDB$FIELDS" +-Problematic key value is ("RDB$FIELD_NAME" = 'TEST') +""" + +@pytest.mark.version('>=3.0') +def test_create_41_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/domain/create/test_42.py b/tests/functional/domain/create/test_42.py new file mode 100644 index 00000000..3fbeb0d6 --- /dev/null +++ b/tests/functional/domain/create/test_42.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: functional.domain.create.42 +# title: CREATE DOMAIN - domain name equal to existing datatype +# decription: Domain creation must fail (SQLCODE -104) if domain name is equal to datatype name. +# tracker_id: +# min_versions: [] +# versions: 2.5.0 +# qmid: functional.domain.create.create_domain_42 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DOMAIN INT AS VARCHAR(32);""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42000 + +Dynamic SQL Error +-SQL error code = -104 +-Token unknown - line 1, column 15 +-INT +""" + +@pytest.mark.version('>=2.5.0') +def test_42_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/domain/create/test_54.py b/tests/functional/domain/create/test_54.py new file mode 100644 index 00000000..d1c61c66 --- /dev/null +++ b/tests/functional/domain/create/test_54.py @@ -0,0 +1,55 @@ +#coding:utf-8 +# +# id: functional.domain.create.54 +# title: Use of domains for Trigger/SP variable definition +# decription: Allow domains to be applied to variables and in/out +# parameters within a trigger or SP +# tracker_id: CORE-660 +# min_versions: [] +# versions: 2.1 +# qmid: functional.domain.create.create_domain_54 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """create domain d as integer; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """set term !!; +create procedure sp (i type of d) returns (o type of d) +as + declare variable v type of d; +begin + v = cast(v as type of d); +end!! +commit!! +set term ;!! +show procedure sp;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Procedure text: +============================================================================= + declare variable v type of d; +begin + v = cast(v as type of d); +end +============================================================================= +Parameters: +I INPUT (TYPE OF D) INTEGER +O OUTPUT (TYPE OF D) INTEGER +""" + +@pytest.mark.version('>=2.1') +def test_54_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/domain/drop/__init__.py b/tests/functional/domain/drop/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/domain/drop/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/domain/drop/test_01.py b/tests/functional/domain/drop/test_01.py new file mode 100644 index 00000000..9726d2c3 --- /dev/null +++ b/tests/functional/domain/drop/test_01.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: functional.domain.drop.01 +# title: DROP DOMAIN +# decription: DROP DOMAIN +# +# Dependencies: +# CREATE DATABASE +# CREATE DOMAIN +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.domain.drop.drop_domain_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE DOMAIN test SMALLINT;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """DROP DOMAIN test; +SHOW DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """There is no domain TEST in this database""" + +@pytest.mark.version('>=1.0') +def test_01_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/domain/drop/test_02.py b/tests/functional/domain/drop/test_02.py new file mode 100644 index 00000000..421640da --- /dev/null +++ b/tests/functional/domain/drop/test_02.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: functional.domain.drop_02 +# title: DROP DOMAIN - in use +# decription: DROP DOMAIN - that was use +# +# Dependencies: +# CREATE DATABASE +# CREATE DOMAIN +# CREATE TABLE +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.domain.drop.drop_domain_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE DOMAIN test SMALLINT; +CREATE TABLE tb( id test);""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """DROP DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42000 +unsuccessful metadata update +-DROP DOMAIN TEST failed +-Domain TEST is used in table TB (local name ID) and cannot be dropped + +""" + +@pytest.mark.version('>=3.0') +def test_drop_02_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/domain/drop/test_03.py b/tests/functional/domain/drop/test_03.py new file mode 100644 index 00000000..cb0277de --- /dev/null +++ b/tests/functional/domain/drop/test_03.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: functional.domain.drop_03 +# title: DROP DOMAIN - that doesn't exists +# decription: DROP DOMAIN - that doesn't exists +# Note:Bad error message (should be like "Domain TEST not exists") +# +# Dependencies: +# CREATE DATABASE +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.domain.drop.drop_domain_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """DROP DOMAIN test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42000 +unsuccessful metadata update +-DROP DOMAIN TEST failed +-Domain not found + +""" + +@pytest.mark.version('>=3.0') +def test_drop_03_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/exception/__init__.py b/tests/functional/exception/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/exception/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/exception/alter/__init__.py b/tests/functional/exception/alter/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/exception/alter/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/exception/alter/test_01.py b/tests/functional/exception/alter/test_01.py new file mode 100644 index 00000000..5654a7b4 --- /dev/null +++ b/tests/functional/exception/alter/test_01.py @@ -0,0 +1,58 @@ +#coding:utf-8 +# +# id: functional.exception.alter.01 +# title: ALTER EXCEPTION +# decription: ALTER EXCEPTION +# +# Dependencies: +# CREATE DATABASE +# CREATE EXCEPTION +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.exception.alter.alter_exception_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create exception test 'message to show'; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + alter exception test 'new message'; + commit; + + set list on; + set width exc_name 31; + set width exc_msg 80; + select + e.rdb$exception_name exc_name + ,e.rdb$exception_number exc_number + ,e.rdb$message exc_msg + from rdb$exceptions e; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + EXC_NAME TEST + EXC_NUMBER 1 + EXC_MSG new message + """ + +@pytest.mark.version('>=2.0') +def test_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/exception/create/__init__.py b/tests/functional/exception/create/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/exception/create/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/exception/create/test_01.py b/tests/functional/exception/create/test_01.py new file mode 100644 index 00000000..7b8ada12 --- /dev/null +++ b/tests/functional/exception/create/test_01.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: functional.exception.create.01 +# title: CREATE EXCEPTION +# decription: CREATE EXCEPTION +# +# Dependencies: +# CREATE DATABASE +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.exception.create.create_exception_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create exception test 'message to show'; + commit; + + set list on; + set width exc_name 31; + set width exc_msg 80; + select + e.rdb$exception_name exc_name + ,e.rdb$exception_number exc_number + ,e.rdb$message exc_msg + from rdb$exceptions e; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + EXC_NAME TEST + EXC_NUMBER 1 + EXC_MSG message to show + """ + +@pytest.mark.version('>=2.0') +def test_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/exception/create/test_02.py b/tests/functional/exception/create/test_02.py new file mode 100644 index 00000000..62004156 --- /dev/null +++ b/tests/functional/exception/create/test_02.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: functional.exception.create_02 +# title: CREATE EXCEPTION - try create Exception with the same name +# decription: CREATE EXCEPTION - try create Exception with the same name +# +# Dependencies: +# CREATE DATABASE +# CREATE EXCEPTION +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.exception.create.create_exception_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE EXCEPTION test 'A1'; +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE EXCEPTION test 'message to show';""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42000 +unsuccessful metadata update +-CREATE EXCEPTION TEST failed +-Exception TEST already exists + +""" + +@pytest.mark.version('>=3.0') +def test_create_02_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/exception/create/test_03.py b/tests/functional/exception/create/test_03.py new file mode 100644 index 00000000..90012dd5 --- /dev/null +++ b/tests/functional/exception/create/test_03.py @@ -0,0 +1,114 @@ +#coding:utf-8 +# +# id: functional.exception.create_03 +# title: CREATE EXCEPTION - too long message +# decription: CREATE EXCEPTION - too long message +# +# Dependencies: +# CREATE DATABASE +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.exception.create.create_exception_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('-At block line: [\\d]+, col: [\\d]+', '-At block line')] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set autoddl off; + commit; + + -- Updated 23-oct-2015: try to create in the SAME transaction exceptions with too long message and correct message (reduce its length with 1) + -- after statement fails. Do that using both ascii and non-ascii characters in these exceptions messages. + -- Expected result: no errors should occur on commit, exceptions should work fine. Taken from eqc ticket #12062. + -- 13.06.2016: replaced 'show exception' with regular select from rdb$exception: output of SHOW commands + -- is volatile in unstable FB versions. + + create exception boo_ascii + 'FOO!BAR!abcdefghijklmnoprstu012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345' + ; + + create exception boo_ascii + 'FOOBAR!abcdefghijklmnoprstu012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345' + ; + + + create exception boo_utf8 + '32ηΣημείωσηΣημείωσηΣημεσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωση' + ; + + create exception boo_utf8 + '3ηΣημείωσηΣημείωσηΣημεσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωση' + ; + + commit; + + set list on; + select rdb$exception_name, rdb$message from rdb$exceptions; + + set term ^; + execute block as + begin + exception boo_ascii; + end + ^ + + execute block as + begin + exception boo_utf8; + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$EXCEPTION_NAME BOO_ASCII + RDB$MESSAGE FOOBAR!abcdefghijklmnoprstu012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345 + + RDB$EXCEPTION_NAME BOO_UTF8 + RDB$MESSAGE 3ηΣημείωσηΣημείωσηΣημεσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωση + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE EXCEPTION BOO_ASCII failed + -Name longer than database column size + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE EXCEPTION BOO_UTF8 failed + -Name longer than database column size + + Statement failed, SQLSTATE = HY000 + exception 1 + -BOO_ASCII + -FOOBAR!abcdefghijklmnoprstu01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901... + -At block line: 3, col: 7 + + Statement failed, SQLSTATE = HY000 + exception 2 + -BOO_UTF8 + -3ηΣημείωσηΣημείωσηΣημεσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείωσηΣημείω... + -At block line: 3, col: 7 + """ + +@pytest.mark.version('>=3.0') +def test_create_03_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/exception/drop/__init__.py b/tests/functional/exception/drop/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/exception/drop/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/exception/drop/test_01.py b/tests/functional/exception/drop/test_01.py new file mode 100644 index 00000000..c43e2775 --- /dev/null +++ b/tests/functional/exception/drop/test_01.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: functional.exception.drop.01 +# title: DROP EXCEPTION +# decription: DROP EXCEPTION +# +# Dependencies: +# CREATE DATABASE +# CREATE EXCEPTION +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.exception.drop.drop_exception_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE EXCEPTION test 'message to show'; +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """DROP EXCEPTION test; +SHOW EXCEPTION test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """There is no exception TEST in this database""" + +@pytest.mark.version('>=1.0') +def test_01_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/exception/drop/test_02.py b/tests/functional/exception/drop/test_02.py new file mode 100644 index 00000000..ee6dbc0e --- /dev/null +++ b/tests/functional/exception/drop/test_02.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: functional.exception.drop.02 +# title: DROP EXCEPTION +# decription: Create exception and SP that uses it. Then try to drop exception - this attempt must FAIL. +# tracker_id: +# min_versions: [] +# versions: 2.5.0 +# qmid: functional.exception.drop.drop_exception_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create exception exc_test 'message to show'; + commit; + set term ^; + create procedure sp_test as + begin + exception exc_test; + end ^ + set term ;^ + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + drop exception exc_test; + commit; + set list on; + set count on; + select e.rdb$exception_name, d.rdb$dependent_name + from rdb$exceptions e join rdb$dependencies d on e.rdb$exception_name = d.rdb$depended_on_name + where e.rdb$exception_name = upper('exc_test'); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$EXCEPTION_NAME EXC_TEST + RDB$DEPENDENT_NAME SP_TEST + Records affected: 1 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -EXCEPTION EXC_TEST + -there are 1 dependencies + """ + +@pytest.mark.version('>=2.5.0') +def test_02_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/exception/drop/test_03.py b/tests/functional/exception/drop/test_03.py new file mode 100644 index 00000000..27c0004f --- /dev/null +++ b/tests/functional/exception/drop/test_03.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: functional.exception.drop_03 +# title: DROP EXCEPTION - that doesn't exists +# decription: DROP EXCEPTION - that doesn't exists +# +# Dependencies: +# CREATE DATABASE +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.exception.drop.drop_exception_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """DROP EXCEPTION test; +SHOW EXCEPTION test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42000 +unsuccessful metadata update +-DROP EXCEPTION TEST failed +-Exception not found +There is no exception TEST in this database + +""" + +@pytest.mark.version('>=3.0') +def test_drop_03_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/exception/test_handling_name_and_message.py b/tests/functional/exception/test_handling_name_and_message.py new file mode 100644 index 00000000..c0e2fad0 --- /dev/null +++ b/tests/functional/exception/test_handling_name_and_message.py @@ -0,0 +1,173 @@ +#coding:utf-8 +# +# id: functional.exception.handling_name_and_message +# title: Context variables EXCEPTION and ERROR_MESSAGE for ability to log exception info (including call stack!) on server side +# decription: +# Testing new built-in context variables for exception handling (appearance: 06-sep-2016 21:12, 4.0 only): +# * 'exception' -- returns name of the active user-defined exception; +# * 'error_message' -- returns interpreted text for the active exception. +# See: https://github.com/FirebirdSQL/firebird/commit/ebd0d3c8133c62b5359100de5f1eec541e43da3b +# Explanation: doc\\sql.extensions\\README.context_variables +# +# GOOD NEWS: +# call stack now can be logged on database without calling of mon$ tables, +# simple by parsing 'error_message' content (part that follows by last newline character). +# +# WARNING-1. +# This test intentionally creates exception with non-ascii name and parametrized non-ascii message text. +# Length of exception *NAME* can be up to 63 non-ascii characters, but upper bound for length of exception +# *MESSAGE* is limited to 1023 *bytes* (NOT chars!) ==> it's max length for two-byte encoding (win1251 etc) +# will be usually much less, about 500...600 characters. This limit can not be overpassed nowadays. +# For database with default cset = utf8 table rdb$exception will have following DDL: +# RDB$EXCEPTION_NAME (RDB$EXCEPTION_NAME) CHAR(63) Nullable +# RDB$MESSAGE (RDB$MESSAGE) VARCHAR(1023) CHARACTER SET NONE Nullable +# Checked on 4.0.0.366 +# +# WARNING-2. +# It seems that handling of message with length = 1023 bytes (i.e. exactly upper limit) works wrong. +# Waiting for reply from dimitr, letter 09-sep-2016 18:27. +# +# ### NOTE ### 07.12.2016 +# 'exception' and 'error_message' context variables were replaced with calls RDB$ERROR(EXCEPTION) and RDB$ERROR(MESSAGE) +# (letter from dimitr, 06.12.2016 21:44; seems that this was done in 4.0.0.461, between 02-dec-2016 and 04-dec-2016) +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('line:\\s[0-9]+,', 'line: x'), ('col:\\s[0-9]+', 'col: y')] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate exception "Что-то неправильно со складом" 'Остаток стал отрицательным: @1'; + + /* + + This will be added after trouble with length = 1023 characters will be solved (TODO after): + + recreate exception "ЙцуКенгШщзХъЭждЛорПавЫфЯчсмиТьбЮЪхЗщШШГнЕкУцЙФывААпрОолДжЭЭюБьТ" + '*Лев Николаевич Толстой * *Анна Каренина * /Мне отмщение, и аз воздам/ *ЧАСТЬ ПЕРВАЯ* *I * + Все счастливые семьи похожи друг на друга, каждая несчастливая + семья несчастлива по-своему. + Все смешалось в доме Облонских. Жена узнала, что муж был в связи + с бывшею в их доме француженкою-гувернанткой, и объявила мужу, что + не может жить с ним в одном доме. Положение это продолжалось уже + третий день и мучительно чувствовалось и самими супругами, и всеми + членами семьи, и домочадцами. Все члены семьи и домочадцы + чувствовали, что нет смысла в их сожительстве и что на каждом + п1 + '; + */ + + recreate table log_user_trouble( + e_declared_name varchar(63) character set utf8, + e_detailed_text varchar(2000) character set utf8 + ); + + set term ^; + create or alter procedure sp_log_user_trouble( + e_declared_name varchar(63) character set utf8, + e_detailed_text varchar(2000) character set utf8 + ) as + begin + in autonomous transaction do + insert into log_user_trouble(e_declared_name, e_detailed_text) values(:e_declared_name, :e_detailed_text); + end + ^ + set term ;^ + commit; + + set list on; + + /* + show table rdb$exceptions; + select + rdb$exception_name, + char_length(trim(rdb$exception_name)) exc_name_char_len, + octet_length(trim(rdb$exception_name)) exc_name_octt_len, + char_length(rdb$message) detailed_text_char_len, + octet_length(rdb$message) detailed_text_octt_len + from rdb$exceptions; + --*/ + + -- RDB$ERROR(GDSCODE|SQLCODE|SQLSTATE|EXCEPTION|MESSAGE) + set term ^; + create or alter procedure sp_check_amount(a_new_qty int) as + begin + begin + if (a_new_qty < 0) then + exception "Что-то неправильно со складом" using( a_new_qty ); + --exception "ЙцуКенгШщзХъЭждЛорПавЫфЯчсмиТьбЮЪхЗщШШГнЕкУцЙФывААпрОолДжЭЭюБьТ"; -- malformed string + + when any do + if ( RDB$ERROR(EXCEPTION) is not null) then + -- before 4.0.0.462 (04.12.2016): execute procedure sp_log_user_trouble(exception, error_message); + execute procedure sp_log_user_trouble( RDB$ERROR(EXCEPTION), RDB$ERROR(MESSAGE) ); + else + exception; + + end + + end + ^ + + create or alter procedure sp_run_write_off(a_new_qty int) as + declare old_qty int = 1; + declare new_qty int; + begin + new_qty = old_qty - a_new_qty; + execute procedure sp_check_amount( new_qty ); + end + ^ + + create or alter procedure "главная точка входа" as + begin + execute procedure sp_run_write_off(9); + end + ^ + set term ;^ + commit; + + set term ^; + execute block as + begin + execute procedure "главная точка входа"; + end + ^ + set term ;^ + commit; + + set count on; + select * from log_user_trouble; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + E_DECLARED_NAME Что-то неправильно со складом + E_DETAILED_TEXT exception 1 + Что-то неправильно со складом + Остаток стал отрицательным: -8 + At procedure 'SP_CHECK_AMOUNT' line: x col: y + At procedure 'SP_RUN_WRITE_OFF' line: x col: y + At procedure 'главная точка входа' line: x col: y + At block line: x col: y + Records affected: 1 + """ + +@pytest.mark.version('>=4.0') +def test_handling_name_and_message_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/fkey/__init__.py b/tests/functional/fkey/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/fkey/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/fkey/primary/__init__.py b/tests/functional/fkey/primary/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/fkey/primary/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/fkey/primary/test_insert_pk_01.py b/tests/functional/fkey/primary/test_insert_pk_01.py new file mode 100644 index 00000000..a09874e2 --- /dev/null +++ b/tests/functional/fkey/primary/test_insert_pk_01.py @@ -0,0 +1,79 @@ +#coding:utf-8 +# +# id: functional.fkey.primary.insert_pk_01 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master transaction doesn't modify primary key. +# Detail transaction inserts record in detail_table. +# Expected: no errors +# tracker_id: +# min_versions: [] +# versions: 2.5 +# qmid: functional.fkey.primary.ins_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (ID); +COMMIT; +INSERT INTO MASTER_TABLE (ID, INT_F) VALUES (1, 10); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# +# db_conn.begin(tpb=TPB_master) +# c = db_conn.cursor() +# c.execute("update master_table set int_f = 10 WHERE ID=1") +# +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# c = con_detail.cursor() +# c.execute("INSERT INTO DETAIL_TABLE (ID, FKEY) VALUES (1,1)") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_insert_pk_01_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/primary/test_insert_pk_02.py b/tests/functional/fkey/primary/test_insert_pk_02.py new file mode 100644 index 00000000..cc6394a6 --- /dev/null +++ b/tests/functional/fkey/primary/test_insert_pk_02.py @@ -0,0 +1,85 @@ +#coding:utf-8 +# +# id: functional.fkey.primary.insert_pk_02 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master transaction modifies primary key. +# Detail transaction inserts record in detail_table. +# Expected: error - primary key in master table has been changed +# tracker_id: +# min_versions: [] +# versions: 2.5.3 +# qmid: functional.fkey.primary.ins_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (ID); +COMMIT; +INSERT INTO MASTER_TABLE (ID, INT_F) VALUES (1, 10); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# +# db_conn.begin(tpb=TPB_master) +# c = db_conn.cursor() +# c.execute("uPDATE MASTER_TABLE SET ID = 2 WHERE ID=1") +# +# #Create second connection - update detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# c = con_detail.cursor() +# c.execute("INSERT INTO DETAIL_TABLE (ID, FKEY) VALUES (1,1)") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Error while executing SQL statement: +- SQLCODE: -530 +- violation of FOREIGN KEY constraint "FK_DETAIL_TABLE" on table "DETAIL_TABLE" +- Foreign key reference target does not exist +- Problematic key value is ("FKEY" = 1) +""" + +@pytest.mark.version('>=2.5.3') +@pytest.mark.xfail +def test_insert_pk_02_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/primary/test_insert_pk_03.py b/tests/functional/fkey/primary/test_insert_pk_03.py new file mode 100644 index 00000000..b98fae3e --- /dev/null +++ b/tests/functional/fkey/primary/test_insert_pk_03.py @@ -0,0 +1,93 @@ +#coding:utf-8 +# +# id: functional.fkey.primary.insert_pk_03 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master transaction: +# 1) modifies non key field +# 2) create savepoint +# 3) modifies primary key +# 4) rollback to savepoint +# Detail transaction inserts record in detail_table. +# Expected: error - primary key has been changed +# tracker_id: +# min_versions: [] +# versions: 2.5.3 +# qmid: functional.fkey.primary.ins_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (ID); +COMMIT; +INSERT INTO MASTER_TABLE (ID, INT_F) VALUES (1, 10); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# +# +# db_conn.begin(tpb=TPB_master) +# cm_1 = db_conn.cursor() +# cm_1.execute('UPDATE MASTER_TABLE SET INT_F=2') +# db_conn.savepoint('A') +# cm_1.execute('UPDATE MASTER_TABLE SET ID=2 WHERE ID=1') +# db_conn.rollback(savepoint='A') +# +# #Create second connection - update detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# cd = con_detail.cursor() +# cd.execute("INSERT INTO DETAIL_TABLE (ID, FKEY) VALUES (1,1)") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Error while executing SQL statement: +- SQLCODE: -530 +- violation of FOREIGN KEY constraint "FK_DETAIL_TABLE" on table "DETAIL_TABLE" +- Foreign key reference target does not exist +- Problematic key value is ("FKEY" = 1) +""" + +@pytest.mark.version('>=2.5.3') +@pytest.mark.xfail +def test_insert_pk_03_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/primary/test_insert_pk_04.py b/tests/functional/fkey/primary/test_insert_pk_04.py new file mode 100644 index 00000000..c1572bd5 --- /dev/null +++ b/tests/functional/fkey/primary/test_insert_pk_04.py @@ -0,0 +1,93 @@ +#coding:utf-8 +# +# id: functional.fkey.primary.insert_pk_04 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master transaction: +# 1) modifies primary key +# 2) create savepoint +# 3) modifies non key field +# 4) rollback to savepoint +# Detail transaction inserts record in detail_table. +# Expected: error because key field in master_table was changed +# tracker_id: +# min_versions: [] +# versions: 2.5.3 +# qmid: functional.fkey.primary.ins_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (ID); +COMMIT; +INSERT INTO MASTER_TABLE (ID, INT_F) VALUES (1, 10); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# +# +# db_conn.begin(tpb=TPB_master) +# cm_1 = db_conn.cursor() +# cm_1.execute('UPDATE MASTER_TABLE SET ID=2 WHERE ID=1') +# db_conn.savepoint('A') +# cm_1.execute('UPDATE MASTER_TABLE SET INT_F=2 ') +# db_conn.rollback(savepoint='A') +# +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# cd = con_detail.cursor() +# cd.execute("INSERT INTO DETAIL_TABLE (ID, FKEY) VALUES (1,1)") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Error while executing SQL statement: +- SQLCODE: -530 +- violation of FOREIGN KEY constraint "FK_DETAIL_TABLE" on table "DETAIL_TABLE" +- Foreign key reference target does not exist +- Problematic key value is ("FKEY" = 1) +""" + +@pytest.mark.version('>=2.5.3') +@pytest.mark.xfail +def test_insert_pk_04_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/primary/test_insert_pk_05.py b/tests/functional/fkey/primary/test_insert_pk_05.py new file mode 100644 index 00000000..cb1ee006 --- /dev/null +++ b/tests/functional/fkey/primary/test_insert_pk_05.py @@ -0,0 +1,80 @@ +#coding:utf-8 +# +# id: functional.fkey.primary.insert_pk_05 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master transaction modifies primary key and committed +# Detail transaction inserts record in detail_table. +# Expected: no errors +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.fkey.primary.ins_05 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (ID); +COMMIT; +INSERT INTO MASTER_TABLE (ID, INT_F) VALUES (1, 10); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# +# db_conn.begin(tpb=TPB_master) +# c = db_conn.cursor() +# c.execute("UPDATE MASTER_TABLE SET ID=2 WHERE ID=1") +# db_conn.commit() +# +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# c = con_detail.cursor() +# c.execute("INSERT INTO DETAIL_TABLE (ID, FKEY) VALUES (1,2)") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1') +@pytest.mark.xfail +def test_insert_pk_05_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/primary/test_insert_pk_06.py b/tests/functional/fkey/primary/test_insert_pk_06.py new file mode 100644 index 00000000..797fcdc4 --- /dev/null +++ b/tests/functional/fkey/primary/test_insert_pk_06.py @@ -0,0 +1,83 @@ +#coding:utf-8 +# +# id: functional.fkey.primary.insert_pk_06 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master transaction modifies primary key and committed. +# Detail transaction inserts record in detail_table. +# Expected: no errors +# tracker_id: +# min_versions: [] +# versions: 2.5 +# qmid: functional.fkey.primary.ins_06 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (ID); +COMMIT; +INSERT INTO MASTER_TABLE (ID, INT_F) VALUES (1, 10); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# +# db_conn.begin(tpb=TPB_master) +# c = db_conn.cursor() +# c.execute("UPDATE MASTER_TABLE SET ID=2 WHERE ID=1") +# db_conn.commit() +# db_conn.begin(tpb=TPB_master) +# c = db_conn.cursor() +# c.execute("UPDATE MASTER_TABLE SET INT_F=10") +# +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# c = con_detail.cursor() +# c.execute("INSERT INTO DETAIL_TABLE (ID, FKEY) VALUES (1,2)") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_insert_pk_06_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/primary/test_insert_pk_07.py b/tests/functional/fkey/primary/test_insert_pk_07.py new file mode 100644 index 00000000..dbe2fc65 --- /dev/null +++ b/tests/functional/fkey/primary/test_insert_pk_07.py @@ -0,0 +1,83 @@ +#coding:utf-8 +# +# id: functional.fkey.primary.insert_pk_07 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master table has primary key consisting of several fields. +# Master transaction modifies non key fields. +# Detail transaction inserts record in detail_table. +# Expected: no errors. +# Related to: CORE-1606. Ability to insert child record if parent record is locked but foreign key target unchanged. +# tracker_id: +# min_versions: [] +# versions: 2.5 +# qmid: functional.fkey.primary.ins_07 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID_1 INTEGER NOT NULL, + ID_2 VARCHAR(20) NOT NULL, + INT_F INTEGER, + PRIMARY KEY (ID_1, ID_2) +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY_1 INTEGER, + FKEY_2 VARCHAR(20) +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY_1, FKEY_2) REFERENCES MASTER_TABLE (ID_1, ID_2); +COMMIT; +INSERT INTO MASTER_TABLE (ID_1, ID_2, INT_F) VALUES (1, 'one', 10); +COMMIT;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# db_conn.begin(tpb=TPB_master) +# cm_1 = db_conn.cursor() +# cm_1.execute('UPDATE MASTER_TABLE SET INT_F=2') +# +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# cd = con_detail.cursor() +# cd.execute("INSERT INTO DETAIL_TABLE (ID, FKEY_1, FKEY_2) VALUES (1, 1, 'one')") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_insert_pk_07_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/primary/test_insert_pk_08.py b/tests/functional/fkey/primary/test_insert_pk_08.py new file mode 100644 index 00000000..c22e44c0 --- /dev/null +++ b/tests/functional/fkey/primary/test_insert_pk_08.py @@ -0,0 +1,88 @@ +#coding:utf-8 +# +# id: functional.fkey.primary.insert_pk_08 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master table has primary key consisting of several fields. +# Master transaction modifies one key field. +# Detail transaction inserts record in detail_table. +# Expected: error - primary key in master_table has been changed. +# tracker_id: +# min_versions: [] +# versions: 2.5.3 +# qmid: functional.fkey.primary.ins_08 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID_1 INTEGER NOT NULL, + ID_2 VARCHAR(20) NOT NULL, + INT_F INTEGER, + PRIMARY KEY (ID_1, ID_2) +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY_1 INTEGER, + FKEY_2 VARCHAR(20) +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY_1, FKEY_2) REFERENCES MASTER_TABLE (ID_1, ID_2); +COMMIT; +INSERT INTO MASTER_TABLE (ID_1, ID_2, INT_F) VALUES (1, 'one', 10); +COMMIT;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# db_conn.begin(tpb=TPB_master) +# cm_1 = db_conn.cursor() +# cm_1.execute('UPDATE MASTER_TABLE SET ID_1=2 WHERE ID_1=1') +# +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# cd = con_detail.cursor() +# cd.execute("INSERT INTO DETAIL_TABLE (ID, FKEY_1, FKEY_2) VALUES (1, 1, 'one')") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Error while executing SQL statement: +- SQLCODE: -530 +- violation of FOREIGN KEY constraint "FK_DETAIL_TABLE" on table "DETAIL_TABLE" +- Foreign key reference target does not exist +- Problematic key value is ("FKEY_1" = 1, "FKEY_2" = 'one') +""" + +@pytest.mark.version('>=2.5.3') +@pytest.mark.xfail +def test_insert_pk_08_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/primary/test_insert_pk_09.py b/tests/functional/fkey/primary/test_insert_pk_09.py new file mode 100644 index 00000000..68e1d694 --- /dev/null +++ b/tests/functional/fkey/primary/test_insert_pk_09.py @@ -0,0 +1,89 @@ +#coding:utf-8 +# +# id: functional.fkey.primary.insert_pk_09 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master table has primary key consisting of several fields. +# Master transaction modifies all primary key fields. +# Detail transaction inserts record in detail_table. +# Expected: error - primary in master_table has been changed. +# tracker_id: +# min_versions: [] +# versions: 2.5.3 +# qmid: functional.fkey.primary.ins_09 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID_1 INTEGER NOT NULL, + ID_2 VARCHAR(20) NOT NULL, + INT_F INTEGER, + PRIMARY KEY (ID_1, ID_2) +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY_1 INTEGER, + FKEY_2 VARCHAR(20) +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY_1, FKEY_2) REFERENCES MASTER_TABLE (ID_1, ID_2); +COMMIT; +INSERT INTO MASTER_TABLE (ID_1, ID_2, INT_F) VALUES (1, 'one', 10); +COMMIT;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# db_conn.begin(tpb=TPB_master) +# cm_1 = db_conn.cursor() +# cm_1.execute("UPDATE MASTER_TABLE SET ID_1=2 WHERE ID_1=1") +# cm_1.execute("UPDATE MASTER_TABLE SET ID_2='two' WHERE ID_2='one'") +# +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# cd = con_detail.cursor() +# cd.execute("INSERT INTO DETAIL_TABLE (ID, FKEY_1, FKEY_2) VALUES (1, 1, 'one')") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Error while executing SQL statement: +- SQLCODE: -530 +- violation of FOREIGN KEY constraint "FK_DETAIL_TABLE" on table "DETAIL_TABLE" +- Foreign key reference target does not exist +- Problematic key value is ("FKEY_1" = 1, "FKEY_2" = 'one') +""" + +@pytest.mark.version('>=2.5.3') +@pytest.mark.xfail +def test_insert_pk_09_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/primary/test_insert_pk_10.py b/tests/functional/fkey/primary/test_insert_pk_10.py new file mode 100644 index 00000000..22ba6553 --- /dev/null +++ b/tests/functional/fkey/primary/test_insert_pk_10.py @@ -0,0 +1,83 @@ +#coding:utf-8 +# +# id: functional.fkey.primary.insert_pk_10 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master table has primary key consisting of several fields. +# Master transaction modifies one field of primary key and committed. +# Detail transaction inserts record in detail_table. +# Expected: no errors +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.fkey.primary.ins_10 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID_1 INTEGER NOT NULL, + ID_2 VARCHAR(20) NOT NULL, + INT_F INTEGER, + PRIMARY KEY (ID_1, ID_2) +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY_1 INTEGER, + FKEY_2 VARCHAR(20) +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY_1, FKEY_2) REFERENCES MASTER_TABLE (ID_1, ID_2); +COMMIT; +INSERT INTO MASTER_TABLE (ID_1, ID_2, INT_F) VALUES (1, 'one', 10); +COMMIT;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# db_conn.begin(tpb=TPB_master) +# cm_1 = db_conn.cursor() +# cm_1.execute('UPDATE MASTER_TABLE SET ID_1=2 WHERE ID_1=1') +# db_conn.commit(); +# +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# cd = con_detail.cursor() +# cd.execute("INSERT INTO DETAIL_TABLE (ID, FKEY_1, FKEY_2) VALUES (1, 2, 'one')") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1') +@pytest.mark.xfail +def test_insert_pk_10_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/primary/test_insert_pk_11.py b/tests/functional/fkey/primary/test_insert_pk_11.py new file mode 100644 index 00000000..6dd03e6e --- /dev/null +++ b/tests/functional/fkey/primary/test_insert_pk_11.py @@ -0,0 +1,83 @@ +#coding:utf-8 +# +# id: functional.fkey.primary.insert_pk_11 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master table has primary key consisting of several fields. +# Master transaction modifies all primary key fields and committed. +# Detail transaction inserts record in detail_table. +# Expected: no errors. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.fkey.primary.ins_11 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID_1 INTEGER NOT NULL, + ID_2 VARCHAR(20) NOT NULL, + INT_F INTEGER, + PRIMARY KEY (ID_1, ID_2) +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY_1 INTEGER, + FKEY_2 VARCHAR(20) +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY_1, FKEY_2) REFERENCES MASTER_TABLE (ID_1, ID_2); +COMMIT; +INSERT INTO MASTER_TABLE (ID_1, ID_2, INT_F) VALUES (1, 'one', 10); +COMMIT;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# db_conn.begin(tpb=TPB_master) +# cm_1 = db_conn.cursor() +# cm_1.execute("UPDATE MASTER_TABLE SET ID_1=2 WHERE ID_1=1") +# cm_1.execute("UPDATE MASTER_TABLE SET ID_2='two' WHERE ID_2='one'") +# db_conn.commit(); +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# cd = con_detail.cursor() +# cd.execute("INSERT INTO DETAIL_TABLE (ID, FKEY_1, FKEY_2) VALUES (1, 2, 'two')") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1') +@pytest.mark.xfail +def test_insert_pk_11_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/primary/test_insert_pk_12.py b/tests/functional/fkey/primary/test_insert_pk_12.py new file mode 100644 index 00000000..87e1e1f4 --- /dev/null +++ b/tests/functional/fkey/primary/test_insert_pk_12.py @@ -0,0 +1,87 @@ +#coding:utf-8 +# +# id: functional.fkey.primary.insert_pk_12 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master table has primary key consisting of several fields. +# Master transaction modifies all primary key fields and committed. +# Detail transaction inserts record in detail_table. +# Expected: no errors. +# tracker_id: +# min_versions: [] +# versions: 2.5 +# qmid: functional.fkey.primary.ins_12 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID_1 INTEGER NOT NULL, + ID_2 VARCHAR(20) NOT NULL, + INT_F INTEGER, + PRIMARY KEY (ID_1, ID_2) +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY_1 INTEGER, + FKEY_2 VARCHAR(20) +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY_1, FKEY_2) REFERENCES MASTER_TABLE (ID_1, ID_2); +COMMIT; +INSERT INTO MASTER_TABLE (ID_1, ID_2, INT_F) VALUES (1, 'one', 10); +COMMIT;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# db_conn.begin(tpb=TPB_master) +# cm_1 = db_conn.cursor() +# cm_1.execute("UPDATE MASTER_TABLE SET ID_1=2 WHERE ID_1=1") +# cm_1.execute("UPDATE MASTER_TABLE SET ID_2='two' WHERE ID_2='one'") +# db_conn.commit(); +# db_conn.begin(tpb=TPB_master) +# cm_1 = db_conn.cursor() +# cm_1.execute("UPDATE MASTER_TABLE SET INT_F=2") +# +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# cd = con_detail.cursor() +# cd.execute("INSERT INTO DETAIL_TABLE (ID, FKEY_1, FKEY_2) VALUES (1, 2, 'two')") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_insert_pk_12_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/primary/test_insert_pk_13.py b/tests/functional/fkey/primary/test_insert_pk_13.py new file mode 100644 index 00000000..b608b645 --- /dev/null +++ b/tests/functional/fkey/primary/test_insert_pk_13.py @@ -0,0 +1,69 @@ +#coding:utf-8 +# +# id: functional.fkey.primary.insert_pk_13 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master transaction deletes record from master_table without commit. +# Detail transaction inserts record in detail_table +# Expected: error primary key field in master_table has been changed. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.fkey.primary.ins_13 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('-At block line: [\\d]+, col: [\\d]+', '-At block line')] + +init_script_1 = """ + recreate table t_detl(id int); + commit; + recreate table t_main( + id int constraint t_main_pk primary key using index t_main_pk + ); + commit; + recreate table t_detl( + id int constraint t_detl_pk primary key using index t_detl_pk, + master_pk_id int constraint fk_tdetl_tmain references t_main(id) using index fk_tdetl_tmain + ); + commit; + insert into t_main(id) values(1); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + commit; + set transaction no wait; + set term ^; + execute block as + begin + delete from t_main where id = 1; + in autonomous transaction do + insert into t_detl(id, master_pk_id) values(100, 1); + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint "FK_TDETL_TMAIN" on table "T_DETL" + -Foreign key reference target does not exist + -Problematic key value is ("MASTER_PK_ID" = 1) + -At block line: 5, col: 9 + """ + +@pytest.mark.version('>=3.0') +def test_insert_pk_13_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/fkey/primary/test_insert_pk_14.py b/tests/functional/fkey/primary/test_insert_pk_14.py new file mode 100644 index 00000000..41654320 --- /dev/null +++ b/tests/functional/fkey/primary/test_insert_pk_14.py @@ -0,0 +1,85 @@ +#coding:utf-8 +# +# id: functional.fkey.primary.insert_pk_14 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master transaction deletes record from master_table and commit. +# Detail transaction inserts record in detail_table. +# Expected: referential integrity error. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.fkey.primary.ins_14 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (ID); +COMMIT; +INSERT INTO MASTER_TABLE (ID, INT_F) VALUES (1, 10); +COMMIT;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# db_conn.begin(tpb=TPB_master) +# cm_1 = db_conn.cursor() +# cm_1.execute('DELETE FROM MASTER_TABLE WHERE ID=1') +# db_conn.commit() +# +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# cd = con_detail.cursor() +# cd.execute("INSERT INTO DETAIL_TABLE (ID, FKEY) VALUES (1,1)") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Error while executing SQL statement: +- SQLCODE: -530 +- violation of FOREIGN KEY constraint "FK_DETAIL_TABLE" on table "DETAIL_TABLE" +- Foreign key reference target does not exist +- Problematic key value is ("FKEY" = 1) +""" + +@pytest.mark.version('>=2.1') +@pytest.mark.xfail +def test_insert_pk_14_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/primary/test_insert_pk_15.py b/tests/functional/fkey/primary/test_insert_pk_15.py new file mode 100644 index 00000000..c40109ef --- /dev/null +++ b/tests/functional/fkey/primary/test_insert_pk_15.py @@ -0,0 +1,67 @@ +#coding:utf-8 +# +# id: functional.fkey.primary.insert_pk_15 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master transaction inserts record into master_table but DOES NOT commit. +# Detail transaction inserts record in detail_table and tries to COMMIT. +# Expected: referential integrity error. +# tracker_id: +# min_versions: ['2.5'] +# versions: 3.0 +# qmid: functional.fkey.primary.ins_15 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('-At block line: [\\d]+, col: [\\d]+', '-At block line')] + +init_script_1 = """ + recreate table t_detl(id int); + commit; + recreate table t_main( + id int constraint t_main_pk primary key using index t_main_pk + ); + commit; + recreate table t_detl( + id int constraint t_detl_pk primary key using index t_detl_pk, + master_pk_id int constraint fk_tdetl_tmain references t_main(id) using index fk_tdetl_tmain + ); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + commit; + set transaction no wait; + set term ^; + execute block as + begin + insert into t_main(id) values(1); + in autonomous transaction do + insert into t_detl(id, master_pk_id) values(100, 1); + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint "FK_TDETL_TMAIN" on table "T_DETL" + -Foreign key reference target does not exist + -Problematic key value is ("MASTER_PK_ID" = 1) + -At block line: 5, col: 9 + """ + +@pytest.mark.version('>=3.0') +def test_insert_pk_15_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/fkey/primary/test_insert_pk_16.py b/tests/functional/fkey/primary/test_insert_pk_16.py new file mode 100644 index 00000000..7fc0f668 --- /dev/null +++ b/tests/functional/fkey/primary/test_insert_pk_16.py @@ -0,0 +1,77 @@ +#coding:utf-8 +# +# id: functional.fkey.primary.insert_pk_16 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master transaction inserts record into master_table and commit. +# Detail transaction inserts record in detail_table. +# Expected: no errors. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.fkey.primary.ins_16 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (ID); +COMMIT;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# db_conn.begin(tpb=TPB_master) +# cm_1 = db_conn.cursor() +# cm_1.execute('INSERT INTO MASTER_TABLE (ID, INT_F) VALUES (1, 10)') +# db_conn.commit() +# +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# cd = con_detail.cursor() +# cd.execute("INSERT INTO DETAIL_TABLE (ID, FKEY) VALUES (1,1)") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1') +@pytest.mark.xfail +def test_insert_pk_16_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/primary/test_insert_pk_17.py b/tests/functional/fkey/primary/test_insert_pk_17.py new file mode 100644 index 00000000..91b6088f --- /dev/null +++ b/tests/functional/fkey/primary/test_insert_pk_17.py @@ -0,0 +1,90 @@ +#coding:utf-8 +# +# id: functional.fkey.primary.insert_pk_17 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# 1 Master transaction modifies non key field. +# 2 Detail transaction inserts record. +# 3 Master transaction modifies primary key. +# Expected: referential integrity error +# tracker_id: +# min_versions: [] +# versions: 2.5.3 +# qmid: functional.fkey.primary.ins_17 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [('lock.*', '')] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (ID); +COMMIT; +INSERT INTO MASTER_TABLE (ID, INT_F) VALUES (1, 10); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# +# db_conn.begin(tpb=TPB_master) +# c = db_conn.cursor() +# c.execute("update master_table set int_f = 10 WHERE ID=1") +# +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# try: +# con_detail.begin(tpb=TPB_detail) +# c = con_detail.cursor() +# c.execute("INSERT INTO DETAIL_TABLE (ID, FKEY) VALUES (1,1)") +# except Exception, e: +# print (e[1]) +# +# try: +# c = db_conn.cursor() +# c.execute("update master_table set ID=10 WHERE ID=1") +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Error while executing SQL statement: +- SQLCODE: -530 +- violation of FOREIGN KEY constraint "FK_DETAIL_TABLE" on table "DETAIL_TABLE" +- Foreign key references are present for the record +- Problematic key value is ("ID" = 1) +""" + +@pytest.mark.version('>=2.5.3') +@pytest.mark.xfail +def test_insert_pk_17_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/primary/test_insert_pk_18.py b/tests/functional/fkey/primary/test_insert_pk_18.py new file mode 100644 index 00000000..181ce9d6 --- /dev/null +++ b/tests/functional/fkey/primary/test_insert_pk_18.py @@ -0,0 +1,92 @@ +#coding:utf-8 +# +# id: functional.fkey.primary.insert_pk_18 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# 1 Master transaction modifies non key field. +# 2 Detail transaction add record. +# 3 Detail transaction commited +# 4 Master transaction modifies primary key. +# Expected: referential integrity error +# tracker_id: +# min_versions: [] +# versions: 2.5.3 +# qmid: functional.fkey.primary.ins_18 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (ID); +COMMIT; +INSERT INTO MASTER_TABLE (ID, INT_F) VALUES (1, 10); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# +# db_conn.begin(tpb=TPB_master) +# c = db_conn.cursor() +# c.execute("update master_table set int_f = 10 WHERE ID=1") +# +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# try: +# con_detail.begin(tpb=TPB_detail) +# c = con_detail.cursor() +# c.execute("INSERT INTO DETAIL_TABLE (ID, FKEY) VALUES (1,1)") +# con_detail.commit() +# except Exception, e: +# print (e[1]) +# +# try: +# c = db_conn.cursor() +# c.execute("update master_table set ID=10 WHERE ID=1") +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Error while executing SQL statement: +- SQLCODE: -530 +- violation of FOREIGN KEY constraint "FK_DETAIL_TABLE" on table "DETAIL_TABLE" +- Foreign key references are present for the record +- Problematic key value is ("ID" = 1) +""" + +@pytest.mark.version('>=2.5.3') +@pytest.mark.xfail +def test_insert_pk_18_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/primary/test_insert_pk_19.py b/tests/functional/fkey/primary/test_insert_pk_19.py new file mode 100644 index 00000000..80ffd73a --- /dev/null +++ b/tests/functional/fkey/primary/test_insert_pk_19.py @@ -0,0 +1,86 @@ +#coding:utf-8 +# +# id: functional.fkey.primary.insert_pk_19 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master transaction: +# 1) modified non key field +# 2) create savepoint +# 3) delete record from master_table +# 4) rollback to savepoint +# Detail transaction insert in detail_table record. +# Expected: no errors +# tracker_id: +# min_versions: [] +# versions: 2.5 +# qmid: functional.fkey.primary.ins_19 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (ID); +COMMIT; +INSERT INTO MASTER_TABLE (ID, INT_F) VALUES (1, 10); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# +# db_conn.begin(tpb=TPB_master) +# cm_1 = db_conn.cursor() +# cm_1.execute('UPDATE MASTER_TABLE SET INT_F=2') +# db_conn.savepoint('A') +# cm_1.execute('DELETE FROM MASTER_TABLE WHERE ID=1') +# db_conn.rollback(savepoint='A') +# +# #Create second connection - update detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# cd = con_detail.cursor() +# cd.execute("INSERT INTO DETAIL_TABLE (ID, FKEY) VALUES (1,1)") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_insert_pk_19_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/primary/test_select_pk_01.py b/tests/functional/fkey/primary/test_select_pk_01.py new file mode 100644 index 00000000..4ef3ccf7 --- /dev/null +++ b/tests/functional/fkey/primary/test_select_pk_01.py @@ -0,0 +1,79 @@ +#coding:utf-8 +# +# id: functional.fkey.primary.select_pk_01 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master transaction is perform select with lock and fetch record. +# Detail transaction inserts record in detail_table. +# Expected: no errors. +# tracker_id: +# min_versions: [] +# versions: 2.5 +# qmid: functional.fkey.primary.select_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (ID); +COMMIT; +INSERT INTO MASTER_TABLE (ID, INT_F) VALUES (1, 10); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# +# db_conn.begin(tpb=TPB_master) +# c = db_conn.cursor() +# c.execute("SELECT INT_F FROM MASTER_TABLE WHERE ID=1 WITH LOCK") +# c.fetchall() +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# c = con_detail.cursor() +# c.execute("INSERT INTO DETAIL_TABLE (ID, FKEY) VALUES (1,1)") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_select_pk_01_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/primary/test_select_pk_02.py b/tests/functional/fkey/primary/test_select_pk_02.py new file mode 100644 index 00000000..f7b34a5c --- /dev/null +++ b/tests/functional/fkey/primary/test_select_pk_02.py @@ -0,0 +1,92 @@ +#coding:utf-8 +# +# id: functional.fkey.primary.select_pk_02 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master transaction is perform select with lock but not perform fetch. +# Detail transaction inserts record in detail_table and commit; +# Master transaction fetched record and trying update it; +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.fkey.primary.select_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (ID); +COMMIT; +INSERT INTO MASTER_TABLE (ID, INT_F) VALUES (1, 10); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# +# db_conn.begin(tpb=TPB_master) +# c = db_conn.cursor() +# c.execute("SELECT INT_F FROM MASTER_TABLE WHERE ID=1 WITH LOCK") +# +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# cd = con_detail.cursor() +# cd.execute("INSERT INTO DETAIL_TABLE (ID, FKEY) VALUES (1,1)") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +# +# try: +# c.fetchall() +# c.execute("UPDATE MASTER_TABLE SET ID=2") +# db_conn.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Error while executing SQL statement: +- SQLCODE: -530 +- violation of FOREIGN KEY constraint "FK_DETAIL_TABLE" on table "DETAIL_TABLE" +- Foreign key references are present for the record +- Problematic key value is ("ID" = 1) +""" + +@pytest.mark.version('>=2.1') +@pytest.mark.xfail +def test_select_pk_02_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/primary/test_upd_pk_01.py b/tests/functional/fkey/primary/test_upd_pk_01.py new file mode 100644 index 00000000..8f6a175e --- /dev/null +++ b/tests/functional/fkey/primary/test_upd_pk_01.py @@ -0,0 +1,80 @@ +#coding:utf-8 +# +# id: functional.fkey.primary.upd_pk_01 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master table has one key field. Master transaction doesn't modify key field. +# Detail transaction updates record in detail_table record. +# Expected: no errors +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.fkey.primary.upd_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (ID); +COMMIT; +INSERT INTO MASTER_TABLE (ID, INT_F) VALUES (1, 10); +INSERT INTO DETAIL_TABLE (ID, FKEY) VALUES (1, 1); +COMMIT;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# +# db_conn.begin(tpb=TPB_master) +# c = db_conn.cursor() +# c.execute("update master_table set int_f = 10") +# +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# c = con_detail.cursor() +# c.execute("UPDATE DETAIL_TABLE SET ID=2 WHERE ID=1") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1') +@pytest.mark.xfail +def test_upd_pk_01_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/primary/test_upd_pk_02.py b/tests/functional/fkey/primary/test_upd_pk_02.py new file mode 100644 index 00000000..ca4d2e54 --- /dev/null +++ b/tests/functional/fkey/primary/test_upd_pk_02.py @@ -0,0 +1,83 @@ +#coding:utf-8 +# +# id: functional.fkey.primary.upd_pk_02 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master transaction modifies primary key and commited +# Detail transaction updates record in detail_table. +# Expected: no errors +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.fkey.primary.upd_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (ID); +COMMIT; +INSERT INTO MASTER_TABLE (ID, INT_F) VALUES (1, 10); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# +# db_conn.begin(tpb=TPB_master) +# c = db_conn.cursor() +# c.execute("UPDATE MASTER_TABLE SET ID=2 WHERE ID=1") +# db_conn.commit() +# db_conn.begin(tpb=TPB_master) +# c = db_conn.cursor() +# c.execute("UPDATE MASTER_TABLE SET INT_F=10") +# +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# c = con_detail.cursor() +# c.execute("UPDATE DETAIL_TABLE SET FKEY = 2") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1') +@pytest.mark.xfail +def test_upd_pk_02_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/unique/__init__.py b/tests/functional/fkey/unique/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/fkey/unique/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/fkey/unique/test_insert_01.py b/tests/functional/fkey/unique/test_insert_01.py new file mode 100644 index 00000000..0e20c902 --- /dev/null +++ b/tests/functional/fkey/unique/test_insert_01.py @@ -0,0 +1,80 @@ +#coding:utf-8 +# +# id: functional.fkey.unique.insert_01 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master table has one primary key field and one unique field. Master transaction doesn't modify primary key or unique field. +# Detail transaction inserts record in detail_table. +# Expected: no errors +# tracker_id: +# min_versions: [] +# versions: 2.5 +# qmid: functional.fkey.unique.ins_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + UF INTEGER UNIQUE, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (UF); +COMMIT; +INSERT INTO MASTER_TABLE (ID, UF, INT_F) VALUES (1, 1, 10); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# +# db_conn.begin(tpb=TPB_master) +# c = db_conn.cursor() +# c.execute("update master_table set int_f = 10 WHERE ID=1") +# +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# c = con_detail.cursor() +# c.execute("INSERT INTO DETAIL_TABLE (ID, FKEY) VALUES (1,1)") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_insert_01_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/unique/test_insert_02.py b/tests/functional/fkey/unique/test_insert_02.py new file mode 100644 index 00000000..5f49fd63 --- /dev/null +++ b/tests/functional/fkey/unique/test_insert_02.py @@ -0,0 +1,86 @@ +#coding:utf-8 +# +# id: functional.fkey.unique.insert_02 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master table has one primary key field and one unique field. Master transaction modifies unique field +# Detail transaction inserts record in detail_table. +# Expected: error - unique field in master table has been changed +# tracker_id: +# min_versions: [] +# versions: 2.5.3 +# qmid: functional.fkey.unique.ins_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + UF INTEGER UNIQUE, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (UF); +COMMIT; +INSERT INTO MASTER_TABLE (ID, UF, INT_F) VALUES (1, 1, 10); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# +# db_conn.begin(tpb=TPB_master) +# c = db_conn.cursor() +# c.execute("uPDATE MASTER_TABLE SET UF=2 WHERE ID=1") +# +# #Create second connection - update detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# c = con_detail.cursor() +# c.execute("INSERT INTO DETAIL_TABLE (ID, FKEY) VALUES (1,2)") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Error while executing SQL statement: +- SQLCODE: -530 +- violation of FOREIGN KEY constraint "FK_DETAIL_TABLE" on table "DETAIL_TABLE" +- Foreign key reference target does not exist +- Problematic key value is ("FKEY" = 2) +""" + +@pytest.mark.version('>=2.5.3') +@pytest.mark.xfail +def test_insert_02_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/unique/test_insert_03.py b/tests/functional/fkey/unique/test_insert_03.py new file mode 100644 index 00000000..aa09a579 --- /dev/null +++ b/tests/functional/fkey/unique/test_insert_03.py @@ -0,0 +1,95 @@ +#coding:utf-8 +# +# id: functional.fkey.unique.insert_03 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master table has one primary key field and one unique field. +# Master transaction: +# 1) modified non key field +# 2) create savepoint +# 3) modified unique field +# 4) rollback to savepoint +# Detail transaction inserts record in detail_table. +# Expected: Error - unique field was changed +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.fkey.unique.ins_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + UF INTEGER UNIQUE, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (UF); +COMMIT; +INSERT INTO MASTER_TABLE (ID, UF, INT_F) VALUES (1, 1, 10); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# +# +# db_conn.begin(tpb=TPB_master) +# cm_1 = db_conn.cursor() +# cm_1.execute('UPDATE MASTER_TABLE SET INT_F=2') +# db_conn.savepoint('A') +# cm_1.execute('UPDATE MASTER_TABLE SET UF=2 WHERE ID=1') +# db_conn.rollback(savepoint='A') +# +# #Create second connection - update detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# cd = con_detail.cursor() +# cd.execute("INSERT INTO DETAIL_TABLE (ID, FKEY) VALUES (1,2)") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Error while executing SQL statement: +- SQLCODE: -530 +- violation of FOREIGN KEY constraint "FK_DETAIL_TABLE" on table "DETAIL_TABLE" +- Foreign key reference target does not exist +- Problematic key value is ("FKEY" = 2) +""" + +@pytest.mark.version('>=2.1') +@pytest.mark.xfail +def test_insert_03_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/unique/test_insert_04.py b/tests/functional/fkey/unique/test_insert_04.py new file mode 100644 index 00000000..bfe168f9 --- /dev/null +++ b/tests/functional/fkey/unique/test_insert_04.py @@ -0,0 +1,95 @@ +#coding:utf-8 +# +# id: functional.fkey.unique.insert_04 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master table has one primary key field and one unique field. +# Master transaction: +# 1) modified unique field +# 2) create savepoint +# 3) modified non key and non unique field +# 4) rollback to savepoint +# Detail transaction inserts record in detail_table record +# Expected: error - unique field in master_table has been changed +# tracker_id: +# min_versions: [] +# versions: 2.5.3 +# qmid: functional.fkey.unique.ins_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + UF INTEGER UNIQUE, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (UF); +COMMIT; +INSERT INTO MASTER_TABLE (ID, UF, INT_F) VALUES (1, 1, 10); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# +# +# db_conn.begin(tpb=TPB_master) +# cm_1 = db_conn.cursor() +# cm_1.execute('UPDATE MASTER_TABLE SET UF=2 WHERE ID=1') +# db_conn.savepoint('A') +# cm_1.execute('UPDATE MASTER_TABLE SET INT_F=2 ') +# db_conn.rollback(savepoint='A') +# +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# cd = con_detail.cursor() +# cd.execute("INSERT INTO DETAIL_TABLE (ID, FKEY) VALUES (1,2)") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Error while executing SQL statement: +- SQLCODE: -530 +- violation of FOREIGN KEY constraint "FK_DETAIL_TABLE" on table "DETAIL_TABLE" +- Foreign key reference target does not exist +- Problematic key value is ("FKEY" = 2) +""" + +@pytest.mark.version('>=2.5.3') +@pytest.mark.xfail +def test_insert_04_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/unique/test_insert_05.py b/tests/functional/fkey/unique/test_insert_05.py new file mode 100644 index 00000000..fabf4217 --- /dev/null +++ b/tests/functional/fkey/unique/test_insert_05.py @@ -0,0 +1,81 @@ +#coding:utf-8 +# +# id: functional.fkey.unique.insert_05 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master table has one primary key field and one unique field. Master transaction modifies unique field and commit. +# Detail transaction inserts record in detail_table. +# Expected: no errors +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.fkey.unique.ins_05 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + UF INTEGER UNIQUE, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (UF); +COMMIT; +INSERT INTO MASTER_TABLE (ID, UF, INT_F) VALUES (1, 1, 10); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# +# db_conn.begin(tpb=TPB_master) +# c = db_conn.cursor() +# c.execute("UPDATE MASTER_TABLE SET UF=2 WHERE ID=1") +# db_conn.commit() +# +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# c = con_detail.cursor() +# c.execute("INSERT INTO DETAIL_TABLE (ID, FKEY) VALUES (1,2)") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1') +@pytest.mark.xfail +def test_insert_05_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/unique/test_insert_06.py b/tests/functional/fkey/unique/test_insert_06.py new file mode 100644 index 00000000..223feec2 --- /dev/null +++ b/tests/functional/fkey/unique/test_insert_06.py @@ -0,0 +1,84 @@ +#coding:utf-8 +# +# id: functional.fkey.unique.insert_06 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master table has one primary key field and one unique field. Master transaction doesn't modifiy unique field and commit +# Detail transaction inserts record in detail_table. +# Expected: no errors +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.fkey.unique.ins_06 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + UF INTEGER UNIQUE, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (UF); +COMMIT; +INSERT INTO MASTER_TABLE (ID, UF, INT_F) VALUES (1, 1, 10); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# +# db_conn.begin(tpb=TPB_master) +# c = db_conn.cursor() +# c.execute("UPDATE MASTER_TABLE SET UF=null WHERE ID=1") +# db_conn.commit() +# db_conn.begin(tpb=TPB_master) +# c = db_conn.cursor() +# c.execute("UPDATE MASTER_TABLE SET INT_F=10") +# +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# c = con_detail.cursor() +# c.execute("INSERT INTO DETAIL_TABLE (ID, FKEY) VALUES (1,null)") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1') +@pytest.mark.xfail +def test_insert_06_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/unique/test_insert_07.py b/tests/functional/fkey/unique/test_insert_07.py new file mode 100644 index 00000000..968fc1ff --- /dev/null +++ b/tests/functional/fkey/unique/test_insert_07.py @@ -0,0 +1,72 @@ +#coding:utf-8 +# +# id: functional.fkey.unique.insert_07 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master table has primary key consisting of several fields. +# Master transaction deletes record from master_table without commit. +# Detail transaction inserts record in detail_table. +# Expected: error - unique field in master_table has been changed. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.fkey.unique.ins_07 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('-At block line: [\\d]+, col: [\\d]+', '-At block line')] + +init_script_1 = """ + recreate table t_detl(id int); + commit; + recreate table t_main( + id int constraint t_main_pk primary key using index t_main_pk + ,uniq_ref int constraint t_main_uk unique using index t_main_uk + ); + commit; + recreate table t_detl( + id int constraint t_detl_pk primary key using index t_detl_pk, + master_uniq_ref int constraint t_detl_fk_mur references t_main(uniq_ref) using index t_detl_fk_mur + ); + commit; + + insert into t_main(id, uniq_ref) values(1, 1); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + commit; + set transaction read committed record_version no wait; + set term ^; + execute block as + begin + delete from t_main where id=1; + in autonomous transaction do + insert into t_detl(id, master_uniq_ref) values(100, 1); + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint "T_DETL_FK_MUR" on table "T_DETL" + -Foreign key reference target does not exist + -Problematic key value is ("MASTER_UNIQ_REF" = 1) + -At block line: 5, col: 9 + """ + +@pytest.mark.version('>=3.0') +def test_insert_07_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/fkey/unique/test_insert_08.py b/tests/functional/fkey/unique/test_insert_08.py new file mode 100644 index 00000000..1853f1b4 --- /dev/null +++ b/tests/functional/fkey/unique/test_insert_08.py @@ -0,0 +1,87 @@ +#coding:utf-8 +# +# id: functional.fkey.unique.insert_08 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master table has primary key and unique fields. +# Master transaction deletes record from master_table and commit. +# Detail transaction inserts record in detail_table. +# Expected: referential integrity error. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.fkey.unique.ins_08 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + UF INTEGER UNIQUE, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (UF); +COMMIT; +INSERT INTO MASTER_TABLE (ID, UF, INT_F) VALUES (1, 1, 10); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# db_conn.begin(tpb=TPB_master) +# cm_1 = db_conn.cursor() +# cm_1.execute('DELETE FROM MASTER_TABLE WHERE ID=1') +# db_conn.commit() +# +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# cd = con_detail.cursor() +# cd.execute("INSERT INTO DETAIL_TABLE (ID, FKEY) VALUES (1,1)") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Error while executing SQL statement: +- SQLCODE: -530 +- violation of FOREIGN KEY constraint "FK_DETAIL_TABLE" on table "DETAIL_TABLE" +- Foreign key reference target does not exist +- Problematic key value is ("FKEY" = 1) +""" + +@pytest.mark.version('>=2.1') +@pytest.mark.xfail +def test_insert_08_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/unique/test_insert_09.py b/tests/functional/fkey/unique/test_insert_09.py new file mode 100644 index 00000000..5ace1f5b --- /dev/null +++ b/tests/functional/fkey/unique/test_insert_09.py @@ -0,0 +1,69 @@ +#coding:utf-8 +# +# id: functional.fkey.unique.insert_09 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master table has unique field. +# Master transaction inserts record into master_table without commit. +# Detail transaction inserts record in detail_table. +# Expected: referential integrity error. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.fkey.unique.ins_09 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('-At block line: [\\d]+, col: [\\d]+', '-At block line')] + +init_script_1 = """ + recreate table t_detl(id int); + commit; + recreate table t_main( + id int constraint t_main_pk primary key using index t_main_pk + ,uniq_ref int constraint t_main_uk unique using index t_main_uk + ); + commit; + recreate table t_detl( + id int constraint t_detl_pk primary key using index t_detl_pk, + master_uniq_ref int constraint t_detl_fk_mur references t_main(uniq_ref) using index t_detl_fk_mur + ); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + commit; + set transaction read committed record_version no wait; + set term ^; + execute block as + begin + insert into t_main(id, uniq_ref) values(1, 1); + in autonomous transaction do + insert into t_detl(id, master_uniq_ref) values(100, 1); + end + ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint "T_DETL_FK_MUR" on table "T_DETL" + -Foreign key reference target does not exist + -Problematic key value is ("MASTER_UNIQ_REF" = 1) + -At block line: 5, col: 9 + """ + +@pytest.mark.version('>=3.0') +def test_insert_09_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/fkey/unique/test_insert_11.py b/tests/functional/fkey/unique/test_insert_11.py new file mode 100644 index 00000000..2345bb04 --- /dev/null +++ b/tests/functional/fkey/unique/test_insert_11.py @@ -0,0 +1,79 @@ +#coding:utf-8 +# +# id: functional.fkey.unique.insert_11 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Update unique field with that not assigned foreign key +# Expected: no errors +# tracker_id: +# min_versions: [] +# versions: 2.5 +# qmid: functional.fkey.unique.ins_11 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + UF INTEGER UNIQUE, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (ID); +COMMIT; +INSERT INTO MASTER_TABLE (ID, UF, INT_F) VALUES (1, 1, 10); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# +# db_conn.begin(tpb=TPB_master) +# c = db_conn.cursor() +# c.execute("update master_table set UF=10 WHERE ID=1") +# +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# c = con_detail.cursor() +# c.execute("INSERT INTO DETAIL_TABLE (ID, FKEY) VALUES (1,1)") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_insert_11_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/unique/test_insert_12.py b/tests/functional/fkey/unique/test_insert_12.py new file mode 100644 index 00000000..71fb3151 --- /dev/null +++ b/tests/functional/fkey/unique/test_insert_12.py @@ -0,0 +1,94 @@ +#coding:utf-8 +# +# id: functional.fkey.unique.insert_12 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master table has one primary key field and one unique field. +# 1 Master transaction modifies non key or unique field. +# 2 Detail transaction inserts record. +# 3 Master transaction modifies unique field. +# Detail transaction inserts record in detail_table. +# Expected: referential integrity error +# tracker_id: +# min_versions: [] +# versions: 2.5.3 +# qmid: functional.fkey.unique.ins_12 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [('lock.*', '')] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + UF INTEGER UNIQUE, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (UF); +COMMIT; +INSERT INTO MASTER_TABLE (ID, UF, INT_F) VALUES (1, 1, 10); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# +# db_conn.begin(tpb=TPB_master) +# c = db_conn.cursor() +# c.execute("update master_table set int_f = 10 WHERE ID=1") +# +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# c = con_detail.cursor() +# c.execute("INSERT INTO DETAIL_TABLE (ID, FKEY) VALUES (1,1)") +# except Exception, e: +# print (e[1]) +# +# try: +# c = db_conn.cursor() +# c.execute("update master_table set UF=10 WHERE ID=1") +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Error while executing SQL statement: +- SQLCODE: -530 +- violation of FOREIGN KEY constraint "FK_DETAIL_TABLE" on table "DETAIL_TABLE" +- Foreign key references are present for the record +- Problematic key value is ("UF" = 1) +""" + +@pytest.mark.version('>=2.5.3') +@pytest.mark.xfail +def test_insert_12_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/unique/test_insert_13.py b/tests/functional/fkey/unique/test_insert_13.py new file mode 100644 index 00000000..f9502a5f --- /dev/null +++ b/tests/functional/fkey/unique/test_insert_13.py @@ -0,0 +1,96 @@ +#coding:utf-8 +# +# id: functional.fkey.unique.insert_13 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master table has one primary key field and one unique field. +# 1 Master transaction modifies non key or unique field. +# 2 Detail transaction inserts record. +# 3 Detail transaction committed. +# 4 Master transaction modifies unique field. +# Detail transaction inserts record in detail_table record. +# Expected: referential integrity error +# tracker_id: +# min_versions: [] +# versions: 2.5.3 +# qmid: functional.fkey.unique.ins_13 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + UF INTEGER UNIQUE, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (UF); +COMMIT; +INSERT INTO MASTER_TABLE (ID, UF, INT_F) VALUES (1, 1, 10); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# +# db_conn.begin(tpb=TPB_master) +# c = db_conn.cursor() +# c.execute("update master_table set int_f = 10 WHERE ID=1") +# +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# c = con_detail.cursor() +# c.execute("INSERT INTO DETAIL_TABLE (ID, FKEY) VALUES (1,1)") +# con_detail.commit() +# except Exception, e: +# print (e[1]) +# +# try: +# c = db_conn.cursor() +# c.execute("update master_table set UF=10 WHERE ID=1") +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Error while executing SQL statement: +- SQLCODE: -530 +- violation of FOREIGN KEY constraint "FK_DETAIL_TABLE" on table "DETAIL_TABLE" +- Foreign key references are present for the record +- Problematic key value is ("UF" = 1) +""" + +@pytest.mark.version('>=2.5.3') +@pytest.mark.xfail +def test_insert_13_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/unique/test_insert_14.py b/tests/functional/fkey/unique/test_insert_14.py new file mode 100644 index 00000000..20473b3c --- /dev/null +++ b/tests/functional/fkey/unique/test_insert_14.py @@ -0,0 +1,79 @@ +#coding:utf-8 +# +# id: functional.fkey.unique.insert_14 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master table has unique field. +# Master transaction inserts record into master_table and commit. +# Detail transaction inserts record in detail_table. +# Expected: no errors. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.fkey.unique.ins_10 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + UF INTEGER UNIQUE, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (UF); +COMMIT;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# db_conn.begin(tpb=TPB_master) +# cm_1 = db_conn.cursor() +# cm_1.execute('INSERT INTO MASTER_TABLE (ID, UF, INT_F) VALUES (1, 1, 10)') +# db_conn.commit() +# +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# cd = con_detail.cursor() +# cd.execute("INSERT INTO DETAIL_TABLE (ID, FKEY) VALUES (1,1)") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1') +@pytest.mark.xfail +def test_insert_14_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/unique/test_select_uf_01.py b/tests/functional/fkey/unique/test_select_uf_01.py new file mode 100644 index 00000000..172c4a15 --- /dev/null +++ b/tests/functional/fkey/unique/test_select_uf_01.py @@ -0,0 +1,80 @@ +#coding:utf-8 +# +# id: functional.fkey.unique.select_uf_01 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master transaction is perform select with lock and fetch record. +# Detail transaction inserts record in detail_table. +# Expected: no errors. +# tracker_id: +# min_versions: [] +# versions: 2.5 +# qmid: functional.fkey.unique.select_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + UF INTEGER UNIQUE, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (UF); +COMMIT; +INSERT INTO MASTER_TABLE (ID, UF, INT_F) VALUES (1, 1, 10); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# +# db_conn.begin(tpb=TPB_master) +# c = db_conn.cursor() +# c.execute("SELECT INT_F FROM MASTER_TABLE WHERE ID=1 WITH LOCK") +# c.fetchall() +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# c = con_detail.cursor() +# c.execute("INSERT INTO DETAIL_TABLE (ID, FKEY) VALUES (1,1)") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_select_uf_01_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/unique/test_select_uf_02.py b/tests/functional/fkey/unique/test_select_uf_02.py new file mode 100644 index 00000000..4ad15941 --- /dev/null +++ b/tests/functional/fkey/unique/test_select_uf_02.py @@ -0,0 +1,92 @@ +#coding:utf-8 +# +# id: functional.fkey.unique.select_uf_02 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master transaction is perform select with lock but not perform fetch. +# Detail transaction inserts record in detail_table and commit; +# Master transaction fetched record and trying update it; +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.fkey.unique.select_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + UF INTEGER UNIQUE, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (UF); +COMMIT; +INSERT INTO MASTER_TABLE (ID, UF, INT_F) VALUES (1, 1, 10); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# +# db_conn.begin(tpb=TPB_master) +# c = db_conn.cursor() +# c.execute("SELECT UF, INT_F FROM MASTER_TABLE WHERE ID=1 WITH LOCK") +# +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# cd = con_detail.cursor() +# cd.execute("INSERT INTO DETAIL_TABLE (ID, FKEY) VALUES (1,1)") +# con_detail.commit() +# except Exception, e: +# print (e[1]) +# try: +# c.fetchall() +# c.execute("UPDATE MASTER_TABLE SET UF=2") +# db_conn.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Error while executing SQL statement: +- SQLCODE: -530 +- violation of FOREIGN KEY constraint "FK_DETAIL_TABLE" on table "DETAIL_TABLE" +- Foreign key references are present for the record +- Problematic key value is ("UF" = 1) +""" + +@pytest.mark.version('>=2.1') +@pytest.mark.xfail +def test_select_uf_02_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/unique/test_upd_01.py b/tests/functional/fkey/unique/test_upd_01.py new file mode 100644 index 00000000..3be79556 --- /dev/null +++ b/tests/functional/fkey/unique/test_upd_01.py @@ -0,0 +1,81 @@ +#coding:utf-8 +# +# id: functional.fkey.unique.upd_01 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master table has unique field. Master transaction doesn't modified it. +# Detail transaction updates record in detail_table record. +# Expected: no errors +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.fkey.unique.upd_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + UF INTEGER UNIQUE, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (UF); +COMMIT; +INSERT INTO MASTER_TABLE (ID, UF, INT_F) VALUES (1, 1, 10); +INSERT INTO DETAIL_TABLE (ID, FKEY) VALUES (1, 1); +COMMIT;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# +# db_conn.begin(tpb=TPB_master) +# c = db_conn.cursor() +# c.execute("UPDATE MASTER_TABLE SET INT_F=10") +# +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# c = con_detail.cursor() +# c.execute("UPDATE DETAIL_TABLE SET ID=2 WHERE ID=1") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1') +@pytest.mark.xfail +def test_upd_01_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/fkey/unique/test_upd_02.py b/tests/functional/fkey/unique/test_upd_02.py new file mode 100644 index 00000000..b2cad746 --- /dev/null +++ b/tests/functional/fkey/unique/test_upd_02.py @@ -0,0 +1,84 @@ +#coding:utf-8 +# +# id: functional.fkey.unique.upd_02 +# title: Check correct work fix with foreign key +# decription: Check foreign key work. +# Master table has unique field. Master transaction modifies it and commit. +# Detail transaction updates record in detail_table. +# Expected: no errors +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.fkey.unique.upd_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE MASTER_TABLE ( + ID INTEGER PRIMARY KEY, + UF INTEGER UNIQUE, + INT_F INTEGER +); + +CREATE TABLE DETAIL_TABLE ( + ID INTEGER PRIMARY KEY, + FKEY INTEGER +); + +ALTER TABLE DETAIL_TABLE ADD CONSTRAINT FK_DETAIL_TABLE FOREIGN KEY (FKEY) REFERENCES MASTER_TABLE (UF); +COMMIT; +INSERT INTO MASTER_TABLE (ID, UF, INT_F) VALUES (1, 1, 10); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# TPB_master = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# TPB_detail = ( +# chr(kdb.isc_tpb_write) +# + chr(kdb.isc_tpb_read_committed) + chr(kdb.isc_tpb_rec_version) +# + chr(kdb.isc_tpb_nowait) +# ) +# +# db_conn.begin(tpb=TPB_master) +# c = db_conn.cursor() +# c.execute("UPDATE MASTER_TABLE SET UF=2 WHERE ID=1") +# db_conn.commit() +# db_conn.begin(tpb=TPB_master) +# c = db_conn.cursor() +# c.execute("UPDATE MASTER_TABLE SET INT_F=10") +# +# #Create second connection for change detail table +# con_detail = kdb.connect( +# dsn=dsn.encode(), +# user=user_name.encode(), +# password=user_password.encode() +# ) +# +# try: +# con_detail.begin(tpb=TPB_detail) +# c = con_detail.cursor() +# c.execute("UPDATE DETAIL_TABLE SET FKEY = 2") +# con_detail.commit() +# except Exception, e: +# print (e[0]) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.1') +@pytest.mark.xfail +def test_upd_02_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/generator/__init__.py b/tests/functional/generator/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/generator/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/generator/alter/test_01.py b/tests/functional/generator/alter/test_01.py new file mode 100644 index 00000000..dd600245 --- /dev/null +++ b/tests/functional/generator/alter/test_01.py @@ -0,0 +1,186 @@ +#coding:utf-8 +# +# id: functional.generator.alter_01 +# title: Run ALTER SEQUENCE +# decription: +# Create sequence and try several cases of ALTER SEQUENCE statement. +# Then check result that is stored in RDB$GENERATORS table and gen_id(, 0) value. +# NB: we have to issue 'COMMIT' after each ALTER SEQUENCE statement in order to see new values in RDB. +# +# 07-aug-2020: we have to separate test for 3.0 and 4.0 because INITIAL value of new sequence +# in FB 4.x now differs from "old good zero" (this is so since CORE-6084 was fixed). +# +# 13-aug-2020: changed code for FB 4.x after introduction of fix for CORE-6386: value that was initially +# written into RDB$GENERATORD.RDB$INITIAL_VALUE column must NOT changed on any kind of ALTER EQUENCE +# statement, even when it contains 'RESTART WITH' clause. Checked on 4.0.0.2151. +# +# See also: doc/README.incompatibilities.3to4.txt +# +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0, 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('===.*', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate generator g; + recreate view v_info as select rdb$initial_value as rdb_init, rdb$generator_increment as rdb_incr, gen_id(g,0) as gen_id_0 from rdb$generators where rdb$generator_name=upper('g'); + commit; + select 'point-00' as msg, v.* from v_info v; + + set heading off; + + alter sequence g increment by -1; commit; + select 'point-01' as msg, v.* from v_info v; + + alter sequence g increment by 1; commit; + select 'point-02' as msg, v.* from v_info v; + + alter sequence g restart with 0; commit; + select 'point-03' as msg, v.* from v_info v; + + alter sequence g restart with -1; commit; + select 'point-04' as msg, v.* from v_info v; + + alter sequence g restart with -1 increment by -1; commit; + select 'point-05' as msg, v.* from v_info v; + + alter sequence g restart with -1 increment by 1; commit; + select 'point-06' as msg, v.* from v_info v; + + alter sequence g restart with 1 increment by -1; commit; + select 'point-07' as msg, v.* from v_info v; + + alter sequence g restart with 1 increment by 1; commit; + select 'point-08' as msg, v.* from v_info v; + commit; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG RDB_INIT RDB_INCR GEN_ID_0 + ======== ===================== ============ ===================== + point-00 0 1 0 + point-01 0 -1 0 + point-02 0 1 0 + point-03 0 1 0 + point-04 -1 1 -1 + point-05 -1 -1 -1 + point-06 -1 1 -1 + point-07 1 -1 1 + point-08 1 1 1 + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_alter_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [('===.*', ''), ('[ \t]+', ' ')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + recreate generator g start with 7654321; + set term ^; + create procedure sp_gen_info returns( rdb_init bigint, rdb_incr bigint, gen_id_curr bigint, gen_id_next bigint) as + begin + select rdb$initial_value , rdb$generator_increment + from rdb$generators + where rdb$generator_name=upper('g') + into rdb_init, rdb_incr; + + execute statement 'select gen_id(g,0) from rdb$database' into gen_id_curr; + execute statement 'select next value for g from rdb$database' into gen_id_next; + suspend; + end^ + set term ;^ + commit; + + select 'point-00' as msg, p.* from sp_gen_info p; + --set echo on; + set heading off; + + ----------------------------------------------------------------------- + + -- Test when only INCREMENT BY clause presents: + + recreate generator g start with 7654321; commit; alter sequence g increment by -23456789; commit; + select 'point-01' as msg, p.* from sp_gen_info p; + ----------------------------------------------------------------------- + + recreate generator g start with 7654321; commit; alter sequence g increment by 23456789; commit; + select 'point-02' as msg, p.* from sp_gen_info p; + ----------------------------------------------------------------------- + + + -- Test when only RESTART clause presents: + + recreate generator g start with 7654321; commit; alter sequence g restart with -1234567; commit; + select 'point-03' as msg, p.* from sp_gen_info p; + + ----------------------------------------------------------------------- + recreate generator g start with 7654321; commit; alter sequence g restart with 1234567; commit; + select 'point-04' as msg, p.* from sp_gen_info p; + + ----------------------------------------------------------------------- + + -- Test when both RESTART and INCREMENT BY clauses present: + + recreate generator g start with 7654321; commit; alter sequence g restart with -1234567 increment by -23456789; commit; + select 'point-05' as msg, p.* from sp_gen_info p; + + ----------------------------------------------------------------------- + recreate generator g start with 7654321; commit; alter sequence g restart with -1234567 increment by 23456789; commit; + select 'point-06' as msg, p.* from sp_gen_info p; + + ----------------------------------------------------------------------- + recreate generator g start with 7654321; commit; alter sequence g restart with 1234567 increment by -23456789; commit; + select 'point-07' as msg, p.* from sp_gen_info p; + + ----------------------------------------------------------------------- + recreate generator g start with 7654321; commit; alter sequence g restart with 1234567 increment by 23456789; commit; + select 'point-08' as msg, p.* from sp_gen_info p; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + MSG RDB_INIT RDB_INCR GEN_ID_CURR GEN_ID_NEXT + ======== ===================== ===================== ===================== ===================== + point-00 7654321 1 7654320 7654321 + point-01 7654321 -23456789 7654320 -15802469 + point-02 7654321 23456789 7654320 31111109 + point-03 7654321 1 -1234568 -1234567 + point-04 7654321 1 1234566 1234567 + point-05 7654321 -23456789 22222222 -1234567 + point-06 7654321 23456789 -24691356 -1234567 + point-07 7654321 -23456789 24691356 1234567 + point-08 7654321 23456789 -22222222 1234567 + """ + +@pytest.mark.version('>=4.0') +def test_alter_01_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/functional/generator/create/test_01.py b/tests/functional/generator/create/test_01.py new file mode 100644 index 00000000..df6c746f --- /dev/null +++ b/tests/functional/generator/create/test_01.py @@ -0,0 +1,89 @@ +#coding:utf-8 +# +# id: functional.generator.create_01 +# title: Run CREATE GENERATOR and query related data from RDB$GENERATORS. +# decription: +# Run 'CREATE GENERATOR' statement and obtain data about it from system table (rdb$generators). +# 07-aug-2020: we have to separate test for 3.0 and 4.0 because INITIAL value of new sequence +# in FB 4.x now differs from "old good zero" (this is so since CORE-6084 was fixed). +# +# See also: doc/README.incompatibilities.3to4.txt +# +# tracker_id: +# min_versions: [] +# versions: 3.0, 4.0 +# qmid: functional.generator.create.create_generator_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('RDB\\$SECURITY_CLASS[ ]+SQL\\$.*', ''), ('RDB\\$GENERATOR_ID.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create generator test; + commit; + set list on; + select * from rdb$generators where rdb$generator_name=upper('test'); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$GENERATOR_NAME TEST + RDB$GENERATOR_ID 12 + RDB$SYSTEM_FLAG 0 + RDB$DESCRIPTION + RDB$SECURITY_CLASS SQL$366 + RDB$OWNER_NAME SYSDBA + RDB$INITIAL_VALUE 0 + RDB$GENERATOR_INCREMENT 1 + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_create_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [('RDB\\$SECURITY_CLASS[ ]+SQL\\$.*', ''), ('RDB\\$GENERATOR_ID.*', '')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + create generator test; + commit; + set list on; + select * from rdb$generators where rdb$generator_name=upper('test'); + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + RDB$GENERATOR_NAME TEST + RDB$GENERATOR_ID 12 + RDB$SYSTEM_FLAG 0 + RDB$DESCRIPTION + RDB$SECURITY_CLASS SQL$366 + RDB$OWNER_NAME SYSDBA + RDB$INITIAL_VALUE 1 + RDB$GENERATOR_INCREMENT 1 + """ + +@pytest.mark.version('>=4.0') +def test_create_01_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/functional/generator/create/test_02.py b/tests/functional/generator/create/test_02.py new file mode 100644 index 00000000..466b4a5c --- /dev/null +++ b/tests/functional/generator/create/test_02.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: functional.generator.create_02 +# title: CREATE GENERATOR - try create gen with same name +# decription: CREATE GENERATOR - try create gen with same name +# +# Dependencies: +# CREATE DATABASE +# CREATE GENERATOR +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.generator.create.create_generator_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + CREATE GENERATOR test; + commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + CREATE GENERATOR test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE SEQUENCE TEST failed + -Sequence TEST already exists + """ + +@pytest.mark.version('>=3.0') +def test_create_02_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/generator/drop/__init__.py b/tests/functional/generator/drop/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/generator/drop/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/generator/drop/test_01.py b/tests/functional/generator/drop/test_01.py new file mode 100644 index 00000000..4de1dad3 --- /dev/null +++ b/tests/functional/generator/drop/test_01.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: functional.generator.drop.01 +# title: DROP GENERATOR +# decription: DROP GENERATOR +# +# Dependencies: +# CREATE DATABASE +# CREATE GENERATOR +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.generator.drop.drop_generator_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE GENERATOR test; +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """DROP GENERATOR test; +SHOW GENERATOR TEST;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """There is no generator TEST in this database +""" + +@pytest.mark.version('>=1.0') +def test_01_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/generator/drop/test_02.py b/tests/functional/generator/drop/test_02.py new file mode 100644 index 00000000..d58b2297 --- /dev/null +++ b/tests/functional/generator/drop/test_02.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: functional.generator.drop.02 +# title: DROP GENERATOR - in use +# decription: DROP GENERATOR +# +# Dependencies: +# CREATE DATABASE +# CREATE GENERATOR +# CREATE PROCEDURE +# tracker_id: +# min_versions: [] +# versions: 2.5.0 +# qmid: functional.generator.drop.drop_generator_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE GENERATOR test; +SET TERM ^; +CREATE PROCEDURE a AS +DECLARE VARIABLE id INT; +BEGIN + id=GEN_ID(test,1); +END ^ +SET TERM ;^ +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """DROP GENERATOR test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42000 + +unsuccessful metadata update +-cannot delete +-GENERATOR TEST +-there are 1 dependencies +""" + +@pytest.mark.version('>=2.5.0') +def test_02_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/generator/drop/test_03.py b/tests/functional/generator/drop/test_03.py new file mode 100644 index 00000000..9e8e3998 --- /dev/null +++ b/tests/functional/generator/drop/test_03.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: functional.generator.drop_03 +# title: DROP GENERATOR - generator does not exists +# decription: DROP GENERATOR - generator does not exists +# +# Dependencies: +# CREATE DATABASE +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.generator.drop.drop_generator_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """DROP GENERATOR test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42000 +unsuccessful metadata update +-DROP SEQUENCE TEST failed +-generator TEST is not defined + +""" + +@pytest.mark.version('>=3.0') +def test_drop_03_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/gtcs/__init__.py b/tests/functional/gtcs/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/gtcs/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/gtcs/test_computed_fields_01.py b/tests/functional/gtcs/test_computed_fields_01.py new file mode 100644 index 00000000..e4b968fd --- /dev/null +++ b/tests/functional/gtcs/test_computed_fields_01.py @@ -0,0 +1,211 @@ +#coding:utf-8 +# +# id: functional.gtcs.computed_fields_01 +# title: computed-fields-01 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_01.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + /*-----------------*/ + /* Computed by (i) */ + /*-----------------*/ + create table t0 (i integer, j computed by (i)); + commit; -- t0; + insert into t0(i) values(1); + insert into t0(i) values(2); + select 'Passed 1 - Insert' from t0 where j = i having count(*) = 2; + + update t0 set i = 99 where i = 2; + select 'Passed 1 - Update' from t0 where j = i having count(*) = 2; + + /*-------------------*/ + /* Computed by (i+i) */ + /*-------------------*/ + create table t5 (i integer, j computed by (i+i)); + commit; -- t5; + insert into t5(i) values(1); + insert into t5(i) values(2); + select 'Passed 2 - Insert' from t5 where j = i+i having count(*) = 2; + + update t5 set i = 99 where i = 2; + select 'Passed 2 - Update' from t5 where j = i+i having count(*) = 2; + + /*-------------------*/ + /* Computed by (i*i) */ + /*-------------------*/ + create table t10 (i integer, j computed by (i*i)); + commit; -- t10; + insert into t10(i) values(1); + insert into t10(i) values(2); + select 'Passed 3 - Insert' from t10 where j = i*i having count(*) = 2; + + update t10 set i = 99 where i = 2; + select 'Paseed 3 - Update' from t10 where j = i*i having count(*) = 2; + + /*-------------------*/ + /* Computed by (i/i) */ + /*-------------------*/ + create table t15 (i integer, j computed by (i/i)); + commit; -- t15; + insert into t15(i) values(1); + insert into t15(i) values(2); + select 'Passed 4 - Insert' from t15 where j = i/i having count(*) = 2; + + update t15 set i = 99 where i = 2; + select 'Passed 4 - Update' from t15 where j = i/i having count(*) = 2; + + /*-------------------*/ + /* Computed by (i+2) */ + /*-------------------*/ + create table t20 (i integer, j computed by (i+2)); + commit; -- t20; + insert into t20(i) values(1); + insert into t20(i) values(2); + select 'Passed 5 - Insert' from t20 where j = i+2 having count(*) = 2; + + update t20 set i = 99 where i = 2; + select 'Passed 5 - Update' from t20 where j = i+2 having count(*) = 2; + + /*-------------------*/ + /* Computed by (i*2) */ + /*-------------------*/ + create table t25 (i integer, j computed by (i*2)); + commit; -- t25; + insert into t25(i) values(1); + insert into t25(i) values(2); + select 'Passed 6 - Insert' from t25 where j = i*2 having count(*) = 2; + + update t25 set i = 99 where i = 2; + select 'Passed 6 - Update' from t25 where j = i*2 having count(*) = 2; + + /*-------------------*/ + /* Computed by (i/2) */ + /*-------------------*/ + create table t30 (i integer, j computed by (i/2)); + commit; -- t30; + insert into t30(i) values(1); + insert into t30(i) values(2); + select 'Passed 7 - Insert' from t30 where j = i/2 having count(*) = 2; + + update t30 set i = 99 where i = 2; + select 'Passed 7 - Update' from t30 where j = i/2 having count(*) = 2; + + /*------------------*/ + /* Computed by (-i) */ + /*------------------*/ + create table t35 (i integer, j computed by (-i)); + commit; -- t35; + insert into t35(i) values(1); + insert into t35(i) values(2); + select 'Passed 8 - Insert' from t35 where j = -i having count(*) = 2; + + update t35 set i = 99 where i = 2; + select 'Passed 8 - Update' from t35 where j = -i having count(*) = 2; + + /*------------------*/ + /* Computed by (+i) */ + /*------------------*/ + + create table t40 (i integer, j computed by (+i)); + commit; -- t40; + insert into t40(i) values(1); + insert into t40(i) values(2); + select 'Passed 9 - Insert' from t40 where j = +i having count(*) = 2; + + update t40 set i = 99 where i = 2; + select 'Passed 9 - Update' from t40 where j = +i having count(*) = 2; + + /*---------------------------*/ + /* Computed by ((i-i+i)*i/i) */ + /*---------------------------*/ + create table t43 (i integer, j computed by ((i-i+i)*i/i)); + commit; -- t43; + insert into t43(i) values(3); + insert into t43(i) values(4); + select 'Passed 9.1 - Insert' from t43 where j = i having count(*) = 2; + + update t43 set i = 99 where i = 4; + select 'Passed 9.1 - Update' from t43 where j = i having count(*) = 2; + + /*-----------------*/ + /* Computed by (0) */ + /*-----------------*/ + create table t45 (i integer, j computed by (0)); + commit; -- t45; + insert into t45(i) values(1); + insert into t45(i) values(2); + select 'Passed 10 - Insert' from t45 where j = 0 having count(*) = 2; + + update t45 set i = 99 where i = 2; + select 'Passed 10 - Update' from t45 where j = 0 having count(*) = 2; + + /*---------------------------*/ + /* Computed by ((4*2-4+4)/2) */ + /*---------------------------*/ + create table t50 (i integer, j computed by ((4*2-4+4)/2)); + commit; -- t50; + insert into t50(i) values(1); + insert into t50(i) values(2); + select 'Passed 11 - Insert' from t50 where j = (4*2-4+4)/2 having count(*) = 2; + + update t50 set i = 99 where i = 2; + select 'Passed 11 - Update' from t50 where j = (4*2-4+4)/2 having count(*) = 2; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Passed 1 - Insert + Passed 1 - Update + Passed 2 - Insert + Passed 2 - Update + Passed 3 - Insert + Paseed 3 - Update + Passed 4 - Insert + Passed 4 - Update + Passed 5 - Insert + Passed 5 - Update + Passed 6 - Insert + Passed 6 - Update + Passed 7 - Insert + Passed 7 - Update + Passed 8 - Insert + Passed 8 - Update + Passed 9 - Insert + Passed 9 - Update + Passed 9.1 - Insert + Passed 9.1 - Update + Passed 10 - Insert + Passed 10 - Update + Passed 11 - Insert + Passed 11 - Update + """ + +@pytest.mark.version('>=2.5') +def test_computed_fields_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_computed_fields_02.py b/tests/functional/gtcs/test_computed_fields_02.py new file mode 100644 index 00000000..d3332000 --- /dev/null +++ b/tests/functional/gtcs/test_computed_fields_02.py @@ -0,0 +1,279 @@ +#coding:utf-8 +# +# id: functional.gtcs.computed_fields_02 +# title: computed-fields-02 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_02.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + /* + ** Syntax test cases - Valid Arithmetic operations on + ** SMALLINT, NUMERIC, DECIMAL, FLOAT, DOUBLE PRECISION + */ + + /* SMALLINT: */ + /*-----------------*/ + /* Computed by (i) */ + /*-----------------*/ + create table t0_s (i smallint, j computed by (i)); + commit; -- t0_s; + insert into t0_s(i) values(-32768); + insert into t0_s(i) values(32767); + select 'Passed 1(s) - Insert' from t0_s where j = i having count(*) = 2; + + update t0_s set i = -32768 where i = 2; + select 'Passed 1(s) - Update' from t0_s where j = i having count(*) = 2; + + /*-------------------*/ + /* Computed by (i+i) */ + /*-------------------*/ + create table t5_s (i smallint, j computed by (i+i)); + commit; -- t5_s; + insert into t5_s(i) values(-32768); + insert into t5_s(i) values(32767); + select 'Passed 2(s) - Insert' from t5_s where j = i+i having count(*) = 2; + + update t5_s set i = -32768 where i = 32767; + select 'Passed 2(s) - Update' from t5_s where j = i+i having count(*) = 2; + + /*-------------------*/ + /* Computed by (i+32768) */ + /*-------------------*/ + create table t10_s (i smallint, j computed by (i+32768)); + commit; -- t10_s; + insert into t10_s(i) values(-32768); + insert into t10_s(i) values(32767); + select 'Passed 3(s) - Insert' from t10_s where j = i+32768 having count(*) = 2; + + update t10_s set i = -32768 where i = 32767; + select 'Passed 3(s) - Update' from t10_s where j = i+32768 having count(*) = 2; + + + /* DECIMAL: */ + /*-----------------*/ + /* Computed by (i) */ + /*-----------------*/ + create table t0_d (i decimal(15,2), j computed by (i)); + commit; -- t0_d; + insert into t0_d(i) values(1); + insert into t0_d(i) values(2); + select 'Passed 1(d) - Insert' from t0_d where j = i having count(*) = 2; + + update t0_d set i = 99 where i = 2; + select 'Passed 1(d) - Update' from t0_d where j = i having count(*) = 2; + + /*-------------------*/ + /* Computed by (i+i) */ + /*-------------------*/ + create table t5_d (i decimal(15,2), j computed by (i+i)); + commit; -- t5_d; + insert into t5_d(i) values(1.0); + insert into t5_d(i) values(2.0); + select 'Passed 2(d) - Insert' from t5_d where j = i+i having count(*) = 2; + + update t5_d set i = 99.0 where i = 2.0; + select 'Passed 2(d) - Update' from t5_d where j = i+i having count(*) = 2; + + /*-------------------*/ + /* Computed by (i+999999999999.99) */ + /*-------------------*/ + create table t10_d (i decimal(15,2), j computed by (i+999999999999.99)); + commit; -- t10_d; + insert into t10_d(i) values(0.01); + insert into t10_d(i) values(0.02); + select 'Passed 3(d) - Insert' from t10_d where j = i+999999999999.99 having count(*) = 2; + + update t10_d set i = 0.2 where i = 0.02; + select 'Passed 3(d) - Update' from t10_d where j = i+999999999999.99 having count(*) = 2; + + -- ########################################################################## + + /* NUMERIC: */ + /*-----------------*/ + /* Computed by (i) */ + /*-----------------*/ + create table t0_n (i numeric(15,2), j computed by (i)); + commit; -- t0_n; + insert into t0_n(i) values(1.0); + insert into t0_n(i) values(2.0); + select 'Passed 1(n) - Insert' from t0_n where j = i having count(*) = 2; + + update t0_n set i = 99.0 where i = 2.0; + select 'Passed 1(n) - Update' from t0_n where j = i having count(*) = 2; + + /*-------------------*/ + /* Computed by (i+i) */ + /*-------------------*/ + create table t5_n (i numeric(15,2), j computed by (i+i)); + commit; -- t5_n; + insert into t5_n(i) values(1.0); + insert into t5_n(i) values(2.0); + select 'Passed 2(n) - Insert' from t5_n where j = i+i having count(*) = 2; + + update t5_n set i = 99.0 where i = 2.0; + select 'Passed 2(n) - Update' from t5_n where j = i+i having count(*) = 2; + + /*-------------------*/ + /* Computed by (i+999999999999.99) */ + /*-------------------*/ + create table t10_n (i decimal(15,2), j computed by (i+999999999999.99)); + commit; -- t10_n; + insert into t10_n(i) values(0.01); + insert into t10_n(i) values(0.02); + select 'Passed 3(n) - Insert' from t10_n where j = i+999999999999.99 having count(*) = 2; + + update t10_n set i = 0.2 where i = 0.02; + select 'Passed 3(n) - Update' from t10_n where j = i+999999999999.99 having count(*) = 2; + + -- ########################################################################## + + /* FLOAT: */ + -- https://en.wikipedia.org/wiki/Single-precision_floating-point_format + -- IEEE 754 32-bit base-2 floating-point variable has a maximum value of (2-2^23)*2^127 ==> ~3.4028234663852886e+38 + -- All integers with 7 or fewer decimal digits, and any 2^n for a whole number -149<=n<=127, can be converted exactly + -- into an IEEE 754 single-precision floating-point value. + + /*-----------------*/ + /* Computed by (i) */ + /*-----------------*/ + create table t0_f (i float, j computed by (i)); + commit; -- t0_f; + insert into t0_f(i) values(1.0); + insert into t0_f(i) values(2.0); + select 'Passed 1(f) - Insert' from t0_f where j = i having count(*) = 2; + + update t0_f set i = 99.0 where i = 2.0; + select 'Passed 1(f) - Update' from t0_f where j = i having count(*) = 2; + + /*-------------------*/ + /* Computed by (i+i) */ + /*-------------------*/ + create table t5_f (i float, j computed by (i+i)); + commit; -- t5_f; + insert into t5_f(i) values(1.0); + insert into t5_f(i) values(2.0); + select 'Passed 2(f) - Insert' from t5_f where j = i+i having count(*) = 2; + + update t5_f set i = 99.0 where i = 2.0; + select 'Passed 2(f) - Update' from t5_f where j = i+i having count(*) = 2; + + /*-------------------*/ + /* Computed by (i+1) */ + /*-------------------*/ + create table t10_f (i float, j computed by (i+1)); + commit; -- t10_f; + insert into t10_f(i) values(1.0); + insert into t10_f(i) values(2.0); + select 'Passed 3(f) - Insert' from t10_f where j = i+1 having count(*) = 2; + + update t10_f set i = 99.0 where i = 2.0; + select 'Passed 3(f) - Update' from t10_f where j = i+1 having count(*) = 2; + + -- ########################################################################## + + /* DOUBLE PRECISION: */ + /*-----------------*/ + /* Computed by (i) */ + /*-----------------*/ + create table t0_dp (i double precision, j computed by (i)); + commit; -- t0_dp; + insert into t0_dp(i) values(1.0); + insert into t0_dp(i) values(2.0); + select 'Passed 1(dp) - Insert' from t0_dp where j = i having count(*) = 2; + + update t0_dp set i = 0.2 where i = 2.0; + select 'Passed 1(dp) - Update' from t0_dp where j = i having count(*) = 2; + + /*-------------------*/ + /* Computed by (i+i) */ + /*-------------------*/ + create table t5_dp (i double precision, j computed by (i+i)); + commit; -- t5_dp; + insert into t5_dp(i) values(1.0); + insert into t5_dp(i) values(2.0); + select 'Passed 2(dp) - Insert' from t5_dp where j = i+i having count(*) = 2; + + update t5_dp set i = 0.2 where i = 2.0; + select 'Passed 2(dp) - Update' from t5_dp where j = i+i having count(*) = 2; + + /*-------------------*/ + /* Computed by (i+1) */ + /*-------------------*/ + create table t10_dp (i double precision, j computed by (i+1)); + commit; -- t10_dp; + insert into t10_dp(i) values(1.0); + insert into t10_dp(i) values(2.0); + select 'Passed 3(dp) - Insert' from t10_dp where j = i+1 having count(*) = 2; + + update t10_dp set i = 0.2 where i = 2.0; + select 'Passed 3(dp) - Update' from t10_dp where j = i+1 having count(*) = 2; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Passed 1(s) - Insert + Passed 1(s) - Update + Passed 2(s) - Insert + Passed 2(s) - Update + Passed 3(s) - Insert + Passed 3(s) - Update + + Passed 1(d) - Insert + Passed 1(d) - Update + Passed 2(d) - Insert + Passed 2(d) - Update + Passed 3(d) - Insert + Passed 3(d) - Update + + Passed 1(n) - Insert + Passed 1(n) - Update + Passed 2(n) - Insert + Passed 2(n) - Update + Passed 3(n) - Insert + Passed 3(n) - Update + + Passed 1(f) - Insert + Passed 1(f) - Update + Passed 2(f) - Insert + Passed 2(f) - Update + Passed 3(f) - Insert + Passed 3(f) - Update + + Passed 1(dp) - Insert + Passed 1(dp) - Update + Passed 2(dp) - Insert + Passed 2(dp) - Update + Passed 3(dp) - Insert + Passed 3(dp) - Update + """ + +@pytest.mark.version('>=2.5') +def test_computed_fields_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_computed_fields_03.py b/tests/functional/gtcs/test_computed_fields_03.py new file mode 100644 index 00000000..d490ce0e --- /dev/null +++ b/tests/functional/gtcs/test_computed_fields_03.py @@ -0,0 +1,162 @@ +#coding:utf-8 +# +# id: functional.gtcs.computed_fields_03 +# title: computed-fields-03 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_03.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + + /* + ** Syntax test cases - Valid string operations + */ + + /*-----------------*/ + /* Computed by (s) */ + /*-----------------*/ + create table t0 (s char(25), sc computed by (s)); + commit; -- t0; + insert into t0(s) values('computed'); + insert into t0(s) values('(s)'); + select 'Passed 1 - Insert' from t0 where sc = s having count(*) = 2; + + update t0 set s = 'by' where s = 'computed'; + select 'Passed 1 - Update' from t0 where sc = s having count(*) = 2; + + /*--------------------*/ + /* Computed by (s||s) */ + /*--------------------*/ + create table t5 (s char(25), sc computed by (s||s)); + commit; -- t5; + insert into t5(s) values('computed'); + insert into t5(s) values('(s)'); + select 'Passed 2 - Insert' from t5 where sc = s||s having count(*) = 2; + + update t5 set s = 'by' where s = 'computed'; + select 'Passed 2 - Update' from t5 where sc = s||s having count(*) = 2; + + /*-------------------*/ + /* Computed by (s|s) */ + /*-------------------*/ + /* + ** Bug 6604: Use of "|" as concat operator not working + ** + create table t10 (s char(25), sc computed by (s|s)) + commit; -- t10 + insert into t10(s) values('computed') + insert into t10(s) values('(s)') + select 'Passed 3 - Insert' from t10 where sc = s|s having count(*) = 2 + + update t10 set s = 'by' where s = 'computed' + select 'Passed 3 - Update' from t10 where sc = s|s having count(*) = 2 + */ + + /*--------------------------*/ + /* Computed by (s||' test') */ + /*--------------------------*/ + create table t15 (s char(25), sc computed by (s||' test')); + commit; -- t15; + insert into t15(s) values('computed'); + insert into t15(s) values('(s||'' test'')'); + select 'Passed 4 - Insert' from t15 where sc = s||' test' having count(*) = 2; + + update t15 set s = 'by' where s = 'computed'; + select 'Passed 4 - Update' from t15 where sc = s||' test' having count(*) = 2; + + /*--------------------------*/ + /* Computed by ('test '||s) */ + /*--------------------------*/ + create table t20 (s char(25), sc computed by ('test '||s)); + commit; -- t20; + insert into t20(s) values('computed'); + insert into t20(s) values('(''test ''||s)'); + select 'Passed 5 - Insert' from t20 where sc = 'test '||s having count(*) = 2; + + update t20 set s = 'by' where s = 'computed'; + select 'Passed 5 - Update' from t20 where sc = 'test '||s having count(*) = 2; + + /*-----------------------------------*/ + /* Computed by ('test '||s||' test') */ + /*-----------------------------------*/ + create table t25 (s char(25), sc computed by ('test '||s||' test')); + commit; -- t25; + insert into t25(s) values('computed'); + insert into t25(s) values('(''test ''||s||'' test'')'); + select 'Passed 6 - Insert' from t25 where sc = 'test '||s||' test' having count(*) = 2; + + update t25 set s = 'by' where s = 'computed'; + select 'Passed 6 - Update' from t25 where sc = 'test '||s||' test' having count(*) = 2; + + /*----------------------*/ + /* Computed by ('test') */ + /*----------------------*/ + create table t30 (s char(25), sc computed by ('test')); + commit; -- t30; + insert into t30(s) values('computed'); + insert into t30(s) values('(''test'')'); + select 'Passed 7 - Insert' from t30 where sc = 'test' having count(*) = 2; + + update t30 set s = 'by' where s = 'computed'; + select 'Passed 7 - Update' from t30 where sc = 'test' having count(*) = 2; + + /*--------------------------------*/ + /* Computed by ('test '||' test') */ + /*--------------------------------*/ + create table t35 (s char(25), sc computed by ('test '||' test')); + commit; -- t35; + insert into t35(s) values('computed'); + insert into t35(s) values('(''test ''||'' test'')'); + select 'Passed 8 - Insert' from t35 where sc = 'test '||' test' having count(*) = 2; + + update t35 set s = 'by' where s = 'computed'; + select 'Passed 8 - Update' from t35 where sc = 'test '||' test' having count(*) = 2; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Passed 1 - Insert + Passed 1 - Update + Passed 2 - Insert + Passed 2 - Update + Passed 4 - Insert + Passed 4 - Update + Passed 5 - Insert + Passed 5 - Update + Passed 6 - Insert + Passed 6 - Update + Passed 7 - Insert + Passed 7 - Update + Passed 8 - Insert + Passed 8 - Update + """ + +@pytest.mark.version('>=2.5') +def test_computed_fields_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_computed_fields_04.py b/tests/functional/gtcs/test_computed_fields_04.py new file mode 100644 index 00000000..d565b162 --- /dev/null +++ b/tests/functional/gtcs/test_computed_fields_04.py @@ -0,0 +1,162 @@ +#coding:utf-8 +# +# id: functional.gtcs.computed_fields_04 +# title: computed-fields-04 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_04.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + + /* + ** Syntax test cases - Valid string operations NOTE: VARCHAR datatype is used here. + */ + + /*-----------------*/ + /* Computed by (s) */ + /*-----------------*/ + create table t0 (s varchar(25), sc computed by (s)); + commit; -- t0; + insert into t0(s) values('computed'); + insert into t0(s) values('(s)'); + select 'Passed 1 - Insert' from t0 where sc = s having count(*) = 2; + + update t0 set s = 'by' where s = 'computed'; + select 'Passed 1 - Update' from t0 where sc = s having count(*) = 2; + + /*--------------------*/ + /* Computed by (s||s) */ + /*--------------------*/ + create table t5 (s varchar(25), sc computed by (s||s)); + commit; -- t5; + insert into t5(s) values('computed'); + insert into t5(s) values('(s)'); + select 'Passed 2 - Insert' from t5 where sc = s||s having count(*) = 2; + + update t5 set s = 'by' where s = 'computed'; + select 'Passed 2 - Update' from t5 where sc = s||s having count(*) = 2; + + /*-------------------*/ + /* Computed by (s|s) */ + /*-------------------*/ + /* + ** Bug 6604: Use of "|" as concat operator not working + ** + create table t10 (s varchar(25), sc computed by (s|s)) + commit; -- t10 + insert into t10(s) values('computed') + insert into t10(s) values('(s)') + select 'Passed 3 - Insert' from t10 where sc = s|s having count(*) = 2 + + update t10 set s = 'by' where s = 'computed' + select 'Passed 3 - Update' from t10 where sc = s|s having count(*) = 2 + */ + + /*--------------------------*/ + /* Computed by (s||' test') */ + /*--------------------------*/ + create table t15 (s varchar(25), sc computed by (s||' test')); + commit; -- t15; + insert into t15(s) values('computed'); + insert into t15(s) values('(s||'' test'')'); + select 'Passed 4 - Insert' from t15 where sc = s||' test' having count(*) = 2; + + update t15 set s = 'by' where s = 'computed'; + select 'Passed 4 - Update' from t15 where sc = s||' test' having count(*) = 2; + + /*--------------------------*/ + /* Computed by ('test '||s) */ + /*--------------------------*/ + create table t20 (s varchar(25), sc computed by ('test '||s)); + commit; -- t20; + insert into t20(s) values('computed'); + insert into t20(s) values('(''test ''||s)'); + select 'Passed 5 - Insert' from t20 where sc = 'test '||s having count(*) = 2; + + update t20 set s = 'by' where s = 'computed'; + select 'Passed 5 - Update' from t20 where sc = 'test '||s having count(*) = 2; + + /*-----------------------------------*/ + /* Computed by ('test '||s||' test') */ + /*-----------------------------------*/ + create table t25 (s varchar(25), sc computed by ('test '||s||' test')); + commit; -- t25; + insert into t25(s) values('computed'); + insert into t25(s) values('(''test ''||s||'' test'')'); + select 'Passed 6 - Insert' from t25 where sc = 'test '||s||' test' having count(*) = 2; + + update t25 set s = 'by' where s = 'computed'; + select 'Passed 6 - Update' from t25 where sc = 'test '||s||' test' having count(*) = 2; + + /*----------------------*/ + /* Computed by ('test') */ + /*----------------------*/ + create table t30 (s varchar(25), sc computed by ('test')); + commit; -- t30; + insert into t30(s) values('computed'); + insert into t30(s) values('(''test'')'); + select 'Passed 7 - Insert' from t30 where sc = 'test' having count(*) = 2; + + update t30 set s = 'by' where s = 'computed'; + select 'Passed 7 - Update' from t30 where sc = 'test' having count(*) = 2; + + /*--------------------------------*/ + /* Computed by ('test '||' test') */ + /*--------------------------------*/ + create table t35 (s varchar(25), sc computed by ('test '||' test')); + commit; -- t35; + insert into t35(s) values('computed'); + insert into t35(s) values('(''test ''||'' test'')'); + select 'Passed 8 - Insert' from t35 where sc = 'test '||' test' having count(*) = 2; + + update t35 set s = 'by' where s = 'computed'; + select 'Passed 8 - Update' from t35 where sc = 'test '||' test' having count(*) = 2; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Passed 1 - Insert + Passed 1 - Update + Passed 2 - Insert + Passed 2 - Update + Passed 4 - Insert + Passed 4 - Update + Passed 5 - Insert + Passed 5 - Update + Passed 6 - Insert + Passed 6 - Update + Passed 7 - Insert + Passed 7 - Update + Passed 8 - Insert + Passed 8 - Update + """ + +@pytest.mark.version('>=2.5') +def test_computed_fields_04_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_computed_fields_05.py b/tests/functional/gtcs/test_computed_fields_05.py new file mode 100644 index 00000000..ffc2f8bf --- /dev/null +++ b/tests/functional/gtcs/test_computed_fields_05.py @@ -0,0 +1,151 @@ +#coding:utf-8 +# +# id: functional.gtcs.computed_fields_05 +# title: computed-fields-05 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_05.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + + /* + ** Syntax test cases - Valid DATE operations + */ + + /*-----------------*/ + /* Computed by (d) */ + /*-----------------*/ + create table t0 (d date, dc computed by (d)); + commit; -- t0; + insert into t0(d) values('today'); + insert into t0(d) values('tomorrow'); + insert into t0(d) values('yesterday'); + insert into t0(d) values('now'); + select 'Passed 1 - Insert' from t0 where dc = d having count(*) = 4; + + /*----------------------------------------------------------------*/ + /* Note: Using cast() to convert 'today' first to a date literal. */ + /* And, then doing date arithmetic. The proper behaviour */ + /* should just allow straight date addition as */ + /* set d = 'today' + 5. There is already a bug entered about*/ + /* this (Bug No. xxxx). Change this test case once this */ + /* bug is fixed. */ + /*----------------------------------------------------------------*/ + update t0 set d = cast('today'as date) + 5 where d = 'today'; + select 'Passed 1 - Update' from t0 where dc = d having count(*) = 4; + + /*---------------------*/ + /* Computed by (d + 1) */ + /*---------------------*/ + create table t5 (d date, dc computed by (d + 1)); + commit; -- t5; + insert into t5(d) values('today'); + insert into t5(d) values('tomorrow'); + insert into t5(d) values('yesterday'); + insert into t5(d) values('now'); + select 'Passed 2 - Insert' from t5 where dc = d + 1 having count(*) = 4; + + update t5 set d = cast('today' as date) + 5 where d = 'today'; + select 'Passed 2 - Update' from t5 where dc = d + 1 having count(*) = 4; + + /*---------------------*/ + /* Computed by (d - 1) */ + /*---------------------*/ + create table t10 (d date, dc computed by (d - 1)); + commit; -- t10; + insert into t10(d) values('today'); + insert into t10(d) values('tomorrow'); + insert into t10(d) values('yesterday'); + insert into t10(d) values('now'); + select 'Passed 3 - Insert' from t10 where dc = d - 1 having count(*) = 4; + + update t10 set d = cast('today' as date) - 5 where d = 'today'; + select 'Passed 3 - Update' from t10 where dc = d - 1 having count(*) = 4; + + /*-----------------------*/ + /* Computed by ('today') */ + /*-----------------------*/ + create table t15 (d date, dc computed by ('today')); + commit; -- t15; + insert into t15(d) values('today'); + insert into t15(d) values('tomorrow'); + insert into t15(d) values('yesterday'); + insert into t15(d) values('now'); + select 'Passed 4 - Insert' from t15 where dc = 'today' having count(*) = 4; + + update t15 set d = cast('today' as date) + 5 where d = 'today'; + select 'Passed 4 - Update' from t15 where dc = 'today' having count(*) = 4; + + /*---------------------------*/ + /* Computed by ('today' + 1) */ + /*---------------------------*/ + create table t20 (d date, dc computed by (cast('today' as date) + 1 )); + commit; -- t20; + insert into t20(d) values('today'); + insert into t20(d) values('tomorrow'); + insert into t20(d) values('yesterday'); + insert into t20(d) values('now'); + select 'Passed 5 - Insert' from t20 where dc = cast('today' as date) + 1 having count(*) = 4; + + update t20 set d = cast('today' as date) + 5 where d = 'today'; + select 'Passed 5 - Update' from t20 where dc = cast('today' as date) + 1 having count(*) = 4; + + /*-----------------------*/ + /* Computed by (d1 - d2) */ + /*-----------------------*/ + create table t25 (d_start date, d_end date, date_diff computed by (d_end - d_start)); + commit; -- t25; + insert into t25(d_start, d_end) values('yesterday', 'today'); + insert into t25(d_start, d_end) values('today', 'tomorrow'); + insert into t25(d_start, d_end) values('yesterday', 'tomorrow'); + select 'Passed 6 - Insert' from t25 where date_diff = d_end - d_start having count(*) = 3; + + update t25 set d_end = cast('today' as date) + 5 where d_start = 'today'; + select 'Passed 6 - Update' from t25 where date_diff = d_end - d_start having count(*) = 3; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Passed 1 - Insert + Passed 1 - Update + Passed 2 - Insert + Passed 2 - Update + Passed 3 - Insert + Passed 3 - Update + Passed 4 - Insert + Passed 4 - Update + Passed 5 - Insert + Passed 5 - Update + Passed 6 - Insert + Passed 6 - Update + """ + +@pytest.mark.version('>=2.5') +def test_computed_fields_05_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_computed_fields_06.py b/tests/functional/gtcs/test_computed_fields_06.py new file mode 100644 index 00000000..0adb066a --- /dev/null +++ b/tests/functional/gtcs/test_computed_fields_06.py @@ -0,0 +1,93 @@ +#coding:utf-8 +# +# id: functional.gtcs.computed_fields_06 +# title: computed-fields-06 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_06.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + + /* + ** Test case which defines computed field with expression that involves more than one column + */ + + /*-------------------*/ + /* Computed by (a*b) */ + /*-------------------*/ + create table t0 (a integer, b integer, a_b computed by (a*b)); + commit; -- t0; + insert into t0(a,b) values(10,10); + insert into t0(a,b) values(11,11); + select 'Passed 1 - Insert' from t0 where a_b = a*b having count(*) = 2; + + update t0 set a = 12, b = 12 where a = 10; + update t0 set a = 13 where a = 11; + select 'Passed 1 - Update' from t0 where a_b = a*b having count(*) = 2; + + /*---------------------*/ + /* Computed by (a*b/c) */ + /*---------------------*/ + create table t5 (a integer, b integer, c integer, a_b_c computed by (a*b/c)); + commit; -- t5; + insert into t5(a,b,c) values(10,10,10); + insert into t5(a,b,c) values(11,11,11); + select 'Passed 2 - Insert' from t5 where a_b_c = a*b/c having count(*) = 2; + + update t5 set a = 12, b = 12, c = 12 where a = 10; + update t5 set a = 13 where a = 11; + select 'Passed 2 - Update' from t5 where a_b_c = a*b/c having count(*) = 2; + + /*----------------------*/ + /* Computed by (a/10*b) */ + /*----------------------*/ + create table t10 (a integer, b integer, a_b_const computed by (a/10*b)); + commit; -- t10; + insert into t10(a,b) values(10,10); + insert into t10(a,b) values(11,11); + select 'Passed 3 - Insert' from t10 where a_b_const = a/10*b having count(*) = 2; + + update t10 set a = 12, b = 12 where a = 10; + update t10 set a = 13 where a = 11; + select 'Passed 3 - Update' from t10 where a_b_const = a/10*b having count(*) = 2; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Passed 1 - Insert + Passed 1 - Update + Passed 2 - Insert + Passed 2 - Update + Passed 3 - Insert + Passed 3 - Update + """ + +@pytest.mark.version('>=2.5') +def test_computed_fields_06_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_computed_fields_07.py b/tests/functional/gtcs/test_computed_fields_07.py new file mode 100644 index 00000000..155e9e95 --- /dev/null +++ b/tests/functional/gtcs/test_computed_fields_07.py @@ -0,0 +1,194 @@ +#coding:utf-8 +# +# id: functional.gtcs.computed_fields_07 +# title: computed-fields-07 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_07.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# ::: NOTE :::: +# DATABASE MUST BE CREATED IN DIALECT 1 FOR THIS TEST +# ::::::::::::: +# Otherwise some of cases will get error related to forbidden actions, e.g.: +# Statement failed, SQLSTATE = 42000 +# Dynamic SQL Error +# -expression evaluation not supported +# -Strings cannot be added or subtracted in dialect 3 +# +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=1, init=init_script_1) + +test_script_1 = """ + set bail on; + set warnings off; + set heading off; + + /* + Test case which defines computed field on more than one column of different types. + */ + + create table t0 (f_integer integer, f_float float, integer_float computed by (f_integer*f_float)); + commit; -- t0; + insert into t0(f_integer,f_float) values(10,10.12); + insert into t0(f_integer,f_float) values(11,11.12); + select 'Passed 1 - Insert' from t0 where integer_float = f_integer*f_float having count(*) = 2; + select * from t0; + + update t0 set f_integer = 12, f_float = 12.12 where f_integer = 10; + update t0 set f_integer = 13 where f_integer = 11; + select 'Passed 1 - Update' from t0 where integer_float = f_integer*f_float having count(*) = 2; + select * from t0; + + /*-------------------------------*/ + /* Computed by integer*character */ + /*-------------------------------*/ + create table t5 (f_integer integer, f_char char(5), integer_char computed by (f_integer*f_char)); + commit; -- t5; + insert into t5(f_integer, f_char) values(10,'10'); + insert into t5(f_integer, f_char) values(11,'11'); + select 'Passed 2 - Insert' from t5 where integer_char = f_integer*f_char having count(*) = 2; + select * from t5; + + update t5 set f_integer = 12, f_char = '12.25' where f_integer = 10; + update t5 set f_integer = 13 where f_integer = 11; + select 'Passed 2 - Update' from t5 where integer_char = f_integer*f_char having count(*) = 2; + select * from t5; + + /*-----------------------------*/ + /* Computed by float*character */ + /*-----------------------------*/ + create table t10 (f_float float, f_char char(5), float_char computed by (f_float*f_char)); + commit; -- t10; + insert into t10(f_float, f_char) values(10.12,'10'); + insert into t10(f_float, f_char) values(11.12,'11'); + select 'Passed 2 - Insert' from t10 where float_char = f_float*f_char having count(*) = 2; + + update t10 set f_float = 12.12, f_char = '12' where f_float = 10.12; + update t10 set f_float = 13.12 where f_float = 11.12; + select 'Passed 2 - Update' from t10 where float_char = f_float*f_char having count(*) = 2; + + /*------------------------*/ + /* Computed by float+date */ + /* Note: Currently the associativity doesn't work. That is, the test case is */ + /* using date+float as expression. This is suppose to be fixed in */ + /* build T. */ + /*------------------------*/ + create table t15 (f_float float, f_date date, float_date computed by (f_date+f_float)); + commit; -- t15; + insert into t15(f_float, f_date) values(10.12,'today'); + insert into t15(f_float, f_date) values(11.12,'today'); + select 'Passed 3 - Insert' from t15 where float_date = f_date+f_float having count(*) = 2; + + update t15 set f_float = 12.12, f_date = 'tomorrow' where f_float = 10.12; + update t15 set f_float = 13.12 where f_float = 11.12; + select 'Passed 3 - Update' from t15 where float_date = f_date+f_float having count(*) = 2; + + + /*-------------------------*/ + /* Computed by char - date */ + /*-------------------------*/ + create table t20 (f_char char(15), f_date date, char_date computed by (f_char - f_date)); + commit; -- t20; + insert into t20(f_char, f_date) values('01/20/93','01/01/93'); + insert into t20(f_char, f_date) values('02/27/93','02/01/93'); + select 'Passed 4 - Insert' from t20 where char_date = f_char - f_date having count(*) = 2; + + update t20 set f_char = '03/20/93', f_date = '03/01/93' where f_char = '01/20/93'; + update t20 set f_char = '02/26/93' where f_char = '02/27/93'; + select 'Passed 4 - Update' from t20 where char_date = f_char - f_date having count(*) = 2; + + + /*----------------------------*/ + /* Computed by "10" + integer */ + /*----------------------------*/ + create table t25 (f_integer integer, literal_integer computed by ('10' + f_integer)); + commit; -- t25; + insert into t25(f_integer) values(10); + insert into t25(f_integer) values(11); + select 'Passed 5 - Insert' from t25 where literal_integer = '10' + f_integer having count(*) = 2; + + update t25 set f_integer = 12 where f_integer = 10; + select 'Passed 5 - Update' from t25 where literal_integer = '10' + f_integer having count(*) = 2; + + /*----------------------------*/ + /* Computed by "1.12" + float */ + /*----------------------------*/ + create table t30 (f_float float, literal_float computed by ('1.12' + f_float)); + commit; -- t30; + insert into t30(f_float) values(10.12); + insert into t30(f_float) values(11.12); + select 'Passed 6 - Insert' from t30 where literal_float = '1.12' + f_float having count(*) = 2; + + update t30 set f_float = 12.12 where f_float = 10.12; + select 'Passed 6 - Update' from t30 where literal_float = '1.12' + f_float having count(*) = 2; + + /*-------------------------------*/ + /* Computed by "01/01/95" - date */ + /*-------------------------------*/ + create table t35 (f_date date, literal_date computed by ('01/01/95' - f_date)); + commit; -- t35; + insert into t35(f_date) values('01/01/94'); + insert into t35(f_date) values('02/01/94'); + select 'Passed 7 - Insert' from t35 where literal_date = '01/01/95' - f_date having count(*) = 2; + + update t35 set f_date = '03/01/94' where f_date = '01/01/94'; + select 'Passed 7 - Update' from t35 where literal_date = '01/01/95' - f_date having count(*) = 2; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Passed 1 - Insert + 10 10.120000 101.1999988555908 + 11 11.120000 122.3199987411499 + + Passed 1 - Update + 12 12.120000 145.4399986267090 + 13 11.120000 144.5599985122681 + + Passed 2 - Insert + 10 10 100.0000000000000 + 11 11 121.0000000000000 + + Passed 2 - Update + 12 12.25 147.0000000000000 + 13 11 143.0000000000000 + + Passed 2 - Insert + Passed 2 - Update + Passed 3 - Insert + Passed 3 - Update + Passed 4 - Insert + Passed 4 - Update + Passed 5 - Insert + Passed 5 - Update + Passed 6 - Insert + Passed 6 - Update + Passed 7 - Insert + Passed 7 - Update + """ + +@pytest.mark.version('>=2.5') +def test_computed_fields_07_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_computed_fields_08.py b/tests/functional/gtcs/test_computed_fields_08.py new file mode 100644 index 00000000..93ee87b4 --- /dev/null +++ b/tests/functional/gtcs/test_computed_fields_08.py @@ -0,0 +1,75 @@ +#coding:utf-8 +# +# id: functional.gtcs.computed_fields_08 +# title: computed-fields-08 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_08.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set heading off; + /*----------------------*/ + /* Computed by UPPER(a) */ + /*----------------------*/ + create table t0 (a char(25), upper_a computed by (upper(a))); + commit; -- t0; + insert into t0(a) values('abcdef'); + insert into t0(a) values('ABCDEF'); + insert into t0(a) values('123456'); + insert into t0(a) values('aBcDeF'); + select 'Passed 1 - Insert' from t0 where upper_a = upper(a) having count(*) = 4; + + update t0 set a = 'xyz' where a = 'abc'; + select 'Passed 1 - Update' from t0 where upper_a = upper(a) having count(*) = 4; + + /*-----------------------------------*/ + /* Computed by a || UPPER('upper()') */ + /*-----------------------------------*/ + create table t5 (a char(25), upper_const computed by (a || upper('upper()'))); + commit; -- t5; + insert into t5(a) values('abcdef'); + insert into t5(a) values('ABCDEF'); + insert into t5(a) values('123456'); + insert into t5(a) values('aBcDeF'); + select 'Passed 2 - Insert' from t5 where upper_const = a || upper('upper()') having count(*) = 4; + + update t5 set a = 'xyz' where a = 'abcdef'; + select 'Passed 2 - Update' from t5 where upper_const = a || upper('upper()') having count(*) = 4; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Passed 1 - Insert + Passed 1 - Update + Passed 2 - Insert + Passed 2 - Update + """ + +@pytest.mark.version('>=2.5') +def test_computed_fields_08_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_computed_fields_09.py b/tests/functional/gtcs/test_computed_fields_09.py new file mode 100644 index 00000000..5f65059d --- /dev/null +++ b/tests/functional/gtcs/test_computed_fields_09.py @@ -0,0 +1,132 @@ +#coding:utf-8 +# +# id: functional.gtcs.computed_fields_09 +# title: computed-fields-09 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_09.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set heading off; + + -- Test verifies COMPUTED-BY field which expression uses CAST + -- of miscelaneous non-text datatypes to char and vice versa. + + /*-----------------------------------*/ + /* Computed by CAST(char as integer) */ + /*-----------------------------------*/ + create table t0 (f_char char(25), char_as_int computed by (cast(f_char as integer))); + commit; -- t0; + insert into t0(f_char) values('10'); + insert into t0(f_char) values('11'); + select 'Passed 1 - Insert' from t0 where char_as_int = cast(f_char as integer) having count(*) = 2; + + update t0 set f_char = '12' where f_char = '10'; + select 'Passed 1 - Update' from t0 where char_as_int = cast(f_char as integer) having count(*) = 2; + + /*---------------------------------*/ + /* Computed by CAST(char as float) */ + /*---------------------------------*/ + create table t5 (f_char char(25), char_as_float computed by (cast(f_char as float))); + commit; -- t5; + insert into t5(f_char) values('10.12'); + insert into t5(f_char) values('11.12'); + select 'Passed 2 - Insert' from t5 where char_as_float = cast(f_char as float) having count(*) = 2; + + update t5 set f_char = '12.12' where f_char = '10.12'; + select 'Passed 2 - Update' from t5 where char_as_float = cast(f_char as float) having count(*) = 2; + + /*--------------------------------*/ + /* Computed by CAST(char as date) */ + /*--------------------------------*/ + create table t10(f_char char(25), char_as_date computed by (cast(f_char as date))); + commit; -- t10; + insert into t10(f_char) values('01/01/93'); + insert into t10(f_char) values('02/01/95'); + select 'Passed 3 - Insert' from t10 where char_as_date = cast(f_char as date) having count(*) = 2; + + update t10 set f_char = '02/01/94' where f_char = '01/01/93'; + select 'Passed 3 - Update' from t10 where char_as_date = cast(f_char as date) having count(*) = 2; + + /*--------------------------------*/ + /* Computed by CAST(date as char) */ + /*--------------------------------*/ + create table t15(f_date date, date_as_char computed by (cast(f_date as char(15)))); + commit; -- t15; + insert into t15(f_date) values('today'); + insert into t15(f_date) values('tomorrow'); + select 'Passed 4 - Insert' from t15 where date_as_char = cast(f_date as char(15)) having count(*) = 2; + + update t15 set f_date = 'yesterday' where f_date = 'today'; + select 'Passed 4 - Update' from t15 where date_as_char = cast(f_date as char(15)) having count(*) = 2; + + /*-------------------------------*/ + /* Computed by CAST(int as char) */ + /*-------------------------------*/ + create table t20(f_int integer, int_as_char computed by (cast(f_int as char(15)))); + commit; -- t20; + insert into t20(f_int) values(10); + insert into t20(f_int) values(11); + select 'Passed 5 - Insert' from t20 where int_as_char = cast(f_int as char(15)) having count(*) = 2; + + update t20 set f_int = 12 where f_int = 10; + select 'Passed 5 - Update' from t20 where int_as_char = cast(f_int as char(15)) having count(*) = 2; + + /*---------------------------------*/ + /* Computed by CAST(float as char) */ + /*---------------------------------*/ + create table t25(f_float float, float_as_char computed by (cast(f_float as char(15)))); + commit; -- t25; + insert into t25(f_float) values(10.12); + insert into t25(f_float) values(11.12); + select 'Passed 6 - Insert' from t25 where float_as_char = cast(f_float as char(15)) having count(*) = 2; + + update t25 set f_float = 12.12 where f_float = 10.12; + select 'Passed 6 - Update' from t25 where float_as_char = cast(f_float as char(15)) having count(*) = 2; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Passed 1 - Insert + Passed 1 - Update + Passed 2 - Insert + Passed 2 - Update + Passed 3 - Insert + Passed 3 - Update + Passed 4 - Insert + Passed 4 - Update + Passed 5 - Insert + Passed 5 - Update + Passed 6 - Insert + Passed 6 - Update + """ + +@pytest.mark.version('>=2.5') +def test_computed_fields_09_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_computed_fields_10.py b/tests/functional/gtcs/test_computed_fields_10.py new file mode 100644 index 00000000..0e1a18e1 --- /dev/null +++ b/tests/functional/gtcs/test_computed_fields_10.py @@ -0,0 +1,77 @@ +#coding:utf-8 +# +# id: functional.gtcs.computed_fields_10 +# title: computed-fields-10 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_10.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set heading off; + + -- Test verifies COMPUTED-BY field which expression involves GEN_ID() call. + + create generator gen1; + set generator gen1 to 1000; + commit; -- show generator gen1; + + /*----------------------------*/ + /* Computed by (a + gen_id()) */ + /*----------------------------*/ + create table t0 (a integer, genid_field computed by (a + gen_id(gen1, 1))); + commit; -- t0; + insert into t0(a) values(10); + insert into t0(a) values(12); + select * from t0; + + set generator gen1 to 1000; + select * from t0; + + /* + ** Since computed fields are evaluated during run-time, the computed + ** field with gen_id() will be different every-time. So, the following + ** select will never have a match. + */ + set generator gen1 to 1000; + select * from t0 where genid_field = gen_id(gen1, 1); + + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 10 1011 + 12 1014 + + 10 1011 + 12 1014 + """ + +@pytest.mark.version('>=2.5') +def test_computed_fields_10_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_computed_fields_11.py b/tests/functional/gtcs/test_computed_fields_11.py new file mode 100644 index 00000000..c2e04bbb --- /dev/null +++ b/tests/functional/gtcs/test_computed_fields_11.py @@ -0,0 +1,90 @@ +#coding:utf-8 +# +# id: functional.gtcs.computed_fields_11 +# title: computed-fields-11 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_11.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('^((?!Statement failed|SQL error code|Column unknown|F01|F02|REL_NAME|Records).)*$', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + set list on; + set count on; + + /*-----------------------------------------*/ + /* Computed field using non-existing field */ + /*-----------------------------------------*/ + create table t0 (f01 integer, f_calc computed by (f02)); + + /*--------------------------------------------*/ + /* Computed field using not yet defined field */ + /*--------------------------------------------*/ + create table t1 (f_calc computed by (f01), f01 integer); + + recreate table t2(f01 int, f99 int); + commit; + alter table t2 + add f_calc computed by( f01 + f99) + ,alter f99 position 3 -- MUST PASS! FB 3+ will produce correct script if we want to extract metadata using isql -x. + --,drop f99 -- Statement failed, SQLSTATE = 42S22 / invalid request BLR at offset 13 / -column f99 is not defined in table T2 + ; + commit; + + select r.rdb$relation_name as rel_name + from rdb$relations r + where r.rdb$relation_name in ( upper('t0'), upper('t1'), upper('t2') ) + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + REL_NAME T2 + Records affected: 1 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42S22 + unsuccessful metadata update + -CREATE TABLE T0 failed + -Dynamic SQL Error + -SQL error code = -206 + -Column unknown + -F02 + + Statement failed, SQLSTATE = 42S22 + unsuccessful metadata update + -CREATE TABLE T1 failed + -Dynamic SQL Error + -SQL error code = -206 + -Column unknown + -F01 + """ + +@pytest.mark.version('>=2.5') +def test_computed_fields_11_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_computed_fields_12.py b/tests/functional/gtcs/test_computed_fields_12.py new file mode 100644 index 00000000..bc635e73 --- /dev/null +++ b/tests/functional/gtcs/test_computed_fields_12.py @@ -0,0 +1,56 @@ +#coding:utf-8 +# +# id: functional.gtcs.computed_fields_12 +# title: computed-fields-12 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_12.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + set list on; + /*---------------------------------------------*/ + /* Computed field using another computed field */ + /*---------------------------------------------*/ + create table t3 (a integer, af computed by (a*3), afaf computed by (af*2)); + insert into t3(a) values(10); + + set count on; + select * from t3; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A 10 + AF 30 + AFAF 60 + Records affected: 1 + """ + +@pytest.mark.version('>=2.5') +def test_computed_fields_12_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_computed_fields_13.py b/tests/functional/gtcs/test_computed_fields_13.py new file mode 100644 index 00000000..ba6010e2 --- /dev/null +++ b/tests/functional/gtcs/test_computed_fields_13.py @@ -0,0 +1,88 @@ +#coding:utf-8 +# +# id: functional.gtcs.computed_fields_13 +# title: computed-fields-13 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_13.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + /*---------------------------------------------*/ + /* Create a table with computed field. */ + /*---------------------------------------------*/ + create table t0 (a integer, af computed by (a*3)); + insert into t0(a) values(10); + + /*---------------------------------------------*/ + /* Create a table with nested computed field. */ + /*---------------------------------------------*/ + create table t1 (a integer, af computed by (a*4), afaf computed by (af*5)); + insert into t1(a) values(11); + + commit; + + /*---------------------------------------------------------------------*/ + /* Now alter table and drop the field which is used in computed field. */ + /* It shouldn't allow you to drop the field. */ + /*---------------------------------------------------------------------*/ + alter table t0 drop a; + select 'point-1' msg, p.* from t0 p; + + /*---------------------------------------------------------------------*/ + /* Now alter table and drop the computed field which is used in other */ + /* computed field. */ + /* It shouldn't allow you to drop the field. */ + /*---------------------------------------------------------------------*/ + alter table t1 drop af; + select 'point-2' msg, p.* from t1 p; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + point-1 10 30 + point-2 11 44 220 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE 42000 + unsuccessful metadata update + -cannot delete + -COLUMN T0.A + -there are 1 dependencies + Statement failed, SQLSTATE 42000 + + unsuccessful metadata update + -cannot delete + -COLUMN T1.AF + -there are 1 dependencies + """ + +@pytest.mark.version('>=2.5') +def test_computed_fields_13_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_computed_fields_14.py b/tests/functional/gtcs/test_computed_fields_14.py new file mode 100644 index 00000000..961fe483 --- /dev/null +++ b/tests/functional/gtcs/test_computed_fields_14.py @@ -0,0 +1,93 @@ +#coding:utf-8 +# +# id: functional.gtcs.computed_fields_14 +# title: GTCS/tests/CF_ISQL_14; computed-fields-14 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_14.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' '), ('attempted update of read-only column.*', 'attempted update of read-only column')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + /*---------------------------------------------*/ + /* Create a table with computed field. */ + /*---------------------------------------------*/ + create table t0 (a integer, af computed by (a*3)); + insert into t0(a) values(10); + + /*---------------------------------------------------------------*/ + /* Insert a value into computed-field column, which should fail. */ + /*---------------------------------------------------------------*/ + insert into t0(af) values(11); + select 'point-1' msg, p.* from t0 p; + + /*---------------------------------------------------------------*/ + /* Update the computed-field column directly, which should fail. */ + /*---------------------------------------------------------------*/ + update t0 set af = 99 where a = 10; + select 'point-2' msg, p.* from t0 p; + + /*---------------------------------------------------------------*/ + /* Create a table with only a computed-field should fail. */ + /*---------------------------------------------------------------*/ + create table t5 (af computed by (1+2)); + + /*-----------------------------------------------------------------*/ + /* Create a table with a computed-field, which has constant value. */ + /* Trying to insert a value in it should fail. */ + /*-----------------------------------------------------------------*/ + create table t6 (af int, bf computed by (1+2)); + insert into t6 values(10, 12); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + point-1 10 30 + point-2 10 30 + """ +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 + unsuccessful metadata update + -TABLE T5 + -Can't have relation with only computed fields or constraints + + Statement failed, SQLSTATE 21S01 + Dynamic SQL Error + -SQL error code -804 + -Count of read-write columns does not equal count of values + """ + +@pytest.mark.version('>=2.5') +def test_computed_fields_14_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_computed_fields_15.py b/tests/functional/gtcs/test_computed_fields_15.py new file mode 100644 index 00000000..c2dc1413 --- /dev/null +++ b/tests/functional/gtcs/test_computed_fields_15.py @@ -0,0 +1,52 @@ +#coding:utf-8 +# +# id: functional.gtcs.computed_fields_15 +# title: computed-fields-15 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_15.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('^((?!Statement failed|SQL error code).)*$', ''), (' = ', ' '), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + /*-----------------------------------------------------------------------------*/ + /* Create a table with computed field which is defined using non-existing UDF. */ + /*-----------------------------------------------------------------------------*/ + create table t0 (a integer, af computed by ( non_exist_udf(a) )); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE 39000 + Dynamic SQL Error + -SQL error code -804 + -Function unknown + -NON_EXIST_UDF + """ + +@pytest.mark.version('>=2.5') +def test_computed_fields_15_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/gtcs/test_computed_fields_16.py b/tests/functional/gtcs/test_computed_fields_16.py new file mode 100644 index 00000000..d99eeff2 --- /dev/null +++ b/tests/functional/gtcs/test_computed_fields_16.py @@ -0,0 +1,105 @@ +#coding:utf-8 +# +# id: functional.gtcs.computed_fields_16 +# title: computed-fields-16 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_16.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + /*-------------------------------------------------------------*/ + /* Create a table with computed field and improper attributes. */ + /*-------------------------------------------------------------*/ + + recreate table t0 (a integer, af computed by (a*3) default 10); + + recreate table t1 (a integer, af computed by (a*3) not null); + + recreate table t2 (a char(5), af computed by (a||a) collate DOS850); + + recreate table t3 (a integer, af computed by (a*3) check (a > 3)); + + recreate table t4 (a integer primary key); + + recreate table t4r (a integer, af computed by (a*3) references t4(a)); + + + recreate table t5 (a integer, af computed by (a*3) unique); + + recreate table t6 (a integer, af computed by (a*3) primary key); + + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Token unknown - line 1, column 52 + -default + + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Token unknown - line 1, column 52 + -not + + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Token unknown - line 1, column 53 + -collate + + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Token unknown - line 1, column 52 + -check + + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Token unknown - line 1, column 53 + -references + + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Token unknown - line 1, column 52 + -unique + + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Token unknown - line 1, column 52 + -primary + """ + +@pytest.mark.version('>=2.5') +def test_computed_fields_16_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/gtcs/test_computed_fields_17.py b/tests/functional/gtcs/test_computed_fields_17.py new file mode 100644 index 00000000..33495025 --- /dev/null +++ b/tests/functional/gtcs/test_computed_fields_17.py @@ -0,0 +1,140 @@ +#coding:utf-8 +# +# id: functional.gtcs.computed_fields_17 +# title: computed-fields-17 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_17.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create generator gen1; + set generator gen1 to 999; + + create generator gen2; + set generator gen2 to 199; + + create generator gen3; + set generator gen3 to 29; + + create table t0 ( + a integer, + genid_field1 computed by (gen_id(gen1, 1)), + genid_field2 computed by (gen_id(gen2, genid_field1)), + genid_field3 computed by (gen_id(gen3, genid_field2)) + ); + commit; + + insert into t0(a) values(4); + insert into t0(a) values(1); + + /************************************************* + first row: + a: 4 + genid_field3:=genid3+(genid2+(genid1+1)) + :=29+(199+(999+1) + :=29+(199+1000) + :=29+1199 + :=1228 + second row: + a: 1 + genid_field3:=genid3+(genid2+(genid1+1)) + :=1228+(1199+(1000+1) + :=1228+(1199+1001) + :=1228+(2200) + :=3428 + + so expected result is: + + A GENID_FIELD3 + ============ ===================== + + 4 1228 + 1 3428 + + *************************************************/ + + select 'point-1' msg, p.a, p.genid_field3 from t0 p; + + /************************************************* + first row: + a: 4 + genid_field3:=genid3+(genid2+(genid1+1)) + :=3428+(2200+(1001+1) + :=3428+(2200+1002) + :=3429+3202 + :=6630 + genid_field2:=genid2+(genid1+1) + :=3202+(1002+1) + :=3202+1003 + :=4205 + genid_field1:=genid1+1 + :=1003+1 + :=1004 + + second row: + a: 1 + genid_field3:=genid3+(genid2+(genid1+1)) + :=6630+(4205+(1004+1)) + :=6630+(4205+1005) + :=6630+5210 + :=11840 + genid_field2:=genid2+(genid1+1) + :=5210+(1005+1) + :=5210+1006 + :=6216 + genid_field1:=genid1+1 + :=1006+1 + :=1007 + + so expected result is: + + A GENID_FIELD1 GENID_FIELD2 GENID_FIELD3 + ============ ===================== ===================== ===================== + + 4 1004 4205 6630 + 1 1007 6216 11840 + + **************************************************/ + + select 'point-2' msg, p.* from t0 p; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG A GENID_FIELD3 + point-1 4 1228 + point-1 1 3428 + + MSG A GENID_FIELD1 GENID_FIELD2 GENID_FIELD3 + point-2 4 1004 4205 6630 + point-2 1 1007 6216 11840 + """ + +@pytest.mark.version('>=2.5') +def test_computed_fields_17_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_conversion_error_from_string.py b/tests/functional/gtcs/test_conversion_error_from_string.py new file mode 100644 index 00000000..3fe7e67b --- /dev/null +++ b/tests/functional/gtcs/test_conversion_error_from_string.py @@ -0,0 +1,438 @@ +#coding:utf-8 +# +# id: functional.gtcs.conversion_error_from_string +# title: GTCS/tests/CF_ISQL_31. Script issues conversion error from string "" +# decription: +# ::: NB ::: +# ### Name of original test has no any relation with actual task of this test: ### +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_31.script +# +# Source description of problem with script for reproducing: +# https://sourceforge.net/p/firebird/mailman/message/17016915/ +# +# Issue in original test: +# bug in devel-list / Reported by lobolo2000 18-May-2004 +# +# Checked on: 4.0.0.1804 SS; 3.0.6.33271 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create domain dm_id as bigint + not null; + + create domain dm_amount as numeric(18,4) + default 0 + not null; + + create domain dm_quantity as numeric(18,3) + default 0 + not null; + + create table items ( + uid dm_id primary key , + description varchar(80)); + + create table mitems ( + uid dm_id primary key, + item_uid dm_id references items(uid) on delete cascade, + mfield1 varchar(15) default '' not null, + mfield2 varchar(15) default '' not null, + mfield3 varchar(15) default '' not null, + mfield4 varchar(15) default '' not null); + + create table bs ( + uid dm_id primary key, + mitem_uid dm_id references mitems(uid) on delete cascade, + be varchar(25)); + + create table mitems_expiry ( + uid dm_id primary key, + mitem_uid dm_id references mitems(uid) on delete cascade, + expiry_date date); + + create table mitems_expiry_warehouses ( + uid dm_id primary key, + mitem_expiry_uid dm_id references mitems_expiry(uid) on delete cascade, + reorder_lvl dm_quantity, + restock_lvl dm_quantity, + qoh dm_quantity, + qoc dm_quantity, + qty_on_order dm_quantity, + qty_reserved dm_quantity, + dtd_qty_purchased dm_quantity, + mtd_qty_purchased dm_quantity, + ytd_qty_purchased dm_quantity, + dtd_qty_sold dm_quantity, + mtd_qty_sold dm_quantity, + ytd_qty_sold dm_quantity); + + alter table mitems_expiry + add reorder_lvl computed by (coalesce((select sum(reorder_lvl) from + + mitems_expiry_warehouses),0)), + add restock_lvl computed by (coalesce((select sum(restock_lvl) from + + mitems_expiry_warehouses),0)), + add qoh computed by (coalesce((select sum(qoh) from + mitems_expiry_warehouses),0)), + add qoc computed by (coalesce((select sum(qoc) from + mitems_expiry_warehouses),0)), + add qty_on_order computed by (coalesce((select sum(qty_on_order) from + + mitems_expiry_warehouses),0)), + add qty_reserved computed by (coalesce((select sum(qty_reserved) from + + mitems_expiry_warehouses),0)), + add dtd_qty_purchased computed by (coalesce((select sum(dtd_qty_purchased) + from + + mitems_expiry_warehouses),0)), + add mtd_qty_purchased computed by (coalesce((select sum(mtd_qty_purchased) + from + + mitems_expiry_warehouses),0)), + add ytd_qty_purchased computed by (coalesce((select sum(ytd_qty_purchased) + from + + mitems_expiry_warehouses),0)), + add dtd_qty_sold computed by (coalesce((select sum(dtd_qty_sold) from + + mitems_expiry_warehouses),0)), + add mtd_qty_sold computed by (coalesce((select sum(mtd_qty_sold) from + + mitems_expiry_warehouses),0)), + add ytd_qty_sold computed by (coalesce((select sum(ytd_qty_sold) from + + mitems_expiry_warehouses),0)); + + alter table mitems + add reorder_lvl computed by (coalesce((select sum(reorder_lvl) from + mitems_expiry),0)), + add restock_lvl computed by (coalesce((select sum(restock_lvl) from + mitems_expiry),0)), + add qoh computed by (coalesce((select sum(qoh) from mitems_expiry),0)), + add qoc computed by (coalesce((select sum(qoc) from mitems_expiry),0)), + add qty_on_order computed by (coalesce((select sum(qty_on_order) from + mitems_expiry),0)), + add qty_reserved computed by (coalesce((select sum(qty_reserved) from + mitems_expiry),0)), + add dtd_qty_purchased computed by (coalesce((select sum(dtd_qty_purchased) + from + + mitems_expiry),0)), + add mtd_qty_purchased computed by (coalesce((select sum(mtd_qty_purchased) + from + + mitems_expiry),0)), + add ytd_qty_purchased computed by (coalesce((select sum(ytd_qty_purchased) + from + + mitems_expiry),0)), + add dtd_qty_sold computed by (coalesce((select sum(dtd_qty_sold) from + mitems_expiry),0)), + add mtd_qty_sold computed by (coalesce((select sum(mtd_qty_sold) from + mitems_expiry),0)), + add ytd_qty_sold computed by (coalesce((select sum(ytd_qty_sold) from + mitems_expiry),0)); + + alter table items + add reorder_lvl computed by (coalesce((select sum(reorder_lvl) from + mitems),0)), + add restock_lvl computed by (coalesce((select sum(restock_lvl) from + mitems),0)), + add qoh computed by (coalesce((select sum(qoh) from mitems),0)), + add qoc computed by (coalesce((select sum(qoc) from mitems),0)), + add qty_on_order computed by (coalesce((select sum(qty_on_order) from + mitems),0)), + add qty_reserved computed by (coalesce((select sum(qty_reserved) from + mitems),0)), + add dtd_qty_purchased computed by (coalesce((select sum(dtd_qty_purchased) + from + + mitems),0)), + add mtd_qty_purchased computed by (coalesce((select sum(mtd_qty_purchased) + from + + mitems),0)), + add ytd_qty_purchased computed by (coalesce((select sum(ytd_qty_purchased) + from + + mitems),0)), + add dtd_qty_sold computed by (coalesce((select sum(dtd_qty_sold) from + mitems),0)), + add mtd_qty_sold computed by (coalesce((select sum(mtd_qty_sold) from + mitems),0)), + add ytd_qty_sold computed by (coalesce((select sum(ytd_qty_sold) from + mitems),0)); + + set term ^; + + create generator items_gen^ + + create trigger items_tr0 for items + active before insert position 0 as + begin + if (new.uid is null or new.uid<0) then new.uid=gen_id(items_gen,1); + end^ + + create trigger items_tr2 for items + active after insert position 2 as + begin + insert into mitems(item_uid) values(new.uid); + end^ + + create generator mitems_gen^ + + create trigger mitems_tr0 for mitems + active before insert position 0 as + begin + if (new.uid is null or new.uid<0) then new.uid=gen_id(mitems_gen,1); + end^ + + create generator bs_gen^ + + create trigger bs_tr0 for bs + active before insert position 0 as + begin + if (new.uid is null or new.uid<0) then new.uid=gen_id(bs_gen,1); + end^ + + create generator mitems_expiry_gen^ + + create trigger mitems_expiry_tr0 for mitems_expiry + active before insert position 0 as + begin + if (new.uid is null or new.uid<0) then + new.uid=gen_id(mitems_expiry_gen,1); + end^ + + create generator mitems_expiry_warehouses_gen^ + + create trigger mitems_expiry_warehouses_tr0 for mitems_expiry_warehouses + active before insert position 0 as + begin + if (new.uid is null or new.uid<0) then + + new.uid=gen_id(mitems_expiry_warehouses_gen,1); + end^ + + set term ;^ + + commit; + + insert into items(description) values('pa'); + insert into items(description) values('fa'); + insert into items(description) values('sa'); + insert into items(description) values('la'); + insert into items(description) values('ma'); + insert into items(description) values('ka'); + + commit; + + set list on; + set count on; + + select 'point-1' msg, m.* from items m; + select 'point-2' msg, m.qoh, m.qoh, m.qoh, m.qoh, m.qoh, m.qoh, m.qoh, m.qoh, m.qoh, m.qoh from items m; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG point-1 + UID 1 + DESCRIPTION pa + REORDER_LVL 0.000 + RESTOCK_LVL 0.000 + QOH 0.000 + QOC 0.000 + QTY_ON_ORDER 0.000 + QTY_RESERVED 0.000 + DTD_QTY_PURCHASED 0.000 + MTD_QTY_PURCHASED 0.000 + YTD_QTY_PURCHASED 0.000 + DTD_QTY_SOLD 0.000 + MTD_QTY_SOLD 0.000 + YTD_QTY_SOLD 0.000 + + MSG point-1 + UID 2 + DESCRIPTION fa + REORDER_LVL 0.000 + RESTOCK_LVL 0.000 + QOH 0.000 + QOC 0.000 + QTY_ON_ORDER 0.000 + QTY_RESERVED 0.000 + DTD_QTY_PURCHASED 0.000 + MTD_QTY_PURCHASED 0.000 + YTD_QTY_PURCHASED 0.000 + DTD_QTY_SOLD 0.000 + MTD_QTY_SOLD 0.000 + YTD_QTY_SOLD 0.000 + + MSG point-1 + UID 3 + DESCRIPTION sa + REORDER_LVL 0.000 + RESTOCK_LVL 0.000 + QOH 0.000 + QOC 0.000 + QTY_ON_ORDER 0.000 + QTY_RESERVED 0.000 + DTD_QTY_PURCHASED 0.000 + MTD_QTY_PURCHASED 0.000 + YTD_QTY_PURCHASED 0.000 + DTD_QTY_SOLD 0.000 + MTD_QTY_SOLD 0.000 + YTD_QTY_SOLD 0.000 + + MSG point-1 + UID 4 + DESCRIPTION la + REORDER_LVL 0.000 + RESTOCK_LVL 0.000 + QOH 0.000 + QOC 0.000 + QTY_ON_ORDER 0.000 + QTY_RESERVED 0.000 + DTD_QTY_PURCHASED 0.000 + MTD_QTY_PURCHASED 0.000 + YTD_QTY_PURCHASED 0.000 + DTD_QTY_SOLD 0.000 + MTD_QTY_SOLD 0.000 + YTD_QTY_SOLD 0.000 + + MSG point-1 + UID 5 + DESCRIPTION ma + REORDER_LVL 0.000 + RESTOCK_LVL 0.000 + QOH 0.000 + QOC 0.000 + QTY_ON_ORDER 0.000 + QTY_RESERVED 0.000 + DTD_QTY_PURCHASED 0.000 + MTD_QTY_PURCHASED 0.000 + YTD_QTY_PURCHASED 0.000 + DTD_QTY_SOLD 0.000 + MTD_QTY_SOLD 0.000 + YTD_QTY_SOLD 0.000 + + MSG point-1 + UID 6 + DESCRIPTION ka + REORDER_LVL 0.000 + RESTOCK_LVL 0.000 + QOH 0.000 + QOC 0.000 + QTY_ON_ORDER 0.000 + QTY_RESERVED 0.000 + DTD_QTY_PURCHASED 0.000 + MTD_QTY_PURCHASED 0.000 + YTD_QTY_PURCHASED 0.000 + DTD_QTY_SOLD 0.000 + MTD_QTY_SOLD 0.000 + YTD_QTY_SOLD 0.000 + + + Records affected: 6 + + MSG point-2 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + + MSG point-2 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + + MSG point-2 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + + MSG point-2 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + + MSG point-2 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + + MSG point-2 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + QOH 0.000 + + + Records affected: 6 + """ + +@pytest.mark.version('>=2.5') +def test_conversion_error_from_string_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_crash_of_group_by_varchar_4000.py b/tests/functional/gtcs/test_crash_of_group_by_varchar_4000.py new file mode 100644 index 00000000..47d87574 --- /dev/null +++ b/tests/functional/gtcs/test_crash_of_group_by_varchar_4000.py @@ -0,0 +1,101 @@ +#coding:utf-8 +# +# id: functional.gtcs.crash_of_group_by_varchar_4000 +# title: GTCS/tests/CF_ISQL_33. Crash on attempt to GROUP BY on table with varchar(4000) field +# decription: +# ::: NB ::: +# ### Name of original test has no any relation with actual task of this test: ### +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_33.script +# +# Source description (dominikfaessler, message of 2004-05-27 13:11:09; FB 1.5.1.4443): +# https://sourceforge.net/p/firebird/mailman/message/17071981/ +# +# Issue in original test: +# bug #961543 Server Crash ISO8859_1 and DE_DE +# +# Checked on: 4.0.0.1804 SS; 3.0.6.33271 SS; 2.5.9.27149 SC. +# NB: it is enough in 'expected_stdout' to show only name of resulting field ('F01') +# rather than the whole output. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('^((?!F01|Records affected).)*$', '')] + +init_script_1 = """""" + +db_1 = db_factory(charset='ISO8859_1', sql_dialect=3, init=init_script_1) + +test_script_1 = """ + CREATE TABLE SNIPPETS ( + f01 VARCHAR(4000) COLLATE DE_DE + ); + + SET TERM ^; + + insert into snippets values(' + function JsShowZeroFilled(inValue) { + if(inValue > 9) { + return inValue; + } else { + return ''0'' + inValue; + } + } + + + + + function JsGetWochentagname(wochentag,wochentagtyp,langcode) { + var wochentagname; + + + array_DE = new Array("SO,Son.,Sonntag", "MO,Mon.,Montag", + "DI,Di.,Dienstag", "MI,Mi.,Mittwoch", + "DO,Don.,Donnerstag","FR,Fr.,Freitag", "SA,Sam.,Samstag"); + array_EN = new Array("SU,Su.,Sunday", "MO,Mon.,Monday", + "TU,Tu.,Tuesday", "WE,We.,Wednesday", "DO,Th.,Thursday", + "FR,Fr.,Friday", "SA,Sa.,Saturday"); + + + if (langcode.toUpperCase() == ''DE'') { + array_wochentagname = array_DE[wochentag].split('',''); + wochentagname = array_wochentagname[wochentagtyp-1]; + } else { + array_wochentagname = array_EN[wochentag].split('',''); + wochentagname = array_wochentagname[wochentagtyp-1]; + } + return wochentagname; + } + ') + ^ + set term ;^ + commit; + + set count on; + set list on; + select f01 from snippets group by f01; + + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F01 + Records affected: 1 + """ + +@pytest.mark.version('>=2.5') +def test_crash_of_group_by_varchar_4000_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_division_by_zero_corrupts_db.py b/tests/functional/gtcs/test_division_by_zero_corrupts_db.py new file mode 100644 index 00000000..de8764c0 --- /dev/null +++ b/tests/functional/gtcs/test_division_by_zero_corrupts_db.py @@ -0,0 +1,97 @@ +#coding:utf-8 +# +# id: functional.gtcs.division_by_zero_corrupts_db +# title: GTCS/tests/CF_ISQL_29. Zero divide in SP can crash database when call this SP several times. +# decription: +# ::: NB ::: +# ### Name of original test has no any relation with actual task of this test: ### +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_29.script +# +# Issue in original test: +# Division by 0 corrupt database +# +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [("-At procedure 'SPX_AUX_TEST' line: .*", ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set term ^ ; + create procedure spx_aux_test (par1 bigint) returns (ret1 bigint) + as + declare lok1 bigint ; + declare itmpvar integer; + begin + begin + lok1=2; + itmpvar = 1/0; + when any do + begin + exception; + end + end + end + ^ + commit + ^ + set term ;^ + + connect '$(DSN)' user 'SYSDBA' password 'masterkey'; -- this is done in original script. + + set term ^; + create or alter procedure spx_aux_test (par1 bigint) returns (ret1 bigint) + as + declare lok1 bigint ; + declare itmpvar integer; + begin + begin + lok1=2; + itmpvar = 1/0; + end + end + ^ + commit + ^ + set term ;^ + + execute procedure spx_aux_test (1); + execute procedure spx_aux_test (1); + execute procedure spx_aux_test (1); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_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. + + 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 = 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. + """ + +@pytest.mark.version('>=2.5') +def test_division_by_zero_corrupts_db_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/gtcs/test_dsql_domain_01.py b/tests/functional/gtcs/test_dsql_domain_01.py new file mode 100644 index 00000000..183d4d23 --- /dev/null +++ b/tests/functional/gtcs/test_dsql_domain_01.py @@ -0,0 +1,320 @@ +#coding:utf-8 +# +# id: functional.gtcs.dsql_domain_01 +# title: GTCS/tests/DSQL_DOMAIN_01. Test the level 0 syntax for SQL create domain defining only the datatype. +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/DSQL_DOMAIN_01.script +# +# NB: avoid usage of ISQL command 'SHOW DOMAIN' because of unstable output. +# We display info about domains using common VIEW based on RDB$FIELDS table. +# +# Checked on 4.0.0.1896; 3.0.6.33288; 2.5.9.27149 +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('^((?!Statement failed|SQL error code).)*$', ''), (' = ', ' '), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create view v_test as + select + ff.rdb$field_name as dm_name + ,ff.rdb$field_type as dm_type + ,ff.rdb$field_sub_type as dm_subtype + ,ff.rdb$field_length as dm_flen + ,ff.rdb$field_scale as dm_fscale + ,ff.rdb$field_precision as dm_fprec + ,ff.rdb$character_set_id as dm_fcset + ,ff.rdb$collation_id as dm_fcoll + ,ff.rdb$character_length dm_fchrlen + ,ff.rdb$null_flag as dm_fnull + ,ff.rdb$validation_source as dm_fvalid + ,ff.rdb$default_source as dm_fdefault + from rdb$fields ff + where + ff.rdb$system_flag is distinct from 1 + and ff.rdb$field_name starting with upper( 'dom0' ) + ; + commit; + + set bail on; + create domain dom01a_1 as smallint; + create domain dom01a_2 as numeric(3,1); + create domain dom01b_1 as integer; + create domain dom01b_2 as int; + create domain dom01b_3 as numeric; + create domain dom01b_4 as numeric(6,2); + create domain dom01c as date; + create domain dom01d_1 as char(20); + create domain dom01d_2 as character(99); + create domain dom01e_1 as varchar(25); + create domain dom01e_2 as character varying(100); + create domain dom01e_3 as char varying(2); + create domain dom01f_1 as decimal(6,2); + create domain dom01g_1 as float; + create domain dom01g_2 as long float; + create domain dom01g_3 as real; + create domain dom01h as double precision; + create domain dom01i_1 as blob; + create domain dom01i_2 as blob(60,1); + commit; + set bail off; + + set list on; + set count on; + select * from v_test order by dm_name; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DM_NAME DOM01A_1 + DM_TYPE 7 + DM_SUBTYPE 0 + DM_FLEN 2 + DM_FSCALE 0 + DM_FPREC 0 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID + DM_FDEFAULT + DM_NAME DOM01A_2 + DM_TYPE 7 + DM_SUBTYPE 1 + DM_FLEN 2 + DM_FSCALE -1 + DM_FPREC 3 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID + DM_FDEFAULT + DM_NAME DOM01B_1 + DM_TYPE 8 + DM_SUBTYPE 0 + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC 0 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID + DM_FDEFAULT + DM_NAME DOM01B_2 + DM_TYPE 8 + DM_SUBTYPE 0 + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC 0 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID + DM_FDEFAULT + DM_NAME DOM01B_3 + DM_TYPE 8 + DM_SUBTYPE 1 + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC 9 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID + DM_FDEFAULT + DM_NAME DOM01B_4 + DM_TYPE 8 + DM_SUBTYPE 1 + DM_FLEN 4 + DM_FSCALE -2 + DM_FPREC 6 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID + DM_FDEFAULT + DM_NAME DOM01C + DM_TYPE 12 + DM_SUBTYPE + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID + DM_FDEFAULT + DM_NAME DOM01D_1 + DM_TYPE 14 + DM_SUBTYPE 0 + DM_FLEN 20 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 0 + DM_FCOLL 0 + DM_FCHRLEN 20 + DM_FNULL + DM_FVALID + DM_FDEFAULT + DM_NAME DOM01D_2 + DM_TYPE 14 + DM_SUBTYPE 0 + DM_FLEN 99 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 0 + DM_FCOLL 0 + DM_FCHRLEN 99 + DM_FNULL + DM_FVALID + DM_FDEFAULT + DM_NAME DOM01E_1 + DM_TYPE 37 + DM_SUBTYPE 0 + DM_FLEN 25 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 0 + DM_FCOLL 0 + DM_FCHRLEN 25 + DM_FNULL + DM_FVALID + DM_FDEFAULT + DM_NAME DOM01E_2 + DM_TYPE 37 + DM_SUBTYPE 0 + DM_FLEN 100 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 0 + DM_FCOLL 0 + DM_FCHRLEN 100 + DM_FNULL + DM_FVALID + DM_FDEFAULT + DM_NAME DOM01E_3 + DM_TYPE 37 + DM_SUBTYPE 0 + DM_FLEN 2 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 0 + DM_FCOLL 0 + DM_FCHRLEN 2 + DM_FNULL + DM_FVALID + DM_FDEFAULT + DM_NAME DOM01F_1 + DM_TYPE 8 + DM_SUBTYPE 2 + DM_FLEN 4 + DM_FSCALE -2 + DM_FPREC 6 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID + DM_FDEFAULT + DM_NAME DOM01G_1 + DM_TYPE 10 + DM_SUBTYPE + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID + DM_FDEFAULT + DM_NAME DOM01G_2 + DM_TYPE 27 + DM_SUBTYPE + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID + DM_FDEFAULT + DM_NAME DOM01G_3 + DM_TYPE 10 + DM_SUBTYPE + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID + DM_FDEFAULT + DM_NAME DOM01H + DM_TYPE 27 + DM_SUBTYPE + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID + DM_FDEFAULT + DM_NAME DOM01I_1 + DM_TYPE 261 + DM_SUBTYPE 0 + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID + DM_FDEFAULT + DM_NAME DOM01I_2 + DM_TYPE 261 + DM_SUBTYPE 1 + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 0 + DM_FCOLL 0 + DM_FCHRLEN + DM_FNULL + DM_FVALID + DM_FDEFAULT + Records affected: 19 + """ + +@pytest.mark.version('>=2.5') +def test_dsql_domain_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_dsql_domain_02.py b/tests/functional/gtcs/test_dsql_domain_02.py new file mode 100644 index 00000000..bcdd4728 --- /dev/null +++ b/tests/functional/gtcs/test_dsql_domain_02.py @@ -0,0 +1,375 @@ +#coding:utf-8 +# +# id: functional.gtcs.dsql_domain_02 +# title: GTCS/tests/DSQL_DOMAIN_02. Test the level 0 syntax for SQL "CREATE DOMAIN" statement using datatype and DEFAULT clauses +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/DSQL_DOMAIN_02.script +# +# NB: avoid usage of ISQL command 'SHOW DOMAIN' because of unstable output. +# We display info about domains using common VIEW based on RDB$FIELDS table. +# Columns with rdb$validation_source and rdb$default_source contain BLOB data thus we have to skip from showing their blob ID - see substitution. +# +# Checked on 4.0.0.1896; 3.0.6.33288; 2.5.9.27149 +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('DM_FDEFAULT_BLOB_ID.*', ''), ('DM_FVALID_BLOB_ID.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create view v_test as + select + ff.rdb$field_name as dm_name + ,ff.rdb$field_type as dm_type + ,ff.rdb$field_sub_type as dm_subtype + ,ff.rdb$field_length as dm_flen + ,ff.rdb$field_scale as dm_fscale + ,ff.rdb$field_precision as dm_fprec + ,ff.rdb$character_set_id as dm_fcset + ,ff.rdb$collation_id as dm_fcoll + ,ff.rdb$character_length dm_fchrlen + ,ff.rdb$null_flag as dm_fnull + ,ff.rdb$validation_source as dm_fvalid_blob_id + ,ff.rdb$default_source as dm_fdefault_blob_id + from rdb$fields ff + where + ff.rdb$system_flag is distinct from 1 + and ff.rdb$field_name starting with upper( 'dom0' ) + ; + commit; + + set bail on; + create domain dom02a1 as smallint default 0; + create domain dom02b1 as integer default 0; + create domain dom02d1 as char(30) default 0; + create domain dom02e1 as varchar(4) default 0; + create domain dom02f1 as decimal(10,1) default 0; + create domain dom02g1 as float default 0; + create domain dom02h1 as double precision default 0; + create domain dom02d2 as char(30) default 'def'; + create domain dom02e2 as varchar(4) default 'def'; + create domain dom02c3_1 as date default '27-JAN-1992'; + create domain dom02c3_2 as date default 'today'; + create domain dom02c3_3 as date default '01/27/92'; + create domain dom02d3 as char(30) default '28-OCT-1990'; + create domain dom02e3 as varchar(8) default '09/01/82'; + create domain dom02j as smallint default null; + create domain dom02k as integer default null; + create domain dom02l as date default null; + create domain dom02m as char(2) default null; + create domain dom02n as varchar(15) default null; + create domain dom02o as decimal(4,1) default null; + create domain dom02p as float default null; + create domain dom02q as double precision default null; + create domain dom02r as blob default null; + create domain dom02v as char(15) default user; + create domain dom02w as varchar(60) default user; + commit; + set bail off; + + set list on; + set count on; + select * from v_test order by dm_name; +--('[ ]+', ' '), + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DM_NAME DOM02A1 + DM_TYPE 7 + DM_SUBTYPE 0 + DM_FLEN 2 + DM_FSCALE 0 + DM_FPREC 0 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + default 0 + DM_NAME DOM02B1 + DM_TYPE 8 + DM_SUBTYPE 0 + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC 0 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + default 0 + DM_NAME DOM02C3_1 + DM_TYPE 12 + DM_SUBTYPE + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + default '27-JAN-1992' + DM_NAME DOM02C3_2 + DM_TYPE 12 + DM_SUBTYPE + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + default 'today' + DM_NAME DOM02C3_3 + DM_TYPE 12 + DM_SUBTYPE + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + default '01/27/92' + DM_NAME DOM02D1 + DM_TYPE 14 + DM_SUBTYPE 0 + DM_FLEN 30 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 0 + DM_FCOLL 0 + DM_FCHRLEN 30 + DM_FNULL + default 0 + DM_NAME DOM02D2 + DM_TYPE 14 + DM_SUBTYPE 0 + DM_FLEN 30 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 0 + DM_FCOLL 0 + DM_FCHRLEN 30 + DM_FNULL + default 'def' + DM_NAME DOM02D3 + DM_TYPE 14 + DM_SUBTYPE 0 + DM_FLEN 30 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 0 + DM_FCOLL 0 + DM_FCHRLEN 30 + DM_FNULL + default '28-OCT-1990' + DM_NAME DOM02E1 + DM_TYPE 37 + DM_SUBTYPE 0 + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 0 + DM_FCOLL 0 + DM_FCHRLEN 4 + DM_FNULL + default 0 + DM_NAME DOM02E2 + DM_TYPE 37 + DM_SUBTYPE 0 + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 0 + DM_FCOLL 0 + DM_FCHRLEN 4 + DM_FNULL + default 'def' + DM_NAME DOM02E3 + DM_TYPE 37 + DM_SUBTYPE 0 + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 0 + DM_FCOLL 0 + DM_FCHRLEN 8 + DM_FNULL + default '09/01/82' + DM_NAME DOM02F1 + DM_TYPE 16 + DM_SUBTYPE 2 + DM_FLEN 8 + DM_FSCALE -1 + DM_FPREC 10 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + default 0 + DM_NAME DOM02G1 + DM_TYPE 10 + DM_SUBTYPE + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + default 0 + DM_NAME DOM02H1 + DM_TYPE 27 + DM_SUBTYPE + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + default 0 + DM_NAME DOM02J + DM_TYPE 7 + DM_SUBTYPE 0 + DM_FLEN 2 + DM_FSCALE 0 + DM_FPREC 0 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + default null + DM_NAME DOM02K + DM_TYPE 8 + DM_SUBTYPE 0 + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC 0 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + default null + DM_NAME DOM02L + DM_TYPE 12 + DM_SUBTYPE + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + default null + DM_NAME DOM02M + DM_TYPE 14 + DM_SUBTYPE 0 + DM_FLEN 2 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 0 + DM_FCOLL 0 + DM_FCHRLEN 2 + DM_FNULL + default null + DM_NAME DOM02N + DM_TYPE 37 + DM_SUBTYPE 0 + DM_FLEN 15 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 0 + DM_FCOLL 0 + DM_FCHRLEN 15 + DM_FNULL + default null + DM_NAME DOM02O + DM_TYPE 8 + DM_SUBTYPE 2 + DM_FLEN 4 + DM_FSCALE -1 + DM_FPREC 4 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + default null + DM_NAME DOM02P + DM_TYPE 10 + DM_SUBTYPE + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + default null + DM_NAME DOM02Q + DM_TYPE 27 + DM_SUBTYPE + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + default null + DM_NAME DOM02R + DM_TYPE 261 + DM_SUBTYPE 0 + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + default null + DM_NAME DOM02V + DM_TYPE 14 + DM_SUBTYPE 0 + DM_FLEN 15 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 0 + DM_FCOLL 0 + DM_FCHRLEN 15 + DM_FNULL + default user + DM_NAME DOM02W + DM_TYPE 37 + DM_SUBTYPE 0 + DM_FLEN 60 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 0 + DM_FCOLL 0 + DM_FCHRLEN 60 + DM_FNULL + default user + Records affected: 25 + """ + +@pytest.mark.version('>=2.5') +def test_dsql_domain_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_dsql_domain_03.py b/tests/functional/gtcs/test_dsql_domain_03.py new file mode 100644 index 00000000..261555b2 --- /dev/null +++ b/tests/functional/gtcs/test_dsql_domain_03.py @@ -0,0 +1,412 @@ +#coding:utf-8 +# +# id: functional.gtcs.dsql_domain_03 +# title: GTCS/tests/DSQL_DOMAIN_03. Test the level 0 syntax for SQL "CREATE DOMAIN" statement using datatype and NOT NULL constraint. +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/DSQL_DOMAIN_03.script +# +# NB: avoid usage of ISQL command 'SHOW DOMAIN' because of unstable output. +# We display info about domains using common VIEW based on RDB$FIELDS table. +# Columns with rdb$validation_source and rdb$default_source contain BLOB data thus we have to skip from showing their blob ID - see substitution. +# +# ::: NOTE ::: +# Added domains with datatype that did appear only in FB 4.0: DECFLOAT and TIME[STAMP] WITH TIME ZONE. For this reason only FB 4.0+ can be tested. +# Checked on 4.0.0.1896. +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('DM_FDEFAULT_BLOB_ID.*', ''), ('DM_FVALID_BLOB_ID.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create view v_test as + select + ff.rdb$field_name as dm_name + ,ff.rdb$field_type as dm_type + ,ff.rdb$field_sub_type as dm_subtype + ,ff.rdb$field_length as dm_flen + ,ff.rdb$field_scale as dm_fscale + ,ff.rdb$field_precision as dm_fprec + ,ff.rdb$character_set_id as dm_fcset + ,ff.rdb$collation_id as dm_fcoll + ,ff.rdb$character_length dm_fchrlen + ,ff.rdb$null_flag as dm_fnull + ,ff.rdb$validation_source as dm_fvalid_blob_id + ,ff.rdb$default_source as dm_fdefault_blob_id + from rdb$fields ff + where + ff.rdb$system_flag is distinct from 1 + and ff.rdb$field_name starting with upper( 'dom0' ) + ; + commit; + + set bail on; + create domain dom03_01 as smallint not null; + create domain dom03_02 as integer not null; + create domain dom03_03 as bigint not null; + create domain dom03_04 as date not null; + create domain dom03_05 as char(20) not null; + create domain dom03_06 as varchar(25) not null; + create domain dom03_07 as decimal(6,2) not null; + create domain dom03_08 as numeric(6,2) not null; + create domain dom03_09 as float not null; + create domain dom03_10 as real not null; + create domain dom03_11 as double precision not null; + create domain dom03_12 as long float not null; + create domain dom03_13 as blob not null; + create domain dom03_14 as blob sub_type text not null; + create domain dom03_15 as blob sub_type binary not null; + create domain dom03_16 as boolean not null; + create domain dom03_17 as time not null; + create domain dom03_18 as time with time zone not null; + create domain dom03_19 as timestamp not null; + create domain dom03_20 as timestamp with time zone not null; + create domain dom03_21 as nchar(20) not null; + create domain dom03_22 as binary(20) not null; -- this datatype is alias for char(N) character set octets + create domain dom03_23 as varbinary(20) not null; + create domain dom03_24 as decfloat not null; + create domain dom03_25 as decfloat(16) not null; + create domain dom03_26 as decfloat(34) not null; + commit; + set list on; + set count on; + select * from v_test order by dm_name; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DM_NAME DOM03_01 + DM_TYPE 7 + DM_SUBTYPE 0 + DM_FLEN 2 + DM_FSCALE 0 + DM_FPREC 0 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL 1 + DM_FVALID_BLOB_ID + DM_FDEFAULT_BLOB_ID + DM_NAME DOM03_02 + DM_TYPE 8 + DM_SUBTYPE 0 + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC 0 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL 1 + DM_FVALID_BLOB_ID + DM_FDEFAULT_BLOB_ID + DM_NAME DOM03_03 + DM_TYPE 16 + DM_SUBTYPE 0 + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC 0 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL 1 + DM_FVALID_BLOB_ID + DM_FDEFAULT_BLOB_ID + DM_NAME DOM03_04 + DM_TYPE 12 + DM_SUBTYPE + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL 1 + DM_FVALID_BLOB_ID + DM_FDEFAULT_BLOB_ID + DM_NAME DOM03_05 + DM_TYPE 14 + DM_SUBTYPE 0 + DM_FLEN 20 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 0 + DM_FCOLL 0 + DM_FCHRLEN 20 + DM_FNULL 1 + DM_FVALID_BLOB_ID + DM_FDEFAULT_BLOB_ID + DM_NAME DOM03_06 + DM_TYPE 37 + DM_SUBTYPE 0 + DM_FLEN 25 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 0 + DM_FCOLL 0 + DM_FCHRLEN 25 + DM_FNULL 1 + DM_FVALID_BLOB_ID + DM_FDEFAULT_BLOB_ID + DM_NAME DOM03_07 + DM_TYPE 8 + DM_SUBTYPE 2 + DM_FLEN 4 + DM_FSCALE -2 + DM_FPREC 6 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL 1 + DM_FVALID_BLOB_ID + DM_FDEFAULT_BLOB_ID + DM_NAME DOM03_08 + DM_TYPE 8 + DM_SUBTYPE 1 + DM_FLEN 4 + DM_FSCALE -2 + DM_FPREC 6 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL 1 + DM_FVALID_BLOB_ID + DM_FDEFAULT_BLOB_ID + DM_NAME DOM03_09 + DM_TYPE 10 + DM_SUBTYPE + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL 1 + DM_FVALID_BLOB_ID + DM_FDEFAULT_BLOB_ID + DM_NAME DOM03_10 + DM_TYPE 10 + DM_SUBTYPE + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL 1 + DM_FVALID_BLOB_ID + DM_FDEFAULT_BLOB_ID + DM_NAME DOM03_11 + DM_TYPE 27 + DM_SUBTYPE + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL 1 + DM_FVALID_BLOB_ID + DM_FDEFAULT_BLOB_ID + DM_NAME DOM03_12 + DM_TYPE 27 + DM_SUBTYPE + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL 1 + DM_FVALID_BLOB_ID + DM_FDEFAULT_BLOB_ID + DM_NAME DOM03_13 + DM_TYPE 261 + DM_SUBTYPE 0 + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL 1 + DM_FVALID_BLOB_ID + DM_FDEFAULT_BLOB_ID + DM_NAME DOM03_14 + DM_TYPE 261 + DM_SUBTYPE 1 + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 0 + DM_FCOLL 0 + DM_FCHRLEN + DM_FNULL 1 + DM_FVALID_BLOB_ID + DM_FDEFAULT_BLOB_ID + DM_NAME DOM03_15 + DM_TYPE 261 + DM_SUBTYPE 0 + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL 1 + DM_FVALID_BLOB_ID + DM_FDEFAULT_BLOB_ID + DM_NAME DOM03_16 + DM_TYPE 23 + DM_SUBTYPE + DM_FLEN 1 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL 1 + DM_FVALID_BLOB_ID + DM_FDEFAULT_BLOB_ID + DM_NAME DOM03_17 + DM_TYPE 13 + DM_SUBTYPE + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL 1 + DM_FVALID_BLOB_ID + DM_FDEFAULT_BLOB_ID + DM_NAME DOM03_18 + DM_TYPE 28 + DM_SUBTYPE + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL 1 + DM_FVALID_BLOB_ID + DM_FDEFAULT_BLOB_ID + DM_NAME DOM03_19 + DM_TYPE 35 + DM_SUBTYPE + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL 1 + DM_FVALID_BLOB_ID + DM_FDEFAULT_BLOB_ID + DM_NAME DOM03_20 + DM_TYPE 29 + DM_SUBTYPE + DM_FLEN 12 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL 1 + DM_FVALID_BLOB_ID + DM_FDEFAULT_BLOB_ID + DM_NAME DOM03_21 + DM_TYPE 14 + DM_SUBTYPE 0 + DM_FLEN 20 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 21 + DM_FCOLL 0 + DM_FCHRLEN 20 + DM_FNULL 1 + DM_FVALID_BLOB_ID + DM_FDEFAULT_BLOB_ID + DM_NAME DOM03_22 + DM_TYPE 14 + DM_SUBTYPE 1 + DM_FLEN 20 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 1 + DM_FCOLL 0 + DM_FCHRLEN 20 + DM_FNULL 1 + DM_FVALID_BLOB_ID + DM_FDEFAULT_BLOB_ID + DM_NAME DOM03_23 + DM_TYPE 37 + DM_SUBTYPE 1 + DM_FLEN 20 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 1 + DM_FCOLL 0 + DM_FCHRLEN 20 + DM_FNULL 1 + DM_FVALID_BLOB_ID + DM_FDEFAULT_BLOB_ID + DM_NAME DOM03_24 + DM_TYPE 25 + DM_SUBTYPE + DM_FLEN 16 + DM_FSCALE 0 + DM_FPREC 34 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL 1 + DM_FVALID_BLOB_ID + DM_FDEFAULT_BLOB_ID + DM_NAME DOM03_25 + DM_TYPE 24 + DM_SUBTYPE + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC 16 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL 1 + DM_FVALID_BLOB_ID + DM_FDEFAULT_BLOB_ID + DM_NAME DOM03_26 + DM_TYPE 25 + DM_SUBTYPE + DM_FLEN 16 + DM_FSCALE 0 + DM_FPREC 34 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL 1 + DM_FVALID_BLOB_ID + DM_FDEFAULT_BLOB_ID + Records affected: 26 + """ + +@pytest.mark.version('>=4.0') +def test_dsql_domain_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_dsql_domain_04.py b/tests/functional/gtcs/test_dsql_domain_04.py new file mode 100644 index 00000000..76493259 --- /dev/null +++ b/tests/functional/gtcs/test_dsql_domain_04.py @@ -0,0 +1,649 @@ +#coding:utf-8 +# +# id: functional.gtcs.dsql_domain_04 +# title: GTCS/tests/DSQL_DOMAIN_04. Test the level 0 syntax for SQL "CREATE DOMAIN" statement using datatype and CHECK constraint clause. +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/DSQL_DOMAIN_04.script +# +# NB: avoid usage of ISQL command 'SHOW DOMAIN' because of unstable output. +# We display info about domains using common VIEW based on RDB$FIELDS table. +# Columns with rdb$validation_source and rdb$default_source contain BLOB data thus we have to skip from showing their blob ID - see substitution. +# +# ::: NOTE ::: +# Added domains with datatype that did appear only in FB 4.0: DECFLOAT and TIME[STAMP] WITH TIME ZONE. For this reason only FB 4.0+ can be tested. +# Checked on 4.0.0.1896. +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('DM_FDEFAULT_BLOB_ID.*', ''), ('DM_FVALID_BLOB_ID.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create view v_test as + select + ff.rdb$field_name as dm_name + ,ff.rdb$field_type as dm_type + ,ff.rdb$field_sub_type as dm_subtype + ,ff.rdb$field_length as dm_flen + ,ff.rdb$field_scale as dm_fscale + ,ff.rdb$field_precision as dm_fprec + ,ff.rdb$character_set_id as dm_fcset + ,ff.rdb$collation_id as dm_fcoll + ,ff.rdb$character_length dm_fchrlen + ,ff.rdb$null_flag as dm_fnull + ,ff.rdb$validation_source as dm_fvalid_blob_id + ,ff.rdb$default_source as dm_fdefault_blob_id + from rdb$fields ff + where + ff.rdb$system_flag is distinct from 1 + and ff.rdb$field_name starting with upper( 'dom0' ) + ; + commit; + + set bail on; + create domain dom03_01 as smallint check (value between 0 and 99); + + -- Statement failed, SQLSTATE = 54000 + -- unsuccessful metadata update + -- -CREATE DOMAIN DOM03_02 failed + -- -Dynamic SQL Error + -- -SQL error code = -901 + -- -Implementation limit exceeded + -- -Too many values (more than 1500) in member list to match against + + -- .py code for generating list: s=','.join( ( str(i) for i in range(1500,1) ) ) + create domain dom03_02 as integer check ( + value in ( + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41, + 42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, + 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112, + 113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140, + 141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168, + 169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196, + 197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224, + 225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252, + 253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280, + 281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308, + 309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336, + 337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364, + 365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392, + 393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420, + 421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448, + 449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476, + 477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504, + 505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532, + 533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560, + 561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588, + 589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616, + 617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644, + 645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672, + 673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700, + 701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728, + 729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756, + 757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784, + 785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812, + 813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840, + 841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868, + 869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896, + 897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924, + 925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952, + 953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980, + 981,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999,1000,1001,1002,1003,1004,1005,1006, + 1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028, + 1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050, + 1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072, + 1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094, + 1095,1096,1097,1098,1099,1100,1101,1102,1103,1104,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116, + 1117,1118,1119,1120,1121,1122,1123,1124,1125,1126,1127,1128,1129,1130,1131,1132,1133,1134,1135,1136,1137,1138, + 1139,1140,1141,1142,1143,1144,1145,1146,1147,1148,1149,1150,1151,1152,1153,1154,1155,1156,1157,1158,1159,1160, + 1161,1162,1163,1164,1165,1166,1167,1168,1169,1170,1171,1172,1173,1174,1175,1176,1177,1178,1179,1180,1181,1182, + 1183,1184,1185,1186,1187,1188,1189,1190,1191,1192,1193,1194,1195,1196,1197,1198,1199,1200,1201,1202,1203,1204, + 1205,1206,1207,1208,1209,1210,1211,1212,1213,1214,1215,1216,1217,1218,1219,1220,1221,1222,1223,1224,1225,1226, + 1227,1228,1229,1230,1231,1232,1233,1234,1235,1236,1237,1238,1239,1240,1241,1242,1243,1244,1245,1246,1247,1248, + 1249,1250,1251,1252,1253,1254,1255,1256,1257,1258,1259,1260,1261,1262,1263,1264,1265,1266,1267,1268,1269,1270, + 1271,1272,1273,1274,1275,1276,1277,1278,1279,1280,1281,1282,1283,1284,1285,1286,1287,1288,1289,1290,1291,1292, + 1293,1294,1295,1296,1297,1298,1299,1300,1301,1302,1303,1304,1305,1306,1307,1308,1309,1310,1311,1312,1313,1314, + 1315,1316,1317,1318,1319,1320,1321,1322,1323,1324,1325,1326,1327,1328,1329,1330,1331,1332,1333,1334,1335,1336, + 1337,1338,1339,1340,1341,1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358, + 1359,1360,1361,1362,1363,1364,1365,1366,1367,1368,1369,1370,1371,1372,1373,1374,1375,1376,1377,1378,1379,1380, + 1381,1382,1383,1384,1385,1386,1387,1388,1389,1390,1391,1392,1393,1394,1395,1396,1397,1398,1399,1400,1401,1402, + 1403,1404,1405,1406,1407,1408,1409,1410,1411,1412,1413,1414,1415,1416,1417,1418,1419,1420,1421,1422,1423,1424, + 1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446, + 1447,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468, + 1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490, + 1491,1492,1493,1494,1495,1496,1497,1498,1499,1500 + ) + ); + + -- .py code for generating list: s=','.join( ( str(i) for i in range(1500,1,-1) ) ) + create domain dom03_03 as bigint check ( + value NOT in ( + 1500,1499,1498,1497,1496,1495,1494,1493,1492,1491,1490,1489,1488,1487,1486,1485,1484,1483,1482,1481,1480,1479, + 1478,1477,1476,1475,1474,1473,1472,1471,1470,1469,1468,1467,1466,1465,1464,1463,1462,1461,1460,1459,1458,1457, + 1456,1455,1454,1453,1452,1451,1450,1449,1448,1447,1446,1445,1444,1443,1442,1441,1440,1439,1438,1437,1436,1435, + 1434,1433,1432,1431,1430,1429,1428,1427,1426,1425,1424,1423,1422,1421,1420,1419,1418,1417,1416,1415,1414,1413, + 1412,1411,1410,1409,1408,1407,1406,1405,1404,1403,1402,1401,1400,1399,1398,1397,1396,1395,1394,1393,1392,1391, + 1390,1389,1388,1387,1386,1385,1384,1383,1382,1381,1380,1379,1378,1377,1376,1375,1374,1373,1372,1371,1370,1369, + 1368,1367,1366,1365,1364,1363,1362,1361,1360,1359,1358,1357,1356,1355,1354,1353,1352,1351,1350,1349,1348,1347, + 1346,1345,1344,1343,1342,1341,1340,1339,1338,1337,1336,1335,1334,1333,1332,1331,1330,1329,1328,1327,1326,1325, + 1324,1323,1322,1321,1320,1319,1318,1317,1316,1315,1314,1313,1312,1311,1310,1309,1308,1307,1306,1305,1304,1303, + 1302,1301,1300,1299,1298,1297,1296,1295,1294,1293,1292,1291,1290,1289,1288,1287,1286,1285,1284,1283,1282,1281, + 1280,1279,1278,1277,1276,1275,1274,1273,1272,1271,1270,1269,1268,1267,1266,1265,1264,1263,1262,1261,1260,1259, + 1258,1257,1256,1255,1254,1253,1252,1251,1250,1249,1248,1247,1246,1245,1244,1243,1242,1241,1240,1239,1238,1237, + 1236,1235,1234,1233,1232,1231,1230,1229,1228,1227,1226,1225,1224,1223,1222,1221,1220,1219,1218,1217,1216,1215, + 1214,1213,1212,1211,1210,1209,1208,1207,1206,1205,1204,1203,1202,1201,1200,1199,1198,1197,1196,1195,1194,1193, + 1192,1191,1190,1189,1188,1187,1186,1185,1184,1183,1182,1181,1180,1179,1178,1177,1176,1175,1174,1173,1172,1171, + 1170,1169,1168,1167,1166,1165,1164,1163,1162,1161,1160,1159,1158,1157,1156,1155,1154,1153,1152,1151,1150,1149, + 1148,1147,1146,1145,1144,1143,1142,1141,1140,1139,1138,1137,1136,1135,1134,1133,1132,1131,1130,1129,1128,1127, + 1126,1125,1124,1123,1122,1121,1120,1119,1118,1117,1116,1115,1114,1113,1112,1111,1110,1109,1108,1107,1106,1105, + 1104,1103,1102,1101,1100,1099,1098,1097,1096,1095,1094,1093,1092,1091,1090,1089,1088,1087,1086,1085,1084,1083, + 1082,1081,1080,1079,1078,1077,1076,1075,1074,1073,1072,1071,1070,1069,1068,1067,1066,1065,1064,1063,1062,1061, + 1060,1059,1058,1057,1056,1055,1054,1053,1052,1051,1050,1049,1048,1047,1046,1045,1044,1043,1042,1041,1040,1039, + 1038,1037,1036,1035,1034,1033,1032,1031,1030,1029,1028,1027,1026,1025,1024,1023,1022,1021,1020,1019,1018,1017, + 1016,1015,1014,1013,1012,1011,1010,1009,1008,1007,1006,1005,1004,1003,1002,1001,1000,999,998,997,996,995,994, + 993,992,991,990,989,988,987,986,985,984,983,982,981,980,979,978,977,976,975,974,973,972,971,970,969,968,967, + 966,965,964,963,962,961,960,959,958,957,956,955,954,953,952,951,950,949,948,947,946,945,944,943,942,941,940, + 939,938,937,936,935,934,933,932,931,930,929,928,927,926,925,924,923,922,921,920,919,918,917,916,915,914,913, + 912,911,910,909,908,907,906,905,904,903,902,901,900,899,898,897,896,895,894,893,892,891,890,889,888,887,886, + 885,884,883,882,881,880,879,878,877,876,875,874,873,872,871,870,869,868,867,866,865,864,863,862,861,860,859, + 858,857,856,855,854,853,852,851,850,849,848,847,846,845,844,843,842,841,840,839,838,837,836,835,834,833,832, + 831,830,829,828,827,826,825,824,823,822,821,820,819,818,817,816,815,814,813,812,811,810,809,808,807,806,805, + 804,803,802,801,800,799,798,797,796,795,794,793,792,791,790,789,788,787,786,785,784,783,782,781,780,779,778, + 777,776,775,774,773,772,771,770,769,768,767,766,765,764,763,762,761,760,759,758,757,756,755,754,753,752,751, + 750,749,748,747,746,745,744,743,742,741,740,739,738,737,736,735,734,733,732,731,730,729,728,727,726,725,724, + 723,722,721,720,719,718,717,716,715,714,713,712,711,710,709,708,707,706,705,704,703,702,701,700,699,698,697, + 696,695,694,693,692,691,690,689,688,687,686,685,684,683,682,681,680,679,678,677,676,675,674,673,672,671,670, + 669,668,667,666,665,664,663,662,661,660,659,658,657,656,655,654,653,652,651,650,649,648,647,646,645,644,643, + 642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627,626,625,624,623,622,621,620,619,618,617,616, + 615,614,613,612,611,610,609,608,607,606,605,604,603,602,601,600,599,598,597,596,595,594,593,592,591,590,589, + 588,587,586,585,584,583,582,581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,566,565,564,563,562, + 561,560,559,558,557,556,555,554,553,552,551,550,549,548,547,546,545,544,543,542,541,540,539,538,537,536,535, + 534,533,532,531,530,529,528,527,526,525,524,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508, + 507,506,505,504,503,502,501,500,499,498,497,496,495,494,493,492,491,490,489,488,487,486,485,484,483,482,481, + 480,479,478,477,476,475,474,473,472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435,434,433,432,431,430,429,428,427, + 426,425,424,423,422,421,420,419,418,417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,401,400, + 399,398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,380,379,378,377,376,375,374,373, + 372,371,370,369,368,367,366,365,364,363,362,361,360,359,358,357,356,355,354,353,352,351,350,349,348,347,346, + 345,344,343,342,341,340,339,338,337,336,335,334,333,332,331,330,329,328,327,326,325,324,323,322,321,320,319, + 318,317,316,315,314,313,312,311,310,309,308,307,306,305,304,303,302,301,300,299,298,297,296,295,294,293,292, + 291,290,289,288,287,286,285,284,283,282,281,280,279,278,277,276,275,274,273,272,271,270,269,268,267,266,265, + 264,263,262,261,260,259,258,257,256,255,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238, + 237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211, + 210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184, + 183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157, + 156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130, + 129,128,127,126,125,124,123,122,121,120,119,118,117,116,115,114,113,112,111,110,109,108,107,106,105,104,103, + 102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68, + 67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32, + 31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1 + ) + ); + + + create domain dom03_04 as date check (value >='01.01.0001' and value <= '31.12.9999'); + create domain dom03_05 as char(31) check (value in (select rdb$field_name from rdb$fields)); + create domain dom03_06 as varchar(31) check ( exists(select 1 from rdb$database) ); + create domain dom03_07 as decimal(6,2) check (value between 2.71 and 3.14); + create domain dom03_08 as numeric(6,2) check (value not between 2.71 and 3.14); + create domain dom03_09 as float check (value = 3.1415926); + create domain dom03_10 as real check (value = 3.1415926); + create domain dom03_11 as double precision check (value <= 1.7976931348623155e308); + create domain dom03_12 as long float check ( abs(value) > exp(-745.1332191)); + create domain dom03_13 as blob check (value = '0xadef'); + create domain dom03_14 as blob sub_type text check (value > ''); + create domain dom03_15 as blob sub_type binary check (value similar to '([0-9]|[a-f]){1,}'); + create domain dom03_16 as boolean check (value in(true, false)); + create domain dom03_17 as time check (value between '00:00:00.000' and '23:59:59.999' ); + create domain dom03_18 as time with time zone check (value >= time '10:00 America/Los_Angeles'); + + create domain dom03_19 as timestamp check (value between '01.01.0001 00:00:00.000' and '31.12.9999 23:59:59.999' ); + create domain dom03_20 as timestamp with time zone check (value >= timestamp '01.01.2020 10:00 America/Los_Angeles'); + + create domain dom03_21 as nchar(20) check (singular(select 1 from rdb$database)); + create domain dom03_22 as binary(20) check (value = 'qwerty' ); -- this datatype is alias for char(N) character set octets + create domain dom03_23 as varbinary(20) check (value = 'mnbvcxz' ); + create domain dom03_24 as decfloat check (value in(-9.999999999999999999999999999999999E+6144, 9.999999999999999999999999999999999E+6144) ); + create domain dom03_25 as decfloat(16) check (value in(-9.999999999999999E+384, 9.999999999999999E+384) ); + create domain dom03_26 as decfloat(34) check (value in(-9.999999999999999999999999999999999E+6144, 9.999999999999999999999999999999999E+6144) ); + + commit; + set list on; + set count on; + select * from v_test order by dm_name; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DM_NAME DOM03_01 + DM_TYPE 7 + DM_SUBTYPE 0 + DM_FLEN 2 + DM_FSCALE 0 + DM_FPREC 0 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + check (value between 0 and 99) + DM_NAME DOM03_02 + DM_TYPE 8 + DM_SUBTYPE 0 + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC 0 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + check ( + value in ( + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41, + 42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, + 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112, + 113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140, + 141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168, + 169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196, + 197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224, + 225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252, + 253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280, + 281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308, + 309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336, + 337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364, + 365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392, + 393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420, + 421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448, + 449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476, + 477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504, + 505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532, + 533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560, + 561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588, + 589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616, + 617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644, + 645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672, + 673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700, + 701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728, + 729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756, + 757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784, + 785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812, + 813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840, + 841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868, + 869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896, + 897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924, + 925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952, + 953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980, + 981,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999,1000,1001,1002,1003,1004,1005,1006, + 1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028, + 1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050, + 1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072, + 1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094, + 1095,1096,1097,1098,1099,1100,1101,1102,1103,1104,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116, + 1117,1118,1119,1120,1121,1122,1123,1124,1125,1126,1127,1128,1129,1130,1131,1132,1133,1134,1135,1136,1137,1138, + 1139,1140,1141,1142,1143,1144,1145,1146,1147,1148,1149,1150,1151,1152,1153,1154,1155,1156,1157,1158,1159,1160, + 1161,1162,1163,1164,1165,1166,1167,1168,1169,1170,1171,1172,1173,1174,1175,1176,1177,1178,1179,1180,1181,1182, + 1183,1184,1185,1186,1187,1188,1189,1190,1191,1192,1193,1194,1195,1196,1197,1198,1199,1200,1201,1202,1203,1204, + 1205,1206,1207,1208,1209,1210,1211,1212,1213,1214,1215,1216,1217,1218,1219,1220,1221,1222,1223,1224,1225,1226, + 1227,1228,1229,1230,1231,1232,1233,1234,1235,1236,1237,1238,1239,1240,1241,1242,1243,1244,1245,1246,1247,1248, + 1249,1250,1251,1252,1253,1254,1255,1256,1257,1258,1259,1260,1261,1262,1263,1264,1265,1266,1267,1268,1269,1270, + 1271,1272,1273,1274,1275,1276,1277,1278,1279,1280,1281,1282,1283,1284,1285,1286,1287,1288,1289,1290,1291,1292, + 1293,1294,1295,1296,1297,1298,1299,1300,1301,1302,1303,1304,1305,1306,1307,1308,1309,1310,1311,1312,1313,1314, + 1315,1316,1317,1318,1319,1320,1321,1322,1323,1324,1325,1326,1327,1328,1329,1330,1331,1332,1333,1334,1335,1336, + 1337,1338,1339,1340,1341,1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358, + 1359,1360,1361,1362,1363,1364,1365,1366,1367,1368,1369,1370,1371,1372,1373,1374,1375,1376,1377,1378,1379,1380, + 1381,1382,1383,1384,1385,1386,1387,1388,1389,1390,1391,1392,1393,1394,1395,1396,1397,1398,1399,1400,1401,1402, + 1403,1404,1405,1406,1407,1408,1409,1410,1411,1412,1413,1414,1415,1416,1417,1418,1419,1420,1421,1422,1423,1424, + 1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446, + 1447,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468, + 1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490, + 1491,1492,1493,1494,1495,1496,1497,1498,1499,1500 + ) + ) + DM_NAME DOM03_03 + DM_TYPE 16 + DM_SUBTYPE 0 + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC 0 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + check ( + value NOT in ( + 1500,1499,1498,1497,1496,1495,1494,1493,1492,1491,1490,1489,1488,1487,1486,1485,1484,1483,1482,1481,1480,1479, + 1478,1477,1476,1475,1474,1473,1472,1471,1470,1469,1468,1467,1466,1465,1464,1463,1462,1461,1460,1459,1458,1457, + 1456,1455,1454,1453,1452,1451,1450,1449,1448,1447,1446,1445,1444,1443,1442,1441,1440,1439,1438,1437,1436,1435, + 1434,1433,1432,1431,1430,1429,1428,1427,1426,1425,1424,1423,1422,1421,1420,1419,1418,1417,1416,1415,1414,1413, + 1412,1411,1410,1409,1408,1407,1406,1405,1404,1403,1402,1401,1400,1399,1398,1397,1396,1395,1394,1393,1392,1391, + 1390,1389,1388,1387,1386,1385,1384,1383,1382,1381,1380,1379,1378,1377,1376,1375,1374,1373,1372,1371,1370,1369, + 1368,1367,1366,1365,1364,1363,1362,1361,1360,1359,1358,1357,1356,1355,1354,1353,1352,1351,1350,1349,1348,1347, + 1346,1345,1344,1343,1342,1341,1340,1339,1338,1337,1336,1335,1334,1333,1332,1331,1330,1329,1328,1327,1326,1325, + 1324,1323,1322,1321,1320,1319,1318,1317,1316,1315,1314,1313,1312,1311,1310,1309,1308,1307,1306,1305,1304,1303, + 1302,1301,1300,1299,1298,1297,1296,1295,1294,1293,1292,1291,1290,1289,1288,1287,1286,1285,1284,1283,1282,1281, + 1280,1279,1278,1277,1276,1275,1274,1273,1272,1271,1270,1269,1268,1267,1266,1265,1264,1263,1262,1261,1260,1259, + 1258,1257,1256,1255,1254,1253,1252,1251,1250,1249,1248,1247,1246,1245,1244,1243,1242,1241,1240,1239,1238,1237, + 1236,1235,1234,1233,1232,1231,1230,1229,1228,1227,1226,1225,1224,1223,1222,1221,1220,1219,1218,1217,1216,1215, + 1214,1213,1212,1211,1210,1209,1208,1207,1206,1205,1204,1203,1202,1201,1200,1199,1198,1197,1196,1195,1194,1193, + 1192,1191,1190,1189,1188,1187,1186,1185,1184,1183,1182,1181,1180,1179,1178,1177,1176,1175,1174,1173,1172,1171, + 1170,1169,1168,1167,1166,1165,1164,1163,1162,1161,1160,1159,1158,1157,1156,1155,1154,1153,1152,1151,1150,1149, + 1148,1147,1146,1145,1144,1143,1142,1141,1140,1139,1138,1137,1136,1135,1134,1133,1132,1131,1130,1129,1128,1127, + 1126,1125,1124,1123,1122,1121,1120,1119,1118,1117,1116,1115,1114,1113,1112,1111,1110,1109,1108,1107,1106,1105, + 1104,1103,1102,1101,1100,1099,1098,1097,1096,1095,1094,1093,1092,1091,1090,1089,1088,1087,1086,1085,1084,1083, + 1082,1081,1080,1079,1078,1077,1076,1075,1074,1073,1072,1071,1070,1069,1068,1067,1066,1065,1064,1063,1062,1061, + 1060,1059,1058,1057,1056,1055,1054,1053,1052,1051,1050,1049,1048,1047,1046,1045,1044,1043,1042,1041,1040,1039, + 1038,1037,1036,1035,1034,1033,1032,1031,1030,1029,1028,1027,1026,1025,1024,1023,1022,1021,1020,1019,1018,1017, + 1016,1015,1014,1013,1012,1011,1010,1009,1008,1007,1006,1005,1004,1003,1002,1001,1000,999,998,997,996,995,994, + 993,992,991,990,989,988,987,986,985,984,983,982,981,980,979,978,977,976,975,974,973,972,971,970,969,968,967, + 966,965,964,963,962,961,960,959,958,957,956,955,954,953,952,951,950,949,948,947,946,945,944,943,942,941,940, + 939,938,937,936,935,934,933,932,931,930,929,928,927,926,925,924,923,922,921,920,919,918,917,916,915,914,913, + 912,911,910,909,908,907,906,905,904,903,902,901,900,899,898,897,896,895,894,893,892,891,890,889,888,887,886, + 885,884,883,882,881,880,879,878,877,876,875,874,873,872,871,870,869,868,867,866,865,864,863,862,861,860,859, + 858,857,856,855,854,853,852,851,850,849,848,847,846,845,844,843,842,841,840,839,838,837,836,835,834,833,832, + 831,830,829,828,827,826,825,824,823,822,821,820,819,818,817,816,815,814,813,812,811,810,809,808,807,806,805, + 804,803,802,801,800,799,798,797,796,795,794,793,792,791,790,789,788,787,786,785,784,783,782,781,780,779,778, + 777,776,775,774,773,772,771,770,769,768,767,766,765,764,763,762,761,760,759,758,757,756,755,754,753,752,751, + 750,749,748,747,746,745,744,743,742,741,740,739,738,737,736,735,734,733,732,731,730,729,728,727,726,725,724, + 723,722,721,720,719,718,717,716,715,714,713,712,711,710,709,708,707,706,705,704,703,702,701,700,699,698,697, + 696,695,694,693,692,691,690,689,688,687,686,685,684,683,682,681,680,679,678,677,676,675,674,673,672,671,670, + 669,668,667,666,665,664,663,662,661,660,659,658,657,656,655,654,653,652,651,650,649,648,647,646,645,644,643, + 642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627,626,625,624,623,622,621,620,619,618,617,616, + 615,614,613,612,611,610,609,608,607,606,605,604,603,602,601,600,599,598,597,596,595,594,593,592,591,590,589, + 588,587,586,585,584,583,582,581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,566,565,564,563,562, + 561,560,559,558,557,556,555,554,553,552,551,550,549,548,547,546,545,544,543,542,541,540,539,538,537,536,535, + 534,533,532,531,530,529,528,527,526,525,524,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508, + 507,506,505,504,503,502,501,500,499,498,497,496,495,494,493,492,491,490,489,488,487,486,485,484,483,482,481, + 480,479,478,477,476,475,474,473,472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435,434,433,432,431,430,429,428,427, + 426,425,424,423,422,421,420,419,418,417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,401,400, + 399,398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,380,379,378,377,376,375,374,373, + 372,371,370,369,368,367,366,365,364,363,362,361,360,359,358,357,356,355,354,353,352,351,350,349,348,347,346, + 345,344,343,342,341,340,339,338,337,336,335,334,333,332,331,330,329,328,327,326,325,324,323,322,321,320,319, + 318,317,316,315,314,313,312,311,310,309,308,307,306,305,304,303,302,301,300,299,298,297,296,295,294,293,292, + 291,290,289,288,287,286,285,284,283,282,281,280,279,278,277,276,275,274,273,272,271,270,269,268,267,266,265, + 264,263,262,261,260,259,258,257,256,255,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238, + 237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211, + 210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184, + 183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157, + 156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130, + 129,128,127,126,125,124,123,122,121,120,119,118,117,116,115,114,113,112,111,110,109,108,107,106,105,104,103, + 102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68, + 67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32, + 31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1 + ) + ) + DM_NAME DOM03_04 + DM_TYPE 12 + DM_SUBTYPE + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + check (value >='01.01.0001' and value <= '31.12.9999') + DM_NAME DOM03_05 + DM_TYPE 14 + DM_SUBTYPE 0 + DM_FLEN 31 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 0 + DM_FCOLL 0 + DM_FCHRLEN 31 + DM_FNULL + check (value in (select rdb$field_name from rdb$fields)) + DM_NAME DOM03_06 + DM_TYPE 37 + DM_SUBTYPE 0 + DM_FLEN 31 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 0 + DM_FCOLL 0 + DM_FCHRLEN 31 + DM_FNULL + check ( exists(select 1 from rdb$database) ) + DM_NAME DOM03_07 + DM_TYPE 8 + DM_SUBTYPE 2 + DM_FLEN 4 + DM_FSCALE -2 + DM_FPREC 6 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + check (value between 2.71 and 3.14) + DM_NAME DOM03_08 + DM_TYPE 8 + DM_SUBTYPE 1 + DM_FLEN 4 + DM_FSCALE -2 + DM_FPREC 6 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + check (value not between 2.71 and 3.14) + DM_NAME DOM03_09 + DM_TYPE 10 + DM_SUBTYPE + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + check (value = 3.1415926) + DM_NAME DOM03_10 + DM_TYPE 10 + DM_SUBTYPE + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + check (value = 3.1415926) + DM_NAME DOM03_11 + DM_TYPE 27 + DM_SUBTYPE + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + check (value <= 1.7976931348623155e308) + DM_NAME DOM03_12 + DM_TYPE 27 + DM_SUBTYPE + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + check ( abs(value) > exp(-745.1332191)) + DM_NAME DOM03_13 + DM_TYPE 261 + DM_SUBTYPE 0 + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + check (value = '0xadef') + DM_NAME DOM03_14 + DM_TYPE 261 + DM_SUBTYPE 1 + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 0 + DM_FCOLL 0 + DM_FCHRLEN + DM_FNULL + check (value > '') + DM_NAME DOM03_15 + DM_TYPE 261 + DM_SUBTYPE 0 + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + check (value similar to '([0-9]|[a-f]){1,}') + DM_NAME DOM03_16 + DM_TYPE 23 + DM_SUBTYPE + DM_FLEN 1 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + check (value in(true, false)) + DM_NAME DOM03_17 + DM_TYPE 13 + DM_SUBTYPE + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + check (value between '00:00:00.000' and '23:59:59.999' ) + DM_NAME DOM03_18 + DM_TYPE 28 + DM_SUBTYPE + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + check (value >= time '10:00 America/Los_Angeles') + DM_NAME DOM03_19 + DM_TYPE 35 + DM_SUBTYPE + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + check (value between '01.01.0001 00:00:00.000' and '31.12.9999 23:59:59.999' ) + DM_NAME DOM03_20 + DM_TYPE 29 + DM_SUBTYPE + DM_FLEN 12 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + check (value >= timestamp '01.01.2020 10:00 America/Los_Angeles') + DM_NAME DOM03_21 + DM_TYPE 14 + DM_SUBTYPE 0 + DM_FLEN 20 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 21 + DM_FCOLL 0 + DM_FCHRLEN 20 + DM_FNULL + check (singular(select 1 from rdb$database)) + DM_NAME DOM03_22 + DM_TYPE 14 + DM_SUBTYPE 1 + DM_FLEN 20 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 1 + DM_FCOLL 0 + DM_FCHRLEN 20 + DM_FNULL + check (value = 'qwerty' ) + DM_NAME DOM03_23 + DM_TYPE 37 + DM_SUBTYPE 1 + DM_FLEN 20 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 1 + DM_FCOLL 0 + DM_FCHRLEN 20 + DM_FNULL + check (value = 'mnbvcxz' ) + DM_NAME DOM03_24 + DM_TYPE 25 + DM_SUBTYPE + DM_FLEN 16 + DM_FSCALE 0 + DM_FPREC 34 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + check (value in(-9.999999999999999999999999999999999E+6144, 9.999999999999999999999999999999999E+6144) ) + DM_NAME DOM03_25 + DM_TYPE 24 + DM_SUBTYPE + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC 16 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + check (value in(-9.999999999999999E+384, 9.999999999999999E+384) ) + DM_NAME DOM03_26 + DM_TYPE 25 + DM_SUBTYPE + DM_FLEN 16 + DM_FSCALE 0 + DM_FPREC 34 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + check (value in(-9.999999999999999999999999999999999E+6144, 9.999999999999999999999999999999999E+6144) ) + Records affected: 26 + """ + +@pytest.mark.version('>=4.0') +def test_dsql_domain_04_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_dsql_domain_06.py b/tests/functional/gtcs/test_dsql_domain_06.py new file mode 100644 index 00000000..5b952f52 --- /dev/null +++ b/tests/functional/gtcs/test_dsql_domain_06.py @@ -0,0 +1,1007 @@ +#coding:utf-8 +# +# id: functional.gtcs.dsql_domain_06 +# title: GTCS/tests/DSQL_DOMAIN_06. Test the level 0 syntax for SQL "CREATE DOMAIN" statement using datatype and CHECK constraint clause. +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/DSQL_DOMAIN_06.script +# +# NB: avoid usage of ISQL command 'SHOW DOMAIN' because of unstable output. +# We display info about domains using common VIEW based on RDB$FIELDS table. +# Columns with rdb$validation_source and rdb$default_source contain BLOB data thus we have to skip from showing their blob ID - see substitution. +# +# ::: NOTE ::: +# Added domains with datatype that did appear only in FB 4.0: DECFLOAT and TIME[STAMP] WITH TIME ZONE. For this reason only FB 4.0+ can be tested. +# +# For each base datatype we: +# * create domain and set default value; +# * alter domain in order to drop default; +# * alter domain in order to set new default; +# * alter domain with doing TWO changes in ONE statement: set new default + drop default; +# * alter domain with doing TWO changes in ONE statement: drop default + set new default. +# +# For some datatypes (float, double precision) we also verify ability to use boundary values for datatype itself. +# For character datatypes we use non-asci characters (currency signs: euro, cent, pound, yena). +# +# Currently following datatypes are NOT checked: +# blob sub_type text not null; +# blob sub_type binary not null; // byt test *does* check BLOB without sub_type specified +# long float not null; +# nchar(20) not null; +# binary(20) not null; +# varbinary(20) not null; +# +# Checked on 4.0.0.1926. +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('DM_FDEFAULT_BLOB_ID.*', ''), ('DM_FVALID_BLOB_ID.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set list on; + + create view v_test as + select + ff.rdb$field_name as dm_name + ,ff.rdb$field_type as dm_type + ,ff.rdb$field_sub_type as dm_subtype + ,ff.rdb$field_length as dm_flen + ,ff.rdb$field_scale as dm_fscale + ,ff.rdb$field_precision as dm_fprec + ,ff.rdb$character_set_id as dm_fcset + ,ff.rdb$collation_id as dm_fcoll + ,ff.rdb$character_length dm_fchrlen + ,ff.rdb$null_flag as dm_fnull + ,ff.rdb$validation_source as dm_fvalid_blob_id + ,ff.rdb$default_source as dm_fdefault_blob_id + from rdb$fields ff + where + ff.rdb$system_flag is distinct from 1 + and ff.rdb$field_name starting with upper( 'dom0' ) + ; + commit; + + create domain dom06_01 as smallint default 1111; + alter domain dom06_01 drop default; + alter domain dom06_01 set default 2222; + alter domain dom06_01 set default 9999 drop default; + alter domain dom06_01 drop default set default 3333; + ------------------------------------------------------------------------------------------------ + create domain dom06_02 as int default 11111; + alter domain dom06_02 drop default; + alter domain dom06_02 set default 22222; + alter domain dom06_02 set default 99999 drop default; + alter domain dom06_02 drop default set default 33333; + ------------------------------------------------------------------------------------------------ + create domain dom06_03 as bigint default 111111; + alter domain dom06_03 drop default; + alter domain dom06_03 set default 222222; + alter domain dom06_03 set default 999999 drop default; + alter domain dom06_03 drop default set default 333333; + ------------------------------------------------------------------------------------------------ + create domain dom06_04 as date default current_date; + alter domain dom06_04 drop default; + alter domain dom06_04 set default 'TODAY'; + alter domain dom06_04 set default 'TOMORROW' drop default; + alter domain dom06_04 drop default set default 'YESTERDAY'; + ------------------------------------------------------------------------------------------------ + create domain dom06_05 as time default current_time; + alter domain dom06_05 drop default; + alter domain dom06_05 set default current_time; + alter domain dom06_05 set default current_time drop default; + alter domain dom06_05 drop default set default current_time; + ------------------------------------------------------------------------------------------------ + create domain dom06_06 as time with time zone default '11:11:11.111 Indian/Cocos'; + alter domain dom06_06 drop default; + alter domain dom06_06 set default '12:31:42.543 Pacific/Fiji'; + alter domain dom06_06 set default '23:34:45.678 Pacific/Galapagos' drop default; + alter domain dom06_06 drop default set default '01:02:03.456 Antarctica/South_Pole'; + ------------------------------------------------------------------------------------------------ + create domain dom06_07 as timestamp not null; + alter domain dom06_07 drop default; + alter domain dom06_07 set default 'now'; + alter domain dom06_07 set default current_timestamp drop default; + alter domain dom06_07 drop default set default current_timestamp; + ------------------------------------------------------------------------------------------------ + create domain dom06_08 as timestamp with time zone default '21.12.2013 11:11:11.111 Indian/Cocos'; + alter domain dom06_08 drop default; + alter domain dom06_08 set default '23.01.2014 12:31:42.543 Pacific/Fiji'; + alter domain dom06_08 set default '27.03.2015 23:34:45.678 Pacific/Galapagos' drop default; + alter domain dom06_08 drop default set default '29.05.2017 01:02:03.456 Antarctica/South_Pole'; + ------------------------------------------------------------------------------------------------ + create domain dom06_09 as char(1) character set utf8 default '€'; + alter domain dom06_09 drop default; + alter domain dom06_09 set default '£'; + alter domain dom06_09 set default '¢' drop default; + alter domain dom06_09 drop default set default '¥'; + ------------------------------------------------------------------------------------------------ + create domain dom06_10 as varchar(1) character set utf8 default '€'; + alter domain dom06_10 drop default; + alter domain dom06_10 set default '£'; + alter domain dom06_10 set default '¢' drop default; + alter domain dom06_10 drop default set default '¥'; + ------------------------------------------------------------------------------------------------ + create domain dom06_11 as nchar(1) default 'Ž'; -- ISO8859_1 + alter domain dom06_11 drop default; + alter domain dom06_11 set default 'š'; + alter domain dom06_11 set default 'Ÿ' drop default; + alter domain dom06_11 drop default set default '¡'; + ------------------------------------------------------------------------------------------------ + create domain dom06_12 as numeric(2,2) default -327.68; + alter domain dom06_12 drop default; + alter domain dom06_12 set default 327.67; + alter domain dom06_12 set default -327.68 drop default; + alter domain dom06_12 drop default set default 327.67; + ------------------------------------------------------------------------------------------------ + -- create domain dom06_13 as decimal(20,2) default 170141183460469231731687303715884105727; -- 0x7FFFFFFFFFFFFFFF; + create domain dom06_13 as decimal(20,2) default -999999999999999999; + alter domain dom06_13 drop default; + alter domain dom06_13 set default 99999999999999999999999999999999; + alter domain dom06_13 set default -999999999999999999 drop default; + alter domain dom06_13 drop default set default 99999999999999999999999999999999; + ------------------------------------------------------------------------------------------------ + -- https://en.wikipedia.org/wiki/Single-precision_floating-point_format, power(2,-149): + -- https://www.wolframalpha.com + + -- (largest normal number): (2-power(2,-23)) * power(2,127) + create domain dom06_14 as float default 340282346638528859811704183484516925440; + alter domain dom06_14 drop default; + + -- (smallest positive subnormal number): power(2, -149) + alter domain dom06_14 set default 1.40129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125e-45; + + -- (largest number less than one): 1 - power(2,-24) + alter domain dom06_14 set default 0.999999940395355224609375 drop default; + + -- (smallest number larger than one): 1 + power(2,-23) + alter domain dom06_14 drop default set default 1.00000011920928955078125; + ------------------------------------------------------------------------------------------------ + create domain dom06_15 as real default 340282346638528859811704183484516925440; -- = FLOAT + alter domain dom06_15 drop default; + alter domain dom06_15 set default 1.40129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125e-45; + alter domain dom06_15 set default 0.999999940395355224609375 drop default; + alter domain dom06_15 drop default set default 1.00000011920928955078125; + + ------------------------------------------------------------------------------------------------ + + -- https://en.wikipedia.org/wiki/Double-precision_floating-point_format + -- create domain dom06_16 as double precision default 0xF0000000; -- 0x7fefffffffffffff; + --create domain dm_testd as double precision default 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368; + --create table test(x dom06_16); + --insert into test default values returning x; -- Statement failed, SQLSTATE = 22003 / Floating-point overflow. The exponent of a floating-point operation is greater than the magnitude allowed. + -- 1.79769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458... × 10^308 + --create domain dom06_16 as double precision default 1.797693134862315708145e308; + + -- (max double): power(2,1023) * (1+(1-power(2,-52)) + create domain dom06_16 as double precision default 1.797693134862315708e308; -- 1.797693134862315708e3081 => SQLSTATE = 22003 / Floating-point overflow + alter domain dom06_16 drop default; + -- (Min. subnormal positive double) power(2,-1074) + -- 4.940656458412465441765687928682213723650598026143247... × 10^-324 + + -- (Max. subnormal double) power(2,-1022) * (1 - power(2,-52)) + -- 2.225073858507200889024586876085859887650423112240959... × 10^-308 + -- alter domain dom06_16 set default 2.225073858507200889024586876085859887650423112240959e-308; -- 0.00000000 + alter domain dom06_16 set default 2e-308; + -- 1 + power(2,-52) = 1.0000000000000002, the smallest number > 1 + -- 1.0000000000000002220446049250313080847263336181640625 + alter domain dom06_16 set default 1.0000000000000002220446049250313080847263336181640625 drop default; + alter domain dom06_16 drop default set default 1.0000000000000006; + ----------------------------------------------------------------------------------------------- + create domain dom06_17 as blob default +' +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +012345678901234567 +' + ; + + alter domain dom06_17 drop default; + alter domain dom06_17 set default +' + + +'; -- several empty lines here + + alter domain dom06_17 set default null drop default; + alter domain dom06_17 drop default set default +' +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +012345678901234567 +' + ; +---------------------------------------------------------------------------------------------------- + create domain dom06_18 as boolean default false; + alter domain dom06_18 drop default; + alter domain dom06_18 set default true; + alter domain dom06_18 set default null drop default; + alter domain dom06_18 drop default set default false; +---------------------------------------------------------------------------------------------------- + create domain dom06_19 as decfloat default -9.999999999999999999999999999999999E6144; + alter domain dom06_19 drop default; + alter domain dom06_19 set default 9.999999999999999999999999999999999E6144; + alter domain dom06_19 set default null drop default; + alter domain dom06_19 drop default set default -1.0E-6143; +---------------------------------------------------------------------------------------------------- + commit; + set count on; + select * from v_test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +DM_NAME DOM06_01 +DM_TYPE 7 +DM_SUBTYPE 0 +DM_FLEN 2 +DM_FSCALE 0 +DM_FPREC 0 +DM_FCSET +DM_FCOLL +DM_FCHRLEN +DM_FNULL +DM_FVALID_BLOB_ID +DM_FDEFAULT_BLOB_ID 2:1e8 +default 3333 + +DM_NAME DOM06_02 +DM_TYPE 8 +DM_SUBTYPE 0 +DM_FLEN 4 +DM_FSCALE 0 +DM_FPREC 0 +DM_FCSET +DM_FCOLL +DM_FCHRLEN +DM_FNULL +DM_FVALID_BLOB_ID +DM_FDEFAULT_BLOB_ID 2:1ec +default 33333 + +DM_NAME DOM06_03 +DM_TYPE 16 +DM_SUBTYPE 0 +DM_FLEN 8 +DM_FSCALE 0 +DM_FPREC 0 +DM_FCSET +DM_FCOLL +DM_FCHRLEN +DM_FNULL +DM_FVALID_BLOB_ID +DM_FDEFAULT_BLOB_ID 2:1f0 +default 333333 + +DM_NAME DOM06_04 +DM_TYPE 12 +DM_SUBTYPE +DM_FLEN 4 +DM_FSCALE 0 +DM_FPREC +DM_FCSET +DM_FCOLL +DM_FCHRLEN +DM_FNULL +DM_FVALID_BLOB_ID +DM_FDEFAULT_BLOB_ID 2:1f4 +default 'YESTERDAY' + +DM_NAME DOM06_05 +DM_TYPE 13 +DM_SUBTYPE +DM_FLEN 4 +DM_FSCALE 0 +DM_FPREC +DM_FCSET +DM_FCOLL +DM_FCHRLEN +DM_FNULL +DM_FVALID_BLOB_ID +DM_FDEFAULT_BLOB_ID 2:1f8 +default current_time + +DM_NAME DOM06_06 +DM_TYPE 28 +DM_SUBTYPE +DM_FLEN 8 +DM_FSCALE 0 +DM_FPREC +DM_FCSET +DM_FCOLL +DM_FCHRLEN +DM_FNULL +DM_FVALID_BLOB_ID +DM_FDEFAULT_BLOB_ID 2:1fc +default '01:02:03.456 Antarctica/South_Pole' + +DM_NAME DOM06_07 +DM_TYPE 35 +DM_SUBTYPE +DM_FLEN 8 +DM_FSCALE 0 +DM_FPREC +DM_FCSET +DM_FCOLL +DM_FCHRLEN +DM_FNULL 1 +DM_FVALID_BLOB_ID +DM_FDEFAULT_BLOB_ID 2:200 +default current_timestamp + +DM_NAME DOM06_08 +DM_TYPE 29 +DM_SUBTYPE +DM_FLEN 12 +DM_FSCALE 0 +DM_FPREC +DM_FCSET +DM_FCOLL +DM_FCHRLEN +DM_FNULL +DM_FVALID_BLOB_ID +DM_FDEFAULT_BLOB_ID 2:204 +default '29.05.2017 01:02:03.456 Antarctica/South_Pole' + +DM_NAME DOM06_09 +DM_TYPE 14 +DM_SUBTYPE 0 +DM_FLEN 4 +DM_FSCALE 0 +DM_FPREC +DM_FCSET 4 +DM_FCOLL 0 +DM_FCHRLEN 1 +DM_FNULL +DM_FVALID_BLOB_ID +DM_FDEFAULT_BLOB_ID 2:208 +default '¥' + +DM_NAME DOM06_10 +DM_TYPE 37 +DM_SUBTYPE 0 +DM_FLEN 4 +DM_FSCALE 0 +DM_FPREC +DM_FCSET 4 +DM_FCOLL 0 +DM_FCHRLEN 1 +DM_FNULL +DM_FVALID_BLOB_ID +DM_FDEFAULT_BLOB_ID 2:20c +default '¥' + +DM_NAME DOM06_11 +DM_TYPE 14 +DM_SUBTYPE 0 +DM_FLEN 1 +DM_FSCALE 0 +DM_FPREC +DM_FCSET 21 +DM_FCOLL 0 +DM_FCHRLEN 1 +DM_FNULL +DM_FVALID_BLOB_ID +DM_FDEFAULT_BLOB_ID 2:210 +default '¡' + +DM_NAME DOM06_12 +DM_TYPE 7 +DM_SUBTYPE 1 +DM_FLEN 2 +DM_FSCALE -2 +DM_FPREC 2 +DM_FCSET +DM_FCOLL +DM_FCHRLEN +DM_FNULL +DM_FVALID_BLOB_ID +DM_FDEFAULT_BLOB_ID 2:214 +default 327.67 + +DM_NAME DOM06_13 +DM_TYPE 26 +DM_SUBTYPE 2 +DM_FLEN 16 +DM_FSCALE -2 +DM_FPREC 20 +DM_FCSET +DM_FCOLL +DM_FCHRLEN +DM_FNULL +DM_FVALID_BLOB_ID +DM_FDEFAULT_BLOB_ID 2:218 +default 99999999999999999999999999999999 + +DM_NAME DOM06_14 +DM_TYPE 10 +DM_SUBTYPE +DM_FLEN 4 +DM_FSCALE 0 +DM_FPREC +DM_FCSET +DM_FCOLL +DM_FCHRLEN +DM_FNULL +DM_FVALID_BLOB_ID +DM_FDEFAULT_BLOB_ID 2:21c +default 1.00000011920928955078125 + +DM_NAME DOM06_15 +DM_TYPE 10 +DM_SUBTYPE +DM_FLEN 4 +DM_FSCALE 0 +DM_FPREC +DM_FCSET +DM_FCOLL +DM_FCHRLEN +DM_FNULL +DM_FVALID_BLOB_ID +DM_FDEFAULT_BLOB_ID 2:220 +default 1.00000011920928955078125 + +DM_NAME DOM06_16 +DM_TYPE 27 +DM_SUBTYPE +DM_FLEN 8 +DM_FSCALE 0 +DM_FPREC +DM_FCSET +DM_FCOLL +DM_FCHRLEN +DM_FNULL +DM_FVALID_BLOB_ID +DM_FDEFAULT_BLOB_ID 2:224 +default 1.0000000000000006 + +DM_NAME DOM06_17 +DM_TYPE 261 +DM_SUBTYPE 0 +DM_FLEN 8 +DM_FSCALE 0 +DM_FPREC +DM_FCSET +DM_FCOLL +DM_FCHRLEN +DM_FNULL +DM_FVALID_BLOB_ID +DM_FDEFAULT_BLOB_ID 2:228 +default +' +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +012345678901234567 +' + +DM_NAME DOM06_18 +DM_TYPE 23 +DM_SUBTYPE +DM_FLEN 1 +DM_FSCALE 0 +DM_FPREC +DM_FCSET +DM_FCOLL +DM_FCHRLEN +DM_FNULL +DM_FVALID_BLOB_ID +DM_FDEFAULT_BLOB_ID 2:22c +default false + +DM_NAME DOM06_19 +DM_TYPE 25 +DM_SUBTYPE +DM_FLEN 16 +DM_FSCALE 0 +DM_FPREC 34 +DM_FCSET +DM_FCOLL +DM_FCHRLEN +DM_FNULL +DM_FVALID_BLOB_ID +DM_FDEFAULT_BLOB_ID 2:230 +default -1.0E-6143 + +Records affected: 19 + """ + +@pytest.mark.version('>=4.0') +def test_dsql_domain_06_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_dsql_domain_07.py b/tests/functional/gtcs/test_dsql_domain_07.py new file mode 100644 index 00000000..d4f1ec37 --- /dev/null +++ b/tests/functional/gtcs/test_dsql_domain_07.py @@ -0,0 +1,831 @@ +#coding:utf-8 +# +# id: functional.gtcs.dsql_domain_07 +# title: GTCS/tests/DSQL_DOMAIN_07. Test CREATE / ALTER domain statement with ADD/DROP CONSTRAINT clauses, together and separately. +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/DSQL_DOMAIN_07.script +# +# NB: avoid usage of ISQL command 'SHOW DOMAIN' because of unstable output. +# We display info about domains using common VIEW based on RDB$FIELDS table. +# Columns with rdb$validation_source and rdb$default_source contain BLOB data thus we have to skip from showing their blob ID - see substitution. +# +# ::: NOTE ::: +# Added domains with datatype that did appear only in FB 4.0: DECFLOAT and TIME[STAMP] WITH TIME ZONE. For this reason only FB 4.0+ can be tested. +# +# For each base datatype we: +# * create domain and set initial CHECK constraint; +# * alter domain in order to add new constraint. This must FAIL with message "Only one constraint allowed for a domain" (SQLSTATE = 42000) +# * alter domain with requirement ADD CONSTRAINT and DROP it. +# ########## +# ### NB ### Clause 'DROP CONSTRAINT' will be executed FIRST in this case, regardless where it is specified. +# ########## +# For this reason such statement must PASS. +# * alter domain and try to add again new CHECK constraint. This thould fail again with SQLSTATE=42000. +# +# Currently following datatypes are NOT checked: +# blob sub_type text not null; +# blob sub_type binary not null; // byt test *does* check BLOB without sub_type specified +# long float not null; +# nchar not null; +# binary not null; +# varbinary not null; +# +# Checked on 4.0.0.1931. +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('DM_FDEFAULT_BLOB_ID.*', ''), ('DM_FVALID_BLOB_ID.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + create view v_test as + select + ff.rdb$field_name as dm_name + ,ff.rdb$field_type as dm_type + ,ff.rdb$field_sub_type as dm_subtype + ,ff.rdb$field_length as dm_flen + ,ff.rdb$field_scale as dm_fscale + ,ff.rdb$field_precision as dm_fprec + ,ff.rdb$character_set_id as dm_fcset + ,ff.rdb$collation_id as dm_fcoll + ,ff.rdb$character_length dm_fchrlen + ,ff.rdb$null_flag as dm_fnull + ,ff.rdb$validation_source as dm_fvalid_blob_id + ,ff.rdb$default_source as dm_fdefault_blob_id + from rdb$fields ff + where + ff.rdb$system_flag is distinct from 1 + and ff.rdb$field_name starting with upper( 'dom0' ) + ; + commit; + + create domain dom06_01 as smallint check( value = 1 ); + alter domain dom06_01 add constraint check( value = 2 ); -- must fail: "Only one constraint allowed for a domain" + alter domain dom06_01 add constraint check( value = 3 ) drop constraint; -- drop will run FIRST here! Statement must PASS! + alter domain dom06_01 add constraint check( value = 4 ); -- must fail + ------------------------------------------------------------------------------------------------ + create domain dom06_02 as int check( value = 1 ); + alter domain dom06_02 add constraint check( value = 2 ); + alter domain dom06_02 add constraint check( value = 3 ) drop constraint; + alter domain dom06_02 add constraint check( value = 4 ); + ------------------------------------------------------------------------------------------------ + create domain dom06_03 as bigint check( value = 1 ); + alter domain dom06_03 add constraint check( value = 2 ); + alter domain dom06_03 add constraint check( value = 3 ) drop constraint; + alter domain dom06_03 add constraint check( value = 4 ); + ------------------------------------------------------------------------------------------------ + create domain dom06_04 as date check( value <= current_date ); + alter domain dom06_04 add constraint check( value = current_date ); + alter domain dom06_04 add constraint check( value < current_date ) drop constraint; + alter domain dom06_04 add constraint check( value > current_date ); + ------------------------------------------------------------------------------------------------ + create domain dom06_05 as time check( value <= current_time ); + alter domain dom06_05 add constraint check( value = current_time ); + alter domain dom06_05 add constraint check( value < current_time ) drop constraint; + alter domain dom06_05 add constraint check( value > current_time ); + ------------------------------------------------------------------------------------------------ + create domain dom06_06 as time with time zone check( value >= '11:11:11.111 Indian/Cocos'); + alter domain dom06_06 add constraint check( value >= '12:31:42.543 Pacific/Fiji' ); + alter domain dom06_06 add constraint check( value < '23:34:45.678 Pacific/Galapagos' ) drop constraint; + alter domain dom06_06 add constraint check( value > '01:02:03.456 Antarctica/South_Pole' ); + ------------------------------------------------------------------------------------------------ + create domain dom06_07 as time check( value <= current_timestamp ); + alter domain dom06_07 add constraint check( value = current_timestamp ); + alter domain dom06_07 add constraint check( value < current_timestamp ) drop constraint; + alter domain dom06_07 add constraint check( value > current_timestamp ); + ------------------------------------------------------------------------------------------------ + create domain dom06_08 as timestamp with time zone check( value >= '21.12.2013 11:11:11.111 Indian/Cocos' ); + alter domain dom06_08 add constraint check( value >= '23.01.2014 12:31:42.543 Pacific/Fiji' ); + alter domain dom06_08 add constraint check( value < '27.03.2015 23:34:45.678 Pacific/Galapagos' ) drop constraint; + alter domain dom06_08 add constraint check( value > '29.05.2017 01:02:03.456 Antarctica/South_Pole' ); + ------------------------------------------------------------------------------------------------ + create domain dom06_09 as char(1) character set utf8 check( value = '€'); + alter domain dom06_09 add constraint check( value = '£' ); + alter domain dom06_09 add constraint check( value = '¢' ) drop constraint; + alter domain dom06_09 add constraint check( value = '¥' ); + ------------------------------------------------------------------------------------------------ + create domain dom06_10 as varchar(1) character set utf8 check( value = '€'); + alter domain dom06_10 add constraint check( value = '£' ); + alter domain dom06_10 add constraint check( value = '¢' ) drop constraint; + alter domain dom06_10 add constraint check( value = '¥' ); + ------------------------------------------------------------------------------------------------ + create domain dom06_11 as nchar(1) check( value = 'Ž'); -- ISO8859_1 + alter domain dom06_11 add constraint check( value = 'š' ); + alter domain dom06_11 add constraint check( value = 'Ÿ' ) drop constraint; + alter domain dom06_11 add constraint check( value = '¡' ); + ------------------------------------------------------------------------------------------------ + create domain dom06_12 as numeric(2,2) check(value = -327.68); + alter domain dom06_12 add constraint check( value = 327.67 ); + alter domain dom06_12 add constraint check( value = -327.68 ) drop constraint; + alter domain dom06_12 add constraint check( value = 327.67 ); + ------------------------------------------------------------------------------------------------ + create domain dom06_13 as decimal(2,2) check(value = -327.68); + alter domain dom06_13 add constraint check( value = 327.67 ); + alter domain dom06_13 add constraint check( value = -327.68 ) drop constraint; + alter domain dom06_13 add constraint check( value = 327.67 ); + ------------------------------------------------------------------------------------------------ + create domain dom06_14 as float check(value < 340282346638528859811704183484516925440); + alter domain dom06_14 add constraint check( value = 327.67 ); + alter domain dom06_14 add constraint check( value = 1.40129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125e-45 ) drop constraint; + alter domain dom06_14 add constraint check( value = 0.999999940395355224609375 ); + ------------------------------------------------------------------------------------------------ + create domain dom06_15 as float check(value < 340282346638528859811704183484516925440); + alter domain dom06_15 add constraint check( value = 327.67 ); + alter domain dom06_15 add constraint check( value = 1.40129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125e-45 ) drop constraint; + alter domain dom06_15 add constraint check( value = 0.999999940395355224609375 ); + ------------------------------------------------------------------------------------------------ + create domain dom06_16 as double precision check(value < 1.797693134862315708e308); + alter domain dom06_16 add constraint check( value = 327.67 ); + alter domain dom06_16 add constraint check( value >= 2e-308 ) drop constraint; + alter domain dom06_16 add constraint check( value = 1.0000000000000002220446049250313080847263336181640625 ); + ----------------------------------------------------------------------------------------------- + create domain dom06_17 as blob check (value = +' +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +012345678901234567 +' +); + + alter domain dom06_17 add constraint check( value = +' + + +'); -- several empty lines here + + alter domain dom06_17 add constraint check( value = +' + + + +') drop constraint; + + alter domain dom06_17 add constraint check( value is not null ); + +---------------------------------------------------------------------------------------------------- + create domain dom06_18 as boolean check( value = false); + alter domain dom06_18 add constraint check( value = true ); + alter domain dom06_18 add constraint check( value is not null ) drop constraint; + alter domain dom06_18 add constraint check( value = false ); +---------------------------------------------------------------------------------------------------- + create domain dom06_19 as decfloat check( value >= -9.999999999999999999999999999999999E6144 ); + alter domain dom06_19 add constraint check( value <= 9.999999999999999999999999999999999E6144 ); + alter domain dom06_19 add constraint check( value is not null ) drop constraint; + alter domain dom06_19 add constraint check( value >= -1.0E-6143 ); +---------------------------------------------------------------------------------------------------- + commit; + set count on; + select * from v_test; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DM_NAME DOM06_01 + DM_TYPE 7 + DM_SUBTYPE 0 + DM_FLEN 2 + DM_FSCALE 0 + DM_FPREC 0 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID_BLOB_ID 2:1e6 + check( value = 3 ) + DM_FDEFAULT_BLOB_ID + + DM_NAME DOM06_02 + DM_TYPE 8 + DM_SUBTYPE 0 + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC 0 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID_BLOB_ID 2:1ea + check( value = 3 ) + DM_FDEFAULT_BLOB_ID + + DM_NAME DOM06_03 + DM_TYPE 16 + DM_SUBTYPE 0 + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC 0 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID_BLOB_ID 2:1ee + check( value = 3 ) + DM_FDEFAULT_BLOB_ID + + DM_NAME DOM06_04 + DM_TYPE 12 + DM_SUBTYPE + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID_BLOB_ID 2:1f2 + check( value < current_date ) + DM_FDEFAULT_BLOB_ID + + DM_NAME DOM06_05 + DM_TYPE 13 + DM_SUBTYPE + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID_BLOB_ID 2:1f6 + check( value < current_time ) + DM_FDEFAULT_BLOB_ID + + DM_NAME DOM06_06 + DM_TYPE 28 + DM_SUBTYPE + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID_BLOB_ID 2:1fa + check( value < '23:34:45.678 Pacific/Galapagos' ) + DM_FDEFAULT_BLOB_ID + + DM_NAME DOM06_07 + DM_TYPE 13 + DM_SUBTYPE + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID_BLOB_ID 2:1fe + check( value < current_timestamp ) + DM_FDEFAULT_BLOB_ID + + DM_NAME DOM06_08 + DM_TYPE 29 + DM_SUBTYPE + DM_FLEN 12 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID_BLOB_ID 2:202 + check( value < '27.03.2015 23:34:45.678 Pacific/Galapagos' ) + DM_FDEFAULT_BLOB_ID + + DM_NAME DOM06_09 + DM_TYPE 14 + DM_SUBTYPE 0 + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 4 + DM_FCOLL 0 + DM_FCHRLEN 1 + DM_FNULL + DM_FVALID_BLOB_ID 2:206 + check( value = '¢' ) + DM_FDEFAULT_BLOB_ID + + DM_NAME DOM06_10 + DM_TYPE 37 + DM_SUBTYPE 0 + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 4 + DM_FCOLL 0 + DM_FCHRLEN 1 + DM_FNULL + DM_FVALID_BLOB_ID 2:20a + check( value = '¢' ) + DM_FDEFAULT_BLOB_ID + + DM_NAME DOM06_11 + DM_TYPE 14 + DM_SUBTYPE 0 + DM_FLEN 1 + DM_FSCALE 0 + DM_FPREC + DM_FCSET 21 + DM_FCOLL 0 + DM_FCHRLEN 1 + DM_FNULL + DM_FVALID_BLOB_ID 2:20e + check( value = 'Ÿ' ) + DM_FDEFAULT_BLOB_ID + + DM_NAME DOM06_12 + DM_TYPE 7 + DM_SUBTYPE 1 + DM_FLEN 2 + DM_FSCALE -2 + DM_FPREC 2 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID_BLOB_ID 2:212 + check( value = -327.68 ) + DM_FDEFAULT_BLOB_ID + + DM_NAME DOM06_13 + DM_TYPE 8 + DM_SUBTYPE 2 + DM_FLEN 4 + DM_FSCALE -2 + DM_FPREC 2 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID_BLOB_ID 2:216 + check( value = -327.68 ) + DM_FDEFAULT_BLOB_ID + + DM_NAME DOM06_14 + DM_TYPE 10 + DM_SUBTYPE + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID_BLOB_ID 2:21a + check( value = 1.40129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125e-45 ) + DM_FDEFAULT_BLOB_ID + + DM_NAME DOM06_15 + DM_TYPE 10 + DM_SUBTYPE + DM_FLEN 4 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID_BLOB_ID 2:21e + check( value = 1.40129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125e-45 ) + DM_FDEFAULT_BLOB_ID + + DM_NAME DOM06_16 + DM_TYPE 27 + DM_SUBTYPE + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID_BLOB_ID 2:222 + check( value >= 2e-308 ) + DM_FDEFAULT_BLOB_ID + + DM_NAME DOM06_17 + DM_TYPE 261 + DM_SUBTYPE 0 + DM_FLEN 8 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID_BLOB_ID 2:226 + check( value = + ' + + + + ') + DM_FDEFAULT_BLOB_ID + + DM_NAME DOM06_18 + DM_TYPE 23 + DM_SUBTYPE + DM_FLEN 1 + DM_FSCALE 0 + DM_FPREC + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID_BLOB_ID 2:22a + check( value is not null ) + DM_FDEFAULT_BLOB_ID + + DM_NAME DOM06_19 + DM_TYPE 25 + DM_SUBTYPE + DM_FLEN 16 + DM_FSCALE 0 + DM_FPREC 34 + DM_FCSET + DM_FCOLL + DM_FCHRLEN + DM_FNULL + DM_FVALID_BLOB_ID 2:22e + check( value is not null ) + DM_FDEFAULT_BLOB_ID + + Records affected: 19 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_01 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_01 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_02 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_02 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_03 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_03 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_04 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_04 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_05 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_05 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_06 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_06 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_07 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_07 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_08 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_08 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_09 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_09 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_10 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_10 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_11 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_11 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_12 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_12 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_13 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_13 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_14 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_14 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_15 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_15 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_16 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_16 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_17 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_17 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_18 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_18 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_19 failed + -"Only one constraint allowed for a domain" + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DOM06_19 failed + -"Only one constraint allowed for a domain" + """ + +@pytest.mark.version('>=4.0') +def test_dsql_domain_07_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_dsql_domain_12.py b/tests/functional/gtcs/test_dsql_domain_12.py new file mode 100644 index 00000000..1a07c418 --- /dev/null +++ b/tests/functional/gtcs/test_dsql_domain_12.py @@ -0,0 +1,476 @@ +#coding:utf-8 +# +# id: functional.gtcs.dsql_domain_12 +# title: GTCS/tests/DSQL_DOMAIN_12. Verify result of INSERT DEFAULT VALUES into a table with domain fields when domains are defined with DEFAULT value. +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/DSQL_DOMAIN_12.script +# +# ::: NOTE ::: +# Added domains with datatype that did appear only in FB 4.0: DECFLOAT and TIME[STAMP] WITH TIME ZONE. For this reason only FB 4.0+ can be tested. +# +# # Comment: This script will run level 1 testing, checking syntax of create +# # domain using datatype and default clauses, then creating a table +# # using the domain fields and inserting data to those fields, +# # allowing missing data to be supplied by the default definitions +# # for the domain. +# +# +# For some datatypes (float, double precision) we also verify ability to use boundary values for datatype itself. +# For character datatypes we use non-asci characters (currency signs: euro, cent, pound, yena). +# +# Currently following datatypes are NOT checked: +# blob sub_type text|binary +# long float; +# binary(20); +# varbinary(20); +# +# Checked on 4.0.0.1935. +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('F16_BLOB_ID.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set list on; + set blob all; + + create domain dom12_01 as smallint default -32768; + create domain dom12_02 as int default -2147483648; + create domain dom12_03 as bigint default -9223372036854775807; + --create domain dom12_03 as bigint default -9223372036854775808; -- currently raises error 'numeric overflow', see CORE-6291 + create domain dom12_04 as date default '31.12.9999'; + create domain dom12_05 as time default '23:59:59.999'; + create domain dom12_06 as time with time zone default '11:11:11.111 Indian/Cocos'; + create domain dom12_07 as timestamp default '01.01.0001 00:00:01.001'; + create domain dom12_08 as timestamp with time zone default '21.12.2013 11:11:11.111 Indian/Cocos'; + create domain dom12_09 as char(1) character set utf8 default '€'; + create domain dom12_10 as varchar(1) character set utf8 default '€'; + -- https://en.wikipedia.org/wiki/ISO/IEC_8859-1, + -- see table "Languages with incomplete coverage", + -- column "Typical workaround" for Hungarian 'Ő': + create domain dom12_11 as nchar(1) default 'Ö' ; + create domain dom12_12 as numeric(2,2) default -327.68; + create domain dom12_13 as decimal(20,2) default -999999999999999999; + + -- Online evaluation of expressions: https://www.wolframalpha.com + + -- https://en.wikipedia.org/wiki/Single-precision_floating-point_format + -- (largest number less than one): 1 - power(2,-24) + create domain dom12_14 as float default 0.999999940395355224609375; + + -- https://en.wikipedia.org/wiki/Double-precision_floating-point_format + -- Max Double: power(2,1023) * ( 1+(1-power(2,-52) ) + create domain dom12_15 as double precision default 1.7976931348623157e308; + + + create domain dom12_16 as blob default +' +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +012345678901234567 +'; + + create domain dom12_17 as boolean default false; + create domain dom12_18 as decfloat(16) default -9.999999999999999E+384; + create domain dom12_19 as decfloat default -9.999999999999999999999999999999999E6144; + commit; + + recreate table test( + f01 dom12_01 + ,f02 dom12_02 + ,f03 dom12_03 + ,f04 dom12_04 + ,f05 dom12_05 + ,f06 dom12_06 + ,f07 dom12_07 + ,f08 dom12_08 + ,f09 dom12_09 + ,f00 dom12_10 + ,f11 dom12_11 + ,f12 dom12_12 + ,f13 dom12_13 + ,f14 dom12_14 + ,f15 dom12_15 + ,f16_blob_id dom12_16 + ,f17 dom12_17 + ,f18 dom12_18 + ,f19 dom12_19 + ); + commit; + insert into test default values; + set count on; + select * from test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +F01 -32768 +F02 -2147483648 +F03 -9223372036854775807 +F04 9999-12-31 +F05 23:59:59.9990 +F06 11:11:11.1110 Indian/Cocos +F07 0001-01-01 00:00:01.0010 +F08 2013-12-21 11:11:11.1110 Indian/Cocos +F09 € +F00 € +F11 Ö +F12 -327.68 +F13 -999999999999999999.00 +F14 0.99999994 +F15 1.797693134862316e+308 +F16_BLOB_ID 80:0 + +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +012345678901234567 + +F17 +F18 -9.999999999999999E+384 +F19 -9.999999999999999999999999999999999E+6144 + +Records affected: 1 + """ + +@pytest.mark.version('>=4.0') +def test_dsql_domain_12_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_dsql_domain_13.py b/tests/functional/gtcs/test_dsql_domain_13.py new file mode 100644 index 00000000..ff8dfccb --- /dev/null +++ b/tests/functional/gtcs/test_dsql_domain_13.py @@ -0,0 +1,190 @@ +#coding:utf-8 +# +# id: functional.gtcs.dsql_domain_13 +# title: GTCS/tests/DSQL_DOMAIN_13. Verify result of INSERT DEFAULT for domain-based fields which have their own default values. +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/DSQL_DOMAIN_13.script +# +# Comment in GTCS +# This script will test level 1 syntax checking for create domain +# statement using datatype and default clauses. The domains are then +# used to create a table where column defaults are also specified. +# Data is then inserted into the table allowing the missing fields +# to be supplied by the column defaults (where specified) and the +# domain defaults (where no column default exists). +# +# ::: NOTE ::: +# Added domains with datatype that did appear only in FB 4.0: DECFLOAT and TIME[STAMP] WITH TIME ZONE. For this reason only FB 4.0+ can be tested. +# +# Fields without default values have names 'F1xx': f101, f102, ... +# Fields with their own default values are 'F2xx': f201, f202, ... +# +# Currently following datatypes are NOT checked: +# blob sub_type text|binary +# long float; +# binary(20); +# varbinary(20); +# +# Checked on 4.0.0.1954. +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('F116_BLOB_ID.*', ''), ('F216_BLOB_ID.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set list on; + set blob all; + + create domain dom13_01 as smallint default -32768; + create domain dom13_02 as int default -2147483648; + create domain dom13_03 as bigint default -9223372036854775807; + --create domain dom13_03 as bigint default -9223372036854775808; -- currently raises error 'numeric overflow', see CORE-6291 + create domain dom13_04 as date default '31.12.9999'; + create domain dom13_05 as time default '23:59:59.999'; + create domain dom13_06 as time with time zone default '11:11:11.111 Indian/Cocos'; + create domain dom13_07 as timestamp default '01.01.0001 00:00:01.001'; + create domain dom13_08 as timestamp with time zone default '21.12.2013 11:11:11.111 Indian/Cocos'; + create domain dom13_09 as char(1) character set utf8 default '€'; + create domain dom13_10 as varchar(1) character set utf8 default '¢'; + -- https://en.wikipedia.org/wiki/ISO/IEC_8859-1, + -- see table "Languages with incomplete coverage", + -- column "Typical workaround" for Hungarian 'Ő': + create domain dom13_11 as nchar(1) default 'Ö' ; + create domain dom13_12 as numeric(2,2) default -327.68; + create domain dom13_13 as decimal(20,2) default -999999999999999999; + + -- Online evaluation of expressions: https://www.wolframalpha.com + + -- https://en.wikipedia.org/wiki/Single-precision_floating-point_format + -- (largest number less than one): 1 - power(2,-24) + create domain dom13_14 as float default 0.999999940395355224609375; + + -- https://en.wikipedia.org/wiki/Double-precision_floating-point_format + -- Max Double: power(2,1023) * ( 1+(1-power(2,-52) ) + create domain dom13_15 as double precision default 1.7976931348623157e308; + + create domain dom13_16 as blob default 'Ø'; + + create domain dom13_17 as boolean default false; + create domain dom13_18 as decfloat(16) default -9.999999999999999E+384; + create domain dom13_19 as decfloat default -9.999999999999999999999999999999999E6144; + commit; + + recreate table test( + f101 dom13_01 + ,f102 dom13_02 + ,f103 dom13_03 + ,f104 dom13_04 + ,f105 dom13_05 + ,f106 dom13_06 + ,f107 dom13_07 + ,f108 dom13_08 + ,f109 dom13_09 + ,f110 dom13_10 + ,f111 dom13_11 + ,f112 dom13_12 + ,f113 dom13_13 + ,f114 dom13_14 + ,f115 dom13_15 + ,f116 dom13_16 + ,f117 dom13_17 + ,f118 dom13_18 + ,f119 dom13_19 + ------------------------------------- + + ,f201 dom13_01 default 32767 + ,f202 dom13_02 default 2147483647 + ,f203 dom13_03 default 9223372036854775807 + ,f204 dom13_04 default '01.01.0001' + ,f205 dom13_05 default '23:59:59.999' + ,f206 dom13_06 default '22:22:22.222 Pacific/Fiji' + ,f207 dom13_07 default '15.12.1234 12:34:56.789' + ,f208 dom13_08 default '22.12.2222 22:22:22.222 Pacific/Fiji' + ,f209 dom13_09 default '¥' + ,f210 dom13_10 default '£' + ,f211 dom13_11 default 'Ç' + ,f212 dom13_12 default 327.67 + ,f213 dom13_13 default 999999999999999999 + ,f214 dom13_14 default 1.0000001192 + ,f215 dom13_15 default 1.4012984643e-45 + ,f216_blob_id dom13_16 default 'Ö' + ,f217 dom13_17 default true + ,f218 dom13_18 default 9.999999999999999E+384 + ,f219 dom13_19 default 9.999999999999999999999999999999999E+6144 + + ); + commit; + + insert into test default values; + set count on; + select * from test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F101 -32768 + F102 -2147483648 + F103 -9223372036854775807 + F104 9999-12-31 + F105 23:59:59.9990 + F106 11:11:11.1110 Indian/Cocos + F107 0001-01-01 00:00:01.0010 + F108 2013-12-21 11:11:11.1110 Indian/Cocos + F109 € + F110 ¢ + F111 Ö + F112 -327.68 + F113 -999999999999999999.00 + F114 0.99999994 + F115 1.797693134862316e+308 + F116 80:0 + Ø + F117 + F118 -9.999999999999999E+384 + F119 -9.999999999999999999999999999999999E+6144 + F201 32767 + F202 2147483647 + F203 9223372036854775807 + F204 0001-01-01 + F205 23:59:59.9990 + F206 22:22:22.2220 Pacific/Fiji + F207 1234-12-15 12:34:56.7890 + F208 2222-12-22 22:22:22.2220 Pacific/Fiji + F209 ¥ + F210 £ + F211 Ç + F212 327.67 + F213 999999999999999999.00 + F214 1.0000001 + F215 1.401298464300000e-45 + F216_BLOB_ID 80:1 + Ö + F217 + F218 9.999999999999999E+384 + F219 9.999999999999999999999999999999999E+6144 + + Records affected: 1 + """ + +@pytest.mark.version('>=4.0') +def test_dsql_domain_13_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_dsql_domain_20.py b/tests/functional/gtcs/test_dsql_domain_20.py new file mode 100644 index 00000000..c7547a9a --- /dev/null +++ b/tests/functional/gtcs/test_dsql_domain_20.py @@ -0,0 +1,237 @@ +#coding:utf-8 +# +# id: functional.gtcs.dsql_domain_20 +# title: GTCS/tests/DSQL_DOMAIN_20. Verify result of ALTER DOMAIN SET/DROP DEFAULT when a table exists with field based on this domain. +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/DSQL_DOMAIN_20.script +# +# Comment in GTCS +# This script will test using the alter domain statement on domains that are already in use in table definitions. +# Related bugs: have to exit db for changes made to domains to affect data being entered into tables. +# +# ::: NOTE ::: +# Added domains with datatype that did appear only in FB 4.0: DECFLOAT and TIME[STAMP] WITH TIME ZONE. For this reason only FB 4.0+ can be tested. +# +# Currently following datatypes are NOT checked: +# blob sub_type text|binary +# long float; +# binary(20); +# varbinary(20); +# +# Checked on 4.0.0.1954. +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('F16_BLOB_ID.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set list on; + set blob all; + + create domain dom20_01 as smallint default -32768; + create domain dom20_02 as int default -2147483648; + create domain dom20_03 as bigint default -9223372036854775807; + --create domain dom20_03 as bigint default -9223372036854775808; -- currently raises error 'numeric overflow', see CORE-6291 + create domain dom20_04 as date default '31.12.9999'; + create domain dom20_05 as time default '23:59:59.999'; + create domain dom20_06 as time with time zone default '11:11:11.111 Indian/Cocos'; + create domain dom20_07 as timestamp default '01.01.0001 00:00:01.001'; + create domain dom20_08 as timestamp with time zone default '21.12.2013 11:11:11.111 Indian/Cocos'; + create domain dom20_09 as char(1) character set utf8 default '€'; + create domain dom20_10 as varchar(1) character set utf8 default '¢'; + -- https://en.wikipedia.org/wiki/ISO/IEC_8859-1, + -- see table "Languages with incomplete coverage", + -- column "Typical workaround" for Hungarian 'Ő': + create domain dom20_11 as nchar(1) default 'Ö' ; + create domain dom20_12 as numeric(2,2) default -327.68; + create domain dom20_13 as decimal(20,2) default -999999999999999999; + + -- Online evaluation of expressions: https://www.wolframalpha.com + + -- https://en.wikipedia.org/wiki/Single-precision_floating-point_format + -- (largest number less than one): 1 - power(2,-24) + create domain dom20_14 as float default 0.999999940395355224609375; + + -- https://en.wikipedia.org/wiki/Double-precision_floating-point_format + -- Max Double: power(2,1023) * ( 1+(1-power(2,-52) ) + create domain dom20_15 as double precision default 1.7976931348623157e308; + + create domain dom20_16 as blob default 'Ø'; + + create domain dom20_17 as boolean default false; + create domain dom20_18 as decfloat(16) default -9.999999999999999E+384; + create domain dom20_19 as decfloat default -9.999999999999999999999999999999999E6144; + commit; + + recreate table test( + f01 dom20_01 + ,f02 dom20_02 + ,f03 dom20_03 + ,f04 dom20_04 + ,f05 dom20_05 + ,f06 dom20_06 + ,f07 dom20_07 + ,f08 dom20_08 + ,f09 dom20_09 + ,f10 dom20_10 + ,f11 dom20_11 + ,f12 dom20_12 + ,f13 dom20_13 + ,f14 dom20_14 + ,f15 dom20_15 + ,f16_blob_id dom20_16 + ,f17 dom20_17 + ,f18 dom20_18 + ,f19 dom20_19 + ); + commit; + + insert into test default values; + select 'point-1' as msg, t.* from test t; + rollback; + + alter domain dom20_01 drop default; + alter domain dom20_02 drop default; + alter domain dom20_03 drop default; + alter domain dom20_04 drop default; + alter domain dom20_05 drop default; + alter domain dom20_06 drop default; + alter domain dom20_07 drop default; + alter domain dom20_08 drop default; + alter domain dom20_09 drop default; + alter domain dom20_10 drop default; + alter domain dom20_11 drop default; + alter domain dom20_12 drop default; + alter domain dom20_13 drop default; + alter domain dom20_14 drop default; + alter domain dom20_15 drop default; + alter domain dom20_16 drop default; + alter domain dom20_17 drop default; + alter domain dom20_18 drop default; + alter domain dom20_19 drop default; + commit; + + insert into test default values; + select 'point-2' as msg, t.* from test t; + rollback; + + alter domain dom20_01 set default 0x7FFF; -- 32767 + alter domain dom20_02 set default 0x7FFFFFFF; -- 2147483647 + alter domain dom20_03 set default 0x7FFFFFFFFFFFFFFF; -- 9223372036854775807 + alter domain dom20_04 set default '01.01.0001'; + alter domain dom20_05 set default '23:59:59.999'; + alter domain dom20_06 set default '22:22:22.222 Pacific/Fiji'; + alter domain dom20_07 set default '15.12.1234 12:34:56.789'; + alter domain dom20_08 set default '22.12.2222 22:22:22.222 Pacific/Fiji'; + alter domain dom20_09 set default '¥'; + alter domain dom20_10 set default '£'; + alter domain dom20_11 set default 'Ç'; + alter domain dom20_12 set default 327.67; + alter domain dom20_13 set default 0xDE0B6B3A763FFFF; -- 999999999999999999 + alter domain dom20_14 set default 1.0000001192; + alter domain dom20_15 set default 1.4012984643e-45; + alter domain dom20_16 set default 'Ö'; + alter domain dom20_17 set default true; + alter domain dom20_18 set default 9.999999999999999E+384; + alter domain dom20_19 set default 9.999999999999999999999999999999999E+6144; + + insert into test default values; + select 'point-3' as msg, t.* from test t; + rollback; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG point-1 + F01 -32768 + F02 -2147483648 + F03 -9223372036854775807 + F04 9999-12-31 + F05 23:59:59.9990 + F06 11:11:11.1110 Indian/Cocos + F07 0001-01-01 00:00:01.0010 + F08 2013-12-21 11:11:11.1110 Indian/Cocos + F09 € + F10 ¢ + F11 Ö + F12 -327.68 + F13 -999999999999999999.00 + F14 0.99999994 + F15 1.797693134862316e+308 + F16_BLOB_ID 80:0 + Ø + F17 + F18 -9.999999999999999E+384 + F19 -9.999999999999999999999999999999999E+6144 + + + + MSG point-2 + F01 + F02 + F03 + F04 + F05 + F06 + F07 + F08 + F09 + F10 + F11 + F12 + F13 + F14 + F15 + F16_BLOB_ID + F17 + F18 + F19 + + + + MSG point-3 + F01 32767 + F02 2147483647 + F03 9223372036854775807 + F04 0001-01-01 + F05 23:59:59.9990 + F06 22:22:22.2220 Pacific/Fiji + F07 1234-12-15 12:34:56.7890 + F08 2222-12-22 22:22:22.2220 Pacific/Fiji + F09 ¥ + F10 £ + F11 Ç + F12 327.67 + F13 999999999999999999.00 + F14 1.0000001 + F15 1.401298464300000e-45 + F16_BLOB_ID 80:0 + Ö + F17 + F18 9.999999999999999E+384 + F19 9.999999999999999999999999999999999E+6144 + """ + +@pytest.mark.version('>=4.0') +def test_dsql_domain_20_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_dsql_domain_21.py b/tests/functional/gtcs/test_dsql_domain_21.py new file mode 100644 index 00000000..b57025bb --- /dev/null +++ b/tests/functional/gtcs/test_dsql_domain_21.py @@ -0,0 +1,580 @@ +#coding:utf-8 +# +# id: functional.gtcs.dsql_domain_21 +# title: GTCS/tests/DSQL_DOMAIN_21. Verify result of ALTER DOMAIN with changing DEFAULT values and DROP constraints when a table exists with field based on this domain. +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/DSQL_DOMAIN_21.script +# +# Comment in GTCS: +# This script will test using the alter domain statement on domains that are already in use in table definitions, +# with domain defaults and check constraints. +# Related bugs: have to exit db for changes made to domains to affect data being entered into tables. +# +# We create domains with default values and constraints. Initially we use such default values that PASS requirements of check-constraints. +# Statement INSERT DEFAULT and query to the test table is used in order to ensure that we have ability to use such values. +# +# Then we change values in DEFAULT clause so that all of them will VILOLATE check expressions. Here take domains one-by-one and try to user +# INSERT DEFAULT after each such change of DEFAULT value. Every such attempt must fail. +# +# Then we drop CHECK constraints in all domains and again try INSERT DEFAULT. It must pass and new default values must be stored in the test table. +# Finally, we drop DEFAULT in all domains and try INSERT DEFAULT one more time. It must result to NULL value in all fields. +# +# ::: NB::: Changing default value for BLOB field to one that violates CHECK-expression of domain leads to strange message that does not +# relates to actual problem: SQLSTATE = 22018 / conversion error from string "BLOB". See CORE-6297 for details. +# +# ::: NOTE ::: +# Added domains with datatype that did appear only in FB 4.0: DECFLOAT and TIME[STAMP] WITH TIME ZONE. For this reason only FB 4.0+ can be tested. +# +# Checked on 4.0.0.1954. +# +# 08.04.2021: changed expected output for date 01-jan-0001 after discuss with Adriano. +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('F18_BLOB_ID.*', ''), ('F19_BLOB_ID.*', ''), ('F20_BLOB_ID.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set list on; + set blob all; + + create or alter view v_test as + select + ff.rdb$field_name as dm_name + ,ff.rdb$field_type as dm_type + ,ff.rdb$field_sub_type as dm_subtype + ,ff.rdb$field_length as dm_flen + ,ff.rdb$field_scale as dm_fscale + ,ff.rdb$field_precision as dm_fprec + ,ff.rdb$character_set_id as dm_fcset + ,ff.rdb$collation_id as dm_fcoll + ,ff.rdb$character_length dm_fchrlen + ,ff.rdb$null_flag as dm_fnull + ,ff.rdb$validation_source as dm_fvalid + ,ff.rdb$default_source as dm_fdefault + from rdb$fields ff + where + ff.rdb$system_flag is distinct from 1 + and ff.rdb$field_name starting with upper( 'dom21' ) + order by dm_name + ; + commit; + + create domain dom21_01 as smallint default -32768 check (value not in ( select r.rdb$relation_id from rdb$relations r where r.rdb$system_flag = 1 ) ); + + create domain dom21_02 as int default 1500 + check ( + value in ( + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41, + 42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, + 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112, + 113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140, + 141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168, + 169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196, + 197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224, + 225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252, + 253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280, + 281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308, + 309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336, + 337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364, + 365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392, + 393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420, + 421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448, + 449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476, + 477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504, + 505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532, + 533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560, + 561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588, + 589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616, + 617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644, + 645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672, + 673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700, + 701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728, + 729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756, + 757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784, + 785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812, + 813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840, + 841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868, + 869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896, + 897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924, + 925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952, + 953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980, + 981,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999,1000,1001,1002,1003,1004,1005,1006, + 1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028, + 1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050, + 1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072, + 1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094, + 1095,1096,1097,1098,1099,1100,1101,1102,1103,1104,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116, + 1117,1118,1119,1120,1121,1122,1123,1124,1125,1126,1127,1128,1129,1130,1131,1132,1133,1134,1135,1136,1137,1138, + 1139,1140,1141,1142,1143,1144,1145,1146,1147,1148,1149,1150,1151,1152,1153,1154,1155,1156,1157,1158,1159,1160, + 1161,1162,1163,1164,1165,1166,1167,1168,1169,1170,1171,1172,1173,1174,1175,1176,1177,1178,1179,1180,1181,1182, + 1183,1184,1185,1186,1187,1188,1189,1190,1191,1192,1193,1194,1195,1196,1197,1198,1199,1200,1201,1202,1203,1204, + 1205,1206,1207,1208,1209,1210,1211,1212,1213,1214,1215,1216,1217,1218,1219,1220,1221,1222,1223,1224,1225,1226, + 1227,1228,1229,1230,1231,1232,1233,1234,1235,1236,1237,1238,1239,1240,1241,1242,1243,1244,1245,1246,1247,1248, + 1249,1250,1251,1252,1253,1254,1255,1256,1257,1258,1259,1260,1261,1262,1263,1264,1265,1266,1267,1268,1269,1270, + 1271,1272,1273,1274,1275,1276,1277,1278,1279,1280,1281,1282,1283,1284,1285,1286,1287,1288,1289,1290,1291,1292, + 1293,1294,1295,1296,1297,1298,1299,1300,1301,1302,1303,1304,1305,1306,1307,1308,1309,1310,1311,1312,1313,1314, + 1315,1316,1317,1318,1319,1320,1321,1322,1323,1324,1325,1326,1327,1328,1329,1330,1331,1332,1333,1334,1335,1336, + 1337,1338,1339,1340,1341,1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358, + 1359,1360,1361,1362,1363,1364,1365,1366,1367,1368,1369,1370,1371,1372,1373,1374,1375,1376,1377,1378,1379,1380, + 1381,1382,1383,1384,1385,1386,1387,1388,1389,1390,1391,1392,1393,1394,1395,1396,1397,1398,1399,1400,1401,1402, + 1403,1404,1405,1406,1407,1408,1409,1410,1411,1412,1413,1414,1415,1416,1417,1418,1419,1420,1421,1422,1423,1424, + 1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446, + 1447,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468, + 1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490, + 1491,1492,1493,1494,1495,1496,1497,1498,1499,1500 + ) + ) + ; + create domain dom21_03 as bigint default -9223372036854775807 + check ( + value NOT in ( + 1500,1499,1498,1497,1496,1495,1494,1493,1492,1491,1490,1489,1488,1487,1486,1485,1484,1483,1482,1481,1480,1479, + 1478,1477,1476,1475,1474,1473,1472,1471,1470,1469,1468,1467,1466,1465,1464,1463,1462,1461,1460,1459,1458,1457, + 1456,1455,1454,1453,1452,1451,1450,1449,1448,1447,1446,1445,1444,1443,1442,1441,1440,1439,1438,1437,1436,1435, + 1434,1433,1432,1431,1430,1429,1428,1427,1426,1425,1424,1423,1422,1421,1420,1419,1418,1417,1416,1415,1414,1413, + 1412,1411,1410,1409,1408,1407,1406,1405,1404,1403,1402,1401,1400,1399,1398,1397,1396,1395,1394,1393,1392,1391, + 1390,1389,1388,1387,1386,1385,1384,1383,1382,1381,1380,1379,1378,1377,1376,1375,1374,1373,1372,1371,1370,1369, + 1368,1367,1366,1365,1364,1363,1362,1361,1360,1359,1358,1357,1356,1355,1354,1353,1352,1351,1350,1349,1348,1347, + 1346,1345,1344,1343,1342,1341,1340,1339,1338,1337,1336,1335,1334,1333,1332,1331,1330,1329,1328,1327,1326,1325, + 1324,1323,1322,1321,1320,1319,1318,1317,1316,1315,1314,1313,1312,1311,1310,1309,1308,1307,1306,1305,1304,1303, + 1302,1301,1300,1299,1298,1297,1296,1295,1294,1293,1292,1291,1290,1289,1288,1287,1286,1285,1284,1283,1282,1281, + 1280,1279,1278,1277,1276,1275,1274,1273,1272,1271,1270,1269,1268,1267,1266,1265,1264,1263,1262,1261,1260,1259, + 1258,1257,1256,1255,1254,1253,1252,1251,1250,1249,1248,1247,1246,1245,1244,1243,1242,1241,1240,1239,1238,1237, + 1236,1235,1234,1233,1232,1231,1230,1229,1228,1227,1226,1225,1224,1223,1222,1221,1220,1219,1218,1217,1216,1215, + 1214,1213,1212,1211,1210,1209,1208,1207,1206,1205,1204,1203,1202,1201,1200,1199,1198,1197,1196,1195,1194,1193, + 1192,1191,1190,1189,1188,1187,1186,1185,1184,1183,1182,1181,1180,1179,1178,1177,1176,1175,1174,1173,1172,1171, + 1170,1169,1168,1167,1166,1165,1164,1163,1162,1161,1160,1159,1158,1157,1156,1155,1154,1153,1152,1151,1150,1149, + 1148,1147,1146,1145,1144,1143,1142,1141,1140,1139,1138,1137,1136,1135,1134,1133,1132,1131,1130,1129,1128,1127, + 1126,1125,1124,1123,1122,1121,1120,1119,1118,1117,1116,1115,1114,1113,1112,1111,1110,1109,1108,1107,1106,1105, + 1104,1103,1102,1101,1100,1099,1098,1097,1096,1095,1094,1093,1092,1091,1090,1089,1088,1087,1086,1085,1084,1083, + 1082,1081,1080,1079,1078,1077,1076,1075,1074,1073,1072,1071,1070,1069,1068,1067,1066,1065,1064,1063,1062,1061, + 1060,1059,1058,1057,1056,1055,1054,1053,1052,1051,1050,1049,1048,1047,1046,1045,1044,1043,1042,1041,1040,1039, + 1038,1037,1036,1035,1034,1033,1032,1031,1030,1029,1028,1027,1026,1025,1024,1023,1022,1021,1020,1019,1018,1017, + 1016,1015,1014,1013,1012,1011,1010,1009,1008,1007,1006,1005,1004,1003,1002,1001,1000,999,998,997,996,995,994, + 993,992,991,990,989,988,987,986,985,984,983,982,981,980,979,978,977,976,975,974,973,972,971,970,969,968,967, + 966,965,964,963,962,961,960,959,958,957,956,955,954,953,952,951,950,949,948,947,946,945,944,943,942,941,940, + 939,938,937,936,935,934,933,932,931,930,929,928,927,926,925,924,923,922,921,920,919,918,917,916,915,914,913, + 912,911,910,909,908,907,906,905,904,903,902,901,900,899,898,897,896,895,894,893,892,891,890,889,888,887,886, + 885,884,883,882,881,880,879,878,877,876,875,874,873,872,871,870,869,868,867,866,865,864,863,862,861,860,859, + 858,857,856,855,854,853,852,851,850,849,848,847,846,845,844,843,842,841,840,839,838,837,836,835,834,833,832, + 831,830,829,828,827,826,825,824,823,822,821,820,819,818,817,816,815,814,813,812,811,810,809,808,807,806,805, + 804,803,802,801,800,799,798,797,796,795,794,793,792,791,790,789,788,787,786,785,784,783,782,781,780,779,778, + 777,776,775,774,773,772,771,770,769,768,767,766,765,764,763,762,761,760,759,758,757,756,755,754,753,752,751, + 750,749,748,747,746,745,744,743,742,741,740,739,738,737,736,735,734,733,732,731,730,729,728,727,726,725,724, + 723,722,721,720,719,718,717,716,715,714,713,712,711,710,709,708,707,706,705,704,703,702,701,700,699,698,697, + 696,695,694,693,692,691,690,689,688,687,686,685,684,683,682,681,680,679,678,677,676,675,674,673,672,671,670, + 669,668,667,666,665,664,663,662,661,660,659,658,657,656,655,654,653,652,651,650,649,648,647,646,645,644,643, + 642,641,640,639,638,637,636,635,634,633,632,631,630,629,628,627,626,625,624,623,622,621,620,619,618,617,616, + 615,614,613,612,611,610,609,608,607,606,605,604,603,602,601,600,599,598,597,596,595,594,593,592,591,590,589, + 588,587,586,585,584,583,582,581,580,579,578,577,576,575,574,573,572,571,570,569,568,567,566,565,564,563,562, + 561,560,559,558,557,556,555,554,553,552,551,550,549,548,547,546,545,544,543,542,541,540,539,538,537,536,535, + 534,533,532,531,530,529,528,527,526,525,524,523,522,521,520,519,518,517,516,515,514,513,512,511,510,509,508, + 507,506,505,504,503,502,501,500,499,498,497,496,495,494,493,492,491,490,489,488,487,486,485,484,483,482,481, + 480,479,478,477,476,475,474,473,472,471,470,469,468,467,466,465,464,463,462,461,460,459,458,457,456,455,454, + 453,452,451,450,449,448,447,446,445,444,443,442,441,440,439,438,437,436,435,434,433,432,431,430,429,428,427, + 426,425,424,423,422,421,420,419,418,417,416,415,414,413,412,411,410,409,408,407,406,405,404,403,402,401,400, + 399,398,397,396,395,394,393,392,391,390,389,388,387,386,385,384,383,382,381,380,379,378,377,376,375,374,373, + 372,371,370,369,368,367,366,365,364,363,362,361,360,359,358,357,356,355,354,353,352,351,350,349,348,347,346, + 345,344,343,342,341,340,339,338,337,336,335,334,333,332,331,330,329,328,327,326,325,324,323,322,321,320,319, + 318,317,316,315,314,313,312,311,310,309,308,307,306,305,304,303,302,301,300,299,298,297,296,295,294,293,292, + 291,290,289,288,287,286,285,284,283,282,281,280,279,278,277,276,275,274,273,272,271,270,269,268,267,266,265, + 264,263,262,261,260,259,258,257,256,255,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238, + 237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211, + 210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184, + 183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157, + 156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130, + 129,128,127,126,125,124,123,122,121,120,119,118,117,116,115,114,113,112,111,110,109,108,107,106,105,104,103, + 102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68, + 67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32, + 31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1 + ) + ) + ; + + create domain dom21_04 as date default '01.01.1980' check ( value >='01.01.0001' and value <= '30.12.9999'); + + create domain dom21_05 as time default '23:59:59.999' check ( extract(hour from value) >=21 ); + + create domain dom21_06 as time with time zone default '11:11:11.111 Indian/Cocos' check ( extract(hour from value) <=12 ); + create domain dom21_07 as timestamp default '01.01.0001 00:00:01.001' check ( extract(minute from value) = 0 ); + create domain dom21_08 as timestamp with time zone default '21.12.2013 11:11:11.111 Indian/Cocos' check ( extract(minute from value) <=30 ); + create domain dom21_09 as char(1) character set utf8 default '€' check( value in ('€', '¢') ); + create domain dom21_10 as varchar(1) character set utf8 default '¢' check( value in ('€', '¢') ); + -- https://en.wikipedia.org/wiki/ISO/IEC_8859-1, + -- see table "Languages with incomplete coverage", + -- column "Typical workaround" for Hungarian 'Ő': + create domain dom21_11 as nchar(1) default 'Ö' check( value in ('Ö', 'Ø') ); + create domain dom21_12 as binary(2) default 'Œ' check( value in ('Œ', 'Ÿ', '¿') ); -- this datatype is alias for char(N) character set octets + create domain dom21_13 as varbinary(2) default 'Œ' check( value in ('Œ', 'Ÿ', '¿') ); + + create domain dom21_14 as numeric(2,2) default -327.68 check ( value < 0 ); + create domain dom21_15 as decimal(20,2) default -999999999999999999 check( value < 0 ); + + -- Online evaluation of expressions: https://www.wolframalpha.com + + -- https://en.wikipedia.org/wiki/Single-precision_floating-point_format + -- (largest number less than one): 1 - power(2,-24) + create domain dom21_16 as float default 0.999999940395355224609375 check( abs(value) < 1 ); + + -- https://en.wikipedia.org/wiki/Double-precision_floating-point_format + -- Max Double: power(2,1023) * ( 1+(1-power(2,-52) ) + create domain dom21_17 as double precision default 1.7976931348623157e308 check( abs(value) > 1 ); + + create domain dom21_18 as blob default 'Ø' check( value in ('Ö', 'Ø') ); + create domain dom21_19 as blob sub_type text default 'W' check (value > ''); + create domain dom21_20 as blob sub_type binary default 'f' check (value similar to '([0-9]|[a-f]){1,}'); + + + create domain dom21_21 as boolean default false check ( value is not true ); + create domain dom21_22 as decfloat(16) default -9.999999999999999E+384 check( log10(abs(value)) >= 384 ); + create domain dom21_23 as decfloat default -9.999999999999999999999999999999999E6144 check( log10(abs(value)) >= 6144 ); + commit; + + --select * from v_test; + + recreate table test( + f01 dom21_01 + ,f02 dom21_02 + ,f03 dom21_03 + ,f04 dom21_04 + ,f05 dom21_05 + ,f06 dom21_06 + ,f07 dom21_07 + ,f08 dom21_08 + ,f09 dom21_09 + ,f10 dom21_10 + ,f11 dom21_11 + ,f12 dom21_12 + ,f13 dom21_13 + ,f14 dom21_14 + ,f15 dom21_15 + ,f16 dom21_16 + ,f17 dom21_17 + ,f18_blob_id dom21_18 + ,f19_blob_id dom21_19 + ,f20_blob_id dom21_20 + ,f21 dom21_21 + ,f22 dom21_22 + ,f23 dom21_23 + ); + commit; + + set bail off; -- ### NB ### + + insert into test default values; -- this must PASS + select 'point-1' as msg, t.* from test t; + rollback; + + ---------------------------------- + -- Now we change DEFAULT values of domains so that they become violate CHECK expressions: + alter domain dom21_01 set default 1; + insert into test default values; -- this must FAIL with SQLSTATE = 23000 / validation error for column "TEST"."F01", value "1" + alter domain dom21_01 drop constraint; -- in order to have ability to test next domain and field + + alter domain dom21_02 set default -1; + insert into test default values; -- validation error for column "TEST"."F02", value "-1" + alter domain dom21_02 drop constraint; + + alter domain dom21_03 set default 1; + insert into test default values; -- validation error for column "TEST"."F03", value "1" + alter domain dom21_03 drop constraint; + + alter domain dom21_04 set default '31.12.9999'; + insert into test default values; -- validation error for column "TEST"."F04", value "9999-12-31" + alter domain dom21_04 drop constraint; + + alter domain dom21_05 set default '20:59:59.999'; + insert into test default values; -- validation error for column "TEST"."F05", value "20:59:59.9990" + alter domain dom21_05 drop constraint; + + alter domain dom21_06 set default '13:00:00 Indian/Cocos'; + insert into test default values; -- validation error for column "TEST"."F06", value "13:00:00.0000 Indian/Cocos" + alter domain dom21_06 drop constraint; + + alter domain dom21_07 set default '01.01.0001 01:01:01.001'; + insert into test default values; -- validation error for column "TEST"."F07", value "01-JAN-1 1:01:01.0010" // changed 08.04.2021, was: '1-jan' + alter domain dom21_07 drop constraint; + + alter domain dom21_08 set default '21.12.2013 10:31:00 Indian/Cocos'; + insert into test default values; -- validation error for column "TEST"."F08", value "21-DEC-2013 10:31:00.0000 Indian/Cocos" + alter domain dom21_08 drop constraint; + + alter domain dom21_09 set default 'Ő'; + insert into test default values; -- validation error for column "TEST"."F09", value "Ő" + alter domain dom21_09 drop constraint; + + alter domain dom21_10 set default ''; + insert into test default values; -- validation error for column "TEST"."F10", value "" + alter domain dom21_10 drop constraint; + + alter domain dom21_11 set default ''; + insert into test default values; -- validation error for column "TEST"."F11", value " " // nchar(1) + alter domain dom21_11 drop constraint; + + alter domain dom21_12 set default 'Ø'; + insert into test default values; -- validation error for column "TEST"."F12", value "Ø" + alter domain dom21_12 drop constraint; + + alter domain dom21_13 set default '¢'; + insert into test default values; -- validation error for column "TEST"."F13", value "¢" + alter domain dom21_13 drop constraint; + + alter domain dom21_14 set default 327.67; + insert into test default values; -- validation error for column "TEST"."F14", value "327.67" + alter domain dom21_14 drop constraint; + + alter domain dom21_15 set default 0; + insert into test default values; -- validation error for column "TEST"."F15", value "0.00" + alter domain dom21_15 drop constraint; + + alter domain dom21_16 set default 1; + insert into test default values; -- validation error for column "TEST"."F16", value "1.0000000" + alter domain dom21_16 drop constraint; + + alter domain dom21_17 set default 1.0000000000000001; + insert into test default values; -- validation error for column "TEST"."F17", value "1.000000000000000" + alter domain dom21_17 drop constraint; + + alter domain dom21_18 set default 'x'; + insert into test default values; -- ### CORE-6297 ### STRANGE MESSAGE HERE: Statement failed, SQLSTATE = 22018 / conversion error from string "BLOB" + alter domain dom21_18 drop constraint; + + alter domain dom21_19 set default ''; + insert into test default values; -- ### CORE-6297 ### STRANGE MESSAGE HERE: Statement failed, SQLSTATE = 22018 / conversion error from string "BLOB" + alter domain dom21_19 drop constraint; + + alter domain dom21_20 set default 'g'; + insert into test default values; -- ### CORE-6297 ### STRANGE MESSAGE HERE: Statement failed, SQLSTATE = 22018 / conversion error from string "BLOB" + alter domain dom21_20 drop constraint; + + alter domain dom21_21 set default true; + insert into test default values; -- validation error for column "TEST"."F21", value "TRUE" + alter domain dom21_21 drop constraint; + + alter domain dom21_22 set default -9.999999999999999E+382; + insert into test default values; -- validation error for column "TEST"."F22", value "-9.999999999999999E+382" + alter domain dom21_22 drop constraint; + + alter domain dom21_23 set default -9.999999999999999999999999999999999E6142; + insert into test default values; -- validation error for column "TEST"."F23", value "-9.999999999999999999999999999999999E+6142" + alter domain dom21_23 drop constraint; + + --------------------------------------- + -- Now we have NO constraints in any domain. + -- We can run again INSERT DEFAULT and verify that new values appear in the table + insert into test default values; -- this must PASS + select 'point-2' as msg, t.* from test t; -- all values must have now NEW defaults for domains + rollback; + + alter domain dom21_01 drop default; + alter domain dom21_02 drop default; + alter domain dom21_03 drop default; + alter domain dom21_04 drop default; + alter domain dom21_05 drop default; + alter domain dom21_06 drop default; + alter domain dom21_07 drop default; + alter domain dom21_08 drop default; + alter domain dom21_09 drop default; + alter domain dom21_10 drop default; + alter domain dom21_11 drop default; + alter domain dom21_12 drop default; + alter domain dom21_13 drop default; + alter domain dom21_14 drop default; + alter domain dom21_15 drop default; + alter domain dom21_16 drop default; + alter domain dom21_17 drop default; + alter domain dom21_18 drop default; + alter domain dom21_19 drop default; + alter domain dom21_20 drop default; + alter domain dom21_21 drop default; + alter domain dom21_22 drop default; + alter domain dom21_23 drop default; + + insert into test default values; -- this must PASS + select 'point-3' as msg, t.* from test t; -- all values now must be NULL + rollback; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG point-1 + F01 -32768 + F02 1500 + F03 -9223372036854775807 + F04 1980-01-01 + F05 23:59:59.9990 + F06 11:11:11.1110 Indian/Cocos + F07 0001-01-01 00:00:01.0010 + F08 2013-12-21 11:11:11.1110 Indian/Cocos + F09 € + F10 ¢ + F11 Ö + F12 C592 + F13 C592 + F14 -327.68 + F15 -999999999999999999.00 + F16 0.99999994 + F17 1.797693134862316e+308 + F18_BLOB_ID 81:0 + Ø + F19_BLOB_ID 81:1 + W + F20_BLOB_ID 81:2 + f + F21 + F22 -9.999999999999999E+384 + F23 -9.999999999999999999999999999999999E+6144 + + + + MSG point-2 + F01 1 + F02 -1 + F03 1 + F04 9999-12-31 + F05 20:59:59.9990 + F06 13:00:00.0000 Indian/Cocos + F07 0001-01-01 01:01:01.0010 + F08 2013-12-21 10:31:00.0000 Indian/Cocos + F09 Ő + F10 + F11 + F12 C398 + F13 C2A2 + F14 327.67 + F15 0.00 + F16 1 + F17 1.000000000000000 + F18_BLOB_ID 81:45 + x + F19_BLOB_ID 81:46 + + F20_BLOB_ID 81:47 + g + F21 + F22 -9.999999999999999E+382 + F23 -9.999999999999999999999999999999999E+6142 + + + + MSG point-3 + F01 + F02 + F03 + F04 + F05 + F06 + F07 + F08 + F09 + F10 + F11 + F12 + F13 + F14 + F15 + F16 + F17 + F18_BLOB_ID + F19_BLOB_ID + F20_BLOB_ID + F21 + F22 + F23 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."F01", value "1" + + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."F02", value "-1" + + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."F03", value "1" + + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."F04", value "9999-12-31" + + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."F05", value "20:59:59.9990" + + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."F06", value "13:00:00.0000 Indian/Cocos" + + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."F07", value "01-JAN-0001 1:01:01.0010" + + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."F08", value "21-DEC-2013 10:31:00.0000 Indian/Cocos" + + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."F09", value "Ő" + + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."F10", value "" + + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."F11", value " " + + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."F12", value "Ø" + + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."F13", value "¢" + + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."F14", value "327.67" + + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."F15", value "0.00" + + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."F16", value "1.0000000" + + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."F17", value "1.000000000000000" + + Statement failed, SQLSTATE = 22018 + conversion error from string "BLOB" + + Statement failed, SQLSTATE = 22018 + conversion error from string "BLOB" + + Statement failed, SQLSTATE = 22018 + conversion error from string "BLOB" + + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."F21", value "TRUE" + + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."F22", value "-9.999999999999999E+382" + + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."F23", value "-9.999999999999999999999999999999999E+6142" + """ + +@pytest.mark.version('>=4.0') +def test_dsql_domain_21_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_execute_statement_within_procedure.py b/tests/functional/gtcs/test_execute_statement_within_procedure.py new file mode 100644 index 00000000..800c35d5 --- /dev/null +++ b/tests/functional/gtcs/test_execute_statement_within_procedure.py @@ -0,0 +1,96 @@ +#coding:utf-8 +# +# id: functional.gtcs.execute_statement_within_procedure +# title: GTCS/tests/CF_ISQL_27. EXECUTE STATEMENT within a stored procedure could lead to a problems +# decription: +# ::: NB ::: +# ### Name of original test has no any relation with actual task of this test: ### +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_27.script +# +# Discuss in fb-devel (subj: "Vulcan, CF_ISQL_27.sql"): +# https://sourceforge.net/p/firebird/mailman/message/17631672/ +# +# Author said that example from this test did not return any error (and he expacted this) +# plus either did not return value into output parameter or even lead server to crash +# (when such SP was called twise). +# For current FB versions no error occurs and output value is issued w/o any problems. +# +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create generator gen_test1; + set generator gen_test1 to 1111111; + create generator gen_test2; + set generator gen_test2 to 2222222; + set term ^; + create procedure rpl$generator_values + returns ( + gen_name varchar(31), + gen_value integer + ) + as + begin + for + select rdb$generator_name + from rdb$generators + where coalesce (rdb$system_flag, 0) = 0 + order by 1 + into :gen_name do + begin + execute statement 'select gen_id(' || gen_name || ',0) from rdb$database' into :gen_value; + suspend; + end + end + ^ + set term ;^ + commit; + + set list on; + select 'point-1' msg, p.* from rpl$generator_values p; + select 'point-2' msg, p.* from rpl$generator_values p; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG point-1 + GEN_NAME GEN_TEST1 + GEN_VALUE 1111111 + + MSG point-1 + GEN_NAME GEN_TEST2 + GEN_VALUE 2222222 + + MSG point-2 + GEN_NAME GEN_TEST1 + GEN_VALUE 1111111 + + MSG point-2 + GEN_NAME GEN_TEST2 + GEN_VALUE 2222222 + """ + +@pytest.mark.version('>=2.5') +def test_execute_statement_within_procedure_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_external_file_03_d.py b/tests/functional/gtcs/test_external_file_03_d.py new file mode 100644 index 00000000..d604e40c --- /dev/null +++ b/tests/functional/gtcs/test_external_file_03_d.py @@ -0,0 +1,96 @@ +#coding:utf-8 +# +# id: functional.gtcs.external_file_03_d +# title: GTCS/tests/external-file-03-d. Test for external table with field of SMALLINT datatype +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/EXT_REL_0_3_D.script +# Checked on: 4.0.0.2240; 3.0.7.33380 +# +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# import time +# +# tmp_file = os.path.join(context['temp_directory'],'tmp_ext_03_d.tmp') +# if os.path.isfile( tmp_file): +# os.remove( tmp_file ) +# +# this_fdb = db_conn.database_name +# +# sql_cmd=''' +# connect 'localhost:%(this_fdb)s' user '%(user_name)s' password '%(user_password)s'; +# create table ext_table external file '%(tmp_file)s' (f01 smallint); +# commit; +# insert into ext_table (f01) values ( 32767); +# insert into ext_table (f01) values (-32768); +# insert into ext_table (f01) values (1); +# insert into ext_table (f01) values (-1); +# insert into ext_table (f01) values (0); +# insert into ext_table (f01) values ( 32768); +# insert into ext_table (f01) values ( -32769); +# commit; +# set list on; +# set count on; +# select * from ext_table order by f01; +# ''' % dict(globals(), **locals()) +# +# runProgram('isql', [ '-q' ], sql_cmd) +# +# f_sql_chk = open( os.path.join(context['temp_directory'],'tmp_ext_03_d.sql'), 'w') +# f_sql_chk.write(sql_cmd) +# f_sql_chk.close() +# +# time.sleep(1) +# +# os.remove(f_sql_chk.name) +# os.remove( tmp_file ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F01 -32768 + F01 -1 + F01 0 + F01 1 + F01 32767 + Records affected: 5 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22003 + arithmetic exception, numeric overflow, or string truncation + -numeric value is out of range + + Statement failed, SQLSTATE = 22003 + arithmetic exception, numeric overflow, or string truncation + -numeric value is out of range + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_external_file_03_d_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/gtcs/test_external_file_04_d.py b/tests/functional/gtcs/test_external_file_04_d.py new file mode 100644 index 00000000..46e97347 --- /dev/null +++ b/tests/functional/gtcs/test_external_file_04_d.py @@ -0,0 +1,96 @@ +#coding:utf-8 +# +# id: functional.gtcs.external_file_04_d +# title: GTCS/tests/external-file-04-d. Test for external table with field of INTEGER datatype +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/EXT_REL_0_4_D.script +# Checked on: 4.0.0.2240; 3.0.7.33380 +# +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# import time +# +# tmp_file = os.path.join(context['temp_directory'],'tmp_ext_04_d.tmp') +# if os.path.isfile( tmp_file): +# os.remove( tmp_file ) +# +# this_fdb = db_conn.database_name +# +# sql_cmd=''' +# connect 'localhost:%(this_fdb)s' user '%(user_name)s' password '%(user_password)s'; +# create table ext_table external file '%(tmp_file)s' (f01 int); +# commit; +# insert into ext_table (f01) values ( 2147483647); +# insert into ext_table (f01) values (-2147483648); +# insert into ext_table (f01) values (1); +# insert into ext_table (f01) values (-1); +# insert into ext_table (f01) values (0); +# insert into ext_table (f01) values ( 2147483648); +# insert into ext_table (f01) values (-2147483649); +# commit; +# set list on; +# set count on; +# select * from ext_table order by f01; +# ''' % dict(globals(), **locals()) +# +# runProgram('isql', [ '-q' ], sql_cmd) +# +# f_sql_chk = open( os.path.join(context['temp_directory'],'tmp_ext_04_d.sql'), 'w') +# f_sql_chk.write(sql_cmd) +# f_sql_chk.close() +# +# time.sleep(1) +# +# os.remove(f_sql_chk.name) +# os.remove( tmp_file ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F01 -2147483648 + F01 -1 + F01 0 + F01 1 + F01 2147483647 + Records affected: 5 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22003 + arithmetic exception, numeric overflow, or string truncation + -numeric value is out of range + + Statement failed, SQLSTATE = 22003 + arithmetic exception, numeric overflow, or string truncation + -numeric value is out of range + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_external_file_04_d_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/gtcs/test_external_file_04_d_bigint.py b/tests/functional/gtcs/test_external_file_04_d_bigint.py new file mode 100644 index 00000000..60de075d --- /dev/null +++ b/tests/functional/gtcs/test_external_file_04_d_bigint.py @@ -0,0 +1,85 @@ +#coding:utf-8 +# +# id: functional.gtcs.external_file_04_d_bigint +# title: GTCS/tests/external-file-04-d-bigint. Test for external table with field of BIGINT datatype +# decription: +# There is no similar test in GTCS, but for INTEGER datatype see: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/EXT_REL_0_4_D.script +# Checked on: 4.0.0.2240; 3.0.7.33380 +# +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# import time +# +# tmp_file = os.path.join(context['temp_directory'],'tmp_ext_04_d_bigint.tmp') +# if os.path.isfile( tmp_file): +# os.remove( tmp_file ) +# +# this_fdb = db_conn.database_name +# +# sql_cmd=''' +# connect 'localhost:%(this_fdb)s' user '%(user_name)s' password '%(user_password)s'; +# create table ext_table external file '%(tmp_file)s' (f01 bigint); +# commit; +# insert into ext_table (f01) values ( 9223372036854775807); +# insert into ext_table (f01) values (-9223372036854775808); +# insert into ext_table (f01) values (1); +# insert into ext_table (f01) values (-1); +# insert into ext_table (f01) values (0); +# commit; +# set list on; +# set count on; +# select * from ext_table order by f01; +# ''' % dict(globals(), **locals()) +# +# runProgram('isql', [ '-q' ], sql_cmd) +# +# f_sql_chk = open( os.path.join(context['temp_directory'],'tmp_ext_04_d_bigint.sql'), 'w') +# f_sql_chk.write(sql_cmd) +# f_sql_chk.close() +# +# time.sleep(1) +# +# os.remove(f_sql_chk.name) +# os.remove( tmp_file ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F01 -9223372036854775808 + F01 -1 + F01 0 + F01 1 + F01 9223372036854775807 + Records affected: 5 + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_external_file_04_d_bigint_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/gtcs/test_external_file_04_d_int128.py b/tests/functional/gtcs/test_external_file_04_d_int128.py new file mode 100644 index 00000000..c6f6b645 --- /dev/null +++ b/tests/functional/gtcs/test_external_file_04_d_int128.py @@ -0,0 +1,85 @@ +#coding:utf-8 +# +# id: functional.gtcs.external_file_04_d_int128 +# title: GTCS/tests/external-file-04-d-int128. Test for external table with field of INT128 datatype +# decription: +# There is no similar test in GTCS, but for INTEGER datatype see: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/EXT_REL_0_4_D.script +# Checked on: 4.0.0.2240 +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# import time +# +# tmp_file = os.path.join(context['temp_directory'],'tmp_ext_04_d_int128.tmp') +# if os.path.isfile( tmp_file): +# os.remove( tmp_file ) +# +# this_fdb = db_conn.database_name +# +# sql_cmd=''' +# connect 'localhost:%(this_fdb)s' user '%(user_name)s' password '%(user_password)s'; +# create table ext_table external file '%(tmp_file)s' (f01 int128); +# commit; +# insert into ext_table (f01) values ( 170141183460469231731687303715884105727); +# insert into ext_table (f01) values (-170141183460469231731687303715884105728); +# insert into ext_table (f01) values (1); +# insert into ext_table (f01) values (-1); +# insert into ext_table (f01) values (0); +# commit; +# set list on; +# set count on; +# select * from ext_table order by f01; +# ''' % dict(globals(), **locals()) +# +# runProgram('isql', [ '-q' ], sql_cmd) +# +# f_sql_chk = open( os.path.join(context['temp_directory'],'tmp_ext_04_d_int128.sql'), 'w') +# f_sql_chk.write(sql_cmd) +# f_sql_chk.close() +# +# time.sleep(1) +# +# os.remove(f_sql_chk.name) +# os.remove( tmp_file ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F01 -170141183460469231731687303715884105728 + F01 -1 + F01 0 + F01 1 + F01 170141183460469231731687303715884105727 + Records affected: 5 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_external_file_04_d_int128_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/gtcs/test_external_file_06_d.py b/tests/functional/gtcs/test_external_file_06_d.py new file mode 100644 index 00000000..cefcb7d7 --- /dev/null +++ b/tests/functional/gtcs/test_external_file_06_d.py @@ -0,0 +1,85 @@ +#coding:utf-8 +# +# id: functional.gtcs.external_file_06_d +# title: GTCS/tests/external-file-06-d. Test for external table with field of DOUBLE PRECISION datatype +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/EXT_REL_0_6_D.script +# Checked on: 4.0.0.2240; 3.0.7.33380 +# +# 03-mar-2021. +# Added substitution for zero value ('F02') as result of evaluating exp(-745.1332192): +# on Windows number of digits in decimal representation more than on Linux for 1. +# +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('0.0000000000000000', '0.000000000000000')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# import time +# +# tmp_file = os.path.join(context['temp_directory'],'tmp_ext_06_d.tmp') +# if os.path.isfile( tmp_file): +# os.remove( tmp_file ) +# +# this_fdb = db_conn.database_name +# +# sql_cmd=''' +# connect 'localhost:%(this_fdb)s' user '%(user_name)s' password '%(user_password)s'; +# create domain dm_dp double precision; +# create table ext_table external file '%(tmp_file)s' (f01 dm_dp, f02 dm_dp, f03 dm_dp); +# commit; +# insert into ext_table (f01, f02, f03) values( exp(-745.1332191), exp(-745.1332192), exp(709.78271289338404) ); +# commit; +# -- connect 'localhost:%(this_fdb)s' user '%(user_name)s' password '%(user_password)s'; +# set list on; +# set count on; +# select * from ext_table; +# ''' % dict(globals(), **locals()) +# +# runProgram('isql', [ '-q' ], sql_cmd) +# +# f_sql_chk = open( os.path.join(context['temp_directory'],'tmp_ext_06_d.sql'), 'w') +# f_sql_chk.write(sql_cmd) +# f_sql_chk.close() +# +# time.sleep(1) +# +# os.remove(f_sql_chk.name) +# os.remove( tmp_file ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F01 4.940656458412465e-324 + F02 0.0000000000000000 + F03 1.797693134862273e+308 + Records affected: 1 + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_external_file_06_d_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/gtcs/test_external_file_09_d.py b/tests/functional/gtcs/test_external_file_09_d.py new file mode 100644 index 00000000..cde82865 --- /dev/null +++ b/tests/functional/gtcs/test_external_file_09_d.py @@ -0,0 +1,98 @@ +#coding:utf-8 +# +# id: functional.gtcs.external_file_09_d +# title: GTCS/tests/external-file-09-d. Test for external table with field of DATE datatype +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/EXT_REL_0_9_D.script +# Checked on: 4.0.0.2240 SS: 2.473s; 3.0.7.33380 SS: 1.924s. +# +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# import time +# +# tmp_file = os.path.join(context['temp_directory'],'tmp_ext_09_d.tmp') +# if os.path.isfile( tmp_file): +# os.remove( tmp_file ) +# +# this_fdb = db_conn.database_name +# +# sql_cmd=''' +# connect 'localhost:%(this_fdb)s' user '%(user_name)s' password '%(user_password)s'; +# create table ext_table external file '%(tmp_file)s' (f01 date); +# commit; +# -- connect 'localhost:%(this_fdb)s' user '%(user_name)s' password '%(user_password)s'; +# insert into ext_table (f01) values ('28-June-94'); +# insert into ext_table (f01) values ('29-feb-4'); +# insert into ext_table (f01) values ('1-september-1'); +# insert into ext_table (f01) values ('1-january-0001'); +# insert into ext_table (f01) values ('31-december-9999'); +# insert into ext_table (f01) values (current_date); +# insert into ext_table (f01) values (current_timestamp); +# insert into ext_table (f01) values ('29-feb-9999'); +# commit; +# set list on; +# set count on; +# select * from ext_table where f01<>current_date; +# set count off; +# select count(*) as this_day_count from ext_table where f01=current_date; +# commit; +# ''' % dict(globals(), **locals()) +# +# runProgram('isql', [ '-q' ], sql_cmd) +# +# f_sql_chk = open( os.path.join(context['temp_directory'],'tmp_ext_09_d.sql'), 'w') +# f_sql_chk.write(sql_cmd) +# f_sql_chk.close() +# +# time.sleep(1) +# +# os.remove(f_sql_chk.name) +# os.remove( tmp_file ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F01 1994-06-28 + F01 2004-02-29 + F01 2001-09-01 + F01 0001-01-01 + F01 9999-12-31 + Records affected: 5 + + THIS_DAY_COUNT 2 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22018 + conversion error from string "29-feb-9999" + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_external_file_09_d_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/gtcs/test_gtcs_proc_cast_isql.py b/tests/functional/gtcs/test_gtcs_proc_cast_isql.py new file mode 100644 index 00000000..9c21a96f --- /dev/null +++ b/tests/functional/gtcs/test_gtcs_proc_cast_isql.py @@ -0,0 +1,383 @@ +#coding:utf-8 +# +# id: functional.gtcs.gtcs_proc_cast_isql +# title: GTCS/tests/PROC_CAST1_ISQL.script ... PROC_CAST10_ISQL.script +# decription: +# Original tests see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROC_CAST1_ISQL.script +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROC_CAST2_ISQL.script +# ... +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROC_CAST10_ISQL.script +# +# Checked on WI-V3.0.6.33283; WI-T4.0.0.1881. +# +# tracker_id: +# min_versions: ['3.0.6'] +# versions: 3.0.6 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0.6 +# resources: None + +substitutions_1 = [('BLOB_ID.*', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import time +# import subprocess +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql_gen_ddl = os.path.join(context['files_location'],'gtcs-cast-gen-ddl.sql') +# +# f_init_run=open( os.path.join(context['temp_directory'],'tmp_gtcs_cast_ddl.sql'), 'w', buffering = 0) +# f_init_err=open( os.path.join(context['temp_directory'],'tmp_gtcs_cast_ddl.err'), 'w', buffering = 0) +# subprocess.call( [context['isql_path'], dsn, '-q', '-i', sql_gen_ddl], stdout=f_init_run, stderr=f_init_err ) +# flush_and_close( f_init_run ) +# flush_and_close( f_init_err ) +# +# +# f_cast_log=open( os.path.join(context['temp_directory'],'tmp_gtcs_cast_run.log'), 'w', buffering = 0) +# f_cast_err=open( os.path.join(context['temp_directory'],'tmp_gtcs_cast_run.err'), 'w', buffering = 0) +# subprocess.call( [context['isql_path'], dsn, '-q', '-i', f_init_run.name], stdout=f_cast_log, stderr=f_cast_err ) +# flush_and_close( f_cast_log ) +# flush_and_close( f_cast_err ) +# +# # CHECKS: +# ######### +# for g in (f_init_err, f_cast_err): +# with open(g.name, 'r') as f: +# for line in f: +# if line.split(): +# print('UNEXPECTED OUTPUT in ' + os.path.split(g.name)[-1] + ': ' + line ) +# +# with open(f_cast_log.name, 'r') as f: +# for line in f: +# if line.split(): +# print( line.strip() ) +# +# # CLEANUP: +# ########## +# # do NOT remove this pause otherwise some of logs will not be enable for deletion and test will finish with +# # Exception raised while executing Python test script. exception: WindowsError: 32 +# time.sleep(1) +# cleanup( ( f_init_run, f_init_err, f_cast_log, f_cast_err ) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + bigint_bigint 80 + BLOB_ID 0:1 + 80.4450 + bigint_char(10) 80.4450 + bigint_date 2003-04-22 + bigint_decimal( 4,2) 0.04 + bigint_decimal( 4,2) 0.05 + bigint_decimal(10,4) 80.4450 + bigint_double precision 80.44499999999999 + bigint_float 80.445 + bigint_nchar(10) 80.4450 + bigint_numeric( 4,2) 0.04 + bigint_numeric( 4,2) 0.05 + bigint_numeric(10,4) 80.4450 + bigint_smallint 80 + bigint_time 01:02:03.0000 + bigint_timestamp 2003-04-22 11:35:39.0000 + bigint_varchar(10) 80.4450 + blob_bigint 9223372036854775807 + blob_boolean + blob_char(30) 81985529216487135 + blob_date 2004-02-29 + blob_decimal(5,2) 80.45 + blob_double precision 80.44499999999999 + blob_float 80.445 + blob_int -2147483648 + blob_nchar(30) 81985529216487135 + blob_numeric(5,2) 80.45 + blob_smallint 32767 + blob_time 01:02:03.4560 + blob_varchar(30) 81985529216487135 + char(30)_bigint 9223372036854775807 + BLOB_ID 0:1 + 81985529216487135 + char(30)_boolean + char(30)_date 2004-02-29 + char(30)_decimal(5,2) 80.45 + char(30)_double precision 80.44499999999999 + char(30)_float 80.445 + char(30)_int -2147483648 + char(30)_nchar(30) 81985529216487135 + char(30)_numeric(5,2) 80.45 + char(30)_smallint 32767 + char(30)_time 01:02:03.4560 + char(30)_varchar(30) 81985529216487135 + date_bigint 147558 + BLOB_ID 0:1 + 2004-02-29 + date_char(10) 2004-02-29 + date_decimal(4,2) 2.00 + date_double precision 2.000000000000000 + date_float 2 + date_int 147558 + date_nchar(10) 2004-02-29 + date_numeric(4,2) 2.00 + date_smallint 1461 + date_time 01:02:05.0000 + date_timestamp 2003-02-03 01:02:03.0000 + date_varchar(10) 2004-02-29 + decimal(4,2)_bigint 80 + BLOB_ID 0:1 + 0.05 + BLOB_ID 0:3 + 0.06 + BLOB_ID 0:5 + 0.08 + decimal(4,2)_char(10) 0.05 + decimal(4,2)_char(10) 0.06 + decimal(4,2)_char(10) 0.08 + decimal(4,2)_date 2003-04-22 + decimal(4,2)_decimal(4,2) 0.05 + decimal(4,2)_decimal(4,2) 0.06 + decimal(4,2)_decimal(4,2) 0.08 + decimal(4,2)_double precision 80.45000000000000 + decimal(4,2)_double precision 0.05000000000000000 + decimal(4,2)_double precision 0.06000000000000000 + decimal(4,2)_double precision 0.08000000000000000 + decimal(4,2)_float 80.449997 + decimal(4,2)_float 0.050000001 + decimal(4,2)_float 0.059999999 + decimal(4,2)_float 0.079999998 + decimal(4,2)_int 80 + decimal(4,2)_nchar(10) 0.05 + decimal(4,2)_nchar(10) 0.06 + decimal(4,2)_nchar(10) 0.08 + decimal(4,2)_numeric(4,2) 0.05 + decimal(4,2)_numeric(4,2) 0.06 + decimal(4,2)_numeric(4,2) 0.08 + decimal(4,2)_smallint 80 + decimal(4,2)_time 01:03:23.4500 + decimal(4,2)_timestamp 2003-04-22 11:50:03.0000 + decimal(4,2)_varchar(10) 0.05 + decimal(4,2)_varchar(10) 0.06 + decimal(4,2)_varchar(10) 0.08 + double precision_bigint 80 + BLOB_ID 0:1 + 80.44499999999999 + double precision_char(10) 80.445000 + double precision_date 2003-04-22 + ouble precision_decimal(10,4) 80.4450 + double precision_decimal(4,2) 0.05 + double precision_decimal(4,2) 0.06 + double precision_decimal(4,2) 0.08 + double precision_float 80.445 + double precision_int 80 + double precision_nchar(10) 80.445000 + ouble precision_numeric(10,4) 80.4450 + double precision_numeric(4,2) 0.05 + double precision_numeric(4,2) 0.06 + double precision_numeric(4,2) 0.08 + double precision_smallint 80 + double precision_time 01:03:23.4450 + double precision_timestamp 2003-04-22 11:42:51.0000 + double precision_varchar(10) 80.445000 + float_bigint 80 + BLOB_ID 0:1 + 80.445000 + float_char(10) 80.445000 + float_date 2003-04-22 + float_decimal(10,4) 80.4450 + float_decimal(4,2) 0.05 + float_double precision 80.44499969482422 + float_int 80 + float_nchar(10) 80.445000 + float_numeric( 4,2) 0.05 + float_numeric(10,4) 80.4450 + float_smallint 80 + float_time 01:03:23.4450 + float_timestamp 2003-04-22 11:42:50.9736 + float_varchar(10) 80.445000 + int_bigint 80 + BLOB_ID 0:1 + 80.4450 + int_char(10) 80.4450 + int_date 2003-04-22 + int_decimal( 4,2) 0.04 + int_decimal( 4,2) 0.05 + int_decimal(10,4) 80.4450 + int_double precision 80.44499999999999 + int_float 80.445 + int_nchar(10) 80.4450 + int_numeric( 4,2) 0.04 + int_numeric( 4,2) 0.05 + int_numeric(10,4) 80.4450 + int_smallint 80 + int_time 01:02:03.0000 + int_timestamp 2003-04-22 11:35:39.0000 + int_varchar(10) 80.4450 + nchar(30)_bigint 9223372036854775807 + BLOB_ID 0:1 + 81985529216487135 + nchar(30)_boolean + nchar(30)_char(30) 81985529216487135 + nchar(30)_date 2004-02-29 + nchar(30)_decimal(5,2) 80.45 + nchar(30)_double precision 80.44499999999999 + nchar(30)_float 80.445 + nchar(30)_int -2147483648 + nchar(30)_numeric(5,2) 80.45 + nchar(30)_smallint 32767 + nchar(30)_time 01:02:03.4560 + nchar(30)_varchar(30) 81985529216487135 + numeric(4,2)_bigint 80 + BLOB_ID 0:1 + 0.05 + BLOB_ID 0:3 + 0.06 + BLOB_ID 0:5 + 0.08 + numeric(4,2)_char(10) 0.05 + numeric(4,2)_char(10) 0.06 + numeric(4,2)_char(10) 0.08 + numeric(4,2)_date 2003-04-22 + numeric(4,2)_decimal(4,2) 0.05 + numeric(4,2)_decimal(4,2) 0.06 + numeric(4,2)_decimal(4,2) 0.08 + numeric(4,2)_double precision 80.45000000000000 + numeric(4,2)_double precision 0.05000000000000000 + numeric(4,2)_double precision 0.06000000000000000 + numeric(4,2)_double precision 0.08000000000000000 + numeric(4,2)_float 80.449997 + numeric(4,2)_float 0.050000001 + numeric(4,2)_float 0.059999999 + numeric(4,2)_float 0.079999998 + numeric(4,2)_int 80 + numeric(4,2)_nchar(10) 0.05 + numeric(4,2)_nchar(10) 0.06 + numeric(4,2)_nchar(10) 0.08 + numeric(4,2)_numeric(4,2) 0.05 + numeric(4,2)_numeric(4,2) 0.06 + numeric(4,2)_numeric(4,2) 0.08 + numeric(4,2)_smallint 80 + numeric(4,2)_time 01:03:23.4500 + numeric(4,2)_timestamp 2003-04-22 11:50:03.0000 + numeric(4,2)_varchar(10) 0.05 + numeric(4,2)_varchar(10) 0.06 + numeric(4,2)_varchar(10) 0.08 + smallint_bigint 10922 + BLOB_ID 0:1 + 80.4450 + smallint_char(10) 80.4450 + smallint_date 2003-11-19 + smallint_decimal( 4,2) 80.45 + smallint_decimal(10,4) 80.4450 + smallint_double precision 80.44499999999999 + smallint_float 80.445 + smallint_int -10922 + smallint_int 10922 + smallint_nchar(10) 80.4450 + smallint_numeric( 4,2) 80.45 + smallint_numeric(10,4) 80.4450 + smallint_time 01:06:55.0000 + smallint_timestamp 2003-11-21 01:02:03.0000 + smallint_varchar(10) 80.4450 + time_bigint 82677 + BLOB_ID 0:1 + 01:02:03.0000 + time_char(13) 01:02:03.0000 + time_date 2003-02-01 + time_decimal(10,2) 82676.67 + time_double precision 82676.66600000000 + time_float 82676.664 + time_int 82677 + time_nchar(13) 01:02:03.0000 + time_numeric(10,2) 82676.67 + time_smallint 3661 + time_timestamp 2003-02-01 01:02:03.0000 + time_varchar(13) 01:02:03.0000 + timestamp_bigint 1 + BLOB_ID 0:1 + 2004-02-29 01:02:03.4560 + timestamp_char(30) 2004-02-29 01:02:03.4560 + timestamp_date 2004-02-29 + timestamp_decimal(10,2) 0.58 + timestamp_double precision 0.5755401160000000 + timestamp_float 0.57554013 + timestamp_int 1 + timestamp_nchar(30) 2004-02-29 01:02:03.4560 + timestamp_numeric(10,2) 0.58 + timestamp_smallint 0 + timestamp_time 01:02:03.0000 + timestamp_varchar(30) 2004-02-29 01:02:03.4560 + varchar(30)_bigint -268435456 + varchar(30)_bigint 4026531840 + varchar(30)_bigint 9223372036854775807 + varchar(30)_bigint -1 + BLOB_ID 0:1 + 81985529216487135 + varchar(30)_boolean + varchar(30)_char(30) 81985529216487135 + varchar(30)_date 2004-02-29 + varchar(30)_decimal(5,2) 80.45 + varchar(30)_double precision 80.44499999999999 + varchar(30)_float 80.445 + varchar(30)_int -2147483648 + varchar(30)_nchar(30) 81985529216487135 + varchar(30)_numeric(5,2) 80.45 + varchar(30)_smallint 32767 + varchar(30)_time 01:02:03.4560 + """ + +@pytest.mark.version('>=3.0.6') +@pytest.mark.xfail +def test_gtcs_proc_cast_isql_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/gtcs/test_gtcs_proc_isql_01.py b/tests/functional/gtcs/test_gtcs_proc_isql_01.py new file mode 100644 index 00000000..6c66a678 --- /dev/null +++ b/tests/functional/gtcs/test_gtcs_proc_isql_01.py @@ -0,0 +1,97 @@ +#coding:utf-8 +# +# id: functional.gtcs.gtcs_proc_isql_01 +# title: gtcs-proc-isql-01 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROC_ISQL_01.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='gtcs_sp1.fbk', init=init_script_1) + +test_script_1 = """ + set bail on; + + set term ^; + create procedure proc1 returns (a integer) as + begin + for + select distinct max(qty) + from sp where qty > 300 + into :a + do + suspend; + end + ^ + set term ; ^ + + execute procedure proc1; + + set count on; + select 'point-1' msg, p.* from proc1 p; + select 'point-2' msg, max(p.a) from proc1 p; + select 'point-3' msg, p.a from proc1 p; + select 'point-4' msg, p.* from proc1 p order by p.a; + select 'point-5' msg, p.a, avg(p.a) from proc1 p group by p.a having avg(p.a) > 350; + select 'point-6' msg, p.a, avg(p.a) from proc1 p group by p.a ; + select 'point-7' msg, p.a from proc1 p where p.a = (select avg(x.a) from proc1 x); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A + 400 + + MSG A + point-1 400 + Records affected: 1 + + MSG MAX + point-2 400 + Records affected: 1 + + MSG A + point-3 400 + Records affected: 1 + + MSG A + point-4 400 + Records affected: 1 + + MSG A AVG + point-5 400 400 + Records affected: 1 + + MSG A AVG + point-6 400 400 + Records affected: 1 + + MSG A + point-7 400 + Records affected: 1 + """ + +@pytest.mark.version('>=2.5') +def test_gtcs_proc_isql_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_gtcs_proc_isql_02.py b/tests/functional/gtcs/test_gtcs_proc_isql_02.py new file mode 100644 index 00000000..08c3022a --- /dev/null +++ b/tests/functional/gtcs/test_gtcs_proc_isql_02.py @@ -0,0 +1,96 @@ +#coding:utf-8 +# +# id: functional.gtcs.gtcs_proc_isql_02 +# title: gtcs-proc-isql-02 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROC_ISQL_02.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='gtcs_sp1.fbk', init=init_script_1) + +test_script_1 = """ + set bail on; + set term ^; + create procedure proc2 returns (a varchar(5), b varchar(5),c integer) as + begin + for + select * from sp where pno = 'P5' + into :a, :b, :c + do + suspend; + end + ^ + set term ;^ + execute procedure proc2; + + set count on; + --set echo on; + select 'point-1' msg, p.* from proc2 p; + select 'point-2' msg, max(p.c) from proc2 p; + select 'point-3' msg, p.a from proc2 p; + select 'point-4' msg, p.* from proc2 p order by p.c; + select 'point-5' msg, p.a, avg(p.c) from proc2 p group by p.a having avg(p.c) > 350; + select 'point-6' msg, p.a, avg(p.c) from proc2 p group by p.a; + select 'point-7' msg, p.a, p.c from proc2 p where p.c = (select avg(x.c) from proc2 x); + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A B C + S4 P5 400 + + MSG A B C + point-1 S4 P5 400 + Records affected: 1 + + MSG MAX + point-2 400 + Records affected: 1 + + MSG A + point-3 S4 + Records affected: 1 + + MSG A B C + point-4 S4 P5 400 + Records affected: 1 + + MSG A AVG + point-5 S4 400 + Records affected: 1 + + MSG A AVG + point-6 S4 400 + Records affected: 1 + + MSG A C + point-7 S4 400 + Records affected: 1 + """ + +@pytest.mark.version('>=2.5') +def test_gtcs_proc_isql_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_gtcs_proc_isql_03.py b/tests/functional/gtcs/test_gtcs_proc_isql_03.py new file mode 100644 index 00000000..524a2a1d --- /dev/null +++ b/tests/functional/gtcs/test_gtcs_proc_isql_03.py @@ -0,0 +1,98 @@ +#coding:utf-8 +# +# id: functional.gtcs.gtcs_proc_isql_03 +# title: gtcs-proc-isql-03 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROC_ISQL_03.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='gtcs_sp1.fbk', init=init_script_1) + +test_script_1 = """ + set bail on; + set term ^; + create procedure proc3 returns (a varchar(5), c integer) as + begin + for + select pno, qty + from sp + where qty > 300 and pno = 'P5' + into :a, :c + do + suspend; + end + ^ + set term ;^ + + execute procedure proc3; + + set count on; + + select 'point-1' msg, p.* from proc3 p; + select 'point-2' msg, max(p.a) from proc3 p; + select 'point-3' msg, p.c from proc3 p; + select 'point-4' msg, p.* from proc3 p order by p.a; + select 'point-5' msg, p.a, avg(p.c) from proc3 p group by p.a having avg(p.c) > 350; + select 'point-6' msg, p.a, avg(p.c) from proc3 p group by p.a; + select 'point-7' msg, p.a, p.c from proc3 p where p.c = (select avg(x.c) from proc3 x); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A C + P5 400 + + MSG A C + point-1 P5 400 + Records affected: 1 + + MSG MAX + point-2 P5 + Records affected: 1 + + MSG C + point-3 400 + Records affected: 1 + + MSG A C + point-4 P5 400 + Records affected: 1 + + MSG A AVG + point-5 P5 400 + Records affected: 1 + + MSG A AVG + point-6 P5 400 + Records affected: 1 + + MSG A C + point-7 P5 400 + Records affected: 1 + """ + +@pytest.mark.version('>=2.5') +def test_gtcs_proc_isql_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_gtcs_proc_isql_04.py b/tests/functional/gtcs/test_gtcs_proc_isql_04.py new file mode 100644 index 00000000..29e28d9c --- /dev/null +++ b/tests/functional/gtcs/test_gtcs_proc_isql_04.py @@ -0,0 +1,96 @@ +#coding:utf-8 +# +# id: functional.gtcs.gtcs_proc_isql_04 +# title: gtcs-proc-isql-04 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROC_ISQL_04.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='gtcs_sp1.fbk', init=init_script_1) + +test_script_1 = """ + set bail on; + set term ^; + create procedure proc4 returns (a varchar(6), b varchar(5),c integer) as + begin + for + select color, pno, weight + from p + where weight = 19 + group by color, pno, weight + into :a, :b, :c + do + suspend; + end + ^ + set term ;^ + + execute procedure proc4 ; + + set count on; + select 'point-1' msg, p.* from proc4 p; + select 'point-2' msg, max(p.a) from proc4 p; + select 'point-3' msg, p.c from proc4 p; + select 'point-4' msg, p.a, p.c from proc4 p order by p.a; + select 'point-5' msg, p.a, avg(p.c) from proc4 p group by p.a having avg(p.c) > 35; + select 'point-6' msg, p.a, avg(p.c) from proc4 p group by p.a ; + select 'point-7' msg, p.a, p.c from proc4 p where p.c = (select avg(x.c) from proc4 x); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A B C + Red P6 19 + + MSG A B C + point-1 Red P6 19 + Records affected: 1 + + MSG MAX + point-2 Red + Records affected: 1 + + MSG C + point-3 19 + Records affected: 1 + + MSG A C + point-4 Red 19 + Records affected: 1 + + Records affected: 0 + + MSG A AVG + point-6 Red 19 + Records affected: 1 + + MSG A C + point-7 Red 19 + Records affected: 1 + """ + +@pytest.mark.version('>=2.5') +def test_gtcs_proc_isql_04_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_gtcs_proc_isql_05.py b/tests/functional/gtcs/test_gtcs_proc_isql_05.py new file mode 100644 index 00000000..eeccac06 --- /dev/null +++ b/tests/functional/gtcs/test_gtcs_proc_isql_05.py @@ -0,0 +1,97 @@ +#coding:utf-8 +# +# id: functional.gtcs.gtcs_proc_isql_05 +# title: gtcs-proc-isql-05 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROC_ISQL_05.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='gtcs_sp1.fbk', init=init_script_1) + +test_script_1 = """ + set bail on; + set term ^; + create procedure proc5 returns (a varchar(20), b integer) as + begin + for + select pname, avg(weight) + from p + group by pname + having avg(weight) > 18 + into :a, :b + do + suspend; + end + ^ + set term ; ^ + + execute procedure proc5 ; + + set count on; + select p.* from proc5 p; + select 'point-1' msg, max(p.a) from proc5 p; + select 'point-2' msg, p.b from proc5 p; + select 'point-3' msg, p.a, p.b from proc5 p order by p.a; + select 'point-4' msg, p.a, avg(p.b) from proc5 p group by p.a having avg(p.b) > 35; + select 'point-5' msg, p.a, avg(p.b) from proc5 p group by p.a; + select 'point-6' msg, p.a, p.b from proc5 p where p.b = (select avg(x.b) from proc5 x); + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A B + Cog 19 + + A B + Cog 19 + Records affected: 1 + + MSG MAX + point-1 Cog + Records affected: 1 + + MSG B + point-2 19 + Records affected: 1 + + MSG A B + point-3 Cog 19 + Records affected: 1 + + Records affected: 0 + + MSG A AVG + point-5 Cog 19 + Records affected: 1 + + MSG A B + point-6 Cog 19 + Records affected: 1 + """ + +@pytest.mark.version('>=2.5') +def test_gtcs_proc_isql_05_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_gtcs_proc_isql_06.py b/tests/functional/gtcs/test_gtcs_proc_isql_06.py new file mode 100644 index 00000000..30992461 --- /dev/null +++ b/tests/functional/gtcs/test_gtcs_proc_isql_06.py @@ -0,0 +1,95 @@ +#coding:utf-8 +# +# id: functional.gtcs.gtcs_proc_isql_06 +# title: gtcs-proc-isql-06 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROC_ISQL_06.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='gtcs_sp1.fbk', init=init_script_1) + +test_script_1 = """ + set bail on; + set term ^; + create procedure proc6 returns (a varchar(20), b integer) as + begin + for + select pname,weight + from p + where weight > (select (avg(weight)+3) from p) + into :a, :b + do + suspend; + end + ^ + set term ; ^ + + execute procedure proc6 ; + + set count on; + select 'point-1' msg, p.* from proc6 p; + select 'point-2' msg, max(p.a) from proc6 p; + select 'point-3' msg, p.b from proc6 p; + select 'point-4' msg, p.a, p.b from proc6 p order by a; + select 'point-5' msg, p.a, avg(p.b) from proc6 p group by a having avg(p.b) > 35; + select 'point-6' msg, p.a, avg(p.b) from proc6 p group by a ; + select 'point-7' msg, p.a , b from proc6 p where b = (select avg(x.b) from proc6 x); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A B + Cog 19 + + MSG A B + point-1 Cog 19 + Records affected: 1 + + MSG MAX + point-2 Cog + Records affected: 1 + + MSG B + point-3 19 + Records affected: 1 + + MSG A B + point-4 Cog 19 + Records affected: 1 + + Records affected: 0 + + MSG A AVG + point-6 Cog 19 + Records affected: 1 + + MSG A B + point-7 Cog 19 + Records affected: 1 + """ + +@pytest.mark.version('>=2.5') +def test_gtcs_proc_isql_06_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_gtcs_proc_isql_07.py b/tests/functional/gtcs/test_gtcs_proc_isql_07.py new file mode 100644 index 00000000..0954bed5 --- /dev/null +++ b/tests/functional/gtcs/test_gtcs_proc_isql_07.py @@ -0,0 +1,99 @@ +#coding:utf-8 +# +# id: functional.gtcs.gtcs_proc_isql_07 +# title: gtcs-proc-isql-07 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROC_ISQL_07.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='gtcs_sp1.fbk', init=init_script_1) + +test_script_1 = """ + set bail on; + set term ^; + create procedure proc7 returns (a integer) as + begin + for + select distinct max(qty) + from sp + where qty > 300 + into :a + do + suspend; + end + ^ + set term ;^ + + execute procedure proc7; + + set count on; + + select 'point-1' msg, p.* from proc7 p; + select 'point-2' msg, max(p.a) from proc7 p; + select 'point-3' msg, p.a from proc7 p; + select 'point-4' msg, p.* from proc7 p order by p.a; + select 'point-5' msg, p.a, avg(p.a) from proc7 p group by p.a having avg(p.a) > 350; + select 'point-6' msg, p.a, avg(p.a) from proc7 p group by p.a; + select 'point-7' msg, p.a from proc7 p where p.a = (select avg(x.a) from proc7 x); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A + 400 + + MSG A + point-1 400 + Records affected: 1 + + MSG MAX + point-2 400 + Records affected: 1 + + MSG A + point-3 400 + + Records affected: 1 + + MSG A + point-4 400 + Records affected: 1 + + MSG A AVG + point-5 400 400 + Records affected: 1 + + MSG A AVG + point-6 400 400 + Records affected: 1 + + MSG A + point-7 400 + Records affected: 1 + """ + +@pytest.mark.version('>=2.5') +def test_gtcs_proc_isql_07_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_gtcs_proc_isql_08.py b/tests/functional/gtcs/test_gtcs_proc_isql_08.py new file mode 100644 index 00000000..925ff88f --- /dev/null +++ b/tests/functional/gtcs/test_gtcs_proc_isql_08.py @@ -0,0 +1,150 @@ +#coding:utf-8 +# +# id: functional.gtcs.gtcs_proc_isql_08 +# title: gtcs-proc-isql-08 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROC_ISQL_08.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# 'd_atabase': 'Restore', +# 'b_ackup_file': 'gtcs_sp1.fbk', +# +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + + recreate table sp ( + sno varchar(6), + pno varchar(6), + qty integer + ); + commit; + + insert into sp (sno, pno, qty) values ('S1', 'P1', 300); + insert into sp (sno, pno, qty) values ('S1', 'P3', 400); + insert into sp (sno, pno, qty) values ('S2', 'P1', 300); + insert into sp (sno, pno, qty) values ('S2', 'P2', 400); + insert into sp (sno, pno, qty) values ('S4', 'P4', 300); + insert into sp (sno, pno, qty) values ('S4', 'P5', 400); + commit; + + + set term ^; + create procedure proc08 returns (a char(5), b char(5), c integer) as + begin + for + select * from sp + into :a, :b, :c + do + suspend; + end + ^ + set term ;^ + + set count on; + + execute procedure proc08; + + select 'point-1' msg, p.a, p.b, p.c from proc08 p order by 2,3,4; + + select 'point-2' msg, max(p.c) from proc08 p; + + select 'point-3' msg, p.a from proc08 p order by 2; + + select 'point-4' msg, p.* from proc08 p order by p.c, p.a, p.b; + + select 'point-5' msg, p.a, avg(p.c) from proc08 p group by a having avg(p.c) > 300 order by p.a; + select 'point-6' msg, p.a, avg(p.c) from proc08 p group by p.a order by p.a; + + select 'point-7' msg, p.a, p.c from proc08 p where p.c < (select avg(x.c) from proc08 x) order by p.a, p.c; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A B C + ====== ====== ============ + S1 P1 300 + + MSG A B C + ======= ====== ====== ============ + point-1 S1 P1 300 + point-1 S1 P3 400 + point-1 S2 P1 300 + point-1 S2 P2 400 + point-1 S4 P4 300 + point-1 S4 P5 400 + Records affected: 6 + + MSG MAX + ======= ============ + point-2 400 + Records affected: 1 + + MSG A + ======= ====== + point-3 S1 + point-3 S1 + point-3 S2 + point-3 S2 + point-3 S4 + point-3 S4 + Records affected: 6 + + MSG A B C + ======= ====== ====== ============ + point-4 S1 P1 300 + point-4 S2 P1 300 + point-4 S4 P4 300 + point-4 S1 P3 400 + point-4 S2 P2 400 + point-4 S4 P5 400 + Records affected: 6 + + MSG A AVG + ======= ====== ===================== + point-5 S1 350 + point-5 S2 350 + point-5 S4 350 + Records affected: 3 + + MSG A AVG + ======= ====== ===================== + point-6 S1 350 + point-6 S2 350 + point-6 S4 350 + Records affected: 3 + + MSG A C + ======= ====== ============ + point-7 S1 300 + point-7 S2 300 + point-7 S4 300 + Records affected: 3 + """ + +@pytest.mark.version('>=2.5') +def test_gtcs_proc_isql_08_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_gtcs_proc_isql_10.py b/tests/functional/gtcs/test_gtcs_proc_isql_10.py new file mode 100644 index 00000000..79018a7e --- /dev/null +++ b/tests/functional/gtcs/test_gtcs_proc_isql_10.py @@ -0,0 +1,105 @@ +#coding:utf-8 +# +# id: functional.gtcs.gtcs_proc_isql_10 +# title: gtcs-proc-isql-10 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROC_ISQL_10.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='gtcs_sp1.fbk', init=init_script_1) + +test_script_1 = """ + set bail on; + set term ^; + create procedure proc10 returns( a varchar(20), b varchar(5), c integer) as + begin + for + select pname, color, weight + from p where color = 'Red' + order by weight + into :a,:b,:c + do + suspend; + end + ^ + set term ;^ + + set count on; + execute procedure proc10 ; + + select 'point-1' msg, p.* from proc10 p; + select 'point-2' msg, max(p.a) from proc10 p; + select 'point-3' msg, p.c from proc10 p; + select 'point-4' msg, p.a, p.c from proc10 p order by p.a; + select 'point-5' msg, p.a, avg(p.c) from proc10 p group by p.a having avg(p.c) > 15; + select 'point-6' msg, p.a, avg(p.c) from proc10 p group by p.a; + select 'point-7' msg, p.a, p.c from proc10 p where p.c > (select avg(x.c) from proc10 x); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A B C + Nut Red 12 + + MSG A B C + point-1 Nut Red 12 + point-1 Screw Red 14 + point-1 Cog Red 19 + Records affected: 3 + + MSG MAX + point-2 Screw + Records affected: 1 + + MSG C + point-3 12 + point-3 14 + point-3 19 + Records affected: 3 + + MSG A C + point-4 Cog 19 + point-4 Nut 12 + point-4 Screw 14 + Records affected: 3 + + MSG A AVG + point-5 Cog 19 + Records affected: 1 + + MSG A AVG + point-6 Cog 19 + point-6 Nut 12 + point-6 Screw 14 + Records affected: 3 + + MSG A C + point-7 Cog 19 + Records affected: 1 + """ + +@pytest.mark.version('>=2.5') +def test_gtcs_proc_isql_10_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_gtcs_proc_isql_11.py b/tests/functional/gtcs/test_gtcs_proc_isql_11.py new file mode 100644 index 00000000..4675aa81 --- /dev/null +++ b/tests/functional/gtcs/test_gtcs_proc_isql_11.py @@ -0,0 +1,109 @@ +#coding:utf-8 +# +# id: functional.gtcs.gtcs_proc_isql_11 +# title: gtcs-proc-isql-11 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROC_ISQL_11.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='gtcs_sp1.fbk', init=init_script_1) + +test_script_1 = """ + set bail on; + set term ^; + create procedure proc11 returns (a varchar(5), b varchar(21), c integer) as + begin + for select p.pno,pname, count(*) from p, sp where p.pno = sp.pno group by p.pno, pname + into :a, :b, :c + do suspend; + end + ^ + set term ;^ + + execute procedure proc11 ; + + set count on; + select 'point-1' msg, p.* from proc11 p; + select 'point-2' msg, max(p.a) from proc11 p; + select 'point-3' msg, p.c from proc11 p; + select 'point-4' msg, p.c, p.a from proc11 p order by p.c; + select 'point-5' msg, p.a, avg(p.c) from proc11 p group by a having avg(p.c) > 1; + select 'point-6' msg, p.a, avg(p.c) from proc11 p group by p.a ; + select 'point-7' msg, p.a, p.c from proc11 p where p.c > (select avg(x.c) from proc11 x); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A B C + P1 Nut 2 + + MSG A B C + point-1 P1 Nut 2 + point-1 P2 Bolt 1 + point-1 P3 Screw 1 + point-1 P4 Screw 1 + point-1 P5 Cam 1 + Records affected: 5 + + MSG MAX + point-2 P5 + Records affected: 1 + + MSG C + point-3 2 + point-3 1 + point-3 1 + point-3 1 + point-3 1 + Records affected: 5 + + MSG C A + point-4 1 P2 + point-4 1 P3 + point-4 1 P4 + point-4 1 P5 + point-4 2 P1 + Records affected: 5 + + MSG A AVG + point-5 P1 2 + Records affected: 1 + + MSG A AVG + point-6 P1 2 + point-6 P2 1 + point-6 P3 1 + point-6 P4 1 + point-6 P5 1 + Records affected: 5 + + MSG A C + point-7 P1 2 + Records affected: 1 + """ + +@pytest.mark.version('>=2.5') +def test_gtcs_proc_isql_11_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_gtcs_proc_isql_12.py b/tests/functional/gtcs/test_gtcs_proc_isql_12.py new file mode 100644 index 00000000..a9b56d3a --- /dev/null +++ b/tests/functional/gtcs/test_gtcs_proc_isql_12.py @@ -0,0 +1,100 @@ +#coding:utf-8 +# +# id: functional.gtcs.gtcs_proc_isql_12 +# title: gtcs-proc-isql-12 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROC_ISQL_12.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='gtcs_sp1.fbk', init=init_script_1) + +test_script_1 = """ + set bail on; + set term ^; + create procedure proc12 returns (a varchar(21), b integer) as + begin + for + select pname, avg(weight) + from p + group by pname + having avg(weight)> 16 + into :a, :b + do + suspend; + end + ^ + set term ;^ + + execute procedure proc12; + + set count on; + select 'point-1' msg, p.* from proc12 p; + select 'point-2' msg, max(p.b) from proc12 p; + select 'point-3' msg, p.b from proc12 p; + select 'point-4' msg, p.a,p.b from proc12 p order by b; + select 'point-5' msg, p.a, avg(p.b) from proc12 p group by a having avg(p.b) > 350; + select 'point-6' msg, p.a, avg(p.b) from proc12 p group by a; + select 'point-7' msg, p.a, p.b from proc12 p where b > (select avg(x.b) from proc12 x); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A B + Bolt 17 + + MSG A B + point-1 Bolt 17 + point-1 Cog 19 + Records affected: 2 + + MSG MAX + point-2 19 + Records affected: 1 + + MSG B + point-3 17 + point-3 19 + Records affected: 2 + + MSG A B + point-4 Bolt 17 + point-4 Cog 19 + Records affected: 2 + + Records affected: 0 + + MSG A AVG + point-6 Bolt 17 + point-6 Cog 19 + Records affected: 2 + + MSG A B + point-7 Cog 19 + Records affected: 1 + """ + +@pytest.mark.version('>=2.5') +def test_gtcs_proc_isql_12_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_gtcs_proc_isql_13.py b/tests/functional/gtcs/test_gtcs_proc_isql_13.py new file mode 100644 index 00000000..e9e73a2d --- /dev/null +++ b/tests/functional/gtcs/test_gtcs_proc_isql_13.py @@ -0,0 +1,121 @@ +#coding:utf-8 +# +# id: functional.gtcs.gtcs_proc_isql_13 +# title: gtcs-proc-isql-13 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROC_ISQL_13.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: +# 4.0.0.1803 SS: 1.822s. +# 3.0.6.33265 SS: 0.849s. +# 2.5.9.27149 SC: 0.313s. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='gtcs_sp1.fbk', init=init_script_1) + +test_script_1 = """ + set bail on; + set term ^; + create procedure proc13 returns (a integer) as + begin + for + select status from s + UNION + select weight from p + into :a + do + suspend; + end + ^ + set term ;^ + + execute procedure proc13 ; + + select 'point-1' msg, p.* from proc13 p; + select 'point-2' msg, max(p.a) from proc13 p; + select 'point-3' msg, p.a from proc13 p; + select 'point-4' msg, p.a from proc13 p order by a; + select 'point-5' msg, p.a, avg(p.a) from proc13 p group by p.a having avg(p.a) > 20; + select 'point-6' msg, p.a, avg(p.a) from proc13 p group by p.a; + select 'point-7' msg, p.a from proc13 p where p.a > (select avg(x.a) from proc13 x); + + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A + 10 + + + MSG A + point-1 10 + point-1 12 + point-1 14 + point-1 17 + point-1 19 + point-1 20 + point-1 30 + + MSG MAX + point-2 30 + + MSG A + point-3 10 + point-3 12 + point-3 14 + point-3 17 + point-3 19 + point-3 20 + point-3 30 + + MSG A + point-4 10 + point-4 12 + point-4 14 + point-4 17 + point-4 19 + point-4 20 + point-4 30 + + MSG A AVG + point-5 30 30 + + MSG A AVG + point-6 10 10 + point-6 12 12 + point-6 14 14 + point-6 17 17 + point-6 19 19 + point-6 20 20 + point-6 30 30 + + MSG A + point-7 19 + point-7 20 + point-7 30 + """ + +@pytest.mark.version('>=2.5') +def test_gtcs_proc_isql_13_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_gtcs_proc_isql_15.py b/tests/functional/gtcs/test_gtcs_proc_isql_15.py new file mode 100644 index 00000000..4b0470dd --- /dev/null +++ b/tests/functional/gtcs/test_gtcs_proc_isql_15.py @@ -0,0 +1,71 @@ +#coding:utf-8 +# +# id: functional.gtcs.gtcs_proc_isql_15 +# title: gtcs-proc-isql-15 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROC_ISQL_15.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: +# 4.0.0.1803 SS: 1.822s. +# 3.0.6.33265 SS: 0.849s. +# 2.5.9.27149 SC: 0.313s. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('={3,}', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='gtcs_sp1.fbk', init=init_script_1) + +test_script_1 = """ + set term ^; + create procedure proc_insert (a char(5), b char(20), c char(6), d smallint, e char(15)) as + begin + insert into p values (:a, :b, :c, :d, :e); + end + ^ + set term ;^ + select 'point-1' msg, p.* from p; + execute procedure proc_insert 'P7', 'Widget', 'Pink', 23, 'Hoboken'; + select 'point-2' msg, p.* from p; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG PNO PNAME COLOR WEIGHT CITY + point-1 P1 Nut Red 12 London + point-1 P2 Bolt Green 17 Paris + point-1 P3 Screw Blue 17 Rome + point-1 P4 Screw Red 14 London + point-1 P5 Cam Blue 12 Paris + point-1 P6 Cog Red 19 London + + MSG PNO PNAME COLOR WEIGHT CITY + point-2 P1 Nut Red 12 London + point-2 P2 Bolt Green 17 Paris + point-2 P3 Screw Blue 17 Rome + point-2 P4 Screw Red 14 London + point-2 P5 Cam Blue 12 Paris + point-2 P6 Cog Red 19 London + point-2 P7 Widget Pink 23 Hoboken + """ + +@pytest.mark.version('>=2.5') +def test_gtcs_proc_isql_15_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_gtcs_proc_isql_16.py b/tests/functional/gtcs/test_gtcs_proc_isql_16.py new file mode 100644 index 00000000..cd9ea2b9 --- /dev/null +++ b/tests/functional/gtcs/test_gtcs_proc_isql_16.py @@ -0,0 +1,73 @@ +#coding:utf-8 +# +# id: functional.gtcs.gtcs_proc_isql_16 +# title: gtcs-proc-isql-16 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROC_ISQL_16.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: +# 4.0.0.1803 SS: 1.822s. +# 3.0.6.33265 SS: 0.849s. +# 2.5.9.27149 SC: 0.313s. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('={3,}', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='gtcs_sp1.fbk', init=init_script_1) + +test_script_1 = """ + set term ^; + create procedure proc_insert (a char(5), b char(20), c char(6), d smallint, e char(15)) as + begin + insert into p values (:a, :b, :c, :d, :e); + end + ^ + set term ;^ + select 'point-1' as msg, p.* from p; + execute procedure proc_insert 'P15', null , 'Pink', null, 'Hoboken'; + insert into p values ('P16', null, null, null, 'Varanasi'); + select 'point-2' as msg, p.* from p; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG PNO PNAME COLOR WEIGHT CITY + point-1 P1 Nut Red 12 London + point-1 P2 Bolt Green 17 Paris + point-1 P3 Screw Blue 17 Rome + point-1 P4 Screw Red 14 London + point-1 P5 Cam Blue 12 Paris + point-1 P6 Cog Red 19 London + + MSG PNO PNAME COLOR WEIGHT CITY + point-2 P1 Nut Red 12 London + point-2 P2 Bolt Green 17 Paris + point-2 P3 Screw Blue 17 Rome + point-2 P4 Screw Red 14 London + point-2 P5 Cam Blue 12 Paris + point-2 P6 Cog Red 19 London + point-2 P15 Pink Hoboken + point-2 P16 Varanasi + """ + +@pytest.mark.version('>=2.5') +def test_gtcs_proc_isql_16_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_gtcs_proc_isql_17.py b/tests/functional/gtcs/test_gtcs_proc_isql_17.py new file mode 100644 index 00000000..b4422459 --- /dev/null +++ b/tests/functional/gtcs/test_gtcs_proc_isql_17.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: functional.gtcs.gtcs_proc_isql_17 +# title: gtcs-proc-isql-17 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROC_ISQL_17.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: +# 4.0.0.1803 SS: 1.822s. +# 3.0.6.33265 SS: 0.849s. +# 2.5.9.27149 SC: 0.313s. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('={3,}', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='gtcs_sp1.fbk', init=init_script_1) + +test_script_1 = """ + set term ^; + create procedure insert_sno (sno varchar(5)) as + declare c int; + begin + select count(*) from sp where sno = :sno into :c; + if (c = 0 ) then + insert into sp(sno) values(:sno); + end + ^ + set term ;^ + execute procedure insert_sno 'S10'; + select p.* from sp p; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + SNO PNO QTY + S1 P1 300 + S1 P3 400 + S2 P1 300 + S2 P2 400 + S4 P4 300 + S4 P5 400 + S10 + """ + +@pytest.mark.version('>=2.5') +def test_gtcs_proc_isql_17_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_gtcs_proc_isql_18.py b/tests/functional/gtcs/test_gtcs_proc_isql_18.py new file mode 100644 index 00000000..212dd797 --- /dev/null +++ b/tests/functional/gtcs/test_gtcs_proc_isql_18.py @@ -0,0 +1,94 @@ +#coding:utf-8 +# +# id: functional.gtcs.gtcs_proc_isql_18 +# title: gtcs-proc-isql-18 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROC_ISQL_18.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: +# 4.0.0.1803 SS: 1.822s. +# 3.0.6.33265 SS: 0.849s. +# 2.5.9.27149 SC: 0.313s. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('={3,}', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='gtcs_sp1.fbk', init=init_script_1) + +test_script_1 = """ + set term ^; + create procedure proc_select_insert as + begin + insert into sp(sno) select sno from s where sno not in (select sno from sp); + end + ^ + set term ;^ + select 'point-1' as msg, p.* from sp p; + execute procedure proc_select_insert; + select 'point-2' as msg, p.* from sp p; + rollback; + select 'point-3' as msg, p.* from sp p; + execute procedure proc_select_insert; + select 'point-4' as msg, p.* from sp p; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG SNO PNO QTY + point-1 S1 P1 300 + point-1 S1 P3 400 + point-1 S2 P1 300 + point-1 S2 P2 400 + point-1 S4 P4 300 + point-1 S4 P5 400 + + MSG SNO PNO QTY + point-2 S1 P1 300 + point-2 S1 P3 400 + point-2 S2 P1 300 + point-2 S2 P2 400 + point-2 S4 P4 300 + point-2 S4 P5 400 + point-2 S3 + point-2 S5 + + MSG SNO PNO QTY + point-3 S1 P1 300 + point-3 S1 P3 400 + point-3 S2 P1 300 + point-3 S2 P2 400 + point-3 S4 P4 300 + point-3 S4 P5 400 + + MSG SNO PNO QTY + point-4 S1 P1 300 + point-4 S1 P3 400 + point-4 S2 P1 300 + point-4 S2 P2 400 + point-4 S4 P4 300 + point-4 S4 P5 400 + point-4 S3 + point-4 S5 + """ + +@pytest.mark.version('>=2.5') +def test_gtcs_proc_isql_18_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_gtcs_proc_isql_19.py b/tests/functional/gtcs/test_gtcs_proc_isql_19.py new file mode 100644 index 00000000..1d911612 --- /dev/null +++ b/tests/functional/gtcs/test_gtcs_proc_isql_19.py @@ -0,0 +1,77 @@ +#coding:utf-8 +# +# id: functional.gtcs.gtcs_proc_isql_19 +# title: gtcs-proc-isql-19 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROC_ISQL_19.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: +# 4.0.0.1803 SS: 1.822s. +# 3.0.6.33265 SS: 0.849s. +# 2.5.9.27149 SC: 0.313s. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('={3,}', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='gtcs_sp1.fbk', init=init_script_1) + +test_script_1 = """ + set term ^; + create procedure proc_select_insert2 as + declare variable t varchar(5); + begin + for select sno from s where sno not in + (select sno from sp) into :t do + begin + insert into sp(sno) values (:t); + end + end + ^ + set term ;^ + select 'result-1' as msg, p.* from sp p; + execute procedure proc_select_insert2; + select 'result-2' as msg, p.* from sp p; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG SNO PNO QTY + result-1 S1 P1 300 + result-1 S1 P3 400 + result-1 S2 P1 300 + result-1 S2 P2 400 + result-1 S4 P4 300 + result-1 S4 P5 400 + + MSG SNO PNO QTY + result-2 S1 P1 300 + result-2 S1 P3 400 + result-2 S2 P1 300 + result-2 S2 P2 400 + result-2 S4 P4 300 + result-2 S4 P5 400 + result-2 S3 + result-2 S5 + """ + +@pytest.mark.version('>=2.5') +def test_gtcs_proc_isql_19_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_gtcs_proc_isql_20.py b/tests/functional/gtcs/test_gtcs_proc_isql_20.py new file mode 100644 index 00000000..19f19746 --- /dev/null +++ b/tests/functional/gtcs/test_gtcs_proc_isql_20.py @@ -0,0 +1,80 @@ +#coding:utf-8 +# +# id: functional.gtcs.gtcs_proc_isql_20 +# title: gtcs-proc-isql-20 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROC_ISQL_20.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: +# 4.0.0.1803 SS: 1.822s. +# 3.0.6.33265 SS: 0.849s. +# 2.5.9.27149 SC: 0.313s. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('={3,}', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='gtcs_sp1.fbk', init=init_script_1) + +test_script_1 = """ + set term ^; + create procedure proc_select_insert3 as + declare t varchar(5); + begin + for + select sno + from s + where sno NOT IN (select sno from sp) + into :t + do begin + insert into sp(sno) values (:t); + exit; + end + end + ^ + set term ;^ + select 'result-1' as msg, p.* from sp p; + execute procedure proc_select_insert3; + select 'result-2' as msg, p.* from sp p; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG SNO PNO QTY + result-1 S1 P1 300 + result-1 S1 P3 400 + result-1 S2 P1 300 + result-1 S2 P2 400 + result-1 S4 P4 300 + result-1 S4 P5 400 + + MSG SNO PNO QTY + result-2 S1 P1 300 + result-2 S1 P3 400 + result-2 S2 P1 300 + result-2 S2 P2 400 + result-2 S4 P4 300 + result-2 S4 P5 400 + result-2 S3 + """ + +@pytest.mark.version('>=2.5') +def test_gtcs_proc_isql_20_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_gtcs_select_delete_isql.py b/tests/functional/gtcs/test_gtcs_select_delete_isql.py new file mode 100644 index 00000000..9c773eb6 --- /dev/null +++ b/tests/functional/gtcs/test_gtcs_select_delete_isql.py @@ -0,0 +1,122 @@ +#coding:utf-8 +# +# id: functional.gtcs.gtcs_select_delete_isql +# title: GTCS/tests/SELECT_DELETE_ISQL. Test for select from SP that deletes record after its output. +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/SELECT_DELETE_ISQL.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='gtcs_sp1.fbk', init=init_script_1) + +test_script_1 = """ + set bail on; + set term ^; + create procedure proc returns (x varchar(5)) as + begin + for select sno from sp into :x + do begin + suspend; + delete from s where sno = :x; + end + end + ^ + create procedure proc1 returns (x varchar(5)) as + begin + for select sno from sp into :x + do begin + suspend; + end + delete from s where sno = :x; + end + ^ + create procedure proc2 returns (x varchar(5)) as + begin + for select sno from sp into :x + do begin + delete from s where sno = :x; + suspend; + end + end + ^ + set term ;^ + + set count on; + + select 'point-1' msg, p.* from proc p; + select 'point-2' msg, s.* from s; + rollback; + select 'point-3' msg, p.* from proc1 p; + select 'point-4' msg, s.* from s; + rollback; + select 'point-5' msg, p.* from proc2 p; + rollback; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG X + point-1 S1 + point-1 S1 + point-1 S2 + point-1 S2 + point-1 S4 + point-1 S4 + Records affected: 6 + + MSG SNO SNAME STATUS CITY + point-2 S3 Blake 30 Paris + point-2 S5 Adams 30 Athens + Records affected: 2 + + MSG X + point-3 S1 + point-3 S1 + point-3 S2 + point-3 S2 + point-3 S4 + point-3 S4 + Records affected: 6 + + MSG SNO SNAME STATUS CITY + point-4 S1 Smith 20 London + point-4 S2 Jones 10 Paris + point-4 S3 Blake 30 Paris + point-4 S5 Adams 30 Athens + Records affected: 4 + + MSG X + point-5 S1 + point-5 S1 + point-5 S2 + point-5 S2 + point-5 S4 + point-5 S4 + Records affected: 6 + """ + +@pytest.mark.version('>=2.5') +def test_gtcs_select_delete_isql_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_invalid_stream_when_use_trim.py b/tests/functional/gtcs/test_invalid_stream_when_use_trim.py new file mode 100644 index 00000000..033daddf --- /dev/null +++ b/tests/functional/gtcs/test_invalid_stream_when_use_trim.py @@ -0,0 +1,51 @@ +#coding:utf-8 +# +# id: functional.gtcs.invalid_stream_when_use_trim +# title: GTCS/tests/CF_ISQL_32. Statement with TRIM raises "bad BLR -- invalid stream" +# decription: +# ::: NB ::: +# ### Name of original test has no any relation with actual task of this test: ### +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_32.script +# +# Source description (Rudo Mihal, message of 2004-05-06 11:32:10; FB 1.5.1.4443): +# https://sourceforge.net/p/firebird/mailman/message/17016190/ +# +# Example for reproducing (by N. Samofatov, with UDF usage): +# https://sourceforge.net/p/firebird/mailman/message/17017012/ +# +# Checked on: 4.0.0.1804 SS; 3.0.6.33271 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('TRIM_RESULT.*', 'TRIM_RESULT')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select trim(TRAILING FROM (select max(rdb$relation_id) from rdb$database)) trim_result from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TRIM_RESULT 128 + """ + +@pytest.mark.version('>=2.5') +def test_invalid_stream_when_use_trim_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_isql_show_command_ambiguity.py b/tests/functional/gtcs/test_isql_show_command_ambiguity.py new file mode 100644 index 00000000..1bd75162 --- /dev/null +++ b/tests/functional/gtcs/test_isql_show_command_ambiguity.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: functional.gtcs.isql_show_command_ambiguity +# title: GTCS/tests/CF_ISQL_22. SHOW TABLE / VIEW: ambiguity between tables and views +# decription: +# ::: NB ::: +# ### Name of original test has no any relation with actual task of this test: ### +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_22.script +# +# bug #223513 ambiguity between tables and views +# +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table t(a int); + create view v as select a from t; + show tables; + show views; + show table v; + show table t; + show view v; + show view t; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + T + V + A INTEGER Nullable + A INTEGER Nullable + + View Source: + select a from t + """ +expected_stderr_1 = """ + There is no table V in this database + There is no view T in this database + """ + +@pytest.mark.version('>=2.5') +def test_isql_show_command_ambiguity_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_isql_show_command_collation.py b/tests/functional/gtcs/test_isql_show_command_collation.py new file mode 100644 index 00000000..050979bd --- /dev/null +++ b/tests/functional/gtcs/test_isql_show_command_collation.py @@ -0,0 +1,68 @@ +#coding:utf-8 +# +# id: functional.gtcs.isql_show_command_collation +# title: GTCS/tests/CF_ISQL_20. Misplaced collation when extracting metadata with isql +# decription: +# ::: NB ::: +# ### Name of original test has no any relation with actual task of this test: ### +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_20.script +# +# bug #223126 Misplaced collation when extracting metadata with isql +# +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create domain domain_with_collate_clause as char(1) + character set iso8859_1 + default 'v' + check(value >='a' and value <='z') + collate es_es; + + create table table_with_collated_field ( + field_01 domain_with_collate_clause + default 'w' + collate pt_pt + ); + alter table table_with_collated_field add constraint f01_check check( field_01 >= 'c' ); + + show domain domain_with_collate_clause; + show table table_with_collated_field; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DOMAIN_WITH_COLLATE_CLAUSE CHAR(1) CHARACTER SET ISO8859_1 Nullable + default 'v' + check(value >='a' and value <='z') + COLLATE ES_ES + FIELD_01 (DOMAIN_WITH_COLLATE_CLAUSE) CHAR(1) CHARACTER SET ISO8859_1 Nullable default 'w' + check(value >='a' and value <='z') + COLLATE PT_PT + CONSTRAINT F01_CHECK: + check( field_01 >= 'c' ) + """ + +@pytest.mark.version('>=2.5') +def test_isql_show_command_collation_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_minimum_grant_test.py b/tests/functional/gtcs/test_minimum_grant_test.py new file mode 100644 index 00000000..13013ea7 --- /dev/null +++ b/tests/functional/gtcs/test_minimum_grant_test.py @@ -0,0 +1,97 @@ +#coding:utf-8 +# +# id: functional.gtcs.minimum_grant_test +# title: GTCS/tests/CF_ISQL_34. minimum-grant-test +# decription: +# ::: NB ::: +# ### Name of original test has no any relation with actual task of this test: ### +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_34.script +# +# Checked on: 4.0.0.1804 SS; 3.0.6.33271 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('no permission for (read/select|SELECT) access.*', 'no permission for read access'), ('no permission for (insert/write|INSERT) access.*', 'no permission for write access'), ('-{0,1}[ ]{0,1}Effective user is.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + 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_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHOAMI TMP$QA_USER1 + WHOAMI TMP$QA_USER2 + C1 1 + """ +expected_stderr_1 = """ + 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 + """ + +@pytest.mark.version('>=2.5') +def test_minimum_grant_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_parser_comments_in_sql.py b/tests/functional/gtcs/test_parser_comments_in_sql.py new file mode 100644 index 00000000..dc05c8ad --- /dev/null +++ b/tests/functional/gtcs/test_parser_comments_in_sql.py @@ -0,0 +1,127 @@ +#coding:utf-8 +# +# id: functional.gtcs.parser_comments_in_sql +# title: GTCS/tests/CF_ISQL_19. Check for problems with comments (single-line and multi-line) +# decription: +# ::: NB ::: +# ### Name of original test has no any relation with actual task of this test: ### +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_19.script +# +# bug #781610 problems with one line comments (--) +# +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set heading off; + + create table test (n integer); + insert into test values (1); + + -- I am a comment + + /* BEGIN */ + -- I am a comment + select * from test; + /* END */ + + /* BEGIN */ + -- comment with unclosed 'quoted string + select * from test; + /* END */ + + /* BEGIN */ + -- comment with unclosed "quoted string + select * from test; + /* END */ + + /* BEGIN */ + -- I am a comment; + select * from test; + /* END */ + + /* BEGIN with unclosed "quoted */ + -- I am a comment; + select * from test; + /* END */ + + select * /* + comment + */ + from test; + + select * + /* comment */ + from test; + + select * + -- comment + from test; + + /* + Comment + */ select * from test; + + + -- Added 18.03.2020 + --################# + + -- single-line comment '*/ + select * from test; + + -- single-line comment --*/ + select * from test; + + /* * / / * q'{ + BEGIN multi-line comment-1 + '*/ + select * from test; + + + /* '' BEGIN multi-line comment-2 + '* / / * */ + select * from test; + + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + """ + +@pytest.mark.version('>=2.5') +def test_parser_comments_in_sql_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_ref_integ_drop_fk_index.py b/tests/functional/gtcs/test_ref_integ_drop_fk_index.py new file mode 100644 index 00000000..e222107e --- /dev/null +++ b/tests/functional/gtcs/test_ref_integ_drop_fk_index.py @@ -0,0 +1,76 @@ +#coding:utf-8 +# +# id: functional.gtcs.ref_integ_drop_fk_index +# title: GTCS/tests/REF_INT.4.ISQL ; ref-integ-drop-fk-index. Index that is used for FK should not be avail for DROP. +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/REF_INT.4.ISQL.script +# Checked on: 4.0.0.1806 SS; 3.0.6.33272 CS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# with open( os.path.join(context['files_location'],'gtcs-ref-integ.sql'), 'r') as f: +# sql_init = f.read() +# +# sql_addi=''' +# drop index ref_key; +# commit; +# insert into employee( emp_no, last_name, dept_no) values (12, 'e12', -1); -- should FAIL +# set count on; +# select * from employee e where e.dept_no < 0; +# ''' +# +# runProgram('isql', [ dsn], os.linesep.join( (sql_init, sql_addi) ) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 27000 + unsuccessful metadata update + -DROP INDEX REF_KEY failed + -action cancelled by trigger (1) to preserve data integrity + -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') +@pytest.mark.xfail +def test_ref_integ_drop_fk_index_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/gtcs/test_ref_integ_drop_fk_then_pk.py b/tests/functional/gtcs/test_ref_integ_drop_fk_then_pk.py new file mode 100644 index 00000000..c13fc430 --- /dev/null +++ b/tests/functional/gtcs/test_ref_integ_drop_fk_then_pk.py @@ -0,0 +1,66 @@ +#coding:utf-8 +# +# id: functional.gtcs.ref_integ_drop_fk_then_pk +# title: GTCS/tests/REF_INT.1.ISQL ; ref-integ-drop-fk-then-pk. Outcome must be SUCCESS if first we drop FK and after this PK constraint. +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/REF_INT.1.ISQL.script +# Checked on: 4.0.0.1806 SS; 3.0.6.33272 CS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# with open( os.path.join(context['files_location'],'gtcs-ref-integ.sql'), 'r') as f: +# sql_init = f.read() +# +# sql_addi=''' +# alter table employee drop constraint ref_key; +# alter table department drop constraint dept_key; +# set count on; +# -- Folowing two statements should PASS: +# insert into department( dept_no, dept_name) values (1, 'k1'); +# insert into employee( emp_no, last_name, dept_no) values (12, 'e12', -1); -- should FAIL +# ''' +# +# runProgram('isql', [ dsn], os.linesep.join( (sql_init, sql_addi) ) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 1 + Records affected: 1 + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_ref_integ_drop_fk_then_pk_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/gtcs/test_ref_integ_drop_pk_constraint.py b/tests/functional/gtcs/test_ref_integ_drop_pk_constraint.py new file mode 100644 index 00000000..d51fa606 --- /dev/null +++ b/tests/functional/gtcs/test_ref_integ_drop_pk_constraint.py @@ -0,0 +1,74 @@ +#coding:utf-8 +# +# id: functional.gtcs.ref_integ_drop_pk_constraint +# title: GTCS/tests/REF_INT.2.ISQL ; ref-integ-drop-pk-constraint. Constraint of PRIMARY KEY should not be avail for DROP if there is FK that depends on it. +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/REF_INT.2.ISQL.script +# Checked on: 4.0.0.1806 SS; 3.0.6.33272 CS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# with open( os.path.join(context['files_location'],'gtcs-ref-integ.sql'), 'r') as f: +# sql_init = f.read() +# +# sql_addi=''' +# drop index dept_key; +# -- Check that PK index still in use: following must FAIL: +# set count on; +# insert into department( dept_no, dept_name) values (1, 'k1'); +# ''' +# +# runProgram('isql', [ dsn], os.linesep.join( (sql_init, sql_addi) ) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 27000 + unsuccessful metadata update + -DROP INDEX DEPT_KEY failed + -action cancelled by trigger (1) to preserve data integrity + -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') +@pytest.mark.xfail +def test_ref_integ_drop_pk_constraint_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/gtcs/test_ref_integ_drop_pk_index.py b/tests/functional/gtcs/test_ref_integ_drop_pk_index.py new file mode 100644 index 00000000..a81de8a6 --- /dev/null +++ b/tests/functional/gtcs/test_ref_integ_drop_pk_index.py @@ -0,0 +1,74 @@ +#coding:utf-8 +# +# id: functional.gtcs.ref_integ_drop_pk_index +# title: GTCS/tests/REF_INT.3.ISQL ; ref-integ-drop-pk-index. Index that is used for PRIMARY KEY should not be avail for DROP. +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/REF_INT.3.ISQL.script +# Checked on: 4.0.0.1806 SS; 3.0.6.33272 CS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# with open( os.path.join(context['files_location'],'gtcs-ref-integ.sql'), 'r') as f: +# sql_init = f.read() +# +# sql_addi=''' +# drop index dept_key; +# -- Check that PK index still in use: following must FAIL: +# set count on; +# insert into department( dept_no, dept_name) values (1, 'k1'); +# ''' +# +# runProgram('isql', [ dsn], os.linesep.join( (sql_init, sql_addi) ) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 27000 + unsuccessful metadata update + -DROP INDEX DEPT_KEY failed + -action cancelled by trigger (1) to preserve data integrity + -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') +@pytest.mark.xfail +def test_ref_integ_drop_pk_index_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/gtcs/test_ref_integ_inactive_fk_index.py b/tests/functional/gtcs/test_ref_integ_inactive_fk_index.py new file mode 100644 index 00000000..985a653d --- /dev/null +++ b/tests/functional/gtcs/test_ref_integ_inactive_fk_index.py @@ -0,0 +1,79 @@ +#coding:utf-8 +# +# id: functional.gtcs.ref_integ_inactive_fk_index +# title: GTCS/tests/REF_INT.8.ISQL ; ref-integ-inactive-fk-index. Index that is used for FK should not be avail for INACTIVE. +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/REF_INT.8.ISQL.script +# Checked on: 4.0.0.1806 SS; 3.0.6.33272 CS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# with open( os.path.join(context['files_location'],'gtcs-ref-integ.sql'), 'r') as f: +# sql_init = f.read() +# +# sql_addi=''' +# alter index ref_key inactive; -- should FAIL +# commit; +# +# insert into employee( emp_no, last_name, dept_no) values (11, 'e11', 1); +# insert into employee( emp_no, last_name, dept_no) values (12, 'e12', -1); +# +# set count on; +# select * from employee e where e.dept_no < 0; +# ''' +# +# runProgram('isql', [ dsn], os.linesep.join( (sql_init, sql_addi) ) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 27000 + unsuccessful metadata update + -ALTER INDEX REF_KEY failed + -action cancelled by trigger (2) to preserve data integrity + -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') +@pytest.mark.xfail +def test_ref_integ_inactive_fk_index_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/gtcs/test_ref_integ_inactive_pk_index.py b/tests/functional/gtcs/test_ref_integ_inactive_pk_index.py new file mode 100644 index 00000000..89c4eae5 --- /dev/null +++ b/tests/functional/gtcs/test_ref_integ_inactive_pk_index.py @@ -0,0 +1,84 @@ +#coding:utf-8 +# +# id: functional.gtcs.ref_integ_inactive_pk_index +# title: GTCS/tests/REF_INT.7.ISQL ; ref-integ-inactive-pk-index. Index that is used for PRIMARY KEY should not be avail for INACTIVE. +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/REF_INT.7.ISQL.script +# Checked on: 4.0.0.1806 SS; 3.0.6.33272 CS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# with open( os.path.join(context['files_location'],'gtcs-ref-integ.sql'), 'r') as f: +# sql_init = f.read() +# +# sql_addi=''' +# alter index dept_key inactive; +# commit; +# -- Check that PK index still in use: following must FAIL: +# insert into department( dept_no, dept_name) values (1, 'k1'); +# +# -- Check that it is ALLOWED to insert record into child table (employee) +# -- if value of dept_no exists in the parent table (department) +# -- QUOTE FROM SOURCE TEST: +# -- "... attempts to insert valid records into another table connected +# -- to this table by foreign key constraint. The current behaviour is +# -- that the insertion of valid records fails because of the index being +# -- inactivated in the other connected table (bug 7517)" +# set count on; +# insert into employee values (11, 'e11', 1); -- ==> Records affected: 1 +# ''' +# +# runProgram('isql', [ dsn], os.linesep.join( (sql_init, sql_addi) ) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 1 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 27000 + unsuccessful metadata update + -ALTER INDEX DEPT_KEY failed + -action cancelled by trigger (2) to preserve data integrity + -Cannot deactivate 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') +@pytest.mark.xfail +def test_ref_integ_inactive_pk_index_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + 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 new file mode 100644 index 00000000..e9e64175 --- /dev/null +++ b/tests/functional/gtcs/test_ref_integ_inactive_pk_index_2.py @@ -0,0 +1,85 @@ +#coding:utf-8 +# +# id: functional.gtcs.ref_integ_inactive_pk_index_2 +# title: GTCS/tests/REF_INT.6.ISQL ; ref-integ-inactive-pk-index-2. Index that is used for PRIMARY KEY should not be avail for INACTIVE. +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/REF_INT.7.ISQL.script +# Checked on: 4.0.0.1806 SS; 3.0.6.33272 CS; 2.5.9.27149 SC. +# +# 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) +# ==== +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# with open( os.path.join(context['files_location'],'gtcs-ref-integ.sql'), 'r') as f: +# sql_init = f.read() +# +# sql_addi=''' +# alter index dept_key inactive; +# commit; +# set count on; +# insert into employee values (11, 'e11', -1); -- ==> Records affected: 0 +# ''' +# +# runProgram('isql', [ dsn], os.linesep.join( (sql_init, sql_addi) ) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 27000 + unsuccessful metadata update + -ALTER INDEX DEPT_KEY failed + -action cancelled by trigger (2) to preserve data integrity + -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') +@pytest.mark.xfail +def test_ref_integ_inactive_pk_index_2_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/gtcs/test_regexp_similar_to.py b/tests/functional/gtcs/test_regexp_similar_to.py new file mode 100644 index 00000000..4430ff5a --- /dev/null +++ b/tests/functional/gtcs/test_regexp_similar_to.py @@ -0,0 +1,258 @@ +#coding:utf-8 +# +# id: functional.gtcs.regexp_similar_to +# title: GTCS/tests/FB_SQL_REGEX_1, statements with SIMILAR TO. Miscelaneous tests. +# decription: +# Test creates table and fills it with unicode data to be checked (field 'str'), +# pattern for right part of SIMILAR TO expression and expected result. +# +# Then data will be verified against pattern twise: +# * without casting them to UTF8 charset; +# * with such casting. +# Checked on: 4.0.0.1789 +# +# ::: NOTE ::: +# Test parameter 'database_character_set' must be SKIPPED here! +# Comparison of non-ascii diacritical character can bring surprising result if we skip preliminary +# casting of characters to UTF8. +# For example consider character 'á' (small A with Acute, https://www.compart.com/en/unicode/U+00E1). +# 1) If we do not specify charset: +# select 'á' similar to '_' from rdb$database -- then this expression returns FALSE; +# (this is because here SIMILAR_TO works using BYTE-basis, and 'á' has 2 bytes and this don't match '_'). +# 2) but if we do this: +# select _utf8 'á' similar to '_' as test_1 from rdb$database -- then result will be TRUE. +# 3) all tests here do NOT check results of substring( similar to , +# see separate test for this: regexp-substring-similar_to.fbt +# +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/FB_SQL_REGEX_1.output +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table tests ( + id integer generated by default as identity, + str varchar(20), + pattern varchar(20), + expected varchar(20) + ); + + insert into tests (str, pattern, expected) values ('aa', '(aa){1}', null); + insert into tests (str, pattern, expected) values ('aa', '(a){1}', null); + insert into tests (str, pattern, expected) values ('a', '(a){1}', null); + insert into tests (str, pattern, expected) values ('A', '(a){1}', null); + insert into tests (str, pattern, expected) values ('á', '(a){1}', null); + insert into tests (str, pattern, expected) values ('Á', '(ã){1}', null); + insert into tests (str, pattern, expected) values ('aa', 'a{1}', null); + insert into tests (str, pattern, expected) values ('', '(1|2){0,}', null); + insert into tests (str, pattern, expected) values ('', '(1|2){1,}', null); + insert into tests (str, pattern, expected) values ('1', '(1|2){0,}', null); + insert into tests (str, pattern, expected) values ('1', '(1|2){0,1}', null); + insert into tests (str, pattern, expected) values ('1', '(1|2){1}', null); + insert into tests (str, pattern, expected) values ('12', '(1|1[2]){1}', null); + insert into tests (str, pattern, expected) values ('1212', '(1|1[2]){3,5}', null); + insert into tests (str, pattern, expected) values ('121212', '(1|1[2]){3,5}', null); + insert into tests (str, pattern, expected) values ('12121212', '(1|1[2]){3,5}', null); + insert into tests (str, pattern, expected) values ('1212121212', '(1|1[2]){3,5}', null); + insert into tests (str, pattern, expected) values ('121212121212', '(1|1[2]){3,5}', null); + insert into tests (str, pattern, expected) values ('á', '_', null); -- <<<<<<<<<<<<<<<<<<<<<<< NB <<<<< + + insert into tests (str, pattern, expected) values ('1', '[1-53-7]', null); + insert into tests (str, pattern, expected) values ('2', '[1-53-7]', null); + insert into tests (str, pattern, expected) values ('4', '[1-53-7]', null); + insert into tests (str, pattern, expected) values ('6', '[1-53-7]', null); + insert into tests (str, pattern, expected) values ('8', '[1-53-7]', null); + + insert into tests (str, pattern, expected) values ('1', '[1-53-78-0]', null); + insert into tests (str, pattern, expected) values ('2', '[1-53-78-0]', null); + insert into tests (str, pattern, expected) values ('4', '[1-53-78-0]', null); + insert into tests (str, pattern, expected) values ('6', '[1-53-78-0]', null); + insert into tests (str, pattern, expected) values ('8', '[1-53-78-0]', null); + + insert into tests (str, pattern, expected) values ('0', '[8-0]', null); + insert into tests (str, pattern, expected) values ('1', '[8-0]', null); + insert into tests (str, pattern, expected) values ('8', '[8-0]', null); + insert into tests (str, pattern, expected) values ('9', '[8-0]', null); + + insert into tests (str, pattern, expected) values ('0', '[8-09-0]', null); + insert into tests (str, pattern, expected) values ('1', '[8-09-0]', null); + insert into tests (str, pattern, expected) values ('8', '[8-09-0]', null); + insert into tests (str, pattern, expected) values ('9', '[8-09-0]', null); + + insert into tests (str, pattern, expected) values ('1', '[1-53-7^4]', null); + insert into tests (str, pattern, expected) values ('2', '[1-53-7^4]', null); + insert into tests (str, pattern, expected) values ('4', '[1-53-7^4]', null); + insert into tests (str, pattern, expected) values ('6', '[1-53-7^4]', null); + insert into tests (str, pattern, expected) values ('8', '[1-53-7^4]', null); + + insert into tests (str, pattern, expected) values ('1', '[1-53-7^2-5]', null); + insert into tests (str, pattern, expected) values ('2', '[1-53-7^2-5]', null); + insert into tests (str, pattern, expected) values ('4', '[1-53-7^2-5]', null); + insert into tests (str, pattern, expected) values ('6', '[1-53-7^2-5]', null); + insert into tests (str, pattern, expected) values ('8', '[1-53-7^2-5]', null); + + insert into tests (str, pattern, expected) values ('1', '[1-53-7^2-53-6]', null); + insert into tests (str, pattern, expected) values ('2', '[1-53-7^2-53-6]', null); + insert into tests (str, pattern, expected) values ('4', '[1-53-7^2-53-6]', null); + insert into tests (str, pattern, expected) values ('6', '[1-53-7^2-53-6]', null); + insert into tests (str, pattern, expected) values ('8', '[1-53-7^2-53-6]', null); + + insert into tests (str, pattern, expected) values ('1', '[1-53-7^5-2]', null); + insert into tests (str, pattern, expected) values ('2', '[1-53-7^5-2]', null); + insert into tests (str, pattern, expected) values ('4', '[1-53-7^5-2]', null); + insert into tests (str, pattern, expected) values ('6', '[1-53-7^5-2]', null); + insert into tests (str, pattern, expected) values ('8', '[1-53-7^5-2]', null); + + set heading off; + select 'without_cast' as msg, str, pattern, iif(str similar to pattern escape '\\', 1, 0) from tests order by id; + + select 'with_utf8_cast' as msg, str, pattern, iif(cast(str as varchar(20) character set utf8) similar to cast(pattern as varchar(20) character set utf8) escape '\\', 1, 0) from tests order by id; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +without_cast aa (aa){1} 1 +without_cast aa (a){1} 0 +without_cast a (a){1} 1 +without_cast A (a){1} 0 +without_cast á (a){1} 0 +without_cast Á (ã){1} 0 +without_cast aa a{1} 0 +without_cast (1|2){0,} 1 +without_cast (1|2){1,} 0 +without_cast 1 (1|2){0,} 1 +without_cast 1 (1|2){0,1} 1 +without_cast 1 (1|2){1} 1 +without_cast 12 (1|1[2]){1} 1 +without_cast 1212 (1|1[2]){3,5} 0 +without_cast 121212 (1|1[2]){3,5} 1 +without_cast 12121212 (1|1[2]){3,5} 1 +without_cast 1212121212 (1|1[2]){3,5} 1 +without_cast 121212121212 (1|1[2]){3,5} 0 +without_cast á _ 0 +without_cast 1 [1-53-7] 1 + +without_cast 2 [1-53-7] 1 +without_cast 4 [1-53-7] 1 +without_cast 6 [1-53-7] 1 +without_cast 8 [1-53-7] 0 +without_cast 1 [1-53-78-0] 1 +without_cast 2 [1-53-78-0] 1 +without_cast 4 [1-53-78-0] 1 +without_cast 6 [1-53-78-0] 1 +without_cast 8 [1-53-78-0] 0 +without_cast 0 [8-0] 0 +without_cast 1 [8-0] 0 +without_cast 8 [8-0] 0 +without_cast 9 [8-0] 0 +without_cast 0 [8-09-0] 0 +without_cast 1 [8-09-0] 0 +without_cast 8 [8-09-0] 0 +without_cast 9 [8-09-0] 0 +without_cast 1 [1-53-7^4] 1 +without_cast 2 [1-53-7^4] 1 +without_cast 4 [1-53-7^4] 0 + +without_cast 6 [1-53-7^4] 1 +without_cast 8 [1-53-7^4] 0 +without_cast 1 [1-53-7^2-5] 1 +without_cast 2 [1-53-7^2-5] 0 +without_cast 4 [1-53-7^2-5] 0 +without_cast 6 [1-53-7^2-5] 1 +without_cast 8 [1-53-7^2-5] 0 +without_cast 1 [1-53-7^2-53-6] 1 +without_cast 2 [1-53-7^2-53-6] 0 +without_cast 4 [1-53-7^2-53-6] 0 +without_cast 6 [1-53-7^2-53-6] 0 +without_cast 8 [1-53-7^2-53-6] 0 +without_cast 1 [1-53-7^5-2] 1 +without_cast 2 [1-53-7^5-2] 1 +without_cast 4 [1-53-7^5-2] 1 +without_cast 6 [1-53-7^5-2] 1 +without_cast 8 [1-53-7^5-2] 0 + + +with_utf8_cast aa (aa){1} 1 +with_utf8_cast aa (a){1} 0 +with_utf8_cast a (a){1} 1 +with_utf8_cast A (a){1} 0 +with_utf8_cast á (a){1} 0 +with_utf8_cast Á (ã){1} 0 +with_utf8_cast aa a{1} 0 +with_utf8_cast (1|2){0,} 1 +with_utf8_cast (1|2){1,} 0 +with_utf8_cast 1 (1|2){0,} 1 +with_utf8_cast 1 (1|2){0,1} 1 +with_utf8_cast 1 (1|2){1} 1 +with_utf8_cast 12 (1|1[2]){1} 1 +with_utf8_cast 1212 (1|1[2]){3,5} 0 +with_utf8_cast 121212 (1|1[2]){3,5} 1 +with_utf8_cast 12121212 (1|1[2]){3,5} 1 +with_utf8_cast 1212121212 (1|1[2]){3,5} 1 +with_utf8_cast 121212121212 (1|1[2]){3,5} 0 +with_utf8_cast á _ 1 +with_utf8_cast 1 [1-53-7] 1 + +with_utf8_cast 2 [1-53-7] 1 +with_utf8_cast 4 [1-53-7] 1 +with_utf8_cast 6 [1-53-7] 1 +with_utf8_cast 8 [1-53-7] 0 +with_utf8_cast 1 [1-53-78-0] 1 +with_utf8_cast 2 [1-53-78-0] 1 +with_utf8_cast 4 [1-53-78-0] 1 +with_utf8_cast 6 [1-53-78-0] 1 +with_utf8_cast 8 [1-53-78-0] 0 +with_utf8_cast 0 [8-0] 0 +with_utf8_cast 1 [8-0] 0 +with_utf8_cast 8 [8-0] 0 +with_utf8_cast 9 [8-0] 0 +with_utf8_cast 0 [8-09-0] 0 +with_utf8_cast 1 [8-09-0] 0 +with_utf8_cast 8 [8-09-0] 0 +with_utf8_cast 9 [8-09-0] 0 +with_utf8_cast 1 [1-53-7^4] 1 +with_utf8_cast 2 [1-53-7^4] 1 +with_utf8_cast 4 [1-53-7^4] 0 + +with_utf8_cast 6 [1-53-7^4] 1 +with_utf8_cast 8 [1-53-7^4] 0 +with_utf8_cast 1 [1-53-7^2-5] 1 +with_utf8_cast 2 [1-53-7^2-5] 0 +with_utf8_cast 4 [1-53-7^2-5] 0 +with_utf8_cast 6 [1-53-7^2-5] 1 +with_utf8_cast 8 [1-53-7^2-5] 0 +with_utf8_cast 1 [1-53-7^2-53-6] 1 +with_utf8_cast 2 [1-53-7^2-53-6] 0 +with_utf8_cast 4 [1-53-7^2-53-6] 0 +with_utf8_cast 6 [1-53-7^2-53-6] 0 +with_utf8_cast 8 [1-53-7^2-53-6] 0 +with_utf8_cast 1 [1-53-7^5-2] 1 +with_utf8_cast 2 [1-53-7^5-2] 1 +with_utf8_cast 4 [1-53-7^5-2] 1 +with_utf8_cast 6 [1-53-7^5-2] 1 +with_utf8_cast 8 [1-53-7^5-2] 0 + """ + +@pytest.mark.version('>=4.0') +def test_regexp_similar_to_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_regexp_substring_similar_to.py b/tests/functional/gtcs/test_regexp_substring_similar_to.py new file mode 100644 index 00000000..a457de6e --- /dev/null +++ b/tests/functional/gtcs/test_regexp_substring_similar_to.py @@ -0,0 +1,89 @@ +#coding:utf-8 +# +# id: functional.gtcs.regexp_substring_similar_to +# title: GTCS/tests/FB_SQL_REGEX_1 SUBSTRING ; Miscelaneous tests of SIMILAR TO . +# decription: +# Test creates table and fills it with unicode data to be checked (field 'str'), pattern and +# performs output of SUBSTRING( SIMILAR ). +# Also, some additional examples presents for other checks. +# Checked on: 4.0.0.1789 +# +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/FB_SQL_REGEX_1.script +# +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table tests ( + id integer generated by default as identity, + str varchar(20), + pattern varchar(20), + expected varchar(20) + ); + create sequence g; + + set heading off; + + insert into tests(id, str, pattern, expected) values ( gen_id(g,1), '(12) 3456-7890', '\\(__\\) \\"%\\-%\\"', '3456-7890'); + insert into tests(id, str, pattern, expected) values ( gen_id(g,1), '(12) 3456-7890', '\\(__\\) \\"%x%\\"', null); + insert into tests(id, str, pattern, expected) values ( gen_id(g,1), 'abc123abc456', '\\"%\\"abc%6', 'abc123'); + insert into tests(id, str, pattern, expected) values ( gen_id(g,1), 'abc123abc456', '\\"%\\"abc%7', null); + commit; + select id, substring(str similar pattern escape '\\'), expected from tests; + + select gen_id(g,1), substring('(12) 3456-7890' similar '\\(__\\) \\"%\\-%\\"' escape '\\') from rdb$database; -- 3.0.6: invalid pattern + select gen_id(g,1), substring('abc123abc456' similar '\\"%\\"abc%6' escape '\\') from rdb$database; + select gen_id(g,1), substring('abc123abc456' similar '\\"%\\"abc%7' escape '\\') from rdb$database; + + select gen_id(g,1), substring('asds 12.34 asd' similar '% \\"[\\+\\-]?[0-9]*([0-9].|.[0-9])?[0-9]*\\" %' escape '\\') from rdb$database; + select gen_id(g,1), substring('asd 5 s 1234 a 12 sd' similar '% \\"[\\+\\-]?[0-9]*\\" %' escape '\\') from rdb$database; + select gen_id(g,1), substring('a 1 b' similar '%#"[0-9]*#" %' escape '#') from rdb$database; + + select gen_id(g,1), substring('çaaaЫxЫЫcccç' similar '%aaa#"%#"ccc%' escape '#') from rdb$database; + select gen_id(g,1), substring(cast('aaaЫxЫЫccc' as varchar(15) character set win1251) similar '%aaa#"%#"ccc%' escape '#') from rdb$database; + select gen_id(g,1), cast(substring(cast(_utf8 'aaaЫxЫЫccc' as varchar(10) character set win1251) similar '%aaa#"%#"ccc%' escape '#') as varchar(10) character set utf8) from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 1 3456-7890 3456-7890 + 2 + 3 abc123 abc123 + 4 + + 5 3456-7890 + 6 abc123 + 7 + + 8 12.34 + 9 5 + 10 + 11 ЫxЫЫ + 12 ЫxЫЫ + 13 ЫxЫЫ + + """ + +@pytest.mark.version('>=4.0') +def test_regexp_substring_similar_to_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_sql_join_03.py b/tests/functional/gtcs/test_sql_join_03.py new file mode 100644 index 00000000..327af1c6 --- /dev/null +++ b/tests/functional/gtcs/test_sql_join_03.py @@ -0,0 +1,120 @@ +#coding:utf-8 +# +# id: functional.gtcs.sql_join_03 +# title: GTCS/tests/C_SQL_JOIN_3. Ability to run query: ( A LEFT JOIN B ) INER JOIN C, plus ORDER BY with fields not from SELECT list. +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/C_SQL_JOIN_3.script +# Original backup file that is used for this test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/test-files/atlas.gbk +# Checked on 4.0.0.1896; 3.0.6.33288; 2.5.9.27149 +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='gtcs_atlas.fbk', init=init_script_1) + +test_script_1 = """ + + select 'DSQL-test' as msg, b.team_name, c.city, s.state_name + from ( + cities c left join states s on s.state = c.state + ) + inner join baseball_teams b on b.city = c.city + --order by b.team_name, c.city, s.state_name; + order by b.home_stadium, c.population, s.capital; + + set term ^; + execute block returns( + msg varchar(10) + ,team_name type of column baseball_teams.team_name + ,city type of column cities.city + ,state_name type of column states.state_name + ) as + declare c cursor for ( + select 'PSQL-test' as msg, b.team_name, c.city, s.state_name + from ( + cities c left join states s on s.state = c.state + ) + inner join baseball_teams b on b.city = c.city + --order by b.team_name, c.city, s.state_name + order by b.home_stadium, c.population, s.capital + ); + begin + open c; + while (1=1) do + begin + fetch c into msg, team_name, city, state_name; + if (row_count = 0) then + leave; + suspend; + end + close c; + end + ^ + set term ;^ + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG TEAM_NAME CITY STATE_NAME + DSQL-test Astros Houston Texas + DSQL-test Braves Atlanta Georgia + DSQL-test Cardinals St. Louis Missouri + DSQL-test Giants San Francisco California + DSQL-test Indians Cleveland Ohio + DSQL-test White Sox Chicago Illinois + DSQL-test Dodgers Los Angeles California + DSQL-test Red Sox Boston Massachusetts + DSQL-test Mariners Seattle Washington + DSQL-test Brewers Milwaukee Wisconsin + DSQL-test Royals Kansas City Missouri + DSQL-test Padres San Diego California + DSQL-test Mets New York New York + DSQL-test Pirates Pittsburgh Pennsylvania + DSQL-test Tigers Detroit Michigan + DSQL-test Phillies Philadelphia Pennsylvania + DSQL-test Cubs Chicago Illinois + DSQL-test Yankees New York New York + + MSG TEAM_NAME CITY STATE_NAME + PSQL-test Astros Houston Texas + PSQL-test Braves Atlanta Georgia + PSQL-test Cardinals St. Louis Missouri + PSQL-test Giants San Francisco California + PSQL-test Indians Cleveland Ohio + PSQL-test White Sox Chicago Illinois + PSQL-test Dodgers Los Angeles California + PSQL-test Red Sox Boston Massachusetts + PSQL-test Mariners Seattle Washington + PSQL-test Brewers Milwaukee Wisconsin + PSQL-test Royals Kansas City Missouri + PSQL-test Padres San Diego California + PSQL-test Mets New York New York + PSQL-test Pirates Pittsburgh Pennsylvania + PSQL-test Tigers Detroit Michigan + PSQL-test Phillies Philadelphia Pennsylvania + PSQL-test Cubs Chicago Illinois + PSQL-test Yankees New York New York + """ + +@pytest.mark.version('>=2.5') +def test_sql_join_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_sql_join_04.py b/tests/functional/gtcs/test_sql_join_04.py new file mode 100644 index 00000000..8dae5b82 --- /dev/null +++ b/tests/functional/gtcs/test_sql_join_04.py @@ -0,0 +1,125 @@ +#coding:utf-8 +# +# id: functional.gtcs.sql_join_04 +# title: GTCS/tests/C_SQL_JOIN_4. Ability to run query: ( A LEFT JOIN B ) , C. Then add ORDER BY with fields not from SELECT list. +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/C_SQL_JOIN_3.script +# Original backup file that is used for this test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/test-files/atlas.gbk +# +# NOTE: cross join here can be specified in IMPLICIT FORM, using ",' instead of "cross join" clause. +# Though this leads to very poor readability, this form is still allowed. +# Because of WHERE-clause, resultset must be the same as it was INNER join here. +# +# Checked on 4.0.0.1896; 3.0.6.33288; 2.5.9.27149 +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='gtcs_atlas.fbk', init=init_script_1) + +test_script_1 = """ + + select 'DSQL-test' as msg, b.team_name, c.city, s.state_name + from ( + cities c left join states s on s.state = c.state + ) + ,baseball_teams b + where b.city = c.city + order by b.home_stadium, c.population, s.capital; + + set term ^; + execute block returns( + msg varchar(10) + ,team_name type of column baseball_teams.team_name + ,city type of column cities.city + ,state_name type of column states.state_name + ) as + declare c cursor for ( + select 'PSQL-test' as msg, b.team_name, c.city, s.state_name + from ( + cities c left join states s on s.state = c.state + ) + ,baseball_teams b + where b.city = c.city + order by b.home_stadium, c.population, s.capital + ); + begin + open c; + while (1=1) do + begin + fetch c into msg, team_name, city, state_name; + if (row_count = 0) then + leave; + suspend; + end + close c; + end + ^ + set term ;^ + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG TEAM_NAME CITY STATE_NAME + DSQL-test Astros Houston Texas + DSQL-test Braves Atlanta Georgia + DSQL-test Cardinals St. Louis Missouri + DSQL-test Giants San Francisco California + DSQL-test Indians Cleveland Ohio + DSQL-test White Sox Chicago Illinois + DSQL-test Dodgers Los Angeles California + DSQL-test Red Sox Boston Massachusetts + DSQL-test Mariners Seattle Washington + DSQL-test Brewers Milwaukee Wisconsin + DSQL-test Royals Kansas City Missouri + DSQL-test Padres San Diego California + DSQL-test Mets New York New York + DSQL-test Pirates Pittsburgh Pennsylvania + DSQL-test Tigers Detroit Michigan + DSQL-test Phillies Philadelphia Pennsylvania + DSQL-test Cubs Chicago Illinois + DSQL-test Yankees New York New York + + MSG TEAM_NAME CITY STATE_NAME + PSQL-test Astros Houston Texas + PSQL-test Braves Atlanta Georgia + PSQL-test Cardinals St. Louis Missouri + PSQL-test Giants San Francisco California + PSQL-test Indians Cleveland Ohio + PSQL-test White Sox Chicago Illinois + PSQL-test Dodgers Los Angeles California + PSQL-test Red Sox Boston Massachusetts + PSQL-test Mariners Seattle Washington + PSQL-test Brewers Milwaukee Wisconsin + PSQL-test Royals Kansas City Missouri + PSQL-test Padres San Diego California + PSQL-test Mets New York New York + PSQL-test Pirates Pittsburgh Pennsylvania + PSQL-test Tigers Detroit Michigan + PSQL-test Phillies Philadelphia Pennsylvania + PSQL-test Cubs Chicago Illinois + PSQL-test Yankees New York New York + """ + +@pytest.mark.version('>=2.5') +def test_sql_join_04_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_time_zone.py b/tests/functional/gtcs/test_time_zone.py new file mode 100644 index 00000000..872601ab --- /dev/null +++ b/tests/functional/gtcs/test_time_zone.py @@ -0,0 +1,1330 @@ +#coding:utf-8 +# +# id: functional.gtcs.time_zone +# title: GTCS/tests/FB_SQL_TIME_ZONE. Miscelaneous tests. +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/FB_SQL_TIME_ZONE.script +# Checked on 4.0.0.1931. +# 05.05.2020: added block for CORE-6271 (from GTCS). Checked on 4.0.0.1954. +# +# 28.10.2020 +# Old code was completely replaced by source from GTCS. +# It was changed to meet new requirements to format of timezone offset: +# 1) it must include SIGN, i.e. + or -; +# 2) in must contain BOTH hours and minutes delimited by colon. +# +# This means that following (old) statements will fail with SQLSTATE = 22009: +# * set time zone '00:00' +# Invalid time zone region: 00:00 +# (because of missed sign "+") +# +# * ... datediff(hour from timestamp '... -03' to timestamp '... -03') +# Invalid time zone offset: -03 - must use format +/-hours:minutes and be between -14:00 and +14:00 +# +# See: https://github.com/FirebirdSQL/firebird/commit/ff37d445ce844f991242b1e2c1f96b80a5d1636d +# Checked on 4.0.0.2238 +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + set time zone '+00:00'; + + select cast('01:23:45' as time with time zone), + cast('2018-01-01 01:23:45' as timestamp with time zone), + extract(timezone_hour from cast('01:23:45' as time with time zone)), + extract(timezone_minute from cast('01:23:45' as time with time zone)), + extract(timezone_hour from cast('2018-01-01 01:23:45' as timestamp with time zone)), + extract(timezone_minute from cast('2018-01-01 01:23:45' as timestamp with time zone)), + cast(cast('01:23:45' as time with time zone) as time), + cast(cast('2018-01-01 01:23:45' as timestamp with time zone) as timestamp) + from rdb$database; + + select cast('01:23:45 +02:00' as time with time zone), + cast('2018-01-01 01:23:45 +02:00' as timestamp with time zone), + extract(timezone_hour from cast('01:23:45 +02:00' as time with time zone)), + extract(timezone_minute from cast('01:23:45 +02:00' as time with time zone)), + extract(timezone_hour from cast('2018-01-01 01:23:45 +02:00' as timestamp with time zone)), + extract(timezone_minute from cast('2018-01-01 01:23:45 +02:00' as timestamp with time zone)), + cast(cast('01:23:45 +02:00' as time with time zone) as time), + cast(cast('2018-01-01 01:23:45 +02:00' as timestamp with time zone) as timestamp) + from rdb$database; + + select time '01:23:45 +02:00', + timestamp '2018-01-01 01:23:45 +02:00', + extract(timezone_hour from time '01:23:45 +02:00'), + extract(timezone_minute from time '01:23:45 +02:00'), + extract(timezone_hour from timestamp '2018-01-01 01:23:45 +02:00'), + extract(timezone_minute from timestamp '2018-01-01 01:23:45 +02:00'), + cast(time '01:23:45 +02:00' as time), + cast(timestamp '2018-01-01 01:23:45 +02:00' as timestamp) + from rdb$database; + + + --- + + + set time zone '-02:00'; + + select cast('01:23:45' as time with time zone), + cast('2018-01-01 01:23:45' as timestamp with time zone), + extract(timezone_hour from cast('01:23:45' as time with time zone)), + extract(timezone_minute from cast('01:23:45' as time with time zone)), + extract(timezone_hour from cast('2018-01-01 01:23:45' as timestamp with time zone)), + extract(timezone_minute from cast('2018-01-01 01:23:45' as timestamp with time zone)), + cast(cast('01:23:45' as time with time zone) as time), + cast(cast('2018-01-01 01:23:45' as timestamp with time zone) as timestamp) + from rdb$database; + + select cast('01:23:45 +02:00' as time with time zone), + cast('2018-01-01 01:23:45 +02:00' as timestamp with time zone), + extract(timezone_hour from cast('01:23:45 +02:00' as time with time zone)), + extract(timezone_minute from cast('01:23:45 +02:00' as time with time zone)), + extract(timezone_hour from cast('2018-01-01 01:23:45 +02:00' as timestamp with time zone)), + extract(timezone_minute from cast('2018-01-01 01:23:45 +02:00' as timestamp with time zone)), + cast(cast('01:23:45 +02:00' as time with time zone) as time), + cast(cast('2018-01-01 01:23:45 +02:00' as timestamp with time zone) as timestamp) + from rdb$database; + + + --- + + + select extract(hour from timestamp '2018-01-02 03:04:05.6789 -03:00'), + extract(minute from timestamp '2018-01-02 03:04:05.6789 -03:00'), + extract(second from timestamp '2018-01-02 03:04:05.6789 -03:00'), + extract(millisecond from timestamp '2018-01-02 03:04:05.6789 -03:00'), + extract(year from timestamp '2018-01-02 03:04:05.6789 -03:00'), + extract(month from timestamp '2018-01-02 03:04:05.6789 -03:00'), + extract(day from timestamp '2018-01-02 03:04:05.6789 -03:00') + from rdb$database; + + select extract(hour from time '03:04:05.6789 -03:00'), + extract(minute from time '03:04:05.6789 -03:00'), + extract(second from time '03:04:05.6789 -03:00'), + extract(millisecond from time '03:04:05.6789 -03:00') + from rdb$database; + + + --- + + + -- DST starts at 2017-10-15 00:00 in America/Sao_Paulo + + select timestamp '2017-10-14 22:00 America/Sao_Paulo', extract(timezone_hour from timestamp '2017-10-14 22:00 America/Sao_Paulo'), + timestamp '2017-10-14 22:00 America/Sao_Paulo' + 1, extract(timezone_hour from timestamp '2017-10-14 22:00 America/Sao_Paulo' + 1), + timestamp '2017-10-14 22:00 America/Sao_Paulo' + 2, extract(timezone_hour from timestamp '2017-10-14 22:00 America/Sao_Paulo' + 2), + timestamp '2017-10-14 22:00 America/Sao_Paulo' + 3, extract(timezone_hour from timestamp '2017-10-14 22:00 America/Sao_Paulo' + 3), + timestamp '2017-10-16 22:00 America/Sao_Paulo', extract(timezone_hour from timestamp '2017-10-16 22:00 America/Sao_Paulo'), + timestamp '2017-10-16 22:00 America/Sao_Paulo' - 1, extract(timezone_hour from timestamp '2017-10-16 22:00 America/Sao_Paulo' - 1), + timestamp '2017-10-16 22:00 America/Sao_Paulo' - 2, extract(timezone_hour from timestamp '2017-10-16 22:00 America/Sao_Paulo' - 2), + timestamp '2017-10-16 22:00 America/Sao_Paulo' - 3, extract(timezone_hour from timestamp '2017-10-16 22:00 America/Sao_Paulo' - 3) + from rdb$database; + + select dateadd(1 hour to timestamp '2017-10-14 20:00 America/Sao_Paulo'), + dateadd(2 hour to timestamp '2017-10-14 20:00 America/Sao_Paulo'), + dateadd(3 hour to timestamp '2017-10-14 20:00 America/Sao_Paulo'), + dateadd(4 hour to timestamp '2017-10-14 20:00 America/Sao_Paulo'), + dateadd(5 hour to timestamp '2017-10-14 20:00 America/Sao_Paulo') + from rdb$database; + + + -- DST ends at 2018-02-18 00:00 in America/Sao_Paulo + + select timestamp '2018-02-17 22:00 America/Sao_Paulo', extract(timezone_hour from timestamp '2018-02-17 22:00 America/Sao_Paulo'), + timestamp '2018-02-17 22:00 America/Sao_Paulo' + 1, extract(timezone_hour from timestamp '2018-02-17 22:00 America/Sao_Paulo' + 1), + timestamp '2018-02-17 22:00 America/Sao_Paulo' + 2, extract(timezone_hour from timestamp '2018-02-17 22:00 America/Sao_Paulo' + 2), + timestamp '2018-02-17 22:00 America/Sao_Paulo' + 3, extract(timezone_hour from timestamp '2018-02-17 22:00 America/Sao_Paulo' + 3), + timestamp '2018-02-19 22:00 America/Sao_Paulo', extract(timezone_hour from timestamp '2018-02-19 22:00 America/Sao_Paulo'), + timestamp '2018-02-19 22:00 America/Sao_Paulo' - 1, extract(timezone_hour from timestamp '2018-02-19 22:00 America/Sao_Paulo' - 1), + timestamp '2018-02-19 22:00 America/Sao_Paulo' - 2, extract(timezone_hour from timestamp '2018-02-19 22:00 America/Sao_Paulo' - 2), + timestamp '2018-02-19 22:00 America/Sao_Paulo' - 3, extract(timezone_hour from timestamp '2018-02-19 22:00 America/Sao_Paulo' - 3) + from rdb$database; + + select dateadd(1 hour to timestamp '2018-02-17 22:00 America/Sao_Paulo'), + dateadd(2 hour to timestamp '2018-02-17 22:00 America/Sao_Paulo'), + dateadd(3 hour to timestamp '2018-02-17 22:00 America/Sao_Paulo'), + dateadd(4 hour to timestamp '2018-02-17 22:00 America/Sao_Paulo') + from rdb$database; + + select dateadd(-1 hour to timestamp '2018-02-18 01:00 America/Sao_Paulo'), + dateadd(-2 hour to timestamp '2018-02-18 01:00 America/Sao_Paulo'), + dateadd(-3 hour to timestamp '2018-02-18 01:00 America/Sao_Paulo'), + dateadd(-4 hour to timestamp '2018-02-18 01:00 America/Sao_Paulo') + from rdb$database; + + + --- + + /* + 28.10.2020: + ... datediff(hour from timestamp '... -03' to timestamp '... -03') + Statement failed, SQLSTATE = 22009 + Invalid time zone offset: -03 - must use format +/-hours:minutes and be between -14:00 and +14:00 + */ + + select datediff(hour from timestamp '2018-04-01 10:00:00' to timestamp '2018-04-01 10:00:00 -03:00'), + datediff(hour from timestamp '2018-04-01 10:00:00 -03:0' to timestamp '2018-04-01 10:00:00 -03:0'), + datediff(hour from timestamp '2018-04-01 10:00:00' to timestamp '2018-04-01 10:00:00 -2:0') + from rdb$database; + + + --- + + + set time zone '-02:20'; + + select cast('01:23:45' as time with time zone), + cast('2018-01-01 01:23:45' as timestamp with time zone), + extract(timezone_hour from cast('01:23:45' as time with time zone)), + extract(timezone_minute from cast('01:23:45' as time with time zone)), + extract(timezone_hour from cast('2018-01-01 01:23:45' as timestamp with time zone)), + extract(timezone_minute from cast('2018-01-01 01:23:45' as timestamp with time zone)), + cast(cast('01:23:45' as time with time zone) as time), + cast(cast('2018-01-01 01:23:45' as timestamp with time zone) as timestamp) + from rdb$database; + + select cast('01:23:45 +02:00' as time with time zone), + cast('2018-01-01 01:23:45 +02:00' as timestamp with time zone), + extract(timezone_hour from cast('01:23:45 +02:00' as time with time zone)), + extract(timezone_minute from cast('01:23:45 +02:00' as time with time zone)), + extract(timezone_hour from cast('2018-01-01 01:23:45 +02:00' as timestamp with time zone)), + extract(timezone_minute from cast('2018-01-01 01:23:45 +02:00' as timestamp with time zone)), + cast(cast('01:23:45 +02:00' as time with time zone) as time), + cast(cast('2018-01-01 01:23:45 +02:00' as timestamp with time zone) as timestamp) + from rdb$database; + + select extract(timezone_hour from time '03:04:05.6789 -03:00'), + extract(timezone_minute from time '03:04:05.6789 -03:00'), + extract(timezone_hour from timestamp '2018-01-01 03:04:05.6789 -03:00'), + extract(timezone_minute from timestamp '2018-01-01 03:04:05.6789 -03:00') + from rdb$database; + + + --- + + + select extract(timezone_hour from cast('now' as timestamp with time zone)) = -2, + extract(timezone_minute from cast('now' as timestamp with time zone)) = -20 + from rdb$database; + + + --- + + + set time zone '-02:00'; + + select cast('01:23:45 -1:0' as time), + cast('01:23:45 +1:0' as time), + cast('2018-01-01 01:23:45 -01:00' as timestamp), + cast('2018-01-01 01:23:45 +01:00' as timestamp) + from rdb$database; + + select cast(cast('01:23:45' as time with time zone) as timestamp with time zone) = cast(current_date || ' 01:23:45' as timestamp with time zone) + from rdb$database; + + select cast(cast('2018-01-01 01:23:45' as timestamp with time zone) as time with time zone) + from rdb$database; + + select cast(cast('2018-01-01 01:23:45 -04:00' as timestamp with time zone) as time with time zone) + from rdb$database; + + select cast(cast('2018-01-01 01:23:45' as timestamp with time zone) as date) + from rdb$database; + + select cast(cast('2018-01-01 01:23:45 -04:00' as timestamp with time zone) as date) + from rdb$database; + + select cast(cast('2018-01-01 01:23:45' as timestamp with time zone) as time) + from rdb$database; + + select cast(cast('2018-01-01 01:23:45 -04:00' as timestamp with time zone) as time) + from rdb$database; + + select cast(cast('2018-01-01 01:23:45' as timestamp with time zone) as timestamp) + from rdb$database; + + select cast(cast('2018-01-01 01:23:45 -04:00' as timestamp with time zone) as timestamp) + from rdb$database; + + select cast(timestamp '2018-01-01 01:23:45' as timestamp with time zone) + from rdb$database; + + select cast(timestamp '2018-01-01 01:23:45' as time with time zone) + from rdb$database; + + select cast(cast('01:23:45' as time) as timestamp with time zone) = cast(cast('01:23:45' as time with time zone) as timestamp with time zone) + from rdb$database; + + select cast(cast('01:23:45' as time) as time with time zone) = '01:23:45 -02:00' + from rdb$database; + + select cast(cast(cast('01:23:45 -03:00' as time with time zone) as timestamp) as time) = '02:23:45' + from rdb$database; + + select cast(cast('01:23:45 -03:00' as time with time zone) as time) = '02:23:45' + from rdb$database; + + -- Error + select cast(cast('01:23:45 -03:00' as time with time zone) as date) + from rdb$database; + + select cast(date '2018-01-01' as timestamp with time zone) + from rdb$database; + + -- Error + select cast(date '2018-01-01' as time with time zone) + from rdb$database; + + + --- + + + select timestamp '2018-02-03 America/Sao_Paulo' + from rdb$database; + + + --- + + + select cast('23:23:34 +05:00' as time with time zone) + 1, + cast('23:23:34 +05:00' as time with time zone) - 1 + from rdb$database; + + select cast('2018-01-01 23:23:34 +05:00' as timestamp with time zone) + 1, + cast('2018-01-01 23:23:34 +05:00' as timestamp with time zone) - 1 + from rdb$database; + + select date '2018-01-01' + cast('23:23:34 +05:00' as time with time zone), + cast('23:23:34 +05:00' as time with time zone) + date '2018-01-01', + date '2018-01-01' + cast('23:23:34 +05:00' as time), + cast('23:23:34 +05:00' as time) + date '2018-01-01' + from rdb$database; + + select cast('12:00:00 +01:00' as time with time zone) - cast('12:00:00 +00:00' as time with time zone), + cast('23:00:00 -01:00' as time with time zone) - cast('23:00:00 +00:00' as time with time zone), + time '12:00:00' - cast('12:00:00 +00:00' as time with time zone), + cast('12:00:00 +00:00' as time with time zone) - time '12:00:00' + from rdb$database; + + select cast('2018-01-01 12:00:00 +01:00' as timestamp with time zone) - cast('2018-01-01 12:00:00 +00:00' as timestamp with time zone), + cast('2018-01-01 23:00:00 -01:00' as timestamp with time zone) - cast('2018-01-01 23:00:00 +00:00' as timestamp with time zone), + timestamp '2018-01-01 12:00:00' - cast('2018-01-01 12:00:00 +00:00' as timestamp with time zone), + cast('2018-01-01 12:00:00 +00:00' as timestamp with time zone) - timestamp '2018-01-01 12:00:00' + from rdb$database; + + + --- + + + select cast('10:00:00 +05:00' as time with time zone) = cast('10:00:00 +05:00' as time with time zone), + cast('10:00:00 +05:00' as time with time zone) = cast('11:00:00 +06:00' as time with time zone), + cast('10:00:00 +12:00' as time with time zone) = cast('10:00:00 -12:00' as time with time zone), + cast('10:00:00 -02:00' as time with time zone) = cast('10:00:00' as time with time zone), + cast('10:00:00 -02:00' as time with time zone) = cast('10:00:00' as time), + cast('10:00:00' as time) = cast('10:00:00 -02:00' as time with time zone), + cast('10:00:00 +05:00' as time with time zone) = cast('10:00:00 +06:00' as time with time zone), + cast('10:00:00 +05:00' as time with time zone) < cast('10:00:00 +06:00' as time with time zone), + cast('10:00:00 +05:00' as time with time zone) > cast('10:00:00 +06:00' as time with time zone), + localtime = current_time at time zone '-02:00' + from rdb$database; + + select cast('2018-01-01 10:00:00 +05:00' as timestamp with time zone) = cast('2018-01-01 10:00:00 +05:00' as timestamp with time zone), + cast('2018-01-01 10:00:00 +05:00' as timestamp with time zone) = cast('2018-01-01 11:00:00 +06:00' as timestamp with time zone), + cast('2018-01-01 10:00:00 +12:00' as timestamp with time zone) = cast('2018-01-01 10:00:00 -12:00' as timestamp with time zone), + cast('2018-01-01 10:00:00 -02:00' as timestamp with time zone) = cast('2018-01-01 10:00:00' as timestamp with time zone), + cast('2018-01-01 10:00:00 -02:00' as timestamp with time zone) = cast('2018-01-01 10:00:00' as timestamp), + cast('2018-01-01 10:00:00' as timestamp) = cast('2018-01-01 10:00:00 -02:00' as timestamp with time zone), + cast('2018-01-01 10:00:00 +05:00' as timestamp with time zone) = cast('2018-01-01 10:00:00 +06:00' as timestamp with time zone), + cast('2018-01-01 10:00:00 +05:00' as timestamp with time zone) < cast('2018-01-01 10:00:00 +06:00' as timestamp with time zone), + cast('2018-01-01 10:00:00 +05:00' as timestamp with time zone) > cast('2018-01-01 10:00:00 +06:00' as timestamp with time zone), + localtimestamp = current_timestamp at time zone '-02:00' + from rdb$database; + + + --- + + + set time zone '-03:00'; + + + select cast(time '10:11:12.1345' as time), + cast(time '10:11:12.1345' as time with time zone), + substring(cast(time '10:11:12.1345' as timestamp) from 12), + substring(cast(time '10:11:12.1345' as timestamp with time zone) from 12) from rdb$database; + + select cast(timestamp '2020-05-20 10:11:12.1345' as time), + cast(timestamp '2020-05-20 10:11:12.1345' as time with time zone), + cast(timestamp '2020-05-20 10:11:12.1345' as timestamp), + cast(timestamp '2020-05-20 10:11:12.1345' as timestamp with time zone) from rdb$database; + + select cast(time '10:11:12.1345 america/sao_paulo' as time), + cast(time '10:11:12.1345 america/sao_paulo' as time with time zone), + substring(cast(time '10:11:12.1345 america/sao_paulo' as timestamp) from 12), + substring(cast(time '10:11:12.1345 america/sao_paulo' as timestamp with time zone) from 12) from rdb$database; + + select cast(timestamp '2020-05-20 10:11:12.1345 america/sao_paulo' as time), + cast(timestamp '2020-05-20 10:11:12.1345 america/sao_paulo' as time with time zone), + cast(timestamp '2020-05-20 10:11:12.1345 america/sao_paulo' as timestamp), + cast(timestamp '2020-05-20 10:11:12.1345 america/sao_paulo' as timestamp with time zone) from rdb$database; + + + --- + + + set time zone '-02:00'; + + + select time '20:01:02 -05:00' at time zone '-05:00', + time '20:01:02 -05:00' at time zone '-02:00', + time '20:01:02 -05:00' at time zone '+03:00', + time '20:01:02' at time zone '-05:00', + time '20:01:02' at time zone '-02:00', + time '20:01:02' at time zone '+03:00', + time '20:01:02 -05:00' at local, + time '20:01:02' at local + from rdb$database; + + select timestamp '2018-01-01 20:01:02 -05:00' at time zone '-05:00', + timestamp '2018-01-01 20:01:02 -05:00' at time zone '-02:00', + timestamp '2018-01-01 20:01:02 -05:00' at time zone '+03:00', + timestamp '2018-01-01 20:01:02' at time zone '-05:00', + timestamp '2018-01-01 20:01:02' at time zone '-02:00', + timestamp '2018-01-01 20:01:02' at time zone '+03:00', + timestamp '2018-01-01 20:01:02 -05:00' at local, + timestamp '2018-01-01 20:01:02' at local + from rdb$database; + + + --- + + + select timestamp '2018-05-01 20:01:02 America/Sao_Paulo' at time zone 'America/Los_Angeles', + timestamp '2018-04-01 20:01:02 America/Sao_Paulo' at time zone 'America/Los_Angeles', + timestamp '2018-03-01 20:01:02 America/Sao_Paulo' at time zone 'America/Los_Angeles', + timestamp '2018-02-01 20:01:02 America/Sao_Paulo' at time zone 'America/Los_Angeles', + timestamp '2018-01-01 20:01:02 America/Sao_Paulo' at time zone 'America/Los_Angeles', + timestamp '2018-01-01 20:01:02 America/Sao_Paulo' at time zone 'America/Los_Angeles' + 1, + 1 + timestamp '2018-01-01 20:01:02 America/Sao_Paulo' at time zone 'America/Los_Angeles', + 1 + timestamp '2018-01-01 20:01:02 America/Sao_Paulo' at time zone 'America/Los_Angeles' + 1 + from rdb$database; + + + --- + + + select first_day(of year from timestamp '2018-03-08 10:11:12 America/Sao_Paulo'), + first_day(of month from timestamp '2018-03-08 10:11:12 America/Sao_Paulo'), + first_day(of week from timestamp '2018-03-08 10:11:12 America/Sao_Paulo'), + last_day(of year from timestamp '2018-03-08 10:11:12 America/Sao_Paulo'), + last_day(of month from timestamp '2018-03-08 10:11:12 America/Sao_Paulo'), + last_day(of week from timestamp '2018-03-08 10:11:12 America/Sao_Paulo') + from rdb$database; + + + --- + + + select timestamp '2017-03-12 02:30 America/New_York' t1, + timestamp '2017-03-12 02:30 America/New_York' at time zone '-05:00' t2, + dateadd(-1 minute to timestamp '2017-03-12 02:30 America/New_York') t3, + dateadd(1 minute to timestamp '2017-03-12 02:30 America/New_York') t4, + dateadd(-1 hour to timestamp '2017-03-12 02:30 America/New_York') t5, + dateadd(1 hour to timestamp '2017-03-12 02:30 America/New_York') t6 + from rdb$database; + + select timestamp '2017-11-05 01:30 America/New_York' t1, + timestamp '2017-11-05 01:30 America/New_York' at time zone '-04:00' t2, + dateadd(-1 minute to timestamp '2017-11-05 01:30 America/New_York') t3, + dateadd(1 minute to timestamp '2017-11-05 01:30 America/New_York') t4, + dateadd(-1 hour to timestamp '2017-11-05 01:30 America/New_York') t5, + dateadd(1 hour to timestamp '2017-11-05 01:30 America/New_York') t6 + from rdb$database; + + + --- + + + set bind of timestamp with time zone to legacy; + set bind of time with time zone to legacy; + set sqlda_display on; + + select timestamp '2018-05-01 20:01:02 America/Sao_Paulo', + dateadd(extract(timezone_hour from time '20:01:02 America/Sao_Paulo') + 3 hour to time '20:01:02 America/Sao_Paulo') + from rdb$database; + + /* + disabled; strange dependency of error message on previous statement; sent letter to dimitr etc, 28.10.2020 09:10 + select 1 + from rdb$database + where current_timestamp = ? and + current_time = ?; + */ + + set sqlda_display off; + set bind of timestamp with time zone to native; + set bind of time with time zone to native; + + + + --- + + + create table timetz (n integer, v time with time zone); + create unique index timetz_uk on timetz (v); + + insert into timetz values (0, '11:33:33 America/Sao_Paulo'); + insert into timetz values (1, '11:33:33.456'); + insert into timetz values (2, '11:33:33.456 -1:0'); + insert into timetz values (3, '11:33:33.456 +1:0'); + insert into timetz values (4, '11:33:33'); + insert into timetz values (5, '11:33:33 -1:0'); + insert into timetz values (6, '11:33:33 +1:0'); + + -- Duplicate in UTC. + insert into timetz values (7, '12:33:33 +0:0'); + insert into timetz values (8, '13:33:33 +1:0'); + insert into timetz values (9, '14:33:33 +2:0'); + insert into timetz values (10, '11:33:33 -03:00'); + + select n, v, cast(v as time) from timetz order by v, n; + + select n, v from timetz order by v + 0, n; + + commit; + drop index timetz_uk; + create index timetz_idx on timetz (v); + + -- Duplicate in UTC. + insert into timetz values (7, '12:33:33 +0:0'); + insert into timetz values (8, '13:33:33 +1:0'); + insert into timetz values (9, '14:33:33 +2:0'); + + select n, v, cast(v as time) from timetz order by cast(v as time), n; + select n, v, cast(v as time) from timetz order by v, n; + + select n, v from timetz order by v + 0, n; + + commit; + drop index timetz_idx; + + select n, v, cast(v as time) from timetz order by v, n; + + delete from timetz; + insert into timetz values (1, '11:33:33.456'); + + + --- + + + create table timestamptz (n integer, v timestamp with time zone); + create unique index timestamptz_uk on timestamptz (v); + + insert into timestamptz values (1, '2018-01-01 11:33:33.456'); + insert into timestamptz values (2, '2018-01-01 11:33:33.456 -1:0'); + insert into timestamptz values (3, '2018-01-01 11:33:33.456 +1:0'); + insert into timestamptz values (4, '2018-01-01 11:33:33'); + insert into timestamptz values (5, '2018-01-01 11:33:33 -1:0'); + insert into timestamptz values (6, '2018-01-01 11:33:33 +1:0'); + + -- Duplicate in UTC. + insert into timestamptz values (7, '2018-01-01 12:33:33 +0:0'); + insert into timestamptz values (8, '2018-01-01 13:33:33 +1:0'); + insert into timestamptz values (9, '2018-01-01 14:33:33 +2:0'); + + select n, v, cast(v as timestamp) from timestamptz order by v, n; + + select n, v from timestamptz order by v + 0, n; + + commit; + drop index timestamptz_uk; + create index timestamptz_idx on timestamptz (v); + + -- Duplicate in UTC. + insert into timestamptz values (7, '2018-01-01 12:33:33 +0:0'); + insert into timestamptz values (8, '2018-01-01 13:33:33 +1:0'); + insert into timestamptz values (9, '2018-01-01 14:33:33 +2:0'); + + select n, v, cast(v as timestamp) from timestamptz order by cast(v as timestamp), n; + select n, v, cast(v as timestamp) from timestamptz order by v, n; + + select n, v from timestamptz order by v + 0, n; + + commit; + drop index timestamptz_idx; + + select n, v, cast(v as timestamp) from timestamptz order by v, n; + + delete from timestamptz; + insert into timestamptz values (1, '2018-01-01 11:33:33.456'); + + + --- + + + select t.*, + extract(timezone_hour from rdb$start_timestamp at time zone 'America/Los_Angeles') start_tzh, + extract(timezone_minute from rdb$start_timestamp at time zone 'America/Los_Angeles') start_tzm, + extract(timezone_hour from rdb$end_timestamp at time zone 'America/Los_Angeles') end_tzh, + extract(timezone_minute from rdb$end_timestamp at time zone 'America/Los_Angeles') end_tzm + from rdb$time_zone_util.transitions( + 'America/Los_Angeles', + timestamp '2015-01-01 GMT', + timestamp '2019-01-01 GMT') t; + + + /******************************* + --- + exit; + >> fb_sql_time_zone_b.sql + connect "WHERE_GDB:time_zone.fdb"; + --- + /******************************* + + select * from timetz; + select * from timestamptz; + + --- + + set term ^; + + set time zone 'America/Sao_Paulo'^ + + select substring(current_timestamp from 26) from rdb$database^ + + execute block returns (t1 varchar(30), t2 varchar(30)) + as + declare procedure p0 returns (t1 varchar(30), t2 varchar(30)) + as + begin + set time zone 'America/New_York'; + t1 = substring(current_timestamp from 26); + set time zone local; + t2 = substring(current_timestamp from 26); + end + + declare procedure p1 returns (t1 varchar(30), t2 varchar(30)) + as + begin + set time zone 'America/Los_Angeles'; + + execute procedure p0 returning_values t1, t2; + end + begin + execute procedure p1 returning_values t1, t2; + suspend; + end^ + + select substring(current_timestamp from 26) from rdb$database^ + + + set time zone 'America/Sao_Paulo'^ + + execute block returns (n integer, t1 varchar(30), t2 varchar(30), t3 varchar(30)) + as + declare procedure p1 returns (n integer, t1 varchar(30), t2 varchar(30), t3 varchar(30)) + as + begin + n = 0; + + while (n <= 4) + do + begin + t1 = substring(current_timestamp from 26); + set time zone 'America/Los_Angeles'; + t2 = substring(current_timestamp from 26); + if (n <= 2) then + set time zone local; + t3 = substring(current_timestamp from 26); + suspend; + + n = n + 1; + end + end + begin + for select n, t1, t2, t3 from p1 into n, t1, t2, t3 + do + begin + suspend; + end + end^ + + + set time zone 'America/Sao_Paulo'^ + + create table t1 (n integer, tz1 varchar(30), tz2 varchar(30), tz3 varchar(30))^ + + create trigger t1_bi before insert on t1 + as + begin + new.tz1 = substring(current_timestamp from 26); + set time zone 'America/New_York'; + new.tz2 = substring(current_timestamp from 26); + set time zone local; + new.tz3 = substring(current_timestamp from 26); + end^ + + insert into t1 (n) values (1)^ + select * from t1^ + + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CAST 01:23:45.0000 +00:00 + CAST 2018-01-01 01:23:45.0000 +00:00 + EXTRACT 0 + EXTRACT 0 + EXTRACT 0 + EXTRACT 0 + CAST 01:23:45.0000 + CAST 2018-01-01 01:23:45.0000 + CAST 01:23:45.0000 +02:00 + CAST 2018-01-01 01:23:45.0000 +02:00 + EXTRACT 2 + EXTRACT 0 + EXTRACT 2 + EXTRACT 0 + CAST 23:23:45.0000 + CAST 2017-12-31 23:23:45.0000 + CONSTANT 01:23:45.0000 +02:00 + CONSTANT 2018-01-01 01:23:45.0000 +02:00 + EXTRACT 2 + EXTRACT 0 + EXTRACT 2 + EXTRACT 0 + CAST 23:23:45.0000 + CAST 2017-12-31 23:23:45.0000 + CAST 01:23:45.0000 -02:00 + CAST 2018-01-01 01:23:45.0000 -02:00 + EXTRACT -2 + EXTRACT 0 + EXTRACT -2 + EXTRACT 0 + CAST 01:23:45.0000 + CAST 2018-01-01 01:23:45.0000 + CAST 01:23:45.0000 +02:00 + CAST 2018-01-01 01:23:45.0000 +02:00 + EXTRACT 2 + EXTRACT 0 + EXTRACT 2 + EXTRACT 0 + CAST 21:23:45.0000 + CAST 2017-12-31 21:23:45.0000 + EXTRACT 3 + EXTRACT 4 + EXTRACT 5.6789 + EXTRACT 678.9 + EXTRACT 2018 + EXTRACT 1 + EXTRACT 2 + EXTRACT 3 + EXTRACT 4 + EXTRACT 5.6789 + EXTRACT 678.9 + CONSTANT 2017-10-14 22:00:00.0000 America/Sao_Paulo + EXTRACT -3 + ADD 2017-10-15 23:00:00.0000 America/Sao_Paulo + EXTRACT -2 + ADD 2017-10-16 23:00:00.0000 America/Sao_Paulo + EXTRACT -2 + ADD 2017-10-17 23:00:00.0000 America/Sao_Paulo + EXTRACT -2 + CONSTANT 2017-10-16 22:00:00.0000 America/Sao_Paulo + EXTRACT -2 + SUBTRACT 2017-10-15 22:00:00.0000 America/Sao_Paulo + EXTRACT -2 + SUBTRACT 2017-10-14 21:00:00.0000 America/Sao_Paulo + EXTRACT -3 + SUBTRACT 2017-10-13 21:00:00.0000 America/Sao_Paulo + EXTRACT -3 + DATEADD 2017-10-14 21:00:00.0000 America/Sao_Paulo + DATEADD 2017-10-14 22:00:00.0000 America/Sao_Paulo + DATEADD 2017-10-14 23:00:00.0000 America/Sao_Paulo + DATEADD 2017-10-15 01:00:00.0000 America/Sao_Paulo + DATEADD 2017-10-15 02:00:00.0000 America/Sao_Paulo + CONSTANT 2018-02-17 22:00:00.0000 America/Sao_Paulo + EXTRACT -2 + ADD 2018-02-18 21:00:00.0000 America/Sao_Paulo + EXTRACT -3 + ADD 2018-02-19 21:00:00.0000 America/Sao_Paulo + EXTRACT -3 + ADD 2018-02-20 21:00:00.0000 America/Sao_Paulo + EXTRACT -3 + CONSTANT 2018-02-19 22:00:00.0000 America/Sao_Paulo + EXTRACT -3 + SUBTRACT 2018-02-18 22:00:00.0000 America/Sao_Paulo + EXTRACT -3 + SUBTRACT 2018-02-17 23:00:00.0000 America/Sao_Paulo + EXTRACT -2 + SUBTRACT 2018-02-16 23:00:00.0000 America/Sao_Paulo + EXTRACT -2 + DATEADD 2018-02-17 23:00:00.0000 America/Sao_Paulo + DATEADD 2018-02-17 23:00:00.0000 America/Sao_Paulo + DATEADD 2018-02-18 00:00:00.0000 America/Sao_Paulo + DATEADD 2018-02-18 01:00:00.0000 America/Sao_Paulo + DATEADD 2018-02-18 00:00:00.0000 America/Sao_Paulo + DATEADD 2018-02-17 23:00:00.0000 America/Sao_Paulo + DATEADD 2018-02-17 23:00:00.0000 America/Sao_Paulo + DATEADD 2018-02-17 22:00:00.0000 America/Sao_Paulo + DATEDIFF 1 + DATEDIFF 0 + DATEDIFF 0 + CAST 01:23:45.0000 -02:20 + CAST 2018-01-01 01:23:45.0000 -02:20 + EXTRACT -2 + EXTRACT -20 + EXTRACT -2 + EXTRACT -20 + CAST 01:23:45.0000 + CAST 2018-01-01 01:23:45.0000 + CAST 01:23:45.0000 +02:00 + CAST 2018-01-01 01:23:45.0000 +02:00 + EXTRACT 2 + EXTRACT 0 + EXTRACT 2 + EXTRACT 0 + CAST 21:03:45.0000 + CAST 2017-12-31 21:03:45.0000 + EXTRACT -3 + EXTRACT 0 + EXTRACT -3 + EXTRACT 0 + + + CAST 00:23:45.0000 + CAST 22:23:45.0000 + CAST 2018-01-01 00:23:45.0000 + CAST 2017-12-31 22:23:45.0000 + + CAST 01:23:45.0000 -02:00 + CAST 01:23:45.0000 -04:00 + CAST 2018-01-01 + CAST 2018-01-01 + CAST 01:23:45.0000 + CAST 03:23:45.0000 + CAST 2018-01-01 01:23:45.0000 + CAST 2018-01-01 03:23:45.0000 + CAST 2018-01-01 01:23:45.0000 -02:00 + CAST 01:23:45.0000 -02:00 + + + + + CAST 2018-01-01 00:00:00.0000 -02:00 + CONSTANT 2018-02-03 00:00:00.0000 America/Sao_Paulo + ADD 23:23:35.0000 +05:00 + SUBTRACT 23:23:33.0000 +05:00 + ADD 2018-01-02 23:23:34.0000 +05:00 + SUBTRACT 2017-12-31 23:23:34.0000 +05:00 + ADD 2018-01-01 23:23:34.0000 +05:00 + ADD 2018-01-01 23:23:34.0000 +05:00 + ADD 2018-01-01 16:23:34.0000 + ADD 2018-01-01 16:23:34.0000 + SUBTRACT -3600.0000 + SUBTRACT -82800.0000 + SUBTRACT 7200.0000 + SUBTRACT -7200.0000 + SUBTRACT -0.041666667 + SUBTRACT 0.041666667 + SUBTRACT 0.083333333 + SUBTRACT -0.083333333 + + + + + + + + + + + + + + + + + + + + + CAST 10:11:12.1345 + CAST 10:11:12.1345 -03:00 + SUBSTRING 10:11:12.1345 + SUBSTRING 10:11:12.1345 -03:00 + CAST 10:11:12.1345 + CAST 10:11:12.1345 -03:00 + CAST 2020-05-20 10:11:12.1345 + CAST 2020-05-20 10:11:12.1345 -03:00 + CAST 10:11:12.1345 + CAST 10:11:12.1345 America/Sao_Paulo + SUBSTRING 10:11:12.1345 + SUBSTRING 10:11:12.1345 America/Sao_Paulo + CAST 10:11:12.1345 + CAST 10:11:12.1345 America/Sao_Paulo + CAST 2020-05-20 10:11:12.1345 + CAST 2020-05-20 10:11:12.1345 America/Sao_Paulo + AT 20:01:02.0000 -05:00 + AT 23:01:02.0000 -02:00 + AT 04:01:02.0000 +03:00 + AT 17:01:02.0000 -05:00 + AT 20:01:02.0000 -02:00 + AT 01:01:02.0000 +03:00 + AT 23:01:02.0000 -02:00 + AT 20:01:02.0000 -02:00 + AT 2018-01-01 20:01:02.0000 -05:00 + AT 2018-01-01 23:01:02.0000 -02:00 + AT 2018-01-02 04:01:02.0000 +03:00 + AT 2018-01-01 17:01:02.0000 -05:00 + AT 2018-01-01 20:01:02.0000 -02:00 + AT 2018-01-02 01:01:02.0000 +03:00 + AT 2018-01-01 23:01:02.0000 -02:00 + AT 2018-01-01 20:01:02.0000 -02:00 + AT 2018-05-01 16:01:02.0000 America/Los_Angeles + AT 2018-04-01 16:01:02.0000 America/Los_Angeles + AT 2018-03-01 15:01:02.0000 America/Los_Angeles + AT 2018-02-01 14:01:02.0000 America/Los_Angeles + AT 2018-01-01 14:01:02.0000 America/Los_Angeles + ADD 2018-01-02 14:01:02.0000 America/Los_Angeles + ADD 2018-01-02 14:01:02.0000 America/Los_Angeles + ADD 2018-01-03 14:01:02.0000 America/Los_Angeles + FIRST_DAY 2018-01-01 10:11:12.0000 America/Sao_Paulo + FIRST_DAY 2018-03-01 10:11:12.0000 America/Sao_Paulo + FIRST_DAY 2018-03-04 10:11:12.0000 America/Sao_Paulo + LAST_DAY 2018-12-31 10:11:12.0000 America/Sao_Paulo + LAST_DAY 2018-03-31 10:11:12.0000 America/Sao_Paulo + LAST_DAY 2018-03-10 10:11:12.0000 America/Sao_Paulo + T1 2017-03-12 03:30:00.0000 America/New_York + T2 2017-03-12 02:30:00.0000 -05:00 + T3 2017-03-12 03:29:00.0000 America/New_York + T4 2017-03-12 03:31:00.0000 America/New_York + T5 2017-03-12 01:30:00.0000 America/New_York + T6 2017-03-12 04:30:00.0000 America/New_York + T1 2017-11-05 01:30:00.0000 America/New_York + T2 2017-11-05 01:30:00.0000 -04:00 + T3 2017-11-05 01:29:00.0000 America/New_York + T4 2017-11-05 01:31:00.0000 America/New_York + T5 2017-11-05 00:30:00.0000 America/New_York + T6 2017-11-05 01:30:00.0000 America/New_York + INPUT message field count: 0 + OUTPUT message field count: 2 + 01: sqltype: 510 TIMESTAMP scale: 0 subtype: 0 len: 8 + : name: CONSTANT alias: CONSTANT + : table: owner: + 02: sqltype: 560 TIME scale: 0 subtype: 0 len: 4 + : name: DATEADD alias: DATEADD + : table: owner: + CONSTANT 2018-05-01 21:01:02.0000 + DATEADD 21:01:02.0000 + N 6 + V 11:33:33.0000 +01:00 + CAST 08:33:33.0000 + N 3 + V 11:33:33.4560 +01:00 + CAST 08:33:33.4560 + N 5 + V 11:33:33.0000 -01:00 + CAST 10:33:33.0000 + N 2 + V 11:33:33.4560 -01:00 + CAST 10:33:33.4560 + N 4 + V 11:33:33.0000 -02:00 + CAST 11:33:33.0000 + N 1 + V 11:33:33.4560 -02:00 + CAST 11:33:33.4560 + N 0 + V 11:33:33.0000 America/Sao_Paulo + CAST 12:33:33.0000 + N 6 + V 11:33:33.0000 +01:00 + N 3 + V 11:33:33.4560 +01:00 + N 5 + V 11:33:33.0000 -01:00 + N 2 + V 11:33:33.4560 -01:00 + N 4 + V 11:33:33.0000 -02:00 + N 1 + V 11:33:33.4560 -02:00 + N 0 + V 11:33:33.0000 America/Sao_Paulo + N 6 + V 11:33:33.0000 +01:00 + CAST 08:33:33.0000 + N 3 + V 11:33:33.4560 +01:00 + CAST 08:33:33.4560 + N 5 + V 11:33:33.0000 -01:00 + CAST 10:33:33.0000 + N 7 + V 12:33:33.0000 +00:00 + CAST 10:33:33.0000 + N 8 + V 13:33:33.0000 +01:00 + CAST 10:33:33.0000 + N 9 + V 14:33:33.0000 +02:00 + CAST 10:33:33.0000 + N 2 + V 11:33:33.4560 -01:00 + CAST 10:33:33.4560 + N 4 + V 11:33:33.0000 -02:00 + CAST 11:33:33.0000 + N 1 + V 11:33:33.4560 -02:00 + CAST 11:33:33.4560 + N 0 + V 11:33:33.0000 America/Sao_Paulo + CAST 12:33:33.0000 + N 6 + V 11:33:33.0000 +01:00 + CAST 08:33:33.0000 + N 3 + V 11:33:33.4560 +01:00 + CAST 08:33:33.4560 + N 5 + V 11:33:33.0000 -01:00 + CAST 10:33:33.0000 + N 7 + V 12:33:33.0000 +00:00 + CAST 10:33:33.0000 + N 8 + V 13:33:33.0000 +01:00 + CAST 10:33:33.0000 + N 9 + V 14:33:33.0000 +02:00 + CAST 10:33:33.0000 + N 2 + V 11:33:33.4560 -01:00 + CAST 10:33:33.4560 + N 4 + V 11:33:33.0000 -02:00 + CAST 11:33:33.0000 + N 1 + V 11:33:33.4560 -02:00 + CAST 11:33:33.4560 + N 0 + V 11:33:33.0000 America/Sao_Paulo + CAST 12:33:33.0000 + N 6 + V 11:33:33.0000 +01:00 + N 3 + V 11:33:33.4560 +01:00 + N 5 + V 11:33:33.0000 -01:00 + N 7 + V 12:33:33.0000 +00:00 + N 8 + V 13:33:33.0000 +01:00 + N 9 + V 14:33:33.0000 +02:00 + N 2 + V 11:33:33.4560 -01:00 + N 4 + V 11:33:33.0000 -02:00 + N 1 + V 11:33:33.4560 -02:00 + N 0 + V 11:33:33.0000 America/Sao_Paulo + N 6 + V 11:33:33.0000 +01:00 + CAST 08:33:33.0000 + N 3 + V 11:33:33.4560 +01:00 + CAST 08:33:33.4560 + N 5 + V 11:33:33.0000 -01:00 + CAST 10:33:33.0000 + N 7 + V 12:33:33.0000 +00:00 + CAST 10:33:33.0000 + N 8 + V 13:33:33.0000 +01:00 + CAST 10:33:33.0000 + N 9 + V 14:33:33.0000 +02:00 + CAST 10:33:33.0000 + N 2 + V 11:33:33.4560 -01:00 + CAST 10:33:33.4560 + N 4 + V 11:33:33.0000 -02:00 + CAST 11:33:33.0000 + N 1 + V 11:33:33.4560 -02:00 + CAST 11:33:33.4560 + N 0 + V 11:33:33.0000 America/Sao_Paulo + CAST 12:33:33.0000 + N 6 + V 2018-01-01 11:33:33.0000 +01:00 + CAST 2018-01-01 08:33:33.0000 + N 3 + V 2018-01-01 11:33:33.4560 +01:00 + CAST 2018-01-01 08:33:33.4560 + N 5 + V 2018-01-01 11:33:33.0000 -01:00 + CAST 2018-01-01 10:33:33.0000 + N 2 + V 2018-01-01 11:33:33.4560 -01:00 + CAST 2018-01-01 10:33:33.4560 + N 4 + V 2018-01-01 11:33:33.0000 -02:00 + CAST 2018-01-01 11:33:33.0000 + N 1 + V 2018-01-01 11:33:33.4560 -02:00 + CAST 2018-01-01 11:33:33.4560 + N 6 + V 2018-01-01 11:33:33.0000 +01:00 + N 3 + V 2018-01-01 11:33:33.4560 +01:00 + N 5 + V 2018-01-01 11:33:33.0000 -01:00 + N 2 + V 2018-01-01 11:33:33.4560 -01:00 + N 4 + V 2018-01-01 11:33:33.0000 -02:00 + N 1 + V 2018-01-01 11:33:33.4560 -02:00 + N 6 + V 2018-01-01 11:33:33.0000 +01:00 + CAST 2018-01-01 08:33:33.0000 + N 3 + V 2018-01-01 11:33:33.4560 +01:00 + CAST 2018-01-01 08:33:33.4560 + N 5 + V 2018-01-01 11:33:33.0000 -01:00 + CAST 2018-01-01 10:33:33.0000 + N 7 + V 2018-01-01 12:33:33.0000 +00:00 + CAST 2018-01-01 10:33:33.0000 + N 8 + V 2018-01-01 13:33:33.0000 +01:00 + CAST 2018-01-01 10:33:33.0000 + N 9 + V 2018-01-01 14:33:33.0000 +02:00 + CAST 2018-01-01 10:33:33.0000 + N 2 + V 2018-01-01 11:33:33.4560 -01:00 + CAST 2018-01-01 10:33:33.4560 + N 4 + V 2018-01-01 11:33:33.0000 -02:00 + CAST 2018-01-01 11:33:33.0000 + N 1 + V 2018-01-01 11:33:33.4560 -02:00 + CAST 2018-01-01 11:33:33.4560 + N 6 + V 2018-01-01 11:33:33.0000 +01:00 + CAST 2018-01-01 08:33:33.0000 + N 3 + V 2018-01-01 11:33:33.4560 +01:00 + CAST 2018-01-01 08:33:33.4560 + N 5 + V 2018-01-01 11:33:33.0000 -01:00 + CAST 2018-01-01 10:33:33.0000 + N 7 + V 2018-01-01 12:33:33.0000 +00:00 + CAST 2018-01-01 10:33:33.0000 + N 8 + V 2018-01-01 13:33:33.0000 +01:00 + CAST 2018-01-01 10:33:33.0000 + N 9 + V 2018-01-01 14:33:33.0000 +02:00 + CAST 2018-01-01 10:33:33.0000 + N 2 + V 2018-01-01 11:33:33.4560 -01:00 + CAST 2018-01-01 10:33:33.4560 + N 4 + V 2018-01-01 11:33:33.0000 -02:00 + CAST 2018-01-01 11:33:33.0000 + N 1 + V 2018-01-01 11:33:33.4560 -02:00 + CAST 2018-01-01 11:33:33.4560 + N 6 + V 2018-01-01 11:33:33.0000 +01:00 + N 3 + V 2018-01-01 11:33:33.4560 +01:00 + N 5 + V 2018-01-01 11:33:33.0000 -01:00 + N 7 + V 2018-01-01 12:33:33.0000 +00:00 + N 8 + V 2018-01-01 13:33:33.0000 +01:00 + N 9 + V 2018-01-01 14:33:33.0000 +02:00 + N 2 + V 2018-01-01 11:33:33.4560 -01:00 + N 4 + V 2018-01-01 11:33:33.0000 -02:00 + N 1 + V 2018-01-01 11:33:33.4560 -02:00 + N 6 + V 2018-01-01 11:33:33.0000 +01:00 + CAST 2018-01-01 08:33:33.0000 + N 3 + V 2018-01-01 11:33:33.4560 +01:00 + CAST 2018-01-01 08:33:33.4560 + N 5 + V 2018-01-01 11:33:33.0000 -01:00 + CAST 2018-01-01 10:33:33.0000 + N 7 + V 2018-01-01 12:33:33.0000 +00:00 + CAST 2018-01-01 10:33:33.0000 + N 8 + V 2018-01-01 13:33:33.0000 +01:00 + CAST 2018-01-01 10:33:33.0000 + N 9 + V 2018-01-01 14:33:33.0000 +02:00 + CAST 2018-01-01 10:33:33.0000 + N 2 + V 2018-01-01 11:33:33.4560 -01:00 + CAST 2018-01-01 10:33:33.4560 + N 4 + V 2018-01-01 11:33:33.0000 -02:00 + CAST 2018-01-01 11:33:33.0000 + N 1 + V 2018-01-01 11:33:33.4560 -02:00 + CAST 2018-01-01 11:33:33.4560 + RDB$START_TIMESTAMP 2014-11-02 09:00:00.0000 GMT + RDB$END_TIMESTAMP 2015-03-08 09:59:59.9999 GMT + RDB$ZONE_OFFSET -480 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET -480 + START_TZH -8 + START_TZM 0 + END_TZH -8 + END_TZM 0 + RDB$START_TIMESTAMP 2015-03-08 10:00:00.0000 GMT + RDB$END_TIMESTAMP 2015-11-01 08:59:59.9999 GMT + RDB$ZONE_OFFSET -480 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET -420 + START_TZH -7 + START_TZM 0 + END_TZH -7 + END_TZM 0 + RDB$START_TIMESTAMP 2015-11-01 09:00:00.0000 GMT + RDB$END_TIMESTAMP 2016-03-13 09:59:59.9999 GMT + RDB$ZONE_OFFSET -480 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET -480 + START_TZH -8 + START_TZM 0 + END_TZH -8 + END_TZM 0 + RDB$START_TIMESTAMP 2016-03-13 10:00:00.0000 GMT + RDB$END_TIMESTAMP 2016-11-06 08:59:59.9999 GMT + RDB$ZONE_OFFSET -480 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET -420 + START_TZH -7 + START_TZM 0 + END_TZH -7 + END_TZM 0 + RDB$START_TIMESTAMP 2016-11-06 09:00:00.0000 GMT + RDB$END_TIMESTAMP 2017-03-12 09:59:59.9999 GMT + RDB$ZONE_OFFSET -480 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET -480 + START_TZH -8 + START_TZM 0 + END_TZH -8 + END_TZM 0 + RDB$START_TIMESTAMP 2017-03-12 10:00:00.0000 GMT + RDB$END_TIMESTAMP 2017-11-05 08:59:59.9999 GMT + RDB$ZONE_OFFSET -480 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET -420 + START_TZH -7 + START_TZM 0 + END_TZH -7 + END_TZM 0 + RDB$START_TIMESTAMP 2017-11-05 09:00:00.0000 GMT + RDB$END_TIMESTAMP 2018-03-11 09:59:59.9999 GMT + RDB$ZONE_OFFSET -480 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET -480 + START_TZH -8 + START_TZM 0 + END_TZH -8 + END_TZM 0 + RDB$START_TIMESTAMP 2018-03-11 10:00:00.0000 GMT + RDB$END_TIMESTAMP 2018-11-04 08:59:59.9999 GMT + RDB$ZONE_OFFSET -480 + RDB$DST_OFFSET 60 + RDB$EFFECTIVE_OFFSET -420 + START_TZH -7 + START_TZM 0 + END_TZH -7 + END_TZM 0 + RDB$START_TIMESTAMP 2018-11-04 09:00:00.0000 GMT + RDB$END_TIMESTAMP 2019-03-10 09:59:59.9999 GMT + RDB$ZONE_OFFSET -480 + RDB$DST_OFFSET 0 + RDB$EFFECTIVE_OFFSET -480 + START_TZH -8 + START_TZM 0 + END_TZH -8 + END_TZM 0 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22018 + conversion error from string "01:23:45.0000 -03:00" + Statement failed, SQLSTATE = 22018 + conversion error from string "2018-01-01" + Statement failed, SQLSTATE = 23000 + attempt to store duplicate value (visible to active transactions) in unique index "TIMETZ_UK" + -Problematic key value is ("V" = '12:33:33.0000 +00:00') + Statement failed, SQLSTATE = 23000 + attempt to store duplicate value (visible to active transactions) in unique index "TIMETZ_UK" + -Problematic key value is ("V" = '13:33:33.0000 +01:00') + Statement failed, SQLSTATE = 23000 + attempt to store duplicate value (visible to active transactions) in unique index "TIMETZ_UK" + -Problematic key value is ("V" = '14:33:33.0000 +02:00') + Statement failed, SQLSTATE = 23000 + attempt to store duplicate value (visible to active transactions) in unique index "TIMETZ_UK" + -Problematic key value is ("V" = '11:33:33.0000 -03:00') + Statement failed, SQLSTATE = 23000 + attempt to store duplicate value (visible to active transactions) in unique index "TIMESTAMPTZ_UK" + -Problematic key value is ("V" = '2018-01-01 12:33:33.0000 +00:00') + Statement failed, SQLSTATE = 23000 + attempt to store duplicate value (visible to active transactions) in unique index "TIMESTAMPTZ_UK" + -Problematic key value is ("V" = '2018-01-01 13:33:33.0000 +01:00') + Statement failed, SQLSTATE = 23000 + attempt to store duplicate value (visible to active transactions) in unique index "TIMESTAMPTZ_UK" + -Problematic key value is ("V" = '2018-01-01 14:33:33.0000 +02:00') + """ + +@pytest.mark.version('>=4.0') +def test_time_zone_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/gtcs/test_transactions_autocommit_1.py b/tests/functional/gtcs/test_transactions_autocommit_1.py new file mode 100644 index 00000000..f0e96c0e --- /dev/null +++ b/tests/functional/gtcs/test_transactions_autocommit_1.py @@ -0,0 +1,172 @@ +#coding:utf-8 +# +# id: functional.gtcs.transactions_autocommit_1 +# title: GTCS/tests/AUTO_COMMIT.1.ESQL. AUTO COMMIT must preserve changes that were made by all DML even if ROLLBACK is issued. +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/AUTO_COMMIT.1.ESQL.script +# +# Test creates three tables (test_1, test_2 and test_3) and AI-trigger for one of them (test_1). +# This trigger does INSERTs into test_2 and test_3. +# +# Then we add record into test_1 and after this INSERT its trigger add records into test_2 and test_3. +# After this we make transaction ROLLED BACK and check how many records are preserved. +# Expected result: each of three tables must have one record in itself, i.e. result looks like we did COMMIT rather than ROLLBACK. +# +# NB: we use custom TPB with fdb.isc_tpb_autocommit in order to start DML transactions in AUTOCOMMIT=1 mode. +# Checked on: +# 4.0.0.1812 SS: 2.344s. +# 4.0.0.1767 SC: 2.339s. +# 4.0.0.1810 SS: 2.151s. +# 3.0.6.33273 SS: 1.023s. +# 3.0.6.33240 SC: 1.301s. +# 3.0.6.33247 CS: 2.598s. +# 2.5.6.27020 SS: 3.156s. +# 2.5.9.27149 SC: 0.323s. +# 2.5.9.27143 CS: 1.159s. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# import inspect +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql_init=''' +# set bail on; +# recreate table test_1 (x integer); +# recreate table test_2 (x integer); +# recreate table test_3 (x integer); +# commit; +# set term ^; +# create or alter trigger trg_test1_ai for test_1 active after insert position 0 as +# begin +# insert into test_2 values (new.x * 7); +# insert into test_3 values (new.x * 777); +# end ^ +# set term ;^ +# commit; +# ''' +# +# f_init_sql = open( os.path.join(context['temp_directory'],'tmp_gtcs_tx_ac2.sql'), 'w', buffering = 0) +# f_init_sql.write( sql_init ) +# flush_and_close( f_init_sql ) +# +# f_init_log = open( '.'.join( (os.path.splitext( f_init_sql.name )[0], 'log') ), 'w', buffering = 0) +# f_init_err = open( '.'.join( (os.path.splitext( f_init_sql.name )[0], 'err') ), 'w', buffering = 0) +# +# subprocess.call( [ context['isql_path'], dsn, '-q', '-i', f_init_sql.name ], stdout = f_init_log, stderr = f_init_err) +# +# flush_and_close( f_init_log ) +# flush_and_close( f_init_err ) +# +# CUSTOM_TX_PARAMS = ( [ fdb.isc_tpb_nowait, fdb.isc_tpb_autocommit ] ) +# +# con1 = fdb.connect( dsn = dsn ) +# tra1 = con1.trans( default_tpb = CUSTOM_TX_PARAMS ) +# +# tra1.begin() +# cur1=tra1.cursor() +# +# cur1.execute('select mon$auto_commit from mon$transactions where mon$transaction_id = current_transaction') +# for r in cur1: +# print( 'mon$auto_commit:', r[0] ) +# +# cur1.execute( 'insert into test_1 values(?)', ( 777,) ) +# +# #---------------------- R O L L B A C K ----------------------- +# +# tra1.rollback() +# cur1.close() +# con1.close() +# +# #---------------------- R E C O N N E C T ----------------------- +# +# con2 = fdb.connect( dsn = dsn ) +# cur2=con2.cursor() +# cur2.execute("select 'test_1' tab_name, x from test_1 union all select 'test_2', x from test_2 union all select 'test_3', x from test_3") +# # Here we must see records from ALL THREE tables. +# for r in cur2: +# print( r[0], r[1] ) +# +# cur2.close() +# con2.close() +# +# # cleanup: +# ########## +# time.sleep(1) +# cleanup( ( f_init_sql, f_init_log, f_init_err) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + mon$auto_commit: 1 + test_1 777 + test_2 5439 + test_3 603729 + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_transactions_autocommit_1_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/gtcs/test_transactions_autocommit_2.py b/tests/functional/gtcs/test_transactions_autocommit_2.py new file mode 100644 index 00000000..54129a50 --- /dev/null +++ b/tests/functional/gtcs/test_transactions_autocommit_2.py @@ -0,0 +1,176 @@ +#coding:utf-8 +# +# id: functional.gtcs.transactions_autocommit_2 +# title: GTCS/tests/AUTO_COMMIT.2.ESQL. Changes within AUTO COMMIT must be cancelled when exception raises in some TRIGGER. +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/AUTO_COMMIT.2.ESQL.script +# +# Test creates three tables (test_1, test_2 and test_3) and AI-trigger for one of them (test_1). +# This trigger does INSERTs into test_2 and test_3. +# For test_3 we create UNIQUE index that will prevent from insertion of duplicates. +# Then we add one record into test_3 with value = 1000. +# Finally, we try to add record into test_1 and after this INSERT its trigger attempts to add records, +# into test_2 and test_3. The latter will fail because of UK violation (we try to insert apropriate value +# into test-1 in order this exception be raised). +# Expected result: NONE of just performed INSERTS must be saved in DB. The only existing record must be +# in the table test_3 that we added there on initial phase. +# +# NB: we use custom TPB with fdb.isc_tpb_autocommit in order to start DML transactions in AUTOCOMMIT=1 mode. +# Checked on: +# 4.0.0.1812 SS: 2.054s. +# 4.0.0.1767 SC: 1.893s. +# 4.0.0.1810 SS: 1.922s. +# 3.0.6.33273 SS: 0.973s. +# 3.0.6.33240 SC: 1.082s. +# 3.0.6.33247 CS: 2.120s. +# 2.5.6.27020 SS: 2.612s. +# 2.5.9.27149 SC: 0.453s. +# 2.5.9.27143 CS: 0.963s. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# import inspect +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql_init=''' +# set bail on; +# recreate table test_1 (x integer); +# recreate table test_2 (x integer); +# recreate table test_3 (x integer); +# create unique index test_3_x_uniq on test_3 (x); +# commit; +# set term ^; +# create or alter trigger trg_test1_ai for test_1 active after insert position 0 as +# begin +# insert into test_2 values (new.x * 10); +# insert into test_3 values (new.x * 100); +# end ^ +# set term ;^ +# +# insert into test_3 values (1000); +# commit; +# ''' +# +# f_init_sql = open( os.path.join(context['temp_directory'],'tmp_gtcs_tx_ac2.sql'), 'w', buffering = 0) +# f_init_sql.write( sql_init ) +# flush_and_close( f_init_sql ) +# +# f_init_log = open( '.'.join( (os.path.splitext( f_init_sql.name )[0], 'log') ), 'w', buffering = 0) +# f_init_err = open( '.'.join( (os.path.splitext( f_init_sql.name )[0], 'err') ), 'w', buffering = 0) +# +# # This can take about 25-30 seconds: +# #################################### +# subprocess.call( [ context['isql_path'], dsn, '-q', '-i', f_init_sql.name ], stdout = f_init_log, stderr = f_init_err) +# +# flush_and_close( f_init_log ) +# flush_and_close( f_init_err ) +# +# #CUSTOM_TX_PARAMS = ( [ fdb.isc_tpb_read_committed, fdb.isc_tpb_no_rec_version, fdb.isc_tpb_nowait, fdb.isc_tpb_autocommit ] ) +# CUSTOM_TX_PARAMS = ( [ fdb.isc_tpb_nowait, fdb.isc_tpb_autocommit ] ) +# +# con = fdb.connect( dsn = dsn ) +# tx = con.trans( default_tpb = CUSTOM_TX_PARAMS ) +# +# tx.begin() +# cx=tx.cursor() +# +# cx.execute('select mon$auto_commit from mon$transactions where mon$transaction_id = current_transaction') +# for r in cx: +# print( 'mon$auto_commit:', r[0] ) +# +# try: +# cx.execute( 'insert into test_1 values(?)', (10,) ) # this leads to PK/UK violation in the table 'test_3' +# except Exception as e: +# #print('exception in ', inspect.stack()[0][3], ': ', sys.exc_info()[0]) +# print('exception occured, gdscode:', e[2]) +# +# tx.commit() +# +# cx.execute("select 'test_1' tab_name, x from test_1 union all select 'test_2', x from test_2 union all select 'test_3', x from test_3") +# for r in cx: +# print( r[0], r[1] ) +# +# cx.close() +# tx.close() +# con.close() +# +# # cleanup +# ######### +# time.sleep(1) +# cleanup( ( f_init_sql, f_init_log, f_init_err) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + mon$auto_commit: 1 + exception occured, gdscode: 335544349 + test_3 1000 + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_transactions_autocommit_2_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/gtcs/test_transactions_autocommit_3.py b/tests/functional/gtcs/test_transactions_autocommit_3.py new file mode 100644 index 00000000..124a8164 --- /dev/null +++ b/tests/functional/gtcs/test_transactions_autocommit_3.py @@ -0,0 +1,130 @@ +#coding:utf-8 +# +# id: functional.gtcs.transactions_autocommit_3 +# title: GTCS/tests/AUTO_COMMIT.3.ESQL. Changes within AUTO COMMIT must be cancelled when exception raises in some PROCEDURE. +# decription: +# Test does the same actions as described in GTCS/tests/AUTO_COMMIT.3.ESQL.script, see: +# https://github.com/FirebirdSQL/fbtcs/commit/166cb8b72a0aad18ef8ece34977d6d87d803616e#diff-69d4c7d7661d57fdf94aaf32a3377c82 +# +# It creates three tables, each with single SMALLINT column (thus max value that we can put in it is 32767). +# Then it creates three procedures which do insert values in 'their' table plus call "next level" SP +# with passing there input value multiplied by 100. +# When sp_ins_1 is called with argument = 3 then sp_ins_2 will insert into test_2 table value = 300 +# and sp_ins_3 will insert into test_3 value = 30000. +# This mean that we can can NOT call sp_ins_1 with values equal or more than 4 because of numeric overflow exception +# that will be raised in sp_ins_3. +# +# Test calls sp_ins1 two times: with arg=3 and arg=4. Second time must fail and we check that all three tables contain only +# values which are from 1st call: 3, 300 and 30000. +# +# NB: we use custom TPB with fdb.isc_tpb_autocommit in order to start DML transactions in AUTOCOMMIT=1 mode. +# +# Checked on: +# 4.0.0.1767 SS: 1.219s. +# 4.0.0.1712 SC: 1.942s. +# 4.0.0.1763 CS: 1.835s. +# 3.0.6.33246 SS: 0.642s. +# 3.0.5.33084 SC: 1.352s. +# 3.0.6.33246 CS: 1.178s. +# 2.5.9.27119 SS: 0.531s. +# 2.5.9.27149 SC: 0.422s. +# 2.5.9.27143 CS: 0.781s. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# import os +# import sys +# import inspect +# import fdb +# +# N_MAX=3 +# +# #CUSTOM_TX_PARAMS = ( [ fdb.isc_tpb_read_committed, fdb.isc_tpb_no_rec_version, fdb.isc_tpb_nowait, fdb.isc_tpb_autocommit ] ) +# CUSTOM_TX_PARAMS = ( [ fdb.isc_tpb_nowait, fdb.isc_tpb_autocommit ] ) +# +# db_conn.begin() +# cx=db_conn.cursor() +# sql_proc=''' +# create procedure sp_ins_%(i)s(a_x bigint) as +# begin +# insert into test_%(i)s(x) values(:a_x); +# if ( %(i)s != %(N_MAX)s ) then +# execute statement ( 'execute procedure sp_ins_%(k)s (?)' ) (:a_x * 100); +# end +# ''' +# +# for i in range(N_MAX,0,-1): +# k = i+1 +# cx.execute( 'create table test_%(i)s(x smallint)' % locals() ) +# cx.execute( sql_proc % locals() ) +# +# db_conn.commit() +# +# tx = db_conn.trans( default_tpb = CUSTOM_TX_PARAMS ) +# +# tx.begin() +# cx=tx.cursor() +# +# cx.execute('select mon$auto_commit from mon$transactions where mon$transaction_id = current_transaction') +# for r in cx: +# print( 'mon$auto_commit:', r[0] ) +# +# cx.callproc( 'sp_ins_1', (3,) ) +# +# try: +# cx.callproc( 'sp_ins_1', (4,) ) +# except Exception as e: +# pass +# #print('Unexpected exception in ', inspect.stack()[0][3], ': ', sys.exc_info()[0]) +# #print(e) +# +# tx.commit() +# +# cx = db_conn.cursor() +# cx.execute('select x from test_1 union all select x from test_2 union all select x from test_3') +# for r in cx: +# print( 'x:', r[0]) +# +# cx.close() +# tx.close() +# db_conn.close() +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + mon$auto_commit: 1 + x: 3 + x: 300 + x: 30000 + """ + +@pytest.mark.version('>=2.5') +@pytest.mark.xfail +def test_transactions_autocommit_3_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/gtcs/test_trigger_variable_assignment.py b/tests/functional/gtcs/test_trigger_variable_assignment.py new file mode 100644 index 00000000..65de627b --- /dev/null +++ b/tests/functional/gtcs/test_trigger_variable_assignment.py @@ -0,0 +1,48 @@ +#coding:utf-8 +# +# id: functional.gtcs.trigger_variable_assignment +# title: GTCS/tests/CF_ISQL_21. Variable in the AFTER-trigger must be allowed for assignment OLD value in it. +# decription: +# ::: NB ::: +# ### Name of original test has no any relation with actual task of this test: ### +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/CF_ISQL_21.script +# +# AP,2005 - can't assign old.* fields in triggers +# +# Checked on: 4.0.0.1803 SS; 3.0.6.33265 SS; 2.5.9.27149 SC. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create table u(a int); + set term ^; + create trigger trg_u_aid for u after insert or update or delete as + declare i int; + begin + i = old.a; + end^ + commit^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=2.5') +def test_trigger_variable_assignment_1(act_1: Action): + act_1.execute() + diff --git a/tests/functional/gtcs/test_window_func_01.py b/tests/functional/gtcs/test_window_func_01.py new file mode 100644 index 00000000..8daf6028 --- /dev/null +++ b/tests/functional/gtcs/test_window_func_01.py @@ -0,0 +1,2562 @@ +#coding:utf-8 +# +# id: functional.gtcs.window_func_01 +# title: GTCS/tests/FB_SQL_WINDOW_FUNC_01 - set of miscelaneous tests for verification of windowed functions. +# decription: +# Statements from this test are added to initial SQL which is stored in: ... +# bt-repo +# iles\\gtcs-window-func.sql +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/FB_SQL_WINDOW_FUNC_01.script +# +# Checked on 4.0.0.1854; 3.0.6.33277 +# +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# with open( os.path.join(context['files_location'],'gtcs-window-func.sql'), 'r') as f: +# sql_init = f.read() +# +# sql_addi=''' +# set list on; +# select +# 'point-01' as msg, +# count(*), count(val), min(val), max(val), +# count(distinct val), min(distinct val), max(distinct val) +# from entries; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# +# select +# 'point-02' as msg, +# count(*) over (), count(val) over (), min(val) over (), max(val) over (), +# count(distinct val) over (), min(distinct val) over (), max(distinct val) over (), +# id +# from entries +# order by id; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-03' as msg, +# count(*) over (), count(val) over (), min(val) over (), max(val) over (), +# count(distinct val) over (), min(distinct val) over (), max(distinct val) over (), +# id +# from entries +# where 1 = 0 +# order by id; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-04' as msg, +# count(*), count(val), min(val), max(val), +# count(distinct val), min(distinct val), max(distinct val), +# person +# from entries +# group by person +# order by person; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-05' as msg, +# count(*) over (partition by person), +# count(val) over (partition by person), +# min(val) over (partition by person), +# max(val) over (partition by person), +# count(distinct val) over (partition by person), +# min(distinct val) over (partition by person), +# max(distinct val) over (partition by person), +# person +# from entries +# order by 1, 2, 3, 4, 5, 6, 7, 8, 9; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-06' as msg, +# count(*), +# count(e.val), +# min(e.val), +# max(e.val), +# count(distinct e.val), +# min(distinct e.val), +# max(distinct e.val), +# p.name +# from entries e +# join persons p on p.id = e.person +# group by p.name +# order by p.name; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-07' as msg, +# count(*) over (partition by p.id), +# count(e.val) over (partition by p.id), +# min(e.val) over (partition by p.id), +# max(e.val) over (partition by p.id), +# count(distinct e.val) over (partition by p.id), +# min(distinct e.val) over (partition by p.id), +# max(distinct e.val) over (partition by p.id), +# p.name +# from entries e +# join persons p on p.id = e.person +# order by e.id; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-08' as msg, +# person, +# count(person) over (partition by person) +# from entries +# group by person +# order by person; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-09' as msg, +# person, +# count(*) over (partition by person) +# from entries +# group by person +# order by person; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-10' as msg, +# v1.*, p.id +# from persons p +# join v1 on v1.x8 = p.name; +# +# select +# 'point-11' as msg, +# v1.*, p.id +# from persons p +# full join v1 on right(v1.x8, 1) = p.id; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-12' as msg, +# v1.*, p.id +# from persons p +# left join v1 on right(v1.x8, 1) = p.id +# where p.id in (1, 3); +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-13' as msg, +# x3, sum(x4) +# from v1 +# group by x3; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-14' as msg, +# x3, sum(x4), count(*)over() +# from v1 +# group by x3; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-15' as msg, +# x3, sum(x4), sum(sum(x4))over() +# from v1 +# group by x3; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-17' as msg, +# v2.person, sum(v2.val), count (*) over () +# from v2 +# join persons p +# on p.id = v2.person +# group by person; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-18' as msg, +# v3.person, v3.name, sum(v3.val), count (*) over (), sum(sum(v3.val)) over () +# from v3 +# join persons p +# on p.id = v3.person +# group by person, name; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-19' as msg, +# person, +# count(*) over (), +# count(*) over (partition by person) +# from entries +# order by 1, 2, 3, 4; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-20' as msg, +# person, +# count(*) over (), +# count(*) over (partition by person) +# from entries +# +# UNION ALL +# +# select +# 'point-20' as msg, +# person, +# count(*) over (), +# count(*) over (partition by person) +# from entries +# order by 1, 2, 3, 4; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-21' as msg, +# entries.*, +# count(*) over (partition by person || person) +# from entries +# order by 2; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-22' as msg, +# entries.*, +# count(*) over (), +# count(val) over (), +# count(*) over (partition by person), +# count(val) over (partition by person), +# count(*) over (partition by dat), +# count(val) over (partition by dat) +# from entries +# order by 2; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-23' as msg, +# entries.*, +# count(*) over (), +# count(val) over (), +# count(*) over (partition by person), +# count(val) over (partition by person), +# count(*) over (partition by extract(month from dat)), +# count(val) over (partition by extract(month from dat)) +# from entries +# order by 2; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-24' as msg, +# entries.*, +# min(dat) over (partition by person), +# max(dat) over (partition by person) +# from entries +# order by 2; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select distinct +# 'point-25' as msg, +# person, +# min(dat) over (partition by person), +# max(dat) over (partition by person) +# from entries; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select distinct +# 'point-26' as msg, +# person, +# count(*) over (), +# count(*) over (partition by person) +# from entries +# order by 2; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-27' as msg, +# person, +# count(*), +# count(*) over (), +# count(*) over (partition by person), +# count(*) over (partition by 1, 2, 3) +# from entries +# group by person +# order by 2; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-28' as msg, +# person, +# count(*), +# count(*) over (), +# count(*) over (partition by person), +# count(*) over (partition by 1, 2, 3) +# from entries +# group by person +# order by 2 desc; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select * +# from ( +# select +# 'point-29' as msg, +# person, +# count(*) c1, +# count(*) over () c2, +# count(*) over (partition by person) c3, +# count(*) over (partition by 1, 2, 3) c4 +# from entries +# group by person +# ) +# order by 2 desc; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-30' as msg, +# person, +# count(*), +# count(*) over (), +# count(*) over (partition by person), +# count(*) over (partition by 1, 2, 3) +# from entries +# group by person +# order by 2 desc; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-31' as msg, +# person, +# count(*), +# count(*) over (), +# count(*) over (partition by person), +# count(*) over (partition by 1, 2, 3), +# count(count(*)) over () +# from entries +# group by person +# order by 4 desc, 2 desc; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-32' as msg, +# person, +# count(*), +# count(*) over (), +# count(*) over (partition by person), +# count(*) over (partition by 1, 2, 3), +# count(count(*)) over () +# from entries +# group by person +# having count(*) = 3 +# order by 4 desc, 2 desc; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-33' as msg, +# person, +# sum(val), +# count(*) over (), +# count(*) over (partition by person), +# count(*) over (partition by 1, 2, 3), +# count(count(*)) over () +# from entries +# group by person +# order by 4 desc, 2 desc; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-34' as msg, +# person, +# sum(val), +# count(*) over (), +# count(*) over (partition by person), +# count(*) over (partition by 1, 2, 3), +# count(count(*)) over () +# from entries +# group by person +# having sum(val) between 16 and 26 +# order by 4 desc, 2 desc; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# -- Test invalid usages. Following statements must raise error: +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-35' as msg, +# person, +# sum(val) over (partition by count(*)) +# from entries; +# +# select +# 'point-36' as msg, +# person +# from entries +# where count(*) over () = 1; +# +# select +# 'point-37' as msg, +# person +# from entries +# group by person +# having count(*) over () = 1; +# ''' +# +# runProgram('isql', [ dsn], os.linesep.join( (sql_init, sql_addi) ) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG point-01 + COUNT 16 + COUNT 15 + MIN 2.30 + MAX 15.40 + COUNT 10 + MIN 2.30 + MAX 15.40 + MSG point-02 + COUNT 16 + COUNT 15 + MIN 2.30 + MAX 15.40 + COUNT 10 + MIN 2.30 + MAX 15.40 + ID 1 + MSG point-02 + COUNT 16 + COUNT 15 + MIN 2.30 + MAX 15.40 + COUNT 10 + MIN 2.30 + MAX 15.40 + ID 2 + MSG point-02 + COUNT 16 + COUNT 15 + MIN 2.30 + MAX 15.40 + COUNT 10 + MIN 2.30 + MAX 15.40 + ID 3 + MSG point-02 + COUNT 16 + COUNT 15 + MIN 2.30 + MAX 15.40 + COUNT 10 + MIN 2.30 + MAX 15.40 + ID 4 + MSG point-02 + COUNT 16 + COUNT 15 + MIN 2.30 + MAX 15.40 + COUNT 10 + MIN 2.30 + MAX 15.40 + ID 5 + MSG point-02 + COUNT 16 + COUNT 15 + MIN 2.30 + MAX 15.40 + COUNT 10 + MIN 2.30 + MAX 15.40 + ID 6 + MSG point-02 + COUNT 16 + COUNT 15 + MIN 2.30 + MAX 15.40 + COUNT 10 + MIN 2.30 + MAX 15.40 + ID 7 + MSG point-02 + COUNT 16 + COUNT 15 + MIN 2.30 + MAX 15.40 + COUNT 10 + MIN 2.30 + MAX 15.40 + ID 8 + MSG point-02 + COUNT 16 + COUNT 15 + MIN 2.30 + MAX 15.40 + COUNT 10 + MIN 2.30 + MAX 15.40 + ID 9 + MSG point-02 + COUNT 16 + COUNT 15 + MIN 2.30 + MAX 15.40 + COUNT 10 + MIN 2.30 + MAX 15.40 + ID 10 + MSG point-02 + COUNT 16 + COUNT 15 + MIN 2.30 + MAX 15.40 + COUNT 10 + MIN 2.30 + MAX 15.40 + ID 11 + MSG point-02 + COUNT 16 + COUNT 15 + MIN 2.30 + MAX 15.40 + COUNT 10 + MIN 2.30 + MAX 15.40 + ID 12 + MSG point-02 + COUNT 16 + COUNT 15 + MIN 2.30 + MAX 15.40 + COUNT 10 + MIN 2.30 + MAX 15.40 + ID 13 + MSG point-02 + COUNT 16 + COUNT 15 + MIN 2.30 + MAX 15.40 + COUNT 10 + MIN 2.30 + MAX 15.40 + ID 14 + MSG point-02 + COUNT 16 + COUNT 15 + MIN 2.30 + MAX 15.40 + COUNT 10 + MIN 2.30 + MAX 15.40 + ID 15 + MSG point-02 + COUNT 16 + COUNT 15 + MIN 2.30 + MAX 15.40 + COUNT 10 + MIN 2.30 + MAX 15.40 + ID 16 + MSG point-04 + COUNT 4 + COUNT 3 + MIN 2.30 + MAX 3.40 + COUNT 2 + MIN 2.30 + MAX 3.40 + PERSON 1 + MSG point-04 + COUNT 3 + COUNT 3 + MIN 4.30 + MAX 6.40 + COUNT 2 + MIN 4.30 + MAX 6.40 + PERSON 2 + MSG point-04 + COUNT 3 + COUNT 3 + MIN 6.30 + MAX 9.40 + COUNT 2 + MIN 6.30 + MAX 9.40 + PERSON 3 + MSG point-04 + COUNT 3 + COUNT 3 + MIN 8.30 + MAX 12.40 + COUNT 2 + MIN 8.30 + MAX 12.40 + PERSON 4 + MSG point-04 + COUNT 3 + COUNT 3 + MIN 10.30 + MAX 15.40 + COUNT 2 + MIN 10.30 + MAX 15.40 + PERSON 5 + MSG point-05 + COUNT 3 + COUNT 3 + MIN 4.30 + MAX 6.40 + COUNT 2 + MIN 4.30 + MAX 6.40 + PERSON 2 + MSG point-05 + COUNT 3 + COUNT 3 + MIN 4.30 + MAX 6.40 + COUNT 2 + MIN 4.30 + MAX 6.40 + PERSON 2 + MSG point-05 + COUNT 3 + COUNT 3 + MIN 4.30 + MAX 6.40 + COUNT 2 + MIN 4.30 + MAX 6.40 + PERSON 2 + MSG point-05 + COUNT 3 + COUNT 3 + MIN 6.30 + MAX 9.40 + COUNT 2 + MIN 6.30 + MAX 9.40 + PERSON 3 + MSG point-05 + COUNT 3 + COUNT 3 + MIN 6.30 + MAX 9.40 + COUNT 2 + MIN 6.30 + MAX 9.40 + PERSON 3 + MSG point-05 + COUNT 3 + COUNT 3 + MIN 6.30 + MAX 9.40 + COUNT 2 + MIN 6.30 + MAX 9.40 + PERSON 3 + MSG point-05 + COUNT 3 + COUNT 3 + MIN 8.30 + MAX 12.40 + COUNT 2 + MIN 8.30 + MAX 12.40 + PERSON 4 + MSG point-05 + COUNT 3 + COUNT 3 + MIN 8.30 + MAX 12.40 + COUNT 2 + MIN 8.30 + MAX 12.40 + PERSON 4 + MSG point-05 + COUNT 3 + COUNT 3 + MIN 8.30 + MAX 12.40 + COUNT 2 + MIN 8.30 + MAX 12.40 + PERSON 4 + MSG point-05 + COUNT 3 + COUNT 3 + MIN 10.30 + MAX 15.40 + COUNT 2 + MIN 10.30 + MAX 15.40 + PERSON 5 + MSG point-05 + COUNT 3 + COUNT 3 + MIN 10.30 + MAX 15.40 + COUNT 2 + MIN 10.30 + MAX 15.40 + PERSON 5 + MSG point-05 + COUNT 3 + COUNT 3 + MIN 10.30 + MAX 15.40 + COUNT 2 + MIN 10.30 + MAX 15.40 + PERSON 5 + MSG point-05 + COUNT 4 + COUNT 3 + MIN 2.30 + MAX 3.40 + COUNT 2 + MIN 2.30 + MAX 3.40 + PERSON 1 + MSG point-05 + COUNT 4 + COUNT 3 + MIN 2.30 + MAX 3.40 + COUNT 2 + MIN 2.30 + MAX 3.40 + PERSON 1 + MSG point-05 + COUNT 4 + COUNT 3 + MIN 2.30 + MAX 3.40 + COUNT 2 + MIN 2.30 + MAX 3.40 + PERSON 1 + MSG point-05 + COUNT 4 + COUNT 3 + MIN 2.30 + MAX 3.40 + COUNT 2 + MIN 2.30 + MAX 3.40 + PERSON 1 + MSG point-06 + COUNT 4 + COUNT 3 + MIN 2.30 + MAX 3.40 + COUNT 2 + MIN 2.30 + MAX 3.40 + NAME Person 1 + MSG point-06 + COUNT 3 + COUNT 3 + MIN 4.30 + MAX 6.40 + COUNT 2 + MIN 4.30 + MAX 6.40 + NAME Person 2 + MSG point-06 + COUNT 3 + COUNT 3 + MIN 6.30 + MAX 9.40 + COUNT 2 + MIN 6.30 + MAX 9.40 + NAME Person 3 + MSG point-06 + COUNT 3 + COUNT 3 + MIN 8.30 + MAX 12.40 + COUNT 2 + MIN 8.30 + MAX 12.40 + NAME Person 4 + MSG point-06 + COUNT 3 + COUNT 3 + MIN 10.30 + MAX 15.40 + COUNT 2 + MIN 10.30 + MAX 15.40 + NAME Person 5 + MSG point-07 + COUNT 4 + COUNT 3 + MIN 2.30 + MAX 3.40 + COUNT 2 + MIN 2.30 + MAX 3.40 + NAME Person 1 + MSG point-07 + COUNT 3 + COUNT 3 + MIN 4.30 + MAX 6.40 + COUNT 2 + MIN 4.30 + MAX 6.40 + NAME Person 2 + MSG point-07 + COUNT 3 + COUNT 3 + MIN 6.30 + MAX 9.40 + COUNT 2 + MIN 6.30 + MAX 9.40 + NAME Person 3 + MSG point-07 + COUNT 3 + COUNT 3 + MIN 8.30 + MAX 12.40 + COUNT 2 + MIN 8.30 + MAX 12.40 + NAME Person 4 + MSG point-07 + COUNT 3 + COUNT 3 + MIN 10.30 + MAX 15.40 + COUNT 2 + MIN 10.30 + MAX 15.40 + NAME Person 5 + MSG point-07 + COUNT 4 + COUNT 3 + MIN 2.30 + MAX 3.40 + COUNT 2 + MIN 2.30 + MAX 3.40 + NAME Person 1 + MSG point-07 + COUNT 3 + COUNT 3 + MIN 4.30 + MAX 6.40 + COUNT 2 + MIN 4.30 + MAX 6.40 + NAME Person 2 + MSG point-07 + COUNT 3 + COUNT 3 + MIN 6.30 + MAX 9.40 + COUNT 2 + MIN 6.30 + MAX 9.40 + NAME Person 3 + MSG point-07 + COUNT 3 + COUNT 3 + MIN 8.30 + MAX 12.40 + COUNT 2 + MIN 8.30 + MAX 12.40 + NAME Person 4 + MSG point-07 + COUNT 3 + COUNT 3 + MIN 10.30 + MAX 15.40 + COUNT 2 + MIN 10.30 + MAX 15.40 + NAME Person 5 + MSG point-07 + COUNT 4 + COUNT 3 + MIN 2.30 + MAX 3.40 + COUNT 2 + MIN 2.30 + MAX 3.40 + NAME Person 1 + MSG point-07 + COUNT 3 + COUNT 3 + MIN 4.30 + MAX 6.40 + COUNT 2 + MIN 4.30 + MAX 6.40 + NAME Person 2 + MSG point-07 + COUNT 3 + COUNT 3 + MIN 6.30 + MAX 9.40 + COUNT 2 + MIN 6.30 + MAX 9.40 + NAME Person 3 + MSG point-07 + COUNT 3 + COUNT 3 + MIN 8.30 + MAX 12.40 + COUNT 2 + MIN 8.30 + MAX 12.40 + NAME Person 4 + MSG point-07 + COUNT 3 + COUNT 3 + MIN 10.30 + MAX 15.40 + COUNT 2 + MIN 10.30 + MAX 15.40 + NAME Person 5 + MSG point-07 + COUNT 4 + COUNT 3 + MIN 2.30 + MAX 3.40 + COUNT 2 + MIN 2.30 + MAX 3.40 + NAME Person 1 + MSG point-08 + PERSON 1 + COUNT 1 + MSG point-08 + PERSON 2 + COUNT 1 + MSG point-08 + PERSON 3 + COUNT 1 + MSG point-08 + PERSON 4 + COUNT 1 + MSG point-08 + PERSON 5 + COUNT 1 + MSG point-09 + PERSON 1 + COUNT 1 + MSG point-09 + PERSON 2 + COUNT 1 + MSG point-09 + PERSON 3 + COUNT 1 + MSG point-09 + PERSON 4 + COUNT 1 + MSG point-09 + PERSON 5 + COUNT 1 + MSG point-10 + X1 4 + X2 3 + X3 2.30 + X4 3.40 + X5 2 + X6 2.30 + X7 3.40 + X8 Person 1 + ID 1 + MSG point-10 + X1 4 + X2 3 + X3 2.30 + X4 3.40 + X5 2 + X6 2.30 + X7 3.40 + X8 Person 1 + ID 1 + MSG point-10 + X1 4 + X2 3 + X3 2.30 + X4 3.40 + X5 2 + X6 2.30 + X7 3.40 + X8 Person 1 + ID 1 + MSG point-10 + X1 4 + X2 3 + X3 2.30 + X4 3.40 + X5 2 + X6 2.30 + X7 3.40 + X8 Person 1 + ID 1 + MSG point-10 + X1 3 + X2 3 + X3 4.30 + X4 6.40 + X5 2 + X6 4.30 + X7 6.40 + X8 Person 2 + ID 2 + MSG point-10 + X1 3 + X2 3 + X3 4.30 + X4 6.40 + X5 2 + X6 4.30 + X7 6.40 + X8 Person 2 + ID 2 + MSG point-10 + X1 3 + X2 3 + X3 4.30 + X4 6.40 + X5 2 + X6 4.30 + X7 6.40 + X8 Person 2 + ID 2 + MSG point-10 + X1 3 + X2 3 + X3 6.30 + X4 9.40 + X5 2 + X6 6.30 + X7 9.40 + X8 Person 3 + ID 3 + MSG point-10 + X1 3 + X2 3 + X3 6.30 + X4 9.40 + X5 2 + X6 6.30 + X7 9.40 + X8 Person 3 + ID 3 + MSG point-10 + X1 3 + X2 3 + X3 6.30 + X4 9.40 + X5 2 + X6 6.30 + X7 9.40 + X8 Person 3 + ID 3 + MSG point-10 + X1 3 + X2 3 + X3 8.30 + X4 12.40 + X5 2 + X6 8.30 + X7 12.40 + X8 Person 4 + ID 4 + MSG point-10 + X1 3 + X2 3 + X3 8.30 + X4 12.40 + X5 2 + X6 8.30 + X7 12.40 + X8 Person 4 + ID 4 + MSG point-10 + X1 3 + X2 3 + X3 8.30 + X4 12.40 + X5 2 + X6 8.30 + X7 12.40 + X8 Person 4 + ID 4 + MSG point-10 + X1 3 + X2 3 + X3 10.30 + X4 15.40 + X5 2 + X6 10.30 + X7 15.40 + X8 Person 5 + ID 5 + MSG point-10 + X1 3 + X2 3 + X3 10.30 + X4 15.40 + X5 2 + X6 10.30 + X7 15.40 + X8 Person 5 + ID 5 + MSG point-10 + X1 3 + X2 3 + X3 10.30 + X4 15.40 + X5 2 + X6 10.30 + X7 15.40 + X8 Person 5 + ID 5 + MSG point-11 + X1 4 + X2 3 + X3 2.30 + X4 3.40 + X5 2 + X6 2.30 + X7 3.40 + X8 Person 1 + ID 1 + MSG point-11 + X1 4 + X2 3 + X3 2.30 + X4 3.40 + X5 2 + X6 2.30 + X7 3.40 + X8 Person 1 + ID 1 + MSG point-11 + X1 4 + X2 3 + X3 2.30 + X4 3.40 + X5 2 + X6 2.30 + X7 3.40 + X8 Person 1 + ID 1 + MSG point-11 + X1 4 + X2 3 + X3 2.30 + X4 3.40 + X5 2 + X6 2.30 + X7 3.40 + X8 Person 1 + ID 1 + MSG point-11 + X1 3 + X2 3 + X3 4.30 + X4 6.40 + X5 2 + X6 4.30 + X7 6.40 + X8 Person 2 + ID 2 + MSG point-11 + X1 3 + X2 3 + X3 4.30 + X4 6.40 + X5 2 + X6 4.30 + X7 6.40 + X8 Person 2 + ID 2 + MSG point-11 + X1 3 + X2 3 + X3 4.30 + X4 6.40 + X5 2 + X6 4.30 + X7 6.40 + X8 Person 2 + ID 2 + MSG point-11 + X1 3 + X2 3 + X3 6.30 + X4 9.40 + X5 2 + X6 6.30 + X7 9.40 + X8 Person 3 + ID 3 + MSG point-11 + X1 3 + X2 3 + X3 6.30 + X4 9.40 + X5 2 + X6 6.30 + X7 9.40 + X8 Person 3 + ID 3 + MSG point-11 + X1 3 + X2 3 + X3 6.30 + X4 9.40 + X5 2 + X6 6.30 + X7 9.40 + X8 Person 3 + ID 3 + MSG point-11 + X1 3 + X2 3 + X3 8.30 + X4 12.40 + X5 2 + X6 8.30 + X7 12.40 + X8 Person 4 + ID 4 + MSG point-11 + X1 3 + X2 3 + X3 8.30 + X4 12.40 + X5 2 + X6 8.30 + X7 12.40 + X8 Person 4 + ID 4 + MSG point-11 + X1 3 + X2 3 + X3 8.30 + X4 12.40 + X5 2 + X6 8.30 + X7 12.40 + X8 Person 4 + ID 4 + MSG point-11 + X1 3 + X2 3 + X3 10.30 + X4 15.40 + X5 2 + X6 10.30 + X7 15.40 + X8 Person 5 + ID 5 + MSG point-11 + X1 3 + X2 3 + X3 10.30 + X4 15.40 + X5 2 + X6 10.30 + X7 15.40 + X8 Person 5 + ID 5 + MSG point-11 + X1 3 + X2 3 + X3 10.30 + X4 15.40 + X5 2 + X6 10.30 + X7 15.40 + X8 Person 5 + ID 5 + MSG point-12 + X1 4 + X2 3 + X3 2.30 + X4 3.40 + X5 2 + X6 2.30 + X7 3.40 + X8 Person 1 + ID 1 + MSG point-12 + X1 4 + X2 3 + X3 2.30 + X4 3.40 + X5 2 + X6 2.30 + X7 3.40 + X8 Person 1 + ID 1 + MSG point-12 + X1 4 + X2 3 + X3 2.30 + X4 3.40 + X5 2 + X6 2.30 + X7 3.40 + X8 Person 1 + ID 1 + MSG point-12 + X1 4 + X2 3 + X3 2.30 + X4 3.40 + X5 2 + X6 2.30 + X7 3.40 + X8 Person 1 + ID 1 + MSG point-12 + X1 3 + X2 3 + X3 6.30 + X4 9.40 + X5 2 + X6 6.30 + X7 9.40 + X8 Person 3 + ID 3 + MSG point-12 + X1 3 + X2 3 + X3 6.30 + X4 9.40 + X5 2 + X6 6.30 + X7 9.40 + X8 Person 3 + ID 3 + MSG point-12 + X1 3 + X2 3 + X3 6.30 + X4 9.40 + X5 2 + X6 6.30 + X7 9.40 + X8 Person 3 + ID 3 + MSG point-13 + X3 2.30 + SUM 13.60 + MSG point-13 + X3 4.30 + SUM 19.20 + MSG point-13 + X3 6.30 + SUM 28.20 + MSG point-13 + X3 8.30 + SUM 37.20 + MSG point-13 + X3 10.30 + SUM 46.20 + MSG point-14 + X3 2.30 + SUM 13.60 + COUNT 5 + MSG point-14 + X3 4.30 + SUM 19.20 + COUNT 5 + MSG point-14 + X3 6.30 + SUM 28.20 + COUNT 5 + MSG point-14 + X3 8.30 + SUM 37.20 + COUNT 5 + MSG point-14 + X3 10.30 + SUM 46.20 + COUNT 5 + MSG point-15 + X3 2.30 + SUM 13.60 + SUM 144.40 + MSG point-15 + X3 4.30 + SUM 19.20 + SUM 144.40 + MSG point-15 + X3 6.30 + SUM 28.20 + SUM 144.40 + MSG point-15 + X3 8.30 + SUM 37.20 + SUM 144.40 + MSG point-15 + X3 10.30 + SUM 46.20 + SUM 144.40 + MSG point-17 + PERSON 1 + SUM 9.10 + COUNT 5 + MSG point-17 + PERSON 2 + SUM 17.10 + COUNT 5 + MSG point-17 + PERSON 3 + SUM 25.10 + COUNT 5 + MSG point-17 + PERSON 4 + SUM 33.10 + COUNT 5 + MSG point-17 + PERSON 5 + SUM 41.10 + COUNT 5 + MSG point-18 + PERSON 1 + NAME Person 1 + SUM 9.10 + COUNT 5 + SUM 125.50 + MSG point-18 + PERSON 2 + NAME Person 2 + SUM 17.10 + COUNT 5 + SUM 125.50 + MSG point-18 + PERSON 3 + NAME Person 3 + SUM 25.10 + COUNT 5 + SUM 125.50 + MSG point-18 + PERSON 4 + NAME Person 4 + SUM 33.10 + COUNT 5 + SUM 125.50 + MSG point-18 + PERSON 5 + NAME Person 5 + SUM 41.10 + COUNT 5 + SUM 125.50 + MSG point-19 + PERSON 1 + COUNT 16 + COUNT 4 + MSG point-19 + PERSON 1 + COUNT 16 + COUNT 4 + MSG point-19 + PERSON 1 + COUNT 16 + COUNT 4 + MSG point-19 + PERSON 1 + COUNT 16 + COUNT 4 + MSG point-19 + PERSON 2 + COUNT 16 + COUNT 3 + MSG point-19 + PERSON 2 + COUNT 16 + COUNT 3 + MSG point-19 + PERSON 2 + COUNT 16 + COUNT 3 + MSG point-19 + PERSON 3 + COUNT 16 + COUNT 3 + MSG point-19 + PERSON 3 + COUNT 16 + COUNT 3 + MSG point-19 + PERSON 3 + COUNT 16 + COUNT 3 + MSG point-19 + PERSON 4 + COUNT 16 + COUNT 3 + MSG point-19 + PERSON 4 + COUNT 16 + COUNT 3 + MSG point-19 + PERSON 4 + COUNT 16 + COUNT 3 + MSG point-19 + PERSON 5 + COUNT 16 + COUNT 3 + MSG point-19 + PERSON 5 + COUNT 16 + COUNT 3 + MSG point-19 + PERSON 5 + COUNT 16 + COUNT 3 + MSG point-20 + PERSON 1 + COUNT 16 + COUNT 4 + MSG point-20 + PERSON 1 + COUNT 16 + COUNT 4 + MSG point-20 + PERSON 1 + COUNT 16 + COUNT 4 + MSG point-20 + PERSON 1 + COUNT 16 + COUNT 4 + MSG point-20 + PERSON 1 + COUNT 16 + COUNT 4 + MSG point-20 + PERSON 1 + COUNT 16 + COUNT 4 + MSG point-20 + PERSON 1 + COUNT 16 + COUNT 4 + MSG point-20 + PERSON 1 + COUNT 16 + COUNT 4 + MSG point-20 + PERSON 2 + COUNT 16 + COUNT 3 + MSG point-20 + PERSON 2 + COUNT 16 + COUNT 3 + MSG point-20 + PERSON 2 + COUNT 16 + COUNT 3 + MSG point-20 + PERSON 2 + COUNT 16 + COUNT 3 + MSG point-20 + PERSON 2 + COUNT 16 + COUNT 3 + MSG point-20 + PERSON 2 + COUNT 16 + COUNT 3 + MSG point-20 + PERSON 3 + COUNT 16 + COUNT 3 + MSG point-20 + PERSON 3 + COUNT 16 + COUNT 3 + MSG point-20 + PERSON 3 + COUNT 16 + COUNT 3 + MSG point-20 + PERSON 3 + COUNT 16 + COUNT 3 + MSG point-20 + PERSON 3 + COUNT 16 + COUNT 3 + MSG point-20 + PERSON 3 + COUNT 16 + COUNT 3 + MSG point-20 + PERSON 4 + COUNT 16 + COUNT 3 + MSG point-20 + PERSON 4 + COUNT 16 + COUNT 3 + MSG point-20 + PERSON 4 + COUNT 16 + COUNT 3 + MSG point-20 + PERSON 4 + COUNT 16 + COUNT 3 + MSG point-20 + PERSON 4 + COUNT 16 + COUNT 3 + MSG point-20 + PERSON 4 + COUNT 16 + COUNT 3 + MSG point-20 + PERSON 5 + COUNT 16 + COUNT 3 + MSG point-20 + PERSON 5 + COUNT 16 + COUNT 3 + MSG point-20 + PERSON 5 + COUNT 16 + COUNT 3 + MSG point-20 + PERSON 5 + COUNT 16 + COUNT 3 + MSG point-20 + PERSON 5 + COUNT 16 + COUNT 3 + MSG point-20 + PERSON 5 + COUNT 16 + COUNT 3 + MSG point-21 + ID 1 + PERSON 1 + DAT 2010-01-03 + VAL 2.30 + COUNT 4 + MSG point-21 + ID 2 + PERSON 2 + DAT 2010-01-04 + VAL 4.30 + COUNT 3 + MSG point-21 + ID 3 + PERSON 3 + DAT 2010-01-05 + VAL 6.30 + COUNT 3 + MSG point-21 + ID 4 + PERSON 4 + DAT 2010-01-06 + VAL 8.30 + COUNT 3 + MSG point-21 + ID 5 + PERSON 5 + DAT 2010-01-07 + VAL 10.30 + COUNT 3 + MSG point-21 + ID 6 + PERSON 1 + DAT 2010-02-02 + VAL 3.40 + COUNT 4 + MSG point-21 + ID 7 + PERSON 2 + DAT 2010-02-03 + VAL 6.40 + COUNT 3 + MSG point-21 + ID 8 + PERSON 3 + DAT 2010-02-04 + VAL 9.40 + COUNT 3 + MSG point-21 + ID 9 + PERSON 4 + DAT 2010-02-05 + VAL 12.40 + COUNT 3 + MSG point-21 + ID 10 + PERSON 5 + DAT 2010-02-06 + VAL 15.40 + COUNT 3 + MSG point-21 + ID 11 + PERSON 1 + DAT 2010-03-02 + VAL 3.40 + COUNT 4 + MSG point-21 + ID 12 + PERSON 2 + DAT 2010-03-03 + VAL 6.40 + COUNT 3 + MSG point-21 + ID 13 + PERSON 3 + DAT 2010-03-04 + VAL 9.40 + COUNT 3 + MSG point-21 + ID 14 + PERSON 4 + DAT 2010-03-05 + VAL 12.40 + COUNT 3 + MSG point-21 + ID 15 + PERSON 5 + DAT 2010-03-06 + VAL 15.40 + COUNT 3 + MSG point-21 + ID 16 + PERSON 1 + DAT + VAL + COUNT 4 + MSG point-22 + ID 1 + PERSON 1 + DAT 2010-01-03 + VAL 2.30 + COUNT 16 + COUNT 15 + COUNT 4 + COUNT 3 + COUNT 1 + COUNT 1 + MSG point-22 + ID 2 + PERSON 2 + DAT 2010-01-04 + VAL 4.30 + COUNT 16 + COUNT 15 + COUNT 3 + COUNT 3 + COUNT 1 + COUNT 1 + MSG point-22 + ID 3 + PERSON 3 + DAT 2010-01-05 + VAL 6.30 + COUNT 16 + COUNT 15 + COUNT 3 + COUNT 3 + COUNT 1 + COUNT 1 + MSG point-22 + ID 4 + PERSON 4 + DAT 2010-01-06 + VAL 8.30 + COUNT 16 + COUNT 15 + COUNT 3 + COUNT 3 + COUNT 1 + COUNT 1 + MSG point-22 + ID 5 + PERSON 5 + DAT 2010-01-07 + VAL 10.30 + COUNT 16 + COUNT 15 + COUNT 3 + COUNT 3 + COUNT 1 + COUNT 1 + MSG point-22 + ID 6 + PERSON 1 + DAT 2010-02-02 + VAL 3.40 + COUNT 16 + COUNT 15 + COUNT 4 + COUNT 3 + COUNT 1 + COUNT 1 + MSG point-22 + ID 7 + PERSON 2 + DAT 2010-02-03 + VAL 6.40 + COUNT 16 + COUNT 15 + COUNT 3 + COUNT 3 + COUNT 1 + COUNT 1 + MSG point-22 + ID 8 + PERSON 3 + DAT 2010-02-04 + VAL 9.40 + COUNT 16 + COUNT 15 + COUNT 3 + COUNT 3 + COUNT 1 + COUNT 1 + MSG point-22 + ID 9 + PERSON 4 + DAT 2010-02-05 + VAL 12.40 + COUNT 16 + COUNT 15 + COUNT 3 + COUNT 3 + COUNT 1 + COUNT 1 + MSG point-22 + ID 10 + PERSON 5 + DAT 2010-02-06 + VAL 15.40 + COUNT 16 + COUNT 15 + COUNT 3 + COUNT 3 + COUNT 1 + COUNT 1 + MSG point-22 + ID 11 + PERSON 1 + DAT 2010-03-02 + VAL 3.40 + COUNT 16 + COUNT 15 + COUNT 4 + COUNT 3 + COUNT 1 + COUNT 1 + MSG point-22 + ID 12 + PERSON 2 + DAT 2010-03-03 + VAL 6.40 + COUNT 16 + COUNT 15 + COUNT 3 + COUNT 3 + COUNT 1 + COUNT 1 + MSG point-22 + ID 13 + PERSON 3 + DAT 2010-03-04 + VAL 9.40 + COUNT 16 + COUNT 15 + COUNT 3 + COUNT 3 + COUNT 1 + COUNT 1 + MSG point-22 + ID 14 + PERSON 4 + DAT 2010-03-05 + VAL 12.40 + COUNT 16 + COUNT 15 + COUNT 3 + COUNT 3 + COUNT 1 + COUNT 1 + MSG point-22 + ID 15 + PERSON 5 + DAT 2010-03-06 + VAL 15.40 + COUNT 16 + COUNT 15 + COUNT 3 + COUNT 3 + COUNT 1 + COUNT 1 + MSG point-22 + ID 16 + PERSON 1 + DAT + VAL + COUNT 16 + COUNT 15 + COUNT 4 + COUNT 3 + COUNT 1 + COUNT 0 + MSG point-23 + ID 1 + PERSON 1 + DAT 2010-01-03 + VAL 2.30 + COUNT 16 + COUNT 15 + COUNT 4 + COUNT 3 + COUNT 5 + COUNT 5 + MSG point-23 + ID 2 + PERSON 2 + DAT 2010-01-04 + VAL 4.30 + COUNT 16 + COUNT 15 + COUNT 3 + COUNT 3 + COUNT 5 + COUNT 5 + MSG point-23 + ID 3 + PERSON 3 + DAT 2010-01-05 + VAL 6.30 + COUNT 16 + COUNT 15 + COUNT 3 + COUNT 3 + COUNT 5 + COUNT 5 + MSG point-23 + ID 4 + PERSON 4 + DAT 2010-01-06 + VAL 8.30 + COUNT 16 + COUNT 15 + COUNT 3 + COUNT 3 + COUNT 5 + COUNT 5 + MSG point-23 + ID 5 + PERSON 5 + DAT 2010-01-07 + VAL 10.30 + COUNT 16 + COUNT 15 + COUNT 3 + COUNT 3 + COUNT 5 + COUNT 5 + MSG point-23 + ID 6 + PERSON 1 + DAT 2010-02-02 + VAL 3.40 + COUNT 16 + COUNT 15 + COUNT 4 + COUNT 3 + COUNT 5 + COUNT 5 + MSG point-23 + ID 7 + PERSON 2 + DAT 2010-02-03 + VAL 6.40 + COUNT 16 + COUNT 15 + COUNT 3 + COUNT 3 + COUNT 5 + COUNT 5 + MSG point-23 + ID 8 + PERSON 3 + DAT 2010-02-04 + VAL 9.40 + COUNT 16 + COUNT 15 + COUNT 3 + COUNT 3 + COUNT 5 + COUNT 5 + MSG point-23 + ID 9 + PERSON 4 + DAT 2010-02-05 + VAL 12.40 + COUNT 16 + COUNT 15 + COUNT 3 + COUNT 3 + COUNT 5 + COUNT 5 + MSG point-23 + ID 10 + PERSON 5 + DAT 2010-02-06 + VAL 15.40 + COUNT 16 + COUNT 15 + COUNT 3 + COUNT 3 + COUNT 5 + COUNT 5 + MSG point-23 + ID 11 + PERSON 1 + DAT 2010-03-02 + VAL 3.40 + COUNT 16 + COUNT 15 + COUNT 4 + COUNT 3 + COUNT 5 + COUNT 5 + MSG point-23 + ID 12 + PERSON 2 + DAT 2010-03-03 + VAL 6.40 + COUNT 16 + COUNT 15 + COUNT 3 + COUNT 3 + COUNT 5 + COUNT 5 + MSG point-23 + ID 13 + PERSON 3 + DAT 2010-03-04 + VAL 9.40 + COUNT 16 + COUNT 15 + COUNT 3 + COUNT 3 + COUNT 5 + COUNT 5 + MSG point-23 + ID 14 + PERSON 4 + DAT 2010-03-05 + VAL 12.40 + COUNT 16 + COUNT 15 + COUNT 3 + COUNT 3 + COUNT 5 + COUNT 5 + MSG point-23 + ID 15 + PERSON 5 + DAT 2010-03-06 + VAL 15.40 + COUNT 16 + COUNT 15 + COUNT 3 + COUNT 3 + COUNT 5 + COUNT 5 + MSG point-23 + ID 16 + PERSON 1 + DAT + VAL + COUNT 16 + COUNT 15 + COUNT 4 + COUNT 3 + COUNT 1 + COUNT 0 + MSG point-24 + ID 1 + PERSON 1 + DAT 2010-01-03 + VAL 2.30 + MIN 2010-01-03 + MAX 2010-03-02 + MSG point-24 + ID 2 + PERSON 2 + DAT 2010-01-04 + VAL 4.30 + MIN 2010-01-04 + MAX 2010-03-03 + MSG point-24 + ID 3 + PERSON 3 + DAT 2010-01-05 + VAL 6.30 + MIN 2010-01-05 + MAX 2010-03-04 + MSG point-24 + ID 4 + PERSON 4 + DAT 2010-01-06 + VAL 8.30 + MIN 2010-01-06 + MAX 2010-03-05 + MSG point-24 + ID 5 + PERSON 5 + DAT 2010-01-07 + VAL 10.30 + MIN 2010-01-07 + MAX 2010-03-06 + MSG point-24 + ID 6 + PERSON 1 + DAT 2010-02-02 + VAL 3.40 + MIN 2010-01-03 + MAX 2010-03-02 + MSG point-24 + ID 7 + PERSON 2 + DAT 2010-02-03 + VAL 6.40 + MIN 2010-01-04 + MAX 2010-03-03 + MSG point-24 + ID 8 + PERSON 3 + DAT 2010-02-04 + VAL 9.40 + MIN 2010-01-05 + MAX 2010-03-04 + MSG point-24 + ID 9 + PERSON 4 + DAT 2010-02-05 + VAL 12.40 + MIN 2010-01-06 + MAX 2010-03-05 + MSG point-24 + ID 10 + PERSON 5 + DAT 2010-02-06 + VAL 15.40 + MIN 2010-01-07 + MAX 2010-03-06 + MSG point-24 + ID 11 + PERSON 1 + DAT 2010-03-02 + VAL 3.40 + MIN 2010-01-03 + MAX 2010-03-02 + MSG point-24 + ID 12 + PERSON 2 + DAT 2010-03-03 + VAL 6.40 + MIN 2010-01-04 + MAX 2010-03-03 + MSG point-24 + ID 13 + PERSON 3 + DAT 2010-03-04 + VAL 9.40 + MIN 2010-01-05 + MAX 2010-03-04 + MSG point-24 + ID 14 + PERSON 4 + DAT 2010-03-05 + VAL 12.40 + MIN 2010-01-06 + MAX 2010-03-05 + MSG point-24 + ID 15 + PERSON 5 + DAT 2010-03-06 + VAL 15.40 + MIN 2010-01-07 + MAX 2010-03-06 + MSG point-24 + ID 16 + PERSON 1 + DAT + VAL + MIN 2010-01-03 + MAX 2010-03-02 + MSG point-25 + PERSON 1 + MIN 2010-01-03 + MAX 2010-03-02 + MSG point-25 + PERSON 2 + MIN 2010-01-04 + MAX 2010-03-03 + MSG point-25 + PERSON 3 + MIN 2010-01-05 + MAX 2010-03-04 + MSG point-25 + PERSON 4 + MIN 2010-01-06 + MAX 2010-03-05 + MSG point-25 + PERSON 5 + MIN 2010-01-07 + MAX 2010-03-06 + MSG point-26 + PERSON 1 + COUNT 16 + COUNT 4 + MSG point-26 + PERSON 2 + COUNT 16 + COUNT 3 + MSG point-26 + PERSON 3 + COUNT 16 + COUNT 3 + MSG point-26 + PERSON 4 + COUNT 16 + COUNT 3 + MSG point-26 + PERSON 5 + COUNT 16 + COUNT 3 + MSG point-27 + PERSON 1 + COUNT 4 + COUNT 5 + COUNT 1 + COUNT 5 + MSG point-27 + PERSON 2 + COUNT 3 + COUNT 5 + COUNT 1 + COUNT 5 + MSG point-27 + PERSON 3 + COUNT 3 + COUNT 5 + COUNT 1 + COUNT 5 + MSG point-27 + PERSON 4 + COUNT 3 + COUNT 5 + COUNT 1 + COUNT 5 + MSG point-27 + PERSON 5 + COUNT 3 + COUNT 5 + COUNT 1 + COUNT 5 + MSG point-28 + PERSON 5 + COUNT 3 + COUNT 5 + COUNT 1 + COUNT 5 + MSG point-28 + PERSON 4 + COUNT 3 + COUNT 5 + COUNT 1 + COUNT 5 + MSG point-28 + PERSON 3 + COUNT 3 + COUNT 5 + COUNT 1 + COUNT 5 + MSG point-28 + PERSON 2 + COUNT 3 + COUNT 5 + COUNT 1 + COUNT 5 + MSG point-28 + PERSON 1 + COUNT 4 + COUNT 5 + COUNT 1 + COUNT 5 + MSG point-29 + PERSON 5 + C1 3 + C2 5 + C3 1 + C4 5 + MSG point-29 + PERSON 4 + C1 3 + C2 5 + C3 1 + C4 5 + MSG point-29 + PERSON 3 + C1 3 + C2 5 + C3 1 + C4 5 + MSG point-29 + PERSON 2 + C1 3 + C2 5 + C3 1 + C4 5 + MSG point-29 + PERSON 1 + C1 4 + C2 5 + C3 1 + C4 5 + MSG point-30 + PERSON 5 + COUNT 3 + COUNT 5 + COUNT 1 + COUNT 5 + MSG point-30 + PERSON 4 + COUNT 3 + COUNT 5 + COUNT 1 + COUNT 5 + MSG point-30 + PERSON 3 + COUNT 3 + COUNT 5 + COUNT 1 + COUNT 5 + MSG point-30 + PERSON 2 + COUNT 3 + COUNT 5 + COUNT 1 + COUNT 5 + MSG point-30 + PERSON 1 + COUNT 4 + COUNT 5 + COUNT 1 + COUNT 5 + MSG point-31 + PERSON 5 + COUNT 3 + COUNT 5 + COUNT 1 + COUNT 5 + COUNT 5 + MSG point-31 + PERSON 4 + COUNT 3 + COUNT 5 + COUNT 1 + COUNT 5 + COUNT 5 + MSG point-31 + PERSON 3 + COUNT 3 + COUNT 5 + COUNT 1 + COUNT 5 + COUNT 5 + MSG point-31 + PERSON 2 + COUNT 3 + COUNT 5 + COUNT 1 + COUNT 5 + COUNT 5 + MSG point-31 + PERSON 1 + COUNT 4 + COUNT 5 + COUNT 1 + COUNT 5 + COUNT 5 + MSG point-32 + PERSON 5 + COUNT 3 + COUNT 4 + COUNT 1 + COUNT 4 + COUNT 4 + MSG point-32 + PERSON 4 + COUNT 3 + COUNT 4 + COUNT 1 + COUNT 4 + COUNT 4 + MSG point-32 + PERSON 3 + COUNT 3 + COUNT 4 + COUNT 1 + COUNT 4 + COUNT 4 + MSG point-32 + PERSON 2 + COUNT 3 + COUNT 4 + COUNT 1 + COUNT 4 + COUNT 4 + MSG point-33 + PERSON 5 + SUM 41.10 + COUNT 5 + COUNT 1 + COUNT 5 + COUNT 5 + MSG point-33 + PERSON 4 + SUM 33.10 + COUNT 5 + COUNT 1 + COUNT 5 + COUNT 5 + MSG point-33 + PERSON 3 + SUM 25.10 + COUNT 5 + COUNT 1 + COUNT 5 + COUNT 5 + MSG point-33 + PERSON 2 + SUM 17.10 + COUNT 5 + COUNT 1 + COUNT 5 + COUNT 5 + MSG point-33 + PERSON 1 + SUM 9.10 + COUNT 5 + COUNT 1 + COUNT 5 + COUNT 5 + MSG point-34 + PERSON 3 + SUM 25.10 + COUNT 2 + COUNT 1 + COUNT 2 + COUNT 2 + MSG point-34 + PERSON 2 + SUM 17.10 + COUNT 2 + COUNT 1 + COUNT 2 + COUNT 2 + """ +expected_stderr_1 = """ + 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 + -Cannot use an aggregate or window function in a WHERE clause, use HAVING (for aggregate only) instead + + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Cannot use an aggregate or window function in a WHERE clause, use HAVING (for aggregate only) instead + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_window_func_01_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/gtcs/test_window_func_02.py b/tests/functional/gtcs/test_window_func_02.py new file mode 100644 index 00000000..384c61cd --- /dev/null +++ b/tests/functional/gtcs/test_window_func_02.py @@ -0,0 +1,1401 @@ +#coding:utf-8 +# +# id: functional.gtcs.window_func_02 +# title: GTCS/tests/FB_SQL_WINDOW_FUNC_02 - set of miscelaneous tests for verification of windowed functions. +# decription: +# Statements from this test are added to initial SQL which is stored in: ... +# bt-repo +# iles\\gtcs-window-func.sql +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/FB_SQL_WINDOW_FUNC_02.script +# +# Checked on 4.0.0.1854; 3.0.6.33277 +# +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# with open( os.path.join(context['files_location'],'gtcs-window-func.sql'), 'r') as f: +# sql_init = f.read() +# +# sql_addi=''' +# set list on; +# +# select +# 'point-01' as msg, +# p.*, +# sum(1) over (order by id) +# from persons p +# order by id; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-02' as msg, +# p.*, +# sum(1) over (order by id desc) +# from persons p +# order by id; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-03' as msg, +# p.*, +# sum(1) over (order by id) +# from persons p +# order by id; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-04' as msg, +# p.*, +# sum(1) over (order by id) +# from persons p +# order by id desc; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-05' as msg, +# p.*, +# sum(1) over (order by id desc) +# from persons p +# order by id desc; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-06' as msg, +# p.*, +# sum(1) over (order by id desc) s +# from persons p +# order by s; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-07' as msg, +# p.*, +# sum(id) over (order by id) +# from persons p; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-08' as msg, +# p.*, +# sum(mod(id, 2)) over (order by id) +# from persons p; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-09' as msg, +# e.*, +# avg(val) over (order by person nulls first), +# avg(val) over (order by dat nulls first) +# from entries e +# order by id; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-10' as msg, +# e.*, +# avg(val) over (order by person nulls last), +# avg(val) over (order by dat nulls last) +# from entries e +# order by id; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-11' as msg, +# e.*, +# count(val) over (order by person), +# count(*) over (order by person), +# count(null) over (order by person) +# from entries e +# order by id; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-12' as msg, +# e.*, +# count(val) over (order by person), +# count(val) over (order by id), +# count(*) over (order by person), +# count(*) over (order by id), +# count(null) over (order by person), +# count(null) over (order by id) +# from entries e +# order by id; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-13' as msg, +# e.*, +# sum(val) over (partition by id order by person), +# sum(val) over (partition by id order by id), +# count(*) over (partition by person order by person), +# count(*) over (partition by person order by id), +# sum(id) over (partition by dat order by person), +# sum(id) over (partition by dat order by id) +# from entries e +# order by id; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-14' as msg, +# e.*, +# sum(val) over (partition by extract(month from dat)), +# sum(id) over (partition by extract(month from dat)), +# sum(val) over (partition by extract(year from dat)), +# sum(id) over (partition by extract(year from dat)), +# sum(val) over (partition by extract(day from dat)), +# sum(id) over (partition by extract(day from dat)) +# from entries e +# order by id; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-15' as msg, +# e.*, +# min(id) over (partition by extract(month from dat)), +# max(id) over (partition by extract(month from dat)), +# min(val) over (partition by extract(month from dat)), +# max(val) over (partition by extract(month from dat)) +# from entries e +# order by id; +# ''' +# +# runProgram('isql', [ dsn], os.linesep.join( (sql_init, sql_addi) ) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG point-01 + ID 1 + NAME Person 1 + SUM 1 + MSG point-01 + ID 2 + NAME Person 2 + SUM 2 + MSG point-01 + ID 3 + NAME Person 3 + SUM 3 + MSG point-01 + ID 4 + NAME Person 4 + SUM 4 + MSG point-01 + ID 5 + NAME Person 5 + SUM 5 + MSG point-02 + ID 1 + NAME Person 1 + SUM 5 + MSG point-02 + ID 2 + NAME Person 2 + SUM 4 + MSG point-02 + ID 3 + NAME Person 3 + SUM 3 + MSG point-02 + ID 4 + NAME Person 4 + SUM 2 + MSG point-02 + ID 5 + NAME Person 5 + SUM 1 + MSG point-03 + ID 1 + NAME Person 1 + SUM 1 + MSG point-03 + ID 2 + NAME Person 2 + SUM 2 + MSG point-03 + ID 3 + NAME Person 3 + SUM 3 + MSG point-03 + ID 4 + NAME Person 4 + SUM 4 + MSG point-03 + ID 5 + NAME Person 5 + SUM 5 + MSG point-04 + ID 5 + NAME Person 5 + SUM 5 + MSG point-04 + ID 4 + NAME Person 4 + SUM 4 + MSG point-04 + ID 3 + NAME Person 3 + SUM 3 + MSG point-04 + ID 2 + NAME Person 2 + SUM 2 + MSG point-04 + ID 1 + NAME Person 1 + SUM 1 + MSG point-05 + ID 5 + NAME Person 5 + SUM 1 + MSG point-05 + ID 4 + NAME Person 4 + SUM 2 + MSG point-05 + ID 3 + NAME Person 3 + SUM 3 + MSG point-05 + ID 2 + NAME Person 2 + SUM 4 + MSG point-05 + ID 1 + NAME Person 1 + SUM 5 + MSG point-06 + ID 5 + NAME Person 5 + S 1 + MSG point-06 + ID 4 + NAME Person 4 + S 2 + MSG point-06 + ID 3 + NAME Person 3 + S 3 + MSG point-06 + ID 2 + NAME Person 2 + S 4 + MSG point-06 + ID 1 + NAME Person 1 + S 5 + MSG point-07 + ID 1 + NAME Person 1 + SUM 1 + MSG point-07 + ID 2 + NAME Person 2 + SUM 3 + MSG point-07 + ID 3 + NAME Person 3 + SUM 6 + MSG point-07 + ID 4 + NAME Person 4 + SUM 10 + MSG point-07 + ID 5 + NAME Person 5 + SUM 15 + MSG point-08 + ID 1 + NAME Person 1 + SUM 1 + MSG point-08 + ID 2 + NAME Person 2 + SUM 1 + MSG point-08 + ID 3 + NAME Person 3 + SUM 2 + MSG point-08 + ID 4 + NAME Person 4 + SUM 2 + MSG point-08 + ID 5 + NAME Person 5 + SUM 3 + MSG point-09 + ID 1 + PERSON 1 + DAT 2010-01-03 + VAL 2.30 + AVG 3.03 + AVG 2.30 + MSG point-09 + ID 2 + PERSON 2 + DAT 2010-01-04 + VAL 4.30 + AVG 4.36 + AVG 3.30 + MSG point-09 + ID 3 + PERSON 3 + DAT 2010-01-05 + VAL 6.30 + AVG 5.70 + AVG 4.30 + MSG point-09 + ID 4 + PERSON 4 + DAT 2010-01-06 + VAL 8.30 + AVG 7.03 + AVG 5.30 + MSG point-09 + ID 5 + PERSON 5 + DAT 2010-01-07 + VAL 10.30 + AVG 8.36 + AVG 6.30 + MSG point-09 + ID 6 + PERSON 1 + DAT 2010-02-02 + VAL 3.40 + AVG 3.03 + AVG 5.81 + MSG point-09 + ID 7 + PERSON 2 + DAT 2010-02-03 + VAL 6.40 + AVG 4.36 + AVG 5.90 + MSG point-09 + ID 8 + PERSON 3 + DAT 2010-02-04 + VAL 9.40 + AVG 5.70 + AVG 6.33 + MSG point-09 + ID 9 + PERSON 4 + DAT 2010-02-05 + VAL 12.40 + AVG 7.03 + AVG 7.01 + MSG point-09 + ID 10 + PERSON 5 + DAT 2010-02-06 + VAL 15.40 + AVG 8.36 + AVG 7.85 + MSG point-09 + ID 11 + PERSON 1 + DAT 2010-03-02 + VAL 3.40 + AVG 3.03 + AVG 7.44 + MSG point-09 + ID 12 + PERSON 2 + DAT 2010-03-03 + VAL 6.40 + AVG 4.36 + AVG 7.35 + MSG point-09 + ID 13 + PERSON 3 + DAT 2010-03-04 + VAL 9.40 + AVG 5.70 + AVG 7.51 + MSG point-09 + ID 14 + PERSON 4 + DAT 2010-03-05 + VAL 12.40 + AVG 7.03 + AVG 7.86 + MSG point-09 + ID 15 + PERSON 5 + DAT 2010-03-06 + VAL 15.40 + AVG 8.36 + AVG 8.36 + MSG point-09 + ID 16 + PERSON 1 + DAT + VAL + AVG 3.03 + AVG + MSG point-10 + ID 1 + PERSON 1 + DAT 2010-01-03 + VAL 2.30 + AVG 3.03 + AVG 2.30 + MSG point-10 + ID 2 + PERSON 2 + DAT 2010-01-04 + VAL 4.30 + AVG 4.36 + AVG 3.30 + MSG point-10 + ID 3 + PERSON 3 + DAT 2010-01-05 + VAL 6.30 + AVG 5.70 + AVG 4.30 + MSG point-10 + ID 4 + PERSON 4 + DAT 2010-01-06 + VAL 8.30 + AVG 7.03 + AVG 5.30 + MSG point-10 + ID 5 + PERSON 5 + DAT 2010-01-07 + VAL 10.30 + AVG 8.36 + AVG 6.30 + MSG point-10 + ID 6 + PERSON 1 + DAT 2010-02-02 + VAL 3.40 + AVG 3.03 + AVG 5.81 + MSG point-10 + ID 7 + PERSON 2 + DAT 2010-02-03 + VAL 6.40 + AVG 4.36 + AVG 5.90 + MSG point-10 + ID 8 + PERSON 3 + DAT 2010-02-04 + VAL 9.40 + AVG 5.70 + AVG 6.33 + MSG point-10 + ID 9 + PERSON 4 + DAT 2010-02-05 + VAL 12.40 + AVG 7.03 + AVG 7.01 + MSG point-10 + ID 10 + PERSON 5 + DAT 2010-02-06 + VAL 15.40 + AVG 8.36 + AVG 7.85 + MSG point-10 + ID 11 + PERSON 1 + DAT 2010-03-02 + VAL 3.40 + AVG 3.03 + AVG 7.44 + MSG point-10 + ID 12 + PERSON 2 + DAT 2010-03-03 + VAL 6.40 + AVG 4.36 + AVG 7.35 + MSG point-10 + ID 13 + PERSON 3 + DAT 2010-03-04 + VAL 9.40 + AVG 5.70 + AVG 7.51 + MSG point-10 + ID 14 + PERSON 4 + DAT 2010-03-05 + VAL 12.40 + AVG 7.03 + AVG 7.86 + MSG point-10 + ID 15 + PERSON 5 + DAT 2010-03-06 + VAL 15.40 + AVG 8.36 + AVG 8.36 + MSG point-10 + ID 16 + PERSON 1 + DAT + VAL + AVG 3.03 + AVG 8.36 + MSG point-11 + ID 1 + PERSON 1 + DAT 2010-01-03 + VAL 2.30 + COUNT 3 + COUNT 4 + COUNT 0 + MSG point-11 + ID 2 + PERSON 2 + DAT 2010-01-04 + VAL 4.30 + COUNT 6 + COUNT 7 + COUNT 0 + MSG point-11 + ID 3 + PERSON 3 + DAT 2010-01-05 + VAL 6.30 + COUNT 9 + COUNT 10 + COUNT 0 + MSG point-11 + ID 4 + PERSON 4 + DAT 2010-01-06 + VAL 8.30 + COUNT 12 + COUNT 13 + COUNT 0 + MSG point-11 + ID 5 + PERSON 5 + DAT 2010-01-07 + VAL 10.30 + COUNT 15 + COUNT 16 + COUNT 0 + MSG point-11 + ID 6 + PERSON 1 + DAT 2010-02-02 + VAL 3.40 + COUNT 3 + COUNT 4 + COUNT 0 + MSG point-11 + ID 7 + PERSON 2 + DAT 2010-02-03 + VAL 6.40 + COUNT 6 + COUNT 7 + COUNT 0 + MSG point-11 + ID 8 + PERSON 3 + DAT 2010-02-04 + VAL 9.40 + COUNT 9 + COUNT 10 + COUNT 0 + MSG point-11 + ID 9 + PERSON 4 + DAT 2010-02-05 + VAL 12.40 + COUNT 12 + COUNT 13 + COUNT 0 + MSG point-11 + ID 10 + PERSON 5 + DAT 2010-02-06 + VAL 15.40 + COUNT 15 + COUNT 16 + COUNT 0 + MSG point-11 + ID 11 + PERSON 1 + DAT 2010-03-02 + VAL 3.40 + COUNT 3 + COUNT 4 + COUNT 0 + MSG point-11 + ID 12 + PERSON 2 + DAT 2010-03-03 + VAL 6.40 + COUNT 6 + COUNT 7 + COUNT 0 + MSG point-11 + ID 13 + PERSON 3 + DAT 2010-03-04 + VAL 9.40 + COUNT 9 + COUNT 10 + COUNT 0 + MSG point-11 + ID 14 + PERSON 4 + DAT 2010-03-05 + VAL 12.40 + COUNT 12 + COUNT 13 + COUNT 0 + MSG point-11 + ID 15 + PERSON 5 + DAT 2010-03-06 + VAL 15.40 + COUNT 15 + COUNT 16 + COUNT 0 + MSG point-11 + ID 16 + PERSON 1 + DAT + VAL + COUNT 3 + COUNT 4 + COUNT 0 + MSG point-12 + ID 1 + PERSON 1 + DAT 2010-01-03 + VAL 2.30 + COUNT 3 + COUNT 1 + COUNT 4 + COUNT 1 + COUNT 0 + COUNT 0 + MSG point-12 + ID 2 + PERSON 2 + DAT 2010-01-04 + VAL 4.30 + COUNT 6 + COUNT 2 + COUNT 7 + COUNT 2 + COUNT 0 + COUNT 0 + MSG point-12 + ID 3 + PERSON 3 + DAT 2010-01-05 + VAL 6.30 + COUNT 9 + COUNT 3 + COUNT 10 + COUNT 3 + COUNT 0 + COUNT 0 + MSG point-12 + ID 4 + PERSON 4 + DAT 2010-01-06 + VAL 8.30 + COUNT 12 + COUNT 4 + COUNT 13 + COUNT 4 + COUNT 0 + COUNT 0 + MSG point-12 + ID 5 + PERSON 5 + DAT 2010-01-07 + VAL 10.30 + COUNT 15 + COUNT 5 + COUNT 16 + COUNT 5 + COUNT 0 + COUNT 0 + MSG point-12 + ID 6 + PERSON 1 + DAT 2010-02-02 + VAL 3.40 + COUNT 3 + COUNT 6 + COUNT 4 + COUNT 6 + COUNT 0 + COUNT 0 + MSG point-12 + ID 7 + PERSON 2 + DAT 2010-02-03 + VAL 6.40 + COUNT 6 + COUNT 7 + COUNT 7 + COUNT 7 + COUNT 0 + COUNT 0 + MSG point-12 + ID 8 + PERSON 3 + DAT 2010-02-04 + VAL 9.40 + COUNT 9 + COUNT 8 + COUNT 10 + COUNT 8 + COUNT 0 + COUNT 0 + MSG point-12 + ID 9 + PERSON 4 + DAT 2010-02-05 + VAL 12.40 + COUNT 12 + COUNT 9 + COUNT 13 + COUNT 9 + COUNT 0 + COUNT 0 + MSG point-12 + ID 10 + PERSON 5 + DAT 2010-02-06 + VAL 15.40 + COUNT 15 + COUNT 10 + COUNT 16 + COUNT 10 + COUNT 0 + COUNT 0 + MSG point-12 + ID 11 + PERSON 1 + DAT 2010-03-02 + VAL 3.40 + COUNT 3 + COUNT 11 + COUNT 4 + COUNT 11 + COUNT 0 + COUNT 0 + MSG point-12 + ID 12 + PERSON 2 + DAT 2010-03-03 + VAL 6.40 + COUNT 6 + COUNT 12 + COUNT 7 + COUNT 12 + COUNT 0 + COUNT 0 + MSG point-12 + ID 13 + PERSON 3 + DAT 2010-03-04 + VAL 9.40 + COUNT 9 + COUNT 13 + COUNT 10 + COUNT 13 + COUNT 0 + COUNT 0 + MSG point-12 + ID 14 + PERSON 4 + DAT 2010-03-05 + VAL 12.40 + COUNT 12 + COUNT 14 + COUNT 13 + COUNT 14 + COUNT 0 + COUNT 0 + MSG point-12 + ID 15 + PERSON 5 + DAT 2010-03-06 + VAL 15.40 + COUNT 15 + COUNT 15 + COUNT 16 + COUNT 15 + COUNT 0 + COUNT 0 + MSG point-12 + ID 16 + PERSON 1 + DAT + VAL + COUNT 3 + COUNT 15 + COUNT 4 + COUNT 16 + COUNT 0 + COUNT 0 + MSG point-13 + ID 1 + PERSON 1 + DAT 2010-01-03 + VAL 2.30 + SUM 2.30 + SUM 2.30 + COUNT 4 + COUNT 1 + SUM 1 + SUM 1 + MSG point-13 + ID 2 + PERSON 2 + DAT 2010-01-04 + VAL 4.30 + SUM 4.30 + SUM 4.30 + COUNT 3 + COUNT 1 + SUM 2 + SUM 2 + MSG point-13 + ID 3 + PERSON 3 + DAT 2010-01-05 + VAL 6.30 + SUM 6.30 + SUM 6.30 + COUNT 3 + COUNT 1 + SUM 3 + SUM 3 + MSG point-13 + ID 4 + PERSON 4 + DAT 2010-01-06 + VAL 8.30 + SUM 8.30 + SUM 8.30 + COUNT 3 + COUNT 1 + SUM 4 + SUM 4 + MSG point-13 + ID 5 + PERSON 5 + DAT 2010-01-07 + VAL 10.30 + SUM 10.30 + SUM 10.30 + COUNT 3 + COUNT 1 + SUM 5 + SUM 5 + MSG point-13 + ID 6 + PERSON 1 + DAT 2010-02-02 + VAL 3.40 + SUM 3.40 + SUM 3.40 + COUNT 4 + COUNT 2 + SUM 6 + SUM 6 + MSG point-13 + ID 7 + PERSON 2 + DAT 2010-02-03 + VAL 6.40 + SUM 6.40 + SUM 6.40 + COUNT 3 + COUNT 2 + SUM 7 + SUM 7 + MSG point-13 + ID 8 + PERSON 3 + DAT 2010-02-04 + VAL 9.40 + SUM 9.40 + SUM 9.40 + COUNT 3 + COUNT 2 + SUM 8 + SUM 8 + MSG point-13 + ID 9 + PERSON 4 + DAT 2010-02-05 + VAL 12.40 + SUM 12.40 + SUM 12.40 + COUNT 3 + COUNT 2 + SUM 9 + SUM 9 + MSG point-13 + ID 10 + PERSON 5 + DAT 2010-02-06 + VAL 15.40 + SUM 15.40 + SUM 15.40 + COUNT 3 + COUNT 2 + SUM 10 + SUM 10 + MSG point-13 + ID 11 + PERSON 1 + DAT 2010-03-02 + VAL 3.40 + SUM 3.40 + SUM 3.40 + COUNT 4 + COUNT 3 + SUM 11 + SUM 11 + MSG point-13 + ID 12 + PERSON 2 + DAT 2010-03-03 + VAL 6.40 + SUM 6.40 + SUM 6.40 + COUNT 3 + COUNT 3 + SUM 12 + SUM 12 + MSG point-13 + ID 13 + PERSON 3 + DAT 2010-03-04 + VAL 9.40 + SUM 9.40 + SUM 9.40 + COUNT 3 + COUNT 3 + SUM 13 + SUM 13 + MSG point-13 + ID 14 + PERSON 4 + DAT 2010-03-05 + VAL 12.40 + SUM 12.40 + SUM 12.40 + COUNT 3 + COUNT 3 + SUM 14 + SUM 14 + MSG point-13 + ID 15 + PERSON 5 + DAT 2010-03-06 + VAL 15.40 + SUM 15.40 + SUM 15.40 + COUNT 3 + COUNT 3 + SUM 15 + SUM 15 + MSG point-13 + ID 16 + PERSON 1 + DAT + VAL + SUM + SUM + COUNT 4 + COUNT 4 + SUM 16 + SUM 16 + MSG point-14 + ID 1 + PERSON 1 + DAT 2010-01-03 + VAL 2.30 + SUM 31.50 + SUM 15 + SUM 125.50 + SUM 120 + SUM 15.10 + SUM 20 + MSG point-14 + ID 2 + PERSON 2 + DAT 2010-01-04 + VAL 4.30 + SUM 31.50 + SUM 15 + SUM 125.50 + SUM 120 + SUM 23.10 + SUM 23 + MSG point-14 + ID 3 + PERSON 3 + DAT 2010-01-05 + VAL 6.30 + SUM 31.50 + SUM 15 + SUM 125.50 + SUM 120 + SUM 31.10 + SUM 26 + MSG point-14 + ID 4 + PERSON 4 + DAT 2010-01-06 + VAL 8.30 + SUM 31.50 + SUM 15 + SUM 125.50 + SUM 120 + SUM 39.10 + SUM 29 + MSG point-14 + ID 5 + PERSON 5 + DAT 2010-01-07 + VAL 10.30 + SUM 31.50 + SUM 15 + SUM 125.50 + SUM 120 + SUM 10.30 + SUM 5 + MSG point-14 + ID 6 + PERSON 1 + DAT 2010-02-02 + VAL 3.40 + SUM 47.00 + SUM 40 + SUM 125.50 + SUM 120 + SUM 6.80 + SUM 17 + MSG point-14 + ID 7 + PERSON 2 + DAT 2010-02-03 + VAL 6.40 + SUM 47.00 + SUM 40 + SUM 125.50 + SUM 120 + SUM 15.10 + SUM 20 + MSG point-14 + ID 8 + PERSON 3 + DAT 2010-02-04 + VAL 9.40 + SUM 47.00 + SUM 40 + SUM 125.50 + SUM 120 + SUM 23.10 + SUM 23 + MSG point-14 + ID 9 + PERSON 4 + DAT 2010-02-05 + VAL 12.40 + SUM 47.00 + SUM 40 + SUM 125.50 + SUM 120 + SUM 31.10 + SUM 26 + MSG point-14 + ID 10 + PERSON 5 + DAT 2010-02-06 + VAL 15.40 + SUM 47.00 + SUM 40 + SUM 125.50 + SUM 120 + SUM 39.10 + SUM 29 + MSG point-14 + ID 11 + PERSON 1 + DAT 2010-03-02 + VAL 3.40 + SUM 47.00 + SUM 65 + SUM 125.50 + SUM 120 + SUM 6.80 + SUM 17 + MSG point-14 + ID 12 + PERSON 2 + DAT 2010-03-03 + VAL 6.40 + SUM 47.00 + SUM 65 + SUM 125.50 + SUM 120 + SUM 15.10 + SUM 20 + MSG point-14 + ID 13 + PERSON 3 + DAT 2010-03-04 + VAL 9.40 + SUM 47.00 + SUM 65 + SUM 125.50 + SUM 120 + SUM 23.10 + SUM 23 + MSG point-14 + ID 14 + PERSON 4 + DAT 2010-03-05 + VAL 12.40 + SUM 47.00 + SUM 65 + SUM 125.50 + SUM 120 + SUM 31.10 + SUM 26 + MSG point-14 + ID 15 + PERSON 5 + DAT 2010-03-06 + VAL 15.40 + SUM 47.00 + SUM 65 + SUM 125.50 + SUM 120 + SUM 39.10 + SUM 29 + MSG point-14 + ID 16 + PERSON 1 + DAT + VAL + SUM + SUM 16 + SUM + SUM 16 + SUM + SUM 16 + MSG point-15 + ID 1 + PERSON 1 + DAT 2010-01-03 + VAL 2.30 + MIN 1 + MAX 5 + MIN 2.30 + MAX 10.30 + MSG point-15 + ID 2 + PERSON 2 + DAT 2010-01-04 + VAL 4.30 + MIN 1 + MAX 5 + MIN 2.30 + MAX 10.30 + MSG point-15 + ID 3 + PERSON 3 + DAT 2010-01-05 + VAL 6.30 + MIN 1 + MAX 5 + MIN 2.30 + MAX 10.30 + MSG point-15 + ID 4 + PERSON 4 + DAT 2010-01-06 + VAL 8.30 + MIN 1 + MAX 5 + MIN 2.30 + MAX 10.30 + MSG point-15 + ID 5 + PERSON 5 + DAT 2010-01-07 + VAL 10.30 + MIN 1 + MAX 5 + MIN 2.30 + MAX 10.30 + MSG point-15 + ID 6 + PERSON 1 + DAT 2010-02-02 + VAL 3.40 + MIN 6 + MAX 10 + MIN 3.40 + MAX 15.40 + MSG point-15 + ID 7 + PERSON 2 + DAT 2010-02-03 + VAL 6.40 + MIN 6 + MAX 10 + MIN 3.40 + MAX 15.40 + MSG point-15 + ID 8 + PERSON 3 + DAT 2010-02-04 + VAL 9.40 + MIN 6 + MAX 10 + MIN 3.40 + MAX 15.40 + MSG point-15 + ID 9 + PERSON 4 + DAT 2010-02-05 + VAL 12.40 + MIN 6 + MAX 10 + MIN 3.40 + MAX 15.40 + MSG point-15 + ID 10 + PERSON 5 + DAT 2010-02-06 + VAL 15.40 + MIN 6 + MAX 10 + MIN 3.40 + MAX 15.40 + MSG point-15 + ID 11 + PERSON 1 + DAT 2010-03-02 + VAL 3.40 + MIN 11 + MAX 15 + MIN 3.40 + MAX 15.40 + MSG point-15 + ID 12 + PERSON 2 + DAT 2010-03-03 + VAL 6.40 + MIN 11 + MAX 15 + MIN 3.40 + MAX 15.40 + MSG point-15 + ID 13 + PERSON 3 + DAT 2010-03-04 + VAL 9.40 + MIN 11 + MAX 15 + MIN 3.40 + MAX 15.40 + MSG point-15 + ID 14 + PERSON 4 + DAT 2010-03-05 + VAL 12.40 + MIN 11 + MAX 15 + MIN 3.40 + MAX 15.40 + MSG point-15 + ID 15 + PERSON 5 + DAT 2010-03-06 + VAL 15.40 + MIN 11 + MAX 15 + MIN 3.40 + MAX 15.40 + MSG point-15 + ID 16 + PERSON 1 + DAT + VAL + MIN 16 + MAX 16 + MIN + MAX + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_window_func_02_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/gtcs/test_window_func_03.py b/tests/functional/gtcs/test_window_func_03.py new file mode 100644 index 00000000..d6c2e2e5 --- /dev/null +++ b/tests/functional/gtcs/test_window_func_03.py @@ -0,0 +1,599 @@ +#coding:utf-8 +# +# id: functional.gtcs.window_func_03 +# title: GTCS/tests/FB_SQL_WINDOW_FUNC_03 - set of miscelaneous tests for verification of windowed functions. +# decription: +# Statements from this test are added to initial SQL which is stored in: ... +# bt-repo +# iles\\gtcs-window-func.sql +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/FB_SQL_WINDOW_FUNC_03.script +# +# Checked on 4.0.0.1854; 3.0.6.33277 +# +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# with open( os.path.join(context['files_location'],'gtcs-window-func.sql'), 'r') as f: +# sql_init = f.read() +# +# sql_addi=''' +# set list on; +# +# select +# 'point-01' as msg, +# p.*, +# dense_rank() over (order by id), +# dense_rank() over (order by id desc), +# rank() over (order by id), +# rank() over (order by id desc), +# row_number() over (order by id), +# row_number() over (order by id desc) +# from persons p +# order by id; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-02' as msg, +# e.*, +# dense_rank() over (order by val nulls first), +# rank() over (order by val nulls first), +# row_number() over (order by val nulls first) +# from entries e +# order by id; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-03' as msg, +# e.*, +# dense_rank() over (partition by person order by val nulls first, dat nulls first), +# rank() over (partition by person order by val nulls first, dat nulls first), +# row_number() over (partition by person order by val nulls first, dat nulls first) +# from entries e +# order by id; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-04' as msg, +# person, +# sum(dr), +# sum(r), +# sum(rn) +# from ( +# select +# e.*, +# dense_rank() over (partition by person) dr, +# rank() over (partition by person) r, +# row_number() over (partition by person) rn +# from entries e +# ) x +# group by +# person +# order by person; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-05' as msg, +# sum(dr), +# sum(r), +# sum(rn) +# from ( +# select +# e.*, +# dense_rank() over (partition by person) dr, +# rank() over (partition by person) r, +# row_number() over (partition by person) rn +# from entries e +# ) x; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-06' as msg, +# id, +# person, +# dat, +# val, +# sum(rn) srn, +# row_number() over (order by id) +# from ( +# select +# e.*, +# row_number() over (partition by person order by id) rn +# from entries e +# ) x +# group by +# id, +# person, +# dat, +# val +# order by id; +# ''' +# +# runProgram('isql', [ dsn], os.linesep.join( (sql_init, sql_addi) ) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG point-01 + ID 1 + NAME Person 1 + DENSE_RANK 1 + DENSE_RANK 5 + RANK 1 + RANK 5 + ROW_NUMBER 1 + ROW_NUMBER 5 + MSG point-01 + ID 2 + NAME Person 2 + DENSE_RANK 2 + DENSE_RANK 4 + RANK 2 + RANK 4 + ROW_NUMBER 2 + ROW_NUMBER 4 + MSG point-01 + ID 3 + NAME Person 3 + DENSE_RANK 3 + DENSE_RANK 3 + RANK 3 + RANK 3 + ROW_NUMBER 3 + ROW_NUMBER 3 + MSG point-01 + ID 4 + NAME Person 4 + DENSE_RANK 4 + DENSE_RANK 2 + RANK 4 + RANK 2 + ROW_NUMBER 4 + ROW_NUMBER 2 + MSG point-01 + ID 5 + NAME Person 5 + DENSE_RANK 5 + DENSE_RANK 1 + RANK 5 + RANK 1 + ROW_NUMBER 5 + ROW_NUMBER 1 + MSG point-02 + ID 1 + PERSON 1 + DAT 2010-01-03 + VAL 2.30 + DENSE_RANK 2 + RANK 2 + ROW_NUMBER 2 + MSG point-02 + ID 2 + PERSON 2 + DAT 2010-01-04 + VAL 4.30 + DENSE_RANK 4 + RANK 5 + ROW_NUMBER 5 + MSG point-02 + ID 3 + PERSON 3 + DAT 2010-01-05 + VAL 6.30 + DENSE_RANK 5 + RANK 6 + ROW_NUMBER 6 + MSG point-02 + ID 4 + PERSON 4 + DAT 2010-01-06 + VAL 8.30 + DENSE_RANK 7 + RANK 9 + ROW_NUMBER 9 + MSG point-02 + ID 5 + PERSON 5 + DAT 2010-01-07 + VAL 10.30 + DENSE_RANK 9 + RANK 12 + ROW_NUMBER 12 + MSG point-02 + ID 6 + PERSON 1 + DAT 2010-02-02 + VAL 3.40 + DENSE_RANK 3 + RANK 3 + ROW_NUMBER 3 + MSG point-02 + ID 7 + PERSON 2 + DAT 2010-02-03 + VAL 6.40 + DENSE_RANK 6 + RANK 7 + ROW_NUMBER 7 + MSG point-02 + ID 8 + PERSON 3 + DAT 2010-02-04 + VAL 9.40 + DENSE_RANK 8 + RANK 10 + ROW_NUMBER 10 + MSG point-02 + ID 9 + PERSON 4 + DAT 2010-02-05 + VAL 12.40 + DENSE_RANK 10 + RANK 13 + ROW_NUMBER 13 + MSG point-02 + ID 10 + PERSON 5 + DAT 2010-02-06 + VAL 15.40 + DENSE_RANK 11 + RANK 15 + ROW_NUMBER 15 + MSG point-02 + ID 11 + PERSON 1 + DAT 2010-03-02 + VAL 3.40 + DENSE_RANK 3 + RANK 3 + ROW_NUMBER 4 + MSG point-02 + ID 12 + PERSON 2 + DAT 2010-03-03 + VAL 6.40 + DENSE_RANK 6 + RANK 7 + ROW_NUMBER 8 + MSG point-02 + ID 13 + PERSON 3 + DAT 2010-03-04 + VAL 9.40 + DENSE_RANK 8 + RANK 10 + ROW_NUMBER 11 + MSG point-02 + ID 14 + PERSON 4 + DAT 2010-03-05 + VAL 12.40 + DENSE_RANK 10 + RANK 13 + ROW_NUMBER 14 + MSG point-02 + ID 15 + PERSON 5 + DAT 2010-03-06 + VAL 15.40 + DENSE_RANK 11 + RANK 15 + ROW_NUMBER 16 + MSG point-02 + ID 16 + PERSON 1 + DAT + VAL + DENSE_RANK 1 + RANK 1 + ROW_NUMBER 1 + MSG point-03 + ID 1 + PERSON 1 + DAT 2010-01-03 + VAL 2.30 + DENSE_RANK 2 + RANK 2 + ROW_NUMBER 2 + MSG point-03 + ID 2 + PERSON 2 + DAT 2010-01-04 + VAL 4.30 + DENSE_RANK 1 + RANK 1 + ROW_NUMBER 1 + MSG point-03 + ID 3 + PERSON 3 + DAT 2010-01-05 + VAL 6.30 + DENSE_RANK 1 + RANK 1 + ROW_NUMBER 1 + MSG point-03 + ID 4 + PERSON 4 + DAT 2010-01-06 + VAL 8.30 + DENSE_RANK 1 + RANK 1 + ROW_NUMBER 1 + MSG point-03 + ID 5 + PERSON 5 + DAT 2010-01-07 + VAL 10.30 + DENSE_RANK 1 + RANK 1 + ROW_NUMBER 1 + MSG point-03 + ID 6 + PERSON 1 + DAT 2010-02-02 + VAL 3.40 + DENSE_RANK 3 + RANK 3 + ROW_NUMBER 3 + MSG point-03 + ID 7 + PERSON 2 + DAT 2010-02-03 + VAL 6.40 + DENSE_RANK 2 + RANK 2 + ROW_NUMBER 2 + MSG point-03 + ID 8 + PERSON 3 + DAT 2010-02-04 + VAL 9.40 + DENSE_RANK 2 + RANK 2 + ROW_NUMBER 2 + MSG point-03 + ID 9 + PERSON 4 + DAT 2010-02-05 + VAL 12.40 + DENSE_RANK 2 + RANK 2 + ROW_NUMBER 2 + MSG point-03 + ID 10 + PERSON 5 + DAT 2010-02-06 + VAL 15.40 + DENSE_RANK 2 + RANK 2 + ROW_NUMBER 2 + MSG point-03 + ID 11 + PERSON 1 + DAT 2010-03-02 + VAL 3.40 + DENSE_RANK 4 + RANK 4 + ROW_NUMBER 4 + MSG point-03 + ID 12 + PERSON 2 + DAT 2010-03-03 + VAL 6.40 + DENSE_RANK 3 + RANK 3 + ROW_NUMBER 3 + MSG point-03 + ID 13 + PERSON 3 + DAT 2010-03-04 + VAL 9.40 + DENSE_RANK 3 + RANK 3 + ROW_NUMBER 3 + MSG point-03 + ID 14 + PERSON 4 + DAT 2010-03-05 + VAL 12.40 + DENSE_RANK 3 + RANK 3 + ROW_NUMBER 3 + MSG point-03 + ID 15 + PERSON 5 + DAT 2010-03-06 + VAL 15.40 + DENSE_RANK 3 + RANK 3 + ROW_NUMBER 3 + MSG point-03 + ID 16 + PERSON 1 + DAT + VAL + DENSE_RANK 1 + RANK 1 + ROW_NUMBER 1 + MSG point-04 + PERSON 1 + SUM 4 + SUM 4 + SUM 10 + MSG point-04 + PERSON 2 + SUM 3 + SUM 3 + SUM 6 + MSG point-04 + PERSON 3 + SUM 3 + SUM 3 + SUM 6 + MSG point-04 + PERSON 4 + SUM 3 + SUM 3 + SUM 6 + MSG point-04 + PERSON 5 + SUM 3 + SUM 3 + SUM 6 + MSG point-05 + SUM 16 + SUM 16 + SUM 34 + MSG point-06 + ID 1 + PERSON 1 + DAT 2010-01-03 + VAL 2.30 + SRN 1 + ROW_NUMBER 1 + MSG point-06 + ID 2 + PERSON 2 + DAT 2010-01-04 + VAL 4.30 + SRN 1 + ROW_NUMBER 2 + MSG point-06 + ID 3 + PERSON 3 + DAT 2010-01-05 + VAL 6.30 + SRN 1 + ROW_NUMBER 3 + MSG point-06 + ID 4 + PERSON 4 + DAT 2010-01-06 + VAL 8.30 + SRN 1 + ROW_NUMBER 4 + MSG point-06 + ID 5 + PERSON 5 + DAT 2010-01-07 + VAL 10.30 + SRN 1 + ROW_NUMBER 5 + MSG point-06 + ID 6 + PERSON 1 + DAT 2010-02-02 + VAL 3.40 + SRN 2 + ROW_NUMBER 6 + MSG point-06 + ID 7 + PERSON 2 + DAT 2010-02-03 + VAL 6.40 + SRN 2 + ROW_NUMBER 7 + MSG point-06 + ID 8 + PERSON 3 + DAT 2010-02-04 + VAL 9.40 + SRN 2 + ROW_NUMBER 8 + MSG point-06 + ID 9 + PERSON 4 + DAT 2010-02-05 + VAL 12.40 + SRN 2 + ROW_NUMBER 9 + MSG point-06 + ID 10 + PERSON 5 + DAT 2010-02-06 + VAL 15.40 + SRN 2 + ROW_NUMBER 10 + MSG point-06 + ID 11 + PERSON 1 + DAT 2010-03-02 + VAL 3.40 + SRN 3 + ROW_NUMBER 11 + MSG point-06 + ID 12 + PERSON 2 + DAT 2010-03-03 + VAL 6.40 + SRN 3 + ROW_NUMBER 12 + MSG point-06 + ID 13 + PERSON 3 + DAT 2010-03-04 + VAL 9.40 + SRN 3 + ROW_NUMBER 13 + MSG point-06 + ID 14 + PERSON 4 + DAT 2010-03-05 + VAL 12.40 + SRN 3 + ROW_NUMBER 14 + MSG point-06 + ID 15 + PERSON 5 + DAT 2010-03-06 + VAL 15.40 + SRN 3 + ROW_NUMBER 15 + MSG point-06 + ID 16 + PERSON 1 + DAT + VAL + SRN 4 + ROW_NUMBER 16 + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_window_func_03_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/gtcs/test_window_func_04.py b/tests/functional/gtcs/test_window_func_04.py new file mode 100644 index 00000000..106739e7 --- /dev/null +++ b/tests/functional/gtcs/test_window_func_04.py @@ -0,0 +1,672 @@ +#coding:utf-8 +# +# id: functional.gtcs.window_func_04 +# title: GTCS/tests/FB_SQL_WINDOW_FUNC_04 - set of miscelaneous tests for verification of windowed functions. +# decription: +# Statements from this test are added to initial SQL which is stored in: ... +# bt-repo +# iles\\gtcs-window-func.sql +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/FB_SQL_WINDOW_FUNC_04.script +# +# Checked on 4.0.0.1854; 3.0.6.33277 +# +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# with open( os.path.join(context['files_location'],'gtcs-window-func.sql'), 'r') as f: +# sql_init = f.read() +# +# sql_addi=''' +# set list on; +# +# select +# 'point-1' as msg, +# e.*, +# first_value(val) over (order by val nulls first, id), +# first_value(val) over (order by val nulls last, id), +# first_value(val) over (partition by e.person order by val nulls last, id), +# nth_value(val, 1) over (order by val nulls first, id), +# nth_value(val, 1) over (order by val nulls last, id), +# nth_value(val, 1) over (partition by e.person order by val nulls last, id), +# nth_value(val, 2) over (order by val nulls first, id), +# nth_value(val, 2) over (order by val nulls last, id), +# nth_value(val, 2) over (partition by e.person order by val nulls last, id), +# last_value(val) over (order by val nulls first, id), +# last_value(val) over (order by val nulls last, id), +# last_value(val) over (partition by e.person order by val nulls last, id) +# from entries e +# order by id; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-2' as msg, +# person, +# sum(val), +# first_value(sum(val)) over (order by person desc), +# nth_value(sum(val), 1) over (order by person desc), +# nth_value(sum(val), 2) over (order by person desc), +# last_value(sum(val)) over (order by person desc) +# from entries +# group by person +# order by person; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-3' as msg, +# e.*, +# lag(val) over (order by val nulls first, id), +# lead(val) over (order by val nulls first, id), +# lag(val, 2) over (order by val nulls first, id), +# lead(val, 3) over (order by val nulls first, id), +# lag(val, 1, -val) over (order by val nulls first, id), +# lag(val, 2, -val) over (order by val nulls first, id), +# lead(val, 3, -1.00) over (order by val nulls first, id) +# from entries e +# order by id; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-4' as msg, +# person, +# sum(val), +# lag(sum(val)) over (order by person), +# lead(sum(val)) over (order by person), +# lag(sum(val), 2) over (order by person), +# lead(sum(val), 3) over (order by person), +# lag(sum(val), 2, -sum(val)) over (order by person), +# lead(sum(val), 3, -1.00) over (order by person) +# from entries +# group by person +# order by person; +# +# ''' +# +# runProgram('isql', [ dsn], os.linesep.join( (sql_init, sql_addi) ) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG point-1 + ID 1 + PERSON 1 + DAT 2010-01-03 + VAL 2.30 + FIRST_VALUE + FIRST_VALUE 2.30 + FIRST_VALUE 2.30 + NTH_VALUE + NTH_VALUE 2.30 + NTH_VALUE 2.30 + NTH_VALUE 2.30 + NTH_VALUE + NTH_VALUE + LAST_VALUE 2.30 + LAST_VALUE 2.30 + LAST_VALUE 2.30 + MSG point-1 + ID 2 + PERSON 2 + DAT 2010-01-04 + VAL 4.30 + FIRST_VALUE + FIRST_VALUE 2.30 + FIRST_VALUE 4.30 + NTH_VALUE + NTH_VALUE 2.30 + NTH_VALUE 4.30 + NTH_VALUE 2.30 + NTH_VALUE 3.40 + NTH_VALUE + LAST_VALUE 4.30 + LAST_VALUE 4.30 + LAST_VALUE 4.30 + MSG point-1 + ID 3 + PERSON 3 + DAT 2010-01-05 + VAL 6.30 + FIRST_VALUE + FIRST_VALUE 2.30 + FIRST_VALUE 6.30 + NTH_VALUE + NTH_VALUE 2.30 + NTH_VALUE 6.30 + NTH_VALUE 2.30 + NTH_VALUE 3.40 + NTH_VALUE + LAST_VALUE 6.30 + LAST_VALUE 6.30 + LAST_VALUE 6.30 + MSG point-1 + ID 4 + PERSON 4 + DAT 2010-01-06 + VAL 8.30 + FIRST_VALUE + FIRST_VALUE 2.30 + FIRST_VALUE 8.30 + NTH_VALUE + NTH_VALUE 2.30 + NTH_VALUE 8.30 + NTH_VALUE 2.30 + NTH_VALUE 3.40 + NTH_VALUE + LAST_VALUE 8.30 + LAST_VALUE 8.30 + LAST_VALUE 8.30 + MSG point-1 + ID 5 + PERSON 5 + DAT 2010-01-07 + VAL 10.30 + FIRST_VALUE + FIRST_VALUE 2.30 + FIRST_VALUE 10.30 + NTH_VALUE + NTH_VALUE 2.30 + NTH_VALUE 10.30 + NTH_VALUE 2.30 + NTH_VALUE 3.40 + NTH_VALUE + LAST_VALUE 10.30 + LAST_VALUE 10.30 + LAST_VALUE 10.30 + MSG point-1 + ID 6 + PERSON 1 + DAT 2010-02-02 + VAL 3.40 + FIRST_VALUE + FIRST_VALUE 2.30 + FIRST_VALUE 2.30 + NTH_VALUE + NTH_VALUE 2.30 + NTH_VALUE 2.30 + NTH_VALUE 2.30 + NTH_VALUE 3.40 + NTH_VALUE 3.40 + LAST_VALUE 3.40 + LAST_VALUE 3.40 + LAST_VALUE 3.40 + MSG point-1 + ID 7 + PERSON 2 + DAT 2010-02-03 + VAL 6.40 + FIRST_VALUE + FIRST_VALUE 2.30 + FIRST_VALUE 4.30 + NTH_VALUE + NTH_VALUE 2.30 + NTH_VALUE 4.30 + NTH_VALUE 2.30 + NTH_VALUE 3.40 + NTH_VALUE 6.40 + LAST_VALUE 6.40 + LAST_VALUE 6.40 + LAST_VALUE 6.40 + MSG point-1 + ID 8 + PERSON 3 + DAT 2010-02-04 + VAL 9.40 + FIRST_VALUE + FIRST_VALUE 2.30 + FIRST_VALUE 6.30 + NTH_VALUE + NTH_VALUE 2.30 + NTH_VALUE 6.30 + NTH_VALUE 2.30 + NTH_VALUE 3.40 + NTH_VALUE 9.40 + LAST_VALUE 9.40 + LAST_VALUE 9.40 + LAST_VALUE 9.40 + MSG point-1 + ID 9 + PERSON 4 + DAT 2010-02-05 + VAL 12.40 + FIRST_VALUE + FIRST_VALUE 2.30 + FIRST_VALUE 8.30 + NTH_VALUE + NTH_VALUE 2.30 + NTH_VALUE 8.30 + NTH_VALUE 2.30 + NTH_VALUE 3.40 + NTH_VALUE 12.40 + LAST_VALUE 12.40 + LAST_VALUE 12.40 + LAST_VALUE 12.40 + MSG point-1 + ID 10 + PERSON 5 + DAT 2010-02-06 + VAL 15.40 + FIRST_VALUE + FIRST_VALUE 2.30 + FIRST_VALUE 10.30 + NTH_VALUE + NTH_VALUE 2.30 + NTH_VALUE 10.30 + NTH_VALUE 2.30 + NTH_VALUE 3.40 + NTH_VALUE 15.40 + LAST_VALUE 15.40 + LAST_VALUE 15.40 + LAST_VALUE 15.40 + MSG point-1 + ID 11 + PERSON 1 + DAT 2010-03-02 + VAL 3.40 + FIRST_VALUE + FIRST_VALUE 2.30 + FIRST_VALUE 2.30 + NTH_VALUE + NTH_VALUE 2.30 + NTH_VALUE 2.30 + NTH_VALUE 2.30 + NTH_VALUE 3.40 + NTH_VALUE 3.40 + LAST_VALUE 3.40 + LAST_VALUE 3.40 + LAST_VALUE 3.40 + MSG point-1 + ID 12 + PERSON 2 + DAT 2010-03-03 + VAL 6.40 + FIRST_VALUE + FIRST_VALUE 2.30 + FIRST_VALUE 4.30 + NTH_VALUE + NTH_VALUE 2.30 + NTH_VALUE 4.30 + NTH_VALUE 2.30 + NTH_VALUE 3.40 + NTH_VALUE 6.40 + LAST_VALUE 6.40 + LAST_VALUE 6.40 + LAST_VALUE 6.40 + MSG point-1 + ID 13 + PERSON 3 + DAT 2010-03-04 + VAL 9.40 + FIRST_VALUE + FIRST_VALUE 2.30 + FIRST_VALUE 6.30 + NTH_VALUE + NTH_VALUE 2.30 + NTH_VALUE 6.30 + NTH_VALUE 2.30 + NTH_VALUE 3.40 + NTH_VALUE 9.40 + LAST_VALUE 9.40 + LAST_VALUE 9.40 + LAST_VALUE 9.40 + MSG point-1 + ID 14 + PERSON 4 + DAT 2010-03-05 + VAL 12.40 + FIRST_VALUE + FIRST_VALUE 2.30 + FIRST_VALUE 8.30 + NTH_VALUE + NTH_VALUE 2.30 + NTH_VALUE 8.30 + NTH_VALUE 2.30 + NTH_VALUE 3.40 + NTH_VALUE 12.40 + LAST_VALUE 12.40 + LAST_VALUE 12.40 + LAST_VALUE 12.40 + MSG point-1 + ID 15 + PERSON 5 + DAT 2010-03-06 + VAL 15.40 + FIRST_VALUE + FIRST_VALUE 2.30 + FIRST_VALUE 10.30 + NTH_VALUE + NTH_VALUE 2.30 + NTH_VALUE 10.30 + NTH_VALUE 2.30 + NTH_VALUE 3.40 + NTH_VALUE 15.40 + LAST_VALUE 15.40 + LAST_VALUE 15.40 + LAST_VALUE 15.40 + MSG point-1 + ID 16 + PERSON 1 + DAT + VAL + FIRST_VALUE + FIRST_VALUE 2.30 + FIRST_VALUE 2.30 + NTH_VALUE + NTH_VALUE 2.30 + NTH_VALUE 2.30 + NTH_VALUE + NTH_VALUE 3.40 + NTH_VALUE 3.40 + LAST_VALUE + LAST_VALUE + LAST_VALUE + MSG point-2 + PERSON 1 + SUM 9.10 + FIRST_VALUE 41.10 + NTH_VALUE 41.10 + NTH_VALUE 33.10 + LAST_VALUE 9.10 + MSG point-2 + PERSON 2 + SUM 17.10 + FIRST_VALUE 41.10 + NTH_VALUE 41.10 + NTH_VALUE 33.10 + LAST_VALUE 17.10 + MSG point-2 + PERSON 3 + SUM 25.10 + FIRST_VALUE 41.10 + NTH_VALUE 41.10 + NTH_VALUE 33.10 + LAST_VALUE 25.10 + MSG point-2 + PERSON 4 + SUM 33.10 + FIRST_VALUE 41.10 + NTH_VALUE 41.10 + NTH_VALUE 33.10 + LAST_VALUE 33.10 + MSG point-2 + PERSON 5 + SUM 41.10 + FIRST_VALUE 41.10 + NTH_VALUE 41.10 + NTH_VALUE + LAST_VALUE 41.10 + MSG point-3 + ID 1 + PERSON 1 + DAT 2010-01-03 + VAL 2.30 + LAG + LEAD 3.40 + LAG + LEAD 4.30 + LAG + LAG -2.30 + LEAD 4.30 + MSG point-3 + ID 2 + PERSON 2 + DAT 2010-01-04 + VAL 4.30 + LAG 3.40 + LEAD 6.30 + LAG 3.40 + LEAD 6.40 + LAG 3.40 + LAG 3.40 + LEAD 6.40 + MSG point-3 + ID 3 + PERSON 3 + DAT 2010-01-05 + VAL 6.30 + LAG 4.30 + LEAD 6.40 + LAG 3.40 + LEAD 8.30 + LAG 4.30 + LAG 3.40 + LEAD 8.30 + MSG point-3 + ID 4 + PERSON 4 + DAT 2010-01-06 + VAL 8.30 + LAG 6.40 + LEAD 9.40 + LAG 6.40 + LEAD 10.30 + LAG 6.40 + LAG 6.40 + LEAD 10.30 + MSG point-3 + ID 5 + PERSON 5 + DAT 2010-01-07 + VAL 10.30 + LAG 9.40 + LEAD 12.40 + LAG 9.40 + LEAD 15.40 + LAG 9.40 + LAG 9.40 + LEAD 15.40 + MSG point-3 + ID 6 + PERSON 1 + DAT 2010-02-02 + VAL 3.40 + LAG 2.30 + LEAD 3.40 + LAG + LEAD 6.30 + LAG 2.30 + LAG + LEAD 6.30 + MSG point-3 + ID 7 + PERSON 2 + DAT 2010-02-03 + VAL 6.40 + LAG 6.30 + LEAD 6.40 + LAG 4.30 + LEAD 9.40 + LAG 6.30 + LAG 4.30 + LEAD 9.40 + MSG point-3 + ID 8 + PERSON 3 + DAT 2010-02-04 + VAL 9.40 + LAG 8.30 + LEAD 9.40 + LAG 6.40 + LEAD 12.40 + LAG 8.30 + LAG 6.40 + LEAD 12.40 + MSG point-3 + ID 9 + PERSON 4 + DAT 2010-02-05 + VAL 12.40 + LAG 10.30 + LEAD 12.40 + LAG 9.40 + LEAD 15.40 + LAG 10.30 + LAG 9.40 + LEAD 15.40 + MSG point-3 + ID 10 + PERSON 5 + DAT 2010-02-06 + VAL 15.40 + LAG 12.40 + LEAD 15.40 + LAG 12.40 + LEAD + LAG 12.40 + LAG 12.40 + LEAD -1.00 + MSG point-3 + ID 11 + PERSON 1 + DAT 2010-03-02 + VAL 3.40 + LAG 3.40 + LEAD 4.30 + LAG 2.30 + LEAD 6.40 + LAG 3.40 + LAG 2.30 + LEAD 6.40 + MSG point-3 + ID 12 + PERSON 2 + DAT 2010-03-03 + VAL 6.40 + LAG 6.40 + LEAD 8.30 + LAG 6.30 + LEAD 9.40 + LAG 6.40 + LAG 6.30 + LEAD 9.40 + MSG point-3 + ID 13 + PERSON 3 + DAT 2010-03-04 + VAL 9.40 + LAG 9.40 + LEAD 10.30 + LAG 8.30 + LEAD 12.40 + LAG 9.40 + LAG 8.30 + LEAD 12.40 + MSG point-3 + ID 14 + PERSON 4 + DAT 2010-03-05 + VAL 12.40 + LAG 12.40 + LEAD 15.40 + LAG 10.30 + LEAD + LAG 12.40 + LAG 10.30 + LEAD -1.00 + MSG point-3 + ID 15 + PERSON 5 + DAT 2010-03-06 + VAL 15.40 + LAG 15.40 + LEAD + LAG 12.40 + LEAD + LAG 15.40 + LAG 12.40 + LEAD -1.00 + MSG point-3 + ID 16 + PERSON 1 + DAT + VAL + LAG + LEAD 2.30 + LAG + LEAD 3.40 + LAG + LAG + LEAD 3.40 + MSG point-4 + PERSON 1 + SUM 9.10 + LAG + LEAD 17.10 + LAG + LEAD 33.10 + LAG -9.10 + LEAD 33.10 + MSG point-4 + PERSON 2 + SUM 17.10 + LAG 9.10 + LEAD 25.10 + LAG + LEAD 41.10 + LAG -17.10 + LEAD 41.10 + MSG point-4 + PERSON 3 + SUM 25.10 + LAG 17.10 + LEAD 33.10 + LAG 9.10 + LEAD + LAG 9.10 + LEAD -1.00 + MSG point-4 + PERSON 4 + SUM 33.10 + LAG 25.10 + LEAD 41.10 + LAG 17.10 + LEAD + LAG 17.10 + LEAD -1.00 + MSG point-4 + PERSON 5 + SUM 41.10 + LAG 33.10 + LEAD + LAG 25.10 + LEAD + LAG 25.10 + LEAD -1.00 + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_window_func_04_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/gtcs/test_window_func_05.py b/tests/functional/gtcs/test_window_func_05.py new file mode 100644 index 00000000..967377e1 --- /dev/null +++ b/tests/functional/gtcs/test_window_func_05.py @@ -0,0 +1,1964 @@ +#coding:utf-8 +# +# id: functional.gtcs.window_func_05 +# title: GTCS/tests/FB_SQL_WINDOW_FUNC_05 - set of miscelaneous tests for verification of windowed functions. +# decription: +# Statements from this test are added to initial SQL which is stored in: ... +# bt-repo +# iles\\gtcs-window-func.sql +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/FB_SQL_WINDOW_FUNC_05.script +# +# ::: NB ::: This test used functionality that exists in FB 4.0+. +# +# Checked on 4.0.0.1854. +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# +# # NOT NEEDED FOR THIS TEST: +# ########################### +# # with open( os.path.join(context['files_location'],'gtcs-window-func.sql'), 'r') as f: +# # sql_init = f.read() +# +# sql_init = '' +# sql_addi=''' +# set list on; +# +# recreate table t1 ( +# n1 integer, +# n2 integer +# ); +# commit; +# +# insert into t1 values (null, 100000); +# insert into t1 values (null, 1000); +# insert into t1 values (1, 1); +# insert into t1 values (1, 10); +# insert into t1 values (1, 100); +# insert into t1 values (1, 10000); +# insert into t1 values (2, 20); +# insert into t1 values (3, 300); +# insert into t1 values (5, 500); +# insert into t1 values (null, 50); +# insert into t1 values (null, 60); +# commit; +# +# select +# 'point-01' as msg, +# n1, +# n2, +# sum(n2) over (partition by n1 order by n2 range between unbounded preceding and current row) x1, +# sum(n2) over (partition by n1 order by n2 range between current row and unbounded following) x2, +# sum(n2) over (partition by n1 order by n2 range between current row and current row) x3, +# sum(n2) over (partition by n1 order by n2 range between 2 following and 3 following) x4, +# sum(n2) over (partition by n1 order by n2 range between 3 preceding and 2 preceding) x5, +# sum(n2) over (partition by n1 order by n2 range between 3 preceding and unbounded following) x6 +# from t1 +# order by n2, n1; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-02' as msg, +# n1, +# n2, +# sum(n2) over (partition by n1 order by n2, n1 rows between unbounded preceding and current row) x1, +# sum(n2) over (partition by n1 order by n2, n1 rows between current row and unbounded following) x2, +# sum(n2) over (partition by n1 order by n2, n1 rows between current row and current row) x3, +# sum(n2) over (partition by n1 order by n2, n1 rows between 2 following and 3 following) x4, +# sum(n2) over (partition by n1 order by n2, n1 rows between 3 preceding and 2 preceding) x5, +# sum(n2) over (partition by n1 order by n2, n1 rows between 3 preceding and unbounded following) x6 +# from t1 +# order by n2, n1; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-03' as msg, +# n1, +# n2, +# sum(n2) over (order by n1 range between unbounded preceding and current row) x1, +# sum(n2) over (order by n1 range between current row and unbounded following) x2, +# sum(n2) over (order by n1 range between current row and current row) x3, +# sum(n2) over (order by n1 range between 2 following and 3 following) x4, +# sum(n2) over (order by n1 range between 3 preceding and 2 preceding) x5, +# sum(n2) over (order by n1 range between 3 preceding and unbounded following) x6 +# from t1 +# order by n1, n2; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-04' as msg, +# n1, +# n2, +# sum(n2) over (order by n1, n2 rows between unbounded preceding and current row) x1, +# sum(n2) over (order by n1, n2 rows between current row and unbounded following) x2, +# sum(n2) over (order by n1, n2 rows between current row and current row) x3, +# sum(n2) over (order by n1, n2 rows between 2 following and 3 following) x4, +# sum(n2) over (order by n1, n2 rows between 3 preceding and 2 preceding) x5, +# sum(n2) over (order by n1, n2 rows between 3 preceding and unbounded following) x6 +# from t1 +# order by n1, n2; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-05' as msg, +# n1, +# n2, +# sum(n2) over (order by n1 nulls first range between unbounded preceding and current row) x1, +# sum(n2) over (order by n1 nulls first range between current row and unbounded following) x2, +# sum(n2) over (order by n1 nulls first range between current row and current row) x3, +# sum(n2) over (order by n1 nulls first range between 2 following and 3 following) x4, +# sum(n2) over (order by n1 nulls first range between 3 preceding and 2 preceding) x5, +# sum(n2) over (order by n1 nulls first range between 3 preceding and unbounded following) x6 +# from t1 +# order by n1 nulls first, n2; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-06' as msg, +# n1, +# n2, +# sum(n2) over (order by n1 nulls first, n2 rows between unbounded preceding and current row) x1, +# sum(n2) over (order by n1 nulls first, n2 rows between current row and unbounded following) x2, +# sum(n2) over (order by n1 nulls first, n2 rows between current row and current row) x3, +# sum(n2) over (order by n1 nulls first, n2 rows between 2 following and 3 following) x4, +# sum(n2) over (order by n1 nulls first, n2 rows between 3 preceding and 2 preceding) x5, +# sum(n2) over (order by n1 nulls first, n2 rows between 3 preceding and unbounded following) x6 +# from t1 +# order by n1 nulls first, n2; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-07' as msg, +# n1, +# n2, +# sum(n2) over (order by n1 nulls last range between unbounded preceding and current row) x1, +# sum(n2) over (order by n1 nulls last range between current row and unbounded following) x2, +# sum(n2) over (order by n1 nulls last range between current row and current row) x3, +# sum(n2) over (order by n1 nulls last range between 2 following and 3 following) x4, +# sum(n2) over (order by n1 nulls last range between 3 preceding and 2 preceding) x5, +# sum(n2) over (order by n1 nulls last range between 3 preceding and unbounded following) x6 +# from t1 +# order by n1 nulls last, n2; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-08' as msg, +# n1, +# n2, +# sum(n2) over (order by n1 nulls last, n2 rows between unbounded preceding and current row) x1, +# sum(n2) over (order by n1 nulls last, n2 rows between current row and unbounded following) x2, +# sum(n2) over (order by n1 nulls last, n2 rows between current row and current row) x3, +# sum(n2) over (order by n1 nulls last, n2 rows between 2 following and 3 following) x4, +# sum(n2) over (order by n1 nulls last, n2 rows between 3 preceding and 2 preceding) x5, +# sum(n2) over (order by n1 nulls last, n2 rows between 3 preceding and unbounded following) x6 +# from t1 +# order by n1 nulls last, n2; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-09' as msg, +# n1, +# n2, +# sum(n2) over (order by n1 desc range between unbounded preceding and current row) x1, +# sum(n2) over (order by n1 desc range between current row and unbounded following) x2, +# sum(n2) over (order by n1 desc range between current row and current row) x3, +# sum(n2) over (order by n1 desc range between 2 following and 3 following) x4, +# sum(n2) over (order by n1 desc range between 3 preceding and 2 preceding) x5, +# sum(n2) over (order by n1 desc range between 3 preceding and unbounded following) x6 +# from t1 +# order by n1 desc, n2; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-10' as msg, +# n1, +# n2, +# sum(n2) over (order by n1 desc, n2 rows between unbounded preceding and current row) x1, +# sum(n2) over (order by n1 desc, n2 rows between current row and unbounded following) x2, +# sum(n2) over (order by n1 desc, n2 rows between current row and current row) x3, +# sum(n2) over (order by n1 desc, n2 rows between 2 following and 3 following) x4, +# sum(n2) over (order by n1 desc, n2 rows between 3 preceding and 2 preceding) x5, +# sum(n2) over (order by n1 desc, n2 rows between 3 preceding and unbounded following) x6 +# from t1 +# order by n1 desc, n2; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-11' as msg, +# n1, +# n2, +# sum(n2) over (order by n1 desc nulls first range between unbounded preceding and current row) x1, +# sum(n2) over (order by n1 desc nulls first range between current row and unbounded following) x2, +# sum(n2) over (order by n1 desc nulls first range between current row and current row) x3, +# sum(n2) over (order by n1 desc nulls first range between 2 following and 3 following) x4, +# sum(n2) over (order by n1 desc nulls first range between 3 preceding and 2 preceding) x5, +# sum(n2) over (order by n1 desc nulls first range between 3 preceding and unbounded following) x6 +# from t1 +# order by n1 desc nulls first, n2; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-12' as msg, +# n1, +# n2, +# sum(n2) over (order by n1 desc nulls first, n2 rows between unbounded preceding and current row) x1, +# sum(n2) over (order by n1 desc nulls first, n2 rows between current row and unbounded following) x2, +# sum(n2) over (order by n1 desc nulls first, n2 rows between current row and current row) x3, +# sum(n2) over (order by n1 desc nulls first, n2 rows between 2 following and 3 following) x4, +# sum(n2) over (order by n1 desc nulls first, n2 rows between 3 preceding and 2 preceding) x5, +# sum(n2) over (order by n1 desc nulls first, n2 rows between 3 preceding and unbounded following) x6 +# from t1 +# order by n1 desc nulls first, n2; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-13' as msg, +# n1, +# n2, +# sum(n2) over (order by n1 desc nulls last range between unbounded preceding and current row) x1, +# sum(n2) over (order by n1 desc nulls last range between current row and unbounded following) x2, +# sum(n2) over (order by n1 desc nulls last range between current row and current row) x3, +# sum(n2) over (order by n1 desc nulls last range between 2 following and 3 following) x4, +# sum(n2) over (order by n1 desc nulls last range between 3 preceding and 2 preceding) x5, +# sum(n2) over (order by n1 desc nulls last range between 3 preceding and unbounded following) x6 +# from t1 +# order by n1 desc nulls last, n2; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-14' as msg, +# n1, +# n2, +# sum(n2) over (order by n1 desc nulls last, n2 rows between unbounded preceding and current row) x1, +# sum(n2) over (order by n1 desc nulls last, n2 rows between current row and unbounded following) x2, +# sum(n2) over (order by n1 desc nulls last, n2 rows between current row and current row) x3, +# sum(n2) over (order by n1 desc nulls last, n2 rows between 2 following and 3 following) x4, +# sum(n2) over (order by n1 desc nulls last, n2 rows between 3 preceding and 2 preceding) x5, +# sum(n2) over (order by n1 desc nulls last, n2 rows between 3 preceding and unbounded following) x6 +# from t1 +# order by n1 desc nulls last, n2; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-15' as msg, +# n1, +# n2, +# count(*) over (order by n1 nulls first range between coalesce(n1, 0) preceding and coalesce(n1, 0) preceding) x1, +# sum(n2) over (order by n1 nulls first range between coalesce(n1, 0) preceding and coalesce(n1, 0) preceding) x2, +# count(*) over (order by n1 nulls first range between coalesce(n1, 0) following and coalesce(n1, 0) following) x3, +# sum(n2) over (order by n1 nulls first range between coalesce(n1, 0) following and coalesce(n1, 0) following) x4 +# from t1 +# order by n1 nulls first, n2; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-16' as msg, +# n1, +# n2, +# count(*) over (order by n1 nulls first, n2 rows between coalesce(n1, 0) preceding and coalesce(n1, 0) preceding) x1, +# sum(n2) over (order by n1 nulls first, n2 rows between coalesce(n1, 0) preceding and coalesce(n1, 0) preceding) x2, +# count(*) over (order by n1 nulls first, n2 rows between coalesce(n1, 0) following and coalesce(n1, 0) following) x3, +# sum(n2) over (order by n1 nulls first, n2 rows between coalesce(n1, 0) following and coalesce(n1, 0) following) x4 +# from t1 +# order by n1 nulls first, n2; +# +# --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# select +# 'point-17' as msg, +# n1, +# n2, +# sum(n2) over (partition by n1 order by date '2000-01-01' + n2 range between unbounded preceding and current row) x1, +# sum(n2) over (partition by n1 order by date '2000-01-01' + n2 range between current row and unbounded following) x2, +# sum(n2) over (partition by n1 order by date '2000-01-01' + n2 range between current row and current row) x3, +# sum(n2) over (partition by n1 order by date '2000-01-01' + n2 range between 10 preceding and 10 following) x4, +# sum(n2) over (partition by n1 order by date '2000-01-01' + n2 range between 3 preceding and unbounded following) x5 +# from t1 +# order by n2, n1; +# ''' +# +# runProgram('isql', [ dsn], os.linesep.join( (sql_init, sql_addi) ) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG point-01 + N1 1 + N2 1 + X1 1 + X2 10111 + X3 1 + X4 + X5 + X6 10111 + MSG point-01 + N1 1 + N2 10 + X1 11 + X2 10110 + X3 10 + X4 + X5 + X6 10110 + MSG point-01 + N1 2 + N2 20 + X1 20 + X2 20 + X3 20 + X4 + X5 + X6 20 + MSG point-01 + N1 + N2 50 + X1 50 + X2 101110 + X3 50 + X4 + X5 + X6 101110 + MSG point-01 + N1 + N2 60 + X1 110 + X2 101060 + X3 60 + X4 + X5 + X6 101060 + MSG point-01 + N1 1 + N2 100 + X1 111 + X2 10100 + X3 100 + X4 + X5 + X6 10100 + MSG point-01 + N1 3 + N2 300 + X1 300 + X2 300 + X3 300 + X4 + X5 + X6 300 + MSG point-01 + N1 5 + N2 500 + X1 500 + X2 500 + X3 500 + X4 + X5 + X6 500 + MSG point-01 + N1 + N2 1000 + X1 1110 + X2 101000 + X3 1000 + X4 + X5 + X6 101000 + MSG point-01 + N1 1 + N2 10000 + X1 10111 + X2 10000 + X3 10000 + X4 + X5 + X6 10000 + MSG point-01 + N1 + N2 100000 + X1 101110 + X2 100000 + X3 100000 + X4 + X5 + X6 100000 + MSG point-02 + N1 1 + N2 1 + X1 1 + X2 10111 + X3 1 + X4 10100 + X5 + X6 10111 + MSG point-02 + N1 1 + N2 10 + X1 11 + X2 10110 + X3 10 + X4 10000 + X5 + X6 10111 + MSG point-02 + N1 2 + N2 20 + X1 20 + X2 20 + X3 20 + X4 + X5 + X6 20 + MSG point-02 + N1 + N2 50 + X1 50 + X2 101110 + X3 50 + X4 101000 + X5 + X6 101110 + MSG point-02 + N1 + N2 60 + X1 110 + X2 101060 + X3 60 + X4 100000 + X5 + X6 101110 + MSG point-02 + N1 1 + N2 100 + X1 111 + X2 10100 + X3 100 + X4 + X5 1 + X6 10111 + MSG point-02 + N1 3 + N2 300 + X1 300 + X2 300 + X3 300 + X4 + X5 + X6 300 + MSG point-02 + N1 5 + N2 500 + X1 500 + X2 500 + X3 500 + X4 + X5 + X6 500 + MSG point-02 + N1 + N2 1000 + X1 1110 + X2 101000 + X3 1000 + X4 + X5 50 + X6 101110 + MSG point-02 + N1 1 + N2 10000 + X1 10111 + X2 10000 + X3 10000 + X4 + X5 11 + X6 10111 + MSG point-02 + N1 + N2 100000 + X1 101110 + X2 100000 + X3 100000 + X4 + X5 110 + X6 101110 + MSG point-03 + N1 + N2 50 + X1 101110 + X2 112041 + X3 101110 + X4 101110 + X5 101110 + X6 112041 + MSG point-03 + N1 + N2 60 + X1 101110 + X2 112041 + X3 101110 + X4 101110 + X5 101110 + X6 112041 + MSG point-03 + N1 + N2 1000 + X1 101110 + X2 112041 + X3 101110 + X4 101110 + X5 101110 + X6 112041 + MSG point-03 + N1 + N2 100000 + X1 101110 + X2 112041 + X3 101110 + X4 101110 + X5 101110 + X6 112041 + MSG point-03 + N1 1 + N2 1 + X1 111221 + X2 10931 + X3 10111 + X4 300 + X5 + X6 10931 + MSG point-03 + N1 1 + N2 10 + X1 111221 + X2 10931 + X3 10111 + X4 300 + X5 + X6 10931 + MSG point-03 + N1 1 + N2 100 + X1 111221 + X2 10931 + X3 10111 + X4 300 + X5 + X6 10931 + MSG point-03 + N1 1 + N2 10000 + X1 111221 + X2 10931 + X3 10111 + X4 300 + X5 + X6 10931 + MSG point-03 + N1 2 + N2 20 + X1 111241 + X2 820 + X3 20 + X4 500 + X5 + X6 10931 + MSG point-03 + N1 3 + N2 300 + X1 111541 + X2 800 + X3 300 + X4 500 + X5 10111 + X6 10931 + MSG point-03 + N1 5 + N2 500 + X1 112041 + X2 500 + X3 500 + X4 + X5 320 + X6 820 + MSG point-04 + N1 + N2 50 + X1 50 + X2 112041 + X3 50 + X4 101000 + X5 + X6 112041 + MSG point-04 + N1 + N2 60 + X1 110 + X2 111991 + X3 60 + X4 100001 + X5 + X6 112041 + MSG point-04 + N1 + N2 1000 + X1 1110 + X2 111931 + X3 1000 + X4 11 + X5 50 + X6 112041 + MSG point-04 + N1 + N2 100000 + X1 101110 + X2 110931 + X3 100000 + X4 110 + X5 110 + X6 112041 + MSG point-04 + N1 1 + N2 1 + X1 101111 + X2 10931 + X3 1 + X4 10100 + X5 1060 + X6 111991 + MSG point-04 + N1 1 + N2 10 + X1 101121 + X2 10930 + X3 10 + X4 10020 + X5 101000 + X6 111931 + MSG point-04 + N1 1 + N2 100 + X1 101221 + X2 10920 + X3 100 + X4 320 + X5 100001 + X6 110931 + MSG point-04 + N1 1 + N2 10000 + X1 111221 + X2 10820 + X3 10000 + X4 800 + X5 11 + X6 10931 + MSG point-04 + N1 2 + N2 20 + X1 111241 + X2 820 + X3 20 + X4 500 + X5 110 + X6 10930 + MSG point-04 + N1 3 + N2 300 + X1 111541 + X2 800 + X3 300 + X4 + X5 10100 + X6 10920 + MSG point-04 + N1 5 + N2 500 + X1 112041 + X2 500 + X3 500 + X4 + X5 10020 + X6 10820 + MSG point-05 + N1 + N2 50 + X1 101110 + X2 112041 + X3 101110 + X4 101110 + X5 101110 + X6 112041 + MSG point-05 + N1 + N2 60 + X1 101110 + X2 112041 + X3 101110 + X4 101110 + X5 101110 + X6 112041 + MSG point-05 + N1 + N2 1000 + X1 101110 + X2 112041 + X3 101110 + X4 101110 + X5 101110 + X6 112041 + MSG point-05 + N1 + N2 100000 + X1 101110 + X2 112041 + X3 101110 + X4 101110 + X5 101110 + X6 112041 + MSG point-05 + N1 1 + N2 1 + X1 111221 + X2 10931 + X3 10111 + X4 300 + X5 + X6 10931 + MSG point-05 + N1 1 + N2 10 + X1 111221 + X2 10931 + X3 10111 + X4 300 + X5 + X6 10931 + MSG point-05 + N1 1 + N2 100 + X1 111221 + X2 10931 + X3 10111 + X4 300 + X5 + X6 10931 + MSG point-05 + N1 1 + N2 10000 + X1 111221 + X2 10931 + X3 10111 + X4 300 + X5 + X6 10931 + MSG point-05 + N1 2 + N2 20 + X1 111241 + X2 820 + X3 20 + X4 500 + X5 + X6 10931 + MSG point-05 + N1 3 + N2 300 + X1 111541 + X2 800 + X3 300 + X4 500 + X5 10111 + X6 10931 + MSG point-05 + N1 5 + N2 500 + X1 112041 + X2 500 + X3 500 + X4 + X5 320 + X6 820 + MSG point-06 + N1 + N2 50 + X1 50 + X2 112041 + X3 50 + X4 101000 + X5 + X6 112041 + MSG point-06 + N1 + N2 60 + X1 110 + X2 111991 + X3 60 + X4 100001 + X5 + X6 112041 + MSG point-06 + N1 + N2 1000 + X1 1110 + X2 111931 + X3 1000 + X4 11 + X5 50 + X6 112041 + MSG point-06 + N1 + N2 100000 + X1 101110 + X2 110931 + X3 100000 + X4 110 + X5 110 + X6 112041 + MSG point-06 + N1 1 + N2 1 + X1 101111 + X2 10931 + X3 1 + X4 10100 + X5 1060 + X6 111991 + MSG point-06 + N1 1 + N2 10 + X1 101121 + X2 10930 + X3 10 + X4 10020 + X5 101000 + X6 111931 + MSG point-06 + N1 1 + N2 100 + X1 101221 + X2 10920 + X3 100 + X4 320 + X5 100001 + X6 110931 + MSG point-06 + N1 1 + N2 10000 + X1 111221 + X2 10820 + X3 10000 + X4 800 + X5 11 + X6 10931 + MSG point-06 + N1 2 + N2 20 + X1 111241 + X2 820 + X3 20 + X4 500 + X5 110 + X6 10930 + MSG point-06 + N1 3 + N2 300 + X1 111541 + X2 800 + X3 300 + X4 + X5 10100 + X6 10920 + MSG point-06 + N1 5 + N2 500 + X1 112041 + X2 500 + X3 500 + X4 + X5 10020 + X6 10820 + MSG point-07 + N1 1 + N2 1 + X1 10111 + X2 112041 + X3 10111 + X4 300 + X5 + X6 112041 + MSG point-07 + N1 1 + N2 10 + X1 10111 + X2 112041 + X3 10111 + X4 300 + X5 + X6 112041 + MSG point-07 + N1 1 + N2 100 + X1 10111 + X2 112041 + X3 10111 + X4 300 + X5 + X6 112041 + MSG point-07 + N1 1 + N2 10000 + X1 10111 + X2 112041 + X3 10111 + X4 300 + X5 + X6 112041 + MSG point-07 + N1 2 + N2 20 + X1 10131 + X2 101930 + X3 20 + X4 500 + X5 + X6 112041 + MSG point-07 + N1 3 + N2 300 + X1 10431 + X2 101910 + X3 300 + X4 500 + X5 10111 + X6 112041 + MSG point-07 + N1 5 + N2 500 + X1 10931 + X2 101610 + X3 500 + X4 + X5 320 + X6 101930 + MSG point-07 + N1 + N2 50 + X1 112041 + X2 101110 + X3 101110 + X4 101110 + X5 101110 + X6 101110 + MSG point-07 + N1 + N2 60 + X1 112041 + X2 101110 + X3 101110 + X4 101110 + X5 101110 + X6 101110 + MSG point-07 + N1 + N2 1000 + X1 112041 + X2 101110 + X3 101110 + X4 101110 + X5 101110 + X6 101110 + MSG point-07 + N1 + N2 100000 + X1 112041 + X2 101110 + X3 101110 + X4 101110 + X5 101110 + X6 101110 + MSG point-08 + N1 1 + N2 1 + X1 1 + X2 112041 + X3 1 + X4 10100 + X5 + X6 112041 + MSG point-08 + N1 1 + N2 10 + X1 11 + X2 112040 + X3 10 + X4 10020 + X5 + X6 112041 + MSG point-08 + N1 1 + N2 100 + X1 111 + X2 112030 + X3 100 + X4 320 + X5 1 + X6 112041 + MSG point-08 + N1 1 + N2 10000 + X1 10111 + X2 111930 + X3 10000 + X4 800 + X5 11 + X6 112041 + MSG point-08 + N1 2 + N2 20 + X1 10131 + X2 101930 + X3 20 + X4 550 + X5 110 + X6 112040 + MSG point-08 + N1 3 + N2 300 + X1 10431 + X2 101910 + X3 300 + X4 110 + X5 10100 + X6 112030 + MSG point-08 + N1 5 + N2 500 + X1 10931 + X2 101610 + X3 500 + X4 1060 + X5 10020 + X6 111930 + MSG point-08 + N1 + N2 50 + X1 10981 + X2 101110 + X3 50 + X4 101000 + X5 320 + X6 101930 + MSG point-08 + N1 + N2 60 + X1 11041 + X2 101060 + X3 60 + X4 100000 + X5 800 + X6 101910 + MSG point-08 + N1 + N2 1000 + X1 12041 + X2 101000 + X3 1000 + X4 + X5 550 + X6 101610 + MSG point-08 + N1 + N2 100000 + X1 112041 + X2 100000 + X3 100000 + X4 + X5 110 + X6 101110 + MSG point-09 + N1 5 + N2 500 + X1 500 + X2 112041 + X3 500 + X4 320 + X5 + X6 112041 + MSG point-09 + N1 3 + N2 300 + X1 800 + X2 111541 + X3 300 + X4 10111 + X5 500 + X6 112041 + MSG point-09 + N1 2 + N2 20 + X1 820 + X2 111241 + X3 20 + X4 + X5 500 + X6 112041 + MSG point-09 + N1 1 + N2 1 + X1 10931 + X2 111221 + X3 10111 + X4 + X5 300 + X6 111541 + MSG point-09 + N1 1 + N2 10 + X1 10931 + X2 111221 + X3 10111 + X4 + X5 300 + X6 111541 + MSG point-09 + N1 1 + N2 100 + X1 10931 + X2 111221 + X3 10111 + X4 + X5 300 + X6 111541 + MSG point-09 + N1 1 + N2 10000 + X1 10931 + X2 111221 + X3 10111 + X4 + X5 300 + X6 111541 + MSG point-09 + N1 + N2 50 + X1 112041 + X2 101110 + X3 101110 + X4 101110 + X5 101110 + X6 101110 + MSG point-09 + N1 + N2 60 + X1 112041 + X2 101110 + X3 101110 + X4 101110 + X5 101110 + X6 101110 + MSG point-09 + N1 + N2 1000 + X1 112041 + X2 101110 + X3 101110 + X4 101110 + X5 101110 + X6 101110 + MSG point-09 + N1 + N2 100000 + X1 112041 + X2 101110 + X3 101110 + X4 101110 + X5 101110 + X6 101110 + MSG point-10 + N1 5 + N2 500 + X1 500 + X2 112041 + X3 500 + X4 21 + X5 + X6 112041 + MSG point-10 + N1 3 + N2 300 + X1 800 + X2 111541 + X3 300 + X4 11 + X5 + X6 112041 + MSG point-10 + N1 2 + N2 20 + X1 820 + X2 111241 + X3 20 + X4 110 + X5 500 + X6 112041 + MSG point-10 + N1 1 + N2 1 + X1 821 + X2 111221 + X3 1 + X4 10100 + X5 800 + X6 112041 + MSG point-10 + N1 1 + N2 10 + X1 831 + X2 111220 + X3 10 + X4 10050 + X5 320 + X6 111541 + MSG point-10 + N1 1 + N2 100 + X1 931 + X2 111210 + X3 100 + X4 110 + X5 21 + X6 111241 + MSG point-10 + N1 1 + N2 10000 + X1 10931 + X2 111110 + X3 10000 + X4 1060 + X5 11 + X6 111221 + MSG point-10 + N1 + N2 50 + X1 10981 + X2 101110 + X3 50 + X4 101000 + X5 110 + X6 111220 + MSG point-10 + N1 + N2 60 + X1 11041 + X2 101060 + X3 60 + X4 100000 + X5 10100 + X6 111210 + MSG point-10 + N1 + N2 1000 + X1 12041 + X2 101000 + X3 1000 + X4 + X5 10050 + X6 111110 + MSG point-10 + N1 + N2 100000 + X1 112041 + X2 100000 + X3 100000 + X4 + X5 110 + X6 101110 + MSG point-11 + N1 + N2 50 + X1 101110 + X2 112041 + X3 101110 + X4 101110 + X5 101110 + X6 112041 + MSG point-11 + N1 + N2 60 + X1 101110 + X2 112041 + X3 101110 + X4 101110 + X5 101110 + X6 112041 + MSG point-11 + N1 + N2 1000 + X1 101110 + X2 112041 + X3 101110 + X4 101110 + X5 101110 + X6 112041 + MSG point-11 + N1 + N2 100000 + X1 101110 + X2 112041 + X3 101110 + X4 101110 + X5 101110 + X6 112041 + MSG point-11 + N1 5 + N2 500 + X1 101610 + X2 10931 + X3 500 + X4 320 + X5 + X6 10931 + MSG point-11 + N1 3 + N2 300 + X1 101910 + X2 10431 + X3 300 + X4 10111 + X5 500 + X6 10931 + MSG point-11 + N1 2 + N2 20 + X1 101930 + X2 10131 + X3 20 + X4 + X5 500 + X6 10931 + MSG point-11 + N1 1 + N2 1 + X1 112041 + X2 10111 + X3 10111 + X4 + X5 300 + X6 10431 + MSG point-11 + N1 1 + N2 10 + X1 112041 + X2 10111 + X3 10111 + X4 + X5 300 + X6 10431 + MSG point-11 + N1 1 + N2 100 + X1 112041 + X2 10111 + X3 10111 + X4 + X5 300 + X6 10431 + MSG point-11 + N1 1 + N2 10000 + X1 112041 + X2 10111 + X3 10111 + X4 + X5 300 + X6 10431 + MSG point-12 + N1 + N2 50 + X1 50 + X2 112041 + X3 50 + X4 101000 + X5 + X6 112041 + MSG point-12 + N1 + N2 60 + X1 110 + X2 111991 + X3 60 + X4 100500 + X5 + X6 112041 + MSG point-12 + N1 + N2 1000 + X1 1110 + X2 111931 + X3 1000 + X4 800 + X5 50 + X6 112041 + MSG point-12 + N1 + N2 100000 + X1 101110 + X2 110931 + X3 100000 + X4 320 + X5 110 + X6 112041 + MSG point-12 + N1 5 + N2 500 + X1 101610 + X2 10931 + X3 500 + X4 21 + X5 1060 + X6 111991 + MSG point-12 + N1 3 + N2 300 + X1 101910 + X2 10431 + X3 300 + X4 11 + X5 101000 + X6 111931 + MSG point-12 + N1 2 + N2 20 + X1 101930 + X2 10131 + X3 20 + X4 110 + X5 100500 + X6 110931 + MSG point-12 + N1 1 + N2 1 + X1 101931 + X2 10111 + X3 1 + X4 10100 + X5 800 + X6 10931 + MSG point-12 + N1 1 + N2 10 + X1 101941 + X2 10110 + X3 10 + X4 10000 + X5 320 + X6 10431 + MSG point-12 + N1 1 + N2 100 + X1 102041 + X2 10100 + X3 100 + X4 + X5 21 + X6 10131 + MSG point-12 + N1 1 + N2 10000 + X1 112041 + X2 10000 + X3 10000 + X4 + X5 11 + X6 10111 + MSG point-13 + N1 5 + N2 500 + X1 500 + X2 112041 + X3 500 + X4 320 + X5 + X6 112041 + MSG point-13 + N1 3 + N2 300 + X1 800 + X2 111541 + X3 300 + X4 10111 + X5 500 + X6 112041 + MSG point-13 + N1 2 + N2 20 + X1 820 + X2 111241 + X3 20 + X4 + X5 500 + X6 112041 + MSG point-13 + N1 1 + N2 1 + X1 10931 + X2 111221 + X3 10111 + X4 + X5 300 + X6 111541 + MSG point-13 + N1 1 + N2 10 + X1 10931 + X2 111221 + X3 10111 + X4 + X5 300 + X6 111541 + MSG point-13 + N1 1 + N2 100 + X1 10931 + X2 111221 + X3 10111 + X4 + X5 300 + X6 111541 + MSG point-13 + N1 1 + N2 10000 + X1 10931 + X2 111221 + X3 10111 + X4 + X5 300 + X6 111541 + MSG point-13 + N1 + N2 50 + X1 112041 + X2 101110 + X3 101110 + X4 101110 + X5 101110 + X6 101110 + MSG point-13 + N1 + N2 60 + X1 112041 + X2 101110 + X3 101110 + X4 101110 + X5 101110 + X6 101110 + MSG point-13 + N1 + N2 1000 + X1 112041 + X2 101110 + X3 101110 + X4 101110 + X5 101110 + X6 101110 + MSG point-13 + N1 + N2 100000 + X1 112041 + X2 101110 + X3 101110 + X4 101110 + X5 101110 + X6 101110 + MSG point-14 + N1 5 + N2 500 + X1 500 + X2 112041 + X3 500 + X4 21 + X5 + X6 112041 + MSG point-14 + N1 3 + N2 300 + X1 800 + X2 111541 + X3 300 + X4 11 + X5 + X6 112041 + MSG point-14 + N1 2 + N2 20 + X1 820 + X2 111241 + X3 20 + X4 110 + X5 500 + X6 112041 + MSG point-14 + N1 1 + N2 1 + X1 821 + X2 111221 + X3 1 + X4 10100 + X5 800 + X6 112041 + MSG point-14 + N1 1 + N2 10 + X1 831 + X2 111220 + X3 10 + X4 10050 + X5 320 + X6 111541 + MSG point-14 + N1 1 + N2 100 + X1 931 + X2 111210 + X3 100 + X4 110 + X5 21 + X6 111241 + MSG point-14 + N1 1 + N2 10000 + X1 10931 + X2 111110 + X3 10000 + X4 1060 + X5 11 + X6 111221 + MSG point-14 + N1 + N2 50 + X1 10981 + X2 101110 + X3 50 + X4 101000 + X5 110 + X6 111220 + MSG point-14 + N1 + N2 60 + X1 11041 + X2 101060 + X3 60 + X4 100000 + X5 10100 + X6 111210 + MSG point-14 + N1 + N2 1000 + X1 12041 + X2 101000 + X3 1000 + X4 + X5 10050 + X6 111110 + MSG point-14 + N1 + N2 100000 + X1 112041 + X2 100000 + X3 100000 + X4 + X5 110 + X6 101110 + MSG point-15 + N1 + N2 50 + X1 4 + X2 101110 + X3 4 + X4 101110 + MSG point-15 + N1 + N2 60 + X1 4 + X2 101110 + X3 4 + X4 101110 + MSG point-15 + N1 + N2 1000 + X1 4 + X2 101110 + X3 4 + X4 101110 + MSG point-15 + N1 + N2 100000 + X1 4 + X2 101110 + X3 4 + X4 101110 + MSG point-15 + N1 1 + N2 1 + X1 0 + X2 + X3 1 + X4 20 + MSG point-15 + N1 1 + N2 10 + X1 0 + X2 + X3 1 + X4 20 + MSG point-15 + N1 1 + N2 100 + X1 0 + X2 + X3 1 + X4 20 + MSG point-15 + N1 1 + N2 10000 + X1 0 + X2 + X3 1 + X4 20 + MSG point-15 + N1 2 + N2 20 + X1 0 + X2 + X3 0 + X4 + MSG point-15 + N1 3 + N2 300 + X1 0 + X2 + X3 0 + X4 + MSG point-15 + N1 5 + N2 500 + X1 0 + X2 + X3 0 + X4 + MSG point-16 + N1 + N2 50 + X1 1 + X2 50 + X3 1 + X4 50 + MSG point-16 + N1 + N2 60 + X1 1 + X2 60 + X3 1 + X4 60 + MSG point-16 + N1 + N2 1000 + X1 1 + X2 1000 + X3 1 + X4 1000 + MSG point-16 + N1 + N2 100000 + X1 1 + X2 100000 + X3 1 + X4 100000 + MSG point-16 + N1 1 + N2 1 + X1 1 + X2 100000 + X3 1 + X4 10 + MSG point-16 + N1 1 + N2 10 + X1 1 + X2 1 + X3 1 + X4 100 + MSG point-16 + N1 1 + N2 100 + X1 1 + X2 10 + X3 1 + X4 10000 + MSG point-16 + N1 1 + N2 10000 + X1 1 + X2 100 + X3 1 + X4 20 + MSG point-16 + N1 2 + N2 20 + X1 1 + X2 100 + X3 1 + X4 500 + MSG point-16 + N1 3 + N2 300 + X1 1 + X2 100 + X3 0 + X4 + MSG point-16 + N1 5 + N2 500 + X1 1 + X2 10 + X3 0 + X4 + MSG point-17 + N1 1 + N2 1 + X1 1 + X2 10111 + X3 1 + X4 11 + X5 10111 + MSG point-17 + N1 1 + N2 10 + X1 11 + X2 10110 + X3 10 + X4 11 + X5 10110 + MSG point-17 + N1 2 + N2 20 + X1 20 + X2 20 + X3 20 + X4 20 + X5 20 + MSG point-17 + N1 + N2 50 + X1 50 + X2 101110 + X3 50 + X4 110 + X5 101110 + MSG point-17 + N1 + N2 60 + X1 110 + X2 101060 + X3 60 + X4 110 + X5 101060 + MSG point-17 + N1 1 + N2 100 + X1 111 + X2 10100 + X3 100 + X4 100 + X5 10100 + MSG point-17 + N1 3 + N2 300 + X1 300 + X2 300 + X3 300 + X4 300 + X5 300 + MSG point-17 + N1 5 + N2 500 + X1 500 + X2 500 + X3 500 + X4 500 + X5 500 + MSG point-17 + N1 + N2 1000 + X1 1110 + X2 101000 + X3 1000 + X4 1000 + X5 101000 + MSG point-17 + N1 1 + N2 10000 + X1 10111 + X2 10000 + X3 10000 + X4 10000 + X5 10000 + MSG point-17 + N1 + N2 100000 + X1 101110 + X2 100000 + X3 100000 + X4 100000 + X5 100000 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_window_func_05_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/index/__init__.py b/tests/functional/index/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/index/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/index/alter/__init__.py b/tests/functional/index/alter/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/index/alter/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/index/alter/test_01.py b/tests/functional/index/alter/test_01.py new file mode 100644 index 00000000..3e504298 --- /dev/null +++ b/tests/functional/index/alter/test_01.py @@ -0,0 +1,56 @@ +#coding:utf-8 +# +# id: functional.index.alter.01 +# title: ALTER INDEX - INACTIVE +# decription: ALTER INDEX - INACTIVE +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# CREATE INDEX +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.index.alter.alter_index_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create table test( a integer); + create index test_idx on test(a); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + alter index test_idx inactive; + commit; + set list on; + select + rdb$index_name as idx_name, + rdb$index_inactive as is_inactive + from rdb$indices + where rdb$index_name=upper('test_idx'); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + IDX_NAME TEST_IDX + IS_INACTIVE 1 + """ + +@pytest.mark.version('>=2.0') +def test_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/index/alter/test_02.py b/tests/functional/index/alter/test_02.py new file mode 100644 index 00000000..2eb4d451 --- /dev/null +++ b/tests/functional/index/alter/test_02.py @@ -0,0 +1,57 @@ +#coding:utf-8 +# +# id: functional.index.alter.02 +# title: ALTER INDEX +# decription: ALTER INDEX +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# CREATE INDEX +# ALTER INDEX +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.index.alter.alter_index_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create table test_active_state_toggle( a integer); + commit; + create index test_active_state_toggle_idx on test_active_state_toggle(a); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + alter index test_active_state_toggle_idx inactive; + alter index test_active_state_toggle_idx active; + commit; + set list on; + select rdb$index_name, rdb$index_inactive + from rdb$indices + where rdb$index_name=upper('test_active_state_toggle_idx'); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$INDEX_NAME TEST_ACTIVE_STATE_TOGGLE_IDX + RDB$INDEX_INACTIVE 0 + """ + +@pytest.mark.version('>=2.0') +def test_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/index/alter/test_03.py b/tests/functional/index/alter/test_03.py new file mode 100644 index 00000000..39c75b40 --- /dev/null +++ b/tests/functional/index/alter/test_03.py @@ -0,0 +1,58 @@ +#coding:utf-8 +# +# id: functional.index.alter.03 +# title: ALTER INDEX - INACTIVE UNIQUE INDEX +# decription: ALTER INDEX - INACTIVE UNIQUE INDEX +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# CREATE INDEX +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.index.alter.alter_index_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create table test( a integer); + create unique index test_idx_unq on test(a); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + alter index test_idx_unq inactive; + commit; + set list on; + select + rdb$index_name as idx_name + ,rdb$index_inactive as is_inactive + ,r.rdb$unique_flag as is_unique + from rdb$indices r + where rdb$index_name=upper('test_idx_unq'); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + IDX_NAME TEST_IDX_UNQ + IS_INACTIVE 1 + IS_UNIQUE 1 + """ + +@pytest.mark.version('>=2.0') +def test_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/index/alter/test_04.py b/tests/functional/index/alter/test_04.py new file mode 100644 index 00000000..87b7810b --- /dev/null +++ b/tests/functional/index/alter/test_04.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: functional.index.alter_04 +# title: ALTER INDEX - INACTIVE PRIMARY KEY +# decription: ALTER INDEX - INACTIVE PRIMARY KEY +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE with PRIMARY KEY +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.index.alter.alter_index_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE t( a INTEGER NOT NULL, + CONSTRAINT pkindx PRIMARY KEY(a) + ); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ALTER INDEX pkindx INACTIVE;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """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 + +""" + +@pytest.mark.version('>=3.0') +def test_alter_04_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/index/alter/test_05.py b/tests/functional/index/alter/test_05.py new file mode 100644 index 00000000..fb4c14b9 --- /dev/null +++ b/tests/functional/index/alter/test_05.py @@ -0,0 +1,55 @@ +#coding:utf-8 +# +# id: functional.index.alter_05 +# title: ALTER INDEX - INACTIVE FOREIGN KEY +# decription: ALTER INDEX - INACTIVE FOREIGN KEY +# +# Note !SF 609538 +# Bad error message "-Cannot deactivate primary index" +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE with PRIMARY KEY +# CREATE TABLE with FOREIGN KEY +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.index.alter.alter_index_05 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """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;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ALTER INDEX fkindx INACTIVE;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """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 + +""" + +@pytest.mark.version('>=3.0') +def test_alter_05_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/index/create/__init__.py b/tests/functional/index/create/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/index/create/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/index/create/test_01.py b/tests/functional/index/create/test_01.py new file mode 100644 index 00000000..2c1d077f --- /dev/null +++ b/tests/functional/index/create/test_01.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: functional.index.create.01 +# title: CREATE INDEX +# decription: CREATE INDEX +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# SHOW INDEX +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.index.create.create_index_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE t( a INTEGER); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE INDEX test ON t(a); +SHOW INDEX test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST INDEX ON T(A) +""" + +@pytest.mark.version('>=1.0') +def test_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/index/create/test_02.py b/tests/functional/index/create/test_02.py new file mode 100644 index 00000000..d20aec64 --- /dev/null +++ b/tests/functional/index/create/test_02.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: functional.index.create.02 +# title: CREATE UNIQUE INDEX +# decription: CREATE UNIQUE INDEX +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# SHOW INDEX +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.index.create.create_index_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE t( a INTEGER); +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE UNIQUE INDEX test ON t(a); +SHOW INDEX test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST UNIQUE INDEX ON T(A) +""" + +@pytest.mark.version('>=1.0') +def test_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/index/create/test_03.py b/tests/functional/index/create/test_03.py new file mode 100644 index 00000000..91bde6f6 --- /dev/null +++ b/tests/functional/index/create/test_03.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: functional.index.create.03 +# title: CREATE ASC INDEX +# decription: CREATE ASC INDEX +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# SHOW INDEX +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.index.create.create_index_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE t( a INTEGER); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE ASC INDEX test ON t(a); +SHOW INDEX test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST INDEX ON T(A)""" + +@pytest.mark.version('>=1.0') +def test_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/index/create/test_04.py b/tests/functional/index/create/test_04.py new file mode 100644 index 00000000..b15bdcf9 --- /dev/null +++ b/tests/functional/index/create/test_04.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: functional.index.create.04 +# title: CREATE ASCENDING INDEX +# decription: CREATE ASCENDING INDEX +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# SHOW INDEX +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.index.create.create_index_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE t( a INTEGER); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE ASCENDING INDEX test ON t(a); +SHOW INDEX test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST INDEX ON T(A) +""" + +@pytest.mark.version('>=1.0') +def test_04_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/index/create/test_05.py b/tests/functional/index/create/test_05.py new file mode 100644 index 00000000..6b473795 --- /dev/null +++ b/tests/functional/index/create/test_05.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: functional.index.create.05 +# title: CREATE DESC INDEX +# decription: CREATE DESC INDEX +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# SHOW INDEX +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.index.create.create_index_05 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE t( a INTEGER);""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DESC INDEX test ON t(a); +SHOW INDEX test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST DESCENDING INDEX ON T(A) +""" + +@pytest.mark.version('>=1.0') +def test_05_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/index/create/test_06.py b/tests/functional/index/create/test_06.py new file mode 100644 index 00000000..7e913b92 --- /dev/null +++ b/tests/functional/index/create/test_06.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: functional.index.create.06 +# title: CREATE DESCENDING INDEX +# decription: CREATE DESCENDING INDEX +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# SHOW INDEX +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.index.create.create_index_06 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE t( a INTEGER); +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE DESCENDING INDEX test ON t(a); +SHOW INDEX test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST DESCENDING INDEX ON T(A) +""" + +@pytest.mark.version('>=1.0') +def test_06_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/index/create/test_07.py b/tests/functional/index/create/test_07.py new file mode 100644 index 00000000..a69ee9c8 --- /dev/null +++ b/tests/functional/index/create/test_07.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: functional.index.create.07 +# title: CREATE INDEX - Multi column +# decription: CREATE INDEX - Multi column +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# SHOW INDEX +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.index.create.create_index_07 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE t( a INTEGER, b INT, c INT, d INT); +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE INDEX test ON t(a,b,c,d); +SHOW INDEX test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST INDEX ON T(A, B, C, D)""" + +@pytest.mark.version('>=1.0') +def test_07_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/index/create/test_08.py b/tests/functional/index/create/test_08.py new file mode 100644 index 00000000..293fb60d --- /dev/null +++ b/tests/functional/index/create/test_08.py @@ -0,0 +1,51 @@ +#coding:utf-8 +# +# id: functional.index.create.08 +# title: CREATE INDEX - Table with data +# decription: CREATE INDEX - Table with data +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# INSERT +# SHOW INDEX +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.index.create.create_index_08 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE t( a INTEGER); +commit; +INSERT INTO t VALUES(0); +INSERT INTO t VALUES(0); +INSERT INTO t VALUES(1); +INSERT INTO t VALUES(2); +INSERT INTO t VALUES(3); +INSERT INTO t VALUES(4); +INSERT INTO t VALUES(null); +COMMIT;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE INDEX test ON t(a); +SHOW INDEX test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST INDEX ON T(A) +""" + +@pytest.mark.version('>=1.0') +def test_08_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/index/create/test_09.py b/tests/functional/index/create/test_09.py new file mode 100644 index 00000000..9a82bd16 --- /dev/null +++ b/tests/functional/index/create/test_09.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: functional.index.create.09 +# title: CREATE UNIQUE INDEX - Table with data +# decription: CREATE UNIQUE INDEX - Table with data +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# INSERT +# SHOW INDEX +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.index.create.create_index_09 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE t( a INTEGER); +commit; +INSERT INTO t VALUES(0); +INSERT INTO t VALUES(1); +INSERT INTO t VALUES(2); +INSERT INTO t VALUES(3); +INSERT INTO t VALUES(4); +COMMIT;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE UNIQUE INDEX test ON t(a); +SHOW INDEX test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEST UNIQUE INDEX ON T(A) +""" + +@pytest.mark.version('>=1.0') +def test_09_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/index/create/test_10.py b/tests/functional/index/create/test_10.py new file mode 100644 index 00000000..d985f85d --- /dev/null +++ b/tests/functional/index/create/test_10.py @@ -0,0 +1,48 @@ +#coding:utf-8 +# +# id: functional.index.create_10 +# title: CREATE INDEX - try create index with same name +# decription: CREATE INDEX - try create index with same name +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# INSERT +# SHOW INDEX +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.index.create.create_index_10 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE t( a INTEGER); +CREATE INDEX test ON t(a); +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE INDEX test ON t(a);""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42S11 +unsuccessful metadata update +-CREATE INDEX TEST failed +-Index TEST already exists + +""" + +@pytest.mark.version('>=3.0') +def test_create_10_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/index/create/test_11.py b/tests/functional/index/create/test_11.py new file mode 100644 index 00000000..bb12d29a --- /dev/null +++ b/tests/functional/index/create/test_11.py @@ -0,0 +1,52 @@ +#coding:utf-8 +# +# id: functional.index.create_11 +# title: CREATE UNIQUE INDEX - Non unique data in table +# decription: CREATE UNIQUE INDEX - Non unique data in table +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# INSERT +# SHOW INDEX +# tracker_id: +# min_versions: [] +# versions: 2.5.3 +# qmid: functional.index.create.create_index_11 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE t( a INTEGER); +commit; +INSERT INTO t VALUES(0); +INSERT INTO t VALUES(0); +INSERT INTO t VALUES(1); +INSERT INTO t VALUES(2); +INSERT INTO t VALUES(3); +INSERT INTO t VALUES(4); +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE UNIQUE INDEX test ON t(a);""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 23000 +attempt to store duplicate value (visible to active transactions) in unique index "TEST" +-Problematic key value is ("A" = 0) +""" + +@pytest.mark.version('>=2.5.3') +def test_create_11_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/index/create/test_12.py b/tests/functional/index/create/test_12.py new file mode 100644 index 00000000..8d3250eb --- /dev/null +++ b/tests/functional/index/create/test_12.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: functional.index.create.12 +# title: CREATE UNIQUE INDEX - Null value in table +# decription: CREATE UNIQUE INDEX - Null value in table +# +# Note: Misinterpretable message (attempt to store duplicate value) +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# INSERT +# SHOW INDEX +# tracker_id: +# min_versions: [] +# versions: 1.5 +# qmid: functional.index.create.create_index_12 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE t( a INTEGER); +commit; +INSERT INTO t VALUES(null); +INSERT INTO t VALUES(0); +INSERT INTO t VALUES(1); +INSERT INTO t VALUES(2); +INSERT INTO t VALUES(3); +INSERT INTO t VALUES(4); +COMMIT;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE UNIQUE INDEX test ON t(a);""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=1.5') +def test_12_1(act_1: Action): + act_1.execute() + diff --git a/tests/functional/intfunc/__init__.py b/tests/functional/intfunc/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/intfunc/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/intfunc/avg/__init__.py b/tests/functional/intfunc/avg/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/intfunc/avg/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/intfunc/avg/test_01.py b/tests/functional/intfunc/avg/test_01.py new file mode 100644 index 00000000..8b090d84 --- /dev/null +++ b/tests/functional/intfunc/avg/test_01.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: functional.intfunc.avg.01 +# title: AVG from single integer row +# decription: AVG from single integer row +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# INSERT +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.intfunc.avg.avg_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE test( id INTEGER NOT NULL CONSTRAINT unq UNIQUE, + text VARCHAR(32)); +INSERT INTO test VALUES(5,null);""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT AVG(id) FROM test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ AVG +===================== + + 5""" + +@pytest.mark.version('>=1.0') +def test_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/avg/test_02.py b/tests/functional/intfunc/avg/test_02.py new file mode 100644 index 00000000..ad257c2f --- /dev/null +++ b/tests/functional/intfunc/avg/test_02.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: functional.intfunc.avg.02 +# title: AVG - Test for INTEGER +# decription: If X is exactly halfway between two whole numbers, the result is always the even number. +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# INSERT +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.intfunc.avg.avg_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE test( id INTEGER NOT NULL); +INSERT INTO test VALUES(5); +INSERT INTO test VALUES(6);""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT AVG(id) FROM test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ AVG +===================== + + 5""" + +@pytest.mark.version('>=1.0') +def test_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/avg/test_03.py b/tests/functional/intfunc/avg/test_03.py new file mode 100644 index 00000000..dc6e4be1 --- /dev/null +++ b/tests/functional/intfunc/avg/test_03.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: functional.intfunc.avg.03 +# title: AVG - Test for INTEGER +# decription: Round down (16/3 = 5.3) +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# INSERT +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.intfunc.avg.avg_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE test( id INTEGER NOT NULL); +INSERT INTO test VALUES(5); +INSERT INTO test VALUES(5); +INSERT INTO test VALUES(6);""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT AVG(id) FROM test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ AVG +===================== + + 5""" + +@pytest.mark.version('>=1.0') +def test_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/avg/test_04.py b/tests/functional/intfunc/avg/test_04.py new file mode 100644 index 00000000..4de2377b --- /dev/null +++ b/tests/functional/intfunc/avg/test_04.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: functional.intfunc.avg.04 +# title: AVG - Test for INTEGER +# decription: Round up (17/3 = 5,66666666666667) +# But it's from INTEGER columns, so 5 is expected. +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# INSERT +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.intfunc.avg.avg_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE test( id INTEGER NOT NULL); +INSERT INTO test VALUES(5); +INSERT INTO test VALUES(6); +INSERT INTO test VALUES(6);""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT AVG(id) FROM test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ AVG +===================== + + 5""" + +@pytest.mark.version('>=1.0') +def test_04_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/avg/test_05.py b/tests/functional/intfunc/avg/test_05.py new file mode 100644 index 00000000..c90a3002 --- /dev/null +++ b/tests/functional/intfunc/avg/test_05.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: functional.intfunc.avg.05 +# title: AVG - DISTINCT +# decription: Dependencies: +# CREATE DATABASE +# CREATE TABLE +# INSERT +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.intfunc.avg.avg_05 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE test( id INTEGER NOT NULL); +INSERT INTO test VALUES(5); +INSERT INTO test VALUES(5); +INSERT INTO test VALUES(7);""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT AVG(DISTINCT id) FROM test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ AVG +===================== + + 6""" + +@pytest.mark.version('>=1.0') +def test_05_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/avg/test_06.py b/tests/functional/intfunc/avg/test_06.py new file mode 100644 index 00000000..07c61ae5 --- /dev/null +++ b/tests/functional/intfunc/avg/test_06.py @@ -0,0 +1,105 @@ +#coding:utf-8 +# +# id: functional.intfunc.avg_06 +# title: AVG - Integer OverFlow +# decription: +# Refactored 14.10.2019: adjusted expected_stdout/stderr +# 25.06.2020, 4.0.0.2076: changed types in SQLDA from numeric to int128 // after discuss with Alex about CORE-6342. +# 09.07.2020, 4.0.0.2091: +# NO more overflow since INT128 was introduced. AVG() is evaluated successfully. +# Removed error message from expected_stderr, added result into expected_stdout. +# +# tracker_id: +# min_versions: [] +# versions: 3.0, 4.0 +# qmid: functional.intfunc.avg.avg_06 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """ + recreate table test( id integer not null); + insert into test values(2100000000); + insert into test values(2100000000); + insert into test values(2100000000); + insert into test values(2100000000); + commit; + create or alter view v_test as select avg(2100000000*id)as avg_result from test; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set sqlda_display on; + select * from v_test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + INPUT message field count: 0 + OUTPUT message field count: 1 + 01: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: AVG_RESULT alias: AVG_RESULT + : table: V_TEST owner: SYSDBA + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22003 + Integer overflow. The result of an integer operation caused the most significant bit of the result to carry. + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_avg_06_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [('^((?!sqltype|AVG_RESULT).)*$', ''), ('[ \t]+', ' ')] + +init_script_2 = """ + recreate table test( id integer not null); + insert into test values(2100000000); + insert into test values(2100000000); + insert into test values(2100000000); + insert into test values(2100000000); + commit; + create or alter view v_test as select avg(2100000000*id)as avg_result from test; + commit; + """ + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + set list on; + set sqlda_display on; + select * from v_test; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + 01: sqltype: 32752 INT128 Nullable scale: 0 subtype: 0 len: 16 + : name: AVG_RESULT alias: AVG_RESULT + : table: V_TEST owner: SYSDBA + + AVG_RESULT 4410000000000000000 + """ + +@pytest.mark.version('>=4.0') +def test_avg_06_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/functional/intfunc/avg/test_07.py b/tests/functional/intfunc/avg/test_07.py new file mode 100644 index 00000000..cd7a9807 --- /dev/null +++ b/tests/functional/intfunc/avg/test_07.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: functional.intfunc.avg.07 +# title: AVG - Integer with NULL +# decription: Dependencies: +# CREATE DATABASE +# CREATE TABLE +# INSERT +# SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.intfunc.avg.avg_07 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE test( id INTEGER); +INSERT INTO test VALUES(12); +INSERT INTO test VALUES(13); +INSERT INTO test VALUES(14); +INSERT INTO test VALUES(NULL);""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT AVG(id) FROM test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ AVG +===================== + + 13""" + +@pytest.mark.version('>=1.0') +def test_07_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/avg/test_08.py b/tests/functional/intfunc/avg/test_08.py new file mode 100644 index 00000000..cfc6f675 --- /dev/null +++ b/tests/functional/intfunc/avg/test_08.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: functional.intfunc.avg.08 +# title: AVG - NULL test +# decription: Dependencies: +# CREATE DATABASE +# CREATE TABLE +# INSERT +# SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.intfunc.avg.avg_08 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE test( id INTEGER); +INSERT INTO test VALUES(NULL);""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT AVG(id) FROM test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ AVG +===================== + + """ + +@pytest.mark.version('>=1.0') +def test_08_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/avg/test_09.py b/tests/functional/intfunc/avg/test_09.py new file mode 100644 index 00000000..8805845d --- /dev/null +++ b/tests/functional/intfunc/avg/test_09.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: functional.intfunc.avg.09 +# title: AVG - DOUBLE PRECISION +# decription: AVG from single DOUBLE PRECISION row +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# INSERT +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.intfunc.avg.avg_09 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE test( id DOUBLE PRECISION NOT NULL); +INSERT INTO test VALUES(5.123456789);""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT AVG(id) FROM test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ AVG +======================= + + 5.123456789000000""" + +@pytest.mark.version('>=1.0') +def test_09_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/binary/__init__.py b/tests/functional/intfunc/binary/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/intfunc/binary/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/intfunc/binary/test_and_01.py b/tests/functional/intfunc/binary/test_and_01.py new file mode 100644 index 00000000..e60587e1 --- /dev/null +++ b/tests/functional/intfunc/binary/test_and_01.py @@ -0,0 +1,48 @@ +#coding:utf-8 +# +# id: functional.intfunc.binary.and_01 +# title: New Built-in Functions, Firebird 2.1 : BIN_AND( [, ...] ) +# decription: test of BIN_AND +# +# Returns the result of a binary AND operation performed on all arguments. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.binary.bin_and_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select BIN_AND( 1, 1) from rdb$database; + +select BIN_AND( 1, 0) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ BIN_AND +============ + 1 + + + BIN_AND +============ + 0 + + +""" + +@pytest.mark.version('>=2.1') +def test_and_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/binary/test_or_01.py b/tests/functional/intfunc/binary/test_or_01.py new file mode 100644 index 00000000..15ce74cd --- /dev/null +++ b/tests/functional/intfunc/binary/test_or_01.py @@ -0,0 +1,56 @@ +#coding:utf-8 +# +# id: functional.intfunc.binary.or_01 +# title: New Built-in Functions, Firebird 2.1 : BIN_OR( [, ...] ) +# decription: test of BIN_OR +# +# +# Returns the result of a binary OR operation performed on all arguments. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.binary.bin_or_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select BIN_OR( 1, 1) from rdb$database; + +select BIN_OR( 1, 0) from rdb$database; +select BIN_OR( 0, 0) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ BIN_OR +============ + 1 + + + BIN_OR +============ + 1 + + + BIN_OR +============ + 0 + + + +""" + +@pytest.mark.version('>=2.1') +def test_or_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/binary/test_shl_01.py b/tests/functional/intfunc/binary/test_shl_01.py new file mode 100644 index 00000000..d032c698 --- /dev/null +++ b/tests/functional/intfunc/binary/test_shl_01.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: functional.intfunc.binary.shl_01 +# title: New Built-in Functions, Firebird 2.1 : BIN_SHL( , ) +# decription: test of BIN_SHL +# +# Returns the result of a binary shift left operation performed on the arguments (first << second). +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.binary.bin_shl_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select BIN_SHL( 8,1) from rdb$database; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ BIN_SHL +===================== + 16 + + + +""" + +@pytest.mark.version('>=2.1') +def test_shl_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/binary/test_shr_01.py b/tests/functional/intfunc/binary/test_shr_01.py new file mode 100644 index 00000000..3bb64beb --- /dev/null +++ b/tests/functional/intfunc/binary/test_shr_01.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: functional.intfunc.binary.shr_01 +# title: New Built-in Functions, Firebird 2.1 : BIN_SHR( , ) +# decription: test of BIN_SHR +# +# Returns the result of a binary shift left operation performed on the arguments (first << second). +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.binary.bin_shr_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select BIN_SHR( 8,1) from rdb$database; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ BIN_SHR +===================== + 4 + + + + +""" + +@pytest.mark.version('>=2.1') +def test_shr_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/binary/test_xor_01.py b/tests/functional/intfunc/binary/test_xor_01.py new file mode 100644 index 00000000..4267839b --- /dev/null +++ b/tests/functional/intfunc/binary/test_xor_01.py @@ -0,0 +1,56 @@ +#coding:utf-8 +# +# id: functional.intfunc.binary.xor_01 +# title: New Built-in Functions, Firebird 2.1 : BIN_XOR( [, ...] ) +# decription: test of BIN_XOR +# +# Returns the result of a binary XOR operation performed on all arguments. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.binary.bin_xor_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select BIN_XOR( 0,1) from rdb$database; +select BIN_XOR( 0,0) from rdb$database; +select BIN_XOR( 1,1) from rdb$database; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ BIN_XOR +============ + 1 + + + BIN_XOR +============ + 0 + + + BIN_XOR +============ + 0 + + + + +""" + +@pytest.mark.version('>=2.1') +def test_xor_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/cast/__init__.py b/tests/functional/intfunc/cast/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/intfunc/cast/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/intfunc/cast/test_01.py b/tests/functional/intfunc/cast/test_01.py new file mode 100644 index 00000000..dec3c526 --- /dev/null +++ b/tests/functional/intfunc/cast/test_01.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: functional.intfunc.cast.01 +# title: CAST Numeric -> CHAR +# decription: CAST Numeric -> CHAR +# +# Dependencies: +# CREATE DATABASE +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.intfunc.cast.cast_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT CAST(1.25001 AS CHAR(21)) FROM rdb$Database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """CAST +===================== + +1.25001 +""" + +@pytest.mark.version('>=1.0') +def test_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/cast/test_02.py b/tests/functional/intfunc/cast/test_02.py new file mode 100644 index 00000000..e8b4edf7 --- /dev/null +++ b/tests/functional/intfunc/cast/test_02.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: functional.intfunc.cast.02 +# title: CAST Numeric -> VARCHAR +# decription: CAST Numeric -> VARCHAR +# +# Dependencies: +# CREATE DATABASE +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.intfunc.cast.cast_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT CAST(1.25001 AS VARCHAR(21)) FROM rdb$Database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """CAST +===================== + +1.25001 +""" + +@pytest.mark.version('>=1.0') +def test_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/cast/test_03.py b/tests/functional/intfunc/cast/test_03.py new file mode 100644 index 00000000..e5c4c894 --- /dev/null +++ b/tests/functional/intfunc/cast/test_03.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: functional.intfunc.cast_03 +# title: CAST Numeric -> DATE +# decription: Convert from number to date is not (yet) supported +# +# CAST Numeric -> DATE +# +# Dependencies: +# CREATE DATABASE +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 2.5 +# qmid: functional.intfunc.cast.cast_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT CAST(CAST(1.25001 AS INT) AS DATE) FROM rdb$Database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """CAST +===========""" +expected_stderr_1 = '''Statement failed, SQLSTATE = 22018 + +conversion error from string "1"''' + +@pytest.mark.version('>=2.5') +def test_cast_03_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/cast/test_04.py b/tests/functional/intfunc/cast/test_04.py new file mode 100644 index 00000000..9cf984a8 --- /dev/null +++ b/tests/functional/intfunc/cast/test_04.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: functional.intfunc.cast.04 +# title: CAST Numeric -> Numeric (Round down) +# decription: CAST Numeric -> Numeric +# Round down +# +# Dependencies: +# CREATE DATABASE +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.intfunc.cast.cast_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT CAST(1.24999 AS NUMERIC(2,1)) FROM rdb$Database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ CAST +======= + + 1.2 +""" + +@pytest.mark.version('>=1.0') +def test_04_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/cast/test_05.py b/tests/functional/intfunc/cast/test_05.py new file mode 100644 index 00000000..9ff95bc7 --- /dev/null +++ b/tests/functional/intfunc/cast/test_05.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: functional.intfunc.cast.05 +# title: CAST Numeric -> Numeric (Round up) +# decription: CAST Numeric -> Numeric +# Round up +# +# Dependencies: +# CREATE DATABASE +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.intfunc.cast.cast_05 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT CAST(1.25001 AS NUMERIC(2,1)) FROM rdb$Database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ CAST +======= + + 1.3 +""" + +@pytest.mark.version('>=1.0') +def test_05_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/cast/test_06.py b/tests/functional/intfunc/cast/test_06.py new file mode 100644 index 00000000..03a408ba --- /dev/null +++ b/tests/functional/intfunc/cast/test_06.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: functional.intfunc.cast.06 +# title: CAST CHAR -> INTEGER +# decription: CAST CHAR -> INTEGER +# Round down +# +# Dependencies: +# CREATE DATABASE +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.intfunc.cast.cast_06 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT CAST('1.25001' AS INTEGER) FROM rdb$Database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ CAST +============ + + 1 +""" + +@pytest.mark.version('>=1.0') +def test_06_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/cast/test_07.py b/tests/functional/intfunc/cast/test_07.py new file mode 100644 index 00000000..edcb6a23 --- /dev/null +++ b/tests/functional/intfunc/cast/test_07.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: functional.intfunc.cast.07 +# title: CAST CHAR -> INTEGER +# decription: CAST CHAR -> INTEGER +# +# Dependencies: +# CREATE DATABASE +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.cast.cast_07 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT CAST('1.5001' AS INTEGER) FROM rdb$Database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """CAST +============ + 2 + +""" + +@pytest.mark.version('>=2.1') +def test_07_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/cast/test_08.py b/tests/functional/intfunc/cast/test_08.py new file mode 100644 index 00000000..67736456 --- /dev/null +++ b/tests/functional/intfunc/cast/test_08.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: functional.intfunc.cast.08 +# title: CAST CHAR -> DATE +# decription: CAST CHAR -> DATE +# Be careful about date format on FB server ! +# Universal format is not defined or not documented. +# +# Dependencies: +# CREATE DATABASE +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.intfunc.cast.cast_08 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT CAST('28.1.2001' AS DATE) FROM rdb$Database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ CAST +=========== + +2001-01-28""" + +@pytest.mark.version('>=1.0') +def test_08_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/cast/test_09.py b/tests/functional/intfunc/cast/test_09.py new file mode 100644 index 00000000..9069bf23 --- /dev/null +++ b/tests/functional/intfunc/cast/test_09.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: functional.intfunc.cast_09 +# title: CAST CHAR -> DATE +# decription: CAST CHAR -> DATE +# Be careful about date format on FB server ! +# Universal format is not defined or not documented. +# +# Dependencies: +# CREATE DATABASE +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 2.5 +# qmid: functional.intfunc.cast.cast_09 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT CAST('29.2.2002' AS DATE) FROM rdb$Database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ CAST +===========""" +expected_stderr_1 = '''Statement failed, SQLSTATE = 22018 + +conversion error from string "29.2.2002"''' + +@pytest.mark.version('>=2.5') +def test_cast_09_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/cast/test_10.py b/tests/functional/intfunc/cast/test_10.py new file mode 100644 index 00000000..7744439e --- /dev/null +++ b/tests/functional/intfunc/cast/test_10.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: functional.intfunc.cast.10 +# title: CAST CHAR -> TIME +# decription: CAST CHAR -> TIME +# Be careful about time format on FB server ! +# Universal format is not defined or not documented. +# +# Dependencies: +# CREATE DATABASE +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.intfunc.cast.cast_10 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT CAST('14:34:59.1234' AS TIME) FROM rdb$Database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ CAST +============= + +14:34:59.1234 +""" + +@pytest.mark.version('>=1.0') +def test_10_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/cast/test_11.py b/tests/functional/intfunc/cast/test_11.py new file mode 100644 index 00000000..f970fa23 --- /dev/null +++ b/tests/functional/intfunc/cast/test_11.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: functional.intfunc.cast.11 +# title: CAST CHAR -> TIME +# decription: CAST CHAR -> TIME +# Be careful about time format on FB server ! +# Universal format is not defined or not documented. +# +# Dependencies: +# CREATE DATABASE +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.intfunc.cast.cast_11 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT CAST('14:34:59.1234' AS TIME) FROM rdb$Database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ CAST +============= +14:34:59.1234""" + +@pytest.mark.version('>=1.0') +def test_11_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/cast/test_12.py b/tests/functional/intfunc/cast/test_12.py new file mode 100644 index 00000000..5310fbf6 --- /dev/null +++ b/tests/functional/intfunc/cast/test_12.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: functional.intfunc.cast_12 +# title: CAST CHAR -> TIME +# decription: CAST CHAR -> TIME +# Be careful about date format on FB server ! +# Universal format is not defined or not documented. +# +# Dependencies: +# CREATE DATABASE +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 2.5 +# qmid: functional.intfunc.cast.cast_12 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT CAST('9:11:60' AS TIME) FROM rdb$Database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ CAST +=============""" +expected_stderr_1 = '''Statement failed, SQLSTATE = 22018 + +conversion error from string "9:11:60"''' + +@pytest.mark.version('>=2.5') +def test_cast_12_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/cast/test_13.py b/tests/functional/intfunc/cast/test_13.py new file mode 100644 index 00000000..b10b8093 --- /dev/null +++ b/tests/functional/intfunc/cast/test_13.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: functional.intfunc.cast.13 +# title: CAST CHAR -> TIMESTAM +# decription: CAST CHAR -> TIMESTAMP +# Be careful about time format on FB server ! +# Universal format is not defined or not documented. +# +# Dependencies: +# CREATE DATABASE +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.intfunc.cast.cast_13 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT CAST('10.2.1489 14:34:59.1234' AS TIMESTAMP) FROM rdb$Database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ CAST +========================= + +1489-02-10 14:34:59.1234""" + +@pytest.mark.version('>=1.0') +def test_13_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/cast/test_14.py b/tests/functional/intfunc/cast/test_14.py new file mode 100644 index 00000000..84282304 --- /dev/null +++ b/tests/functional/intfunc/cast/test_14.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: functional.intfunc.cast.14 +# title: CAST CHAR -> TIMESTAMP +# decription: CAST CHAR -> TIMESTAMP +# Be careful about time format on FB server ! +# Universal format is not defined or not documented. +# +# Dependencies: +# CREATE DATABASE +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.intfunc.cast.cast_14 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT CAST('10.2.1489 14:34:59.1234' AS TIMESTAMP) FROM rdb$Database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ CAST +========================= + +1489-02-10 14:34:59.1234""" + +@pytest.mark.version('>=1.0') +def test_14_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/cast/test_15.py b/tests/functional/intfunc/cast/test_15.py new file mode 100644 index 00000000..ccb62226 --- /dev/null +++ b/tests/functional/intfunc/cast/test_15.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: functional.intfunc.cast.15 +# title: CAST DATE -> CHAR +# decription: CAST DATE -> CHAR +# Be careful about time format on FB server ! +# Universal format is not defined or not documented. +# +# Dependencies: +# CREATE DATABASE +# CAST CHAR -> DATE +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.intfunc.cast.cast_15 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT CAST(CAST('10.2.1973' AS DATE) AS CHAR(32)) FROM rdb$Database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """CAST +================================ + +1973-02-10""" + +@pytest.mark.version('>=1.0') +def test_15_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/cast/test_16.py b/tests/functional/intfunc/cast/test_16.py new file mode 100644 index 00000000..e9a37ebe --- /dev/null +++ b/tests/functional/intfunc/cast/test_16.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: functional.intfunc.cast.16 +# title: CAST DATE -> VARCHAR +# decription: CAST DATE -> VARCHAR +# Be careful about time format on FB server ! +# Universal format is not defined or not documented. +# +# Dependencies: +# CREATE DATABASE +# CAST CHAR -> DATE +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.intfunc.cast.cast_16 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT CAST(CAST('10.2.1973' AS DATE) AS VARCHAR(40)) FROM rdb$Database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """CAST +======================================== + +1973-02-10""" + +@pytest.mark.version('>=1.0') +def test_16_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/cast/test_17.py b/tests/functional/intfunc/cast/test_17.py new file mode 100644 index 00000000..4ec1d0c1 --- /dev/null +++ b/tests/functional/intfunc/cast/test_17.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: functional.intfunc.cast.17 +# title: CAST DATE -> TIMESTAMP +# decription: CAST DATE -> TIMESTAMP +# Be careful about date/time format on FB server ! +# Universal format is not defined or not documented. +# +# Dependencies: +# CREATE DATABASE +# CAST CHAR -> DATE +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.intfunc.cast.cast_17 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT CAST(CAST('10.2.1973' AS DATE) AS TIMESTAMP) FROM rdb$Database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ CAST +========================= + +1973-02-10 00:00:00.0000""" + +@pytest.mark.version('>=1.0') +def test_17_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/cast/test_18.py b/tests/functional/intfunc/cast/test_18.py new file mode 100644 index 00000000..6420c577 --- /dev/null +++ b/tests/functional/intfunc/cast/test_18.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: functional.intfunc.cast.18 +# title: CAST TIME -> CHAR +# decription: CAST TIME -> CHAR +# Be careful about date/time format on FB server ! +# Universal format is not defined or not documented. +# +# Dependencies: +# CREATE DATABASE +# CAST CHAR -> TIME +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.intfunc.cast.cast_18 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT CAST(CAST('13:28:45' AS TIME) AS CHAR(32)) FROM rdb$Database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """CAST +================================ + +13:28:45.0000""" + +@pytest.mark.version('>=1.0') +def test_18_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/cast/test_19.py b/tests/functional/intfunc/cast/test_19.py new file mode 100644 index 00000000..b88aabed --- /dev/null +++ b/tests/functional/intfunc/cast/test_19.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: functional.intfunc.cast.19 +# title: CAST TIME -> VARCHAR +# decription: CAST TIME -> VARCHAR +# Be careful about date/time format on FB server ! +# Universal format is not defined or not documented. +# +# Dependencies: +# CREATE DATABASE +# CAST CHAR -> TIME +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.intfunc.cast.cast_19 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT CAST(CAST('13:28:45' AS TIME) AS VARCHAR(32)) FROM rdb$Database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """CAST +================================ + +13:28:45.0000""" + +@pytest.mark.version('>=1.0') +def test_19_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/cast/test_20.py b/tests/functional/intfunc/cast/test_20.py new file mode 100644 index 00000000..8a44668b --- /dev/null +++ b/tests/functional/intfunc/cast/test_20.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: functional.intfunc.cast.20 +# title: CAST TIMESTAMP -> CHAR +# decription: CAST TIMESTAMP -> CHAR +# Be careful about date/time format on FB server ! +# Universal format is not defined or not documented. +# +# Dependencies: +# CREATE DATABASE +# CAST CHAR -> TIMESTAMP +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.intfunc.cast.cast_20 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT CAST(CAST('1.4.2002 0:59:59.1' AS TIMESTAMP) AS CHAR(50)) FROM rdb$Database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """CAST +================================================== + +2002-04-01 00:59:59.1000""" + +@pytest.mark.version('>=1.0') +def test_20_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/cast/test_21.py b/tests/functional/intfunc/cast/test_21.py new file mode 100644 index 00000000..070e890b --- /dev/null +++ b/tests/functional/intfunc/cast/test_21.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: functional.intfunc.cast.21 +# title: CAST TIMESTAMP -> VARCHAR +# decription: CAST TIMESTAMP -> VARCHAR +# Be careful about date/time format on FB server ! +# Universal format is not defined or not documented. +# +# Dependencies: +# CREATE DATABASE +# CAST CHAR -> TIMESTAMP +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.intfunc.cast.cast_21 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT CAST(CAST('1.4.2002 0:59:59.1' AS TIMESTAMP) AS VARCHAR(50)) FROM rdb$Database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """CAST +================================================== + +2002-04-01 00:59:59.1000""" + +@pytest.mark.version('>=1.0') +def test_21_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/cast/test_22.py b/tests/functional/intfunc/cast/test_22.py new file mode 100644 index 00000000..575a6728 --- /dev/null +++ b/tests/functional/intfunc/cast/test_22.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: functional.intfunc.cast.22 +# title: CAST TIMESTAMP -> DATE +# decription: CAST TIMESTAMP -> DATE +# Be careful about date/time format on FB server ! +# Universal format is not defined or not documented. +# +# Dependencies: +# CREATE DATABASE +# CAST CHAR -> TIMESTAMP +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.intfunc.cast.cast_22 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT CAST(CAST('1.4.2002 0:59:59.1' AS TIMESTAMP) AS DATE) FROM rdb$Database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ CAST +=========== + +2002-04-01""" + +@pytest.mark.version('>=1.0') +def test_22_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/cast/test_23.py b/tests/functional/intfunc/cast/test_23.py new file mode 100644 index 00000000..36fd625a --- /dev/null +++ b/tests/functional/intfunc/cast/test_23.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: functional.intfunc.cast.23 +# title: CAST TIMESTAMP -> TIME +# decription: CAST TIMESTAMP -> TIME +# Be careful about date/time format on FB server ! +# Universal format is not defined or not documented. +# +# Dependencies: +# CREATE DATABASE +# CAST CHAR -> TIMESTAMP +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.intfunc.cast.cast_23 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT CAST(CAST('1.4.2002 0:59:59.1' AS TIMESTAMP) AS TIME) FROM rdb$Database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ CAST +============= + +00:59:59.1000 +""" + +@pytest.mark.version('>=1.0') +def test_23_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/count/test_01.py b/tests/functional/intfunc/count/test_01.py new file mode 100644 index 00000000..d2133b93 --- /dev/null +++ b/tests/functional/intfunc/count/test_01.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: functional.intfunc.count_01 +# title: COUNT - empty +# decription: COUNT - Select from empty table +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.intfunc.count.count_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE test( id INTEGER);""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT COUNT(*) FROM test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ COUNT +===================== + 0 + +""" + +@pytest.mark.version('>=3.0') +def test_count_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/count/test_02.py b/tests/functional/intfunc/count/test_02.py new file mode 100644 index 00000000..a8febdf0 --- /dev/null +++ b/tests/functional/intfunc/count/test_02.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: functional.intfunc.count_02 +# title: COUNT +# decription: Count of Not Null values and count of rows and count of distinct values +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# INSERT +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.intfunc.count.count_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE test( id INTEGER); +INSERT INTO test VALUES(0); +INSERT INTO test VALUES(0); +INSERT INTO test VALUES(null); +INSERT INTO test VALUES(null); +INSERT INTO test VALUES(null); +INSERT INTO test VALUES(1); +INSERT INTO test VALUES(1); +INSERT INTO test VALUES(1); +INSERT INTO test VALUES(1); +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT COUNT(*), COUNT(ID), COUNT(DISTINCT ID) FROM test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ COUNT COUNT COUNT +===================== ===================== ===================== + 9 6 2 + +""" + +@pytest.mark.version('>=3.0') +def test_count_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/date/__init__.py b/tests/functional/intfunc/date/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/intfunc/date/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/intfunc/date/test_dateadd_01.py b/tests/functional/intfunc/date/test_dateadd_01.py new file mode 100644 index 00000000..ae142782 --- /dev/null +++ b/tests/functional/intfunc/date/test_dateadd_01.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: functional.intfunc.date.dateadd_01 +# title: test de la fonction dateadd pour l'ajout d'un jour +# decription: Returns a date/time/timestamp value increased (or decreased, when negative) by the specified amount of time. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.date.dateadd_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select dateadd(-1 day TO date '2008-02-06' ) as yesterday from rdb$database; +select dateadd(day,-1, date '2008-02-06' ) as yesterday from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + YESTERDAY +=========== +2008-02-05 + + + YESTERDAY +=========== +2008-02-05 + +""" + +@pytest.mark.version('>=2.1') +def test_dateadd_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/date/test_dateadd_02.py b/tests/functional/intfunc/date/test_dateadd_02.py new file mode 100644 index 00000000..22d12fb4 --- /dev/null +++ b/tests/functional/intfunc/date/test_dateadd_02.py @@ -0,0 +1,93 @@ +#coding:utf-8 +# +# id: functional.intfunc.date.dateadd_02 +# title: Test results of DATEADD function for MONTH +# decription: Returns a date/time/timestamp value increased (or decreased, when negative) by the specified amount of time. +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: functional.intfunc.date.dateadd_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + + -- doc\\sql.extensions\\README.builtin_functions.txt + -- 5) When using YEAR or MONTH and the input day is greater than the maximum possible day in the + -- result year/month, the result day is returned in the last day of the result year/month. + + set list on; + + select dateadd( 1 month to date '2004-01-31') as leap_jan_31_plus__01_month from rdb$database; + select dateadd( 1 month to date '2004-02-28') as leap_feb_28_plus__01_month from rdb$database; + select dateadd( 1 month to date '2004-02-29') as leap_feb_29_plus__01_month from rdb$database; + select dateadd( -1 month to date '2004-02-28') as leap_feb_28_minus_01_month from rdb$database; + select dateadd( -1 month to date '2004-02-29') as leap_feb_29_minus_01_month from rdb$database; + select dateadd( 11 month to date '2004-02-28') as leap_feb_28_plus__11_month from rdb$database; + select dateadd( 11 month to date '2004-02-29') as leap_feb_29_plus__11_month from rdb$database; + select dateadd( 12 month to date '2004-02-28') as leap_feb_28_plus__12_month from rdb$database; + select dateadd( 12 month to date '2004-02-29') as leap_feb_29_plus__12_month from rdb$database; + select dateadd(-11 month to date '2004-02-28') as leap_feb_28_minus_11_month from rdb$database; + select dateadd(-11 month to date '2004-02-29') as leap_feb_29_minus_11_month from rdb$database; + select dateadd(-12 month to date '2004-02-28') as leap_feb_28_minus_12_month from rdb$database; + select dateadd(-12 month to date '2004-02-29') as leap_feb_29_minus_12_month from rdb$database; + select dateadd( -1 month to date '2004-03-31') as leap_mar_31_minus_01_month from rdb$database; + + select dateadd( 1 month to date '2003-01-31') as nonl_jan_31_plus__01_month from rdb$database; + select dateadd( 1 month to date '2003-02-28') as nonl_feb_28_plus__01_month from rdb$database; + select dateadd( -1 month to date '2003-02-28') as nonl_feb_28_minus_01_month from rdb$database; + select dateadd( 11 month to date '2003-02-28') as nonl_feb_28_plus__11_month from rdb$database; + select dateadd( 12 month to date '2003-02-28') as nonl_feb_28_plus__12_month from rdb$database; + select dateadd(-11 month to date '2003-02-28') as nonl_feb_28_minus_11_month from rdb$database; + select dateadd(-12 month to date '2003-02-28') as nonl_feb_28_minus_12_month from rdb$database; + select dateadd( -1 month to date '2003-03-31') as nonl_mar_31_minus_01_month from rdb$database; + + -- old test code: + -- select dateadd(-1 month TO date '2008-02-06' ) as yesterday from rdb$database; + -- select dateadd(month,-1, date '2008-02-06' ) as yesterday from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + LEAP_JAN_31_PLUS__01_MONTH 2004-02-29 + LEAP_FEB_28_PLUS__01_MONTH 2004-03-28 + LEAP_FEB_29_PLUS__01_MONTH 2004-03-29 + LEAP_FEB_28_MINUS_01_MONTH 2004-01-28 + LEAP_FEB_29_MINUS_01_MONTH 2004-01-29 + LEAP_FEB_28_PLUS__11_MONTH 2005-01-28 + LEAP_FEB_29_PLUS__11_MONTH 2005-01-31 + LEAP_FEB_28_PLUS__12_MONTH 2005-02-28 + LEAP_FEB_29_PLUS__12_MONTH 2005-02-28 + LEAP_FEB_28_MINUS_11_MONTH 2003-03-28 + LEAP_FEB_29_MINUS_11_MONTH 2003-03-29 + LEAP_FEB_28_MINUS_12_MONTH 2003-02-28 + LEAP_FEB_29_MINUS_12_MONTH 2003-02-28 + LEAP_MAR_31_MINUS_01_MONTH 2004-02-29 + + NONL_JAN_31_PLUS__01_MONTH 2003-02-28 + NONL_FEB_28_PLUS__01_MONTH 2003-03-28 + NONL_FEB_28_MINUS_01_MONTH 2003-01-28 + NONL_FEB_28_PLUS__11_MONTH 2004-01-28 + NONL_FEB_28_PLUS__12_MONTH 2004-02-28 + NONL_FEB_28_MINUS_11_MONTH 2002-03-28 + NONL_FEB_28_MINUS_12_MONTH 2002-02-28 + NONL_MAR_31_MINUS_01_MONTH 2003-02-28 + """ + +@pytest.mark.version('>=2.5') +def test_dateadd_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/date/test_dateadd_03.py b/tests/functional/intfunc/date/test_dateadd_03.py new file mode 100644 index 00000000..4dad2053 --- /dev/null +++ b/tests/functional/intfunc/date/test_dateadd_03.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: functional.intfunc.date.dateadd_03 +# title: test de la fonction dateadd pour l'ajout d'une année +# decription: Returns a date/time/timestamp value increased (or decreased, when negative) by the specified amount of time. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.date.dateadd_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select dateadd(-1 year TO date '2008-02-06' ) as yesterday from rdb$database; +select dateadd(year,-1, date '2008-02-06' ) as yesterday from rdb$database; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + YESTERDAY +=========== +2007-02-06 + + + YESTERDAY +=========== +2007-02-06 + +""" + +@pytest.mark.version('>=2.1') +def test_dateadd_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/date/test_dateadd_04.py b/tests/functional/intfunc/date/test_dateadd_04.py new file mode 100644 index 00000000..f095202d --- /dev/null +++ b/tests/functional/intfunc/date/test_dateadd_04.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: functional.intfunc.date.dateadd_04 +# title: test de la fonction dateadd pour l'ajout d'une semaine +# decription: Returns a date/time/timestamp value increased (or decreased, when negative) by the specified amount of time. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.date.dateadd_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select dateadd(-1 day TO timestamp '2008-02-06 10:10:00' ) as yesterday from rdb$database; +select dateadd(day,-1, timestamp '2008-02-06 10:10:00' ) as yesterday from rdb$database; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + YESTERDAY +========================= +2008-02-05 10:10:00.0000 + + + YESTERDAY +========================= +2008-02-05 10:10:00.0000 + +""" + +@pytest.mark.version('>=2.1') +def test_dateadd_04_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/date/test_dateadd_05.py b/tests/functional/intfunc/date/test_dateadd_05.py new file mode 100644 index 00000000..23c83e1d --- /dev/null +++ b/tests/functional/intfunc/date/test_dateadd_05.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: functional.intfunc.date.dateadd_05 +# title: test de la fonction dateadd pour l'ajout d'une heure +# decription: Returns a date/time/timestamp value increased (or decreased, when negative) by the specified amount of time. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.date.dateadd_05 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select dateadd(-1 hour to time '12:12:00' ) as yesterday from rdb$database; +select dateadd(hour,-1, time '12:12:00' ) as yesterday from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + YESTERDAY +============= +11:12:00.0000 + + + YESTERDAY +============= +11:12:00.0000 + +""" + +@pytest.mark.version('>=2.1') +def test_dateadd_05_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/date/test_dateadd_06.py b/tests/functional/intfunc/date/test_dateadd_06.py new file mode 100644 index 00000000..4bee9a20 --- /dev/null +++ b/tests/functional/intfunc/date/test_dateadd_06.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: functional.intfunc.date.dateadd_06 +# title: test de la fonction dateadd pour l'ajout de minute a une heure +# decription: Returns a date/time/timestamp value increased (or decreased, when negative) by the specified amount of time. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.date.dateadd_06 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select dateadd(-1 minute to time '12:12:00' ) as yesterday from rdb$database; +select dateadd(minute,-1, time '12:12:00' ) as yesterday from rdb$database; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + YESTERDAY +============= +12:11:00.0000 + + + YESTERDAY +============= +12:11:00.0000 + +""" + +@pytest.mark.version('>=2.1') +def test_dateadd_06_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/date/test_dateadd_07.py b/tests/functional/intfunc/date/test_dateadd_07.py new file mode 100644 index 00000000..b7d5a03f --- /dev/null +++ b/tests/functional/intfunc/date/test_dateadd_07.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: functional.intfunc.date.dateadd_07 +# title: test de la fonction dateadd pour l'ajout d'une seconde +# decription: Returns a date/time/timestamp value increased (or decreased, when negative) by the specified amount of time. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.date.dateadd_07 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select dateadd(-1 second to time '12:12:00' ) as yesterday from rdb$database; +select dateadd(second,-1, time '12:12:00' ) as yesterday from rdb$database; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + YESTERDAY +============= +12:11:59.0000 + + + YESTERDAY +============= +12:11:59.0000 + +""" + +@pytest.mark.version('>=2.1') +def test_dateadd_07_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/date/test_dateadd_08.py b/tests/functional/intfunc/date/test_dateadd_08.py new file mode 100644 index 00000000..e5e4d89c --- /dev/null +++ b/tests/functional/intfunc/date/test_dateadd_08.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: functional.intfunc.date.dateadd_08 +# title: Dateadd milliseconds +# decription: +# tracker_id: CORE-1387 +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.date.dateadd_08 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select dateadd(-1 millisecond to time '12:12:00:0000' ) as test from rdb$database; +select dateadd(millisecond,-1, time '12:12:00:0000' ) as test from rdb$database; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TEST +============= +12:11:59.9990 + + + TEST +============= +12:11:59.9990 + +""" + +@pytest.mark.version('>=2.1') +def test_dateadd_08_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/date/test_datediff_01.py b/tests/functional/intfunc/date/test_datediff_01.py new file mode 100644 index 00000000..5f4b85bb --- /dev/null +++ b/tests/functional/intfunc/date/test_datediff_01.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: functional.intfunc.date.datediff_01 +# title: test de la fonction datediff pour avoir un resultat en seconde +# decription: Returns an exact numeric value representing the interval of time from the first date/time/timestamp value to the second one. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.date.datediff_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select datediff(SECOND,cast( '12/02/2008 13:33:33' as timestamp),cast( '12/02/2008 13:33:35' as timestamp)) from rdb$database; +select datediff(SECOND FROM cast( '12/02/2008 13:33:33' as timestamp) TO cast( '12/02/2008 13:33:35' as timestamp)) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DATEDIFF +===================== + 2 + + + DATEDIFF +===================== + 2 + +""" + +@pytest.mark.version('>=2.1') +def test_datediff_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/date/test_datediff_02.py b/tests/functional/intfunc/date/test_datediff_02.py new file mode 100644 index 00000000..b2c7937c --- /dev/null +++ b/tests/functional/intfunc/date/test_datediff_02.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: functional.intfunc.date.datediff_02 +# title: test de la fonction datediff pour avoir le resultat en minute +# decription: Returns an exact numeric value representing the interval of time from the first date/time/timestamp value to the second one. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.date.datediff_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select datediff(MINUTE,cast( '12/02/2008 13:33:33' as timestamp),cast( '12/02/2008 13:34:35' as timestamp)) from rdb$database; +select datediff(MINUTE FROM cast( '12/02/2008 13:33:33' as timestamp) TO cast( '12/02/2008 13:34:35' as timestamp)) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DATEDIFF +===================== + 1 + + + DATEDIFF +===================== + 1 + +""" + +@pytest.mark.version('>=2.1') +def test_datediff_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/date/test_datediff_03.py b/tests/functional/intfunc/date/test_datediff_03.py new file mode 100644 index 00000000..f59ffb53 --- /dev/null +++ b/tests/functional/intfunc/date/test_datediff_03.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: functional.intfunc.date.datediff_03 +# title: test de la fonction datediff pour avoir le resultat en heure +# decription: Returns an exact numeric value representing the interval of time from the first date/time/timestamp value to the second one. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.date.datediff_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select datediff(HOUR,cast( '12/02/2008 13:33:33' as timestamp),cast( '12/02/2008 14:34:35' as timestamp)) from rdb$database; +select datediff(HOUR FROM cast( '12/02/2008 13:33:33' as timestamp) TO cast( '12/02/2008 14:34:35' as timestamp)) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DATEDIFF +===================== + 1 + + + DATEDIFF +===================== + 1 + +""" + +@pytest.mark.version('>=2.1') +def test_datediff_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/date/test_datediff_04.py b/tests/functional/intfunc/date/test_datediff_04.py new file mode 100644 index 00000000..bea96903 --- /dev/null +++ b/tests/functional/intfunc/date/test_datediff_04.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: functional.intfunc.date.datediff_04 +# title: test de la fonction datediff pour avoir le resultat en annee +# decription: Returns an exact numeric value representing the interval of time from the first date/time/timestamp value to the second one. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.date.datediff_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select datediff(YEAR,cast( '12/02/2008 13:33:33' as timestamp),cast( '12/02/2009 13:34:35' as timestamp)) from rdb$database; +select datediff(YEAR FROM cast( '12/02/2008 13:33:33' as timestamp) TO cast( '12/02/2009 13:34:35' as timestamp)) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DATEDIFF +===================== + 1 + + + DATEDIFF +===================== + 1 + +""" + +@pytest.mark.version('>=2.1') +def test_datediff_04_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/date/test_datediff_05.py b/tests/functional/intfunc/date/test_datediff_05.py new file mode 100644 index 00000000..f25a7a98 --- /dev/null +++ b/tests/functional/intfunc/date/test_datediff_05.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: functional.intfunc.date.datediff_05 +# title: test de la fonction datediff pour avoir le resultat en mois +# decription: Returns an exact numeric value representing the interval of time from the first date/time/timestamp value to the second one. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.date.datediff_05 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select datediff(MONTH,cast( '12/02/2008 13:33:33' as timestamp),cast( '12/02/2009 13:34:35' as timestamp)) from rdb$database; +select datediff(MONTH FROM cast( '12/02/2008 13:33:33' as timestamp) TO cast( '12/02/2009 13:34:35' as timestamp)) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DATEDIFF +===================== + 12 + + + DATEDIFF +===================== + 12 + +""" + +@pytest.mark.version('>=2.1') +def test_datediff_05_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/date/test_datediff_06.py b/tests/functional/intfunc/date/test_datediff_06.py new file mode 100644 index 00000000..3b869217 --- /dev/null +++ b/tests/functional/intfunc/date/test_datediff_06.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: functional.intfunc.date.datediff_06 +# title: test de la fonction datediff pour avoir le resultat en jour +# decription: Returns an exact numeric value representing the interval of time from the first date/time/timestamp value to the second one. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.date.datediff_06 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select datediff(DAY,cast( '12/02/2008 13:33:33' as timestamp),cast( '12/02/2009 13:34:35' as timestamp)) from rdb$database; +select datediff(DAY FROM cast( '12/02/2008 13:33:33' as timestamp) TO cast( '12/02/2009 13:34:35' as timestamp)) from rdb$database; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DATEDIFF +===================== + 365 + + + DATEDIFF +===================== + 365 + +""" + +@pytest.mark.version('>=2.1') +def test_datediff_06_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/date/test_datediff_07.py b/tests/functional/intfunc/date/test_datediff_07.py new file mode 100644 index 00000000..88792fac --- /dev/null +++ b/tests/functional/intfunc/date/test_datediff_07.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: functional.intfunc.date.datediff_07 +# title: test de la fonction datediff pour avoir le resultat en minute +# decription: Returns an exact numeric value representing the interval of time from the first date/time/timestamp value to the second one. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.date.datediff_07 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select datediff(MILLISECOND,cast( '12/02/2008 13:33:33.0001' as timestamp),cast( '12/02/2008 13:33:35.0000' as timestamp)) from rdb$database; +select datediff(MILLISECOND FROM cast( '12/02/2008 13:33:33.0001' as timestamp) TO cast( '12/02/2008 13:33:35.0000' as timestamp)) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DATEDIFF +===================== + 1999 + + + DATEDIFF +===================== + 1999 + +""" + +@pytest.mark.version('>=2.1') +def test_datediff_07_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/date/test_extract_01.py b/tests/functional/intfunc/date/test_extract_01.py new file mode 100644 index 00000000..6921c2e0 --- /dev/null +++ b/tests/functional/intfunc/date/test_extract_01.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: functional.intfunc.date.extract_01 +# title: Test the extract week function +# decription: +# tracker_id: CORE-663 +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.date.extract_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select extract(week from date '30.12.2008'), extract(week from date '30.12.2009') from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +EXTRACT EXTRACT +======= ======= + 1 53 + +""" + +@pytest.mark.version('>=2.1') +def test_extract_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/date/test_extract_02.py b/tests/functional/intfunc/date/test_extract_02.py new file mode 100644 index 00000000..ea764316 --- /dev/null +++ b/tests/functional/intfunc/date/test_extract_02.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: functional.intfunc.date.extract_02 +# title: test extract function with miliseconds +# decription: +# tracker_id: CORE-1387 +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.date.extract_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select extract(millisecond from time '12:12:00.1111' ) as test from rdb$database; +select extract(millisecond from timestamp '2008-12-08 12:12:00.1111' ) as test from rdb$database; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TEST +============ + 111.1 + + + TEST +============ + 111.1 + +""" + +@pytest.mark.version('>=2.1') +def test_extract_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/encryption/__init__.py b/tests/functional/intfunc/encryption/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/intfunc/encryption/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/intfunc/encryption/test_block_cipher_basic.py b/tests/functional/intfunc/encryption/test_block_cipher_basic.py new file mode 100644 index 00000000..5bea7115 --- /dev/null +++ b/tests/functional/intfunc/encryption/test_block_cipher_basic.py @@ -0,0 +1,482 @@ +#coding:utf-8 +# +# id: functional.intfunc.encryption.block_cipher_basic +# title: +# Verify block crypto algorithms that are implemented in ENCRYPT/DECRYPT built-in functions. +# See doc\\sql.extensions\\README.builtin_functions.txt for details. +# +# Checked on 4.0.0.1691: OK, 1.561s. +# +# decription: +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set blob all; + + create or alter procedure sp_char_block_test(a_alg varchar(30)) as begin end; + commit; + + recreate table test_char( crypto_alg varchar(30), mode varchar(30), source_text varchar(32765), crypto_key varchar(128), crypto_iv varchar(16) ); + commit; + + set term ^; + execute block as + begin + rdb$set_context('USER_SESSION', 'DATA_LEN', 31744); + end + ^ + set term ;^ + + -- AES supports three key sizes: 128 bits, 192 bits, and 256 bits. + insert into test_char( + crypto_alg, + mode, + source_text, + crypto_key, + crypto_iv ) + values( + 'AES', + 'cfb', + lpad('', cast(rdb$get_context('USER_SESSION', 'DATA_LEN') as int),uuid_to_char(gen_uuid()) ), + '0101010101010101', + lpad('',16, uuid_to_char( gen_uuid() )) + ); + + + insert into test_char( + crypto_alg, + mode, + source_text, + crypto_key, + crypto_iv ) + values( + 'AES', + 'ctr', + lpad('', cast(rdb$get_context('USER_SESSION', 'DATA_LEN') as int),uuid_to_char(gen_uuid()) ), + lpad('',16, replace(uuid_to_char(gen_uuid()),'-','') ), + lpad('',16, uuid_to_char( gen_uuid() )) + ); + + + insert into test_char( + crypto_alg, + mode, + source_text, + crypto_key, + crypto_iv ) + values( + 'AES', + 'ecb', + lpad('', cast(rdb$get_context('USER_SESSION', 'DATA_LEN') as int),uuid_to_char(gen_uuid()) ), -- NB!! data_len must be divided to 16 w/o remainder for ECB! + lpad('',16, replace(uuid_to_char(gen_uuid()),'-','') ), + null + ); + + + + insert into test_char( + crypto_alg, + mode, + source_text, + crypto_key, + crypto_iv ) + values( + 'AES', + 'ofb', + lpad('', cast(rdb$get_context('USER_SESSION', 'DATA_LEN') as int),uuid_to_char(gen_uuid()) ), + lpad('',16, replace(uuid_to_char(gen_uuid()),'-','') ), + lpad('',16, uuid_to_char( gen_uuid() )) + ); + + ------------------------------------------------------ + + insert into test_char + select + 'ANUBIS', + mode, + source_text, + crypto_key, + crypto_iv + from test_char + where crypto_alg = 'AES' + ; + + + insert into test_char + select + 'BLOWFISH', + mode, + source_text, + crypto_key, + left(crypto_iv,8) + from test_char + where crypto_alg = 'AES' + ; + + + insert into test_char + select + 'KHAZAD', + mode, + source_text, + crypto_key, + left(crypto_iv,8) + from test_char + where crypto_alg = 'AES' + ; + + + insert into test_char + select + 'RC5', + mode, + source_text, + crypto_key, + left(crypto_iv,8) + from test_char + where crypto_alg = 'AES' + ; + + + insert into test_char + select + 'RC6', + mode, + source_text, + crypto_key, + lpad('', 16, crypto_iv) + from test_char + where crypto_alg = 'AES' + ; + + + insert into test_char + select + '"SAFER+"', + mode, + source_text, + crypto_key, + lpad('', 16, crypto_iv) + from test_char + where crypto_alg = 'AES' + ; + + + insert into test_char + select + 'TWOFISH', + mode, + source_text, + crypto_key, + lpad('', 16, crypto_iv) + from test_char + where crypto_alg = 'AES' + ; + + insert into test_char + select + 'XTEA', + mode, + source_text, + crypto_key, + lpad('', 8, crypto_iv) + from test_char + where crypto_alg = 'AES' + ; + + + + set term ^; + create or alter procedure sp_char_block_test + returns( + crypto_alg type of column test_char.crypto_alg + ,mode type of column test_char.mode + ,result_msg varchar(80) + ,src_text type of column test_char.source_text + ,decrypted_text type of column test_char.source_text + ) as + declare v_encrypted varchar(32700); + declare v_decrypted varchar(32700); + declare v_encrypt_sttm varchar(32700); + declare v_decrypt_sttm varchar(32700); + begin + for + select + t.source_text + ,t.crypto_alg + ,t.mode + ,t.crypto_key + ,t.crypto_iv + from test_char t + as cursor c + do begin + v_encrypt_sttm = 'select encrypt( q''{' || c.source_text || '}'' using ' || c.crypto_alg || coalesce( ' mode ' || c.mode , '' ) || ' key q''{' || c.crypto_key || '}''' || coalesce(' iv q''{' || c.crypto_iv || '}'' ', '') || ') from rdb$database'; + execute statement v_encrypt_sttm into v_encrypted; + + --v_decrypt_sttm = 'select decrypt( q''{' || v_encrypted || '}'' using ' || c.crypto_alg || coalesce( ' mode ' || c.mode , '' ) || ' key q''{' || c.crypto_key || '}''' || coalesce(' iv q''{' || c.crypto_iv || '}'' ', '') || ') from rdb$database'; + --v_decrypt_sttm = 'select decrypt( x''' || v_encrypted || ''' using ' || c.crypto_alg || coalesce( ' mode ' || c.mode , '' ) || ' key q''{' || c.crypto_key || '}''' || coalesce(' iv q''{' || c.crypto_iv || '}'' ', '') || ') from rdb$database'; + v_decrypt_sttm = 'select decrypt( cast(? as varbinary(32700)) using ' || c.crypto_alg || coalesce( ' mode ' || c.mode , '' ) || ' key q''{' || c.crypto_key || '}''' || coalesce(' iv q''{' || c.crypto_iv || '}'' ', '') || ') from rdb$database'; + execute statement ( v_decrypt_sttm ) ( v_encrypted ) into v_decrypted; + + crypto_alg = upper(c.crypto_alg); + mode = upper(c.mode); + result_msg = 'Source and decrypted strings ' || iif ( v_decrypted = c.source_text, 'are identical.', 'DIFFERS (ERROR!)' ); + if ( v_decrypted is distinct from c.source_text ) then + begin + src_text = c.source_text; + decrypted_text = v_decrypted; + end + suspend; + end + end + ^ + set term ;^ + commit; + + select * from sp_char_block_test; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CRYPTO_ALG AES + MODE CFB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG AES + MODE CTR + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG AES + MODE ECB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG AES + MODE OFB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG ANUBIS + MODE CFB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG ANUBIS + MODE CTR + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG ANUBIS + MODE ECB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG ANUBIS + MODE OFB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG BLOWFISH + MODE CFB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG BLOWFISH + MODE CTR + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG BLOWFISH + MODE ECB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG BLOWFISH + MODE OFB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG KHAZAD + MODE CFB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG KHAZAD + MODE CTR + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG KHAZAD + MODE ECB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG KHAZAD + MODE OFB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG RC5 + MODE CFB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG RC5 + MODE CTR + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG RC5 + MODE ECB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG RC5 + MODE OFB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG RC6 + MODE CFB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG RC6 + MODE CTR + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG RC6 + MODE ECB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG RC6 + MODE OFB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG "SAFER+" + MODE CFB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG "SAFER+" + MODE CTR + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG "SAFER+" + MODE ECB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG "SAFER+" + MODE OFB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG TWOFISH + MODE CFB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG TWOFISH + MODE CTR + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG TWOFISH + MODE ECB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG TWOFISH + MODE OFB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG XTEA + MODE CFB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG XTEA + MODE CTR + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG XTEA + MODE ECB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG XTEA + MODE OFB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + """ + +@pytest.mark.version('>=4.0') +def test_block_cipher_basic_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/encryption/test_block_cipher_special.py b/tests/functional/intfunc/encryption/test_block_cipher_special.py new file mode 100644 index 00000000..4fa82eb6 --- /dev/null +++ b/tests/functional/intfunc/encryption/test_block_cipher_special.py @@ -0,0 +1,325 @@ +#coding:utf-8 +# +# id: functional.intfunc.encryption.block_cipher_special +# title: +# Verify block crypto algorithms that are implemented in ENCRYPT/DECRYPT built-in functions. +# Additional tests for key length = 192 and 256 bits. +# See doc\\sql.extensions\\README.builtin_functions.txt for details. +# +# Checked on 4.0.0.1691: OK, 1.343s. +# +# decription: +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + create or alter procedure sp_char_block_test(a_alg varchar(30)) as begin end; + commit; + + recreate table test_char( crypto_alg varchar(30), mode varchar(30), source_text varchar(32765), crypto_key varchar(128), crypto_iv varchar(16) ); + commit; + + set term ^; + execute block as + begin + rdb$set_context('USER_SESSION', 'DATA_LEN', 31744); + end + ^ + set term ;^ + + + --############################ AES mode OFB ########################## + insert into test_char( + crypto_alg, + mode, + source_text, + crypto_key, + crypto_iv ) + values( + 'AES', + 'ofb', + lpad('', cast(rdb$get_context('USER_SESSION', 'DATA_LEN') as int),uuid_to_char(gen_uuid()) ), + lpad('', 24, '01'), -- 192 bits + lpad('',16, uuid_to_char( gen_uuid() )) + ); + + insert into test_char( + crypto_alg, + mode, + source_text, + crypto_key, + crypto_iv ) + values( + 'AES', + 'ofb', + lpad('', cast(rdb$get_context('USER_SESSION', 'DATA_LEN') as int),uuid_to_char(gen_uuid()) ), + lpad('', 32, '01'), -- 256 bits + lpad('',16, uuid_to_char( gen_uuid() )) + ); + + + + --############################ AES mode CFB ########################## + insert into test_char( + crypto_alg, + mode, + source_text, + crypto_key, + crypto_iv ) + values( + 'AES', + 'cfb', + lpad('', cast(rdb$get_context('USER_SESSION', 'DATA_LEN') as int),uuid_to_char(gen_uuid()) ), + lpad('', 24, '01'), -- 192 bits + lpad('',16, uuid_to_char( gen_uuid() )) + ); + + insert into test_char( + crypto_alg, + mode, + source_text, + crypto_key, + crypto_iv ) + values( + 'AES', + 'cfb', + lpad('', cast(rdb$get_context('USER_SESSION', 'DATA_LEN') as int),uuid_to_char(gen_uuid()) ), + lpad('', 32, '01'), -- 256 bits + lpad('',16, uuid_to_char( gen_uuid() )) + ); + + + --############################ AES mode CTR ########################## + insert into test_char( + crypto_alg, + mode, + source_text, + crypto_key, + crypto_iv ) + values( + 'AES', + 'ctr', + lpad('', cast(rdb$get_context('USER_SESSION', 'DATA_LEN') as int),uuid_to_char(gen_uuid()) ), + lpad('', 24, '01'), -- 192 bits + lpad('',16, uuid_to_char( gen_uuid() )) + ); + + insert into test_char( + crypto_alg, + mode, + source_text, + crypto_key, + crypto_iv ) + values( + 'AES', + 'ctr', + lpad('', cast(rdb$get_context('USER_SESSION', 'DATA_LEN') as int),uuid_to_char(gen_uuid()) ), + lpad('', 32, '01'), -- 256 bits + lpad('',16, uuid_to_char( gen_uuid() )) + ); + + + --############################ AES mode ECB ########################## + insert into test_char( + crypto_alg, + mode, + source_text, + crypto_key ) + values( + 'AES', + 'ecb', + lpad('', cast(rdb$get_context('USER_SESSION', 'DATA_LEN') as int),uuid_to_char(gen_uuid()) ), + lpad('', 24, '01') -- 192 bits + ); + + insert into test_char( + crypto_alg, + mode, + source_text, + crypto_key ) + values( + 'AES', + 'ecb', + lpad('', cast(rdb$get_context('USER_SESSION', 'DATA_LEN') as int),uuid_to_char(gen_uuid()) ), + lpad('', 32, '01') -- 256 bits + ); + + + --############################ AES mode CBC ########################## + insert into test_char( + crypto_alg, + mode, + source_text, + crypto_key, + crypto_iv ) + values( + 'AES', + 'cbc', + lpad('', cast(rdb$get_context('USER_SESSION', 'DATA_LEN') as int),uuid_to_char(gen_uuid()) ), + lpad('', 24, '01'), -- 192 bits + lpad('', 16, uuid_to_char( gen_uuid() )) + ); + + insert into test_char( + crypto_alg, + mode, + source_text, + crypto_key, + crypto_iv ) + values( + 'AES', + 'cbc', + lpad('', cast(rdb$get_context('USER_SESSION', 'DATA_LEN') as int),uuid_to_char(gen_uuid()) ), + lpad('', 32, '01'), -- 256 bits + lpad('',16, uuid_to_char( gen_uuid() )) + ); + + + +/* +select encrypt('897897' using aes mode cfb key 'AbcdAbcdAbcdAbcd' iv '0123456789012345') from rdb$database; +select encrypt('897897' using aes mode ctr key 'AbcdAbcdAbcdAbcd' iv '0123456789012345') from rdb$database; +select encrypt( lpad('', 16, 'A') using aes mode ecb key '123456789012345678901234') from rdb$database; +select encrypt( lpad('', 16, 'A') using aes mode ecb key '12345678901234567890123456789012') from rdb$database; +select encrypt( lpad('', 16, 'A') using aes mode cbc key '123456789012345678901234' iv '1234567812345678') from rdb$database; +select encrypt( lpad('', 16, 'A') using aes mode cbc key '12345678901234567890123456789012' iv '1234567812345678') from rdb$database; + +*/ + + commit; + + set term ^; + create or alter procedure sp_char_block_test + returns( + crypto_alg type of column test_char.crypto_alg + ,mode type of column test_char.mode + ,result_msg varchar(80) + ,src_text type of column test_char.source_text + ,decrypted_text type of column test_char.source_text + ) as + declare v_encrypted varchar(32700); + declare v_decrypted varchar(32700); + declare v_encrypt_sttm varchar(32700); + declare v_decrypt_sttm varchar(32700); + begin + for + select + t.source_text + ,t.crypto_alg + ,t.mode + ,t.crypto_key + ,t.crypto_iv + from test_char t + as cursor c + do begin + v_encrypt_sttm = 'select encrypt( q''{' || c.source_text || '}'' using ' || c.crypto_alg || coalesce( ' mode ' || c.mode , '' ) || ' key q''{' || c.crypto_key || '}''' || coalesce(' iv q''{' || c.crypto_iv || '}'' ', '') || ') from rdb$database'; + execute statement v_encrypt_sttm into v_encrypted; + + v_decrypt_sttm = 'select decrypt( cast(? as varbinary(32700)) using ' || c.crypto_alg || coalesce( ' mode ' || c.mode , '' ) || ' key q''{' || c.crypto_key || '}''' || coalesce(' iv q''{' || c.crypto_iv || '}'' ', '') || ') from rdb$database'; + execute statement ( v_decrypt_sttm ) ( v_encrypted ) into v_decrypted; + + crypto_alg = upper(c.crypto_alg); + mode = upper(c.mode); + result_msg = 'Source and decrypted strings ' || iif ( v_decrypted = c.source_text, 'are identical.', 'DIFFERS (ERROR!)' ); + if ( v_decrypted is distinct from c.source_text ) then + begin + src_text = c.source_text; + decrypted_text = v_decrypted; + end + suspend; + end + end + ^ + set term ;^ + commit; + + select * from sp_char_block_test; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CRYPTO_ALG AES + MODE OFB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG AES + MODE OFB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG AES + MODE CFB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG AES + MODE CFB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG AES + MODE CTR + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG AES + MODE CTR + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG AES + MODE ECB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG AES + MODE ECB + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG AES + MODE CBC + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + + CRYPTO_ALG AES + MODE CBC + RESULT_MSG Source and decrypted strings are identical. + SRC_TEXT + DECRYPTED_TEXT + """ + +@pytest.mark.version('>=4.0') +def test_block_cipher_special_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/list/test_01.py b/tests/functional/intfunc/list/test_01.py new file mode 100644 index 00000000..8cf23fdb --- /dev/null +++ b/tests/functional/intfunc/list/test_01.py @@ -0,0 +1,229 @@ +#coding:utf-8 +# +# id: functional.intfunc.list_01 +# title: List with default options +# decription: +# tracker_id: CORE-964 +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.list.list_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [('list_blob_id.*', '')] + +init_script_1 = """ + recreate table test( + rel_name char(31) character set unicode_fss + ,idx_name char(31) character set unicode_fss + ); + commit; + + insert into test values ('RDB$RELATIONS', 'RDB$INDEX_0'); + insert into test values ('RDB$RELATIONS', 'RDB$INDEX_1'); + insert into test values ('RDB$FIELDS', 'RDB$INDEX_2'); + insert into test values ('RDB$RELATION_FIELDS', 'RDB$INDEX_3'); + insert into test values ('RDB$RELATION_FIELDS', 'RDB$INDEX_4'); + insert into test values ('RDB$INDICES', 'RDB$INDEX_5'); + insert into test values ('RDB$INDEX_SEGMENTS', 'RDB$INDEX_6'); + insert into test values ('RDB$SECURITY_CLASSES', 'RDB$INDEX_7'); + insert into test values ('RDB$TRIGGERS', 'RDB$INDEX_8'); + insert into test values ('RDB$FUNCTIONS', 'RDB$INDEX_9'); + insert into test values ('RDB$FUNCTION_ARGUMENTS', 'RDB$INDEX_10'); + insert into test values ('RDB$GENERATORS', 'RDB$INDEX_11'); + insert into test values ('RDB$RELATION_CONSTRAINTS', 'RDB$INDEX_12'); + insert into test values ('RDB$REF_CONSTRAINTS', 'RDB$INDEX_13'); + insert into test values ('RDB$CHECK_CONSTRAINTS', 'RDB$INDEX_14'); + insert into test values ('RDB$RELATION_FIELDS', 'RDB$INDEX_15'); + insert into test values ('RDB$FORMATS', 'RDB$INDEX_16'); + insert into test values ('RDB$FILTERS', 'RDB$INDEX_17'); + insert into test values ('RDB$PROCEDURE_PARAMETERS', 'RDB$INDEX_18'); + insert into test values ('RDB$CHARACTER_SETS', 'RDB$INDEX_19'); + insert into test values ('RDB$COLLATIONS', 'RDB$INDEX_20'); + insert into test values ('RDB$PROCEDURES', 'RDB$INDEX_21'); + insert into test values ('RDB$PROCEDURES', 'RDB$INDEX_22'); + insert into test values ('RDB$EXCEPTIONS', 'RDB$INDEX_23'); + insert into test values ('RDB$EXCEPTIONS', 'RDB$INDEX_24'); + insert into test values ('RDB$CHARACTER_SETS', 'RDB$INDEX_25'); + insert into test values ('RDB$COLLATIONS', 'RDB$INDEX_26'); + insert into test values ('RDB$DEPENDENCIES', 'RDB$INDEX_27'); + insert into test values ('RDB$DEPENDENCIES', 'RDB$INDEX_28'); + insert into test values ('RDB$USER_PRIVILEGES', 'RDB$INDEX_29'); + insert into test values ('RDB$USER_PRIVILEGES', 'RDB$INDEX_30'); + insert into test values ('RDB$INDICES', 'RDB$INDEX_31'); + insert into test values ('RDB$TRANSACTIONS', 'RDB$INDEX_32'); + insert into test values ('RDB$VIEW_RELATIONS', 'RDB$INDEX_33'); + insert into test values ('RDB$VIEW_RELATIONS', 'RDB$INDEX_34'); + insert into test values ('RDB$TRIGGER_MESSAGES', 'RDB$INDEX_35'); + insert into test values ('RDB$FIELD_DIMENSIONS', 'RDB$INDEX_36'); + insert into test values ('RDB$TYPES', 'RDB$INDEX_37'); + insert into test values ('RDB$TRIGGERS', 'RDB$INDEX_38'); + insert into test values ('RDB$ROLES', 'RDB$INDEX_39'); + insert into test values ('RDB$CHECK_CONSTRAINTS', 'RDB$INDEX_40'); + insert into test values ('RDB$INDICES', 'RDB$INDEX_41'); + insert into test values ('RDB$RELATION_CONSTRAINTS', 'RDB$INDEX_42'); + insert into test values ('RDB$RELATION_CONSTRAINTS', 'RDB$INDEX_43'); + insert into test values ('RDB$BACKUP_HISTORY', 'RDB$INDEX_44'); + insert into test values ('RDB$FILTERS', 'RDB$INDEX_45'); + insert into test values ('RDB$GENERATORS', 'RDB$INDEX_46'); + insert into test values ('RDB$PACKAGES', 'RDB$INDEX_47'); + insert into test values ('RDB$PROCEDURE_PARAMETERS', 'RDB$INDEX_48'); + insert into test values ('RDB$FUNCTION_ARGUMENTS', 'RDB$INDEX_49'); + insert into test values ('RDB$PROCEDURE_PARAMETERS', 'RDB$INDEX_50'); + insert into test values ('RDB$FUNCTION_ARGUMENTS', 'RDB$INDEX_51'); + insert into test values ('RDB$AUTH_MAPPING', 'RDB$INDEX_52'); + commit; + + create index test_rel_name_idx on test(rel_name); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set blob all; + select x.rel_name, list(trim(x.idx_name)) "list_blob_id" + from test x + where x.rel_name starting with upper('rdb$') + group by 1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + REL_NAME RDB$AUTH_MAPPING + list_blob_id 0:1 + RDB$INDEX_52 + + REL_NAME RDB$BACKUP_HISTORY + list_blob_id 0:2 + RDB$INDEX_44 + + REL_NAME RDB$CHARACTER_SETS + list_blob_id 0:3 + RDB$INDEX_19,RDB$INDEX_25 + + REL_NAME RDB$CHECK_CONSTRAINTS + list_blob_id 0:4 + RDB$INDEX_14,RDB$INDEX_40 + + REL_NAME RDB$COLLATIONS + list_blob_id 0:5 + RDB$INDEX_20,RDB$INDEX_26 + + REL_NAME RDB$DEPENDENCIES + list_blob_id 0:6 + RDB$INDEX_27,RDB$INDEX_28 + + REL_NAME RDB$EXCEPTIONS + list_blob_id 0:7 + RDB$INDEX_23,RDB$INDEX_24 + + REL_NAME RDB$FIELDS + list_blob_id 0:8 + RDB$INDEX_2 + + REL_NAME RDB$FIELD_DIMENSIONS + list_blob_id 0:9 + RDB$INDEX_36 + + REL_NAME RDB$FILTERS + list_blob_id 0:a + RDB$INDEX_17,RDB$INDEX_45 + + REL_NAME RDB$FORMATS + list_blob_id 0:b + RDB$INDEX_16 + + REL_NAME RDB$FUNCTIONS + list_blob_id 0:c + RDB$INDEX_9 + + REL_NAME RDB$FUNCTION_ARGUMENTS + list_blob_id 0:d + RDB$INDEX_10,RDB$INDEX_49,RDB$INDEX_51 + + REL_NAME RDB$GENERATORS + list_blob_id 0:e + RDB$INDEX_11,RDB$INDEX_46 + + REL_NAME RDB$INDEX_SEGMENTS + list_blob_id 0:f + RDB$INDEX_6 + + REL_NAME RDB$INDICES + list_blob_id 0:10 + RDB$INDEX_5,RDB$INDEX_31,RDB$INDEX_41 + + REL_NAME RDB$PACKAGES + list_blob_id 0:11 + RDB$INDEX_47 + + REL_NAME RDB$PROCEDURES + list_blob_id 0:12 + RDB$INDEX_21,RDB$INDEX_22 + + REL_NAME RDB$PROCEDURE_PARAMETERS + list_blob_id 0:13 + RDB$INDEX_18,RDB$INDEX_48,RDB$INDEX_50 + + REL_NAME RDB$REF_CONSTRAINTS + list_blob_id 0:14 + RDB$INDEX_13 + + REL_NAME RDB$RELATIONS + list_blob_id 0:15 + RDB$INDEX_0,RDB$INDEX_1 + + REL_NAME RDB$RELATION_CONSTRAINTS + list_blob_id 0:16 + RDB$INDEX_12,RDB$INDEX_42,RDB$INDEX_43 + + REL_NAME RDB$RELATION_FIELDS + list_blob_id 0:17 + RDB$INDEX_3,RDB$INDEX_4,RDB$INDEX_15 + + REL_NAME RDB$ROLES + list_blob_id 0:18 + RDB$INDEX_39 + + REL_NAME RDB$SECURITY_CLASSES + list_blob_id 0:19 + RDB$INDEX_7 + + REL_NAME RDB$TRANSACTIONS + list_blob_id 0:1a + RDB$INDEX_32 + + REL_NAME RDB$TRIGGERS + list_blob_id 0:1b + RDB$INDEX_8,RDB$INDEX_38 + + REL_NAME RDB$TRIGGER_MESSAGES + list_blob_id 0:1c + RDB$INDEX_35 + + REL_NAME RDB$TYPES + list_blob_id 0:1d + RDB$INDEX_37 + + REL_NAME RDB$USER_PRIVILEGES + list_blob_id 0:1e + RDB$INDEX_29,RDB$INDEX_30 + + REL_NAME RDB$VIEW_RELATIONS + list_blob_id 0:1f + RDB$INDEX_33,RDB$INDEX_34 + """ + +@pytest.mark.version('>=2.1') +def test_list_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/list/test_02.py b/tests/functional/intfunc/list/test_02.py new file mode 100644 index 00000000..363964c5 --- /dev/null +++ b/tests/functional/intfunc/list/test_02.py @@ -0,0 +1,229 @@ +#coding:utf-8 +# +# id: functional.intfunc.list_02 +# title: List function with delimiter specified +# decription: +# tracker_id: CORE-964 +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.list.list_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [('list_blob_id.*', '')] + +init_script_1 = """ + recreate table test( + rel_name char(31) character set unicode_fss + ,idx_name char(31) character set unicode_fss + ); + commit; + + insert into test values ('RDB$RELATIONS', 'RDB$INDEX_0'); + insert into test values ('RDB$RELATIONS', 'RDB$INDEX_1'); + insert into test values ('RDB$FIELDS', 'RDB$INDEX_2'); + insert into test values ('RDB$RELATION_FIELDS', 'RDB$INDEX_3'); + insert into test values ('RDB$RELATION_FIELDS', 'RDB$INDEX_4'); + insert into test values ('RDB$INDICES', 'RDB$INDEX_5'); + insert into test values ('RDB$INDEX_SEGMENTS', 'RDB$INDEX_6'); + insert into test values ('RDB$SECURITY_CLASSES', 'RDB$INDEX_7'); + insert into test values ('RDB$TRIGGERS', 'RDB$INDEX_8'); + insert into test values ('RDB$FUNCTIONS', 'RDB$INDEX_9'); + insert into test values ('RDB$FUNCTION_ARGUMENTS', 'RDB$INDEX_10'); + insert into test values ('RDB$GENERATORS', 'RDB$INDEX_11'); + insert into test values ('RDB$RELATION_CONSTRAINTS', 'RDB$INDEX_12'); + insert into test values ('RDB$REF_CONSTRAINTS', 'RDB$INDEX_13'); + insert into test values ('RDB$CHECK_CONSTRAINTS', 'RDB$INDEX_14'); + insert into test values ('RDB$RELATION_FIELDS', 'RDB$INDEX_15'); + insert into test values ('RDB$FORMATS', 'RDB$INDEX_16'); + insert into test values ('RDB$FILTERS', 'RDB$INDEX_17'); + insert into test values ('RDB$PROCEDURE_PARAMETERS', 'RDB$INDEX_18'); + insert into test values ('RDB$CHARACTER_SETS', 'RDB$INDEX_19'); + insert into test values ('RDB$COLLATIONS', 'RDB$INDEX_20'); + insert into test values ('RDB$PROCEDURES', 'RDB$INDEX_21'); + insert into test values ('RDB$PROCEDURES', 'RDB$INDEX_22'); + insert into test values ('RDB$EXCEPTIONS', 'RDB$INDEX_23'); + insert into test values ('RDB$EXCEPTIONS', 'RDB$INDEX_24'); + insert into test values ('RDB$CHARACTER_SETS', 'RDB$INDEX_25'); + insert into test values ('RDB$COLLATIONS', 'RDB$INDEX_26'); + insert into test values ('RDB$DEPENDENCIES', 'RDB$INDEX_27'); + insert into test values ('RDB$DEPENDENCIES', 'RDB$INDEX_28'); + insert into test values ('RDB$USER_PRIVILEGES', 'RDB$INDEX_29'); + insert into test values ('RDB$USER_PRIVILEGES', 'RDB$INDEX_30'); + insert into test values ('RDB$INDICES', 'RDB$INDEX_31'); + insert into test values ('RDB$TRANSACTIONS', 'RDB$INDEX_32'); + insert into test values ('RDB$VIEW_RELATIONS', 'RDB$INDEX_33'); + insert into test values ('RDB$VIEW_RELATIONS', 'RDB$INDEX_34'); + insert into test values ('RDB$TRIGGER_MESSAGES', 'RDB$INDEX_35'); + insert into test values ('RDB$FIELD_DIMENSIONS', 'RDB$INDEX_36'); + insert into test values ('RDB$TYPES', 'RDB$INDEX_37'); + insert into test values ('RDB$TRIGGERS', 'RDB$INDEX_38'); + insert into test values ('RDB$ROLES', 'RDB$INDEX_39'); + insert into test values ('RDB$CHECK_CONSTRAINTS', 'RDB$INDEX_40'); + insert into test values ('RDB$INDICES', 'RDB$INDEX_41'); + insert into test values ('RDB$RELATION_CONSTRAINTS', 'RDB$INDEX_42'); + insert into test values ('RDB$RELATION_CONSTRAINTS', 'RDB$INDEX_43'); + insert into test values ('RDB$BACKUP_HISTORY', 'RDB$INDEX_44'); + insert into test values ('RDB$FILTERS', 'RDB$INDEX_45'); + insert into test values ('RDB$GENERATORS', 'RDB$INDEX_46'); + insert into test values ('RDB$PACKAGES', 'RDB$INDEX_47'); + insert into test values ('RDB$PROCEDURE_PARAMETERS', 'RDB$INDEX_48'); + insert into test values ('RDB$FUNCTION_ARGUMENTS', 'RDB$INDEX_49'); + insert into test values ('RDB$PROCEDURE_PARAMETERS', 'RDB$INDEX_50'); + insert into test values ('RDB$FUNCTION_ARGUMENTS', 'RDB$INDEX_51'); + insert into test values ('RDB$AUTH_MAPPING', 'RDB$INDEX_52'); + commit; + + create index test_rel_name_idx on test(rel_name); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set blob all; + select x.rel_name, list(trim(x.idx_name), ':') "list_blob_id" + from test x + where x.rel_name starting with upper('rdb$') + group by 1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + REL_NAME RDB$AUTH_MAPPING + list_blob_id 0:1 + RDB$INDEX_52 + + REL_NAME RDB$BACKUP_HISTORY + list_blob_id 0:2 + RDB$INDEX_44 + + REL_NAME RDB$CHARACTER_SETS + list_blob_id 0:3 + RDB$INDEX_19:RDB$INDEX_25 + + REL_NAME RDB$CHECK_CONSTRAINTS + list_blob_id 0:4 + RDB$INDEX_14:RDB$INDEX_40 + + REL_NAME RDB$COLLATIONS + list_blob_id 0:5 + RDB$INDEX_20:RDB$INDEX_26 + + REL_NAME RDB$DEPENDENCIES + list_blob_id 0:6 + RDB$INDEX_27:RDB$INDEX_28 + + REL_NAME RDB$EXCEPTIONS + list_blob_id 0:7 + RDB$INDEX_23:RDB$INDEX_24 + + REL_NAME RDB$FIELDS + list_blob_id 0:8 + RDB$INDEX_2 + + REL_NAME RDB$FIELD_DIMENSIONS + list_blob_id 0:9 + RDB$INDEX_36 + + REL_NAME RDB$FILTERS + list_blob_id 0:a + RDB$INDEX_17:RDB$INDEX_45 + + REL_NAME RDB$FORMATS + list_blob_id 0:b + RDB$INDEX_16 + + REL_NAME RDB$FUNCTIONS + list_blob_id 0:c + RDB$INDEX_9 + + REL_NAME RDB$FUNCTION_ARGUMENTS + list_blob_id 0:d + RDB$INDEX_10:RDB$INDEX_49:RDB$INDEX_51 + + REL_NAME RDB$GENERATORS + list_blob_id 0:e + RDB$INDEX_11:RDB$INDEX_46 + + REL_NAME RDB$INDEX_SEGMENTS + list_blob_id 0:f + RDB$INDEX_6 + + REL_NAME RDB$INDICES + list_blob_id 0:10 + RDB$INDEX_5:RDB$INDEX_31:RDB$INDEX_41 + + REL_NAME RDB$PACKAGES + list_blob_id 0:11 + RDB$INDEX_47 + + REL_NAME RDB$PROCEDURES + list_blob_id 0:12 + RDB$INDEX_21:RDB$INDEX_22 + + REL_NAME RDB$PROCEDURE_PARAMETERS + list_blob_id 0:13 + RDB$INDEX_18:RDB$INDEX_48:RDB$INDEX_50 + + REL_NAME RDB$REF_CONSTRAINTS + list_blob_id 0:14 + RDB$INDEX_13 + + REL_NAME RDB$RELATIONS + list_blob_id 0:15 + RDB$INDEX_0:RDB$INDEX_1 + + REL_NAME RDB$RELATION_CONSTRAINTS + list_blob_id 0:16 + RDB$INDEX_12:RDB$INDEX_42:RDB$INDEX_43 + + REL_NAME RDB$RELATION_FIELDS + list_blob_id 0:17 + RDB$INDEX_3:RDB$INDEX_4:RDB$INDEX_15 + + REL_NAME RDB$ROLES + list_blob_id 0:18 + RDB$INDEX_39 + + REL_NAME RDB$SECURITY_CLASSES + list_blob_id 0:19 + RDB$INDEX_7 + + REL_NAME RDB$TRANSACTIONS + list_blob_id 0:1a + RDB$INDEX_32 + + REL_NAME RDB$TRIGGERS + list_blob_id 0:1b + RDB$INDEX_8:RDB$INDEX_38 + + REL_NAME RDB$TRIGGER_MESSAGES + list_blob_id 0:1c + RDB$INDEX_35 + + REL_NAME RDB$TYPES + list_blob_id 0:1d + RDB$INDEX_37 + + REL_NAME RDB$USER_PRIVILEGES + list_blob_id 0:1e + RDB$INDEX_29:RDB$INDEX_30 + + REL_NAME RDB$VIEW_RELATIONS + list_blob_id 0:1f + RDB$INDEX_33:RDB$INDEX_34 + """ + +@pytest.mark.version('>=2.1') +def test_list_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/list/test_03.py b/tests/functional/intfunc/list/test_03.py new file mode 100644 index 00000000..91680670 --- /dev/null +++ b/tests/functional/intfunc/list/test_03.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: functional.intfunc.list_03 +# title: List function with distinct option +# decription: +# tracker_id: CORE-964 +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.list.list_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# c = db_conn.cursor() +# c.execute("SELECT RDB$SYSTEM_FLAG, LIST(DISTINCT TRIM(RDB$OWNER_NAME)) FROM RDB$RELATIONS WHERE RDB$SYSTEM_FLAG=1 GROUP BY 1;") +# +# printData(c) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """RDB$SYSTEM_FLAG LIST +--------------- ---- +1 SYSDBA +""" + +@pytest.mark.version('>=2.1') +@pytest.mark.xfail +def test_list_03_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/intfunc/math/__init__.py b/tests/functional/intfunc/math/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/intfunc/math/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/intfunc/math/test_abs_01.py b/tests/functional/intfunc/math/test_abs_01.py new file mode 100644 index 00000000..c451aa34 --- /dev/null +++ b/tests/functional/intfunc/math/test_abs_01.py @@ -0,0 +1,37 @@ +#coding:utf-8 +# +# id: functional.intfunc.math.abs_01 +# title: New Built-in Functions, Firebird 2.1 : ABS( ) +# decription: test of ABS( ) function Returns the absolute value of a number. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.math.abs_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select ABS( -1 ) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ ABS +===================== + 1 +""" + +@pytest.mark.version('>=2.1') +def test_abs_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/math/test_acos_01.py b/tests/functional/intfunc/math/test_acos_01.py new file mode 100644 index 00000000..7ef65319 --- /dev/null +++ b/tests/functional/intfunc/math/test_acos_01.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: functional.intfunc.math.acos_01 +# title: New Built-in Functions, Firebird 2.1 : ACOS( ) +# decription: test of ACOS +# +# Returns the arc cosine of a number. Argument to ACOS must be in the range -1 to 1. Returns a value in the range 0 to PI. er. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.math.acos_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select cast( ACOS( 1 ) AS DECIMAL(18,15)) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CAST +===================== + 0.000000000000000 + +""" + +@pytest.mark.version('>=2.1') +def test_acos_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/math/test_asin_01.py b/tests/functional/intfunc/math/test_asin_01.py new file mode 100644 index 00000000..034a0682 --- /dev/null +++ b/tests/functional/intfunc/math/test_asin_01.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: functional.intfunc.math.asin_01 +# title: New Built-in Functions, Firebird 2.1 : ASIN( ) +# decription: test of ASIN +# +# Returns the arc sine of a number. The argument to ASIN must be in the range -1 to 1. It returns a result in the range -PI/2 to PI/2. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.math.asin_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select asin( 1 ) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ ASIN +======================= + 1.570796326794897 +""" + +@pytest.mark.version('>=2.1') +def test_asin_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/math/test_atan2_01.py b/tests/functional/intfunc/math/test_atan2_01.py new file mode 100644 index 00000000..9911f39b --- /dev/null +++ b/tests/functional/intfunc/math/test_atan2_01.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: functional.intfunc.math.atan2_01 +# title: New Built-in Functions, Firebird 2.1 : ATAN2( , ) +# decription: test of ATAN2 +# +# Returns the arc tangent of the first number / the second number. Returns a value in the range -PI to PI. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.math.atan2_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select ATAN2( 1, 1) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ ATAN2 +======================= + 0.7853981633974483 + +""" + +@pytest.mark.version('>=2.1') +def test_atan2_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/math/test_atan_01.py b/tests/functional/intfunc/math/test_atan_01.py new file mode 100644 index 00000000..7baac9b5 --- /dev/null +++ b/tests/functional/intfunc/math/test_atan_01.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: functional.intfunc.math.atan_01 +# title: New Built-in Functions, Firebird 2.1 : ATAN( ) +# decription: test of ATAN +# +# Returns the arc tangent of a number. Returns a value in the range -PI/2 to PI/2. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.math.atan_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select ATAN( 1 ) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ ATAN +======================= + 0.7853981633974483 + +""" + +@pytest.mark.version('>=2.1') +def test_atan_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/math/test_ceil_01.py b/tests/functional/intfunc/math/test_ceil_01.py new file mode 100644 index 00000000..3856aa5c --- /dev/null +++ b/tests/functional/intfunc/math/test_ceil_01.py @@ -0,0 +1,48 @@ +#coding:utf-8 +# +# id: functional.intfunc.math.ceil_01 +# title: New Built-in Functions, Firebird 2.1 : CEIL( ) +# decription: test of CEIL +# Returns a value representing the smallest integer that is greater than or equal to the input argument. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.math.ceil_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select CEIL( 2.1) from rdb$database; +select CEIL( -2.1) from rdb$database; + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ CEIL +===================== + 3 + CEIL +===================== + -2 + + + + +""" + +@pytest.mark.version('>=2.1') +def test_ceil_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/math/test_cos_01.py b/tests/functional/intfunc/math/test_cos_01.py new file mode 100644 index 00000000..45fb203c --- /dev/null +++ b/tests/functional/intfunc/math/test_cos_01.py @@ -0,0 +1,48 @@ +#coding:utf-8 +# +# id: functional.intfunc.math.cos_01 +# title: New Built-in Functions, Firebird 2.1 : COS( ) +# decription: test of COS +# Returns the cosine of a number. The angle is specified in radians and returns a value in the range -1 to 1. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.math.cos_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select COS( 14) from rdb$database; +select COS( 0) from rdb$database; + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ COS + ======================= + 0.1367372182078336 + COS + ======================= + 1.000000000000000 + + + + +""" + +@pytest.mark.version('>=2.1') +def test_cos_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/math/test_cosh_01.py b/tests/functional/intfunc/math/test_cosh_01.py new file mode 100644 index 00000000..6b2eedca --- /dev/null +++ b/tests/functional/intfunc/math/test_cosh_01.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: functional.intfunc.math.cosh_01 +# title: New Built-in Functions, Firebird 2.1 : COSH( ) +# decription: test of COSH +# Returns the hyperbolic cosine of a number. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.math.cosh_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select COSH( 1) from rdb$database; +select COSH( 0) from rdb$database; + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ COSH + ======================= + 1.543080634815244 + + + COSH + ======================= + 1.000000000000000 + + + + +""" + +@pytest.mark.version('>=2.1') +def test_cosh_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/math/test_cot_01.py b/tests/functional/intfunc/math/test_cot_01.py new file mode 100644 index 00000000..21328e4c --- /dev/null +++ b/tests/functional/intfunc/math/test_cot_01.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: functional.intfunc.math.cot_01 +# title: test de la fonction cot +# decription: returns 1 / tan(argument) +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.math.cot_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select cast(COT(1) AS DECIMAL(18,15)) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CAST +===================== + 0.642092615934331 + +""" + +@pytest.mark.version('>=2.1') +def test_cot_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/math/test_exp_01.py b/tests/functional/intfunc/math/test_exp_01.py new file mode 100644 index 00000000..7305fca8 --- /dev/null +++ b/tests/functional/intfunc/math/test_exp_01.py @@ -0,0 +1,38 @@ +#coding:utf-8 +# +# id: functional.intfunc.math.exp_01 +# title: test for EXP( ) +# decription: Returns the exponential e to the argument. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.math.exp_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ +select EXP( 3) from rdb$database; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ EXP + ======================= + 20.08553692318767""" + +@pytest.mark.version('>=2.1') +def test_exp_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/math/test_floor_01.py b/tests/functional/intfunc/math/test_floor_01.py new file mode 100644 index 00000000..9acb9aec --- /dev/null +++ b/tests/functional/intfunc/math/test_floor_01.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: functional.intfunc.math.floor_01 +# title: test for FLOOR +# decription: Returns a value representing the largest integer that is less than or equal to the input argument +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.math.floor_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select FLOOR(2.1) from rdb$database; + select FLOOR(-4.4) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ FLOOR + ===================== + 2 + + + FLOOR + ===================== + -5""" + +@pytest.mark.version('>=2.1') +def test_floor_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/math/test_ln_01.py b/tests/functional/intfunc/math/test_ln_01.py new file mode 100644 index 00000000..2df2edbb --- /dev/null +++ b/tests/functional/intfunc/math/test_ln_01.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: functional.intfunc.math.ln_01 +# title: test for LN function +# decription: LN( ) +# Returns the natural logarithm of a number. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.math.ln_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + select ln(5) from rdb$database; + + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ LN + ======================= + 1.609437912434100""" + +@pytest.mark.version('>=2.1') +def test_ln_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/math/test_log10_01.py b/tests/functional/intfunc/math/test_log10_01.py new file mode 100644 index 00000000..d18b4034 --- /dev/null +++ b/tests/functional/intfunc/math/test_log10_01.py @@ -0,0 +1,38 @@ +#coding:utf-8 +# +# id: functional.intfunc.math.log10_01 +# title: test for LOG10 function +# decription: LOG10( ) +# +# Returns the logarithm base ten of a number. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.math.log10_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ select log10(6) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ LOG10 + ======================= + 0.7781512503836436""" + +@pytest.mark.version('>=2.1') +def test_log10_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/math/test_log_01.py b/tests/functional/intfunc/math/test_log_01.py new file mode 100644 index 00000000..7aa1068e --- /dev/null +++ b/tests/functional/intfunc/math/test_log_01.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: functional.intfunc.math.log_01 +# title: test for LOG function +# decription: LOG( , ) +# +# returns the logarithm base x of y. +# +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.math.log_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select log(6, 10) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ LOG + ======================= + 1.285097208938469""" + +@pytest.mark.version('>=2.1') +def test_log_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/math/test_maxvalue_01.py b/tests/functional/intfunc/math/test_maxvalue_01.py new file mode 100644 index 00000000..2af59efd --- /dev/null +++ b/tests/functional/intfunc/math/test_maxvalue_01.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: functional.intfunc.math.maxvalue_01 +# title: test for MAXVALUE function +# decription: MAXVALUE( [, ...] ) +# +# Returns the maximum value of a list of values. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.math.maxvalue_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ select maxvalue(54, 87, 10) from rdb$database; + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ MAXVALUE + ============ + 87 +""" + +@pytest.mark.version('>=2.1') +def test_maxvalue_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/math/test_minvalue_01.py b/tests/functional/intfunc/math/test_minvalue_01.py new file mode 100644 index 00000000..48839557 --- /dev/null +++ b/tests/functional/intfunc/math/test_minvalue_01.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: functional.intfunc.math.minvalue_01 +# title: test for MINVALUE function +# decription: MINVALUE( [, ... ) +# +# Returns the minimun value of a list of values. +# +# +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.math.minvalue_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ select minvalue(9, 7, 10) from rdb$database; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ MINVALUE + ============ + 7""" + +@pytest.mark.version('>=2.1') +def test_minvalue_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/math/test_mod_01.py b/tests/functional/intfunc/math/test_mod_01.py new file mode 100644 index 00000000..a2b8c2c2 --- /dev/null +++ b/tests/functional/intfunc/math/test_mod_01.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: functional.intfunc.math.mod_01 +# title: test for MOD function +# decription: +# MOD( , ) +# +# Modulo: MOD(X, Y) returns the remainder part of the division of X by Y. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.math.mod_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ select MOD(11,10) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ MOD + ============ + 1 +""" + +@pytest.mark.version('>=2.1') +def test_mod_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/math/test_pi_01.py b/tests/functional/intfunc/math/test_pi_01.py new file mode 100644 index 00000000..05f8fe17 --- /dev/null +++ b/tests/functional/intfunc/math/test_pi_01.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: functional.intfunc.math.pi_01 +# title: test for PI function +# decription: PI() +# +# Returns the PI constant (3.1459...). +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.math.pi_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ select PI() from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ PI + ======================= + 3.141592653589793 +""" + +@pytest.mark.version('>=2.1') +def test_pi_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/math/test_power_01.py b/tests/functional/intfunc/math/test_power_01.py new file mode 100644 index 00000000..a7903b09 --- /dev/null +++ b/tests/functional/intfunc/math/test_power_01.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: functional.intfunc.math.power_01 +# title: test for POWER function +# decription: POWER( , ) +# +# POWER(X, Y) returns X to the power of Y. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.math.power_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ select power(2, 3) from rdb$database; + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ POWER + ======================= + 8.000000000000000""" + +@pytest.mark.version('>=2.1') +def test_power_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/math/test_rand_01.py b/tests/functional/intfunc/math/test_rand_01.py new file mode 100644 index 00000000..20a1f639 --- /dev/null +++ b/tests/functional/intfunc/math/test_rand_01.py @@ -0,0 +1,68 @@ +#coding:utf-8 +# +# id: functional.intfunc.math.rand_01 +# title: test for RAND function +# decription: +# RAND() +# Returns a random number between 0 and 1. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.intfunc.math.rand_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """create table test( id char(30) ); + +--on verrifie qu'il y en a pas deux identique +insert into test values(CAST(rand() AS VARCHAR(255)) ); +insert into test values(CAST(rand() AS VARCHAR(255)) ); +insert into test values(CAST(rand() AS VARCHAR(255)) ); +insert into test values(CAST(rand() AS VARCHAR(255)) ); +insert into test values(CAST(rand() AS VARCHAR(255)) ); +insert into test values(CAST(rand() AS VARCHAR(255)) ); +insert into test values(CAST(rand() AS VARCHAR(255)) ); +insert into test values(CAST(rand() AS VARCHAR(255)) ); +insert into test values(CAST(rand() AS VARCHAR(255)) ); +insert into test values(CAST(rand() AS VARCHAR(255)) ); +insert into test values(CAST(rand() AS VARCHAR(255)) ); +insert into test values(CAST(rand() AS VARCHAR(255)) ); + + +select count(id) from test group by id;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ COUNT +===================== + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + +""" + +@pytest.mark.version('>=3.0') +def test_rand_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/math/test_round_01.py b/tests/functional/intfunc/math/test_round_01.py new file mode 100644 index 00000000..4a43d8df --- /dev/null +++ b/tests/functional/intfunc/math/test_round_01.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: functional.intfunc.math.round_01 +# title: test for ROUND function +# decription: +# +# ROUND( , ) +# +# Returns a number rounded to the specified scale. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.math.round_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ select ROUND(5.7778, 3) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ ROUND + ===================== + 5.7780""" + +@pytest.mark.version('>=2.1') +def test_round_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/math/test_sign_01.py b/tests/functional/intfunc/math/test_sign_01.py new file mode 100644 index 00000000..c735539b --- /dev/null +++ b/tests/functional/intfunc/math/test_sign_01.py @@ -0,0 +1,51 @@ +#coding:utf-8 +# +# id: functional.intfunc.math.sign_01 +# title: test for SIGN function +# decription: +# SIGN( ) +# +# Returns 1, 0, or -1 depending on whether the input value is positive, zero or negative, respectively. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.math.sign_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ select SIGN(-9) from rdb$database; + select SIGN(8) from rdb$database; + select SIGN(0) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ SIGN + ======= + -1 + + + SIGN + ======= + 1 + + + SIGN + ======= + 0""" + +@pytest.mark.version('>=2.1') +def test_sign_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/math/test_sin_01.py b/tests/functional/intfunc/math/test_sin_01.py new file mode 100644 index 00000000..a7044956 --- /dev/null +++ b/tests/functional/intfunc/math/test_sin_01.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: functional.intfunc.math.sin_01 +# title: test for SIN function +# decription: +# +# SIN( ) +# +# +# Returns the sine of an input number that is expressed in radians. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.math.sin_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ select CAST(SIN(12) AS DECIMAL(18,15)) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CAST +===================== + -0.536572918000435 + +""" + +@pytest.mark.version('>=2.1') +def test_sin_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/math/test_sinh_01.py b/tests/functional/intfunc/math/test_sinh_01.py new file mode 100644 index 00000000..cb713383 --- /dev/null +++ b/tests/functional/intfunc/math/test_sinh_01.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: functional.intfunc.math.sinh_01 +# title: test for SINH function +# decription: +# +# SINH( ) +# +# +# Returns the hyperbolic sine of a number. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.math.sinh_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ select SINH(4) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ SINH + ======================= + 27.28991719712775""" + +@pytest.mark.version('>=2.1') +def test_sinh_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/math/test_sqrt_01.py b/tests/functional/intfunc/math/test_sqrt_01.py new file mode 100644 index 00000000..0d33288d --- /dev/null +++ b/tests/functional/intfunc/math/test_sqrt_01.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: functional.intfunc.math.sqrt_01 +# title: test for SQRT function +# decription: +# SQRT( ) +# +# Returns the square root of a number. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.math.sqrt_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ select SQRT(4) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ SQRT + ======================= + 2.000000000000000""" + +@pytest.mark.version('>=2.1') +def test_sqrt_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/math/test_tan_01.py b/tests/functional/intfunc/math/test_tan_01.py new file mode 100644 index 00000000..12f827e9 --- /dev/null +++ b/tests/functional/intfunc/math/test_tan_01.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: functional.intfunc.math.tan_01 +# title: test for TAN function +# decription: +# TAN( ) +# +# Returns the tangent of an input number that is expressed in radians. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.math.tan_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ select TAN(43) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ TAN + ======================= + -1.498387338855171""" + +@pytest.mark.version('>=2.1') +def test_tan_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/math/test_tanh_01.py b/tests/functional/intfunc/math/test_tanh_01.py new file mode 100644 index 00000000..fa8a8fe7 --- /dev/null +++ b/tests/functional/intfunc/math/test_tanh_01.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: functional.intfunc.math.tanh_01 +# title: test for TANH function +# decription: +# TANH( ) +# +# Returns the hyperbolic tangent of a number. +# select tanh(x) from y; +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.math.tanh_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ select TANH(5) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ TANH + ======================= + 0.9999092042625951 +""" + +@pytest.mark.version('>=2.1') +def test_tanh_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/math/test_trunc_01.py b/tests/functional/intfunc/math/test_trunc_01.py new file mode 100644 index 00000000..d104adcb --- /dev/null +++ b/tests/functional/intfunc/math/test_trunc_01.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: functional.intfunc.math.trunc_01 +# title: test for TRUNC function +# decription: TRUNC( [, ] ) +# +# Returns the integral part (up to the specified scale) of a number. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.string.trunc_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select trunc(-2.8), trunc(2.8) + from rdb$database; -- returns -2, 2 +select trunc(987.65, 1), trunc(987.65, -1) + from rdb$database; -- returns 987.60, 980.00""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ TRUNC TRUNC + ===================== ===================== + -2 2 + + + TRUNC TRUNC + ===================== ===================== + 987.60 980.00""" + +@pytest.mark.version('>=2.1') +def test_trunc_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/misc/__init__.py b/tests/functional/intfunc/misc/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/intfunc/misc/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/intfunc/misc/test_decode_01.py b/tests/functional/intfunc/misc/test_decode_01.py new file mode 100644 index 00000000..fa82e7cd --- /dev/null +++ b/tests/functional/intfunc/misc/test_decode_01.py @@ -0,0 +1,57 @@ +#coding:utf-8 +# +# id: functional.intfunc.misc.decode_01 +# title: test de la fonction decode +# decription: decode is a shortcut for a case when else expreession. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.intfunc.misc.decode_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET ECHO OFF; +CREATE TABLE TMPTEST( id INTEGER ); + +insert into TMPTEST(id) +values(1); +insert into TMPTEST(id) +values(2); +insert into TMPTEST(id) +values(3); +insert into TMPTEST(id) +values(4); +insert into TMPTEST(id) +values(5); + +-- count doit etre egal a 0 dans ce cas +select decode(id,1,'un',2,'deux',3,'trois','plus grand') from TMPTEST;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """DECODE +========== +un +deux +trois +plus grand +plus grand + +""" + +@pytest.mark.version('>=3.0') +def test_decode_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/misc/test_gen_uuid_01.py b/tests/functional/intfunc/misc/test_gen_uuid_01.py new file mode 100644 index 00000000..87139b04 --- /dev/null +++ b/tests/functional/intfunc/misc/test_gen_uuid_01.py @@ -0,0 +1,67 @@ +#coding:utf-8 +# +# id: functional.intfunc.misc.gen_uuid_01 +# title: test for GEN_UUID() +# decription: Returns a universal unique number. +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.intfunc.misc.gen_uuid_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ +create table test( id char(30) ); + +--on verrifie qu'il y en a pas deux identique +insert into test values(CAST(GEN_UUID() AS VARCHAR(255)) ); +insert into test values(CAST(GEN_UUID() AS VARCHAR(255)) ); +insert into test values(CAST(GEN_UUID() AS VARCHAR(255)) ); +insert into test values(CAST(GEN_UUID() AS VARCHAR(255)) ); +insert into test values(CAST(GEN_UUID() AS VARCHAR(255)) ); +insert into test values(CAST(GEN_UUID() AS VARCHAR(255)) ); +insert into test values(CAST(GEN_UUID() AS VARCHAR(255)) ); +insert into test values(CAST(GEN_UUID() AS VARCHAR(255)) ); +insert into test values(CAST(GEN_UUID() AS VARCHAR(255)) ); +insert into test values(CAST(GEN_UUID() AS VARCHAR(255)) ); +insert into test values(CAST(GEN_UUID() AS VARCHAR(255)) ); +insert into test values(CAST(GEN_UUID() AS VARCHAR(255)) ); + + +select count(id) from test group by id;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ COUNT +===================== + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + +""" + +@pytest.mark.version('>=3.0') +def test_gen_uuid_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/misc/test_hash_01.py b/tests/functional/intfunc/misc/test_hash_01.py new file mode 100644 index 00000000..61c60e96 --- /dev/null +++ b/tests/functional/intfunc/misc/test_hash_01.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: functional.intfunc.misc.hash_01 +# title: test for HASH +# decription: Returns a HASH of a value. +# +# HASH( ) +# +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.misc.hash_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ select hash('toto') from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ HASH + ===================== + 505519""" + +@pytest.mark.version('>=2.1') +def test_hash_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/string/__init__.py b/tests/functional/intfunc/string/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/intfunc/string/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/intfunc/string/test_ascii_01.py b/tests/functional/intfunc/string/test_ascii_01.py new file mode 100644 index 00000000..65075721 --- /dev/null +++ b/tests/functional/intfunc/string/test_ascii_01.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: functional.intfunc.string.ascii_01 +# title: New Built-in Functions, Firebird 2.1 : ASCII_CHAR( ) +# decription: test of ASCII_CHAR +# +# Returns the ASCII character with the specified code. The argument to ASCII_CHAR must be in the range 0 to 255. The result is returned in character set NONE. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.string.ascii_char_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select ASCII_CHAR( 065 ) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ASCII_CHAR +========== +A + +""" + +@pytest.mark.version('>=2.1') +def test_ascii_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/string/test_ascii_val_01.py b/tests/functional/intfunc/string/test_ascii_val_01.py new file mode 100644 index 00000000..7a06c401 --- /dev/null +++ b/tests/functional/intfunc/string/test_ascii_val_01.py @@ -0,0 +1,89 @@ +#coding:utf-8 +# +# id: functional.intfunc.string.ascii_val_01 +# title: New Built-in Functions, Firebird 2.1 : ASCII_VAL( ) +# decription: test of ASCII_VAL +# +# Returns the ASCII code of the first character of the specified string. +# +# 1. +# +# Returns 0 if the string is empty +# 2. +# +# Throws an error if the first character is multi-byte +# +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.string.ascii_val_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# c = db_conn.cursor() +# try: +# c.execute("select ascii_val( 'A' ) from rdb$database") +# print (c.fetchall()) +# except Exception,e: +# print ("Test Failed for ascii_val( 'A' )") +# print (e) +# else: +# pass +# try: +# c.execute("select ascii_val( 'Ã' ) from rdb$database") +# print (c.fetchall()) +# except: +# pass +# else: +# print ("Test Failed for ascii_val( 'Ã' )") +# try: +# c.execute("select ascii_val(cast('A' as BLOB)) from rdb$database") +# print (c.fetchall()) +# except Exception,e: +# print ("Test Failed for ascii_val(CAST('A' AS BLOB))") +# print (e) +# else: +# pass +# try: +# c.execute("select ascii_val(NULL) from rdb$database") +# print (c.fetchall()) +# except Exception,e: +# print ("Test Failed for ascii_val(NULL)") +# print (e) +# else: +# pass +# try: +# c.execute("select ascii_val('') from rdb$database") +# print (c.fetchall()) +# except Exception,e: +# print ("Test Failed for ascii_val('')") +# print (e) +# else: +# pass +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """[(65,)] +[(65,)] +[(None,)] +[(0,)] +""" + +@pytest.mark.version('>=2.1') +@pytest.mark.xfail +def test_ascii_val_01_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/intfunc/string/test_left_01.py b/tests/functional/intfunc/string/test_left_01.py new file mode 100644 index 00000000..d91149ee --- /dev/null +++ b/tests/functional/intfunc/string/test_left_01.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: functional.intfunc.string.left_01 +# title: test for LEFT function +# decription: Returns the substring of a specified length that appears at the start of a left-to-right string. +# +# LEFT +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.string.left_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """select left('bonjour', 3) + from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ LEFT + ======= + bon""" + +@pytest.mark.version('>=2.1') +def test_left_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/string/test_lpad_01.py b/tests/functional/intfunc/string/test_lpad_01.py new file mode 100644 index 00000000..57b15191 --- /dev/null +++ b/tests/functional/intfunc/string/test_lpad_01.py @@ -0,0 +1,171 @@ +#coding:utf-8 +# +# id: functional.intfunc.string.lpad_01 +# title: test for LPAD function, including non-ascii characters. +# decription: +# 03-mar-2021. 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. +# +# Checked on: +# * Windows: 4.0.0.2377, 3.0.8.33420 +# * Linux: 4.0.0.2377, 3.0.8.33415 +# +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('BLOB_ID_.*', ''), ('.*After line \\d+.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(charset='ISO8859_1', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import codecs +# import subprocess +# import time +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# # 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 +# +# sql_txt=''' set names ISO8859_1; +# connect '%(dsn)s' user '%(user_name)s' password '%(user_password)s'; +# set list on; +# recreate table test(c varchar(32765), b blob sub_type text); +# insert into test(c, b) values( '%(data)s', '%(data)s' ); +# 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)s') as txt_lpad_06a +# ,lpad('÷øùúûüýþÿ',32765-char_length('÷øùúûüýþÿ'), '%(data)s') as txt_lpad_06b +# from rdb$database; +# +# out %(null_dev)s; +# 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 :-) +# +# +# ''' % dict(globals(), **locals()) +# +# f_run_sql = open( os.path.join(context['temp_directory'], 'tmp_func_lpad_iso8859_1.sql'), 'w' ) +# f_run_sql.write( sql_txt.decode('utf8').encode('iso-8859-1') ) +# flush_and_close( f_run_sql ) +# # result: file tmp_func_lpad_iso8859_1.sql is encoded in iso8859_1 (aka 'latin-1') +# +# f_run_log = open( os.path.splitext(f_run_sql.name)[0]+'.log', 'w') +# f_run_err = open( os.path.splitext(f_run_sql.name)[0]+'.err', 'w') +# subprocess.call( [ context['isql_path'], '-q', '-i', f_run_sql.name ], +# stdout = f_run_log, +# stderr = f_run_err +# ) +# flush_and_close( f_run_log ) +# flush_and_close( f_run_err ) +# +# # result: output will be encoded in iso9959_1, error log must be empty. +# with codecs.open(f_run_log.name, 'r', encoding='iso-8859-1' ) as f: +# stdout_encoded_in_latin_1 = f.readlines() +# +# with codecs.open(f_run_err.name, 'r', encoding='iso-8859-1' ) as f: +# stderr_encoded_in_latin_1 = f.readlines() +# +# for i in stdout_encoded_in_latin_1: +# print( i.encode('utf8') ) +# +# # NO error must occur: +# ###################### +# for i in stderr_encoded_in_latin_1: +# print( 'EXPECTED STDERR: ', i.encode('utf8') ) +# +# # cleanup: +# ########### +# cleanup( (f_run_sql, f_run_log, f_run_err) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ + ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ + TXT_LPAD_03 ¡ + ¡ + TXT_LPAD_05A ¿ + TXT_LPAD_05B À + TXT_LPAD_06A ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄ÷øùúûüýþÿ + TXT_LPAD_06B ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄ÷øùúûüýþÿ + EXPECTED STDERR: Statement failed, SQLSTATE = 22001 + EXPECTED STDERR: arithmetic exception, numeric overflow, or string truncation + EXPECTED STDERR: -string right truncation + EXPECTED STDERR: -expected length 32765, actual 32766 + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_lpad_01_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/intfunc/string/test_overlay_01.py b/tests/functional/intfunc/string/test_overlay_01.py new file mode 100644 index 00000000..3a43c0b8 --- /dev/null +++ b/tests/functional/intfunc/string/test_overlay_01.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: functional.intfunc.string.overlay_01 +# title: test for OVERLAY function +# decription: OVERLAY See below Returns string1 replacing the substring FROM start FOR length by string2. +# +# +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.string.overlay_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ select OVERLAY( 'il fait beau dans le sud de la france' PLACING 'NORD' FROM 22 for 4 ) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ OVERLAY + ========================================== + il fait beau dans le NORD de la france +""" + +@pytest.mark.version('>=2.1') +def test_overlay_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/string/test_position_01.py b/tests/functional/intfunc/string/test_position_01.py new file mode 100644 index 00000000..733a9b80 --- /dev/null +++ b/tests/functional/intfunc/string/test_position_01.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: functional.intfunc.string.position_01 +# title: test for POSITION function +# decription: POSITION( IN ) +# +# POSITION(X IN Y) returns the position of the substring X in the string Y. Returns 0 if X is not found within Y. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.string.position_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ select position('beau' IN 'il fait beau dans le nord' ) from rdb$database; + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ POSITION + ============ + 9""" + +@pytest.mark.version('>=2.1') +def test_position_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/string/test_position_02.py b/tests/functional/intfunc/string/test_position_02.py new file mode 100644 index 00000000..a1b00948 --- /dev/null +++ b/tests/functional/intfunc/string/test_position_02.py @@ -0,0 +1,40 @@ +#coding:utf-8 +# +# id: functional.intfunc.string.position_02 +# title: Test Position +# decription: +# tracker_id: CORE-1511 +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.string.position_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT POSITION('beau','beau,il fait beau') C1,POSITION('beau','beau,il fait beau',2) C2 FROM RDB$DATABASE; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + C1 C2 +============ ============ + 1 14 + +""" + +@pytest.mark.version('>=2.1') +def test_position_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/string/test_replace_01.py b/tests/functional/intfunc/string/test_replace_01.py new file mode 100644 index 00000000..ac1436cc --- /dev/null +++ b/tests/functional/intfunc/string/test_replace_01.py @@ -0,0 +1,38 @@ +#coding:utf-8 +# +# id: functional.intfunc.string.replace_01 +# title: test for REPLACE function +# decription: REPLACE( , , ) +# +# Replaces all occurrences of in with . +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.string.replace_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ select REPLACE('toto','o','i') from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ REPLACE + ======= + titi""" + +@pytest.mark.version('>=2.1') +def test_replace_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/string/test_reverse_01.py b/tests/functional/intfunc/string/test_reverse_01.py new file mode 100644 index 00000000..e5b6b6c9 --- /dev/null +++ b/tests/functional/intfunc/string/test_reverse_01.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: functional.intfunc.string.reverse_01 +# title: test for REVERSE function +# decription: REVERSE( ) +# +# Returns a string in reverse order. Useful function for creating an expression index that indexes strings from right to left. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.string.reverse_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ select REVERSE('DRON') from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + REVERSE + ======= + NORD""" + +@pytest.mark.version('>=2.1') +def test_reverse_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/string/test_right_01.py b/tests/functional/intfunc/string/test_right_01.py new file mode 100644 index 00000000..a46a3f4d --- /dev/null +++ b/tests/functional/intfunc/string/test_right_01.py @@ -0,0 +1,39 @@ +#coding:utf-8 +# +# id: functional.intfunc.string.right_01 +# title: test for RIGHT function +# decription: +# RIGHT( , ) +# +# Returns the substring, of the specified length, from the right-hand end of a string +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.intfunc.string.right_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ select RIGHT('NORD PAS DE CALAIS', 13) from rdb$database;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ RIGHT + ================== + PAS DE CALAIS""" + +@pytest.mark.version('>=2.1') +def test_right_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/intfunc/string/test_rpad_01.py b/tests/functional/intfunc/string/test_rpad_01.py new file mode 100644 index 00000000..495bdb75 --- /dev/null +++ b/tests/functional/intfunc/string/test_rpad_01.py @@ -0,0 +1,172 @@ +#coding:utf-8 +# +# id: functional.intfunc.string.rpad_01 +# title: test for RPAD function, including non-ascii characters. +# decription: +# 03-mar-2021. 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. +# +# Checked on: +# * Windows: 4.0.0.2377, 3.0.8.33420 +# * Linux: 4.0.0.2377, 3.0.8.33415 +# +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('BLOB_ID_.*', ''), ('.*After line \\d+.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(charset='ISO8859_1', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import codecs +# import subprocess +# import time +# +# db_conn.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.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# # 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 +# +# sql_txt=''' set names ISO8859_1; +# connect '%(dsn)s' user '%(user_name)s' password '%(user_password)s'; +# set list on; +# recreate table test(c varchar(32765), b blob sub_type text); +# insert into test(c, b) values( '%(data)s', '%(data)s' ); +# 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)s') as txt_rpad_06a +# ,rpad('÷øùúûüýþÿ',32765-char_length('÷øùúûüýþÿ'), '%(data)s') as txt_rpad_06b +# from rdb$database; +# +# out %(null_dev)s; +# 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; +# +# -- select char_length(rpad('', 2147483647, b)) as r_03 from test; -- <<< 152s :-) +# +# +# ''' % dict(globals(), **locals()) +# +# f_run_sql = open( os.path.join(context['temp_directory'], 'tmp_func_rpad_iso8859_1.sql'), 'w' ) +# f_run_sql.write( sql_txt.decode('utf8').encode('iso-8859-1') ) +# flush_and_close( f_run_sql ) +# # result: file tmp_func_rpad_iso8859_1.sql is encoded in iso8859_1 (aka 'latin-1') +# +# f_run_log = open( os.path.splitext(f_run_sql.name)[0]+'.log', 'w') +# f_run_err = open( os.path.splitext(f_run_sql.name)[0]+'.err', 'w') +# subprocess.call( [ context['isql_path'], '-q', '-i', f_run_sql.name ], +# stdout = f_run_log, +# stderr = f_run_err +# ) +# flush_and_close( f_run_log ) +# flush_and_close( f_run_err ) +# +# # result: output will be encoded in iso9959_1, error log must be empty. +# with codecs.open(f_run_log.name, 'r', encoding='iso-8859-1' ) as f: +# stdout_encoded_in_latin_1 = f.readlines() +# +# with codecs.open(f_run_err.name, 'r', encoding='iso-8859-1' ) as f: +# stderr_encoded_in_latin_1 = f.readlines() +# +# for i in stdout_encoded_in_latin_1: +# print( i.encode('utf8') ) +# +# # NO error must occur: +# ###################### +# for i in stderr_encoded_in_latin_1: +# print( 'EXPECTED STDERR: ', i.encode('utf8') ) +# +# # cleanup: +# ########### +# cleanup( (f_run_sql, f_run_log, f_run_err) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ + ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ + TXT_RPAD_03 ¡ + ¡ + TXT_RPAD_05A ¿ + TXT_RPAD_05B À + TXT_RPAD_06A ÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄ + TXT_RPAD_06B ÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄ + + EXPECTED STDERR: Statement failed, SQLSTATE = 22001 + EXPECTED STDERR: arithmetic exception, numeric overflow, or string truncation + EXPECTED STDERR: -string right truncation + EXPECTED STDERR: -expected length 32765, actual 32766 + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_rpad_01_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/monitoring/__init__.py b/tests/functional/monitoring/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/monitoring/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/monitoring/test_01.py b/tests/functional/monitoring/test_01.py new file mode 100644 index 00000000..beb82351 --- /dev/null +++ b/tests/functional/monitoring/test_01.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: functional.monitoring.01 +# title: Get isolation level of the current transaction +# decription: +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.monitoring.monitoring_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SELECT MON$ISOLATION_MODE + FROM MON$TRANSACTIONS + WHERE MON$TRANSACTION_ID = CURRENT_TRANSACTION;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +MON$ISOLATION_MODE +================== + 1 + +""" + +@pytest.mark.version('>=2.1') +def test_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/monitoring/test_02.py b/tests/functional/monitoring/test_02.py new file mode 100644 index 00000000..484a4071 --- /dev/null +++ b/tests/functional/monitoring/test_02.py @@ -0,0 +1,52 @@ +#coding:utf-8 +# +# id: functional.monitoring.02 +# title: Monitoring: get data about active statements from current attachment (WHERE-filter: mon$statements.mon$state=1). +# decription: +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.monitoring.monitoring_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('SQL_TEXT.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set width usr 31; + set list on; + select a.mon$user usr, s.mon$sql_text sql_text + from mon$attachments a + join mon$statements s on a.mon$attachment_id = s.mon$attachment_id + where + a.mon$attachment_id = current_connection + and s.mon$state = 1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + USR SYSDBA + SQL_TEXT 0:1 + select a.mon$user usr, s.mon$sql_text sql_text + from mon$attachments a + join mon$statements s on a.mon$attachment_id = s.mon$attachment_id + where + a.mon$attachment_id = current_connection + and s.mon$state = 1 + """ + +@pytest.mark.version('>=3.0') +def test_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/monitoring/test_04.py b/tests/functional/monitoring/test_04.py new file mode 100644 index 00000000..2339e092 --- /dev/null +++ b/tests/functional/monitoring/test_04.py @@ -0,0 +1,131 @@ +#coding:utf-8 +# +# id: functional.monitoring.04 +# title: Monitoring: SYSDBA must see all attachments and their transactions, non-privileged user - only those which was of his login. +# decription: +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.monitoring.monitoring_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('[=]{1,}', ''), ('[ \t]+', ' ')] + +init_script_1 = """ + set wng off; + create or alter user u01 password '123'; + create or alter user u02 password '456'; + commit; + create or alter view v_who as + select + current_user as who_am_i + ,a.mon$user who_else + ,dense_rank()over(partition by a.mon$user order by t.mon$transaction_id) tid_rown + ,t.mon$isolation_mode isol_mode + -- 15.01.2019: removed detailed info about read committed TIL because of read consistency TIL that 4.0 introduces. + -- Any record with t.mon$isolation_mode = 4 now is considered just as read committed, w/o any detalization (this not much needed here). + ,decode( t.mon$isolation_mode, 0,'CONSISTENCY', 1,'SNAPSHOT', 2, 'READ_COMMITTED', 3, 'READ_COMMITTED', 4, 'READ_COMMITTED', '??' ) as isol_descr + from + mon$attachments a + LEFT join mon$transactions t using(mon$attachment_id) + where + a.mon$attachment_id is distinct from current_connection + and a.mon$system_flag is distinct from 1 -- remove Cache Writer and Garbage Collector from resultset + order by a.mon$user, t.mon$transaction_id; + commit; + + revoke all on all from u01; + revoke all on all from u02; + grant select on v_who to u01; + grant select on v_who to u02; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# db_conn.close() +# +# #---------------------------------------------------------------------- +# +# con_1 = fdb.connect(dsn=dsn, user=user_name, password=user_password ) +# con_2 = fdb.connect(dsn=dsn, user='U01', password='123') +# con_3 = fdb.connect(dsn=dsn, user='U01', password='123') +# +# con_1.begin() +# con_2.begin() +# con_3.begin() +# +# #---------------------------------------------------------------------- +# +# custom_tpb4 = fdb.TPB() +# custom_tpb4.isolation_level = (fdb.isc_tpb_read_committed, fdb.isc_tpb_rec_version) +# +# custom_tpb5 = fdb.TPB() +# custom_tpb5.isolation_level = fdb.isc_tpb_concurrency +# +# custom_tpb6 = fdb.TPB() +# custom_tpb6.isolation_level = fdb.isc_tpb_consistency +# +# con_4 = fdb.connect(dsn=dsn, user='U02', password='456') +# con_5 = fdb.connect(dsn=dsn, user='U02', password='456') +# con_6 = fdb.connect(dsn=dsn, user='U02', password='456') +# +# con_4.begin( tpb = custom_tpb4 ) +# con_5.begin( tpb = custom_tpb5 ) +# con_6.begin( tpb = custom_tpb6 ) +# +# sql_chk=''' +# set width who_am_i 12; +# set width who_else 12; +# set width isol_descr 30; +# set count on; +# +# connect '$(DSN)' user 'u01' password '123'; +# select 1 as check_no, v.* from v_who v; +# commit; +# +# connect '$(DSN)' user 'SYSDBA' password 'masterkey'; +# +# select 2 as check_no, v.* from v_who v; +# commit; +# +# drop user u01; +# drop user u02; +# commit; +# ''' +# +# runProgram('isql',[ '-pag','99999','-q' ], sql_chk) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CHECK_NO WHO_AM_I WHO_ELSE TID_ROWN ISOL_MODE ISOL_DESCR + 1 U01 U01 1 2 READ_COMMITTED + 1 U01 U01 2 2 READ_COMMITTED + Records affected: 2 + + CHECK_NO WHO_AM_I WHO_ELSE TID_ROWN ISOL_MODE ISOL_DESCR + 2 SYSDBA SYSDBA 1 2 READ_COMMITTED + 2 SYSDBA U01 1 2 READ_COMMITTED + 2 SYSDBA U01 2 2 READ_COMMITTED + 2 SYSDBA U02 1 2 READ_COMMITTED + 2 SYSDBA U02 2 1 SNAPSHOT + 2 SYSDBA U02 3 0 CONSISTENCY + Records affected: 6 + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_04_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/procedure/__init__.py b/tests/functional/procedure/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/procedure/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/procedure/alter/__init__.py b/tests/functional/procedure/alter/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/procedure/alter/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/procedure/alter/test_01.py b/tests/functional/procedure/alter/test_01.py new file mode 100644 index 00000000..73f6fa5e --- /dev/null +++ b/tests/functional/procedure/alter/test_01.py @@ -0,0 +1,56 @@ +#coding:utf-8 +# +# id: functional.procedure.alter.01 +# title: ALTER PROCEDURE - Simple ALTER +# decription: ALTER PROCEDURE - Simple ALTER +# +# Dependencies: +# CREATE DATABASE +# CREATE PROCEDURE +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.procedure.alter.alter_procedure_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """SET TERM ^; +CREATE PROCEDURE test RETURNS (id INTEGER)AS +BEGIN + id=1; +END ^ +SET TERM ;^ +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET TERM ^; +ALTER PROCEDURE test RETURNS (id INTEGER)AS +BEGIN + id=2; +END ^ +SET TERM ;^ +commit; +EXECUTE PROCEDURE test; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ ID +============ + 2 +""" + +@pytest.mark.version('>=1.0') +def test_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/procedure/alter/test_02.py b/tests/functional/procedure/alter/test_02.py new file mode 100644 index 00000000..a2c88378 --- /dev/null +++ b/tests/functional/procedure/alter/test_02.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: functional.procedure.alter_02 +# title: ALTER PROCEDURE - Alter non exists procedure +# decription: ALTER PROCEDURE - Alter non exists procedure +# +# Dependencies: +# CREATE DATABASE +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.procedure.alter.alter_procedure_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET TERM ^; +ALTER PROCEDURE test RETURNS (id INTEGER)AS +BEGIN + id=2; +END ^ +SET TERM ;^ +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42000 +unsuccessful metadata update +-ALTER PROCEDURE TEST failed +-Procedure TEST not found +""" + +@pytest.mark.version('>=3.0') +def test_alter_02_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/procedure/create/__init__.py b/tests/functional/procedure/create/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/procedure/create/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/procedure/create/test_01.py b/tests/functional/procedure/create/test_01.py new file mode 100644 index 00000000..c8185bb5 --- /dev/null +++ b/tests/functional/procedure/create/test_01.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: functional.procedure.create.01 +# title: CREATE PROCEDURE +# decription: CREATE PROCEDURE +# +# Dependencies: +# CREATE DATABASE +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.procedure.create.create_procedure_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET TERM ^; +CREATE PROCEDURE test AS +BEGIN + POST_EVENT 'Test'; +END ^ +SET TERM ;^ +commit; +SHOW PROCEDURE test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Procedure text: +============================================================================= +BEGIN + POST_EVENT 'Test'; +END +============================================================================= +""" + +@pytest.mark.version('>=2.1') +def test_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/procedure/create/test_02.py b/tests/functional/procedure/create/test_02.py new file mode 100644 index 00000000..1666a9f1 --- /dev/null +++ b/tests/functional/procedure/create/test_02.py @@ -0,0 +1,67 @@ +#coding:utf-8 +# +# id: functional.procedure.create.02 +# title: CREATE PROCEDURE - Input parameters +# decription: CREATE PROCEDURE - Input parameters +# +# Dependencies: +# CREATE DATABASE +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.procedure.create.create_procedure_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET TERM ^; +CREATE PROCEDURE test( + p1 SMALLINT, p2 INTEGER, p3 FLOAT, p4 DOUBLE PRECISION, p5 DECIMAL(9,3), p6 NUMERIC(10,4), + p7 DATE, p8 TIME, p9 TIMESTAMP, p10 CHAR(40), p11 VARCHAR(60), p12 NCHAR(70)) +AS +BEGIN + POST_EVENT 'Test'; +END ^ +SET TERM ;^ +commit; +SHOW PROCEDURE test; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Procedure text: +============================================================================= +BEGIN + POST_EVENT 'Test'; +END +============================================================================= +Parameters: +P1 INPUT SMALLINT +P2 INPUT INTEGER +P3 INPUT FLOAT +P4 INPUT DOUBLE PRECISION +P5 INPUT DECIMAL(9, 3) +P6 INPUT NUMERIC(10, 4) +P7 INPUT DATE +P8 INPUT TIME +P9 INPUT TIMESTAMP +P10 INPUT CHAR(40) +P11 INPUT VARCHAR(60) +P12 INPUT CHAR(70) CHARACTER SET ISO8859_1 +""" + +@pytest.mark.version('>=2.1') +def test_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/procedure/create/test_03.py b/tests/functional/procedure/create/test_03.py new file mode 100644 index 00000000..049e81e7 --- /dev/null +++ b/tests/functional/procedure/create/test_03.py @@ -0,0 +1,89 @@ +#coding:utf-8 +# +# id: functional.procedure.create.03 +# title: CREATE PROCEDURE - Output paramaters +# decription: CREATE PROCEDURE - Output paramaters +# +# Dependencies: +# CREATE DATABASE +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.procedure.create.create_procedure_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET TERM ^; +CREATE PROCEDURE test RETURNS( + p1 SMALLINT, p2 INTEGER, p3 FLOAT, p4 DOUBLE PRECISION, p5 DECIMAL(9,3), p6 NUMERIC(10,4), + p7 DATE, p8 TIME, p9 TIMESTAMP, p10 CHAR(40), p11 VARCHAR(60), p12 NCHAR(70)) +AS +BEGIN + p1=1; + p2=2; + p3=3.4; + p4=4.5; + p5=5.6; + p6=6.7; + p7='31.8.1995'; + p8='13:45:57.1'; + p9='29.2.200 14:46:59.9'; + p10='Text p10'; + p11='Text p11'; + p12='Text p13'; +END ^ +SET TERM ;^ +commit; +SHOW PROCEDURE test; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Procedure text: +============================================================================= +BEGIN + p1=1; + p2=2; + p3=3.4; + p4=4.5; + p5=5.6; + p6=6.7; + p7='31.8.1995'; + p8='13:45:57.1'; + p9='29.2.200 14:46:59.9'; + p10='Text p10'; + p11='Text p11'; + p12='Text p13'; +END +============================================================================= +Parameters: +P1 OUTPUT SMALLINT +P2 OUTPUT INTEGER +P3 OUTPUT FLOAT +P4 OUTPUT DOUBLE PRECISION +P5 OUTPUT DECIMAL(9, 3) +P6 OUTPUT NUMERIC(10, 4) +P7 OUTPUT DATE +P8 OUTPUT TIME +P9 OUTPUT TIMESTAMP +P10 OUTPUT CHAR(40) +P11 OUTPUT VARCHAR(60) +P12 OUTPUT CHAR(70) CHARACTER SET ISO8859_1 +""" + +@pytest.mark.version('>=2.1') +def test_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/procedure/create/test_04.py b/tests/functional/procedure/create/test_04.py new file mode 100644 index 00000000..a028a4a7 --- /dev/null +++ b/tests/functional/procedure/create/test_04.py @@ -0,0 +1,98 @@ +#coding:utf-8 +# +# id: functional.procedure.create.04 +# title: CREATE PROCEDURE - Output paramaters +# decription: CREATE PROCEDURE - Output paramaters +# +# Dependencies: +# CREATE DATABASE +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.procedure.create.create_procedure_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET TERM ^; +CREATE PROCEDURE test +AS +DECLARE VARIABLE p1 SMALLINT; +DECLARE VARIABLE p2 INTEGER; +DECLARE VARIABLE p3 FLOAT; +DECLARE VARIABLE p4 DOUBLE PRECISION; +DECLARE VARIABLE p5 DECIMAL(9,3); +DECLARE VARIABLE p6 NUMERIC(10,4); +DECLARE VARIABLE p7 DATE; +DECLARE VARIABLE p8 TIME; +DECLARE VARIABLE p9 TIMESTAMP; +DECLARE VARIABLE p10 CHAR(40); +DECLARE VARIABLE p11 VARCHAR(60); +DECLARE VARIABLE p12 NCHAR(70); +BEGIN + p1=1; + p2=2; + p3=3.4; + p4=4.5; + p5=5.6; + p6=6.7; + p7='31.8.1995'; + p8='13:45:57.1'; + p9='29.2.200 14:46:59.9'; + p10='Text p10'; + p11='Text p11'; + p12='Text p13'; +END ^ +SET TERM ;^ +commit; +SHOW PROCEDURE test; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Procedure text: +============================================================================= +DECLARE VARIABLE p1 SMALLINT; +DECLARE VARIABLE p2 INTEGER; +DECLARE VARIABLE p3 FLOAT; +DECLARE VARIABLE p4 DOUBLE PRECISION; +DECLARE VARIABLE p5 DECIMAL(9,3); +DECLARE VARIABLE p6 NUMERIC(10,4); +DECLARE VARIABLE p7 DATE; +DECLARE VARIABLE p8 TIME; +DECLARE VARIABLE p9 TIMESTAMP; +DECLARE VARIABLE p10 CHAR(40); +DECLARE VARIABLE p11 VARCHAR(60); +DECLARE VARIABLE p12 NCHAR(70); +BEGIN + p1=1; + p2=2; + p3=3.4; + p4=4.5; + p5=5.6; + p6=6.7; + p7='31.8.1995'; + p8='13:45:57.1'; + p9='29.2.200 14:46:59.9'; + p10='Text p10'; + p11='Text p11'; + p12='Text p13'; +END +============================================================================= +""" + +@pytest.mark.version('>=2.1') +def test_04_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/procedure/create/test_05.py b/tests/functional/procedure/create/test_05.py new file mode 100644 index 00000000..b8536c9c --- /dev/null +++ b/tests/functional/procedure/create/test_05.py @@ -0,0 +1,125 @@ +#coding:utf-8 +# +# id: functional.procedure.create.05 +# title: CREATE PROCEDURE - PSQL Stataments +# decription: CREATE PROCEDURE - PSQL Stataments +# +# Dependencies: +# CREATE DATABASE +# CREATE EXCEPTION +# CREATE TABLE +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.procedure.create.create_procedure_05 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE EXCEPTION test 'test exception'; +CREATE TABLE tb(id INT, text VARCHAR(32)); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET TERM ^; +CREATE PROCEDURE dummy (id INT) AS +BEGIN + id=id; +END ^ + +CREATE PROCEDURE dummy2 (id INT) RETURNS(newID INT) AS +BEGIN + newid=id; +END ^ + +CREATE PROCEDURE test +AS +DECLARE VARIABLE p1 SMALLINT; +BEGIN +/* Comments */ + p1=1+1; /* assigment */ + EXCEPTION test; /* Exception */ + EXECUTE PROCEDURE dummy(:p1); /* Call SP */ + EXECUTE PROCEDURE dummy2(:p1) RETURNING_VALUES :p1; + EXECUTE PROCEDURE test; /*recursive call */ + EXIT; + FOR SELECT id FROM tb INTO :p1 DO BEGIN + p1=p1+2; + END + INSERT INTO tb(id) VALUES(:p1); + UPDATE tb SET text='new text' WHERE id=:p1; + DELETE FROM tb WHERE text=:p1+1; + SELECT id FROM tb WHERE text='ggg' INTO :p1; + IF(p1 IS NOT NULL)THEN BEGIN + p1=NULL; + END + IF(p1 IS NULL)THEN p1=2; + ELSE BEGIN + p1=2; + END + POST_EVENT 'My Event'; + POST_EVENT p1; + WHILE(p1>30)DO BEGIN + p1=p1-1; + END + BEGIN + EXCEPTION test; + WHEN ANY DO p1=45; + END +END ^ +SET TERM ;^ +commit; +SHOW PROCEDURE test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Procedure text: +============================================================================= +DECLARE VARIABLE p1 SMALLINT; +BEGIN +/* Comments */ + p1=1+1; /* assigment */ + EXCEPTION test; /* Exception */ + EXECUTE PROCEDURE dummy(:p1); /* Call SP */ + EXECUTE PROCEDURE dummy2(:p1) RETURNING_VALUES :p1; + EXECUTE PROCEDURE test; /*recursive call */ + EXIT; + FOR SELECT id FROM tb INTO :p1 DO BEGIN + p1=p1+2; + END + INSERT INTO tb(id) VALUES(:p1); + UPDATE tb SET text='new text' WHERE id=:p1; + DELETE FROM tb WHERE text=:p1+1; + SELECT id FROM tb WHERE text='ggg' INTO :p1; + IF(p1 IS NOT NULL)THEN BEGIN + p1=NULL; + END + IF(p1 IS NULL)THEN p1=2; + ELSE BEGIN + p1=2; + END + POST_EVENT 'My Event'; + POST_EVENT p1; + WHILE(p1>30)DO BEGIN + p1=p1-1; + END + BEGIN + EXCEPTION test; + WHEN ANY DO p1=45; + END +END +============================================================================= +""" + +@pytest.mark.version('>=2.1') +def test_05_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/procedure/create/test_06.py b/tests/functional/procedure/create/test_06.py new file mode 100644 index 00000000..dce47b2f --- /dev/null +++ b/tests/functional/procedure/create/test_06.py @@ -0,0 +1,60 @@ +#coding:utf-8 +# +# id: functional.procedure.create.06 +# title: CREATE PROCEDURE - PSQL Stataments - SUSPEND +# decription: CREATE PROCEDURE - PSQL Stataments - SUSPEND +# +# Dependencies: +# CREATE DATABASE +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.procedure.create.create_procedure_06 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET TERM ^; +CREATE PROCEDURE test RETURNS(id INT)AS +BEGIN + ID=4; + SUSPEND; + ID=5; + SUSPEND; +END ^ +SET TERM ;^ +commit; +SHOW PROCEDURE test; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Procedure text: +============================================================================= + +BEGIN + ID=4; + SUSPEND; + ID=5; + SUSPEND; +END +============================================================================= +Parameters: +ID OUTPUT INTEGER +""" + +@pytest.mark.version('>=1.0') +def test_06_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/procedure/create/test_07.py b/tests/functional/procedure/create/test_07.py new file mode 100644 index 00000000..efa1f1f8 --- /dev/null +++ b/tests/functional/procedure/create/test_07.py @@ -0,0 +1,56 @@ +#coding:utf-8 +# +# id: functional.procedure.create_07 +# title: CREATE PROCEDURE - try create SP with same name +# decription: CREATE PROCEDURE - try create SP with same name +# +# Dependencies: +# CREATE DATABASE +# CREATE PROCEDURE +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.procedure.create.create_procedure_07 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """SET TERM ^; +CREATE PROCEDURE test RETURNS(id INT)AS +BEGIN + ID=4; + SUSPEND; +END ^ +SET TERM ;^ +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET TERM ^; +CREATE PROCEDURE test RETURNS(id INT)AS +BEGIN + ID=5; + SUSPEND; +END ^ +SET TERM ;^ +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42000 +unsuccessful metadata update +-CREATE PROCEDURE TEST failed +-Procedure TEST already exists +""" + +@pytest.mark.version('>=3.0') +def test_create_07_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/procedure/create/test_08.py b/tests/functional/procedure/create/test_08.py new file mode 100644 index 00000000..71c62f9c --- /dev/null +++ b/tests/functional/procedure/create/test_08.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: functional.procedure.create.08 +# title: CREATE PROCEDURE - COMMIT in SP is not alowed +# decription: CREATE PROCEDURE - COMMIT in SP is not alowed +# +# Dependencies: +# CREATE DATABASE +# tracker_id: +# min_versions: [] +# versions: 2.5.0 +# qmid: functional.procedure.create.create_procedure_08 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET TERM ^; +CREATE PROCEDURE test RETURNS(id INT)AS +BEGIN + COMMIT; +END ^ +SET TERM ;^ +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42000 + +Dynamic SQL Error +-SQL error code = -104 +-Token unknown - line 3, column 3 +-COMMIT +""" + +@pytest.mark.version('>=2.5.0') +def test_08_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/procedure/create/test_15.py b/tests/functional/procedure/create/test_15.py new file mode 100644 index 00000000..1a6abbab --- /dev/null +++ b/tests/functional/procedure/create/test_15.py @@ -0,0 +1,68 @@ +#coding:utf-8 +# +# id: functional.procedure.create.15 +# title: COLLATE IN STORED PROCEDURE +# decription: +# tracker_id: CORE-684 +# min_versions: [] +# versions: 2.1 +# qmid: functional.procedure.create.create_procedure_15 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """SET TERM !!; +CREATE PROCEDURE NEW_PROCEDURE (NOM1 VARCHAR(20) CHARACTER SET ISO8859_1 COLLATE FR_FR) + RETURNS (NOM3 VARCHAR(20) CHARACTER SET ISO8859_1 COLLATE ISO8859_1) + AS + DECLARE VARIABLE NOM2 VARCHAR(20) CHARACTER SET ISO8859_1 COLLATE FR_CA; +BEGIN + NOM2=NOM1; + NOM3=NOM2; + SUSPEND; +END !! +SET TERM ;!! +COMMIT; + + + +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SHOW PROCEDURE NEW_PROCEDURE; +SELECT * FROM NEW_PROCEDURE('TEST'); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Procedure text: +============================================================================= + DECLARE VARIABLE NOM2 VARCHAR(20) CHARACTER SET ISO8859_1 COLLATE FR_CA; +BEGIN + NOM2=NOM1; + NOM3=NOM2; + SUSPEND; +END +============================================================================= +Parameters: +NOM1 INPUT VARCHAR(20) CHARACTER SET ISO8859_1 COLLATE FR_FR +NOM3 OUTPUT VARCHAR(20) CHARACTER SET ISO8859_1 + +NOM3 +==================== +TEST + +""" + +@pytest.mark.version('>=2.1') +def test_15_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/procedure/create/test_16.py b/tests/functional/procedure/create/test_16.py new file mode 100644 index 00000000..0b64fd2a --- /dev/null +++ b/tests/functional/procedure/create/test_16.py @@ -0,0 +1,68 @@ +#coding:utf-8 +# +# id: functional.procedure.create.16 +# title: Type Flaq for Stored Procedures +# decription: +# Checked on: +# 2.5.9.27126: OK, 0.579s. +# 3.0.5.33086: OK, 1.219s. +# 4.0.0.1378: OK, 8.219s. +# +# tracker_id: CORE-779 +# min_versions: [] +# versions: 2.5 +# qmid: functional.procedure.create.create_procedure_16 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + set term ^; + create or alter procedure with_suspend (nom1 varchar(20) character set iso8859_1 collate fr_fr) + returns (nom3 varchar(20) character set iso8859_1 collate iso8859_1) as + declare variable nom2 varchar(20) character set iso8859_1 collate fr_ca; + begin + nom2=nom1; + nom3=nom2; + suspend; + end ^ + + create or alter procedure no_suspend returns(p1 smallint) as + begin + p1=1; + end ^ + set term ;^ + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select p.rdb$procedure_name, p.rdb$procedure_type + from rdb$procedures p + where upper(p.rdb$procedure_name) in ( upper('with_suspend'), upper('no_suspend') ) + order by 1; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$PROCEDURE_NAME NO_SUSPEND + RDB$PROCEDURE_TYPE 2 + + RDB$PROCEDURE_NAME WITH_SUSPEND + RDB$PROCEDURE_TYPE 1 + """ + +@pytest.mark.version('>=2.5') +def test_16_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/role/__init__.py b/tests/functional/role/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/role/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/role/create/__init__.py b/tests/functional/role/create/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/role/create/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/role/create/test_01.py b/tests/functional/role/create/test_01.py new file mode 100644 index 00000000..3caa9c8f --- /dev/null +++ b/tests/functional/role/create/test_01.py @@ -0,0 +1,96 @@ +#coding:utf-8 +# +# id: functional.role.create.01 +# title: CREATE ROLE +# decription: +# CREATE ROLE +# Dependencies: +# CREATE DATABASE +# Basic SELECT +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 3.0, 4.0 +# qmid: functional.role.create.create_role_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('SQL\\$.*', 'SQLnnnn')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create role test; + commit; + set list on; + select * from rdb$roles order by rdb$role_name; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RDB$ROLE_NAME RDB$ADMIN + RDB$OWNER_NAME SYSDBA + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS SQLnnnn + + RDB$ROLE_NAME TEST + RDB$OWNER_NAME SYSDBA + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 0 + RDB$SECURITY_CLASS SQLnnnn + """ + +@pytest.mark.version('>=3.0,<4.0') +def test_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + +# version: 4.0 +# resources: None + +substitutions_2 = [('SQL\\$.*', 'SQLnnnn')] + +init_script_2 = """""" + +db_2 = db_factory(sql_dialect=3, init=init_script_2) + +test_script_2 = """ + create role test; + commit; + set list on; + select * from rdb$roles order by rdb$role_name; + """ + +act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2) + +expected_stdout_2 = """ + RDB$ROLE_NAME RDB$ADMIN + RDB$OWNER_NAME SYSDBA + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 1 + RDB$SECURITY_CLASS SQLnnnn + RDB$SYSTEM_PRIVILEGES FFFFFFFFFFFFFFFF + + RDB$ROLE_NAME TEST + RDB$OWNER_NAME SYSDBA + RDB$DESCRIPTION + RDB$SYSTEM_FLAG 0 + RDB$SECURITY_CLASS SQLnnnn + RDB$SYSTEM_PRIVILEGES 0000000000000000 + """ + +@pytest.mark.version('>=4.0') +def test_01_2(act_2: Action): + act_2.expected_stdout = expected_stdout_2 + act_2.execute() + assert act_2.clean_expected_stdout == act_2.clean_stdout + diff --git a/tests/functional/role/create/test_02.py b/tests/functional/role/create/test_02.py new file mode 100644 index 00000000..f24e0040 --- /dev/null +++ b/tests/functional/role/create/test_02.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: functional.role.create_02 +# title: CREATE ROLE - try create role with same name +# decription: CREATE ROLE - try create role with same name +# +# Dependencies: +# CREATE DATABASE +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.role.create.create_role_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE ROLE test; +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE ROLE test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42000 +unsuccessful metadata update +-CREATE ROLE TEST failed +-SQL role TEST already exists + +""" + +@pytest.mark.version('>=3.0') +def test_create_02_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/services/__init__.py b/tests/functional/services/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/services/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/services/test_role_in_service_attachment.py b/tests/functional/services/test_role_in_service_attachment.py new file mode 100644 index 00000000..ed9e04ef --- /dev/null +++ b/tests/functional/services/test_role_in_service_attachment.py @@ -0,0 +1,225 @@ +#coding:utf-8 +# +# id: functional.services.role_in_service_attachment +# title: Check that trace plugin shows ROLE used in service attachment. Format: USER[:ROLE]. +# decription: +# See: https://github.com/FirebirdSQL/firebird/commit/dd241208f203e54a9c5e9b8b24c0ef24a4298713 +# Checked on 4.0.0.2070 SS/CS. +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import sys +# import os +# import re +# import subprocess +# import time +# from fdb import services +# from subprocess import Popen +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# f_sql_cmd = open( os.path.join(context['temp_directory'],'tmp_trace_prepare.sql'), 'w', buffering=0) +# f_sql_txt=''' +# set wng off; +# set bail on; +# create or alter user tmp$watcher password '123' using plugin Srp; +# revoke all on all from tmp$watcher; +# commit; +# set term ^; +# execute block as +# begin +# execute statement 'drop role r4watch'; +# when any do begin end +# end +# ^ +# set term ;^ +# commit; +# -- Trace other users' attachments +# create role r4watch set system privileges to TRACE_ANY_ATTACHMENT; +# commit; +# grant default r4watch to user tmp$watcher; +# commit; +# ''' +# f_sql_cmd.write(f_sql_txt) +# flush_and_close(f_sql_cmd) +# +# f_prepare_log=open( os.path.join(context['temp_directory'],'tmp_trace_prepare.log'), 'w', buffering=0) +# subprocess.call( [ context['isql_path'], dsn, "-i", f_sql_cmd.name ], stdout=f_prepare_log, stderr=subprocess.STDOUT ) +# flush_and_close(f_prepare_log) +# +# txt = ''' +# database= +# { +# enabled = false +# } +# services +# { +# enabled = true +# log_initfini = false +# include_filter = "%(Start|Stop) Trace Session%" +# log_services = true +# log_errors = true +# log_warnings = false +# } +# +# ''' +# +# f_trc_cfg=open( os.path.join(context['temp_directory'],'tmp_trace_test.cfg'), 'w', buffering = 0) +# f_trc_cfg.write(txt) +# flush_and_close(f_trc_cfg) +# +# # ############################################################## +# # S T A R T T R A C E i n S E P A R A T E P R O C E S S +# # ############################################################## +# +# f_trc_log=open( os.path.join(context['temp_directory'],'tmp_trace_test.log'), "w", buffering = 0) +# f_trc_err=open( os.path.join(context['temp_directory'],'tmp_trace_test.err'), "w", buffering = 0) +# +# # ::: NB ::: DO NOT USE 'localhost:service_mgr' here! Use only local protocol: +# p_trace = Popen( [ context['fbsvcmgr_path'], 'localhost:service_mgr', 'user', 'tmp$watcher', 'password', '123', 'role', 'r4watch', 'action_trace_start' , 'trc_cfg', f_trc_cfg.name],stdout=f_trc_log,stderr=f_trc_err) +# +# time.sleep(1) +# +# # #################################################### +# # G E T A C T I V E T R A C E S E S S I O N I D +# # #################################################### +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# +# f_trc_lst = open( os.path.join(context['temp_directory'],'tmp_trace_test.lst'), 'w', buffering = 0) +# subprocess.call([context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_list'], stdout=f_trc_lst) +# flush_and_close(f_trc_lst) +# +# # !!! DO NOT REMOVE THIS LINE !!! +# time.sleep(1) +# +# trcssn=0 +# with open( f_trc_lst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# +# # Here we are waiting for trace log will be fulfilled with data related to SERVICE activity, namely: trace session that was just started. +# time.sleep(3) +# +# # #################################################### +# # S E N D R E Q U E S T T R A C E T O S T O P +# # #################################################### +# if trcssn>0: +# fn_nul = open(os.devnull, 'w') +# subprocess.call([context['fbsvcmgr_path'], 'localhost:service_mgr', 'action_trace_stop','trc_id', trcssn], stdout=fn_nul) +# fn_nul.close() +# # DO NOT REMOVE THIS LINE: +# time.sleep(1) +# +# p_trace.terminate() +# flush_and_close(f_trc_log) +# flush_and_close(f_trc_err) +# +# p_new = re.compile('service_mgr.*\\s+tmp\\$watcher:r4watch,.*', re.IGNORECASE) +# p_old = re.compile('service_mgr.*\\s+tmp\\$watcher,.*', re.IGNORECASE) +# +# # Check: +# ######### +# # Log of preparation .sql must be empty: +# with open( f_prepare_log.name,'r') as f: +# for line in f: +# if line.split(): +# print('UNEXPECTED output in '+f_prepare_log.name+': '+line) +# +# # Trace STDOUT must contain line like: +# # service_mgr, (Service 0000000004F893C0, TMP$WATCHER:r4watch, TCPv6:::1/55274, C:\\FB SS +# bsvcmgr.exe:6752) +# with open( f_trc_log.name,'r') as f: +# for line in f: +# if 'service_mgr' in line: +# if p_new.search(line): +# print('EXPECTED output found in the trace log') +# elif p_old.search(line): +# print('ERROR: trace output contains only USER, without ROLE.') +# else: +# print('ERROR: format in the trace log differs from expected.') +# +# # Trace STDERR must be empty: +# with open( f_trc_err.name,'r') as f: +# for line in f: +# if line.split(): +# print('UNEXPECTED STDERR in '+f_trc_err.name+': '+line) +# +# +# # Cleanup: +# ########### +# cleanup( ( f_sql_cmd, f_prepare_log, f_trc_log, f_trc_err, f_trc_cfg, f_trc_lst ) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + EXPECTED output found in the trace log + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_role_in_service_attachment_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/services/test_user_management.py b/tests/functional/services/test_user_management.py new file mode 100644 index 00000000..af06a7d2 --- /dev/null +++ b/tests/functional/services/test_user_management.py @@ -0,0 +1,117 @@ +#coding:utf-8 +# +# id: functional.services.user_management +# title: Check ability to make connect to FB services and add/drop user. +# decription: +# We check here: +# 1) FB services features which add and remove user; +# 2) Python fdb driver functions (from class Connection): add_user(), get_users() and remove_user() +# +# 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. +# +# See doc: +# https://firebirdsql.org/file/documentation/drivers_documentation/python/fdb/reference.html#fdb.services.Connection.add_user +# https://firebirdsql.org/file/documentation/drivers_documentation/python/fdb/usage-guide.html#user-maintanance +# +# Checked on: +# FB25Cs, build 2.5.8.27067: OK, 1.015s. +# FB25SC, build 2.5.8.27070: OK, 0.813s. +# fb30Cs, build 3.0.3.32805: OK, 2.297s. +# FB30SS, build 3.0.3.32813: OK, 2.109s. +# FB40CS, build 4.0.0.748: OK, 2.859s. +# FB40SS, build 4.0.0.767: OK, 2.000s. +# +# tracker_id: +# min_versions: ['2.5.8'] +# versions: 2.5.8 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.8 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# from fdb import services +# +# TEST_USER_NAME='tmp$test$user$'.upper() +# db_conn.close() +# +# svc_con = services.connect( host='localhost', user = user_name, password = user_password ) +# +# u01 = services.User(TEST_USER_NAME) +# u01.password = 'QweRty' +# u01.first_name = 'Foo' +# u01.last_name = 'Bar' +# +# +# print('Adding user.') +# svc_con.add_user(u01) +# print('Done.') +# +# usr_list = svc_con.get_users() +# print('Search in users list.') +# for u in usr_list: +# if u.name == TEST_USER_NAME: +# print('Found user:', u.name) +# +# sql=''' +# select +# mon$user as user_connected +# ,iif( upper(mon$remote_protocol) starting with upper('TCP'), 'TCP', coalesce(mon$remote_protocol, '') ) as protocol_info +# from mon$attachments +# where mon$attachment_id = current_connection +# ''' +# +# try: +# print('Trying to establish connection.') +# usr_con = fdb.connect( dsn = dsn, user=TEST_USER_NAME, password='QweRty') +# cur2 = usr_con.cursor() +# cur2.execute( sql ) +# for r in cur2: +# for i in range(0,len(r)): +# print( ''.join( ( r[i] ) ) ) +# print('Done.') +# finally: +# usr_con.close() +# +# +# print('Removing user.') +# svc_con.remove_user(u01) +# print('Done.') +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Adding user. + Done. + Search in users list. + Found user: TMP$TEST$USER$ + Trying to establish connection. + TMP$TEST$USER$ + TCP + Done. + Removing user. + Done. + """ + +@pytest.mark.version('>=2.5.8') +@pytest.mark.xfail +def test_user_management_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/session/__init__.py b/tests/functional/session/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/session/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/session/test_alter_session_reset.py b/tests/functional/session/test_alter_session_reset.py new file mode 100644 index 00000000..4ef8b45e --- /dev/null +++ b/tests/functional/session/test_alter_session_reset.py @@ -0,0 +1,289 @@ +#coding:utf-8 +# +# id: functional.session.alter_session_reset +# title: +# Test results of ALTER SESSION RESET +# +# decription: +# Checked on FB40SS, build 4.0.0.1166: OK, 4.329s. +# 31.10.2019. Refactoring: +# * remove IDs of attachment/transaction from output. +# * replaced mon$isolation_mode with its describing text - take in account that in FB 4.0 +# READ CONSISTENCY is default isolation mode for READ COMMITTED Tx. +# +# Checked on: +# 4.0.0.1635 SS: 2.049s. +# 4.0.0.1633 CS: 2.266s. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('-At line[:]{0,1}[\\s]+[\\d]+,[\\s]+column[:]{0,1}[\\s]+[\\d]+', ''), ('line[:]{0,1}[\\s]+[\\d]+,[\\s]+col[:]{0,1}[\\s]+[\\d]+', ''), ('[-]{0,1}Effective user is.*', 'Effective user')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + --set bail on; + -- set wng off; + set autoddl off; + set list on; + -- connect '$(DSN)' user sysdba password 'masterkey'; + commit; + + create or alter user tmp$user4test password 'bar'; + commit; + recreate global temporary table gtt_test(id int, x int) on commit preserve rows; + commit; + + set term ^; + execute block as + begin + begin + execute statement 'drop role acnt'; + when any do begin end + end + begin + execute statement 'drop role boss'; + when any do begin end + end + end + ^ + create or alter procedure sp_decfloat_test returns( raised_gds int, raised_sqlst char(5) ) as + declare a1 decfloat(34) = 9e6144; + begin + --rdb$set_context('USER_SESSION', 'RAISED_GDSCODE', null); + --rdb$set_context('USER_SESSION', 'RAISED_SQLSTATE', null); + begin + ------------------------------------ + -- When decfloat traps set to default (Division_by_zero, Invalid_operation, Overflow): + -- RAISED_GDS 335545142 + -- RAISED_SQLST 22003 + -- Message text: Decimal float overflow. The exponent of a result is greater than the magnitude allowed. + ------------------------------------ + -- When decfloat traps set to Inexact: + -- RAISED_GDS 335545140 + -- RAISED_SQLST 22000 + -- Message text: Decimal float inexact result. The result of an operation cannot be represented as a decimal fraction. + a1 = a1 + a1; + + when any do + begin + --rdb$set_context('USER_SESSION', 'RAISED_GDSCODE', gdscode); + --rdb$set_context('USER_SESSION', 'RAISED_SQLSTATE', sqlstate); + raised_gds = gdscode; + raised_sqlst = sqlstate; + suspend; + exception; + end + end + suspend; + end + ^ + set term ;^ + commit; + + create role acnt; + create role boss; + commit; + grant acnt to tmp$user4test; + grant boss to tmp$user4test; + grant execute on procedure sp_decfloat_test to tmp$user4test; + commit; + + grant select, insert, update, delete on gtt_test to boss; + commit; + + recreate view v_info as + select + current_user as my_name + ,current_role as my_role + ,t.mon$lock_timeout as tx_lock_timeout + ,t.mon$read_only as tx_read_only + ,t.mon$auto_undo as tx_auto_undo + -- ,mon$isolation_mode as tx_isol_mode + -- 15.01.2019: removed detailed info about read committed TIL because of read consistency TIL that 4.0 introduces. + -- Any record with t.mon$isolation_mode = 4 now is considered just as read committed, w/o any detalization (this not much needed here). + ,decode( t.mon$isolation_mode, 0,'CONSISTENCY', 1,'SNAPSHOT', 2, 'READ_COMMITTED', 3, 'READ_COMMITTED', 4, 'READ_COMMITTED', '??' ) as isol_descr + from mon$transactions t + where t.mon$attachment_id = current_connection; + commit; + + recreate view v_ctx_vars as + select m.mon$variable_name as context_var_name, m.mon$variable_value as context_var_value + from rdb$database r left join mon$context_variables m on 1=1; + + grant select on v_info to public; + grant select on v_ctx_vars to public; + commit; + + connect '$(DSN)' user tmp$user4test password 'bar' role 'acnt'; + + ------------------ 1: change Tx attributes ---------- + commit; + set transaction read only read committed lock timeout 9 no auto undo; + + ------------------ 2: change current role ----------- + set role boss; + + ------------------ 3: write into session-level GTT + -- should PASS because now we work as BOSS who has granted to write into this table: + insert into gtt_test(id, x) values(1,100); + + ------------------ 4: define session-level context variables + set term ^; + execute block as + begin + rdb$set_context('USER_SESSION','WHATS_MY_NAME', current_user); + rdb$set_context('USER_SESSION','WHATS_MY_ROLE', current_role); + end^ + set term ;^ + + ---------------------- 5: make num overflow with default decfloat trap settings + -- Should raise: + -- Statement failed, SQLSTATE = 22003 + -- Decimal float overflow. The exponent of a result is greater than the magnitude allowed. + + select 'Point before call sp_decfloat_test with trap settings: {Division_by_zero, Invalid_operation, Overflow}' as msg from rdb$database; + select * from sp_decfloat_test; + + -- this will CLEAR previous trap settings which were: {Division_by_zero, Invalid_operation, Overflow} + set decfloat traps to Inexact; + + + select 'Point before call sp_decfloat_test with trap settings: {Inexact}' as msg from rdb$database; + -- Should raise: + -- Statement failed, SQLSTATE = 22000 + -- Decimal float inexact result. The result of an operation cannot be represented as a decimal fraction. + select * from sp_decfloat_test; + + + ------------------ check state BEFORE session reset: + select * from v_info; + set count on; + select * from gtt_test; -- should PASS because current role is BOSS and it was allowed to query GTT_TEST table to this role. + set count off; + select * from v_ctx_vars; -- should issue two records for context vars: WHATS_MY_NAME='TMP$USER4TEST' and WHATS_MY_ROLE='BOSS' + + + -- ################################### + -- ### R E S E T S E S S I O N ### + -- ################################### + + -- Should issue: + -- Session was reset with warning(s) + -- -Transaction is rolled back due to session reset, all changes are lost + --################## + alter session reset; + --################## + + + select 'Point AFTER reset session, before call sp_decfloat_test' as msg from rdb$database; + -- Should raise: + -- Statement failed, SQLSTATE = 22003 + -- Decimal float overflow. The exponent of a result is greater than the magnitude allowed. + -- (i.e. the same as it was when trap setting were: {Division_by_zero, Invalid_operation, Overflow} ) + select * from sp_decfloat_test; + + + ------------------ check state AFTER session reset: + + select * from v_info; -- should contain "MY_ROLE ACNT" + set count on; + select * from gtt_test; -- should raise Statement failed, SQLSTATE = 28000 / no permission for SELECT access to TABLE GTT_TEST / -Effective user is TMP$USER4TEST + set count off; + select * from v_ctx_vars; -- should issue one record with nulls: no context variables exist now because ALTER SESSION RESET was done. + commit; + + -- cleanup: + -- ######## + connect '$(DSN)' user sysdba password 'masterkey'; + drop user tmp$user4test; + commit; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG Point before call sp_decfloat_test with trap settings: {Division_by_zero, Invalid_operation, Overflow} + RAISED_GDS 335545142 + RAISED_SQLST 22003 + + MSG Point before call sp_decfloat_test with trap settings: {Inexact} + RAISED_GDS 335545140 + RAISED_SQLST 22000 + + MY_NAME TMP$USER4TEST + MY_ROLE BOSS + TX_LOCK_TIMEOUT 9 + TX_READ_ONLY 1 + TX_AUTO_UNDO 0 + ISOL_DESCR READ_COMMITTED + + ID 1 + X 100 + Records affected: 1 + + CONTEXT_VAR_NAME WHATS_MY_NAME + CONTEXT_VAR_VALUE TMP$USER4TEST + + CONTEXT_VAR_NAME WHATS_MY_ROLE + CONTEXT_VAR_VALUE BOSS + + + MSG Point AFTER reset session, before call sp_decfloat_test + RAISED_GDS 335545142 + RAISED_SQLST 22003 + + MY_NAME TMP$USER4TEST + MY_ROLE ACNT + TX_LOCK_TIMEOUT 9 + TX_READ_ONLY 1 + TX_AUTO_UNDO 0 + ISOL_DESCR READ_COMMITTED + + CONTEXT_VAR_NAME + CONTEXT_VAR_VALUE + + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22003 + Decimal float overflow. The exponent of a result is greater than the magnitude allowed. + -At procedure 'SP_DECFLOAT_TEST' line: 17, col: 13 + -At procedure 'SP_DECFLOAT_TEST' line: 26, col: 17 + + Statement failed, SQLSTATE = 22000 + Decimal float inexact result. The result of an operation cannot be represented as a decimal fraction. + -At procedure 'SP_DECFLOAT_TEST' line: 17, col: 13 + -At procedure 'SP_DECFLOAT_TEST' line: 26, col: 17 + + Session was reset with warning(s) + -Transaction is rolled back due to session reset, all changes are lost + Statement failed, SQLSTATE = 22003 + Decimal float overflow. The exponent of a result is greater than the magnitude allowed. + -At procedure 'SP_DECFLOAT_TEST' line: 17, col: 13 + -At procedure 'SP_DECFLOAT_TEST' line: 26, col: 17 + + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE GTT_TEST + -Effective user is TMP$USER4TEST + """ + +@pytest.mark.version('>=4.0') +def test_alter_session_reset_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/session/test_alter_session_reset_allow_2pc_prepared.py b/tests/functional/session/test_alter_session_reset_allow_2pc_prepared.py new file mode 100644 index 00000000..089758b3 --- /dev/null +++ b/tests/functional/session/test_alter_session_reset_allow_2pc_prepared.py @@ -0,0 +1,162 @@ +#coding:utf-8 +# +# id: functional.session.alter_session_reset_allow_2pc_prepared +# title: +# ALTER SESSION RESET: do NOT raise error if prepared 2PC transactions present. +# +# decription: +# Test issue from CORE-5832 about ALTER SESSION RESET: +# "throw error (isc_ses_reset_err) if any open transaction exist in current conneciton, +# except of ... prepared 2PC transactions which is allowed and ignored by this check" +# +# We create two databases with table (id int, x int) in each of them. +# Then we create two connections (one per each DB). +# +# These connections are added to the instance of fdb.ConnectionGroup() in order to have +# ability to use 2PC mechanism. +# +# In the first connection we start TWO transactions, in the second it is enough to start one. +# Then we do trivial DML in each of these three transactions: insert one row in a table. +# +# Finally, we run prepare() method in one of pair transactions that belong to 1st connection. +# After this, we must be able to run ALTER SESSION RESET in the *second* Tx of this pair, and +# this statement must NOT raise any error. +# +# NB! Without prepare() such action must lead to exception: +# "SQLCODE: -901 / Cannot reset user session / There are open transactions (2 active)" +# +# Output of this test must remain EMPTY. +# +# Checked on 4.0.0.2307 SS/CS. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import time +# import subprocess +# import re +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# #-------------------------------------------- +# +# def cleanup( f_names_list ): +# global os +# for i in range(len( f_names_list )): +# if os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# +# #-------------------------------------------- +# +# db_conn.close() +# svc = services.connect(host='localhost', user=user_name, password=user_password) +# fb_home = svc.get_home_directory() +# +# +# DBNAME_A = os.path.join(context['temp_directory'],'tmp_2pc_a.fdb') +# DBNAME_B = os.path.join(context['temp_directory'],'tmp_2pc_b.fdb') +# +# if os.path.isfile(DBNAME_A): +# os.remove(DBNAME_A) +# if os.path.isfile(DBNAME_B): +# os.remove(DBNAME_B) +# +# con1 = fdb.create_database( dsn = 'localhost:' + DBNAME_A) +# con2 = fdb.create_database( dsn = 'localhost:' + DBNAME_B) +# +# con1.execute_immediate( 'create table test(id int, x int, constraint test_pk primary key(id) using index test_pk)' ) +# con1.commit() +# +# con2.execute_immediate( 'create table test(id int, x int, constraint test_pk primary key(id) using index test_pk)' ) +# con2.commit() +# +# con1.close() +# con2.close() +# +# cgr = fdb.ConnectionGroup() +# +# con1 = fdb.connect( dsn = 'localhost:' + DBNAME_A) +# con2 = fdb.connect( dsn = 'localhost:' + DBNAME_B) +# +# cgr.add(con1) +# cgr.add(con2) +# +# # https://pythonhosted.org/fdb/reference.html#fdb.TPB +# # https://pythonhosted.org/fdb/reference.html#fdb.Connection.trans +# +# tx1a = con1.trans() +# tx2 = con2.trans() +# +# tx1b = con1.trans() +# +# tx1a.begin() +# tx2.begin() +# tx1b.begin() +# +# cur1a=tx1a.cursor() +# cur2=tx2.cursor() +# cur1b=tx1b.cursor() +# +# cur1a.execute( "insert into test(id, x) values( ?, ? )", (1, 111) ) +# cur2.execute( "insert into test(id, x) values( ?, ? )", (2, 222) ) +# cur1b.execute( "insert into test(id, x) values( ?, ? )", (3, 333) ) +# +# # ::: NB ::: WITHOUT following prepare() exception will raise: +# # Error while executing SQL statement: / SQLCODE: -901 / Cannot reset user session / There are open transactions (2 active); -901; 335545206L +# tx1a.prepare() +# +# cur1b.execute( "alter session reset" ) +# +# cur1a.close() +# cur1b.close() +# cur2.close() +# tx1a.rollback() +# tx1b.rollback() +# tx2.rollback() +# +# # ::: NB ::: +# # We can NOT ecplicitly close connections that participate in ConnectionGroup. +# # Exception will raise in that case: "Cannot close a connection that is a member of a ConnectionGroup." +# #con1.close() +# #con2.close() +# +# cgr.clear() +# +# # change state of test databases to full shutdown otherwise get "Object in use" (set linger = 0 does not help!) +# runProgram('gfix',['localhost:' + DBNAME_A,'-shut','full','-force','0']) +# runProgram('gfix',['localhost:' + DBNAME_B,'-shut','full','-force','0']) +# +# cleanup( (DBNAME_A, DBNAME_B) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_alter_session_reset_allow_2pc_prepared_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/session/test_alter_session_reset_clear_gtt.py b/tests/functional/session/test_alter_session_reset_clear_gtt.py new file mode 100644 index 00000000..fb1140df --- /dev/null +++ b/tests/functional/session/test_alter_session_reset_clear_gtt.py @@ -0,0 +1,87 @@ +#coding:utf-8 +# +# id: functional.session.alter_session_reset_clear_gtt +# title: +# ALTER SESSION RESET: clear contents of all used GTT ON COMMIT PRESERVE ROWS +# +# decription: +# Test issue from CORE-5832 about ALTER SESSION RESET: +# "clear contents of all used GLOBAL TEMPORARY TABLE ... ON COMMIT PRESERVE ROWS". +# +# NOTE. *** SET AUTODDL OFF REQUIRED *** +# Following is detailed explanation of this note: +# ======== +# Default ISQL behaviour is to start always *TWO* transactions (for DML and second for DDL) +# after previous commit / rollback and before *ANY* further satement is to be executed, except +# those which control ISQL itself (e.g. 'SET TERM'; 'IN ...'; 'SET BAIL' etc). +# So, even when statement has nothing to change, ISQL will start TWO transactions +# just before executing . +# This means that these transactions will start even if want to run 'ALTER SESSION RESET'. +# This, in turn, makes one of them (which must perform DDL) be 'active and NOT current' +# from ALTER SESSION point of view (which is run within DML transaction). +# +# According to description given in CORE-5832, ALTER SESSION throws error isc_ses_reset_err +# "if any open transaction exist in current conneciton, *except of current transaction* and +# prepared 2PC transactions which is allowed and ignored by this check". +# +# So, we have to prohibit 'autostart' of DDL-transaction because otherwise ALTER SESSION will +# throw: "SQLSTATE = 01002 / Cannot reset user session / -There are open transactions (2 active)". +# This is done by 'SET AUTODDL OFF' statement at the beginning of this test script. +# ======== +# +# Thanks to Vlad for explanations (discussed 18.01.2021). +# Checked on 4.0.0.2307 SS/CS. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set autoddl off; + commit; + + recreate global temporary table gtt_test(id int) on commit preserve rows; + commit; + + insert into gtt_test(id) values(1); + commit; + + set count on; + select * from gtt_test; + + -------------------- + alter session reset; + -------------------- + + select * from gtt_test; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + Records affected: 1 + Records affected: 0 + """ + +@pytest.mark.version('>=4.0') +def test_alter_session_reset_clear_gtt_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/session/test_alter_session_reset_clear_timeouts.py b/tests/functional/session/test_alter_session_reset_clear_timeouts.py new file mode 100644 index 00000000..3c2ff35c --- /dev/null +++ b/tests/functional/session/test_alter_session_reset_clear_timeouts.py @@ -0,0 +1,91 @@ +#coding:utf-8 +# +# id: functional.session.alter_session_reset_clear_timeouts +# title: +# ALTER SESSION RESET: reset session and statement timeouts to zero +# +# decription: +# Test issue from CORE-5832 about ALTER SESSION RESET: +# "reset session and statement timeouts to zero". +# +# NOTE. *** SET AUTODDL OFF REQUIRED *** +# Following is detailed explanation of this note: +# ======== +# Default ISQL behaviour is to start always *TWO* transactions (for DML and second for DDL) +# after previous commit / rollback and before *ANY* further satement is to be executed, except +# those which control ISQL itself (e.g. 'SET TERM'; 'IN ...'; 'SET BAIL' etc). +# So, even when statement has nothing to change, ISQL will start TWO transactions +# just before executing . +# This means that these transactions will start even if want to run 'ALTER SESSION RESET'. +# This, in turn, makes one of them (which must perform DDL) be 'active and NOT current' +# from ALTER SESSION point of view (which is run within DML transaction). +# +# According to description given in CORE-5832, ALTER SESSION throws error isc_ses_reset_err +# "if any open transaction exist in current conneciton, *except of current transaction* and +# prepared 2PC transactions which is allowed and ignored by this check". +# +# So, we have to prohibit 'autostart' of DDL-transaction because otherwise ALTER SESSION will +# throw: "SQLSTATE = 01002 / Cannot reset user session / -There are open transactions (2 active)". +# This is done by 'SET AUTODDL OFF' statement at the beginning of this test script. +# ======== +# +# Thanks to Vlad for explanations (discussed 18.01.2021). +# Checked on 4.0.0.2307 SS/CS. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set list on; + set autoddl off; + commit; + + set session idle timeout 15 hour; + set statement timeout 15 second; + select + rdb$get_context('SYSTEM','SESSION_IDLE_TIMEOUT') as session_idle_timeout_before_reset + ,rdb$get_context('SYSTEM','STATEMENT_TIMEOUT') as statement_timeout_before_reset + from rdb$database; + + -------------------- + alter session reset; + -------------------- + + select + rdb$get_context('SYSTEM','SESSION_IDLE_TIMEOUT') as session_idle_timeout_after_reset + ,rdb$get_context('SYSTEM','STATEMENT_TIMEOUT') as statement_timeout_after_reset + from rdb$database; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + SESSION_IDLE_TIMEOUT_BEFORE_RESET 54000 + STATEMENT_TIMEOUT_BEFORE_RESET 15000 + + SESSION_IDLE_TIMEOUT_AFTER_RESET 0 + STATEMENT_TIMEOUT_AFTER_RESET 0 + """ + +@pytest.mark.version('>=4.0') +def test_alter_session_reset_clear_timeouts_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/session/test_alter_session_reset_decfloat.py b/tests/functional/session/test_alter_session_reset_decfloat.py new file mode 100644 index 00000000..dee5f8e2 --- /dev/null +++ b/tests/functional/session/test_alter_session_reset_decfloat.py @@ -0,0 +1,128 @@ +#coding:utf-8 +# +# id: functional.session.alter_session_reset_decfloat +# title: +# ALTER SESSION RESET: DECFLOAT parameters must be returned to default values +# +# decription: +# Test issue from CORE-5832 about ALTER SESSION RESET: +# "DECFLOAT parameters (BIND, TRAP and ROUND) must be reset to default values". +# +# We change all three specified parameters and evaluate some expressions. +# Then we run RESET SESSION and evaluate the same expressions. +# Results must differ for all of them. +# +# NOTE-1. +# FDB driver 2.0.1 does not support DEFCFLOAT datatype (at least version 2.0.1), +# so test type must be ISQL. +# +# NOTE-2. *** SET AUTODDL OFF REQUIRED *** +# Following is detailed explanation of this note: +# ======== +# Default ISQL behaviour is to start always *TWO* transactions (for DML and second for DDL) +# after previous commit / rollback and before *ANY* further satement is to be executed, except +# those which control ISQL itself (e.g. 'SET TERM'; 'IN ...'; 'SET BAIL' etc). +# So, even when statement has nothing to change, ISQL will start TWO transactions +# just before executing . +# This means that these transactions will start even if want to run 'ALTER SESSION RESET'. +# This, in turn, makes one of them (which must perform DDL) be 'active and NOT current' +# from ALTER SESSION point of view (which is run within DML transaction). +# +# According to description given in CORE-5832, ALTER SESSION throws error isc_ses_reset_err +# "if any open transaction exist in current conneciton, *except of current transaction* and +# prepared 2PC transactions which is allowed and ignored by this check". +# +# So, we have to prohibit 'autostart' of DDL-transaction because otherwise ALTER SESSION will +# throw: "SQLSTATE = 01002 / Cannot reset user session / -There are open transactions (2 active)". +# This is done by 'SET AUTODDL OFF' statement at the beginning of this test script. +# ======== +# +# Thanks to Vlad for explanations (discussed 18.01.2021). +# Checked on 4.0.0.2307 SS/CS. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('^((?!(sqltype|before_reset|after_reset)).)*$', ''), ('[ \t]+', ' '), ('.*alias.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + + recreate table test(a decfloat, b decfloat, c decfloat); + insert into test(a,b,c) values(1608.90, 5.00, 100.00); + commit; + + set list on; + set autoddl off; + commit; + + set bind of decfloat to smallint; + set decfloat traps to; + set decfloat round ceiling; + + set sqlda_display on; + select cast(1234.5678 as decfloat(16)) as "before_reset: check datatype" from rdb$database; + set sqlda_display off; + + -- Should issue: Infinity + select 1/1e-9999 as "before_reset: check division result" from rdb$database; + + + select a * b / c as "before_reset: check round result" from test; + + -------------------- + alter session reset; + -------------------- + + set sqlda_display on; + select cast(1234.5678 as decfloat(16)) as "after_reset: check datatype" from rdb$database; + set sqlda_display off; + + -- Should issue: + -- Statement failed, SQLSTATE = 22012 + -- Decimal float divide by zero. The code attempted to divide a DECFLOAT value by zero. + select 1/1e-9999 "after_reset: check division result" from rdb$database; + + select a * b / c as "after_reset: check round result" from test; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + 01: sqltype: 500 SHORT scale: 0 subtype: 0 len: 2 + before_reset: check datatype 1235 + + before_reset: check division result 0 + + before_reset: check round result 81 + + 01: sqltype: 32760 DECFLOAT(16) scale: 0 subtype: 0 len: 8 + after_reset: check datatype 1234.5678 + + after_reset: check round result 80.445 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 22012 + Decimal float divide by zero. The code attempted to divide a DECFLOAT value by zero. + """ + +@pytest.mark.version('>=4.0') +def test_alter_session_reset_decfloat_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/session/test_alter_session_reset_raise_if_open_tx.py b/tests/functional/session/test_alter_session_reset_raise_if_open_tx.py new file mode 100644 index 00000000..09979f26 --- /dev/null +++ b/tests/functional/session/test_alter_session_reset_raise_if_open_tx.py @@ -0,0 +1,79 @@ +#coding:utf-8 +# +# id: functional.session.alter_session_reset_raise_if_open_tx +# title: +# ALTER SESSION RESET: throw error (isc_ses_reset_err) if any open transaction exist in current connection... +# +# decription: +# Test issue from CORE-5832 about ALTER SESSION RESET: +# "throw error (isc_ses_reset_err) if any open transaction exist in current connection except +# of current transaction..." +# +# We start three transactions within the same connection. First of them runs 'ALTER SESSION RESET'. +# It must fail with error with phrase about active transactions that prevent from doing this action. +# +# NOTE: this test does NOT check admissibility of session reset when prepared 2PC transactions exist. +# It checks only ERROR RAISING when there are several Tx opened within the same connection. +# +# Checked on 4.0.0.2307 SS/CS. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# tx1 = db_conn.trans() +# tx2 = db_conn.trans() +# tx3 = db_conn.trans() +# +# tx1.begin() +# tx2.begin() +# tx3.begin() +# +# cur1=tx1.cursor() +# try: +# cur1.execute('alter session reset') +# except Exception,e: +# for x in e: +# print(x) +# finally: +# tx1.commit() +# tx2.commit() +# tx3.commit() +# +# db_conn.close() +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Error while executing SQL statement: + - SQLCODE: -901 + - Cannot reset user session + - There are open transactions (3 active) + -901 + 335545206 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_alter_session_reset_raise_if_open_tx_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/session/test_alter_session_reset_remove_context_vars.py b/tests/functional/session/test_alter_session_reset_remove_context_vars.py new file mode 100644 index 00000000..292629e5 --- /dev/null +++ b/tests/functional/session/test_alter_session_reset_remove_context_vars.py @@ -0,0 +1,87 @@ +#coding:utf-8 +# +# id: functional.session.alter_session_reset_remove_context_vars +# title: +# ALTER SESSION RESET: remove all context variables in 'USER_SESSION' namespace +# +# decription: +# Test issue from CORE-5832 about ALTER SESSION RESET: +# "remove all context variables in 'USER_SESSION' namespace ". +# +# NOTE. *** SET AUTODDL OFF REQUIRED *** +# Following is detailed explanation of this note: +# ======== +# Default ISQL behaviour is to start always *TWO* transactions (for DML and second for DDL) +# after previous commit / rollback and before *ANY* further satement is to be executed, except +# those which control ISQL itself (e.g. 'SET TERM'; 'IN ...'; 'SET BAIL' etc). +# So, even when statement has nothing to change, ISQL will start TWO transactions +# just before executing . +# This means that these transactions will start even if want to run 'ALTER SESSION RESET'. +# This, in turn, makes one of them (which must perform DDL) be 'active and NOT current' +# from ALTER SESSION point of view (which is run within DML transaction). +# +# According to description given in CORE-5832, ALTER SESSION throws error isc_ses_reset_err +# "if any open transaction exist in current conneciton, *except of current transaction* and +# prepared 2PC transactions which is allowed and ignored by this check". +# +# So, we have to prohibit 'autostart' of DDL-transaction because otherwise ALTER SESSION will +# throw: "SQLSTATE = 01002 / Cannot reset user session / -There are open transactions (2 active)". +# This is done by 'SET AUTODDL OFF' statement at the beginning of this test script. +# ======== +# +# Thanks to Vlad for explanations (discussed 18.01.2021). +# Checked on 4.0.0.2307 SS/CS. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set autoddl off; + commit; + + set term ^; + execute block as + declare c smallint; + begin + c = rdb$set_context('USER_SESSION', 'TEST_VAR', '123'); + end + ^ + set term ;^ + select rdb$get_context('USER_SESSION', 'TEST_VAR') as session_level_context_var_before_reset from rdb$database; + + -------------------- + alter session reset; + -------------------- + + select rdb$get_context('USER_SESSION', 'TEST_VAR') as session_level_context_var_after_reset from rdb$database; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + SESSION_LEVEL_CONTEXT_VAR_BEFORE_RESET 123 + SESSION_LEVEL_CONTEXT_VAR_AFTER_RESET + """ + +@pytest.mark.version('>=4.0') +def test_alter_session_reset_remove_context_vars_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/session/test_alter_session_reset_restore_role.py b/tests/functional/session/test_alter_session_reset_restore_role.py new file mode 100644 index 00000000..abe95f90 --- /dev/null +++ b/tests/functional/session/test_alter_session_reset_restore_role.py @@ -0,0 +1,105 @@ +#coding:utf-8 +# +# id: functional.session.alter_session_reset_restore_role +# title: +# ALTER SESSION RESET: restore ROLE which was passed with DPB and clear all cached security classes (if role was changed) +# +# decription: +# Test issue from CORE-5832 about ALTER SESSION RESET: +# "restore ROLE which was passed with DPB and clear all cached security classes (if role was changed) ". +# +# NOTE. *** SET AUTODDL OFF REQUIRED *** +# Following is detailed explanation of this note: +# ======== +# Default ISQL behaviour is to start always *TWO* transactions (for DML and second for DDL) +# after previous commit / rollback and before *ANY* further satement is to be executed, except +# those which control ISQL itself (e.g. 'SET TERM'; 'IN ...'; 'SET BAIL' etc). +# So, even when statement has nothing to change, ISQL will start TWO transactions +# just before executing . +# This means that these transactions will start even if want to run 'ALTER SESSION RESET'. +# This, in turn, makes one of them (which must perform DDL) be 'active and NOT current' +# from ALTER SESSION point of view (which is run within DML transaction). +# +# According to description given in CORE-5832, ALTER SESSION throws error isc_ses_reset_err +# "if any open transaction exist in current conneciton, *except of current transaction* and +# prepared 2PC transactions which is allowed and ignored by this check". +# +# So, we have to prohibit 'autostart' of DDL-transaction because otherwise ALTER SESSION will +# throw: "SQLSTATE = 01002 / Cannot reset user session / -There are open transactions (2 active)". +# This is done by 'SET AUTODDL OFF' statement at the beginning of this test script. +# ======== +# +# Thanks to Vlad for explanations (discussed 18.01.2021). +# Checked on 4.0.0.2307 SS/CS. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + + create role acnt; + create role boss; + commit; + + create view v_test as + select mon$user as who_ami, mon$role as whats_my_role + from mon$attachments + where mon$attachment_id = current_connection; + commit; + + grant acnt to sysdba; + grant boss to sysdba; + commit; + + set list on; + set autoddl off; + commit; + + connect '$(DSN)' user 'SYSDBA' password 'masterkey' role boss; + + select * from v_test; + set role acnt; + commit; + select * from v_test; + + -------------------- + alter session reset; + -------------------- + select * from v_test; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHO_AMI SYSDBA + WHATS_MY_ROLE BOSS + + WHO_AMI SYSDBA + WHATS_MY_ROLE ACNT + + WHO_AMI SYSDBA + WHATS_MY_ROLE BOSS + """ + +@pytest.mark.version('>=4.0') +def test_alter_session_reset_restore_role_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/session/test_alter_session_reset_rollback.py b/tests/functional/session/test_alter_session_reset_rollback.py new file mode 100644 index 00000000..130a6af8 --- /dev/null +++ b/tests/functional/session/test_alter_session_reset_rollback.py @@ -0,0 +1,90 @@ +#coding:utf-8 +# +# id: functional.session.alter_session_reset_rollback +# title: +# ALTER SESSION RESET: ROLLBACK current user transaction (if present) and issue warning if that transaction changes any table before reset +# +# decription: +# Test issue from CORE-5832 about ALTER SESSION RESET: +# "ROLLBACK current user transaction (if present) and issue warning if that transaction changes any table before reset ". +# +# We create trivial table and insert one row in it. +# Then, without committing changes, we issue 'ALTER SESSION RESET'. +# Warning must be thrown after it (in STDERR) and no records must remain in the table as result. +# +# NOTE. *** SET AUTODDL OFF REQUIRED *** +# Following is detailed explanation of this note: +# ======== +# Default ISQL behaviour is to start always *TWO* transactions (for DML and second for DDL) +# after previous commit / rollback and before *ANY* further satement is to be executed, except +# those which control ISQL itself (e.g. 'SET TERM'; 'IN ...'; 'SET BAIL' etc). +# So, even when statement has nothing to change, ISQL will start TWO transactions +# just before executing . +# This means that these transactions will start even if want to run 'ALTER SESSION RESET'. +# This, in turn, makes one of them (which must perform DDL) be 'active and NOT current' +# from ALTER SESSION point of view (which is run within DML transaction). +# +# According to description given in CORE-5832, ALTER SESSION throws error isc_ses_reset_err +# "if any open transaction exist in current conneciton, *except of current transaction* and +# prepared 2PC transactions which is allowed and ignored by this check". +# +# So, we have to prohibit 'autostart' of DDL-transaction because otherwise ALTER SESSION will +# throw: "SQLSTATE = 01002 / Cannot reset user session / -There are open transactions (2 active)". +# This is done by 'SET AUTODDL OFF' statement at the beginning of this test script. +# ======== +# +# Thanks to Vlad for explanations (discussed 18.01.2021). +# Checked on 4.0.0.2307 SS/CS. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test(id int); + commit; + + set list on; + set autoddl off; + commit; + + insert into test(id) values(1); + + -------------------- + alter session reset; + -------------------- + set count on; + select * from test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + """ +expected_stderr_1 = """ + Session was reset with warning(s) + -Transaction is rolled back due to session reset, all changes are lost + """ + +@pytest.mark.version('>=4.0') +def test_alter_session_reset_rollback_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/session/test_alter_session_reset_start_new_tx.py b/tests/functional/session/test_alter_session_reset_start_new_tx.py new file mode 100644 index 00000000..e218f1ac --- /dev/null +++ b/tests/functional/session/test_alter_session_reset_start_new_tx.py @@ -0,0 +1,156 @@ +#coding:utf-8 +# +# id: functional.session.alter_session_reset_start_new_tx +# title: +# ALTER SESSION RESET: START new transaction with the same properties as transaction that was rolled back (if transaction was present before reset) +# +# decription: +# Test issue from CORE-5832 about ALTER SESSION RESET: +# "START new transaction with the same properties as transaction that was rolled back (if transaction was present before reset)". +# +# We create trivial table and insert one row in it with ID = current_transaction - and use AUTONOMOUS tranaction for this (ES is used). +# Then, without committing changes in main Tx, we issue 'ALTER SESSION RESET'. +# Warning must be thrown after it (in STDERR) and no records must remain in the table as result. +# After this, we check that new transaction has ID different than used before and that attributes of this Tx were NOT changed. +# +# NOTE. *** SET AUTODDL OFF REQUIRED *** +# Following is detailed explanation of this note: +# ======== +# Default ISQL behaviour is to start always *TWO* transactions (for DML and second for DDL) +# after previous commit / rollback and before *ANY* further satement is to be executed, except +# those which control ISQL itself (e.g. 'SET TERM'; 'IN ...'; 'SET BAIL' etc). +# So, even when statement has nothing to change, ISQL will start TWO transactions +# just before executing . +# This means that these transactions will start even if want to run 'ALTER SESSION RESET'. +# This, in turn, makes one of them (which must perform DDL) be 'active and NOT current' +# from ALTER SESSION point of view (which is run within DML transaction). +# +# According to description given in CORE-5832, ALTER SESSION throws error isc_ses_reset_err +# "if any open transaction exist in current conneciton, *except of current transaction* and +# prepared 2PC transactions which is allowed and ignored by this check". +# +# So, we have to prohibit 'autostart' of DDL-transaction because otherwise ALTER SESSION will +# throw: "SQLSTATE = 01002 / Cannot reset user session / -There are open transactions (2 active)". +# This is done by 'SET AUTODDL OFF' statement at the beginning of this test script. +# ======== +# +# Thanks to Vlad for explanations (discussed 18.01.2021). +# Checked on 4.0.0.2307 SS/CS. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- set echo on; + set bail on; + recreate table test( + trn_id bigint + ,trn_isolation_mode smallint + ,trn_lock_timeout int + ,trn_read_only smallint + ,trn_auto_undo smallint + ); + commit; + + set autoddl off; + commit; + + set transaction read committed record_version lock timeout 5 no auto undo; + set term ^; + execute block as + declare v_isolation_mode type of column mon$transactions.mon$isolation_mode; + declare v_lock_timeout type of column mon$transactions.mon$lock_timeout; + declare v_read_only type of column mon$transactions.mon$read_only; + declare v_auto_undo type of column mon$transactions.mon$auto_undo; + begin + select + mon$isolation_mode + ,mon$lock_timeout + ,mon$read_only + ,mon$auto_undo + from mon$transactions + where mon$transaction_id = current_transaction + into + v_isolation_mode + ,v_lock_timeout + ,v_read_only + ,v_auto_undo + ; + in autonomous transaction do + insert into test(trn_id, trn_isolation_mode, trn_lock_timeout, trn_read_only, trn_auto_undo) + values(current_transaction, :v_isolation_mode, :v_lock_timeout, :v_read_only, :v_auto_undo ); + end + ^ + set term ;^ + + -------------------- + alter session reset; + -------------------- + + set term ^; + execute block as + declare v_isolation_mode type of column mon$transactions.mon$isolation_mode; + declare v_lock_timeout type of column mon$transactions.mon$lock_timeout; + declare v_read_only type of column mon$transactions.mon$read_only; + declare v_auto_undo type of column mon$transactions.mon$auto_undo; + begin + select + mon$isolation_mode + ,mon$lock_timeout + ,mon$read_only + ,mon$auto_undo + from mon$transactions + where mon$transaction_id = current_transaction + into + v_isolation_mode + ,v_lock_timeout + ,v_read_only + ,v_auto_undo + ; + insert into test(trn_id, trn_isolation_mode, trn_lock_timeout, trn_read_only, trn_auto_undo) + values(current_transaction, :v_isolation_mode, :v_lock_timeout, :v_read_only, :v_auto_undo ); + end + ^ + set term ;^ + + set list on; + select + count(distinct trn_id) as trn_id_distinct_cnt + ,count(distinct trn_isolation_mode) as trn_isolation_mode_distinct_cnt + ,count(distinct trn_lock_timeout) as trn_lock_timeout_distinct_cnt + ,count(distinct trn_read_only) as trn_read_distinct_cnt + ,count(distinct trn_auto_undo) as trn_auto_undo_distinct_cnt + from test; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TRN_ID_DISTINCT_CNT 2 + TRN_ISOLATION_MODE_DISTINCT_CNT 1 + TRN_LOCK_TIMEOUT_DISTINCT_CNT 1 + TRN_READ_DISTINCT_CNT 1 + TRN_AUTO_UNDO_DISTINCT_CNT 1 + """ + +@pytest.mark.version('>=4.0') +def test_alter_session_reset_start_new_tx_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/session/test_ext_conn_pool_01.py b/tests/functional/session/test_ext_conn_pool_01.py new file mode 100644 index 00000000..3ee64514 --- /dev/null +++ b/tests/functional/session/test_ext_conn_pool_01.py @@ -0,0 +1,778 @@ +#coding:utf-8 +# +# id: functional.session.ext_conn_pool_01 +# title: External Connections Pool, functionality test 01 +# decription: +# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +# ATTENTION! CURRENT FB INSTANCE DOES NOT PARTICIPATE IN THIS TEST WORK! TEMPORARY INSTANCE IS USED! +# RESULT OF THIS TEST HAS NO "LINK: WITH CURRENTLY CHECKED FB SERVERMODE! DIFF OUTPUT MUST BE CHECKED! +# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +# +# Basic check of External Connections Pool. We verify here following: +# * ability to reuse connections from ECP in case running ES/EDS by "frequent" attachments +# * ability to distinguish connect/disconnect from reuse connections within apropriate +# DB-level trigger (system variable RESETTING = faluse | true) +# * ability to get information about ECP state: total number of active and idle connections. +# +# See $FB_HOME/doc/sql.extensions/README.external_connections_pool and CORE-5832. +# ------------------------------------------------------------------------------------------- +# Test retrieves FB_HOME directory and makes copy of firebird.conf and database.conf files. +# Then it searches for free TCP port and overwrites content of firebird.conf: this new port +# will be specified for RemoveServicePort (see 'TMP_FREE_PORT'). +# Also, parameters for working with External Connections Pool (hereafter: ECP) will be added: +# ExtConnPoolSize = +# ExtConnPoolLifeTime = +# -- where can be set to 5...10 s (but not less than 3). +# +# New alias is added to databases.conf for test .fdb which must be created as self-security DB: +# tmp_ecp_01 = { +# SecurityDatabase = tmp_ecp_01 +# RemoteAccess = true +# } +# File $FB_HOME/security4.fdb is copied to the . +# +# After this test launches new Firebird instance *as application* (see async. call of Popen()) and make +# some actions with just created test DB (alias = tmp_ecp_01). Because this DB is self-secutity, we can +# use it for connect without any conflict with existing FB instance. +# +# When all needed actions with this DB complete, this FB temporary instance will be stopped. +# Test does start and stop of this FB instance _two_ times because of checking following ServerMode: +# * Super +# * SuperClassic +# +# ::: NOTE ::: +# Test does NOT check Servermode = Classic because of unpredictable results when ExtConnPoolLifeTime less than 7s. +# In some cases number of IDLE connections can differ from one run to another. The reason is remaining unknown. +# ------------------------------------------------------------------------------------------- +# After FB instance launch, test runs ISQL that connects to using port and creates +# several DB objects: +# * DB-level triggers on CONNECT / DISCONNECT; +# * table 'audit' for logging these events, with specifying detailed info: whether current +# connect/disconnect is caused by SESSION RESET (variable RESETTING is TRUE) or no; +# * two users who which further perform connect and run several ES/EDS statements: +# 'freq' -- will do ES/EDS 'frequently', i.e. with interval LESS than ExtConnPoolLifeTime; +# 'rare' -- will do ES/EDS 'rarely', with interval GREATER than ExtConnPoolLifeTime; +# * role 'cleaner_ext_pool' with granting to it system privilege MODIFY_EXT_CONN_POOL, in order +# to have ability to clear ext pool after final ES/EDS. Grant this role to both 'freq' and 'rare' +# +# Then we create several connections for user 'freq' (appending them into a list) and for each of them +# do ES/EDS. Number of connections is specified by variable ITER_LOOP_CNT. Delay between subsequent +# ES/EDS for 'freq' is minimal: 1 second. +# After this, we repeate the same for user 'rare', and use delay between subsequent ES/EDS GREATER +# than ExtConnPoolLifeTime for seconds. +# After loop we clear ExtConnPool and close all connections from list. +# +# Finally test terminates Firebird application process and queries to the table 'audit' for check results. +# Number of rows (and unique connection IDs) for user 'freq' must be significantly less than for user 'rare', +# despite the fact that both of them did the same work. This is because engine held idle connections in the pool +# and user FREQ could re-use them when ran subsequent ES/EDS. +# +# ::: CAUTION ::: +# Windows Firewall can block attempt to launch FB as application (dialog window appears in this case). +# One may need to configure Firewall so that process +# irebird.exe is enable to operate on any port. +# +# Perhaps, following command will be useful: netsh advfirewall set privateprofile state off +# +# Checked on 4.0.0.2235, FB instances were launched as 'Super' and 'SuperClassic'. Time: ~52s. +# +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import sys +# import os +# import socket +# import platform +# import shutil +# import time +# import datetime +# import tempfile +# import difflib +# import subprocess +# import fdb +# from fdb import services +# +# # POSIX: '/opt/fb40/lib/libfbclient.so' +# # Windows: r'C:\\FB SS +# bclient.dll' +# #FB_CLNT = r'C:\\FB SS +# bclient.dll' +# +# +# os.environ["ISC_USER"] = 'SYSDBA' +# os.environ["ISC_PASSWORD"] = 'masterkey' +# +# TMP_DBA_PSWD = 'M@$terkeX' +# +# # Ext. Poll size and lifetime: +# ECP_SIZE = 10 +# +# # === !!! do NOT set ECP_LIFE less than 4 !!! === +# # SuperClassic can fail in that case (approx every 40...50 run): mismatch in last column (number of ECP idle connections): +# # Example of diff: +# ######################################################################################################## +# # - SuperClassic FREQ 2 12 BYE 0 7 +# # + SuperClassic FREQ 2 12 BYE 0 6 +# # +# # - SuperClassic FREQ 4 13 RUN DML 1 6 +# # + SuperClassic FREQ 4 13 RUN DML 1 5 +# # +# # - SuperClassic FREQ 4 14 MOVE INTO POOL: ACTIVE -> IDLE 1 6 +# # + SuperClassic FREQ 4 14 MOVE INTO POOL: ACTIVE -> IDLE 1 5 +# # +# # - SuperClassic FREQ 4 15 TAKE FROM POOL: IDLE -> ACTIVE 2 6 +# # + SuperClassic FREQ 4 15 TAKE FROM POOL: IDLE -> ACTIVE 2 5 +# ######################################################################################################## +# # +# ECP_LIFE = 5 +# +# # How many seconds will be added to delay = when user 'RARE' works with database. +# # For Classic it was needed to set this value about 4(!) seconds but this did not help and results remained non-stable +# # For Super and SuperClassic it is enough to add 2 seconds: +# # +# ADD_DELAY_FOR_RARE = 2 +# +# # How many connections will be done by users 'FREQ' and (after him) by 'RARE'. +# # Each connection will run _single_ DML using ES/EDS and then immediately is closed +# # Subsequent connection will run its DML after N seconds where: +# # N = 1 -- for user 'FREQ' +# # N = ECP_LIFE + ADD_DELAY_FOR_RARE -- for user 'RARE' +# # +# ITER_LOOP_CNT = 3 +# +# +# FB_HOME = services.connect(host='localhost', user=user_name, password=user_password).get_home_directory() +# FB_BINS = os.path.join( FB_HOME, 'bin'+os.sep if platform.system() == 'Linux' else '' ) +# +# #-------------------------------------------- +# +# 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'): +# # 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: +# del_name = None +# +# if os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# def find_free_port(): +# global socket +# from contextlib import closing +# # 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) +# return s.getsockname()[1] +# +# #-------------------------------------------- +# def check_server(address, port): +# global socket +# # Create a TCP socket +# s = socket.socket() +# try: +# s.connect((address, port)) +# return True +# except socket.error, e: +# return False +# finally: +# s.close() +# +# #-------------------------------------------- +# +# def do_shutdown_bring_online( FB_BINS, tcp_port, db_name, dba_pwd ): +# global subprocess +# subprocess.call( [ os.path.join( FB_BINS, 'gfix'), '-user', 'SYSDBA', '-pas', dba_pwd, '-shut', 'full', '-force', '0', 'localhost/%d:%s' % (tcp_port, db_name) ] ) +# subprocess.call( [ os.path.join( FB_BINS, 'gfix'), '-user', 'SYSDBA', '-online', db_name ] ) +# +# #-------------------------------------------- +# +# def get_fb_arch(a_dsn): +# try: +# con1 = fdb.connect(dsn = a_dsn) +# con2 = fdb.connect(dsn = a_dsn) +# +# cur1 = con1.cursor() +# +# sql=( +# "select count(distinct a.mon$server_pid), min(a.mon$remote_protocol), max(iif(a.mon$remote_protocol is null,1,0))" +# +" from mon$attachments a" +# +" where a.mon$attachment_id in (%s, %s) or upper(a.mon$user) = upper('%s')" +# % (con1.attachment_id, con2.attachment_id, 'cache writer') +# ) +# +# cur1.execute(sql) +# for r in cur1.fetchall(): +# server_cnt=r[0] +# server_pro=r[1] +# cache_wrtr=r[2] +# +# if server_pro == None: +# fba='Embedded' +# elif cache_wrtr == 1: +# fba='SS' +# elif server_cnt == 2: +# fba='CS' +# else: +# +# f1=con1.db_info(fdb.isc_info_fetches) +# +# cur2=con2.cursor() +# cur2.execute('select 1 from rdb$database') +# for r in cur2.fetchall(): +# pass +# +# f2=con1.db_info(fdb.isc_info_fetches) +# +# fba = 'SC' if f1 ==f2 else 'SS' +# +# #print(fba, con1.engine_version, con1.version) +# return fba +# +# finally: +# con1.close() +# con2.close() +# +# #------------------------------------------------- +# +# fb_vers = str(db_conn.engine_version)[:1] # character for security.db file: engine = 4.0 --> '4' +# db_conn.close() +# +# sec_db = os.path.join( FB_HOME, 'security' + fb_vers+ '.fdb') +# +# fdb_test = os.path.join(context['temp_directory'],'ext-conn-pool-01.fdb') +# cleanup( (fdb_test,) ) +# +# dts = datetime.datetime.now().strftime("%y%m%d_%H%M%S") +# +# fbconf_cur = os.path.join(FB_HOME, 'firebird.conf') +# fbconf_bak = os.path.join(context['temp_directory'], 'firebird_'+dts+'.bak') +# +# dbconf_cur = os.path.join(FB_HOME, 'databases.conf') +# dbconf_bak = os.path.join(context['temp_directory'], 'databases_'+dts+'.bak') +# +# shutil.copy2( sec_db, fdb_test ) +# f_init_err = 0 +# +# ################################# +# TMP_FREE_PORT = find_free_port() +# ################################# +# +# #fb_arch = get_fb_arch( dsn ) +# +# CHECKED_MODE_LIST=( 'Super,', 'SuperClassic', ) +# +# # NO SENSE, ALWAYS DIFFERENT VALUES IN 'IDLE' COLUMN >>> CHECKED_MODE_LIST=('Classic',) +# +# for srvidx,srvmode in enumerate( CHECKED_MODE_LIST ): +# +# shutil.copy2( fbconf_cur, fbconf_bak ) +# shutil.copy2( dbconf_cur, dbconf_bak ) +# +# cfg_params_to_change= { +# 'ServerMode' : srvmode +# ,'RemoteServicePort' : str(TMP_FREE_PORT) +# ,'ExtConnPoolLifeTime' : str(ECP_LIFE) +# ,'ExtConnPoolSize' : str(ECP_SIZE) +# ,'DefaultDbCachePages' : '2048' +# ,'UseFileSystemCache' : 'true' +# ,'IpcName' : 'fb4x_ipc_ecp' +# ,'RemoteServiceName' : 'fb4x_svc_ecp' +# ,'BugcheckAbort' : '1' +# ,'AuthClient' : 'Srp' +# ,'AuthServer' : 'Srp' +# } +# +# f_fbconf=open( fbconf_cur, 'w') +# for k,v in sorted(cfg_params_to_change.items()): +# f_fbconf.write( ''.join( (k, ' = ', v, '\\n') ) ) +# flush_and_close( f_fbconf ) +# +# alias_data= ''' +# # Added temporarily for executing test ext-conn-pool-01.fbt +# tmp_ecp_01 = %(fdb_test)s { +# SecurityDatabase = tmp_ecp_01 +# RemoteAccess = true +# } +# ''' % locals() +# +# f_dbconf=open( dbconf_cur, 'w') +# f_dbconf.write(alias_data) +# flush_and_close( f_dbconf ) +# +# ######################################################################## +# ### L A U N C H F B A S A P P L I C A T I O N ### +# ######################################################################## +# fb_process = subprocess.Popen( [ os.path.join( FB_BINS, 'firebird'), '-a'] ) +# time.sleep(2) +# +# if not check_server('localhost', TMP_FREE_PORT): +# print('### ERROR ### FB instance not yet started. Increase delay and repeat!') +# +# if srvidx == 0: +# # initial creation of test DB +# ############################# +# +# sql_text= ''' +# set bail on; +# set wng off; +# set echo on; +# +# connect 'tmp_ecp_01'; +# +# create or alter user sysdba password '%(TMP_DBA_PSWD)s' using plugin Srp; +# +# -- !! otherwise next attempt to attach via TCP will fail with Windows +# -- error 32 process can not access file it is used by another process !! +# alter database set linger to 0; +# commit; +# +# connect 'localhost/%(TMP_FREE_PORT)s:tmp_ecp_01' user sysdba password '%(TMP_DBA_PSWD)s'; +# +# set list on; +# --select * from mon$database; +# --commit; +# +# create or alter user freq password '123' using plugin Srp; +# create or alter user rare password '123' using plugin Srp; +# commit; +# +# create role cleaner_ext_pool +# set system privileges to MODIFY_EXT_CONN_POOL; +# commit; +# +# grant default cleaner_ext_pool to user freq; +# grant default cleaner_ext_pool to user rare; +# commit; +# +# create table audit( +# id smallint generated by default as identity constraint pk_audit primary key +# ,srvmode varchar(12) -- 'Super' / 'SuperClassic' / 'Classic' +# ,who varchar(10) default current_user -- 'freq' / 'rare' / 'sysdba' +# ,evt varchar(40) not null +# ,att smallint default current_connection +# ,trn smallint default current_transaction +# ,dts timestamp default 'now' +# ,pool_active_count smallint +# ,pool_idle_count smallint +# ,aux_info varchar(100) +# ); +# +# create view v_audit as +# select +# srvmode +# ,who +# ,att +# ,id +# ,evt +# ,active_cnt +# ,idle_cnt +# from ( +# select +# srvmode +# ,who +# ,cast(dense_rank()over(partition by srvmode,who order by att) as smallint) as att +# ,cast(dense_rank()over(partition by srvmode,who order by id) as smallint) as id +# ,evt +# ,trn +# ,pool_active_count as active_cnt +# ,pool_idle_count as idle_cnt +# from audit +# ) +# --order by srvmode, who, att, id +# order by srvmode, who, id +# ; +# +# +# grant select,insert on audit to public; +# grant select on v_audit to public; +# commit; +# +# set term ^; +# create or alter procedure sys_get_fb_arch ( +# a_connect_as_user varchar(31) default 'SYSDBA' +# ,a_connect_with_pwd varchar(31) default '%(TMP_DBA_PSWD)s' +# ) returns( +# fb_arch varchar(50) +# ) as +# declare cur_server_pid int; +# declare ext_server_pid int; +# declare att_protocol varchar(255); +# declare v_test_sttm varchar(255); +# declare v_fetches_beg bigint; +# declare v_fetches_end bigint; +# begin +# +# select a.mon$server_pid, a.mon$remote_protocol +# from mon$attachments a +# where a.mon$attachment_id = current_connection +# into cur_server_pid, att_protocol; +# +# if ( att_protocol is null ) then +# fb_arch = 'Embedded'; +# else +# begin +# v_test_sttm = +# 'select a.mon$server_pid' -- + 0*(select 1 from rdb$database)' +# ||' from mon$attachments a ' +# ||' where a.mon$attachment_id = current_connection'; +# +# execute statement v_test_sttm +# on external +# 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME') +# as +# user a_connect_as_user +# password a_connect_with_pwd +# role left('R' || replace(uuid_to_char(gen_uuid()),'-',''),31) +# into ext_server_pid; +# +# if ( cur_server_pid is distinct from ext_server_pid ) then +# fb_arch = 'Classic'; +# else +# begin +# select i.mon$page_fetches +# from mon$io_stats i +# where i.mon$stat_group = 0 -- db_level +# into v_fetches_beg; +# +# in autonomous transaction do +# select i.mon$page_fetches +# from mon$io_stats i +# where i.mon$stat_group = 0 -- db_level +# into v_fetches_end; +# +# fb_arch = iif( v_fetches_beg is not distinct from v_fetches_end, +# 'SuperClassic', +# 'Super' +# ); +# end +# end +# suspend; +# end +# ^ +# +# create or alter trigger trg_aud_bi for audit active before insert sql security definer as +# declare v_srvmode varchar(30); +# declare p int; +# begin +# new.srvmode = rdb$get_context('USER_SESSION', 'FB_ARCH'); +# if ( new.srvmode is null ) then +# begin +# -- Here we get current FB server mode. Procedure 'sys_get_fb_arch' does ES/EDS, +# -- but is uses SYSDBA account and (because of this) table 'audit' will not be +# -- changed in [dis]connect triggers: +# new.srvmode = ( select fb_arch from sys_get_fb_arch('SYSDBA', '%(TMP_DBA_PSWD)s') ); +# +# -- 11.01.2021 22:00: WEIRD! If this statement enabled then .py script HANGS on 2nd iter! +# rdb$set_context('USER_SESSION', 'FB_ARCH', new.srvmode); +# end +# +# new.pool_active_count = rdb$get_context('SYSTEM','EXT_CONN_POOL_ACTIVE_COUNT'); +# new.pool_idle_count = rdb$get_context('SYSTEM','EXT_CONN_POOL_IDLE_COUNT'); +# end +# ^ +# +# create or alter trigger trg_connect inactive on connect sql security definer as +# declare p smallint; +# begin +# if (current_user <> 'SYSDBA') then +# begin +# +# insert into audit( +# evt +# ) values ( +# iif(resetting, 'TAKE FROM POOL: IDLE -> ACTIVE', 'NEW') +# ); +# end +# end +# ^ +# +# create or alter trigger trg_disconnect inactive on disconnect sql security definer as +# begin +# if (current_user <> 'SYSDBA') then +# begin +# insert into audit( +# evt +# ) values ( +# iif(resetting, 'MOVE INTO POOL: ACTIVE -> IDLE', 'BYE') +# ); +# end +# end +# ^ +# set term ;^ +# commit; +# alter trigger trg_connect active; +# alter trigger trg_disconnect active; +# grant execute on procedure sys_get_fb_arch to public; +# commit; +# ''' % locals() +# +# +# f_sql_cmd = open( os.path.join(context['temp_directory'],'ecp-resetting-DDL.sql'), 'w') +# f_sql_cmd.write( sql_text ) +# flush_and_close( f_sql_cmd ) +# +# f_sql_log = open( os.path.splitext(f_sql_cmd.name)[0] + '-init.log', 'w') +# f_sql_err = open( os.path.splitext(f_sql_cmd.name)[0] + '-init.err', 'w') +# subprocess.call( [ os.path.join( FB_BINS, 'isql'), '-q', '-i', f_sql_cmd.name, '-user', 'SYSDBA'], stdout=f_sql_log, stderr=f_sql_err ) +# flush_and_close( f_sql_log ) +# flush_and_close( f_sql_err ) +# +# f_init_err = os.path.getsize(f_sql_err.name) +# +# with open( f_sql_err.name,'r') as f: +# for line in f: +# print("Unexpected STDERR, file " + f_sql_err.name + ": "+line) +# +# cleanup( [ i.name for i in (f_sql_cmd, f_sql_log, f_sql_err) ] ) +# +# #< srvidx == 0 (process 1st of srvmode list) +# +# ############################################################################## +# do_shutdown_bring_online( FB_BINS, TMP_FREE_PORT, 'tmp_ecp_01', TMP_DBA_PSWD ) +# ############################################################################## +# +# if f_init_err == 0: +# +# sql_for_run=''' +# execute block as +# declare c int; +# begin +# execute statement ( q'{ insert into audit( evt ) values( 'RUN DML') }' ) +# on external 'localhost/%(TMP_FREE_PORT)s:' || rdb$get_context('SYSTEM','DB_NAME') +# +# with autonomous transaction -- <<< !!! THIS IS MANDATORY IF WE WANT TO USE EXT CONN POOL !!! <<< +# +# as user current_user password '123' +# ; +# end +# ''' % locals() +# +# +# ########################################################################### +# +# for usr_name in ('freq','rare'): +# conn_list = [] +# for i in range(0, ITER_LOOP_CNT): +# conn_list.append( fdb.connect( dsn = 'localhost/%(TMP_FREE_PORT)s:tmp_ecp_01' % locals(), user = usr_name, password = '123' ) ) +# +# for i,c in enumerate(conn_list): +# +# # ::: NOTE ::: +# # :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +# # On every iteration DIFFERENT connection is used for run ES/EDS, +# # but all of them use the same user/password/role, so apropriate +# # item in the ExtConnPool can be used to run this statement. +# # But this will be so only for user = 'FREQ' because he does such +# # actions 'frequently': each ( - 2) seconds. +# # For user 'RARE' new attachment will be created every time when +# # he runs ES/EDS because he does that 'rarely' and idle connection +# # (from his previous iteration) is removed from ExtConnPool due to +# # expiration of ExtConnPoolLifeTime: +# # :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +# c.execute_immediate( sql_for_run ) +# +# if i < len(conn_list)-1: +# time.sleep( 1 if usr_name == 'freq' else ECP_LIFE + ADD_DELAY_FOR_RARE ) +# else: +# c.execute_immediate( 'ALTER EXTERNAL CONNECTIONS POOL CLEAR ALL' ) +# +# c.close() +# +# ### for c in conn_list: +# ### c.close() +# +# ############################################################################## +# do_shutdown_bring_online( FB_BINS, TMP_FREE_PORT, 'tmp_ecp_01', TMP_DBA_PSWD ) +# ############################################################################## +# +# if srvidx == len(CHECKED_MODE_LIST)-1: +# +# sql_check=''' +# -- set echo on; +# connect 'localhost/%(TMP_FREE_PORT)s:tmp_ecp_01' user sysdba password '%(TMP_DBA_PSWD)s'; +# set count on; +# select * from v_audit; +# --select * from v_audit where who = 'FREQ'; +# --select * from v_audit where who = 'RARE'; +# ''' % locals() +# +# f_sql_cmd = open( os.path.join(context['temp_directory'],'ext_conn-pool-results.sql'), 'w') +# f_sql_cmd.write( sql_check ) +# flush_and_close( f_sql_cmd ) +# +# f_sql_log = open( os.path.splitext(f_sql_cmd.name)[0] + '.log', 'w') +# +# ################################## +# ### f i n a l q u e r y ### +# ################################## +# subprocess.call( [ os.path.join( FB_BINS, 'isql'), '-q', '-pag', '99999', '-i', f_sql_cmd.name ], stdout=f_sql_log, stderr=subprocess.STDOUT ) +# +# flush_and_close( f_sql_log ) +# +# with open(f_sql_log.name) as f: +# for line in f: +# print(line) +# +# #< indent 'f_init_err == 0' +# +# ######################################################################## +# ### S T O P T E M P O R A R Y F B I N S T A N C E ### +# ######################################################################## +# +# fb_process.terminate() +# time.sleep(2) +# +# shutil.move( fbconf_bak, fbconf_cur ) +# shutil.move( dbconf_bak, dbconf_cur ) +# +# if f_init_err > 0: +# break +# +# if check_server('localhost', TMP_FREE_PORT): +# print('### ERROR ### FB instance was not yet terminated. Increase delay and repeat!') +# +# # IDLE 1 4 + Super FREQ 4 7 TAKE FROM POOL: IDLE -> ACTIVE 2 4 + Super FREQ 1 8 BYE 0 6 + Super FREQ 4 9 RUN DML 1 5 + Super FREQ 4 10 MOVE INTO POOL: ACTIVE -> IDLE 1 5 + Super FREQ 4 11 TAKE FROM POOL: IDLE -> ACTIVE 2 5 + Super FREQ 2 12 BYE 0 7 + Super FREQ 4 13 RUN DML 1 6 + Super FREQ 4 14 MOVE INTO POOL: ACTIVE -> IDLE 1 6 + Super FREQ 4 15 TAKE FROM POOL: IDLE -> ACTIVE 2 6 + Super FREQ 4 16 BYE 0 0 + Super FREQ 3 17 BYE 0 0 + Super RARE 1 1 NEW 1 0 + Super RARE 2 2 NEW 1 1 + Super RARE 3 3 NEW 1 2 + Super RARE 4 4 NEW 1 3 + Super RARE 4 5 RUN DML 1 4 + Super RARE 4 6 MOVE INTO POOL: ACTIVE -> IDLE 1 4 + Super RARE 4 7 TAKE FROM POOL: IDLE -> ACTIVE 2 4 + Super RARE 4 8 BYE 0 0 + Super RARE 1 9 BYE 0 0 + Super RARE 5 10 NEW 1 0 + Super RARE 5 11 RUN DML 1 1 + Super RARE 5 12 MOVE INTO POOL: ACTIVE -> IDLE 1 1 + Super RARE 5 13 TAKE FROM POOL: IDLE -> ACTIVE 2 1 + Super RARE 5 14 BYE 0 0 + Super RARE 2 15 BYE 0 0 + Super RARE 6 16 NEW 1 0 + Super RARE 6 17 RUN DML 1 1 + Super RARE 6 18 MOVE INTO POOL: ACTIVE -> IDLE 1 1 + Super RARE 6 19 TAKE FROM POOL: IDLE -> ACTIVE 2 1 + Super RARE 6 20 BYE 0 0 + Super RARE 3 21 BYE 0 0 + SuperClassic FREQ 1 1 NEW 1 0 + SuperClassic FREQ 2 2 NEW 1 1 + SuperClassic FREQ 3 3 NEW 1 2 + SuperClassic FREQ 4 4 NEW 1 3 + SuperClassic FREQ 4 5 RUN DML 1 4 + SuperClassic FREQ 4 6 MOVE INTO POOL: ACTIVE -> IDLE 1 4 + SuperClassic FREQ 4 7 TAKE FROM POOL: IDLE -> ACTIVE 2 4 + SuperClassic FREQ 1 8 BYE 0 6 + SuperClassic FREQ 4 9 RUN DML 1 5 + SuperClassic FREQ 4 10 MOVE INTO POOL: ACTIVE -> IDLE 1 5 + SuperClassic FREQ 4 11 TAKE FROM POOL: IDLE -> ACTIVE 2 5 + SuperClassic FREQ 2 12 BYE 0 7 + SuperClassic FREQ 4 13 RUN DML 1 6 + SuperClassic FREQ 4 14 MOVE INTO POOL: ACTIVE -> IDLE 1 6 + SuperClassic FREQ 4 15 TAKE FROM POOL: IDLE -> ACTIVE 2 6 + SuperClassic FREQ 4 16 BYE 0 0 + SuperClassic FREQ 3 17 BYE 0 0 + SuperClassic RARE 1 1 NEW 1 0 + SuperClassic RARE 2 2 NEW 1 1 + SuperClassic RARE 3 3 NEW 1 2 + SuperClassic RARE 4 4 NEW 1 3 + SuperClassic RARE 4 5 RUN DML 1 4 + SuperClassic RARE 4 6 MOVE INTO POOL: ACTIVE -> IDLE 1 4 + SuperClassic RARE 4 7 TAKE FROM POOL: IDLE -> ACTIVE 2 4 + SuperClassic RARE 4 8 BYE 0 0 + SuperClassic RARE 1 9 BYE 0 0 + SuperClassic RARE 5 10 NEW 1 0 + SuperClassic RARE 5 11 RUN DML 1 1 + SuperClassic RARE 5 12 MOVE INTO POOL: ACTIVE -> IDLE 1 1 + SuperClassic RARE 5 13 TAKE FROM POOL: IDLE -> ACTIVE 2 1 + SuperClassic RARE 5 14 BYE 0 0 + SuperClassic RARE 2 15 BYE 0 0 + SuperClassic RARE 6 16 NEW 1 0 + SuperClassic RARE 6 17 RUN DML 1 1 + SuperClassic RARE 6 18 MOVE INTO POOL: ACTIVE -> IDLE 1 1 + SuperClassic RARE 6 19 TAKE FROM POOL: IDLE -> ACTIVE 2 1 + SuperClassic RARE 6 20 BYE 0 0 + SuperClassic RARE 3 21 BYE 0 0 + + Records affected: 76 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_ext_conn_pool_01_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/shadow/test_create_01.py b/tests/functional/shadow/test_create_01.py new file mode 100644 index 00000000..cbab248d --- /dev/null +++ b/tests/functional/shadow/test_create_01.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: functional.shadow.create_01 +# title: CREATE SHADOW +# decription: CREATE SHADOW +# +# Dependencies: +# CREATE DATABASE +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.shadow.create.create_shadow_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create shadow 1 '$(DATABASE_LOCATION)/test_defaults.shd'; + commit; + -- SHOW DATABASE -- Removed from here because this test must verify only ability to create shadow. + set list on; + set count on; + select + --right(trim(rdb$file_name), char_length('test_defaults.shd')) as file_name + iif( replace(rdb$file_name,'\\','/') containing replace('$(DATABASE_LOCATION)','','/') + and + upper(right( trim(rdb$file_name), char_length('test_defaults.shd') )) = upper('test_defaults.shd') + ,'OK' + ,'BAD: ' || rdb$file_name + ) check_shd_file_name + ,rdb$file_sequence as file_sequence + ,rdb$file_start as file_start + ,rdb$file_length as file_length + ,rdb$file_flags as file_flags + ,rdb$shadow_number as shadow_number + from rdb$files; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CHECK_SHD_FILE_NAME OK + FILE_SEQUENCE 0 + FILE_START 0 + FILE_LENGTH 0 + FILE_FLAGS 1 + SHADOW_NUMBER 1 + Records affected: 1 + """ + +@pytest.mark.version('>=3.0') +def test_create_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/shadow/test_create_02.py b/tests/functional/shadow/test_create_02.py new file mode 100644 index 00000000..f94cb188 --- /dev/null +++ b/tests/functional/shadow/test_create_02.py @@ -0,0 +1,66 @@ +#coding:utf-8 +# +# id: functional.shadow.create_02 +# title: CREATE SHADOW +# decription: CREATE SHADOW +# +# Dependencies: +# CREATE DATABASE +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.shadow.create.create_shadow_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create shadow 1 manual conditional '$(DATABASE_LOCATION)/TEST.SHD' file '$(DATABASE_LOCATION)/TEST.S00' starting at page 1000; + commit; + set list on; + set count on; + select + right(trim(rdb$file_name), char_length('test.s??')) as file_name + ,rdb$file_sequence as file_sequence + ,rdb$file_start as file_start + ,rdb$file_length as file_length + ,rdb$file_flags as file_flags + ,rdb$shadow_number as shadow_number + from rdb$files; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + FILE_NAME TEST.SHD + FILE_SEQUENCE 0 + FILE_START 0 + FILE_LENGTH 0 + FILE_FLAGS 5 + SHADOW_NUMBER 1 + + FILE_NAME TEST.S00 + FILE_SEQUENCE 1 + FILE_START 1000 + FILE_LENGTH 0 + FILE_FLAGS 5 + SHADOW_NUMBER 1 + + Records affected: 2 + """ + +@pytest.mark.version('>=3.0') +def test_create_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/syspriv/__init__.py b/tests/functional/syspriv/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/syspriv/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/syspriv/test_access_any_object.py b/tests/functional/syspriv/test_access_any_object.py new file mode 100644 index 00000000..7e040776 --- /dev/null +++ b/tests/functional/syspriv/test_access_any_object.py @@ -0,0 +1,160 @@ +#coding:utf-8 +# +# id: functional.syspriv.access_any_object +# title: Check ability to query, modify and deleting data plus add/drop constraints on any table. +# decription: +# We create two master-detail tables (under SYSDBA) and add some data to them. +# Then we connect as U01 who has system privilege to query and change (including deletion) data from ANY table. +# Under this user we first try to run DML statements (IUD) and after - to remove some old and create new +# constraint. +# +# Checked on WI-T4.0.0.267. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set wng off; + set bail on; + set list on; + + create or alter view v_check as + select + current_user as who_ami + ,r.rdb$role_name + ,rdb$role_in_use(r.rdb$role_name) as RDB_ROLE_IN_USE + ,r.rdb$system_privileges + from mon$database m cross join rdb$roles r; + commit; + grant select on v_check to public; + + recreate table tdetl( + id int, + pid int, + x int, + y int, + constraint tdetl_pk primary key(id), + constraint tdetl_x_unq unique(x), + constraint tdetl_y_gz check(y>0) + ); + recreate table tmain(id int, constraint tmain_pk primary key(id)); + commit; + + insert into tmain(id) values(1); + insert into tdetl(id, pid, x, y) values(10, 1, 111, 7); + insert into tdetl(id, pid, x, y) values(20, 1, 222, 6); + insert into tdetl(id, pid, x, y) values(30, 1, 333, 5); + commit; + + create or alter user u01 password '123' revoke admin role; + revoke all on all from u01; + commit; + + set term ^; + execute block as + begin + execute statement 'drop role role_for_ddl_dml_any_obj'; + when any do begin end + end^ + set term ;^ + commit; + + -- Add/change/delete non-system records in RDB$TYPES + create role role_for_ddl_dml_any_obj + set system privileges to + SELECT_ANY_OBJECT_IN_DATABASE, + MODIFY_ANY_OBJECT_IN_DATABASE, + ACCESS_ANY_OBJECT_IN_DATABASE; + commit; + grant default role_for_ddl_dml_any_obj to user u01; + commit; + + connect '$(DSN)' user u01 password '123'; + + select * from v_check; + commit; + + set count on; + select * from tdetl; + update tdetl set id=-id order by id desc rows 1; + delete from tdetl order by id rows 1; + commit; + + alter table tdetl + add constraint tdetl_fk foreign key(pid) references tmain using index tdetl_fk_pid + ,drop constraint tdetl_x_unq + ,drop constraint tdetl_y_gz + ,drop constraint tdetl_pk + ; + commit; + + set bail off; + insert into tdetl(id, pid, x, y) values(40, 2, null, null); -- should issue FK violation + insert into tdetl(id, pid, x, y) values(40, 1, 111, null); -- should NOT issue error + insert into tdetl(id, pid, x, y) values(40, 1, 222, -777); -- should NOT issue error + commit; + + connect '$(DSN)' user sysdba password 'masterkey'; + drop user u01; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHO_AMI U01 + RDB$ROLE_NAME RDB$ADMIN + RDB_ROLE_IN_USE + RDB$SYSTEM_PRIVILEGES FFFFFFFFFFFFFFFF + WHO_AMI U01 + RDB$ROLE_NAME ROLE_FOR_DDL_DML_ANY_OBJ + RDB_ROLE_IN_USE + RDB$SYSTEM_PRIVILEGES 0000070000000000 + ID 10 + PID 1 + X 111 + Y 7 + ID 20 + PID 1 + X 222 + Y 6 + ID 30 + PID 1 + X 333 + Y 5 + Records affected: 3 + Records affected: 1 + Records affected: 1 + Records affected: 0 + Records affected: 1 + Records affected: 1 + """ +expected_stderr_1 = """ + 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('>=4.0') +def test_access_any_object_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/syspriv/test_access_shutdown_database.py b/tests/functional/syspriv/test_access_shutdown_database.py new file mode 100644 index 00000000..74135807 --- /dev/null +++ b/tests/functional/syspriv/test_access_shutdown_database.py @@ -0,0 +1,316 @@ +#coding:utf-8 +# +# id: functional.syspriv.access_shutdown_database +# title: Check ability to access to database in shutdown single mode as non-sysdba. +# decription: +# We create role with granting system privilege ACCESS_SHUTDOWN_DATABASE to it. +# Then we create user and make this role as DEFAULT to him. +# Then we check that user U01: +# 1. can NOT CHANGE database attribute, i.e. can NOT shutdown or bring online database; +# 2. CAN make attachment to DB in 'shutdown single maintenace' mode and select smth from there. +# Also, we check that while U01 is connected, NO other attachment is possible. +# This is done by trying to make ES EDS as SYSDBA - this should fail with "335544528 : database shutdown". +# +# Checked on 4.0.0.267. See also letter from Alex 23.06.2016 11:46. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('.* access to database.*', 'access to database'), ('.* -Some database.*', ''), ('335544528 : database.* shutdown', '335544528 : database shutdown'), ('Data source : Firebird::localhost:.*', 'Data source : Firebird::localhost:'), ('-At block line: [\\d]+, col: [\\d]+', '-At block line')] + +init_script_1 = """ + set wng off; + create or alter view v_check as + select + current_user as who_ami + ,r.rdb$role_name + ,rdb$role_in_use(r.rdb$role_name) as RDB_ROLE_IN_USE + ,r.rdb$system_privileges + from mon$database m cross join rdb$roles r; + commit; + + create or alter user u01 password '123' revoke admin role; + revoke all on all from u01; + + create or alter trigger trg_connect active on connect as + begin + end; + commit; + + recreate table att_log ( + att_id int, + att_name varchar(255), + att_user varchar(255), + att_prot varchar(255) + ); + + commit; + + grant select on v_check to public; + grant all on att_log to public; + commit; + + set term ^; + execute block as + begin + execute statement 'drop role role_for_access_shutdown_db'; + when any do begin end + end + ^ + create or alter trigger trg_connect active on connect as + begin + if ( upper(current_user) <> upper('SYSDBA') ) then + in autonomous transaction do + insert into att_log(att_name, att_user, att_prot) + select + mon$attachment_name + ,mon$user + ,left(mon$remote_protocol,3) + from mon$attachments + where mon$user = current_user + ; + end + ^ + set term ;^ + commit; + + create role role_for_access_shutdown_db + set system privileges to ACCESS_SHUTDOWN_DATABASE; -- CHANGE_SHUTDOWN_MODE, USE_GFIX_UTILITY, IGNORE_DB_TRIGGERS; + commit; + grant default role_for_access_shutdown_db to user u01; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# from subprocess import Popen +# +# db_file=db_conn.database_name +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# # Change DB state to 'shutdown single maintenance': +# ################################################## +# +# f_dbshut_u01_log=open( os.path.join(context['temp_directory'],'tmp_dbshut_u01.log'), 'w') +# f_dbshut_u01_err=open( os.path.join(context['temp_directory'],'tmp_dbshut_u01.err'), 'w') +# +# # Must FAIL when we do this as non-sysdba: +# +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "user", "U01", "password", "123", +# "action_properties", +# "dbname", db_file, +# "prp_shutdown_mode", "prp_sm_single", +# "prp_force_shutdown", "0" +# ], +# stdout=f_dbshut_u01_log, +# stderr=f_dbshut_u01_err +# ) +# +# flush_and_close( f_dbshut_u01_log ) +# flush_and_close( f_dbshut_u01_err ) +# +# #------------------------------------------------- +# # Must PASS because 2nd time se do this as SYSDBA: +# +# f_dbshut_sys_log=open( os.path.join(context['temp_directory'],'tmp_dbshut_sys.log'), 'w') +# f_dbshut_sys_err=open( os.path.join(context['temp_directory'],'tmp_dbshut_sys.err'), 'w') +# +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "user", user_name, "password", user_password, +# "action_properties", +# "dbname", db_file, +# "prp_shutdown_mode", "prp_sm_single", +# "prp_force_shutdown", "0" +# ], +# stdout=f_dbshut_sys_log, +# stderr=f_dbshut_sys_err +# ) +# flush_and_close( f_dbshut_sys_log ) +# flush_and_close( f_dbshut_sys_err ) +# +# #--------------------------------------------------------------------------------------------------- +# +# sql_chk=''' +# set list on; +# set count on; +# commit; +# select v.* from v_check v; +# select m.mon$shutdown_mode from mon$database m; +# select a.att_user, att_prot from att_log a; +# set term ^; +# execute block returns( who_else_here rdb$user ) as +# declare another_user varchar(31); +# begin +# execute statement 'select current_user from rdb$database' +# on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') +# as user 'SYSDBA' password 'masterkey' +# into who_else_here; +# +# suspend; +# end +# ^ +# set term ;^ +# ''' +# +# # Check ability to connect as NON sysdba to database that is in 'shutdown single' mode (mon$shutdown_mode=2) +# ########################## +# runProgram('isql',[dsn, '-user','U01', '-pas', '123'], sql_chk) +# +# +# # Return database to online state: +# ################################## +# +# f_online_u01_log=open( os.path.join(context['temp_directory'],'tmp_online_u01.log'), 'w') +# f_online_u01_err=open( os.path.join(context['temp_directory'],'tmp_online_u01.err'), 'w') +# +# # Must FAIL when we do this as non-sysdba: +# +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "user", "U01", "password", "123", +# "action_properties", +# "dbname", db_file, +# "prp_online_mode", "prp_sm_normal" +# ], +# stdout=f_online_u01_log, +# stderr=f_online_u01_err +# ) +# flush_and_close( f_online_u01_log ) +# flush_and_close( f_online_u01_err ) +# +# #------------------------------------------------- +# # Must PASS because 2nd time se do this as SYSDBA: +# +# f_online_sys_log=open( os.path.join(context['temp_directory'],'tmp_online_sys.log'), 'w') +# f_online_sys_err=open( os.path.join(context['temp_directory'],'tmp_online_sys.err'), 'w') +# +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "user", user_name, "password", user_password, +# "action_properties", +# "dbname", db_file, +# "prp_online_mode", "prp_sm_normal" +# ], +# stdout=f_online_sys_log, +# stderr=f_online_sys_err +# ) +# +# flush_and_close( f_online_sys_log ) +# flush_and_close( f_online_sys_err ) +# +# # ------------------------------------------------------------------------ +# +# # Check: +# ######## +# +# f_list=( +# f_dbshut_u01_log, +# f_dbshut_u01_err, +# f_dbshut_sys_log, +# f_dbshut_sys_err, +# f_online_u01_log, +# f_online_u01_err, +# f_online_sys_log, +# f_online_sys_err +# ) +# +# # Only f_dbshut_u01_err and f_online_u01_err must contain single message. +# # All other files from f_list must be EMPTY: +# +# for i in range(len(f_list)): +# with open( f_list[i].name,'r') as f: +# for line in f: +# print( os.path.basename( f_list[i].name ) + ' : ' + line) +# os.remove(f_list[i].name) +# +# # cleanup: drop user 'U01' +# ########## +# runProgram('isql',[dsn, '-user', user_name, '-pas', user_password], 'drop user u01; commit;') +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHO_AMI U01 + RDB$ROLE_NAME RDB$ADMIN + RDB_ROLE_IN_USE + RDB$SYSTEM_PRIVILEGES FFFFFFFFFFFFFFFF + + WHO_AMI U01 + RDB$ROLE_NAME ROLE_FOR_ACCESS_SHUTDOWN_DB + RDB_ROLE_IN_USE + RDB$SYSTEM_PRIVILEGES 0001000000000000 + Records affected: 2 + + MON$SHUTDOWN_MODE 2 + Records affected: 1 + + ATT_USER U01 + ATT_PROT TCP + Records affected: 1 + + Records affected: 0 + + tmp_dbshut_u01.err : no permission for shutdown access to database + tmp_online_u01.err : no permission for bring online access to database + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + Execute statement error at attach : + 335544528 : database shutdown + Data source : Firebird::localhost: + -At block line: 4, col: 9 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_access_shutdown_database_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/syspriv/test_change_header_settings.py b/tests/functional/syspriv/test_change_header_settings.py new file mode 100644 index 00000000..6b4f7aa1 --- /dev/null +++ b/tests/functional/syspriv/test_change_header_settings.py @@ -0,0 +1,226 @@ +#coding:utf-8 +# +# id: functional.syspriv.change_header_settings +# title: Check ability to change some database header attributes by non-sysdba user who is granted with necessary system privileges. +# decription: +# Checked on 4.0.0.262. +# NB: attributes should be changed one at a time, i.e. one fbsvcmgr call should change only ONE atribute. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + set wng off; + set bail on; + set list on; + set count on; + + create or alter view v_check as + select + current_user as who_ami + ,r.rdb$role_name + ,rdb$role_in_use(r.rdb$role_name) as RDB_ROLE_IN_USE + ,r.rdb$system_privileges + from mon$database m cross join rdb$roles r; + commit; + + create or alter user u01 password '123' revoke admin role; + revoke all on all from u01; + + create or alter trigger trg_connect active on connect as + begin + end; + commit; + + recreate table att_log ( + att_id int, + att_name varchar(255), + att_user varchar(255), + att_addr varchar(255), + att_prot varchar(255), + att_dts timestamp default 'now' + ); + + commit; + + grant select on v_check to public; + grant all on att_log to public; + commit; + + set term ^; + execute block as + begin + execute statement 'drop role role_for_change_header_settings'; + when any do begin end + end + ^ + create or alter trigger trg_connect active on connect as + begin + if ( upper(current_user) <> upper('SYSDBA') ) then + in autonomous transaction do + insert into att_log(att_id, att_name, att_user, att_prot) + select + mon$attachment_id + ,mon$attachment_name + ,mon$user + ,mon$remote_protocol + from mon$attachments + where mon$user = current_user + ; + end + ^ + set term ;^ + commit; + + -- NB: Privilege 'IGNORE_DB_TRIGGERS' is needed when we return database to ONLINE + -- and this DB has DB-level trigger. + create role role_for_change_header_settings + set system privileges to CHANGE_HEADER_SETTINGS, USE_GFIX_UTILITY, IGNORE_DB_TRIGGERS; + commit; + grant default role_for_change_header_settings to user u01; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# +# db_file = db_conn.database_name +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# # Check that current non-sysdba user: +# # 1) can SKIP db-level trigger firing: +# # 2) IS granted with role 'role_for_change_header_settings': +# +# runProgram('isql',[dsn,'-nod','-user','U01', '-pas', '123'], 'set list on; set count on; select * from att_log; select * from v_check;') +# +# f_hdr_props_log = open( os.path.join(context['temp_directory'],'tmp_syspriv_hdr_props.log'), 'w') +# subprocess.call( [context['fbsvcmgr_path'],"localhost:service_mgr", +# "user","U01", "password", "123", +# "action_properties", +# "dbname", db_file, +# "prp_sweep_interval", "54321", +# ], +# stdout=f_hdr_props_log, +# stderr=subprocess.STDOUT +# ) +# +# subprocess.call( [context['fbsvcmgr_path'],"localhost:service_mgr", +# "user","U01", "password", "123", +# "action_properties", +# "dbname", db_file, +# "prp_set_sql_dialect", "1", +# ], +# stdout=f_hdr_props_log, +# stderr=subprocess.STDOUT +# ) +# +# subprocess.call( [context['fbsvcmgr_path'],"localhost:service_mgr", +# "user","U01", "password", "123", +# "action_properties", +# "dbname", db_file, +# "prp_write_mode", "prp_wm_async" +# ], +# stdout=f_hdr_props_log, +# stderr=subprocess.STDOUT +# ) +# +# flush_and_close( f_hdr_props_log ) +# +# # Checks +# ######## +# +# sql_chk=''' +# set list on; +# set count on; +# select m.mon$sweep_interval, m.mon$sql_dialect, m.mon$forced_writes from mon$database m; +# ''' +# runProgram('isql',[dsn,'-nod','-user','U01', '-pas', '123'], sql_chk) +# +# +# # Must be EMPTY: +# ################ +# with open( f_hdr_props_log.name,'r') as f: +# for line in f: +# print('DB SHUTDOWN LOG: '+line.upper()) +# +# +# # Cleanup: +# ########## +# cleanup( (f_hdr_props_log,) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + WHO_AMI U01 + RDB$ROLE_NAME RDB$ADMIN + RDB_ROLE_IN_USE + RDB$SYSTEM_PRIVILEGES FFFFFFFFFFFFFFFF + WHO_AMI U01 + RDB$ROLE_NAME ROLE_FOR_CHANGE_HEADER_SETTINGS + RDB_ROLE_IN_USE + RDB$SYSTEM_PRIVILEGES 00E0000000000000 + Records affected: 2 + MON$SWEEP_INTERVAL 54321 + MON$SQL_DIALECT 1 + MON$FORCED_WRITES 0 + Records affected: 1 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_change_header_settings_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/syspriv/test_change_shutdown_mode.py b/tests/functional/syspriv/test_change_shutdown_mode.py new file mode 100644 index 00000000..f3fed03a --- /dev/null +++ b/tests/functional/syspriv/test_change_shutdown_mode.py @@ -0,0 +1,225 @@ +#coding:utf-8 +# +# id: functional.syspriv.change_shutdown_mode +# title: Check ability to change database shutdown mode by non-sysdba user who is granted with necessary system privileges. +# decription: +# Checked on 4.0.0.262. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + set wng off; + set bail on; + set list on; + set count on; + + create or alter view v_check as + select + current_user as who_ami + ,r.rdb$role_name + ,rdb$role_in_use(r.rdb$role_name) as RDB_ROLE_IN_USE + ,r.rdb$system_privileges + from mon$database m cross join rdb$roles r; + commit; + + create or alter user u01 password '123' revoke admin role; + revoke all on all from u01; + + create or alter trigger trg_connect active on connect as + begin + end; + commit; + + recreate table att_log ( + att_id int, + att_name varchar(255), + att_user varchar(255), + att_addr varchar(255), + att_prot varchar(255), + att_dts timestamp default 'now' + ); + + commit; + + grant select on v_check to public; + grant all on att_log to public; + commit; + + set term ^; + execute block as + begin + execute statement 'drop role role_for_change_shutdown_mode'; + when any do begin end + end + ^ + create or alter trigger trg_connect active on connect as + begin + if ( upper(current_user) <> upper('SYSDBA') ) then + in autonomous transaction do + insert into att_log(att_id, att_name, att_user, att_prot) + select + mon$attachment_id + ,mon$attachment_name + ,mon$user + ,mon$remote_protocol + from mon$attachments + where mon$user = current_user + ; + end + ^ + set term ;^ + commit; + + -- Shutdown DB and bring online + -- Add/change/delete non-system records in RDB$TYPES. + -- NB: Privilege 'IGNORE_DB_TRIGGERS' is needed when we return database to ONLINE + -- and this DB has DB-level trigger. + create role role_for_change_shutdown_mode + set system privileges to CHANGE_SHUTDOWN_MODE, USE_GFIX_UTILITY, IGNORE_DB_TRIGGERS; + commit; + grant default role_for_change_shutdown_mode to user u01; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# +# db_file = db_conn.database_name +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# # Check that current non-sysdba user: +# # 1) can SKIP db-level trigger firing: +# # 2) IS granted with role 'role_for_change_shutdown_mode': +# +# runProgram('isql',[dsn,'-nod','-user','U01', '-pas', '123'], 'set list on; set count on; select * from att_log; select * from v_check;') +# +# f_shutdown_log = open( os.path.join(context['temp_directory'],'tmp_syspriv_dbshut.log'), 'w') +# subprocess.call( [context['fbsvcmgr_path'],"localhost:service_mgr", +# "user","U01", "password", "123", +# "action_properties", +# "dbname", db_file, +# "prp_shutdown_mode", "prp_sm_full", "prp_force_shutdown", "0" +# ], +# stdout=f_shutdown_log, +# stderr=subprocess.STDOUT +# ) +# flush_and_close( f_shutdown_log ) +# +# f_dbheader_log = open( os.path.join(context['temp_directory'],'tmp_syspriv_dbhead.log'), 'w') +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "user", "U01", "password" , "123", +# "action_db_stats", "sts_hdr_pages", +# "dbname", db_file +# ], +# stdout=f_dbheader_log, +# stderr=subprocess.STDOUT +# ) +# flush_and_close( f_dbheader_log ) +# +# f_ret2online_log = open( os.path.join(context['temp_directory'],'tmp_syspriv_dbonline.log'), 'w') +# subprocess.call( [context['fbsvcmgr_path'], "localhost:service_mgr", +# "user","U01", "password", "123", +# "action_properties", "prp_db_online", +# "dbname", db_file, +# ], +# stdout = f_ret2online_log, +# stderr = subprocess.STDOUT +# ) +# flush_and_close( f_ret2online_log ) +# +# # Must be EMPTY: +# with open( f_shutdown_log.name,'r') as f: +# for line in f: +# print('DB SHUTDOWN LOG: '+line.upper()) +# +# +# # Must contain: "Attributes force write, full shutdown" +# with open( f_dbheader_log.name,'r') as f: +# for line in f: +# if 'Attributes' in line: +# print('DB HEADER: ' + ' '.join(line.split()).upper() ) +# +# +# # Must be EMPTY: +# with open( f_ret2online_log.name,'r') as f: +# for line in f: +# print('DB ONLINE LOG: '+line.upper()) +# +# +# # Cleanup: +# ########## +# cleanup( (f_shutdown_log, f_dbheader_log, f_ret2online_log) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + WHO_AMI U01 + RDB$ROLE_NAME RDB$ADMIN + RDB_ROLE_IN_USE + RDB$SYSTEM_PRIVILEGES FFFFFFFFFFFFFFFF + WHO_AMI U01 + RDB$ROLE_NAME ROLE_FOR_CHANGE_SHUTDOWN_MODE + RDB_ROLE_IN_USE + RDB$SYSTEM_PRIVILEGES 2060000000000000 + Records affected: 2 + DB HEADER: ATTRIBUTES FORCE WRITE, FULL SHUTDOWN + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_change_shutdown_mode_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/syspriv/test_create_privileged_roles.py b/tests/functional/syspriv/test_create_privileged_roles.py new file mode 100644 index 00000000..3ab100b6 --- /dev/null +++ b/tests/functional/syspriv/test_create_privileged_roles.py @@ -0,0 +1,97 @@ +#coding:utf-8 +# +# id: functional.syspriv.create_privileged_roles +# title: Check ability of non-sysdba user to CREATE privileged role (but NOT use it) +# decription: +# Checked on WI-T4.0.0.267. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set wng off; + set bail on; + set list on; + + + create or alter user u01 password '123' revoke admin role; + revoke all on all from u01; + grant create role to u01; + commit; + + set term ^; + execute block as + begin + begin + execute statement 'drop role role_for_CREATE_PRIVILEGED_ROLES'; + when any do begin end + end + begin + execute statement 'drop role role_for_USE_GRANTED_BY_CLAUSE'; + when any do begin end + end + end^ + set term ;^ + commit; + + create role role_for_CREATE_PRIVILEGED_ROLES set system privileges to CREATE_PRIVILEGED_ROLES; + commit; + grant default role_for_CREATE_PRIVILEGED_ROLES to user u01; + commit; + + connect '$(DSN)' user u01 password '123'; + + -- Here we check that U01 can CREATE privileged role but this is the ONLY what he can do, + -- i.e. he is NOT granted with this role! + create role role_for_USE_GRANTED_BY_CLAUSE SET SYSTEM PRIVILEGES TO USE_GRANTED_BY_CLAUSE; + commit; + + select current_user as who_am_i,r.rdb$role_name,rdb$role_in_use(r.rdb$role_name),r.rdb$system_privileges + from mon$database m cross join rdb$roles r; + + commit; + + connect '$(DSN)' user sysdba password 'masterkey'; + drop user u01; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHO_AM_I U01 + RDB$ROLE_NAME RDB$ADMIN + RDB$ROLE_IN_USE + RDB$SYSTEM_PRIVILEGES FFFFFFFFFFFFFFFF + + WHO_AM_I U01 + RDB$ROLE_NAME ROLE_FOR_CREATE_PRIVILEGED_ROLES + RDB$ROLE_IN_USE + RDB$SYSTEM_PRIVILEGES 0000800000000000 + + WHO_AM_I U01 + RDB$ROLE_NAME ROLE_FOR_USE_GRANTED_BY_CLAUSE + RDB$ROLE_IN_USE + RDB$SYSTEM_PRIVILEGES 0000100000000000 + """ + +@pytest.mark.version('>=4.0') +def test_create_privileged_roles_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/syspriv/test_create_user_types.py b/tests/functional/syspriv/test_create_user_types.py new file mode 100644 index 00000000..0732043a --- /dev/null +++ b/tests/functional/syspriv/test_create_user_types.py @@ -0,0 +1,151 @@ +#coding:utf-8 +# +# id: functional.syspriv.create_user_types +# title: Check ability to update content of RDB$TYPES. +# decription: +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('RDB\\$DESCRIPTION.*', 'RDB$DESCRIPTION')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set wng off; + set list on; + set count on; + + create or alter view v_check as + select + current_user as who_ami + ,r.rdb$role_name + ,rdb$role_in_use(r.rdb$role_name) as RDB_ROLE_IN_USE + ,r.rdb$system_privileges + from mon$database m cross join rdb$roles r; + commit; + grant select on v_check to public; + commit; + + create or alter user u01 password '123' revoke admin role; + revoke all on all from u01; + commit; + + set term ^; + execute block as + begin + execute statement 'drop role role_for_create_user_types'; + when any do begin end + end^ + set term ;^ + commit; + + -- Add/change/delete non-system records in RDB$TYPES + create role role_for_create_user_types set system privileges to CREATE_USER_TYPES; + commit; + grant default role_for_create_user_types to user u01; + commit; + + connect '$(DSN)' user u01 password '123'; + select * from v_check; + commit; + + --set echo on; + + insert into rdb$types(rdb$field_name, rdb$type, rdb$type_name, rdb$description, rdb$system_flag) + values( 'amount_avaliable', + -32767, + 'stock_amount', + 'Total number of units that can be sold immediately to any customer', + 0 -- rdb$system_flag + ) + returning rdb$field_name, rdb$type, rdb$type_name, rdb$description, rdb$system_flag + ; + + insert into rdb$types(rdb$field_name, rdb$type, rdb$type_name, rdb$description, rdb$system_flag) + values( 'amount_ion_reserve', + -2, + 'stock_amount', + 'Total number of units that is to be sold for customers who previously did order them', + 1 -- rdb$system_flag + ); + + update rdb$types set rdb$type = -32768, rdb$field_name = null + where rdb$type < 0 + order by rdb$type + rows 1 + returning rdb$field_name, rdb$type, rdb$type_name, rdb$description, rdb$system_flag; + + delete from rdb$types where rdb$type < 0 + returning rdb$field_name, rdb$type, rdb$type_name, + -- rdb$description, -- TODO: uncomment this after core-5287 will be fixed + rdb$system_flag + ; + commit; + + connect '$(DSN)' user sysdba password 'masterkey'; + drop user u01; + drop role role_for_create_user_types; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHO_AMI U01 + RDB$ROLE_NAME RDB$ADMIN + RDB_ROLE_IN_USE + RDB$SYSTEM_PRIVILEGES FFFFFFFFFFFFFFFF + + WHO_AMI U01 + RDB$ROLE_NAME ROLE_FOR_CREATE_USER_TYPES + RDB_ROLE_IN_USE + RDB$SYSTEM_PRIVILEGES 0800000000000000 + + Records affected: 2 + + RDB$FIELD_NAME amount_avaliable + RDB$TYPE -32767 + RDB$TYPE_NAME stock_amount + RDB$DESCRIPTION b:782 + Total number of units that can be sold immediately to any customer + RDB$SYSTEM_FLAG 0 + + Records affected: 0 + + RDB$FIELD_NAME + RDB$TYPE -32768 + RDB$TYPE_NAME stock_amount + RDB$DESCRIPTION b:782 + Total number of units that can be sold immediately to any customer + RDB$SYSTEM_FLAG 0 + + + RDB$FIELD_NAME + RDB$TYPE -32768 + RDB$TYPE_NAME stock_amount + RDB$SYSTEM_FLAG 0 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + INSERT operation is not allowed for system table RDB$TYPES + """ + +@pytest.mark.version('>=4.0') +def test_create_user_types_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/syspriv/test_drop_database.py b/tests/functional/syspriv/test_drop_database.py new file mode 100644 index 00000000..f1add9d9 --- /dev/null +++ b/tests/functional/syspriv/test_drop_database.py @@ -0,0 +1,179 @@ +#coding:utf-8 +# +# id: functional.syspriv.drop_database +# title: Check ability to DROP database by non-sysdba user who is granted with necessary system privileges. +# decription: +# We make backup and restore of current DB to other name ('functional.syspriv.drop_database.tmp'). +# Than we attach to DB 'functional.syspriv.drop_database.tmp' as user U01 and try to DROP it. +# This should NOT raise any error, database file should be deleted from disk. +# +# Checked on 4.0.0.267. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('DB_NAME.*FUNCTIONAL.SYSPRIV.DROP_DATABASE.TMP', 'DB_NAME FUNCTIONAL.SYSPRIV.DROP_DATABASE.TMP')] + +init_script_1 = """ + set wng off; + set bail on; + set list on; + set count on; + + create or alter view v_check as + select + upper(mon$database_name) as db_name + ,current_user as who_ami + ,r.rdb$role_name + ,rdb$role_in_use(r.rdb$role_name) as RDB_ROLE_IN_USE + ,r.rdb$system_privileges + from mon$database m cross join rdb$roles r; + commit; + + grant select on v_check to public; + commit; + + create or alter user u01 password '123' revoke admin role; + revoke all on all from u01; + commit; + + set term ^; + execute block as + begin + execute statement 'drop role role_for_drop_this_database'; + when any do begin end + end^ + set term ;^ + commit; + + create role role_for_drop_this_database set system privileges to DROP_DATABASE; + commit; + grant default role_for_drop_this_database to user u01; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import time +# +# db_pref = os.path.splitext(db_conn.database_name)[0] +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# fdb_this = db_pref+'.fdb' +# fbk_name = db_pref+'.fbk' +# fdb_test = db_pref+'.tmp' +# +# f_backup_restore=open( os.path.join(context['temp_directory'],'tmp_drop_db_backup_restore.log'), 'w') +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "user","SYSDBA","password","masterkey", +# "action_backup", +# "dbname", fdb_this, +# "bkp_file", fbk_name, +# "verbose"], +# stdout=f_backup_restore, +# stderr=subprocess.STDOUT +# ) +# +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "user","SYSDBA","password","masterkey", +# "action_restore", "res_replace", +# "verbose", +# "bkp_file", fbk_name, +# "dbname", fdb_test], +# stdout=f_backup_restore, +# stderr=subprocess.STDOUT +# ) +# flush_and_close( f_backup_restore ) +# +# +# # Check that non-sysdba user can connect and DROP database +# ####### +# sql_chk=''' +# set list on; +# set count on; +# select * from v_check; +# commit; +# drop database; +# ''' +# +# runProgram('isql',['localhost:'+fdb_test,'-user','U01', '-pas', '123'], sql_chk) +# +# if os.path.isfile(fdb_test): +# print('ERROR WHILE DROP DATABASE: FILE REMAINS ON DISK!') +# +# # Cleanup: +# ########## +# time.sleep(1) +# cleanup( (fbk_name, fdb_test, f_backup_restore) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + DB_NAME FUNCTIONAL.SYSPRIV.DROP_DATABASE.TMP + WHO_AMI U01 + RDB$ROLE_NAME RDB$ADMIN + RDB_ROLE_IN_USE + RDB$SYSTEM_PRIVILEGES FFFFFFFFFFFFFFFF + + DB_NAME FUNCTIONAL.SYSPRIV.DROP_DATABASE.TMP + WHO_AMI U01 + RDB$ROLE_NAME ROLE_FOR_DROP_THIS_DATABASE + RDB_ROLE_IN_USE + RDB$SYSTEM_PRIVILEGES 0004000000000000 + Records affected: 2 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_drop_database_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/syspriv/test_grant_revoke_any_object.py b/tests/functional/syspriv/test_grant_revoke_any_object.py new file mode 100644 index 00000000..6b9d653e --- /dev/null +++ b/tests/functional/syspriv/test_grant_revoke_any_object.py @@ -0,0 +1,139 @@ +#coding:utf-8 +# +# id: functional.syspriv.grant_revoke_any_object +# title: Check ability to query, modify and deleting data plus add/drop constraints on any table. +# decription: +# Two users are created, U01 and U02. +# User U01 is granted with system privilege grant_revoke_any_object. +# User U02 has NO any privilege. +# User U01 then creates table and issue GRANT SELECT statement for U02 (WITHOUT using 'granted by clause). +# Then we +# 1) check result (contrent of RDB$ tables) +# 2) connect as U02 and query this table - this should work OK +# 3) connect as U01 and revoke grant on just queried table from U02 +# 4) connect again as U02 and repeat select - this shoiuld fail. +# +# Checked on WI-T4.0.0.267. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set wng off; + set bail on; + set list on; + + + create or alter user u01 password '123' revoke admin role; + create or alter user u02 password '456' revoke admin role; + revoke all on all from u01; + revoke all on all from u02; + grant create table to u01; + commit; + + set term ^; + execute block as + begin + execute statement 'drop role role_for_grant_revoke_any_object'; + when any do begin end + end^ + set term ;^ + commit; + + -- Add/change/delete non-system records in RDB$TYPES + create role role_for_grant_revoke_any_object set system privileges to GRANT_REVOKE_ON_ANY_OBJECT; + commit; + grant default role_for_grant_revoke_any_object to user u01; + commit; + + connect '$(DSN)' user u01 password '123'; + select current_user as who_am_i,r.rdb$role_name,rdb$role_in_use(r.rdb$role_name),r.rdb$system_privileges + from mon$database m cross join rdb$roles r; + commit; + + recreate table test_u01(id int, who_is_author varchar(31) default current_user); + commit; + insert into test_u01(id) values(1); + commit; + + grant select on table test_u01 to u02; -- nb: do NOT add here "granted by sysdba"! + commit; + + -- this should give output with rdb$grantor = 'SYSDBA' despite that actual grantor was 'U01': + select * from rdb$user_privileges where rdb$relation_name=upper('test_u01') and rdb$user=upper('u02'); + commit; + + connect '$(DSN)' user u02 password '456'; + select current_user as who_am_i, u.* from test_u01 u; + commit; + + connect '$(DSN)' user u01 password '123'; + revoke select on test_u01 from u02; + commit; + + set bail off; + connect '$(DSN)' user u02 password '456'; + select current_user as who_am_i, u.* from test_u01 u; -- this should FAIL + commit; + set bail on; + + connect '$(DSN)' user sysdba password 'masterkey'; + drop user u01; + drop user u02; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHO_AM_I U01 + RDB$ROLE_NAME RDB$ADMIN + RDB$ROLE_IN_USE + RDB$SYSTEM_PRIVILEGES FFFFFFFFFFFFFFFF + + WHO_AM_I U01 + RDB$ROLE_NAME ROLE_FOR_GRANT_REVOKE_ANY_OBJECT + RDB$ROLE_IN_USE + RDB$SYSTEM_PRIVILEGES 0000200000000000 + + RDB$USER U02 + RDB$GRANTOR U01 + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME TEST_U01 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + WHO_AM_I U02 + ID 1 + WHO_IS_AUTHOR U01 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE TEST_U01 + -Effective user is U02 + """ + +@pytest.mark.version('>=4.0') +def test_grant_revoke_any_object_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/syspriv/test_monitor_any_attachment.py b/tests/functional/syspriv/test_monitor_any_attachment.py new file mode 100644 index 00000000..15d916c1 --- /dev/null +++ b/tests/functional/syspriv/test_monitor_any_attachment.py @@ -0,0 +1,157 @@ +#coding:utf-8 +# +# id: functional.syspriv.monitor_any_attachment +# title: Check ability to monitor any attachment. +# decription: +# Checked: +# 4.0.0.1635 SS: 1.497s. +# 4.0.0.1633 CS: 2.024s. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set wng off; + set bail on; + set list on; + set count on; + + create or alter view v_check as + select + current_user as who_ami + ,r.rdb$role_name + ,rdb$role_in_use(r.rdb$role_name) as RDB_ROLE_IN_USE + ,r.rdb$system_privileges + from mon$database m cross join rdb$roles r; + commit; + + create or alter user u01 password '123' revoke admin role; + revoke all on all from u01; + commit; + + grant select on v_check to public; + commit; + + set term ^; + execute block as + begin + execute statement 'drop role role_for_monitor_any_attach'; + when any do begin end + end + ^ + set term ;^ + commit; + + -- Monitor (via MON$ tables) attachments from other users: + create role role_for_monitor_any_attach + set system privileges to MONITOR_ANY_ATTACHMENT; + commit; + grant default role_for_monitor_any_attach to user u01; + commit; + + connect '$(DSN)' user u01 password '123'; + commit; + select * from v_check; + commit; + + set term ^; + execute block returns( + who_am_i rdb$user, + who_else_here rdb$user, + what_he_is_doing varchar(250) + ) as + declare another_user varchar(31); + declare v_other_sttm varchar(40); + begin + v_other_sttm = 'select current_user from rdb$database'; + + execute statement (v_other_sttm) + on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') + as user 'SYSDBA' password 'masterkey' + into another_user; + + for + select + current_user, + a.mon$user, + s.mon$sql_text + from mon$attachments a + join mon$statements s using(mon$attachment_id) + where + a.mon$user<>current_user + and a.mon$system_flag is distinct from 1 + -- NB: for Classic 4.0 we should prevent output from: + -- SELECT + -- RDB$MAP_USING, RDB$MAP_PLUGIN, RDB$MAP_DB, + -- RDB$MAP_FROM_TYPE, RDB$MAP_FROM, RDB$MAP_TO_TYPE, RDB$MAP_TO + -- FROM RDB$AUTH_MAPPING + -- -- so we add filter on s.mon$sql_text: + and s.mon$sql_text containing :v_other_sttm + into who_am_i, who_else_here, what_he_is_doing + do + suspend; + end + ^ + set term ;^ + commit; + set count off; + + connect '$(DSN)' user sysdba password 'masterkey'; + + -- |||||||||||||||||||||||||||| + -- ###################################||| 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; + + drop user u01; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHO_AMI U01 + RDB$ROLE_NAME RDB$ADMIN + RDB_ROLE_IN_USE + RDB$SYSTEM_PRIVILEGES FFFFFFFFFFFFFFFF + WHO_AMI U01 + RDB$ROLE_NAME ROLE_FOR_MONITOR_ANY_ATTACH + RDB_ROLE_IN_USE + RDB$SYSTEM_PRIVILEGES 8000000000000000 + Records affected: 2 + WHO_AM_I U01 + WHO_ELSE_HERE SYSDBA + WHAT_HE_IS_DOING select current_user from rdb$database + Records affected: 1 + """ + +@pytest.mark.version('>=4.0') +def test_monitor_any_attachment_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/syspriv/test_trace_any_attachment.py b/tests/functional/syspriv/test_trace_any_attachment.py new file mode 100644 index 00000000..f29becda --- /dev/null +++ b/tests/functional/syspriv/test_trace_any_attachment.py @@ -0,0 +1,215 @@ +#coding:utf-8 +# +# id: functional.syspriv.trace_any_attachment +# title: Check ability to trace any attachment by non-sysdba user who is granted with necessary system privileges. +# decription: +# Checked on 4.0.0.262. +# 03-mar-2021. Checked on: +# * Windows: 4.0.0.2377, 3.0.8.33420 +# * Linux: 4.0.0.2377, 3.0.8.33415 +# +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + set wng off; + set bail on; + create or alter user sys_tracer_for_anyone password '123' revoke admin role; + revoke all on all from sys_tracer_for_anyone; + commit; + -- Trace other users' attachments + create role role_for_trace_any_attachment + set system privileges to TRACE_ANY_ATTACHMENT; + commit; + grant default role_for_trace_any_attachment to user sys_tracer_for_anyone; + commit; + + recreate table test_trace_any_attachment(id int); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# from subprocess import Popen +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_file=os.path.basename(db_conn.database_name) +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# trace_options = '''# Trace config, format for 3.0 and above. Generated auto, do not edit! +# database=%%[\\\\\\\\/]%(db_file)s +# { +# enabled = true +# log_initfini = false +# log_errors = true +# time_threshold = 0 +# log_statement_start = true +# log_statement_finish = true +# print_perf = true +# max_sql_length = 16384 +# } +# ''' % locals() +# +# f_trccfg=open( os.path.join(context['temp_directory'],'tmp_syspriv_trace_any_attacmhent.cfg'), 'w') +# f_trccfg.write(trace_options) +# flush_and_close( f_trccfg ) +# +# # Starting trace session in new child process (async.): +# ####################################################### +# +# f_trclog=open( os.path.join(context['temp_directory'],'tmp_syspriv_trace_any_attacmhent.log'), 'w') +# f_trcerr=open( os.path.join(context['temp_directory'],'tmp_syspriv_trace_any_attacmhent.err'), 'w') +# +# # Execute a child program in a new process, redirecting STDERR to the same target as of STDOUT: +# p_trace=Popen([context['fbsvcmgr_path'], "localhost:service_mgr", +# "user", "sys_tracer_for_anyone", "password", "123", +# "action_trace_start", +# "trc_cfg", f_trccfg.name], +# stdout=f_trclog, +# stderr=f_trcerr +# ) +# +# +# time.sleep(1) +# +# ##################################################### +# # Getting ID of launched trace session and STOP it: +# +# # Save active trace session info into file for further parsing it and obtain session_id back (for stop): +# f_trclst=open( os.path.join(context['temp_directory'],'tmp_trace_5273.lst'), 'w') +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "user", "sys_tracer_for_anyone", "password", "123", +# "action_trace_list"], +# stdout=f_trclst, +# stderr=subprocess.STDOUT +# ) +# flush_and_close( f_trclst ) +# +# trcssn=0 +# with open( f_trclst.name,'r') as f: +# for line in f: +# i=1 +# if 'Session ID' in line: +# for word in line.split(): +# if i==3: +# trcssn=word +# i=i+1 +# break +# +# # Result: `trcssn` is ID of active trace session. Now we have to terminate it: +# +# runProgram('isql',[dsn, '-q', '-n'], 'insert into test_trace_any_attachment(id) values(123456789);') +# time.sleep(1) +# +# # REQUEST TRACE TO STOP: +# ######################## +# f_trclst=open(f_trclst.name,'a') +# f_trclst.seek(0,2) +# subprocess.call([context['fbsvcmgr_path'], "localhost:service_mgr", +# "user", "sys_tracer_for_anyone", "password", "123", +# "action_trace_stop", +# "trc_id",trcssn], +# stdout=f_trclst, stderr=subprocess.STDOUT +# ) +# flush_and_close( f_trclst ) +# +# time.sleep(2) +# +# # Terminate child process of launched trace session (though it should already be killed): +# p_trace.terminate() +# flush_and_close( f_trclog ) +# flush_and_close( f_trcerr ) +# +# +# # Must be EMPTY: +# with open( f_trcerr.name,'r') as f: +# for line in f: +# print(line) +# +# # Must contain info about SYSDBA activity (this was traced by non-sysdba user): +# +# found_sysdba_attachment, found_sysdba_statement = False, False +# with open( f_trclog.name,'r') as f: +# for line in f: +# if 'SYSDBA:NONE' in line: +# if not found_sysdba_attachment: +# print('FOUND SYSDBA ATTACHMENT.') +# found_sysdba_attachment = True +# if '123456789' in line: +# if not found_sysdba_statement: +# print('FOUND SYSDBA STATEMENT.') +# found_sysdba_statement = True +# +# runProgram('isql',[dsn], 'drop user sys_tracer_for_anyone;') +# +# # Cleanup: +# ########## +# time.sleep(1) +# cleanup( (f_trclst,f_trcerr,f_trclog, f_trccfg) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + FOUND SYSDBA ATTACHMENT. + FOUND SYSDBA STATEMENT. + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_trace_any_attachment_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/syspriv/test_use_gbak_utility.py b/tests/functional/syspriv/test_use_gbak_utility.py new file mode 100644 index 00000000..16de950a --- /dev/null +++ b/tests/functional/syspriv/test_use_gbak_utility.py @@ -0,0 +1,272 @@ +#coding:utf-8 +# +# id: functional.syspriv.use_gbak_utility +# title: Check ability to to make database backup. +# decription: +# We create user and grant system privileges USE_GBAK_UTILITY, SELECT_ANY_OBJECT_IN_DATABASE to him +# (but revoke all other rights), and then we try to make BACKUP with attaching to database as this user (U01). +# Then we check that this user: +# 1) can NOT restore .fbk to another file name (backup <> restore!) +# 2) CAN query to the table which is not granted to him by regular GRANT statement +# (restoring is done by SYSDBA). +# +# Checked on 4.0.0.267. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('.*NO PERMISSION FOR CREATE ACCESS TO DATABASE.*', 'NO PERMISSION FOR CREATE ACCESS TO DATABASE'), ('.*-FAILED TO CREATE DATABASE.*', '-FAILED TO CREATE DATABASE'), ('CLOSING FILE, COMMITTING, AND FINISHING.*', 'CLOSING FILE, COMMITTING, AND FINISHING'), ('DB_NAME.*FUNCTIONAL.SYSPRIV.USE_GBAK_UTILITY.TMP', 'DB_NAME FUNCTIONAL.SYSPRIV.USE_GBAK_UTILITY.TMP'), ('BLOB_ID.*', '')] + +init_script_1 = """ + set wng off; + set bail on; + set list on; + set count on; + + create or alter view v_check as + select + upper(mon$database_name) as db_name + ,current_user as who_ami + ,r.rdb$role_name + ,rdb$role_in_use(r.rdb$role_name) as RDB_ROLE_IN_USE + ,r.rdb$system_privileges + from mon$database m cross join rdb$roles r; + commit; + + create or alter user u01 password '123' revoke admin role; + revoke all on all from u01; + commit; + + recreate table test(x int, b blob); + commit; + + insert into test values(1, upper('qwertyuioplkjhgfdsazxcvbnm') ); + commit; + + grant select on v_check to public; + --------------------------------- [ !! ] -- do NOT: grant select on test to u01; -- [ !! ] + commit; + + set term ^; + execute block as + begin + execute statement 'drop role role_for_use_gbak_utility'; + when any do begin end + end + ^ + set term ;^ + commit; + + -- Ability to make database backup. + -- NB: SELECT_ANY_OBJECT_IN_DATABASE - mandatory for reading data from tables et al. + create role role_for_use_gbak_utility + set system privileges to USE_GBAK_UTILITY, SELECT_ANY_OBJECT_IN_DATABASE; + commit; + grant default role_for_use_gbak_utility to user u01; + commit; + + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# +# db_pref = os.path.splitext(db_conn.database_name)[0] +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# fdb_this = db_pref+'.fdb' +# fbk_name = db_pref+'.fbk' +# fdb_test = db_pref+'.tmp' +# +# # !!! NB !!! See CORE-5291. We have to remove file that will be used as target for restoring, +# # otherwise error msg will contain strange phrase "gbak: ERROR:could not drop ... (database might be in use)" +# cleanup( (fdb_test,) ) +# +# f_backup_u01_log=open( os.path.join(context['temp_directory'],'tmp_backup_u01.log'), 'w') +# f_backup_u01_err=open( os.path.join(context['temp_directory'],'tmp_backup_u01.err'), 'w') +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "user","U01","password","123", +# "action_backup", +# "dbname", fdb_this, +# "bkp_file", fbk_name, +# "verbose"], +# stdout=f_backup_u01_log, +# stderr=f_backup_u01_err +# ) +# +# flush_and_close( f_backup_u01_log ) +# flush_and_close( f_backup_u01_err ) +# +# # NB: user U01 has right only to make BACKUP, but has NO right for RESTORING database +# # (to restore he has to be granted with system privilege CREATE_DATABASE). +# # Thus following attempt should be finished with ERROR: +# # === +# # gbak: ERROR:no permission for CREATE access to DATABASE C:\\MIX\\FIREBIRD\\QA\\FBT-REPO\\TMP\\TMP.TMP +# # gbak: ERROR:failed to create database localhost/3400:C:\\MIX +# irebird\\QA +# bt-repo mp mp.tmp +# # gbak:Exiting before completion due to errors +# # === +# +# f_restore_u01_log=open( os.path.join(context['temp_directory'],'tmp_restore_u01.log'), 'w') +# f_restore_u01_err=open( os.path.join(context['temp_directory'],'tmp_restore_u01.err'), 'w') +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "user","U01","password","123", +# "action_restore", "res_replace", +# "verbose", +# "bkp_file", fbk_name, +# "dbname", fdb_test], +# stdout=f_restore_u01_log, +# stderr=f_restore_u01_err +# ) +# flush_and_close( f_restore_u01_log ) +# flush_and_close( f_restore_u01_err ) +# +# +# # Now try to restore as SYSDBA and then check that U01 will be able +# # to connect to this DB and run query on table TEST: +# +# f_restore_sys_log=open( os.path.join(context['temp_directory'],'tmp_restore_sys.log'), 'w') +# f_restore_sys_err=open( os.path.join(context['temp_directory'],'tmp_restore_sys.err'), 'w') +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "user", user_name, "password", user_password, +# "action_restore", "res_replace", +# "verbose", +# "bkp_file", fbk_name, +# "dbname", fdb_test], +# stdout=f_restore_sys_log, +# stderr=f_restore_sys_err +# ) +# flush_and_close( f_restore_sys_log ) +# flush_and_close( f_restore_sys_err ) +# +# +# # Check content of logs. +# +# # Must be EMPTY: +# with open( f_backup_u01_err.name,'r') as f: +# for line in f: +# print('U01 BACKUP STDERR: '+line.upper()) +# +# # Must contain: "closing file, committing, and finishing" +# with open( f_backup_u01_log.name,'r') as f: +# for line in f: +# if 'closing file' in line: +# print('U01 BACKUP STDLOG: ' + ' '.join(line.split()).upper() ) +# +# +# # Must contain errors: +# # no permission for CREATE access to DATABASE C:/MIX/firebird/QA/fbt-repo/tmp/functional.syspriv.use_gbak_utility.tmp +# # -failed to create database C:/MIX/firebird/QA/fbt-repo/tmp/functional.syspriv.use_gbak_utility.tmp +# # -Exiting before completion due to errors +# with open( f_restore_u01_err.name,'r') as f: +# for line in f: +# print('U01 RESTORE STDERR: ' + ' '.join(line.split()).upper() ) +# +# # Must contain: "finishing, closing, and going home " +# with open( f_restore_sys_log.name,'r') as f: +# for line in f: +# if 'going home' in line: +# print('SYSDBA RESTORE STDLOG: ' + ' '.join(line.split()).upper() ) +# +# # Must be EMPTY: +# with open( f_restore_sys_err.name,'r') as f: +# for line in f: +# print('SYSDBA RESTORE STDERR: '+line.upper()) +# +# # Check that non-sysdba user can connect and query table 'test': +# ####### +# sql_chk=''' +# set list on; +# set count on; +# set blob all; +# select * from v_check; +# select x,b as blob_id from test; +# commit; +# ''' +# +# runProgram('isql',['localhost:'+fdb_test,'-user','U01', '-pas', '123'], sql_chk) +# +# # Cleanup: +# ########## +# runProgram('isql',[dsn,'-user',user_name, '-pas', user_password], 'drop user u01; commit;') +# cleanup( (fbk_name, fdb_test, f_backup_u01_log,f_backup_u01_err,f_restore_u01_log,f_restore_u01_err,f_restore_sys_log,f_restore_sys_err) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + U01 BACKUP STDLOG: GBAK:CLOSING FILE, COMMITTING, AND FINISHING + U01 RESTORE STDERR: NO PERMISSION FOR CREATE ACCESS TO DATABASE + U01 RESTORE STDERR: -FAILED TO CREATE DATABASE + U01 RESTORE STDERR: -EXITING BEFORE COMPLETION DUE TO ERRORS + SYSDBA RESTORE STDLOG: GBAK:FINISHING, CLOSING, AND GOING HOME + + DB_NAME FUNCTIONAL.SYSPRIV.USE_GBAK_UTILITY.TMP + WHO_AMI U01 + RDB$ROLE_NAME RDB$ADMIN + RDB_ROLE_IN_USE + RDB$SYSTEM_PRIVILEGES FFFFFFFFFFFFFFFF + DB_NAME FUNCTIONAL.SYSPRIV.USE_GBAK_UTILITY.TMP + WHO_AMI U01 + RDB$ROLE_NAME ROLE_FOR_USE_GBAK_UTILITY + RDB_ROLE_IN_USE + RDB$SYSTEM_PRIVILEGES 0008010000000000 + Records affected: 2 + X 1 + QWERTYUIOPLKJHGFDSAZXCVBNM + Records affected: 1 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_use_gbak_utility_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/syspriv/test_use_granted_by_clause.py b/tests/functional/syspriv/test_use_granted_by_clause.py new file mode 100644 index 00000000..e5f52518 --- /dev/null +++ b/tests/functional/syspriv/test_use_granted_by_clause.py @@ -0,0 +1,139 @@ +#coding:utf-8 +# +# id: functional.syspriv.use_granted_by_clause +# title: Check ability to query, modify and deleting data plus add/drop constraints on any table. +# decription: +# Two users are created, U01 and U02. +# User U01 is granted with system privilege USE_GRANTED_BY_CLAUSE. +# User U02 has NO any privilege. +# User U01 then creates table and issue GRANT SELECT statement for U02 as it was granted by SYSDBA. +# Then we +# 1) check result (contrent of RDB$ tables) +# 2) connect as U02 and query this table - this should work OK +# 3) connect as U01 and revoke grant on just queried table from U02 +# 4) connect again as U02 and repeat select - this shoiuld fail. +# +# Checked on WI-T4.0.0.267. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set wng off; + set bail on; + set list on; + + + create or alter user u01 password '123' revoke admin role; + create or alter user u02 password '456' revoke admin role; + revoke all on all from u01; + revoke all on all from u02; + grant create table to u01; + commit; + + set term ^; + execute block as + begin + execute statement 'drop role role_for_use_granted_by_clause'; + when any do begin end + end^ + set term ;^ + commit; + + -- Add/change/delete non-system records in RDB$TYPES + create role role_for_use_granted_by_clause set system privileges to USE_GRANTED_BY_CLAUSE; + commit; + grant default role_for_use_granted_by_clause to user u01; + commit; + + connect '$(DSN)' user u01 password '123'; + select current_user as who_am_i,r.rdb$role_name,rdb$role_in_use(r.rdb$role_name),r.rdb$system_privileges + from mon$database m cross join rdb$roles r; + commit; + + recreate table test_u01(id int, who_is_author varchar(31) default current_user); + commit; + insert into test_u01(id) values(1); + commit; + + grant select on table test_u01 to u02 granted by sysdba; + commit; + + -- this should give output with rdb$grantor = 'SYSDBA' despite that actual grantor was 'U01': + select * from rdb$user_privileges where rdb$relation_name=upper('test_u01') and rdb$user=upper('u02'); + commit; + + connect '$(DSN)' user u02 password '456'; + select current_user as who_am_i, u.* from test_u01 u; + commit; + + connect '$(DSN)' user u01 password '123'; + revoke select on test_u01 from u02 granted by sysdba; + commit; + + set bail off; + connect '$(DSN)' user u02 password '456'; + select current_user as who_am_i, u.* from test_u01 u; -- this should FAIL + commit; + set bail on; + + connect '$(DSN)' user sysdba password 'masterkey'; + drop user u01; + drop user u02; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHO_AM_I U01 + RDB$ROLE_NAME RDB$ADMIN + RDB$ROLE_IN_USE + RDB$SYSTEM_PRIVILEGES FFFFFFFFFFFFFFFF + + WHO_AM_I U01 + RDB$ROLE_NAME ROLE_FOR_USE_GRANTED_BY_CLAUSE + RDB$ROLE_IN_USE + RDB$SYSTEM_PRIVILEGES 0000100000000000 + + RDB$USER U02 + RDB$GRANTOR SYSDBA + RDB$PRIVILEGE S + RDB$GRANT_OPTION 0 + RDB$RELATION_NAME TEST_U01 + RDB$FIELD_NAME + RDB$USER_TYPE 8 + RDB$OBJECT_TYPE 0 + + WHO_AM_I U02 + ID 1 + WHO_IS_AUTHOR U01 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE TEST_U01 + -Effective user is U02 + """ + +@pytest.mark.version('>=4.0') +def test_use_granted_by_clause_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/syspriv/test_use_gstat_utility.py b/tests/functional/syspriv/test_use_gstat_utility.py new file mode 100644 index 00000000..6cd1723b --- /dev/null +++ b/tests/functional/syspriv/test_use_gstat_utility.py @@ -0,0 +1,313 @@ +#coding:utf-8 +# +# id: functional.syspriv.use_gstat_utility +# title: Check ability to obtain database statistics. +# decription: +# We create user and grant system privileges USE_GSTAT_UTILITY and IGNORE_DB_TRIGGERS to him. +# Then we check that this user can extract DB statistics in TWO ways: +# 1) common data except encryption info (it is called here 'base "sts_" output') +# 2) only encryption info (I don't know why "sts_encryption" can not be used together with other switches...) +# Both these actions should not produce any error. +# Also, logs of them should contain all needed 'check words' and patterns - and we check this. +# Finally, we ensure that when user U01 gathered DB statistics then db-level trigger did NOT fire. +# +# Checked on 4.0.0.267. +# 31.10.2019: added check for generator pages in encryption block. +# Checked on: +# 4.0.0.1635 SS: 2.660s. +# 4.0.0.1633 CS: 3.164s. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' '), ('.* data pages: total [\\d]+[,]{0,1} encrypted [\\d]+[,]{0,1} non-crypted [\\d]+', 'data pages total encrypted non-crypted'), ('.* index pages: total [\\d]+[,]{0,1} encrypted [\\d]+[,]{0,1} non-crypted [\\d]+', 'index pages total encrypted non-crypted'), ('.* blob pages: total [\\d]+[,]{0,1} encrypted [\\d]+[,]{0,1} non-crypted [\\d]+', 'blob pages total encrypted non-crypted'), ('.* generator pages: total [\\d]+[,]{0,1} encrypted [\\d]+[,]{0,1} non-crypted [\\d]+', 'generator pages total encrypted non-crypted')] + +init_script_1 = """ + set wng off; + set bail on; + set list on; + set count on; + + create or alter view v_check as + select + mon$database_name + ,current_user as who_ami + ,r.rdb$role_name + ,rdb$role_in_use(r.rdb$role_name) as RDB_ROLE_IN_USE + ,r.rdb$system_privileges + from mon$database m cross join rdb$roles r; + commit; + + create or alter user u01 password '123' revoke admin role; + revoke all on all from u01; + commit; + + create or alter trigger trg_connect active on connect as + begin + end; + commit; + + recreate table att_log ( + att_user varchar(255), + att_prot varchar(255) + ); + + commit; + + + recreate table test(s char(1000) unique using index test_s_unq); + commit; + + insert into test select rpad('', 1000, uuid_to_char(gen_uuid()) ) from rdb$types; + commit; + + grant select on v_check to public; + grant select on att_log to public; + --------------------------------- [ !! ] -- do NOT: grant select on test to u01; -- [ !! ] + commit; + + set term ^; + execute block as + begin + execute statement 'drop role role_for_use_gstat_utility'; + when any do begin end + end + ^ + create or alter trigger trg_connect active on connect as + begin + if ( upper(current_user) <> upper('SYSDBA') ) then + in autonomous transaction do + insert into att_log( att_user, att_prot ) + select + mon$user + ,mon$remote_protocol + from mon$attachments + where mon$user = current_user + ; + end + ^ + set term ;^ + commit; + + -- Ability to get database statistics. + -- NB: 'IGNORE_DB_TRIGGERS' - required for get full db statistics, otherwise: + -- Unable to perform operation: system privilege IGNORE_DB_TRIGGERS is missing + create role role_for_use_gstat_utility + set system privileges to USE_GSTAT_UTILITY, IGNORE_DB_TRIGGERS; + commit; + grant default role_for_use_gstat_utility to user u01; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import re +# +# db_file=db_conn.database_name +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# f_db_stat_log=open( os.path.join(context['temp_directory'],'tmp_dbstat.log'), 'w') +# f_db_stat_err=open( os.path.join(context['temp_directory'],'tmp_dbstat.err'), 'w') +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "user","U01","password","123", +# "action_db_stats", +# "dbname", db_file, +# "sts_record_versions", +# "sts_data_pages", +# "sts_idx_pages", +# "sts_sys_relations" +# ], +# stdout=f_db_stat_log, +# stderr=f_db_stat_err +# ) +# +# flush_and_close( f_db_stat_log ) +# flush_and_close( f_db_stat_err ) +# +# # Separate call for get encryption statistics: +# +# f_db_encr_log=open( os.path.join(context['temp_directory'],'tmp_dbencr.log'), 'w') +# f_db_encr_err=open( os.path.join(context['temp_directory'],'tmp_dbencr.err'), 'w') +# +# subprocess.call([context['fbsvcmgr_path'],"localhost:service_mgr", +# "user","U01","password","123", +# "action_db_stats", +# "dbname", db_file, +# "sts_encryption" +# ], +# stdout=f_db_encr_log, +# stderr=f_db_encr_err +# ) +# +# flush_and_close( f_db_encr_log ) +# flush_and_close( f_db_encr_err ) +# +# #----------------------- +# +# +# # Check content of logs: +# ####### +# +# # Must be EMPTY: +# with open( f_db_stat_err.name,'r') as f: +# for line in f: +# print('UNEXPECTED GSTAT STDERR: '+line.upper()) +# +# # Pointer pages: 1, data page slots: 2 +# # Data pages: 2, average fill: 8% +# # Primary pages: 1, secondary pages: 1, swept pages: 0 +# # Empty pages: 0, full pages: 0 +# # Blobs: 9, total length: 160, blob pages: 0 +# +# # Must contain: +# check_words=[ +# "rdb$database" +# ,"rdb$index" +# ,"primary pointer page" +# ,"index root page" +# ,"total formats" +# ,"total records" +# ,"total versions" +# ,"total fragments" +# ,"compression ratio" +# ,"pointer pages" +# ,"data pages" +# ,"primary pages" +# ,"empty pages" +# ,"blobs" +# ,"swept pages" +# ,"full pages" +# ,"fill distribution" +# ,"0 - 19%" +# ,"80 - 99%" +# ] +# +# f = open( f_db_stat_log.name, 'r') +# lines = f.read().lower() +# for i in range(len(check_words)): +# if check_words[i].lower() in lines: +# print( 'Found in base "sts_" output: ' + check_words[i].lower() ) +# else: +# print( 'UNEXPECTEDLY NOT found in base "sts_" output: ' + check_words[i].lower() ) +# flush_and_close( f ) +# +# +# # Must be EMPTY: +# with open( f_db_encr_err.name,'r') as f: +# for line in f: +# print('UNEXPECTED STS_ENCRYPTION STDERR: '+line.upper()) +# +# +# # Encryption statistics should be like this: +# # --------------------- +# # Data pages: total NNN, encrypted 0, non-crypted NNN +# # Index pages: total MMM, encrypted 0, non-crypted MMM +# # Blob pages: total 0, encrypted 0, non-crypted 0 +# # Generator pages: total PPP, encrypted 0, non-crypted PPP ------------- 31.10.2019 NB: THIS WAS ADDED RECENLTLY +# +# enc_pattern=re.compile(".*total[\\s]+[\\d]+,[\\s]+encrypted[\\s]+[\\d]+,[\\s]+non-crypted[\\s]+[\\d]+") +# with open( f_db_encr_log.name,'r') as f: +# for line in f: +# # if enc_pattern.match(line): +# if 'encrypted' in line: +# print('Found in "sts_encryption" output: ' + line.lower()) +# +# +# # Cleanup: +# ########## +# +# sql_final=''' +# set list on; +# set count on; +# select * from att_log; -- this should output: "Records affected: 0" because U01 must ignore DB-level trigger +# commit; +# drop user u01; +# commit; +# ''' +# runProgram('isql',[dsn,'-user',user_name, '-pas', user_password], sql_final) +# +# cleanup( (f_db_stat_log, f_db_stat_err, f_db_encr_log, f_db_encr_err) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Found in base "sts_" output: rdb$database + Found in base "sts_" output: rdb$index + Found in base "sts_" output: primary pointer page + Found in base "sts_" output: index root page + Found in base "sts_" output: total formats + Found in base "sts_" output: total records + Found in base "sts_" output: total versions + Found in base "sts_" output: total fragments + Found in base "sts_" output: compression ratio + Found in base "sts_" output: pointer pages + Found in base "sts_" output: data pages + Found in base "sts_" output: primary pages + Found in base "sts_" output: empty pages + Found in base "sts_" output: blobs + Found in base "sts_" output: swept pages + Found in base "sts_" output: full pages + Found in base "sts_" output: fill distribution + Found in base "sts_" output: 0 - 19% + Found in base "sts_" output: 80 - 99% + Found in "sts_encryption" output: data pages: total 131, encrypted 0, non-crypted 131 + Found in "sts_encryption" output: index pages: total 150, encrypted 0, non-crypted 150 + Found in "sts_encryption" output: blob pages: total 0, encrypted 0, non-crypted 0 + Found in "sts_encryption" output: generator pages: total 1, encrypted 0, non-crypted 1 + Records affected: 0 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_use_gstat_utility_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/syspriv/test_use_nbackup_utility.py b/tests/functional/syspriv/test_use_nbackup_utility.py new file mode 100644 index 00000000..536f6540 --- /dev/null +++ b/tests/functional/syspriv/test_use_nbackup_utility.py @@ -0,0 +1,130 @@ +#coding:utf-8 +# +# id: functional.syspriv.use_nbackup_utility +# title: Check ability to use nbackup. +# decription: +# Verify ability to issue ALTER DATABASE BEGIN/END BACKUP command by non-sysdba user. +# Checked on 4.0.0.262. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set wng off; + set bail on; + set list on; + set count on; + + create or alter view v_check as + select + current_user as who_ami + ,r.rdb$role_name + ,rdb$role_in_use(r.rdb$role_name) as RDB_ROLE_IN_USE + ,r.rdb$system_privileges + from mon$database m cross join rdb$roles r; + commit; + grant select on v_check to public; + + commit; + connect '$(DSN)' user sysdba password 'masterkey'; + create or alter user u01 password '123' revoke admin role; + revoke all on all from u01; + commit; + + set term ^; + execute block as + begin + execute statement 'drop role role_for_use_nbackup_utility'; + when any do begin end + end^ + set term ;^ + commit; + + -- Use nbackup to create database's copies + create role role_for_use_nbackup_utility set system privileges to USE_NBACKUP_UTILITY; + commit; + + -- Without following grant user U01 will NOT be able to set database-level lock that + -- is used by "alter database begin backup" command (that's what "nbackup -L 0" does): + -- Statement failed, SQLSTATE = 28000 + -- unsuccessful metadata update + -- -ALTER DATABASE failed + -- -no permission for ALTER access to DATABASE + grant default role_for_use_nbackup_utility to user u01; + commit; + + connect '$(DSN)' user u01 password '123'; + select * from v_check; + commit; + + set list on; + + select mon$backup_state from mon$database; + alter database begin backup; + commit; + + select mon$backup_state from mon$database; + alter database end backup; + commit; + + select mon$backup_state from mon$database; + commit; + + connect '$(DSN)' user sysdba password 'masterkey'; + drop user u01; + drop role role_for_use_nbackup_utility; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHO_AMI U01 + RDB$ROLE_NAME RDB$ADMIN + RDB_ROLE_IN_USE + RDB$SYSTEM_PRIVILEGES FFFFFFFFFFFFFFFF + + WHO_AMI U01 + RDB$ROLE_NAME ROLE_FOR_USE_NBACKUP_UTILITY + RDB_ROLE_IN_USE + RDB$SYSTEM_PRIVILEGES 1000000000000000 + + + Records affected: 2 + + MON$BACKUP_STATE 0 + + + Records affected: 1 + + MON$BACKUP_STATE 1 + + + Records affected: 1 + + MON$BACKUP_STATE 0 + + + Records affected: 1 + """ + +@pytest.mark.version('>=4.0') +def test_use_nbackup_utility_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/table/__init__.py b/tests/functional/table/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/table/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/table/alter/__init__.py b/tests/functional/table/alter/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/table/alter/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/table/alter/test_01.py b/tests/functional/table/alter/test_01.py new file mode 100644 index 00000000..1fb88beb --- /dev/null +++ b/tests/functional/table/alter/test_01.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: functional.table.alter.01 +# title: ALTER TABLE - ADD column +# decription: ALTER TABLE - ADD column +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.table.alter.alter_table_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE test( id INTEGER); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ALTER TABLE test ADD text varchar(32); +SHOW TABLE test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ID INTEGER Nullable +TEXT VARCHAR(32) Nullable +""" + +@pytest.mark.version('>=1.0') +def test_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/table/alter/test_02.py b/tests/functional/table/alter/test_02.py new file mode 100644 index 00000000..d4763c08 --- /dev/null +++ b/tests/functional/table/alter/test_02.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: functional.table.alter.02 +# title: ALTER TABLE - ADD column (test2) +# decription: ALTER TABLE - ADD column (test2) +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.table.alter.alter_table_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE test( id INTEGER); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ALTER TABLE test ADD text varchar(32) DEFAULT CURRENT_ROLE NOT NULL CONSTRAINT pk PRIMARY KEY; +SHOW TABLE test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ID INTEGER Nullable +TEXT VARCHAR(32) Not Null DEFAULT CURRENT_ROLE +CONSTRAINT PK: + Primary key (TEXT) +""" + +@pytest.mark.version('>=1.0') +def test_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/table/alter/test_03.py b/tests/functional/table/alter/test_03.py new file mode 100644 index 00000000..b0a72a18 --- /dev/null +++ b/tests/functional/table/alter/test_03.py @@ -0,0 +1,42 @@ +#coding:utf-8 +# +# id: functional.table.alter.03 +# title: ALTER TABLE - ADD CONSTRAINT - PRIMARY KEY +# decription: ALTER TABLE - ADD CONSTRAINT - PRIMARY KEY +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.table.alter.alter_table_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE test( id INTEGER NOT NULL); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ALTER TABLE test ADD CONSTRAINT pk PRIMARY KEY(id); +SHOW TABLE test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ID INTEGER Not Null +CONSTRAINT PK: + Primary key (ID)""" + +@pytest.mark.version('>=1.0') +def test_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/table/alter/test_04.py b/tests/functional/table/alter/test_04.py new file mode 100644 index 00000000..bd40a3de --- /dev/null +++ b/tests/functional/table/alter/test_04.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: functional.table.alter.04 +# title: ALTER TABLE - ADD CONSTRAINT - UNIQUE +# decription: ALTER TABLE - ADD CONSTRAINT - UNIQUE +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.table.alter.alter_table_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE test( id INTEGER NOT NULL); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ALTER TABLE test ADD CONSTRAINT unq UNIQUE(id); +SHOW TABLE test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ID INTEGER Not Null +CONSTRAINT UNQ: + Unique key (ID) +""" + +@pytest.mark.version('>=1.0') +def test_04_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/table/alter/test_05.py b/tests/functional/table/alter/test_05.py new file mode 100644 index 00000000..8067c99a --- /dev/null +++ b/tests/functional/table/alter/test_05.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: functional.table.alter.05 +# title: ALTER TABLE - ALTER - TO +# decription: ALTER TABLE - ALTER - TO +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.table.alter.alter_table_05 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE test( id INTEGER NOT NULL); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ALTER TABLE test ALTER id TO new_col_name; +SHOW TABLE test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """NEW_COL_NAME INTEGER Not Null +""" + +@pytest.mark.version('>=1.0') +def test_05_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/table/alter/test_06.py b/tests/functional/table/alter/test_06.py new file mode 100644 index 00000000..ccadf210 --- /dev/null +++ b/tests/functional/table/alter/test_06.py @@ -0,0 +1,41 @@ +#coding:utf-8 +# +# id: functional.table.alter.06 +# title: ALTER TABLE - ALTER - TYPE +# decription: ALTER TABLE - ALTER - TYPE +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.table.alter.alter_table_06 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE test( id INTEGER NOT NULL); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ALTER TABLE test ALTER id TYPE VARCHAR(32); +SHOW TABLE test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ID VARCHAR(32) Not Null +""" + +@pytest.mark.version('>=1.0') +def test_06_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/table/alter/test_07.py b/tests/functional/table/alter/test_07.py new file mode 100644 index 00000000..1ed59659 --- /dev/null +++ b/tests/functional/table/alter/test_07.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: functional.table.alter.07 +# title: ALTER TABLE - ALTER - POSITION +# decription: ALTER TABLE - ALTER - POSITION +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.table.alter.alter_table_07 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE test( id INTEGER NOT NULL, + text VARCHAR(32)); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ALTER TABLE test ALTER text POSITION 1; +SHOW TABLE test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEXT VARCHAR(32) Nullable +ID INTEGER Not Null +""" + +@pytest.mark.version('>=1.0') +def test_07_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/table/alter/test_08.py b/tests/functional/table/alter/test_08.py new file mode 100644 index 00000000..a22fdcbb --- /dev/null +++ b/tests/functional/table/alter/test_08.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: functional.table.alter.08 +# title: ALTER TABLE - DROP +# decription: ALTER TABLE - DROP +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# SHOW TABLE +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.table.alter.alter_table_08 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE test( id INTEGER NOT NULL, + text VARCHAR(32)); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ALTER TABLE test DROP text; +SHOW TABLE test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ID INTEGER Not Null +""" + +@pytest.mark.version('>=1.0') +def test_08_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/table/alter/test_09.py b/tests/functional/table/alter/test_09.py new file mode 100644 index 00000000..8ec53b7c --- /dev/null +++ b/tests/functional/table/alter/test_09.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: functional.table.alter.09 +# title: ALTER TABLE - DROP (with data) +# decription: ALTER TABLE - DROP (with data) +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# INSERT +# BASIC SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.table.alter.alter_table_09 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE test( id INTEGER NOT NULL, + text VARCHAR(32)); +commit; +INSERT INTO test(id,text) VALUES(0,'text 1'); +COMMIT;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ALTER TABLE test DROP text; +SELECT * FROM test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ ID +============ + + 0 +""" + +@pytest.mark.version('>=1.0') +def test_09_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/table/alter/test_10.py b/tests/functional/table/alter/test_10.py new file mode 100644 index 00000000..cf6802bf --- /dev/null +++ b/tests/functional/table/alter/test_10.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: functional.table.alter.10 +# title: ALTER TABLE - DROP CONSTRAINT - PRIMARY KEY +# decription: ALTER TABLE - DROP CONSTRAINT - PRIMARY KEY +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# SHOW TABLE +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.table.alter.alter_table_10 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE test( id INTEGER NOT NULL CONSTRAINT pk PRIMARY KEY, + text VARCHAR(32)); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ALTER TABLE test DROP CONSTRAINT pk; +SHOW TABLE test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ID INTEGER Not Null +TEXT VARCHAR(32) Nullable +""" + +@pytest.mark.version('>=1.0') +def test_10_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/table/alter/test_11.py b/tests/functional/table/alter/test_11.py new file mode 100644 index 00000000..42635af9 --- /dev/null +++ b/tests/functional/table/alter/test_11.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: functional.table.alter.11 +# title: ALTER TABLE - DROP CONSTRAINT - UNIQUE +# decription: ALTER TABLE - DROP CONSTRAINT - UNIQUE +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# SHOW TABLE +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.table.alter.alter_table_11 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE test( id INTEGER NOT NULL CONSTRAINT unq UNIQUE, + text VARCHAR(32)); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ALTER TABLE test DROP CONSTRAINT unq; +SHOW TABLE test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ID INTEGER Not Null +TEXT VARCHAR(32) Nullable +""" + +@pytest.mark.version('>=1.0') +def test_11_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/table/alter/test_12.py b/tests/functional/table/alter/test_12.py new file mode 100644 index 00000000..97aeee8f --- /dev/null +++ b/tests/functional/table/alter/test_12.py @@ -0,0 +1,817 @@ +#coding:utf-8 +# +# id: functional.table.alter.12 +# title: Verify ability to create exactly 254 changes of format (increasing it by 1) after initial creating table +# decription: +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test1(f0 int); -- this also create "format #1" + -- following shoudl run OK because of 254 changes: + alter table test1 add f1 int; + alter table test1 add f2 int; + alter table test1 add f3 int; + alter table test1 add f4 int; + alter table test1 add f5 int; + alter table test1 add f6 int; + alter table test1 add f7 int; + alter table test1 add f8 int; + alter table test1 add f9 int; + alter table test1 add f10 int; + alter table test1 add f11 int; + alter table test1 add f12 int; + alter table test1 add f13 int; + alter table test1 add f14 int; + alter table test1 add f15 int; + alter table test1 add f16 int; + alter table test1 add f17 int; + alter table test1 add f18 int; + alter table test1 add f19 int; + alter table test1 add f20 int; + alter table test1 add f21 int; + alter table test1 add f22 int; + alter table test1 add f23 int; + alter table test1 add f24 int; + alter table test1 add f25 int; + alter table test1 add f26 int; + alter table test1 add f27 int; + alter table test1 add f28 int; + alter table test1 add f29 int; + alter table test1 add f30 int; + alter table test1 add f31 int; + alter table test1 add f32 int; + alter table test1 add f33 int; + alter table test1 add f34 int; + alter table test1 add f35 int; + alter table test1 add f36 int; + alter table test1 add f37 int; + alter table test1 add f38 int; + alter table test1 add f39 int; + alter table test1 add f40 int; + alter table test1 add f41 int; + alter table test1 add f42 int; + alter table test1 add f43 int; + alter table test1 add f44 int; + alter table test1 add f45 int; + alter table test1 add f46 int; + alter table test1 add f47 int; + alter table test1 add f48 int; + alter table test1 add f49 int; + alter table test1 add f50 int; + alter table test1 add f51 int; + alter table test1 add f52 int; + alter table test1 add f53 int; + alter table test1 add f54 int; + alter table test1 add f55 int; + alter table test1 add f56 int; + alter table test1 add f57 int; + alter table test1 add f58 int; + alter table test1 add f59 int; + alter table test1 add f60 int; + alter table test1 add f61 int; + alter table test1 add f62 int; + alter table test1 add f63 int; + alter table test1 add f64 int; + alter table test1 add f65 int; + alter table test1 add f66 int; + alter table test1 add f67 int; + alter table test1 add f68 int; + alter table test1 add f69 int; + alter table test1 add f70 int; + alter table test1 add f71 int; + alter table test1 add f72 int; + alter table test1 add f73 int; + alter table test1 add f74 int; + alter table test1 add f75 int; + alter table test1 add f76 int; + alter table test1 add f77 int; + alter table test1 add f78 int; + alter table test1 add f79 int; + alter table test1 add f80 int; + alter table test1 add f81 int; + alter table test1 add f82 int; + alter table test1 add f83 int; + alter table test1 add f84 int; + alter table test1 add f85 int; + alter table test1 add f86 int; + alter table test1 add f87 int; + alter table test1 add f88 int; + alter table test1 add f89 int; + alter table test1 add f90 int; + alter table test1 add f91 int; + alter table test1 add f92 int; + alter table test1 add f93 int; + alter table test1 add f94 int; + alter table test1 add f95 int; + alter table test1 add f96 int; + alter table test1 add f97 int; + alter table test1 add f98 int; + alter table test1 add f99 int; + alter table test1 add f100 int; + alter table test1 add f101 int; + alter table test1 add f102 int; + alter table test1 add f103 int; + alter table test1 add f104 int; + alter table test1 add f105 int; + alter table test1 add f106 int; + alter table test1 add f107 int; + alter table test1 add f108 int; + alter table test1 add f109 int; + alter table test1 add f110 int; + alter table test1 add f111 int; + alter table test1 add f112 int; + alter table test1 add f113 int; + alter table test1 add f114 int; + alter table test1 add f115 int; + alter table test1 add f116 int; + alter table test1 add f117 int; + alter table test1 add f118 int; + alter table test1 add f119 int; + alter table test1 add f120 int; + alter table test1 add f121 int; + alter table test1 add f122 int; + alter table test1 add f123 int; + alter table test1 add f124 int; + alter table test1 add f125 int; + alter table test1 add f126 int; + alter table test1 add f127 int; + alter table test1 add f128 int; + alter table test1 add f129 int; + alter table test1 add f130 int; + alter table test1 add f131 int; + alter table test1 add f132 int; + alter table test1 add f133 int; + alter table test1 add f134 int; + alter table test1 add f135 int; + alter table test1 add f136 int; + alter table test1 add f137 int; + alter table test1 add f138 int; + alter table test1 add f139 int; + alter table test1 add f140 int; + alter table test1 add f141 int; + alter table test1 add f142 int; + alter table test1 add f143 int; + alter table test1 add f144 int; + alter table test1 add f145 int; + alter table test1 add f146 int; + alter table test1 add f147 int; + alter table test1 add f148 int; + alter table test1 add f149 int; + alter table test1 add f150 int; + alter table test1 add f151 int; + alter table test1 add f152 int; + alter table test1 add f153 int; + alter table test1 add f154 int; + alter table test1 add f155 int; + alter table test1 add f156 int; + alter table test1 add f157 int; + alter table test1 add f158 int; + alter table test1 add f159 int; + alter table test1 add f160 int; + alter table test1 add f161 int; + alter table test1 add f162 int; + alter table test1 add f163 int; + alter table test1 add f164 int; + alter table test1 add f165 int; + alter table test1 add f166 int; + alter table test1 add f167 int; + alter table test1 add f168 int; + alter table test1 add f169 int; + alter table test1 add f170 int; + alter table test1 add f171 int; + alter table test1 add f172 int; + alter table test1 add f173 int; + alter table test1 add f174 int; + alter table test1 add f175 int; + alter table test1 add f176 int; + alter table test1 add f177 int; + alter table test1 add f178 int; + alter table test1 add f179 int; + alter table test1 add f180 int; + alter table test1 add f181 int; + alter table test1 add f182 int; + alter table test1 add f183 int; + alter table test1 add f184 int; + alter table test1 add f185 int; + alter table test1 add f186 int; + alter table test1 add f187 int; + alter table test1 add f188 int; + alter table test1 add f189 int; + alter table test1 add f190 int; + alter table test1 add f191 int; + alter table test1 add f192 int; + alter table test1 add f193 int; + alter table test1 add f194 int; + alter table test1 add f195 int; + alter table test1 add f196 int; + alter table test1 add f197 int; + alter table test1 add f198 int; + alter table test1 add f199 int; + alter table test1 add f200 int; + alter table test1 add f201 int; + alter table test1 add f202 int; + alter table test1 add f203 int; + alter table test1 add f204 int; + alter table test1 add f205 int; + alter table test1 add f206 int; + alter table test1 add f207 int; + alter table test1 add f208 int; + alter table test1 add f209 int; + alter table test1 add f210 int; + alter table test1 add f211 int; + alter table test1 add f212 int; + alter table test1 add f213 int; + alter table test1 add f214 int; + alter table test1 add f215 int; + alter table test1 add f216 int; + alter table test1 add f217 int; + alter table test1 add f218 int; + alter table test1 add f219 int; + alter table test1 add f220 int; + alter table test1 add f221 int; + alter table test1 add f222 int; + alter table test1 add f223 int; + alter table test1 add f224 int; + alter table test1 add f225 int; + alter table test1 add f226 int; + alter table test1 add f227 int; + alter table test1 add f228 int; + alter table test1 add f229 int; + alter table test1 add f230 int; + alter table test1 add f231 int; + alter table test1 add f232 int; + alter table test1 add f233 int; + alter table test1 add f234 int; + alter table test1 add f235 int; + alter table test1 add f236 int; + alter table test1 add f237 int; + alter table test1 add f238 int; + alter table test1 add f239 int; + alter table test1 add f240 int; + alter table test1 add f241 int; + alter table test1 add f242 int; + alter table test1 add f243 int; + alter table test1 add f244 int; + alter table test1 add f245 int; + alter table test1 add f246 int; + alter table test1 add f247 int; + alter table test1 add f248 int; + alter table test1 add f249 int; + alter table test1 add f250 int; + alter table test1 add f251 int; + alter table test1 add f252 int; + alter table test1 add f253 int; + alter table test1 add f254 int; + commit; + + show table test1; + + -- following shoudl FAIL because of 255 changes: + recreate table test2(f0 int); + alter table test2 add f1 int; + alter table test2 add f2 int; + alter table test2 add f3 int; + alter table test2 add f4 int; + alter table test2 add f5 int; + alter table test2 add f6 int; + alter table test2 add f7 int; + alter table test2 add f8 int; + alter table test2 add f9 int; + alter table test2 add f10 int; + alter table test2 add f11 int; + alter table test2 add f12 int; + alter table test2 add f13 int; + alter table test2 add f14 int; + alter table test2 add f15 int; + alter table test2 add f16 int; + alter table test2 add f17 int; + alter table test2 add f18 int; + alter table test2 add f19 int; + alter table test2 add f20 int; + alter table test2 add f21 int; + alter table test2 add f22 int; + alter table test2 add f23 int; + alter table test2 add f24 int; + alter table test2 add f25 int; + alter table test2 add f26 int; + alter table test2 add f27 int; + alter table test2 add f28 int; + alter table test2 add f29 int; + alter table test2 add f30 int; + alter table test2 add f31 int; + alter table test2 add f32 int; + alter table test2 add f33 int; + alter table test2 add f34 int; + alter table test2 add f35 int; + alter table test2 add f36 int; + alter table test2 add f37 int; + alter table test2 add f38 int; + alter table test2 add f39 int; + alter table test2 add f40 int; + alter table test2 add f41 int; + alter table test2 add f42 int; + alter table test2 add f43 int; + alter table test2 add f44 int; + alter table test2 add f45 int; + alter table test2 add f46 int; + alter table test2 add f47 int; + alter table test2 add f48 int; + alter table test2 add f49 int; + alter table test2 add f50 int; + alter table test2 add f51 int; + alter table test2 add f52 int; + alter table test2 add f53 int; + alter table test2 add f54 int; + alter table test2 add f55 int; + alter table test2 add f56 int; + alter table test2 add f57 int; + alter table test2 add f58 int; + alter table test2 add f59 int; + alter table test2 add f60 int; + alter table test2 add f61 int; + alter table test2 add f62 int; + alter table test2 add f63 int; + alter table test2 add f64 int; + alter table test2 add f65 int; + alter table test2 add f66 int; + alter table test2 add f67 int; + alter table test2 add f68 int; + alter table test2 add f69 int; + alter table test2 add f70 int; + alter table test2 add f71 int; + alter table test2 add f72 int; + alter table test2 add f73 int; + alter table test2 add f74 int; + alter table test2 add f75 int; + alter table test2 add f76 int; + alter table test2 add f77 int; + alter table test2 add f78 int; + alter table test2 add f79 int; + alter table test2 add f80 int; + alter table test2 add f81 int; + alter table test2 add f82 int; + alter table test2 add f83 int; + alter table test2 add f84 int; + alter table test2 add f85 int; + alter table test2 add f86 int; + alter table test2 add f87 int; + alter table test2 add f88 int; + alter table test2 add f89 int; + alter table test2 add f90 int; + alter table test2 add f91 int; + alter table test2 add f92 int; + alter table test2 add f93 int; + alter table test2 add f94 int; + alter table test2 add f95 int; + alter table test2 add f96 int; + alter table test2 add f97 int; + alter table test2 add f98 int; + alter table test2 add f99 int; + alter table test2 add f100 int; + alter table test2 add f101 int; + alter table test2 add f102 int; + alter table test2 add f103 int; + alter table test2 add f104 int; + alter table test2 add f105 int; + alter table test2 add f106 int; + alter table test2 add f107 int; + alter table test2 add f108 int; + alter table test2 add f109 int; + alter table test2 add f110 int; + alter table test2 add f111 int; + alter table test2 add f112 int; + alter table test2 add f113 int; + alter table test2 add f114 int; + alter table test2 add f115 int; + alter table test2 add f116 int; + alter table test2 add f117 int; + alter table test2 add f118 int; + alter table test2 add f119 int; + alter table test2 add f120 int; + alter table test2 add f121 int; + alter table test2 add f122 int; + alter table test2 add f123 int; + alter table test2 add f124 int; + alter table test2 add f125 int; + alter table test2 add f126 int; + alter table test2 add f127 int; + alter table test2 add f128 int; + alter table test2 add f129 int; + alter table test2 add f130 int; + alter table test2 add f131 int; + alter table test2 add f132 int; + alter table test2 add f133 int; + alter table test2 add f134 int; + alter table test2 add f135 int; + alter table test2 add f136 int; + alter table test2 add f137 int; + alter table test2 add f138 int; + alter table test2 add f139 int; + alter table test2 add f140 int; + alter table test2 add f141 int; + alter table test2 add f142 int; + alter table test2 add f143 int; + alter table test2 add f144 int; + alter table test2 add f145 int; + alter table test2 add f146 int; + alter table test2 add f147 int; + alter table test2 add f148 int; + alter table test2 add f149 int; + alter table test2 add f150 int; + alter table test2 add f151 int; + alter table test2 add f152 int; + alter table test2 add f153 int; + alter table test2 add f154 int; + alter table test2 add f155 int; + alter table test2 add f156 int; + alter table test2 add f157 int; + alter table test2 add f158 int; + alter table test2 add f159 int; + alter table test2 add f160 int; + alter table test2 add f161 int; + alter table test2 add f162 int; + alter table test2 add f163 int; + alter table test2 add f164 int; + alter table test2 add f165 int; + alter table test2 add f166 int; + alter table test2 add f167 int; + alter table test2 add f168 int; + alter table test2 add f169 int; + alter table test2 add f170 int; + alter table test2 add f171 int; + alter table test2 add f172 int; + alter table test2 add f173 int; + alter table test2 add f174 int; + alter table test2 add f175 int; + alter table test2 add f176 int; + alter table test2 add f177 int; + alter table test2 add f178 int; + alter table test2 add f179 int; + alter table test2 add f180 int; + alter table test2 add f181 int; + alter table test2 add f182 int; + alter table test2 add f183 int; + alter table test2 add f184 int; + alter table test2 add f185 int; + alter table test2 add f186 int; + alter table test2 add f187 int; + alter table test2 add f188 int; + alter table test2 add f189 int; + alter table test2 add f190 int; + alter table test2 add f191 int; + alter table test2 add f192 int; + alter table test2 add f193 int; + alter table test2 add f194 int; + alter table test2 add f195 int; + alter table test2 add f196 int; + alter table test2 add f197 int; + alter table test2 add f198 int; + alter table test2 add f199 int; + alter table test2 add f200 int; + alter table test2 add f201 int; + alter table test2 add f202 int; + alter table test2 add f203 int; + alter table test2 add f204 int; + alter table test2 add f205 int; + alter table test2 add f206 int; + alter table test2 add f207 int; + alter table test2 add f208 int; + alter table test2 add f209 int; + alter table test2 add f210 int; + alter table test2 add f211 int; + alter table test2 add f212 int; + alter table test2 add f213 int; + alter table test2 add f214 int; + alter table test2 add f215 int; + alter table test2 add f216 int; + alter table test2 add f217 int; + alter table test2 add f218 int; + alter table test2 add f219 int; + alter table test2 add f220 int; + alter table test2 add f221 int; + alter table test2 add f222 int; + alter table test2 add f223 int; + alter table test2 add f224 int; + alter table test2 add f225 int; + alter table test2 add f226 int; + alter table test2 add f227 int; + alter table test2 add f228 int; + alter table test2 add f229 int; + alter table test2 add f230 int; + alter table test2 add f231 int; + alter table test2 add f232 int; + alter table test2 add f233 int; + alter table test2 add f234 int; + alter table test2 add f235 int; + alter table test2 add f236 int; + alter table test2 add f237 int; + alter table test2 add f238 int; + alter table test2 add f239 int; + alter table test2 add f240 int; + alter table test2 add f241 int; + alter table test2 add f242 int; + alter table test2 add f243 int; + alter table test2 add f244 int; + alter table test2 add f245 int; + alter table test2 add f246 int; + alter table test2 add f247 int; + alter table test2 add f248 int; + alter table test2 add f249 int; + alter table test2 add f250 int; + alter table test2 add f251 int; + alter table test2 add f252 int; + alter table test2 add f253 int; + alter table test2 add f254 int; + alter table test2 add f255 int; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F0 INTEGER Nullable + F1 INTEGER Nullable + F2 INTEGER Nullable + F3 INTEGER Nullable + F4 INTEGER Nullable + F5 INTEGER Nullable + F6 INTEGER Nullable + F7 INTEGER Nullable + F8 INTEGER Nullable + F9 INTEGER Nullable + F10 INTEGER Nullable + F11 INTEGER Nullable + F12 INTEGER Nullable + F13 INTEGER Nullable + F14 INTEGER Nullable + F15 INTEGER Nullable + F16 INTEGER Nullable + F17 INTEGER Nullable + F18 INTEGER Nullable + F19 INTEGER Nullable + F20 INTEGER Nullable + F21 INTEGER Nullable + F22 INTEGER Nullable + F23 INTEGER Nullable + F24 INTEGER Nullable + F25 INTEGER Nullable + F26 INTEGER Nullable + F27 INTEGER Nullable + F28 INTEGER Nullable + F29 INTEGER Nullable + F30 INTEGER Nullable + F31 INTEGER Nullable + F32 INTEGER Nullable + F33 INTEGER Nullable + F34 INTEGER Nullable + F35 INTEGER Nullable + F36 INTEGER Nullable + F37 INTEGER Nullable + F38 INTEGER Nullable + F39 INTEGER Nullable + F40 INTEGER Nullable + F41 INTEGER Nullable + F42 INTEGER Nullable + F43 INTEGER Nullable + F44 INTEGER Nullable + F45 INTEGER Nullable + F46 INTEGER Nullable + F47 INTEGER Nullable + F48 INTEGER Nullable + F49 INTEGER Nullable + F50 INTEGER Nullable + F51 INTEGER Nullable + F52 INTEGER Nullable + F53 INTEGER Nullable + F54 INTEGER Nullable + F55 INTEGER Nullable + F56 INTEGER Nullable + F57 INTEGER Nullable + F58 INTEGER Nullable + F59 INTEGER Nullable + F60 INTEGER Nullable + F61 INTEGER Nullable + F62 INTEGER Nullable + F63 INTEGER Nullable + F64 INTEGER Nullable + F65 INTEGER Nullable + F66 INTEGER Nullable + F67 INTEGER Nullable + F68 INTEGER Nullable + F69 INTEGER Nullable + F70 INTEGER Nullable + F71 INTEGER Nullable + F72 INTEGER Nullable + F73 INTEGER Nullable + F74 INTEGER Nullable + F75 INTEGER Nullable + F76 INTEGER Nullable + F77 INTEGER Nullable + F78 INTEGER Nullable + F79 INTEGER Nullable + F80 INTEGER Nullable + F81 INTEGER Nullable + F82 INTEGER Nullable + F83 INTEGER Nullable + F84 INTEGER Nullable + F85 INTEGER Nullable + F86 INTEGER Nullable + F87 INTEGER Nullable + F88 INTEGER Nullable + F89 INTEGER Nullable + F90 INTEGER Nullable + F91 INTEGER Nullable + F92 INTEGER Nullable + F93 INTEGER Nullable + F94 INTEGER Nullable + F95 INTEGER Nullable + F96 INTEGER Nullable + F97 INTEGER Nullable + F98 INTEGER Nullable + F99 INTEGER Nullable + F100 INTEGER Nullable + F101 INTEGER Nullable + F102 INTEGER Nullable + F103 INTEGER Nullable + F104 INTEGER Nullable + F105 INTEGER Nullable + F106 INTEGER Nullable + F107 INTEGER Nullable + F108 INTEGER Nullable + F109 INTEGER Nullable + F110 INTEGER Nullable + F111 INTEGER Nullable + F112 INTEGER Nullable + F113 INTEGER Nullable + F114 INTEGER Nullable + F115 INTEGER Nullable + F116 INTEGER Nullable + F117 INTEGER Nullable + F118 INTEGER Nullable + F119 INTEGER Nullable + F120 INTEGER Nullable + F121 INTEGER Nullable + F122 INTEGER Nullable + F123 INTEGER Nullable + F124 INTEGER Nullable + F125 INTEGER Nullable + F126 INTEGER Nullable + F127 INTEGER Nullable + F128 INTEGER Nullable + F129 INTEGER Nullable + F130 INTEGER Nullable + F131 INTEGER Nullable + F132 INTEGER Nullable + F133 INTEGER Nullable + F134 INTEGER Nullable + F135 INTEGER Nullable + F136 INTEGER Nullable + F137 INTEGER Nullable + F138 INTEGER Nullable + F139 INTEGER Nullable + F140 INTEGER Nullable + F141 INTEGER Nullable + F142 INTEGER Nullable + F143 INTEGER Nullable + F144 INTEGER Nullable + F145 INTEGER Nullable + F146 INTEGER Nullable + F147 INTEGER Nullable + F148 INTEGER Nullable + F149 INTEGER Nullable + F150 INTEGER Nullable + F151 INTEGER Nullable + F152 INTEGER Nullable + F153 INTEGER Nullable + F154 INTEGER Nullable + F155 INTEGER Nullable + F156 INTEGER Nullable + F157 INTEGER Nullable + F158 INTEGER Nullable + F159 INTEGER Nullable + F160 INTEGER Nullable + F161 INTEGER Nullable + F162 INTEGER Nullable + F163 INTEGER Nullable + F164 INTEGER Nullable + F165 INTEGER Nullable + F166 INTEGER Nullable + F167 INTEGER Nullable + F168 INTEGER Nullable + F169 INTEGER Nullable + F170 INTEGER Nullable + F171 INTEGER Nullable + F172 INTEGER Nullable + F173 INTEGER Nullable + F174 INTEGER Nullable + F175 INTEGER Nullable + F176 INTEGER Nullable + F177 INTEGER Nullable + F178 INTEGER Nullable + F179 INTEGER Nullable + F180 INTEGER Nullable + F181 INTEGER Nullable + F182 INTEGER Nullable + F183 INTEGER Nullable + F184 INTEGER Nullable + F185 INTEGER Nullable + F186 INTEGER Nullable + F187 INTEGER Nullable + F188 INTEGER Nullable + F189 INTEGER Nullable + F190 INTEGER Nullable + F191 INTEGER Nullable + F192 INTEGER Nullable + F193 INTEGER Nullable + F194 INTEGER Nullable + F195 INTEGER Nullable + F196 INTEGER Nullable + F197 INTEGER Nullable + F198 INTEGER Nullable + F199 INTEGER Nullable + F200 INTEGER Nullable + F201 INTEGER Nullable + F202 INTEGER Nullable + F203 INTEGER Nullable + F204 INTEGER Nullable + F205 INTEGER Nullable + F206 INTEGER Nullable + F207 INTEGER Nullable + F208 INTEGER Nullable + F209 INTEGER Nullable + F210 INTEGER Nullable + F211 INTEGER Nullable + F212 INTEGER Nullable + F213 INTEGER Nullable + F214 INTEGER Nullable + F215 INTEGER Nullable + F216 INTEGER Nullable + F217 INTEGER Nullable + F218 INTEGER Nullable + F219 INTEGER Nullable + F220 INTEGER Nullable + F221 INTEGER Nullable + F222 INTEGER Nullable + F223 INTEGER Nullable + F224 INTEGER Nullable + F225 INTEGER Nullable + F226 INTEGER Nullable + F227 INTEGER Nullable + F228 INTEGER Nullable + F229 INTEGER Nullable + F230 INTEGER Nullable + F231 INTEGER Nullable + F232 INTEGER Nullable + F233 INTEGER Nullable + F234 INTEGER Nullable + F235 INTEGER Nullable + F236 INTEGER Nullable + F237 INTEGER Nullable + F238 INTEGER Nullable + F239 INTEGER Nullable + F240 INTEGER Nullable + F241 INTEGER Nullable + F242 INTEGER Nullable + F243 INTEGER Nullable + F244 INTEGER Nullable + F245 INTEGER Nullable + F246 INTEGER Nullable + F247 INTEGER Nullable + F248 INTEGER Nullable + F249 INTEGER Nullable + F250 INTEGER Nullable + F251 INTEGER Nullable + F252 INTEGER Nullable + F253 INTEGER Nullable + F254 INTEGER Nullable + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 54000 + unsuccessful metadata update + -TABLE TEST2 + -too many versions + """ + +@pytest.mark.version('>=2.5') +def test_12_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/table/create/__init__.py b/tests/functional/table/create/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/table/create/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/table/create/test_01.py b/tests/functional/table/create/test_01.py new file mode 100644 index 00000000..ecd8a219 --- /dev/null +++ b/tests/functional/table/create/test_01.py @@ -0,0 +1,85 @@ +#coding:utf-8 +# +# id: functional.table.create.01 +# title: CREATE TABLE - types +# decription: CREATE TABLE - types +# +# Dependencies: +# CREATE DATABASE +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.table.create.create_table_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE TABLE test( + c1 SMALLINT, + c2 INTEGER, + c3 FLOAT, + c4 DOUBLE PRECISION, + c5 DATE, + c6 TIME, + c7 TIMESTAMP, + c8 DECIMAL(18,4), + c9 NUMERIC(1,1), + c10 CHAR(800), + c11 CHARACTER(9000), + c12 CHARACTER VARYING(1600), + c13 VARCHAR(12000), + c14 NCHAR (12), + c15 NATIONAL CHARACTER(20), + c16 NATIONAL CHAR(200), + c17 NCHAR VARYING(1600), + c18 NATIONAL CHARACTER VARYING(16000), + c19 NATIONAL CHAR VARYING(16000), + c20 BLOB, + c21 BLOB SUB_TYPE 1, + c22 BLOB SEGMENT SIZE 512, + c23 BLOB (1024,1) +); +SHOW TABLE test; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """C1 SMALLINT Nullable +C2 INTEGER Nullable +C3 FLOAT Nullable +C4 DOUBLE PRECISION Nullable +C5 DATE Nullable +C6 TIME Nullable +C7 TIMESTAMP Nullable +C8 DECIMAL(18, 4) Nullable +C9 NUMERIC(1, 1) Nullable +C10 CHAR(800) Nullable +C11 CHAR(9000) Nullable +C12 VARCHAR(1600) Nullable +C13 VARCHAR(12000) Nullable +C14 CHAR(12) CHARACTER SET ISO8859_1 Nullable +C15 CHAR(20) CHARACTER SET ISO8859_1 Nullable +C16 CHAR(200) CHARACTER SET ISO8859_1 Nullable +C17 VARCHAR(1600) CHARACTER SET ISO8859_1 Nullable +C18 VARCHAR(16000) CHARACTER SET ISO8859_1 Nullable +C19 VARCHAR(16000) CHARACTER SET ISO8859_1 Nullable +C20 BLOB segment 80, subtype BINARY Nullable +C21 BLOB segment 80, subtype TEXT Nullable +C22 BLOB segment 512, subtype BINARY Nullable +C23 BLOB segment 1024, subtype TEXT Nullable""" + +@pytest.mark.version('>=2.0') +def test_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/table/create/test_02.py b/tests/functional/table/create/test_02.py new file mode 100644 index 00000000..1f4c9998 --- /dev/null +++ b/tests/functional/table/create/test_02.py @@ -0,0 +1,67 @@ +#coding:utf-8 +# +# id: functional.table.create.02 +# title: CREATE TABLE - column properties +# decription: CREATE TABLE - column properties +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.table.create.create_table_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE fk(id INT NOT NULL PRIMARY KEY); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE TABLE test( + c1 SMALLINT NOT NULL, + c2 INTEGER DEFAULT 0, + c3 FLOAT NOT NULL UNIQUE, + c4 DOUBLE PRECISION NOT NULL PRIMARY KEY, + c5 INT REFERENCES fk(id), + c6 INT CHECK (c6>c5), + c7 COMPUTED (c1+c2), + c8 CHAR(31) DEFAULT USER, + c9 VARCHAR(40) DEFAULT 'data' +); +SHOW TABLE test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """C1 SMALLINT Not Null +C2 INTEGER Nullable DEFAULT 0 +C3 FLOAT Not Null +C4 DOUBLE PRECISION Not Null +C5 INTEGER Nullable +C6 INTEGER Nullable +C7 Computed by: (c1+c2) +C8 CHAR(31) Nullable DEFAULT USER +C9 VARCHAR(40) Nullable DEFAULT 'data' +CONSTRAINT INTEG_8: + Foreign key (C5) References FK (ID) +CONSTRAINT INTEG_7: + Primary key (C4) +CONSTRAINT INTEG_5: + Unique key (C3) +CONSTRAINT INTEG_9: + CHECK (c6>c5) +""" + +@pytest.mark.version('>=2.1') +def test_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/table/create/test_03.py b/tests/functional/table/create/test_03.py new file mode 100644 index 00000000..e594f310 --- /dev/null +++ b/tests/functional/table/create/test_03.py @@ -0,0 +1,51 @@ +#coding:utf-8 +# +# id: functional.table.create.03 +# title: CREATE TABLE - charset + colations + domain +# decription: CREATE TABLE - charset + colations + domain +# +# Dependencies: +# CREATE DATABASE +# CREATE DOMAIN +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.table.create.create_table_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE DOMAIN test VARCHAR(32765)[40000]; +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE TABLE test( + c1 VARCHAR(40) CHARACTER SET CYRL COLLATE CYRL, + c2 VARCHAR(40) CHARACTER SET DOS437 COLLATE DB_DEU437, + c3 BLOB SUB_TYPE TEXT CHARACTER SET DOS437, + c4 test +); +SHOW TABLE test; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """C1 VARCHAR(40) CHARACTER SET CYRL Nullable +C2 VARCHAR(40) CHARACTER SET DOS437 Nullable + COLLATE DB_DEU437 +C3 BLOB segment 80, subtype TEXT CHARACTER SET DOS437 Nullable +C4 (TEST) ARRAY OF [40000] + VARCHAR(32765) Nullable""" + +@pytest.mark.version('>=2.0') +def test_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/table/create/test_04.py b/tests/functional/table/create/test_04.py new file mode 100644 index 00000000..dd7d18fe --- /dev/null +++ b/tests/functional/table/create/test_04.py @@ -0,0 +1,68 @@ +#coding:utf-8 +# +# id: functional.table.create.04 +# title: CREATE TABLE - constraints +# decription: CREATE TABLE - constraints +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.table.create.create_table_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE fk(id INT NOT NULL PRIMARY KEY); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE TABLE test( + c1 SMALLINT NOT NULL, + c2 SMALLINT NOT NULL, + c3 SMALLINT NOT NULL, + PRIMARY KEY(c1), + UNIQUE(c2), + FOREIGN KEY (c2) REFERENCES fk(id) ON DELETE CASCADE, + CHECK (c2>c1), + CONSTRAINT test UNIQUE(c3), + CONSTRAINT test2 FOREIGN KEY (c3) REFERENCES fk(id) ON DELETE SET NULL, + CONSTRAINT test3 CHECK (NOT c3>c1) +); +SHOW TABLE test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """C1 SMALLINT Not Null +C2 SMALLINT Not Null +C3 SMALLINT Not Null +CONSTRAINT INTEG_8: + Foreign key (C2) References FK (ID) On Delete Cascade +CONSTRAINT TEST2: + Foreign key (C3) References FK (ID) On Delete Set Null +CONSTRAINT INTEG_6: + Primary key (C1) +CONSTRAINT INTEG_7: + Unique key (C2) +CONSTRAINT TEST: + Unique key (C3) +CONSTRAINT INTEG_9: + CHECK (c2>c1) +CONSTRAINT TEST3: + CHECK (NOT c3>c1) +""" + +@pytest.mark.version('>=2.1') +def test_04_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/table/create/test_05.py b/tests/functional/table/create/test_05.py new file mode 100644 index 00000000..469ec552 --- /dev/null +++ b/tests/functional/table/create/test_05.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: functional.table.create_05 +# title: CREATE TABLE - create table with same name +# decription: CREATE TABLE - create table with same name +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.table.create.create_table_05 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE test( + c1 SMALLINT +); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE TABLE test( + c1 SMALLINT, + c2 INTEGER +);""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42S01 +unsuccessful metadata update +-CREATE TABLE TEST failed +-Table TEST already exists + +""" + +@pytest.mark.version('>=3.0') +def test_create_05_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/table/create/test_06.py b/tests/functional/table/create/test_06.py new file mode 100644 index 00000000..af34a4fe --- /dev/null +++ b/tests/functional/table/create/test_06.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: functional.table.create_06 +# title: CREATE TABLE - two column with same name +# decription: CREATE TABLE - two column with same name +# +# Dependencies: +# CREATE DATABASE +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.table.create.create_table_06 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE TABLE test( + c1 SMALLINT, + c1 INTEGER +); + +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 23000 +unsuccessful metadata update +-CREATE TABLE TEST failed +-violation of PRIMARY or UNIQUE KEY constraint "RDB$INDEX_15" on table "RDB$RELATION_FIELDS" +-Problematic key value is ("RDB$FIELD_NAME" = 'C1', "RDB$RELATION_NAME" = 'TEST') +""" + +@pytest.mark.version('>=3.0') +def test_create_06_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/table/create/test_07.py b/tests/functional/table/create/test_07.py new file mode 100644 index 00000000..950d9739 --- /dev/null +++ b/tests/functional/table/create/test_07.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: functional.table.create_07 +# title: CREATE TABLE - unknown datatype (domain) +# decription: CREATE TABLE - unknown datatype (domain) +# +# Dependencies: +# CREATE DATABASE +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.table.create.create_table_07 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE TABLE test( + c1 unk_domain +);""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 42000 +unsuccessful metadata update +-CREATE TABLE TEST failed +-SQL error code = -607 +-Invalid command +-Specified domain or source column UNK_DOMAIN does not exist + +""" + +@pytest.mark.version('>=3.0') +def test_create_07_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/tabloid/__init__.py b/tests/functional/tabloid/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/tabloid/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/tabloid/test_arithmetic_cast_float_to_int_as_round.py b/tests/functional/tabloid/test_arithmetic_cast_float_to_int_as_round.py new file mode 100644 index 00000000..abb495d7 --- /dev/null +++ b/tests/functional/tabloid/test_arithmetic_cast_float_to_int_as_round.py @@ -0,0 +1,38 @@ +#coding:utf-8 +# +# id: functional.tabloid.arithmetic_cast_float_to_int_as_round +# title: Result of CAST for numbers is implementation defined +# decription: See also: sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1062610&msg=15214333 +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; select cast( sqrt(24) as smallint) casted_sqrt from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CASTED_SQRT 5 + """ + +@pytest.mark.version('>=2.5.0') +def test_arithmetic_cast_float_to_int_as_round_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_arithmetic_numexpr_eval_dialect_1.py b/tests/functional/tabloid/test_arithmetic_numexpr_eval_dialect_1.py new file mode 100644 index 00000000..8c5799cf --- /dev/null +++ b/tests/functional/tabloid/test_arithmetic_numexpr_eval_dialect_1.py @@ -0,0 +1,38 @@ +#coding:utf-8 +# +# id: functional.tabloid.arithmetic_numexpr_eval_dialect_1 +# title: Check result of integer division on dialect 1. +# decription: Was fixed in 2.1, see: sql.ru/forum/actualutils.aspx?action=gotomsg&tid=708324&msg=7865013 +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=1, init=init_script_1) + +test_script_1 = """ + set list on; select 36/-4/3 d from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + D -3.000000000000000 + """ + +@pytest.mark.version('>=2.5') +def test_arithmetic_numexpr_eval_dialect_1_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_arithmetic_numexpr_eval_dialect_3.py b/tests/functional/tabloid/test_arithmetic_numexpr_eval_dialect_3.py new file mode 100644 index 00000000..30fac650 --- /dev/null +++ b/tests/functional/tabloid/test_arithmetic_numexpr_eval_dialect_3.py @@ -0,0 +1,38 @@ +#coding:utf-8 +# +# id: functional.tabloid.arithmetic_numexpr_eval_dialect_3 +# title: Check result of integer division on dialect 3. +# decription: Was fixed in 2.1, see: sql.ru/forum/actualutils.aspx?action=gotomsg&tid=708324&msg=7865013 +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; select 36/-4/3 d from rdb$database; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + D -3 + """ + +@pytest.mark.version('>=2.5') +def test_arithmetic_numexpr_eval_dialect_3_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_bus_3103_windowed_funcs.py b/tests/functional/tabloid/test_bus_3103_windowed_funcs.py new file mode 100644 index 00000000..a3ccafc7 --- /dev/null +++ b/tests/functional/tabloid/test_bus_3103_windowed_funcs.py @@ -0,0 +1,62 @@ +#coding:utf-8 +# +# id: functional.tabloid.bus_3103_windowed_funcs +# title: Query for test MAX()OVER(). +# decription: +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='tabloid-bus-3103.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + with + dx as ( + select + t.cid + ,p.pid + ,hash(src) + hash(tgt) sth + ,datediff(minute from dts0 to dts1 + iif(t.dts1 < t.dts0, 1, 0)) dd + from tmove t + left join pmove p on t.id = p.tid + ) + ,mx as ( + select + dx.*, + nullif( abs( max(dd)over() - max(dd)over(partition by cid, sth) ), 1) ns + from dx + ) + select + (select name from clist c where c.id = mx.cid) cnm, + count(pid) cnt + from mx + where ns = 0 + group by mx.cid + having count(pid) > 0; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CNM ba + CNT 13 + """ + +@pytest.mark.version('>=3.0') +def test_bus_3103_windowed_funcs_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_comment_in_object_names.py b/tests/functional/tabloid/test_comment_in_object_names.py new file mode 100644 index 00000000..f2ee006b --- /dev/null +++ b/tests/functional/tabloid/test_comment_in_object_names.py @@ -0,0 +1,121 @@ +#coding:utf-8 +# +# id: functional.tabloid.comment_in_object_names +# title: All DB objects types must allow name COMMENT. Also, COMMENT ON ... must allow occurence of "comment" in it. +# decription: +# Original issue: https://granicus.if.org/pgbugs/15555 +# +# tracker_id: +# min_versions: ['3.0.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter user comment password 'comment'; + + create collation comment for utf8 from unicode case insensitive 'NUMERIC-SORT=1'; + create exception comment 'comment'; + create domain comment varchar(100); + create table comment(comment comment); + create index comment on comment(comment); + create role comment; + create sequence comment; + recreate trigger comment for comment active before insert as begin end; + + comment on database is '"comment": this is database with strange name: "comment"'; + comment on user comment is '"comment": this is user with strange name: "comment"'; + comment on collation comment is '"comment": this is collation with strange name: "comment"'; + comment on exception comment is '"comment": this is exception with strange name: "comment"'; + comment on domain comment is '"comment": this is domain with strange name: "comment"'; + comment on table comment is '"comment": this is table with strange name: "comment"'; + comment on column comment.comment is '"comment": this is a column with strange name: "comment"'; + comment on index comment is '"comment": this is index for table with strange name: "comment"'; + comment on role comment is '"comment": this is role with strange name: "comment"'; + comment on sequence comment is '"comment": this is generator with strange name: "comment"'; + comment on trigger comment is '"comment": this is trigger for table with strange name: "comment"'; + commit; + + drop user comment; + commit; + + + drop table comment; + commit; + + create view comment as select 1 x from rdb$database; + comment on view comment is '"comment": this is view with strange name: "comment"'; + commit; + drop view comment; + commit; + + + create procedure comment as begin end; + comment on procedure comment is '"comment": this is procedure with strange name: "comment"'; + commit; + + set term ^; + create function comment returns comment as + begin + return 'comment'; + end^ + set term ;^ + commit; + + comment on function comment is '"comment": this is function with strange name: "comment"'; + commit; + + set term ^; + create or alter package comment as + begin + function comment returns comment; + procedure comment returns (comment comment); + end + ^ + recreate package body comment as + begin + function comment returns comment as + begin + return 'comment'; + end + + procedure comment returns (comment comment) as + begin + comment='comment'; + suspend; + end + + end + ^ + execute block as + declare comment comment; + begin + comment = 'comment'; + end + ^ + set term ;^ + commit; + + comment on package comment is '"comment": this is procedure with strange name: "comment"'; + commit; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +def test_comment_in_object_names_1(act_1: Action): + act_1.execute() + diff --git a/tests/functional/tabloid/test_core_3611_aux.py b/tests/functional/tabloid/test_core_3611_aux.py new file mode 100644 index 00000000..362e6272 --- /dev/null +++ b/tests/functional/tabloid/test_core_3611_aux.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: functional.tabloid.core_3611_aux +# title: Wrong data while retrieving from CTEs (or derived tables) with same column names +# decription: See another sample in this ticket (by dimitr, 30/Oct/12 07:13 PM) +# tracker_id: CORE-3611 +# min_versions: ['2.5.2'] +# versions: 2.5.2 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.2 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set planonly; + with tab as + ( + select 1 as p1 + from rdb$relations + ) + select f1.p1, f2.p1 as p2 + from tab f1 cross join tab f2 + group by f1.p1 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + 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) + """ + +@pytest.mark.version('>=2.5.2') +def test_core_3611_aux_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/tabloid/test_dbp_0951_multiple_nested_cte.py b/tests/functional/tabloid/test_dbp_0951_multiple_nested_cte.py new file mode 100644 index 00000000..45f9572f --- /dev/null +++ b/tests/functional/tabloid/test_dbp_0951_multiple_nested_cte.py @@ -0,0 +1,304 @@ +#coding:utf-8 +# +# id: functional.tabloid.dbp_0951_multiple_nested_cte +# title: Query for test multiple CTEs +# decription: +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='tabloid-dbp-0951.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + with dup as(select 1 i from rdb$database union all select 2 from rdb$database) + ,mx as + (select iif(d.i=1,q, v) q, iif(d.i=1, v, q) v, 1 d + from( + select distinct + iif(ari<=tbi, ari, tbi) q, + iif(ari<=tbi, tbi, ari) v + from pdata + where ari<>tbi + )t cross join dup d + ) + + ,m2 as + ( + select q,v,min(dx) d + from( + select mp.q, iif(d.i=1, mp.v, mx.v) v,mp.d+d.i-1 dx + from mx mp left join mx on mp.d=1 and mp.v=mx.q and mp.q<>mx.v + cross join dup d where d.i=1 or d.i=2 and mx.v>0 + )t + group by q,v + ) + ,m3 as + ( + select q,v,min(dx) d + from( + select mp.q,iif(d.i=1, mp.v, mx.v) v,mp.d+d.i-1 dx + from m2 mp left join mx on mp.d=2 and mp.v=mx.q and mp.q<>mx.v + cross join dup d where d.i=1 or d.i=2 and mx.v>0 + )t + group by q,v + ) + ,m4 as + ( + select q,v,min(dx) d + from( + select mp.q,iif(d.i=1, mp.v, mx.v) v,mp.d+d.i-1 dx + from m3 mp left join mx on mp.d=3 and mp.v=mx.q and mp.q<>mx.v + cross join dup d where d.i=1 or d.i=2 and mx.v>0 + )t + group by q,v + ) + + ,m5 as + ( + select q,v,min(dx) d + from( + select mp.q,iif(d.i=1, mp.v, mx.v) v,mp.d+d.i-1 dx + from m4 mp left join mx on mp.d=4 and mp.v=mx.q and mp.q<>mx.v + cross join dup d where d.i=1 or d.i=2 and mx.v>0 + )t + group by q,v + ) + + ,m6 as + ( + select q,v,min(dx) d + from( + select mp.q,iif(d.i=1, mp.v, mx.v) v,mp.d+d.i-1 dx + from m5 mp left join mx on mp.d=5 and mp.v=mx.q and mp.q<>mx.v + cross join dup d where d.i=1 or d.i=2 and mx.v>0 + )t + group by q,v + ) + + ,m7 as + ( + select q,v,min(dx) d + from( + select mp.q,iif(d.i=1, mp.v, mx.v) v,mp.d+d.i-1 dx + from m6 mp left join mx on mp.d=6 and mp.v=mx.q and mp.q<>mx.v + cross join dup d where d.i=1 or d.i=2 and mx.v>0 + )t + group by q,v + ) + + ,m8 as + ( + select q,v,min(dx) d + from( + select mp.q,iif(d.i=1, mp.v, mx.v) v,mp.d+d.i-1 dx + from m7 mp left join mx on mp.d=7 and mp.v=mx.q and mp.q<>mx.v + cross join dup d where d.i=1 or d.i=2 and mx.v>0 + )t + group by q,v + ) + + ,m9 as + ( + select q,v,min(dx) d + from( + select mp.q,iif(d.i=1, mp.v, mx.v) v,mp.d+d.i-1 dx + from m8 mp left join mx on mp.d=8 and mp.v=mx.q and mp.q<>mx.v + cross join dup d where d.i=1 or d.i=2 and mx.v>0 + )t + group by q,v + ) + + ,m10 as + ( + select q,v,min(dx) d + from( + select mp.q,iif(d.i=1, mp.v, mx.v) v,mp.d+d.i-1 dx + from m9 mp left join mx on mp.d=9 and mp.v=mx.q and mp.q<>mx.v + cross join dup d where d.i=1 or d.i=2 and mx.v>0 + )t + group by q,v + ) + + ,m11 as + ( + select q,v,min(dx) d + from( + select mp.q,iif(d.i=1, mp.v, mx.v) v,mp.d+d.i-1 dx + from m10 mp left join mx on mp.d=10 and mp.v=mx.q and mp.q<>mx.v + cross join dup d where d.i=1 or d.i=2 and mx.v>0 + )t + group by q,v + ) + + ,m12 as + ( + select q,v,min(dx) d + from( + select mp.q,iif(d.i=1, mp.v, mx.v) v,mp.d+d.i-1 dx + from m11 mp left join mx on mp.d=11 and mp.v=mx.q and mp.q<>mx.v cross join dup d where d.i=1 or d.i=2 and mx.v>0 + )t + group by q,v + ) + + ,m13 as + ( + select q,v,min(dx) d + from( + select mp.q,iif(d.i=1, mp.v, mx.v) v,mp.d+d.i-1 dx + from m12 mp left join mx on mp.d=12 and mp.v=mx.q and mp.q<>mx.v cross join dup d where d.i=1 or d.i=2 and mx.v>0 + )t + group by q,v + ) + + ,m14 as + ( + select q,v,min(dx) d + from( + select mp.q,iif(d.i=1, mp.v, mx.v) v,mp.d+d.i-1 dx + from m13 mp left join mx on mp.d=13 and mp.v=mx.q and mp.q<>mx.v cross join dup d where d.i=1 or d.i=2 and mx.v>0 + )t + group by q,v + ) + + ,m15 as + ( + select q,v,min(dx) d + from( + select mp.q,iif(d.i=1, mp.v, mx.v) v,mp.d+d.i-1 dx + from m14 mp left join mx on mp.d=14 and mp.v=mx.q and mp.q<>mx.v + cross join dup d where d.i=1 or d.i=2 and mx.v>0 + )t + group by q,v + ) + + ,m16 as + ( + select q,v,min(dx) d + from( + select mp.q,iif(d.i=1, mp.v, mx.v) v,mp.d+d.i-1 dx + from m15 mp left join mx on mp.d=15 and mp.v=mx.q and mp.q<>mx.v + cross join dup d where d.i=1 or d.i=2 and mx.v>0 + )t + group by q,v + ) + + ,m17 as + ( + select q,v,min(dx) d + from( + select mp.q,iif(d.i=1, mp.v, mx.v) v,mp.d+d.i-1 dx + from m16 mp left join mx on mp.d=16 and mp.v=mx.q and mp.q<>mx.v + cross join dup d where d.i=1 or d.i=2 and mx.v>0 + )t + group by q,v + ) + + ,m18 as + ( + select q,v,min(dx) d + from( + select mp.q,iif(d.i=1, mp.v, mx.v) v,mp.d+d.i-1 dx + from m17 mp left join mx on mp.d=17 and mp.v=mx.q and mp.q<>mx.v cross join dup d where d.i=1 or d.i=2 and mx.v>0 + )t + group by q,v + ) + + ,m19 as + ( + select + cast(q as varchar(12)) q + ,cast(v as varchar(12)) ||',' v + ,min(dx) d + ,sign(v-q)*dense_rank()over(partition by q order by abs(q-v)) rk + from( + select mp.q,iif(d.i=1, mp.v, mx.v) v,mp.d+d.i-1 dx + from m18 mp left join mx on mp.d=18 and mp.v=mx.q and mp.q<>mx.v cross join dup d where d.i=1 or d.i=2 and mx.v>0 + )t + group by t.q,t.v + ) + ,p as ( + select + q, max(d) d + , max(iif(rk=-59,v,'')) || max(iif(rk=-58,v,'')) || max(iif(rk=-57,v,'')) || max(iif(rk=-56,v,'')) || max(iif(rk=-55,v,'')) + || max(iif(rk=-54,v,'')) || max(iif(rk=-53,v,'')) || max(iif(rk=-52,v,'')) || max(iif(rk=-51,v,'')) || max(iif(rk=-50,v,'')) + || max(iif(rk=-49,v,'')) || max(iif(rk=-48,v,'')) || max(iif(rk=-47,v,'')) || max(iif(rk=-46,v,'')) || max(iif(rk=-45,v,'')) + || max(iif(rk=-44,v,'')) || max(iif(rk=-43,v,'')) || max(iif(rk=-42,v,'')) || max(iif(rk=-41,v,'')) || max(iif(rk=-40,v,'')) + || max(iif(rk=-39,v,'')) || max(iif(rk=-38,v,'')) || max(iif(rk=-37,v,'')) || max(iif(rk=-36,v,'')) || max(iif(rk=-35,v,'')) + || max(iif(rk=-34,v,'')) || max(iif(rk=-33,v,'')) || max(iif(rk=-32,v,'')) || max(iif(rk=-31,v,'')) || max(iif(rk=-30,v,'')) + || max(iif(rk=-29,v,'')) || max(iif(rk=-28,v,'')) || max(iif(rk=-27,v,'')) || max(iif(rk=-26,v,'')) || max(iif(rk=-25,v,'')) + || max(iif(rk=-24,v,'')) || max(iif(rk=-23,v,'')) || max(iif(rk=-22,v,'')) || max(iif(rk=-21,v,'')) || max(iif(rk=-20,v,'')) + || max(iif(rk=-19,v,'')) || max(iif(rk=-18,v,'')) || max(iif(rk=-17,v,'')) || max(iif(rk=-16,v,'')) || max(iif(rk=-15,v,'')) + || max(iif(rk=-14,v,'')) || max(iif(rk=-13,v,'')) || max(iif(rk=-12,v,'')) || max(iif(rk=-11,v,'')) || max(iif(rk=-10,v,'')) + || max(iif(rk=-09,v,'')) || max(iif(rk=-08,v,'')) || max(iif(rk=-07,v,'')) || max(iif(rk=-06,v,'')) || max(iif(rk=-05,v,'')) + || max(iif(rk=-04,v,'')) || max(iif(rk=-03,v,'')) || max(iif(rk=-02,v,'')) || max(iif(rk=-01,v,'')) + || q || ',' + || max(iif(rk= 01,v,'')) || max(iif(rk= 02,v,'')) || max(iif(rk= 03,v,'')) || max(iif(rk= 04,v,'')) || max(iif(rk= 05,v,'')) + || max(iif(rk= 06,v,'')) || max(iif(rk= 07,v,'')) || max(iif(rk= 08,v,'')) || max(iif(rk= 09,v,'')) + || max(iif(rk= 10,v,'')) || max(iif(rk= 11,v,'')) || max(iif(rk= 12,v,'')) || max(iif(rk= 13,v,'')) || max(iif(rk= 14,v,'')) + || max(iif(rk= 15,v,'')) || max(iif(rk= 16,v,'')) || max(iif(rk= 17,v,'')) || max(iif(rk= 18,v,'')) || max(iif(rk= 19,v,'')) + || max(iif(rk= 20,v,'')) || max(iif(rk= 21,v,'')) || max(iif(rk= 22,v,'')) || max(iif(rk= 23,v,'')) || max(iif(rk= 24,v,'')) + || max(iif(rk= 25,v,'')) || max(iif(rk= 26,v,'')) || max(iif(rk= 27,v,'')) || max(iif(rk= 28,v,'')) || max(iif(rk= 29,v,'')) + || max(iif(rk= 30,v,'')) || max(iif(rk= 31,v,'')) || max(iif(rk= 32,v,'')) || max(iif(rk= 33,v,'')) || max(iif(rk= 34,v,'')) + || max(iif(rk= 35,v,'')) || max(iif(rk= 36,v,'')) || max(iif(rk= 37,v,'')) || max(iif(rk= 38,v,'')) || max(iif(rk= 39,v,'')) + || max(iif(rk= 40,v,'')) || max(iif(rk= 41,v,'')) || max(iif(rk= 42,v,'')) || max(iif(rk= 43,v,'')) || max(iif(rk= 44,v,'')) + || max(iif(rk= 45,v,'')) || max(iif(rk= 46,v,'')) || max(iif(rk= 47,v,'')) || max(iif(rk= 48,v,'')) || max(iif(rk= 49,v,'')) + || max(iif(rk= 50,v,'')) || max(iif(rk= 51,v,'')) || max(iif(rk= 52,v,'')) || max(iif(rk= 53,v,'')) || max(iif(rk= 54,v,'')) + || max(iif(rk= 55,v,'')) || max(iif(rk= 56,v,'')) || max(iif(rk= 57,v,'')) || max(iif(rk= 58,v,'')) || max(iif(rk= 59,v,'')) + as s + from m19 + group by q + ) + select count(*) c,max(d) d, left(s, char_length(s)-1) s + from p + group by s + order by 1,2,3 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + C 2 + D 1 + S 4,37 + C 2 + D 1 + S 8,38 + C 4 + D 3 + S 13,14,39,40 + C 6 + D 4 + S 15,16,41,42,43,47 + C 6 + D 4 + S 21,22,48,49,50,51 + C 7 + D 2 + S 10,25,26,27,28,29,30 + C 7 + D 4 + S 17,18,19,20,44,45,46 + C 8 + D 2 + S 11,12,31,32,33,34,35,36 + """ + +@pytest.mark.version('>=3.0') +def test_dbp_0951_multiple_nested_cte_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_dbp_1697_windowed_funcs.py b/tests/functional/tabloid/test_dbp_1697_windowed_funcs.py new file mode 100644 index 00000000..d0f8bf80 --- /dev/null +++ b/tests/functional/tabloid/test_dbp_1697_windowed_funcs.py @@ -0,0 +1,108 @@ +#coding:utf-8 +# +# id: functional.tabloid.dbp_1697_windowed_funcs +# title: Query for test SUM()OVER() and COUNT()OVER(). +# decription: +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='tabloid-dbp-1697.fbk', init=init_script_1) + +test_script_1 = """ + delete from tresult; + -------------------- + insert into tresult + with + x as( + select ari q, tbi v, sum(cv) cv from pdata group by ari, tbi + ) + ,y as ( + select q, v + ,sum(iif( tc = 'Romania', cv, null))over(partition by q) rmn + ,sum(iif( tc = 'France', cv, null))over(partition by q) frn + ,sum(iif( tc = 'Belgium', cv, null))over(partition by q) bgm + from x + join ptube on v=id + ) + + select ari + from pdata x + join ptube on tbi=id + group by ari + having + coalesce(sum(iif( tc = 'Romania', cv, null)),0) between 0 and 50 + and sum(iif( tc = 'France', cv, null)) between 50 and 100 + and sum(iif( tc = 'Belgium', cv, null)) between 100 and 150 + and not exists( + select q + from ( + select q, v + from y -- do not add `x` ==> CTE 'X' has cyclic dependencies + where coalesce(rmn,0) between 0 and 50 and frn between 50 and 100 and bgm between 100 and 150 + ) y + join pdata on tbi=v + where q<>x.ari and ari=x.ari + group by q + having min(v)<>max(v) + ) + ; + + insert into tresult + with + t as ( + select ari + ,sum(case when tc = 'Romania' then cv else 0 end) as rmn + ,sum(case when tc = 'France' then cv else 0 end) as frn + ,sum(case when tc = 'Belgium' then cv else 0 end) as bgm + from pdata join ptube on ptube.id = pdata.tbi + group by ari + ) + ,t1 as( + select ari, rmn, frn, bgm + from t + where + t.rmn between 0 and 50 + and t.frn between 50 and 100 + and t.bgm between 100 and 150 + ) + ,t2 as( + select distinct ub1.ari, ub1.tbi v1, ub2.tbi v2 + from pdata ub1 + join pdata ub2 on ub2.ari = ub1.ari and ub1.tbi < ub2.tbi + ) + ,f as( + select t1.ari, t2.v1, t2.v2 + ,count(*)over(partition by bin_or( bin_shl(t2.v1,32), t2.v2)) s + from t1 + join t2 on t2.ari = t1.ari + ) + select ari from f + group by ari + having max(s) = 1 + ; + + + -- check result of subsequent inserts (instead of heavy full join) for mimatches: + --------------- + select id,count(*) from tresult group by id having count(*)<>2; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=3.0') +def test_dbp_1697_windowed_funcs_1(act_1: Action): + act_1.execute() + diff --git a/tests/functional/tabloid/test_dbp_1940_20040130_1740.py b/tests/functional/tabloid/test_dbp_1940_20040130_1740.py new file mode 100644 index 00000000..ba6d5744 --- /dev/null +++ b/tests/functional/tabloid/test_dbp_1940_20040130_1740.py @@ -0,0 +1,147 @@ +#coding:utf-8 +# +# id: functional.tabloid.dbp_1940_20040130_1740 +# title: Common SQL. Check correctness of the results +# decription: +# tracker_id: +# min_versions: ['2.5.3'] +# versions: 2.5.3 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.3 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='tabloid-dbp-1940.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + with recursive + a1 as ( + select min(q.tm) as mt from + (select xxx.tm, + (select count(vi) from + (select y.vi, sum( bv ) as bv + from bbb y + where y.tm<=xxx.tm + group by vi + )ws where ws.bv=255 )as cntr + from bbb xxx + )q where q.cntr>0 + ) + ,a2 as ( + select 0 i from rdb$database union all select r.i+1 from a2 as r where r.i<29 + ) + ,b1 as ( + select dateadd(a2.i second to a1.mt) as ww1 + from a1, a2 + ) + ,b2 as + (select tm from bbb) + ,c as ( + select * + from b1, b2 + where b1.ww1>=b2.tm + ) + --select * from c + + ,d1 as ( + select ww1,max(tm) as maxt + from c group by ww1 + ) + -- select * from d1 + ,d2 as ( + select xxx.tm, + (select count(vi) from + (select vi, sum( bv ) as bv + from bbb y + where y.tm<=xxx.tm + group by vi + )ws where ws.bv>=85 and ws.bv<=170 + )as cntr + from bbb xxx + ) + select distinct ww1 as f01, cntr as f02 + from d1,d2 + where d1.maxt=d2.tm + order by 1,2 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F01 2003-01-01 01:11:00.0000 + F02 1 + F01 2003-01-01 01:11:01.0000 + F02 3 + F01 2003-01-01 01:11:02.0000 + F02 4 + F01 2003-01-01 01:11:03.0000 + F02 4 + F01 2003-01-01 01:11:04.0000 + F02 3 + F01 2003-01-01 01:11:05.0000 + F02 3 + F01 2003-01-01 01:11:06.0000 + F02 3 + F01 2003-01-01 01:11:07.0000 + F02 3 + F01 2003-01-01 01:11:08.0000 + F02 3 + F01 2003-01-01 01:11:09.0000 + F02 3 + F01 2003-01-01 01:11:10.0000 + F02 4 + F01 2003-01-01 01:11:11.0000 + F02 5 + F01 2003-01-01 01:11:12.0000 + F02 4 + F01 2003-01-01 01:11:13.0000 + F02 4 + F01 2003-01-01 01:11:14.0000 + F02 3 + F01 2003-01-01 01:11:15.0000 + F02 3 + F01 2003-01-01 01:11:16.0000 + F02 3 + F01 2003-01-01 01:11:17.0000 + F02 4 + F01 2003-01-01 01:11:18.0000 + F02 4 + F01 2003-01-01 01:11:19.0000 + F02 4 + F01 2003-01-01 01:11:20.0000 + F02 4 + F01 2003-01-01 01:11:21.0000 + F02 4 + F01 2003-01-01 01:11:22.0000 + F02 4 + F01 2003-01-01 01:11:23.0000 + F02 4 + F01 2003-01-01 01:11:24.0000 + F02 4 + F01 2003-01-01 01:11:25.0000 + F02 4 + F01 2003-01-01 01:11:26.0000 + F02 4 + F01 2003-01-01 01:11:27.0000 + F02 4 + F01 2003-01-01 01:11:28.0000 + F02 4 + F01 2003-01-01 01:11:29.0000 + F02 4 + """ + +@pytest.mark.version('>=2.5.3') +def test_dbp_1940_20040130_1740_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_dbp_1940_20061108_2141.py b/tests/functional/tabloid/test_dbp_1940_20061108_2141.py new file mode 100644 index 00000000..2c720d16 --- /dev/null +++ b/tests/functional/tabloid/test_dbp_1940_20061108_2141.py @@ -0,0 +1,119 @@ +#coding:utf-8 +# +# id: functional.tabloid.dbp_1940_20061108_2141 +# title: Common SQL. Check correctness of the results +# decription: +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='tabloid-dbp-1940.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + select + dateadd(n-1 second to dat) f01 + ,(select count(*) from + (select vi, sum(bv) as s from bbb where + dateadd(n-1 second to dat)>=tm + group by vi + having sum(bv) between 85 and 170) t + ) f02 + from + ( select row_number() over(order by qi) n from bbb rows 30 ) z + cross join + ( + select min(tm) as dat from bbb b + where exists ( + select vi, sum(bv) from bbb + where b.tm>=tm + group by vi + having sum(bv)=255 + ) + ) q + order by 1,2 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F01 2003-01-01 01:11:00.0000 + F02 1 + F01 2003-01-01 01:11:01.0000 + F02 3 + F01 2003-01-01 01:11:02.0000 + F02 4 + F01 2003-01-01 01:11:03.0000 + F02 4 + F01 2003-01-01 01:11:04.0000 + F02 3 + F01 2003-01-01 01:11:05.0000 + F02 3 + F01 2003-01-01 01:11:06.0000 + F02 3 + F01 2003-01-01 01:11:07.0000 + F02 3 + F01 2003-01-01 01:11:08.0000 + F02 3 + F01 2003-01-01 01:11:09.0000 + F02 3 + F01 2003-01-01 01:11:10.0000 + F02 4 + F01 2003-01-01 01:11:11.0000 + F02 5 + F01 2003-01-01 01:11:12.0000 + F02 4 + F01 2003-01-01 01:11:13.0000 + F02 4 + F01 2003-01-01 01:11:14.0000 + F02 3 + F01 2003-01-01 01:11:15.0000 + F02 3 + F01 2003-01-01 01:11:16.0000 + F02 3 + F01 2003-01-01 01:11:17.0000 + F02 4 + F01 2003-01-01 01:11:18.0000 + F02 4 + F01 2003-01-01 01:11:19.0000 + F02 4 + F01 2003-01-01 01:11:20.0000 + F02 4 + F01 2003-01-01 01:11:21.0000 + F02 4 + F01 2003-01-01 01:11:22.0000 + F02 4 + F01 2003-01-01 01:11:23.0000 + F02 4 + F01 2003-01-01 01:11:24.0000 + F02 4 + F01 2003-01-01 01:11:25.0000 + F02 4 + F01 2003-01-01 01:11:26.0000 + F02 4 + F01 2003-01-01 01:11:27.0000 + F02 4 + F01 2003-01-01 01:11:28.0000 + F02 4 + F01 2003-01-01 01:11:29.0000 + F02 4 + """ + +@pytest.mark.version('>=3.0') +def test_dbp_1940_20061108_2141_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_dbp_1940_20080912_1005.py b/tests/functional/tabloid/test_dbp_1940_20080912_1005.py new file mode 100644 index 00000000..14399ff1 --- /dev/null +++ b/tests/functional/tabloid/test_dbp_1940_20080912_1005.py @@ -0,0 +1,128 @@ +#coding:utf-8 +# +# id: functional.tabloid.dbp_1940_20080912_1005 +# title: Common SQL. Check correctness of the results +# decription: +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='tabloid-dbp-1940.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + select + x.t as f01 + ,( + select count(distinct iif(bx.s>=85 and bx.s<=170,bx.vi, null)) + from ( + select + x2.vi + ,x2.s + ,row_number()over(partition by x2.vi order by x2.t desc) rn2 + from ( + select b.vi, b.tm t + ,(select sum(b2.bv) from bbb b2 where b2.vi=b.vi and b2.tm<=b.tm) s + from bbb b + ) x2 + where x2.t<=x.t + ) bx + where bx.rn2=1 + ) as f02 + from ( + select dateadd(q2.s second to q3.t) t + from ( select min(q1.tm) t + from ( + select b.tm + ,(select sum(b2.bv) from bbb b2 where b.vi=b2.vi and b2.tm<=b.tm) s + from bbb b + ) q1 + where q1.s=255 + ) q3 + , (select row_number()over(order by bbb.qi)-1 s from bbb rows 30) q2 + ) x + order by 1,2; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F01 2003-01-01 01:11:00.0000 + F02 1 + F01 2003-01-01 01:11:01.0000 + F02 3 + F01 2003-01-01 01:11:02.0000 + F02 4 + F01 2003-01-01 01:11:03.0000 + F02 4 + F01 2003-01-01 01:11:04.0000 + F02 3 + F01 2003-01-01 01:11:05.0000 + F02 3 + F01 2003-01-01 01:11:06.0000 + F02 3 + F01 2003-01-01 01:11:07.0000 + F02 3 + F01 2003-01-01 01:11:08.0000 + F02 3 + F01 2003-01-01 01:11:09.0000 + F02 3 + F01 2003-01-01 01:11:10.0000 + F02 4 + F01 2003-01-01 01:11:11.0000 + F02 5 + F01 2003-01-01 01:11:12.0000 + F02 4 + F01 2003-01-01 01:11:13.0000 + F02 4 + F01 2003-01-01 01:11:14.0000 + F02 3 + F01 2003-01-01 01:11:15.0000 + F02 3 + F01 2003-01-01 01:11:16.0000 + F02 3 + F01 2003-01-01 01:11:17.0000 + F02 4 + F01 2003-01-01 01:11:18.0000 + F02 4 + F01 2003-01-01 01:11:19.0000 + F02 4 + F01 2003-01-01 01:11:20.0000 + F02 4 + F01 2003-01-01 01:11:21.0000 + F02 4 + F01 2003-01-01 01:11:22.0000 + F02 4 + F01 2003-01-01 01:11:23.0000 + F02 4 + F01 2003-01-01 01:11:24.0000 + F02 4 + F01 2003-01-01 01:11:25.0000 + F02 4 + F01 2003-01-01 01:11:26.0000 + F02 4 + F01 2003-01-01 01:11:27.0000 + F02 4 + F01 2003-01-01 01:11:28.0000 + F02 4 + F01 2003-01-01 01:11:29.0000 + F02 4 + """ + +@pytest.mark.version('>=3.0') +def test_dbp_1940_20080912_1005_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_dbp_1940_20090521_1520.py b/tests/functional/tabloid/test_dbp_1940_20090521_1520.py new file mode 100644 index 00000000..8762e8e1 --- /dev/null +++ b/tests/functional/tabloid/test_dbp_1940_20090521_1520.py @@ -0,0 +1,122 @@ +#coding:utf-8 +# +# id: functional.tabloid.dbp_1940_20090521_1520 +# title: Common SQL. Check correctness of the results +# decription: +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='tabloid-dbp-1940.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + with recursive + n as ( + select 0 s from rdb$database union all select r.s+1 from n as r where r.s<29 + ) + select + f01 + ,coalesce( + ( + select distinct count(vi)over() + from bbb + where tm<=f01 + group by vi + having 255-sum(bv) between 255/3 and 255*2/3 + ) + ,0 + ) f02 + from ( + select dateadd(n.s second to min(tm)) f01 + from bbb a + cross join n + where (select sum(bv) from bbb where vi=a.vi and tm<=a.tm)=255 + group by n.s + ) w + order by 1,2 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F01 2003-01-01 01:11:00.0000 + F02 1 + F01 2003-01-01 01:11:01.0000 + F02 3 + F01 2003-01-01 01:11:02.0000 + F02 4 + F01 2003-01-01 01:11:03.0000 + F02 4 + F01 2003-01-01 01:11:04.0000 + F02 3 + F01 2003-01-01 01:11:05.0000 + F02 3 + F01 2003-01-01 01:11:06.0000 + F02 3 + F01 2003-01-01 01:11:07.0000 + F02 3 + F01 2003-01-01 01:11:08.0000 + F02 3 + F01 2003-01-01 01:11:09.0000 + F02 3 + F01 2003-01-01 01:11:10.0000 + F02 4 + F01 2003-01-01 01:11:11.0000 + F02 5 + F01 2003-01-01 01:11:12.0000 + F02 4 + F01 2003-01-01 01:11:13.0000 + F02 4 + F01 2003-01-01 01:11:14.0000 + F02 3 + F01 2003-01-01 01:11:15.0000 + F02 3 + F01 2003-01-01 01:11:16.0000 + F02 3 + F01 2003-01-01 01:11:17.0000 + F02 4 + F01 2003-01-01 01:11:18.0000 + F02 4 + F01 2003-01-01 01:11:19.0000 + F02 4 + F01 2003-01-01 01:11:20.0000 + F02 4 + F01 2003-01-01 01:11:21.0000 + F02 4 + F01 2003-01-01 01:11:22.0000 + F02 4 + F01 2003-01-01 01:11:23.0000 + F02 4 + F01 2003-01-01 01:11:24.0000 + F02 4 + F01 2003-01-01 01:11:25.0000 + F02 4 + F01 2003-01-01 01:11:26.0000 + F02 4 + F01 2003-01-01 01:11:27.0000 + F02 4 + F01 2003-01-01 01:11:28.0000 + F02 4 + F01 2003-01-01 01:11:29.0000 + F02 4 + """ + +@pytest.mark.version('>=3.0') +def test_dbp_1940_20090521_1520_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_dbp_1940_20110426_1906.py b/tests/functional/tabloid/test_dbp_1940_20110426_1906.py new file mode 100644 index 00000000..bd241d00 --- /dev/null +++ b/tests/functional/tabloid/test_dbp_1940_20110426_1906.py @@ -0,0 +1,139 @@ +#coding:utf-8 +# +# id: functional.tabloid.dbp_1940_20110426_1906 +# title: Common SQL. Check correctness of the results +# decription: +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='tabloid-dbp-1940.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + with recursive + n as ( + select 0 n from rdb$database union all select r.n+1 from n as r where r.n<29 + ) + ,t as ( + select min(d) dd + from + ( + select b.vi v, b.tm d, sum(b1.bv) as vol + from bbb b left join bbb b1 on b1.vi=b.vi + and b1.tm <= b.tm + group by b.vi, b.tm + ) cc + where vol = 255 + ) + ,b as ( + select b.vi v, b.tm d, sum(b1.bv) as vol + from bbb b + left join bbb b1 on b1.vi=b.vi and b1.tm <= b.tm + group by b.vi, b.tm + ) + ,t1 as ( + select dateadd(n second to dd) d + from t, n + ) + ,tx as + ( + select t1.d as f01, count(distinct t2.v) f02 + from t1 + left join + ( + select v, d, vol + from b + where vol between 85 and 170 + ) t2 + on t2.d<=t1.d + where 170 > all (select vol from b where b.v=t2.v and b.d<=t1.d) + group by t1.d + ) + select * from tx + order by 1,2 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F01 2003-01-01 01:11:00.0000 + F02 1 + F01 2003-01-01 01:11:01.0000 + F02 3 + F01 2003-01-01 01:11:02.0000 + F02 4 + F01 2003-01-01 01:11:03.0000 + F02 4 + F01 2003-01-01 01:11:04.0000 + F02 3 + F01 2003-01-01 01:11:05.0000 + F02 3 + F01 2003-01-01 01:11:06.0000 + F02 3 + F01 2003-01-01 01:11:07.0000 + F02 3 + F01 2003-01-01 01:11:08.0000 + F02 3 + F01 2003-01-01 01:11:09.0000 + F02 3 + F01 2003-01-01 01:11:10.0000 + F02 4 + F01 2003-01-01 01:11:11.0000 + F02 5 + F01 2003-01-01 01:11:12.0000 + F02 4 + F01 2003-01-01 01:11:13.0000 + F02 4 + F01 2003-01-01 01:11:14.0000 + F02 3 + F01 2003-01-01 01:11:15.0000 + F02 3 + F01 2003-01-01 01:11:16.0000 + F02 3 + F01 2003-01-01 01:11:17.0000 + F02 4 + F01 2003-01-01 01:11:18.0000 + F02 4 + F01 2003-01-01 01:11:19.0000 + F02 4 + F01 2003-01-01 01:11:20.0000 + F02 4 + F01 2003-01-01 01:11:21.0000 + F02 4 + F01 2003-01-01 01:11:22.0000 + F02 4 + F01 2003-01-01 01:11:23.0000 + F02 4 + F01 2003-01-01 01:11:24.0000 + F02 4 + F01 2003-01-01 01:11:25.0000 + F02 4 + F01 2003-01-01 01:11:26.0000 + F02 4 + F01 2003-01-01 01:11:27.0000 + F02 4 + F01 2003-01-01 01:11:28.0000 + F02 4 + F01 2003-01-01 01:11:29.0000 + F02 4 + """ + +@pytest.mark.version('>=3.0') +def test_dbp_1940_20110426_1906_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_dbp_1940_20110725_1159.py b/tests/functional/tabloid/test_dbp_1940_20110725_1159.py new file mode 100644 index 00000000..56520106 --- /dev/null +++ b/tests/functional/tabloid/test_dbp_1940_20110725_1159.py @@ -0,0 +1,146 @@ +#coding:utf-8 +# +# id: functional.tabloid.dbp_1940_20110725_1159 +# title: Common SQL. Check correctness of the results +# decription: +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='tabloid-dbp-1940.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + with + a as ( + select + sum( max(t1.bv) )over(partition by t1.vi) sv + ,max(t1.tm)over(partition by t1.vi) mt + ,sum(coalesce(t2.bv, 0)) + max(t1.bv) rt + ,t1.vi + ,t1.tm + from bbb t1 + left join bbb t2 + on t2.vi = t1.vi and t2.tm < t1.tm + group by t1.vi,t1.tm + ) + ,b as( + select + iif( t.sv = 255, min(t.mt)over(partition by iif(t.sv = 255,1,null)), null) as mt + ,t.sv + ,t.tm + ,t.vi + ,t.rt + from a t + ) + ,c as ( + select + min(t.mt)over() mt + ,t.tm + ,t.vi + ,t.rt + from b t + ) + ,d as ( + select + t.vi, + dateadd(t2.rn second to t.mt) xdt, + max(iif(t.tm > dateadd(t2.rn second to t.mt) and t.tm >= dateadd(t2.rn second to t.mt), 0, t.rt) ) rt + from c t + cross join ( + select t.rn + from (select row_number()over(order by (tm))-1 rn from bbb) t + where t.rn < 30 + ) t2 + group by 1,2 + ) + select t.xdt f01, count(*) f02 + from d t + where t.rt >= 255. / 3. and t.rt <= ( 255. / 3. ) * 2. + group by 1 + order by 1,2 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F01 2003-01-01 01:11:00.0000 + F02 1 + F01 2003-01-01 01:11:01.0000 + F02 3 + F01 2003-01-01 01:11:02.0000 + F02 4 + F01 2003-01-01 01:11:03.0000 + F02 4 + F01 2003-01-01 01:11:04.0000 + F02 3 + F01 2003-01-01 01:11:05.0000 + F02 3 + F01 2003-01-01 01:11:06.0000 + F02 3 + F01 2003-01-01 01:11:07.0000 + F02 3 + F01 2003-01-01 01:11:08.0000 + F02 3 + F01 2003-01-01 01:11:09.0000 + F02 3 + F01 2003-01-01 01:11:10.0000 + F02 4 + F01 2003-01-01 01:11:11.0000 + F02 5 + F01 2003-01-01 01:11:12.0000 + F02 4 + F01 2003-01-01 01:11:13.0000 + F02 4 + F01 2003-01-01 01:11:14.0000 + F02 3 + F01 2003-01-01 01:11:15.0000 + F02 3 + F01 2003-01-01 01:11:16.0000 + F02 3 + F01 2003-01-01 01:11:17.0000 + F02 4 + F01 2003-01-01 01:11:18.0000 + F02 4 + F01 2003-01-01 01:11:19.0000 + F02 4 + F01 2003-01-01 01:11:20.0000 + F02 4 + F01 2003-01-01 01:11:21.0000 + F02 4 + F01 2003-01-01 01:11:22.0000 + F02 4 + F01 2003-01-01 01:11:23.0000 + F02 4 + F01 2003-01-01 01:11:24.0000 + F02 4 + F01 2003-01-01 01:11:25.0000 + F02 4 + F01 2003-01-01 01:11:26.0000 + F02 4 + F01 2003-01-01 01:11:27.0000 + F02 4 + F01 2003-01-01 01:11:28.0000 + F02 4 + F01 2003-01-01 01:11:29.0000 + F02 4 + """ + +@pytest.mark.version('>=3.0') +def test_dbp_1940_20110725_1159_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_dbp_1940_20130412_1008.py b/tests/functional/tabloid/test_dbp_1940_20130412_1008.py new file mode 100644 index 00000000..64092889 --- /dev/null +++ b/tests/functional/tabloid/test_dbp_1940_20130412_1008.py @@ -0,0 +1,138 @@ +#coding:utf-8 +# +# id: functional.tabloid.dbp_1940_20130412_1008 +# title: Common SQL. Check correctness of the results +# decription: +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='tabloid-dbp-1940.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + with recursive + s as ( + select 0 rn from rdb$database union all select s.rn+1 from s where s.rn<29 + ) + ,b as ( + select + max(tm) mdate + from bbb + where vi + in( + select vi + from bbb + group by vi + having sum(bv) = 255 + ) + group by vi + order by max(tm) rows 1 + ) + ,t as ( + select dateadd(s.rn second to b.mdate) mdate + from b cross join s + ) + ,e as ( + select t.mdate f01 + ,( + select count(s) from + ( + select sum(x.bv) s + from bbb x + where x.tm <= t.mdate + group by x.vi + having sum(x.bv) between 85 and 170 + ) + ) f02 + from t + ) + select f01,f02 + from e + where f02>0 + order by 1,2 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F01 2003-01-01 01:11:00.0000 + F02 1 + F01 2003-01-01 01:11:01.0000 + F02 3 + F01 2003-01-01 01:11:02.0000 + F02 4 + F01 2003-01-01 01:11:03.0000 + F02 4 + F01 2003-01-01 01:11:04.0000 + F02 3 + F01 2003-01-01 01:11:05.0000 + F02 3 + F01 2003-01-01 01:11:06.0000 + F02 3 + F01 2003-01-01 01:11:07.0000 + F02 3 + F01 2003-01-01 01:11:08.0000 + F02 3 + F01 2003-01-01 01:11:09.0000 + F02 3 + F01 2003-01-01 01:11:10.0000 + F02 4 + F01 2003-01-01 01:11:11.0000 + F02 5 + F01 2003-01-01 01:11:12.0000 + F02 4 + F01 2003-01-01 01:11:13.0000 + F02 4 + F01 2003-01-01 01:11:14.0000 + F02 3 + F01 2003-01-01 01:11:15.0000 + F02 3 + F01 2003-01-01 01:11:16.0000 + F02 3 + F01 2003-01-01 01:11:17.0000 + F02 4 + F01 2003-01-01 01:11:18.0000 + F02 4 + F01 2003-01-01 01:11:19.0000 + F02 4 + F01 2003-01-01 01:11:20.0000 + F02 4 + F01 2003-01-01 01:11:21.0000 + F02 4 + F01 2003-01-01 01:11:22.0000 + F02 4 + F01 2003-01-01 01:11:23.0000 + F02 4 + F01 2003-01-01 01:11:24.0000 + F02 4 + F01 2003-01-01 01:11:25.0000 + F02 4 + F01 2003-01-01 01:11:26.0000 + F02 4 + F01 2003-01-01 01:11:27.0000 + F02 4 + F01 2003-01-01 01:11:28.0000 + F02 4 + F01 2003-01-01 01:11:29.0000 + F02 4 + """ + +@pytest.mark.version('>=3.0') +def test_dbp_1940_20130412_1008_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_dbp_1940_20130831_2039.py b/tests/functional/tabloid/test_dbp_1940_20130831_2039.py new file mode 100644 index 00000000..3cc484c1 --- /dev/null +++ b/tests/functional/tabloid/test_dbp_1940_20130831_2039.py @@ -0,0 +1,127 @@ +#coding:utf-8 +# +# id: functional.tabloid.dbp_1940_20130831_2039 +# title: Common SQL. Check correctness of the results +# decription: +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='tabloid-dbp-1940.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + with recursive + n as ( + select 0 n from rdb$database union all select s.n+1 from n s where s.n<29 + ) + ,b1 as ( + select min(mt) st + from ( + select yyy.*, bbb.*, + sum(bv)over(partition by yyy.id) sv, + max(tm)over(partition by yyy.id) mt + from yyy join bbb on vi = yyy.id + ) z + where sv = 255 + ) + ,b2 as ( + select dateadd(n.n second to b1.st) f01 + from b1, n + ) + select f01 + ,(select count(distinct id) + from ( + select yyy.*, bbb.*, + sum(bv)over(partition by yyy.id) sv + from yyy join bbb on vi = yyy.id + where tm <= f01 + ) x + where sv >= 255/3 and sv < 2*255/3 + ) f02 + from b2 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F01 2003-01-01 01:11:00.0000 + F02 1 + F01 2003-01-01 01:11:01.0000 + F02 3 + F01 2003-01-01 01:11:02.0000 + F02 4 + F01 2003-01-01 01:11:03.0000 + F02 4 + F01 2003-01-01 01:11:04.0000 + F02 3 + F01 2003-01-01 01:11:05.0000 + F02 3 + F01 2003-01-01 01:11:06.0000 + F02 3 + F01 2003-01-01 01:11:07.0000 + F02 3 + F01 2003-01-01 01:11:08.0000 + F02 3 + F01 2003-01-01 01:11:09.0000 + F02 3 + F01 2003-01-01 01:11:10.0000 + F02 4 + F01 2003-01-01 01:11:11.0000 + F02 5 + F01 2003-01-01 01:11:12.0000 + F02 4 + F01 2003-01-01 01:11:13.0000 + F02 4 + F01 2003-01-01 01:11:14.0000 + F02 3 + F01 2003-01-01 01:11:15.0000 + F02 3 + F01 2003-01-01 01:11:16.0000 + F02 3 + F01 2003-01-01 01:11:17.0000 + F02 4 + F01 2003-01-01 01:11:18.0000 + F02 4 + F01 2003-01-01 01:11:19.0000 + F02 4 + F01 2003-01-01 01:11:20.0000 + F02 4 + F01 2003-01-01 01:11:21.0000 + F02 4 + F01 2003-01-01 01:11:22.0000 + F02 4 + F01 2003-01-01 01:11:23.0000 + F02 4 + F01 2003-01-01 01:11:24.0000 + F02 4 + F01 2003-01-01 01:11:25.0000 + F02 4 + F01 2003-01-01 01:11:26.0000 + F02 4 + F01 2003-01-01 01:11:27.0000 + F02 4 + F01 2003-01-01 01:11:28.0000 + F02 4 + F01 2003-01-01 01:11:29.0000 + F02 4 + """ + +@pytest.mark.version('>=3.0') +def test_dbp_1940_20130831_2039_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_dbp_1940_20130912_1908.py b/tests/functional/tabloid/test_dbp_1940_20130912_1908.py new file mode 100644 index 00000000..06aa3deb --- /dev/null +++ b/tests/functional/tabloid/test_dbp_1940_20130912_1908.py @@ -0,0 +1,124 @@ +#coding:utf-8 +# +# id: functional.tabloid.dbp_1940_20130912_1908 +# title: Common SQL. Check correctness of the results +# decription: +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='tabloid-dbp-1940.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + with + bx as( select tm,sum(bv)over(partition by vi order by tm)s from bbb) + select distinct d f01, count( iif(v >= 85 and v <= 170 , 1, null))over(partition by d) f02 + from + ( + select d,i,sum(v)v + from + ( + select vi i,bv v + ,dateadd(s.ns second to + ( select min(tm) + from bx a + where s = 255 + ) + ) d + from bbb + left join (select row_number()over(order by vi)-1 ns from bbb)s on s.ns<=29 + where tm <= + ( + select dateadd( s.ns second to min(tm) )m + from bx a + where s = 255 + ) + )a + group by d,i + )a + order by 1,2; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F01 2003-01-01 01:11:00.0000 + F02 1 + F01 2003-01-01 01:11:01.0000 + F02 3 + F01 2003-01-01 01:11:02.0000 + F02 4 + F01 2003-01-01 01:11:03.0000 + F02 4 + F01 2003-01-01 01:11:04.0000 + F02 3 + F01 2003-01-01 01:11:05.0000 + F02 3 + F01 2003-01-01 01:11:06.0000 + F02 3 + F01 2003-01-01 01:11:07.0000 + F02 3 + F01 2003-01-01 01:11:08.0000 + F02 3 + F01 2003-01-01 01:11:09.0000 + F02 3 + F01 2003-01-01 01:11:10.0000 + F02 4 + F01 2003-01-01 01:11:11.0000 + F02 5 + F01 2003-01-01 01:11:12.0000 + F02 4 + F01 2003-01-01 01:11:13.0000 + F02 4 + F01 2003-01-01 01:11:14.0000 + F02 3 + F01 2003-01-01 01:11:15.0000 + F02 3 + F01 2003-01-01 01:11:16.0000 + F02 3 + F01 2003-01-01 01:11:17.0000 + F02 4 + F01 2003-01-01 01:11:18.0000 + F02 4 + F01 2003-01-01 01:11:19.0000 + F02 4 + F01 2003-01-01 01:11:20.0000 + F02 4 + F01 2003-01-01 01:11:21.0000 + F02 4 + F01 2003-01-01 01:11:22.0000 + F02 4 + F01 2003-01-01 01:11:23.0000 + F02 4 + F01 2003-01-01 01:11:24.0000 + F02 4 + F01 2003-01-01 01:11:25.0000 + F02 4 + F01 2003-01-01 01:11:26.0000 + F02 4 + F01 2003-01-01 01:11:27.0000 + F02 4 + F01 2003-01-01 01:11:28.0000 + F02 4 + F01 2003-01-01 01:11:29.0000 + F02 4 + """ + +@pytest.mark.version('>=3.0') +def test_dbp_1940_20130912_1908_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_dbp_2146_distinct_not_in.py b/tests/functional/tabloid/test_dbp_2146_distinct_not_in.py new file mode 100644 index 00000000..f864d9d1 --- /dev/null +++ b/tests/functional/tabloid/test_dbp_2146_distinct_not_in.py @@ -0,0 +1,104 @@ +#coding:utf-8 +# +# id: functional.tabloid.dbp_2146_distinct_not_in +# title: Common SQL. Check correctness of the results +# decription: +# tracker_id: +# min_versions: ['2.5'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='tabloid-dbp-2146.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + with + eset + as( + select tbi, count(distinct ari) as cnt + from pdata u + where ( + select count(distinct ari) + from pdata where tbi=u.tbi + ) > 2 + group by tbi having sum(cv)=16*16-1 + ) + ,wset + as( + select ari + from pdata + where tbi in ( + select tbi from pdata group by tbi + having sum(cv)=16*16-1 + ) + group by ari having sum(cv)=1000-235 + ) + ,q1 as( + select distinct pa.id ari, pt.id tbi, p.cnt + from pdata u + join eset p on p.tbi=u.tbi + join parea pa on pa.id=u.ari + join ptube pt on pt.id=u.tbi + join wset b on b.ari=u.ari + ) + ,q2 as ( + select + a.ari + ,a.tbi + ,b.cnt + from + ( + select distinct a.ari, b.tbi + from + ( + select ari + from pdata + where tbi not in ( + select tbi + from pdata + group by tbi + having sum(cv) <> 16*16-1 + ) + group by ari + having 1000 - sum(cv) = 235 + ) a + , pdata b + where a.ari = b.ari + ) a, + ( + select tbi, count(distinct ari) cnt + from pdata group by tbi + having count(distinct ari) > 2 + ) b + where a.tbi = b.tbi + ) + select ari,tbi,cnt + from q1 natural join q2 + order by 1,2,3 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ARI 6 + TBI 10 + CNT 3 + """ + +@pytest.mark.version('>=2.5') +def test_dbp_2146_distinct_not_in_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_dbp_4137_combo_full_join_and_windowed_funcs.py b/tests/functional/tabloid/test_dbp_4137_combo_full_join_and_windowed_funcs.py new file mode 100644 index 00000000..00762d3f --- /dev/null +++ b/tests/functional/tabloid/test_dbp_4137_combo_full_join_and_windowed_funcs.py @@ -0,0 +1,88 @@ +#coding:utf-8 +# +# id: functional.tabloid.dbp_4137_combo_full_join_and_windowed_funcs +# title: Common SQL. Check correctness of the results +# decription: +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='tabloid-dbp-4137.fbk', init=init_script_1) + +test_script_1 = """ + select x.ari ari_x, y.ari ari_y, z.ari ari_z + from( + select ari + from (select ari, cv, + max(ari)over(partition by tbi)-min(ari)over(partition by tbi) m + from pdata b1 + ) q + group by ari + having sum(cv)=255*3 and max(m)=0 + ) x + natural full join + ( + select a.ari + from ( + select a.*,max(rank)over(partition by tbi) max_rank + from ( + select tbi,ari,cv, + rank()over(partition by tbi order by ari) rank + from pdata b + ) a + ) a + where max_rank=1 + group by ari + having sum(cv)=765 + ) y + natural full join + ( + select ari + from ( + select distinct + ari, + min( + (select min(ari) from pdata where ari<>s.ari and tbi=s.tbi) + ) over (partition by ari) st + from pdata s + where ari in + ( + select d.ari + from pdata d join ptube t on d.tbi=t.id + group by d.ari + having sum(d.cv)=255*3 + and count(distinct t.tc)=3 + ) + ) z + where st is null + ) z + order by 1,2 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ARI_X ARI_Y ARI_Z + 2 2 2 + 53 53 53 + 90 90 90 + """ + +@pytest.mark.version('>=3.0') +def test_dbp_4137_combo_full_join_and_windowed_funcs_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_dbp_4391_combo_full_join_and_windowed_funcs.py b/tests/functional/tabloid/test_dbp_4391_combo_full_join_and_windowed_funcs.py new file mode 100644 index 00000000..2ef44bec --- /dev/null +++ b/tests/functional/tabloid/test_dbp_4391_combo_full_join_and_windowed_funcs.py @@ -0,0 +1,83 @@ +#coding:utf-8 +# +# id: functional.tabloid.dbp_4391_combo_full_join_and_windowed_funcs +# title: Common SQL. Check correctness of the results +# decription: +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='tabloid-dbp-4391.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + with + n as ( + select rank()over(partition by pdata.ari order by pdata.dts, ptube.id ) rnk, + pdata.dts, pdata.ari, pdata.tbi, ptube.tc + from pdata + join ptube on pdata.tbi = ptube.id + ) + ,h as ( + select t.*, rank()over(partition by q,g order by t,v) - 1 as r + from( + select t.*, y.tc, sum( iif( y.tc='rio',1,0) )over( partition by q order by t,v ) g + from( select * from pdata )t (t,q,v,w), ptube y + where t.v = y.id + )t + ) + ,x as ( + select --distinct + n1.ari, n1.tbi as v1, n2.tbi as v2, n3.tbi as v3 + from n n1 + join n n2 on n1.ari = n2.ari and n1.rnk = n2.rnk - 1 and n1.tc = 'rio' and n2.tc = 'foo' + join n n3 on n1.ari = n3.ari and n1.rnk = n3.rnk - 2 and n3.tc = 'bar' + ) + ,z as( + select --distinct + q as ari + ,max(iif(r=0,v,'')) v1 + ,max(iif(r=1,v,'')) v2 + ,max(iif(r=2,v,'')) v3 + from h where r<=3 + group by q,g + having + count(*)>=3 + and max(iif(r=0,tc,''))='rio' + and max(iif(r=1,tc,''))='foo' + and max(iif(r=2,tc,''))='bar' + + ) + select count(*) cnt + from x full join z using(ari, v1, v2, v3) + where + x.ari is distinct from z.ari + or x.v1 is distinct from z.v1 + or x.v2 is distinct from z.v2 + or x.v3 is distinct from z.v3 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CNT 0 + """ + +@pytest.mark.version('>=3.0') +def test_dbp_4391_combo_full_join_and_windowed_funcs_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_dbp_4391_combo_full_join_and_windowed_funcs2.py b/tests/functional/tabloid/test_dbp_4391_combo_full_join_and_windowed_funcs2.py new file mode 100644 index 00000000..ef8d8a96 --- /dev/null +++ b/tests/functional/tabloid/test_dbp_4391_combo_full_join_and_windowed_funcs2.py @@ -0,0 +1,99 @@ +#coding:utf-8 +# +# id: functional.tabloid.dbp_4391_combo_full_join_and_windowed_funcs2 +# title: Common SQL. Check correctness of the results +# decription: +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='tabloid-dbp-4391.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + with recursive + nx as (select 0 x from rdb$database union all select r.x+1 from nx r where r.x<2) + ,t as ( + select + row_number()over(partition by d.ari order by d.dts, d.tbi) n, + d.ari, d.tbi, t.tc c + from pdata d cross join ptube t + where d.tbi = t.id + ) + ,z as( + select + t.ari + ,max(iif(x=0, tbi, null)) v1 + ,max(iif(x=1, tbi, null)) v2 + ,max(iif(x=2, tbi, null)) v3 + from t cross join nx + group by t.ari, t.n - x + having + max(iif(x=0, c, null) )='rio' and + max(iif(x=1, c, null) )='foo' and + max(iif(x=2, c, null) )='bar' + ) + ,dx as + ( + select ari, + row_number()over(partition by ari order by dts, tbi ) as i, + tc, + tbi as bx + from pdata join ptube on tbi = id + ) + ,tx as + ( + select + ari, + tc as c1, + lead(tc)over(partition by ari order by i ) as c2, + lead(tc,2)over(partition by ari order by i ) as c3, + bx as v1 , + lead(bx)over(partition by ari order by i ) as v2, + lead(bx,2)over(partition by ari order by i ) as v3 + from dx + ) + ,x as( + select + ari, + v1, + v2, + v3 + from tx + where c1 = 'rio' + and c2 = 'foo' + and c3 = 'bar' + ) + select count(*) cnt + from z full join x using(ari, v1, v2, v3) + where + x.ari is distinct from z.ari + or x.v1 is distinct from z.v1 + or x.v2 is distinct from z.v2 + or x.v3 is distinct from z.v3 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CNT 0 + """ + +@pytest.mark.version('>=3.0') +def test_dbp_4391_combo_full_join_and_windowed_funcs2_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_dbp_5125_windowed_funcs.py b/tests/functional/tabloid/test_dbp_5125_windowed_funcs.py new file mode 100644 index 00000000..e8c499b9 --- /dev/null +++ b/tests/functional/tabloid/test_dbp_5125_windowed_funcs.py @@ -0,0 +1,76 @@ +#coding:utf-8 +# +# id: functional.tabloid.dbp_5125_windowed_funcs +# title: Common SQL. Check correctness of the results +# decription: +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='tabloid-dbp-5125.fbk', init=init_script_1) + +test_script_1 = """ + with + cx as( + select ari, tbi, + dense_rank() over(partition by ari order by dts) ra, + dense_rank() over(partition by ari order by dts desc)rd + from pdata + ) + ,dx as ( + select ari, tbi, dts + ,min(dts)over(partition by ari) dts_min + ,max(dts)over(partition by ari) dts_max + from pdata + ) + + select + c1.tbi vx + ,c1.ari q1 + ,c2.ari q2 + from cx c1 + join cx c2 on + c1.ari<>c2.ari + and c1.tbi=c2.tbi + and c1.ra=c2.rd + and c1.ra=1 + + full join ( + select a.tbi as vx, a.ari as q1, b.ari as q2 + from dx a, dx b + where a.dts_min = a.dts and b.dts_max=b.dts and a.ari<>b.ari and a.tbi=b.tbi + ) d + on c1.tbi = d.vx and c1.ari=d.q1 and c2.ari=d.q2 + order by 1,2,3 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + VX Q1 Q2 + 26 10 9 + 39 14 13 + 42 16 15 + 44 17 19 + 45 18 17 + 45 20 17 + """ + +@pytest.mark.version('>=3.0') +def test_dbp_5125_windowed_funcs_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_dbp_7029_heavy_test_for_windowed_funcs.py b/tests/functional/tabloid/test_dbp_7029_heavy_test_for_windowed_funcs.py new file mode 100644 index 00000000..19a738a2 --- /dev/null +++ b/tests/functional/tabloid/test_dbp_7029_heavy_test_for_windowed_funcs.py @@ -0,0 +1,393 @@ +#coding:utf-8 +# +# id: functional.tabloid.dbp_7029_heavy_test_for_windowed_funcs +# title: Common SQL. Check correctness of the results +# decription: +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='tabloid-dbp-7029.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + with + b as + ( + select ai,sc,k1,(k1-1)/sc+1 x, mod((k1-1),sc) + 1 y + from + ( + select id ai,row_number()over(order by id )k1, + cast(floor(sqrt((select count(*)from parea))) as int) sc + from parea + ) q where k1<=sc*sc + ) + + ,a as( + select + sc,k1, + coalesce(u,0)*1000000+coalesce(v,0)*1000+coalesce(w,0)c, + ai,x,y,x+sc*(y-1) k2 + from b + left join + ( + select ari, + sum(iif(tc='Argon', cv, 0)) u, + sum(iif(tc='Krypton', cv, 0)) v, + sum(iif(tc='Xenon', cv, 0)) w + from pdata join ptube on tbi = id + group by ari + )a + on ai=ari + ) + + ,t as + ( + select t.*, + count(*)over(partition by c, ax) cxa, + count(*)over(partition by c, bx) cxb, + min(ai)over(partition by c, ax) maa, + min(ai)over(partition by c, bx) mab + from + ( + select + c,ai,x,y, + k1-row_number()over(partition by c,x order by k1) ax, + k2-row_number()over(partition by c,y order by k2) bx + from a + )t + ) + + ,w1 as + ( + select c,min(az) over(partition by maa) az,ai,maa,mab + from + ( + select c,min(maa)over(partition by mab) az,ai,maa,mab + from T where cxa>1 or cxb>1 + )t + ) + + ,w2 as + ( + select c,min(az) over(partition by maa) az,ai,maa,mab + from (select c,min(az)over(partition by mab) az,ai,maa,mab from w1 )t + ) + + ,w3 as + ( + select c,min(az) over(partition by maa) az,ai,maa,mab + from (select c, min(az)over(partition by mab) az,ai,maa,mab from w2)t + ) + + ,w4 as + ( + select c,min(az) over(partition by maa) az,ai,maa,mab + from (select c, min(az)over(partition by mab) az,ai,maa,mab from w3)t + ) + + ,w5 as + ( + select c,min(az) over(partition by maa) az,ai,maa,mab + from (select c,min(az)over(partition by mab) az,ai,maa,mab from w4 )t + ) + + ,w6 as + ( + select c,min(az)over(partition by mab) az,ai,maa,mab + from w5 + ) + ,w7 as ( + select + c,az,ai + ,row_number()over(partition by az order by ai) r + ,min(ai)over(partition by az) mq + ,count(*)over(partition by az) mc + from w6 + ) + + select + cast(mod(c, 16*16) as varchar(12)) || ',' + || cast(mod(c,65536)/256 as varchar(12)) || ',' || cast(c/65536 as varchar(12)) f01 + ,max(mc) f02 + ,cast(az as varchar(12)) + || max(iif(r=2, ',' || cast(ai as varchar(12)), '')) + || max(iif(r=3, ',' || cast(ai as varchar(12)), '')) + || max(iif(r=4, ',' || cast(ai as varchar(12)), '')) + || max(iif(r=5, ',' || cast(ai as varchar(12)), '')) + || max(iif(r=6, ',' || cast(ai as varchar(12)), '')) + || max(iif(r=7, ',' || cast(ai as varchar(12)), '')) + || max(iif(r=8, ',' || cast(ai as varchar(12)), '')) + || max(iif(r=9, ',' || cast(ai as varchar(12)), '')) + || max(iif(r=10,',' || cast(ai as varchar(12)), '')) as f03 + from w7 + where mc < 11 and mq = az + group by c, az + order by 1,2,3; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + F01 0,0,0 + F02 9 + F03 9,10,58,59,60,108,109,110,1158 + F01 0,0,0 + F02 10 + F03 16,65,114,1163,1212,1213,1214,1215,1216,1217 + F01 0,0,0 + F02 10 + F03 2406,2416,2417,2418,2419,2420,2421,2422,2423,3472 + F01 0,0,0 + F02 10 + F03 3556,3605,4654,4655,4656,4705,4743,4744,4754,4755 + F01 0,0,0 + F02 10 + F03 38,86,87,88,134,135,137,138,1183,1187 + F01 0,0,0 + F02 10 + F03 79,80,120,130,1170,1219,1268,2316,2317,2318 + F01 0,0,0 + F02 10 + F03 8092,8093,8133,8134,8183,8184,9233,9234,9283,9284 + F01 0,0,0 + F02 10 + F03 8097,8098,8099,8100,8101,8146,8148,8150,8186,8197 + F01 0,0,0 + F02 10 + F03 94,104,105,106,143,1146,1192,1193,1194,1195 + F01 132,83,184 + F02 2 + F03 4610,4659 + F01 132,83,184 + F02 2 + F03 4757,5806 + F01 138,150,152 + F02 2 + F03 1169,1218 + F01 138,150,152 + F02 2 + F03 31,32 + F01 138,150,152 + F02 2 + F03 55,56 + F01 138,150,152 + F02 4 + F03 118,119,1166,1167 + F01 138,150,152 + F02 4 + F03 13,14,61,62 + F01 138,150,152 + F02 4 + F03 2364,2365,2403,2404 + F01 138,150,152 + F02 5 + F03 34,35,82,83,131 + F01 138,150,152 + F02 6 + F03 133,1172,1182,1220,1221,1269 + F01 138,150,152 + F02 7 + F03 1235,1274,1275,2322,2323,2370,2371 + F01 138,150,152 + F02 7 + F03 28,29,67,68,115,116,1164 + F01 138,150,152 + F02 7 + F03 52,53,91,92,139,140,1188 + F01 138,150,152 + F02 8 + F03 1241,1242,1289,1290,2328,2338,2376,2377 + F01 138,150,152 + F02 8 + F03 1262,1263,2301,2302,2349,2350,2397,2398 + F01 138,150,152 + F02 8 + F03 1265,1266,2313,2314,2352,2353,2400,2401 + F01 138,150,152 + F02 8 + F03 142,1190,1191,1238,1239,1286,1287,2326 + F01 138,150,152 + F02 9 + F03 1211,1250,1260,1298,2299,2346,2347,2394,2395 + F01 140,150,152 + F02 2 + F03 2325,2374 + F01 140,150,152 + F02 2 + F03 40,89 + F01 170,195,1220 + F02 2 + F03 3454,3455 + F01 170,195,1220 + F02 2 + F03 3457,3458 + F01 170,195,1220 + F02 2 + F03 3469,3470 + F01 170,195,1220 + F02 2 + F03 3496,3497 + F01 170,195,1220 + F02 2 + F03 3499,3500 + F01 26,39,0 + F02 2 + F03 10378,10379 + F01 26,39,0 + F02 2 + F03 10381,10382 + F01 26,39,0 + F02 2 + F03 10384,10385 + F01 26,39,0 + F02 2 + F03 9339,9340 + F01 26,39,0 + F02 2 + F03 9342,9352 + F01 26,39,0 + F02 2 + F03 9354,9355 + F01 26,39,0 + F02 2 + F03 9357,9358 + F01 26,39,0 + F02 2 + F03 9360,9361 + F01 26,39,0 + F02 2 + F03 9363,9364 + F01 26,39,0 + F02 8 + F03 1,2,3,4,5,6,7,8 + F01 4,207,153 + F02 2 + F03 3604,4653 + F01 4,207,153 + F02 2 + F03 4703,4704 + F01 4,207,153 + F02 2 + F03 5814,5815 + F01 4,207,153 + F02 3 + F03 3508,3509,3557 + F01 4,207,153 + F02 3 + F03 3520,3559,3560 + F01 4,207,153 + F02 3 + F03 3547,3548,3587 + F01 4,207,153 + F02 3 + F03 4658,4706,4707 + F01 4,207,153 + F02 3 + F03 5787,5835,5836 + F01 4,207,153 + F02 4 + F03 3577,3578,4625,4626 + F01 4,207,153 + F02 4 + F03 4634,4635,4682,4683 + F01 4,207,153 + F02 4 + F03 4691,4692,4739,4740 + F01 4,207,153 + F02 4 + F03 5793,5794,5841,5842 + F01 4,207,153 + F02 5 + F03 3523,3524,3562,3572,4611 + F01 4,207,153 + F02 5 + F03 4730,5769,5770,5817,5818 + F01 4,207,153 + F02 5 + F03 4742,5790,5791,5838,5839 + F01 4,207,153 + F02 7 + F03 4664,4712,4713,4760,5761,5808,5809 + F01 4,207,153 + F02 9 + F03 3526,3527,3574,3575,4613,4614,4661,4662,4710 + F01 42,72,1 + F02 2 + F03 3502,3503 + F01 48,56,61 + F02 2 + F03 8180,9229 + F01 96,48,61 + F02 2 + F03 7048,7049 + F01 96,48,61 + F02 2 + F03 7051,7052 + F01 96,48,61 + F02 2 + F03 8132,8181 + F01 96,48,61 + F02 2 + F03 8147,8196 + F01 96,48,61 + F02 3 + F03 7045,7046,8094 + F01 96,48,61 + F02 3 + F03 8096,8144,8145 + F01 96,48,61 + F02 3 + F03 9261,9309,9310 + F01 96,48,61 + F02 3 + F03 9282,9330,9331 + F01 96,48,61 + F02 4 + F03 8108,8118,8156,8157 + F01 96,48,61 + F02 4 + F03 8174,8175,8222,9223 + F01 96,48,61 + F02 4 + F03 9231,9232,9279,9280 + F01 96,48,61 + F02 4 + F03 9288,9289,9336,9337 + F01 96,48,61 + F02 5 + F03 7030,7040,8078,8079,8127 + F01 96,48,61 + F02 5 + F03 7054,7055,8102,8103,8151 + F01 96,48,61 + F02 5 + F03 8204,9252,9253,9300,9301 + F01 96,48,61 + F02 5 + F03 9228,9276,9277,9315,9316 + F01 96,48,61 + F02 8 + F03 8198,8199,9237,9238,9285,9286,9333,9334 + F01 96,48,61 + F02 9 + F03 7066,7067,8105,8106,8153,8154,8201,8202,9250 + """ + +@pytest.mark.version('>=3.0') +def test_dbp_7029_heavy_test_for_windowed_funcs_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_dbp_7114_windowed_funcs.py b/tests/functional/tabloid/test_dbp_7114_windowed_funcs.py new file mode 100644 index 00000000..6834de79 --- /dev/null +++ b/tests/functional/tabloid/test_dbp_7114_windowed_funcs.py @@ -0,0 +1,131 @@ +#coding:utf-8 +# +# id: functional.tabloid.dbp_7114_windowed_funcs +# title: Common SQL. Check correctness of the results +# decription: +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('=.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='tabloid-dbp-7114.fbk', init=init_script_1) + +test_script_1 = """ + delete from tresult; + insert into tresult(ip_a, ip_b, cnt) + select + d1||'.'||d2||'.'||d3||'.'||d4 as ip_a + ,d5||'.'||d6||'.'||d7||'.'||d8 as ip_b + ,1 + abs( cast( d1-d5 as bigint ) * 16777216 + (d2-d6) * 65536 + (d3-d7) * 256 + d4 - d8 ) as cnt + from + ( + select rn, + cvsum as d1, + lead(cvsum, 1, 0)over(order by rn) as d2, + lead(cvsum, 2, 0)over(order by rn) as d3, + lead(cvsum, 3, 0)over(order by rn) as d4, + iif(cnt - rn - 4 >= 0, lead(cvsum, 4, 0)over(order by rn), lag(cvsum, cnt_int, 0)over(order by rn)) as d5, + iif(cnt - rn - 4 >= 0, lead(cvsum, 5, 0)over(order by rn), lag(cvsum, cnt_int - 1, 0)over(order by rn)) as d6, + iif(cnt - rn - 4 >= 0, lead(cvsum, 6, 0)over(order by rn), lag(cvsum, cnt_int - 2, 0)over(order by rn)) as d7, + iif(cnt - rn - 4 >= 0, lead(cvsum, 7, 0)over(order by rn), lag(cvsum, cnt_int - 3, 0)over(order by rn)) as d8 + from + ( + select cvsum + ,row_number()over(order by dt asc, tbi desc) as rn + ,count(*)over() as cnt + ,count(*)over() / 4 * 4 as cnt_int + from + ( + select t.id as tbi, + coalesce(min(dts), '99991231') as dt, + 255 - sum(coalesce(cv, 0)) as cvsum + from ptube t + left join pdata d on d.tbi = t.id + group by t.id + ) as a1 + ) as a2 + ) as a3 + where mod(rn, 4) = 1 + ; + + insert into tresult(ip_a, ip_b, cnt) + select + n5.ip as ip_a + ,coalesce( + lead(n5.ip)over(order by n5.adr1) + ,first_value(n5.ip)over (order by n5.adr1) + ) as ip_b + ,abs( n5.ip_num + - coalesce( lead(n5.ip_num)over(order by n5.adr1) + ,first_value(n5.ip_num)over(order by n5.adr1) + ) + ) + 1 as cnt + from + ( + select + n4.adr1, + cast(max( iif(n4.adr2=1, n4.afree,null) ) as varchar(12)) || '.' || + coalesce(cast(max( iif(n4.adr2=2, n4.afree,null) ) as varchar(12)),'0')|| '.' || + coalesce(cast(max( iif(n4.adr2=3, n4.afree,null) ) as varchar(12)),'0')|| '.' || + coalesce(cast(max( iif(n4.adr2=4, n4.afree,null) ) as varchar(12)),'0') as ip, + + cast(max(iif(n4.adr2=1, n4.afree,0)) as bigint) * 256 * 256 * 256 + + coalesce(cast(max( iif(n4.adr2=2, n4.afree,0) ) as bigint),0) * 256 * 256 + + coalesce(cast(max( iif(n4.adr2=3, n4.afree,0) ) as bigint),0) * 256 + + coalesce(cast(max( iif(n4.adr2=4, n4.afree,0) ) as bigint),0) as ip_num + from ( + select n3.*, row_number()over(partition by n3.adr1 order by n3.dts , n3.vid desc) adr2 + from ( + select n2.*, (row_number()over(order by n2.dts, n2.vid desc)-1)/4 adr1 + from + ( + select + coalesce(n1.tbi, ptube.id) as vid, + coalesce(n1.dts, '99991231') as dts, + 255 - coalesce(cvsum,0) as afree + from( + select pdata.tbi, min(pdata.dts) as dts ,sum (pdata.cv) as cvsum + from pdata + group by pdata.tbi + ) n1 + right join ptube on n1.tbi = ptube.id + ) n2 + ) n3 + ) n4 + group by n4.adr1 + ) n5 + ; + + set list on; + select count(*) cnt_mism + from ( + select 1 x + from tresult + group by ip_a, ip_b, cnt + having count(*)<>2 + ); + set list off; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CNT_MISM 0 + """ + +@pytest.mark.version('>=3.0') +def test_dbp_7114_windowed_funcs_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_dml_privileges_sufficiency.py b/tests/functional/tabloid/test_dml_privileges_sufficiency.py new file mode 100644 index 00000000..dd330cb9 --- /dev/null +++ b/tests/functional/tabloid/test_dml_privileges_sufficiency.py @@ -0,0 +1,349 @@ +#coding:utf-8 +# +# id: functional.tabloid.dml_privileges_sufficiency +# title: Verify sufficiency of privileges for performing DML actions. Verify that RETURNING clause can not be used without SELECT privilege. +# decription: +# Test creates three users (for I/U/D) and gives them initial privileges for INSERT, UPDATE and DELETE (but without SELECT). +# Then we check that each user: +# 1) can do "his" DML without using RETURNING clause and this action must pass; +# 2) can NOT do "his" DML with using RETURNING clause because of absense of SELETC privilege. +# After this we add SELECT privilege for all of them and repeat. All actions must pased in this case. +# +# Created by request of dimitr, letter 16.06.2020 13:54. +# Checked on 4.0.0.2066. +# ::: NB ::: +# Do NOT use this test on 4.0.0.2046 and 4.0.0.2048 - these snapshots have bug and will crash on this test. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set wng off; + set list on; + + set term ^; + execute block as + begin + begin + execute statement 'drop user tmp$modifier_ins' with autonomous transaction; + when any do begin end + end + + begin + execute statement 'drop user tmp$modifier_upd' with autonomous transaction; + when any do begin end + end + + begin + execute statement 'drop user tmp$modifier_del' with autonomous transaction; + when any do begin end + end + end^ + set term ;^ + commit; --------------- 4.0.0.2046, 4.0.0.2048: crash here + + set bail off; + + create user tmp$modifier_ins password '123'; + create user tmp$modifier_upd password '123'; + create user tmp$modifier_del password '123'; + revoke all on all from tmp$modifier_ins; + revoke all on all from tmp$modifier_upd; + revoke all on all from tmp$modifier_del; + + + create sequence g; + recreate table test(id int primary key, x int); + insert into test(id,x) values( gen_id(g,1), 100); + commit; + + grant usage on sequence g to tmp$modifier_ins; + grant usage on sequence g to tmp$modifier_upd; + + grant insert on test to tmp$modifier_ins; + grant update on test to tmp$modifier_upd; + grant delete on test to tmp$modifier_del; + commit; + + create or alter view v_privs as + select + rdb$user -- tmp$c6317 + ,rdb$relation_name -- test + ,rdb$privilege -- S + ,rdb$grant_option -- 0 + ,rdb$field_name -- + ,rdb$object_type -- 0 + from rdb$user_privileges p + where rdb$user in ( upper('tmp$modifier_ins'), upper('tmp$modifier_upd'), upper('tmp$modifier_del') ) + order by rdb$user, rdb$privilege + ; + commit; + + + -- ####### P R I V I L E G E O N L Y F O R I N S E R T ######## + + connect '$(DSN)' user tmp$modifier_ins password '123'; + + select current_user as whoami, 'Has only INSERT privilege' as msg from rdb$database; + + -- must fail because no 'select' privilege was granted to 'tmp$modifier_ins': + select * from test; + + -- no exception must be here: + insert into test(id,x) values(gen_id(g,1), 200); + rollback; + + -- must fail because no 'select' privilege was granted to 'tmp$modifier_ins': + insert into test(id,x) values(gen_id(g,1), 1234567) returning id,x; + rollback; + + + -- must PASS: we have privilege to add record and RETURNING clause + -- does NOT contain anything from *table*: + insert into test(id,x) values(gen_id(g,1), 1234567) returning pi(); + rollback; + + -- ####### P R I V I L E G E O N L Y F O R U P D A T E ######## + + connect '$(DSN)' user tmp$modifier_upd password '123'; + + select current_user as whoami, 'Has only UPDATE privilege' as msg from rdb$database; + + -- must fail because no 'select' privilege was granted to 'tmp$modifier_upd': + select * from test; + + -- must fail because no 'select' privilege was granted to 'tmp$modifier_upd' + -- NB: "set x = -x" - this statement DOES query to old value of 'x', + -- i.e. is SELECTS table thust must fail: + update test set x = -x; + rollback; + + -- must PASS, no exception must be here: we do NOT interesting on old value of 'x': + update test set x = 0; + rollback; + + -- must fail because no 'select' privilege was granted to 'tmp$modifier_upd': + update test set x = 0 order by id rows 1; + rollback; + + + -- must fail because no 'select' privilege was granted to 'tmp$modifier_upd': + update test set x = 111 where id = 1; + rollback; + + -- must PASS: we have privilege to change column and RETURNING clause + -- does NOT contain anything from *table*: + update test set x = 0 returning pi(); + rollback; + + -- must fail because no 'select' privilege was granted to 'tmp$modifier_upd': + update test set x = 0 returning x; + rollback; + + + -- ####### P R I V I L E G E O N L Y F O R D E L E T E ######## + + connect '$(DSN)' user tmp$modifier_del password '123'; + + select current_user as whoami, 'Has only DELETE privilege' as msg from rdb$database; + + -- must fail because no 'select' privilege was granted to 'tmp$modifier_del': + select * from test; + + -- must PASS: user has privilege to DELETE rows from this table: + delete from test; + rollback; + + -- must fail because no 'select' privilege was granted to 'tmp$modifier_del': + delete from test where id > 0; + rollback; + + -- must fail because no 'select' privilege was granted to 'tmp$modifier_del': + delete from test order by id rows 1; + rollback; + + -- must fail because no 'select' privilege was granted to 'tmp$modifier_del': + delete from test returning id; + rollback; + + + -- ############################################################## + -- ### A D D P R I V I L E G E F O R S E L E C T ### + -- ############################################################## + connect '$(DSN)' user SYSDBA password 'masterkey'; + + grant select on test to tmp$modifier_ins; + grant select on test to tmp$modifier_upd; + grant select on test to tmp$modifier_del; + commit; + + + -- #### P R I V I L E G E F O R I N S E R T + S E L E C T ##### + + connect '$(DSN)' user tmp$modifier_ins password '123'; + + select current_user as whoami, 'Has INSERT + SELECT privileges' as msg from rdb$database; + + -- All subsequent statements must PASS: + select * from test; + + insert into test(id,x) values(-1, 1234567) returning id,x; + rollback; + + + -- #### P R I V I L E G E F O R U P D A T E + S E L E C T ##### + + connect '$(DSN)' user tmp$modifier_upd password '123'; + + select current_user as whoami, 'Has UPDATE + SELECT privileges' as msg from rdb$database; + + -- All subsequent statements must PASS: + select * from test; + update test set x = -x; + rollback; + update test set x = 0; + rollback; + update test set x = 0 order by id rows 1; + rollback; + update test set x = 111 where id = 1; + rollback; + update test set x = 0 returning x; + rollback; + + + -- #### P R I V I L E G E F O R D E L E T E + S E L E C T ##### + + connect '$(DSN)' user tmp$modifier_del password '123'; + + select current_user as whoami, 'Has DELETE + SELECT privileges' as msg from rdb$database; + + -- All subsequent statements must PASS: + select * from test; + delete from test where id > 0; + rollback; + delete from test order by id rows 1; + rollback; + delete from test returning id; + rollback; + + + -- ######################### + -- ### C L E A N U P ### + -- ######################### + connect '$(DSN)' user SYSDBA password 'masterkey'; + + drop user tmp$modifier_ins; + drop user tmp$modifier_upd; + drop user tmp$modifier_del; + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + WHOAMI TMP$MODIFIER_INS + MSG Has only INSERT privilege + + PI 3.141592653589793 + + WHOAMI TMP$MODIFIER_UPD + MSG Has only UPDATE privilege + + PI 3.141592653589793 + + WHOAMI TMP$MODIFIER_DEL + MSG Has only DELETE privilege + + WHOAMI TMP$MODIFIER_INS + MSG Has INSERT + SELECT privileges + + ID 1 + X 100 + + ID -1 + X 1234567 + + WHOAMI TMP$MODIFIER_UPD + MSG Has UPDATE + SELECT privileges + + ID 1 + X 100 + + X 0 + + WHOAMI TMP$MODIFIER_DEL + MSG Has DELETE + SELECT privileges + + ID 1 + X 100 + + ID 1 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE TEST + -Effective user is TMP$MODIFIER_INS + + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE TEST + -Effective user is TMP$MODIFIER_INS + + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE TEST + -Effective user is TMP$MODIFIER_UPD + + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE TEST + -Effective user is TMP$MODIFIER_UPD + + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE TEST + -Effective user is TMP$MODIFIER_UPD + + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE TEST + -Effective user is TMP$MODIFIER_UPD + + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE TEST + -Effective user is TMP$MODIFIER_UPD + + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE TEST + -Effective user is TMP$MODIFIER_DEL + + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE TEST + -Effective user is TMP$MODIFIER_DEL + + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE TEST + -Effective user is TMP$MODIFIER_DEL + + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE TEST + -Effective user is TMP$MODIFIER_DEL + """ + +@pytest.mark.version('>=4.0') +def test_dml_privileges_sufficiency_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_eqc_136030.py b/tests/functional/tabloid/test_eqc_136030.py new file mode 100644 index 00000000..a4e20407 --- /dev/null +++ b/tests/functional/tabloid/test_eqc_136030.py @@ -0,0 +1,380 @@ +#coding:utf-8 +# +# id: functional.tabloid.eqc_136030 +# title: Check ability for preparing and then run query with parameters. Query should use ORDER-BY clause. +# decription: +# 02.02.2019: removed from DB metadata calls to UDFs - they are not used in this test but can not be used in FB 4.0 by default. +# Removed triggers because they have no deal here. +# Checked on: +# 3.0.5.33097: OK, 2.782s. +# 4.0.0.1421: OK, 3.642s. +# +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import zipfile +# +# os.environ["ISC_USER"] = 'SYSDBA' +# os.environ["ISC_PASSWORD"] = 'masterkey' +# +# db_conn.close() +# zf = zipfile.ZipFile( os.path.join(context['files_location'],'eqc136030.zip') ) +# zf.extractall( context['temp_directory'] ) +# zf.close() +# +# fbk = os.path.join(context['temp_directory'],'eqc136030.fbk') +# +# runProgram('gbak',['-rep',fbk, dsn]) +# +# script=""" +# set list on; +# set sqlda_display on; +# set planonly; +# +# select +# a.csoc, a.nreserc , a.coddoc , a.codgio , +# a.macchina, a.rec_upd, a.utente_upd, +# cast(a.fblc as integer) fblc, +# cast(a.fdel as integer) fdel, +# b.tipdoc, b.desdoc, b.fblc , c.tipgio, c.desgio , c.fblc +# from docgio a +# left join doctip (a.csoc, a.nreserc) b on ( a.coddoc = b.coddoc ) +# left join giotip (a.csoc, a.nreserc) c on (a.codgio = c.codgio) +# where +# a.csoc = ? +# and a.nreserc = ? +# order by a.codgio, a.coddoc; +# +# set planonly; +# set plan off; +# set sqlda_display off; +# +# select +# a.csoc, a.nreserc , a.coddoc , a.codgio , +# a.macchina, a.rec_upd, a.utente_upd, +# cast(a.fblc as integer) fblc, +# cast(a.fdel as integer) fdel, +# b.tipdoc, b.desdoc, b.fblc , c.tipgio, c.desgio , c.fblc +# from docgio a +# left join doctip (a.csoc, a.nreserc) b on ( a.coddoc = b.coddoc ) +# left join giotip (a.csoc, a.nreserc) c on (a.codgio = c.codgio) +# where +# a.csoc = 'DEM1' -- :csoc +# and a.nreserc = '' -- :nreserc +# order by a.codgio, a.coddoc; +# """ +# runProgram('isql',[dsn,'-q'],script) +# +# ############################### +# # Cleanup. +# os.remove(fbk) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + INPUT message field count: 2 + 01: sqltype: 448 VARYING scale: 0 subtype: 0 len: 4 charset: 0 NONE + : name: alias: + : table: owner: + 02: sqltype: 448 VARYING scale: 0 subtype: 0 len: 2 charset: 0 NONE + : name: alias: + : table: owner: + + PLAN JOIN (JOIN (A ORDER DOCGIO_PK, B NATURAL), C NATURAL) + + OUTPUT message field count: 15 + 01: sqltype: 448 VARYING scale: 0 subtype: 0 len: 4 charset: 0 NONE + : name: CSOC alias: CSOC + : table: DOCGIO owner: SYSDBA + 02: sqltype: 448 VARYING scale: 0 subtype: 0 len: 2 charset: 0 NONE + : name: NRESERC alias: NRESERC + : table: DOCGIO owner: SYSDBA + 03: sqltype: 448 VARYING scale: 0 subtype: 0 len: 3 charset: 0 NONE + : name: CODDOC alias: CODDOC + : table: DOCGIO owner: SYSDBA + 04: sqltype: 448 VARYING scale: 0 subtype: 0 len: 3 charset: 0 NONE + : name: CODGIO alias: CODGIO + : table: DOCGIO owner: SYSDBA + 05: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 30 charset: 0 NONE + : name: MACCHINA alias: MACCHINA + : table: DOCGIO owner: SYSDBA + 06: sqltype: 510 TIMESTAMP scale: 0 subtype: 0 len: 8 + : name: REC_UPD alias: REC_UPD + : table: DOCGIO owner: SYSDBA + 07: sqltype: 496 LONG scale: 0 subtype: 0 len: 4 + : name: UTENTE_UPD alias: UTENTE_UPD + : table: DOCGIO owner: SYSDBA + 08: sqltype: 496 LONG scale: 0 subtype: 0 len: 4 + : name: CAST alias: FBLC + : table: owner: + 09: sqltype: 496 LONG scale: 0 subtype: 0 len: 4 + : name: CAST alias: FDEL + : table: owner: + 10: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 3 charset: 0 NONE + : name: TIPDOC alias: TIPDOC + : table: DOCTIP owner: SYSDBA + 11: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 60 charset: 0 NONE + : name: DESDOC alias: DESDOC + : table: DOCTIP owner: SYSDBA + 12: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 1 charset: 0 NONE + : name: FBLC alias: FBLC + : table: DOCTIP owner: SYSDBA + 13: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 3 charset: 0 NONE + : name: TIPGIO alias: TIPGIO + : table: GIOTIP owner: SYSDBA + 14: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 60 charset: 0 NONE + : name: DESGIO alias: DESGIO + : table: GIOTIP owner: SYSDBA + 15: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 1 charset: 0 NONE + : name: FBLC alias: FBLC + : table: GIOTIP owner: SYSDBA + + + CSOC DEM1 + NRESERC + CODDOC AUT + CODGIO CGB + MACCHINA VAIO-ADAL + REC_UPD 2007-06-17 22:50:41.0000 + UTENTE_UPD 1 + FBLC 0 + FDEL 0 + TIPDOC + DESDOC + FBLC + TIPGIO + DESGIO + FBLC + + CSOC DEM1 + NRESERC + CODDOC CGE + CODGIO CGB + MACCHINA VAIO-ADAL + REC_UPD 2007-06-17 22:50:41.0000 + UTENTE_UPD 1 + FBLC 0 + FDEL 0 + TIPDOC + DESDOC + FBLC + TIPGIO + DESGIO + FBLC + + CSOC DEM1 + NRESERC + CODDOC CTI + CODGIO CGB + MACCHINA VAIO-ADAL + REC_UPD 2007-06-17 22:50:41.0000 + UTENTE_UPD 1 + FBLC 0 + FDEL 0 + TIPDOC + DESDOC + FBLC + TIPGIO + DESGIO + FBLC + + CSOC DEM1 + NRESERC + CODDOC FAA + CODGIO CGB + MACCHINA VAIO-ADAL + REC_UPD 2007-06-17 22:50:41.0000 + UTENTE_UPD 1 + FBLC 0 + FDEL 0 + TIPDOC + DESDOC + FBLC + TIPGIO + DESGIO + FBLC + + CSOC DEM1 + NRESERC + CODDOC FAV + CODGIO CGB + MACCHINA VAIO-ADAL + REC_UPD 2007-06-17 22:50:41.0000 + UTENTE_UPD 1 + FBLC 0 + FDEL 0 + TIPDOC + DESDOC + FBLC + TIPGIO + DESGIO + FBLC + + CSOC DEM1 + NRESERC + CODDOC FTA + CODGIO CGB + MACCHINA VAIO-ADAL + REC_UPD 2007-06-17 22:50:41.0000 + UTENTE_UPD 1 + FBLC 0 + FDEL 0 + TIPDOC + DESDOC + FBLC + TIPGIO + DESGIO + FBLC + + CSOC DEM1 + NRESERC + CODDOC FTV + CODGIO CGB + MACCHINA VAIO-ADAL + REC_UPD 2007-06-17 22:50:41.0000 + UTENTE_UPD 1 + FBLC 0 + FDEL 0 + TIPDOC + DESDOC + FBLC + TIPGIO + DESGIO + FBLC + + CSOC DEM1 + NRESERC + CODDOC FAA + CODGIO RAC + MACCHINA VAIO-ADAL + REC_UPD 2007-06-17 22:50:41.0000 + UTENTE_UPD 1 + FBLC 0 + FDEL 0 + TIPDOC + DESDOC + FBLC + TIPGIO + DESGIO + FBLC + + CSOC DEM1 + NRESERC + CODDOC FTA + CODGIO RAC + MACCHINA VAIO-ADAL + REC_UPD 2007-06-17 22:50:41.0000 + UTENTE_UPD 1 + FBLC 0 + FDEL 0 + TIPDOC + DESDOC + FBLC + TIPGIO + DESGIO + FBLC + + CSOC DEM1 + NRESERC + CODDOC NCA + CODGIO RAC + MACCHINA VAIO-ADAL + REC_UPD 2007-06-17 22:50:41.0000 + UTENTE_UPD 1 + FBLC 0 + FDEL 0 + TIPDOC + DESDOC + FBLC + TIPGIO + DESGIO + FBLC + + CSOC DEM1 + NRESERC + CODDOC NDA + CODGIO RAC + MACCHINA VAIO-ADAL + REC_UPD 2007-06-17 22:50:41.0000 + UTENTE_UPD 1 + FBLC 0 + FDEL 0 + TIPDOC + DESDOC + FBLC + TIPGIO + DESGIO + FBLC + + CSOC DEM1 + NRESERC + CODDOC FAV + CODGIO RFV + MACCHINA VAIO-ADAL + REC_UPD 2007-06-17 22:50:41.0000 + UTENTE_UPD 1 + FBLC 0 + FDEL 0 + TIPDOC + DESDOC + FBLC + TIPGIO + DESGIO + FBLC + + CSOC DEM1 + NRESERC + CODDOC FTV + CODGIO RFV + MACCHINA VAIO-ADAL + REC_UPD 2007-06-17 22:50:41.0000 + UTENTE_UPD 1 + FBLC 0 + FDEL 0 + TIPDOC + DESDOC + FBLC + TIPGIO + DESGIO + FBLC + + CSOC DEM1 + NRESERC + CODDOC NCV + CODGIO RFV + MACCHINA VAIO-ADAL + REC_UPD 2007-06-17 22:50:41.0000 + UTENTE_UPD 1 + FBLC 0 + FDEL 0 + TIPDOC + DESDOC + FBLC + TIPGIO + DESGIO + FBLC + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_eqc_136030_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/tabloid/test_eqc_141347.py b/tests/functional/tabloid/test_eqc_141347.py new file mode 100644 index 00000000..ff38dce8 --- /dev/null +++ b/tests/functional/tabloid/test_eqc_141347.py @@ -0,0 +1,71 @@ +#coding:utf-8 +# +# id: functional.tabloid.eqc_141347 +# title: Check correctness of LEFT JOIN result when right source has two FK and one of fields from FK present both in ON and WHERE clauses. +# decription: +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + recreate table t2 ( + id int primary key, + pid0 int, + pid1 int + ); + recreate table t1 (id int primary key); + recreate table t0 (id int primary key); + + alter table t2 + add constraint fk_t0 foreign key (pid0) references t0 + ,add constraint fk_t1 foreign key (pid1) references t1 + ; + commit; + + insert into t0 (id) values (1); + + insert into t1 (id) values (1); + insert into t1 (id) values (2); + insert into t1 (id) values (3); + insert into t1 (id) values (4); + + insert into t2 (id, pid1, pid0) values (1, 1, 1); + insert into t2 (id, pid1, pid0) values (2, 4, 1); + commit; + + select a.id, b.pid1 + from t1 a + left join t2 b on ( a.id = b.pid1 ) and ( b.pid0 = 1 ) + where (b.pid1 is null); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 2 + PID1 + + ID 3 + PID1 + """ + +@pytest.mark.version('>=2.5') +def test_eqc_141347_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_eqc_160757.py b/tests/functional/tabloid/test_eqc_160757.py new file mode 100644 index 00000000..8561479b --- /dev/null +++ b/tests/functional/tabloid/test_eqc_160757.py @@ -0,0 +1,110 @@ +#coding:utf-8 +# +# id: functional.tabloid.eqc_160757 +# title: Check correctness of LEFT JOIN result when left source is table with several -vs- single rows and right source is SP. +# decription: +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + create or alter procedure sp_test as begin end; + + recreate table test ( + id int primary key using index test_pk, + val_a int, + val_b int + ); + + set term ^; + create or alter procedure sp_test( + a_id int, + a_val_1 int, + a_val_2 int + ) + returns ( + o_id int, + o_is_equ varchar(10) + ) + as + begin + o_id=a_id; + o_is_equ = iif( a_val_1 is not distinct from a_val_2, 'Passed.', 'Failed.'); + suspend; + end + ^ + set term ;^ + commit; + + insert into test (id, val_a, val_b ) values (1, 0, 0); + insert into test (id, val_a, val_b ) values (2, 1, 0); + insert into test (id, val_a, val_b ) values (3, 0, 1); + + set list on; + + --set echo on; + + select 'test_1' as msg, t.*, p.* + from test t + left join sp_test(t.id,t.val_a,t.val_b) p + on p.o_id=t.id + ; + + select 'test_2' as msg, t.*, p.* + from test t + left join sp_test (t.id,t.val_a,t.val_b) p on p.o_id=t.id + where t.id=2 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG test_1 + ID 1 + VAL_A 0 + VAL_B 0 + O_ID 1 + O_IS_EQU Passed. + + MSG test_1 + ID 2 + VAL_A 1 + VAL_B 0 + O_ID 2 + O_IS_EQU Failed. + + MSG test_1 + ID 3 + VAL_A 0 + VAL_B 1 + O_ID 3 + O_IS_EQU Failed. + + MSG test_2 + ID 2 + VAL_A 1 + VAL_B 0 + O_ID 2 + O_IS_EQU Failed. + """ + +@pytest.mark.version('>=2.5') +def test_eqc_160757_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_eqc_166663.py b/tests/functional/tabloid/test_eqc_166663.py new file mode 100644 index 00000000..41a7d599 --- /dev/null +++ b/tests/functional/tabloid/test_eqc_166663.py @@ -0,0 +1,144 @@ +#coding:utf-8 +# +# id: functional.tabloid.eqc_166663 +# title: Index(es) should not become corrupted after two updates and raising exception in one Tx, doing inside SP +# decription: +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('exception .*', 'exception'), ('line: .*', 'line')] + +init_script_1 = """""" + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- NB: changed expected value of SQLSTATE from 42000 to HY000, see: + -- "Prevent stack trace (line/column info) from overriding the real error's SQLSTATE", 30-apr-2016 + -- https://github.com/FirebirdSQL/firebird/commit/d1d8b36a07d4f11d98d2c8ec16fb8ec073da442b // FB 4.0 + -- https://github.com/FirebirdSQL/firebird/commit/849bfac745bc9158e9ef7990f5d52913f8b72f02 // FB 3.0 + -- https://github.com/FirebirdSQL/firebird/commit/b9d4142c4ed1fdf9b7c633edc7b2425f7b93eed0 // FB 2.5 + -- See also letter from dimitr, 03-may-2016 19:24. + + + create or alter procedure sp_test ( a_id int) as begin end; + set term ^; + execute block as + begin + execute statement 'drop exception ex_foo'; when any do begin end + end + ^ + set term ;^ + commit; + + recreate table tdetl ( + id int primary key using index tdetl_pk, + pid int + ); + commit; + + recreate table tmain ( + id int primary key using index tmain_pk , + name varchar(20) + ); + commit; + + alter table tdetl add constraint tdetl_fk foreign key (pid) references tmain(id); + commit; + + insert into tmain (id, name) values (1, 'qwerty'); + commit; + + + create exception ex_foo 'ex_foo'; + commit; + + set term ^; + create or alter procedure sp_test ( a_id int) + as + begin + update tdetl set id = id where id = :a_id; + update tdetl set pid = 1 where id = :a_id; + exception ex_foo; + end + ^ + set term ;^ + commit; + + insert into tdetl (id, pid) values (1,null); + execute procedure sp_test(1); + + set plan on; + set list on; + set count on; + set heading off; + set echo on; + + select * from tdetl where id >= 0; + + select * from tdetl where pid is null; + + select * from tdetl; + + select * from tmain where id >= 0; + + select * from tmain; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + select * from tdetl where id >= 0; + PLAN (TDETL INDEX (TDETL_PK)) + ID 1 + PID + Records affected: 1 + + select * from tdetl where pid is null; + PLAN (TDETL INDEX (TDETL_FK)) + ID 1 + PID + Records affected: 1 + + select * from tdetl; + PLAN (TDETL NATURAL) + ID 1 + PID + Records affected: 1 + + select * from tmain where id >= 0; + PLAN (TMAIN INDEX (TMAIN_PK)) + ID 1 + NAME qwerty + Records affected: 1 + + select * from tmain; + PLAN (TMAIN NATURAL) + ID 1 + NAME qwerty + Records affected: 1 + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = HY000 + exception 2 + -EX_FOO + -ex_foo + -At procedure 'SP_TEST' line: 6, col: 8 + """ + +@pytest.mark.version('>=2.5') +def test_eqc_166663_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_eqc_200762.py b/tests/functional/tabloid/test_eqc_200762.py new file mode 100644 index 00000000..957bff87 --- /dev/null +++ b/tests/functional/tabloid/test_eqc_200762.py @@ -0,0 +1,152 @@ +#coding:utf-8 +# +# id: functional.tabloid.eqc_200762 +# title: Check results of CONTAINING when search pattern can span on one or several blob segments +# decription: +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(page_size=8192, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set term ^; + execute block as + begin + execute statement 'drop sequence g'; when any do begin end + end + ^ + set term ;^ + commit; + + create sequence g; + + recreate table test ( + id int primary key, + pattern varchar(32765), + memotext blob sub_type 1 segment size 1024 character set none + ); + + set term ^; + execute block returns(id int, ptrn_len int, blob_len int, ptrn_pos int) as + declare v_pattern varchar(32765); + declare v_db_page smallint; + declare v_id int; + begin + + select mon$page_size from mon$database into v_db_page; + + delete from test; + + v_pattern = 'qwertyuioplkjhgfdsa1234567890zxcvbnm'; + + -- short pattern (len < 50 bytes), start on 1st segment and spans to 2nd: + insert into test(id, pattern, memotext) + values( gen_id(g,1), :v_pattern, rpad( '', 1000, uuid_to_char(gen_uuid()) ) || :v_pattern ); + + -- middle length pattern (len > 1024 and <= db_page_size) + + insert into test(id, pattern) + values(gen_id(g,1), rpad( '', 2.0/3 * :v_db_page, uuid_to_char(gen_uuid()) ) ) + returning id, pattern into v_id, v_pattern; + update test set memotext = rpad( '', 1001, uuid_to_char(gen_uuid()) ) || :v_pattern + where id = :v_id; + + insert into test(id, pattern) values(gen_id(g,1), rpad( '', 3.0/4 * :v_db_page, uuid_to_char(gen_uuid()) ) ) + returning id, pattern into v_id, v_pattern; + update test set memotext = rpad( '', 1002, uuid_to_char(gen_uuid()) ) || :v_pattern + where id = :v_id; + + insert into test(id, pattern) values(gen_id(g,1), rpad( '', :v_db_page, uuid_to_char(gen_uuid()) ) ) + returning id, pattern into v_id, v_pattern; + update test set memotext = rpad( '', 1003, uuid_to_char(gen_uuid()) ) || :v_pattern + where id = :v_id; + + -- large length pattern ( > db_page_size): + + insert into test(id, pattern) values(gen_id(g,1), rpad( '', 5.0/4 * :v_db_page, uuid_to_char(gen_uuid()) ) ) + returning id, pattern into v_id, v_pattern; + update test set memotext = rpad( '', 1004, uuid_to_char(gen_uuid()) ) || :v_pattern + where id = :v_id; + + insert into test(id, pattern) values(gen_id(g,1), rpad( '', 4.0/3 * :v_db_page, uuid_to_char(gen_uuid()) ) ) + returning id, pattern into v_id, v_pattern; + update test set memotext = rpad( '', 1005, uuid_to_char(gen_uuid()) ) || :v_pattern + where id = :v_id; + + insert into test(id, pattern) values(gen_id(g,1), rpad( '', 31724, uuid_to_char(gen_uuid()) ) ) + returning id, pattern into v_id, v_pattern; + update test set memotext = rpad( '', 1006, uuid_to_char(gen_uuid()) ) || :v_pattern + where id = :v_id; + + for + select id, char_length(pattern), char_length(memotext), position(pattern in memotext) + from test + where memotext containing pattern + order by id + into id, ptrn_len, blob_len, ptrn_pos + do + suspend; + end + ^ + set term ;^ + commit; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + PTRN_LEN 36 + BLOB_LEN 1036 + PTRN_POS 1001 + + ID 2 + PTRN_LEN 4915 + BLOB_LEN 5916 + PTRN_POS 1002 + + ID 3 + PTRN_LEN 5734 + BLOB_LEN 6736 + PTRN_POS 1003 + + ID 4 + PTRN_LEN 8192 + BLOB_LEN 9195 + PTRN_POS 1004 + + ID 5 + PTRN_LEN 9830 + BLOB_LEN 10834 + PTRN_POS 1005 + + ID 6 + PTRN_LEN 10650 + BLOB_LEN 11655 + PTRN_POS 1006 + + ID 7 + PTRN_LEN 31724 + BLOB_LEN 32730 + PTRN_POS 1007 + """ + +@pytest.mark.version('>=2.5') +def test_eqc_200762_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_eqc_306263.py b/tests/functional/tabloid/test_eqc_306263.py new file mode 100644 index 00000000..498e8cd4 --- /dev/null +++ b/tests/functional/tabloid/test_eqc_306263.py @@ -0,0 +1,131 @@ +#coding:utf-8 +# +# id: functional.tabloid.eqc_306263 +# title: Check ability to run complex query +# decription: +# +# tracker_id: +# min_versions: ['2.5.5'] +# versions: 2.5.5 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.5 +# resources: None + +substitutions_1 = [('0.000000000000000.*', '0.0000000000000000')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import zipfile +# os.environ["ISC_USER"] = 'SYSDBA' +# os.environ["ISC_PASSWORD"] = 'masterkey' +# +# db_conn.close() +# +# zf = zipfile.ZipFile( os.path.join(context['files_location'],'eqc306263.zip') ) +# zf.extractall( context['temp_directory'] ) +# zf.close() +# +# fbk = os.path.join(context['temp_directory'],'eqc306263.fbk') +# +# runProgram('gbak',['-rep', fbk, dsn]) +# +# script="""set list on; +# select +# objeschlue.obsch_schl, +# schluedef.schld_bzg, +# objeschlue.obj_id, +# darlehen.vertrag, +# darlkond.dlko_annui, +# zuschkond.zuko_wrt, +# darlkond.dlko_unom, +# darlgeber.darlg_bzg, +# objeschlue.obsch_gb, +# objeschlue.obsch_gabd, +# darlkond.flgk_kz, +# zuschkond.faelligkeit, +# darl_obper.top_id, +# darlkond.dlko_gvond, +# darlkond.dlko_gbisd, +# zuschkond.zuko_id, +# zuschkond.zuko_gvond, +# zuschkond.zuko_gbid, +# darl_obper.obj_id +# from +# ( +# ( +# ( +# ( +# ( +# ( +# darl_obper darl_obper +# inner join darlehen darlehen on darl_obper.darl_id=darlehen.darl_id +# ) +# inner join objeschlue objeschlue on darlehen.darl_id=objeschlue.darl_id +# ) +# inner join darlgeber darlgeber on darlehen.darlg_id=darlgeber.darlg_id +# ) +# inner join darlkond darlkond on darlehen.darl_id=darlkond.darl_id +# ) +# left outer join schluedef schluedef on objeschlue.schld_id=schluedef.schld_id +# ) +# left outer join zuschkond zuschkond on darlehen.darl_id=zuschkond.darl_id +# ) +# where +# darl_obper.obj_id=3759 +# and darlkond.dlko_gvond<'12/02/2011 00:00:00' +# and darlkond.dlko_gbisd>='12/01/2011 00:00:00' +# and objeschlue.obj_id=3759 +# and objeschlue.obsch_gb>='12/02/2011 00:00:00' +# and objeschlue.obsch_gabd<'12/02/2011 00:00:00' +# and darl_obper.top_id is null +# and ( +# zuschkond.zuko_id is null +# or zuschkond.zuko_gvond<'12/02/2011 00:00:00' and zuschkond.zuko_gbid>='12/01/2011 00:00:00' +# ); +# commit; +# """ +# runProgram('isql',[dsn,'-q'],script) +# +# ############################### +# # Cleanup. +# os.remove(fbk) +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + OBSCH_SCHL 1.000000000000000 + SCHLD_BZG + OBJ_ID 3759 + VERTRAG + DLKO_ANNUI 0.0000000000000000 + ZUKO_WRT + DLKO_UNOM 0.0000000000000000 + DARLG_BZG + OBSCH_GB 2100-01-01 00:00:00.0000 + OBSCH_GABD 2005-08-01 00:00:00.0000 + FLGK_KZ 4 + FAELLIGKEIT + TOP_ID + DLKO_GVOND 2011-01-01 00:00:00.0000 + DLKO_GBISD 2100-01-01 00:00:00.0000 + ZUKO_ID + ZUKO_GVOND + ZUKO_GBID + OBJ_ID 3759 + """ + +@pytest.mark.version('>=2.5.5') +@pytest.mark.xfail +def test_eqc_306263_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/tabloid/test_eqc_343715.py b/tests/functional/tabloid/test_eqc_343715.py new file mode 100644 index 00000000..d3890703 --- /dev/null +++ b/tests/functional/tabloid/test_eqc_343715.py @@ -0,0 +1,167 @@ +#coding:utf-8 +# +# id: functional.tabloid.eqc_343715 +# title: Checking PK index is used when table is joined as driven (right) source in LEFT OUTER join from VIEW +# decription: +# Number of index reads per TABLE can be watched only in 3.0 by using mon$table_stats. +# We have to ensure that table TEST1 in following queries is accessed only by its PK index, i.e. NO natural reads for it can occur. +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + create or alter view vlast_test1_for_test3_a as select 1 id from rdb$database; + create or alter view vlast_test1_for_test3_b as select 1 id from rdb$database; + create or alter procedure get_last_test1_for_test3 as begin end; + + recreate table test2( + id int primary key using index pk_test2_id, + id1 int not null + ); + recreate table test1( + id int primary key using index pk_test1_id + ); + + alter table test2 add constraint fk_test2_test1 foreign key(id1) references test1(id); + + recreate table test3( + id int primary key using index pk_test3_id + ); + + alter table test2 add id3 integer; + alter table test2 add constraint fk_test2_test3 foreign key(id3) references test3(id); + + set term ^; + create or alter procedure get_last_test1_for_test3(id3 integer) + returns(out_id1 integer) + as + begin + for + select t2.id1 + from test2 t2 + where t2.id3=:id3 + order by t2.id1 desc + rows 1 + into :out_id1 + do + suspend; + end + ^ + set term ;^ + commit; + + create or alter view vlast_test1_for_test3_a(id3, id1) as + select + t3.id + ,(select p.out_id1 from get_last_test1_for_test3(t3.id) p) + from test3 t3 + ; + + create or alter view vlast_test1_for_test3_b(id3, id1) as + select + t3.id + ,( + select t2.id1 + from test2 t2 + where t2.id3 = t3.id + order by t2.id1 desc + rows 1 + ) + from test3 t3 + ; + commit; + """ + +db_1 = db_factory(from_backup='mon-stat-gathering-3_0.fbk', init=init_script_1) + +test_script_1 = """ + insert into test3(id) values(1); + insert into test3(id) values(2); + insert into test3(id) values(3); + + + insert into test1(id) values(1); + insert into test2(id, id1, id3) values(1, 1, 2); + insert into test2(id, id1, id3) values(2, 1, 2); + insert into test2(id, id1, id3) values(3, 1, 2); + insert into test1(id) values(2); + insert into test2(id, id1, id3) values(4, 2, 2); + insert into test2(id, id1, id3) values(5, 2, 2); + insert into test1(id) values(3); + insert into test2(id, id1, id3) values(6, 3, 3); + insert into test2(id, id1, id3) values(7, 3, 3); + insert into test1(id) values(4); + insert into test2(id, id1, id3) values(8, 4, 3); + insert into test2(id, id1, id3) values(9, 4, 3); + insert into test1(id) values(5); + insert into test2(id, id1, id3) values(10, 5, 3); + insert into test2(id, id1, id3) values(11, 5, 3); + insert into test1(id) values(6); + insert into test2(id, id1, id3) values(12, 6, 1); + insert into test2(id, id1, id3) values(13, 6, 1); + insert into test2(id, id1, id3) values(14, 6, 1); + insert into test2(id, id1, id3) values(15, 6, 1); + + commit; + + execute procedure sp_truncate_stat; + commit; + + execute procedure sp_gather_stat; ------- catch statistics BEFORE measured statement(s) + commit; + + set term ^; + execute block as + declare c int; + begin + select count(*) -- v.*, t3.*, t1.* + from vlast_test1_for_test3_a v + join test3 t3 on t3.id=v.id3 + left join test1 t1 on t1.id=v.id1 + into c; + + select count(*) -- v.*, t3.*, t1.* + from vlast_test1_for_test3_b v + join test3 t3 on t3.id=v.id3 + left join test1 t1 on t1.id=v.id1 + into c; + end + ^ + set term ;^ + + execute procedure sp_gather_stat; ------- catch statistics AFTER measured statement(s) + commit; + + -- Show results (differences of saved monitoring counters): + -- ======================================================== + + set list on; + --set width table_name 10; + select v.table_name, v.natural_reads, v.indexed_reads + from v_agg_stat_tabs v + where table_name = upper('TEST1'); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TABLE_NAME TEST1 + NATURAL_READS 0 + INDEXED_READS 6 + """ + +@pytest.mark.version('>=3.0') +def test_eqc_343715_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_eqc_344124.py b/tests/functional/tabloid/test_eqc_344124.py new file mode 100644 index 00000000..b6578592 --- /dev/null +++ b/tests/functional/tabloid/test_eqc_344124.py @@ -0,0 +1,57 @@ +#coding:utf-8 +# +# id: functional.tabloid.eqc_344124 +# title: Check ability to run selectable SP with input parameter which inserts into GTT (on commit DELETE rows) and then does suspend +# decription: NB: if either a_id, suspend or the insert is removed, or if gtt_test is changed to on commit preserve rows - no crash +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate global temporary table gtt_test ( + id integer + ) on commit delete rows; + + set term ^; + create procedure test + returns ( + o_id integer) + as + begin + insert into gtt_test(id) values( 1 + rand() * 100 ) returning sign(id) into o_id; + --o_id = 0; + suspend; + end + ^ + set term ;^ + commit; + + set list on; + select * from test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + O_ID 1 + """ + +@pytest.mark.version('>=2.5') +def test_eqc_344124_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_gtcs_proc_isql_14.py b/tests/functional/tabloid/test_gtcs_proc_isql_14.py new file mode 100644 index 00000000..419c33cf --- /dev/null +++ b/tests/functional/tabloid/test_gtcs_proc_isql_14.py @@ -0,0 +1,103 @@ +#coding:utf-8 +# +# id: functional.tabloid.gtcs_proc_isql_14 +# title: gtcs-proc-isql-14 +# decription: +# Original test see in: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROC_ISQL_14.script +# SQL script for creating test database ('gtcs_sp1.fbk') and fill it with some data: +# https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/PROCS_QA_INIT_ISQL.script +# Checked on: +# 4.0.0.1803 SS: 1.822s. +# 3.0.6.33265 SS: 0.849s. +# 2.5.9.27149 SC: 0.313s. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='gtcs_sp1.fbk', init=init_script_1) + +test_script_1 = """ + set bail on; + set term ^; + create procedure proc14 returns (a varchar(20), b integer) as + begin + for + select pname,weight + from p + where weight < (select avg(weight) from p) + into :a, :b + do + suspend; + end + ^ + set term ;^ + + execute procedure proc14 ; + + select 'point-1' msg, p.* from proc14 p; + select 'point-2' msg, max(p.b) from proc14 p; + select 'point-3' msg, p.b from proc14 p; + select 'point-4' msg, p.a, p.b from proc14 p order by p.a; + select 'point-5' msg, p.a, avg(p.b) from proc14 p group by p.a having avg(p.b) > 10; + select 'point-6' msg, p.a, avg(p.b) from proc14 p group by p.a; + select 'point-7' msg, p.a, p.b from proc14 p where p.b > (select avg(x.b) from proc14 x); + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A B + Nut 12 + + + MSG A B + point-1 Nut 12 + point-1 Screw 14 + point-1 Cam 12 + + MSG MAX + point-2 14 + + MSG B + point-3 12 + point-3 14 + point-3 12 + + MSG A B + point-4 Cam 12 + point-4 Nut 12 + point-4 Screw 14 + + MSG A AVG + point-5 Cam 12 + point-5 Nut 12 + point-5 Screw 14 + + MSG A AVG + point-6 Cam 12 + point-6 Nut 12 + point-6 Screw 14 + + MSG A B + point-7 Screw 14 + """ + +@pytest.mark.version('>=2.5') +def test_gtcs_proc_isql_14_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_join_on_position_function_result.py b/tests/functional/tabloid/test_join_on_position_function_result.py new file mode 100644 index 00000000..5f383faf --- /dev/null +++ b/tests/functional/tabloid/test_join_on_position_function_result.py @@ -0,0 +1,78 @@ +#coding:utf-8 +# +# id: functional.tabloid.join_on_position_function_result +# title: Records with NULLs could be lost from resultset. +# decription: +# http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1009792&msg=14032086 +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table t(id int, s varchar(30)); + commit; + insert into t values(1, 'aaa'); + insert into t values(11, 'bbb'); + insert into t values(111, 'ccc'); + insert into t values(12, 'ddd'); + insert into t values(123, 'eee'); + insert into t values(1234, 'fff'); + commit; + + set list on; + select t.id, t.s, x.p, position(','||cast(t.id as varchar(11))||',', x.p) k + from t + left join (select ',123,12,11,' p from rdb$database) x + on position(','||cast(t.id as varchar(11))||',', x.p)>0 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + S aaa + P + K + ID 11 + S bbb + P ,123,12,11, + K 8 + ID 111 + S ccc + P + K + ID 12 + S ddd + P ,123,12,11, + K 5 + ID 123 + S eee + P ,123,12,11, + K 1 + ID 1234 + S fff + P + K + """ + +@pytest.mark.version('>=2.5') +def test_join_on_position_function_result_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_join_transformation_001.py b/tests/functional/tabloid/test_join_transformation_001.py new file mode 100644 index 00000000..d7b36e1c --- /dev/null +++ b/tests/functional/tabloid/test_join_transformation_001.py @@ -0,0 +1,94 @@ +#coding:utf-8 +# +# id: functional.tabloid.join_transformation_001 +# title: Check ability of outer join simplification. +# decription: Use null-rejected predicate, trivial case. +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='join-transformations.fbk', init=init_script_1) + +test_script_1 = """ + execute procedure sp_fill( 25, 30 ); + -- ^ ^- probability of assign each field on each row to NULL (percent). + -- +- number of rows in each of tables t1...t6 + + commit; + execute procedure sp_recalc_idx_stat; + commit; + + set list on; + set term ^; + execute block returns(result varchar(50)) as + begin + select result + from sp_run( + ---------------------- Query-1 (not simplified) + -- NB: we have to make "padding" of null literals up to 6 fields + -- if query returns less columns: + 'select t1.id, t2.id, t3.id, t4.id, null, null + from t1 + left join t2 on t1.x = t2.x + left join t3 on t2.y = t3.y + join t4 on t4.z not in( t1.u, t2.v, t3.w) and t4.y = t1.v' + , + ---------------------- Query-2 (simplified and we assume that it ALWAYS produces the same result as Q1) + 'select t1.id, t2.id, t3.id, t4.id, null, null + from t1 + inner join t2 on t1.x = t2.x + inner join t3 on t2.y = t3.y + inner join t4 on t4.z not in( t1.u, t2.v, t3.w) and t4.y = t1.v' + , 0 ------------------------------------ nr_total: when 0 then do NOT run sp_fill because we already do have data for checking + ) into result; + + suspend; + + if ( result not containing 'Passed' ) then + -- this context variable serves as 'flag' to show + -- problematic data (see following EB): + rdb$set_context('USER_SESSION', 'FAULT', '1'); + end + ^ + execute block returns( failed_on varchar(255) ) as + begin + -- When queries are NOT equal on some data then we have to output + -- rows from all tables in order to reproduce this trouble later: + if ( rdb$get_context('USER_SESSION', 'FAULT') = '1' ) then + begin + for + select dml from sp_show_data + into failed_on + do + suspend; + end + end + ^ + set term ^; + + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT Passed. + """ + +@pytest.mark.version('>=3.0') +def test_join_transformation_001_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_join_transformation_002.py b/tests/functional/tabloid/test_join_transformation_002.py new file mode 100644 index 00000000..15705a81 --- /dev/null +++ b/tests/functional/tabloid/test_join_transformation_002.py @@ -0,0 +1,92 @@ +#coding:utf-8 +# +# id: functional.tabloid.join_transformation_002 +# title: Check ability of outer join simplification. +# decription: Use null-rejected predicate in WHERE filtering leads to replacement of TWO outer joins. +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='join-transformations.fbk', init=init_script_1) + +test_script_1 = """ + execute procedure sp_fill( 50, 30 ); + -- ^ ^- probability of assign each field on each row to NULL (percent). + -- +- number of rows in each of tables t1...t6 + + commit; + execute procedure sp_recalc_idx_stat; + commit; + + set list on; + set term ^; + execute block returns(result varchar(50)) as + begin + select result + from sp_run( + ---------------------- Query-1 (not simplified) + -- NB: we have to make "padding" of null literals up to 6 fields + -- if query returns less columns: + 'select t1.id, t2.id, t3.id, null, null, null + from t1 + left join (t2 left join t3 on t2.x = t3.x) on t1.y = t2.y + where t3.u > 0' + , + ---------------------- Query-2 (simplified and we assume that it ALWAYS produces the same result as Q1) + 'select t1.id, t2.id, t3.id, null, null, null + from t1 + inner join (t2 inner join t3 on t2.x = t3.x) on t1.y = t2.y + where t3.u > 0' + , 0 ------------------------------------ nr_total: when 0 then do NOT run sp_fill because we already do have data for checking + ) into result; + + suspend; + + if ( result not containing 'Passed' ) then + -- this context variable serves as 'flag' to show + -- problematic data (see following EB): + rdb$set_context('USER_SESSION', 'FAULT', '1'); + end + ^ + execute block returns( failed_on varchar(255) ) as + begin + -- When queries are NOT equal on some data then we have to output + -- rows from all tables in order to reproduce this trouble later: + if ( rdb$get_context('USER_SESSION', 'FAULT') = '1' ) then + begin + for + select dml from sp_show_data + into failed_on + do + suspend; + end + end + ^ + set term ^; + + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT Passed. + """ + +@pytest.mark.version('>=3.0') +def test_join_transformation_002_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_join_transformation_003.py b/tests/functional/tabloid/test_join_transformation_003.py new file mode 100644 index 00000000..b93e2d7b --- /dev/null +++ b/tests/functional/tabloid/test_join_transformation_003.py @@ -0,0 +1,110 @@ +#coding:utf-8 +# +# id: functional.tabloid.join_transformation_003 +# title: Check ability of outer join simplification. +# decription: Null-rejected expr in WHERE clause refers to most right datasource, and this leads to replacement of TWO outer joins. +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='join-transformations.fbk', init=init_script_1) + +test_script_1 = """ + execute procedure sp_fill( 50, 30 ); + -- ^ ^- probability of assign each field on each row to NULL (percent). + -- +- number of rows in each of tables t1...t6 + + commit; + execute procedure sp_recalc_idx_stat; + commit; + + set list on; + set term ^; + execute block returns(result varchar(50)) as + begin + select result + from sp_run( + ---------------------- Query-1 (not simplified) + -- NB: we have to make "padding" of null literals up to 6 fields + -- if query returns less columns: + 'select a.id, b.id, c.id, d.id, null, null + from ( + t1 a + left + join t2 b using(x,y) + ) + left + join ( + t3 c + left + join t4 d using(x,y) + ) using(x,y) + where d.x>0' -- NB: 'd' is alias for t4 which is most right data source. + , + ---------------------- Query-2 (simplified and we assume that it ALWAYS produces the same result as Q1) + 'select a.id, b.id, c.id, d.id, null, null + from ( + t1 a + left -- NB: this can NOT be replaced with "inner"! + join t2 b using(x,y) + ) + inner -- [1] + join ( + t3 c + inner -- [2] + join t4 d using(x,y) + ) using(x,y) + where d.x>0' + , 0 ------------------------------------ nr_total: when 0 then do NOT run sp_fill because we already do have data for checking + ) into result; + + suspend; + + if ( result not containing 'Passed' ) then + -- this context variable serves as 'flag' to show + -- problematic data (see following EB): + rdb$set_context('USER_SESSION', 'FAULT', '1'); + end + ^ + execute block returns( failed_on varchar(255) ) as + begin + -- When queries are NOT equal on some data then we have to output + -- rows from all tables in order to reproduce this trouble later: + if ( rdb$get_context('USER_SESSION', 'FAULT') = '1' ) then + begin + for + select dml from sp_show_data + into failed_on + do + suspend; + end + end + ^ + set term ^; + + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT Passed. + """ + +@pytest.mark.version('>=3.0') +def test_join_transformation_003_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_join_transformation_004.py b/tests/functional/tabloid/test_join_transformation_004.py new file mode 100644 index 00000000..a5bf4020 --- /dev/null +++ b/tests/functional/tabloid/test_join_transformation_004.py @@ -0,0 +1,107 @@ +#coding:utf-8 +# +# id: functional.tabloid.join_transformation_004 +# title: Check ability of outer join simplification. +# decription: +# Two datasources are involved in the null-rejecting predicate in the WHERE-filtering. +# Because of DISJUNCTION usage ('where ... OR ...'), replacement of outer join with +# inner one is possible only for part of query that is BEFORE (left-side) of first DS. +# This means that we can not simplify LOJ of 'c' and 'd' datasources - see code below. +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='join-transformations.fbk', init=init_script_1) + +test_script_1 = """ + execute procedure sp_fill( 35, 30 ); + -- ^ ^- probability of assign each field on each row to NULL (percent). + -- +- number of rows in each of tables t1...t6 + + commit; + execute procedure sp_recalc_idx_stat; + commit; + + set list on; + set term ^; + execute block returns(result varchar(50)) as + begin + select result + from sp_run( + ---------------------- Query-1 (not simplified) + -- NB: we have to make "padding" of null literals up to 6 fields + -- if query returns less columns: + 'select a.id, b.id, c.id, d.id, null, null + from (t1 a left join t2 b using(x,y) ) + left ----------------------------------------- [1] + join ( + t3 c + left ------------------------------------- [2]: this can NOT be replaced with INNER because of disjunction expr in WHERE-filtering + join t4 d using(x,y) + ) using(x,y) + where c.u>0 or d.v>0' + -- ^-------------------------------------- !!! + , + ---------------------- Query-2 (simplified and we assume that it ALWAYS produces the same result as Q1) + 'select a.id, b.id, c.id, d.id, null, null + from (t1 a left join t2 b using(x,y) ) + INNER + join ( + t3 c + left + join t4 d using(x,y) + ) using(x,y) + where c.u>0 or d.v>0' + , 0 ------------------------------------ nr_total: when 0 then do NOT run sp_fill because we already do have data for checking + ) into result; + + suspend; + + if ( result not containing 'Passed' ) then + -- this context variable serves as 'flag' to show + -- problematic data (see following EB): + rdb$set_context('USER_SESSION', 'FAULT', '1'); + end + ^ + execute block returns( failed_on varchar(255) ) as + begin + -- When queries are NOT equal on some data then we have to output + -- rows from all tables in order to reproduce this trouble later: + if ( rdb$get_context('USER_SESSION', 'FAULT') = '1' ) then + begin + for + select dml from sp_show_data + into failed_on + do + suspend; + end + end + ^ + set term ^; + + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT Passed. + """ + +@pytest.mark.version('>=3.0') +def test_join_transformation_004_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_join_transformation_005.py b/tests/functional/tabloid/test_join_transformation_005.py new file mode 100644 index 00000000..9019a971 --- /dev/null +++ b/tests/functional/tabloid/test_join_transformation_005.py @@ -0,0 +1,100 @@ +#coding:utf-8 +# +# id: functional.tabloid.join_transformation_005 +# title: Check ability of outer join simplification. +# decription: +# Query like this: +# A inner join B left join C can be simplified to: +# A inner join B inner join C +# -- if join-expression of 'B left join C' is null-rejecting. +# +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='join-transformations.fbk', init=init_script_1) + +test_script_1 = """ + execute procedure sp_fill( 35, 30 ); + -- ^ ^- probability of assign each field on each row to NULL (percent). + -- +- number of rows in each of tables t1...t6 + + commit; + execute procedure sp_recalc_idx_stat; + commit; + + set list on; + set term ^; + execute block returns(result varchar(50)) as + begin + select result + from sp_run( + ---------------------- Query-1 (not simplified) + -- NB: we have to make "padding" of null literals up to 6 fields + -- if query returns less columns: + 'select a.id, b.id, c.id, null, null, null + from t1 a + left ---------------------------- [1]: this can be replaced with INNER. + join t2 b on a.x = b.y + join t3 c on b.y = c.z' + -- ^^^^^^^^^------------ this is null-rejected expression + , + ---------------------- Query-2 (simplified and we assume that it ALWAYS produces the same result as Q1) + 'select a.id, b.id, c.id, null, null, null + from t1 a + inner + join t2 b on a.x = b.y + join t3 c on b.y = c.z' + , 0 ------------------------------------ nr_total: when 0 then do NOT run sp_fill because we already do have data for checking + ) into result; + + suspend; + + if ( result not containing 'Passed' ) then + -- this context variable serves as 'flag' to show + -- problematic data (see following EB): + rdb$set_context('USER_SESSION', 'FAULT', '1'); + end + ^ + execute block returns( failed_on varchar(255) ) as + begin + -- When queries are NOT equal on some data then we have to output + -- rows from all tables in order to reproduce this trouble later: + if ( rdb$get_context('USER_SESSION', 'FAULT') = '1' ) then + begin + for + select dml from sp_show_data + into failed_on + do + suspend; + end + end + ^ + set term ^; + + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT Passed. + """ + +@pytest.mark.version('>=3.0') +def test_join_transformation_005_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_join_transformation_006.py b/tests/functional/tabloid/test_join_transformation_006.py new file mode 100644 index 00000000..07380349 --- /dev/null +++ b/tests/functional/tabloid/test_join_transformation_006.py @@ -0,0 +1,115 @@ +#coding:utf-8 +# +# id: functional.tabloid.join_transformation_006 +# title: Check ability of outer join simplification. +# decription: +# We can replace 'A left join B' with 'A inner join B' if: +# 1. Both of these datasources are referred later in the expression of INNER join with some else datasource, and +# 2. There are no disjunction in this expression, i.e. its parts aren't linked by "OR", and +# 3. Each part of this expression is null-rejected. +# +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='join-transformations.fbk', init=init_script_1) + +test_script_1 = """ + execute procedure sp_fill( 40, 30 ); + -- ^ ^- probability of assign each field on each row to NULL (percent). + -- +- number of rows in each of tables t1...t6 + + commit; + execute procedure sp_recalc_idx_stat; + commit; + + set list on; + set term ^; + execute block returns(result varchar(50)) as + begin + select result + from sp_run( + ---------------------- Query-1 (not simplified) + -- NB: we have to make "padding" of null literals up to 6 fields + -- if query returns less columns: + 'select a.id, b.id, c.id, d.id, null, null + from + ( + ( t1 a + LEFT + join t2 b on a.x = b.y + ) + left join t3 c on a.y = c.z + ) + inner join t4 d on a.v = d.w and b.z = d.u' + -- ^-- INNER clause + absence of disjunction ("or"-parts) + null-rejecting of each parts ("a.v = d.w"; "b.z = d.u") + -- makes this expression as whole null-rejecting. + , + ---------------------- Query-2 (simplified and we assume that it ALWAYS produces the same result as Q1) + 'select a.id, b.id, c.id, d.id, null, null + from + ( + ( t1 a + INNER + join t2 b on a.x = b.y + ) + left join t3 c on a.y = c.z + ) + inner join t4 d on a.v = d.w and b.z = d.u' + -- ^ ^ + -- +-------------+------> these datasources can be INNER joined because they + -- BOTH participate in null-rejecting expression. + + , 0 ------------------------------------ nr_total: when 0 then do NOT run sp_fill because we already do have data for checking + ) into result; + + suspend; + + if ( result not containing 'Passed' ) then + -- this context variable serves as 'flag' to show + -- problematic data (see following EB): + rdb$set_context('USER_SESSION', 'FAULT', '1'); + end + ^ + execute block returns( failed_on varchar(255) ) as + begin + -- When queries are NOT equal on some data then we have to output + -- rows from all tables in order to reproduce this trouble later: + if ( rdb$get_context('USER_SESSION', 'FAULT') = '1' ) then + begin + for + select dml from sp_show_data + into failed_on + do + suspend; + end + end + ^ + set term ^; + + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT Passed. + """ + +@pytest.mark.version('>=3.0') +def test_join_transformation_006_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_join_transformation_007.py b/tests/functional/tabloid/test_join_transformation_007.py new file mode 100644 index 00000000..487290f2 --- /dev/null +++ b/tests/functional/tabloid/test_join_transformation_007.py @@ -0,0 +1,126 @@ +#coding:utf-8 +# +# id: functional.tabloid.join_transformation_007 +# title: Check ability of outer join simplification. +# decription: +# For two datasources (S1, S2) and some complex query Q which has inside itself: "... left join S2 [...]" +# we can replace LEFT OUTER joins inside Q with INNER if S1 and S2 are involved in INNER join with +# null-rejected expression, i.e.: +# +# S1 join ( Q left join S2 ) on null_rej (S1.b,S2.f) ==> S1 join ( Q join S2 ) on null_rej (S1.b,S2.f) +# +# +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='join-transformations.fbk', init=init_script_1) + +test_script_1 = """ + execute procedure sp_fill( 40, 30 ); + -- ^ ^- probability of assign each field on each row to NULL (percent). + -- +- number of rows in each of tables t1...t6 + + commit; + execute procedure sp_recalc_idx_stat; + commit; + + set list on; + set term ^; + execute block returns(result varchar(50)) as + begin + select result + from sp_run( + ---------------------- Query-1 (not simplified) + -- NB: we have to make "padding" of null literals up to 6 fields + -- if query returns less columns: + 'select a.id, b.id, c.id, d.id, e.id, f.id + from t1 a + left join + (t2 b ------------------------------------------------------ source_1 + join + (t3 c + left + join (t4 d + left + join (t5 e + left + join t6 f ----------------------------- source_2 + on e.y=f.z + ) on d.x = e.y and f.y = d.z + ) on c.y = e.z + ) on c.u = d.w + ) on b.x = f.z' + -- ^-----^--------------------- columns from source_1 and source_2 participates here in null-rejecting expr. + , + ---------------------- Query-2 (simplified and we assume that it ALWAYS produces the same result as Q1) + 'select a.id, b.id, c.id, d.id, e.id, f.id + from t1 a + left join + (t2 b + join + (t3 c + inner + join (t4 d + inner + join (t5 e + inner + join t6 f + on e.y=f.z + ) on d.x = e.y and f.y = d.z + ) on c.y = e.z + ) on c.u = d.w + ) on b.x = f.z' + , 0 ------------------------------------ nr_total: when 0 then do NOT run sp_fill because we already do have data for checking + ) into result; + + suspend; + + if ( result not containing 'Passed' ) then + -- this context variable serves as 'flag' to show + -- problematic data (see following EB): + rdb$set_context('USER_SESSION', 'FAULT', '1'); + end + ^ + execute block returns( failed_on varchar(255) ) as + begin + -- When queries are NOT equal on some data then we have to output + -- rows from all tables in order to reproduce this trouble later: + if ( rdb$get_context('USER_SESSION', 'FAULT') = '1' ) then + begin + for + select dml from sp_show_data + into failed_on + do + suspend; + end + end + ^ + set term ^; + + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT Passed. + """ + +@pytest.mark.version('>=3.0') +def test_join_transformation_007_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_join_transformation_008.py b/tests/functional/tabloid/test_join_transformation_008.py new file mode 100644 index 00000000..6f3e75e9 --- /dev/null +++ b/tests/functional/tabloid/test_join_transformation_008.py @@ -0,0 +1,158 @@ +#coding:utf-8 +# +# id: functional.tabloid.join_transformation_008 +# title: Check ability of outer join simplification. +# decription: +# From join-transformation-008.fbt: +# === +# For two sources, S and T, which: +# 1) are separated by at least one "intermediate" source G (e.g. which is just "after" S and is "before" T), and +# 2) are involved into left join predicate P(S,T) which does not participate in disjunction ("OR"ed) expression +# -- one may to replace all LEFT joins starting from G and up to T with INNER ones. +# Join condition between S and its adjacent datasource (G) should be preserved as it is in original query. +# === +# Additional case here: when a query has several predicates {P1, P2,..., Pn} that involves non-adjacent datasources +# and are null-rejected then we can replace left-outer joins with inner ones separately for each of {P1, P2,..., Pn}. +# Moreover, if some pair of them (say, Px and Py) have common "affecting area" (affects on the same datasources) then +# result of replacement for Px can be preserved even if some of aliases (affected by Px) are starting pair for Py +# (which could NOT be replaced if query would have only one Py) - this effect looks like "bin_or". +# +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='join-transformations.fbk', init=init_script_1) + +test_script_1 = """ + execute procedure sp_fill( 20, 20 ); + -- ^ ^- probability of assign each field on each row to NULL (percent). + -- +- number of rows in each of tables t1...t6 + + commit; + execute procedure sp_recalc_idx_stat; + commit; + + set list on; + set term ^; + execute block returns(result varchar(50)) as + begin + select result + from sp_run( + ---------------------- Query-1 (not simplified) + -- NB: we have to make "padding" of null literals up to 6 fields + -- if query returns less columns. + + -- Here we have two predicates that "jumps" over more than one datasource, + -- i.e. they involve relations which are NOT adjacent in the query. + -- Hereafter such predicates are called "jumpers". + -- First such predicate is "a.z = d.x" - it involve relations A & D and + -- its affecting area is marked below as "::::::::::::::". + -- Second is "b.w = e.y" - it involve relations B &E and its affecting area + -- is marked as "%%%%%%%%%%%%%". + -- Note that these areas are crossed, i.e. they have common portion: + -- a b c d e + -- ::::::::::::::::::::::::: + -- %%%%%%%%%%%%%%%%%%%%%%%%% + -- + -- Note also that relation F is not affected by these predicates. + -- Because all expressions are null-rejected, we can replace LEFT joins with INNER ones + -- in the following places: + -- 1) for predicate "a.z=d.x" - starting from 'b left join c' and up to 'c left join d'; + -- 2) for predicate "b.w=e.y" - starting from 'c left join d' and up to 'd left join d'. + -- If 2nd predicate would be single that "jumps" over several datasources, then we could + -- NOT to change 'b left join c' with inner. But we DO this when handle 1st "jumper", and + -- this replacement (will be made for "a.z=d.x") is NOT discarded: this looks like "bin_or" + -- result. In other words, if some LEFT_JOIN could be replaced with INNER one because of + -- "jumping" predicate, this result shoudl be preserved during handling of further "jumpers". + + 'select a.id, b.id, c.id, d.id, e.id, f.id + from t1 a + LEFT + join t2 b + left + join t3 c + left + join t4 d + left -- +-- this alias is NOT afffected by any of "jumpers"! + join t5 e -- | + left -- | + join t6 F + on e.x = f.u + on d.z = e.y + on c.y = e.x + on b.w = e.y + -- %%%%%%%%% (2ns "jumper") + on a.z = d.x' + -- ::::::::: (1st "jumper") + , + 'select a.id, b.id, c.id, d.id, e.id, f.id + from t1 a + LEFT -- this should be preserved anyway; explanation see in "join-transformation-008.fbt" + join t2 b + INNER -- "BIN_OR" here! This could NOT be done if we have only 2nd "jumper" (`b.w = e.y`) which STARTS from `b`. + -- -- -- can be replaced because of jumper-1 ("a.z = d.x"); and this result will be PRESERVED despite of jumper-2. + join t3 c + inner -- can be replaced because of jumper-2 ("b.w = e.y") + join t4 d + inner -- can be replaced because of jumper-2 ("b.w = e.y") + join t5 e + LEFT -- <<< !! this should be preserved as OUTER join !! + join t6 F + on e.x = f.u + on d.z = e.y + on c.y = e.x + on b.w = e.y + on a.z = d.x' + , 0 ------------------------------------ nr_total: when 0 then do NOT run sp_fill because we already do have data for checking + ) into result; + + suspend; + + if ( result not containing 'Passed' ) then + -- this context variable serves as 'flag' to show + -- problematic data (see following EB): + rdb$set_context('USER_SESSION', 'FAULT', '1'); + end + ^ + execute block returns( failed_on varchar(255) ) as + begin + -- When queries are NOT equal on some data then we have to output + -- rows from all tables in order to reproduce this trouble later: + if ( rdb$get_context('USER_SESSION', 'FAULT') = '1' ) then + begin + for + select dml from sp_show_data + into failed_on + do + suspend; + end + end + ^ + set term ^; + + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT Passed. + """ + +@pytest.mark.version('>=3.0') +def test_join_transformation_008_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_loose_record_when_relief_where_expr.py b/tests/functional/tabloid/test_loose_record_when_relief_where_expr.py new file mode 100644 index 00000000..8628b92c --- /dev/null +++ b/tests/functional/tabloid/test_loose_record_when_relief_where_expr.py @@ -0,0 +1,79 @@ +#coding:utf-8 +# +# id: functional.tabloid.loose_record_when_relief_where_expr +# title: Uncomment of one part of OR'ed expression led to loose of record from resultset. +# decription: +# "OR" could __reduce__ number of rows in resultset. +# See leters to/from dimitr 23.09.2010 (probably this bug was due to occasional typo). +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + with + tset_init as + ( + select + 61844284 srvt_id + ,n.row_id + from + rdb$database lcat + left join ( + select 1 row_id from rdb$database + union all select 2 from rdb$database + ) n on 1=1 + ) + ,t_separate as + ( + select + srvt_id + ,row_id + ,v.c selected_case + from tset_init + join ( + select 'A' c from rdb$database + union all + select 'B' from rdb$database + ) v + on + v.c='A' + -- One record DISappeared from resultset when this part + -- of OR'ed expression was UNcommented. + or v.c='B' and srvt_id=0 -- 2.5.0, /src/jrd/opt.cpp, line 4228: for (UCHAR i = 1; i <= streams[0]; i++) + ) + select t.* from t_separate t + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + SRVT_ID 61844284 + ROW_ID 1 + SELECTED_CASE A + SRVT_ID 61844284 + ROW_ID 2 + SELECTED_CASE A + """ + +@pytest.mark.version('>=2.5') +def test_loose_record_when_relief_where_expr_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_max_path_length.py b/tests/functional/tabloid/test_max_path_length.py new file mode 100644 index 00000000..5d47b253 --- /dev/null +++ b/tests/functional/tabloid/test_max_path_length.py @@ -0,0 +1,604 @@ +#coding:utf-8 +# +# id: functional.tabloid.max_path_length +# title: Check ability to create database with total length of path and file name about maximal allowed limit in Windows +# decription: +# Maximal TOTAL length of :\\\\ on Windows is about 260 characters. +# Firebird can *not* create DB file with such length, attempt to do this will failed with message: +# SQLSTATE = 08001 / I/O error during "CreateFile (create)" ... / -Error while trying to create file ... +# +# Firebird *allows* to create database with path length = 259 but this DB can not be referred +# neither using rdb$get_context('SYSTEM','DB_NAME') nor vis MON$DATABASE. +# +# Firebird database with path+name length >= 253 can not be subject of NBACKUP -L because of ".delta" suffix +# which always is added to the full path+name of database and this will raise: +# PROBLEM ON "begin backup: commit". +# I/O error during "CreateFile (create)" operation for file "<...>.FDB.delta" +# -Error while trying to create file +# - // localized message here +# SQLCODE:-902 +# +# Firebird database with length >= 246 can be backed up but can not be restored (if DB name will be such length). +# Maximal length of database that is created on Windows (:\\\\) is 245. +# +# Test uses this length (see below, MAX_FILE_NAME_SIZE) and cheks that one may to do following: +# * create such database and add some DB objects in it (table with index and procedure); +# * use encrypt and decrypt actions against this DB; SHOW database must display actual state of this DB; +# * extract metadata from this database; +# * call fb_lock_print utility with requirement to show Lock Manager info about this database; +# * invoke utilities: gstat -r; gfix; fbsvcmgr +# +# See also: http://tracker.firebirdsql.org/browse/CORE-6248 +# +# All these actions are performed with active trace user session, which registers database and services activity. +# Finally we check that: +# * all above mentioned actions did not failed, i.e. they did not issue somewhat into STDERR; +# * trace log has records about all services which did start. +# * trace log does NOT contain 'FAILED START_SERVICE' +# +# Note-1. +# Test database that is created by fbtest framework will be encrypted here using IBSurgeon Demo Encryption package +# ( https://ib-aid.com/download-demo-firebird-encryption-plugin/ ; https://ib-aid.com/download/crypt/CryptTest.zip ) +# License file plugins\\dbcrypt.conf with unlimited expiration was provided by IBSurgeon to Firebird Foundation (FF). +# This file was preliminary stored in FF Test machine. +# Test assumes that this file and all neccessary libraries already were stored into FB_HOME and %FB_HOME%\\plugins. +# +# Anyone who wants to run this test on his own machine must +# 1) download https://ib-aid.com/download/crypt/CryptTest.zip AND +# 2) PURCHASE LICENSE and get from IBSurgeon file plugins\\dbcrypt.conf with apropriate expiration date and other info. +# +# ################################################ ! ! ! N O T E ! ! ! ############################################## +# FF tests storage (aka "fbt-repo") does not (and will not) contain any license file for IBSurgeon Demo Encryption package! +# ######################################################################################################################### +# +# Note-2. +# Encryption/decryption is executed as separate server thread and can not be done instantly thus requiring some pause. +# This delay is implemented by starting transaction with LOCK TIMEOUT and making attempt to insert duplicate into +# table with unique index. Though error can be supressed in PSQL code, it *does* appear in the trace log as two lines: +# Error in the trace: 335544665 : violation of PRIMARY or UNIQUE KEY constraint "TEST_UNQ" on table "TEST" +# Error in the trace: 335545072 : Problematic key value is ("S" = '000000000000000000000000000000000000') +# We have to ignore these errors because it is expected (they must appear twise: after start of encryption and decruption). +# +# Checked on: +# 4.0.0.1767 SS: 15.266s. +# 4.0.0.1712 SC: 16.438s. +# 4.0.0.1763 CS: 17.719s. +# 3.0.6.33246 SS: 10.656s. +# 3.0.5.33084 SC: 14.563s. +# 3.0.6.33246 CS: 14.595s. +# +# 21.01.2021: added check for trace STDERR because of crash FB 4.0.0.2335 SS/CS. Refactored code for saving logs. +# +# +# tracker_id: +# min_versions: ['3.0.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import time +# import re +# import subprocess +# from fdb import services +# +# MAX_FILE_NAME_SIZE=245 # last value with result = ok +# #MAX_FILE_NAME_SIZE=246 # 246 --> get error in gbak; 254 --> can not run nbackup -L +# #MAX_FILE_NAME_SIZE=254 +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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'): +# # 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 os.path.isfile( f_names_list[i]): +# os.remove( f_names_list[i] ) +# +# #-------------------------------------------- +# +# +# fb_home = services.connect(host='localhost', user= user_name, password= user_password).get_home_directory() +# +# db_folder=context['temp_directory'] +# db_ext = '.fdb' +# bk_ext = '.fbk' +# db_longest_name = ('1234567890' * 1000) [ : MAX_FILE_NAME_SIZE - len( db_folder ) - len(db_ext) ] + db_ext +# bk_longest_name = db_longest_name[ : -len(db_ext )] + bk_ext +# db_longest_repl = db_longest_name[ : -len(db_ext )] + '.tmp' +# nb_longest_name = db_longest_name[ : -len(db_ext )] + '.nb0' +# +# # --------------------------- generate trace config and launch trace ------------------------------------ +# +# txt = ''' database=%%[\\\\\\\\/]%(db_longest_name)s +# { +# enabled = true +# time_threshold = 0 +# log_initfini = false +# log_connections = true +# # log_transactions = true +# log_errors = true +# log_sweep = true +# log_statement_finish = true +# } +# +# services +# { +# enabled = true +# log_errors = true +# log_initfini = false +# log_services = true +# exclude_filter = "%%((List Trace Sessions)|(Start Trace Session)|(Stop Trace Session))%%" +# # include_filter = "%%((backup database)|(restore database)|(repair database)|(validate database)|(incremental backup database)|(incremental restore database))%%" +# } +# ''' % locals() +# +# trc_cfg=open( os.path.join(context['temp_directory'],'trc_maxpath.cfg'), 'w') +# trc_cfg.write(txt) +# trc_cfg.close() +# +# ##################################################################### +# # Async. launch of trace session using FBSVCMGR action_trace_start: +# +# trc_log = open( os.path.join(context['temp_directory'],'trc_maxpath.log'), "w") +# trc_err = open( os.path.join(context['temp_directory'],'trc_maxpath.err'), "w") +# # Execute a child program in a new process, redirecting STDERR to the same target as of STDOUT: +# p_svcmgr = subprocess.Popen( [ "fbsvcmgr", "localhost:service_mgr", +# "action_trace_start", +# "trc_cfg", trc_cfg.name +# ], +# stdout=trc_log, +# stderr=trc_err +# ) +# +# # 08.01.2020. This delay is mandatory, otherwise file with trace session info can remain (sometimes) +# # empty when we will read it at the next step: +# time.sleep(2) +# +# +# # Determine active trace session ID (for further stop): +# ######################## +# trc_lst=open( os.path.join(context['temp_directory'],'trc_maxpath.lst'), 'w') +# subprocess.call(["fbsvcmgr", "localhost:service_mgr", +# "action_trace_list"], +# stdout=trc_lst, stderr=subprocess.STDOUT +# ) +# flush_and_close( trc_lst ) +# +# # Session ID: 5 +# # user: +# # date: 2015-08-27 15:24:14 +# # flags: active, trace +# +# sid_pattern = re.compile('Session\\s+ID[:]{0,1}\\s+\\d+', re.IGNORECASE) +# +# trc_ssn=0 +# with open( trc_lst.name,'r') as f: +# for line in f: +# if sid_pattern.search( line ) and len( line.split() ) == 3: +# trc_ssn = line.split()[2] +# break +# +# # Result: `trc_ssn` is ID of active trace session. +# # We have to terminate trace session that is running on server BEFORE we termitane process `p_svcmgr` +# +# +# # ---------------------- generating .SQL and create databse with long name ------------------------------ +# +# if os.path.isfile( db_folder + db_longest_name ): +# os.remove( db_folder + db_longest_name ) +# +# sql_ddl=''' +# -- set bail on; +# set list on; +# set names utf8; +# shell del %(db_folder)s%(db_longest_name)s 2>nul; +# create database 'localhost:%(db_folder)s%(db_longest_name)s' default character set utf8; +# create table test( s varchar(36), constraint test_unq unique(s) ); +# commit; +# insert into test(s) values( lpad('', 36, '0') ); +# commit; +# +# alter database set linger to 0; +# commit; +# insert into test select uuid_to_char(gen_uuid()) from rdb$types; +# commit; +# set term ^; +# create procedure sp_pause as +# declare s1 varchar(36); +# begin +# update test set s = s +# order by s rows 1 +# returning s into s1; +# execute statement ( 'insert into test(s) values(?)' ) ( s1 ) +# on external +# 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') +# as user 'SYSDBA' password 'masterkey' role left(replace( uuid_to_char(gen_uuid()), '-', ''), 31); +# when any do +# begin +# +# end +# end +# ^ +# set term ;^ +# commit; +# +# alter database encrypt with dbcrypt key Red; +# commit; +# set transaction lock timeout 1; +# execute procedure sp_pause; +# show database; +# +# alter database decrypt; +# commit; +# set transaction lock timeout 1; +# execute procedure sp_pause; +# show database; +# +# shell %(fb_home)sfb_lock_print -c -d %(db_folder)s%(db_longest_name)s; +# +# ''' % locals() +# +# f_isql_cmd=open( os.path.join(context['temp_directory'],'tmp_maxpath_test.sql'), 'w', buffering = 0) +# f_isql_cmd.write(sql_ddl) +# flush_and_close( f_isql_cmd ) +# +# # ---------------------- generating .bat for execute actions with DB via Firebird utilities ------------------------- +# +# f_isql_name=f_isql_cmd.name +# tmp_bat_text=''' +# @echo off +# setlocal enabledelayedexpansion enableextensions +# set tmplog=%%~dpn0.log +# set tmperr=%%~dpn0.err +# +# del !tmplog! 2>nul +# del !tmperr! 2>nul +# +# set ISC_USER=%(user_name)s +# set ISC_PASSWORD=%(user_password)s +# +# set run_cmd=%(fb_home)sisql -q -i %(f_isql_name)s +# echo. >>!tmplog! +# echo !run_cmd! 1>>!tmplog! +# cmd /c !run_cmd! 1>>!tmplog! 2>!tmperr! +# @rem --------------------------------------------------------------------------------------- +# +# set run_cmd=%(fb_home)sisql localhost:%(db_folder)s%(db_longest_name)s -x -ch utf8 +# echo. >>!tmplog! +# echo !run_cmd! 1>>!tmplog! +# cmd /c !run_cmd! 1>>!tmplog! 2>!tmperr! +# +# @rem --------------------------------------------------------------------------------------- +# +# set run_cmd=%(fb_home)sgstat -r localhost:%(db_folder)s%(db_longest_name)s +# echo. >>!tmplog! +# echo !run_cmd! 1>>!tmplog! +# cmd /c !run_cmd! 1>>!tmplog! 2>!tmperr! +# @rem --------------------------------------------------------------------------------------- +# +# set run_cmd=%(fb_home)sgfix -shut full -force 0 localhost:%(db_folder)s%(db_longest_name)s +# echo. >>!tmplog! +# echo !run_cmd! 1>>!tmplog! +# cmd /c !run_cmd! 1>>!tmplog! 2>!tmperr! +# @rem --------------------------------------------------------------------------------------- +# +# set run_cmd=%(fb_home)sgfix -online localhost:%(db_folder)s%(db_longest_name)s +# echo. >>!tmplog! +# echo !run_cmd! 1>>!tmplog! +# cmd /c !run_cmd! 1>>!tmplog! 2>!tmperr! +# @rem --------------------------------------------------------------------------------------- +# +# set run_cmd=%(fb_home)sgfix -v -full localhost:%(db_folder)s%(db_longest_name)s +# echo. >>!tmplog! +# echo !run_cmd! 1>>!tmplog! +# cmd /c !run_cmd! 1>>!tmplog! 2>!tmperr! +# @rem --------------------------------------------------------------------------------------- +# +# set run_cmd=%(fb_home)sgfix -w async localhost:%(db_folder)s%(db_longest_name)s +# echo. >>!tmplog! +# echo !run_cmd! 1>>!tmplog! +# cmd /c !run_cmd! 1>>!tmplog! 2>!tmperr! +# @rem --------------------------------------------------------------------------------------- +# +# +# set run_cmd=%(fb_home)sgfix -sweep localhost:%(db_folder)s%(db_longest_name)s +# echo. >>!tmplog! +# echo !run_cmd! 1>>!tmplog! +# cmd /c !run_cmd! 1>>!tmplog! 2>!tmperr! +# @rem --------------------------------------------------------------------------------------- +# +# set run_cmd=%(fb_home)snbackup -L %(db_folder)s%(db_longest_name)s +# echo. >>!tmplog! +# echo !run_cmd! 1>>!tmplog! +# cmd /c !run_cmd! 1>>!tmplog! 2>!tmperr! +# @rem --------------------------------------------------------------------------------------- +# +# set run_cmd=%(fb_home)snbackup -N %(db_folder)s%(db_longest_name)s +# echo. >>!tmplog! +# echo !run_cmd! 1>>!tmplog! +# cmd /c !run_cmd! 1>>!tmplog! 2>!tmperr! +# @rem --------------------------------------------------------------------------------------- +# +# set run_cmd=%(fb_home)sfbsvcmgr localhost:service_mgr action_repair rpr_sweep_db dbname %(db_folder)s%(db_longest_name)s +# echo. >>!tmplog! +# echo !run_cmd! 1>>!tmplog! +# cmd /c !run_cmd! 1>>!tmplog! 2>!tmperr! +# +# @rem --------------------------------------------------------------------------------------- +# +# +# set run_cmd=%(fb_home)sfbsvcmgr localhost:service_mgr action_validate dbname %(db_folder)s%(db_longest_name)s +# echo. >>!tmplog! +# echo !run_cmd! 1>>!tmplog! +# cmd /c !run_cmd! 1>>!tmplog! 2>!tmperr! +# +# @rem --------------------------------------------------------------------------------------- +# +# set run_cmd=%(fb_home)sfbsvcmgr localhost:service_mgr action_properties dbname %(db_folder)s%(db_longest_name)s prp_sweep_interval 12345 +# echo. >>!tmplog! +# echo !run_cmd! 1>>!tmplog! +# cmd /c !run_cmd! 1>>!tmplog! 2>!tmperr! +# +# @rem --------------------------------------------------------------------------------------- +# +# set run_cmd=%(fb_home)sfbsvcmgr localhost:service_mgr action_backup dbname %(db_folder)s%(db_longest_name)s bkp_file %(db_folder)s%(bk_longest_name)s +# echo. >>!tmplog! +# echo !run_cmd! 1>>!tmplog! +# cmd /c !run_cmd! 1>>!tmplog! 2>!tmperr! +# +# if exist %(db_folder)s%(bk_longest_name)s ( +# set run_cmd=%(fb_home)sfbsvcmgr localhost:service_mgr action_restore res_replace bkp_file %(db_folder)s%(bk_longest_name)s dbname %(db_folder)s%(db_longest_repl)s +# echo. >>!tmplog! +# echo !run_cmd! 1>>!tmplog! +# cmd /c !run_cmd! 1>>!tmplog! 2>!tmperr! +# ) else ( +# ( +# echo Record-level backup via FB services API FAILED, target file: +# echo %(db_folder)s%(bk_longest_name)s +# echo -- does not exist. +# echo Subsequent restore from this file has been SKIPPED. +# ) >>!tmplog! +# ) +# +# del %(db_folder)s%(bk_longest_name)s 2>nul +# +# +# @rem --------------------------------------------------------------------------------------- +# +# @rem Drop TARGET file for ongoing INCREMENTAL BACKUP operation: +# @rem ~~~~~~~~~~~~~~~~ +# del %(db_folder)s%(nb_longest_name)s 2>nul +# +# set run_cmd=%(fb_home)sfbsvcmgr localhost:service_mgr action_nbak dbname %(db_folder)s%(db_longest_name)s nbk_file %(db_folder)s%(nb_longest_name)s nbk_level 0 +# echo. >>!tmplog! +# echo !run_cmd! 1>>!tmplog! +# cmd /c !run_cmd! 1>>!tmplog! 2>!tmperr! +# +# @rem --------------------------------------------------------------------------------------- +# +# if exist %(db_folder)s%(nb_longest_name)s ( +# +# @rem Drop TARGET file for ongoing INCREMENTAL RESTORE operation: +# @rem ~~~~~~~~~~~~~~~~ +# del %(db_folder)s%(db_longest_repl)s 2>nul +# +# set run_cmd=%(fb_home)sfbsvcmgr localhost:service_mgr action_nrest nbk_file %(db_folder)s%(nb_longest_name)s dbname %(db_folder)s%(db_longest_repl)s +# echo. >>!tmplog! +# echo !run_cmd! 1>>!tmplog! +# cmd /c !run_cmd! 1>>!tmplog! 2>!tmperr! +# ) else ( +# ( +# echo Physical-level backup via FB services API FAILED, target file: +# echo %(db_folder)s%(nb_longest_name)s +# echo -- does not exist. +# echo Subsequent incremental restore from this file has been SKIPPED. +# ) >>!tmplog! +# ) +# +# +# @rem --------------------------------------------------------------------------------------- +# +# set run_cmd=%(fb_home)sgbak -b -v localhost:%(db_folder)s%(db_longest_name)s %(db_folder)s%(bk_longest_name)s +# echo. >>!tmplog! +# echo !run_cmd! 1>>!tmplog! +# cmd /c !run_cmd! 1>>!tmplog! 2>!tmperr! +# @rem --------------------------------------------------------------------------------------- +# +# if exist %(db_folder)s%(bk_longest_name)s ( +# +# ( +# echo. +# echo Check backup file from which we will perform record-level restore: +# dir /-c %(db_folder)s%(bk_longest_name)s | findstr /i /c:"%(bk_ext)s" +# echo. +# ) 1>>!tmplog! +# +# set run_cmd=%(fb_home)sgbak -rep -v %(db_folder)s%(bk_longest_name)s localhost:%(db_folder)s%(db_longest_repl)s +# echo. >>!tmplog! +# echo !run_cmd! 1>>!tmplog! +# cmd /c !run_cmd! 1>>!tmplog! 2>!tmperr! +# @rem --------------------------------------------------------------------------------------- +# +# @rem set run_cmd=%(fb_home)sgbak -b localhost:%(db_folder)s%(db_longest_name)s stdout ^| %(fb_home)sgbak -rep -v stdin localhost:%(db_folder)s%(db_longest_repl)s +# @rem echo. >>!tmplog! +# @rem echo !run_cmd! 1>>!tmplog! +# @rem cmd /c !run_cmd! 1>>!tmplog! 2>!tmperr! +# @rem --------------------------------------------------------------------------------------- +# ) else ( +# +# ( +# echo Record-level backup using gbak utility FAILED, target file: +# echo %(db_folder)s%(bk_longest_name)s +# echo -- does not exist. +# echo Subsequent restore from this file has been SKIPPED. +# ) >>!tmplog! +# ) +# +# del %(db_folder)s%(nb_longest_name)s 2>nul +# del %(db_folder)s%(bk_longest_name)s 2>nul +# del %(db_folder)s%(db_longest_name)s 2>nul +# del %(db_folder)s%(db_longest_repl)s 2>nul +# +# ''' % dict(globals(), **locals()) +# +# +# # ---------------------- execute .bat ------------------------- +# +# f_tmp_bat=open( os.path.join(context['temp_directory'],'tmp_maxpath_test.bat'), 'w', buffering = 0) +# f_tmp_bat.write( tmp_bat_text ) +# flush_and_close( f_tmp_bat ) +# +# subprocess.call( [ f_tmp_bat.name ] ) +# +# # ::: NB ::: Here we have to be idle at least 2s (two seconds) otherwise trace log will +# # not contain some or all of messages about create DB, start Tx, ES, Tx and drop DB. +# # See also discussion with hvlad, 08.01.2020 15:16 +# # (subj: "action_trace_stop does not flush trace log (fully or partially)") +# time.sleep(2) +# +# # Stop trace session: +# ##################### +# +# trc_lst=open(trc_lst.name, "a") +# trc_lst.seek(0,2) +# +# subprocess.call( [ "fbsvcmgr", "localhost:service_mgr", +# "action_trace_stop", +# "trc_id",trc_ssn +# ], +# stdout=trc_lst, +# stderr=subprocess.STDOUT +# ) +# flush_and_close( trc_lst ) +# +# p_svcmgr.terminate() +# flush_and_close( trc_log ) +# flush_and_close( trc_err ) +# +# f_bat_log = '.'.join( ( os.path.splitext( f_tmp_bat.name )[0], 'log') ) +# f_bat_err = '.'.join( ( os.path.splitext( f_tmp_bat.name )[0], 'err') ) +# +# with open(f_bat_err,'r', buffering = 0) as f: +# for line in f: +# if line.split(): +# print( 'Unexpected STDERR: ' + line ) +# +# +# runtime_error_ptn = re.compile( '\\d{8}\\s+:\\s+.' ) +# services_patterns = { +# '1. DB_REPAIR' : re.compile('"Repair\\s+Database"', re.IGNORECASE) +# ,'2. DB_VALIDATE' : re.compile('"Validate\\s+Database"', re.IGNORECASE) +# ,'3. DB_PROPS' : re.compile('"Database\\s+Properties"', re.IGNORECASE) +# ,'4. DB_BACKUP' : re.compile('"Backup\\s+Database"', re.IGNORECASE) +# ,'5. DB_RESTORE' : re.compile('"Restore\\s+Database"', re.IGNORECASE) +# ,'6. DB_NBACKUP' : re.compile('"Incremental\\s+Backup\\s+Database"', re.IGNORECASE) +# ,'7. DB_NRESTORE' : re.compile('"Incremental\\s+Restore\\s+Database"', re.IGNORECASE) +# } +# +# found_patterns={} +# +# with open( trc_err.name,'r') as f: +# for line in f: +# if line.rstrip(): +# print( 'UNEXPECTED error in the trace: ' + line ) +# +# with open( trc_log.name,'r') as f: +# for line in f: +# if line.rstrip().split(): +# if 'FAILED START_SERVICE' in line: +# print( 'UNEXPECTED error with FB SERVICES: ' + line ) +# if runtime_error_ptn.search(line): +# if '335544528 :' in line: +# # ::: NOTE ::: +# # Change DB state to full shutdown (by gfix) produced in the trace log +# # failed_attach event that is issued by secondary attachment of gfix.exe: +# # FAILED ATTACH_DATABASE +# # +# # ERROR AT JProvider::attachDatabase +# # +# # 335544528 : database ... shutdown +# # This is actutal at least for Firebird 3.0.6, so we have to IGNORE this line. +# pass +# else: +# print( 'Expected error in the trace: ' + line ) +# +# for k,v in services_patterns.items(): +# if v.search(line): +# found_patterns[k] = 'FOUND in the trace log' +# +# +# for k,v in sorted( found_patterns.items() ): +# print( 'Pattern', k, ':', v) +# +# ################################################ +# +# # 02.04.2020, WindowsError: 32 The process cannot access the file because it is being used by another process +# ############# +# time.sleep(2) +# +# #cleanup: +# f_list = [ i.name for i in (trc_cfg, trc_log, trc_err, trc_lst, f_isql_cmd, f_tmp_bat) ] +# f_list += [ db_longest_name,bk_longest_name,db_longest_repl,nb_longest_name, f_bat_log, f_bat_err ] +# +# cleanup( f_list ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Expected error in the trace: 335544665 : violation of PRIMARY or UNIQUE KEY constraint "TEST_UNQ" on table "TEST" + Expected error in the trace: 335545072 : Problematic key value is ("S" = '000000000000000000000000000000000000') + Expected error in the trace: 335544665 : violation of PRIMARY or UNIQUE KEY constraint "TEST_UNQ" on table "TEST" + Expected error in the trace: 335545072 : Problematic key value is ("S" = '000000000000000000000000000000000000') + Pattern 1. DB_REPAIR : FOUND in the trace log + Pattern 2. DB_VALIDATE : FOUND in the trace log + Pattern 3. DB_PROPS : FOUND in the trace log + Pattern 4. DB_BACKUP : FOUND in the trace log + Pattern 5. DB_RESTORE : FOUND in the trace log + Pattern 6. DB_NBACKUP : FOUND in the trace log + Pattern 7. DB_NRESTORE : FOUND in the trace log + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.platform('Windows') +@pytest.mark.xfail +def test_max_path_length_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/tabloid/test_no_dups_in_call_stack.py b/tests/functional/tabloid/test_no_dups_in_call_stack.py new file mode 100644 index 00000000..703dabbb --- /dev/null +++ b/tests/functional/tabloid/test_no_dups_in_call_stack.py @@ -0,0 +1,189 @@ +#coding:utf-8 +# +# id: functional.tabloid.no_dups_in_call_stack +# title: Avoid info duplication when statements in call stack attached to different transactions (for example: monitoring snapshot is created in autonomous transaction) +# decription: Fixed in rev. 59971 for 3.0; rev. 59972 for 2.5 (backporting) -- 12-aug-2014 +# tracker_id: +# min_versions: ['2.5.4'] +# versions: 2.5.4 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5.4 +# resources: None + +substitutions_1 = [] + +init_script_1 = """ + -- sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1109867&msg=16438071 + -- run: fbt_run -b functional.tabloid.no-dups-in-call-stack -o localhost/ + set term ^; + create or alter procedure dbg_get_stack as begin end^ + create or alter procedure p_01 as begin end^ + create or alter procedure p_02 as begin end^ + create or alter procedure p_03 as begin end^ + create or alter procedure p_04 as begin end^ + set term ;^ + recreate table dbg_stack( + whoami varchar(31) + ,call_level int + ,statement_id int + ,call_id int + ,object_name char(31) + ,object_type smallint + ,source_line int + ,source_column int + ); + commit; + + set term ^; + create or alter procedure dbg_get_stack(a_whoami varchar(31)) + as + declare v_call_level smallint; + declare v_mon$statement_id type of column mon$call_stack.mon$statement_id; + declare v_mon$call_id type of column mon$call_stack.mon$call_id; + declare v_mon$object_name type of column mon$call_stack.mon$object_name; + declare v_mon$object_type type of column mon$call_stack.mon$object_type; + declare v_mon$source_line type of column mon$call_stack.mon$source_line; + declare v_mon$source_column type of column mon$call_stack.mon$source_column; + begin + in autonomous transaction do + begin + for + with recursive + r as ( + select 1 call_level, + c.mon$statement_id, + c.mon$call_id, + c.mon$object_name, + c.mon$object_type, + c.mon$source_line, + c.mon$source_column + from mon$call_stack c + where c.mon$caller_id is null + + UNION ALL + + select r.call_level+1, + c.mon$statement_id, + c.mon$call_id, + c.mon$object_name, + c.mon$object_type, + c.mon$source_line, + c.mon$source_column + from mon$call_stack c + join r + on c.mon$caller_id = r.mon$call_id + ) + select + r.call_level + ,r.mon$statement_id + ,r.mon$call_id + ,r.mon$object_name + ,r.mon$object_type + ,r.mon$source_line + ,r.mon$source_column + from r + --as cursor cr do + into + v_call_level + ,v_mon$statement_id + ,v_mon$call_id + ,v_mon$object_name + ,v_mon$object_type + ,v_mon$source_line + ,v_mon$source_column + do begin + insert into dbg_stack + values( + :a_whoami + ,:v_call_level + ,:v_mon$statement_id + ,:v_mon$call_id + ,:v_mon$object_name + ,:v_mon$object_type + ,:v_mon$source_line + ,:v_mon$source_column + ); + end + end + + end + ^ + set term ;^ + commit; + + --------------------------------- + set term ^; + create or alter procedure p_04 as + declare n int; + begin + -- dummy row 1 + -- dummy row 2 + -- dummy row 3 + -- dummy row 4 + execute procedure dbg_get_stack( 'p_04' ); + end + ^ + create or alter procedure p_03 as + declare n int; + begin + -- dummy row 1 + -- dummy row 2 + -- dummy row 3 + execute procedure p_04; + end + ^ + create or alter procedure p_02 as + declare n int; + begin + -- dummy row 1 + -- dummy row 2 + execute procedure p_03; + end + ^ + create or alter procedure p_01 as + declare n int; + begin + -- dummy row 1 + delete from dbg_stack; + execute procedure p_02; + end + ^ + set term ;^ + commit; + """ + +db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1) + +test_script_1 = """ + delete from dbg_stack; + commit; + execute procedure p_01; + commit; + set width whoami 6; + set width object_name 15; + select s.whoami, s.call_level, s.object_name, s.object_type, s.source_line + from dbg_stack s; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ +WHOAMI CALL_LEVEL OBJECT_NAME OBJECT_TYPE SOURCE_LINE +====== ============ =============== =========== ============ +p_04 1 P_01 5 6 +p_04 2 P_02 5 6 +p_04 3 P_03 5 7 +p_04 4 P_04 5 8 +p_04 5 DBG_GET_STACK 5 13 + """ + +@pytest.mark.version('>=2.5.4') +def test_no_dups_in_call_stack_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_oltp_emul_30_compiler_check.py b/tests/functional/tabloid/test_oltp_emul_30_compiler_check.py new file mode 100644 index 00000000..0e9ae098 --- /dev/null +++ b/tests/functional/tabloid/test_oltp_emul_30_compiler_check.py @@ -0,0 +1,17558 @@ +#coding:utf-8 +# +# id: functional.tabloid.oltp_emul_30_compiler_check +# title: Compiler check. Test ability to compile source code of OLTP-EMUL test. +# decription: +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('start at .*', 'start at'), ('finish at .*', 'finish at')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ +-- This test was created only for daily checking of FB compiler: there were several times +-- in the past when DDL of OLTP-EMUL test could not be compiled because of regressions. +-- Discuss with dimitr: letter for 11-apr-2016 15:34. + +-- ############################## +-- Begin of script oltp30_DDL.sql +-- ############################## +-- ::: nb-1 ::: Required FB version: 3.0 and above. +-- ::: nb-2 ::: Use '-nod' switch when run this script from isql +set term ^; +execute block as +begin + begin + execute statement 'recreate exception ex_exclusive_required ''At least one concurrent connection detected.'''; + when any do begin end + end + begin + execute statement 'recreate exception ex_not_suitable_fb_version ''This script requires at least Firebird 3.x version'''; + when any do begin end + end +end +^ +set term ;^ +COMMIT; + +set bail on; +set autoddl off; +set list on; +select 'oltp30_DDL.sql start at ' || current_timestamp as msg from rdb$database; +set list off; + + +set term ^; +execute block as +begin + if ( rdb$get_context('SYSTEM','ENGINE_VERSION') starting with '2.' ) then + begin + exception ex_not_suitable_fb_version; + end + + -- NB. From doc/README.monitoring_tables: + -- columns MON$REMOTE_PID and MON$REMOTE_PROCESS contains non-NULL values + -- only if the client library has version 2.1 or higher + -- column MON$REMOTE_PROCESS can contain a non-pathname value + -- if an application has specified a custom process name via DPB + if ( exists( select * from mon$attachments a + where a.mon$attachment_id<>current_connection + and a.mon$remote_protocol is not null + ) + ) then + begin + exception ex_exclusive_required; + end +end +^ +set term ;^ + + +-- ############################################################################ +-- ######################### C L E A N I N G ############################# +-- ############################################################################ + +-- 1. Separate EB for devastation views with preserving their column names +-- (otherwise can get ISC error 336397288. invalid request BLR at offset 2. context not defined (BLR error).) +-- see letter to dimitr, 29.03.2014 22:43 +set term ^; +execute block as + declare stt varchar(8190); + declare ref_name varchar(31); + declare tab_name varchar(31); + declare view_ddl varchar(8190); + declare c_view cursor for ( + with + a as( + select rf.rdb$relation_name view_name, rf.rdb$field_position fld_pos, trim(rf.rdb$field_name) fld_name + --rf.rdb$field_name fld_name + from rdb$relation_fields rf + join rdb$relations rr + on rf.rdb$relation_name=rr.rdb$relation_name + where + coalesce(rf.rdb$system_flag,0)=0 and coalesce(rr.rdb$system_flag,0)=0 and rr.rdb$relation_type=1 + ) + select view_name, + cast( 'create or alter view '||trim(view_name)||' as select ' + ||list( fld_pos||' '||trim(lower( fld_name )) ) + ||' from rdb$database' as varchar(8190) + ) view_ddl + from a + group by view_name + ); +begin + open c_view; + while (1=1) do + begin + fetch c_view into tab_name, stt; + if (row_count = 0) then leave; + execute statement (:stt); + end + close c_view; +end^ +set term ;^ +COMMIT; + +------------------------------------------------------------------------------- + +-- 2. Removing all objects from database is they exists: +set term ^; +execute block as + declare stt varchar(512); + declare ref_name varchar(31); + declare tab_name varchar(31); + --declare view_ddl varchar(8190); + + declare c_trig cursor for + (select rt.rdb$trigger_name + from rdb$triggers rt + where coalesce(rt.rdb$system_flag,0)=0 + ); + + declare c_view cursor for + (select rr.rdb$relation_name + from rdb$relations rr + where rr.rdb$relation_type=1 and coalesce(rr.rdb$system_flag,0)=0 + ); + declare c_func cursor for + (select rf.rdb$function_name + from rdb$functions rf + where coalesce(rf.rdb$system_flag,0)=0 + ); + declare c_proc cursor for + (select rp.rdb$procedure_name + from rdb$procedures rp + where coalesce(rp.rdb$system_flag,0)=0 + ); + + declare c_excp cursor for + (select re.rdb$exception_name + from rdb$exceptions re + where coalesce(re.rdb$system_flag,0)=0 + ); + + declare c_fk cursor for + (select rc.rdb$constraint_name, rc.rdb$relation_name + from rdb$relation_constraints rc + where rc.rdb$constraint_type ='FOREIGN KEY' + ); + + declare c_tabs cursor for -- fixed tables and GTTs + (select rr.rdb$relation_name + from rdb$relations rr + where rr.rdb$relation_type in(0,4,5) and coalesce(rr.rdb$system_flag,0)=0 + -- todo: what about external tables ? + ); + + declare c_doms cursor for -- domains + (select rf.rdb$field_name + from rdb$fields rf + where coalesce(rf.rdb$system_flag,0)=0 + and rf.rdb$field_name not starting with 'RDB$' + ); + + declare c_coll cursor for -- collations + (select rc.rdb$collation_name + from rdb$collations rc + where coalesce(rc.rdb$system_flag,0)=0 + ); + declare c_gens cursor for -- generators + (select rg.rdb$generator_name + from rdb$generators rg + where coalesce(rg.rdb$system_flag,0)=0 + ); + declare c_role cursor for -- roles + (select rr.rdb$role_name + from rdb$roles rr + where coalesce(rr.rdb$system_flag,0)=0 + ); + +begin + + -- ################ D R O P T R I G G E R S ################ + open c_trig; + while (1=1) do + begin + fetch c_trig into stt; + if (row_count = 0) then leave; + stt = 'drop trigger '||stt; + execute statement (:stt); + end + close c_trig; + + -- ######### Z A P F U N C S & P R O C S ########## + -- not needed views has been already "zapped", see above separate EB + + open c_func; + while (1=1) do + begin + fetch c_func into stt; + if (row_count = 0) then leave; + stt = 'create or alter function '||stt||' returns int as begin return 1; end'; + execute statement (:stt); + end + close c_func; + + open c_proc; + while (1=1) do + begin + fetch c_proc into stt; + if (row_count = 0) then leave; + stt = 'create or alter procedure '||stt||' as begin end'; + execute statement (:stt); + end + close c_proc; + + -- ###################### D R O P O B J E C T S ###################### + + open c_view;---------------------- d r o p v i e w s --------------------- + while (1=1) do + begin + fetch c_view into stt; + if (row_count = 0) then leave; + stt = 'drop view '||stt; + execute statement (:stt); + end + close c_view; + + open c_func; -------------------- d r o p f u c t i o n s ---------------- + while (1=1) do + begin + fetch c_func into stt; + if (row_count = 0) then leave; + stt = 'drop function '||stt; + execute statement (:stt); + end + close c_func; + + open c_proc; ----------------- d r o p p r o c e d u r e s --------------- + while (1=1) do + begin + fetch c_proc into stt; + if (row_count = 0) then leave; + stt = 'drop procedure '||stt; + execute statement (:stt); + end + close c_proc; + + open c_excp; ----------------- d r o p e x c e p t i o n s --------------- + while (1=1) do + begin + fetch c_excp into stt; + if (row_count = 0) then leave; + stt = 'drop exception '||stt; + execute statement (:stt); + end + close c_excp; + + open c_fk; ----------- d r o p r e f. c o n s t r a i n t s ------------ + while (1=1) do + begin + fetch c_fk into ref_name, tab_name; + if (row_count = 0) then leave; + stt = 'alter table '||tab_name||' drop constraint '||ref_name; + execute statement (:stt); + end + close c_fk; + + open c_tabs; ----------- d r o p t a b l e s ------------ + while (1=1) do + begin + fetch c_tabs into stt; + if (row_count = 0) then leave; + stt = 'drop table '||stt; + execute statement (:stt); + end + close c_tabs; + + open c_doms; ------------------- d r o p d o m a i n s ------------------- + while (1=1) do + begin + fetch c_doms into stt; + if (row_count = 0) then leave; + stt = 'drop domain '||stt; + execute statement (:stt); + end + close c_doms; + + open c_coll; --------------- d r o p c o l l a t i o n s ----------------- + while (1=1) do + begin + fetch c_coll into stt; + if (row_count = 0) then leave; + stt = 'drop collation '||stt; + execute statement (:stt); + end + close c_coll; + + open c_gens; ----------------- d r o p s e q u e n c e s ----------------- + while (1=1) do + begin + fetch c_gens into stt; + if (row_count = 0) then leave; + stt = 'drop sequence '||stt; + execute statement (:stt); + end + close c_gens; + + open c_role; -------------------- d r o p r o l e s ---------------------- + while (1=1) do + begin + fetch c_role into stt; + if (row_count = 0) then leave; + stt = 'drop role '||stt; + execute statement (:stt); + end + close c_role; + +end +^ +set term ;^ + + + +------------------------------------------------------------------------------- +-- ######################### C R E A T I N G ############################# +------------------------------------------------------------------------------- + +create sequence g_common; +create sequence g_doc_data; +create sequence g_perf_log; +create sequence g_init_pop; +create sequence g_qdistr; +create sequence g_success_counter; -- used in .bat / .sh for displaying estimated performance value +create sequence g_stop_test; -- serves as signal to self-stop every ISQL attachment its job + + +-- create collations: +create collation name_coll for utf8 from unicode case insensitive; +create collation nums_coll for utf8 from unicode case insensitive 'NUMERIC-SORT=1'; + + +-- create exceptions +recreate exception ex_context_var_not_found 'required context variable(s): @1 - not found or has invalid value'; +recreate exception ex_bad_working_mode_value 'db-level trigger TRG_CONNECT: no found rows for settings.working_mode=''@1'', correct it!'; +recreate exception ex_bad_argument 'argument @1 passed to unit @2 is invalid'; +recreate exception ex_test_cancellation 'test_has_been_cancelled (either by adding text into external text file ''stoptest'' or by changing value of sequence ''g_stop_test'' to non-zero)'; + +recreate exception ex_record_not_found 'required record not found, datasource: @1, key: @2'; +recreate exception ex_cant_lock_semaphore_record 'can`t lock record in SEMAPHORES table for serialization'; +recreate exception ex_cant_lock_row_for_qdistr 'can`t lock any row in `qdistr`: optype=@1, ware_id=@2, qty_required=@3'; +recreate exception ex_cant_find_row_for_qdistr 'no rows found for FIFO-distribution: optype=@1, rows in tmp$shopping_cart=@2'; + +recreate exception ex_no_doc_found_for_handling 'no document found for handling in datasource = ''@1'' with id=@2'; +recreate exception ex_no_rows_in_shopping_cart 'shopping_cart is empty, check source ''@1'''; + +recreate exception ex_not_all_storned_rows_removed 'at least one storned row found in ''qstorned'' table, doc=@1'; -- 4debug, 27.06.2014 +recreate exception ex_neg_remainders_encountered 'at least one neg. remainder, ware_id: @1, info: @2'; -- 4debug, 27.06.2014 +recreate exception ex_mism_doc_data_qd_qs 'at least one mismatch btw doc_data.id=@1 and qdistr+qstorned: qty=@2, qd_cnt=@3, qs_cnt=@4'; -- 4debug, 07.08.2014 +recreate exception ex_orphans_qd_qs_found 'at least one row found for DELETED doc id=@1, snd_id=@2: @3.id=@4'; + +recreate exception ex_can_not_lock_any_record 'no records could be locked in datasource = ''@1'' with ID >= @2.'; +recreate exception ex_can_not_select_random_id 'no id @1 @2 in @3 found within scope @4 ... @5'; -- @1 is '>=' or '<='; @2 = random_selected_value; @3 = data source; @4 = min; @5 = max + +recreate exception ex_snapshot_isolation_required 'operation must run only in TIL = SNAPSHOT.'; +recreate exception ex_read_committed_isolation_req 'operation must run only in TIL = READ COMMITTED.'; +recreate exception ex_nowait_or_timeout_required 'transaction must start in NO WAIT mode or with LOCK_TIMEOUT.'; + +recreate exception ex_update_operation_forbidden 'update operation not allowed on table @1'; +recreate exception ex_delete_operation_forbidden 'delete operation not allowed on table @1 when user-data exists'; +recreate exception ex_debug_forbidden_operation 'debug: operation not allowed'; + + + +------------------------------------------------------------------------------- + +-- create domains +-- ::: NB::: 08.06.2014: +-- not null constraints were taken out due to http://tracker.firebirdsql.org/browse/CORE-4453 +create domain dm_dbkey as char(8) character set octets; -- do NOT: not null; -- for variables stored rdb$db_key +create domain dm_ids as smallint; -- IDs for operations and document states (will be assigned explicitly in 'oltp_main_filling.sql' to small values) +create domain dm_idb as bigint; -- not null; -- all IDs + +create domain dm_ctxns as varchar(16) character set utf8 check( value in ('','USER_SESSION','USER_TRANSACTION', 'SYSTEM')); +create domain dm_ctxnv as varchar(80) character set none; -- m`on$context_variables.m`on$variable_name +create domain dm_dbobj as varchar(31) character set unicode_fss; +create domain dm_setting_value as varchar(160) character set utf8 collate name_coll; -- special for settings.value field (long lists can be there) +create domain dm_mcode as varchar(3) character set utf8 collate name_coll; -- optypes.mcode: mnemonic for operation +create domain dm_name as varchar(80) character set utf8 collate name_coll; -- character set utf8 not null collate name_coll; -- name of wares, contragents et al +create domain dm_nums as varchar(20) character set utf8 collate nums_coll; -- character set utf8 not null collate nums_coll; -- original (manufacturer) numbers +create domain dm_qty as numeric(12,3) check(value>=0); -- not null check(value>=0); +create domain dm_qtz as numeric(12,3) default 0 check(value>=0); -- default 0 not null check(value>=0); +create domain dm_cost as numeric(12,2); -- temply dis 15.05.2014 for DEBUG! uncomment later: not null check(value>=0); +create domain dm_vals as numeric(12,2); -- numeric(12,2) not null; -- money_turnover_log.costXXXX, can be < 0 +create domain dm_aux as double precision; +create domain dm_sign as smallint default 0 check(value in(-1, 1, 0)) ; -- smallint default 0 not null check(value in(-1, 1, 0)) ; +create domain dm_account_type as varchar(1) character set utf8 NOT null check( value in('1','2','i','o','c','s') ); -- incoming; outgoing; payment + +create domain dm_unit varchar(80); +create domain dm_info varchar(255); +create domain dm_stack varchar(512); +-- Remote address to be written into perf_log, mon_log. +-- Size should be enough to fit IPv6 and port number or even port text mnemona! +-- See: http://www.networksorcery.com/enp/protocol/ip/ports04000.htm +-- See also reply from dimitr, letter 11-jan-2016 16:04 (subj: "SOS. M`ON$REMOTE_ADDRESS, ...") +-- Fixed in http://sourceforge.net/p/firebird/code/62802 (only port numbers will serve as "suffixes") +create domain dm_ip varchar(255); + + + +------------------------------------------------------------------------------- +---- aux table for auto stop running attaches: +--recreate table ext_stoptest external 'stoptest.txt' ( +-- s char(2) +--); + +------------------------------------------------------------------------------- +-- ************** G L O B A L T E M P. T A B L E S ***************** +------------------------------------------------------------------------------- +recreate global temporary table tmp$shopping_cart( + id dm_idb, -- = ware_id + snd_id bigint, -- nullable! ref to invoice in case when create reserve doc (one invoice for each reserve; 03.06.2014) + qty numeric(12,3) not null, + optype_id bigint, + snd_optype_id bigint, + rcv_optype_id bigint, + storno_sub smallint default 1, -- see table rules_for_qistr.storno_sub + qty_bak numeric(12,3) default 0, -- debug + dup_cnt int default 0, -- debug + cost_purchase dm_cost, -- for sp_sp_fill_shopping_cart when create client order + cost_retail dm_cost, + constraint tmp_shopcart_unq unique(id, snd_id) using index tmp_shopcart_unq +) on commit delete rows; + +-- 08.01.2015, see sp make_qty_storno, investigatin perf. for NL vs MERGE +--create index tmp_shopcart_rcv_op on tmp$shopping_cart(rcv_optype_id); +-- + +recreate global temporary table tmp$dep_docs( + base_doc_id dm_idb, + dependend_doc_id dm_idb, + dependend_doc_state dm_idb, + dependend_doc_dbkey dm_dbkey, + dependend_doc_agent_id dm_idb, + -- 29.07.2014 (4 misc debug) + ware_id dm_idb, + base_doc_qty dm_qty, + dependend_doc_qty dm_qty, + constraint tmp_dep_docs_unq unique(base_doc_id, dependend_doc_id) using index tmp_dep_docs_unq +) on commit delete rows; + + +recreate global temporary table tmp$result_set( + snd_id bigint, + id bigint, + storno_sub smallint, + qdistr_id bigint, + qdistr_dbkey dm_dbkey, + doc_id bigint, + optype_id bigint, + oper varchar(80), + base_doc_id bigint, + doc_data_id bigint, + ware_id bigint, + qty numeric(12,3), + cost_purchase numeric(12,2), + cost_retail numeric(12,2), + qty_clo numeric(12,3), + qty_clr numeric(12,3), + qty_ord numeric(12,3), + qty_sup numeric(12,3), + qty_inc numeric(12,3), + qty_avl numeric(12,3), + qty_res numeric(12,3), + qty_out numeric(12,3), + cost_inc numeric(12,2), + cost_out numeric(12,2), + qty_acn numeric(12,3), + cost_acn numeric(12,2), + state_id bigint, + agent_id bigint, + dts_edit timestamp, + dts_open timestamp, + dts_fix timestamp, + dts_clos timestamp, + state bigint +) on commit delete rows; + +create index tmp_result_set_ware_doc on tmp$result_set(ware_id, doc_id); +create index tmp_result_set_doc on tmp$result_set(doc_id); + +-- for materializing temp results in some report SPs: +recreate global temporary table tmp$perf_mon( + unit dm_name, + cnt_all int, + cnt_ok int, + cnt_err int, + err_prc numeric(6,2), + ok_min_ms int, + ok_max_ms int, + ok_avg_ms int, + cnt_deadlock int, + cnt_upd_conf int, + cnt_lk_confl int, + cnt_user_exc int, + cnt_chk_viol int, + cnt_no_valid int, + cnt_unq_viol int, + cnt_fk_viol int, + cnt_stack_trc int, -- 335544842, 'stack_trace': appears at the TOP of stack in 3.0 SC (strange!) + cnt_zero_gds int, -- core-4565 (gdscode=0 in when-section! 3.0 SC only) + cnt_other_exc int, + first_done timestamp, + last_done timestamp, + rollup_level smallint, + dts_beg timestamp, + dts_end timestamp +) on commit delete rows; + + +recreate global temporary table tmp$idx_recalc( + tab_name dm_dbobj, + idx_name dm_dbobj, + idx_stat_befo double precision, + idx_stat_afte double precision, + idx_stat_diff computed by( idx_stat_afte - idx_stat_befo ), + constraint tmp_idx_recalc_idx_name_unq unique(idx_name) +) on commit preserve rows; + + +recreate global temporary table tmp$mon_log( -- used in tmp_random_run.sql + unit dm_unit + ,fb_gdscode int + ,att_id bigint default current_connection + ,trn_id bigint + ----------------------------------------- + ,pg_reads bigint + ,pg_writes bigint + ,pg_fetches bigint + ,pg_marks bigint + ,rec_inserts bigint + ,rec_updates bigint + ,rec_deletes bigint + ,rec_backouts bigint + ,rec_purges bigint + ,rec_expunges bigint + ,rec_seq_reads bigint + ,rec_idx_reads bigint + ---------- counters avaliable only in FB 3.0, since rev. 59953 -------------- + ,rec_rpt_reads bigint -- <<< since rev. 60005, 27.08.2014 18:52 + ,bkv_reads bigint -- mon$backversion_reads, since rev. 60012, 28.08.2014 19:16 + -- since rev. 59953, 05.08.2014 08:46: + ,frg_reads bigint + ,rec_locks bigint + ,rec_waits bigint + ,rec_confl bigint + ----------------------------------------------------------------------------- + ,mem_used bigint + ,mem_alloc bigint + ,stat_id bigint + ,server_pid bigint + ,mult dm_sign + ,add_info dm_info + ,dts timestamp default 'now' + ,rowset bigint -- for grouping records that related to the same measurement +) on commit preserve rows; + + +-- 29.08.2014: for identifying troubles by analyzing results per each table: +recreate global temporary table tmp$mon_log_table_stats( -- used in tmp_random_run.sql + unit dm_unit + ,fb_gdscode int + ,att_id bigint default current_connection + ,trn_id bigint + ,table_id smallint + ,table_name dm_dbobj -- filled in SP srv_fill_mon + ------------------- + ,rec_inserts bigint + ,rec_updates bigint + ,rec_deletes bigint + ,rec_backouts bigint + ,rec_purges bigint + ,rec_expunges bigint + ,rec_seq_reads bigint + ,rec_idx_reads bigint + ,rec_rpt_reads bigint + ,bkv_reads bigint + ,frg_reads bigint + ,rec_locks bigint + ,rec_waits bigint + ,rec_confl bigint + ,stat_id bigint + ,mult dm_sign + ,rowset bigint -- for grouping records that related to the same measurement +) on commit preserve rows; + + +-- Used only when config parameter create_with_split_heavy_tabs = 1: +-- stores INITIAL source code of sp_get_random_id as basis for generation +-- of new DB object with this name which almost fully excludes running of +-- dynamic SQL statements for getting random selection of IDs: +recreate global temporary table tmp$autogen$source( + line_no int, + text varchar(8190), + line_type varchar(10) +) on commit delete rows; + +-- Used only when config parameter create_with_split_heavy_tabs = 1: library of known +-- views which names should be written explicitly in new sp_get_random_id code: +recreate global temporary table tmp$autogen$rand$calls( + view_name_for_find varchar(31) + ,view_name_for_min_id varchar(31) + ,view_name_for_max_id varchar(31) +) on commit delete rows; + + + +------------------------------------------------------------------------------- +-- ************ D E B U G T A B L E S (can be taken out after) ********** +------------------------------------------------------------------------------- +-- moved out, see oltp_misc_debug.sql +-- (this script will be involved only when config parameter create_with_debug_objects = 1) + +------------------------------------------------------------------------------- +-- **************** A P P L I C A T I O N T A B L E S ***************** +------------------------------------------------------------------------------- +-- Some values which are constant during app work, definitions for worload modes: +-- Values from 'svalue' field will be stored in session-level CONTEXT variables +-- with names defined in field 'mcode' ('C_CUSTOMER_DOC_MAX_ROWS' etc): +recreate table settings( + working_mode varchar(20) character set utf8, + mcode dm_name, -- mnemonic code + context varchar(16) default 'USER_SESSION', + svalue dm_setting_value, + init_on varchar(20) default 'connect', -- read this value in context var in trg_connect; 'db_prepare' ==> not needed in runtime + description dm_info, + constraint settings_unq unique(working_mode, mcode) using index settings_mode_code, + constraint settings_valid_ctype check(context in(null,'USER_SESSION','USER_TRANSACTION')) +); + + +-- lookup table: types of operations +recreate table optypes( + id dm_ids constraint pk_optypes primary key using index pk_optypes + ,mcode dm_mcode -- mnemonic code + ,name dm_name + ,m_qty_clo dm_sign -- how this op. affects on remainder "clients order" + ,m_qty_clr dm_sign -- how this op. affects on remainder "REFUSED clients order" + ,m_qty_ord dm_sign -- how this op. affects on remainder "stock order" + ,m_qty_sup dm_sign -- how this op. affects on remainder "unclosed invoices from supplier" + ,m_qty_avl dm_sign -- how this op. affects on remainder "avaliable to be reserved" + ,m_qty_res dm_sign -- how this op. affects on remainder "in reserve for some customer" + ,m_cost_inc computed by(iif(m_qty_avl=1,1,0)) -- see field invnt_saldo.cost_inc + ,m_cost_out computed by(iif(m_qty_res=-1,1,0)) -- see field invnt_saldo.cost_out + ,m_cust_debt dm_sign -- auxiliary field: affect on mutual settlements with customer + ,m_supp_debt dm_sign -- auxiliary field: affect on mutual settlements with supplier + -- kind of this operation: 'i' = incoming; 'o' = outgoing; 'p' = payment + ,acn_type dm_account_type -- need for FIFO distribution + ,multiply_rows_for_fifo dm_sign default 0 + ,end_state bigint -- (todo later) state of document after operation is completed (-1 = "not changed") + -- operation can not change both cost_INC and cost_OUT: + ,constraint optypes_mcode_unq unique(mcode) using index optypes_mcode_unq + ,constraint optype_mutual_inc_out check( abs(m_cost_inc)+abs(m_cost_out) < 2 ) + ,constraint optype_mult_pay_only check( + m_supp_debt=1 and m_cost_inc=1 + or + m_cust_debt=1 and m_cost_out=1 + or + m_supp_debt<=0 and m_cust_debt <=0 and (m_cost_inc=0 and m_cost_out=0) + ) + ); + + +-- Definitions for "value_to_rows" distributions for operations when it's needed: +recreate table rules_for_qdistr( + mode dm_name -- 'new_doc_only' (rcv='clo'), 'distr_only' (snd='clo', rcv='res'), 'distr+new_doc' (all others) + ,snd_optype_id dm_ids -- nullable: there is no 'sender' for client order operation (this is start of business chain) + ,rcv_optype_id dm_ids -- nullable: there is no 'receiver' for reserve write-off (this is end of business chain) + ,storno_sub smallint -- NB: for rcv_optype_id=3300 there will be TWO records: 1 (snd_op=2100) and 2 (snd_op=1000) + ,constraint rules_for_qdistr_unq unique(snd_optype_id, rcv_optype_id) using index rules_for_qdistr_unq +); +-- 10.09.2014: investigate performance vs sp_rules_for_qdistr; result: join with TABLE wins. +create index rules_for_qdistr_rcvop on rules_for_qdistr(rcv_optype_id); + + +-- create tables without ref. constraints +-- doc headers: +recreate table doc_list( + id dm_idb + ,optype_id dm_ids + ,agent_id dm_idb + ,state_id dm_ids + ,base_doc_id bigint -- id of document that is 'base' for current (stock order => incoming invoice etc) + ,cost_purchase dm_cost default 0 -- total in PURCHASING cost; can be ZERO for payment from customers + ,cost_retail dm_cost default 0 -- total in RETAIL cost; can be zero OUR PAYMENT to suppliers + ,acn_type dm_account_type + ,dts_open timestamp default 'now' + ,dts_fix timestamp -- when changes of CONTENT of this document became disabled + ,dts_clos timestamp -- when ALL changes of this doc. became disabled + ,constraint pk_doc_list primary key(id) using index pk_doc_list + ,constraint dts_clos_greater_than_open check(dts_clos is null or dts_clos > dts_open) +); +create descending index doc_list_id_desc on doc_list(id); -- need for quick select random doc + + +-- doc detailization (child for doc_list): +recreate table doc_data( + id dm_idb not null + ,doc_id dm_idb + ,ware_id dm_idb + ,qty dm_qty + ,cost_purchase dm_cost + ,cost_retail dm_cost default 0 + ,dts_edit timestamp -- last modification timestamp; do NOT use `default 'now'` here! + -- PK will be removed from this table if setting 'HALT_TEST_ON_ERRORS' does NOT containing + -- word ',PK,'. See statements in EB at the ending part of oltp_main_filling.sql: + ,constraint pk_doc_data primary key(id) using index pk_doc_data + ,constraint doc_data_doc_ware_unq unique(doc_id, ware_id) using index doc_data_doc_ware_unq + ,constraint doc_data_qty_cost_both check ( qty>0 and cost_purchase>0 and cost_retail>0 or qty = 0 and cost_purchase = 0 and cost_retail=0 ) +); +create descending index doc_data_id_desc on doc_data(id); -- get max in fn_g`et_random_id; 04.06.2014 + +-- Cost turnovers "log", by contragents + doc_id + operation types +-- (will be agregated in sp_make_cost_storno, with serialized access to this SP) +-- (NB: *not* all operations add rows in this table) +recreate table money_turnover_log( + id dm_idb not null + ,doc_id dm_idb + ,agent_id dm_idb + ,optype_id dm_ids + ,cost_purchase dm_vals -- can be < 0 when deleting records in doc_xxx + ,cost_retail dm_vals -- can be < 0 when deleting records in doc_xxx + ,dts timestamp default 'now' +); +-- 27.09.2015: refactored SP srv_make_money_saldo +create index money_turnover_log_agent_optype on money_turnover_log(agent_id, optype_id); + +-- Result of data aggregation of table money_turnover_log in sp_make_cost_storno +-- This table is updated only in 'serialized' mode by SINGLE attach at a time. +recreate table money_saldo( + agent_id dm_idb constraint pk_money_saldo primary key using index pk_money_saldo, + cost_purchase dm_vals, + cost_retail dm_vals +); + +-- lookup table: reference of wares (full price list of manufacturer) +-- This table is filled only once, at the test PREPARING phase, see oltp_data_filling.sql +recreate table wares( + id dm_idb generated by default as identity constraint pk_wares primary key using index pk_wares + ,group_id dm_idb + ,numb dm_nums -- original manufacturer number, provided by supplier (for testing SIMILAR TO perfomnace) + ,name dm_name -- name of ware (for testing SIMILAR TO perfomnace) + ,price_purchase dm_cost -- we buy from supplier (non fixed price, can vary - sp_client_order) + ,price_retail dm_cost -- we sale to customers (non fixed price, can vary - see sp_client_order) + -- business logic contraint: all wares must have unique numbers: + ,constraint wares_numb_unq unique(numb) + using index wares_numb_unq + ); +-- aux. index for randomly selecting during emulating create docs: +create descending index wares_id_desc on wares(id); + +-- aux table to check performance of similar_to (when search for STRINGS instead of IDs): +recreate table phrases( + id dm_idb generated by default as identity constraint pk_phrases primary key using index pk_phrases + ,pattern dm_name + ,name dm_name + ,constraint phrases_unq unique(pattern) using index phrases_unq + --,constraint fk_words_wares_id foreign key (wares_id) references wares(id) +); +create index phrases_name on phrases(name); +create descending index phrases_id_desc on phrases(id); + +-- catalog of views which are used in sp_get_random_id (4debug) +recreate table z_used_views( name dm_dbobj, constraint z_used_views_unq unique(name) using index z_used_views_unq); + +-- Inventory registry (~agg. matview: how many wares do we have currently) +-- related 1-to-1 to table `wares`; updated periodically and only in "SERIALIZED manner", see s`rv_make_invnt_saldo +recreate table invnt_saldo( + id dm_idb generated by default as identity constraint pk_invnt_saldo primary key using index pk_invnt_saldo + ,qty_clo dm_qty default 0 -- amount that clients ordered us + ,qty_clr dm_qty default 0 -- amount that was REFUSED by clients (s`p_cancel_client_order) + ,qty_ord dm_qty default 0 -- amount that we ordered (sent to supplier) + ,qty_sup dm_qty default 0 -- amount that supplier sent to us (specified in incoming doc) + ,qty_avl dm_qty default 0 -- amount that is avaliable to be taken (after finish checking of incoming doc) + ,qty_res dm_qty default 0 -- amount that is reserved for customers (for further sale) + ,qty_inc dm_qty default 0 -- total amount of incomings + ,qty_out dm_qty default 0 -- total amount of outgoings + ,cost_inc dm_cost default 0 -- total cost of incomings (total on closed incoming docs) + ,cost_out dm_cost default 0 -- total cost of outgoings (total on closed outgoing docs) + ,qty_acn computed by(qty_avl+qty_res) -- amount "on hand" as it seen by accounter + ,cost_acn computed by ( cost_inc - cost_out ) -- total cost "on hand" + ,dts_edit timestamp default 'now' -- last modification timestamp + ,constraint invnt_saldo_acn_zero check (NOT (qty_acn = 0 and cost_acn<>0 or qty_acn<>0 and cost_acn=0 )) +); + + +-------------------------------------------------------------------------------- +-- Result of "value_to_rows" transformation of AMOUNTS (integers) in doc_data: +-- when we write doc_data.qty=5 then 5 rows with snd_qty=1 will be added to QDistr +-- (these rows will be moved from this table to QStorned during every storning +-- operation, see s`p_make_qty_storno): +recreate table qdistr( + id dm_idb not null + ,doc_id dm_idb -- denorm for speed, also 4debug + ,ware_id dm_idb + ,snd_optype_id dm_ids -- denorm for speed + ,snd_id dm_idb -- ==> doc_data.id of "sender" + ,snd_qty dm_qty + ,rcv_doc_id bigint -- 30.12.2014, always null, for some debug views + ,rcv_optype_id dm_ids + ,rcv_id bigint -- nullable! ==> doc_data.id of "receiver" + ,rcv_qty numeric(12,3) + ,snd_purchase dm_cost + ,snd_retail dm_cost + ,rcv_purchase dm_cost + ,rcv_retail dm_cost + ,trn_id bigint default current_transaction + ,dts timestamp default 'now' +); + +-- 21.09.2015: DDL of indices for QDistr table depends on config parameter 'separ_qd_idx' (0 or 1), +-- definition of index key(s) see in 'oltp_create_with_split_heavy_tabs_0.sql' (for non-splitted QDistr) or in +-- 'oltp_create_with_split_heavy_tabs_1.sql' (when table QDistr is replaced with XQD* tables). +-- ................................................................................................ +-- ::: nb ::: PK on this table will be REMOVED at the end of script 'oltp_main_filling.sql' +-- if setting 'LOG_PK_VIOLATION' = '0' and 'HALT_TEST_ON_ERRORS' not containing ',PK,' +alter table qdistr add constraint pk_qdistr primary key(id) using index pk_qdistr; + + +-- 22.05.2014: storage for records which are removed from Qdistr when they are 'storned' +-- (will be returned back into qdistr when cancel operation or delete document, see s`p_kill_qty_storno): +recreate table qstorned( + id dm_idb not null + ,doc_id dm_idb -- denorm for speed + ,ware_id dm_idb + ,snd_optype_id dm_ids -- denorm for speed + ,snd_id dm_idb -- ==> doc_data.id of "sender" + ,snd_qty dm_qty + ,rcv_doc_id dm_idb -- 30.12.2014, for enable to remove PK on doc_data, see S`P_LOCK_DEPENDENT_DOCS + ,rcv_optype_id dm_ids + ,rcv_id dm_idb + ,rcv_qty dm_qty + ,snd_purchase dm_cost + ,snd_retail dm_cost + ,rcv_purchase dm_cost + ,rcv_retail dm_cost + ,trn_id bigint default current_transaction + ,dts timestamp default 'now' +); +create index qstorned_doc_id on qstorned(doc_id); -- confirmed 16.09.2014, see s`p_lock_dependent_docs +create index qstorned_snd_id on qstorned(snd_id); -- confirmed 16.09.2014, see s`p_kill_qty_storno +create index qstorned_rcv_id on qstorned(rcv_id); -- confirmed 16.09.2014, see s`p_kill_qty_storno +-- ::: nb ::: PK on this table will be REMOVED at the end of script 'oltp_main_filling.sql' +-- if setting 'LOG_PK_VIOLATION' = '0' and 'HALT_TEST_ON_ERRORS' not containing ',PK,' +alter table qstorned add constraint pk_qdstorned primary key(id) using index pk_qdstorned; + +------------------------------------------------------------------------------- +-- Result of "value_to_rows" transformation of COSTS in doc_list +-- for payment docs and when we change document state in: +-- s`p_add_invoice_to_stock, s`p_reserve_write_off, s`p_cancel_adding_invoice, s`p_cancel_write_off +recreate table pdistr( + -- ::: nb ::: PK on this table will be REMOVED at the end of script 'oltp_main_filling.sql' + -- if setting 'LOG_PK_VIOLATION' = '0' and 'HALT_TEST_ON_ERRORS' not containing ',PK,' + id dm_idb generated by default as identity constraint pk_pdistr primary key using index pk_pdistr + ,agent_id dm_idb + ,snd_optype_id dm_ids -- denorm for speed + ,snd_id dm_idb -- ==> doc_list.id of "sender" + ,snd_cost dm_qty + ,rcv_optype_id dm_ids + ,trn_id bigint default current_transaction + ,constraint pdistr_snd_op_diff_rcv_op check( snd_optype_id is distinct from rcv_optype_id ) +); +create index pdistr_snd_id on pdistr(snd_id); -- for fast seek when emul cascade deleting in s`p_kill_cost_storno +-- 09.09.2014: attempt to speed-up random choise of non-paid realizations and invoices +-- plus reduce number of doc_list IRs (see v_r`andom_find_non_paid_*, v_min_non_paid_*, v_max_non_paid_*) +create index pdistr_sndop_rcvop_sndid_asc on pdistr (snd_optype_id, rcv_optype_id, snd_id); -- see plan in V_MIN_NON_PAID_xxx +create descending index pdistr_sndop_rcvop_sndid_desc on pdistr (snd_optype_id, rcv_optype_id, snd_id); -- see plan in V_MAX_NON_PAID_xxx +create index pdistr_agent_id on pdistr(agent_id); -- confirmed, 16.09.2014: see s`p_make_cost_storno + + +-- Storage for records which are removed from Pdistr when they are 'storned' +-- (will returns back into Pdistr when cancel operation - see sp_k`ill_cost_storno): +recreate table pstorned( + -- ::: nb ::: PK on this table will be REMOVED at the end of script 'oltp_main_filling.sql' + -- if setting 'LOG_PK_VIOLATION' = '0' and 'HALT_TEST_ON_ERRORS' not containing ',PK,' + id dm_idb generated by default as identity constraint pk_pstorned primary key using index pk_pstorned + ,agent_id dm_idb + ,snd_optype_id dm_ids -- denorm for speed + ,snd_id dm_idb -- ==> doc_list.id of "sender" + ,snd_cost dm_cost + ,rcv_optype_id dm_ids + ,rcv_id dm_idb + ,rcv_cost dm_cost + ,trn_id bigint default current_transaction + ,constraint pstorned_snd_op_diff_rcv_op check( snd_optype_id is distinct from rcv_optype_id ) +); +create index pstorned_snd_id on pstorned(snd_id); -- confirmed, 16.09.2014: see s`p_kill_cost_storno +create index pstorned_rcv_id on pstorned(rcv_id); -- confirmed, 16.09.2014: see s`p_kill_cost_storno + +-- Definitions for "value-to-rows" COST distribution: +recreate table rules_for_pdistr( + mode dm_name -- 'new_doc_only' (rcv='clo'), 'distr_only' (snd='clo', rcv='res'), 'distr+new_doc' (all others) + ,snd_optype_id dm_ids + ,rcv_optype_id dm_ids + ,rows_to_multiply int default 10 -- how many rows to create when new doc of 'snd_optype_id' is created + ,constraint rules_for_pdistr_unq unique(snd_optype_id, rcv_optype_id) using index rules_for_pdistr_unq +); + + +------------------------------------------------------------------------------- + +-- lookup table: doc_states of documents (filled manually, see oltp_main_filling.sql) +recreate table doc_states( + id dm_ids constraint pk_doc_states primary key using index pk_doc_states + ,mcode dm_name -- mnemonic code + ,name dm_name + ,constraint doc_states_mcode_unq unique(mcode) using index doc_states_mcode_unq + ,constraint doc_states_name_unq unique(name) using index doc_states_name_unq +); + +-- lookup table: contragents: +recreate table agents( + id dm_idb generated by default as identity constraint pk_agents primary key using index pk_agents + ,name dm_name + ,is_customer dm_sign default 1 + ,is_supplier dm_sign default 0 + ,is_our_firm dm_sign default 0 -- for OUR orders to supplier (do NOT make reserves after add invoice for such docs) + ,constraint agents_mutual_excl check( bin_xor( is_our_firm, bin_or(is_customer, is_supplier) )=1 ) + ,constraint agents_name_unq unique(name) using index agents_name_unq +); +-- aux. index for randomly selecting during emulating create docs: +create descending index agents_id_desc on agents(id); +create index agents_is_supplier on agents(is_supplier); +create index agents_is_our_firm on agents(is_our_firm); + +-- groups of wares (filled only once before test, see oltp_data_filling.sql) +recreate table ware_groups( + id dm_idb constraint pk_ware_groups primary key using index pk_ware_groups + ,name dm_name + ,descr blob + ,constraint ware_groups_name_unq unique(name) using index ware_groups_name_unq +); + +-- Tasks like 'make_total_saldo' which should be serialized, i.e. run only +-- in 'SINGLETONE mode' (no two attaches can run such tasks at the same time); +-- Filled in oltp_main_filling.sql +recreate table semaphores( + id dm_idb constraint pk_semaphores primary key using index pk_semaphores + ,task dm_name + ,constraint semaphores_task_unq unique(task) using index semaphores_task_unq +); + + +-- Log for all changes in doc_data.qty (including DELETION of rows from doc_data). +-- Only INSERTION is allowed to this table for 'common' business operations. +-- Fields qty_diff & cost_diff can be NEGATIVE when document is removed ('cancelled') +-- Aggregating and deleting rows from this table - see s`rv_make_invnt_saldo +recreate table invnt_turnover_log( + ware_id dm_idb + ,qty_diff numeric(12,3) -- can be < 0 when cancelling document + ,cost_diff numeric(12,2) -- can be < 0 when cancelling document + ,doc_list_id bigint + ,doc_pref dm_mcode + ,doc_data_id bigint + ,optype_id dm_ids + ,id dm_idb not null -- FB 3.x: do NOT `generated by default as identity`, we use bulk-getting new IDs (or trigger with gen_id) instead + ,dts_edit timestamp default 'now' -- last modification timestamp + ,att_id int default current_connection + ,trn_id int default current_transaction + -- finally dis 09.01.2015, not needed for this table: ,constraint pk_invnt_turnover_log primary key(id) using index pk_invnt_turnover_log +); +create index invnt_turnover_log_ware_dd_id on invnt_turnover_log(ware_id, doc_data_id); + +-- Aux. table for random choise of app. unit to be performed and overall perfomance report. +-- see script %tmpdir% mp_random_run.sql which is auto generated by 1run_oltp_emul.bat: +recreate table business_ops( + unit dm_unit, + sort_prior int unique, + info dm_info, + mode dm_name, + kind dm_name, + random_selection_weight smallint, + constraint bo_unit unique(unit) using index bo_unit_unq +); +create index business_ops_rnd_wgth on business_ops(random_selection_weight); -- 23.07.2014 + + +-- standard Firebird error list with descriptions: +recreate table fb_errors( + fb_sqlcode int, + fb_gdscode int, + fb_mnemona varchar(31), + fb_errtext varchar(100), + constraint fb_errors_gds_code_unq unique(fb_gdscode) using index fb_errors_gds_code +); + + +-- 28.10.2015: source for view z_estimated_perf_per_minute, see oltp_isql_run_worker.bat (.sh): +-- data of estimated overall performance value with detalization to one minute, useful for +-- finding proper value of config parameter 'warm_time'. Values in the field SUCCESS_COUNT are +-- result of total count of business ops that SUCCESSFUL finished, see auto-generated script +-- $tmpdir/tmp_random_run.sql: +-- v_success_ops_increment = cast(rdb$get_context('USER_TRANSACTION', 'BUSINESS_OPS_CNT') as int); +-- result = gen_id( g_success_counter, v_success_ops_increment ); +-- Context variable 'BUSINESS_OPS_CNT' is incremented by 1 on every invokation of each unit +-- that implements BUSINESS action: client order, order to supplier, etc, -- see table business_ops +recreate table perf_estimated( + minute_since_test_start int, + success_count numeric(12,2), + att_id int default current_connection, + dts timestamp default 'now' +); +create index perf_est_minute_since_start on perf_estimated (minute_since_test_start); + + +-- Log of parsing ISQL statistics +recreate table perf_isql_stat( + trn_id bigint default current_transaction + ,isql_current bigint + ,isql_delta bigint + ,isql_max bigint + ,isql_elapsed numeric(12,3) + ,isql_reads bigint + ,isql_writes bigint + ,isql_fetches bigint + ,sql_state varchar(5) +); +create index perf_isql_stat_trn on perf_isql_stat(trn_id); + + +-- 23.12.2015 Log of parsed trace for ISQL session #1 +recreate table trace_stat( + unit dm_unit + ,dts_end timestamp + ,success smallint + ,elapsed_ms int + ,reads bigint + ,writes bigint + ,fetches bigint + ,marks bigint +); + +--create index trace_stat_dts_end on trace_stat(dts_end); +--create index trace_stat_unit_dts on trace_stat(unit, dts_end); + +-- Log for performance and errors (filled via autonom. tx if exc`eptions occur) +recreate table perf_log( + id dm_idb -- value from sequence where record has been added into GTT tmp$perf_log + --,id2 bigint -- value from sequence where record has been written from tmp$perf_log into fixed table perf_log (need for debug) + ,unit dm_unit -- name of executed SP + ,exc_unit char(1) -- was THIS unit the place where exception raised ? yes ==> '#' + ,fb_gdscode int -- how did finish this unit (0 = OK) + ,trn_id bigint default current_transaction + ,att_id int default current_connection + ,elapsed_ms bigint -- do not make it computed_by, updating occur in single point (s`p_add_to_perf_log) + ,info dm_info -- info for debug + ,exc_info dm_info -- info about exception (if occured) + ,stack dm_stack + ,ip dm_ip -- rdb$get_context('SYSTEM','CLIENT_ADDRESS'); for IPv6: 'FF80:0000:0000:0000:0123:1234:ABCD:EF12' - enough 39 chars + ,dts_beg timestamp default 'now' -- current_timestamp + ,dts_end timestamp + ,aux1 double precision -- for srv_recalc_idx_stat: new value of index statistics + ,aux2 double precision -- for srv_recalc_idx_stat: difference after recalc idx stat + ,dump_trn bigint default current_transaction +); +-- finally dis 09.01.2015, not needed for this table: create index perf_log_id on perf_log(id); +create descending index perf_log_dts_beg_desc on perf_log(dts_beg); +create descending index perf_log_unit on perf_log(unit, elapsed_ms); +-- 4 some analysis, added 25.06.2014: +-- dis 20.08.2014: create index perf_log_att on perf_log(att_id); +create descending index perf_log_trn_desc on perf_log(trn_id); -- descending - for fast access to last actions, e.g. of srv_mon_idx +-- 20.08.2014: +create index perf_log_gdscode on perf_log(fb_gdscode); + +-- Table to store single record for every *start* point of any app. unit. +-- When unit finishes NORMALLY (without exc.) this record is removed to fixed +-- storage (perf_log). Otherwise this table will serve as source to 'transfer' +-- uncommitted data to fixed perf_log via autonom. tx and session-level contexts +-- This results all such uncommitted data to be saved even in case of exc`eption. +recreate global temporary table tmp$perf_log( + id dm_idb + ,id2 bigint -- == gen_id(g_perf_log, 0) at the end of unit (when doing update) + ,unit dm_unit + ,exc_unit char(1) + ,fb_gdscode int + ,trn_id bigint default current_transaction + ,att_id int default current_connection + ,elapsed_ms bigint + ,info dm_info + ,exc_info dm_info + ,stack dm_stack + ,ip dm_ip + ,dts_beg timestamp default 'now' -- current_timestamp + ,dts_end timestamp + ,aux1 double precision + ,aux2 double precision + ,dump_trn bigint default current_transaction +) on commit delete rows; +create index tmp$perf_log_unit_trn_dts_end on tmp$perf_log(unit, trn_id, dts_end); + +-- introduced 09.08.2014, for checking mon$-tables stability: gather stats +-- Also used when context 'traced_units' is not empty (see s`p_add_to_perf_log). +-- see mail: SF.net SVN: firebird:[59967] firebird/trunk/src/jrd +-- (dimitr: Better (methinks) synchronization for the monitoring stuff) +recreate table mon_log( + unit dm_unit + ,fb_gdscode int + ,elapsed_ms int -- added 08.09.2014 + ,trn_id bigint + ,add_info dm_info + -------------------- + ,rec_inserts bigint + ,rec_updates bigint + ,rec_deletes bigint + ,rec_backouts bigint + ,rec_purges bigint + ,rec_expunges bigint + ,rec_seq_reads bigint + ,rec_idx_reads bigint + ---------- counters avaliable only in FB 3.0, since rev. 59953 -------------- + ,rec_rpt_reads bigint -- <<< since rev. 60005, 27.08.2014 18:52 + ,bkv_reads bigint -- mon$backversion_reads, since rev. 60012, 28.08.2014 19:16 + -- since rev. 59953, 05.08.2014 08:46: + ,frg_reads bigint + -- optimal values for (letter by dimitr 27.08.2014 21:30): + -- bkv_per_rec_reads = 1.0...1.2 + -- frg_per_rec_reads = 0.01...0.1 (better < 0.01), depending on record width; increase page size if high value + ,bkv_per_seq_idx_rpt computed by ( 1.00 * bkv_reads / nullif((rec_seq_reads + rec_idx_reads + rec_rpt_reads),0) ) + ,frg_per_seq_idx_rpt computed by ( 1.00 * frg_reads / nullif((rec_seq_reads + rec_idx_reads + rec_rpt_reads),0) ) + ,rec_locks bigint + ,rec_waits bigint + ,rec_confl bigint + ----------------------------------------------------------------------------- + ,pg_reads bigint + ,pg_writes bigint + ,pg_fetches bigint + ,pg_marks bigint + ,mem_used bigint + ,mem_alloc bigint + ,server_pid bigint + ,remote_pid bigint + ,stat_id bigint + ,dump_trn bigint default current_transaction + ,ip dm_ip + ,usr dm_dbobj + ,remote_process dm_info + ,rowset bigint -- for grouping records that related to the same measurement + ,att_id bigint + ,id dm_idb generated by default as identity constraint pk_mon_log primary key using index pk_mon_log + ,dts timestamp default 'now' + ,sec int +); +create descending index mon_log_rowset_desc on mon_log(rowset); +create index mon_log_gdscode on mon_log(fb_gdscode); +create index mon_log_unit on mon_log(unit); +create index mon_log_dts on mon_log(dts); -- 26.09.2015, for SP srv_mon_stat_per_units + + +-- 29.08.2014 +recreate table mon_log_table_stats( + unit dm_unit + ,fb_gdscode int + ,trn_id bigint + ,table_name dm_dbobj + -------------------- + ,rec_inserts bigint + ,rec_updates bigint + ,rec_deletes bigint + ,rec_backouts bigint + ,rec_purges bigint + ,rec_expunges bigint + ,rec_seq_reads bigint + ,rec_idx_reads bigint + -------------------- + ,rec_rpt_reads bigint + ,bkv_reads bigint + ,frg_reads bigint + ,bkv_per_seq_idx_rpt computed by ( 1.00 * bkv_reads / nullif((rec_seq_reads + rec_idx_reads + rec_rpt_reads),0) ) + ,frg_per_seq_idx_rpt computed by ( 1.00 * frg_reads / nullif((rec_seq_reads + rec_idx_reads + rec_rpt_reads),0) ) + ,rec_locks bigint + ,rec_waits bigint + ,rec_confl bigint + ,stat_id bigint + ,rowset bigint -- for grouping records that related to the same measurement + ,table_id smallint + ,is_system_table smallint + ,rel_type smallint + ,att_id bigint default current_connection + ,id dm_idb generated by default as identity constraint pk_mon_log_table_stats primary key using index pk_mon_log_table_stats + ,dts timestamp default 'now' +); +create descending index mon_log_table_stats_rowset on mon_log_table_stats(rowset); +create index mon_log_table_stats_gdscode on mon_log_table_stats(fb_gdscode); +create index mon_log_table_stats_tn_unit on mon_log_table_stats(table_name, unit); +create index mon_log_table_stats_dts on mon_log_table_stats(dts); -- 26.09.2015, for SP srv_mon_stat_per_tables + + +-------------------------------------------------------------------------------- +-- # # # # # F O R E I G N K E Y S # # # # # +-------------------------------------------------------------------------------- +-- create ref constraints (NB: must be defined AFTER creation parent tables with PK/UK) +-- ::: NB ::: See about cascades caution: +-- sql.ru/forum/1081231/kaskadnoe-udalenie-pochemu-trigger-tablicy-detali-ne-vidit-master-zapisi?hl= +alter table doc_list + add constraint fk_doc_list_agents foreign key (agent_id) references agents(id) +; + +alter table doc_data + add constraint fk_doc_data_doc_list foreign key (doc_id) references doc_list(id) + on delete cascade + using index fk_doc_data_doc_list +; + +alter table wares + add constraint fk_wares_ware_groups foreign key (group_id) references ware_groups(id) +; + +-- do NOT: alter table money_turnover_log add constraint fk_money_turnover_log_doc_list foreign key (doc_id) references doc_list(id); +-- (documents can be deleted but it mean that NEW record in money_turnover_log appear with cost < 0!) + +-- dis 28.01.2015 0135, no need: +--alter table money_turnover_log +-- add constraint fk_money_turnover_log_agents foreign key (agent_id) references agents(id) +--; + + + +set term ^; + +-------------------------------------------------------------------------------- +------- "S y s t e m" f u n c s & s t o r e d p r o c s -------- +-------------------------------------------------------------------------------- + +------------ P S Q L S t o r e d F u n c t i o n s ----------------- +-- As of current FB-3.x state, deterministic function can use internal 'cache' +-- only while some query is running. Its result is RE-CALCULATED every time when +-- 1) running new query with this func; 2) encounter every new call inside PSQL +-- see sql.ru/forum/actualutils.aspx?action=gotomsg&tid=951736&msg=12787923 +create or alter function fn_infinity returns bigint deterministic as +begin + return 9223372036854775807; +end -- fn_infinity +^ + +create or alter function fn_is_lock_trouble(a_gdscode int) returns boolean +as +begin + -- lock_conflict, concurrent_transaction, deadlock, update_conflict + return a_gdscode in (335544345, 335544878, 335544336,335544451 ); +end + +^ -- fn_is_lock_trouble + +create or alter function fn_is_validation_trouble(a_gdscode int) returns boolean +as +begin + -- 335544558 check_constraint Operation violates CHECK constraint @1 on view or table @2. + -- 335544347 not_valid Validation error for column @1, value "@2". + return a_gdscode in ( 335544347,335544558 ); +end + +^ -- fn_is_validation_trouble + +create or alter function fn_is_uniqueness_trouble(a_gdscode int) returns boolean +as +begin + -- if table has unique constraint: 335544665 unique_key_violation (violation of PRIMARY or UNIQUE KEY constraint "T1_XY" on table "T1") + -- if table has only unique index: 335544349 no_dup (attempt to store duplicate value (visible to active transactions) in unique index "T2_XY") + return a_gdscode in ( 335544665,335544349 ); +end + +^ -- fn_is_uniqueness_trouble + +create or alter function fn_halt_sign(a_gdscode int) returns dm_sign +as + declare function fn_halt_on_severe_error() returns dm_name deterministic as + begin + return rdb$get_context('USER_SESSION', 'HALT_TEST_ON_ERRORS'); + end + declare result dm_sign = 0; +begin + if ( a_gdscode = 0 ) then result =1; -- 3.x SC & CS trouble, core-4565! + -- refactored 13.08.2014 - see setting 'HALT_TEST_ON_ERRORS' (oltp_main_filling.sql) + if ( result = 0 and fn_halt_on_severe_error() containing 'CK' ) then + result = iif( a_gdscode + in ( 335544347 -- not_valid Validation error for column @1, value "@2". + ,335544558 -- check_constraint Operation violates CHECK constraint @1 on view or table @2. + ) + ,1 + ,0 + ); + if (result = 0 and fn_halt_on_severe_error() containing 'PK' ) then + result = iif( a_gdscode + in ( 335544665 -- unique_key_violation (violation of PRIMARY or UNIQUE KEY constraint "T1_XY" on table "T1") + ,335544349 -- no_dup (attempt to store duplicate value (visible to active transactions) in unique index "T2_XY") - without UNQ constraint + ) + ,1 + ,0 + ); + if (result = 0 and fn_halt_on_severe_error() containing 'FK' ) then + result = iif( a_gdscode + in ( 335544466 -- violation of FOREIGN KEY constraint @1 on table @2 + ,335544838 -- Foreign key reference target does not exist (when attempt to ins/upd in DETAIL table FK-field with value for which parent ID has been changed or deleted - even in uncommitted concurrent Tx) + ,335544839 -- Foreign key references are present for the record (when attempt to upd/del in PARENT table PK-field and rows in DETAIL (no-cascaded!) exists for old value) + ) + ,1 + ,0 + ); + + if ( result = 0 and fn_halt_on_severe_error() containing 'ST' ) then + result = iif( a_gdscode = 335544842, 1, 0); -- trouble in 3.0 SC only: this error appears at the TOP of stack and this prevent following job f Tx + + return result; -- 1 ==> force test to be stopped itself + +end + +^ -- fn_halt_sign + +create or alter function fn_remote_process returns varchar(255) deterministic as +begin + return rdb$get_context('SYSTEM', 'CLIENT_PROCESS'); +end +^ + +create or alter function fn_remote_address returns dm_ip deterministic as +begin + return rdb$get_context('SYSTEM','CLIENT_ADDRESS'); +end +^ + +create or alter function fn_is_snapshot returns boolean deterministic as +begin + return + fn_remote_process() containing 'IBExpert' + or + rdb$get_context('SYSTEM','ISOLATION_LEVEL') is not distinct from upper('SNAPSHOT'); +end +^ + +------ stored functions for caching data from DOC_STATES table: -------- +-- ::: NB ::: as of current FB-3 state, deterministic function will re-calculate +-- it's result on EVERY NEW call of the SAME statement inside the same transaction. +-- www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1081535&msg=15694407 +-- Also such repeating work will be done on every function call from trigger or SP. +-- So instead of access to table it's better to return value of context variable +-- which has been defined once (at 1st call of this determ. function). +----------------------------------------------------------------------------- +create or alter function fn_doc_open_state returns int deterministic as + declare v_id type of dm_idb = null; + declare v_key type of dm_name = 'DOC_OPEN_STATE'; + declare v_stt varchar(255); +begin + -- find id for documents state where any changes enabled: + v_id=rdb$get_context('USER_SESSION', 'FN_DOC_OPEN_STATE'); + if (v_id is null) then begin + v_stt='select s.id from doc_states s where s.mcode=:x'; + execute statement (v_stt) ( x := :v_key ) into v_id; + if (v_id is null) then + begin + exception ex_record_not_found using( 'DOC_STATES', v_key ); + end + rdb$set_context('USER_SESSION', 'FN_DOC_OPEN_STATE', v_id); + end + + return v_id; +end + +^ -- fn_doc_open_state + +create or alter function fn_doc_fix_state returns int deterministic as + declare v_id type of dm_idb = null; + declare v_key type of dm_name = 'DOC_FIX_STATE'; + declare v_stt varchar(255); +begin + -- find id for documents state where no change except payment enabled: + v_id=rdb$get_context('USER_SESSION', 'FN_DOC_FIX_STATE'); + if (v_id is null) then begin + v_stt='select s.id from doc_states s where s.mcode=:x'; + --select s.id from doc_states s where s.mcode=:v_key into v_id; + execute statement (v_stt) ( x := :v_key ) into v_id; + if (v_id is null) then + begin + exception ex_record_not_found using( 'DOC_STATES', v_key ); + end + + rdb$set_context('USER_SESSION', 'FN_DOC_FIX_STATE', v_id); + end + + return v_id; + +end + +^ -- fn_doc_fix_state + +create or alter function fn_doc_clos_state returns int deterministic as + declare v_id type of dm_idb = null; + declare v_key type of dm_name = 'DOC_CLOS_STATE'; + declare v_stt varchar(255); +begin + -- find id for documents state where ALL changes disabled: + v_id=rdb$get_context('USER_SESSION', 'FN_DOC_CLOS_STATE'); + if (v_id is null) then begin + v_stt='select s.id from doc_states s where s.mcode=:x'; + --select s.id from doc_states s where s.mcode=:v_key into v_id; + execute statement (v_stt) ( x := :v_key ) into v_id; + if (v_id is null) then + begin + exception ex_record_not_found using( 'DOC_STATES', v_key ); + end + + rdb$set_context('USER_SESSION', 'FN_DOC_CLOS_STATE', v_id); + end + + return v_id; +end -- fn_doc_clos_state + +^ + +create or alter function fn_doc_canc_state returns int deterministic as + declare v_id type of dm_idb = null; + declare v_key type of dm_name = 'DOC_CANC_STATE'; + declare v_stt varchar(255); +begin + -- find id for documents state where ALL changes disabled: + v_id=rdb$get_context('USER_SESSION', 'FN_DOC_CANC_STATE'); + if (v_id is null) then begin + v_stt='select s.id from doc_states s where s.mcode=:x'; + --select s.id from doc_states s where s.mcode=:v_key into v_id; + execute statement (v_stt) ( x := :v_key ) into v_id; + if (v_id is null) then + begin + exception ex_record_not_found using( 'DOC_STATES', v_key ); + end + + rdb$set_context('USER_SESSION', 'FN_DOC_CANC_STATE', v_id); + end + + return v_id; +end + +^ -- fn_doc_canc_state + +------ stored functions for caching data from OPTYPES table: -------- + +create or alter function fn_oper_order_by_customer returns int deterministic as + declare v_id type of dm_idb = null; + declare v_key dm_sign; + declare v_stt varchar(255); +begin + -- find id for operation "client's order". + -- Raises ex`ception if it can`t be found. + v_id=rdb$get_context('USER_SESSION', 'FN_OPER_ORDER_BY_CUSTOMER'); + if (v_id is null) then begin + v_stt = 'select o.id from optypes o where o.m_qty_clo = :x and o.m_qty_clr = 0'; + v_key = 1; + execute statement (v_stt) ( x := :v_key ) into v_id; + if (v_id is null) then + begin + exception ex_record_not_found using( 'OPTYPES', v_key ); + end + rdb$set_context('USER_SESSION', 'FN_OPER_ORDER_BY_CUSTOMER', v_id); + end + + return v_id; + +end + +^ -- fn_oper_order_by_customer + +create or alter function fn_oper_cancel_customer_order returns int deterministic as + declare v_id type of dm_idb = null; + declare v_key dm_sign; + declare v_stt varchar(255); +begin + -- find id for operation "client's order". + -- Raises ex`ception if it can`t be found. + v_id=rdb$get_context('USER_SESSION', 'FN_OPER_CANCEL_CUSTOMER_ORDER'); + if (v_id is null) then begin + v_stt = 'select o.id from optypes o where o.m_qty_clr = :x'; + v_key = 1; + execute statement (v_stt) ( x := :v_key ) into v_id; + if (v_id is null) then + begin + exception ex_record_not_found using( 'OPTYPES', v_key ); + end + rdb$set_context('USER_SESSION', 'FN_OPER_CANCEL_CUSTOMER_ORDER', v_id); + end + + return v_id; + +end + +^ -- fn_oper_cancel_customer_order + +create or alter function fn_oper_order_for_supplier returns int deterministic as + declare v_id type of dm_idb = null; + declare v_key dm_sign; + declare v_stt varchar(255); +begin + -- find id for operation "add to stock order, sent to supplier". + -- Raises ex`ception if it can`t be found. + v_id=rdb$get_context('USER_SESSION', 'FN_OPER_ORDER_FOR_SUPPLIER'); + if (v_id is null) then begin + v_stt = 'select o.id from optypes o where o.m_qty_ord = :x'; + v_key = 1; + execute statement (v_stt) ( x := :v_key ) into v_id; + if (v_id is null) then + begin + exception ex_record_not_found using( 'OPTYPES', v_key ); + end + rdb$set_context('USER_SESSION', 'FN_OPER_ORDER_FOR_SUPPLIER', v_id); + end + + return v_id; + +end + +^ -- fn_oper_order_for_supplier + +create or alter function fn_oper_invoice_get returns int deterministic as + declare v_id type of dm_idb = null; + declare v_key1 dm_sign; + declare v_key2 dm_sign; + declare v_stt varchar(255); +begin + -- find id for operation "get invoice from supplier" (invoice need to be checked) + -- Raises ex`ception if it can`t be found. + v_id=rdb$get_context('USER_SESSION', 'FN_OPER_INVOICE_GET'); + if (v_id is null) then begin + v_stt = 'select o.id from optypes o where o.m_qty_ord=:x and o.m_qty_sup=:y'; + v_key1 = -1; + v_key2 = 1; + execute statement (v_stt) ( x := :v_key1, y := :v_key2 ) into v_id; + if (v_id is null) then + begin + exception ex_record_not_found using( 'OPTYPES', 'm_qty_ord=-1 and m_qty_sup=1' ); + end + rdb$set_context('USER_SESSION', 'FN_OPER_INVOICE_GET', v_id); + end + + return v_id; + +end + +^ -- fn_oper_invoice_get + +create or alter function fn_oper_invoice_add returns int deterministic as + declare v_id type of dm_idb = null; + declare v_key dm_sign; + declare v_key1 dm_sign; + declare v_key2 dm_sign; + declare v_stt varchar(255); +begin + -- find id for operation "invoice checked and accepted" (added to avaliable remainders) + -- Raises exc`eption if it can`t be found. + v_id=rdb$get_context('USER_SESSION', 'FN_OPER_INVOICE_ADD'); + if (v_id is null) then begin + v_stt = 'select o.id from optypes o where o.m_qty_avl=:x'; + v_key = 1; + execute statement (v_stt) ( x := :v_key ) into v_id; + if (v_id is null) then + begin + exception ex_record_not_found using( 'OPTYPES', 'm_qty_sup=-1 and m_qty_avl=1' ); + end + + rdb$set_context('USER_SESSION', 'FN_OPER_INVOICE_ADD', v_id); + end + + return v_id; +end + +^ -- fn_oper_invoice_add + + +create or alter function fn_oper_retail_reserve returns int deterministic as + declare v_id type of dm_idb = null; + declare v_key1 dm_sign; + declare v_key2 dm_sign; + declare v_stt varchar(255); +begin + -- find id for operation "retail selling - reserve for customer". + -- Raises exc`eption if it can`t be found. + v_id=rdb$get_context('USER_SESSION', 'FN_OPER_RETAIL_RESERVE'); + if (v_id is null) then begin + v_stt = 'select o.id from optypes o where o.m_qty_avl=:x and o.m_qty_res=:y'; + v_key1 = -1; + v_key2 = 1; + execute statement (v_stt) ( x := :v_key1, y := :v_key2 ) into v_id; + if (v_id is null) then + begin + exception ex_record_not_found using( 'OPTYPES', 'm_qty_avl=-1 and m_qty_res=1' ); + end + rdb$set_context('USER_SESSION', 'FN_OPER_RETAIL_RESERVE', v_id); + end + + return v_id; + +end + +^ -- fn_oper_retail_reserve + +create or alter function fn_oper_retail_realization returns int deterministic as + declare v_id type of dm_idb = null; + declare v_key1 dm_sign; + declare v_key2 dm_sign; + declare v_stt varchar(255); +begin + -- find id for operation "retail selling - write-off (realization)". + -- Raises exc`eption if it can`t be found. + v_id=rdb$get_context('USER_SESSION', 'FN_OPER_RETAIL_REALIZATION'); + if (v_id is null) then begin + v_stt = 'select o.id from optypes o where o.m_qty_res=:x and o.m_cost_out=:y'; + v_key1 = -1; + v_key2 = 1; + execute statement (v_stt) ( x := :v_key1, y := :v_key2 ) into v_id; + if (v_id is null) then + begin + exception ex_record_not_found using( 'OPTYPES', 'm_qty_res=-1 and m_cost_out=1' ); + end + rdb$set_context('USER_SESSION', 'FN_OPER_RETAIL_REALIZATION', v_id); + end + + return v_id; + +end + +^ -- fn_oper_retail_realization + +create or alter function fn_oper_pay_to_supplier returns int deterministic as + declare v_id type of dm_idb = null; + declare v_key dm_sign; + declare v_stt varchar(255); +begin + -- find id for operation "incoming - we pay to supplier for wares". + -- Raises exc`eption if it can`t be found. + v_id=rdb$get_context('USER_SESSION', 'FN_OPER_PAY_TO_SUPPLIER'); + if (v_id is null) then begin + v_stt = 'select o.id from optypes o where o.m_supp_debt=:x'; + v_key = -1; + execute statement (v_stt) ( x := :v_key ) into v_id; + if (v_id is null) then + begin + exception ex_record_not_found using( 'OPTYPES', 'm_qty_res=-1 and m_cost_out=1' ); + end + rdb$set_context('USER_SESSION', 'FN_OPER_PAY_TO_SUPPLIER', v_id); + end + + return v_id; + +end + +^ -- fn_oper_pay_to_supplier + +create or alter function fn_oper_pay_from_customer returns int deterministic as + declare v_id type of dm_idb = null; + declare v_key dm_sign; + declare v_stt varchar(255); +begin + -- find id for operation "accept payment for sold wares (target transfer)". + -- Raises exc`eption if it can`t be found. + v_id=rdb$get_context('USER_SESSION', 'FN_OPER_PAY_FROM_CUSTOMER'); + if (v_id is null) then begin + v_stt = 'select o.id from optypes o where o.m_cust_debt=:x'; + v_key = -1; + execute statement (v_stt) ( x := :v_key ) into v_id; + if (v_id is null) then + begin + exception ex_record_not_found using( 'OPTYPES', 'm_qty_res=-1 and m_cost_out=1' ); + end + + rdb$set_context('USER_SESSION', 'FN_OPER_PAY_FROM_CUSTOMER', v_id); + end + + return v_id; + +end + +^ -- fn_oper_pay_from_customer + +create or alter function fn_mcode_for_oper(a_oper_id dm_idb) returns dm_mcode deterministic +as + declare v_mnemonic_code type of dm_mcode; +begin + -- returns mnemonic code for operation ('ORD' for stock order, et al) + v_mnemonic_code = rdb$get_context('USER_SESSION','OPER_MCODE_'||:a_oper_id); + if (v_mnemonic_code is null) then begin + select o.mcode from optypes o where o.id = :a_oper_id into v_mnemonic_code; + rdb$set_context('USER_SESSION','OPER_MCODE_'||:a_oper_id, v_mnemonic_code); + end + return v_mnemonic_code; +end + +^ -- fn_mcode_for_oper + +create or alter function fn_get_stack( + a_halt_due_to_error smallint default 0 +) + returns dm_stack +as + declare v_call_stack dm_stack; + declare function fn_internal_stack_disabled returns boolean deterministic as + begin + return ( coalesce(rdb$get_context('USER_SESSION','ENABLE_MON_QUERY'),0) = 0 ); + end + declare v_line dm_stack; + declare v_this dm_dbobj = 'fn_get_stack'; +begin + -- :: NB :: + -- 1. currently building of stack stack IGNORES procedures which are + -- placed b`etween top-level SP and 'this' unit. See: + -- sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1109867&msg=16422390 + -- (resolved, see: ChangeLog, issue "2014-08-12 10:21 hvlad") + -- 2. mon$call_stack is UNAVALIABLE if some SP is called from trigger and + -- this trigger, in turn, fires IMPLICITLY due to cascade FK. + -- 13.08.2014: still UNRESOLVED. See: + -- sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1109867&msg=16438071 + -- 3. Deadlocks trouble when heavy usage of monitoring was resolved only + -- in FB-3, approx. 09.08.2014, see letter to dimitr 11.08.2014 11:56 + v_call_stack=''; + if ( fn_remote_process() NOT containing 'IBExpert' + and a_halt_due_to_error = 0 + and fn_internal_stack_disabled() + ) then + --#### + exit; + --#### + + for + with recursive + r as ( + select 1 call_level, + c.mon$statement_id as stt_id, + c.mon$call_id as call_id, + c.mon$object_name as obj_name, + c.mon$object_type as obj_type, + c.mon$source_line as src_row, + c.mon$source_column as src_col + -- NB, 13.08.2014: unavaliable record if SP is called from: + -- 1) trigger which is fired by CASCADE + -- 2) dyn SQL (ES) + -- see: + -- sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1109867&msg=16438071 + -- sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1109867&msg=16442098 + from mon$call_stack c + where c.mon$caller_id is null + + UNION ALL + + select r.call_level+1, + c.mon$statement_id, + c.mon$call_id, + c.mon$object_name, + c.mon$object_type, + c.mon$source_line, + c.mon$source_column + from mon$call_stack c + join r + on c.mon$caller_id = r.call_id + ) + ,b as( + select h.call_level, + h.obj_name, + h.obj_type, + h.src_row, + h.src_col + --count(*)over() cnt + from r h + join mon$statements s + on s.mon$statement_id = h.stt_id + where s.mon$attachment_id = current_connection + ) + select obj_name, obj_type, src_row, src_col, call_level + from b + -- where k < cnt -- <<< do NOT include THIS sp name in call_stack + order by call_level -- ::: NB ::: + as cursor c + do + begin + v_line = trim(c.obj_name)||'('||c.src_row||':'||c.src_col||') ==> '; + if ( char_length(v_call_stack) + char_length(v_line) >= 512 ) + then + exit; + + if ( v_call_stack NOT containing v_line and v_line NOT containing v_this||'(' ) + then + v_call_stack = v_call_stack || v_line; + end + if ( v_call_stack > '' ) then + v_call_stack = substring( v_call_stack from 1 for char_length(v_call_stack)-5 ); + return v_call_stack; +end + +^ -- fn_get_stack + +-- STUB, will be redefined when config parameter 'use_external_to_stop' +-- has some non-empty value of [path+]file of external table that will serve +-- as mean to stop test from outside (i.e. this parameter is UNcommented) +create or alter view v_stoptest as +select 1 as need_to_stop +from rdb$database +where 1 = 0 +^ + +create or alter procedure sp_stoptest +returns(need_to_stop smallint) as +begin + need_to_stop = sign( gen_id(g_stop_test, 0) ); + if ( need_to_stop = 0 and exists( select * from v_stoptest ) ) + then + need_to_stop = -1; + if ( need_to_stop <> 0 ) then + -- "+1" => test_time expired, normal finish; + -- "-1" ==> outside command to premature stop test by adding line into + -- text file defined by 'ext_stoptest' table or running temp + -- batch file %tmpdir%stoptest.tmp.bat (1stoptest.tmp.sh) + suspend; +end +^ + +create or alter procedure sp_halt_on_error( + a_char char(1) default '1', + a_gdscode bigint default null, + a_trn_id bigint default null, + a_need_to_stop smallint default null +) as + declare v_curr_trn bigint; + declare v_dummy bigint; + declare v_need_to_stop smallint; +begin + -- Adding single character + LF into external table (text file) 'stoptest.txt' + -- when test is needed to stop (either due to test_time expiration or because of + -- encountering some critical errors like PK/FK violations or negative amount remainders). + -- Input argument a_char: + -- '1' ==> call from SP_ADD_TO_ABEND_LOG: unexpected test finish due to PK/FK violation, + -- and also call from SRV_FIND_QD_QS_MISM when founding mismatches between total + -- sum of doc_data amounts and count of rows in QDistr + QStorned. + -- '2' ==> call from SP_CHECK_TO_STOP_WORK: expected test finish due to test_time expired. + -- In this case argument a_gdscode = -1 and we do NOT need to evaluate call stack. + -- '5' ==> call from SRV_CHECK_NEG_REMAINDERS: unexpected test finish due to encountering + -- negative remainder of some ware_id. NB: context var 'QMISM_VERIFY_BITSET' should + -- have value N for which result of bin_and( N, 2 ) will be 1 in order this checkto be done. + + if ( (a_need_to_stop < 0 or gen_id(g_stop_test, 0) <= 0) and fn_remote_process() NOT containing 'IBExpert' ) + then + begin + v_curr_trn = coalesce(a_trn_id, current_transaction); + + -- "-1" ==> decision to premature stop all ISQL sessions by issuing EXTERNAl command + -- (either running $tmpdir/1stoptest.tmp.sh or adding line into external file 'stoptest.txt') + v_need_to_stop = coalesce( :a_need_to_stop, (select p.need_to_stop from sp_stoptest p rows 1) ); + + v_dummy = gen_id( g_stop_test, 2147483647); + + in autonomous transaction do + begin + -- set elapsed_ms = -1 to skip this record from srv_mon_perf_detailed output: + insert into perf_log( + unit + ,fb_gdscode + ,ip + ,trn_id + ,dts_end + ,elapsed_ms + ,stack + ,exc_unit + ,exc_info + ) values( + 'sp_halt_on_error' + ,:a_gdscode + ,fn_remote_address() + ,:v_curr_trn + ,'now' + ,-1 + ,fn_get_stack( iif(:a_gdscode>=0, 1, 0) ) -- pass '1' to force write call_stack into perf_log if this is NOT expected test finish + ,:a_char + ,iif( -- write info for reporting state of how test finished: + :a_gdscode >= 0, 'ABNORMAL: GDSCODE='||coalesce(:a_gdscode,'') + ,iif( :v_need_to_stop < 0 + ,'PREMATURE: EXTERNAL COMMAND.' + ,'NORMAL: TEST_TIME EXPIRED.' + ) + ) + ); + + begin + -- moved here from sp_check_to_stop_work: avoid excessive start auton. Tx! + update perf_log p set p.info = 'closed' + where p.unit = 'perf_watch_interval' and p.info containing 'active' + order by dts_beg desc -- "+0" ? + rows 1; + when any do + begin + -- NOP -- + end + end + end + end +end + +^ -- sp_halt_on_error + +create or alter procedure sp_flush_tmpperf_in_auton_tx( + a_starter dm_unit, -- name of module which STARTED job, = rdb$get_context('USER_SESSION','LOG_PERF_STARTED_BY') + a_context_rows_cnt int, -- how many 'records' with context vars need to be processed + a_gdscode int default null +) +as + declare i smallint; + declare v_id dm_idb; + declare v_curr_tx int; + declare v_exc_unit type of column perf_log.exc_unit; + declare v_stack dm_stack; + declare v_dbkey dm_dbkey; + declare v_remote_addr dm_ip; +begin + -- Flushes all data from context variables with names 'PERF_LOG_xxx' + -- which have been set in sp_f`lush_perf_log_on_abend for saving uncommitted + -- data in tmp$perf_log in case of error. Frees namespace USER_SESSION from + -- all such vars (allowing them to store values from other records in tmp$perf_log) + -- Called only from sp_abend_flush_perf_log + v_curr_tx = current_transaction; + v_remote_addr = fn_remote_address(); -- out from loop (seems that recalc on every iteration + cost of savepoint when call this fn) + + -- 13.08.2014: we have to get full call_stack in AUTONOMOUS trn! + -- sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1109867&msg=16422273 + in autonomous transaction do -- ***** A U T O N O M O U S T x, due to call fn_get_stack ***** + begin + -- 11.01.2015: decided to profile this: + insert into perf_log(unit, dts_beg, trn_id, ip) + values( 't$perf-abend:' || :a_starter, + 'now', + :v_curr_tx, + :v_remote_addr + ) + returning rdb$db_key into v_dbkey; -- will return to this row after loop + + i=0; + while (i < a_context_rows_cnt) do + begin + v_exc_unit = rdb$get_context('USER_SESSION', 'PERF_LOG_'|| :i ||'_XUNI'); + if ( v_exc_unit = '#' ) then -- ==> call from unit where exception occured (not from callers of ) + v_stack = fn_get_stack( fn_halt_sign(a_gdscode) ); + else + v_stack = null; + + insert into perf_log( + id, + unit, + fb_gdscode, + info, + exc_unit, + exc_info, + dts_beg, + dts_end, + elapsed_ms, + aux1, + aux2, + trn_id, + ip, + stack + ) + values( + rdb$get_context('USER_SESSION', 'PERF_LOG_'|| :i ||'_ID'), + rdb$get_context('USER_SESSION', 'PERF_LOG_'|| :i ||'_UNIT'), + rdb$get_context('USER_SESSION', 'PERF_LOG_'|| :i ||'_GDS'), + rdb$get_context('USER_SESSION', 'PERF_LOG_'|| :i ||'_INFO'), + :v_exc_unit, + rdb$get_context('USER_SESSION', 'PERF_LOG_'|| :i ||'_XNFO'), + rdb$get_context('USER_SESSION', 'PERF_LOG_'|| :i ||'_BEG'), + rdb$get_context('USER_SESSION', 'PERF_LOG_'|| :i ||'_END'), + rdb$get_context('USER_SESSION', 'PERF_LOG_'|| :i ||'_MS'), + rdb$get_context('USER_SESSION', 'PERF_LOG_'|| :i ||'_AUX1'), + rdb$get_context('USER_SESSION', 'PERF_LOG_'|| :i ||'_AUX2'), + :v_curr_tx, + :v_remote_addr, + :v_stack + ); + + -- free space for new context vars which can be set on later iteration: + rdb$set_context('USER_SESSION', 'PERF_LOG_'|| :i ||'_ID', null); -- 1 + rdb$set_context('USER_SESSION', 'PERF_LOG_'|| :i ||'_UNIT', null); + rdb$set_context('USER_SESSION', 'PERF_LOG_'|| :i ||'_GDS', null); + rdb$set_context('USER_SESSION', 'PERF_LOG_'|| :i ||'_INFO', null); + rdb$set_context('USER_SESSION', 'PERF_LOG_'|| :i ||'_XUNI', null); -- 5 + rdb$set_context('USER_SESSION', 'PERF_LOG_'|| :i ||'_XNFO', null); + rdb$set_context('USER_SESSION', 'PERF_LOG_'|| :i ||'_BEG', null); + rdb$set_context('USER_SESSION', 'PERF_LOG_'|| :i ||'_END', null); + rdb$set_context('USER_SESSION', 'PERF_LOG_'|| :i ||'_MS', null); + rdb$set_context('USER_SESSION', 'PERF_LOG_'|| :i ||'_AUX1', null); -- 10 + rdb$set_context('USER_SESSION', 'PERF_LOG_'|| :i ||'_AUX2', null); + + i = i + 1; + end -- while (i < a_context_rows_cnt) + + update perf_log g + set info = 'gds='|| :a_gdscode||', autonomous Tx: ' ||:i||' rows', + dts_end = 'now', + elapsed_ms = datediff( millisecond from dts_beg to cast('now' as timestamp) ), + aux1 = :i + where g.rdb$db_key = :v_dbkey; + + end -- in autonom. tx +end + +^ -- sp_flush_tmpperf_in_auton_tx + +create or alter procedure sp_flush_perf_log_on_abend( + a_starter dm_unit, -- name of module which STARTED job, = rdb$get_context('USER_SESSION','LOG_PERF_STARTED_BY') + a_unit dm_unit, -- name of module where trouble occured + a_gdscode int default null, + a_info dm_info default null, -- additional info for debug + a_exc_info dm_info default null, -- user-def or standard ex`ception description + a_aux1 dm_aux default null, + a_aux2 dm_aux default null +) +as + declare v_cnt smallint; + declare v_dts timestamp; + declare v_info dm_info = ''; + declare v_ctx_lim smallint; -- max number of context vars which can be put in one 'batch' + declare c_max_context_var_cnt int = 1000; -- limitation of Firebird: not more than 1000 context variables + declare c_std_user_exc int = 335544517; -- std FB code for user defined exceptions + declare c_gen_inc_step_pf int = 20; -- size of `batch` for get at once new IDs for perf_log (reduce lock-contention of gen page) + declare v_gen_inc_iter_pf int; -- increments from 1 up to c_gen_inc_step_pf and then restarts again from 1 + declare v_gen_inc_last_pf dm_idb; -- last got value after call gen_id (..., c_gen_inc_step_pf) + declare v_pf_new_id dm_idb; +begin + + -- called only if ***ABEND*** occurs (from sp`_add_to_abend_log) + if ( rdb$get_context('USER_TRANSACTION', 'DONE_FLUSH_PERF_LOG_ON_ABEND') is NOT null ) + then + exit; -- we already done this (just after unit where exc`exption occured) + + v_ctx_lim = cast( rdb$get_context('USER_SESSION', 'CTX_LIMIT_FOR_FLUSH_PERF_LOG') as smallint ); + if ( v_ctx_lim is null ) then + begin + -- First, calculate (approx) avaliable limit for creating new ctx vars: + -- limitation of Firebird: not more than 1000 context variables; take twise less than this limit + select :c_max_context_var_cnt - sum(c) + from ( + select count(*) c + from settings s + where s.working_mode in( + 'COMMON', + rdb$get_context('USER_SESSION','WORKING_MODE') + ) + union all + select count(*) from optypes -- look at fn_oper_xxx stored funcs + union all + select count(*) from doc_states -- look at fn_doc_xxx_state stored funcs + union all + select count(*) from rules_for_qdistr -- look at sp_cache_rules_for_distr('QDISTR') + union all + select count(*) from rules_for_pdistr -- look at sp_cache_rules_for_distr('PDISTR') + ) + into v_ctx_lim; + -- Get number of ROWS from tmp$perf_log to start flush data after reaching it: + -- "0.8*" - to be sure that we won`t reach limit; + -- "/12" - number of context vars for each record of tmp$perf_log (see below) + v_ctx_lim = cast( (0.8 * v_ctx_lim) / 12.0 as smallint); + rdb$set_context('USER_SESSION', 'CTX_LIMIT_FOR_FLUSH_PERF_LOG', v_ctx_lim); + end + + c_gen_inc_step_pf = v_ctx_lim; -- value to increment IDs in PERF_LOG at one call of gen_id + v_gen_inc_iter_pf = c_gen_inc_step_pf; + + -- Perform `transfer` from tmp$perf_log to 'fixed' perf_log table + -- in auton. tx, saving fields data in context vars: + v_cnt = 0; + v_dts = 'now'; + for + select + unit + ,coalesce( fb_gdscode, :a_gdscode, :c_std_user_exc ) as fb_gdscode + ,info + ,exc_unit -- '#' ==> exception occured in the module with name = tmp$perf_log.unit + ,iif( exc_unit is not null, coalesce( exc_info, :a_exc_info), null ) as exc_info -- fill exc_info only for unit where exc`eption really occured (NOT for unit that calls this 'problem' unit) + ,dts_beg + ,coalesce(dts_end, :v_dts) as dts_end + ,iif(unit = :a_unit, coalesce(aux1, :a_aux1), aux1) as aux1 + ,iif(unit = :a_unit, coalesce(aux2, :a_aux2), aux2) as aux2 + from tmp$perf_log g + -- ::: NB ::: CORE-4483: "Changed data not visible in WHEN-section if exception occured inside SP that has been called from this code" + -- We have to save data from tmp$perf_log for ALL units that are now in it! + as cursor c + do + begin + if ( v_cnt < v_ctx_lim ) then + -- there is enough place in namespace to create new context vars + -- instead of starting auton. tx (performance!) + begin + v_info = coalesce(c.info, ''); + -- Some unit (e.g. ) could run several times and exc`eption could occured + -- in Nth call of that unit (N >= 2). We must add :a_info to v_info + -- *ONLY* if processed record in tmp$perf_log relates to that Nth call + -- of unit (where exc`ption occured). + -- Sample: sp_cancel_adding_invoice => create list of dependent + -- docs, lock all of them, and then for each of these docs (reserves): + -- sp_cancel_reserve => trigger doc_list_aiud => sp_kill_qstorno_ret_qs2qd + if (c.unit = a_unit + and + c.exc_unit is NOT null + ) then + v_info = left(v_info || trim(iif( v_info>'', '; ', '')) || coalesce(a_info,''), 255); + + if ( v_gen_inc_iter_pf = c_gen_inc_step_pf ) then -- its time to get another batch of IDs + begin + v_gen_inc_iter_pf = 1; + -- take subsequent bulk IDs at once (reduce lock-contention for GEN page) + v_gen_inc_last_pf = gen_id( g_perf_log, :c_gen_inc_step_pf ); + end + v_pf_new_id = v_gen_inc_last_pf - ( c_gen_inc_step_pf - v_gen_inc_iter_pf ); + v_gen_inc_iter_pf = v_gen_inc_iter_pf + 1; + + rdb$set_context('USER_SESSION', 'PERF_LOG_'|| :v_cnt ||'_ID', v_pf_new_id); -- 1 + rdb$set_context('USER_SESSION', 'PERF_LOG_'|| :v_cnt ||'_UNIT', c.unit); -- 2 + rdb$set_context('USER_SESSION', 'PERF_LOG_'|| :v_cnt ||'_GDS', c.fb_gdscode ); -- 3 + rdb$set_context('USER_SESSION', 'PERF_LOG_'|| :v_cnt ||'_INFO', v_info); -- 4 + rdb$set_context('USER_SESSION', 'PERF_LOG_'|| :v_cnt ||'_XUNI', c.exc_unit); -- 5 + rdb$set_context('USER_SESSION', 'PERF_LOG_'|| :v_cnt ||'_XNFO', c.exc_info); -- 6 + rdb$set_context('USER_SESSION', 'PERF_LOG_'|| :v_cnt ||'_BEG', c.dts_beg); -- 7 + rdb$set_context('USER_SESSION', 'PERF_LOG_'|| :v_cnt ||'_END', c.dts_end); -- 8 + rdb$set_context('USER_SESSION', 'PERF_LOG_'|| :v_cnt ||'_MS', datediff(millisecond from c.dts_beg to c.dts_end)); + rdb$set_context('USER_SESSION', 'PERF_LOG_'|| :v_cnt ||'_AUX1', c.aux1); -- 10 + rdb$set_context('USER_SESSION', 'PERF_LOG_'|| :v_cnt ||'_AUX2', c.aux2); -- 11 + v_cnt = v_cnt + 1; + end + else -- it's time to "flush" data from context vars to fixed table pref_log using auton tx + begin + -- namespace usage should be reduced ==> flush data from context vars + execute procedure sp_flush_tmpperf_in_auton_tx(a_starter, v_cnt, a_gdscode); + v_cnt = 0; + end + end -- cursor for all rows of tmp$perf_log + + if (v_cnt > 0) then + begin + -- flush (again!) to perf_log data from rest of context vars (v_cnt now can be >0 and < c_limit): + execute procedure sp_flush_tmpperf_in_auton_tx( a_starter, v_cnt, a_gdscode); + end + + -- create new ctx in order to prevent repeat of transfer on next-level stack: + rdb$set_context('USER_TRANSACTION', 'DONE_FLUSH_PERF_LOG_ON_ABEND','1'); + +end + +^ -- sp_flush_perf_log_on_abend + +-- STUBS for two SP, they will be defined later, need in s`p_add_to_perf_log (30.08.2014) +create or alter procedure srv_fill_mon(a_rowset bigint default null) returns(rows_added int) as +begin + suspend; +end + +^ -- srv_fill_mon (stub!) + +create or alter procedure srv_fill_tmp_mon( + a_rowset dm_idb, + a_ignore_system_tables smallint default 1, + a_unit dm_unit default null, + a_info dm_info default null, + a_gdscode int default null +) +returns( + rows_added int +) +as begin + suspend; +end + +^ -- srv_fill_tmp_mon (stub!) + +-------------------------------------------------------------------------------- + +create or alter procedure srv_log_mon_for_traced_units( + a_unit dm_unit, + a_gdscode integer default null, + a_info dm_info default null +) +as + declare v_rowset bigint; + declare v_dummy bigint; +begin + if ( + --rdb$get_context('SYSTEM','ENGINE_VERSION') starting with '3.' -- new mon counters were introduced only in 3.0! + --and fn_remote_process() containing 'IBExpert' + rdb$get_context('USER_SESSION', 'ENABLE_MON_QUERY') = 1 + and + rdb$get_context('USER_SESSION','TRACED_UNITS') containing ','||a_unit||',' -- this is call from some module which we want to analyze + ) then + begin + -- Gather all avaliable mon info about caller module: add pair of row sets + -- (for beg and end) and then calculate DIFFERENCES of mon. counters with + -- logging in tables `mon_log` and `mon_log_table_stats`. + -- NOT work in 2.5 due to bulk of deadlocks when intensive monitoring using + v_rowset = rdb$get_context('USER_SESSION','MON_ROWSET_'||a_unit); + if ( v_rowset is null ) then + begin + -- define context var which will identify rowset field + -- in mon_log and mon_log_table_stats: + -- (this value is ised after call app. unit): + v_rowset = gen_id(g_common,1); + rdb$set_context('USER_SESSION','MON_ROWSET_'||a_unit, v_rowset); + -- gather mon$ tables: add FIRST row to GTT tmp$mon_log, + -- all counters will be written as NEGATIVE values + in autonomous transaction do + select count(*) + from srv_fill_tmp_mon + ( + :v_rowset -- :a_rowset + ,1 -- :a_ignore_system_tables + ,:a_unit -- :a_unit + ) + into v_dummy; + end + else -- add second row to GTT, all counters will be written as POSITIVE values: + begin + rdb$set_context('USER_SESSION','MON_ROWSET_'||a_unit, null); + in autonomous transaction do -- NB: add in AT both when v_abend = true / false, otherwise records in tmp$mon$log_* remains when rollback (01.09.2014) + begin + select count(*) + from srv_fill_tmp_mon + (:v_rowset -- :a_rowset + ,1 -- :a_ignore_system_tables + ,:a_unit + ,:a_info + ,:a_gdscode + ) into v_dummy; + + -- TOTALLING mon counters for this unit: + -- insert into mon_log(...) + -- select sum(...) from tmp$mon_log t + -- where t.rowset = :a_rowset group by t.rowset + select count(*) from srv_fill_mon( :v_rowset ) + into v_dummy; + end + + end + + end -- engine = '3.x' and remote_process containing 'IBExpert' and ctx TRACED_UNITS containing ',,' + +end + +^ -- srv_log_mon_for_traced_units + +------------------------------------------------------------------------------- + +create or alter procedure sp_add_perf_log ( + a_is_unit_beginning dm_sign, + a_unit dm_unit, + a_gdscode integer default null, + a_info dm_info default null, + a_aux1 dm_aux default null, + a_aux2 dm_aux default null +) as + declare v_curr_tx bigint; + declare v_dts timestamp; + declare v_save_dts_beg timestamp; + declare v_save_dts_end timestamp; + declare v_save_gtt_cnt int; + declare v_id dm_idb; + declare v_unit dm_unit; + declare v_info dm_info; + declare c_gen_inc_step_pf int = 20; -- size of `batch` for get at once new IDs for perf_log (reduce lock-contention of gen page) + declare v_gen_inc_iter_pf int; -- increments from 1 up to c_gen_inc_step_pf and then restarts again from 1 + declare v_gen_inc_last_pf dm_idb; -- last got value after call gen_id (..., c_gen_inc_step_pf) + declare v_pf_new_id dm_idb; +begin + -- Registration of all STARTs and FINISHes (both normal and failed) + -- for all application SPs and some service units: + v_curr_tx = current_transaction; + v_dts = cast('now' as timestamp); + + -- Gather all avaliable mon info about caller module if its name belongs + -- to list specified in `TRACED_UNITS` context var: add pair of row sets + -- (for beg and end) and then calculate DIFFERENCES of mon. counters with + -- logging in tables `mon_log` and `mon_log_table_stats`. + execute procedure srv_log_mon_for_traced_units( a_unit, a_gdscode, a_info ); + + if ( not exists(select * from tmp$perf_log) ) then + begin + rdb$set_context('USER_SESSION','LOG_PERF_STARTED_BY', a_unit); + a_is_unit_beginning = 1; + end + + if ( a_is_unit_beginning = 1 ) then -- this is call from ENTRY of :a_unit + begin + insert into tmp$perf_log( + unit, + info, + ip, + trn_id, + dts_beg + ) + values( + :a_unit, + :a_info, + fn_remote_address(), + :v_curr_tx, + :v_dts + ); + -- save info about last started unit (which can raise exc): + rdb$set_context('USER_TRANSACTION','TPLOG_LAST_UNIT', a_unit); + rdb$set_context('USER_TRANSACTION','TPLOG_LAST_BEG', v_dts); + rdb$set_context('USER_TRANSACTION','TPLOG_LAST_INFO', v_info); + end + else -- a_is_unit_beginning = 0 ==> this is _NORMAL_ finish of :a_unit (i.e. w/o exception) + begin + update tmp$perf_log t set + info = left(coalesce( info, '' ) || coalesce( trim(iif( info>'', '; ', '') || :a_info), ''), 255), + dts_end = :v_dts, + -- dis 12.01.2015, not need more: id2 = gen_id(g_perf_log, 1), -- 4 debug! 28.09.2014 + elapsed_ms = datediff(millisecond from dts_beg to :v_dts), + aux1 = :a_aux1, + aux2 = :a_aux2 + where -- Bitmap Index "TMP$PERF_LOG_UNIT_TRN" Range Scan (full match) + t.unit = :a_unit + and t.trn_id = :v_curr_tx + and dts_end is NULL -- we are looking for record that was added at the BEG of this unit call + ; + + if ( a_unit = rdb$get_context('USER_SESSION','LOG_PERF_STARTED_BY') ) then + begin + v_gen_inc_iter_pf = c_gen_inc_step_pf; + + -- Finish of top-level unit (which start business op.): + -- MOVE *ALL* data currently stored in GTT tmp$perf_log to fixed table perf_log + + v_save_dts_beg = 'now'; -- for logging time and number of moved records + v_save_gtt_cnt = 0; + + for + select + unit + ,exc_unit + ,fb_gdscode + ,trn_id + ,att_id + ,elapsed_ms + ,info + ,exc_info + ,stack + ,ip + ,dts_beg + ,dts_end + ,aux1 + ,aux2 + from tmp$perf_log g + as cursor ct + do begin + if ( v_gen_inc_iter_pf = c_gen_inc_step_pf ) then -- its time to get another batch of IDs + begin + v_gen_inc_iter_pf = 1; + -- take subsequent bulk IDs at once (reduce lock-contention for GEN page) + v_gen_inc_last_pf = gen_id( g_perf_log, :c_gen_inc_step_pf ); + end + v_pf_new_id = v_gen_inc_last_pf - ( c_gen_inc_step_pf - v_gen_inc_iter_pf ); + v_gen_inc_iter_pf = v_gen_inc_iter_pf + 1; + + insert into perf_log( + id + ,unit, exc_unit + ,fb_gdscode, trn_id, att_id, elapsed_ms + ,info, exc_info, stack + ,ip, dts_beg, dts_end + ,aux1, aux2 + ) values ( + :v_pf_new_id + ,ct.unit, ct.exc_unit + ,ct.fb_gdscode, ct.trn_id, ct.att_id, ct.elapsed_ms + ,ct.info, ct.exc_info, ct.stack + ,ct.ip, ct.dts_beg, ct.dts_end + ,ct.aux1, ct.aux2 + ); + v_save_gtt_cnt = v_save_gtt_cnt + 1; + + delete from tmp$perf_log where current of ct; + end -- end of loop moving rows from GTT tmp$perf_log to fixed perf_log + + v_save_dts_end = 'now'; + + -- Add info about timing and num. of record (tmp$ --> fixed): + insert into perf_log( + id, + unit, info, dts_beg, dts_end, elapsed_ms, ip, aux1) + values( iif( :v_gen_inc_iter_pf < :c_gen_inc_step_pf, :v_pf_new_id+1, gen_id( g_perf_log, 1 ) ), + 't$perf-norm:'||:a_unit, + 'ok saved '||:v_save_gtt_cnt||' rows', + :v_save_dts_beg, + :v_save_dts_end, + datediff( millisecond from :v_save_dts_beg to :v_save_dts_end ), + fn_remote_address(), + :v_save_gtt_cnt + ); + end -- a_unit = rdb$get_context('USER_SESSION','LOG_PERF_STARTED_BY') + end -- a_is_unit_beginning = 0 +end + +^ -- sp_add_perf_log + +create or alter procedure sp_upd_in_perf_log( + a_unit dm_unit, + a_gdscode int default null, + a_info dm_info default null +) as +begin + -- need in case when we want to update info in just added row + -- (e.g. info about selected doc etc) + update tmp$perf_log t set + t.fb_gdscode = coalesce(t.fb_gdscode, :a_gdscode), + t.info = coalesce( t.info, '' ) || coalesce( trim(iif( t.info>'', '; ', '') || :a_info), '') + where + t.unit = :a_unit + and t.trn_id = current_transaction + and t.dts_end is NULL + and coalesce(t.info,'') NOT containing coalesce(trim(:a_info),''); +end + +^ -- sp_upd_in_perf_log + +-- stub, will be overwritten, see below: +create or alter procedure zdump4dbg( + a_doc_list_id bigint default null, + a_doc_data_id bigint default null, + a_ware_id bigint default null +) as begin + -- ::: NB ::: This SP is overwritten in script 'oltp_misc_debug.sql' which + -- is called ONLY if config parameter 'create_with_debug_objects' is set to 1. + -- Open oltpNN_config.*** file and change this parameter if you want this + -- proc and some other aux tables (named with "Z_" prefix) to be created. +end +^ -- zdump4dbg (STUB!) + +create or alter procedure sp_add_to_abend_log( + a_exc_info dm_info, + a_gdscode int default null, + a_info dm_info default null, + a_caller dm_unit default null, + a_halt_due_to_error smallint default 0 -- 1 ==> forcely extract FULL STACK ignoring settings, because of error + halt test +) as + declare v_last_unit dm_unit; + declare v_last_info dm_info; + declare v_last_beg timestamp; + declare v_last_end timestamp; +begin + -- SP for register info about e`xception occured in application module. + -- When each module starts, it call sp_add_to_perf_log and creates record in + -- perf_log table for this event. If some e`xception occurs in that module + -- than code jumps into when_any section with call of this SP. + -- Now we have to call sp_add_to_perf_log with special argument ('!abend!') + -- signalling that all data from GTT tmp$perf_log should be saved now via ATx. + if ( a_gdscode is NOT null and nullif(a_exc_info, '') is null ) then -- this is standard error + begin + select f.fb_mnemona + from fb_errors f + where f.fb_gdscode = :a_gdscode + into a_exc_info; + end + -- For displaying in ISQL session logs: + rdb$set_context('USER_SESSION','ADD_INFO', left( coalesce(a_exc_info, 'no-mnemona'), 255)); + + + v_last_unit = rdb$get_context('USER_TRANSACTION','TPLOG_LAST_UNIT'); + + if ( a_caller = v_last_unit ) then + begin + -- CORE-4483. "Changed data not visible in WHEN-section if exception + -- occured inside SP that has been called from this code" ==> last record + -- in tmp$perf_log that has been added in SP_ADD_PERF_LOG which has been + -- called at the START point of this SP CALLER, will be backed out (REMOVED!) + -- when exception occurs later in the intermediate point of caller, so + -- HERE we get tmp$perf_log WITHOUT last record! + -- 10.01.2015: replaced 'update' with 'update or insert': record in + -- tmp$perf_log can be 'lost' in case of exc in caller before we come + -- in this SP (sp_cancel_client_order => sp_lock_selected_doc). + v_last_beg = rdb$get_context('USER_TRANSACTION','TPLOG_LAST_BEG'); + v_last_end = cast('now' as timestamp); + v_last_info = rdb$get_context('USER_TRANSACTION','TPLOG_LAST_INFO'); + + update tmp$perf_log t + set + fb_gdscode = :a_gdscode, + info = :a_info, -- coalesce( :v_last_info, ''), + exc_unit = '#', -- exc_unit: direct CALLER of this SP is the SOURCE of raised exception + dts_end = :v_last_end, + elapsed_ms = datediff(millisecond from :v_last_beg to :v_last_end) + where + t.unit = rdb$get_context('USER_TRANSACTION','TPLOG_LAST_UNIT') + and t.trn_id = current_transaction + and dts_end is NULL; -- index key: UNIT,TRN_ID,DTS_END + + if ( row_count = 0 ) then + insert into tmp$perf_log( + unit + ,fb_gdscode + ,info + ,exc_unit + ,dts_beg + ,dts_end + ,elapsed_ms + ,trn_id + ) values ( + :a_caller + ,:a_gdscode + ,:a_info --- coalesce( :v_last_info, '') + ,'#' -- ==> module :a_caller IS the source of raised exception + ,:v_last_beg + ,:v_last_end + ,datediff(millisecond from :v_last_beg to :v_last_end) + ,current_transaction + ); + + -- before 10.01.2015: + -- update tmp$perf_log set ... where t.unit = :a_caller and and t.trn_id = current_transaction and dts_end is NULL; + rdb$set_context('USER_TRANSACTION','TPLOG_LAST_UNIT', null); + + -- Save uncommitted data from tmp$perf_log to perf_log (via autonom. tx): + -- NB: All records in GTT tmp$perf_log are visible ONLY at the "deepest" point + -- when exc` occured. If SP_03 add records to tmp$perf_log and then raises exc + -- then all its callers (SP_00==>SP_01==>SP_02) will NOT see these record because + -- these changes will be rolled back when exc. comes into these caller. + -- So, we must flush records from GTT to fixed table only in the "deepest" point, + -- i.e. just in that SP where exc raises. + execute procedure sp_flush_perf_log_on_abend( + rdb$get_context('USER_SESSION','LOG_PERF_STARTED_BY'), -- unit which start this job + a_caller, + a_gdscode, + a_info, -- info for analysis + a_exc_info -- info about user-defined or standard e`xception which occured now + ); + + end -- a_caller = v_last_unit + + -- ######################## H A L T T E S T ###################### + if ( a_halt_due_to_error = 1 ) then + begin + execute procedure sp_halt_on_error('1', a_gdscode); + if ( fn_halt_sign(a_gdscode)=1 ) then -- 27.07.2014 1003 + begin + execute procedure zdump4dbg; + end + end + -- ##################################################################### + +end + +^ -- sp_add_to_abend_log + +set term ;^ + + +set term ^; + +create or alter procedure sp_check_ctx( + ctx_nmspace_01 dm_ctxns, + ctx_varname_01 dm_ctxnv, + ctx_nmspace_02 dm_ctxns = '', + ctx_varname_02 dm_ctxnv = '', + ctx_nmspace_03 dm_ctxns = '', + ctx_varname_03 dm_ctxnv = '', + ctx_nmspace_04 dm_ctxns = '', + ctx_varname_04 dm_ctxnv = '', + ctx_nmspace_05 dm_ctxns = '', + ctx_varname_05 dm_ctxnv = '', + ctx_nmspace_06 dm_ctxns = '', + ctx_varname_06 dm_ctxnv = '', + ctx_nmspace_07 dm_ctxns = '', + ctx_varname_07 dm_ctxnv = '', + ctx_nmspace_08 dm_ctxns = '', + ctx_varname_08 dm_ctxnv = '', + ctx_nmspace_09 dm_ctxns = '', + ctx_varname_09 dm_ctxnv = '', + ctx_nmspace_10 dm_ctxns = '', + ctx_varname_10 dm_ctxnv = '' +) +as + declare msg varchar(512) = ''; +begin + -- Check for each non-empty pair that corresponding context variable + -- EXISTS in it's namespace. Raises exception and pass to it list of pairs + -- which does not exists. + + if (ctx_nmspace_01>'' and rdb$get_context( upper(ctx_nmspace_01), upper(ctx_varname_01) ) is null ) then + msg = msg||upper(ctx_nmspace_01)||':'||coalesce(upper(ctx_varname_01),'''null'''); + + if (ctx_nmspace_02>'' and rdb$get_context( upper(ctx_nmspace_02), upper(ctx_varname_02) ) is null ) then + msg = msg||iif(msg='', '', '; ')||upper(ctx_nmspace_02)||':'||coalesce(upper(ctx_varname_02),'''null'''); + + if (ctx_nmspace_03>'' and rdb$get_context( upper(ctx_nmspace_03), upper(ctx_varname_03) ) is null ) then + msg = msg||iif(msg='', '', '; ')||upper(ctx_nmspace_03)||':'||coalesce(upper(ctx_varname_03),'''null'''); + + if (ctx_nmspace_04>'' and rdb$get_context( upper(ctx_nmspace_04), upper(ctx_varname_04) ) is null ) then + msg = msg||iif(msg='', '', '; ')||upper(ctx_nmspace_04)||':'||coalesce(upper(ctx_varname_04),'''null'''); + + if (ctx_nmspace_05>'' and rdb$get_context( upper(ctx_nmspace_05), upper(ctx_varname_05) ) is null ) then + msg = msg||iif(msg='', '', '; ')||upper(ctx_nmspace_05)||':'||coalesce(upper(ctx_varname_05),'''null'''); + + if (ctx_nmspace_06>'' and rdb$get_context( upper(ctx_nmspace_06), upper(ctx_varname_06) ) is null ) then + msg = msg||iif(msg='', '', '; ')||upper(ctx_nmspace_06)||':'||coalesce(upper(ctx_varname_06),'''null'''); + + if (ctx_nmspace_07>'' and rdb$get_context( upper(ctx_nmspace_07), upper(ctx_varname_07) ) is null ) then + msg = msg||iif(msg='', '', '; ')||upper(ctx_nmspace_07)||':'||coalesce(upper(ctx_varname_07),'''null'''); + + if (ctx_nmspace_08>'' and rdb$get_context( upper(ctx_nmspace_08), upper(ctx_varname_08) ) is null ) then + msg = msg||iif(msg='', '', '; ')||upper(ctx_nmspace_08)||':'||coalesce(upper(ctx_varname_08),'''null'''); + + if (ctx_nmspace_09>'' and rdb$get_context( upper(ctx_nmspace_09), upper(ctx_varname_09) ) is null ) then + msg = msg||iif(msg='', '', '; ')||upper(ctx_nmspace_09)||':'||coalesce(upper(ctx_varname_09),'''null'''); + + if (ctx_nmspace_10>'' and rdb$get_context( upper(ctx_nmspace_10), upper(ctx_varname_10) ) is null ) then + msg = msg||iif(msg='', '', '; ')||upper(ctx_nmspace_10)||':'||coalesce(upper(ctx_varname_10),'''null'''); + + if (msg<>'') then + begin + execute procedure sp_add_to_abend_log( left( msg, 255 ), null, '', 'sp_check_ctx' ); + exception ex_context_var_not_found using( msg ); + end +end -- sp_check_ctx + +^ +set term ;^ + + +set term ^; +create or alter procedure sp_check_nowait_or_timeout as + declare msg varchar(255); + declare function fn_internal() returns int deterministic as + begin + return rdb$get_context('SYSTEM', 'LOCK_TIMEOUT'); + end +begin + if ( fn_remote_process() containing 'IBExpert' ) then exit; -- 4debug + + -- Must be called from all SPs which are at 'top' level of data handling. + -- Checks that current Tx is running with NO WAIT or LOCK_TIMEOUT. + -- Otherwise raises error + if ( fn_internal() < 0 ) then -- better than call every time rdb$get_context('SYSTEM', 'LOCK_TIMEOUT') up to 4 times! + begin + msg = 'NO WAIT or LOCK_TIMEOUT required!'; + execute procedure sp_add_to_abend_log( msg, null, null, 'sp_check_nowait_or_timeout' ); + exception ex_nowait_or_timeout_required; + end +end +^ +set term ;^ + + +set term ^; + +create or alter procedure sp_check_to_stop_work as + declare v_dts_beg timestamp; + declare v_dts_end timestamp; + declare v_need_to_stop smallint; +begin + -- Must be called from all SPs which are at 'top' level of data handling. + -- Checks that special external *TEXT* file is EMPTY, otherwise raise exc. + -- Script tmp_random_run.sql (generated by 1run_oltp_emul.bat) contains + -- 'set bail on' before each call of application unit, so if here we raise + -- ex`ception EX_TEST_CANCELLATION than script tmp_random_run.sql will be + -- cancelledthis immediatelly. The word "EX_TEST_CANCELLATION" will appear + -- in .err file - log of errors for each ISQL session. + -- Batch `oltp_isql_run_worker.bat` checks .err file for this word and if it + -- is found there - all the batch will be finished via "goto test_canc" + exit + + if ( fn_remote_process() containing 'IBExpert' ) then exit; -- 4debug; 23.07.2014 + + if ( rdb$get_context('USER_SESSION','PERF_WATCH_END') is null ) then + begin + -- this record is added in 1run_oltp_emul.bat before FIRST attach + -- will begin it's work: + -- PLAN (P ORDER PERF_LOG_DTS_BEG_DESC INDEX (PERF_LOG_UNIT)) + select p.dts_beg, p.dts_end + from perf_log p + where p.unit = 'perf_watch_interval' and p.info containing 'active' + order by dts_beg + 0 desc -- !! 24.09.2014, speed !! (otherwise dozen fetches!) + rows 1 + into v_dts_beg, v_dts_end; + rdb$set_context('USER_SESSION','PERF_WATCH_BEG', v_dts_beg); + rdb$set_context('USER_SESSION','PERF_WATCH_END', coalesce(v_dts_end, dateadd(3 hour to current_timestamp) ) ); + end + else + begin + v_dts_end = rdb$get_context('USER_SESSION','PERF_WATCH_END'); + end + + v_need_to_stop = null; + select p.need_to_stop from sp_stoptest p rows 1 into v_need_to_stop; + + if ( cast('now' as timestamp) > v_dts_end -- NORMAL finish because of test_time expiration + or + v_need_to_stop < 0 -- External force all ISQL sessions PREMATURE be stopped itself (either by running $tmpdir/1stoptest.tmp batch or by adding line to 'stoptest.txt') + ) + then + begin + execute procedure sp_halt_on_error('2', -1, current_transaction, :v_need_to_stop); + exception ex_test_cancellation; -- E X C E P T I O N: C A N C E L T E S T + end +end + +^ -- sp_check_to_stop_work + +create or alter procedure sp_init_ctx +as + declare v_name type of dm_name; + declare v_context type of column settings.context; + declare v_value type of dm_setting_value; + declare v_counter int = 0; + declare msg varchar(255); +begin + -- Called from db-level trigger on CONNECT. Reads table 'settings' and + -- assigns values to context variables (in order to avoid further DB scans). + + -- ::: NOTE ABOUT POSSIBLE PROBLEM WHEN CONNECT TO DATABASE ::: + -- On Classic installed on *nix one may get exception on connect to database + -- with following text: + -- Statement failed, SQLSTATE = 2F000 + -- Error while parsing procedure SP_INIT_CTX's BLR + -- -Error while parsing procedure SP_ADD_TO_ABEND_LOG's BLR + -- -Error while parsing procedure SP_FLUSH_PERF_LOG_ON_ABEND's BLR + -- -I/O error during "open O_CREAT" operation for file "" + -- -Error while trying to create file + -- This exception is caused by TRG_CONNECT trigger on database connect event. + -- When this trigger calls SP_INIT_CTX, which then can attempt to add data + -- into GTT table TMP$PERF_LOG. File which must store data for this GTT + -- is created in the folder defined by FIREBIRD_TMP env. variable. + -- Exception will occur when this folder is undefined xinetd daemon has + -- no rights to create files in it. + -- SOLUTION: check script /etc/init.d/xinetd - it should contain text like: + -- ######### + -- FIREBIRD_TMP = /tmp/firebird + -- export FIREBIRD_TMP, ... + + if (rdb$get_context('USER_SESSION','WORKING_MODE') is null) then + begin + rdb$set_context( + 'USER_SESSION', + 'WORKING_MODE', + (select s.svalue + from settings s + where s.working_mode = 'INIT' and s.mcode = 'WORKING_MODE') + ); + end + + if ( rdb$get_context('USER_SESSION','WORKING_MODE') is not null + and + exists (select * from settings s + where s.working_mode = rdb$get_context('USER_SESSION','WORKING_MODE') + ) + ) then + begin + -- initializes all needed context variables (scan `setting` table) + for + select upper(s.mcode), upper(s.context), s.svalue + from settings s + where s.context in('USER_SESSION','USER_TRANSACTION') + and + ( s.working_mode = rdb$get_context('USER_SESSION','WORKING_MODE') + and s.init_on = 'connect' -- 03.09.2014: exclude 'C_NUMBER_OF_AGENTS', 'C_WARES_MAX_ID' - need only in init db building + or + s.working_mode = 'COMMON' + ) + into + v_name, v_context, v_value + do begin + rdb$set_context(v_context, v_name, v_value); + v_counter = v_counter + 1; + end + end + if (v_counter = 0 and exists (select * from settings s) ) then + begin + msg = 'Context variable ''WORKING_MODE'' is invalid.'; + execute procedure sp_add_to_abend_log( msg, null, null, 'sp_init_ctx' ); + exception ex_bad_working_mode_value + using ( coalesce( '>'||rdb$get_context('USER_SESSION','WORKING_MODE')||'<', '') ); + -- "-db-level trigger TRG_CONNECT: no found rows for settings.working_mode='>****<', correct it!" + end +end + +^ -- sp_init_ctx + +-- STUB! Redefinition see in file oltp_misc_debug.sql +create or alter procedure z_remember_view_usage ( + a_view_for_search dm_dbobj, + a_view_for_min_id dm_dbobj default null, + a_view_for_max_id dm_dbobj default null +) as + declare i smallint; + declare v_ctxn dm_ctxnv; + declare v_name dm_dbobj; +begin + +end + +^ -- z_remember_view_usage (STUB!)s + +create or alter procedure sp_get_random_id ( + a_view_for_search dm_dbobj, + a_view_for_min_id dm_dbobj default null, + a_view_for_max_id dm_dbobj default null, + a_raise_exc dm_sign default 1, -- raise exc`eption if no record will be found + a_can_skip_order_clause dm_sign default 0, -- 17.07.2014 (for some views where document is taken into processing and will be REMOVED from scope of this view after Tx is committed) + a_find_using_desc_index dm_sign default 0, -- 11.09.2014: if 1, then query will be: "where id <= :a order by id desc" + a_count_to_generate int default 1 -- 09.10.2015: how many values to generate and return as resultset (to reduce number of ES preparing) +) +returns ( + id_selected bigint +) +as + declare i smallint; + declare v_stt varchar(255); + declare id_min double precision; + declare id_max double precision; + declare v_rows int; + declare id_random bigint; + declare msg dm_info; + declare v_info dm_info; + declare v_this dm_dbobj = 'sp_get_random_id'; + declare v_ctxn dm_ctxnv; + declare v_name dm_dbobj; + declare fn_internal_max_rows_usage int; +begin + -- Selects random record from view + -- using select first 1 id from ... where id >= :id_random order by id. + -- Aux. parameters: + -- # a_view_for_min_id and a_view_for_max_id -- separate views that + -- might be more effective to find min & max LIMITS than scan using a_view_for_search. + -- # a_raise_exc (default=1) - do we raise exc`eption if record not found. + -- # a_can_skip_order_clause (default=0) - can we SKIP including of 'order by' clause + -- in statement which will be passed to ES ? (for some cases we CAN do it for efficiency) + -- # a_find_using_desc_index - do we construct ES for search using DESCENDING index + -- (==> it will use "where id <= :r order by id DESC" rather than "where id >= :r order by id ASC") + -- [only when TIL = RC] Repeats times if result is null + -- (possible if bounds of IDs has been changed since previous call) + + v_this = trim(a_view_for_search); + + -- max difference b`etween min_id and max_id to allow scan random id via + -- select id from rows :x to :y, where x = y = random_int + fn_internal_max_rows_usage = cast( rdb$get_context('USER_SESSION','RANDOM_SEEK_VIA_ROWS_LIMIT') as int); + + -- Use either stub or non-empty executing code (depends on was 'oltp_dump.sql' compiled or no): + -- save fact of usage views in the table `z_used_views`: + execute procedure z_remember_view_usage(a_view_for_search, a_view_for_min_id, a_view_for_max_id); + + a_view_for_min_id = coalesce( a_view_for_min_id, a_view_for_search ); + a_view_for_max_id = coalesce( a_view_for_max_id, a_view_for_min_id, a_view_for_search ); + + if ( rdb$get_context('USER_TRANSACTION', upper(:a_view_for_min_id)||'_ID_MIN' ) is null + or + rdb$get_context('USER_TRANSACTION', upper(:a_view_for_max_id)||'_ID_MAX' ) is null + ) then + begin + execute procedure sp_add_perf_log(1, a_view_for_min_id ); + -- v`iew z_get_min_max_id may be used to see average, min and max elapsed time + -- of this sttm: + v_stt='select min(id)-0.5 from '|| a_view_for_min_id; + execute statement (:v_stt) into id_min; -- do via ES in order to see statistics in the TRACE! + execute procedure sp_add_perf_log(0, a_view_for_min_id, null, 'id_min='||coalesce(id_min,'') ); + + if ( id_min is NOT null ) then -- ==> source is NOT empty + begin + + execute procedure sp_add_perf_log(1, a_view_for_max_id ); + -- v`iew z_get_min_max_id may be used to see average, min and max elapsed time + -- of this sttm: + v_stt='select max(id)+0.5 from '|| a_view_for_max_id; + execute statement (:v_stt) into id_max; -- do via ES in order to see statistics in the TRACE! + execute procedure sp_add_perf_log(0, a_view_for_max_id, null, 'id_max='||coalesce(id_max,'') ); + + if ( id_max is NOT null ) then -- ==> source is NOT empty + begin + -- Save values for subsequent calls of this func in this tx (minimize DB access) + -- (limit will never change in SNAPSHOT and can change with low probability in RC): + rdb$set_context('USER_TRANSACTION', upper(:a_view_for_min_id)||'_ID_MIN', :id_min); + rdb$set_context('USER_TRANSACTION', upper(:a_view_for_max_id)||'_ID_MAX', :id_max); + + if ( id_max - id_min < fn_internal_max_rows_usage ) then + begin + -- when difference b`etween id_min and id_max is not too high, we can simple count rows: + execute statement 'select count(*) from '||a_view_for_search into v_rows; + rdb$set_context('USER_TRANSACTION', upper(:a_view_for_search)||'_COUNT', v_rows ); + end + end -- id_max is NOT null + end -- id_min is NOT null + end + else begin + -- minimize database access! Performance on 10'000 loops: 1485 ==> 590 ms + id_min=cast( rdb$get_context('USER_TRANSACTION', upper(:a_view_for_min_id)||'_ID_MIN' ) as double precision); + id_max=cast( rdb$get_context('USER_TRANSACTION', upper(:a_view_for_max_id)||'_ID_MAX' ) as double precision); + v_rows=cast( rdb$get_context('USER_TRANSACTION', upper(:a_view_for_search)||'_COUNT') as int); + end + + if ( id_max - id_min < fn_internal_max_rows_usage ) then + begin + v_stt='select id from '||a_view_for_search||' rows :x to :y'; -- ::: nb ::: `ORDER` clause not needed here! + end + else + begin + -- 17.07.2014: for some cases it is ALLOWED to query random ID without "ORDER BY" + -- clause because this ID will be handled in such manner that it will be REMOVED + -- after this handling from the scope of view! Samples of such cases are: + -- sp_cancel_supplier_order, sp_cancel_supplier_invoice, sp_cancel_customer_reserve + v_stt='select id from ' + ||a_view_for_search + ||iif(a_find_using_desc_index = 0, ' where id >= :x', ' where id <= :x'); + if ( a_can_skip_order_clause = 0 ) then + v_stt = v_stt || iif(a_find_using_desc_index = 0, ' order by id ', ' order by id desc'); + v_stt = v_stt || ' rows 1'; + end + + i = a_count_to_generate; + while ( i > 0 ) do + begin + id_selected = null; + if ( id_max - id_min < fn_internal_max_rows_usage ) then + begin + id_random = ceiling( rand() * v_rows ); + execute statement (:v_stt) (x := id_random, y := id_random) into id_selected; + end + else + begin + id_random = cast( id_min + rand() * (id_max - id_min) as bigint); + execute statement (:v_stt) (x := id_random) into id_selected; + end + + if ( id_selected is null and coalesce(a_raise_exc, 1) = 1 ) then + begin + + v_info = 'view: '||:a_view_for_search; + if ( id_min is NOT null ) then + v_info = v_info || ', id_min=' || id_min || ', id_max='||id_max; + else + v_info = v_info || ' - EMPTY'; + + v_info = v_info ||', id_rnd='||coalesce(id_random,''); + + -- 'no id @1 @2 in @3 found within scope @4 ... @5'; -- @1 is '>=' or '<='; @2 = random_selected_value; @3 = data source; @4 = min; @5 = max + exception ex_can_not_select_random_id + using( + iif(a_find_using_desc_index = 0,'>=','<=') + ,coalesce(id_random,'') + ,a_view_for_search + ,coalesce(id_min,'') + ,coalesce(id_max,'') + ); + end + else + suspend; + + i = i - 1; + end + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + v_stt, + gdscode, + v_info, + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + +^ -- sp_get_random_id + +create or alter procedure sp_lock_selected_doc( + doc_list_id type of dm_idb, + a_view_for_search dm_dbobj, -- 'v_reserve_write_off', + a_selected_doc_id type of dm_idb default null +) as + declare v_dbkey dm_dbkey = null; + declare v_id dm_idb; + declare v_stt varchar(255); + declare v_exc_info dm_info; + declare v_info dm_info; + declare v_this dm_dbobj = 'sp_lock_selected_doc'; +begin + -- Seeks selected id in doc_list with checking existence + -- of this ID in a_view_for_search (if need). + -- Raises exc if not found, otherwise tries to lock ID in doc_list + + v_info = 'doc_id='||coalesce(doc_list_id, '')||', src='||a_view_for_search; + execute procedure sp_add_perf_log(1, v_this, null, v_info); + + v_stt = + 'select rdb$db_key from doc_list' + ||' where ' + ||' id = :x' + ||' and ( :y is null' -- ==> doc_list_id was defined via sp_get_random_id + ||' or' + ||' exists( select id from '||a_view_for_search||' v where v.id = :x )' + ||')'; + + execute statement (v_stt) ( x := :doc_list_id, y := :a_selected_doc_id ) into v_dbkey; + + if ( v_dbkey is null ) then + begin + -- no document found for handling in datasource = ''@1'' with id=@2'; + exception ex_no_doc_found_for_handling using( a_view_for_search, :doc_list_id ); + end + rdb$set_context('USER_SESSION','ADD_INFO','doc='||v_id||': try to lock'); -- to be displayed in log of 1run_oltp_emul.bat + + select id from doc_list h + where h.rdb$db_key = :v_dbkey + for update with lock + into v_id; -- trace rows: deadlock; update conflicts with conc.; 335544878 conc tran number is ...; at proc + rdb$set_context('USER_SESSION','ADD_INFO','doc='||v_id||': captured Ok'); -- to be displayed in log of 1run_oltp_emul.bat + + execute procedure sp_add_perf_log(0, v_this); + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( '', gdscode, v_info, v_this ); + --######## + exception; -- all number of retries exceeded: raise concurrent_transaction OR deadlock + --######## + end +end + +^ -- sp_lock_selected_doc + +create or alter procedure sp_cache_rules_for_distr( a_table dm_dbobj ) +returns( + mode dm_name, + snd_optype_id bigint, + rcv_optype_id bigint, + rows_to_multiply int +) +as + declare v_ctx_prefix type of dm_ctxnv; + declare v_stt varchar(255); + declare i int; + declare v_mode dm_name; + declare v_snd_optype_id type of dm_idb; + declare v_rcv_optype_id type of dm_idb; + declare v_rows_to_multiply int; +begin + if ( upper(coalesce(a_table,'')) not in ( upper('QDISTR'), upper('PDISTR') ) ) + then + exception ex_bad_argument using( coalesce(a_table,''), 'sp_cache_rules_for_distr' ); -- 'argument @1 passed to unit @2 is invalid'; + + -- cache records from rules_for_Qdistr and rules_for_Pdistr in context variables + -- for fast output of them (without database access) + + v_ctx_prefix = 'MEM_TABLE_'||upper(a_table)||'_'; -- 'MEM_TABLE_QDISTR' or 'MEM_TABLE_PDISTR' + v_stt='select mode, snd_optype_id, rcv_optype_id' || iif( upper(a_table)=upper('QDISTR'),', storno_sub',', rows_to_multiply ' ) + ||' from rules_for_'||a_table; + if ( rdb$get_context('USER_SESSION', v_ctx_prefix||'CNT') is null ) then + begin + i = 1; + for + execute statement( v_stt ) + into v_mode, v_snd_optype_id, v_rcv_optype_id, v_rows_to_multiply + do begin + rdb$set_context( + 'USER_SESSION' + ,v_ctx_prefix||i + ,rpad( v_mode ,80,' ') + || coalesce( cast(v_snd_optype_id as char(18)), rpad('', 18,' ') ) + || coalesce( cast(v_rcv_optype_id as char(18)), rpad('', 18,' ') ) + || coalesce( cast(v_rows_to_multiply as char(10)), rpad('', 10,' ') ) + ); + rdb$set_context('USER_SESSION', v_ctx_prefix||'CNT', i); + i = i+1; + end + end + i = 1; + while ( i <= cast(rdb$get_context('USER_SESSION', v_ctx_prefix||'CNT') as int) ) + do begin + mode = trim( substring( rdb$get_context('USER_SESSION', v_ctx_prefix||i) from 1 for 80 ) ); + snd_optype_id = cast( nullif(trim(substring( rdb$get_context('USER_SESSION', v_ctx_prefix||i) from 81 for 18 )), '') as dm_idb); + rcv_optype_id = cast( nullif(trim(substring( rdb$get_context('USER_SESSION', v_ctx_prefix||i) from 99 for 18 )), '') as dm_idb); + rows_to_multiply = cast( nullif(trim(substring( rdb$get_context('USER_SESSION', v_ctx_prefix||i) from 117 for 10 )), '') as int); + suspend; + i = i+1; + end +end + +^ -- sp_cache_rules_for_distr + +create or alter procedure sp_rules_for_qdistr +returns( + mode dm_name, + snd_optype_id bigint, + rcv_optype_id bigint, + storno_sub smallint -- 28.07.2014 +) as +begin + for + select p.mode,p.snd_optype_id, p.rcv_optype_id, + p.rows_to_multiply -- 28.07.2014 + from sp_cache_rules_for_distr('QDISTR') p + into mode, snd_optype_id, rcv_optype_id, + storno_sub -- 28.07.2014 + do + suspend; +end + +^ -- sp_rules_for_qdistr + +create or alter procedure sp_rules_for_pdistr +returns( + snd_optype_id bigint, + rcv_optype_id bigint, + rows_to_multiply int +) +as +begin + for + select p.snd_optype_id, p.rcv_optype_id, p.rows_to_multiply + from sp_cache_rules_for_distr('PDISTR') p + into snd_optype_id, rcv_optype_id, rows_to_multiply + do + suspend; +end + +^ -- sp_rules_for_pdistr + +set term ;^ + + + +-- STUB, need for sp_multiply_rows_for_qdistr; will be redefined after (see below): +create or alter view v_our_firm as select 1 id from rdb$database +; + +-- Views for usage in procedure s~p_multiply_rows_for_qdistr. +-- Their definition will be REPLACED with 'select * from XQD_1000_1200' and +-- 'select * from XQD_1000_3300' if config 'create_with_split_heavy_tabs' = 1 + +create or alter view v_qdistr_multiply_1 as +select * from qdistr +; + +create or alter view v_qdistr_multiply_2 as +select * from qdistr +; + +-- 07.09.2015: probe to replace ES in all cases of fn_get_rand_id: +create or alter view name$to$substutite$min$id$ as select 1 id from rdb$database; +create or alter view name$to$substutite$max$id$ as select 1 id from rdb$database; +create or alter view name$to$substutite$search$ as select 1 id from rdb$database; + +-- Updatable views (one-to-one data projections) for handling rows in heavy loaded +-- tables QDistr/QStorned (or in XQD_*, XQS_* when config par. create_with_split_heavy_tabs = 1): +-- See usage in SP_KILL_QSTORNO_RET_QS2QD and also in redirection procedures that +-- can be replaced when 'create_with_split_heavy_tabs=1': +-- sp_ret_qs2qd_on_canc_wroff, sp_ret_qs2qd_on_canc_reserve, +-- sp_ret_qs2qd_on_canc_invoice, sp_ret_qs2qd_on_canc_supp_order + +create or alter view v_qdistr_source_1 as +select * +from qdistr +; + +create or alter view v_qdistr_source_2 as +select * +from qdistr +; + +create or alter view v_qdistr_target_1 as +select * +from qdistr +; + +create or alter view v_qdistr_target_2 as +select * +from qdistr +; + +create or alter view v_qstorned_target_1 as +select * +from qstorned +; + +create or alter view v_qstorned_target_2 as +select * +from qstorned +; + +create or alter view v_qdistr_name_for_del as +select * +from qdistr +; + +create or alter view v_qdistr_name_for_ins as +select * +from qdistr +; + +create or alter view v_qstorno_name_for_del as +select * +from qstorned +; + +create or alter view v_qstorno_name_for_ins as +select * +from qstorned +; + + + +set term ^; +create or alter procedure sp_multiply_rows_for_qdistr( + a_doc_list_id dm_idb, + a_optype_id dm_idb, + a_clo_for_our_firm dm_idb, + a_qty_sum dm_qty +) as + declare c_gen_inc_step_qd int = 100; -- size of `batch` for get at once new IDs for QDistr (reduce lock-contention of gen page) + declare v_gen_inc_iter_qd int; -- increments from 1 up to c_gen_inc_step_qd and then restarts again from 1 + declare v_gen_inc_last_qd dm_idb; -- last got value after call gen_id (..., c_gen_inc_step_qd) + declare v_doc_data_id dm_idb; + declare v_ware_id dm_idb; + declare v_qty_for_distr dm_qty; + declare v_purchase_for_distr type of dm_cost; + declare v_retail_for_distr type of dm_cost; + declare v_rcv_optype_id type of dm_idb; + declare n_rows_to_add int; + declare v_qty_for_one_row type of dm_qty; + declare v_qty_acc type of dm_qty; + declare v_purchase_acc type of dm_cost; + declare v_retail_acc type of dm_cost; + declare v_dbkey dm_dbkey; + declare v_info dm_info; + declare v_this dm_dbobj = 'sp_multiply_rows_for_qdistr'; + declare v_storno_sub smallint; +begin + -- Performs "value-to-rows" filling of QDISTR table: add rows which + -- later will be "storned" (removed from qdistr to qstorned) + + v_info = 'dh='||a_doc_list_id||', q_sum='||a_qty_sum; + execute procedure sp_add_perf_log(1, v_this, null, v_info); + + v_gen_inc_iter_qd = 1; + c_gen_inc_step_qd = (1 + a_qty_sum) * iif(a_clo_for_our_firm=1, 1, 2) + 1; + -- take bulk IDs at once (reduce lock-contention for GEN page): + v_gen_inc_last_qd = gen_id( g_qdistr, :c_gen_inc_step_qd ); + + -- Cursor: how many distributions must be done for this doc if it is "sender" ? + -- =2 for customer order (if agent <> our firm!!): + -- it will be storned by stock order + -- and later by customer reserve + -- =1 for all other operations: + for + select r.rcv_optype_id, c.snd_id, c.id as ware_id, c.qty, c.cost_purchase, c.cost_retail, r.storno_sub + from rules_for_qdistr r + cross join tmp$shopping_cart c + where + r.snd_optype_id = :a_optype_id + and ( + :a_clo_for_our_firm = 0 + or + -- do NOT multiply rows for rcv_op = 'RES' if current doc = client order for OUR firm! + :a_clo_for_our_firm = 1 and r.rcv_optype_id <> 3300 -- fn_oper_retail_reserve() + ) + into v_rcv_optype_id, v_doc_data_id, v_ware_id, v_qty_for_distr, v_purchase_for_distr, v_retail_for_distr, v_storno_sub + do + begin + v_qty_acc = 0; + v_purchase_acc = 0; + v_retail_acc = 0; + n_rows_to_add = ceiling( v_qty_for_distr ); + while( n_rows_to_add > 0 ) do + begin + v_qty_for_one_row = iif( n_rows_to_add > v_qty_for_distr, n_rows_to_add - v_qty_for_distr, 1 ); + if ( v_storno_sub = 1 ) then + insert into v_qdistr_multiply_1 ( + id, + doc_id, + ware_id, + snd_optype_id, + rcv_optype_id, + snd_id, + snd_qty, + snd_purchase, + snd_retail) + values( + :v_gen_inc_last_qd - ( :c_gen_inc_step_qd - :v_gen_inc_iter_qd ), -- iter=1: 12345 - (100-1); iter=2: 12345 - (100-2); ...; iter=100: 12345 - (100-100) + :a_doc_list_id, + :v_ware_id, + :a_optype_id, + :v_rcv_optype_id, + :v_doc_data_id, + :v_qty_for_one_row, + :v_purchase_for_distr * :v_qty_for_one_row / :v_qty_for_distr, + :v_retail_for_distr * :v_qty_for_one_row / :v_qty_for_distr + ) + returning + rdb$db_key, + :v_qty_acc + snd_qty, + :v_purchase_acc + snd_purchase, + :v_retail_acc + snd_retail + into + v_dbkey, + :v_qty_acc, + :v_purchase_acc, + :v_retail_acc + ; + else + insert into v_qdistr_multiply_2 ( + id, + doc_id, + ware_id, + snd_optype_id, + rcv_optype_id, + snd_id, + snd_qty, + snd_purchase, + snd_retail) + values( + :v_gen_inc_last_qd - ( :c_gen_inc_step_qd - :v_gen_inc_iter_qd ), -- iter=1: 12345 - (100-1); iter=2: 12345 - (100-2); ...; iter=100: 12345 - (100-100) + :a_doc_list_id, + :v_ware_id, + :a_optype_id, + :v_rcv_optype_id, + :v_doc_data_id, + :v_qty_for_one_row, + :v_purchase_for_distr * :v_qty_for_one_row / :v_qty_for_distr, + :v_retail_for_distr * :v_qty_for_one_row / :v_qty_for_distr + ) + returning + rdb$db_key, + :v_qty_acc + snd_qty, + :v_purchase_acc + snd_purchase, + :v_retail_acc + snd_retail + into + v_dbkey, + :v_qty_acc, + :v_purchase_acc, + :v_retail_acc + ; + + n_rows_to_add = n_rows_to_add - 1; + v_gen_inc_iter_qd = v_gen_inc_iter_qd + 1; + + if ( n_rows_to_add = 0 and + ( v_qty_acc <> v_qty_for_distr + or v_purchase_acc <> v_purchase_for_distr + or v_retail_acc <> v_retail_for_distr + ) + ) then + if ( v_storno_sub = 1 ) then + update v_qdistr_multiply_1 q set + q.snd_qty = q.snd_qty + ( :v_qty_for_distr - :v_qty_acc ), + q.snd_purchase = q.snd_purchase + ( :v_purchase_for_distr - :v_purchase_acc ), + q.snd_retail = q.snd_retail + ( :v_retail_for_distr - :v_retail_acc ) + where q.rdb$db_key = :v_dbkey; + else + update v_qdistr_multiply_2 q set + q.snd_qty = q.snd_qty + ( :v_qty_for_distr - :v_qty_acc ), + q.snd_purchase = q.snd_purchase + ( :v_purchase_for_distr - :v_purchase_acc ), + q.snd_retail = q.snd_retail + ( :v_retail_for_distr - :v_retail_acc ) + where q.rdb$db_key = :v_dbkey; + else + if ( v_gen_inc_iter_qd = c_gen_inc_step_qd ) then -- its time to get another batch of IDs + begin + v_gen_inc_iter_qd = 1; + -- take subsequent bulk IDs at once (reduce lock-contention for GEN page) + v_gen_inc_last_qd = gen_id( g_qdistr, :c_gen_inc_step_qd ); + end + end -- while( n_rows_to_add > 0 ) + end -- cursor on doc_data cross join rules_for_qdistr + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this); + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + v_info, + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + +^ -- sp_multiply_rows_for_qdistr + +create or alter procedure sp_multiply_rows_for_pdistr( + a_doc_list_id dm_idb, + a_agent_id dm_idb, + a_optype_id dm_idb, + a_cost_for_distr type of dm_cost +) as + declare v_rcv_optype_id type of dm_idb; + declare n_rows_to_add int; + declare v_dbkey dm_dbkey; + declare v_cost_acc type of dm_cost; + declare v_cost_for_one_row type of dm_cost; + declare v_cost_div int; + declare v_id dm_idb; + declare v_key type of dm_unit; + declare v_info dm_info; + declare v_this dm_dbobj = 'sp_multiply_rows_for_pdistr'; + declare function fn_internal_min_cost_4_split returns int deterministic as + begin + return cast(rdb$get_context('USER_SESSION', 'C_MIN_COST_TO_BE_SPLITTED' ) as int); + end +begin + -- Performs "cost-to-rows" filling of PDISTR table: add rows which + -- later will be "storned" (removed from pdistr to pstorned) + v_info = 'dh='||a_doc_list_id||', op='||a_optype_id||', $='||a_cost_for_distr; + execute procedure sp_add_perf_log(1, v_this, null, v_info); + + for + select r.rcv_optype_id, iif( :a_cost_for_distr < fn_internal_min_cost_4_split(), 1, r.rows_to_multiply ) + from sp_rules_for_pdistr r + where r.snd_optype_id = :a_optype_id + into v_rcv_optype_id, n_rows_to_add + do + begin + v_cost_acc = 0; + v_cost_div = round( a_cost_for_distr / n_rows_to_add, -2 ); -- round to handreds + while( v_cost_acc < a_cost_for_distr ) do + begin + v_cost_for_one_row = iif( a_cost_for_distr > v_cost_div, v_cost_div, a_cost_for_distr ); + + insert into pdistr( + agent_id, + snd_optype_id, + snd_id, + snd_cost, + rcv_optype_id + ) + values( + :a_agent_id, + :a_optype_id, + :a_doc_list_id, + :v_cost_for_one_row, + :v_rcv_optype_id + ) + returning + rdb$db_key, + :v_cost_acc + snd_cost + into + v_dbkey, + :v_cost_acc + ; + + if ( v_cost_acc > a_cost_for_distr ) then + update pdistr p set + p.snd_cost = p.snd_cost + ( :a_cost_for_distr - :v_cost_acc ) + where p.rdb$db_key = :v_dbkey; + end + end + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this); + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + v_info, + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end +end + +^ -- sp_multiply_rows_for_pdistr + +create or alter procedure sp_make_cost_storno( + a_doc_id dm_idb, -- sp_add_invoice_to_stock: invoice_id; sp_reserve_write_off: reserve_id + a_optype_id dm_idb, + a_agent_id dm_idb, + a_cost_diff dm_cost +) +as + declare v_pass smallint; + declare not_storned_cost type of dm_cost; + declare v_storned_cost type of dm_cost; + declare v_storned_acc type of dm_cost; + declare v_storned_doc_optype_id type of dm_idb; + declare v_this dm_dbobj = 'sp_make_cost_storno'; + declare v_rows int = 0; + declare v_lock int = 0; + declare v_skip int = 0; + declare v_sign dm_sign; +begin + -- Performs attempt to make storno of: + -- 1) payment docs by cost of stock document which state is changed + -- to "closed"(sp_add_invoice_to_stock or sp_reserve_write_off) + -- 2) old stock documents when adding new payment (sp_pay_from_customer, sp_pay_to_supplier) + -- ::: nb ::: If record in "source" table (pdistr) can`t be locked - SKIP it + -- and try to lock next one (in order to reduce number of lock conflicts) + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(1, v_this); + + v_storned_acc = 0; + v_pass = 1; + v_sign = iif( bin_and(current_transaction, 1)=0, 1, -1); + + while ( v_pass <= 2 ) do + begin + select r.snd_optype_id -- iif( :v_pass=1, r.snd_optype_id, r.rcv_optype_id ) + from sp_rules_for_pdistr r + where iif( :v_pass = 1, r.rcv_optype_id, r.snd_optype_id ) = :a_optype_id + into v_storned_doc_optype_id; -- sp_add_invoice_to_stock ==> v_storned_doc_optype_id = fn_oper_pay_to_supplier() + + not_storned_cost = iif( v_pass=1, :a_cost_diff, v_storned_acc); + + if ( not_storned_cost <= 0 ) then leave; + + for + select + p.rdb$db_key as dbkey, + p.id, + p.agent_id, + p.snd_optype_id, + p.snd_id, + p.snd_cost as cost_to_be_storned, + p.rcv_optype_id, + :a_doc_id as rcv_id + from pdistr p + where p.agent_id = :a_agent_id and p.snd_optype_id = :v_storned_doc_optype_id + order by + p.snd_id+0 -- 23.07.2014: PLAN SORT (P INDEX (PDISTR_AGENT_ID) + ,:v_sign * p.id -- attempt to reduce lock conflicts: odd and even Tx handling the same doc must have a chance do not encounter locked rows at all + --order by p.id (wrong if new pdistr.id is generated via sequence when records returns from pstorned) + as cursor c + do + begin + v_rows = v_rows + 1; + + -- 26.10.2015. Additional begin..end block needs for providing DML + -- 'atomicity' of BOTH tables pdistr & pstorned! Otherwise changes + -- can become inconsistent if online validation will catch table-2 + -- after this code finish changes on table-1 but BEFORE it will + -- start to change table-2. + -- See CORE-4973 (example of WRONG code which did not used this addi block!) + begin + + -- Explicitly lock record; skip to next if it is already locked + -- (see below `when` section: supress all lock_conflict kind exc) + -- benchmark: sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1108762&msg=16393721 + update pdistr set id = id where current of c; -- faster than 'where rdb$db_key = ...' + + v_storned_cost = minvalue( :not_storned_cost, c.cost_to_be_storned ); + + -- move into `storage` table *PART* of prepayment that is now storned + -- by just created customer reserve: + -- :: nb :: pstorned PK = (id, rcv_id) - compound! + if ( v_pass = 1 ) then + begin + insert into pstorned( + agent_id, + snd_optype_id, + snd_id, + snd_cost, + rcv_optype_id, + rcv_id, + rcv_cost + ) + values( + c.agent_id, + c.snd_optype_id, + c.snd_id, + :v_storned_cost, -- s.cost_to_be_storned, + c.rcv_optype_id, + c.rcv_id, + :v_storned_cost + ); + end + + if ( c.cost_to_be_storned = v_storned_cost ) then + delete from pdistr p where current of c; + else + -- leave this record for futher storning (it has rest of cost > 0!): + update pdistr p set p.snd_cost = p.snd_cost - :v_storned_cost where current of c; + + not_storned_cost = not_storned_cost - v_storned_cost; + v_lock = v_lock + 1; + + if ( v_pass = 1 ) then + v_storned_acc = v_storned_acc + v_storned_cost; -- used in v_pass = 2 + + if ( not_storned_cost <= 0 ) then leave; + end -- atomicity of changes several tables (CORE-4973!) + when any do + -- ::: nb ::: do NOT use "wh`en gdscode " followed by "wh`en any": + -- the latter ("w`hen ANY") will handle ALWAYS, even if "w`hen " + -- catched it's kind of exception! + -- 1) tracker.firebirdsql.org/browse/CORE-3275 + -- "W`HEN ANY handles exceptions even if they are handled in another W`HEN section" + -- 2) sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1088890&msg=15879669 + begin + if ( fn_is_lock_trouble( gdscode ) ) then + -- suppress this exc! we'll skip to next row of pdistr + v_skip = v_skip + 1; + else -- some other ex`ception + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + + end -- cursor on pdistr + + v_pass = v_pass + 1; + end -- v_pass=1..2 + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log( + 0, + v_this, + null, + 'dh='||coalesce(:a_doc_id,'') + ||', pd ('||iif(:v_sign=1,'asc','dec')||'): capt='||:v_lock||', skip='||:v_skip||', scan='||:v_rows + ); + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + 'doc_id='||a_doc_id, + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end +end + +^ -- sp_make_cost_storno + +create or alter procedure sp_kill_cost_storno( a_deleted_or_cancelled_doc_id dm_idb ) as + declare agent_id dm_idb; + declare snd_optype_id dm_idb; + declare snd_id dm_idb; + declare storned_cost dm_cost; + declare rcv_optype_id dm_idb; + declare v_msg dm_info; + declare v_this dm_dbobj = 'sp_kill_cost_storno'; + declare cs cursor for ( + select + s.agent_id, + iif(:a_deleted_or_cancelled_doc_id = s.rcv_id, s.snd_optype_id, s.rcv_optype_id) as snd_optype_id, + iif(:a_deleted_or_cancelled_doc_id = s.rcv_id, s.snd_id, s.rcv_id) as snd_id, + iif(:a_deleted_or_cancelled_doc_id = s.rcv_id, s.rcv_cost, s.snd_cost) as storned_cost, + iif(:a_deleted_or_cancelled_doc_id = s.rcv_id, s.rcv_optype_id, s.snd_optype_id) as rcv_optype_id + from pstorned s + where + :a_deleted_or_cancelled_doc_id in (s.rcv_id, s.snd_id) + ); +begin + -- Called from trg D`OC_LIST_AIUD for operations: + -- 1) delete document which cost was storned before (e.g. payment to supplier / from customer) + -- 2) s`p_cancel_adding_invoice, s`p_cancel_write_off (i.e. REVERT state of doc) + -- :a_deleted_or_cancelled_doc_id = doc + -- 1) which is removed now + -- XOR + -- 2) which operation is cancelled now + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(1, v_this); + + open cs; + while (1=1) do + begin + fetch cs into agent_id, snd_optype_id, snd_id, storned_cost, rcv_optype_id; + if ( row_count = 0) then leave; + -- ::: nb ::: Revert sequence of these two commands if use `as cursor C`. + -- See CORE-4488 ("Cursor references are not variables, they're not cached + -- when reading. Instead, they represent the current state of the record") + + -- 04.08.2014: though no updates in statistics for 'select ... for update with lock' engine DOES them! + -- See benchmark and issue by dimitr: + -- sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1108762&msg=16394591 + delete from pstorned where current of cs; + -- insert using variables instead of cursor ref (CORE-4488): + insert into pdistr + ( agent_id, snd_optype_id, snd_id, snd_cost, rcv_optype_id ) + values( :agent_id, :snd_optype_id, :snd_id, :storned_cost, :rcv_optype_id ); + end + close cs; + + delete from pdistr p where p.snd_id = :a_deleted_or_cancelled_doc_id; + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this, null, 'doc_id='||a_deleted_or_cancelled_doc_id); + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + v_msg, + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + +^ -- sp_kill_cost_storno + +create or alter procedure srv_log_dups_qd_qs( -- needed only in 3.0, SuperCLASSIC, in sep...oct 2014 + a_unit dm_dbobj, + a_gdscode int, + a_inserting_table dm_dbobj, + a_inserting_id type of dm_idb, + a_inserting_info dm_info +) +as + declare v_curr_tx bigint; + declare v_get_stt varchar(512); + declare v_put_stt varchar(512); + declare v_doc_id dm_idb; + declare v_ware_id dm_idb; + declare v_snd_optype_id dm_idb; + declare v_snd_id dm_idb; + declare v_snd_qty dm_qty; + declare v_rcv_optype_id dm_idb; + declare v_rcv_id dm_idb; + declare v_rcv_qty dm_qty; + declare v_snd_purchase dm_cost; + declare v_snd_retail dm_cost; + declare v_rcv_purchase dm_cost; + declare v_rcv_retail dm_cost; + declare v_trn_id dm_idb; + declare v_dts timestamp; +begin + -- 09.10.2014, continuing trouble with PK violations in 3.0 SuperCLASSIC. + -- Add log info using auton Tx when PK violation occurs in QDistr or QStorned. + -- 08.01.2014: replace wrong algorithm that ignored invisible data for auton Tx + v_curr_tx = current_transaction; + v_get_stt = 'select doc_id, ware_id, snd_optype_id, snd_id, snd_qty,' + ||'rcv_optype_id, rcv_id, rcv_qty, snd_purchase, snd_retail,' + ||'rcv_purchase,rcv_retail,trn_id,dts' + ||' from '|| a_inserting_table ||' q' + ||' where q.id = :x'; + + v_put_stt = 'insert into ' + || iif( upper(a_inserting_table)=upper('QDISTR'), 'ZQdistr', 'ZQStorned' ) + ||'( id, doc_id, ware_id, snd_optype_id, snd_id, snd_qty,' + ||' rcv_optype_id, rcv_id, rcv_qty, snd_purchase, snd_retail,' + ||' rcv_purchase, rcv_retail, trn_id, dts, dump_att, dump_trn' + ||') values ' + ||'(:id,:doc_id,:ware_id,:snd_optype_id,:snd_id,:snd_qty,' + ||' :rcv_optype_id,:rcv_id,:rcv_qty,:snd_purchase,:snd_retail,' + ||' :rcv_purchase,:rcv_retail,:trn_id,:dts,:dump_att,:dump_trn' + ||')'; + + + execute statement (v_get_stt) ( x := a_inserting_id ) + into + v_doc_id, + v_ware_id, + v_snd_optype_id, + v_snd_id, + v_snd_qty, + v_rcv_optype_id, + v_rcv_id, + v_rcv_qty, + v_snd_purchase, + v_snd_retail, + v_rcv_purchase, + v_rcv_retail, + v_trn_id, + v_dts; + + in autonomous transaction do + begin + + insert into perf_log( unit, exc_unit, fb_gdscode, trn_id, info, stack ) + values ( :a_unit, 'U', :a_gdscode, :v_curr_tx, :a_inserting_info, fn_get_stack( 1 ) ); + + execute statement ( v_put_stt ) + ( + id := a_inserting_id, + doc_id := v_doc_id, + ware_id := v_ware_id, + snd_optype_id := v_snd_optype_id, + snd_id := v_snd_id, + snd_qty := v_snd_qty, + rcv_optype_id := v_rcv_optype_id, + rcv_id := v_rcv_id, + rcv_qty := v_rcv_qty, + snd_purchase := v_snd_purchase, + snd_retail := v_snd_retail, + rcv_purchase := v_rcv_purchase, + rcv_retail := v_rcv_retail, + trn_id := v_trn_id, + dts := v_dts, + dump_att := current_connection, + dump_trn := v_curr_tx + ); + + end -- in auton Tx +end + +^ -- srv_log_dups_qd_qs + +create or alter procedure sp_kill_qstorno_ret_qs2qd( + a_doc_id dm_idb, + a_old_optype dm_idb, + a_deleting_doc dm_sign, + a_aux_handling dm_sign default 0 +) +as + declare c_gen_inc_step_nt int = 100; -- size of `batch` for get at once new IDs for QDistr (reduce lock-contention of gen page) + declare v_gen_inc_iter_nt int; -- increments from 1 up to c_gen_inc_step_nt and then restarts again from 1 + declare v_gen_inc_last_nt dm_idb; -- last got value after call gen_id (..., c_gen_inc_step_nt) + declare v_this dm_dbobj = 'sp_kill_qstorno_ret_qs2qd'; + declare v_call dm_dbobj; + declare v_info dm_info; + declare v_suffix dm_info; + declare i int = 0; + declare k int = 0; + declare v_dd_id dm_idb; + declare v_id dm_idb; + declare v_doc_id dm_idb; + declare v_doc_optype dm_idb; + declare v_dd_ware_id dm_idb; + declare v_dd_qty dm_qty; + declare v_dd_cost dm_qty; + declare v_doc_pref dm_mcode; + declare v_snd_optype_id dm_idb; + declare v_snd_id dm_idb; + declare v_snd_qty dm_qty; + declare v_rcv_optype_id dm_idb; + declare v_rcv_id dm_idb; + declare v_rcv_qty dm_qty; + declare v_snd_purchase dm_cost; + declare v_snd_retail dm_cost; + declare v_rcv_purchase dm_cost; + declare v_rcv_retail dm_cost; + declare v_log_cursor dm_dbobj; -- 4debug only + declare v_ret_cursor dm_dbobj; -- 4debug only + declare v_oper_retail_realization dm_idb; + declare v_old_rcv_optype type of dm_idb; + + declare c_dd_rows_for_doc cursor for ( + -- used to immediatelly delete record in doc_data when document + -- is to be deleted (avoid scanning doc_data rows in FK-trigger again) + select d.id, d.ware_id, d.qty, d.cost_purchase + from doc_data d + where d.doc_id = :a_doc_id + ); + + declare c_qd_rows_for_doc cursor for ( + select id + from v_qdistr_name_for_del q -- this name will be replaced with 'autogen_qdNNNN' when config 'create_with_split_heavy_tabs=1' + where + q.ware_id = :v_dd_ware_id + and q.snd_optype_id = :a_old_optype + and q.rcv_optype_id = :v_old_rcv_optype + and q.snd_id = :v_dd_id + ); + + declare c_ret_qs2qd_by_rcv cursor for ( + select + qs.id + ,qs.doc_id + ,qs.snd_optype_id + ,qs.snd_id + ,qs.snd_qty + ,qs.rcv_optype_id + ,null as rcv_id + ,null as rcv_qty + ,qs.snd_purchase + ,qs.snd_retail + ,null as rcv_purchase + ,null as rcv_retail + from v_qstorno_name_for_del qs -- this name will be replaced with 'autogen_qdNNNN' when config 'create_with_split_heavy_tabs=1' + where qs.rcv_id = :v_dd_id -- for all cancel ops except sp_cancel_wroff + ); + + declare c_ret_qs2qd_by_snd cursor for ( + select + qs.id + ,qs.doc_id + ,qs.snd_optype_id + ,qs.snd_id + ,qs.snd_qty + ,qs.rcv_optype_id + ,null as rcv_id + ,null as rcv_qty + ,qs.snd_purchase + ,qs.snd_retail + ,null as rcv_purchase + ,null as rcv_retail + from v_qstorno_name_for_del qs -- this name will be replaced with 'autogen_qdNNNN' when config 'create_with_split_heavy_tabs=1' + where qs.snd_id = :v_dd_id -- for sp_cancel_wroff + ); +begin + -- Aux SP, called from sp_kill_qty_storno for + -- 1) sp_cancel_wroff (a_deleting = 0!) or + -- 2) all doc removals (sp_cancel_xxx, a_deleting = 1) + + v_call = v_this; + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(1, v_call,null); + + v_oper_retail_realization = fn_oper_retail_realization(); + v_doc_pref = fn_mcode_for_oper(a_old_optype); + + select r.rcv_optype_id + from rules_for_qdistr r + where + r.snd_optype_id = :a_old_optype + and coalesce(r.storno_sub,1) = 1 -- nb: old_op=2000 ==> storno_sub=NULL! + into v_old_rcv_optype; + + v_gen_inc_iter_nt = 1; + v_gen_inc_last_nt = gen_id( g_common, :c_gen_inc_step_nt );-- take bulk IDs at once (reduce lock-contention for GEN page) + + -- only for logging in perf_log.info name of handling cursor: + v_ret_cursor = iif(a_old_optype <> fn_oper_retail_realization(), 'c_ret_qs2qd_by_rcv', 'c_ret_qs2qd_by_snd'); + + -- return from QStorned to QDistr records which were previously moved + -- (when currently deleting doc was created). + -- Use explicitly declared cursor for immediate removing row from doc_data + -- when document is to be deleted: + open c_dd_rows_for_doc; + while (1=1) do + begin + fetch c_dd_rows_for_doc + into v_dd_id, v_dd_ware_id, v_dd_qty, v_dd_cost; + if ( row_count = 0 ) then leave; + + if ( a_deleting_doc = 1 and a_aux_handling = 0 ) then + begin + v_log_cursor = 'c_qd_rows_for_doc'; -- 4debug + open c_qd_rows_for_doc; + while (1=1) do + begin + fetch c_qd_rows_for_doc into v_id; + if ( row_count = 0 ) then leave; + i = i+1; -- total number of processed rows + delete from v_qdistr_name_for_del where current of c_qd_rows_for_doc; + end + close c_qd_rows_for_doc; + end + ---------------------------------------------------------- + if ( a_old_optype <> v_oper_retail_realization ) then + open c_ret_qs2qd_by_rcv; -- from qstorned qs where qs.RCV_id = :v_dd_id + else + open c_ret_qs2qd_by_snd; -- from qstorned where qs.SND_id = :v_dd_id + + v_log_cursor = v_ret_cursor; + while (1=1) do + begin + if ( a_old_optype <> v_oper_retail_realization ) then + fetch c_ret_qs2qd_by_rcv into + v_id + ,v_doc_id + ,v_snd_optype_id + ,v_snd_id + ,v_snd_qty + ,v_rcv_optype_id + ,v_rcv_id + ,v_rcv_qty + ,v_snd_purchase + ,v_snd_retail + ,v_rcv_purchase + ,v_rcv_retail; + else + fetch c_ret_qs2qd_by_snd into + v_id + ,v_doc_id + ,v_snd_optype_id + ,v_snd_id + ,v_snd_qty + ,v_rcv_optype_id + ,v_rcv_id + ,v_rcv_qty + ,v_snd_purchase + ,v_snd_retail + ,v_rcv_purchase + ,v_rcv_retail; + + if ( row_count = 0 ) then leave; + i = i+1; -- total number of processed rows + + v_suffix = ', id=' || :v_id || ', doc_id=' || :v_doc_id; + + -- debug info for logging in srv_log_dups_qd_qs if PK + -- violation will occur on INSERT INTO QDISTR statement + -- (remained for possible analysis): + v_call = v_this || ':try_del_qstorned'; + v_info = v_ret_cursor + || ': try DELETE in qStorned' + || ' where ' || iif(v_ret_cursor = 'c_ret_qs2qd_by_rcv', 'rcv_id =', 'snd_id =') || :v_dd_id + || v_suffix + ; + + -- We can try to delete record in QStorned *before* inserting + -- data in QDistr: all fields from cursor now are in variables. + -- ::: NB ::: (measurements 28.01-05.02.2015) + -- replacing qStorned with "unioned-view" based on N tables + -- and applying "where id = :a" leads to performance DEGRADATION + -- due to need to have index on ID field in each underlying table. + + -- execute procedure sp_add_perf_log(1, v_call, null, v_info, v_id); -- 10.02.2015, debug + -- rdb$set_context('USER_TRANSACTION','DBG_RETQS2QD_TRY_DEL_QSTORNO_ID', v_id); + + if ( a_old_optype <> v_oper_retail_realization ) then + delete from v_qstorno_name_for_del where current of c_ret_qs2qd_by_rcv; + else + delete from v_qstorno_name_for_del where current of c_ret_qs2qd_by_snd; + + --rdb$set_context('USER_TRANSACTION','DBG_RETQS2QD_OK_DEL_QSTORNO_ID', v_id); + --execute procedure sp_add_perf_log(0, v_call); + + -- debug info for logging in srv_log_dups_qd_qs if PK + -- violation will occur on INSERT INTO QDISTR statement + -- (remained for possible analysis): + v_info = v_ret_cursor || ': try INSERT in qDistr' || v_suffix; + v_call = v_this || ':try_ins_qdistr'; + + -- execute procedure sp_add_perf_log(1, v_call, null, v_info, v_id); -- 10.02.2015, debug + -- rdb$set_context('USER_TRANSACTION','DBG_RETQS2QD_TRY_INS_QDISTR_ID', v_id); + + insert into v_qdistr_name_for_ins( + id, + doc_id, + ware_id, + snd_optype_id, + snd_id, + snd_qty, + rcv_optype_id, + rcv_id, + rcv_qty, + snd_purchase, + snd_retail, + rcv_purchase, + rcv_retail + ) + values( + :v_id + ,:v_doc_id + ,:v_dd_ware_id + ,:v_snd_optype_id + ,:v_snd_id + ,:v_snd_qty + ,:v_rcv_optype_id + ,:v_rcv_id + ,:v_rcv_qty + ,:v_snd_purchase + ,:v_snd_retail + ,:v_rcv_purchase + ,:v_rcv_retail + ); + --rdb$set_context('USER_TRANSACTION','DBG_RETQS2QD_OK_INS_QDISTR_ID', v_id); + --execute procedure sp_add_perf_log(0, v_call); + + when any do + begin + if ( fn_is_uniqueness_trouble(gdscode) ) then + -- ############################################### + -- PK violation on INSERT INTO QDISTR, log this: + -- ############################################### + -- 12.02.2015: the reason of PK violations is unpredictable order + -- of UNDO, ultimately explained by dimitr, see letters in e-mail. + -- Also: sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1142271&msg=17257984 + execute procedure srv_log_dups_qd_qs( -- 09.10.2014: add log info using auton Tx + :v_call, + gdscode, + 'qdistr', + :v_id, + :v_info + ); + + exception; -- ::: nb ::: anonimous but in when-block! + end + + end -- cursor c_ret_qs2qd_by _rcv | _snd + + if ( a_old_optype <> v_oper_retail_realization ) then + close c_ret_qs2qd_by_rcv; + else + close c_ret_qs2qd_by_snd; + + -- 20.09.2014: move here from trigger on doc_list + -- (reduce scans of doc_data) + if ( a_aux_handling = 0 ) then + begin + insert into invnt_turnover_log( + id -- explicitly assign this field in order NOT to call gen_id in trigger (use v_gen_... counter instead) + ,ware_id + ,qty_diff + ,cost_diff + ,doc_list_id + ,doc_pref + ,doc_data_id + ,optype_id + ) values ( + :v_gen_inc_last_nt - ( :c_gen_inc_step_nt - :v_gen_inc_iter_nt ) + ,:v_dd_ware_id + ,-(:v_dd_qty) + ,-(:v_dd_cost) + ,:a_doc_id + ,:v_doc_pref + ,:v_dd_id + ,:a_old_optype + ); + + v_gen_inc_iter_nt = v_gen_inc_iter_nt + 1; + if ( v_gen_inc_iter_nt = c_gen_inc_step_nt ) then -- its time to get another batch of IDs + begin + v_gen_inc_iter_nt = 1; + -- take subsequent bulk IDs at once (reduce lock-contention for GEN page) + v_gen_inc_last_nt = gen_id( g_common, :c_gen_inc_step_nt ); + end + end + + if ( a_deleting_doc = 1 and a_aux_handling = 0 ) then + delete from doc_data where current of c_dd_rows_for_doc; + + end -- cursor on doc_data rows for a_doc_id + close c_dd_rows_for_doc; + + -- add to performance log timestamp about start/finish this unit: + v_info = + 'qs->qd: doc='||a_doc_id||', op='||a_old_optype + ||', ret_rows='||i + ||', cur='||v_ret_cursor + ; + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + v_call = v_this; + execute procedure sp_add_perf_log(0, v_call,null,v_info); + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + v_info, -- 'qs->qd, doc='||a_doc_id||': try ins qd.id='||coalesce(v_id,'')||', v_dd_id='||coalesce(v_dd_id,''), + v_call, -- ::: NB ::: do NOT use 'v_this' !! name of last started unit must be actual, see sp_add_to_abend_log! + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + +^ -- sp_kill_qstorno_ret_qs2qd + +create or alter procedure sp_ret_qs2qd_on_canc_wroff( + a_doc_id dm_idb, + a_old_optype dm_idb, + a_deleting_doc dm_sign, + a_aux_handling dm_sign default 0 +) +as +begin + -- This proc serves just as trivial 'redirector' when config parameter 'create_with_split_heavy_tabs = 0'. + -- Otherwise it will be OVERWRITTEN: its code will be replaced with one from sp_kill_qstorno_ret_qs2qd + -- and replacing of 'QDistr' and 'QStorned' sources with appropriate to current cancel operation. + + execute procedure sp_kill_qstorno_ret_qs2qd( :a_doc_id, :a_old_optype, :a_deleting_doc ); +end + +^ -- sp_ret_qs2qd_on_canc_wroff + +create or alter procedure sp_ret_qs2qd_on_canc_reserve( + a_doc_id dm_idb, + a_old_optype dm_idb, + a_deleting_doc dm_sign, + a_aux_handling dm_sign default 0 +) +as +begin + -- This proc serves just as trivial 'redirector' when config parameter 'create_with_split_heavy_tabs = 0'. + -- Otherwise it will be OVERWRITTEN: its code will be replaced with one from sp_kill_qstorno_ret_qs2qd + -- and replacing of 'QDistr' and 'QStorned' sources with appropriate to current cancel operation. + + execute procedure sp_kill_qstorno_ret_qs2qd( :a_doc_id, :a_old_optype, :a_deleting_doc ); +end + +^ -- sp_ret_qs2qd_on_canc_reserve + +create or alter procedure sp_ret_qs2qd_on_canc_res_aux( + a_doc_id dm_idb, + a_old_optype dm_idb, + a_deleting_doc dm_sign, + a_aux_handling dm_sign default 1 +) +as +begin + -- This proc remains EMPTY when config parameter 'create_with_split_heavy_tabs = 0'. + -- Otherwise it will be OVERWRITTEN: its code will be replaced with one from sp_kill_qstorno_ret_qs2qd + -- and replacing of 'QDistr' and 'QStorned' sources with autogen_qd1000 and autogen_qs1000. + exit; +end + +^ -- sp_ret_qs2qd_on_canc_res_aux + +create or alter procedure sp_ret_qs2qd_on_canc_invoice( + a_doc_id dm_idb, + a_old_optype dm_idb, + a_deleting_doc dm_sign, + a_aux_handling dm_sign default 0 +) +as +begin + -- This proc serves just as trivial 'redirector' when config parameter 'create_with_split_heavy_tabs = 0'. + -- Otherwise it will be OVERWRITTEN: its code will be replaced with one from sp_kill_qstorno_ret_qs2qd + -- and replacing of 'QDistr' and 'QStorned' sources with appropriate to current cancel operation. + + execute procedure sp_kill_qstorno_ret_qs2qd( :a_doc_id, :a_old_optype, :a_deleting_doc ); +end + +^ -- sp_ret_qs2qd_on_canc_invoice + +create or alter procedure sp_ret_qs2qd_on_canc_supp_order( + a_doc_id dm_idb, + a_old_optype dm_idb, + a_deleting_doc dm_sign, + a_aux_handling dm_sign default 0 +) +as +begin + -- This proc serves just as trivial 'redirector' when config parameter 'create_with_split_heavy_tabs = 0'. + -- Otherwise it will be OVERWRITTEN: its code will be replaced with one from sp_kill_qstorno_ret_qs2qd + -- and replacing of 'QDistr' and 'QStorned' sources with appropriate to current cancel operation. + + execute procedure sp_kill_qstorno_ret_qs2qd( :a_doc_id, :a_old_optype, :a_deleting_doc ); +end + +^ -- sp_ret_qs2qd_on_canc_supp_order + +create or alter procedure sp_qd_handle_on_reserve_upd_sts ( -- old name: s~p_kill_qstorno_mov_qd2qs( + a_doc_id dm_idb, + a_old_optype dm_idb, + a_new_optype dm_idb +) as + declare c_gen_inc_step_nt int = 100; -- size of `batch` for get at once new IDs for QDistr (reduce lock-contention of gen page) + declare v_gen_inc_iter_nt int; -- increments from 1 up to c_gen_inc_step_nt and then restarts again from 1 + declare v_gen_inc_last_nt dm_idb; -- last got value after call gen_id (..., c_gen_inc_step_nt) + + declare v_this dm_dbobj = 'sp_qd_handle_on_reserve_upd_sts'; + declare v_info dm_info; + declare v_curr_tx bigint; + declare i int = 0; + declare v_dd_id dm_idb; + declare v_dd_ware_id dm_qty; + declare v_dd_qty dm_qty; + declare v_dd_cost dm_qty; + declare v_doc_pref dm_mcode; + + declare v_old_rcv_optype type of dm_idb; + declare v_storno_sub smallint; + declare v_id dm_idb; + declare v_doc_id dm_idb; + declare v_doc_optype dm_idb; + declare v_ware_id dm_idb; + declare v_snd_optype_id dm_idb; + declare v_snd_id dm_idb; + declare v_snd_qty dm_qty; + declare v_rcv_optype_id dm_idb; + declare v_rcv_id dm_idb; + declare v_rcv_qty dm_qty; + declare v_snd_purchase dm_cost; + declare v_snd_retail dm_cost; + declare v_rcv_purchase dm_cost; + declare v_rcv_retail dm_cost; + + declare c_mov_from_qd2qs cursor for ( + -- rows which will be MOVED from qdistr to qstorned + select + qd.id + ,qd.doc_id + ,qd.ware_id + ,qd.snd_optype_id + ,qd.snd_id + ,qd.snd_qty + ,qd.rcv_optype_id + ,qd.rcv_id + ,qd.rcv_qty + ,qd.snd_purchase + ,qd.snd_retail + ,qd.rcv_purchase + ,qd.rcv_retail + from v_qdistr_name_for_del qd -- this name will be replaced when config parameter create_with_split_heavy_tabs = 1 + where + qd.ware_id = :v_dd_ware_id + and qd.snd_optype_id = :a_old_optype + and qd.rcv_optype_id = :v_old_rcv_optype + and qd.snd_id = :v_dd_id + ); + +begin + -- Aux SP, called from sp_kill_qty_storno ONLY for sp_reserve_write_off + -- (change state of customer reserve to 'waybill' when wares are written-off) + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(1, v_this); + + v_doc_pref = fn_mcode_for_oper(a_new_optype); + + v_gen_inc_iter_nt = 1; + v_gen_inc_last_nt = gen_id( g_common, :c_gen_inc_step_nt );-- take bulk IDs at once (reduce lock-contention for GEN page) + + -- return from QStorned to QDistr records which were previously moved + -- (when currently deleting doc was created): + for + select d.id, r.rcv_optype_id, r.storno_sub, d.ware_id, d.qty, d.cost_purchase + from doc_data d + cross join rules_for_qdistr r + where d.doc_id = :a_doc_id and r.snd_optype_id = :a_old_optype + into v_dd_id, v_old_rcv_optype, v_storno_sub, v_dd_ware_id, v_dd_qty, v_dd_cost + do + begin + if ( coalesce(v_storno_sub,1) = 1 ) then + begin + insert into invnt_turnover_log( + id -- explicitly assign this field in order NOT to call gen_id in trigger (use v_gen_... counter instead) + ,ware_id + ,qty_diff + ,cost_diff + ,doc_list_id + ,doc_pref + ,doc_data_id + ,optype_id + ) values ( + :v_gen_inc_last_nt - ( :c_gen_inc_step_nt - :v_gen_inc_iter_nt ) -- iter=1: 12345 - (100-1); iter=2: 12345 - (100-2); ...; iter=100: 12345 - (100-100) + ,:v_dd_ware_id + ,:v_dd_qty + ,:v_dd_cost + ,:a_doc_id + ,:v_doc_pref + ,:v_dd_id + ,:a_new_optype + ); + v_gen_inc_iter_nt = v_gen_inc_iter_nt + 1; + if ( v_gen_inc_iter_nt = c_gen_inc_step_nt ) then -- its time to get another batch of IDs + begin + v_gen_inc_iter_nt = 1; + -- take subsequent bulk IDs at once (reduce lock-contention for GEN page) + v_gen_inc_last_nt = gen_id( g_common, :c_gen_inc_step_nt ); + end + end + + open c_mov_from_qd2qs; -- from qstorned qs where qs.rcv_id = :v_dd_id + while (1=1) do + begin + fetch c_mov_from_qd2qs into + v_id + ,v_doc_id + ,v_ware_id + ,v_snd_optype_id + ,v_snd_id + ,v_snd_qty + ,v_rcv_optype_id + ,v_rcv_id + ,v_rcv_qty + ,v_snd_purchase + ,v_snd_retail + ,v_rcv_purchase + ,v_rcv_retail; + if ( row_count = 0 ) then leave; + i = i + 1; + -- moved here 16.09.2014: all cursor fields are stored now in variables + delete from v_qdistr_name_for_del where current of c_mov_from_qd2qs; + + -- for logging in autonom. Tx if PK violation occurs in subsequent sttmt: + v_info = 'qd->qs, c_mov_from_qd2qs: try ins qStorned.id='||:v_id; + + -- S P _ R E S E R V E _ W R I T E _ O F F + -- (FINAL point of ware turnover ==> remove data from qdistr in qstorned) + insert into v_qstorno_name_for_ins ( -- this name will be replaced when config parameter create_with_split_heavy_tabs = 1 + id, + doc_id, + ware_id, + snd_optype_id, + snd_id, + snd_qty, + rcv_optype_id, + rcv_id, + rcv_qty, + snd_purchase, + snd_retail, + rcv_purchase, + rcv_retail + ) + values( + :v_id, + :v_doc_id, + :v_ware_id, + :v_snd_optype_id, + :v_snd_id, + :v_snd_qty, + :v_rcv_optype_id, + :v_rcv_id, + :v_rcv_qty, + :v_snd_purchase, + :v_snd_retail, + :v_rcv_purchase, + :v_rcv_retail + ); + + when any do + begin + if ( fn_is_uniqueness_trouble(gdscode) ) then + -- temply, 09.10.2014 2120: resume investigate trouble with PK violation + execute procedure srv_log_dups_qd_qs( + :v_this, + gdscode, + 'qstorned', + :v_id, + :v_info + ); + exception; -- ::: nb ::: anonimous but in when-block! + end + + end -- cursor c_mov_from_qd2qs + + close c_mov_from_qd2qs; + end -- cursor on doc_data + + -- add to performance log timestamp about start/finish this unit: + v_info = 'qd->qs, doc='||a_doc_id||', rows='||i; + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this,null,v_info); + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + 'qs->qd, doc='||a_doc_id||': try ins qs.id='||coalesce(v_id,'')||', v_dd_id='||coalesce(v_dd_id,''||', old_op='||a_old_optype ), + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + +^ -- sp_qd_handle_on_reserve_upd_sts + +create or alter procedure sp_qd_handle_on_cancel_clo ( + a_doc_id dm_idb, + a_old_optype dm_idb, + a_new_optype dm_idb) +as + declare c_gen_inc_step_nt int = 100; -- size of `batch` for get at once new IDs for QDistr (reduce lock-contention of gen page) + declare v_gen_inc_iter_nt int; -- increments from 1 up to c_gen_inc_step_nt and then restarts again from 1 + declare v_gen_inc_last_nt dm_idb; -- last got value after call gen_id (..., c_gen_inc_step_nt) + declare v_this dm_dbobj = 'sp_qd_handle_on_cancel_clo'; + declare v_info dm_info; + declare v_id dm_idb; + declare v_snd_id dm_idb; + declare v_dd_rows int = 0; + declare v_dd_qsum int = 0; + declare v_del_sign dm_sign; + declare v_qd_rows int = 0; + declare v_qs_rows int = 0; + declare v_dd_id dm_idb; + declare v_dd_ware_id dm_qty; + declare v_dd_qty dm_qty; + declare v_dd_cost dm_qty; + declare v_doc_pref dm_mcode; + declare v_log_mult dm_sign; + declare v_log_oper dm_idb; + declare v_rcv_optype_id type of dm_idb; + declare v_storno_sub smallint; + + declare c_qd_rows_sub_1 cursor for ( + select q.id, q.snd_id + from v_qdistr_target_1 q -- this name will be replaced when config parameter create_with_split_heavy_tabs = 1 + where + q.ware_id = :v_dd_ware_id + and q.snd_optype_id = :a_old_optype + and q.rcv_optype_id = :v_rcv_optype_id + and q.snd_id = :v_dd_id + ); + declare c_qd_rows_sub_2 cursor for ( + select q.id, q.snd_id + from v_qdistr_target_2 q -- this name will be replaced when config parameter create_with_split_heavy_tabs = 1 + where + q.ware_id = :v_dd_ware_id + and q.snd_optype_id = :a_old_optype + and q.rcv_optype_id = :v_rcv_optype_id + and q.snd_id = :v_dd_id + ); + + declare c_qs_rows_sub_1 cursor for ( + select qs.id, qs.snd_id + from v_qstorned_target_1 qs -- this name will be replaced when config parameter create_with_split_heavy_tabs = 1 + where qs.snd_id = :v_dd_id + ); + declare c_qs_rows_sub_2 cursor for ( + select qs.id, qs.snd_id + from v_qstorned_target_2 qs -- this name will be replaced when config parameter create_with_split_heavy_tabs = 1 + where qs.snd_id = :v_dd_id + ); + +begin + + -- Aux SP, called from sp_kill_qty_storno ONLY for: + -- 1) sp_cancel_client_order; 2) sp_add_invoice_to_stock (apply and cancel) + + -- add to performance log timestamp about start/finish this unit: + v_info = iif( a_new_optype = fn_oper_cancel_customer_order(), 'DEL', 'UPD' ) + || ' in qdistr, doc='||a_doc_id + || ', old_op='||a_old_optype + || iif( a_new_optype <> fn_oper_cancel_customer_order(), ', new_op='||a_new_optype, ''); + execute procedure sp_add_perf_log(1, v_this, null, v_info); + + v_log_oper = iif( a_new_optype = fn_oper_invoice_get(), fn_oper_invoice_add(), a_new_optype); + v_log_mult = iif( a_new_optype = fn_oper_invoice_get(), -1, 1); + v_doc_pref = fn_mcode_for_oper(v_log_oper); + v_del_sign = 1; -- iif(a_new_optype = fn_oper_cancel_customer_order(), 1, 0); + + v_gen_inc_iter_nt = 1; + v_gen_inc_last_nt = gen_id( g_common, :c_gen_inc_step_nt );-- take bulk IDs at once (reduce lock-contention for GEN page) + + for + select r.rcv_optype_id, r.storno_sub + from rules_for_qdistr r + where r.snd_optype_id = :a_old_optype + --and coalesce(r.storno_sub,1) = 1 -- do NOT! old_op=1000 ==> two rows (storno_sub=1 and 2) - needs to be processed for sp_cancel_client_order + into v_rcv_optype_id, v_storno_sub + do + begin + for + select d.id, d.ware_id, d.qty, d.cost_purchase + from doc_data d + where d.doc_id = :a_doc_id + into v_dd_id, v_dd_ware_id, v_dd_qty, v_dd_cost + do + begin + v_dd_rows = v_dd_rows + 1; + v_dd_qsum = v_dd_qsum + v_dd_qty; + -- 20.09.2014: move here from trigger on doc_list + -- (reduce scans of doc_data) + if ( coalesce(v_storno_sub,1) = 1 ) then + begin + insert into invnt_turnover_log( + id -- explicitly specify this field in order NOT to call gen_id in trigger (use v_gen_... counter instead) + ,ware_id + ,qty_diff + ,cost_diff + ,doc_list_id + ,doc_pref + ,doc_data_id + ,optype_id + ) values ( + :v_gen_inc_last_nt - ( :c_gen_inc_step_nt - :v_gen_inc_iter_nt ) -- iter=1: 12345 - (100-1); iter=2: 12345 - (100-2); ...; iter=100: 12345 - (100-100) + ,:v_dd_ware_id + ,:v_log_mult * :v_dd_qty + ,:v_log_mult * :v_dd_cost + ,:a_doc_id + ,:v_doc_pref + ,:v_dd_id + ,:v_log_oper + ); + + v_gen_inc_iter_nt = v_gen_inc_iter_nt + 1; + if ( v_gen_inc_iter_nt = c_gen_inc_step_nt ) then -- its time to get another batch of IDs + begin + v_gen_inc_iter_nt = 1; + -- take subsequent bulk IDs at once (reduce lock-contention for GEN page) + v_gen_inc_last_nt = gen_id( g_common, :c_gen_inc_step_nt ); + end + end + + open c_qd_rows_sub_1; + while (1=1) do + begin + fetch c_qd_rows_sub_1 into v_id, v_snd_id; + if ( row_count = 0 ) then leave; + v_qd_rows = v_qd_rows + 1; + delete from v_qdistr_target_1 + where current of c_qd_rows_sub_1; + end + close c_qd_rows_sub_1; + + open c_qd_rows_sub_2; + while (1=1) do + begin + fetch c_qd_rows_sub_2 into v_id, v_snd_id; + if ( row_count = 0 ) then leave; + v_qd_rows = v_qd_rows + 1; + delete from v_qdistr_target_2 + where current of c_qd_rows_sub_2; + end + close c_qd_rows_sub_2; + + open c_qs_rows_sub_1; + while (1=1) do + begin + fetch c_qs_rows_sub_1 into v_id, v_snd_id; + if ( row_count = 0 ) then leave; + v_qs_rows = v_qs_rows+1; + delete from v_qstorned_target_1 + where current of c_qs_rows_sub_1; + end + close c_qs_rows_sub_1; + + open c_qs_rows_sub_2; + while (1=1) do + begin + fetch c_qs_rows_sub_2 into v_id, v_snd_id; + if ( row_count = 0 ) then leave; + v_qs_rows = v_qs_rows+1; + delete from v_qstorned_target_2 + where current of c_qs_rows_sub_2; + end + close c_qs_rows_sub_2; + + end + end + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this, null, 'dd_qsum='||v_dd_qsum||', rows: dd='||v_dd_rows||', qd='||v_qd_rows||', qs='||v_qs_rows ); + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + v_info, + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + +^ -- sp_qd_handle_on_cancel_clo + +create or alter procedure sp_qd_handle_on_invoice_upd_sts ( + a_doc_id dm_idb, + a_old_optype dm_idb, + a_new_optype dm_idb) +as + declare c_gen_inc_step_nt int = 100; -- size of `batch` for get at once new IDs for QDistr (reduce lock-contention of gen page) + declare v_gen_inc_iter_nt int; -- increments from 1 up to c_gen_inc_step_nt and then restarts again from 1 + declare v_gen_inc_last_nt dm_idb; -- last got value after call gen_id (..., c_gen_inc_step_nt) + declare v_this dm_dbobj = 'sp_qd_handle_on_invoice_upd_sts'; + declare v_info dm_info; + + declare v_qd_id dm_idb; + declare v_qd_doc_id dm_idb; + declare v_qd_ware_id dm_idb; + + declare v_qd_snd_id dm_idb; + declare v_qd_snd_qty dm_qty; + declare v_qd_rcv_doc_id bigint; + declare v_qd_rcv_optype_id bigint; + declare v_qd_rcv_id bigint; + declare v_qd_rcv_qty numeric(12,3); + declare v_qd_snd_purchase dm_cost; + declare v_qd_snd_retail dm_cost; + declare v_qd_rcv_purchase dm_cost; + declare v_qd_rcv_retail dm_cost; + + declare v_dd_rows int = 0; + declare v_dd_qsum int = 0; + + declare v_qd_rows int = 0; + declare v_dd_id dm_idb; + declare v_dd_ware_id dm_qty; + declare v_dd_qty dm_qty; + declare v_dd_cost dm_qty; + declare v_doc_pref dm_mcode; + declare v_log_mult dm_sign; + declare v_log_oper dm_idb; + declare v_rcv_optype_id type of dm_idb; + declare v_storno_sub smallint; + + declare c_qd_rows_for_doc cursor for ( + select --q.id, q.snd_id + id, + doc_id, + ware_id, + snd_id, + snd_qty, + rcv_doc_id, + rcv_optype_id, + rcv_id, + rcv_qty, + snd_purchase, + snd_retail, + rcv_purchase, + rcv_retail + from v_qdistr_name_for_del q -- name of this datasource will be replaced when config 'create_with_split_heavy_tabs=1' + where + q.ware_id = :v_dd_ware_id + and q.snd_optype_id = :a_old_optype + and q.rcv_optype_id = :v_rcv_optype_id + and q.snd_id = :v_dd_id + ); + +begin + + -- Aux SP, called from sp_kill_qty_storno ONLY for + -- sp_add_invoice_to_stock (apply and cancel) + -- ####################### + + -- Old name: s~p_kill_qstorno_handle_qd4dd + + -- add to performance log timestamp about start/finish this unit: + v_info = 'UPD in qdistr, doc='||a_doc_id + || ', old_op='||a_old_optype + || ', new_op='||a_new_optype; + execute procedure sp_add_perf_log(1, v_this, null, v_info); + + + v_log_oper = iif( a_new_optype = fn_oper_invoice_get(), fn_oper_invoice_add(), a_new_optype); + v_log_mult = iif( a_new_optype = fn_oper_invoice_get(), -1, 1); + v_doc_pref = fn_mcode_for_oper(v_log_oper); + + v_gen_inc_iter_nt = 1; + v_gen_inc_last_nt = gen_id( g_common, :c_gen_inc_step_nt ); -- take bulk IDs at once (reduce lock-contention for GEN page) + + for + select r.rcv_optype_id, r.storno_sub + from rules_for_qdistr r + where r.snd_optype_id = :a_old_optype + into v_rcv_optype_id, v_storno_sub -- 'v_rcv_optype_id' see in WHERE condition in c_qd_rows_for_doc + do + begin + for + select d.id, d.ware_id, d.qty, d.cost_purchase + from doc_data d + where d.doc_id = :a_doc_id + into v_dd_id, v_dd_ware_id, v_dd_qty, v_dd_cost + do + begin + v_dd_rows = v_dd_rows + 1; + v_dd_qsum = v_dd_qsum + v_dd_qty; + -- 20.09.2014: move here from trigger on doc_list + -- (reduce scans of doc_data) + if ( coalesce(v_storno_sub,1) = 1 ) then + begin + insert into invnt_turnover_log( + id -- explicitly specify this field in order NOT to call gen_id in trigger (use v_gen_... counter instead) + ,ware_id + ,qty_diff + ,cost_diff + ,doc_list_id + ,doc_pref + ,doc_data_id + ,optype_id + ) values ( + :v_gen_inc_last_nt - ( :c_gen_inc_step_nt - :v_gen_inc_iter_nt ) -- iter=1: 12345 - (100-1); iter=2: 12345 - (100-2); ...; iter=100: 12345 - (100-100) + ,:v_dd_ware_id + ,:v_log_mult * :v_dd_qty + ,:v_log_mult * :v_dd_cost + ,:a_doc_id + ,:v_doc_pref + ,:v_dd_id + ,:v_log_oper + ); + + v_gen_inc_iter_nt = v_gen_inc_iter_nt + 1; + if ( v_gen_inc_iter_nt = c_gen_inc_step_nt ) then -- its time to get another batch of IDs + begin + v_gen_inc_iter_nt = 1; + -- take subsequent bulk IDs at once (reduce lock-contention for GEN page) + v_gen_inc_last_nt = gen_id( g_common, :c_gen_inc_step_nt ); + end + end + + open c_qd_rows_for_doc; + while (1=1) do + begin + fetch c_qd_rows_for_doc + into -- v_qd_id, v_qd_snd_id; + v_qd_id + ,v_qd_doc_id + ,v_qd_ware_id + ,v_qd_snd_id + ,v_qd_snd_qty + ,v_qd_rcv_doc_id + ,v_qd_rcv_optype_id + ,v_qd_rcv_id + ,v_qd_rcv_qty + ,v_qd_snd_purchase + ,v_qd_snd_retail + ,v_qd_rcv_purchase + ,v_qd_rcv_retail; + if ( row_count = 0 ) then leave; + v_qd_rows = v_qd_rows+1; + + -- sp_add_invoice_to_stock: apply and cancel + -- ######################################### + + -- 31.08.2015: replaced 'update qdistr' to del_ins algorithm, + -- so this can be applied later for replacing to 'autogen_qdNNNN'. + + delete from v_qdistr_name_for_del where current of c_qd_rows_for_doc; -- name will be replaced when config 'create_with_split_heavy_tabs=1' + + insert into v_qdistr_name_for_ins( -- name will be replaced when config 'create_with_split_heavy_tabs=1' + id, + doc_id, + ware_id, + snd_optype_id, + snd_id, + snd_qty, + rcv_doc_id, + rcv_optype_id, + rcv_id, + rcv_qty, + snd_purchase, + snd_retail, + rcv_purchase, + rcv_retail + ) values( + :v_qd_id + ,:v_qd_doc_id + ,:v_qd_ware_id + ,:a_new_optype ----------- !! + ,:v_qd_snd_id + ,:v_qd_snd_qty + ,:v_qd_rcv_doc_id + ,:v_qd_rcv_optype_id + ,:v_qd_rcv_id + ,:v_qd_rcv_qty + ,:v_qd_snd_purchase + ,:v_qd_snd_retail + ,:v_qd_rcv_purchase + ,:v_qd_rcv_retail + ); + + end + close c_qd_rows_for_doc; + end + end + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this, null, 'dd_qsum='||v_dd_qsum||', rows: dd='||v_dd_rows||', qd='||v_qd_rows ); + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + v_info, + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + +^ -- sp_qd_handle_on_invoice_upd_sts + +-- Aux SP that serves just as "redirector" to sp_qd_handle_on_invoice_upd_sts when config 'create_with_split_heavy_tabs=0' +-- Source of this SP will be replaced to reflect actual value of autogen_qdNNNN when config 'create_with_split_heavy_tabs=1' +create or alter procedure sp_qd_handle_on_invoice_adding ( + a_doc_id dm_idb, + a_old_optype dm_idb, + a_new_optype dm_idb +) as +begin + execute procedure sp_qd_handle_on_invoice_upd_sts( :a_doc_id, :a_old_optype, :a_new_optype ); +end + +^ -- sp_qd_handle_on_invoice_adding (REDIRECTOR) + +-- Aux SP that serves just as "redirector" to sp_qd_handle_on_invoice_upd_sts when config 'create_with_split_heavy_tabs=0' +-- Source of this SP will be replaced to reflect actual value of autogen_qdNNNN when config 'create_with_split_heavy_tabs=1' +create or alter procedure sp_qd_handle_on_invoice_reopen ( + a_doc_id dm_idb, + a_old_optype dm_idb, + a_new_optype dm_idb +) as +begin + execute procedure sp_qd_handle_on_invoice_upd_sts( :a_doc_id, :a_old_optype, :a_new_optype ); +end + +^ -- sp_qd_handle_on_invoice_reopen (REDIRECTOR) + +create or alter procedure sp_kill_qty_storno ( + a_doc_id dm_idb, + a_old_optype dm_idb, + a_new_optype dm_idb, + a_updating dm_sign, + a_deleting dm_sign) +as + declare v_this dm_dbobj = 'sp_kill_qty_storno'; + declare v_info dm_info; + declare v_dbkey dm_dbkey; +begin + -- Called from doc_list_biud for deleting doc or updating with changing it state. + -- 1. For sp_reserve_write_off (FINAL point of ware turnover): + -- remove data from qdistr into qstorned) + -- 2. For CANCEL operations (deleting doc or change its state to "previous"): + -- return storned rows from qstorned to qdistr + -- 3. For sp_add_invoice_to_stock: change IDs in qdistr.snd_op XOR rcv_op to + -- new ID (2000-->2100) + + if ( NOT (a_deleting = 1 or a_updating = 1 and a_new_optype is distinct from a_old_optype) ) + then + --##### + exit; + --##### + + v_info = 'dh='|| a_doc_id + ||' '||iif(a_updating=1,'UPD','DEL') + ||iif(a_updating=1, ' old_op='||a_old_optype||' new_op='||a_new_optype, ' op='||a_old_optype); + + execute procedure sp_add_perf_log(1, v_this,null, v_info); + + if ( a_updating = 1 and a_new_optype is distinct from a_old_optype ) then + begin + ---------------- c h a n g e o p t y p e _ i d ------------------ + -- see s`p_cancel_client_order; sp_add_invoice_to_stock; + -- sp_reserve_write_off, s`p_cancel_write_off + -- ==> they all change doc_data.optype_id + if ( a_new_optype = fn_oper_cancel_customer_order() ) then + begin + -- S P _ C A N C E L _ C L I E N T _ O R D E R + -- Kill all records for this doc both in QDistr & QStorned + -- delete rows in qdistr for currently cancelled client order: + execute procedure sp_qd_handle_on_cancel_clo( :a_doc_id, :a_old_optype, fn_oper_cancel_customer_order() ); + end + + else if ( a_old_optype = fn_oper_retail_realization() and a_new_optype = fn_oper_retail_reserve() ) then + -- S P _ C A N C E L _ W R I T E _ O F F + -- return from QStorned to QDistr records which were previously moved + -- (when currently deleting doc was created): + execute procedure sp_ret_qs2qd_on_canc_wroff( :a_doc_id, :a_old_optype, :a_deleting ); + -- prev: direct call execute procedure s~p_kill_qstorno_ret_qs2qd( :a_doc_id, :a_old_optype, :a_deleting ); + + else if ( a_old_optype = fn_oper_retail_reserve() and a_new_optype = fn_oper_retail_realization() ) then + -- S P _ R E S E R V E _ W R I T E _ O F F + execute procedure sp_qd_handle_on_reserve_upd_sts( :a_doc_id, :a_old_optype, :a_new_optype ); + -- prev: direct call of s~p_kill_qstorno_mov_qd2qs( :a_doc_id, :a_old_optype, :a_new_optype); + + else -- all other updates of doc state, except s`p_cancel_write_off + -- update rows in qdistr for currently selected doc (3dr arg <> fn_oper_cancel_cust_order): + if ( a_old_optype = fn_oper_invoice_get() ) then + -- S P _ A D D _ I N V O I C E _ T O _ S T O C K + execute procedure sp_qd_handle_on_invoice_adding( :a_doc_id, :a_old_optype, :a_new_optype ); + else if ( a_old_optype = fn_oper_invoice_add() ) then + -- S P _ C A N C E L _ A D D I N G _ I N V O I C E + execute procedure sp_qd_handle_on_invoice_reopen( :a_doc_id, :a_old_optype, :a_new_optype ); + else + exception ex_bad_argument using(':a_old_optype='||:a_old_optype, v_this ); + -- before: execute procedure s~p_kill_qstorno_handle_qd4dd( :a_doc_id, :a_old_optype, :a_new_optype ); + + end -- a_updating = 1 and a_new_optype is distinct from a_old_optype + + if ( a_deleting = 1 ) then -- all other operations that delete document + begin + -- return from QStorned to QDistr records which were previously moved + -- (when currently deleting doc was created): + if ( :a_old_optype = fn_oper_invoice_get() ) then + execute procedure sp_ret_qs2qd_on_canc_invoice( :a_doc_id, :a_old_optype, :a_deleting ); + else if ( :a_old_optype = fn_oper_order_for_supplier() ) then + execute procedure sp_ret_qs2qd_on_canc_supp_order( :a_doc_id, :a_old_optype, :a_deleting ); + else if ( :a_old_optype = fn_oper_retail_reserve() ) then + begin + execute procedure sp_ret_qs2qd_on_canc_res_aux( :a_doc_id, :a_old_optype, :a_deleting ); + execute procedure sp_ret_qs2qd_on_canc_reserve( :a_doc_id, :a_old_optype, :a_deleting ); + end + else + exception ex_bad_argument using(':a_old_optype='||:a_old_optype, v_this ); + -- prev: direct call of s~p_kill_qstorno_ret_qs2qd( :a_doc_id, :a_old_optype, :a_deleting ); + end -- a_deleting = 1 + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this); + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + v_info, + v_this, + fn_halt_sign(gdscode) -- iif( fn_is_uniqueness_trouble(gdscode), 1, 0) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + +^ -- sp_kill_qty_storno + + +set term ;^ +-- View for using in SRV_FIND_QD_QS_MISM as alias of table 'QDistr'. +-- Will be altered in 'oltp_autogen_ddl.sql' when config 'create_with_split_heavy_tabs=1'. +create or alter view v_qdistr_source as +select * +from qdistr +; + +-- View for using in SRV_FIND_QD_QS_MISM as alias of table 'QStorned'. +-- Will be altered in 'oltp_autogen_ddl.sql' when config 'create_with_split_heavy_tabs=1'. +create or alter view v_qstorned_source as +select * +from qstorned +; + + +set term ^; + +create or alter procedure srv_find_qd_qs_mism( + a_doc_list_id type of dm_idb, + a_optype_id type of dm_idb, + a_after_deleting_doc dm_sign -- 1==> doc has been deleted, must check orphans only in qdistr+qstorned +) as + declare v_this dm_dbobj = 'srv_find_qd_qs_mism'; + declare v_gdscode int; + declare v_dd_mismatch_id bigint; + declare v_dd_mismatch_qty dm_qty; + declare v_qd_qs_orphan_src dm_dbobj; -- name of table where orphan row(s) found + declare v_qd_qs_orphan_doc dm_idb; + declare v_qd_qs_orphan_id dm_idb; + declare v_qd_qs_orphan_sid dm_idb; + declare v_qd_sum dm_qty; + declare v_qs_sum dm_qty; + declare v_info dm_info = ''; + declare c_chk_violation_code int = 335544558; -- check_constraint + declare v_dh_id dm_idb; + declare v_dd_id dm_idb; + declare v_ware_id dm_idb; + declare v_dd_qty dm_qty; + declare v_all_qty_sum dm_qty; + declare v_all_qd_sum dm_qty; + declare v_all_qs_sum dm_qty; + declare v_snd_optype_id dm_idb; + declare v_rcv_optype_id dm_idb; + declare v_rows_handled int; + + declare c_qd_qs_orphans cursor for ( -- used after deletion of doc: search for orphans in qd & qs + -- deciced neither add index on qdistr.doc_id nor modify qdistr PK and set its key = {id, doc_id} (performance) + select r.doc_data_id, r.ware_id + from tmp$result_set r -- ::: NB ::: this table must be always filled in SPs which REMOVES (cancel) doc with wares + where r.doc_id = :a_doc_list_id + ); + + declare c_dd_qty_match_qd_qs_counts cursor for ( + select f.dd_id, f.ware_id, f.dd_qty, f.qd_cnt, f.qs_cnt + from ( + select e.dd_id, e.ware_id, e.qty as dd_qty, e.qd_cnt, coalesce(sum(qs.snd_qty),0) as qs_cnt + -- PLAN SORT (JOIN (JOIN (SORT (E D D INDEX (FK_DOC_DATA_DOC_LIST)), E QD INDEX (QDISTR_SNDOP_RCVOP_SNDID_DESC)), QS INDEX (QSTORNED_SND_ID))) + from ( + select + d.id as dd_id + ,d.ware_id + ,d.qty + ,coalesce(sum(qd.snd_qty),0) qd_cnt + --,iif(:a_optype_id=3400, 3300, :a_optype_id) as snd_optype_id + --,:v_snd_optype_id as snd_optype_id -- core-4927, affected 2.5 only + from doc_data d + left join v_qdistr_source qd on + -- {ware,snd_optype_id,rcv_optype_id} ==> Index Range Scan (full match, since ) + -- Full match since 01.09.2015 2355, see: + -- http://sourceforge.net/p/firebird/code/62176 (3.0) + -- http://sourceforge.net/p/firebird/code/62177 (2.5.5) + qd.ware_id = d.ware_id + -- 07.09.2015. In 2.5, before core-4927 (http://sourceforge.net/p/firebird/code/62200): + -- we had to avoid usage of "iif()" for evaluating column that will be involved in + -- JOIN with "unioned" view: it (IIF function) prevented the condition from being + -- pushed into the union for better optimization. This lead to unneccessary index + -- scans of tables from unioned-view that sor sure did not contain req. data. + -- Thus we use here parameter ":v_snd_optype_id" which will be evaluated BEFORE + -- in separate IIF statement: + and qd.snd_optype_id = :v_snd_optype_id + and qd.rcv_optype_id = :v_rcv_optype_id + and qd.snd_id = d.id + where + d.doc_id = :a_doc_list_id + group by d.id, d.ware_id, d.qty + ) e + left join v_qstorned_source qs on + -- NB: we can skip this join if previous one produces ERROR in results: + -- sum of amounts in doc_data rows has to be NOT LESS than sum(snd_qty) on qdistr + -- (except CANCELLED client order for which qdistr must NOT contain any row for this doc) + ( + :v_snd_optype_id <> 1100 and e.qty >= e.qd_cnt + or + :v_snd_optype_id = 1100 and e.qd_cnt = 0 + ) + and qs.snd_id = e.dd_id + group by e.dd_id, e.ware_id, e.qty, e.qd_cnt + ) f + ); + +begin + + -- Search for mismatches b`etween doc_data.qty and number of records in + -- v_qdistr + v_qstorned, for all operation. Algorithm for deleted ("cancelled") + -- document differs from document that was just created or updated its state: + -- we need found orphan rows in v_qdistr + v_qstorned when document has been removed + -- (vs. checking sums of doc_data.qty and sum(qty) when doc. is created/updated) + -- Log mismatches if they found and raise exc`eption. + -- ### NB ### GTT tmp$result_set need to be fulfilled with data of doc that + -- is to be deleted, BEFORE this deletion issues. It's bad (strong link between + -- modules) but this is the only way to avoid excessive indexing of v_qdistr & v_qstorned. + + v_info = 'dh='||a_doc_list_id||', op='||a_optype_id; + execute procedure sp_add_perf_log(1, v_this); -- , null, v_info); + + v_dd_mismatch_id = null; + -- This value is used in CURSOR c_dd_qty_match_qd_qs_counts as argument of join: + v_snd_optype_id = iif(:a_optype_id=3400, 3300, :a_optype_id); + + select r.rcv_optype_id + from rules_for_qdistr r + where r.snd_optype_id = :a_optype_id and coalesce(r.storno_sub,1)=1 + into v_rcv_optype_id; + + if ( a_after_deleting_doc = 1 ) then -- call after doc has been deleted: NO rows in doc_data but we must check orphan rows in qd&qs for this doc! + begin + select h.id from doc_list h where h.id = :a_doc_list_id into v_dh_id; + if ( v_dh_id is NOT null or not exists(select * from tmp$result_set) ) then + exception ex_bad_argument using('a_after_deleting_doc', v_this) ; -- 'argument @1 passed to unit @2 is invalid'; + + v_rows_handled = 0; + open c_qd_qs_orphans; + while ( v_dh_id is null ) do + begin + fetch c_qd_qs_orphans into v_dd_id, v_ware_id; -- get data of doc which have been saved in tmp$result_set + if ( row_count = 0 ) then leave; + v_rows_handled = v_rows_handled + 1; + + select first 1 'v_qdistr' as src, qd.doc_id, qd.snd_id, qd.id + from v_qdistr_source qd + where + -- {ware,snd_optype_id,rcv_optype_id} ==> Index Range Scan (full match, since ) + -- Full match since 01.09.2015 2355, see: + -- http://sourceforge.net/p/firebird/code/62176 (3.0) + -- http://sourceforge.net/p/firebird/code/62177 (2.5.5) + qd.ware_id = :v_ware_id + and qd.snd_optype_id = :v_snd_optype_id + and qd.rcv_optype_id = :v_rcv_optype_id + -- This is mandatory otherwise get lot of different docs for the same {ware,snd_optype_id,rcv_optype_id}: + and qd.snd_id = :v_dd_id + into v_qd_qs_orphan_src, v_qd_qs_orphan_doc, v_qd_qs_orphan_sid, v_qd_qs_orphan_id; + + if ( v_qd_qs_orphan_id is null ) then -- run 2nd check only if there are NO row in QDistr + select first 1 'v_qstorned' as src, qs.doc_id, qs.snd_id, qs.id + from v_qstorned_source qs + where qs.snd_id = :v_dd_id + into v_qd_qs_orphan_src, v_qd_qs_orphan_doc, v_qd_qs_orphan_sid, v_qd_qs_orphan_id; + + if ( v_qd_qs_orphan_id is NOT null ) then + begin + v_info = trim(v_info) + || ': orphan '||v_qd_qs_orphan_src||'.id='||v_qd_qs_orphan_id + || ' for deleted doc='||v_qd_qs_orphan_doc + || ', snd_id='||v_qd_qs_orphan_sid + || ', ware='||v_ware_id; + leave; + end + end + close c_qd_qs_orphans; + if ( v_qd_qs_orphan_id is null ) then + v_info = trim(v_info)||': no data in qd+qs for deleted '||v_rows_handled||' rows'; + + end + else ------------------ _N O T_ a f t e r d e l e t i n g ------- + begin + v_all_qty_sum = 0; + v_all_qd_sum = 0; + v_all_qs_sum = 0; + + v_rows_handled = 0; + open c_dd_qty_match_qd_qs_counts; + while ( 1 = 1 ) do + begin + fetch c_dd_qty_match_qd_qs_counts + into v_dd_id, v_ware_id, v_dd_qty, v_qd_sum, v_qs_sum; + -- e.dd_id, e.qty, e.qd_cnt, coalesce(sum(qs.snd_qty),0) as qs_cnt + if (row_count = 0) then leave; + + v_rows_handled = v_rows_handled + v_qd_sum + v_qs_sum; + v_all_qty_sum = v_all_qty_sum + v_dd_qty; -- total AMOUNT in ALL rows of document + v_all_qd_sum = v_all_qd_sum + v_qd_sum; -- number of rows in QDistr for ALL wares of document + v_all_qs_sum = v_all_qs_sum + v_qs_sum; -- number of rows in v_qstorned for ALL wares of document + + if ( a_optype_id <> 1100 and v_dd_qty <> v_qd_sum + v_qs_sum -- error, immediately stop check if so! + or + a_optype_id = 1100 and v_qd_sum + v_qs_sum > 0 -- it's WRONG when we cancel client order and some rows still exist in qdistr or v_qstorned for this doc! + ) then + begin + v_dd_mismatch_id = v_dd_id; + v_dd_mismatch_qty = v_dd_qty; + leave; + end + end + close c_dd_qty_match_qd_qs_counts; + + if ( v_dd_mismatch_id is NOT null ) then + begin + v_info=trim(v_info) + || ': dd='||v_dd_mismatch_id + || ', ware='||v_ware_id + || ', sum_qty='||cast(v_all_qty_sum as int) + || ', problem_qty='||cast(v_dd_mismatch_qty as int); + if ( a_optype_id <> 1100 ) then + v_info = v_info + || ' - mism: qd_cnt='||cast(v_qd_sum as int) + || iif( v_qs_sum >=0, ', qs_cnt='||cast(v_qs_sum as int), ', qs_cnt=n/a'); + else + v_info = v_info + || ' - no_removal: qd_cnt='||cast(v_qd_sum as int) + || iif( v_qs_sum >=0, ', qs_cnt='||cast(v_qs_sum as int), ', qs_cnt=n/a'); + end + else -- ok + v_info = trim(v_info) + ||', sum_qty='||cast(v_all_qty_sum as int) + ||', cnt_qds='||cast((v_all_qd_sum + v_all_qs_sum) as int) + ||', rows_handled='||v_rows_handled; + + end -- block for NOT after deleting doc + + if ( a_after_deleting_doc = 0 and v_dd_mismatch_id is NOT null + or + a_after_deleting_doc = 1 and v_qd_qs_orphan_id is NOT null + ) then + begin + -- dump dirty data: + execute procedure zdump4dbg(:a_doc_list_id); --,:a_doc_data_id); + --####### + if ( a_after_deleting_doc = 1) then + exception ex_orphans_qd_qs_found using( a_doc_list_id, v_qd_qs_orphan_sid, v_qd_qs_orphan_src, v_qd_qs_orphan_id ); + -- 'at least one row found for DELETED doc id=@1, snd_id=@2: @3.id=@4'; + else + exception ex_mism_doc_data_qd_qs using( v_dd_mismatch_id, v_dd_mismatch_qty, v_qd_sum, v_qs_sum ); + -- at least one mismatch btw doc_data.id=@1 and qdistr+v_qstorned: qty=@2, qd_cnt=@3, qs_cnt=@4 + --####### + end + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this, null, 'ok, '||v_info); + +when any do + begin + v_gdscode = iif( :v_dd_mismatch_id is null, gdscode, :c_chk_violation_code); + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + :v_gdscode, + 'MISMATCH, '||v_info, + v_this, + fn_halt_sign(:v_gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + --######## + exception; -- ::: nb ::: anonimous but in when-block! + --######## + end +end + +^ -- srv_find_qd_qs_mism + +create or alter procedure sp_add_money_log( + a_doc_id dm_idb, + a_old_mult dm_sign, + a_old_agent_id dm_idb, + a_old_op dm_idb, + a_old_purchase type of dm_cost, -- NB: must allow negative values! + a_old_retail type of dm_cost, -- NB: must allow negative values! + a_new_mult dm_sign, + a_new_agent_id dm_idb, + a_new_op dm_idb, + a_new_purchase type of dm_cost, -- NB: must allow negative values! + a_new_retail type of dm_cost -- NB: must allow negative values! +) +as +begin + -- called from trg d`oc_list_aiud for every operation which affects to contragent saldo + if ( a_old_mult <> 0 ) then + insert into money_turnover_log ( -- "log" of all changes in doc_list.cost_xxx + doc_id, + agent_id, + optype_id, + cost_purchase, -- NB: this field must allow negative values! + cost_retail -- NB: this field must allow negative values! + ) + values( + :a_doc_id, -- ref to doc_list + :a_old_agent_id, + :a_old_op, + -:a_old_purchase, + -:a_old_retail + ); + + if ( a_new_mult <> 0 ) then + insert into money_turnover_log ( -- "log" of all changes in doc_list.cost_xxx + doc_id, + agent_id, + optype_id, + cost_purchase, -- NB: this field must allow negative values! + cost_retail -- NB: this field must allow negative values! + ) + values( + :a_doc_id, -- ref to doc_list + :a_new_agent_id, + :a_new_op, + :a_new_purchase, + :a_new_retail + ); +end + +^ -- sp_add_money_log + +------------------------------------------------------------------------------ + +create or alter procedure sp_lock_dependent_docs( + a_base_doc_id dm_idb, + a_base_doc_oper_id dm_idb default null -- = (for invoices which are to be 'reopened' - old_oper_id) +) +as + declare v_rcv_optype_id dm_idb; + declare v_dependend_doc_id dm_idb; + declare v_dependend_doc_state dm_idb; + declare v_catch_bitset bigint; + declare v_dbkey dm_dbkey; + declare v_info dm_info; + declare v_list dm_info; + declare v_this dm_dbobj = 'sp_lock_dependent_docs'; +begin + + v_info = 'base_doc='||a_base_doc_id; + execute procedure sp_add_perf_log(1, v_this, null, v_info); + + if ( a_base_doc_oper_id is null ) then + select h.optype_id + from doc_list h + where h.id = :a_base_doc_id + into a_base_doc_oper_id; + + v_rcv_optype_id = decode(a_base_doc_oper_id, + fn_oper_invoice_add(), fn_oper_retail_reserve(), + fn_oper_order_for_supplier(), fn_oper_invoice_get(), + null + ); + delete from tmp$dep_docs d where d.base_doc_id = :a_base_doc_id; + for + select x.dependend_doc_id, h.state_id, h.rdb$db_key + -- 30.12.2014: PLAN JOIN (SORT (X Q INDEX (QSTORNED_DOC_ID)), H INDEX (PK_DOC_LIST)) + -- (added field rcv_doc_id in table qstorned, now can remove join with doc_data!) + from ( + -- Checked plan 13.07.2014: + -- PLAN (Q ORDER QSTORNED_RCV_ID INDEX (QSTORNED_DOC_ID)) + select q.rcv_doc_id dependend_doc_id + from v_qstorned_source q + where + q.doc_id = :a_base_doc_id -- choosen invoice which is to be re-opened + and q.snd_optype_id = :a_base_doc_oper_id + and q.rcv_optype_id = :v_rcv_optype_id + group by 1 + ) x + join doc_list h on x.dependend_doc_id = h.id + into v_dependend_doc_id, v_dependend_doc_state, v_dbkey + do begin + -- immediatelly try to lock record in order to avoid wast handling + -- of 99 docs and get fault on 100th one! + -- (see s`p_cancel_adding_invoice, s`p_cancel_supplier_order) + v_info = 'try lock dependent doc_id='||v_dependend_doc_id; + select h.rdb$db_key + from doc_list h + where h.rdb$db_key = :v_dbkey -- lock_conflict can occur here! + for update with lock + into v_dbkey; + + begin + -- NB: BASE_DOC_ID,DEPENDEND_DOC_ID ==> UNIQ index in tmp$dep_docs + insert into tmp$dep_docs( base_doc_id, dependend_doc_id, dependend_doc_state) + values( :a_base_doc_id, :v_dependend_doc_id, :v_dependend_doc_state ); + when any do + -- ::: nb ::: do NOT use "wh`en gdscode " followed by "wh`en any": + -- the latter ("w`hen ANY") will handle ALWAYS, even if "w`hen " + -- catched it's kind of exception! + -- 1) tracker.firebirdsql.org/browse/CORE-3275 + -- "W`HEN ANY handles exceptions even if they are handled in another W`HEN section" + -- 2) sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1088890&msg=15879669 + begin + -- supress dup ex`ception - it is normal in this case! + if ( NOT fn_is_uniqueness_trouble(gdscode) ) then exception; + end + end + end + + v_catch_bitset = cast(rdb$get_context('USER_SESSION','QMISM_VERIFY_BITSET') as bigint); + -- See oltp_main_filling.sql for definition of bitset var `QMISM_VERIFY_BITSET`: + -- bit#0 := 1 ==> perform calls of srv_catch_qd_qs_mism in d`oc_list_aiud => sp_add_invnt_log + -- in order to register mismatches b`etween doc_data.qty and total number of rows + -- in qdistr + qstorned for doc_data.id + -- bit#1 := 1 ==> perform calls of SRV_CATCH_NEG_REMAINDERS from INVNT_TURNOVER_LOG_AI + -- (instead of totalling turnovers to `invnt_saldo` table) + -- bit#2 := 1 ==> allow dump dirty data into z-tables for analysis, see sp zdump4dbg, in case + -- when some 'bad exception' occurs (see ctx var `HALT_TEST_ON_ERRORS`) + if ( bin_and( v_catch_bitset, 7 ) > 0 ) then -- ==> any of bits #0..2 is ON + begin + v_list=left( ( select list(d.dependend_doc_id) from tmp$dep_docs d where d.base_doc_id=:a_base_doc_id ), 255-char_length(v_info)-15); + v_info = 'depDocsLst='|| coalesce(nullif(v_list,''),''); + end + else + begin + v_info = 'depDocsCnt='||( select count(*) from tmp$dep_docs d where d.base_doc_id=:a_base_doc_id ); + end + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this, null, v_info ); + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + v_info, + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + +^ -- sp_lock_dependent_docs + +-- 29.07.2014: STUB, need for debug view z_invoices_to_be_adopted, will be redefined in oltp30_sp.sql: +create or alter procedure sp_get_clo_for_invoice( a_selected_doc_id dm_idb ) +returns ( + clo_doc_id type of dm_idb, + clo_agent_id type of dm_idb +) +as begin + suspend; +end +^ +set term ;^ + + +------------------------------------------------------------------------------ + +set term ^; + +-- several debug proc for catch cases when negative remainders encountered +create or alter procedure srv_check_neg_remainders( -- 28.09.2014, instead s`rv_catch_neg + a_doc_list_id dm_idb, + a_optype_id dm_idb +) as +declare v_id bigint; + declare v_catch_bitset bigint; + declare v_curr_tx bigint; + declare c_chk_violation_code int = 335544558; -- check_constraint + declare v_msg dm_info = ''; + declare v_info dm_info = ''; + declare v_this dm_dbobj = 'srv_check_neg_remainders'; +begin + -- called from d`oc_list_aiud + -- ######################### + -- See oltp_main_filling.sql for definition of bitset var `QMISM_VERIFY_BITSET`: + -- bit#0 := 1 ==> perform calls of srv_catch_qd_qs_mism in d`oc_list_aiud => sp_add_invnt_log + -- in order to register mismatches b`etween doc_data.qty and total number of rows + -- in qdistr + qstorned for doc_data.id + -- bit#1 := 1 ==> perform calls of SRV_CATCH_NEG_REMAINDERS from INVNT_TURNOVER_LOG_AI + -- (instead of totalling turnovers to `invnt_saldo` table) + -- bit#2 := 1 ==> allow dump dirty data into z-tables for analysis, see sp zdump4dbg, in case + -- when some 'bad exception' occurs (see ctx var `HALT_TEST_ON_ERRORS`) + v_catch_bitset = cast(rdb$get_context('USER_SESSION','QMISM_VERIFY_BITSET') as bigint); + if ( bin_and( v_catch_bitset, 2 ) = 0 ) then -- job of this SP meaningless because of totalling + --#### + exit; + --#### + + -- do NOT add calls of sp_check_to_stop_work or sp_check_nowait_or_timeout: + -- this SP is called very often! + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(1, v_this); + + v_msg ='dh='||:a_doc_list_id || ', op='||fn_mcode_for_oper( :a_optype_id ); + + v_id = null; + select first 1 + n.ware_id + ,:v_msg + || ', w='||n.ware_id||', dd='||n.dd_id + || ', neg:' + || trim( trailing from iif( n.qty_ord<0,' q_ord='||n.qty_ord,'' ) ) + || trim( trailing from iif( n.qty_sup<0,' q_sup='||n.qty_sup,'' ) ) + || trim( trailing from iif( n.qty_avl<0,' q_avl='||n.qty_avl,'' ) ) + || trim( trailing from iif( n.qty_res<0,' q_res='||n.qty_res,'' ) ) + || trim( trailing from iif( n.qty_inc<0,' q_inc='||n.qty_inc,'' ) ) + || trim( trailing from iif( n.qty_out<0,' q_out='||n.qty_out,'' ) ) + || trim( trailing from iif( n.qty_clo<0,' q_clo='||n.qty_clo,'' ) ) + || trim( trailing from iif( n.qty_clr<0,' q_clr='||n.qty_clr,'' ) ) + || trim( trailing from iif( n.qty_acn<0,' q_acn='||n.qty_acn,'' ) ) + || trim( trailing from iif( n.cost_acn<0,' $_acn='||n.cost_acn,'' ) ) + from --v_saldo_invnt n + ( + select + ng.ware_id + ,min(ng.doc_data_id) as dd_id -- no matter min or max + ,sum(o.m_qty_clo * ng.qty_diff) qty_clo + ,sum(o.m_qty_clr * ng.qty_diff) qty_clr + ,sum(o.m_qty_ord * ng.qty_diff) qty_ord + ,sum(o.m_qty_sup * ng.qty_diff) qty_sup + ,sum(o.m_qty_avl * ng.qty_diff) qty_avl + ,sum(o.m_qty_res * ng.qty_diff) qty_res + ,sum(o.m_cost_inc * ng.qty_diff) qty_inc + ,sum(o.m_cost_out * ng.qty_diff) qty_out + ,sum(o.m_cost_inc * ng.cost_diff) cost_inc + ,sum(o.m_cost_out * ng.cost_diff) cost_out + -- amount "on hand" as it seen by accounter: + ,sum(o.m_qty_avl * ng.qty_diff) + sum(o.m_qty_res * ng.qty_diff) qty_acn + -- total cost "on hand" in purchasing prices: + ,sum(o.m_cost_inc * ng.cost_diff) - sum(o.m_cost_out * ng.cost_diff) cost_acn + from invnt_turnover_log ng + join optypes o on ng.optype_id=o.id + join doc_data d on ng.ware_id = d.ware_id -- ng.doc_data_id = d.id + where d.doc_id = :a_doc_list_id + --where ng.ware_id = :a_ware_id + group by + ng.ware_id + --,ng.doc_data_id + ) n + where + n.qty_ord<0 or n.qty_sup<0 or n.qty_avl<0 or n.qty_res<0 + or n.qty_inc<0 or n.qty_out<0 or n.qty_clo<0 or n.qty_clr<0 + or n.qty_acn<0 or n.cost_acn<0 + into v_id, v_info; + + if ( v_id is not null) then + begin + v_curr_tx = current_transaction; + in autonomous transaction do + begin -- 26.09.2014 2222, temply + insert into perf_log( + unit, + exc_unit, + fb_gdscode, + trn_id, + info, + exc_info, + stack, + dump_trn + ) values ( + :v_this, + '!', + :c_chk_violation_code, + :v_curr_tx, + :v_info, + :v_info, --'ex_neg_remainders_encountered', + :v_this, -- fn_get_stack(), + current_transaction + ); + execute procedure sp_halt_on_error('5', :c_chk_violation_code, :v_curr_tx); -- temply + end + -- 335544558 check_constraint Operation violates CHECK constraint @1 on view or table @2. + execute procedure sp_add_to_abend_log( + 'ex_neg_remainders_encountered', + :c_chk_violation_code, + v_info, + v_this, + 1 -- ::: nb ::: force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + -- 4 debug: dump dirty data: + execute procedure zdump4dbg; -- (null, a_doc_data_id, v_id); + + --######## + exception ex_neg_remainders_encountered using( v_id, v_info ); -- 'at least one remainder < 0, ware_id=@1'; + --######## + end + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(0, v_this,null, 'ok, '||v_msg); + +when any do + begin + --######## + exception; -- ::: nb ::: anonimous but in when-block! + --######## + end +end + +^ -- srv_check_neg_remainders + +set term ;^ + + +------------------------------------------------------------------------------- +-- ############################ V I E W S ################################# +------------------------------------------------------------------------------- + +-- 07.09.2015: probe to replace ES in all cases of fn_get_rand_id: +create or alter view name$to$substutite$min$id$ as select 1 id from rdb$database; +create or alter view name$to$substutite$max$id$ as select 1 id from rdb$database; +create or alter view name$to$substutite$search$ as select 1 id from rdb$database; + +create or alter view v_cancel_client_order as +-- source for random choose client_order document to be cancelled +select h.id +from doc_list h +where + h.optype_id = 1000 -- fn_oper_order_by_customer +; + +create or alter view v_cancel_supplier_order as +-- Source for random choose supplier order doc to be cancelled +select h.id +from doc_list h +where + h.optype_id = 1200 -- fn_oper_order_for_supplier +; + + +create or alter view v_cancel_supplier_invoice as +-- source for random choose invoice from supplier that will be cancelled +select h.id +from doc_list h +where + h.optype_id = 2000 -- fn_oper_invoice_get +; + +create or alter view v_add_invoice_to_stock as +select h.id +from doc_list h +where + h.optype_id = 2000 -- fn_oper_invoice_get +; + +create or alter view v_cancel_adding_invoice as +select h.id +from doc_list h +where + h.optype_id = 2100 -- fn_oper_invoice_add +; + +create or alter view v_cancel_customer_reserve as +-- source for s`p_cancel_customer_reserve: random take customer reserve +-- and CANCEL it (i.e. DELETE from doc_list) +select h.id +from doc_list h +where + h.optype_id = 3300 -- fn_oper_retail_reserve +; + +create or alter view v_reserve_write_off as +-- source for random take customer reserve and make WRITE-OFF (i.e. 'close' it): +select h.id, h.agent_id, h.state_id, h.dts_open, h.dts_clos, h.cost_retail +from doc_list h +where + h.optype_id = 3300 -- fn_oper_retail_reserve +; + +create or alter view v_cancel_write_off as +-- source for random take CLOSED customer reserve and CANCEL writing-off +-- (i.e. 'reopen' this doc for changes or removing): +select h.id +from doc_list h +where + h.optype_id = 3400 -- fn_oper_retail_realization +; + +create or alter view v_cancel_payment_to_supplier as +-- source for random taking INVOICE with some payment and CANCEL all payments: +select h.id, h.agent_id, h.cost_purchase +from doc_list h +where + h.optype_id = 4000 -- fn_oper_pay_to_supplier +; + +create or alter view v_cancel_customer_prepayment as +select h.id, h.agent_id, h.cost_retail +from doc_list h +where + h.optype_id = 5000 -- fn_oper_pay_from_customer +; + + +create or alter view v_all_customers as +-- source for random taking agent from ALL customers +-- (see sp_customer_prepayment in case when all customer reserve docs are full paid) +select a.id +from agents a +where a.is_customer=1 +; + +create or alter view v_all_suppliers as +select a.id +from agents a +where a.is_supplier=1 +; + +create or alter view v_our_firm as +select a.id +from agents a +where a.is_our_firm=1 +; + +create or alter view v_all_wares as +-- source for random choose ware_id in SP_CLIENT_ORDER => SP_FILL_SHOPPING_CART +-- Plan in 3.0 (checked 06.02.2015): +-- PLAN (C ORDER TMP_SHOPCART_UNQ) // prevent from bitmap building in tmp$shopping_cart for each row of wares! +-- PLAN (A NATURAL) +select a.id +from wares a +where not exists(select * from tmp$shopping_cart c where c.id = a.id order by c.id) -- 19.09.2014 +; + +------------------------------ +-- 12.09.2014 1920: refactoring v_random_find_xxx views for avl_res, clo_ord and ord_sup +-- use `wares` as driver table instead of scanning qdistr for seach doc_data.id +-- Performance increased from ~1250 up to ~2000 bop / minute (!) +------------------------------ + +-- ############## A V L => R E S ############### +-- Views for operation 'Create customer reserve from AVALIABLE remainders' +-- ############################################# + +create or alter view v_random_find_avl_res +as +-- 08.07.2014. used in dynamic sql in sp_get_random_id, see it's call in sp_fill_shopping_cart +-- source for random choose ware_id in sp_customer_reserve => sp_fill_shopping_cart: +-- take record from invoice which has been added to stock and add it to set for +-- new customer reserve - from avaliable remainders (not linked with client order) +-- Checked 12.09.2014: +--PLAN (V TMP$SHOPPING_CART INDEX (TMP_SHOPCART_UNQ)) +--PLAN (V QDISTR ORDER QDISTR_WARE_SNDOP_RCVOP) -- ::: NB ::: no bitmap here (speed!) +--PLAN (V W ORDER WARES_ID_DESC) +select w.id +from wares w +where + not exists(select * from tmp$shopping_cart c where c.id = w.id order by c.id) + and exists( + select * from qdistr q + where + q.ware_id = w.id + and q.snd_optype_id = 2100 + and q.rcv_optype_id = 3300 + order by ware_id, snd_optype_id, rcv_optype_id -- supress building index bitmap on QDistr! + ); + +create or alter view v_min_id_avl_res as +-- 08.07.2014. used in dynamic sql in sp_get_random_id, see it's call in sp_fill_shopping_cart +-- source for random choose ware_id in sp_customer_reserve => sp_fill_shopping_cart: +-- take record from invoice which has been added to stock and add it to set for +-- new customer reserve - from ***AVALIABLE*** remainders (not linked with client order) + select w.id + from wares w + where + exists( + select * from qdistr q + where + q.ware_id = w.id + and q.snd_optype_id = 2100 + and q.rcv_optype_id = 3300 + -- 3.0 only: supress building index bitmap on QDistr: + order by ware_id, snd_optype_id, rcv_optype_id -- do NOT use this 'order by' in 2.5! + ) + order by w.id asc -- ascend, we search for MINIMAL id + rows 1 +; + +create or alter view v_max_id_avl_res as +-- 08.07.2014. used in dynamic sql in sp_get_random_id, see it's call in sp_fill_shopping_cart +-- source for random choise record from client order to be added into supplier order +--PLAN (Q ORDER QDISTR_WARE_SNDOP_RCVOP) +--PLAN (W ORDER WARES_ID_DESC) + select w.id + from wares w + where + exists( + select * from qdistr q + where + q.ware_id = w.id + and q.snd_optype_id = 2100 + and q.rcv_optype_id = 3300 + -- 3.0 only: supress building index bitmap on QDistr: + order by ware_id, snd_optype_id, rcv_optype_id -- do NOT use this 'order by' in 2.5! + ) + order by w.id desc -- descend, we search for MAXIMAL id + rows 1 +; + +-- ############## C L O => O R D ############### +-- Views for operation 'Create order to SUPPLIER on the basis of CUSTOMER orders' +-- ############################################# + +create or alter view v_random_find_clo_ord as +-- 08.07.2014. used in dynamic sql in sp_get_random_id, see it's call in sp_fill_shopping_cart +-- source for random choise record from client order to be added into supplier order +-- Checked 12.09.2014 +--PLAN (V TMP$SHOPPING_CART INDEX (TMP_SHOPCART_UNQ)) +--PLAN (V QDISTR ORDER QDISTR_WARE_SNDOP_RCVOP) -- ::: NB ::: no bitmap here (speed!) +--PLAN (V W ORDER WARES_ID_DESC) +select w.id +from wares w +where + not exists(select * from tmp$shopping_cart c where c.id = w.id order by c.id) + and exists( + select * from qdistr q + where + q.ware_id = w.id + and q.snd_optype_id = 1000 + and q.rcv_optype_id = 1200 + -- 3.0 only: supress building index bitmap on QDistr + order by ware_id, snd_optype_id, rcv_optype_id + ); + +create or alter view v_min_id_clo_ord as +-- 08.07.2014. used in dynamic sql in sp_get_random_id, see it's call in sp_fill_shopping_cart +-- source for random choise record from client order to be added into supplier order + select w.id + from wares w + where + exists( + select * from qdistr q + where + q.ware_id = w.id + and q.snd_optype_id = 1000 + and q.rcv_optype_id = 1200 + -- 3.0 only: supress building index bitmap on QDistr: + order by ware_id, snd_optype_id, rcv_optype_id -- do NOT use this 'order by' in 2.5! + ) + order by w.id asc -- ascend, we search for MINIMAL id + rows 1 +; + +create or alter view v_max_id_clo_ord as +-- 08.07.2014. used in dynamic sql in sp_get_random_id, see it's call in sp_fill_shopping_cart +-- source for random choise record from client order to be added into supplier order + select w.id + from wares w + where exists( + select * from qdistr q + where + q.ware_id = w.id + and q.snd_optype_id = 1000 + and q.rcv_optype_id = 1200 + -- 3.0 only: supress building index bitmap on QDistr: + order by ware_id, snd_optype_id, rcv_optype_id -- do NOT use this 'order by' in 2.5! + ) + order by w.id desc -- descend, we search for MAXIMAL id + rows 1 +; + +-- ############## O R D => S U P ############### +-- Views for operation 'Create invoice from supplier on the basis of OUR orders to him' +-- ############################################# + +create or alter view v_random_find_ord_sup as +-- 08.07.2014. used in dynamic sql in sp_get_random_id, see it's call in sp_fill_shopping_cart +-- source for random choise record from supplier order to be added into invoice by him +-- Checked 12.09.2014: +--PLAN (V TMP$SHOPPING_CART INDEX (TMP_SHOPCART_UNQ)) +--PLAN (V QDISTR ORDER QDISTR_WARE_SNDOP_RCVOP) -- ::: NB ::: no bitmap here (speed!) +--PLAN (V W ORDER WARES_ID_DESC) + select w.id + from wares w + where + not exists(select * from tmp$shopping_cart c where c.id = w.id order by c.id) + and exists( + select * from qdistr q + where + q.ware_id = w.id + and q.snd_optype_id = 1200 -- fn_oper_order_for_supplier() + and q.rcv_optype_id = 2000 + order by ware_id, snd_optype_id, rcv_optype_id -- supress building index bitmap on QDistr! + ) +; + +create or alter view v_min_id_ord_sup as +-- 08.07.2014. used in dynamic sql in sp_get_random_id, see it's call in sp_fill_shopping_cart +-- source for random choise record from client order to be added into supplier order + select w.id + from wares w + where + exists( + select * from qdistr q + where + q.ware_id = w.id + and q.snd_optype_id = 1200 + and q.rcv_optype_id = 2000 + -- 3.0 only: supress building index bitmap on QDistr: + order by ware_id, snd_optype_id, rcv_optype_id -- do NOT use this 'order by' in 2.5! + ) + order by w.id asc -- ascend, we search for MINIMAL id + rows 1 +; + +create or alter view v_max_id_ord_sup as +-- 08.07.2014. used in dynamic sql in sp_get_random_id, see it's call in sp_fill_shopping_cart +-- source for random choise record from client order to be added into supplier order + select w.id + from wares w + where exists( + select * from qdistr q + where + q.ware_id = w.id + and q.snd_optype_id = 1200 + and q.rcv_optype_id = 2000 + -- 3.0 only: supress building index bitmap on QDistr: + order by ware_id, snd_optype_id, rcv_optype_id -- do NOT use this 'order by' in 2.5! + ) + order by w.id desc -- descend, we search for MAXIMAL id + rows 1 +; + +-- ############## C L O => R E S ############### +-- Views for operation 'Create reserve based on client order' +-- ############################################# + +create or alter view v_random_find_clo_res as +-- 08.09.2015: remove join from here, reduce number of IRs at ~1.5x + select h.id + from doc_list h + where h.optype_id = 1000 + and exists( + select * + from doc_data d where d.doc_id = h.id + and exists( + select * + from qdistr q + where + q.ware_id = d.ware_id + and q.snd_optype_id = 1000 -- fn_oper_order_by_customer() + and q.rcv_optype_id = 3300 -- fn_oper_retail_reserve() + and q.snd_id = d.id + -- prevent from building bitmap, 3.0 only: + order by q.ware_id, q.snd_optype_id, q.rcv_optype_id + ) + order by d.doc_id -- prevent from building bitmap, 3.0 only + ) +; + +------------------------------------------------------------------------------- + +create or alter view v_min_id_clo_res as +-- 22.09.2014 +--PLAN (Q ORDER QDISTR_SNDOP_RCVOP_SNDID_DESC) +--PLAN JOIN (H ORDER PK_DOC_LIST, D INDEX (FK_DOC_DATA_DOC_LIST)) +-- 05.09.2015 +--PLAN (Q ORDER QDISTR_WARE_SNDOP_RCVOP) +--PLAN JOIN (H ORDER PK_DOC_LIST, D INDEX (FK_DOC_DATA_DOC_LIST)) +select h.id +from doc_list h +join doc_data d on h.id = d.doc_id +where h.optype_id = 1000 +and exists( + select * + from qdistr q + where + q.ware_id = d.ware_id + and q.snd_optype_id = 1000 -- fn_oper_order_by_customer() + and q.rcv_optype_id = 3300 -- fn_oper_retail_reserve() + and q.snd_id = d.id + order by q.ware_id, q.snd_optype_id, q.rcv_optype_id +) +order by h.id +rows 1 +; + +------------------------------------------------------------------------------- + +create or alter view v_max_id_clo_res as +-- 22.09.2014 +--PLAN (Q ORDER QDISTR_SNDOP_RCVOP_SNDID_DESC) +--PLAN JOIN (H ORDER DOC_LIST_ID_DESC, D INDEX (FK_DOC_DATA_DOC_LIST)) +-- 05.09.2015 +--PLAN (Q ORDER QDISTR_WARE_SNDOP_RCVOP) +--PLAN JOIN (H ORDER DOC_LIST_ID_DESC, D INDEX (FK_DOC_DATA_DOC_LIST)) +select h.id +from doc_list h +join doc_data d on h.id = d.doc_id +where h.optype_id = 1000 +and exists( + select * + from qdistr q + where + q.ware_id = d.ware_id + and q.snd_optype_id = 1000 -- fn_oper_order_by_customer() + and q.rcv_optype_id = 3300 -- fn_oper_retail_reserve() + and q.snd_id = d.id + order by q.ware_id, q.snd_optype_id, q.rcv_optype_id +) +order by h.id desc +rows 1; + +------------------------------------------------------------------------------- + +create or alter view v_random_find_non_paid_invoice as +-- 09.09.2014. Used in dynamic SQL in sp_get_random_id, see SP_PAYMENT_COMMON +-- Source for random choose document of accepted invoice (optype=2100) +-- which still has some cost to be paid (==> has records in PDistr) +-- Introduced instead of v_p`distr_non_paid_realization to avoid scans doc_list +select p.snd_id as id -- this value match doc_list.id +from pdistr p +where + p.snd_optype_id = 2100 -- fn_oper_invoice_add() + and p.rcv_optype_id = 4000 -- fn_oper_pay_to_supplier() +; + +------------------------------------------------------------------------------- + +create or alter view v_min_non_paid_invoice as +-- 09.09.2014: source for fast get min snd_id (==> doc_list.id) before making +-- random choise of accepted invoice (optype=2100) which still has some +-- cost to be paid (==> has records in PDistr) +-- PLAN (P ORDER PDISTR_SNDOP_RCVOP_SNDID_ASC) +select p.snd_id as id -- this value match doc_list.id +from pdistr p +where + p.snd_optype_id = 2100 -- fn_oper_invoice_add() + and p.rcv_optype_id = 4000 -- fn_oper_pay_to_supplier() +order by + snd_id +rows 1 +; + +------------------------------------------------------------------------------- + +create or alter view v_max_non_paid_invoice as +-- 09.09.2014: source for fast get MAX snd_id (==> doc_list.id) before making +-- random choise of accepted invoice (optype=2100) which still has some +-- cost to be paid (==> has records in PDistr) +-- PLAN (P ORDER PDISTR_SNDOP_RCVOP_SNDID_DESC) +select p.snd_id as id -- this value match doc_list.id +from pdistr p +where + p.snd_optype_id = 2100 -- fn_oper_invoice_add() + and p.rcv_optype_id = 4000 -- fn_oper_pay_to_supplier() +order by + p.snd_optype_id desc, p.rcv_optype_id desc, p.snd_id desc +rows 1 +; + +------------------------------------------------------------------------------- + +create or alter view v_random_find_non_paid_realizn as +-- 09.09.2014. Used in dynamic SQL in sp_get_random_id, see SP_PAYMENT_COMMON +-- Source for random choose document of written-off realization (optype=3400) +-- which still has some cost to be paid (==> has records in PDistr) +-- Introduced instead of v_p`distr_non_paid_realization to avoid scans doc_list +select p.snd_id as id -- this value match doc_list.id +from pdistr p +where + p.snd_optype_id = 3400 -- fn_oper_retail_realization() + and p.rcv_optype_id = 5000 -- fn_oper_pay_from_customer() +; + +------------------------------------------------------------------------------- + +create or alter view v_min_non_paid_realizn as +-- 09.09.2014: source for fast get min snd_id (==> doc_list.id) before making +-- random choise of written-off realization (optype=3400) which still has some +-- cost to be paid (==> has records in PDistr) +-- PLAN (P ORDER PDISTR_SNDOP_RCVOP_SNDID_ASC) +select p.snd_id as id -- this value match doc_list.id +from pdistr p +where + p.snd_optype_id = 3400 -- fn_oper_retail_realization() + and p.rcv_optype_id = 5000 -- fn_oper_pay_from_customer() +order by + snd_id +rows 1 +; + +------------------------------------------------------------------------------- + +create or alter view v_max_non_paid_realizn as +-- 09.09.2014: source for fast get MAX snd_id (==> doc_list.id) before making +-- random choise of written-off realization (optype=3400) which still has some +-- cost to be paid (==> has records in PDistr) +-- PLAN (P ORDER PDISTR_SNDOP_RCVOP_SNDID_DESC) +select p.snd_id as id -- this value match doc_list.id +from pdistr p +where + p.snd_optype_id = 3400 -- fn_oper_retail_realization() + and p.rcv_optype_id = 5000 -- fn_oper_pay_from_customer() +order by + p.snd_optype_id desc, p.rcv_optype_id desc, p.snd_id desc +rows 1 +; + + +------------------------------------------------------------------------------- + +create or alter view v_saldo_invnt as +-- 21.04.2014 +-- ::: NB ::: this view can return NEGATIVE remainders in qty_xxx +-- if parallel attaches call of sp_make_invnt_saldo +-- (because of deleting rows in invnt_turnover_log in this SP) +-- !!! look at table INVNT_SALDO for actual remainders !!! +select + ng.ware_id + ,sum(o.m_qty_clo * ng.qty_diff) qty_clo + ,sum(o.m_qty_clr * ng.qty_diff) qty_clr + ,sum(o.m_qty_ord * ng.qty_diff) qty_ord + ,sum(o.m_qty_sup * ng.qty_diff) qty_sup + ,sum(o.m_qty_avl * ng.qty_diff) qty_avl + ,sum(o.m_qty_res * ng.qty_diff) qty_res + ,sum(o.m_cost_inc * ng.qty_diff) qty_inc + ,sum(o.m_cost_out * ng.qty_diff) qty_out + ,sum(o.m_cost_inc * ng.cost_diff) cost_inc + ,sum(o.m_cost_out * ng.cost_diff) cost_out + -- amount "on hand" as it seen by accounter: + ,sum(o.m_qty_avl * ng.qty_diff) + sum(o.m_qty_res * ng.qty_diff) qty_acn + -- total cost "on hand" in purchasing prices: + ,sum(o.m_cost_inc * ng.cost_diff) - sum(o.m_cost_out * ng.cost_diff) cost_acn +from invnt_turnover_log ng +join optypes o on ng.optype_id + 0 = o.id + 0 -- ==> for 3.0 only: hash join, reduce number of`optypes` scans! +group by 1 +; + + + +--------------------------- + +create or alter view v_doc_detailed as +-- Used in all app unit for returning final resultset to client. +-- Also very useful for debugging +select + h.id doc_id, + h.optype_id, + o.mcode as oper, + h.base_doc_id, + d.id doc_data_id, + d.ware_id, + d.qty, + coalesce(d.cost_purchase, h.cost_purchase) cost_purchase, -- cost in purchase price + coalesce(d.cost_retail, h.cost_retail) cost_retail, -- cost in retail price + n.qty_clo, -- amount of ORDERED by customer (which we not yet sent to supplier) + n.qty_clr, -- amount of REFUSED by customer + n.qty_ord, -- amount that we have already sent to supplier + n.qty_sup, -- amount in invoices of supplier, in state + n.qty_inc, -- amount of incomings (when invoices were added) + n.qty_avl, -- amount avaliable to be sold (usially - due to refused client orders) + n.qty_res, -- amount in reserve to be sold to customer + n.qty_out, -- amount of written-off + n.cost_inc, -- total cost of incomes, in purchase prices + n.cost_out, -- total cost of outgoings, in purchase prices + n.qty_acn, + n.cost_acn, + h.state_id, + h.agent_id, + d.dts_edit, + h.dts_open, + h.dts_fix, + h.dts_clos, + s.mcode state +from doc_list h + join optypes o on h.optype_id = o.id + join doc_states s on h.state_id=s.id + left join doc_data d on h.id = d.doc_id + -- ::: NB ::: do NOT remove "left" from here otherwise performance will degrade + -- (FB will not push predicate inside view; 22.04.2014) + LEFT join v_saldo_invnt n on d.ware_id=n.ware_id +--left join sp_saldo_invnt(d.ware_id) n on 1=1 -- speed +; + +------------------------------------------------------------------------------- +-- ### v i e w s f o r m o n i t o r g a t h e r e d d a t a #### +------------------------------------------------------------------------------- +-- Following views are used in 'oltp_isql_run_worker.bat' during its first +-- launched ISQL session makes final report. These views will contain data +-- only when config parameter mon_unit_perf=1. +create or alter view z_mon_stat_per_units as +-- 29.08.2014: data from measuring statistics per each unit +-- (need FB rev. >= 60013: new mon$ counters were introduced, 28.08.2014) +-- 25.01.2015: added rec_locks, rec_confl. +-- 06.02.2015: reorder columns, made all `max` values most-right +select + m.unit + ,count(*) iter_counts + -------------- speed ------------- + ,avg(m.elapsed_ms) avg_elap_ms + ,avg(1000.00 * ( (m.rec_seq_reads + m.rec_idx_reads + m.bkv_reads ) / nullif(m.elapsed_ms,0)) ) avg_rec_reads_sec + ,avg(1000.00 * ( (m.rec_inserts + m.rec_updates + m.rec_deletes ) / nullif(m.elapsed_ms,0)) ) avg_rec_dmls_sec + ,avg(1000.00 * ( m.rec_backouts / nullif(m.elapsed_ms,0)) ) avg_bkos_sec + ,avg(1000.00 * ( m.rec_purges / nullif(m.elapsed_ms,0)) ) avg_purg_sec + ,avg(1000.00 * ( m.rec_expunges / nullif(m.elapsed_ms,0)) ) avg_xpng_sec + ,avg(1000.00 * ( m.pg_fetches / nullif(m.elapsed_ms,0)) ) avg_fetches_sec + ,avg(1000.00 * ( m.pg_marks / nullif(m.elapsed_ms,0)) ) avg_marks_sec + ,avg(1000.00 * ( m.pg_reads / nullif(m.elapsed_ms,0)) ) avg_reads_sec + ,avg(1000.00 * ( m.pg_writes / nullif(m.elapsed_ms,0)) ) avg_writes_sec + -------------- reads --------------- + ,avg(m.rec_seq_reads) avg_seq + ,avg(m.rec_idx_reads) avg_idx + ,avg(m.rec_rpt_reads) avg_rpt + ,avg(m.bkv_reads) avg_bkv + ,avg(m.frg_reads) avg_frg + ,avg(m.bkv_per_seq_idx_rpt) avg_bkv_per_rec + ,avg(m.frg_per_seq_idx_rpt) avg_frg_per_rec + ---------- modifications ---------- + ,avg(m.rec_inserts) avg_ins + ,avg(m.rec_updates) avg_upd + ,avg(m.rec_deletes) avg_del + ,avg(m.rec_backouts) avg_bko + ,avg(m.rec_purges) avg_pur + ,avg(m.rec_expunges) avg_exp + --------------- io ----------------- + ,avg(m.pg_fetches) avg_fetches + ,avg(m.pg_marks) avg_marks + ,avg(m.pg_reads) avg_reads + ,avg(m.pg_writes) avg_writes + ----------- locks and conflicts ---------- + ,avg(m.rec_locks) avg_locks + ,avg(m.rec_confl) avg_confl + ,datediff( minute from min(m.dts) to max(m.dts) ) workload_minutes + --- 06.02.2015 moved here all MAX values, separate them from AVG ones: --- + ,max(m.rec_seq_reads) max_seq + ,max(m.rec_idx_reads) max_idx + ,max(m.rec_rpt_reads) max_rpt + ,max(m.bkv_reads) max_bkv + ,max(m.frg_reads) max_frg + ,max(m.bkv_per_seq_idx_rpt) max_bkv_per_rec + ,max(m.frg_per_seq_idx_rpt) max_frg_per_rec + ,max(m.rec_inserts) max_ins + ,max(m.rec_updates) max_upd + ,max(m.rec_deletes) max_del + ,max(m.rec_backouts) max_bko + ,max(m.rec_purges) max_pur + ,max(m.rec_expunges) max_exp + ,max(m.pg_fetches) max_fetches + ,max(m.pg_marks) max_marks + ,max(m.pg_reads) max_reads + ,max(m.pg_writes) max_writes + ,max(m.rec_locks) max_locks + ,max(m.rec_confl) max_confl +from mon_log m +group by unit +; + +-------------------------------------------------------------------------------- + +create or alter view z_mon_stat_per_tables +as +-- 29.08.2014: data from measuring statistics per each unit+table +-- (new table MON$TABLE_STATS required, see srv_fill_mon, srv_fill_tmp_mon) +-- 25.01.2015: added rec_locks, rec_confl; +-- ::: do NOT add `bkv_per_seq_idx_rpt` and `frg_per_seq_idx_rpt` into WHERE +-- clause with check sum > 0, because they can be NULL, see DDL! +-- 06.02.2015: reorder columns, made all `max` values most-right +select + t.table_name + ,t.unit + ,count(*) iter_counts + --------------- reads --------------- + ,avg(t.rec_seq_reads) avg_seq + ,avg(t.rec_idx_reads) avg_idx + ,avg(t.rec_rpt_reads) avg_rpt + ,avg(t.bkv_reads) avg_bkv + ,avg(t.frg_reads) avg_frg + ,avg(t.bkv_per_seq_idx_rpt) avg_bkv_per_rec + ,avg(t.frg_per_seq_idx_rpt) avg_frg_per_rec + ---------- modifications ---------- + ,avg(t.rec_inserts) avg_ins + ,avg(t.rec_updates) avg_upd + ,avg(t.rec_deletes) avg_del + ,avg(t.rec_backouts) avg_bko + ,avg(t.rec_purges) avg_pur + ,avg(t.rec_expunges) avg_exp + ----------- locks and conflicts ---------- + ,avg(t.rec_locks) avg_locks + ,avg(t.rec_confl) avg_confl + ,datediff( minute from min(t.dts) to max(t.dts) ) elapsed_minutes + --- 06.02.2015 moved here all MAX values, separate them from AVG ones: --- + ,max(t.rec_seq_reads) max_seq + ,max(t.rec_idx_reads) max_idx + ,max(t.rec_rpt_reads) max_rpt + ,max(t.bkv_reads) max_bkv + ,max(t.frg_reads) max_frg + ,max(t.bkv_per_seq_idx_rpt) max_bkv_per_rec + ,max(t.frg_per_seq_idx_rpt) max_frg_per_rec + ,max(t.rec_inserts) max_ins + ,max(t.rec_updates) max_upd + ,max(t.rec_deletes) max_del + ,max(t.rec_backouts) max_bko + ,max(t.rec_purges) max_pur + ,max(t.rec_expunges) max_exp + ,max(t.rec_locks) max_locks + ,max(t.rec_confl) max_confl +from mon_log_table_stats t +where + t.rec_seq_reads + + t.rec_idx_reads + + t.rec_rpt_reads + + t.bkv_reads + + t.frg_reads + + t.rec_inserts + + t.rec_updates + + t.rec_deletes + + t.rec_backouts + + t.rec_purges + + t.rec_expunges + + t.rec_locks + + t.rec_confl + > 0 +group by t.table_name,t.unit +; + +------------------------------------------------------------------------------- + +create or alter view z_estimated_perf_per_minute as +-- Do NOT delete! 28.10.2015. +-- This view is used in oltp_isql_run_worker.bat (.sh) when it creates final report. +-- Table PERF_ESTIMATED is filled up by temply created .sql which scans log +-- of 1st ISQL session (which, in turn, makes final report). This log contains +-- rows like this: +-- EST_OVERALL_AT_MINUTE_SINCE_BEG 0.00 0 +-- - where 1st number is estimated performance value and 2nd is datediff(minute) +-- from test start to the moment when each business transaction SUCCESSFULLY finished. +-- Data in this view is performance value in *dynamic* but with detalization per +-- ONE minute, from time when all ISQL sessions start (rather then all other reports +-- which make starting point after database was warmed up). +-- This report can help to find proper value of warm-time in oltpNN_config. +select + e.minute_since_test_start + ,avg(e.success_count) avg_estimated + ,min(e.success_count) / nullif(avg(e.success_count), 0) min_to_avg_ratio + ,max(e.success_count) / nullif(avg(e.success_count), 0) max_to_avg_ratio + ,count(e.success_count) rows_aggregated + ,count(distinct e.att_id) distinct_attachments -- 22.12.2015: helps to ensure that all ISQL sessions were alive in every minute of test work time +from perf_estimated e +where e.minute_since_test_start>0 +group by e.minute_since_test_start +; + + + +------------------------------------------------------------------------------- +--###################### d e b u g v i e w s ############################ +------------------------------------------------------------------------------- + +create or alter view z_current_test_settings as +-- This view is used in 1run_oltp_emulbat (.sh) to display current settings before test run. +-- Do NOT delete it! +select s.mcode as setting_name, s.svalue as setting_value, 'init' as stype +from settings s +where s.working_mode='INIT' and s.mcode='WORKING_MODE' + +UNION ALL + +select '--- Detalization for WORKING_MODE: ---' as setting_name, '' as setting_value, 'inf1' as stype +from rdb$database +UNION ALL + +select ' ' || t.mcode as setting_name, t.svalue as setting_value, 'mode' as stype +from settings s +join settings t on s.svalue=t.working_mode +where s.working_mode='INIT' and s.mcode='WORKING_MODE' + +UNION ALL + +select '--- Main test settings: ---' as setting_name, '' as setting_value, 'inf2' as stype +from rdb$database +UNION ALL + +select setting_name, setting_value, 'main' as stype +from ( + select ' ' || s.mcode as setting_name, s.svalue as setting_value + from settings s + where + s.working_mode='COMMON' + and s.mcode + in ( + 'BUILD_WITH_SPLIT_HEAVY_TABS' + ,'BUILD_WITH_SEPAR_QDISTR_IDX' + ,'BUILD_WITH_QD_COMPOUND_ORDR' + ,'ENABLE_MON_QUERY' + ,'TRACED_UNITS' + ,'HALT_TEST_ON_ERRORS' + ,'QMISM_VERIFY_BITSET' + ,'LOG_PK_VIOLATION' + ,'ENABLE_RESERVES_WHEN_ADD_INVOICE' + ) + order by setting_name +) x +; + +-------------------------------------------------------------------------------- + +create or alter view z_settings_pivot as +-- vivid show of all workload settings (pivot rows to separate columns +-- for each important kind of setting). Currently selected workload mode +-- is marked by '*' and displayed in UPPER case, all other - in lower. +-- The change these settings open oltp_main_filling.sql and find EB +-- with 'v_insert_settings_statement' variable +select + iif(s.working_mode=c.svalue,'* '||upper(s.working_mode), lower(s.working_mode) ) as working_mode + ,cast(max( iif(mcode = upper('c_wares_max_id'), s.svalue, null ) ) as int) as wares_cnt + ,cast(max( iif(mcode = upper('c_customer_doc_max_rows'), s.svalue, null ) ) as int) as cust_max_rows + ,cast(max( iif(mcode = upper('c_supplier_doc_max_rows'), s.svalue, null ) ) as int) as supp_max_rows + ,cast(max( iif(mcode = upper('c_customer_doc_max_qty'), s.svalue, null ) ) as int) as cust_max_qty + ,cast(max( iif(mcode = upper('c_supplier_doc_max_qty'), s.svalue, null ) ) as int) as supp_max_qty + ,cast(max( iif(mcode = upper('c_number_of_agents'), s.svalue, null ) ) as int) as agents_cnt +from settings s +left join (select s.svalue from settings s where s.mcode='working_mode') c on s.working_mode=c.svalue +where s.mcode +in ( + 'c_wares_max_id' + ,'c_customer_doc_max_rows' + ,'c_supplier_doc_max_rows' + ,'c_customer_doc_max_qty' + ,'c_supplier_doc_max_qty' + ,'c_number_of_agents' +) +group by s.working_mode, c.svalue +order by + iif(s.working_mode starting with 'DEBUG', 0, + iif(s.working_mode starting with 'SMALL', 1, + iif(s.working_mode starting with 'MEDIUM', 2, + iif(s.working_mode starting with 'LARGE', 3, + iif(s.working_mode starting with 'HEAVY', 5, + null) ) ) ) ) + nulls last + ,s.working_mode +; + +-------------------------------------------------------------------------------- + +create or alter view z_qd_indices_ddl as + +-- This view is used in 1run_oltp_emulbat (.sh) to display current DDL of QDistr xor XQD* indices. +-- Do NOT delete it! + +with recursive +r as ( + select + ri.rdb$relation_name tab_name + ,ri.rdb$index_name idx_name + ,rs.rdb$field_name fld_name + ,rs.rdb$field_position fld_pos + ,cast( trim(rs.rdb$field_name) as varchar(512)) as idx_key + from rdb$indices ri + join rdb$index_segments rs using ( rdb$index_name ) + left join ( + select cast(t.svalue as int) as svalue + from settings t + where t.working_mode='COMMON' and t.mcode='BUILD_WITH_SPLIT_HEAVY_TABS' + ) t on 1=1 + where + rs.rdb$field_position = 0 + and ( + t.svalue = 0 and trim( ri.rdb$relation_name ) is not distinct from 'QDISTR' + or + t.svalue = 1 and trim( ri.rdb$relation_name ) starts with 'XQD_' + ) + + UNION ALL + + select + r.tab_name + ,r.idx_name + ,rs.rdb$field_name + ,rs.rdb$field_position + ,r.idx_key || ',' || trim(rs.rdb$field_name) + from r + join rdb$indices ri + on r.idx_name = ri.rdb$index_name + join rdb$index_segments rs + on + ri.rdb$index_name = rs.rdb$index_name + and r.fld_pos +1 = rs.rdb$field_position +) +select r.tab_name, r.idx_name, max(r.idx_key) as idx_key +from r +group by r.tab_name, r.idx_name +; + +-------------------------------------------------------------------------------- + +create or alter view z_halt_log as -- upd 28.09.2014 +select p.id, p.fb_gdscode, p.unit, p.trn_id, p.dump_trn, p.att_id, p.exc_unit, p.info, p.ip, p.dts_beg, e.fb_mnemona, p.exc_info,p.stack +from perf_log p +join ( + select g.trn_id, g.fb_gdscode + from perf_log g + -- 335544558 check_constraint Operation violates CHECK constraint @1 on view or table @2. + -- 335544347 not_valid Validation error for column @1, value "@2". + -- if table has unique constraint: 335544665 unique_key_violation (violation of PRIMARY or UNIQUE KEY constraint "T1_XY" on table "T1") + -- if table has only unique index: 335544349 no_dup (attempt to store duplicate value (visible to active transactions) in unique index "T2_XY") + where g.fb_gdscode in ( 0 -- 3.0 SC trouble, core-4565 (gdscode can come in when-section with value = 0!) + ,335544347, 335544558 -- not_valid or viol. of check constr. + ,335544665, 335544349 -- viol. of UNQ constraint or just unq. index (without binding to unq constr) + ,335544466 -- viol. of FOREIGN KEY constraint @1 on table @2 + ,335544838 -- Foreign key reference target does not exist (when attempt to ins/upd in DETAIL table FK-field with value which doesn`t exists in PARENT) + ,335544839 -- Foreign key references are present for the record (when attempt to upd/del in PARENT table PK-field and rows in DETAIL (no-cascaded!) exists for old value) + ) + group by 1,2 +) g +on p.trn_id = g.trn_id +left join fb_errors e on p.fb_gdscode = e.fb_gdscode +order by p.id +; + +-------------------------------------------------------------------------------- + +create or alter view z_agents_tunrover_saldo as +-- 4 misc reports and debug, do not delete: agent turnovers and sums; only in 3.0 +select + m.agent_id, m.doc_id, o.mcode, o.acn_type + ,o.m_supp_debt * m.cost_purchase vol_supp + ,o.m_cust_debt * m.cost_retail vol_cust + ,sum(o.m_supp_debt * m.cost_purchase)over(partition by m.agent_id) sum_supp + ,sum(o.m_cust_debt * m.cost_retail )over(partition by m.agent_id) sum_cust +from money_turnover_log m +join optypes o on m.optype_id = o.id +; + +------------------------------------------------------------------------------ +-- create or alter view z_mon_stat_per_units ==> moved in 'oltp_misc_debug.sql' +-- create or alter view z_mon_stat_per_tables ==> moved in 'oltp_misc_debug.sql' +------------------------------------------------------------------------------ + + + +-------------------------------------------------------------------------------- +-- ######################## T R I G G E R S ################################ +-------------------------------------------------------------------------------- + +set term ^; +-- not needed in 3.0, see DDL of their `ID` field ('generated as identity'): +--create or alter trigger wares_bi for wares active +--before insert position 0 +--as +--begin +-- new.id = coalesce(new.id, gen_id(g_common, 1) ); +--end +--^ +-- +--create or alter trigger phrases_bi for phrases active +--before insert position 0 +--as +--begin +-- new.id = coalesce(new.id, gen_id(g_common, 1) ); +--end +--^ +-- +--create or alter trigger agents_bi for agents active +--before insert position 0 +--as +--begin +-- new.id = coalesce(new.id, gen_id(g_common, 1) ); +--end +--^ +-- +--create or alter trigger invnt_saldo_bi for invnt_saldo active +--before insert position 0 +--as +--begin +-- new.id = coalesce(new.id, gen_id(g_common, 1) ); +--end +--^ + +create or alter trigger money_turnover_log_bi for money_turnover_log active before insert position 0 as +begin + new.id = coalesce(new.id, gen_id(g_common, 1) ); -- new.id is NOT null for all docs except payments +end + +^ -- money_turnover_log_bi + +create or alter trigger perf_log_bi for perf_log active before insert position 0 as +begin + new.id = coalesce(new.id, gen_id(g_perf_log, 1) ); +end + +^ -- perf_log_bi +-- not needed in 3.0, see DDL of their `ID` field ('generated as identity'): +--create or alter trigger pdistr_bi for pdistr +--active before insert position 0 as +--begin +-- new.id = coalesce(new.id, gen_id(g_common,1)); +--end +-- +--^ -- pdistr_bi +-- +--create or alter trigger pstorned_bi for pstorned +--active before insert position 0 as +--begin +-- new.id = coalesce(new.id, gen_id(g_common,1)); +--end +-- +--^ -- pstorned_bi + +set term ;^ + +set term ^; + +-------------------------------------------------------------------------------- + +create or alter trigger doc_list_biud for doc_list +active before insert or update or delete position 0 +as + declare v_msg dm_info = ''; + declare v_info dm_info = ''; + declare v_this dm_dbobj = 'doc_list_biud'; + declare v_affects_on_inventory_balance smallint; + declare v_old_op type of dm_idb; + declare v_new_op type of dm_idb; +begin + + if ( inserting ) then + new.id = coalesce(new.id, gen_id(g_common,1)); + + v_info = 'dh='|| iif(not inserting, old.id, new.id) + || ', op='||iif(inserting,'INS',iif(updating,'UPD','DEL')) + || iif(not inserting, ' old='||old.optype_id, '') + || iif(not deleting, ' new='||new.optype_id, ''); + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log( 1, v_this, null, v_info ); + + if (inserting) then + begin + new.state_id = coalesce(new.state_id, fn_doc_open_state()); + -- 'i'=incoming; 'o' = outgoing; 's' = payment to supplier; 'c' = payment from customer + new.acn_type = (select o.acn_type from optypes o where o.id = new.optype_id); + v_msg = v_msg || ' new.id='||new.id||', acn_type='||coalesce(new.acn_type,''); + end + + if ( not deleting ) then + begin + if ( new.state_id <> fn_doc_open_state() ) then + begin + new.dts_fix = coalesce(new.dts_fix, 'now'); + new.dts_clos = iif( new.state_id in( fn_doc_clos_state(), fn_doc_canc_state() ), 'now', null); + end + if ( new.state_id = fn_doc_open_state() ) then -- 31.03.2014 + begin + new.dts_fix = null; + new.dts_clos = null; + end + end + else + v_msg = v_msg || ' doc='||old.id||', op='||old.optype_id; + + -- add to invnt_turnover_log + -- rows that are 'totalled' in doc_data when make doc content in sp_create_doc_using_fifo + -- (there are multiple rows from qdistr and multiple calls to sp_add_doc_data for each one) + v_old_op=iif(inserting, null, old.optype_id); + v_new_op=iif(deleting, null, new.optype_id); + + select max(maxvalue(abs(o.m_qty_clo), abs(o.m_qty_clr), abs(o.m_qty_ord), abs(o.m_qty_sup), abs(o.m_qty_avl), abs(o.m_qty_res))) q_mult_abs_max + from optypes o + where o.id in( :v_old_op, :v_new_op ) + into v_affects_on_inventory_balance; + + -- 20.09.2014 1825: remove calls of s`p_add_invnt_log to SPs (reduce scans of doc_data) + -- 16.09.2014: moved here from d`oc_data_biud: + if ( v_affects_on_inventory_balance > 0 and (deleting or updating and new.optype_id is distinct from old.optype_id) ) + then + execute procedure sp_kill_qty_storno( + old.id, + old.optype_id, + iif( deleting, null, new.optype_id), + iif( updating, 1, 0), + iif( deleting, 1, 0) + ); + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this,null,v_msg); + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + 'error in '||v_this, + gdscode, + v_msg, + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + +^ -- doc_list_biud + +------------------------------------------------------------------------------- + +create or alter trigger doc_list_aiud for doc_list +active after insert or update or delete position 0 +as + declare v_affects_on_monetary_balance smallint; + declare v_affects_on_inventory_balance smallint; + declare v_doc_id dm_idb; + declare v_old_op type of dm_idb; + declare v_new_op type of dm_idb; + declare v_old_mult type of dm_sign = null; + declare v_new_mult type of dm_sign = null; + declare v_affects_on_customer_saldo smallint; + declare v_affects_on_supplier_saldo smallint; + declare v_oper_changing_cust_saldo type of dm_idb; + declare v_oper_changing_supp_saldo type of dm_idb; + declare v_cost_diff type of dm_cost; + declare v_msg type of dm_info = ''; + declare v_this dm_dbobj = 'doc_list_aiud'; + declare v_catch_bitset bigint; +begin + + -- AFTER trigger on master table (THIS) will fired BEFORE any triggers on detail (doc_data)! + -- www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1081231&msg=15685218 + v_affects_on_monetary_balance = 1; + v_affects_on_inventory_balance = 1; + v_doc_id=iif(deleting, old.id, new.id); + v_old_op=iif(inserting, null, old.optype_id); + v_new_op=iif(deleting, null, new.optype_id); + + v_msg = 'dh='|| iif(not inserting, old.id, new.id) + || ', op='||iif(inserting,'INS',iif(updating,'UPD','DEL')) + || iif(not inserting, ' old='||old.optype_id, '') + || iif(not deleting, ' new='||new.optype_id, ''); + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log( 1, v_this , null, v_msg ); + + select + iif(m_cust_4old<>0, m_cust_4old, m_supp_4old), -- they are mutually excluded: only ONE can be <> 0 + iif(m_cust_4new<>0, m_cust_4new, m_supp_4new), -- they are mutually excluded: only ONE can be <> 0 + iif(m_cust_4old<>0, v_old_op, iif(m_cust_4new<>0, v_new_op, 0)) v_oper_changing_cust_saldo, + iif(m_supp_4old<>0, v_old_op, iif(m_supp_4new<>0, v_new_op, 0)) v_oper_changing_supp_saldo, + iif(m_cust_4old<>0 or m_cust_4new<>0, 1, 0) v_affects_on_customer_saldo, + iif(m_supp_4old<>0 or m_supp_4new<>0, 1, 0) v_affects_on_supplier_saldo, + q_mult_abs_max + from( + select + max(iif(o.id=:v_old_op, o.m_cust_debt, null)) m_cust_4old, + max(iif(o.id=:v_old_op, o.m_supp_debt, null)) m_supp_4old, + max(iif(o.id=:v_new_op, o.m_cust_debt, null)) m_cust_4new, + max(iif(o.id=:v_new_op, o.m_supp_debt, null)) m_supp_4new, + max(iif(o.id=:v_old_op, :v_old_op, null)) v_old_op, + max(iif(o.id=:v_new_op, :v_new_op, null)) v_new_op, + max(maxvalue(abs(o.m_qty_clo), abs(o.m_qty_clr), abs(o.m_qty_ord), abs(o.m_qty_sup), abs(o.m_qty_avl), abs(o.m_qty_res))) q_mult_abs_max + from optypes o + where o.id in( :v_old_op, :v_new_op ) + ) + into + v_old_mult, + v_new_mult, + v_oper_changing_cust_saldo, + v_oper_changing_supp_saldo, + v_affects_on_customer_saldo, + v_affects_on_supplier_saldo, + v_affects_on_inventory_balance; + + --------------- + if ( v_affects_on_inventory_balance > 0 + and + ( + inserting and new.cost_purchase > 0 + or + updating + and ( new.cost_purchase is distinct from old.cost_purchase + or + new.optype_id is distinct from old.optype_id + ) + or deleting + ) + ) then + begin + v_catch_bitset = cast(rdb$get_context('USER_SESSION','QMISM_VERIFY_BITSET') as bigint); + if ( bin_and( v_catch_bitset, 1 ) <> 0 ) then + begin + -- check that number of rows in qdistr+qstorned exactly equals + -- add to perf_log row with exc. info about mismatch, gds=335544558 + execute procedure srv_find_qd_qs_mism( iif(deleting, old.id, new.id), iif(deleting, :v_old_op, :v_new_op), iif(deleting, 1, 0) ); + end + + if ( bin_and( v_catch_bitset, 2 ) <> 0 ) then + begin + --execute procedure srv_catch_neg_remainders( new.ware_id, new.optype_id, new.doc_list_id, new.doc_data_id, new.qty_diff ); + execute procedure srv_check_neg_remainders( iif(deleting, old.id, new.id), iif(deleting, :v_old_op, :v_new_op) ); + end + end + --------------- + + if ( coalesce(v_old_mult,0)=0 and coalesce(v_new_mult,0)=0 + ) then -- this op does NOT affect on MONETARY turnovers (of customer or supplier) + --#### + v_affects_on_monetary_balance = 0; + --#### + + if ( v_affects_on_monetary_balance <> 0 ) then + begin + if ( + new.cost_purchase is distinct from old.cost_purchase + or + new.cost_retail is distinct from old.cost_retail + ) + then -- creating new doc or deleting it + begin + ---------- + if ( v_oper_changing_cust_saldo <> 0 or v_oper_changing_supp_saldo <> 0 ) then + begin + if ( inserting or updating ) then + begin + + if ( v_oper_changing_cust_saldo <> 0 ) then + v_cost_diff = new.cost_retail - iif(inserting, 0, old.cost_retail); + else + v_cost_diff = new.cost_purchase - iif(inserting, 0, old.cost_purchase); + + -- 1: add rows for v_cost_diff for being storned further + execute procedure sp_multiply_rows_for_pdistr( + new.id, + new.agent_id, + v_new_op, + v_cost_diff + ); + + -- 2: storn old docs by v_cost_diff ( fn_oper_pay_to_supplier, fn_oper_pay_from_customer ) + execute procedure sp_make_cost_storno( new.id, :v_new_op, new.agent_id, :v_cost_diff ); + + end -- ins or upd + else --- deleting in doc_list + begin + -- return back records from pstorned to pdistr + -- ::: nb ::: use MERGE instead of insert because partial + -- cost storning (when move PART of cost from pdistr to pstorned) + execute procedure sp_kill_cost_storno( old.id ); + end -- deleting + + end -- v_oper_changing_cust_saldo<>0 or v_oper_changing_supp_saldo<>0 + + ------------------- add to money_turnover_log ---------------------- + execute procedure sp_add_money_log( + iif(not deleting, new.id, old.id), + 0, -- v_old_mult, + 0, -- old.agent_id, + 0, -- v_old_op, + 0, -- old.cost_purchase, + 0, -- old.cost_retail, + 1, -- v_new_mult, + iif(not deleting, new.agent_id, old.agent_id), + iif(not deleting, new.optype_id, old.optype_id), --v_new_op, + iif(not deleting, new.cost_purchase - coalesce(old.cost_purchase,0), -old.cost_purchase), -- new.cost_purchase, + iif(not deleting, new.cost_retail - coalesce(old.cost_retail,0), - old.cost_retail) -- new.cost_retail + ); + + end + -- ######################################## + else -- cost_purchase and cost_retail - the same (sp_add_invoice_to_stock; sp_reserve_write_off; s`p_cancel_adding_invoice; s`p_cancel_write_off) + -- ######################################## + + if (updating) then + begin + if ( --new.agent_id is distinct from old.agent_id -- todo later, not implemented yet + --or + new.optype_id is distinct from old.optype_id + ) then + begin + ----------- + if ( v_oper_changing_cust_saldo <> 0 or v_oper_changing_supp_saldo <> 0 ) then + begin + if ( v_new_op in (v_oper_changing_cust_saldo, v_oper_changing_supp_saldo) ) then + begin + -- F O R W A R D operation: sp_add_invoice_to_stock; sp_reserve_write_off + v_cost_diff = iif( v_oper_changing_cust_saldo <> 0, new.cost_retail, new.cost_purchase ); + + -- 1: add rows for rest of cost for being storned by further docs + execute procedure sp_multiply_rows_for_pdistr( + new.id, + new.agent_id, + v_new_op, + v_cost_diff + ); + -- 2: storn old docs by v_cost_diff (sp_add_invoice_to_stock; sp_reserve_write_off) + execute procedure sp_make_cost_storno( new.id, :v_new_op, new.agent_id, :v_cost_diff ); + + end + else -- R E V E R T operation: s`p_cancel_adding_invoice, s`p_cancel_write_off + begin + -- AFTER trigger on master table (THIS) will fired BEFORE any triggers on detail (doc_data)! + -- http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1081231&msg=15685218 + -- return back records from pstorned to pdistr + -- ::: nb ::: use MERGE instead of insert because partial + -- cost storning (when move PART of cost from pdistr to pstorned) + execute procedure sp_kill_cost_storno( old.id ); + end -- v_new_op in (v_oper_changing_cust_saldo, v_oper_changing_supp_saldo) ==> true / false + + end -- ( v_oper_changing_cust_saldo <> 0 or v_oper_changing_supp_saldo <> 0 ) + + ------------------- add to money_turnover_log ---------------------- + execute procedure sp_add_money_log( + old.id, + v_old_mult, + old.agent_id, + v_old_op, + old.cost_purchase, + old.cost_retail, + v_new_mult, + new.agent_id, + v_new_op, + new.cost_purchase, + new.cost_retail + ); + end -- changes occur in agent_id or optype_id + end -- updating + + end -- v_affects_on_monetary_balance <> 0 + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this); + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + 'error in '||v_this, + gdscode, + v_msg, + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + +^ -- doc_list_aiud + +set term ;^ + + +------------------------------------------------------------------------------- + +set term ^; +-- NOTE: currently tis trigger is created with INactive state. +-- It will be Active at the end of all database building process, see 'oltp_data_filling.sql' +create or alter trigger trg_connect inactive on connect as +begin + execute procedure sp_init_ctx; + if ( rdb$get_context ('SYSTEM', 'NETWORK_PROTOCOL') is null ) then + begin + insert into perf_log(unit, info ) + values( 'trg_connect', 'attach using NON-TCP protocol' ); + end +end + +^ -- trg_connect + +set term ;^ + + +-------------------------------------------------------------------------------- +-- #################### C O R E P R O C s a n d F U N C s ########## +-------------------------------------------------------------------------------- +set term ^; + +create or alter procedure sp_add_doc_list( + a_gen_id type of dm_idb, -- preliminary obtained from sequence (used in s`p_make_qty_storno) + a_optype_id type of dm_idb, + a_agent_id type of dm_idb, + a_new_state type of dm_idb default null, + a_base_doc_id type of dm_idb default null, -- need only for customer reserve which linked to client order + a_new_cost_purchase type of dm_cost default 0, + a_new_cost_retail type of dm_cost default 0 +) returns( + id dm_idb, + dbkey dm_dbkey +) +as +begin + -- add single record into doc_list (document header) + insert into doc_list( + id, -- 06.09.2014 2200 + optype_id, + agent_id, + state_id, + base_doc_id, + cost_purchase, + cost_retail + ) + values( + coalesce(:a_gen_id, gen_id(g_common,1)), + :a_optype_id, + :a_agent_id, + :a_new_state, + :a_base_doc_id, + :a_new_cost_purchase, + :a_new_cost_retail + ) + returning id, rdb$db_key + into id, dbkey; + + rdb$set_context('USER_SESSION','ADD_INFO','doc='||id||': created Ok'); -- to be displayed in log of 1run_oltp_emul.bat (debug) + + if ( rdb$get_context('USER_TRANSACTION','INIT_DATA_POP') = 1 ) + then -- now we only run INITIAL data filling, see 1run_oltp_emul.bat + -- 18.07.2014: added gen_id to analyze in init data populate script, + -- see 1run_oltp_emul.bat + id = id + 0 * gen_id(g_init_pop, 1); + + suspend; +end + +^ -- sp_add_doc_list + +------------------------------------------------ + +create or alter procedure sp_add_doc_data( + a_doc_id dm_idb, + a_optype_id dm_idb, + a_gen_dd_id dm_idb, -- preliminary calculated ID for new record in doc_data (reduce lock-contention of GEN page) + a_gen_nt_id dm_idb, -- preliminary calculated ID for new record in invnt_turnover_log (reduce lock-contention of GEN page) + a_ware_id dm_idb, + a_qty type of dm_qty, + a_cost_purchase type of dm_cost, + a_cost_retail type of dm_cost +) returns( + id dm_idb, + dbkey dm_dbkey +) +as + declare v_this dm_dbobj = 'sp_add_doc_data'; +begin + -- add to performance log timestamp about start/finish this unit: + -- uncomment if need analyze perormance in mon_log tables + -- + update settings set svalue=',sp_make_qty_storno,sp_add_doc_data,pdetl_add,' where mcode='TRACED_UNITS'; + -- execute procedure sp_add_perf_log(1, v_this, null, 'a_gen_dd_id='||trim(coalesce(a_gen_dd_id||'=>ins','null'))||', a_dbkey: '||trim(iif(a_dbkey is null,'isNull','hasVal=>upd')) ); + + -- insert single record into doc_data + -- :: NB :: update & "if row_count = 0 ? => insert" is much effective + -- then insert & "when uniq_violation ? => update" (no backouts, less fetches) + if ( a_gen_dd_id is NOT null ) then + insert into doc_data( + id, + doc_id, + ware_id, + qty, + cost_purchase, + cost_retail, + dts_edit) + values( + :a_gen_dd_id, + :a_doc_id, + :a_ware_id, + :a_qty, + :a_cost_purchase, + :a_cost_retail, + 'now') + returning id, rdb$db_key into id, dbkey; + else + begin + update doc_data t set + t.qty = t.qty + :a_qty, + t.cost_purchase = t.cost_purchase + :a_cost_purchase, + t.cost_retail = t.cost_retail + :a_cost_retail, + t.dts_edit = 'now' + where t.doc_id = :a_doc_id and t.ware_id = :a_ware_id + returning t.id, t.rdb$db_key into id, dbkey; + + if ( row_count = 0 ) then + insert into doc_data( doc_id, ware_id, qty, cost_purchase, cost_retail, dts_edit) + values( :a_doc_id, :a_ware_id, :a_qty, :a_cost_purchase, :a_cost_retail, 'now') + returning id, rdb$db_key into id, dbkey; + end + ---------------------------------------------------------------------------- + -- 20.09.2014: move here from trigger on doc_list + -- (reduce scans of doc_data) + if ( :a_qty <> 0 ) then + insert into invnt_turnover_log( + id + ,ware_id + ,qty_diff + ,cost_diff + ,doc_list_id + ,doc_pref + ,doc_data_id + ,optype_id + ) values ( + :a_gen_nt_id + ,:a_ware_id + ,:a_qty + ,:a_cost_purchase + ,:a_doc_id + ,fn_mcode_for_oper(:a_optype_id) + ,:id + ,:a_optype_id + ); + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + -- uncomment if need analyze perormance in mon_log tables: + --execute procedure sp_add_to_perf_log(v_this,null,'out: id='||id); + + suspend; + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + 'out: id='||coalesce(id,''), + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + +^ -- sp_add_doc_data + +create or alter function fn_get_random_quantity( + a_ctx_max_name dm_ctxnv +) +returns dm_qty as + declare v_min double precision; + declare v_max double precision; +begin + v_min = 0.5; + v_max = cast( rdb$get_context('USER_SESSION',a_ctx_max_name) as int) + 0.5; + return cast( v_min + rand()* (v_max - v_min) as int); + +end + +^ -- fn_get_random_quantity + +create or alter function fn_get_random_cost( + a_ctx_min_name dm_ctxnv, + a_ctx_max_name dm_ctxnv, + a_make_check_before smallint default 1 +) +returns dm_cost as + declare v_min double precision; + declare v_max double precision; +begin + if (a_make_check_before = 1) then + execute procedure sp_check_ctx( + 'USER_SESSION',a_ctx_min_name, + 'USER_SESSION',a_ctx_max_name + ); + v_min = cast( rdb$get_context('USER_SESSION',a_ctx_min_name) as int) - 0.5; + v_max = cast( rdb$get_context('USER_SESSION',a_ctx_max_name) as int) + 0.5; + return cast( v_min + rand()* (v_max - v_min) as dm_cost); + +end + +^ -- fn_get_random_cost + +create or alter function fn_get_random_customer returns bigint as +begin + return (select id_selected from sp_get_random_id('v_all_customers', null, null, 0) ); +end +^ + +create or alter function fn_get_random_supplier returns bigint as +begin + return (select id_selected from sp_get_random_id('v_all_suppliers', null, null, 0) ); +end + +^ -- fn_get_random_customer + +------------------------------------------------------------------------------ + +create or alter procedure sp_make_qty_storno( + a_optype_id dm_idb + ,a_agent_id dm_idb + ,a_state_id type of dm_idb default null + ,a_client_order_id type of dm_idb default null + ,a_rows_in_shopcart int default null + ,a_qsum_in_shopcart dm_qty default null +) +returns ( + doc_list_id bigint +) +as + declare c_gen_inc_step_qd int = 100; -- size of `batch` for get at once new IDs for QDistr (reduce lock-contention of gen page) + declare v_gen_inc_iter_qd int; -- increments from 1 up to c_gen_inc_step_qd and then restarts again from 1 + declare v_gen_inc_last_qd dm_idb; -- last got value after call gen_id (..., c_gen_inc_step_qd) + declare c_gen_inc_step_dd int = 20; -- size of `batch` for get at once new IDs for doc_data (reduce lock-contention of gen page) + declare v_gen_inc_iter_dd int; -- increments from 1 up to c_gen_inc_step_dd and then restarts again from 1 + declare v_gen_inc_last_dd dm_idb; -- last got value after call gen_id (..., c_gen_inc_step_dd) + declare c_gen_inc_step_nt int = 20; -- size of `batch` for get at once new IDs for invnt_turnover_log (reduce lock-contention of gen page) + declare v_gen_inc_iter_nt int; -- increments from 1 up to c_gen_inc_step_dd and then restarts again from 1 + declare v_gen_inc_last_nt dm_idb; -- last got value after call gen_id (..., c_gen_inc_step_dd) + declare v_inserting_table dm_dbobj; + declare v_id type of dm_idb; + declare v_curr_tx bigint; + declare v_ware_id dm_idb; + declare v_dh_new_id bigint; + declare v_dd_new_id bigint; + declare v_nt_new_id dm_idb; + declare v_dd_dbkey dm_dbkey; + declare v_dd_clo_id dm_idb; + declare v_doc_data_purchase_sum dm_cost; + declare v_doc_data_retail_sum dm_cost; + declare v_doc_list_purchase_sum dm_cost; + declare v_doc_list_retail_sum dm_cost; + declare v_doc_list_dbkey dm_dbkey; + declare v_rows_added int; + declare v_storno_sub smallint; + declare v_qty_storned_acc type of dm_qty; + declare v_qty_required type of dm_qty; + declare v_qty_could_storn type of dm_qty; + declare v_snd_optype_id type of dm_idb; + declare v_rcv_optype_id type of dm_idb; + declare v_next_rcv_op type of dm_idb; + declare v_this dm_dbobj = 'sp_make_qty_storno'; + declare v_call dm_dbobj; + declare v_info dm_info; + declare v_rows int = 0; + declare v_lock int = 0; + declare v_skip int = 0; + declare v_dummy bigint; + declare v_sign dm_sign; + declare v_cq_id dm_idb; + declare v_cq_snd_list_id dm_idb; + declare v_cq_snd_data_id dm_idb; + declare v_cq_snd_qty dm_qty; + declare v_cq_snd_purchase dm_cost; + declare v_cq_snd_retail dm_cost; + declare v_cq_snd_optype_id dm_idb; + declare v_cq_rcv_optype_id type of dm_idb; + declare v_cq_trn_id dm_idb; + declare v_cq_dts timestamp; + + declare c_shop_cart cursor for ( + select + id, + dd_clo_id, + snd_optype_id, + rcv_optype_id, + qty, + storno_sub + from ( + select + c.id, + cast(null as dm_idb) as dd_clo_id, -- 22.09.2014 + c.snd_optype_id, + c.rcv_optype_id, + c.qty, + c.storno_sub + from tmp$shopping_cart c + + UNION ALL + + select + c.id, + c.snd_id, -- 22.09.2014, for clo_res + r.snd_optype_id, + c.rcv_optype_id, + c.qty, + r.storno_sub + from tmp$shopping_cart c + INNER join rules_for_qdistr r + on :a_client_order_id is NOT null + -- only in 3.0: hash join (todo: check perf when NL, create indices) + and c.rcv_optype_id + 0 = r.rcv_optype_id + 0 -- PLAN HASH (R NATURAL, C NATURAL) + and r.storno_sub = 2 + ) u + order by id, storno_sub + ); + ---------------------------------------------------------------------------- + -- 22.09.2014: two separate cursors for diff storno_sub + declare c_make_amount_distr_1 cursor for ( + select + q.id + ,q.doc_id as snd_list_id + ,q.snd_id as snd_data_id + ,q.snd_qty + ,q.snd_purchase + ,q.snd_retail + ,q.snd_optype_id + ,q.rcv_optype_id + ,q.trn_id + ,q.dts + -- 'v_qdistr_source_1' initially this is one-to-one projection of 'QDistr' table. + -- But it can be replaced with 'AUTOGEN_QDnnnn' when config create_with_split_heavy_tabs = 1. + from v_qdistr_source_1 q + where + q.ware_id = :v_ware_id -- find invoices to be storned storning by new customer reserve, and all other ops except storning client orders + and q.snd_optype_id = :v_snd_optype_id + and q.rcv_optype_id = :v_rcv_optype_id + order by + q.doc_id + + 0 -- handle docs in FIFO order + ,:v_sign * q.id -- attempt to reduce locks: odd and even Tx handles rows in opposite manner (for the same doc) thus have a chance do not encounter locked rows at all + ); + + declare c_make_amount_distr_2 cursor for ( + select + q.id + ,q.doc_id as snd_list_id + ,q.snd_id as snd_data_id + ,q.snd_qty + ,q.snd_purchase + ,q.snd_retail + ,q.snd_optype_id + ,q.rcv_optype_id + ,q.trn_id + ,q.dts + -- 'v_qdistr_source_2' initially this is one-to-one projection of 'QDistr' table. + -- But it can be replaced with 'AUTOGEN_QD1000' when config create_with_split_heavy_tabs = 1. + from v_qdistr_source_2 q + where + q.ware_id = :v_ware_id -- find client orders to be storned by new customer reserve + and q.snd_optype_id = :v_snd_optype_id + and q.rcv_optype_id = :v_rcv_optype_id + and q.snd_id = :v_dd_clo_id + order by + q.doc_id + + 0 -- handle docs in FIFO order + ,:v_sign * q.id -- attempt to reduce locks: odd and even Tx handles rows in opposite manner (for the same doc) thus have a chance do not encounter locked rows at all + ); +begin + + -- Issue about QDistr & QStorned: for each SINGLE record from doc_data with + -- qty= table QDistr initially contains DIFFERENT records (if no storning + -- yet occur for that amount from doc_data). + -- Each storning takes off some records from this set and "moves" them into + -- table QStorned. This SP *does* such storning. + ---------------------------------------------------------------------------- + -- Performs attempt to make distribution of AMOUNTS which were added to "sender" docs + -- and then 'multiplied' (added in QDISTR table) using "value-to-rows" + -- algorithm in sp_multiply_rows_for_qdistr. If some row is locked now, + -- SUPRESS exc`eption and skip to next one. If required amount can NOT + -- be satisfied, it will be reduced (in tmp$shopping_cart) or even REMOVED + -- at all from tmp$shopping_cart (without raising exc: we must minimize them) + -- ::: NB ::: + -- Method: "try_to_lock_src => upd_confl ? skip : {ins_target & del_in_src}" + -- is more than 3 times FASTER than: "ins_tgt => uniq_viol ? skip : del_in_src" + -- (see benchmark in letter to dimitr 26.08.2014 13:00) + -- 01.09.2014: refactored, remove cursor on doc_data (huge values of IDX_READS!) + -- 02.09.2014: move here code block from sp_create_doc_using_fifo, further reduce scans of doc_data + -- 06.09.2014: doc_data: 3 idx_reads per each unique ware_id (one here, two in SP s`rv_find_qd_qs_mism) + + select r.rcv_optype_id + from rules_for_qdistr r + where r.snd_optype_id = :a_optype_id + into v_next_rcv_op; + + v_call = v_this; + -- doc_list.id must be defined PRELIMINARY, before cursor that handles with qdistr: + v_dh_new_id = gen_id(g_common, 1); + + v_info = + 'op='||a_optype_id + ||', next_op='||coalesce(v_next_rcv_op,'') + ||coalesce(', clo='||a_client_order_id, ''); + execute procedure sp_add_perf_log(1, v_call, null, v_info); + + v_qty_could_storn = 0; + v_rows_added = 0; + v_doc_list_purchase_sum = 0; + v_doc_list_retail_sum = 0; + + v_gen_inc_iter_dd = 1; + c_gen_inc_step_dd = coalesce( 1 + a_rows_in_shopcart, 20 ); -- adjust value to increment IDs in DOC_DATA at one call of gen_id + v_gen_inc_last_dd = gen_id( g_doc_data, :c_gen_inc_step_dd );-- take bulk IDs at once (reduce lock-contention for GEN page) + + v_gen_inc_iter_qd = 1; + c_gen_inc_step_qd = coalesce( 1 + a_qsum_in_shopcart, 100 ); -- adjust value to increment IDs in QDISTR at one call of gen_id + v_gen_inc_last_qd = gen_id( g_qdistr, :c_gen_inc_step_qd );-- take bulk IDs at once (reduce lock-contention for GEN page) + + v_gen_inc_iter_nt = 1; + c_gen_inc_step_nt = coalesce( 1 + a_rows_in_shopcart, 20 ); -- adjust value to increment IDs in INVNT_TURNOVER_LOG at one call of gen_id + v_gen_inc_last_nt = gen_id( g_common, :c_gen_inc_step_nt );-- take bulk IDs at once (reduce lock-contention for GEN page) + + v_sign = iif( bin_and(current_transaction, 1)=0, 1, -1); + + -- rules_for_qdistr.storno_sub = 2 - storno data of clo when creating customer RESERVE: + -- MODE SND_OPTYPE_ID RCV_OPTYPE_ID STORNO_SUB + -- mult_rows_only 1000 3300 2 + -- Result of cursor c_shop_cart for ware_id=1 when call from sp_customer_reserve: + -- ID SND_OPTYPE_ID RCV_OPTYPE_ID QTY STORNO_SUB + -- 1 2100 3300 1 1 + -- 1 1000 3300 1 2 + open c_shop_cart; + while (1=1) do + begin + fetch c_shop_cart + into v_ware_id, v_dd_clo_id, v_snd_optype_id, v_rcv_optype_id, v_qty_required, v_storno_sub; + if ( row_count = 0 ) then leave; + + v_qty_could_storn = iif(v_storno_sub=1, 0, v_qty_could_storn); + v_qty_required = iif(v_storno_sub=1, v_qty_required, v_qty_could_storn); + + v_dd_dbkey = iif(v_storno_sub=1, null, v_dd_dbkey); + v_dd_new_id = iif(v_storno_sub=1, null, v_dd_new_id); + + v_qty_storned_acc = 0; -- how many units will provide required Qty from CURRENT LINE of shopping cart + v_doc_data_purchase_sum = 0; + v_doc_data_retail_sum = 0; + + if ( v_storno_sub = 1 ) then + open c_make_amount_distr_1; + else + open c_make_amount_distr_2; + ------------------------------------------------------------------------ + while ( :v_qty_storned_acc < :v_qty_required ) do + begin + if ( v_storno_sub = 1 ) then + fetch c_make_amount_distr_1 + into + v_cq_id,v_cq_snd_list_id,v_cq_snd_data_id + ,v_cq_snd_qty,v_cq_snd_purchase,v_cq_snd_retail + ,v_cq_snd_optype_id,v_cq_rcv_optype_id + ,v_cq_trn_id,v_cq_dts; + else + fetch c_make_amount_distr_2 + into + v_cq_id,v_cq_snd_list_id,v_cq_snd_data_id + ,v_cq_snd_qty,v_cq_snd_purchase,v_cq_snd_retail + ,v_cq_snd_optype_id,v_cq_rcv_optype_id + ,v_cq_trn_id,v_cq_dts; + + if ( row_count = 0 ) then leave; + v_info = 'fetch ' + ||iif( v_storno_sub = 1, 'c_make_amount_distr_1', 'c_make_amount_distr_2') + ||', qd.id='||v_cq_id; + v_rows = v_rows + 1; -- total ATTEMPTS to make delete/update in QDistr + + -- ### A.C.H.T.U.N.G ### + -- Make increment of `v_gen_inc_iter_**` ALWAYS BEFORE any lock-conflict statements + -- (otherwise duplicates will appear in ID because of suppressing lock-conflict ex`c.) + -- ##################### + if ( v_storno_sub = 1 ) then + begin -- calculate subsequent value for doc_data.id from previously obtained batch: + if ( v_gen_inc_iter_qd >= c_gen_inc_step_qd ) then -- its time to get another batch of IDs + begin + v_gen_inc_iter_qd = 1; + -- take subsequent bulk IDs at once (reduce lock-contention for GEN page) + v_gen_inc_last_qd = gen_id( g_qdistr, :c_gen_inc_step_qd ); + end + + if ( v_qty_storned_acc = 0 ) then + begin + -- NO rows could be locked in QDistr (by now) for providing + -- QTY from current line of shopping cart ==> we did not yet + -- inserted row into doc_data with :v_ware_id ==> get subseq. + -- value for :v_dd_new_id from `pool`: + if ( v_gen_inc_iter_dd >= c_gen_inc_step_dd ) then -- its time to get another batch of IDs + begin + v_gen_inc_iter_dd = 1; + -- take subsequent bulk IDs at once (reduce lock-contention for GEN page) + v_gen_inc_last_dd = gen_id( g_doc_data, :c_gen_inc_step_dd ); + end + v_dd_new_id = v_gen_inc_last_dd - ( c_gen_inc_step_dd - v_gen_inc_iter_dd ); + v_gen_inc_iter_dd = v_gen_inc_iter_dd + 1; + end + end + + + -- 26.10.2015. Additional begin..end block needs for providing DML + -- 'atomicity' of BOTH tables pdistr & pstorned! Otherwise changes + -- can become inconsistent if online validation will catch table-2 + -- after this code finish changes on table-1 but BEFORE it will + -- start to change table-2. + -- See CORE-4973 (example of WRONG code which did not used this addi block!) + begin + -- We can place delete sttmt BEFORE insert because of using explicit cursor and + -- fetch old fields data (which is to be moved into QStorned) into declared vars: + if ( v_storno_sub = 1 ) then + begin + v_call = v_this || ':try_del_qdsub1'; + -- execute procedure sp_add_perf_log(1, v_call, null, v_info); -- 10.02.2015 + -- rdb$set_context('USER_TRANSACTION','DBG_MAKE_STSUB1_TRY_DEL_QD_ID', v_cq_id); + + delete from v_qdistr_source_1 q where current of c_make_amount_distr_1; --- lock_conflict can occur here + + -- rdb$set_context('USER_TRANSACTION','DBG_MAKE_STSUB1_OK_DEL_QD_ID', v_cq_id); + -- execute procedure sp_add_perf_log(0, v_call); + end -- v_storno_sub = 1 + else + begin + + v_call = v_this || ':try_del_qdsub2'; + -- execute procedure sp_add_perf_log(1, v_call, null, v_info); + -- rdb$set_context('USER_TRANSACTION','DBG_MAKE_STSUB2_TRY_DEL_QD_ID', v_cq_id); + + -- When config parameter 'create_with_split_heavy_tabs' is 1 then 'v_qdistr_source_2' should be changed to 'XQD_*' + delete from v_qdistr_source_2 q where current of c_make_amount_distr_2; --- lock_conflict can occur here + + -- rdb$set_context('USER_TRANSACTION','DBG_MAKE_STSUB2_OK_DEL_QD_ID', v_cq_id); + -- execute procedure sp_add_perf_log(0, v_call); + end -- v_storno_sub = 2 + + if ( v_storno_sub = 1 ) then -- ==> distr_mode containing 'new_doc' + begin + v_inserting_table = 'qdistr'; + -- iter=1: v_id = 12345 - (100-1); iter=2: 12345 - (100-2); ... + v_id = v_gen_inc_last_qd - ( c_gen_inc_step_qd - v_gen_inc_iter_qd ); + + -- debug info for logging in srv_log_dups_qd_qs if PK + -- violation will occur on INSERT INTO QSTORNED statement + -- (remained for possible analysis): + v_call = v_this || ':try_ins_qdsub1'; + v_info = v_info || ', try INSERT into QDistr id='||v_id; + + -- execute procedure sp_add_perf_log(1, v_call, null, v_info); -- 10.02.2015, debug + -- rdb$set_context('USER_TRANSACTION','DBG_MAKE_STSUB1_TRY_INS_QD_ID', v_id); + + insert into v_qdistr_target_1 ( + id, + doc_id, + ware_id, + snd_optype_id, + rcv_optype_id, + snd_id, + snd_qty, + snd_purchase, + snd_retail) + values( + :v_id, + :v_dh_new_id, + :v_ware_id, + :a_optype_id, + :v_next_rcv_op, + :v_dd_new_id, + :v_cq_snd_qty, + :v_cq_snd_purchase, + :v_cq_snd_retail + ); + + -- rdb$set_context('USER_TRANSACTION','DBG_MAKE_STSUB1_OK_INS_QD_ID', v_id); + -- execute procedure sp_add_perf_log(0, v_call); + + v_gen_inc_iter_qd = v_gen_inc_iter_qd + 1; + v_info = v_info || ' - ok'; + end -- v_storno_sub = 1 + + v_inserting_table = 'qstorned'; + v_id = v_cq_id; + + -- debug info for logging in srv_log_dups_qd_qs if PK + -- violation will occur on INSERT INTO QSTORNED statement + -- (remained for possible analysis): + v_info = v_info||', try INSERT into QStorned: id='||:v_id; + v_call = v_this || ':try_ins_qStorn'; + + -- execute procedure sp_add_perf_log(1, v_call, null, v_info); -- 10.02.2015, debug + -- rdb$set_context('USER_TRANSACTION','DBG_MAKE_QSTORN_TRY_INS_QS_ID', v_id); + + if ( v_storno_sub = 1 ) then + insert into v_qstorned_target_1 ( + id, + doc_id, ware_id, dts, -- do NOT specify field `trn_id` here! 09.10.2014 2120 + snd_optype_id, snd_id, snd_qty, + rcv_optype_id, + rcv_doc_id, -- 30.12.2014 + rcv_id, + snd_purchase, snd_retail + ) values ( + :v_id + ,:v_cq_snd_list_id, :v_ware_id, :v_cq_dts -- dis 09.10.2014 2120: :v_cq_trn_id, + ,:v_cq_snd_optype_id, :v_cq_snd_data_id,:v_cq_snd_qty + ,:v_cq_rcv_optype_id + ,:v_dh_new_id -- 30.12.2014 + ,:v_dd_new_id + ,:v_cq_snd_purchase,:v_cq_snd_retail + ); + else + insert into v_qstorned_target_2 ( + id, + doc_id, ware_id, dts, -- do NOT specify field `trn_id` here! 09.10.2014 2120 + snd_optype_id, snd_id, snd_qty, + rcv_optype_id, + rcv_doc_id, -- 30.12.2014 + rcv_id, + snd_purchase, snd_retail + ) values ( + :v_id + ,:v_cq_snd_list_id, :v_ware_id, :v_cq_dts -- dis 09.10.2014 2120: :v_cq_trn_id, + ,:v_cq_snd_optype_id, :v_cq_snd_data_id,:v_cq_snd_qty + ,:v_cq_rcv_optype_id + ,:v_dh_new_id -- 30.12.2014 + ,:v_dd_new_id + ,:v_cq_snd_purchase,:v_cq_snd_retail + ); + + + v_info = v_info || ' - ok'; + + v_qty_storned_acc = v_qty_storned_acc + v_cq_snd_qty; -- ==> will be written in doc_data.qty (actual amount that could be gathered) + v_lock = v_lock + 1; -- total number of SUCCESSFULY locked records + + if ( v_storno_sub = 1 ) then + begin + -- increment sums that will be written into doc_data line: + v_qty_could_storn = v_qty_could_storn + v_cq_snd_qty; + v_doc_data_purchase_sum = v_doc_data_purchase_sum + v_cq_snd_purchase; + v_doc_data_retail_sum = v_doc_data_retail_sum + v_cq_snd_retail; + end + end -- begin..end for atomicity of changes several tables (CORE-4973!) + when any do + -- ::: nb ::: do NOT use "wh`en gdscode " followed by "wh`en any": + -- the latter ("w`hen ANY") will handle ALWAYS, even if "w`hen " + -- catched it's kind of exception! + -- 1) tracker.firebirdsql.org/browse/CORE-3275 + -- "W`HEN ANY handles exceptions even if they are handled in another W`HEN section" + -- 2) sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1088890&msg=15879669 + begin + if ( fn_is_lock_trouble(gdscode) ) then + -- suppress this kind of exc`eption and + -- skip to next record! + v_skip = v_skip + 1; + else + begin + -- ############################################### + -- PK violation on INSERT INTO QSTORNED, log this: + -- ############################################### + if ( fn_is_uniqueness_trouble(gdscode) ) then + -- 12.02.2015: the reason of PK violations is unpredictable order + -- of UNDO, ultimately explained by dimitr, see letters in e-mail. + -- Also: sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1142271&msg=17257984 + execute procedure srv_log_dups_qd_qs( -- 09.10.2014: add log info using auton Tx + :v_call, + gdscode, + :v_inserting_table, + :v_id, + :v_info + ); + + exception; -- ::: nb ::: anonimous but in when-block! + end + end + end -- cursor on QDistr find rows for storning amount from tmp$shopping_cart for current v_ware_id, and MAKE such storning (move them in QStorned table) + if ( v_storno_sub = 1 ) then + close c_make_amount_distr_1; + else + close c_make_amount_distr_2; + + + if ( v_dd_new_id is not null and v_storno_sub = 1 ) then + begin + if ( v_qty_storned_acc > 0 ) then + begin + if (doc_list_id is null) then + begin + -- add new record in doc_list (header) + execute procedure sp_add_doc_list( + :v_dh_new_id + ,:a_optype_id + ,:a_agent_id + ,:a_state_id + ,:a_client_order_id + ) + returning_values :doc_list_id, :v_doc_list_dbkey; + end + + if ( v_gen_inc_iter_nt = c_gen_inc_step_nt ) then -- its time to get another batch of IDs + begin + v_gen_inc_iter_nt = 1; + -- take subsequent bulk IDs at once (reduce lock-contention for GEN page) + v_gen_inc_last_nt = gen_id( g_common, :c_gen_inc_step_nt ); + end + v_nt_new_id = v_gen_inc_last_nt - ( c_gen_inc_step_nt - v_gen_inc_iter_nt ); + v_gen_inc_iter_nt = v_gen_inc_iter_nt + 1; + + -- single update of doc_data for each ware after scanning N records in qdistr: + -- (remove call of sp_multiply_rows_for_qdistr from d`oc_data_aiud): + execute procedure sp_add_doc_data( + :v_dh_new_id -- preliminary defined above + ,:a_optype_id + ,:v_dd_new_id -- preliminary calculated above (to reduce lock-contention of GEN page) + ,:v_nt_new_id -- preliminary calculated above (to reduce lock-contention of GEN page) + ,:v_ware_id + ,:v_qty_could_storn + ,:v_doc_data_purchase_sum + ,:v_doc_data_retail_sum + ) + returning_values :v_dummy, :v_dd_dbkey; + + v_rows_added = v_rows_added + 1; + -- increment sums that will be written into doc header: + v_doc_list_purchase_sum = v_doc_list_purchase_sum + v_doc_data_purchase_sum; + v_doc_list_retail_sum = v_doc_list_retail_sum + v_doc_data_retail_sum; + end + end + + end -- cursor on tmp$shopping_cart c [join rules_for_qdistr r] + close c_shop_cart; + + + if ( :doc_list_id is NOT null and v_rows_added > 0) then -- v_lock > 0 ) then + begin + -- single update of doc header (not for every row added in doc_data) + -- Trigger d`oc_list_aiud will call sp_add_invnt_log to add rows to invnt_turnover_log + update doc_list h set + h.cost_purchase = :v_doc_list_purchase_sum, + h.cost_retail = :v_doc_list_retail_sum, + h.dts_fix = iif( :a_state_id = fn_doc_fix_state(), 'now', h.dts_fix) + where h.rdb$db_key = :v_doc_list_dbkey; + + end -- ( :doc_list_id is NOT null ) + else + begin + v_info = + fn_mcode_for_oper(a_optype_id) + ||iif(a_optype_id = fn_oper_retail_reserve(), ', clo='||coalesce( a_client_order_id, ''), '') + ||', rows in tmp$cart: '||(select count(*) from tmp$shopping_cart); + + if ( a_client_order_id is null ) then -- ==> all except call of sp_customer_reserve for client order + exception ex_cant_find_row_for_qdistr using( a_optype_id, (select count(*) from tmp$shopping_cart) ); + --'no rows found for FIFO-distribution: optype=@1, rows in tmp$shopping_cart=@2'; + end + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + v_call = v_this; + execute procedure sp_add_perf_log(0, v_call, null, 'dh='||coalesce(:doc_list_id,'')||', qd ('||iif(:v_sign=1,'asc','dec')||'): capt='||v_lock||', skip='||v_skip||', scan='||v_rows||'; dd: add='||v_rows_added ); + + suspend; + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + v_info, + v_call, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + +^ -- sp_make_qty_storno + +-------------------------------------------------------------------------------- + +create or alter procedure sp_split_into_words( + a_text dm_name, + a_dels varchar(50) default ',.<>/?;:''"[]{}`~!@#$%^&*()-_=+\\|/', + a_special char(1) default ' ' +) +returns ( + word dm_name +) as +begin +-- Aux SP, used only in oltp_data_filling.sql to filling table PATTERNS +-- with miscelan combinations of words to be used in SIMILAR TO testing. +for + with recursive + j as( -- loop #1: transform list of delimeters to rows + select s,1 i, substring(s from 1 for 1) del + from( + select replace(:a_dels,:a_special,'') s + from rdb$database + ) + + UNION ALL + + select s, i+1, substring(s from i+1 for 1) + from j + where substring(s from i+1 for 1)<>'' + ) + + ,d as( + select :a_text s, :a_special sp from rdb$database + ) + ,e as( -- loop #2: perform replacing each delimeter to `space` + select d.s, replace(d.s, j.del, :a_special) s1, j.i, j.del + from d join j on j.i=1 + + UNION ALL + + select e.s, replace(e.s1, j.del, :a_special) s1, j.i, j.del + from e + -- nb: here 'column unknown: e.i' error will be on old builds of 2.5, + -- e.g: WI-V2.5.2.26540 (letter from Alexey Kovyazin, 24.08.2014 14:34) + join j on j.i = e.i + 1 + ) + ,f as( + select s1 from e order by i desc rows 1 + ) + + ,r as ( -- loop #3: perform split text into single words + select iif(t.k>0, substring(t.s from t.k+1 ), t.s) s, + iif(t.k>0,position( del, substring(t.s from t.k+1 )),-1) k, + t.i, + t.del, + iif(t.k>0,left(t.s, t.k-1),t.s) word + from( + select f.s1 s, d.sp del, position(d.sp, s1) k, 0 i from f cross join d + )t + + UNION ALL + + select iif(r.k>0, substring(r.s from r.k+1 ), r.s) s, + iif(r.k>0,position(r.del, substring(r.s from r.k+1 )),-1) k, + r.i+1, + r.del, + iif(r.k>0,left(r.s, r.k-1),r.s) word + from r + where r.k>=0 + ) + select word from r where word>'' + into + word +do + suspend; +end + +^ -- sp_split_into_words + +create or alter procedure srv_random_unit_choice( + a_included_modes dm_info default '', + a_included_kinds dm_info default '', + a_excluded_modes dm_info default '', + a_excluded_kinds dm_info default '' +) +returns( + unit dm_name, + sort_prior int, + rnd_weight int, + r double precision, + c int, + n int +) as + declare r_max int; + declare v_last_recalc_idx_dts timestamp; + declare v_last_recalc_idx_minutes_ago int; + declare v_this dm_dbobj = 'srv_random_unit_choice'; + declare c_unit_for_mon_query dm_dbobj = 'srv_fill_mon'; -- do NOT change the name of thios SP! + declare function fn_internal_enable_mon_query returns smallint deterministic as + begin + return ( cast(rdb$get_context('USER_SESSION', 'ENABLE_MON_QUERY') as smallint) ); + end +begin + -- refactored 18.07.2014 (for usage in init data pop) + -- sample: select * from srv_random_unit_choice( '','creation,state_next','','removal' ) + -- (will return first randomly choosen record related to creation of document + -- or to changing its state in 'forward' way; excludes all cancellations and change + -- doc states in 'backward') + a_included_modes = coalesce( a_included_modes, ''); + a_included_kinds = coalesce( a_included_kinds, ''); + a_excluded_modes = coalesce( a_excluded_modes, ''); + a_excluded_kinds = coalesce( a_excluded_kinds, ''); + + select g.dts_beg + from perf_log g where g.unit = 'srv_recalc_idx_stat' + order by g.dts_beg desc rows 1 + into v_last_recalc_idx_dts; + -- FB 3.0: on database with size = 101Gb, non-cached: + -- 454 ms, 92 read(s), 95 fetch(es) + -- Table Natural Index + -- **************************************************** + -- PERF_LOG 1 + + if ( rdb$get_context('USER_SESSION','PERF_WATCH_BEG')is not null ) then -- see SP_CHECK_TO_STOP_WORK + v_last_recalc_idx_dts = maxvalue(v_last_recalc_idx_dts, cast(rdb$get_context('USER_SESSION','PERF_WATCH_BEG') as timestamp) ); + + v_last_recalc_idx_minutes_ago = coalesce( datediff(minute from v_last_recalc_idx_dts to cast('now' as timestamp)), cast( rdb$get_context('USER_SESSION', 'RECALC_IDX_MIN_INTERVAL') as int ) ); + + r_max = rdb$get_context('USER_SESSION', 'BOP_RND_MAX'); + if ( r_max is null ) then + begin + select max( b.random_selection_weight ) from business_ops b into r_max; + rdb$set_context('USER_SESSION', 'BOP_RND_MAX', r_max); + end + + r = rand() * r_max; + delete from tmp$perf_log p where p.stack = :v_this; + + insert into tmp$perf_log(unit, aux1, aux2, stack) + select o.unit, o.sort_prior, o.random_selection_weight, :v_this + from business_ops o + where o.random_selection_weight >= :r + and (fn_internal_enable_mon_query() = 1 or o.unit <> :c_unit_for_mon_query) + and ( -- 27.11.2015: skip call of index statistics recalc if it was done not so far: + o.unit <> 'srv_recalc_idx_stat' + or + o.unit = 'srv_recalc_idx_stat' + and + :v_last_recalc_idx_minutes_ago + >= + cast( rdb$get_context('USER_SESSION', 'RECALC_IDX_MIN_INTERVAL') as int ) + ) + and (:a_included_modes = '' or :a_included_modes||',' containing trim(o.mode)||',' ) + and (:a_included_kinds = '' or :a_included_kinds||',' containing trim(o.kind)||',' ) + and (:a_excluded_modes = '' or :a_excluded_modes||',' NOT containing trim(o.mode)||',' ) + and (:a_excluded_kinds = '' or :a_excluded_kinds||',' NOT containing trim(o.kind)||',' ) + ; + c = row_count; + n = cast( 0.5+rand()*(c+0.5) as int ); + n = minvalue(maxvalue(1, n),c); + + select p.unit, p.aux1, p.aux2 + from tmp$perf_log p + where p.aux2 >= :r + order by rand() + rows :n to :n -- get SINGLE row! + into unit, sort_prior, rnd_weight; + + delete from tmp$perf_log p where p.stack = :v_this; -- 18.08.2014! cleanup this temply created data! + + suspend; + +end + + +^ -- srv_random_unit_choice + +--------------------------------------------------------------------------- + +create or alter procedure srv_diag_pay_distr( -- ::: NB ::: 3.0 only! + a_doc_id dm_idb default null +) returns( + result varchar(3), -- 'ok.' | 'err' + ptab varchar(8), + ptab_id int, + snd_oper dm_mcode, + snd_id dm_idb, + rcv_oper dm_mcode, + rcv_id dm_idb, + ptab_cost dm_cost, + ptab_sum_cost dm_cost, + payment_id dm_idb, + payment_cost dm_cost +) +as +begin + for + select + iif( iif( h.optype_id=fn_oper_pay_from_customer(), h.cost_retail, h.cost_retail) = sum(ps.cost)over( partition by iif(ps.ptab='pdistr',ps.snd_optype_id,ps.rcv_optype_id)), 'ok.','err' ) result + ,cast(ps.ptab as varchar(8)) as ptab + ,ps.id as ptab_id + ,ps.snd_oper + ,ps.snd_id as ptab_snd_id + ,ps.rcv_oper + ,ps.rcv_id as ptab_rcv_id + ,ps.cost as ptab_cost + ,sum(ps.cost)over( partition by iif(ps.ptab='pdistr',ps.snd_optype_id,ps.rcv_optype_id)) ptab_sum_cost + --,ps.trn_id as ptab_trn + ,h.id as payment_id + ,iif( h.optype_id=fn_oper_pay_from_customer(), h.cost_retail, h.cost_retail) as payment_cost + from ( + select + 'pdistr' ptab, + pd.trn_id, + pd.snd_optype_id, + so.mcode as snd_oper, + pd.rcv_optype_id, + ro.mcode as rcv_oper, + pd.id, + pd.snd_id, + pd.snd_cost cost, -- NOT YET storned value + cast(null as int) as rcv_id + from pdistr pd + --join doc_list h on pd.snd_id = h.id and pd.snd_optype_id = h.optype_id + join optypes so on pd.snd_optype_id=so.id + join optypes ro on pd.rcv_optype_id=ro.id + where (pd.snd_id = :a_doc_id or :a_doc_id is null) -- OR'ed optimization, 3.0 only + + UNION ALL + + select + 'pstorned', + ps.trn_id, + ps.snd_optype_id, + so.mcode as snd_oper, + ps.rcv_optype_id, + ro.mcode as rcv_oper, + ps.id, + ps.snd_id, + ps.rcv_cost, -- ALREADY STORNED value + ps.rcv_id + from pstorned ps + --join doc_list h on ps.rcv_id = h.id and ps.rcv_optype_id = h.optype_id + join optypes so on ps.snd_optype_id=so.id + join optypes ro on ps.rcv_optype_id=ro.id + where (ps.rcv_id = :a_doc_id or :a_doc_id is null) -- OR'ed optimization, 3.0 only + ) ps + join doc_list h on h.id = iif(ps.ptab='pdistr',ps.snd_id,ps.rcv_id) + into + result + ,ptab + ,ptab_id + ,snd_oper + ,snd_id + ,rcv_oper + ,rcv_id + ,ptab_cost + ,ptab_sum_cost + ,payment_id + ,payment_cost + do suspend; +end + +^ -- srv_diag_pay_distr + +create or alter procedure sys_list_to_rows ( + A_LST blob sub_type 1 segment size 80, + A_DEL char(1) = ',') +returns ( + LINE integer, + EOF integer, + ITEM varchar(8192)) +AS + declare pos_ int; + declare noffset int = 1; + declare beg int; + declare buf varchar(30100); +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 + +^ -- sys_list_to_rows + +create or alter procedure sys_get_proc_ddl ( + a_proc varchar(31), + a_mode smallint = 1, + a_include_setterm smallint = 1) +returns ( + src varchar(32760)) +as +begin + if ( a_proc is null or + not singular(select * from rdb$procedures p where p.rdb$procedure_name starting with upper(:a_proc)) + ) then + begin + src = '-- invalid input argument a_proc = ' || coalesce('"'||trim(a_proc)||'"', ''); + suspend; + exception ex_bad_argument using( coalesce('"'||trim(a_proc)||'"', ''), 'sys_get_proc_ddl' ); + end + + for + -- Extracts metadata of STORED PROCSEDURES to be executed as statements in isql. + -- Samples: + -- select src from sys_get_proc_ddl('', 0) -- output all procs with EMPTY body (preparing to update) + -- select src from sys_get_proc_ddl('', 1) -- output all procs with ODIGIN body (finalizing update) + + with + s as( + select + m.mon$sql_dialect db_dialect + ,:a_mode mode -- -1=only SP name and its parameters, 0 = name+parameters+empty body, 1=full text + ,:a_include_setterm add_set_term -- 1 => include `set term ^;` clause + ,r.rdb$character_set_name db_default_cset + ,p.rdb$procedure_name p_nam + ,ascii_char(10) d + ,replace(cast(p.rdb$procedure_source as blob sub_type 1), ascii_char(13), '') p_src + ,( + select + coalesce(sum(iif(px.rdb$parameter_type=0,1,0))*1000 + sum(iif(px.rdb$parameter_type=1,1,0)),0) + from rdb$procedure_parameters px + where px.rdb$procedure_name = p.rdb$procedure_name + ) pq -- cast(pq/1000 as int) = qty of IN-args, mod(pq,1000) = qty of OUT args + from mon$database m -- put it FIRST in the list of sources! + join rdb$database r on 1=1 + join rdb$procedures p on 1=1 + where p.rdb$procedure_name starting with upper(:a_proc) -- substitute with some name if needed + ) + --select * from s + ,r as( + select + db_dialect + ,mode + ,add_set_term + ,db_default_cset + ,p_nam + ,p.line as i + ,p.item as word + ,d + ,pq + ,p_src + ,cast(pq/1000 as int) pq_in + ,mod(pq,1000) pq_ou + ,p.eof k + from s + left join sys_list_to_rows(p_src, d) p on 1=1 + ) + --select * from r + + ,p as( + select + db_dialect + ,mode + ,add_set_term + ,db_default_cset + ,p_nam,i + ,word + ,r.pq_in + ,r.pq_ou + ,pt -- ip=0, op=1 + ,pp.rdb$field_source ppar_fld_src + ,pp.rdb$parameter_name par_name + ,pp.rdb$parameter_number par_num + ,pp.rdb$parameter_type par_ty + ,pp.rdb$null_flag p_not_null -- 1==> not null + ,pp.rdb$parameter_mechanism ppar_mechan -- 1=type of (table.column, domain, other...) + ,pp.rdb$relation_name ppar_rel_name + ,pp.rdb$field_name par_fld + ,case f.rdb$field_type + when 7 then 'smallint' + when 8 then 'integer' + when 10 then 'float' + --when 14 then 'char(' || cast(cast(f.rdb$field_length / iif(ce.rdb$character_set_name=upper('utf8'),4,1) as int) as varchar(5)) || ')' + when 14 then 'char(' || cast(cast(f.rdb$field_length / ce.rdb$bytes_per_character as int) as varchar(5)) || ')' + when 16 then -- dialect 3 only + case f.rdb$field_sub_type + when 0 then 'bigint' + when 1 then 'numeric(15,' || cast(-f.rdb$field_scale as varchar(6)) || ')' + when 2 then 'decimal(15,' || cast(-f.rdb$field_scale as varchar(6)) || ')' + else 'unknown' + end + when 12 then 'date' + when 13 then 'time' + when 27 then -- dialect 1 only + case f.rdb$field_scale + when 0 then 'double precision' + else 'numeric(15,' || cast(-f.rdb$field_scale as varchar(6)) || ')' + end + when 35 then iif(db_dialect=1, 'date', 'timestamp') + when 37 then 'varchar(' || cast(cast(f.rdb$field_length / ce.rdb$bytes_per_character as int) as varchar(5)) || ')' + when 261 then 'blob sub_type ' || f.rdb$field_sub_type || ' segment size ' || f.rdb$segment_length + else 'unknown' + end + as fddl + ,f.rdb$character_set_id fld_source_cset_id + ,f.rdb$collation_id fld_coll_id + ,ce.rdb$character_set_name fld_src_cset_name + ,co.rdb$collation_name fld_collation + ,cast(f.rdb$default_source as varchar(1024)) fld_default_src + ,cast(pp.rdb$default_source as varchar(1024)) ppar_default_src -- ppar_default_src + ,k -- k=-1 ==> last line of sp + from r + join ( + select -2 pt from rdb$database -- 'set term ^;' + union all select -1 from rdb$database -- header stmt: 'create or alter procedure ...(' + union all select 0 from rdb$database -- input pars + union all select 5 from rdb$database -- 'returns (' + union all select 10 from rdb$database -- output pars + union all select 20 from rdb$database -- 'as' + union all select 50 from rdb$database -- source code + union all select 100 from rdb$database -- '^set term ;^' + ) x on + -- `i`=line of body, 0='begin' + i = 0 and x.pt = -1 -- header + or i =0 and x.pt = 0 and pq_in > 0 -- input args, if exists + or i =0 and x.pt in(5,10) and pq_ou > 0 -- output args, if exists ('returns(' line) + or i =0 and x.pt = 20 -- 'AS' + or pt = 50 + or i = 0 and x.pt in(-2, 100) and add_set_term = 1 -- 'set term ^;', final '^set term ;^' + left join rdb$procedure_parameters pp on + r.p_nam = pp.rdb$procedure_name + and (x.pt = 0 and pp.rdb$parameter_type = 0 or x.pt = 10 and pp.rdb$parameter_type = 1) + --x.pt=pp.rdb$parameter_type-- =0 => in, 1=out + left join rdb$fields f on + pp.rdb$field_source = f.rdb$field_name + left join rdb$collations co on + f.rdb$character_set_id = co.rdb$character_set_id + and f.rdb$collation_id = co.rdb$collation_id + left join rdb$character_sets ce on + co.rdb$character_set_id = ce.rdb$character_set_id + ) + --select * from p + + ,fin as( + select + db_dialect + ,mode + ,add_set_term + ,db_default_cset + ,p_nam + ,i + ,par_num + ,case + when pt=-2 then 'set term ^;' + when pt=100 then '^set term ;^' + when pt=-1 then 'create or alter procedure '||trim(p_nam)||iif(pq_in>0,' (','') + when pt=5 then 'returns (' + when pt=20 then 'AS' + when pt in(0,10) then --in or out argument definition + ' ' + ||trim(par_name)||' ' + ||lower(trim( iif(nullif(p.ppar_mechan,0) is null, -- ==> parameter is defined with direct reference to base type, NOT like 'type of ...' + iif(ppar_fld_src starting with 'RDB$', p.fddl, ppar_fld_src), + ' type of '||coalesce('column '||trim(ppar_rel_name)||'.'||trim(par_fld), ppar_fld_src) + ) + ) + ) -- parameter type + ||iif(nullif(p.ppar_mechan,0) is not null -- parameter is defined as: "type of column|domain" + or + ppar_fld_src NOT starting with 'RDB$' -- parameter is defined by DOMAIN: "a_id dm_idb" + or + nullif(p.fld_src_cset_name,upper('NONE')) is null -- field of non-text type or charset was not specified + --coalesce(p.fld_src_cset_name, p.db_default_cset) is not distinct from p.db_default_cset + ,trim(trailing from iif(p.p_not_null=1, ' not null', '')) + ,' character set '||trim(p.fld_src_cset_name) + ||trim(trailing from iif(p.p_not_null=1, ' not null', '')) + ||iif(p.fld_collation is distinct from p.fld_src_cset_name, ' collate '||trim(p.fld_collation), '') + ) + ||coalesce( + ' '||trim( + iif( ppar_fld_src starting with upper('RDB$'), ----- adding "default ..." clause + coalesce(ppar_default_src, fld_default_src), -- this is only for 2.5; on 3.0 default values always are stored in ppar_default_src + ppar_default_src + ) + ) + ,'') + ||iif(pt=0 and par_num=pq_in-1 or pt=10 and par_num=pq_ou-1,')',',') + when k=-1 then coalesce(nullif(word,'')||';','') -- nb: some sp can finish with empty line! + else word + end word + ,pt + ,ppar_fld_src + ,par_name + ,par_ty + ,pq_in + ,pq_ou + --,f.rdb$field_type ftyp ,f.rdb$field_length flen,f.rdb$field_scale fdec + ,p.fddl + ,p.fld_src_cset_name + ,p.fld_collation + ,k + --,'#'l,f.* + from p + left join rdb$fields f on p.ppar_fld_src = f.rdb$field_name + ) + --select * from fin order by p_nam,pt,par_num,i + + select --mode,p_nam, + cast( + case + when mode<=0 then + case when pt <50 /*is not null*/ then word + when pt in(-2, 100) and add_set_term = 1 then word + when mode = 0 and i = 0 and pt < 100 then ' begin'||iif(k = -1, ' end','') + when mode = 0 and i = 1 then iif(pq_ou>0, ' suspend;', ' exit;') + when mode = 0 and k = -1 then 'end;' -- last line of body + end + else word + end + as varchar(8192)) -- blob can incorrectly displays (?) + as src + --,f.* -- do not! implementation exceeded + from fin f + where mode<=0 and (i in(0,1) or k=-1 /*or pt in(-2, 100) and strm=1*/ ) or mode=1 + order by p_nam,pt,par_num,i + into src + do + suspend; + +end + +^ -- sys_get_proc_ddl + +create or alter procedure sys_get_func_ddl ( + a_func varchar(31), + a_mode smallint = 1, + a_include_setterm smallint = 1) +returns ( + src varchar(32760)) +as +begin + for + -- Extracts metadata of STORED PROCSEDURES to be executed as statements in isql. + -- Samples: + -- select src from sys_get_proc_ddl('', 0) -- output all procs with EMPTY body (preparing to update) + -- select src from sys_get_proc_ddl('', 1) -- output all procs with ODIGIN body (finalizing update) + with + s as( + + select + m.mon$sql_dialect db_dialect + ,:a_mode mode -- -1=only SP name and its parameters, 0 = name+parameters+empty body, 1=full text + ,:a_include_setterm add_set_term -- 1 => include `set term ^;` clause + ,r.rdb$character_set_name db_default_cset + ,p.rdb$function_name p_nam + ,coalesce(p.rdb$deterministic_flag,0) p_det + ,ascii_char(10) d + ,replace(cast(p.rdb$function_source as blob sub_type 1), ascii_char(13), '') p_src + ,( + select + --coalesce(sum(iif(px.rdb$parameter_type=0,1,0))*1000 + sum(iif(px.rdb$parameter_type=1,1,0)),0) + 1000 * count( px.rdb$argument_position ) + 1 + from rdb$function_arguments px + where px.rdb$function_name = p.rdb$function_name + and px.rdb$argument_position > 0 -- take in account only INPUT args, because OUT always = 1 + ) pq -- cast(pq/1000 as int) = qty of IN-args, mod(pq,1000) = qty of OUT args + from mon$database m -- put it FIRST in the list of sources! + join rdb$database r on 1=1 + join rdb$functions p on 1=1 + where p.rdb$function_name starting with upper(:a_func) -- substitute with some name if needed + --upper( 'fn$get$random$id$subst$names' )-- upper(:a_proc) -- substitute with some name if needed + + ) + --select * from s + ,r as( + select + db_dialect + ,mode + ,add_set_term + ,db_default_cset + ,p_nam + ,p.line as i + ,p.item as word + ,d + ,pq + ,p_src + ,cast(pq/1000 as int) pq_in + ,mod(pq,1000) pq_ou + ,s.p_det + ,p.eof k + from s + left join sys_list_to_rows(p_src, d) p on 1=1 + ) + -- select * from r + + ,p as( + select + db_dialect + ,mode + ,add_set_term + ,db_default_cset + ,p_nam,i + ,word + ,r.pq_in + ,r.pq_ou + ,r.p_det + ,pt -- ip=0, op=1 + ,pp.rdb$field_source ppar_fld_src + ,pp.rdb$argument_name par_name + ,pp.rdb$argument_position par_num + -- ?! ,pp.rdb$parameter_type par_ty + ,pp.rdb$null_flag p_not_null -- 1==> not null + ,pp.rdb$argument_mechanism ppar_mechan -- 1=type of (table.column, domain, other...) + ,pp.rdb$relation_name ppar_rel_name + ,pp.rdb$field_name par_fld + ,case f.rdb$field_type + when 7 then 'smallint' + when 8 then 'integer' + when 10 then 'float' + --when 14 then 'char(' || cast(cast(f.rdb$field_length / iif(ce.rdb$character_set_name=upper('utf8'),4,1) as int) as varchar(5)) || ')' + when 14 then 'char(' || cast(cast(f.rdb$field_length / ce.rdb$bytes_per_character as int) as varchar(5)) || ')' + when 16 then -- dialect 3 only + case f.rdb$field_sub_type + when 0 then 'bigint' + when 1 then 'numeric(15,' || cast(-f.rdb$field_scale as varchar(6)) || ')' + when 2 then 'decimal(15,' || cast(-f.rdb$field_scale as varchar(6)) || ')' + else 'unknown' + end + when 12 then 'date' + when 13 then 'time' + when 27 then -- dialect 1 only + case f.rdb$field_scale + when 0 then 'double precision' + else 'numeric(15,' || cast(-f.rdb$field_scale as varchar(6)) || ')' + end + when 35 then iif(db_dialect=1, 'date', 'timestamp') + when 37 then 'varchar(' || cast(cast(f.rdb$field_length / ce.rdb$bytes_per_character as int) as varchar(5)) || ')' + when 261 then 'blob sub_type ' || f.rdb$field_sub_type || ' segment size ' || f.rdb$segment_length + else 'unknown' + end + as fddl + ,f.rdb$character_set_id fld_source_cset_id + ,f.rdb$collation_id fld_coll_id + ,ce.rdb$character_set_name fld_src_cset_name + ,co.rdb$collation_name fld_collation + ,cast(f.rdb$default_source as varchar(1024)) fld_default_src + ,cast(pp.rdb$default_source as varchar(1024)) ppar_default_src -- ppar_default_src + ,k -- k=-1 ==> last line of sp + from r + join ( + select -2 pt from rdb$database -- 'set term ^;' + union all select -1 from rdb$database -- header stmt: 'create or alter procedure ...(' + union all select 0 from rdb$database -- input pars + union all select 5 from rdb$database -- 'returns <...> [deterministic]' + union all select 10 from rdb$database -- output pars + union all select 20 from rdb$database -- 'as' + union all select 50 from rdb$database -- source code + union all select 100 from rdb$database -- '^set term ;^' + ) x on + -- `i`=line of body, 0='begin' + i = 0 and x.pt = -1 -- header + or i =0 and x.pt = 0 and pq_in > 0 -- input args, if exists + or i =0 and x.pt in(5,10) and pq_ou > 0 -- output argument, always single ( for line: "returns ..." ) + or i =0 and x.pt = 20 -- 'AS' + or pt = 50 + or i = 0 and x.pt in(-2, 100) and add_set_term = 1 -- 'set term ^;', final '^set term ;^' + left join rdb$function_arguments pp on -- rdb$procedure_parameters pp on + r.p_nam = pp.rdb$function_name -- rdb$procedure_name + and ( x.pt = 0 and pp.rdb$argument_position >= 1 -- input arg + or + x.pt = 10 and pp.rdb$argument_position = 0 -- single output arg + ) + --x.pt=pp.rdb$parameter_type-- =0 => in, 1=out + left join rdb$fields f on + pp.rdb$field_source = f.rdb$field_name + left join rdb$collations co on + f.rdb$character_set_id = co.rdb$character_set_id + and f.rdb$collation_id = co.rdb$collation_id + left join rdb$character_sets ce on + co.rdb$character_set_id = ce.rdb$character_set_id + ) + --select * from p + + ,fin as( + select + db_dialect + ,mode + ,add_set_term + ,db_default_cset + ,p.ppar_mechan + ,p_nam + ,i + ,par_num + ,p_det + ,case + when pt=-2 then 'set term ^;' + when pt=100 then '^set term ;^' + when pt=-1 then 'create or alter function '||trim(p_nam)||iif(pq_in>0,' (','') + when pt=5 then 'returns ' + when pt=20 then 'AS' + when pt in(0,10) then --in or out argument definition + ' ' + ||trim( coalesce( lower(par_name), '') )||' ' + ||lower(trim( iif(nullif(p.ppar_mechan,0) is null, -- ==> parameter is defined with direct reference to base type, NOT like 'type of ...' + iif(ppar_fld_src starting with 'RDB$', p.fddl, ppar_fld_src), + ' type of '||coalesce('column '||trim(ppar_rel_name)||'.'||trim(par_fld), ppar_fld_src) + ) + ) + ) -- parameter type + ||iif(nullif(p.ppar_mechan,0) is not null -- parameter is defined as: "type of column|domain" + or + ppar_fld_src NOT starting with 'RDB$' -- parameter is defined by DOMAIN: "a_id dm_idb" + or + nullif(p.fld_src_cset_name,upper('NONE')) is null -- field of non-text type or charset was not specified + --coalesce(p.fld_src_cset_name, p.db_default_cset) is not distinct from p.db_default_cset + ,trim(trailing from iif(p.p_not_null=1, ' not null', '')) + ,' character set '||trim(p.fld_src_cset_name) + ||trim(trailing from iif(p.p_not_null=1, ' not null', '')) + ||iif(p.fld_collation is distinct from p.fld_src_cset_name, ' collate '||trim(p.fld_collation), '') + ) + ||coalesce( + ' '||trim( + iif( ppar_fld_src starting with upper('RDB$'), ----- adding "default ..." clause + coalesce(ppar_default_src, fld_default_src), -- this is only for 2.5; on 3.0 default values always are stored in ppar_default_src + ppar_default_src + ) + ) + ,'') + ||trim(trailing from iif( pt=0, iif( par_num = pq_in, ')', ','), iif( p_det = 1, ' deterministic', '') ) ) + when k=-1 then coalesce(nullif(word,'')||';','') -- nb: some sp can finish with empty line! + else word + end word + ,pt + ,ppar_fld_src + ,par_name + --,par_ty + ,pq_in + ,pq_ou + --,f.rdb$field_type ftyp ,f.rdb$field_length flen,f.rdb$field_scale fdec + ,p.fddl + ,p.fld_src_cset_name + ,p.fld_collation + ,k + --,'#'l,f.* + from p + left join rdb$fields f on p.ppar_fld_src = f.rdb$field_name + ) + -- select * from fin order by p_nam,pt,par_num,i + + select --mode,p_nam, + cast( + case + when mode<=0 then + case when pt <50 /*is not null*/ then word + when pt in(-2, 100) and add_set_term = 1 then word + when mode = 0 and i = 0 and pt < 100 then ' begin'||iif(k = -1, ' end','') + when mode = 0 and i = 1 then 'return null;' + when mode = 0 and k = -1 then 'end' || iif(add_set_term = 1, '', ';') -- last line of body + end + else word + end + as varchar(8190)) -- varchar(8192)) -- blob can incorrectly displays (?) + as src + --,f.* -- do not! implementation exceeded + from fin f + where mode<=0 and (i in(0,1) or k=-1 /*or pt in(-2, 100) and strm=1*/ ) or mode=1 + order by p_nam,pt,par_num,i + into src + do + suspend; + +end + +^ -- sys_get_func_ddl + +create or alter procedure sys_get_view_ddl ( + A_VIEW varchar(31) = '', + A_MODE smallint = 1) +returns ( + SRC varchar(8192)) +AS +begin + -- Extracts metadata of VIEWS to be executed as statements in isql. + -- Samples: + -- select src from sys_get_view_ddl('', 0) -- output all views with EMPTY body (preparing to update) + -- select src from sys_get_view_ddl('', 1) -- output all views with ODIGIN body (finalizing update) + + for + with + inp as(select :a_view a_view, :a_mode mode from rdb$database) + ,s as( + select + m.mon$sql_dialect di + ,i.mode mode -- 1=> fill + ,1 strm -- 1 => include `set term ^;` clause + ,r.rdb$character_set_name cs + ,p.rdb$relation_name v_name + ,(select count(*) from rdb$relation_fields rf where p.rdb$relation_name=rf.rdb$relation_name) fq -- count of fields + ,ascii_char(10) d + ,replace(cast(p.rdb$view_source as blob sub_type 1), ascii_char(13), '') ||ascii_char(10)||';' p_src + from mon$database m -- put it FIRST in the list of sources! + join rdb$database r on 1=1 + join rdb$relations p on 1=1 + join inp i on 1=1 + where coalesce(p.rdb$system_flag,0) = 0 + and p.rdb$view_source is not null -- views; do NOT: p.rdb$relation_type=1 !! + and (i.a_view='' or p.rdb$relation_name = upper(i.a_view)) + ) + ,r as( + select --* --s.*,'#'l,p.*,rf.* + di + ,mode + ,strm + ,cs + ,v_name + ,fq + ,p.item word + ,p.line i + ,p.eof k + ,rf.rdb$field_position fld_pos + ,x.rt + ,rf.rdb$field_name v_fld + ,rf.rdb$field_source v_src + ,case f.rdb$field_type + when 7 then 'smallint' + when 8 then 'integer' + when 10 then 'float' + when 14 then 'char(' || cast(cast(f.rdb$field_length / ce.rdb$bytes_per_character as int) as varchar(5)) || ')' + when 16 then -- dialect 3 only + case f.rdb$field_sub_type + when 0 then 'bigint' + when 1 then 'numeric(15,' || cast(-f.rdb$field_scale as varchar(6)) || ')' + when 2 then 'decimal(15,' || cast(-f.rdb$field_scale as varchar(6)) || ')' + else 'unknown' + end + when 12 then 'date' + when 13 then 'time' + when 27 then -- dialect 1 only + case f.rdb$field_scale + when 0 then 'double precision' + else 'numeric(15,' || cast(-f.rdb$field_scale as varchar(6)) || ')' + end + when 35 then iif(di=1, 'date', 'timestamp') + when 37 then 'varchar(' || cast(cast(f.rdb$field_length / ce.rdb$bytes_per_character as int) as varchar(5)) || ')' + when 261 then 'blob sub_type ' || f.rdb$field_sub_type || ' segment size ' || f.rdb$segment_length + else 'unknown' + end fddl + ,f.rdb$character_set_id fld_cset + ,f.rdb$collation_id fld_coll_id + ,ce.rdb$character_set_name cset_name + ,co.rdb$collation_name fld_collation + from s + left join sys_list_to_rows(p_src, d) p + on p.line=0 or mode=1 + left join + ( + select -2 rt from rdb$database -- create or alter view + union all select -1 from rdb$database -- for fields of view + union all select 0 from rdb$database -- body + union all select 99 from rdb$database -- final ';' + ) x on + p.line=0 and x.rt in(-2,-1,99) or x.rt=0 and mode=1 + left join rdb$relation_fields rf on -- fields of the view + ( /*mode=0 or mode=1 and*/ p.line=0 and x.rt=-1) + and s.v_name=rf.rdb$relation_name + left join rdb$fields f on + rf.rdb$field_source=f.rdb$field_name + left join rdb$collations co on + f.rdb$character_set_id=co.rdb$character_set_id + and f.rdb$collation_id=co.rdb$collation_id + left join rdb$character_sets ce on + co.rdb$character_set_id=ce.rdb$character_set_id + ) + --select * from r order by v_name,rt,i,fld_pos + + ,fin as( + select + di + ,mode + ,strm + ,cs + ,v_name + ,fq + ,case + when 1=1 or mode=0 then + case + when rt=-2 then + 'create or alter view '||trim(v_name)||iif( mode=0, ' as select',' (' ) + when mode=1 and rt=-1 then -- rt=-1: fields of view + trim(v_fld)||trim(iif(fld_pos+1=fq,') as',',')) + when mode=0 and rt=-1 then + iif(fld_pos=0, '', ', ')|| + case when + lower(fddl) in ('smallint','integer','bigint','double precision','float') + or lower(fddl) starting with 'numeric' + or lower(fddl) starting with 'decimal' + then '0 as '||v_fld + when + lower(fddl) starting with 'varchar' + or lower(fddl) starting with 'char' + or lower(fddl) starting with 'blob' + then ''''' as '||v_fld + when + lower(fddl) in ('timestamp','date') + then 'cast(''now'' as '||lower(fddl)||') as '||v_fld + end + when rt=0 then word + when rt=99 then iif(mode=0,'from rdb$database;',';') -- final row + end + when mode=1 then + case + when rt=-1 then 'create or alter view '||trim(v_name)||' as ' + else word||iif(k=-1 and right(word,1)<>';', ';','') + end + end + as word + ,i + ,k + ,rt + ,v_fld + ,v_src + ,fld_pos + ,fddl + ,fld_cset + ,fld_coll_id + ,cset_name + ,fld_collation + from r + where word not in(';') + ) + select word + from fin + order by v_name, rt, i,fld_pos + into src + do + suspend; + +end + +^ -- sys_get_view_ddl + +create or alter procedure sys_get_indx_ddl( + a_relname varchar(31) = '') +returns ( + src varchar(8192)) +as +begin + -- extract DDLs of all indices EXCEPT those which are participated + -- in PRIMARY KEYS + for + with + inp as(select :a_relname nm from rdb$database) + ,pk_defs as( -- determine primary keys + select + rc.rdb$relation_name rel_name + ,rc.rdb$constraint_name pk_name + ,rc.rdb$index_name pk_idx + from rdb$relation_constraints rc + where rc.rdb$constraint_type containing 'PRIMARY' + ) + --select * from pk_defs + + ,ix_defs as( + select + ri.rdb$relation_name rel_name + ,rc.rdb$constraint_name con_name + ,rc.rdb$constraint_type con_type + ,ri.rdb$index_id idx_id + ,ri.rdb$index_name idx_name + ,ri.rdb$unique_flag unq + ,ri.rdb$index_type des + ,ri.rdb$foreign_key fk + ,ri.rdb$system_flag sy + ,rs.rdb$field_name fld + ,rs.rdb$field_position pos + ,ri.rdb$expression_source ix_expr + ,p.pk_idx + from rdb$indices ri + join inp i on (ri.rdb$relation_name = upper(i.nm) or i.nm='') + left join rdb$relation_constraints rc on ri.rdb$index_name=rc.rdb$index_name + left join pk_defs p on ri.rdb$relation_name=p.rel_name and ri.rdb$index_name=p.pk_idx + left join rdb$index_segments rs on ri.rdb$index_name=rs.rdb$index_name + where + ri.rdb$system_flag=0 + and p.pk_idx is null -- => this index is not participated in PK + order by rel_name,idx_id, pos + ) + --select * from ix_defs + ,ix_grp as( + select rel_name,con_name,con_type,idx_id,idx_name,unq,des,fk,ix_key,ix_expr + ,r.rdb$relation_name parent_rname + ,r.rdb$constraint_name parent_cname + ,r.rdb$constraint_type parent_ctype + ,iif(r.rdb$constraint_type='PRIMARY KEY' + ,(select cast(list(trim(pk_fld),',') as varchar(8192)) from + (select rs.rdb$field_name pk_fld + from rdb$index_segments rs + where rs.rdb$index_name=t.fk + order by rs.rdb$field_position + )u + ) + ,null) parent_pkey + from( + select rel_name,con_name,con_type,idx_id,idx_name,unq,des,fk + ,cast(list(trim(fld),',') as varchar(8192)) ix_key + ,cast(ix_expr as varchar(8192)) ix_expr + from ix_defs + group by rel_name,con_name,con_type,idx_id,idx_name,unq,des,fk,ix_expr + )t + left join rdb$relation_constraints r on t.fk=r.rdb$index_name + ) + --select * from ix_grp + + ,fin as( + select + rel_name,con_name,con_type,idx_id,idx_name,unq,des,fk + ,parent_rname,parent_cname,parent_ctype,parent_pkey + ,case + when con_type='UNIQUE' then + 'alter table ' + ||trim(rel_name) + ||' add '||trim(con_type) + ||'('||trim(ix_key)||')' + ||iif(idx_name like 'RDB$%', '', ' using index '||trim(idx_name)) + ||';' + when con_type='FOREIGN KEY' and con_name like 'INTEG%' then + 'alter table ' + ||trim(rel_name) + ||' add '||trim(con_type) + ||'('||trim(ix_key)||') references ' + ||trim(parent_rname) + ||'('||trim(coalesce(parent_pkey,ix_key)) ||')' + ||iif(idx_name like 'RDB$FOREIGN%', '', ' using index '||trim(idx_name)) + ||';' + when con_type='FOREIGN KEY' then + 'alter table ' + ||trim(rel_name) + ||' add constraint '||trim(con_name)||' '||trim(con_type) + ||'('||trim(ix_key)||') references ' + ||trim(parent_rname)||'('||trim(parent_pkey)||')' + ||' using index '||trim(idx_name) + ||';' + end ct_ddl + ,'create ' + ||trim(iif(unq=1,' unique','') + ||iif(des=1,' descending','')) + ||' index '||trim(idx_name) + ||' on '||trim(rel_name) + ||' '||iif(ix_expr is null,'('||trim(ix_key)||')', 'computed by ('||trim(ix_expr)||')' ) + ||';' ix_ddl + from ix_grp + ) + select coalesce(ct_ddl, ix_ddl) idx_ddl --, f.* + from fin f + into + src + do + suspend; +end + +^ -- sys_get_indx_ddl + +create or alter procedure sys_get_fb_arch ( + a_connect_with_usr varchar(31) default 'SYSDBA' + ,a_connect_with_pwd varchar(31) default 'masterkey' +) returns( + fb_arch varchar(50) +) as + declare cur_server_pid int; + declare ext_server_pid int; + declare att_protocol varchar(255); + declare v_test_sttm varchar(255); + declare v_fetches_beg bigint; + declare v_fetches_end bigint; +begin + + -- Aux SP for detect FB architecture. + + select a.mon$server_pid, a.mon$remote_protocol + from mon$attachments a + where a.mon$attachment_id = current_connection + into cur_server_pid, att_protocol; + + if ( att_protocol is null ) then + fb_arch = 'Embedded'; + else if ( upper(current_user) = upper('SYSDBA') + and rdb$get_context('SYSTEM','ENGINE_VERSION') NOT starting with '2.5' + and exists(select * from mon$attachments a + where a.mon$remote_protocol is null + and upper(a.mon$user) in ( upper('Cache Writer'), upper('Garbage Collector')) + ) + ) then + fb_arch = 'SuperServer'; + else + begin + v_test_sttm = + 'select a.mon$server_pid + 0*(select 1 from rdb$database)' + ||' from mon$attachments a ' + ||' where a.mon$attachment_id = current_connection'; + + select i.mon$page_fetches + from mon$io_stats i + where i.mon$stat_group = 0 -- db_level + into v_fetches_beg; + + execute statement v_test_sttm + on external + 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME') + as + user a_connect_with_usr + password a_connect_with_pwd + role left('R' || replace(uuid_to_char(gen_uuid()),'-',''),31) + into ext_server_pid; + + in autonomous transaction do + select i.mon$page_fetches + from mon$io_stats i + where i.mon$stat_group = 0 -- db_level + into v_fetches_end; + + fb_arch = iif( cur_server_pid is distinct from ext_server_pid, + 'Classic', + iif( v_fetches_beg is not distinct from v_fetches_end, + 'SuperClassic', + 'SuperServer' + ) + ); + end + + fb_arch = fb_arch || ' ' || rdb$get_context('SYSTEM','ENGINE_VERSION'); + + suspend; + +end + +^ -- sys_get_fb_arch + +create or alter function fn$get$random$id$subst$names ( + a_view_for_search dm_dbobj, + a_view_for_min_id dm_dbobj default null, + a_view_for_max_id dm_dbobj default null, + a_raise_exc dm_sign default 1, -- raise exc`eption if no record will be found + a_can_skip_order_clause dm_sign default 0, -- 17.07.2014 (for some views where document is taken into processing and will be REMOVED from scope of this view after Tx is committed) + a_find_using_desc_index dm_sign default 0 -- 11.09.2014: if 1, then query will be: "where id <= :a order by id desc" +) +returns bigint +as + + declare i smallint; + declare v_stt varchar(255); + declare id_min double precision; + declare id_max double precision; + declare v_rows int; + declare id_random bigint; + declare id_selected bigint = null; + declare msg dm_info; + declare v_info dm_info; + declare v_this dm_dbobj = 'fn_get_random_id'; + declare v_ctxn dm_ctxnv; + declare v_name dm_dbobj; + declare fn_internal_max_rows_usage int; + declare v_is_known smallint = 0; +begin + -- Selects random record from view + -- using select first 1 id from ... where id >= :id_random order by id. + -- Aux. parameters: + -- # a_view_for_min_id and a_view_for_max_id -- separate views that + -- might be more effective to find min & max LIMITS than scan using a_view_for_search. + -- # a_raise_exc (default=1) - do we raise exc`eption if record not found. + -- # a_can_skip_order_clause (default=0) - can we SKIP including of 'order by' clause + -- in statement which will be passed to ES ? (for some cases we CAN do it for efficiency) + -- # a_find_using_desc_index - do we construct ES for search using DESCENDING index + -- (==> it will use "where id <= :r order by id DESC" rather than "where id >= :r order by id ASC") + -- [only when TIL = RC] Repeats times if result is null + -- (possible if bounds of IDs has been changed since previous call) + + v_this = trim(a_view_for_search); + + -- max difference b`etween min_id and max_id to allow scan random id via + -- select id from rows :x to :y, where x = y = random_int + fn_internal_max_rows_usage = cast( rdb$get_context('USER_SESSION','RANDOM_SEEK_VIA_ROWS_LIMIT') as int); + + -- Use either stub or non-empty executing code (depends on was 'oltp_dump.sql' compiled or no): + -- save fact of usage views in the table `z_used_views`: + execute procedure z_remember_view_usage(a_view_for_search, a_view_for_min_id, a_view_for_max_id); + + a_view_for_min_id = coalesce( a_view_for_min_id, a_view_for_search ); + a_view_for_max_id = coalesce( a_view_for_max_id, a_view_for_min_id, a_view_for_search ); + + -- Label: $name_to_substutite_start_of_loop. Do not delete this line! + + if ( upper(a_view_for_search) = upper(trim('name$to$substutite$search$')) ) then + begin + v_is_known = 1; + if ( rdb$get_context('USER_TRANSACTION', upper(trim('name$to$substutite$min$id$'))||'_ID_MIN' ) is null + or + rdb$get_context('USER_TRANSACTION', upper(trim('name$to$substutite$max$id$'))||'_ID_MAX' ) is null + ) then + begin + execute procedure sp_add_perf_log(1, a_view_for_min_id); + + if ( a_view_for_min_id is not null ) then + select min(id)-0.5 from name$to$substutite$min$id$ into id_min; + else + select min(id)-0.5 from name$to$substutite$search$ into id_min; + + execute procedure sp_add_perf_log(0, a_view_for_min_id, null, 'static SQL, id_min='||coalesce(id_min,'') ); + + if ( id_min is NOT null ) then -- ==> source is NOT empty + begin + + execute procedure sp_add_perf_log(1, a_view_for_max_id ); + + if ( a_view_for_max_id is not null ) then + select max(id)+0.5 from name$to$substutite$max$id$ into id_max; + else + select max(id)+0.5 from name$to$substutite$search$ into id_max; + + execute procedure sp_add_perf_log(0, a_view_for_max_id, null, 'static SQL, id_max='||coalesce(id_max,'') ); + + if ( id_max is NOT null ) then -- ==> source is NOT empty + begin + -- Save values for subsequent calls of this func in this tx (minimize DB access) + -- (limit will never change in SNAPSHOT and can change with low probability in RC): + rdb$set_context('USER_TRANSACTION', upper(trim('name$to$substutite$min$id$')) || '_ID_MIN', :id_min); + rdb$set_context('USER_TRANSACTION', upper(trim('name$to$substutite$max$id$')) || '_ID_MAX', :id_max); + + if ( id_max - id_min < fn_internal_max_rows_usage ) then + begin + -- when difference b`etween id_min and id_max is not too high, we can simple count rows: + select count(*) from name$to$substutite$search$ into v_rows; + rdb$set_context('USER_TRANSACTION', upper(trim('name$to$substutite$search$')) || '_COUNT', v_rows ); + end + end -- id_max is NOT null + end -- id_min is NOT null + end + else + begin + -- minimize database access! Performance on 10'000 loops: 1485 ==> 590 ms + id_min=cast( rdb$get_context('USER_TRANSACTION', upper(trim('name$to$substutite$min$id$')) || '_ID_MIN' ) as double precision); + id_max=cast( rdb$get_context('USER_TRANSACTION', upper(trim('name$to$substutite$max$id$')) || '_ID_MAX' ) as double precision); + v_rows=cast( rdb$get_context('USER_TRANSACTION', upper(trim('name$to$substutite$search$')) || '_COUNT') as int); + end + + if ( id_max - id_min < fn_internal_max_rows_usage ) then + begin + --id_random = cast( 1 + rand() * (v_rows - 1) as int); -- WRONG when data skewed to low values; 30.07.2014 + id_random = ceiling( rand() * (v_rows) ); + select id + from name$to$substutite$search$ + -- ::: nb ::: `ORDER` clause not needed here + rows :id_random to :id_random + into id_selected; + end + else + begin + -- 17.07.2014: for some cases it is ALLOWED to query random ID without "ORDER BY" + -- clause because this ID will be handled in such manner that it will be REMOVED + -- after this handling from the scope of view! Samples of such cases are: + -- sp_cancel_supplier_order, sp_cancel_supplier_invoice, sp_cancel_customer_reserve + id_random = cast( id_min + rand() * (id_max - id_min) as bigint); + + if ( a_can_skip_order_clause = 0 and a_find_using_desc_index = 0 ) then + select id + from name$to$substutite$search$ + where id >= :id_random + order by id ASC + rows 1 + into id_selected; + else if ( a_can_skip_order_clause = 0 and a_find_using_desc_index = 1 ) then + select id + from name$to$substutite$search$ + where id <= :id_random + order by id DESC + rows 1 + into id_selected; + else if ( a_can_skip_order_clause = 1 and a_find_using_desc_index = 0 ) then + select id + from name$to$substutite$search$ + where id >= :id_random + rows 1 + into id_selected; + else if ( a_can_skip_order_clause = 1 and a_find_using_desc_index = 1 ) then + select id + from name$to$substutite$search$ + where id <= :id_random + rows 1 + into id_selected; + else + exception ex_bad_argument using('a_can_skip_order_clause and/or a_find_using_desc_index', v_this); + + end + + end -- upper(a_view_for_search) = upper(trim('name$to$substutite$min$id$')) + + -- Label: $name_to_substutite_end_of_loop. Do not delete this line! + + if ( v_is_known = 0 ) then -- passed view not from list of known names + begin -- use ES (old code) + + if ( rdb$get_context('USER_TRANSACTION', upper(:a_view_for_min_id)||'_ID_MIN' ) is null + or + rdb$get_context('USER_TRANSACTION', upper(:a_view_for_max_id)||'_ID_MAX' ) is null + ) then + begin + execute procedure sp_add_perf_log(1, a_view_for_min_id ); + -- v`iew z_get_min_max_id may be used to see average, min and max elapsed time + -- of this sttm: + v_stt='select min(id)-0.5 from '|| a_view_for_min_id; + execute statement (:v_stt) into id_min; -- do via ES in order to see statistics in the TRACE! + execute procedure sp_add_perf_log(0, a_view_for_min_id, null, 'dyn SQL, id_min='||coalesce(id_min,'') ); + + if ( id_min is NOT null ) then -- ==> source is NOT empty + begin + + execute procedure sp_add_perf_log(1, a_view_for_max_id ); + -- v`iew z_get_min_max_id may be used to see average, min and max elapsed time + -- of this sttm: + v_stt='select max(id)+0.5 from '|| a_view_for_max_id; + execute statement (:v_stt) into id_max; -- do via ES in order to see statistics in the TRACE! + execute procedure sp_add_perf_log(0, a_view_for_max_id, null, 'dyn SQL, id_max='||coalesce(id_max,'') ); + + if ( id_max is NOT null ) then -- ==> source is NOT empty + begin + -- Save values for subsequent calls of this func in this tx (minimize DB access) + -- (limit will never change in SNAPSHOT and can change with low probability in RC): + rdb$set_context('USER_TRANSACTION', upper(:a_view_for_min_id)||'_ID_MIN', :id_min); + rdb$set_context('USER_TRANSACTION', upper(:a_view_for_max_id)||'_ID_MAX', :id_max); + + if ( id_max - id_min < fn_internal_max_rows_usage ) then + begin + -- when difference b`etween id_min and id_max is not too high, we can simple count rows: + execute statement 'select count(*) from '||a_view_for_search into v_rows; + rdb$set_context('USER_TRANSACTION', upper(:a_view_for_search)||'_COUNT', v_rows ); + end + end -- id_max is NOT null + end -- id_min is NOT null + end + else begin + -- minimize database access! Performance on 10'000 loops: 1485 ==> 590 ms + id_min=cast( rdb$get_context('USER_TRANSACTION', upper(:a_view_for_min_id)||'_ID_MIN' ) as double precision); + id_max=cast( rdb$get_context('USER_TRANSACTION', upper(:a_view_for_max_id)||'_ID_MAX' ) as double precision); + v_rows=cast( rdb$get_context('USER_TRANSACTION', upper(:a_view_for_search)||'_COUNT') as int); + end + + if ( id_max - id_min < fn_internal_max_rows_usage ) then + begin + v_stt='select id from '||a_view_for_search||' rows :x to :y'; -- ::: nb ::: `ORDER` clause not needed here! + --id_random = cast( 1 + rand() * (v_rows - 1) as int); -- WRONG when data skewed to low values; 30.07.2014 + id_random = ceiling( rand() * (v_rows) ); + execute statement (:v_stt) (x := id_random, y := id_random) into id_selected; + end + else + begin + -- 17.07.2014: for some cases it is ALLOWED to query random ID without "ORDER BY" + -- clause because this ID will be handled in such manner that it will be REMOVED + -- after this handling from the scope of view! Samples of such cases are: + -- sp_cancel_supplier_order, sp_cancel_supplier_invoice, sp_cancel_customer_reserve + v_stt='select id from ' + ||a_view_for_search + ||iif(a_find_using_desc_index = 0, ' where id >= :x', ' where id <= :x'); + if ( a_can_skip_order_clause = 0 ) then + v_stt = v_stt || iif(a_find_using_desc_index = 0, ' order by id ', ' order by id desc'); + v_stt = v_stt || ' rows 1'; + id_random = cast( id_min + rand() * (id_max - id_min) as bigint); + + -- execute procedure sp_add_perf_log(1, a_view_for_search ); + -- do via ES in order to see statistics in the TRACE: + execute statement (:v_stt) (x := id_random) into id_selected; + -- execute procedure sp_add_perf_log(0, a_view_for_search, null, 'id_sel='||coalesce(id_selected,'') ); + end + + end -- v_is_known = 0 ==> use ES (old code, when passed name of view NOT from known list) + + + if ( id_selected is null and coalesce(a_raise_exc, 1) = 1 ) then + begin + + v_info = 'view: ' || a_view_for_search; -- name$to$substutite$search$'; + if ( id_min is NOT null ) then + v_info = v_info || ', id_min=' || id_min || ', id_max='||id_max; + else + v_info = v_info || ' - EMPTY'; + + v_info = v_info ||', id_rnd='||coalesce(id_random,''); + + -- 'no id @1 @2 in @3 found within scope @4 ... @5'; -- @1 is '>=' or '<='; @2 = random_selected_value; @3 = data source; @4 = min; @5 = max + exception ex_can_not_select_random_id + using( + iif(a_find_using_desc_index = 0,'>=','<=') + ,coalesce(id_random,'') + ,a_view_for_search + ,coalesce(id_min,'') + ,coalesce(id_max,'') + ); + + end + + return id_selected; + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + v_stt, + gdscode, + v_info, + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end -- fn$get$random$id$subst$names + +^ + +create or alter procedure sys_get_run_info(a_mode varchar(12)) returns( + dts varchar(12) + ,trn varchar(14) + ,unit dm_unit + ,msg varchar(20) + ,add_info varchar(40) + ,elapsed_ms varchar(10) +) +as +begin + -- Aux SP for output info about unit that is to be performed now. + -- used in batch 'oltpNN_worker.bat' + dts = substring(cast(current_timestamp as varchar(24)) from 12 for 12); + unit = rdb$get_context('USER_SESSION','SELECTED_UNIT'); + if ( a_mode='start' ) then + begin + trn = 'tra_'||coalesce(current_transaction,''); + msg = 'start'; + add_info = 'att_'||current_connection; + end + else + begin + trn = 'tra_'||rdb$get_context('USER_SESSION','APP_TRANSACTION'); + msg = rdb$get_context('USER_SESSION', 'RUN_RESULT'); + add_info = rdb$get_context('USER_SESSION','ADD_INFO'); + elapsed_ms = + lpad( + cast( + datediff( + millisecond + from cast(left(rdb$get_context('USER_SESSION','BAT_PHOTO_UNIT_DTS'),24) as timestamp) + to cast(right(rdb$get_context('USER_SESSION','BAT_PHOTO_UNIT_DTS'),24) as timestamp) + ) + as varchar(10) + ) + ,10 + ,' ' + ); + end + suspend; +end + +^ -- sys_get_run_info + +create or alter procedure sys_timestamp_to_ansi (a_dts timestamp default 'now') +returns ( ansi_dts varchar(15) ) as +begin + ansi_dts = + cast(extract( year from a_dts)*10000 + extract(month from a_dts) * 100 + extract(day from a_dts) as char(8)) + || '_' + || substring(cast(cast(1000000 + extract(hour from a_dts) * 10000 + extract(minute from a_dts) * 100 + extract(second from a_dts) as int) as char(7)) from 2); + suspend; +end + +^ -- sys_timestamp_to_ansi + +set term ;^ +set list on; +set echo off; +select 'oltp30_DDL.sql finish at ' || current_timestamp as msg from rdb$database; +set list off; + + +-- ########################################################### +-- End of script oltp30_DDL.sql; next to be run: oltp30_SP.sql +-- ########################################################### + +-- ################################################# +-- Begin of script oltp30_SP.sql (application units) +-- ################################################# +-- ::: nb ::: Required FB version: 3.0 and above +set autoddl off; +set list on; +select 'oltp30_sp.sql start at ' || current_timestamp as msg from rdb$database; +set list off; + + +set term ^; +execute block as +begin + begin + execute statement 'recreate exception ex_exclusive_required ''At least one concurrent connection detected.'''; + when any do begin end + end + begin + execute statement 'recreate exception ex_not_suitable_fb_version ''This script requires at least Firebird 3.x version'''; + when any do begin end + end +end +^ +set term ;^ + + +set term ^; +execute block as +begin + if ( rdb$get_context('SYSTEM','ENGINE_VERSION') starting with '2.' ) then + begin + exception ex_not_suitable_fb_version; + end + + -- NB. From doc/README.monitoring_tables: + -- columns MON$REMOTE_PID and MON$REMOTE_PROCESS contains non-NULL values + -- only if the client library has version 2.1 or higher + -- column MON$REMOTE_PROCESS can contain a non-pathname value + -- if an application has specified a custom process name via DPB + if ( exists( select * from mon$attachments a + where a.mon$attachment_id<>current_connection + and a.mon$remote_protocol is not null + ) + ) then + begin + exception ex_exclusive_required; + end +end +^ +set term ;^ + + +set term ^; + +create or alter procedure srv_increment_tx_bops_counter +as +begin + rdb$set_context( 'USER_TRANSACTION', 'BUSINESS_OPS_CNT', coalesce( cast(rdb$get_context('USER_TRANSACTION', 'BUSINESS_OPS_CNT') as int), 0) + 1); +end + +^ -- srv_increment_tx_bops_counter + +create or alter procedure sp_fill_shopping_cart( + a_optype_id dm_idb, + a_rows2add int default null, + a_maxq4row int default null) +returns( + row_cnt int, -- number of rows added to tmp$shop_cart + qty_sum dm_qty -- total on QTY field in tmp$shop_cart +) +as + declare v_doc_rows int; + declare v_id dm_idb; + declare v_ware_id type of dm_idb; + declare v_qty dm_qty; + declare v_cost_purchase dm_cost; + declare v_cost_retail dm_cost; + declare v_snd_optype_id dm_idb; + declare v_storno_sub smallint; + declare v_ctx_max_rows type of dm_ctxnv; + declare v_ctx_max_qty type of dm_ctxnv; + declare v_stt varchar(255); + declare v_pattern type of dm_name; + declare v_source_for_random_id dm_dbobj; + declare v_source_for_min_id dm_dbobj; + declare v_source_for_max_id dm_dbobj; + declare v_raise_exc_on_nofind dm_sign; + declare v_can_skip_order_clause dm_sign; + declare v_find_using_desc_index dm_sign; + declare v_this dm_dbobj = 'sp_fill_shopping_cart'; + declare v_info dm_info = ''; +begin + -- Fills "shopping cart" table with wares ID for futher handling. + -- If context var 'ENABLE_FILL_PHRASES' = 1 then does it via SIMILAR TO + -- by searching phrases (patterns) in wares.name table. + -- Used in apps that CREATE new documents (client order, customer reserve etc) + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(1, v_this); + + v_ctx_max_rows = iif( a_optype_id in ( fn_oper_order_for_supplier(), fn_oper_invoice_get() ), + 'C_SUPPLIER_DOC_MAX_ROWS', + 'C_CUSTOMER_DOC_MAX_ROWS' + ); + v_ctx_max_qty = iif( a_optype_id in ( fn_oper_order_for_supplier(), fn_oper_invoice_get() ), + 'C_SUPPLIER_DOC_MAX_QTY', + 'C_CUSTOMER_DOC_MAX_QTY' + ); + + v_doc_rows = coalesce( a_rows2add, fn_get_random_quantity( v_ctx_max_rows ) ) ; + + v_source_for_random_id = + decode( a_optype_id, + fn_oper_order_by_customer(), 'v_all_wares', + fn_oper_order_for_supplier(), 'v_random_find_clo_ord', + fn_oper_invoice_get(), 'v_random_find_ord_sup', + fn_oper_retail_reserve(), 'v_random_find_avl_res', + 'unknown_source' + ); + + v_source_for_min_id = + decode( a_optype_id, + fn_oper_order_for_supplier(), 'v_min_id_clo_ord', + fn_oper_invoice_get(), 'v_min_id_ord_sup', + fn_oper_retail_reserve(), 'v_min_id_avl_res', + null + ); + + v_source_for_max_id = + decode( a_optype_id, + fn_oper_order_for_supplier(), 'v_max_id_clo_ord', + fn_oper_invoice_get(), 'v_max_id_ord_sup', + fn_oper_retail_reserve(), 'v_max_id_avl_res', + null + ); + + -- 17.07.2014: for some cases we allow to skip 'ORDER BY ID' clause + -- in sp_get_random_id when it will generate SQL expr for ES, + -- because all such randomly choosen IDs are handled in so way + -- that thay will be unavaliable in the source view + -- after this handling after it successfully ends. + -- Since 11.09.2014, start usage id desc in sp_get_random_id, + -- bitmaps building is very expensive ==> always set this var = 0. + v_can_skip_order_clause = 0; + + -- 19.07.2014, see DDL of views v_random_find_xxx: + -- they have `where not exists(select * from ... c id >= :id_rand_selected)`, + -- so it can be that search will NOT found any ID due to unhappy result of random + -- selection of 'anchor-ID' (no IDs will be found in 'where id >= :id_selected' + -- due to all of them have been removed etc) ==> we suppress e`xc in such case! + v_raise_exc_on_nofind = + decode( a_optype_id, + fn_oper_order_by_customer(), 0, + fn_oper_order_for_supplier(), 0, + fn_oper_invoice_get(), 0, + fn_oper_retail_reserve(), 0, + 1 + ); + + v_find_using_desc_index = + decode( a_optype_id, + fn_oper_order_for_supplier(), 1, + fn_oper_invoice_get(), 1, + fn_oper_retail_reserve(), 1, + 0 + ); + + select + r.snd_optype_id + ,r.storno_sub + from rules_for_qdistr r + where + r.rcv_optype_id = :a_optype_id + and r.mode containing 'new_doc' + into v_snd_optype_id, v_storno_sub; + + v_info = 'view='||v_source_for_random_id||', rows='||v_doc_rows||', oper='||a_optype_id; + + delete from tmp$shopping_cart where 1=1; + row_cnt = 0; + qty_sum = 0; + + for + select p.id_selected + from + sp_get_random_id( + :v_source_for_random_id, + :v_source_for_min_id, + :v_source_for_max_id, + :v_raise_exc_on_nofind, -- 19.07.2014: 0 ==> do NOT raise exception if not able to find any ID in view :v_source_for_random_id + :v_can_skip_order_clause, -- 17.07.2014: if = 1, then 'order by id' will be SKIPPED in statement inside fn + :v_find_using_desc_index, -- 11.09.2014, performance of select id from v_xxx order by id DESC rows 1 + :v_doc_rows + ) p + into v_ware_id + do + begin + v_qty = coalesce(a_maxq4row, fn_get_random_quantity( v_ctx_max_qty )); + if ( a_optype_id = fn_oper_order_by_customer() ) then + begin + -- Define cost of ware being added in customer order, + -- in purchasing and retailing prices (allow them to vary): + select + round( w.price_purchase + rand() * 300, -2) * :v_qty + ,round( w.price_retail + rand() * 300, -2) * :v_qty + from wares w + where w.id = :v_ware_id + into v_cost_purchase, v_cost_retail; + end + + if ( v_ware_id is not null ) then + begin + -- All the views v_r`andom_finx_xxx have checking clause like + -- "where NOT exists(select * from tmp$shopping_cart c where ...)" + -- so we can immediatelly do INSERT rather than update+check row_count=0 + insert into tmp$shopping_cart( + id, + snd_optype_id, + rcv_optype_id, + qty, + storno_sub, + cost_purchase, + cost_retail + ) + values ( + :v_ware_id, + :v_snd_optype_id, + :a_optype_id, + :v_qty, + :v_storno_sub, + :v_cost_purchase, + :v_cost_retail + ); + row_cnt = row_cnt + 1; -- out arg, will be used in getting batch IDs for doc_data (reduce lock-contention of GEN page) + qty_sum = qty_sum + ceiling( v_qty ); -- out arg, will be passed to s`p_multiply_rows_for_pdistr, s`p_make_qty_storno + + when any + do begin + if ( fn_is_uniqueness_trouble(gdscode) ) then + update tmp$shopping_cart t + set t.dup_cnt = t.dup_cnt+1 -- 4debug only + where t.id = :v_ware_id; + else + exception; -- anonimous but in WHEN block + end + end -- v_ware_id not null + end + +-- while ( v_doc_rows > 0 ) do begin +-- +-- v_qty = coalesce(a_maxq4row, fn_get_random_quantity( v_ctx_max_qty )); +-- +-- if ( a_optype_id = fn_oper_order_by_customer() ) then +-- begin +-- if ( rdb$get_context('USER_SESSION','ENABLE_FILL_PHRASES')='1' -- enable check performance of similar_to +-- and +-- exists( select * from phrases ) +-- ) then +-- begin +-- -- For checking performance of SIMILAR TO: +-- -- search using preliminary generated patterns +-- -- (generation of them see in oltp_fill_data.sql): +-- select p.pattern from phrases p +-- where p.id = (select sp_get_random_id('phrases',null,null, :v_raise_exc_on_nofind) from rdb$database) +-- into v_pattern; +-- v_stt = 'select id from wares where '||v_pattern||' rows 1'; +-- execute statement(v_stt) into v_ware_id; +-- if ( v_ware_id is null ) then +-- exception ex_record_not_found using ('wares', v_pattern); +-- end +-- else +-- v_ware_id = +-- sp_get_random_id( +-- v_source_for_random_id, +-- null, +-- null, +-- :v_raise_exc_on_nofind +-- ); -- <<< take random ware from price list +-- +-- -- Define cost of ware being added in customer order, +-- -- in purchasing and retailing prices (allow them to vary): +-- select +-- round( w.price_purchase + rand() * 300, -2) * :v_qty +-- ,round( w.price_retail + rand() * 300, -2) * :v_qty +-- from wares w +-- where w.id = :v_ware_id +-- into v_cost_purchase, v_cost_retail; +-- end +-- else -- a_optype_id <> fn_oper_order_by_customer() +-- begin +-- v_ware_id = +-- sp_get_random_id( +-- v_source_for_random_id, +-- v_source_for_min_id, +-- v_source_for_max_id, +-- v_raise_exc_on_nofind, -- 19.07.2014: 0 ==> do NOT raise exception if not able to find any ID in view :v_source_for_random_id +-- v_can_skip_order_clause, -- 17.07.2014: if = 1, then 'order by id' will be SKIPPED in statement inside fn +-- v_find_using_desc_index -- 11.09.2014, performance of select id from v_xxx order by id DESC rows 1 +-- ); +-- end +-- +-- if ( v_ware_id is not null ) then +-- begin +-- -- All the views v_r`andom_finx_xxx have checking clause like +-- -- "where NOT exists(select * from tmp$shopping_cart c where ...)" +-- -- so we can immediatelly do INSERT rather than update+check row_count=0 +-- insert into tmp$shopping_cart( +-- id, +-- snd_optype_id, +-- rcv_optype_id, +-- qty, +-- storno_sub, +-- cost_purchase, +-- cost_retail +-- ) +-- values ( +-- :v_ware_id, +-- :v_snd_optype_id, +-- :a_optype_id, +-- :v_qty, +-- :v_storno_sub, +-- :v_cost_purchase, +-- :v_cost_retail +-- ); +-- row_cnt = row_cnt + 1; -- out arg, will be used in getting batch IDs for doc_data (reduce lock-contention of GEN page) +-- qty_sum = qty_sum + ceiling( v_qty ); -- out arg, will be passed to s`p_multiply_rows_for_pdistr, s`p_make_qty_storno +-- +-- when any +-- do begin +-- if ( fn_is_uniqueness_trouble(gdscode) ) then +-- update tmp$shopping_cart t +-- set t.dup_cnt = t.dup_cnt+1 -- 4debug only +-- where t.id = :v_ware_id; +-- else +-- exception; -- anonimous but in WHEN block +-- end +-- end -- v_ware_id not null +-- v_doc_rows = v_doc_rows -1; +-- +-- end -- while ( v_doc_rows > 0 ) + + if ( not exists(select * from tmp$shopping_cart) ) then + exception ex_no_rows_in_shopping_cart using( v_source_for_random_id ); -- 'shopping_cart is empty, check source ''@1''' + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this,null, v_info ); + + suspend; -- row_cnt, qty_sum + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + v_info, + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end +end + +^ -- sp_fill_shopping_cart + +------------------------------------------------------------------------------ + +create or alter procedure sp_client_order( + dbg int default 0, + dbg_rows2add int default null, + dbg_maxq4row int default null +) +returns ( + doc_list_id type of dm_idb, + agent_id type of dm_idb, + doc_data_id type of dm_idb, + ware_id type of dm_idb, + qty type of dm_qty, + purchase type of dm_cost, -- purchasing cost for qty + retail type of dm_cost, -- retail cost + qty_clo type of dm_qty, -- new value of corresponding row in invnt_saldo + qty_clr type of dm_qty, -- new value of corresponding row in invnt_saldo + qty_ord type of dm_qty -- new value of corresponding row in invnt_saldo +) +as + declare c_gen_inc_step_dd int = 20; -- size of `batch` for get at once new IDs for doc_data (reduce lock-contention of gen page) + declare v_gen_inc_iter_dd int; -- increments from 1 up to c_gen_inc_step_dd and then restarts again from 1 + declare v_gen_inc_last_dd dm_idb; -- last got value after call gen_id (..., c_gen_inc_step_dd) + + declare c_gen_inc_step_nt int = 20; -- size of `batch` for get at once new IDs for invnt_turnover_log (reduce lock-contention of gen page) + declare v_gen_inc_iter_nt int; -- increments from 1 up to c_gen_inc_step_dd and then restarts again from 1 + declare v_gen_inc_last_nt dm_idb; -- last got value after call gen_id (..., c_gen_inc_step_dd) + + declare v_oper_order_by_customer dm_idb; + declare v_nt_new_id dm_idb; + declare v_clo_for_our_firm dm_sign = 0; + declare v_rows_added int = 0; + declare v_qty_sum dm_qty = 0; + declare v_purchase_sum dm_cost; + declare v_retail_sum dm_cost; + declare v_ibe smallint; + declare v_stt varchar(255); + declare v_dd_new_id bigint; + declare v_dd_dbkey dm_dbkey; + declare v_dbkey dm_dbkey; + declare v_this dm_dbobj = 'sp_client_order'; + + declare c_shop_cart cursor for ( + select + c.id, + c.qty, + c.cost_purchase, + c.cost_retail + from tmp$shopping_cart c + ); +begin + -- Selects randomly agent, wares and creates a new document with wares which + -- we should provide to customer ("CLIENT ORDER"). Business starts from THIS + -- kind of doc: customer comes in our office and wants to buy / order smthn. + + -- Check that table `ext_stoptest` (external text file) is EMPTY, + -- otherwise raises ex`ception to stop test: + execute procedure sp_check_to_stop_work; + + -- Check that current Tx run in NO wait or with lock_timeout. + -- Otherwise raise error: performance degrades almost to zero. + execute procedure sp_check_nowait_or_timeout; + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(1, v_this); + + -- increment number of total business routine calls within this Tx, + -- in order to display estimated overall performance in ISQL session + -- logs (see generated $tmpdir/tmp_random_run.sql). + -- Instead of querying perf_log join business_ops it was decided to + -- use only context variables in user_tran namespace: + execute procedure srv_increment_tx_bops_counter; + + v_oper_order_by_customer = fn_oper_order_by_customer(); + + -- Random select contragent for this client order + -- About 20...30% of orders are for our firm (==> they will NOT move to + -- 'reserves' after corresponding invoices will be added to stock balance): + if ( rand()*100 <= cast(rdb$get_context('USER_SESSION', 'ORDER_FOR_OUR_FIRM_PERCENT') as int) ) then + begin + v_clo_for_our_firm = 1; + --agent_id = sp_get_random_id('v_our_firm', null, null, 0); + select id_selected from sp_get_random_id('v_our_firm', null, null, 0) into agent_id; + end + else + agent_id = fn_get_random_customer(); + + execute procedure sp_fill_shopping_cart( v_oper_order_by_customer, dbg_rows2add, dbg_maxq4row ) + returning_values v_rows_added, v_qty_sum; + + if (dbg=1) then exit; + + execute procedure sp_add_doc_list( + null, + v_oper_order_by_customer, + agent_id, + fn_doc_fix_state() + ) + returning_values + :doc_list_id, -- out arg + :v_dbkey; + + v_gen_inc_iter_dd = 1; + c_gen_inc_step_dd = 1 + v_rows_added; -- for adding rows in doc_data: size of batch = number of rows in tmp$shop_cart + 1 + v_gen_inc_last_dd = gen_id( g_doc_data, :c_gen_inc_step_dd );-- take bulk IDs at once (reduce lock-contention for GEN page) + + v_gen_inc_iter_nt = 1; + c_gen_inc_step_nt = 1 + v_rows_added; -- for adding rows in invnt_turnover_log: size of batch = number of rows in tmp$shop_cart + 1 + v_gen_inc_last_nt = gen_id( g_common, :c_gen_inc_step_nt );-- take bulk IDs at once (reduce lock-contention for GEN page) + + v_purchase_sum = 0; + v_retail_sum = 0; + + -- Process each record in tmp$shopping_cart: + -- 1) add row to detalization table (doc_data) with amount that client orders; + -- 2) add for each row from shoping cart SEVERAL rows in QDistr - they form + -- set of records for futher STORNING by new document(s) in next business + -- operation (our order to supplier). Number of rows being added in QDistr + -- equals to doc_data.qty (for simplicity of code these amounts are considered + -- to be always INTEGER values). + open c_shop_cart; + while (1=1) do + begin + fetch c_shop_cart into ware_id, qty, purchase, retail; + if ( row_count = 0 ) then leave; + + if ( v_gen_inc_iter_dd = c_gen_inc_step_dd ) then -- its time to get another batch of IDs + begin + v_gen_inc_iter_dd = 1; + -- take subsequent bulk IDs at once (reduce lock-contention for GEN page) + v_gen_inc_last_dd = gen_id( g_doc_data, :c_gen_inc_step_dd ); + end + v_dd_new_id = v_gen_inc_last_dd - ( c_gen_inc_step_dd - v_gen_inc_iter_dd ); + +-- rdb$set_context('USER_TRANSACTION','DBG_DD_D', +-- 'v_dd_new_id='||v_dd_new_id +-- ||', v_last_dd='||v_gen_inc_last_dd +-- ||', c_step_dd='||c_gen_inc_step_dd +-- ||', v_iter_dd='||v_gen_inc_iter_dd +-- ); + v_gen_inc_iter_dd = v_gen_inc_iter_dd + 1; + + if ( v_gen_inc_iter_nt = c_gen_inc_step_nt ) then -- its time to get another batch of IDs + begin + v_gen_inc_iter_nt = 1; + -- take subsequent bulk IDs at once (reduce lock-contention for GEN page) + v_gen_inc_last_nt = gen_id( g_common, :c_gen_inc_step_nt ); + end + v_nt_new_id = v_gen_inc_last_nt - ( c_gen_inc_step_nt - v_gen_inc_iter_nt ); + v_gen_inc_iter_nt = v_gen_inc_iter_nt + 1; + + execute procedure sp_add_doc_data( + doc_list_id, + v_oper_order_by_customer, + v_dd_new_id, -- preliminary calculated ID for new record in doc_data (reduce lock-contention of GEN page) + v_nt_new_id, -- preliminary calculated ID for new record in invnt_turnover_log (reduce lock-contention of GEN page) + ware_id, + qty, + purchase, + retail + ) returning_values v_dd_new_id, v_dd_dbkey; + + -- Write ref to doc_data.id - it will be used in sp_multiply_rows_for_qdistr: + update tmp$shopping_cart c set c.snd_id = :v_dd_new_id where current of c_shop_cart; + + -- do NOT use trigger-way updates of doc header for each row being added + -- in detalization table: it will be run only once after this loop (performance): + v_purchase_sum = v_purchase_sum + purchase; + v_retail_sum = v_retail_sum + retail; + end -- cursor on tmp$shopping_car join wares + close c_shop_cart; + + if (dbg=2) then exit; + -- 02.09.2014 2205: remove call of sp_multiply_rows_for_qdistr from t`rigger d`oc_data_aiud + -- (otherwise fractional values in cumulative qdistr.snd_purchase will be when costs for + -- same ware in several storned docs differs): + -- 30.09.2014: move out from for-loop, single call: + execute procedure sp_multiply_rows_for_qdistr( + doc_list_id, + v_oper_order_by_customer, + v_clo_for_our_firm, + v_qty_sum -- this is number of _ROWS_ that will be added into QDistr (used to calc. size of 'bulks' of new IDs - minimize call of gen_id in sp_multiply_rows_for_qdistr) + ); + if (dbg=3) then exit; + + -- Single update of doc header (not for every row added in doc_data table + -- as it would be via it's trigger). + -- Trigger d`oc_list_aiud will call sp_add_invnt_log to add rows to invnt_turnover_log + update doc_list h set + h.cost_purchase = :v_purchase_sum, + h.cost_retail = :v_retail_sum + where h.rdb$db_key = :v_dbkey; + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this,null, 'doc_id='||coalesce(doc_list_id,'')||', rows='||v_rows_added ); + + v_ibe = iif( fn_remote_process() containing 'IBExpert', 1, 0); + -- 16.07.2014: make ES more 'smart': we do NOT need any records from view + -- v_doc_detailed (==> v_saldo_invnt!) if there is NO debug now (performance!) + if ( v_ibe = 1 ) then + v_stt = 'select v.agent_id, v.doc_data_id, v.ware_id, v.qty, v.cost_purchase, v.cost_retail' + ||',v.qty_clo ,v.qty_clr ,v.qty_ord' + ||' from v_doc_detailed v where v.doc_id = :x'; + else + v_stt = 'select h.agent_id, d.id, d.ware_id, d.qty, d.cost_purchase, d.cost_retail' + ||',null ,null ,null' + ||' from doc_data d join doc_list h on d.doc_id = h.id where d.doc_id = :x'; + + -- final resultset (need only in IBE, for debug purposes): + for + execute statement(v_stt) ( x := :doc_list_id ) + into + agent_id + ,doc_data_id + ,ware_id + ,qty + ,purchase + ,retail + ,qty_clo + ,qty_clr + ,qty_ord + do + suspend; + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + 'doc_id='||coalesce(doc_list_id,''), + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + +^ -- end of sp_client_order +------------------------------------------------------------------------------ + +create or alter procedure sp_cancel_client_order( + a_selected_doc_id type of dm_idb default null, + dbg int default 0 +) +returns ( + doc_list_id type of dm_idb, + agent_id type of dm_idb, + doc_data_id type of dm_idb, + ware_id type of dm_idb, + qty type of dm_qty, + purchase type of dm_cost, -- purchasing cost for qty + retail type of dm_cost, -- retail cost + qty_clo type of dm_qty, -- new value of corresponding row in invnt_saldo + qty_clr type of dm_qty, -- new value of corresponding row in invnt_saldo + qty_ord type of dm_qty +) +as + declare v_ibe smallint; + declare v_stt varchar(255); + declare v_dummy bigint; + declare c_raise_exc_when_no_found dm_sign = 1; + declare c_can_skip_order_clause dm_sign = 0; + declare v_this dm_dbobj = 'sp_cancel_client_order'; +begin + + -- Moves client order in 'cancelled' state. No rows from such client order + -- will be ordered to supplier (except those which we already ordered before) + + -- Check that table `ext_stoptest` (external text file) is EMPTY, + -- otherwise raises ex`ception to stop test: + execute procedure sp_check_to_stop_work; + + -- Check that current Tx run in NO wait or with lock_timeout. + -- Otherwise raise error: performance degrades almost to zero. + execute procedure sp_check_nowait_or_timeout; + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(1, v_this); + + -- increment number of total business routine calls within this Tx, + -- in order to display estimated overall performance in ISQL session + -- logs (see generated $tmpdir/tmp_random_run.sql). + -- Instead of querying perf_log join business_ops it was decided to + -- use only context variables in user_tran namespace: + execute procedure srv_increment_tx_bops_counter; + + -- Choose random doc of corresponding kind. + -- 25.09.2014: do NOT set c_can_skip_order_clause = 1, + -- performance degrades from ~4900 to ~1900. + doc_list_id = coalesce( :a_selected_doc_id, + (select id_selected from + sp_get_random_id( 'v_cancel_client_order' -- a_view_for_search + ,null -- a_view_for_min_id ==> the same as a_view_for_search + ,null -- a_view_for_max_id ==> the same as a_view_for_search + ,:c_raise_exc_when_no_found + ,:c_can_skip_order_clause + ) + ) + ); + + -- Find doc ID (with checking in view v_*** is need) and try to LOCK it. + -- Raise exc if can`t lock: + execute procedure sp_lock_selected_doc( doc_list_id, 'v_cancel_client_order', a_selected_doc_id); + + -- 20.05.2014: BLOCK client_order in ALL cases instead of solving question about deletion + -- Trigger doc_list_biud will (only for deleting doc or updating it's state): + -- 1) call s`p_kill_qty_storno that returns rows from Q`Storned to Q`distr + -- Trigger doc_list_aiud will: + -- 1) add rows in table i`nvnt_turnover_log (log to be processed by SP s`rv_make_invnt_saldo) + -- 2) call s`p_multiply_rows_for_pdistr, s`p_make_cost_storno or s`p_kill_cost_storno, s`p_add_money_log + update doc_list h set + h.optype_id = fn_oper_cancel_customer_order(), + h.state_id = fn_doc_canc_state() --"cancelled without revert" + where h.id = :doc_list_id; + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this,null, 'doc_id='||doc_list_id); + + v_ibe = iif( fn_remote_process() containing 'IBExpert', 1, 0); + -- 16.07.2014: make ES more 'smart': we do NOT need any records from view + -- v_doc_detailed (==> v_saldo_invnt!) if there is NO debug now (performance!) + if ( v_ibe = 1 ) then + v_stt = 'select v.agent_id, v.doc_data_id, v.ware_id, v.qty, v.cost_purchase, v.cost_retail' + ||',v.qty_clo ,v.qty_clr ,v.qty_ord' + ||' from v_doc_detailed v where v.doc_id = :x'; + else + v_stt = 'select h.agent_id, d.id, d.ware_id, d.qty, d.cost_purchase, d.cost_retail' + ||',null ,null ,null' + ||' from doc_data d join doc_list h on d.doc_id = h.id where d.doc_id = :x'; + + -- final resultset (need only in IBE, for debug purposes): + for + execute statement(v_stt) ( x := :doc_list_id ) + into + agent_id + ,doc_data_id + ,ware_id + ,qty + ,purchase + ,retail + ,qty_clo + ,qty_clr + ,qty_ord + do + suspend; + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + 'doc_id='||coalesce(doc_list_id,''), + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + +^ -- end of sp_cancel_client_order + +------------------------------------------------------------------------------ + +create or alter procedure sp_supplier_order( + dbg int default 0, + dbg_rows2add int default null, + dbg_maxq4row int default null +) +returns ( + doc_list_id type of dm_idb, + agent_id type of dm_idb, + doc_data_id type of dm_idb, + ware_id type of dm_idb, + qty type of dm_qty, -- amount that we ordered for client + purchase type of dm_cost, -- purchasing cost for qty + retail type of dm_cost, -- retail cost + qty_clo type of dm_qty, -- new value of corresponding row in invnt_saldo + qty_ord type of dm_qty -- new value of corresponding row in invnt_saldo +) +as + declare v_id bigint; + declare v_rows_added int; + declare v_qty_sum dm_qty; + declare v_ibe smallint; + declare v_stt varchar(255); + declare v_dummy bigint; + declare v_this dm_dbobj = 'sp_supplier_order'; +begin + + -- Processes several client orders and creates OUR order of wares to randomly + -- selected supplier (i.e. we expect these wares to be supplied by him). + -- Makes storning of corresp. amounts, so preventing duplicate including in further + -- supplier orders such wares (part of their total amounts) which was already ordered. + -- This operation is NEXT after client order in 'business chain'. + + -- Check that table `ext_stoptest` (external text file) is EMPTY, + -- otherwise raises ex`ception to stop test: + execute procedure sp_check_to_stop_work; + + -- Check that current Tx run in NO wait or with lock_timeout. + -- Otherwise raise error: performance degrades almost to zero. + execute procedure sp_check_nowait_or_timeout; + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(1, v_this); + + -- increment number of total business routine calls within this Tx, + -- in order to display estimated overall performance in ISQL session + -- logs (see generated $tmpdir/tmp_random_run.sql). + -- Instead of querying perf_log join business_ops it was decided to + -- use only context variables in user_tran namespace: + execute procedure srv_increment_tx_bops_counter; + + -- choose randomly contragent that will be supplier for this order: + agent_id = fn_get_random_supplier(); + + execute procedure sp_fill_shopping_cart( fn_oper_order_for_supplier(), dbg_rows2add, dbg_maxq4row ) + returning_values v_rows_added, v_qty_sum; + + if (dbg=1) then exit; + + -- 1. Find rows in QDISTR (and silently try to LOCK them) which can provide + -- required amounts in tmp$shopping_cart, in FIFO manner. + -- 2. Perform "STORNING" of them (moves these rows from QDISTR to QSTORNED) + -- 3. Create new document: header (doc_list) and detalization (doc_data). + execute procedure sp_make_qty_storno( + fn_oper_order_for_supplier() + ,agent_id + ,fn_doc_open_state() + ,null + ,v_rows_added -- used there for 'smart' definition of value to increment gen + ,v_qty_sum -- used there for 'smart' definition of value to increment gen + ) returning_values doc_list_id; + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this, null, 'doc_id='||coalesce(doc_list_id,'')); + + v_ibe = iif( fn_remote_process() containing 'IBExpert', 1, 0); + + -- 16.07.2014: make ES more 'smart': we do NOT need any records from view + -- v_doc_detailed (==> v_saldo_invnt!) if there is NO debug now (performance!) + if ( v_ibe = 1 ) then + v_stt = 'select v.agent_id, v.doc_data_id, v.ware_id, v.qty, v.cost_purchase, v.cost_retail' + ||' ,v.qty_clo ,v.qty_ord' + ||' from v_doc_detailed v where v.doc_id = :x'; + else + v_stt = 'select h.agent_id, d.id, d.ware_id, d.qty, d.cost_purchase, d.cost_retail' + ||' ,null ,null' + ||' from doc_data d join doc_list h on d.doc_id = h.id where d.doc_id = :x'; + + -- final resultset (need only in IBE, for debug purposes): + for + execute statement(v_stt) ( x := :doc_list_id ) + into + agent_id + ,doc_data_id + ,ware_id + ,qty + ,purchase + ,retail + ,qty_clo + ,qty_ord + do + suspend; + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + 'doc_id='||coalesce(doc_list_id,''), + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + +^ -- end of sp_supplier_order + +----------------------------------------- + +create or alter procedure sp_supplier_invoice ( + dbg int = 0, + dbg_rows2add int default null, + dbg_maxq4row int default null +) +returns ( + doc_list_id type of dm_idb, + agent_id type of dm_idb, + doc_data_id type of dm_idb, + ware_id type of dm_idb, + qty type of dm_qty, + purchase type of dm_cost, + retail type of dm_cost, + qty_clo type of dm_qty, + qty_ord type of dm_qty, + qty_sup type of dm_qty +) +as + declare v_rows_added int; + declare v_qty_sum dm_qty; + declare v_ibe smallint; + declare v_stt varchar(255); + declare v_this dm_dbobj = 'sp_supplier_invoice'; +begin + + -- Simulates activity of our SUPPLIER when he got from us several orders: + -- process randomly chosen wares from our orders and add them into INVOICE - + -- the document that we consider as preliminary income (i.e. NOT yet accepted). + -- Makes storning of corresp. amounts, so preventing duplicate including in further + -- supplier invoices such wares (part of their total amounts) which was already + -- included in this invoice. + -- This operation is NEXT after our order to supplier in 'business chain'. + + -- Check that table `ext_stoptest` (external text file) is EMPTY, + -- otherwise raises exc`eption to stop test: + execute procedure sp_check_to_stop_work; + + -- Check that current Tx run in NO wait or with lock_timeout. + -- Otherwise raise error: performance degrades almost to zero. + execute procedure sp_check_nowait_or_timeout; + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(1, v_this); + + -- increment number of total business routine calls within this Tx, + -- in order to display estimated overall performance in ISQL session + -- logs (see generated $tmpdir/tmp_random_run.sql). + -- Instead of querying perf_log join business_ops it was decided to + -- use only context variables in user_tran namespace: + execute procedure srv_increment_tx_bops_counter; + + -- select supplier, random: + agent_id = fn_get_random_supplier(); + + execute procedure sp_fill_shopping_cart( fn_oper_invoice_get(), dbg_rows2add, dbg_maxq4row ) + returning_values v_rows_added, v_qty_sum; + + if (dbg=1) then exit; + + -- 1. Find rows in QDISTR (and silently try to LOCK them) which can provide required + -- amounts in tmp$shopping_cart, in FIFO manner. + -- 2. Perform "STORNING" of them (moves these rows from QDISTR to QSTORNED) + -- 3. Create new document: header (doc_list) and detalization (doc_data). + execute procedure sp_make_qty_storno( + fn_oper_invoice_get() + ,agent_id + ,fn_doc_open_state() + ,null + ,v_rows_added -- used there for 'smart' definition of value to increment gen + ,v_qty_sum -- used there for 'smart' definition of value to increment gen + ) returning_values doc_list_id; + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this, null, 'doc_id='||coalesce(doc_list_id,'')); + + v_ibe = iif( fn_remote_process() containing 'IBExpert', 1, 0); + -- 16.07.2014: make ES more 'smart': we do NOT need any records from view + -- v_doc_detailed (==> v_saldo_invnt!) if there is NO debug now (performance!) + if ( v_ibe = 1 ) then + v_stt = 'select v.agent_id, v.doc_data_id, v.ware_id, v.qty, v.cost_purchase, v.cost_retail' + ||' ,v.qty_clo ,v.qty_ord ,v.qty_sup' + ||' from v_doc_detailed v where v.doc_id = :x'; + else + v_stt = 'select h.agent_id, d.id, d.ware_id, d.qty, d.cost_purchase, d.cost_retail' + ||' ,null ,null ,null' + ||' from doc_data d join doc_list h on d.doc_id = h.id where d.doc_id = :x'; + + -- final resultset (need only in IBE, for debug purposes): + for + execute statement(v_stt) ( x := :doc_list_id ) + into + agent_id + ,doc_data_id + ,ware_id + ,qty + ,purchase + ,retail + ,qty_clo + ,qty_ord + ,qty_sup + do + suspend; + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + 'doc_id='||coalesce(doc_list_id,''), + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end +end + +^ -- end of sp_supplier_invoice + +----------------------------------------- + +create or alter procedure sp_cancel_supplier_invoice( + a_selected_doc_id type of dm_idb default null, + a_skip_lock_attempt dm_sign default 0 -- 1==> do NOT call sp_lock_selected_doc because this doc is already locked (see call from sp_cancel_adding_invoice) +) +returns( + doc_list_id type of dm_idb, -- id of created invoice + agent_id type of dm_idb, -- id of supplier + doc_data_id type of dm_idb, -- id of created records in doc_data + ware_id type of dm_idb, -- id of wares that we will get from supplier + qty type of dm_qty, -- amount that supplier will send to us + purchase type of dm_cost, -- total purchasing cost for qty + retail type of dm_cost, -- assigned retail cost + qty_clo type of dm_qty, -- new value of corresponding row in invnt_saldo + qty_ord type of dm_qty, -- new value of corresponding row in invnt_saldo + qty_sup type of dm_qty -- new value of corresponding row in invnt_saldo +) +as + declare v_dummy bigint; + declare v_ibe smallint; + declare v_stt varchar(255); + declare c_raise_exc_when_no_found dm_sign = 1; + declare c_can_skip_order_clause dm_sign = 0; + declare v_this dm_dbobj = 'sp_cancel_supplier_invoice'; +begin + + -- Randomly chooses invoice from supplier (NOT yet accepted) and CANCEL it + -- by REMOVING all its data + record in docs header table. It occurs when + -- we mistakenly created such invoice and now have to cancel this operation. + -- All wares which were in such invoice will be enabled again to be included + -- in new (another) invoice which we create after this - due to removing info + -- about amounts storning that was done before when invoice was created. + + -- Check that table `ext_stoptest` (external text file) is EMPTY, + -- otherwise raises exc`eption to stop test: + execute procedure sp_check_to_stop_work; + + -- Check that current Tx run in NO wait or with lock_timeout. + -- Otherwise raise error: performance degrades almost to zero. + execute procedure sp_check_nowait_or_timeout; + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(1, v_this); + + -- increment number of total business routine calls within this Tx, + -- in order to display estimated overall performance in ISQL session + -- logs (see generated $tmpdir/tmp_random_run.sql). + -- Instead of querying perf_log join business_ops it was decided to + -- use only context variables in user_tran namespace: + execute procedure srv_increment_tx_bops_counter; + + -- Choose random doc of corresponding kind. + -- 25.09.2014: do NOT set c_can_skip_order_clause = 1, + -- performance degrades from ~4900 to ~1900. + doc_list_id = coalesce( :a_selected_doc_id, + ( select id_selected from + sp_get_random_id( 'v_cancel_supplier_invoice' -- a_view_for_search + ,null -- a_view_for_min_id ==> the same as a_view_for_search + ,null -- a_view_for_max_id ==> the same as a_view_for_search + ,:c_raise_exc_when_no_found + ,:c_can_skip_order_clause + ) + ) + ); + -- upd. log with doc id whic is actually handling now: + execute procedure sp_upd_in_perf_log( v_this, null, 'dh='||doc_list_id); + + -- Try to LOCK just selected doc, raise exc if can`t: + if ( NOT (a_selected_doc_id is NOT null and a_skip_lock_attempt = 1) ) then + execute procedure sp_lock_selected_doc( doc_list_id, 'v_cancel_supplier_invoice', a_selected_doc_id); + + -- 17.07.2014: add cond for indexed scan to minimize fetches when multiple + -- calls of this SP from sp_cancel_adding_invoice: + delete from tmp$result_set r where r.doc_id = :doc_list_id; + + -- save data which is to be deleted (NB! this action became MANDATORY for + -- checking in srv_find_qd_qs_mism, do NOT delete it!): + insert into tmp$result_set( doc_id, agent_id, doc_data_id, ware_id, qty, cost_purchase, cost_retail) + select :doc_list_id, h.agent_id, d.id, d.ware_id, d.qty, d.cost_purchase, d.cost_retail + from doc_data d + join doc_list h on d.doc_id = h.id + where d.doc_id = :doc_list_id; -- invoice which is to be removed now + + -- Trigger doc_list_biud will (only for deleting doc or updating it's state): + -- 1) call s`p_kill_qty_storno that returns rows from Q`Storned to Q`distr + -- Trigger doc_list_aiud will: + -- 1) add rows in table i`nvnt_turnover_log (log to be processed by SP s`rv_make_invnt_saldo) + -- 2) call s`p_multiply_rows_for_pdistr, s`p_make_cost_storno or s`p_kill_cost_storno, s`p_add_money_log + delete from doc_list h where h.id = :doc_list_id; + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this, null); + + v_ibe = iif( fn_remote_process() containing 'IBExpert', 1, 0); + -- 16.07.2014: make ES more 'smart': we do NOT need any records from view + -- v_doc_detailed (==> v_saldo_invnt!) if there is NO debug now (performance!) + v_stt = 'select r.doc_id,r.agent_id,r.doc_data_id,r.ware_id,r.qty,r.cost_purchase,r.cost_retail'; + + if ( v_ibe = 1 ) then + v_stt = v_stt || ' ,n.qty_clo ,n.qty_ord ,n.qty_sup'; + else + v_stt = v_stt || ' ,null ,null ,null'; + + v_stt = v_stt ||' from tmp$result_set r'; + if ( v_ibe = 1 ) then + v_stt = v_stt || ' left join v_saldo_invnt n on r.ware_id = n.ware_id'; + + -- 17.07.2014: add cond for indexed scan to minimize fetches when multiple + -- calls of this SP from s`p_cancel_supplier_order: + v_stt = v_stt || ' where r.doc_id = :x'; + + -- final resultset (need only in IBE, for debug purposes): + for + execute statement (v_stt) ( x := :doc_list_id ) + into + doc_list_id + ,agent_id + ,doc_data_id + ,ware_id + ,qty + ,purchase + ,retail + ,qty_clo + ,qty_ord + ,qty_sup + do + suspend; + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + 'doc_id='||coalesce(doc_list_id,''), + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + +^ -- sp_cancel_supplier_invoice + +----------------------------------------- + +create or alter procedure sp_fill_shopping_cart_clo_res( + a_client_order_id dm_idb +) +returns ( + row_cnt int, -- number of rows added to tmp$shop_cart + qty_sum dm_qty -- total on QTY field in tmp$shop_cart +) +as + declare v_oper_invoice_add dm_idb; + declare v_oper_retail_reserve dm_idb; + declare v_oper_order_by_customer dm_idb; + declare v_ware_id dm_idb; + declare v_dd_id dm_idb; + declare v_clo_qty_need_to_reserve dm_qty; + declare v_this dm_dbobj = 'sp_fill_shopping_cart_clo_res'; +begin + -- Aux. SP: fills tmp$shopping_cart with data from client_order, but take in + -- account only those amounts which still need to be reserved. + + execute procedure sp_add_perf_log(1, v_this, null, 'clo='||a_client_order_id); + + v_oper_invoice_add = fn_oper_invoice_add(); + v_oper_order_by_customer = fn_oper_order_by_customer(); + v_oper_retail_reserve = fn_oper_retail_reserve(); + qty_sum = 0; -- out arg + for + select + d.ware_id, + d.id as dd_id, -- 22.09.2014: for processing in separate cursor in sp_make_qty_distr that used index on snd_op, rcv_op, snd_id + sum(q.snd_qty) as clo_qty_need_to_reserve -- rest of init amount in client order that still needs to be reserved + -- 16.09.2014 PLAN SORT (JOIN (D INDEX (FK_DOC_DATA_DOC_LIST), Q INDEX (QDISTR_SNDOP_RCVOP_SNDID_DESC))) + -- (much faster than old: from qdistr where q.doc_id = :a_client_order_id and snd_op = ... and rcv_op = ...) + from doc_data d + LEFT -- !! force to fix plan with 'doc_data' as drive table, see CORE-4926 + join v_qdistr_source q on + -- :: NB :: full match on index range scan must be here! + q.ware_id = d.ware_id + and q.snd_optype_id = :v_oper_order_by_customer + and q.rcv_optype_id = :v_oper_retail_reserve + and q.snd_id = d.id --- :: NB :: full match on index range scan must be here! + where + d.doc_id = :a_client_order_id + and q.id is not null + group by d.ware_id, d.id + into v_ware_id, v_dd_id, v_clo_qty_need_to_reserve + do begin + insert into tmp$shopping_cart( + id, + snd_id, -- 22.09.2014: for handling qdistr in separate cursor wher storno_sub=2! + snd_optype_id, + rcv_optype_id, + qty, + storno_sub + ) + values ( + :v_ware_id, + :v_dd_id, + :v_oper_invoice_add, + :v_oper_retail_reserve, + :v_clo_qty_need_to_reserve, -- :: NB :: this is the REST of initially ordered amount (i.e. LESS or equal to origin value in doc_data.qty for clo!) + 1 + ); + row_cnt = row_cnt + 1; -- out arg + qty_sum = qty_sum + v_clo_qty_need_to_reserve; -- out arg + end + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this, null, 'rc='||row_count ); + + suspend; -- row_cnt, qty_sum + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + 'clo='||a_client_order_id, + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + +^ -- sp_fill_shopping_cart_clo_res + +----------------------------------------- + +create or alter procedure sp_customer_reserve( + a_client_order_id type of dm_idb default null, + dbg integer default 0) +returns ( + doc_list_id type of dm_idb, + client_order_id type of dm_idb, + doc_data_id type of dm_idb, + ware_id type of dm_idb, + qty type of dm_qty, + purchase type of dm_cost, + retail type of dm_cost, + qty_ord type of dm_qty, + qty_avl type of dm_qty, + qty_res type of dm_qty +) +as + declare v_rows_added int; + declare v_qty_sum dm_qty; + declare v_dbkey dm_dbkey; + declare v_agent_id type of dm_idb; + declare v_raise_exc_on_nofind dm_sign; + declare v_can_skip_order_clause dm_sign; + declare v_find_using_desc_index dm_sign; + declare v_ibe smallint; + declare v_stt varchar(255); + declare v_this dm_dbobj = 'sp_customer_reserve'; +begin + + -- Takes several wares, adds them into + -- tmp$shopping_cart and and creates new document that reserves + -- these wares for customer, in amount that is currently avaliable + -- If parameter a_client_order_id is NOT_null then fill tmp$shopping_cart + -- with wares from THAT client order rather than random choosen wares set + -- Document 'customer_reserve' can appear in business chain in TWO places: + -- 1) at the beginning (when customer comes to us and wants to buy some wares + -- which we have just now); + -- 2) after we accept invoice which has wares from client order - in that case + -- we need to reserve wares for customer(s) as soon as possible and we do + -- it in the same Tx with accepting invoice (==> this will be 'heavy' Tx). + + -- Check that table `ext_stoptest` (external text file) is EMPTY, + -- otherwise raises exc`eption to stop test: + execute procedure sp_check_to_stop_work; + + -- Check that current Tx run in NO wait or with lock_timeout. + -- Otherwise raise error: performance degrades almost to zero. + execute procedure sp_check_nowait_or_timeout; + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log( + 1, + v_this, + null, + iif( a_client_order_id is null, 'from avaliable remainders', 'for clo_id='||a_client_order_id ) + ); + + -- increment number of total business routine calls within this Tx, + -- in order to display estimated overall performance in ISQL session + -- logs (see generated $tmpdir/tmp_random_run.sql). + -- Instead of querying perf_log join business_ops it was decided to + -- use only context variables in user_tran namespace: + execute procedure srv_increment_tx_bops_counter; + + if ( a_client_order_id = -1 ) then -- create reserve from avaliable remainders + a_client_order_id = null; + else if ( a_client_order_id is null ) then + begin + v_raise_exc_on_nofind = 0; -- do NOT raise exc if random seacrh will not find any record + v_can_skip_order_clause = 0; -- do NOT skip `order by` clause in sp_get_random_id (if order by id DESC will be used!) + v_find_using_desc_index = 0; -- 22.09.2014; befo: 1; -- use 'order by id DESC' (11.09.2014) + -- First of all try to search among client_orders which have + -- at least one row with NOT_fully reserved ware. + -- Call sp_get_random_id with arg NOT to raise exc`eption if + -- it will not found such documents: + select id_selected + from + sp_get_random_id( + 'v_random_find_clo_res', + 'v_min_id_clo_res', + 'v_max_id_clo_res', + :v_raise_exc_on_nofind, + :v_can_skip_order_clause, + :v_find_using_desc_index + ) + into + a_client_order_id; + end + + v_qty_sum = 0; + while (1=1) do begin -- ............... m a i n l o o p ................. + + delete from tmp$shopping_cart where 1=1; + + if (a_client_order_id is null) then -- 'common' reserve, NOT related to client order + begin + -- ###### R E S E R V E A V A L I A B L E W A R E S ##### + execute procedure sp_fill_shopping_cart( fn_oper_retail_reserve() ) + returning_values v_rows_added, v_qty_sum; + + -- select customer, random: + v_agent_id = fn_get_random_customer(); + end + else begin -- reserve based on client order: scan its wares which still need to be reserved + + -- ########## R E S E R V E F O R C L I E N T O R D E R ###### + + select h.rdb$db_key, h.agent_id + from doc_list h + where h.id = :a_client_order_id + into v_dbkey, v_agent_id; + + if (v_dbkey is null) then exception ex_no_doc_found_for_handling using('doc_list', :a_client_order_id); + + -- fill tmp$shopping_cart with client_order data + -- (NB: sp_make_qty_storno will put in reserve only those amounts + -- for which there are at least one row in qdistr, so we can put in + -- tmp$shopp_cart ALL rows from client order and no filter them now): + execute procedure sp_fill_shopping_cart_clo_res( :a_client_order_id ) + returning_values v_rows_added, v_qty_sum; + + end -- a_client_order_id order NOT null + + if (dbg=1) then leave; + + -- 1. Find rows in QDISTR (and silently try to LOCK them) which can provide required + -- amounts in tmp$shopping_cart, in FIFO manner. + -- 2. Perform "STORNING" of them (moves these rows from QDISTR to QSTORNED) + -- 3. Create new document: header (doc_list) and detalization (doc_data). + if ( v_qty_sum > 0 ) then + begin + execute procedure sp_make_qty_storno( + fn_oper_retail_reserve() + ,v_agent_id + ,fn_doc_open_state() + ,a_client_order_id + ,v_rows_added + ,v_qty_sum + ) returning_values doc_list_id; -- out arg + end + leave; + + end -- while (1=1) -- ............... m a i n l o o p ................. + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this, null, coalesce(doc_list_id,'') ); + + if ( dbg=4 ) then exit; + + v_ibe = iif( fn_remote_process() containing 'IBExpert', 1, 0); + -- 16.07.2014: make ES more 'smart': we do NOT need any records from view + -- v_doc_detailed (==> v_saldo_invnt!) if there is NO debug now (performance!) + if ( v_ibe = 1 ) then + v_stt = 'select v.base_doc_id, v.doc_data_id, v.ware_id, v.qty,v.cost_purchase, v.cost_retail' + ||',v.qty_ord ,v.qty_avl ,v.qty_res' + ||' from v_doc_detailed v where v.doc_id = :x'; + else + v_stt = 'select h.base_doc_id, d.id, d.ware_id, d.qty,d.cost_purchase, d.cost_retail' + ||',null ,null ,null ' + ||' from doc_data d join doc_list h on d.doc_id = h.id where d.doc_id = :x'; + + -- final resultset (need only in IBE, for debug purposes): + for + execute statement (v_stt) ( x := :doc_list_id ) + into + client_order_id + ,doc_data_id + ,ware_id + ,qty + ,purchase + ,retail + ,qty_ord + ,qty_avl + ,qty_res + do + suspend; + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + 'doc_id='||coalesce(doc_list_id,''), + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end +end + +^ -- sp_customer_reserve + +-------------------------------------------------------------------------------- + +create or alter procedure sp_cancel_customer_reserve( + a_selected_doc_id type of dm_idb default null, + a_skip_lock_attempt dm_sign default 0 -- 1==> do NOT call sp_lock_selected_doc because this doc is already locked (see call from sp_cancel_adding_invoice) +) +returns ( + doc_list_id type of dm_idb, -- id of new created reserve doc + client_order_id type of dm_idb, -- id of client order (if current reserve was created with link to it) + doc_data_id type of dm_idb, -- id of created records in doc_data + ware_id type of dm_idb, -- id of wares that we resevre for customer + qty type of dm_qty, -- amount that we can reserve (not greater than invnt_saldo.qty_avl) + purchase type of dm_cost, -- cost in purchasing prices + retail type of dm_cost, -- cost in retailing prices + qty_ord type of dm_qty, -- new value of corresp. row + qty_avl type of dm_qty, -- new value of corresp. row + qty_res type of dm_qty -- new value of corresp. row +) as + declare v_linked_client_order type of dm_idb; + declare v_stt varchar(255); + declare v_ibe smallint; + declare v_dummy bigint; + declare c_raise_exc_when_no_found dm_sign = 1; + declare c_can_skip_order_clause dm_sign = 0; + declare v_this dm_dbobj = 'sp_cancel_customer_reserve'; +begin + + -- Randomly chooses customer reserve (which is NOT yet sold) and CANCEL it + -- by REMOVING all its data + record in docs header table. It occurs when + -- we mistakenly created such reserve and now have to cancel this operation. + -- All wares which were in such reserve will be enabled to be reserved for + -- other customer - due to removing info about storning that was done before + -- when this customer reserve was created. + + -- Check that table `ext_stoptest` (external text file) is EMPTY, + -- otherwise raises ex`ception to stop test: + execute procedure sp_check_to_stop_work; + + -- Check that current Tx run in NO wait or with lock_timeout. + -- Otherwise raise error: performance degrades almost to zero. + execute procedure sp_check_nowait_or_timeout; + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(1, v_this); + + -- increment number of total business routine calls within this Tx, + -- in order to display estimated overall performance in ISQL session + -- logs (see generated $tmpdir/tmp_random_run.sql). + -- Instead of querying perf_log join business_ops it was decided to + -- use only context variables in user_tran namespace: + execute procedure srv_increment_tx_bops_counter; + + v_ibe = iif( fn_remote_process() containing 'IBExpert', 1, 0); + + -- Choose random doc of corresponding kind. + -- 25.09.2014: do NOT set c_can_skip_order_clause = 1, + -- performance degrades from ~4900 to ~1900. + doc_list_id = coalesce( :a_selected_doc_id, + ( select id_selected from + sp_get_random_id( + 'v_cancel_customer_reserve' -- a_view_for_search + ,null -- a_view_for_min_id ==> the same as a_view_for_search + ,null -- a_view_for_max_id ==> the same as a_view_for_search + ,:c_raise_exc_when_no_found + ,:c_can_skip_order_clause + ) + ) + ); + + -- Try to LOCK just selected doc, raise exc if can`t: + if ( NOT (a_selected_doc_id is NOT null and a_skip_lock_attempt = 1) ) then + execute procedure sp_lock_selected_doc( doc_list_id, 'v_cancel_customer_reserve', a_selected_doc_id); + + select + h.base_doc_id + from doc_list h + where + h.id = :doc_list_id + into + v_linked_client_order; -- not null ==> this reserve was filled with wares from client order + + -- 17.07.2014: add cond for indexed scan to minimize fetches when multiple + -- calls of this SP from sp_cancel_adding_invoice: + delete from tmp$result_set r where r.doc_id = :doc_list_id; + + -- save data which is to be deleted (NB! this action became MANDATORY for + -- checking in srv_find_qd_qs_mism, do NOT delete it!): + insert into tmp$result_set( + doc_id, + base_doc_id, + doc_data_id, + ware_id, + qty, + cost_purchase, + cost_retail + ) + select + :doc_list_id, + :v_linked_client_order, + d.id, + d.ware_id, + d.qty, + d.cost_purchase, + d.cost_retail + from doc_data d + where d.doc_id = :doc_list_id; -- customer reserve which is to be deleted now + + -- Remove selected customer reserve. + -- Trigger d`oc_list_biud will (only for deleting doc or updating it's state): + -- 1) call s`p_kill_qty_storno that returns rows from Q`Storned to Q`distr + -- Trigger d`oc_list_aiud will: + -- 1) add rows in table i`nvnt_turnover_log (log to be processed by SP s`rv_make_invnt_saldo) + -- 2) call s`p_multiply_rows_for_pdistr, s`p_make_cost_storno or s`p_kill_cost_storno, s`p_add_money_log + delete from doc_list h where h.id = :doc_list_id; + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this, null, 'doc_id='||doc_list_id); + + -- 16.07.2014: make ES more 'smart': we do NOT need any records from view + -- v_doc_detailed (==> v_saldo_invnt!) if there is NO debug now (performance!) + v_stt = 'select r.doc_id,r.base_doc_id,r.doc_data_id,r.ware_id,r.qty,r.cost_purchase,r.cost_retail'; + if ( v_ibe = 1 ) then + v_stt = v_stt || ' ,n.qty_ord, n.qty_avl, n.qty_res'; + else + v_stt = v_stt || ' ,null as qty_ord, null as qty_avl, null as qty_res'; + + v_stt = v_stt ||' from tmp$result_set r'; + if ( v_ibe = 1 ) then + v_stt = v_stt || ' left join v_saldo_invnt n on r.ware_id = n.ware_id'; + + -- 17.07.2014: add cond for indexed scan to minimize fetches when multiple + -- calls of this SP from sp_cancel_adding_invoice: + v_stt = v_stt || ' where r.doc_id = :x'; + + -- final resultset (need only in IBE, for debug purposes): + for + execute statement (v_stt) ( x := :doc_list_id) + into + doc_list_id + ,client_order_id + ,doc_data_id + ,ware_id + ,qty + ,purchase + ,retail + ,qty_ord + ,qty_avl + ,qty_res + do + suspend; + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + 'doc_id='||coalesce(doc_list_id,''), + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end +end + +^ -- sp_cancel_customer_reserve + +----------------------------------------- + +create or alter procedure sp_cancel_write_off( + a_selected_doc_id type of dm_idb default null, + a_skip_lock_attempt dm_sign default 0 -- 1==> do NOT call sp_lock_selected_doc because this doc is already locked (see call from sp_cancel_adding_invoice) +) +returns ( + doc_list_id type of dm_idb, -- id of invoice being added to stock + client_order_id type of dm_idb, -- id of client order (if current reserve was created with link to it) + doc_data_id type of dm_idb, -- id of created records in doc_data + ware_id type of dm_idb, -- id of wares that we will get from supplier + qty type of dm_qty, + purchase type of dm_cost, + retail type of dm_cost, + qty_avl type of dm_qty, -- new value of corresponding row in invnt_saldo + qty_res type of dm_qty, -- new value of corresponding row in invnt_saldo + qty_out type of dm_qty -- new value of corresponding row in invnt_saldo +) +as + declare v_dummy bigint; + declare v_ibe smallint; + declare v_stt varchar(255); + declare v_agent_id type of dm_idb; + declare v_linked_client_order type of dm_idb; + declare v_this dm_dbobj = 'sp_cancel_write_off'; + declare c_raise_exc_when_no_found dm_sign = 1; + declare c_can_skip_order_clause dm_sign = 0; +begin + + -- Randomly chooses waybill (ex. customer reserve after it was sold) and + -- MOVES ("returns") it back to state "customer reserve" thus cancelling + -- write-off operation that was previously done with these wares. + -- All wares which were in such waybill will be returned back on stock and + -- will be reported as 'reserved'. So, we only change the STATE of document + -- rather its content. + -- Total cost of realization will be added (INSERTED) into money_turnover_log table + -- with "-" sign to be gathered later in service sp_make_money_saldo + -- that calculates balance of contragents. + + -- Check that table `ext_stoptest` (external text file) is EMPTY, + -- otherwise raises ex`ception to stop test: + execute procedure sp_check_to_stop_work; + + -- Check that current Tx run in NO wait or with lock_timeout. + -- Otherwise raise error: performance degrades almost to zero. + execute procedure sp_check_nowait_or_timeout; + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(1, v_this); + + -- increment number of total business routine calls within this Tx, + -- in order to display estimated overall performance in ISQL session + -- logs (see generated $tmpdir/tmp_random_run.sql). + -- Instead of querying perf_log join business_ops it was decided to + -- use only context variables in user_tran namespace: + execute procedure srv_increment_tx_bops_counter; + + v_ibe = iif( fn_remote_process() containing 'IBExpert', 1, 0); + + -- Choose random doc of corresponding kind ("closed" customer reserve) + -- 25.09.2014: do NOT set c_can_skip_order_clause = 1, + -- performance degrades from ~4900 to ~1900. + doc_list_id = coalesce( :a_selected_doc_id, + ( select id_selected from + sp_get_random_id( + 'v_cancel_write_off' -- a_view_for_search + ,null -- a_view_for_min_id ==> the same as a_view_for_search + ,null -- a_view_for_max_id ==> the same as a_view_for_search + ,:c_raise_exc_when_no_found + ,:c_can_skip_order_clause + ) + ) + ); + + -- Try to LOCK just selected doc, raise exc if can`t: + if ( NOT (a_selected_doc_id is NOT null and a_skip_lock_attempt = 1) ) then + execute procedure sp_lock_selected_doc( doc_list_id, 'v_cancel_write_off', a_selected_doc_id); + + -- Change STATE of document back to "Reserve". + -- Trigger doc_list_biud will (only for deleting doc or updating it's state): + -- 1) call s`p_kill_qty_storno that returns rows from Q`Storned to Q`distr + -- Trigger doc_list_aiud will: + -- 1) add rows in table i`nvnt_turnover_log (log to be processed by SP s`rv_make_invnt_saldo) + -- 2) call s`p_multiply_rows_for_pdistr, s`p_make_cost_storno or s`p_kill_cost_storno, s`p_add_money_log + update doc_list h + set + h.state_id = fn_doc_open_state(), -- return to prev. docstate + h.optype_id = fn_oper_retail_reserve(), -- return to prev. optype + dts_fix = null, + dts_clos = null + where + h.id = :doc_list_id + returning + h.base_doc_id + into + client_order_id; -- out arg + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this, null, 'doc_id='||doc_list_id); + + -- 16.07.2014: make ES more 'smart': we do NOT need any records from view + -- v_doc_detailed (==> v_saldo_invnt!) if there is NO debug now (performance!) + v_stt = 'select d.doc_id, d.ware_id, d.qty, d.cost_purchase, d.cost_retail'; + if ( v_ibe = 1 ) then + v_stt = v_stt || ',d.doc_data_id ,d.qty_avl ,d.qty_res ,d.qty_out from v_doc_detailed d'; + else + v_stt = v_stt || ',d.id ,null ,null ,null from doc_data d'; + + v_stt = v_stt || ' where d.doc_id = :x'; + + -- final resultset (need only in IBE, for debug purposes): + for + execute statement (v_stt) ( x := :doc_list_id ) + into + doc_list_id + ,ware_id + ,qty + ,purchase + ,retail + ,doc_data_id + ,qty_avl + ,qty_res + ,qty_out + do + suspend; + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + 'doc_id='||coalesce(doc_list_id,''), + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + +^ -- sp_cancel_write_off + +------------------------------------------------------------------------------- + +create or alter procedure sp_get_clo_for_invoice( a_invoice_doc_id dm_idb ) +returns ( + clo_doc_id type of dm_idb, + clo_agent_id type of dm_idb -- 23.07.2014 +) +as + declare v_dbkey dm_dbkey; + declare v_qty_acc dm_qty; + declare v_qty_sup type of dm_qty; + declare v_snd_qty dm_qty; + declare v_qty_clo_still_not_reserved dm_qty; + declare v_clo_doc_id dm_idb; + declare v_clo_agent_id dm_idb; + declare v_ware_id dm_idb; + declare v_cnt int = 0; + declare v_this dm_dbobj = 'sp_get_clo_for_invoice'; + declare v_oper_order_by_customer dm_idb; + declare v_oper_retail_reserve dm_idb; +begin + + -- Aux SP: find client orders which have at least one unit of amount of + -- some ware that still not reserved for customer. + -- This SP is called when we finish checking invoice data and move invoice + -- to state "Accepted". We need then find for immediate RESERVING such + -- wares which customers waiting for. + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(1, v_this); + + --?! 06.02.2015 2020, performance affect ? + v_oper_order_by_customer = fn_oper_order_by_customer(); + v_oper_retail_reserve = fn_oper_retail_reserve(); + + delete from tmp$dep_docs d where d.base_doc_id = :a_invoice_doc_id; + + -- :: NB :: We need handle rows via CURSOR here because of immediate leave + -- from cursor when limit (invoice doc_data.qty as v_qty_sup) will be exceeded + -- FB 3.0 analitycal function sum()over(order by) which get running total + -- is inefficient here (poor performance) + for + select d.ware_id, d.qty + from doc_data d + where d.doc_id = :a_invoice_doc_id -- invoice which we are closing now + into v_ware_id, v_qty_sup + do begin + v_qty_acc = 0; + + -- Gather REMAINDER of initial amount in ALL client orders + -- that still not yet reserved. + -- 05.09.2015. Note: we have to stop scrolling on QDistr for each ware + -- from invoice as soon as number of scrolled records will be >= v_qty_sup + -- (because we can`t put in reserve more than we got from supplier; + -- also because of performance: there are usially **LOT** of rows in QDistr + -- for the same value of {ware, snd_op, rcv_op}) + for + select + q.doc_id as clo_doc_id, -- id of customer order + q.snd_qty as clo_qty -- always = 1 (in current implementation) + from v_qdistr_source q + where + -- :: NB :: PARTIAL match on index range scan will be here. + -- For that reason we have to STOP scrolling as soon as possible! + q.ware_id = :v_ware_id + and q.snd_optype_id = :v_oper_order_by_customer + and q.rcv_optype_id = :v_oper_retail_reserve + and not exists( + select * from tmp$dep_docs t + where + t.base_doc_id = :a_invoice_doc_id + and t.dependend_doc_id = q.doc_id + -- prevent from building index bitmap (has effect only in 3.0; do NOT repeat in 2.5!): + order by t.base_doc_id, t.dependend_doc_id + ) + order by q.ware_id, q.snd_optype_id, q.rcv_optype_id, q.snd_id -- ==> 3.0: plan_order, avoid bild bitmap + into v_clo_doc_id, v_snd_qty + do begin + v_qty_acc = v_qty_acc + v_snd_qty; + v_cnt = v_cnt + 1; + + update or insert into tmp$dep_docs( + base_doc_id, + dependend_doc_id) + values ( + :a_invoice_doc_id, + :v_clo_doc_id) + matching(base_doc_id, dependend_doc_id); + + if ( v_qty_acc >= v_qty_sup ) then leave; -- we can`t put in reserve more than we got from supplier + when any do -- added 10.09.2014: strange 'concurrent transaction' error occured on GTT! + -- ::: nb ::: do NOT use "wh`en gdscode " followed by "wh`en any": + -- the latter ("w`hen ANY") will handle ALWAYS, even if "w`hen " + -- catched it's kind of exception! + -- 1) tracker.firebirdsql.org/browse/CORE-3275 + -- "W`HEN ANY handles exceptions even if they are handled in another W`HEN section" + -- 2) sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1088890&msg=15879669 + begin + if ( NOT fn_is_uniqueness_trouble(gdscode) ) then exception; + end + end + + end + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this, null, 'doc_id='||a_invoice_doc_id||', gather_qd_rows='||v_cnt); + + for + select f.dependend_doc_id, h.agent_id + from tmp$dep_docs f + join doc_list h on + f.dependend_doc_id = h.id + and h.optype_id = :v_oper_order_by_customer -- 31.07.2014: exclude cancelled customer orders! + where f.base_doc_id = :a_invoice_doc_id + -- not needed! >>> group by f.dependend_doc_id, h.agent_id + into clo_doc_id, clo_agent_id + do + suspend; + +when any do -- added 10.09.2014: strange 'concurrent transaction' error occured on INSERT! + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + 'doc_id='||coalesce(a_invoice_doc_id,''), + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + + +^ -- sp_get_clo_for_invoice + +------------------------------------------------------------------------------- + +create or alter procedure sp_add_invoice_to_stock( + a_selected_doc_id type of dm_idb default null, + a_cancel_mode dm_sign default 0, + a_skip_lock_attempt dm_sign default 0, -- 1==> do NOT call sp_lock_selected_doc because this doc is already locked (see call from s`p_cancel_supplier_order) + dbg int default 0 +) +returns ( + doc_list_id type of dm_idb, -- id of invoice being added to stock + agent_id type of dm_idb, -- id of supplier + doc_data_id type of dm_idb, -- id of created records in doc_data + ware_id type of dm_idb, -- id of wares that we will get from supplier + qty type of dm_qty, -- amount that supplier will send to us + purchase type of dm_cost, -- how much we must pay to supplier for this ware + qty_sup type of dm_qty, -- new value of corresponding row in invnt_saldo + qty_avl type of dm_qty, -- new value of corresponding row in invnt_saldo + qty_res type of dm_qty, -- new value of corresponding row in invnt_saldo + res_ok int, -- number of successfully created reserves for client orders + res_err int, -- number of FAULTS when attempts to create reserves for client orders + res_nul int -- 4debug: number of mismatches between estimated and actually created reserves +) +as + declare v_dummy bigint; + declare v_ibe smallint; + declare v_stt varchar(255); + declare v_info dm_info; + declare v_new_doc_state type of dm_idb; + declare v_old_oper_id type of dm_idb; + declare v_new_oper_id type of dm_idb; + declare v_client_order type of dm_idb; + declare v_linked_reserve_id type of dm_idb; + declare v_linked_reserve_state type of dm_idb; + declare v_view_for_search dm_dbobj; + declare v_this dm_dbobj = 'sp_add_invoice_to_stock'; + declare c_raise_exc_when_no_found dm_sign = 1; + declare c_can_skip_order_clause dm_sign = 0; + + declare function fn_internal_enable_reserving() returns boolean deterministic as + begin + return rdb$get_context('USER_SESSION', 'ENABLE_RESERVES_WHEN_ADD_INVOICE')='1'; + end + +begin + + -- This SP implements TWO tasks (see parameter `a_cancel_mode`): + -- 1) MOVES invoice to the state "ACCEPTED" after we check its content; + -- 2) CANCEL previously accepted invoice and MOVES it to the state "TO BE CHECKED". + -- For "1)" it will also find all client orders which have at least one unit + -- of amount that still not reserved and CREATE customer reserve(s). + -- Total cost of invoice will be added (INSERTED) into money_turnover_log table + -- with "+" sign to be gathered later in service sp_make_money_saldo that + -- calculates balance of contragents. + -- For "2)" it will find all customer reserves and waybills ('closed reserves') + -- and firstly CANCEL all of them and, if no errors occur, will then cancel + -- currently selected invoice. + -- Total cost of cancelled invoice will be added (INSERTED) into money_turnover_log table + -- with "-" sign to be gathered later in service sp_make_money_saldo that + -- calculates balance of contragents. + -- ::: NB-1 ::: This SP supresses lock-conflicts which can be occur when trying + -- to CREATE customer reserves in module sp_make_qty_storno which storning amounts. + -- In such case amount will be stored in 'avaliable' remainder. + -- ::: NB-2 ::: This SP does NOT supress lock-conflicts when invoice is to be + -- CANCELLED (i.e. moved back to state 'to be checked') - otherwise we get + -- negative values in 'reserved' or 'sold' kinds of stock remainder. + + -- Check that table `ext_stoptest` (external text file) is EMPTY, + -- otherwise raises ex`ception to stop test: + execute procedure sp_check_to_stop_work; + + -- Check that current Tx run in NO wait or with lock_timeout. + -- Otherwise raise error: performance degrades almost to zero. + execute procedure sp_check_nowait_or_timeout; + + -- input arg a_cancel_mode = 0 ==> ADD invoice to stock and 'fix' it; + -- otherwise ==> CANCEL adding and return to 'open' state + ---------------------------------------------------------------------------- + -- add to performance log timestamp about start/finish this unit: + if ( a_cancel_mode = 1 ) then v_this = 'sp_cancel_adding_invoice'; + + execute procedure sp_add_perf_log(1, v_this); + + -- increment number of total business routine calls within this Tx, + -- in order to display estimated overall performance in ISQL session + -- logs (see generated $tmpdir/tmp_random_run.sql). + -- Instead of querying perf_log join business_ops it was decided to + -- use only context variables in user_tran namespace: + execute procedure srv_increment_tx_bops_counter; + + -- check that special context var EXISTS otherwise raise exc: + execute procedure sp_check_ctx('USER_SESSION', 'ENABLE_RESERVES_WHEN_ADD_INVOICE'); + + v_new_doc_state = iif( a_cancel_mode = 0, fn_doc_fix_state(), fn_doc_open_state() ); + v_old_oper_id = iif( a_cancel_mode = 0, fn_oper_invoice_get(), fn_oper_invoice_add() ); + v_new_oper_id = iif( a_cancel_mode = 0, fn_oper_invoice_add(), fn_oper_invoice_get() ); + v_view_for_search = iif( a_cancel_mode = 0, 'v_add_invoice_to_stock', 'v_cancel_adding_invoice' ); + + v_ibe = iif( fn_remote_process() containing 'IBExpert', 1, 0); + + -- Choose random doc of corresponding kind. + -- 25.09.2014: do NOT set c_can_skip_order_clause = 1, + -- performance degrades from ~4900 to ~1900. + doc_list_id = coalesce( :a_selected_doc_id, + (select id_selected + from sp_get_random_id( :v_view_for_search -- a_view_for_search + ,null -- a_view_for_min_id ==> the same as a_view_for_search + ,null -- a_view_for_max_id ==> the same as a_view_for_search + ,:c_raise_exc_when_no_found + ,:c_can_skip_order_clause + ) + ) + ); + + + execute procedure sp_upd_in_perf_log(v_this, null, 'doc_id='||doc_list_id); -- 06.07.2014, 4debug + + -- Try to LOCK just selected doc, raise exc if can`t: + if ( NOT (a_selected_doc_id is NOT null and a_skip_lock_attempt = 1) ) then + execute procedure sp_lock_selected_doc( doc_list_id, v_view_for_search, a_selected_doc_id); + + res_ok = 0; + res_err = 0; + res_nul = 0; + + while (1=1) do begin -- ................ m a i n l o o p ............... + + if ( a_cancel_mode = 1 ) then + begin + -- search all RESERVES (including those that are written-off) which + -- stornes some amounts from currently selected invoice and lock them + -- (add to tmp$dep_docs.dependend_doc_id) + execute procedure sp_lock_dependent_docs( :doc_list_id, :v_old_oper_id ); + -- result: tmp$dep_docs.dependend_doc_id filled by ID of all locked + -- RESERVES which depends on currently selected invoice. + -- Extract set of reserve docs that storned amounts from current + -- invoice and cancel them: + for + select d.dependend_doc_id, d.dependend_doc_state + from tmp$dep_docs d + where d.base_doc_id = :doc_list_id + into + v_linked_reserve_id, v_linked_reserve_state + do begin + -- if we are here then ALL dependend docs have been SUCCESSFULLY locked. + if ( v_linked_reserve_state <> fn_doc_open_state() ) then + select count(*) from sp_cancel_write_off( :v_linked_reserve_id, 1 ) into v_dummy; + + select count(*) from sp_cancel_customer_reserve(:v_linked_reserve_id, 1 ) into v_dummy; + + res_ok = res_ok + 1; + + -- do NOT supress any lock_conflict ex`ception here + -- otherwise get negative remainders! + + end + end -- block for CANCELLING mode + + -- Change info in doc header for INVOICE. + -- 1. trigger d`oc_list_biud will call sp_kill_qty_storno which: + -- update qdistr.snd_optype_id (or rcv_optype_id) + -- where qd.snd_id = doc_data.id or qd.rcv_id = doc_data.id + -- 2. trigger d`oc_list_aiud will: + -- 2.1 add rows into invnt_turnover_log + -- 2.2 add rows into money_turnover_log + update doc_list h + set h.optype_id = :v_new_oper_id, -- iif( a_cancel_mode = 0, fn_oper_invoice_add(), fn_oper_invoice_get() ); + h.state_id = :v_new_doc_state, -- iif( :a_cancel_mode = 0 , :fn_doc_clos_state , :v_new_doc_state), + dts_fix = iif( :a_cancel_mode = 0, 'now', null ) + where h.id = :doc_list_id; + + if (dbg=1) then leave; + + -- build unique list of client orders which still need to reserve some wares + -- and create for each item of this list new reserve that is linked to client_order. + v_client_order = null; + if (a_cancel_mode = 0) then -- create reserve docs (avaliable remainders exists after adding this invoice) + begin + + if (dbg=3) then leave; + + if (fn_internal_enable_reserving() ) then + begin + for + select p.clo_doc_id + from sp_get_clo_for_invoice( :doc_list_id ) p + where not exists( + select * from v_our_firm v + where v.id = p.clo_agent_id + -- 3.0: fixed 16.12.2014, revision 60368 + -- "Postfix for CORE-1550 Unnecessary index scan happens + --- when the same index is mapped to both WHERE and ORDER BY clauses." + order by v.id -- <<< can do this since 16.12.2014 + ) + into v_client_order + do begin + -- reserve immediatelly all avaliable wares for each found client order: + select min(doc_list_id) from sp_customer_reserve( :v_client_order, iif(:dbg=4, 2, null) ) + into v_linked_reserve_id; + + if ( v_linked_reserve_id is null ) then + res_nul = res_nul + 1; + else + res_ok = res_ok + 1; + + when any do + -- ::: nb ::: do NOT use "wh`en gdscode " followed by "wh`en any": + -- the latter ("w`hen ANY") will handle ALWAYS, even if "w`hen " + -- catched it's kind of exception! + -- 1) tracker.firebirdsql.org/browse/CORE-3275 + -- "W`HEN ANY handles exceptions even if they are handled in another W`HEN section" + -- 2) sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1088890&msg=15879669 + begin + if ( fn_is_lock_trouble(gdscode) ) then + begin + execute procedure sp_add_to_abend_log( + 'can`t create res', + gdscode, + 'clo_id='||coalesce(v_client_order, ''), + v_this + ); + res_err = res_err + 1; + end + else + begin + execute procedure sp_add_to_abend_log('', gdscode, 'doc_id='||doc_list_id, v_this ); + --######## + exception; -- ::: nb ::: anonimous but in when-block! + end + end + end -- cursor select clo_doc_id from sp_get_clo_for_invoice( :doc_list_id ) + end -- ENABLE_RESERVES_WHEN_ADD_INVOICE ==> '1' + end -- a_cancel_mode = 0 + leave; + end -- while (1=1) -- ................ m a i n l o o p ............... + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this, null, 'dh='||doc_list_id, res_ok, res_nul); + + -- 16.07.2014: make ES more 'smart': we do NOT need any records from view + -- v_doc_detailed (==> v_saldo_invnt!) if there is NO debug now (performance!) + if ( v_ibe = 1 ) then + v_stt = 'select v.agent_id, v.doc_data_id, v.ware_id, v.qty, v.cost_purchase, v.qty_sup, v.qty_avl, v.qty_res' + ||' from v_doc_detailed v where v.doc_id = :x'; + else + v_stt = 'select h.agent_id, d.id, d.ware_id, d.qty, d.cost_purchase, null, null, null ' + ||' from doc_data d join doc_list h on d.doc_id = h.id where d.doc_id = :x'; + + -- final resultset (need only in IBE, for debug purposes): + for + execute statement (v_stt) ( x := :doc_list_id ) + into + agent_id + ,doc_data_id + ,ware_id + ,qty + ,purchase + ,qty_sup + ,qty_avl + ,qty_res + do + suspend; + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + 'doc_id='||coalesce(doc_list_id,''), + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end +end + +^ -- end of sp_add_invoice_to_stock + +create or alter procedure sp_cancel_adding_invoice( + a_selected_doc_id type of dm_idb default null, + a_skip_lock_attempt dm_sign default 0, -- 1==> do NOT call sp_lock_selected_doc because this doc is already locked (see call from s`p_cancel_supplier_order) + dbg int default 0 +) +returns ( + doc_list_id type of dm_idb, -- id of invoice being added to stock + agent_id type of dm_idb, -- id of supplier + doc_data_id type of dm_idb, -- id of created records in doc_data + ware_id type of dm_idb, -- id of wares that we will get from supplier + qty type of dm_qty, -- amount that supplier will send to us + purchase type of dm_cost, -- how much we must pay to supplier for this ware + qty_sup type of dm_qty, -- new value of corresponding row in invnt + qty_avl type of dm_qty, -- new value of corresponding row in invnt + qty_res type of dm_qty, -- new value of corresponding row in invnt_saldo + res_ok int, -- number of successfully CANCELLED reserves for client orders + res_err int -- number of FAULTS when attempts to CANCEL reserves for client orders +) +as + declare v_dummy bigint; + declare v_ibe smallint; + declare v_stt varchar(255); + declare v_this dm_dbobj = 'sp_cancel_adding_invoice'; +begin + + -- MOVES invoice from state 'accepted' to state 'to be checked'. + -- Delegates all this work to sp_add_invoice_to_stock. + + -- add to performance log timestamp about start/finish this unit: + -- no need, see s`p_add_invoice: execute procedure s`p_add_to_perf_log(v_this); + + select min(doc_list_id), min(res_ok), min(res_err) + from sp_add_invoice_to_stock( + :a_selected_doc_id, + 1, -- <<<<<<<<< sign to CANCEL document <<<<< + :a_skip_lock_attempt, + :dbg + ) + into doc_list_id, res_ok, res_err; + + v_ibe = iif( fn_remote_process() containing 'IBExpert', 1, 0); + + -- 16.07.2014: make ES more 'smart': we do NOT need any records from view + -- v_doc_detailed (==> v_saldo_invnt!) if there is NO debug now (performance!) + if ( v_ibe = 1 ) then + v_stt = 'select v.agent_id, v.doc_data_id, v.ware_id, v.qty, v.cost_purchase, v.qty_sup, v.qty_avl, v.qty_res' + ||' from v_doc_detailed v where v.doc_id = :x'; + else + v_stt = 'select h.agent_id, d.id, d.ware_id, d.qty, d.cost_purchase, null, null, null' + ||' from doc_data d join doc_list h on d.doc_id = h.id where d.doc_id = :x'; + + -- final resultset (need only in IBE, for debug purposes): + for + execute statement (v_stt) ( x := :doc_list_id ) + into + agent_id + ,doc_data_id + ,ware_id + ,qty + ,purchase + ,qty_sup + ,qty_avl + ,qty_res + do + suspend; + + -- add to performance log timestamp about start/finish this unit: + -- no need, see s`p_add_invoice: execute procedure s`p_add_to_perf_log(v_this, null, 'doc_id='||doc_list_id); +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + 'doc_id='||coalesce(doc_list_id,''), + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end -- sp_cancel_adding_invoice + +^ +-------------------------------------------------------------------------------- + +create or alter procedure sp_cancel_supplier_order( + a_selected_doc_id type of dm_idb default null) +returns ( + doc_list_id type of dm_idb, + agent_id type of dm_idb, + doc_data_id type of dm_idb, + ware_id type of dm_idb, + qty type of dm_qty, -- amount that we ordered for client + purchase type of dm_cost, -- purchasing cost for qty + retail type of dm_cost, -- retail cost + qty_clo type of dm_qty, -- new value of corresponding row in invnt_saldo + qty_ord type of dm_qty -- new value of corresponding row in invnt_saldo +) +as + declare v_dummy bigint; + declare v_ibe smallint; + declare v_stt varchar(255); + declare v_info dm_info = ''; + declare v_linked_invoice_id bigint; + declare v_linked_invoice_state bigint; + declare v_linked_reserve_id bigint; + declare v_linked_reserve_state bigint; + declare v_this dm_dbobj = 'sp_cancel_supplier_order'; + declare c_raise_exc_when_no_found dm_sign = 1; + declare c_can_skip_order_clause dm_sign = 0; +begin + + -- Randomly chooses our order to supplier and CANCEL it by REMOVING all its + -- data + record in docs header table. It occurs when we mistakenly created + -- such order and now have to cancel this operation. + -- All wares which were in such supplier order will be enabled again + -- to be included in new (another) order which we create after this. + -- ::: NB ::: + -- Before cancelling supplier order we need to find all INVOICES which have + -- at least one unit of amounts that was participated in storning process of + -- currently selected order. All these invoices need to be: + -- 1) moved from state 'accepted' to state 'to be checked' (if need); + -- 2) cancelled at all (i.e. removed from database). + -- Because each 'accepted' invoice can be cancelled only when all customer + -- reserves and waybills are cancelled first, we need, in turn, to find all + -- these documents and cancel+remove them. + -- For that reason this SP is most 'heavy' vs any others: it can fail with + -- 'lock-conflict' up to 75% of calls in concurrent environment. + + -- Check that table `ext_stoptest` (external text file) is EMPTY, + -- otherwise raises ex`ception to stop test: + execute procedure sp_check_to_stop_work; + + -- Check that current Tx run in NO wait or with lock_timeout. + -- Otherwise raise error: performance degrades almost to zero. + execute procedure sp_check_nowait_or_timeout; + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(1, v_this); + + -- increment number of total business routine calls within this Tx, + -- in order to display estimated overall performance in ISQL session + -- logs (see generated $tmpdir/tmp_random_run.sql). + -- Instead of querying perf_log join business_ops it was decided to + -- use only context variables in user_tran namespace: + execute procedure srv_increment_tx_bops_counter; + + v_ibe = iif( fn_remote_process() containing 'IBExpert', 1, 0); + + -- Choose random doc of corresponding kind. + -- 25.09.2014: do NOT set c_can_skip_order_clause = 1, + -- performance degrades from ~4900 to ~1900. + doc_list_id = coalesce( :a_selected_doc_id, + (select id_selected from + sp_get_random_id( 'v_cancel_supplier_order' -- a_view_for_search + ,null -- a_view_for_min_id ==> the same as a_view_for_search + ,null -- a_view_for_max_id ==> the same as a_view_for_search + ,:c_raise_exc_when_no_found + ,:c_can_skip_order_clause + ) + ) + ); + v_info = 'dh='||doc_list_id; + -- upd. log with doc id whic is actually handling now: + --execute procedure sp_upd_in_perf_log( v_this, null, 'dh='||doc_list_id); + + -- Try to LOCK just selected doc, raise exc if can`t: + execute procedure sp_lock_selected_doc( doc_list_id, 'v_cancel_supplier_order', a_selected_doc_id); + + -- Since 08.08.2014: first get and lock *ALL* dependent docs - both invoices and reserves + -- Continue handling of them only after we get ALL locks! + -- 1. lock all INVOICES that storned amounts from currently selected supp_order: + execute procedure sp_lock_dependent_docs( :doc_list_id, fn_oper_order_for_supplier() ); + -- result: tmp$dep_docs.dependend_doc_id filled by ID of all locked dependent invoices + + -- 2. for each of invoices search all RESERVES (including those that are written-off) + -- and also lock them (add to tmp$dep_docs.dependend_doc_id) + for + select + d.dependend_doc_id as linked_invoice_id + from tmp$dep_docs d + where d.base_doc_id = :doc_list_id + order by d.base_doc_id+0 + into v_linked_invoice_id + do begin + execute procedure sp_lock_dependent_docs(:v_linked_invoice_id, fn_oper_invoice_add()); + end + -- result: tmp$dep_docs.dependend_doc_id filled by ID of all locked RESERVES + -- which depends on invoices. + + -- 3. Scan tmp$dep_docs filtering only RESERVES and cancel them + -- (do NOT delegate this job to sp_cancel_adding_invoice...) + for + select d.dependend_doc_id, d.dependend_doc_state + from tmp$dep_docs d + where d.base_doc_id <> :doc_list_id + group by 1,2 -- ::: NB ::: one reserve can depends on SEVERAL invoices! + into v_linked_reserve_id, v_linked_reserve_state + do begin + if ( v_linked_reserve_state <> fn_doc_open_state() ) then + -- a_skip_lock_hdr = 1 ==> do NOT try to lock doc header, it was ALREADY locked in sp_lock_dependent_docs + select count(*) from sp_cancel_write_off( :v_linked_reserve_id, 1 ) into v_dummy; + + -- a_skip_lock_hdr = 1 ==> do NOT try to lock doc header, it was ALREADY locked in sp_lock_dependent_docs + select count(*) from sp_cancel_customer_reserve(:v_linked_reserve_id, 1 ) into v_dummy; + + -- do NOT supress any lock_conflict ex`ception here + -- otherwise get negative remainders! + end + + -- 4. Scan tmp$dep_docs filtering only INVOICES and cancel them: + for + select d.dependend_doc_id, d.dependend_doc_state + from tmp$dep_docs d + where d.base_doc_id = :doc_list_id + into v_linked_invoice_id, v_linked_invoice_state + do begin + if ( v_linked_invoice_state <> fn_doc_open_state() ) then + -- a_skip_lock_hdr = 1 ==> do NOT try to lock doc header, it was ALREADY locked in sp_lock_dependent_docs + select count(*) from sp_cancel_adding_invoice( :v_linked_invoice_id, 1 ) into v_dummy; + + -- a_skip_lock_hdr = 1 ==> do NOT try to lock doc header, it was ALREADY locked in sp_lock_dependent_docs + select count(*) from sp_cancel_supplier_invoice( :v_linked_invoice_id, 1 ) into v_dummy; + + -- do NOT supress any lock_conflict ex`ception here + -- otherwise get negative remainders! + + end + + -- 17.07.2014: add cond for indexed scan to minimize fetches: + delete from tmp$result_set r where r.doc_id = :doc_list_id; + + -- save data which is to be deleted (NB! this action became MANDATORY for + -- checking in srv_find_qd_qs_mism, do NOT delete it!): + insert into tmp$result_set( doc_id, agent_id, doc_data_id, ware_id, qty, cost_purchase, cost_retail) + select + :doc_list_id, + h.agent_id, + d.id, + d.ware_id, + d.qty, + d.cost_purchase, + d.cost_retail + from doc_data d + join doc_list h on d.doc_id = h.id + where d.doc_id = :doc_list_id; -- supplier order which is to be removed now + + -- 1. Trigger doc_list_biud will (only for deleting doc or updating it's state) + -- call s`p_kill_qty_storno that returns rows from Q`Storned to Q`distr. + -- 2. FK cascade will remove records from table doc_data. + -- 3. Trigger doc_list_aiud will: + -- 3.1) add rows in table i`nvnt_turnover_log (log to be processed by SP s`rv_make_invnt_saldo) + -- 3.2) call s`p_multiply_rows_for_pdistr, s`p_make_cost_storno or s`p_kill_cost_storno, s`p_add_money_log + delete from doc_list h where h.id = :doc_list_id; + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this,null, v_info); + + -- 16.07.2014: make ES more 'smart': we do NOT need any records from view + -- v_doc_detailed (==> v_saldo_invnt!) if there is NO debug now (performance!) + v_stt = 'select r.agent_id,r.doc_data_id,r.ware_id,r.qty,r.cost_purchase,r.cost_retail'; + if ( v_ibe = 1 ) then + v_stt = v_stt ||' ,n.qty_clo,n.qty_ord' + ||' from tmp$result_set r left join v_saldo_invnt n on r.ware_id = n.ware_id'; + else + v_stt = v_stt ||' ,null ,null from tmp$result_set r'; + + -- 17.07.2014: add cond for indexed scan to minimize fetches: + v_stt = v_stt || ' where r.doc_id = :x'; + + -- final resultset (need only in IBE, for debug purposes): + for + execute statement (v_stt) ( x := :doc_list_id ) + into + agent_id + ,doc_data_id + ,ware_id + ,qty + ,purchase + ,retail + ,qty_clo + ,qty_ord + do + suspend; + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + v_info, + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + +^ -- sp_cancel_supplier_order + +-------------------------------------------------------------------------------- + +create or alter procedure sp_reserve_write_off(a_selected_doc_id type of dm_idb default null) +returns ( + doc_list_id type of dm_idb, -- id of customer reserve doc + client_order_id type of dm_idb, -- id of client order (if current reserve was created with link to it) + doc_data_id type of dm_idb, -- id of processed records in doc_data + ware_id type of dm_idb, -- id of ware + qty type of dm_qty, -- amount that is written-offf + purchase type of dm_cost, -- cost in purchasing prices + retail type of dm_cost, -- cost in retailing prices + qty_avl type of dm_qty, -- new value of corresponding row in invnt_saldo + qty_res type of dm_qty, -- new value of corresponding row in invnt_saldo + qty_out type of dm_qty -- new value of corresponding row in invnt_saldo +) +as + declare v_linked_client_order type of dm_idb; + declare v_ibe smallint; + declare v_stt varchar(255); + declare v_dummy bigint; + declare v_this dm_dbobj = 'sp_reserve_write_off'; + declare c_raise_exc_when_no_found dm_sign = 1; + declare c_can_skip_order_clause dm_sign = 0; +begin + + -- Randomly choose customer reserve and MOVES it to the state 'sold', + -- so this doc becomes 'waybill' (customer can take out his wares since + -- that moment). + -- Total cost of realization will be added (INSERTED) into money_turnover_log table + -- with "+" sign to be gathered later in service sp_make_money_saldo + -- that calculates balance of contragents. + + -- Check that table `ext_stoptest` (external text file) is EMPTY, + -- otherwise raises e`xception to stop test: + execute procedure sp_check_to_stop_work; + + -- Check that current Tx run in NO wait or with lock_timeout. + -- Otherwise raise error: performance degrades almost to zero. + execute procedure sp_check_nowait_or_timeout; + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(1, v_this); + + -- increment number of total business routine calls within this Tx, + -- in order to display estimated overall performance in ISQL session + -- logs (see generated $tmpdir/tmp_random_run.sql). + -- Instead of querying perf_log join business_ops it was decided to + -- use only context variables in user_tran namespace: + execute procedure srv_increment_tx_bops_counter; + + v_ibe = iif( fn_remote_process() containing 'IBExpert', 1, 0); + + -- Choose random doc of corresponding kind. + -- 25.09.2014: do NOT set c_can_skip_order_clause = 1, + -- performance degrades from ~4900 to ~1900. + doc_list_id = coalesce( :a_selected_doc_id, + (select id_selected from + sp_get_random_id( 'v_reserve_write_off' -- a_view_for_search + ,null -- a_view_for_min_id ==> the same as a_view_for_search + ,null -- a_view_for_max_id ==> the same as a_view_for_search + ,:c_raise_exc_when_no_found + ,:c_can_skip_order_clause + ) + ) + ); + + -- Try to LOCK just selected doc, raise exc if can`t: + execute procedure sp_lock_selected_doc( doc_list_id, 'v_reserve_write_off', a_selected_doc_id); + + -- Change info in doc header for CUSTOMER RESERVE. + -- 1. Trigger doc_list_biud will (only for deleting doc or updating it's state) + -- call s`p_kill_qty_storno that returns rows from Q`Storned to Q`distr. + -- 2. FK cascade will remove records from table doc_data. + -- 3. Trigger doc_list_aiud will: + -- 3.1) add rows in table i`nvnt_turnover_log (log to be processed by SP s`rv_make_invnt_saldo) + -- 3.2) call s`p_multiply_rows_for_pdistr, s`p_make_cost_storno or s`p_kill_cost_storno, s`p_add_money_log + update doc_list h + set + h.state_id = fn_doc_fix_state(), -- goto "next" docstate: 'waybill' + h.optype_id = fn_oper_retail_realization() -- goto "next" optype ==> add row to money_turnover_log + where h.id = :doc_list_id + returning h.base_doc_id + into client_order_id; -- out arg + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this, null, 'doc_id='||doc_list_id); + + -- 16.07.2014: make ES more 'smart': we do NOT need any records from view + -- v_doc_detailed (==> v_saldo_invnt!) if there is NO debug now (performance!) + if ( v_ibe = 1 ) then + v_stt = 'select v.doc_data_id,v.ware_id,v.qty,v.cost_purchase,v.cost_retail' + ||',v.qty_avl,v.qty_res,v.qty_out' + ||' from v_doc_detailed v where v.doc_id = :x'; + else + v_stt = 'select d.id,d.ware_id,d.qty,d.cost_purchase,d.cost_retail' + ||',null ,null ,null' + ||' from doc_data d where d.doc_id = :x'; + + -- final resultset (need only in IBE, for debug purposes): + for + execute statement (v_stt) ( x := :doc_list_id ) + into + doc_data_id + ,ware_id + ,qty + ,purchase + ,retail + ,qty_avl + ,qty_res + ,qty_out + do + suspend; + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + 'doc_id='||coalesce(doc_list_id,''), + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end -- sp_reserve_write_off + +^ +------------------------------------------------------------------------------- +-- ########################### P A Y M E N T S ############################## +------------------------------------------------------------------------------- + +create or alter procedure sp_payment_common( + a_payment_oper dm_idb, -- fn_oper_pay_from_customer() or fn_oper_pay_to_supplier() + a_selected_doc_id type of dm_idb default null, + a_total_pay type of dm_cost default null +) +returns ( + source_doc_id type of dm_idb, -- id of doc which is paid (reserve or invoice) + agent_id type of dm_idb, + current_pay_sum type of dm_cost +) +as + declare v_stt varchar(255); + declare v_source_for_random_id dm_dbobj; + declare v_source_for_min_id dm_dbobj; + declare v_source_for_max_id dm_dbobj; + declare v_can_skip_order_clause smallint; + declare v_find_using_desc_index dm_sign; + declare view_to_search_agent dm_dbobj; + declare v_non_paid_total type of dm_cost; + declare v_round_to smallint; + declare v_id bigint; + declare v_dummy bigint; + declare v_this dm_dbobj = 'sp_payment_common'; +begin + + -- Aux SP - common for both payments from customers and our payments + -- to suppliers. + -- If parameter `a_selected_doc_id` is NOT null than we create payment + -- that is LINKED to existent doc of realization (for customer) or incomings + -- (for supplier). Otherwise this is ADVANCE payment. + -- This SP tries firstly to find 'linked' document for payment an returns it + -- in out argument 'source_doc_id' if it was found. Otherwise it only randomly + -- choose agent + total cost of payment and return them. + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(1, v_this,null); + + -- added 09.09.2014 due to new views for getting bounds & random find: + v_source_for_random_id = + decode( a_payment_oper, + fn_oper_pay_from_customer(), 'v_random_find_non_paid_realizn', + fn_oper_pay_to_supplier(), 'v_random_find_non_paid_invoice', + 'unknown_source' + ); + + v_source_for_min_id = + decode( a_payment_oper, + fn_oper_pay_from_customer(), 'v_min_non_paid_realizn', + fn_oper_pay_to_supplier(), 'v_min_non_paid_invoice', + null + ); + + v_source_for_max_id = + decode( a_payment_oper, + fn_oper_pay_from_customer(), 'v_max_non_paid_realizn', + fn_oper_pay_to_supplier(), 'v_max_non_paid_invoice', + null + ); + + v_can_skip_order_clause = + decode( a_payment_oper, + fn_oper_pay_from_customer(), 1, + fn_oper_pay_to_supplier(), 1, + 0 + ); + v_find_using_desc_index = + decode( a_payment_oper, + fn_oper_pay_from_customer(), 1, + fn_oper_pay_to_supplier(), 1, + 0 + ); + + view_to_search_agent = iif( a_payment_oper = fn_oper_pay_from_customer(), 'v_all_customers', 'v_all_suppliers'); + v_round_to = iif( a_payment_oper = fn_oper_pay_from_customer(), -2, -3); + + if ( :a_selected_doc_id is null ) then + begin + select id_selected + from sp_get_random_id( + :v_source_for_random_id, + :v_source_for_min_id, + :v_source_for_max_id, + 0, -- 19.07.2014: 0 ==> do NOT raise exception if not able to find any ID in view :v_source_for_random_id + :v_can_skip_order_clause, -- 17.07.2014: if = 1, then 'order by id' will be SKIPPED in statement inside fn + :v_find_using_desc_index -- 11.09.2014 + ) + into source_doc_id; + if ( source_doc_id is not null ) then + begin + select agent_id from doc_list h where h.id = :source_doc_id into agent_id; + end + end + else + select :a_selected_doc_id, h.agent_id + from doc_list h + where h.id = :a_selected_doc_id + into source_doc_id, agent_id; + + if ( source_doc_id is not null ) then + begin + -- Find doc ID (with checking in view v_*** if need) and try to LOCK it. + -- Raise exc if no found or can`t lock: + -- ::: do NOT ::: execute procedure sp_lock_selected_doc( source_doc_id, 'doc_list', a_selected_doc_id); + + select h.agent_id from doc_list h where h.id = :a_selected_doc_id into agent_id; + if ( agent_id is null ) then + exception ex_no_doc_found_for_handling using('doc_list', a_selected_doc_id); + -- no document found for handling in datasource = '@1' with id=@2 + + if ( a_total_pay is null ) then + begin + select sum( p.snd_cost ) from pdistr p where p.snd_id = :source_doc_id into v_non_paid_total; + current_pay_sum = round( v_non_paid_total, v_round_to ); + if (current_pay_sum < v_non_paid_total) then + begin + current_pay_sum = current_pay_sum + power(10, abs(v_round_to)); + end + end + else + current_pay_sum = a_total_pay; + + end + else -- source_doc_id is null + begin + select id_selected from sp_get_random_id( :view_to_search_agent, null, null, 0 ) into agent_id; + if ( a_total_pay is null ) then + begin + if (a_payment_oper = fn_oper_pay_from_customer() ) then + current_pay_sum = round(fn_get_random_cost('C_PAYMENT_FROM_CLIENT_MIN_TOTAL', 'C_PAYMENT_FROM_CLIENT_MAX_TOTAL'), v_round_to); -- round to hundreds + else + current_pay_sum = round(fn_get_random_cost('C_PAYMENT_TO_SUPPLIER_MIN_TOTAL', 'C_PAYMENT_TO_SUPPLIER_MAX_TOTAL'), v_round_to); -- round to thousands + end + else + current_pay_sum = a_total_pay; + end + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this,null,'doc_id='||coalesce(source_doc_id, '') ); + + suspend; + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + 'doc_id='||coalesce(source_doc_id, ''), + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + +^ -- sp_payment_common + +-------------------------------------------------------------------------------- + +create or alter procedure sp_pay_from_customer( + a_selected_doc_id type of dm_idb default null, + a_total_pay type of dm_cost default null, + dbg int default 0 +) +returns ( + agent_id type of dm_idb, + prepayment_id type of dm_idb, -- id of prepayment that was done here + realization_id type of dm_idb, -- id of reserve realization doc that 'receives' this advance + current_pay_sum type of dm_cost +) +as + declare v_dbkey dm_dbkey; + declare v_this dm_dbobj = 'sp_pay_from_customer'; +begin + + -- Implementation for payment from customer to us. + -- Randomly choose invoice that is not yet fully paid (by customer) and creates + -- payment document (with sum that can be equal or LESS than rest of value + -- that should be 100% paid). + + -- Check that table `ext_stoptest` (external text file) is EMPTY, + -- otherwise raises e`xception to stop test: + execute procedure sp_check_to_stop_work; + + -- Check that current Tx run in NO wait or with lock_timeout. + -- Otherwise raise error: performance degrades almost to zero. + execute procedure sp_check_nowait_or_timeout; + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(1, v_this); + + -- increment number of total business routine calls within this Tx, + -- in order to display estimated overall performance in ISQL session + -- logs (see generated $tmpdir/tmp_random_run.sql). + -- Instead of querying perf_log join business_ops it was decided to + -- use only context variables in user_tran namespace: + execute procedure srv_increment_tx_bops_counter; + + execute procedure sp_payment_common( + fn_oper_pay_from_customer(), + a_selected_doc_id, + a_total_pay + ) returning_values realization_id, agent_id, current_pay_sum; + + -- add new record in doc_list (header) + execute procedure sp_add_doc_list( + null, + fn_oper_pay_from_customer(), + agent_id, + null, + null, + 0, + current_pay_sum + ) + returning_values :prepayment_id, :v_dbkey; + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this, null, 'payment_id='||prepayment_id); + + suspend; + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + 'doc_id='||coalesce(prepayment_id,''), + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end +end + +^ -- sp_pay_from_customer + +create or alter procedure sp_cancel_pay_from_customer( + a_selected_doc_id type of dm_idb default null +) +returns ( + doc_list_id type of dm_idb, -- id of selected doc (prepayment that is deleted) + agent_id type of dm_idb, -- id of customer + prepayment_sum type of dm_cost -- customer's payment (in retailing prices) +) +as + declare v_dummy bigint; + declare c_raise_exc_when_no_found dm_sign = 1; + declare c_can_skip_order_clause dm_sign = 0; + declare v_this dm_dbobj = 'sp_cancel_pay_from_customer'; +begin + + -- Check that table `ext_stoptest` (external text file) is EMPTY, + -- otherwise raises e`xception to stop test: + execute procedure sp_check_to_stop_work; + + -- Check that current Tx run in NO wait or with lock_timeout. + -- Otherwise raise error: performance degrades almost to zero. + execute procedure sp_check_nowait_or_timeout; + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(1, v_this); + + -- increment number of total business routine calls within this Tx, + -- in order to display estimated overall performance in ISQL session + -- logs (see generated $tmpdir/tmp_random_run.sql). + -- Instead of querying perf_log join business_ops it was decided to + -- use only context variables in user_tran namespace: + execute procedure srv_increment_tx_bops_counter; + + -- Choose random doc of corresponding kind. + -- 25.09.2014: do NOT set c_can_skip_order_clause = 1, + -- performance degrades from ~4900 to ~1900. + doc_list_id = coalesce( :a_selected_doc_id, + (select id_selected from + sp_get_random_id( 'v_cancel_customer_prepayment' -- a_view_for_search + ,null -- a_view_for_min_id ==> the same as a_view_for_search + ,null -- a_view_for_max_id ==> the same as a_view_for_search + ,:c_raise_exc_when_no_found + ,:c_can_skip_order_clause + ) + ) + ); + + -- Try to LOCK just selected doc, raise exc if can`t: + execute procedure sp_lock_selected_doc( doc_list_id, 'v_cancel_customer_prepayment', a_selected_doc_id); + + select agent_id, cost_retail + from doc_list h + where h.id = :doc_list_id + into agent_id, prepayment_sum; + + -- finally, remove prepayment doc (decision about corr. `money_turnover_log` - see trigger doc_list_aiud) + delete from doc_list h where h.id = :doc_list_id; + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this, null, 'doc_id='||doc_list_id); + + suspend; + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + 'doc_id='||coalesce(doc_list_id,''), + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + +^ -- sp_cancel_pay_from_customer + + +create or alter procedure sp_pay_to_supplier( + a_selected_doc_id type of dm_idb default null, + a_total_pay type of dm_cost default null, + dbg int default 0 +) +returns ( + agent_id type of dm_idb, + prepayment_id type of dm_idb, -- id of prepayment that was done here + invoice_id type of dm_idb, -- id of open supplier invoice(s) that 'receives' this advance + current_pay_sum type of dm_cost -- total sum of prepayment (advance) +) +as + declare v_dbkey dm_dbkey; + declare v_round_to smallint; + declare v_id type of dm_idb; + declare v_this dm_dbobj = 'sp_pay_to_supplier'; +begin + + -- Implementation for our payment to supplier. + -- Randomly choose invoice that is not yet fully paid (by us) and creates + -- payment document (with sum that can be equal or LESS than rest of value + -- that should be 100% paid). + + -- Check that table `ext_stoptest` (external text file) is EMPTY, + -- otherwise raises e`xception to stop test: + execute procedure sp_check_to_stop_work; + + -- Check that current Tx run in NO wait or with lock_timeout. + -- Otherwise raise error: performance degrades almost to zero. + execute procedure sp_check_nowait_or_timeout; + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(1, v_this); + + -- increment number of total business routine calls within this Tx, + -- in order to display estimated overall performance in ISQL session + -- logs (see generated $tmpdir/tmp_random_run.sql). + -- Instead of querying perf_log join business_ops it was decided to + -- use only context variables in user_tran namespace: + execute procedure srv_increment_tx_bops_counter; + + execute procedure sp_payment_common( + fn_oper_pay_to_supplier(), + a_selected_doc_id, + a_total_pay + ) returning_values invoice_id, agent_id, current_pay_sum; + + -- add new record in doc_list (header) + execute procedure sp_add_doc_list( + null, + fn_oper_pay_to_supplier(), + agent_id, + null, + null, + current_pay_sum, + 0 + ) + returning_values :prepayment_id, :v_dbkey; + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(0, v_this, null, 'payment_id='||prepayment_id); + + suspend; + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + 'doc_id='||coalesce(prepayment_id,''), + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end +end + +^ -- sp_pay_to_supplier + +create or alter procedure sp_cancel_pay_to_supplier( + a_selected_doc_id type of dm_idb default null +) +returns ( + doc_list_id type of dm_idb, -- id of selected doc + agent_id type of dm_idb, -- id of customer + prepayment_sum type of dm_cost +) +as + declare v_dummy bigint; + declare v_this dm_dbobj = 'sp_cancel_pay_to_supplier'; + declare c_raise_exc_when_no_found dm_sign = 1; + declare c_can_skip_order_clause dm_sign = 0; +begin + + -- Check that table `ext_stoptest` (external text file) is EMPTY, + -- otherwise raises e`xception to stop test: + execute procedure sp_check_to_stop_work; + + -- Check that current Tx run in NO wait or with lock_timeout. + -- Otherwise raise error: performance degrades almost to zero. + execute procedure sp_check_nowait_or_timeout; + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(1, v_this); + + -- increment number of total business routine calls within this Tx, + -- in order to display estimated overall performance in ISQL session + -- logs (see generated $tmpdir/tmp_random_run.sql). + -- Instead of querying perf_log join business_ops it was decided to + -- use only context variables in user_tran namespace: + execute procedure srv_increment_tx_bops_counter; + + -- Choose random doc of corresponding kind. + -- 25.09.2014: do NOT set c_can_skip_order_clause = 1, + -- performance degrades from ~4900 to ~1900. + doc_list_id = coalesce( :a_selected_doc_id, + (select id_selected from + sp_get_random_id( 'v_cancel_payment_to_supplier' -- a_view_for_search + ,null -- a_view_for_min_id ==> the same as a_view_for_search + ,null -- a_view_for_max_id ==> the same as a_view_for_search + ,:c_raise_exc_when_no_found + ,:c_can_skip_order_clause + ) + ) + ); + + -- Try to LOCK just selected doc, raise exc if can`t: + execute procedure sp_lock_selected_doc( doc_list_id, 'v_cancel_payment_to_supplier', a_selected_doc_id); + + select agent_id, cost_purchase + from doc_list h + where h.id = :doc_list_id + into agent_id, prepayment_sum; + + -- finally, remove prepayment doc (decision about corr. `money_turnover_log` - see trigger doc_list_aiud) + delete from doc_list h where h.id = :doc_list_id; + + -- add to performance log timestamp about start/finish this unit + -- (records from GTT tmp$perf_log will be MOVED in fixed table perf_log): + execute procedure sp_add_perf_log(0, v_this, null, 'doc_id='||doc_list_id); + + suspend; + +when any do + begin + -- in a`utonomous tx: + -- 1) add to tmp$perf_log error info + timestamp, + -- 2) move records from tmp$perf_log to perf_log + execute procedure sp_add_to_abend_log( + '', + gdscode, + 'doc_id='||coalesce(doc_list_id,''), + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + +^ -- sp_cancel_pay_to_supplier + +-------------------------------------------------------------------------------- +-- ####################### S E R V I C E U N I T S ####################### +-------------------------------------------------------------------------------- + +create or alter procedure srv_make_invnt_saldo( + a_selected_ware_id type of dm_idb default null +) +returns ( + msg dm_info, + ins_rows int, + upd_rows int, + del_rows int +) +as + declare v_semaphore_id type of dm_idb; + declare v_deferred_to_next_time boolean = false; + declare v_gdscode int = null; + declare v_catch_bitset bigint; + declare v_exc_on_chk_violation smallint; + declare v_this dm_dbobj = 'srv_make_invnt_saldo'; + declare s_qty_clo type of dm_qty; + declare s_qty_clr type of dm_qty; + declare s_qty_ord type of dm_qty; + declare s_qty_sup type of dm_qty; + declare s_qty_avl type of dm_qty; + declare s_qty_res type of dm_qty; + declare s_qty_inc type of dm_qty; + declare s_qty_out type of dm_qty; + declare s_cost_inc type of dm_cost; + declare s_cost_out type of dm_cost; + declare v_rc int; + declare v_err_msg dm_info; + declare v_neg_info dm_info; + declare c_chk_violation_code int = 335544558; -- check_constraint + declare c_semaphores cursor for ( select id from semaphores s where s.task = :v_this rows 1); +begin + -- Gathers all turnovers for wares in 'invnt_turnover_log' table and makes them total + -- to merge in table 'invnt_saldo' + -- Original idea: sql.ru/forum/964534/hranimye-agregaty-bez-konfliktov-i-blokirovok-recept?hl= + -- 21.08.2014: refactored in order to maximal detailed info (via cursor) + -- and SKIP problem wares (with logging first ware which has neg. remainder) + -- and continue totalling for other ones. + + v_catch_bitset = cast(rdb$get_context('USER_SESSION','QMISM_VERIFY_BITSET') as bigint); + -- bit#0 := 1 ==> perform calls of srv_catch_qd_qs_mism in doc_list_aiud => sp_add_invnt_log + -- bit#1 := 1 ==> perform calls of srv_catch_neg_remainders from invnt_turnover_log_ai + -- (instead of totalling turnovers to `invnt_saldo` table) + -- bit#2 := 1 ==> allow dump dirty data into z-tables for analysis, see sp zdump4dbg, in case + -- when some 'bad exception' occurs (see ctx var `HALT_TEST_ON_ERRORS`) + if ( bin_and( v_catch_bitset, 2 ) = 2 ) then + -- instead of totalling turnovers (invnt_turnover_log => group_by => invnt_saldo) + -- we make verification of remainders after every time invnt_turnover_log is + -- changed, see: INVNT_TURNOVER_LOG_AI => SRV_CATCH_NEG_REMAINDERS + --#### + exit; + --#### + + -- Check that table `ext_stoptest` (external text file) is EMPTY, + -- otherwise raises e`xception to stop test: + execute procedure sp_check_to_stop_work; + + -- Check that current Tx run in NO wait or with lock_timeout. + -- Otherwise raise error: performance degrades almost to zero. + execute procedure sp_check_nowait_or_timeout; + + if ( not fn_is_snapshot() ) + then + exception ex_snapshot_isolation_required; + + + -- Ensure that current attach is the ONLY one which tries to make totals. + -- Use locking record from `semaphores` table to serialize access to this + -- code: + begin + v_semaphore_id = null; + open c_semaphores; + while (1=1) do + begin + fetch c_semaphores into v_semaphore_id; + if ( row_count = 0 ) then + exception ex_record_not_found using('semaphores', v_this); + update semaphores set id = id where current of c_semaphores; + leave; + end + close c_semaphores; + + when any do + -- ::: nb ::: do NOT use "wh`en gdscode " followed by "wh`en any": + -- the latter ("w`hen ANY") will handle ALWAYS, even if "w`hen " + -- catched it's kind of exception! + -- 1) tracker.firebirdsql.org/browse/CORE-3275 + -- "W`HEN ANY handles exceptions even if they are handled in another W`HEN section" + -- 2) sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1088890&msg=15879669 + begin + if ( fn_is_lock_trouble(gdscode) ) then + begin + -- concurrent_transaction ==> if select for update failed; + -- deadlock ==> if attempt of UPDATE set id=id failed. + v_gdscode = gdscode; + del_rows = -gdscode; + v_deferred_to_next_time = true; + end + else + exception; -- ::: nb ::: anonimous but in when-block! (check will it be really raised! find topic in sql.ru) + end + end + + if ( v_deferred_to_next_time ) then + begin + -- Info to be stored in context var. A`DD_INFO, see below call of sp_add_to_abend_log (in W`HEN ANY section): + msg = 'can`t lock semaphores.id='|| coalesce(v_semaphore_id,'') ||', deferred'; + exception ex_cant_lock_semaphore_record msg; + end + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(1, v_this); + + -- increment number of total business routine calls within this Tx, + -- in order to display estimated overall performance in ISQL session + -- logs (see generated $tmpdir/tmp_random_run.sql). + -- Instead of querying perf_log join business_ops it was decided to + -- use only context variables in user_tran namespace: + execute procedure srv_increment_tx_bops_counter; + + ins_rows = 0; + upd_rows = 0; + del_rows = 0; + v_neg_info = ''; + v_exc_on_chk_violation = iif( rdb$get_context('USER_SESSION', 'HALT_TEST_ON_ERRORS') containing ',CK,', 1, 0); + + for + select + ware_id, + qty_clo, qty_clr, qty_ord, qty_sup, + qty_avl, qty_res, qty_inc, qty_out, + cost_inc, cost_out + from v_saldo_invnt sn -- result MUST be totalled by WARE_ID (see DDL of this view) + as cursor cn + do + begin + s_qty_clo=0; s_qty_clr=0; s_qty_ord=0; s_qty_sup=0; + s_qty_avl=0; s_qty_res=0; s_qty_inc=0; s_qty_out=0; + s_cost_inc=0; s_cost_out=0; + + select + qty_clo, qty_clr, qty_ord, qty_sup, + qty_avl, qty_res, qty_inc, qty_out, + cost_inc, cost_out + from invnt_saldo t + where t.id = cn.ware_id + into + s_qty_clo, s_qty_clr, s_qty_ord, s_qty_sup + ,s_qty_avl, s_qty_res, s_qty_inc,s_qty_out + ,s_cost_inc, s_cost_out; + + v_rc = row_count; -- 0=> will be INSERT, otherwise UPDATE + -- these values WILL be written in invnt_saldo: + s_qty_clo = s_qty_clo + cn.qty_clo; + s_qty_clr = s_qty_clr + cn.qty_clr; + s_qty_ord = s_qty_ord + cn.qty_ord; + s_qty_sup = s_qty_sup + cn.qty_sup; + s_qty_avl = s_qty_avl + cn.qty_avl; + s_qty_res = s_qty_res + cn.qty_res; + s_qty_inc = s_qty_inc + cn.qty_inc; + s_qty_out = s_qty_out + cn.qty_out; + s_cost_inc = s_cost_inc + cn.cost_inc; + s_cost_out = s_cost_out + cn.cost_out; + + v_err_msg=''; + -- Check all new values before writing into invnt_saldo for matching + -- rule of non-negative remainders, to be able DETAILED LOG of any + -- violation (we can`t get any info about data that violates rule when + -- exception raising): + if ( s_qty_clo < 0 ) then v_err_msg = v_err_msg||' clo='||s_qty_clo; + if ( s_qty_clr < 0 ) then v_err_msg = v_err_msg||' clr='||s_qty_clr; + if ( s_qty_ord < 0 ) then v_err_msg = v_err_msg||' ord='||s_qty_ord; + if ( s_qty_sup < 0 ) then v_err_msg = v_err_msg||' sup='||s_qty_sup; + if ( s_qty_avl < 0 ) then v_err_msg = v_err_msg||' avl='||s_qty_avl; + if ( s_qty_res < 0 ) then v_err_msg = v_err_msg||' res='||s_qty_res; + if ( s_qty_inc < 0 ) then v_err_msg = v_err_msg||' inc='||s_qty_inc; + if ( s_qty_out < 0 ) then v_err_msg = v_err_msg||' out='||s_qty_out; + if ( s_cost_inc < 0 ) then v_err_msg = v_err_msg||' $inc='||s_cost_inc; + if ( s_cost_out < 0 ) then v_err_msg = v_err_msg||' $out='||s_cost_out; + + if ( v_err_msg > '' and v_neg_info = '' ) then + -- register info only for FIRST ware when negative remainder found: + v_neg_info = 'ware='||cn.ware_id||v_err_msg; + + if ( v_neg_info > '' ) then + begin + -- ::: NB ::: do NOT raise exc`eption! Let all wares which have NO troubles + -- be totalled and removed from invnt_turnover_log (=> reduce size of this table) + rdb$set_context( 'USER_SESSION','ADD_INFO', v_neg_info ); -- to be displayed in log of 1run_oltp_emul.bat + msg = v_neg_info||'; '||msg; + execute procedure sp_upd_in_perf_log( + v_this, + c_chk_violation_code, + msg + ); + end + + if ( v_err_msg = '' -- all remainders will be CORRECT => can write + or + v_exc_on_chk_violation = 1 -- allow attempt to write incorrect remainder in order to raise not_valid e`xception and auto-cancel test itself + ) then + begin + update or insert into invnt_saldo( + id + ,qty_clo,qty_clr,qty_ord,qty_sup + ,qty_avl,qty_res,qty_inc,qty_out + ,cost_inc,cost_out + ) values ( + cn.ware_id + ,:s_qty_clo,:s_qty_clr,:s_qty_ord,:s_qty_sup + ,:s_qty_avl,:s_qty_res,:s_qty_inc,:s_qty_out + ,:s_cost_inc,:s_cost_out + ) + matching(id); + + delete from invnt_turnover_log ng + where ng.ware_id = cn.ware_id; + + del_rows = del_rows + row_count; + ins_rows = ins_rows + iif( v_rc=0, 1, 0 ); + upd_rows = upd_rows + iif( v_rc=0, 0, 1 ); + + end -- v_err_msg = '' + end -- cursor on v_saldo_invnt + + msg = 'i='||ins_rows||', u='||upd_rows||', d='||del_rows; + if ( v_neg_info = '' ) then + rdb$set_context('USER_SESSION','ADD_INFO', msg); -- to be displayed in result log of isql + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(0, v_this, v_gdscode, msg ); + + suspend; + +when any do + begin + -- NB: proc sp_add_to_abend_log will set rdb$set_context('USER_SESSION','A`DD_INFO', msg) + -- in order to show this additional info in ISQL log after operation will finish: + execute procedure sp_add_to_abend_log( + msg, -- ==> context var. ADD_INFO will be = "can`t lock semaphores.id=..., deferred" - to be shown in ISQL log + gdscode, + v_neg_info, + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + +^ -- end of srv_make_invnt_saldo + +-------------------------------------------------------------------------------- + +create or alter procedure srv_make_money_saldo( + a_selected_agent_id type of dm_idb default null +) +returns ( + msg dm_info, + ins_rows int, + upd_rows int, + del_rows int +) +as + declare v_semaphore_id type of dm_ids; + declare v_deferred_to_next_time boolean = false; + declare v_gdscode int = null; + declare v_dbkey dm_dbkey; + declare agent_id type of dm_ids; + declare m_cust_debt dm_sign; + declare m_supp_debt dm_sign; + declare cost_purchase type of dm_cost; + declare cost_retail type of dm_cost; + declare v_dts_beg timestamp; + declare v_dummy bigint; + declare v_this dm_dbobj = 'srv_make_money_saldo'; + declare c_semaphores cursor for ( select id from semaphores s where s.task = :v_this rows 1); +begin + + -- Gathers all turnovers for agents in 'money_turnover_log' table and makes them total + -- to merge in table 'money_saldo' + -- Original idea by Dimitry Sibiryakov: + -- sql.ru/forum/964534/hranimye-agregaty-bez-konfliktov-i-blokirovok-recept?hl= + + -- Check that table `ext_stoptest` (external text file) is EMPTY, + -- otherwise raises e`xception to stop test: + execute procedure sp_check_to_stop_work; + + -- Check that current Tx run in NO wait or with lock_timeout. + -- Otherwise raise error: performance degrades almost to zero. + execute procedure sp_check_nowait_or_timeout; + + if ( not fn_is_snapshot() ) + then + exception ex_snapshot_isolation_required; + + -- Ensure that current attach is the ONLY one which tries to make totals. + -- Use locking record from `semaphores` table to serialize access to this + -- code: + begin + open c_semaphores; + while (1=1) do + begin + fetch c_semaphores into v_semaphore_id; + if ( row_count = 0 ) then + exception ex_record_not_found using('semaphores', v_this); + update semaphores set id = id where current of c_semaphores; + leave; + end + close c_semaphores; + when any do + -- ::: nb ::: do NOT use "wh`en gdscode " followed by "wh`en any": + -- the latter ("w`hen ANY") will handle ALWAYS, even if "w`hen " + -- catched it's kind of exception! + -- 1) tracker.firebirdsql.org/browse/CORE-3275 + -- "W`HEN ANY handles exceptions even if they are handled in another W`HEN section" + -- 2) sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1088890&msg=15879669 + begin + if ( fn_is_lock_trouble(gdscode) ) then + begin + -- concurrent_transaction ==> if select for update failed; + -- deadlock ==> if attempt of UPDATE set id=id failed. + v_gdscode = gdscode; + v_deferred_to_next_time = true; + end + else + exception; -- ::: nb ::: anonimous but in when-block! (check will it be really raised! find topic in sql.ru) + end + end + + if ( v_deferred_to_next_time ) then + begin + -- Info to be stored in context var. A`DD_INFO, see below call of sp_add_to_abend_log (in W`HEN ANY section): + msg = 'can`t lock semaphores.id='|| coalesce(v_semaphore_id,'') ||', deferred'; + exception ex_cant_lock_semaphore_record msg; + end + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(1, v_this); + + -- increment number of total business routine calls within this Tx, + -- in order to display estimated overall performance in ISQL session + -- logs (see generated $tmpdir/tmp_random_run.sql). + -- Instead of querying perf_log join business_ops it was decided to + -- use only context variables in user_tran namespace: + execute procedure srv_increment_tx_bops_counter; + + ins_rows = 0; + upd_rows = 0; + del_rows = 0; + v_dts_beg = 'now'; + for + select x.agent_id, + sum( o.m_supp_debt * x.sum_purchase ) sum_purchase, + sum( o.m_cust_debt * x.sum_retail ) sum_retail + from ( + select + m.agent_id, + m.optype_id, + sum( m.cost_purchase ) sum_purchase, + sum( m.cost_retail ) sum_retail + from money_turnover_log m + -- 27.09.2015: added index on (agent_id, optype_id) + group by m.agent_id, m.optype_id + ) x + join optypes o on x.optype_id = o.id + group by x.agent_id + into + agent_id, + cost_purchase, + cost_retail + do begin + + delete from money_turnover_log m + where m.agent_id = :agent_id; + del_rows = del_rows + row_count; + + update money_saldo + set cost_purchase = cost_purchase + :cost_purchase, + cost_retail = cost_retail + :cost_retail + where agent_id = :agent_id; + + if ( row_count = 0 ) then + begin + insert into money_saldo( agent_id, cost_purchase, cost_retail ) + values( :agent_id, :cost_purchase, :cost_retail); + + ins_rows = ins_rows + 1; + end + else + upd_rows = upd_rows + row_count; + + end -- cursor for money_turnover_log m join optypes o on m.optype_id = o.id + + msg = 'i='||ins_rows||', u='||upd_rows||', d='||del_rows + ||', ms='||datediff(millisecond from v_dts_beg to cast('now' as timestamp) ); + rdb$set_context('USER_SESSION','ADD_INFO', msg); -- to be displayed in result log of isql + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(0, v_this, v_gdscode, msg ); + + suspend; + +when any do + begin + -- NB: proc sp_add_to_abend_log will set rdb$set_context('USER_SESSION','A`DD_INFO', msg) + -- in order to show this additional info in ISQL log after operation will finish: + execute procedure sp_add_to_abend_log( + msg, -- ==> context var. ADD_INFO will be = "can`t lock semaphores.id=..., deferred" - to be shown in ISQL log + gdscode, + 'agent_id='||agent_id, + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + +^ -- srv_make_money_saldo + +-------------------------------------------------------------------------------- + +create or alter procedure srv_recalc_idx_stat returns( + tab_name dm_dbobj, + idx_name dm_dbobj, + elapsed_ms int +) +as + declare msg dm_info; + declare v_semaphore_id type of dm_idb; + declare v_deferred_to_next_time boolean = false; + declare v_dummy bigint; + declare idx_stat_befo double precision; + declare v_gdscode int = null; + declare v_this dm_dbobj = 'srv_recalc_idx_stat'; + declare v_start timestamp; + declare c_semaphores cursor for ( select id from semaphores s where s.task = :v_this rows 1); +begin + + -- Refresh index statistics for most changed tables. + -- Needs to be run in regular basis otherwise ineffective plans + -- can be generated when doing inner joins! + + -- Check that table `ext_stoptest` (external text file) is EMPTY, + -- otherwise raises ex`ception to stop test: + execute procedure sp_check_to_stop_work; + + -- Check that current Tx run in NO wait or with lock_timeout. + -- Otherwise raise error: performance degrades almost to zero. + execute procedure sp_check_nowait_or_timeout; + + -- Use locking record from `semaphores` table to synchronize access to this + -- code: + begin + v_semaphore_id = null; + open c_semaphores; + while (1=1) do + begin + fetch c_semaphores into v_semaphore_id; + if ( row_count = 0 ) then + exception ex_record_not_found using('semaphores', v_this); + update semaphores set id = id where current of c_semaphores; + leave; + end + close c_semaphores; + when any do + -- ::: nb ::: do NOT use "wh`en gdscode " followed by "wh`en any": + -- the latter ("w`hen ANY") will handle ALWAYS, even if "w`hen " + -- catched it's kind of exception! + -- 1) tracker.firebirdsql.org/browse/CORE-3275 + -- "W`HEN ANY handles exceptions even if they are handled in another W`HEN section" + -- 2) sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1088890&msg=15879669 + begin + if ( fn_is_lock_trouble(gdscode) ) then + begin + -- concurrent_transaction ==> if select for update failed; + -- deadlock ==> if attempt of UPDATE set id=id failed. + v_deferred_to_next_time = true; + v_gdscode = gdscode; + end + else + exception; -- ::: nb ::: anonimous but in when-block! + end + end + + if ( v_deferred_to_next_time ) then + begin + -- Info to be stored in context var. A`DD_INFO, see below call of sp_add_to_abend_log (in W`HEN ANY section): + msg = 'can`t lock semaphores.id='|| coalesce(v_semaphore_id,'') ||', deferred'; + exception ex_cant_lock_semaphore_record msg; + exit; + end + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(1, v_this); + + -- increment number of total business routine calls within this Tx, + -- in order to display estimated overall performance in ISQL session + -- logs (see generated $tmpdir/tmp_random_run.sql). + -- Instead of querying perf_log join business_ops it was decided to + -- use only context variables in user_tran namespace: + execute procedure srv_increment_tx_bops_counter; + + for + select ri.rdb$relation_name, ri.rdb$index_name, ri.rdb$statistics + from rdb$indices ri + where + coalesce(ri.rdb$system_flag,0)=0 + -- make recalc only for most used tables: + and ri.rdb$relation_name in ( 'DOC_DATA', 'DOC_LIST', 'QDISTR', 'QSTORNED', 'PDISTR', 'PSTORNED') + order by ri.rdb$relation_name, ri.rdb$index_name + into + tab_name, idx_name, idx_stat_befo + do begin + -- Check that table `ext_stoptest` (external text file) is EMPTY, + -- otherwise raises ex`ception to stop test: + execute procedure sp_check_to_stop_work; + + execute procedure sp_add_perf_log(1, v_this||'_'||idx_name); + + v_start='now'; + + execute statement( 'set statistics index '||idx_name ) + with autonomous transaction -- again since 27.11.2015 (c`ommit for ALL indices at once is too long for huge databases!) + ; + + elapsed_ms = datediff(millisecond from v_start to cast('now' as timestamp)); -- 15.09.2015 + + execute procedure sp_add_perf_log(0, v_this||'_'||idx_name,null,tab_name, idx_stat_befo); + suspend; + end + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(0, v_this, v_gdscode); + +when any do + begin + -- NB: proc sp_add_to_abend_log will set rdb$set_context('USER_SESSION','A`DD_INFO', msg) + -- in order to show this additional info in ISQL log after operation will finish: + execute procedure sp_add_to_abend_log( + msg, -- ==> context var. ADD_INFO will be = "can`t lock semaphores.id=..., deferred" - to be shown in ISQL log + gdscode, + null, + v_this + ); + + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + +^ -- srv_recalc_idx_stat + +-------------------------------------------------------------------------- +-- ########################### R E P O R T S ######################## +-------------------------------------------------------------------------- + +create or alter procedure srv_get_last_launch_beg_end( + a_last_hours smallint default 3, + a_last_mins smallint default 0) +returns ( + last_launch_beg timestamp + ,last_launch_end timestamp +) as +begin + -- Auxiliary SP: finds moments of start and finish business operations in perf_log + -- on timestamp interval that is [L, N] where: + -- "L" = latest from {-abs( :a_last_hours * 60 + :a_last_mins ), 'perf_watch_interval'} + -- "N" = latest record in perf_log table + select maxvalue( x.last_job_start_dts, y.last_job_finish_dts ) as last_job_start_dts + from ( + select p.dts_beg as last_job_start_dts + from perf_log p + where p.unit = 'perf_watch_interval' + order by dts_beg desc rows 1 + ) x + cross join + ( + select dateadd( -abs( :a_last_hours * 60 + :a_last_mins ) minute to p.dts_beg) as last_job_finish_dts + from perf_log p + where exists(select 1 from business_ops b where b.unit=p.unit order by b.unit) -- nb: do NOT use inner join here (bad plan with sort) + order by p.dts_beg desc + rows 1 + ) y + into last_launch_beg; + + select p.dts_end as report_end + from perf_log p + where + p.dts_beg >= :last_launch_beg + and p.dts_end is not null + order by p.dts_beg desc + rows 1 + into last_launch_end; + suspend; +end + +^ -- srv_get_last_launch_beg_end + +create or alter procedure srv_mon_perf_total( + a_last_hours smallint default 3, + a_last_mins smallint default 0) +returns ( + business_action dm_info, + job_beg varchar(16), + job_end varchar(16), + avg_times_per_minute numeric(12,2), + avg_elapsed_ms int, + successful_times_done int +) +as + declare v_sort_prior int; + declare v_overall_performance double precision; + declare v_all_minutes int; + declare v_succ_all_times int; + declare v_this dm_dbobj = 'srv_mon_perf_total'; +begin + -- MAIN SP for estimating performance: provides number of business operations + -- per minute which were SUCCESSFULLY finished. Suggested by Alexey Kovyazin. + + a_last_hours = abs( a_last_hours ); + a_last_mins = iif( a_last_mins between 0 and 59, a_last_mins, 0 ); + + delete from tmp$perf_log p where p.stack = :v_this; + + insert into tmp$perf_log(unit, info, id, dts_beg, dts_end, aux1, aux2, stack) + with + a as( + -- reduce needed number of minutes from most last event of some SP starts: + -- 18.07.2014: handle only data which belongs to LAST job. + -- Record with p.unit = 'perf_watch_interval' is added in + -- oltp_isql_run_worker.bat before FIRST isql will be launched + -- for each mode ('sales', 'logist' etc) + select maxvalue( x.last_job_start_dts, y.last_job_finish_dts ) as last_job_start_dts + from ( + select p.dts_beg as last_job_start_dts + from perf_log p + where p.unit = 'perf_watch_interval' + order by dts_beg desc rows 1 + ) x + join + ( + select dateadd( -abs( :a_last_hours * 60 + :a_last_mins ) minute to p.dts_beg) as last_job_finish_dts + from perf_log p + -- nb: do NOT use inner join here (bad plan with sort) + where exists(select 1 from business_ops b where b.unit=p.unit order by b.unit) -- "order by" - only for 3.0 + order by p.dts_beg desc + rows 1 + ) y + on 1=1 + ) + ,p as( + select + g.unit + ,min( g.dts_beg ) report_beg + ,max( g.dts_end ) report_end + ,count(*) successful_times_done + ,avg(g.elapsed_ms) successful_avg_ms + from perf_log g + join business_ops b on b.unit=g.unit + join a on g.dts_beg >= a.last_job_start_dts -- only rows which are from THIS job! + where -- we must take in account only SUCCESSFULLY finished units, i.e. fb_gdscode is NULL. + g.fb_gdscode + 0 -- 25.11.2015: suppress making bitmap for this index! almost 90% of rows contain NULL in this field. + is null + group by g.unit + ) + select b.unit, b.info, b.sort_prior, p.report_beg, p.report_end, + p.successful_times_done, p.successful_avg_ms, :v_this + from business_ops b + left join p on b.unit = p.unit; + -- tmp$perf_log(unit, info, id, dts_beg, dts_end, aux1, aux2) + + -- total elapsed minutes and number of successfully finished SPs for ALL units: + select nullif(datediff( minute from min_beg to max_end ),0), + succ_all_times, + left(cast(min_beg as varchar(24)),16), + left(cast(max_end as varchar(24)),16) + from ( + select min(p.dts_beg) min_beg, max(p.dts_end) max_end, sum(p.aux1) succ_all_times + from tmp$perf_log p + where p.stack = :v_this + ) + into v_all_minutes, v_succ_all_times, job_beg, job_end; + + for + select + business_action + ,avg_times_per_minute + ,avg_elapsed_ms + ,successful_times_done + ,sort_prior + from ( + select + 0 as sort_prior + ,'*** OVERALL *** for '|| :v_all_minutes ||' minutes: ' as business_action -- 'Average ops/minute = '||:v_all_minutes||' ;'||(sum( aux1 ) / :v_all_minutes) as business_action + ,1.00*sum( aux1 ) / :v_all_minutes as avg_times_per_minute + ,avg(aux2) as avg_elapsed_ms + ,sum(aux1) as successful_times_done + from tmp$perf_log p + where p.stack = :v_this + + UNION ALL + + select + p.id as sort_prior + ,p.info as business_action + ,1.00 * aux1 / maxvalue( 1, datediff( minute from p.dts_beg to p.dts_end ) ) as avg_times_per_minute + ,aux2 as avg_elapsed_ms + ,aux1 as successful_times_done + from tmp$perf_log p + where p.stack = :v_this + ) x + order by x.sort_prior + into + business_action + ,avg_times_per_minute + ,avg_elapsed_ms + ,successful_times_done + ,v_sort_prior + do begin + if ( v_sort_prior = 0 ) then -- save value to be written into perf_log + v_overall_performance = avg_times_per_minute; + suspend; + end + + delete from tmp$perf_log p where p.stack = :v_this; + + begin + -- 02.11.2015: save overall performance value so it can be used later: + update perf_log p set aux1 = :v_overall_performance + where p.unit = 'perf_watch_interval' + order by dts_beg desc rows 1; + when any do + begin + -- lock/update conflict can be here with another ISQL session with SID #1 + -- (running on other machine) that makes this report at the same time. + -- We suppress this exception because this record will anyway contain + -- value that we want to save. + end + end + -- Statistics for database with size = 100 Gb and cleaned OS cache (LI-V3.0.0.32179): + -- sync + -- echo 3 > /proc/sys/vm/drop_caches + -- 20 records fetched + -- 600187 ms, 233041 read(s), 4 write(s), 3206400 fetch(es), 70 mark(s) + -- + -- Table Natural Index Update Insert Delete + -- *********************************************************************************** + -- RDB$INDICES 9 + -- BUSINESS_OPS 19 38 + -- PERF_LOG 369967 1 + -- TMP$PERF_LOG 76 19 19 + +end + +^ -- srv_mon_perf_total + +create or alter procedure srv_mon_perf_dynamic( + a_intervals_number smallint default 10, + a_last_hours smallint default 3, + a_last_mins smallint default 0) +returns ( + business_action dm_info + ,interval_no smallint + ,cnt_ok_per_minute int + ,cnt_all int + ,cnt_ok int + ,cnt_err int + ,err_prc numeric(12,2) + ,ok_avg_ms int + ,interval_beg timestamp + ,interval_end timestamp +) +as + declare v_this dm_dbobj = 'srv_mon_perf_dynamic'; +begin + + -- 15.09.2014 Get performance results 'in dynamic': split all job time to N + -- intervals, where N is specified by 1st input argument. + -- 03.09.2015 Removed cross join perf_log and CTE 'inp_args as i' because + -- of inefficient plan. Input parameters are injected inside DT. + -- See: http://www.sql.ru/forum/1173774/select-a-b-from-a-cross-b-order-by-indexed-field-of-a-rows-n-ignorit-rows-n-why + + a_intervals_number = iif( a_intervals_number <= 0, 10, a_intervals_number); + a_last_hours = abs( a_last_hours ); + a_last_mins = iif( a_last_mins between 0 and 59, a_last_mins, 0 ); + + delete from tmp$perf_log p where p.stack = :v_this; + insert into tmp$perf_log( + unit + ,info + ,id -- interval_no + ,dts_beg -- interval_beg + ,dts_end -- interval_end + ,aux1 -- cnt_ok + ,aux2 -- cnt_err + ,elapsed_ms -- ok_avg_ms + ,stack + ) + with + a as( + -- reduce needed number of minutes from most last event of some SP starts: + -- 18.07.2014: handle only data which belongs to LAST job. + -- Record with p.unit = 'perf_watch_interval' is added in + -- oltp_isql_run_worker.bat before FIRST isql will be launched + select + maxvalue( x.last_added_watch_row_dts, y.first_measured_start_dts ) as first_job_start_dts + ,y.last_job_finish_dts + ,y.intervals_number + from ( + select p.dts_beg as last_added_watch_row_dts + from perf_log p + where p.unit = 'perf_watch_interval' + order by dts_beg desc rows 1 + ) x + join ( + select + dateadd( p.scan_bak_minutes minute to p.dts_beg) as first_measured_start_dts + ,p.dts_beg as last_job_finish_dts + ,p.intervals_number + from + ( -- since 03.09.2015: + select + p.* + , -abs( :a_last_hours * 60 + :a_last_mins ) as scan_bak_minutes + , :a_intervals_number as intervals_number + from perf_log p + ) p + -- nb: do NOT use inner join here (bad plan with sort) + where exists(select 1 from business_ops b where b.unit=p.unit order by b.unit) + order by p.dts_beg desc + rows 1 +-- Before 03.09.2015 +-- (inefficient plan with nested loops of all pef_log rows + SORT, 'rows 1' was ignored! +-- See: http://www.sql.ru/forum/1173774/select-a-b-from-a-cross-b-order-by-indexed-field-of-a-rows-n-ignorit-rows-n-why +-- select +-- dateadd( i.scan_bak_minutes minute to p.dts_beg) as first_measured_start_dts +-- ,p.dts_beg as last_job_finish_dts +-- ,i.intervals_number +-- from perf_log p +-- join i on 1=1 -- CTE 'i' was: "with i as(select :a_intervals_number, :a_last_hours, :a_last_mins from rdb$database) +-- -- nb: do NOT use inner join here (bad plan with sort) +-- where exists(select 1 from business_ops b where b.unit=p.unit order by b.unit) +-- order by p.dts_beg desc +-- rows 1 + ) y on 1=1 + ) + ,d as( + select + a.first_job_start_dts + ,a.last_job_finish_dts + ,1+datediff(second from a.first_job_start_dts to a.last_job_finish_dts) / a.intervals_number as sec_for_one_interval + from a + ) + -- select * from d + + ,p as( + select + g.unit + ,b.info + ,1+cast(datediff(second from d.first_job_start_dts to g.dts_beg) / d.sec_for_one_interval as int) as interval_no + ,count(*) cnt_all + ,count( iif( g.fb_gdscode is null, 1, null ) ) cnt_ok + ,count( iif( g.fb_gdscode is NOT null, 1, null ) ) cnt_err + ,100.00 * count( nullif(g.fb_gdscode,0) ) / count(*) err_prc + ,avg( iif( g.fb_gdscode is null, g.elapsed_ms, null ) ) ok_avg_ms + ,min(d.first_job_start_dts) as first_job_start_dts + ,min(d.sec_for_one_interval) as sec_for_one_interval + from perf_log g + join business_ops b on b.unit = g.unit + join d on g.dts_beg >= d.first_job_start_dts -- only rows which are from THIS measured test run! + group by 1,2,3 + ) + ,q as( + select + unit + ,info + ,interval_no + ,dateadd( (interval_no-1) * sec_for_one_interval+1 second to first_job_start_dts ) as interval_beg + ,dateadd( interval_no * sec_for_one_interval second to first_job_start_dts ) as interval_end + ,cnt_all + ,cnt_ok + ,cnt_err + ,err_prc + ,ok_avg_ms + from p + ) + --select * from q; + select + unit + ,info + ,interval_no + ,interval_beg + ,interval_end + ,cnt_ok -- aux1 + ,cnt_err -- aux2 + ,ok_avg_ms + ,:v_this + from q; + ----------------------------- + + for + select + business_action + ,interval_no + ,cnt_ok_per_minute + ,cnt_all + ,cnt_ok + ,cnt_err + ,err_prc + ,ok_avg_ms + ,interval_beg + ,interval_end + from ( + select + 0 as sort_prior + ,'interval #'||lpad(id, 4, ' ')||', overall' as business_action + ,id as interval_no + ,min(dts_beg) as interval_beg + ,min(dts_end) as interval_end + ,round(sum(aux1) / nullif(datediff(minute from min(dts_beg) to min(dts_end)),0), 0) cnt_ok_per_minute + ,sum(aux1 + aux2) as cnt_all + ,sum(aux1) as cnt_ok + ,sum(aux2) as cnt_err + ,100 * sum(aux2) / sum(aux1 + aux2) as err_prc + ,cast(null as int) as ok_avg_ms + --,avg(elapsed_ms) as ok_avg_ms + from tmp$perf_log p + where p.stack = :v_this + group by id + + UNION ALL + + select + 1 as sort_prior + ,info as business_action + ,id as interval_no + ,dts_beg as interval_beg + ,dts_end as interval_end + ,aux1 / nullif(datediff(minute from dts_beg to dts_end),0) cnt_ok_per_minute + ,aux1 + aux2 as cnt_all + ,aux1 as cnt_ok + ,aux2 as cnt_err + ,100 * aux2 / (aux1 + aux2) as err_prc + ,elapsed_ms as ok_avg_ms + from tmp$perf_log p + where p.stack = :v_this + ) + order by sort_prior, business_action, interval_no + into + business_action + ,interval_no + ,cnt_ok_per_minute + ,cnt_all + ,cnt_ok + ,cnt_err + ,err_prc + ,ok_avg_ms + ,interval_beg + ,interval_end + do suspend; +end + +^ -- srv_mon_perf_dynamic + +create or alter procedure srv_mon_perf_detailed ( + a_last_hours smallint default 3, + a_last_mins smallint default 0, + a_show_detl smallint default 0) +returns ( + unit type of dm_unit, + cnt_all integer, + cnt_ok integer, + cnt_err integer, + err_prc numeric(6,2), + ok_min_ms integer, + ok_max_ms integer, + ok_avg_ms integer, + cnt_lk_confl integer, + cnt_user_exc integer, + cnt_chk_viol integer, + cnt_unq_viol integer, + cnt_fk_viol integer, + cnt_stack_trc integer, -- 335544842, 'stack_trace': appears at the TOP of stack in 3.0 SC (strange!) + cnt_zero_gds integer, -- 03.10.2014: core-4565 (gdscode=0 in when-section! 3.0 SC only) + cnt_other_exc integer, + job_beg varchar(16), + job_end varchar(16) +) +as +begin + -- SP for detailed performance analysis: count of operations + -- (NOT only business ops; including BOTH successful and failed ones), + -- count of errors (including by their types) + a_last_hours = abs( coalesce(a_last_hours, 3) ); + a_last_mins = coalesce(a_last_mins, 0); + a_last_mins = iif( a_last_mins between 0 and 59, a_last_mins, 0 ); + + delete from tmp$perf_mon where 1=1; + + insert into tmp$perf_mon( + dts_beg -- 1 + ,dts_end + ,unit + ,cnt_all + ,cnt_ok -- 5 + ,cnt_err + ,err_prc + ,ok_min_ms + ,ok_max_ms + ,ok_avg_ms -- 10 + ,cnt_chk_viol + ,cnt_unq_viol + ,cnt_fk_viol + ,cnt_lk_confl + ,cnt_user_exc -- 15 + ,cnt_stack_trc + ,cnt_zero_gds + ,cnt_other_exc + ) + with + a as( + -- reduce needed number of minutes from most last event of some SP starts: + -- 18.07.2014: handle only data which belongs to LAST job. + -- Record with p.unit = 'perf_watch_interval' is added in + -- oltp_isql_run_worker.bat before FIRST isql will be launched + -- for each mode ('sales', 'logist' etc) + select maxvalue( x.last_job_start_dts, y.last_job_finish_dts ) as last_job_start_dts + from ( + select p.dts_beg as last_job_start_dts + from perf_log p + where p.unit = 'perf_watch_interval' + order by dts_beg desc rows 1 + ) x + join + ( + select dateadd( -abs( :a_last_hours * 60 + :a_last_mins ) minute to p.dts_beg) as last_job_finish_dts + from perf_log p + where exists(select 1 from business_ops b where b.unit=p.unit order by b.unit) -- nb: do NOT use inner join here (bad plan with sort) + order by p.dts_beg desc + rows 1 + ) y + on 1=1 + ) +-- a as( select p.dts_beg last_beg from perf_log p order by p.dts_beg desc rows 1 ) + ,r as( + select min(p.dts_beg) report_beg, max(dts_end) report_end + from perf_log p + join a on p.dts_beg >= a.last_job_start_dts + ) + ,c as ( + select + r.report_beg + ,r.report_end + ,pg.unit + ,count(*) cnt_all + ,count( iif( nullif(pg.fb_gdscode,0) is null, 1, null) ) cnt_ok -- 5 + ,count( nullif(pg.fb_gdscode,0) ) cnt_err + ,100.00 * count( nullif(pg.fb_gdscode,0) ) / count(*) err_prc + ,min( iif( nullif(pg.fb_gdscode,0) is null, pg.elapsed_ms, null) ) ok_min_ms + ,max( iif( nullif(pg.fb_gdscode,0) is null, pg.elapsed_ms, null) ) ok_max_ms + ,avg( iif( nullif(pg.fb_gdscode,0) is null, pg.elapsed_ms, null) ) ok_avg_ms + ,count( iif(pg.fb_gdscode in( 335544347, 335544558 ), 1, null ) ) cnt_chk_viol -- 10 + ,count( iif(pg.fb_gdscode in( 335544665, 335544349 ), 1, null ) ) cnt_unq_viol + ,count( iif(pg.fb_gdscode in( 335544466, 335544838, 335544839 ), 1, null ) ) cnt_fk_viol + ,count( iif(pg.fb_gdscode in( 335544345, 335544878, 335544336, 335544451 ), 1, null ) ) cnt_lk_confl + ,count( iif(pg.fb_gdscode = 335544517, 1, null) ) cnt_user_exc + ,count( iif(pg.fb_gdscode = 335544842, 1, null) ) cnt_stack_trc -- 15 + ,count( iif(pg.fb_gdscode = 0, 1, null) ) cnt_zero_gds + ,count( iif( pg.fb_gdscode + in ( + 335544347, 335544558, + 335544665, 335544349, + 335544466, 335544838, 335544839, + 335544345, 335544878, 335544336, 335544451, + 335544517, + 335544842, + 0 + ) + ,null + ,pg.fb_gdscode + ) + ) cnt_other_exc + from perf_log pg + join r on pg.dts_beg between r.report_beg and r.report_end + where + pg.elapsed_ms >= 0 and -- 24.09.2014: prevent from display in result 'sp_halt_on_error', 'perf_watch_interval' and so on + pg.unit not starting with 'srv_recalc_idx_stat_' + group by + r.report_beg + ,r.report_end + ,pg.unit + ) + select * + from c; + + insert into tmp$perf_mon( + rollup_level + ,unit + ,cnt_all + ,cnt_ok + ,cnt_err + ,err_prc + ,ok_min_ms + ,ok_max_ms + ,ok_avg_ms + ,cnt_chk_viol + ,cnt_unq_viol + ,cnt_fk_viol + ,cnt_lk_confl + ,cnt_user_exc + ,cnt_stack_trc + ,cnt_zero_gds + ,cnt_other_exc + ,dts_beg + ,dts_end + ) + select + 1 + ,unit + ,sum(cnt_all) + ,sum(cnt_ok) + ,sum(cnt_err) + ,100.00 * sum(cnt_err) / sum(cnt_all) + ,min(ok_min_ms) + ,max(ok_max_ms) + ,max(ok_avg_ms) + ,sum( cnt_chk_viol ) cnt_chk_viol + ,sum( cnt_unq_viol ) cnt_unq_viol + ,sum( cnt_fk_viol ) cnt_fk_viol + ,sum( cnt_lk_confl ) cnt_lk_confl + ,sum( cnt_user_exc ) cnt_user_exc + ,sum( cnt_stack_trc ) cnt_stack_trc + ,sum( cnt_zero_gds ) cnt_zero_gds + ,sum( cnt_other_exc ) cnt_other_exc + ,max( dts_beg ) + ,max( dts_end ) + from tmp$perf_mon + group by unit; -- overall totals + + if ( :a_show_detl = 0 ) then + delete from tmp$perf_mon m where m.rollup_level is null; + + -- final resultset (with overall totals first): + for + select + unit, cnt_all, cnt_ok, cnt_err, err_prc, ok_min_ms, ok_max_ms, ok_avg_ms + ,cnt_chk_viol + ,cnt_unq_viol + ,cnt_fk_viol + ,cnt_lk_confl + ,cnt_user_exc + ,cnt_stack_trc + ,cnt_zero_gds + ,cnt_other_exc + ,left(cast(dts_beg as varchar(24)),16) + ,left(cast(dts_end as varchar(24)),16) + from tmp$perf_mon + --order by dy desc nulls first,hr desc, unit + into unit, cnt_all, cnt_ok, cnt_err, err_prc, ok_min_ms, ok_max_ms, ok_avg_ms + ,cnt_chk_viol + ,cnt_unq_viol + ,cnt_fk_viol + ,cnt_lk_confl + ,cnt_user_exc + ,cnt_stack_trc + ,cnt_zero_gds + ,cnt_other_exc + ,job_beg + ,job_end + do + suspend; + +end + +^ -- srv_mon_perf_detailed + +create or alter procedure srv_mon_business_perf_with_exc ( + a_last_hours smallint default 3, + a_last_mins smallint default 0) +returns ( + info dm_info, + unit dm_unit, + cnt_all integer, + cnt_ok integer, + cnt_err integer, + err_prc numeric(6,2), + cnt_chk_viol integer, + cnt_unq_viol integer, + cnt_lk_confl integer, + cnt_user_exc integer, + cnt_other_exc integer, + job_beg varchar(16), + job_end varchar(16) +) +AS +declare v_dummy int; +begin + + a_last_hours = abs( coalesce(a_last_hours, 3) ); + a_last_mins = coalesce(a_last_mins, 0); + a_last_mins = iif( a_last_mins between 0 and 59, a_last_mins, 0 ); + + delete from tmp$perf_mon where 1=1; + -- call to fill tmp$perf_mon with ONLY aggregated data: + select count(*) from srv_mon_perf_detailed(:a_last_hours, :a_last_mins, 0) into v_dummy; + + for + select + o.info,s.unit, s.cnt_all, s.cnt_ok,s.cnt_err,s.err_prc + ,s.cnt_chk_viol + ,s.cnt_unq_viol + ,s.cnt_lk_confl + ,s.cnt_user_exc + ,s.cnt_other_exc + ,left(cast(s.dts_beg as varchar(24)),16) + ,left(cast(s.dts_end as varchar(24)),16) + from business_ops o + left join tmp$perf_mon s on o.unit=s.unit + order by o.sort_prior + into + info + ,unit + ,cnt_all + ,cnt_ok + ,cnt_err + ,err_prc + ,cnt_chk_viol + ,cnt_unq_viol + ,cnt_lk_confl + ,cnt_user_exc + ,cnt_other_exc + ,job_beg + ,job_end + do + suspend; + +end + +^ -- srv_mon_business_perf_with_exc + +create or alter procedure srv_mon_exceptions( + a_last_hours smallint default 3, + a_last_mins smallint default 0) +returns ( + fb_gdscode int, + fb_mnemona type of column fb_errors.fb_mnemona, + unit type of dm_unit, + cnt int, + dts_min timestamp, + dts_max timestamp +) +as +begin + a_last_hours = abs( a_last_hours ); + a_last_mins = iif( a_last_mins between 0 and 59, a_last_mins, 0 ); + + for + with + a as( + -- reduce needed number of minutes from most last event of some SP starts: + -- 18.07.2014: handle only data which belongs to LAST job. + -- Record with p.unit = 'perf_watch_interval' is added in + -- oltp_isql_run_worker.bat before FIRST isql will be launched + -- for each mode ('sales', 'logist' etc) + select maxvalue( x.last_job_start_dts, y.last_job_finish_dts ) as last_job_start_dts + from ( + select p.dts_beg as last_job_start_dts + from perf_log p + where p.unit = 'perf_watch_interval' + order by dts_beg desc rows 1 + ) x + join + ( + select dateadd( -abs( :a_last_hours * 60 + :a_last_mins ) minute to p.dts_beg) as last_job_finish_dts + from perf_log p + -- nb: do NOT use inner join here (bad plan with sort) + where exists(select 1 from business_ops b where b.unit=p.unit order by b.unit) + order by p.dts_beg desc + rows 1 + ) y + on 1=1 + ) + select p.fb_gdscode, e.fb_mnemona, p.unit, count(*) cnt, min(p.dts_beg) dts_min, max(p.dts_beg) dts_max + from perf_log p + join a on p.dts_beg >= a.last_job_start_dts + LEFT -- !! some exceptions can missing in fb_errors !! + join fb_errors e on p.fb_gdscode = e.fb_gdscode + where + p.fb_gdscode > 0 + and p.exc_unit='#' -- 10.01.2015, see sp_add_to_abend_log: take in account only those units where exception occured, and skip callers of them + group by 1,2,3 + into + fb_gdscode, fb_mnemona, unit, cnt, dts_min, dts_max + do + suspend; +end + +^ -- srv_mon_exceptions + +create or alter procedure srv_mon_perf_trace ( + a_intervals_number smallint default 10, + a_last_hours smallint default 3, + a_last_mins smallint default 0 +) +returns ( + unit dm_unit + ,info dm_info + ,interval_no smallint + ,cnt_success int + ,fetches_per_second int + ,marks_per_second int + ,reads_to_fetches_prc numeric(6,2) + ,writes_to_marks_prc numeric(6,2) + ,interval_beg timestamp + ,interval_end timestamp +) as +begin + + -- Report based on result of parsing TRACE log which was started by + -- ISQL session #1 when config parameter trc_unit_perf = 1. + -- Data for each business operation are displayed separately because + -- they depends on execution plans and can not be compared each other. + -- We have to analyze only RATIOS between reads/fetches and writes/marks, + -- and also values of speed (fetches and marks per second) instead of + -- absolute their values. + + a_intervals_number = iif( a_intervals_number <= 0, 10, a_intervals_number); + a_last_hours = abs( a_last_hours ); + a_last_mins = iif( a_last_mins between 0 and 59, a_last_mins, 0 ); + + for + with + a as( + -- reduce needed number of minutes from most last event of some SP starts: + -- 18.07.2014: handle only data which belongs to LAST job. + -- Record with p.unit = 'perf_watch_interval' is added in + -- oltp_isql_run_worker.bat before FIRST isql will be launched + select + maxvalue( x.last_added_watch_row_dts, y.first_measured_start_dts ) as first_job_start_dts + ,y.last_job_finish_dts + ,y.intervals_number + from ( + select p.dts_beg as last_added_watch_row_dts + from perf_log p + where p.unit = 'perf_watch_interval' + order by dts_beg desc rows 1 + ) x + join ( + select + dateadd( p.scan_bak_minutes minute to p.dts_beg) as first_measured_start_dts + ,p.dts_beg as last_job_finish_dts + ,p.intervals_number + from + ( -- since 03.09.2015: + select + p.* + , -abs( :a_last_hours * 60 + :a_last_mins ) as scan_bak_minutes + , :a_intervals_number as intervals_number + from perf_log p + ) p + -- nb: do NOT use inner join here (bad plan with sort) + where exists(select 1 from business_ops b where b.unit=p.unit order by b.unit) + order by p.dts_beg desc + rows 1 + ) y on 1=1 + ) + ,d as( + select + a.first_job_start_dts + ,a.last_job_finish_dts + ,1+datediff(second from a.first_job_start_dts to a.last_job_finish_dts) / a.intervals_number as sec_for_one_interval + from a + ) + --select * from d + ,p as( + select + t.unit + ,b.info + ,1+cast(datediff(second from d.first_job_start_dts to t.dts_end) / d.sec_for_one_interval as int) as interval_no + ,count(*) cnt_success + ,avg( 1000 * t.fetches / nullif(t.elapsed_ms,0) ) fetches_per_second + ,avg( 1000 * t.marks / nullif(t.elapsed_ms,0) ) marks_per_second + ,avg( 100.00 * t.reads/nullif(t.fetches,0) ) reads_to_fetches_prc + ,avg( 100.00 * t.writes/nullif(t.marks,0) ) writes_to_marks_prc + --,count( nullif(t.success,0) ) cnt_ok + --,count( nullif(t.success,1) ) cnt_err + --,100.00 * count( nullif(t.success,1) ) / count(*) err_prc + --,avg( iif( g.fb_gdscode is null, g.elapsed_ms, null ) ) ok_avg_ms + ,min(d.first_job_start_dts) as first_job_start_dts + ,min(d.sec_for_one_interval) as sec_for_one_interval + from trace_stat t + join business_ops b on t.unit = b.unit + join d on t.dts_end between d.first_job_start_dts and d.last_job_finish_dts -- only rows which are from THIS measured test run! + where t.success = 1 + group by 1,2,3 + ) + --select * from p + ,q as ( + select + unit + ,info + ,interval_no + ,cnt_success + ,fetches_per_second + ,marks_per_second + ,reads_to_fetches_prc + ,writes_to_marks_prc + ,first_job_start_dts + ,sec_for_one_interval + ,dateadd( (interval_no-1) * sec_for_one_interval+1 second to first_job_start_dts ) as interval_beg + ,dateadd( interval_no * sec_for_one_interval second to first_job_start_dts ) as interval_end + from p + ) + --select * from q + select + unit + ,info + ,interval_no + ,cnt_success + ,fetches_per_second + ,marks_per_second + ,reads_to_fetches_prc + ,writes_to_marks_prc + ,interval_beg + ,interval_end + from q + into + unit + ,info + ,interval_no + ,cnt_success + ,fetches_per_second + ,marks_per_second + ,reads_to_fetches_prc + ,writes_to_marks_prc + ,interval_beg + ,interval_end + do + suspend; +end + +^ -- srv_mon_perf_trace + +create or alter procedure srv_mon_perf_trace_pivot ( + a_intervals_number smallint default 10, + a_last_hours smallint default 3, + a_last_mins smallint default 0 +) +returns ( + traced_data varchar(30), + interval_no smallint, + sp_client_order bigint, + sp_cancel_client_order bigint, + sp_supplier_order bigint, + sp_cancel_supplier_order bigint, + sp_supplier_invoice bigint, + sp_cancel_supplier_invoice bigint, + sp_add_invoice_to_stock bigint, + sp_cancel_adding_invoice bigint, + sp_customer_reserve bigint, + sp_cancel_customer_reserve bigint, + sp_reserve_write_off bigint, + sp_cancel_write_off bigint, + sp_pay_from_customer bigint, + sp_cancel_pay_from_customer bigint, + sp_pay_to_supplier bigint, + sp_cancel_pay_to_supplier bigint, + srv_make_invnt_saldo bigint, + srv_make_money_saldo bigint, + srv_recalc_idx_stat bigint, + interval_beg timestamp, + interval_end timestamp +) as +begin + + -- Report based on result of parsing TRACE log which was started by + -- ISQL session #1 when config parameter trc_unit_perf = 1. + -- Data for each business operation are displayed separately because + -- they depends on execution plans and can not be compared each other. + -- We have to analyze only RATIOS between reads/fetches and writes/marks, + -- and also values of speed (fetches and marks per second) instead of + -- absolute their values. + + a_intervals_number = iif( a_intervals_number <= 0, 10, a_intervals_number); + a_last_hours = abs( a_last_hours ); + a_last_mins = iif( a_last_mins between 0 and 59, a_last_mins, 0 ); + + for + with recursive + a as( + -- reduce needed number of minutes from most last event of some SP starts: + -- 18.07.2014: handle only data which belongs to LAST job. + -- Record with p.unit = 'perf_watch_interval' is added in + -- oltp_isql_run_worker.bat before FIRST isql will be launched + select + maxvalue( x.last_added_watch_row_dts, y.first_trace_statd_start_dts ) as first_job_start_dts + ,y.last_job_finish_dts + ,y.intervals_number + from ( + select p.dts_beg as last_added_watch_row_dts + from perf_log p + where p.unit = 'perf_watch_interval' + order by dts_beg desc rows 1 + ) x + join ( + select + dateadd( p.scan_bak_minutes minute to p.dts_beg) as first_trace_statd_start_dts + ,p.dts_beg as last_job_finish_dts + ,p.intervals_number + from + ( -- since 03.09.2015: + select + p.* + , -abs( :a_last_hours * 60 + :a_last_mins ) as scan_bak_minutes + , :a_intervals_number as intervals_number + from perf_log p + ) p + -- nb: do NOT use inner join here (bad plan with sort) + where exists(select 1 from business_ops b where b.unit=p.unit order by b.unit) + order by p.dts_beg desc + rows 1 + ) y on 1=1 + ) + ,d as( + select + a.first_job_start_dts + ,a.last_job_finish_dts + ,1+datediff(second from a.first_job_start_dts to a.last_job_finish_dts) / a.intervals_number as sec_for_one_interval + from a + ) + --select * from d + ,p as( + select + t.unit + ,b.info + ,1+cast(datediff(second from d.first_job_start_dts to t.dts_end) / d.sec_for_one_interval as int) as interval_no + ,count(*) cnt_success + ,avg( 1000 * t.fetches / nullif(t.elapsed_ms,0) ) fetches_per_second + ,avg( 1000 * t.marks / nullif(t.elapsed_ms,0) ) marks_per_second + ,avg( 100.00 * t.reads/nullif(t.fetches,0) ) reads_to_fetches_prc + ,avg( 100.00 * t.writes/nullif(t.marks,0) ) writes_to_marks_prc + --,count( nullif(t.success,0) ) cnt_ok + --,count( nullif(t.success,1) ) cnt_err + --,100.00 * count( nullif(t.success,1) ) / count(*) err_prc + --,avg( iif( g.fb_gdscode is null, g.elapsed_ms, null ) ) ok_avg_ms + ,min(d.first_job_start_dts) as first_job_start_dts + ,min(d.sec_for_one_interval) as sec_for_one_interval + from trace_stat t + join business_ops b on t.unit = b.unit + join d on t.dts_end between d.first_job_start_dts and d.last_job_finish_dts -- only rows which are from THIS trace_statd test run! + where t.success = 1 + group by 1,2,3 + ) + --select * from p + ,q as ( + select + unit + ,info + ,interval_no + ,cnt_success + ,fetches_per_second + ,marks_per_second + ,reads_to_fetches_prc + ,writes_to_marks_prc + ,first_job_start_dts + ,sec_for_one_interval + ,dateadd( (interval_no-1) * sec_for_one_interval+1 second to first_job_start_dts ) as interval_beg + ,dateadd( interval_no * sec_for_one_interval second to first_job_start_dts ) as interval_end + from p + ) + --select * from q + , n as ( + select 1 i from rdb$database union all + select n.i+1 from n where n.i+1<=4 + ) + + select + decode(n.i, 1, 'fetches per second', 2, 'marks per second', 3, 'reads/fetches*100', 'writes/marks*100') as trace_stat + ,interval_no + ,max( iif(unit='sp_client_order', decode(n.i, 1, fetches_per_second, 2, marks_per_second, 3, reads_to_fetches_prc, writes_to_marks_prc), null) ) as sp_client_order + ,max( iif(unit='sp_cancel_client_order', decode(n.i, 1, fetches_per_second, 2, marks_per_second, 3, reads_to_fetches_prc, writes_to_marks_prc), null) ) as sp_cancel_client_order + ,max( iif(unit='sp_supplier_order', decode(n.i, 1, fetches_per_second, 2, marks_per_second, 3, reads_to_fetches_prc, writes_to_marks_prc), null) ) as sp_supplier_order + ,max( iif(unit='sp_cancel_supplier_order', decode(n.i, 1, fetches_per_second, 2, marks_per_second, 3, reads_to_fetches_prc, writes_to_marks_prc), null) ) as sp_cancel_supplier_order + ,max( iif(unit='sp_supplier_invoice', decode(n.i, 1, fetches_per_second, 2, marks_per_second, 3, reads_to_fetches_prc, writes_to_marks_prc), null) ) as sp_supplier_invoice + ,max( iif(unit='sp_cancel_supplier_invoice', decode(n.i, 1, fetches_per_second, 2, marks_per_second, 3, reads_to_fetches_prc, writes_to_marks_prc), null) ) as sp_cancel_supplier_invoice + ,max( iif(unit='sp_add_invoice_to_stock', decode(n.i, 1, fetches_per_second, 2, marks_per_second, 3, reads_to_fetches_prc, writes_to_marks_prc), null) ) as sp_add_invoice_to_stock + ,max( iif(unit='sp_cancel_adding_invoice', decode(n.i, 1, fetches_per_second, 2, marks_per_second, 3, reads_to_fetches_prc, writes_to_marks_prc), null) ) as sp_cancel_adding_invoice + ,max( iif(unit='sp_customer_reserve', decode(n.i, 1, fetches_per_second, 2, marks_per_second, 3, reads_to_fetches_prc, writes_to_marks_prc), null) ) as sp_customer_reserve + ,max( iif(unit='sp_cancel_customer_reserve', decode(n.i, 1, fetches_per_second, 2, marks_per_second, 3, reads_to_fetches_prc, writes_to_marks_prc), null) ) as sp_cancel_customer_reserve + ,max( iif(unit='sp_reserve_write_off', decode(n.i, 1, fetches_per_second, 2, marks_per_second, 3, reads_to_fetches_prc, writes_to_marks_prc), null) ) as sp_reserve_write_off + ,max( iif(unit='sp_cancel_write_off', decode(n.i, 1, fetches_per_second, 2, marks_per_second, 3, reads_to_fetches_prc, writes_to_marks_prc), null) ) as sp_cancel_write_off + ,max( iif(unit='sp_pay_from_customer', decode(n.i, 1, fetches_per_second, 2, marks_per_second, 3, reads_to_fetches_prc, writes_to_marks_prc), null) ) as sp_pay_from_customer + ,max( iif(unit='sp_cancel_pay_from_customer', decode(n.i, 1, fetches_per_second, 2, marks_per_second, 3, reads_to_fetches_prc, writes_to_marks_prc), null) ) as sp_cancel_pay_from_customer + ,max( iif(unit='sp_pay_to_supplier', decode(n.i, 1, fetches_per_second, 2, marks_per_second, 3, reads_to_fetches_prc, writes_to_marks_prc), null) ) as sp_pay_to_supplier + ,max( iif(unit='sp_cancel_pay_to_supplier', decode(n.i, 1, fetches_per_second, 2, marks_per_second, 3, reads_to_fetches_prc, writes_to_marks_prc), null) ) as sp_cancel_pay_to_supplier + ,max( iif(unit='srv_make_invnt_saldo', decode(n.i, 1, fetches_per_second, 2, marks_per_second, 3, reads_to_fetches_prc, writes_to_marks_prc), null) ) as srv_make_invnt_saldo + ,max( iif(unit='srv_make_money_saldo', decode(n.i, 1, fetches_per_second, 2, marks_per_second, 3, reads_to_fetches_prc, writes_to_marks_prc), null) ) as srv_make_money_saldo + ,max( iif(unit='srv_recalc_idx_stat', decode(n.i, 1, fetches_per_second, 2, marks_per_second, 3, reads_to_fetches_prc, writes_to_marks_prc), null) ) as srv_recalc_idx_stat + ,interval_beg + ,interval_end + from q + cross join n + group by n.i, interval_no, interval_beg, interval_end + into + traced_data + ,interval_no + ,sp_client_order + ,sp_cancel_client_order + ,sp_supplier_order + ,sp_cancel_supplier_order + ,sp_supplier_invoice + ,sp_cancel_supplier_invoice + ,sp_add_invoice_to_stock + ,sp_cancel_adding_invoice + ,sp_customer_reserve + ,sp_cancel_customer_reserve + ,sp_reserve_write_off + ,sp_cancel_write_off + ,sp_pay_from_customer + ,sp_cancel_pay_from_customer + ,sp_pay_to_supplier + ,sp_cancel_pay_to_supplier + ,srv_make_invnt_saldo + ,srv_make_money_saldo + ,srv_recalc_idx_stat + ,interval_beg + ,interval_end + do + suspend; +end + +^ -- srv_mon_perf_trace_pivot + + +create or alter procedure srv_mon_idx +returns ( + tab_name dm_dbobj, + idx_name dm_dbobj, + last_stat double precision, + curr_stat double precision, + diff_stat double precision, + last_done timestamp +) as + declare v_last_recalc_trn bigint; +begin + + select p.trn_id + from perf_log p + where p.unit starting with 'srv_recalc_idx_stat_' + order by p.trn_id desc rows 1 + into v_last_recalc_trn; + + -- SP for analyzing results of index statistics recalculation: + -- ########################################################### + for + select + t.tab_name + ,t.idx_name + ,t.last_stat + ,r.rdb$statistics + ,t.last_stat - r.rdb$statistics + ,t.last_done + from ( + select + g.info as tab_name + ,substring(g.unit from char_length('srv_recalc_idx_stat_')+1 ) as idx_name + ,g.aux1 as last_stat + ,g.dts_end as last_done + from perf_log g + where g.trn_id = :v_last_recalc_trn + ) t + join rdb$indices r on t.idx_name = r.rdb$index_name + into + tab_name, + idx_name, + last_stat, + curr_stat, + diff_stat, + last_done + do suspend; +end + +^ -- srv_mon_idx +-------------------------------------------------------------------------------- + +create or alter procedure srv_fill_mon( + a_rowset bigint default null -- not null ==> gather info from tmp$mo_log (2 rows); null ==> gather info from ALL attachments +) +returns( + rows_added int +) +as + declare v_curr_trn bigint; + declare v_total_stat_added_rows int = 0; + declare v_table_stat_added_rows int = 0; + declare v_dummy bigint; + declare v_info dm_info; + declare v_this dm_dbobj = 'srv_fill_mon'; +begin + rows_added = -1; + + if ( fn_remote_process() NOT containing 'IBExpert' + and + coalesce(rdb$get_context('USER_SESSION', 'ENABLE_MON_QUERY'), 0) = 0 + ) then + begin + rdb$set_context( 'USER_SESSION','MON_INFO', 'mon$_dis!'); -- to be displayed in log of 1run_oltp_emul.bat + suspend; + --### + exit; + --### + end + -- Check that table `ext_stoptest` (external text file) is EMPTY, + -- otherwise raises e`xception to stop test: + execute procedure sp_check_to_stop_work; + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(1, v_this); + + v_curr_trn = current_transaction; + if ( a_rowset is NULL ) then -- gather data from ALL attachments (separate call of this SP) + begin + in autonomous transaction do + begin + insert into mon_log( + ----------------------- ALL attachments: set #1 + --dts, + sec, + usr, + att_id, + ----------------------- ALL attachments: set #2 + pg_reads, + pg_writes, + pg_fetches, + pg_marks, + ----------------------- ALL attachments: set #3 + rec_inserts, + rec_updates, + rec_deletes, + rec_backouts, + rec_purges, + rec_expunges, + rec_seq_reads, + rec_idx_reads, + ----------------------- ALL attachments: set #4 + rec_rpt_reads, + bkv_reads, -- mon$backversion_reads, since rev. 60012, 28.08.2014 19:16 + frg_reads, + ----------------------- ALL attachments: set #5 + rec_locks, + rec_waits, + rec_confl, + ----------------------- ALL attachments: set #6 + mem_used, + mem_alloc, + ----------------------- ALL attachments: set #7 + stat_id, + server_pid, + remote_pid, + ----------------------- ALL attachments: set #8 + ip, + remote_process, + dump_trn, + unit, + add_info + ) + -- 09.08.2014 + select + ----------------------- ALL attachments: set #1 + --current_time dts + datediff(second from current_date-1 to current_timestamp ) sec + -- mon$attachments(1): + ,a.mon$user mon_user + ,a.mon$attachment_id attach_id + ----------------------- ALL attachments: set #2 + -- mon$io_stats: + ,i.mon$page_reads reads + ,i.mon$page_writes writes + ,i.mon$page_fetches fetches + ,i.mon$page_marks marks + ----------------------- ALL attachments: set #3 + -- mon$record_stats: + ,r.mon$record_inserts ins_cnt + ,r.mon$record_updates upd_cnt + ,r.mon$record_deletes del_cnt + ,r.mon$record_backouts bk_outs + ,r.mon$record_purges purges + ,r.mon$record_expunges expunges + ,r.mon$record_seq_reads seq_reads + ,r.mon$record_idx_reads idx_reads + ----------------------- ALL attachments: set #4 + ,r.mon$record_rpt_reads + ,r.mon$backversion_reads -- since rev. 60012, 28.08.2014 19:16 + ,r.mon$fragment_reads + ----------------------- ALL attachments: set #5 + ,r.mon$record_locks + ,r.mon$record_waits + ,r.mon$record_conflicts + ----------------------- ALL attachments: set #6 + -- mon$memory_usage: + ,u.mon$memory_used used_memory + ,u.mon$memory_allocated alloc_by_OS + ----------------------- ALL attachments: set #7 + -- mon$attachments(2): + ,a.mon$stat_id stat_id + ,a.mon$server_pid server_PID + ,a.mon$remote_pid remote_PID + ----------------------- ALL attachments: set #8 + ,a.mon$remote_address remote_IP + -- aux info: + ,right(a.mon$remote_process,30) remote_process + ,:v_curr_trn + ,:v_this + ,'all_attaches' + from mon$attachments a + --left join mon$statements s on a.mon$attachment_id = s.mon$attachment_id + left join mon$memory_usage u on a.mon$stat_id=u.mon$stat_id + left join mon$io_stats i on a.mon$stat_id=i.mon$stat_id + left join mon$record_stats r on a.mon$stat_id=r.mon$stat_id + where + a.mon$attachment_id<>current_connection + order by + iif( a.mon$user in ('Garbage Collector', 'Cache Writer' ) + ,1 + , iif( a.mon$remote_process containing 'gfix' + ,2 + ,iif( a.mon$remote_process containing 'nbackup' + or a.mon$remote_process containing 'gbak' + or a.mon$remote_process containing 'gstat' + ,3 + ,1000+a.mon$attachment_id + ) + ) + ) + ; + v_total_stat_added_rows = row_count; + end -- in AT + end + else -- input arg :a_rowset is NOT null ==> gather data from tmp$mon_log (were added there in calls before and after application unit from tmp_random_run.sql) + begin + insert into mon_log( + ---------------- CURRENT attachment only: set #1 + rowset, + --dts, + sec, + usr, + att_id, + trn_id, + ---------------- CURRENT attachment only: set #2 + pg_reads, + pg_writes, + pg_fetches, + pg_marks, + ---------------- CURRENT attachment only: set #3 + rec_inserts, + rec_updates, + rec_deletes, + rec_backouts, + rec_purges, + rec_expunges, + --------------- CURRENT attachment only: set #4 + rec_seq_reads, + rec_idx_reads, + rec_rpt_reads, + --------------- CURRENT attachment only: set #5 + bkv_reads, -- mon$backversion_reads, since rev. 60012, 28.08.2014 19:16 + frg_reads, + --------------- CURRENT attachment only: set #6 + rec_locks, + rec_waits, + rec_confl, + --------------- CURRENT attachment only: set #7 + mem_used, + mem_alloc, + --------------- CURRENT attachment only: set #8 + stat_id, + server_pid, + remote_pid, + --------------- CURRENT attachment only: set #9 + ip, + remote_process, + dump_trn, + --------------- CURRENT attachment only: set #10 + unit, + add_info, + fb_gdscode, + elapsed_ms -- added 08.09.2014 + ) + select + ------------------------------- set #1: dts, sec, usr, att_id + t.rowset + --,current_time + ,datediff(second from current_date-1 to current_timestamp ) + ,current_user + ,current_connection + ,max( t.trn_id ) + ------------ CURRENT attachment only: set #2: pg_reads,pg_writes,pg_fetches,pg_marks + ,sum( t.mult * t.pg_reads) -- t.mult = -1 for first meause, +1 for second -- see srv_fill_tmp_mon + ,sum( t.mult * t.pg_writes) + ,sum( t.mult * t.pg_fetches) + ,sum( t.mult * t.pg_marks) + ------------ CURRENT attachment only: set #3: inserts,updates,deletes,backouts,purges,expunges, + ,sum( t.mult * t.rec_inserts) + ,sum( t.mult * t.rec_updates) + ,sum( t.mult * t.rec_deletes) + ,sum( t.mult * t.rec_backouts) + ,sum( t.mult * t.rec_purges) + ,sum( t.mult * t.rec_expunges) + ------------ CURRENT attachment only: set #4: seq_reads,idx_reads,rpt_reads + ,sum( t.mult * t.rec_seq_reads) + ,sum( t.mult * t.rec_idx_reads) + ,sum( t.mult * t.rec_rpt_reads) -- <<< since rev. 60005 27.08.2014 18:52 + ------------ CURRENT attachment only: set #5: ver_reads, frg_reads (since rev. 59953 05.08.2014 08:46) + ,sum( t.mult * t.bkv_reads) -- mon$backversion_reads, since rev. 60012, 28.08.2014 19:16 + ,sum( t.mult * t.frg_reads) + ------------- CURRENT attachment only: set #6: rec_locks,rec_waits,rec_confl (since rev. 59953) + ,sum( t.mult * t.rec_locks) + ,sum( t.mult * t.rec_waits) + ,sum( t.mult * t.rec_confl) + -------------- CURRENT attachment only: set #7: mem_used,mem_alloc + ,sum( t.mult * t.mem_used) + ,sum( t.mult * t.mem_alloc) + -------------- CURRENT attachment only: set #8 stat_id,server_pid,remote_pid + ,max( t.stat_id ) + ,max( t.server_pid ) + ,rdb$get_context('SYSTEM', 'CLIENT_PID') + --------------- CURRENT attachment only: set #9: ip,remote_process,dump_trn + ,fn_remote_address() -- rdb$get_context('SYSTEM', 'CLIENT_ADDRESS') + ,right( fn_remote_process(), 30) -- rdb$get_context('SYSTEM', 'CLIENT_PROCESS') + ,:v_curr_trn + --------------- CURRENT attachment only: set #10 unit,add_info + ,max(unit) + ,max(add_info) + ,max(fb_gdscode) + ,datediff(millisecond from min(t.dts) to max(t.dts) ) + from tmp$mon_log t + where t.rowset = :a_rowset + group by t.rowset; + + v_total_stat_added_rows = row_count; + + delete from tmp$mon_log t where t.rowset = :a_rowset; + + ----------------------------------------- + -- 29.08.2014: gather data from tmp$mon_log_table_stats to mon_log_table_stats + insert into mon_log_table_stats( + rowset -- 1 + ,table_name + ,att_id + ,table_id + ,is_system_table -- 5 + ,rel_type + ,unit + ,fb_gdscode + ,rec_inserts + ,rec_updates -- 10 + ,rec_deletes + ,rec_backouts + ,rec_purges + ,rec_expunges + ,rec_seq_reads -- 15 + ,rec_idx_reads + ,rec_rpt_reads + ,bkv_reads + ,frg_reads + ,rec_locks -- 20 + ,rec_waits + ,rec_confl + ,trn_id + ,stat_id -- 24 + ) + select + s.rowset -- 1 + ,s.table_name as tab_name -- :: NB :: mon$table_stats has field mon$table_NAME rather than mon$table_ID + ,current_connection as att_id + ,max( r.rdb$relation_id ) as tab_id + ,max( r.rdb$system_flag ) as sys_flag -- 5 + ,max( r.rdb$relation_type ) as rel_type + ,max( s.unit ) -- can be NULL before random choise of app unit! + ,sum( s.mult * s.fb_gdscode ) -- t.mult = -1 for first measure, +1 for second -- see srv_fill_tmp_mon + ,sum( s.mult * s.rec_inserts ) + ,sum( s.mult * s.rec_updates ) -- 10 + ,sum( s.mult * s.rec_deletes ) + ,sum( s.mult * s.rec_backouts ) + ,sum( s.mult * s.rec_purges ) + ,sum( s.mult * s.rec_expunges ) + ,sum( s.mult * s.rec_seq_reads ) -- 15 + ,sum( s.mult * s.rec_idx_reads ) + ,sum( s.mult * s.rec_rpt_reads ) + ,sum( s.mult * s.bkv_reads ) + ,sum( s.mult * s.frg_reads ) + ,sum( s.mult * s.rec_locks ) -- 20 + ,sum( s.mult * s.rec_waits ) + ,sum( s.mult * s.rec_confl ) + ,max( s.trn_id ) + ,max( s.stat_id ) -- 24 + from tmp$mon_log_table_stats s + join rdb$relations r on s.table_name = r.rdb$relation_name + where s.rowset = :a_rowset + group by s.rowset, s.table_name; + + v_table_stat_added_rows = row_count; + + delete from tmp$mon_log_table_stats s where s.rowset = :a_rowset; + + end + + rows_added = v_total_stat_added_rows + v_table_stat_added_rows; + v_info='rows added: total_stat='||v_total_stat_added_rows||', table_stat='||v_table_stat_added_rows; + -- ::: nb ::: do NOT use the name 'ADD_INFO', it is reserved to common app unit result! + rdb$set_context( 'USER_SESSION','MON_INFO', v_info ); -- to be displayed in log of 1run_oltp_emul.bat + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(0, v_this, null, v_info ); + + suspend; + +when any do + begin + rdb$set_context( 'USER_SESSION','MON_INFO', 'gds='||gdscode ); + execute procedure sp_add_to_abend_log( + '', + gdscode, + '', + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + +^ -- srv_fill_mon + +-------------------------------------------------------------------------------- + +create or alter procedure srv_fill_tmp_mon( + a_rowset dm_idb, + a_ignore_system_tables smallint default 1, + a_unit dm_unit default null, + a_info dm_info default null, + a_gdscode int default null +) +returns( + rows_added int +) +as + declare v_mult dm_sign; + declare v_curr_trn bigint; + declare v_this dm_dbobj = 'srv_fill_tmp_mon'; + declare v_total_stat_added_rows int; + declare v_table_stat_added_rows int; + declare v_info dm_info; +begin + rows_added = -1; + + if ( fn_remote_process() NOT containing 'IBExpert' + and + coalesce(rdb$get_context('USER_SESSION', 'ENABLE_MON_QUERY'), 0) = 0 + ) then + begin + rdb$set_context( 'USER_SESSION','MON_INFO', 'mon$_dis!'); -- to be displayed in log of 1run_oltp_emul.bat + suspend; + --### + exit; + --### + end + -- Check that table `ext_stoptest` (external text file) is EMPTY, + -- otherwise raises e`xception to stop test: + execute procedure sp_check_to_stop_work; + + -- add to performance log timestamp about start/finish this unit: + execute procedure sp_add_perf_log(1, v_this); + + v_mult = iif( exists(select * from tmp$mon_log g where g.rowset is not distinct from :a_rowset), 1, -1); + v_curr_trn = iif( v_mult = 1, current_transaction, null); + + insert into tmp$mon_log( -- NB: on c`ommit PRESERVE rows! + -- mon$io_stats: + pg_reads + ,pg_writes + ,pg_fetches + ,pg_marks + -- mon$record_stats: + ,rec_inserts + ,rec_updates + ,rec_deletes + ,rec_backouts + ,rec_purges + ,rec_expunges + ,rec_seq_reads + ,rec_idx_reads + + ,rec_rpt_reads + ,bkv_reads -- mon$backversion_reads, since rev. 60012, 28.08.2014 19:16 + ,frg_reads + + ,rec_locks + ,rec_waits + ,rec_confl + ------------ + ,mem_used + ,mem_alloc + ,stat_id + ,server_pid + ------------ + ,rowset + ,unit + ,add_info + ,fb_gdscode + ,mult + ,trn_id + ) + select + -- mon$io_stats: + i.mon$page_reads + ,i.mon$page_writes + ,i.mon$page_fetches + ,i.mon$page_marks + -- mon$record_stats: + ,r.mon$record_inserts + ,r.mon$record_updates + ,r.mon$record_deletes + ,r.mon$record_backouts + ,r.mon$record_purges + ,r.mon$record_expunges + ,r.mon$record_seq_reads + ,r.mon$record_idx_reads + + ,r.mon$record_rpt_reads + ,r.mon$backversion_reads -- since rev. 60012, 28.08.2014 19:16 + ,r.mon$fragment_reads + + ,r.mon$record_locks + ,r.mon$record_waits + ,r.mon$record_conflicts + ------------------------ + ,u.mon$memory_used + ,u.mon$memory_allocated + ,a.mon$stat_id + ,a.mon$server_pid + ------------------------ + ,:a_rowset + ,:a_unit + ,:a_info + ,:a_gdscode + ,:v_mult + ,:v_curr_trn + from mon$attachments a + --left join mon$statements s on a.mon$attachment_id = s.mon$attachment_id + left join mon$memory_usage u on a.mon$stat_id=u.mon$stat_id + left join mon$io_stats i on a.mon$stat_id=i.mon$stat_id + left join mon$record_stats r on a.mon$stat_id=r.mon$stat_id + where + a.mon$attachment_id = current_connection; + + v_total_stat_added_rows = row_count; + + -- 29.08.2014: use also mon$table_stats to analyze per table: + insert into tmp$mon_log_table_stats( + table_name + ,rec_inserts + ,rec_updates + ,rec_deletes + ,rec_backouts + ,rec_purges + ,rec_expunges + --------- + ,rec_seq_reads + ,rec_idx_reads + ,rec_rpt_reads + ,bkv_reads + ,frg_reads + --------- + ,rec_locks + ,rec_waits + ,rec_confl + --------- + ,rowset + ,unit + ,fb_gdscode + ,stat_id + ,mult + ,trn_id + ) + select + t.mon$table_name + ,r.mon$record_inserts + ,r.mon$record_updates + ,r.mon$record_deletes + ,r.mon$record_backouts + ,r.mon$record_purges + ,r.mon$record_expunges + ----------- + ,r.mon$record_seq_reads + ,r.mon$record_idx_reads + ,r.mon$record_rpt_reads + ,r.mon$backversion_reads + ,r.mon$fragment_reads + ----------- + ,r.mon$record_locks + ,r.mon$record_waits + ,r.mon$record_conflicts + ------------ + ,:a_rowset + ,:a_unit + ,:a_gdscode + ,a.mon$stat_id + ,:v_mult + ,:v_curr_trn + from mon$record_stats r + join mon$table_stats t on r.mon$stat_id = t.mon$record_stat_id + join mon$attachments a on t.mon$stat_id = a.mon$stat_id + where + a.mon$attachment_id = current_connection + and ( :a_ignore_system_tables = 0 or t.mon$table_name not starting with 'RDB$' ); + + v_table_stat_added_rows = row_count; + + -- add to performance log timestamp about start/finish this unit: + v_info = 'unit: '||coalesce(a_unit,'') + || ', rowset='||coalesce(a_rowset,'') + || ', rows added: total_stat='||v_total_stat_added_rows||', table_stat='||v_table_stat_added_rows; + execute procedure sp_add_perf_log(0, v_this, null, v_info ); + + rows_added = v_total_stat_added_rows + v_table_stat_added_rows; -- out arg + + suspend; + +when any do + begin + -- ::: nb ::: do NOT use the name 'ADD_INFO', it;s reserved to common app unit result! + rdb$set_context( 'USER_SESSION','MON_INFO', 'gds='||gdscode ); -- to be displayed in isql output, see 1run_oltp_emul.bat + execute procedure sp_add_to_abend_log( + '', + gdscode, + '', + v_this, + fn_halt_sign(gdscode) -- ::: nb ::: 1 ==> force get full stack, ignoring settings `DISABLE_CALL_STACK` value, and HALT test + ); + + --####### + exception; -- ::: nb ::: anonimous but in when-block! + --####### + end + +end + +^ -- srv_fill_tmp_mon + +create or alter procedure srv_mon_stat_per_units ( + a_last_hours smallint default 3, + a_last_mins smallint default 0 ) +returns ( + unit dm_unit + ,iter_counts bigint + ,avg_elap_ms bigint + ,avg_rec_reads_sec numeric(12,2) + ,avg_rec_dmls_sec numeric(12,2) + ,avg_bkos_sec numeric(12,2) + ,avg_purg_sec numeric(12,2) + ,avg_xpng_sec numeric(12,2) + ,avg_fetches_sec numeric(12,2) + ,avg_marks_sec numeric(12,2) + ,avg_reads_sec numeric(12,2) + ,avg_writes_sec numeric(12,2) + ,avg_seq bigint + ,avg_idx bigint + ,avg_rpt bigint + ,avg_bkv bigint + ,avg_frg bigint + ,avg_bkv_per_rec numeric(12,2) + ,avg_frg_per_rec numeric(12,2) + ,avg_ins bigint + ,avg_upd bigint + ,avg_del bigint + ,avg_bko bigint + ,avg_pur bigint + ,avg_exp bigint + ,avg_fetches bigint + ,avg_marks bigint + ,avg_reads bigint + ,avg_writes bigint + ,avg_locks bigint + ,avg_confl bigint + ,max_seq bigint + ,max_idx bigint + ,max_rpt bigint + ,max_bkv bigint + ,max_frg bigint + ,max_bkv_per_rec numeric(12,2) + ,max_frg_per_rec numeric(12,2) + ,max_ins bigint + ,max_upd bigint + ,max_del bigint + ,max_bko bigint + ,max_pur bigint + ,max_exp bigint + ,max_fetches bigint + ,max_marks bigint + ,max_reads bigint + ,max_writes bigint + ,max_locks bigint + ,max_confl bigint + ,job_beg varchar(16) + ,job_end varchar(16) +) as + declare v_report_beg timestamp; + declare v_report_end timestamp; +begin + -- SP for detailed performance analysis: count of operations + -- (NOT only business ops; including BOTH successful and failed ones), + -- count of errors (including by their types) + a_last_hours = abs( coalesce(a_last_hours, 3) ); + a_last_mins = coalesce(a_last_mins, 0); + a_last_mins = iif( a_last_mins between 0 and 59, a_last_mins, 0 ); + + select p.last_launch_beg, p.last_launch_end + from srv_get_last_launch_beg_end( :a_last_hours, :a_last_mins ) p + into v_report_beg, v_report_end; + + for + -- 29.08.2014: data from measuring statistics per each unit + -- (need FB rev. >= 60013: new mon$ counters were introduced, 28.08.2014) + -- 25.01.2015: added rec_locks, rec_confl. + -- 06.02.2015: reorder columns, made all `max` values most-right + select + m.unit + ,count(*) iter_counts + -------------- speed ------------- + ,avg(m.elapsed_ms) avg_elap_ms + ,avg(1000.00 * ( (m.rec_seq_reads + m.rec_idx_reads + m.bkv_reads ) / nullif(m.elapsed_ms,0)) ) avg_rec_reads_sec + ,avg(1000.00 * ( (m.rec_inserts + m.rec_updates + m.rec_deletes ) / nullif(m.elapsed_ms,0)) ) avg_rec_dmls_sec + ,avg(1000.00 * ( m.rec_backouts / nullif(m.elapsed_ms,0)) ) avg_bkos_sec + ,avg(1000.00 * ( m.rec_purges / nullif(m.elapsed_ms,0)) ) avg_purg_sec + ,avg(1000.00 * ( m.rec_expunges / nullif(m.elapsed_ms,0)) ) avg_xpng_sec + ,avg(1000.00 * ( m.pg_fetches / nullif(m.elapsed_ms,0)) ) avg_fetches_sec + ,avg(1000.00 * ( m.pg_marks / nullif(m.elapsed_ms,0)) ) avg_marks_sec + ,avg(1000.00 * ( m.pg_reads / nullif(m.elapsed_ms,0)) ) avg_reads_sec + ,avg(1000.00 * ( m.pg_writes / nullif(m.elapsed_ms,0)) ) avg_writes_sec + -------------- reads --------------- + ,avg(m.rec_seq_reads) avg_seq + ,avg(m.rec_idx_reads) avg_idx + ,avg(m.rec_rpt_reads) avg_rpt + ,avg(m.bkv_reads) avg_bkv + ,avg(m.frg_reads) avg_frg + ,avg(m.bkv_per_seq_idx_rpt) avg_bkv_per_rec + ,avg(m.frg_per_seq_idx_rpt) avg_frg_per_rec + ---------- modifications ---------- + ,avg(m.rec_inserts) avg_ins + ,avg(m.rec_updates) avg_upd + ,avg(m.rec_deletes) avg_del + ,avg(m.rec_backouts) avg_bko + ,avg(m.rec_purges) avg_pur + ,avg(m.rec_expunges) avg_exp + --------------- io ----------------- + ,avg(m.pg_fetches) avg_fetches + ,avg(m.pg_marks) avg_marks + ,avg(m.pg_reads) avg_reads + ,avg(m.pg_writes) avg_writes + ----------- locks and conflicts ---------- + ,avg(m.rec_locks) avg_locks + ,avg(m.rec_confl) avg_confl + --- 06.02.2015 moved here all MAX values, separate them from AVG ones: --- + ,max(m.rec_seq_reads) max_seq + ,max(m.rec_idx_reads) max_idx + ,max(m.rec_rpt_reads) max_rpt + ,max(m.bkv_reads) max_bkv + ,max(m.frg_reads) max_frg + ,max(m.bkv_per_seq_idx_rpt) max_bkv_per_rec + ,max(m.frg_per_seq_idx_rpt) max_frg_per_rec + ,max(m.rec_inserts) max_ins + ,max(m.rec_updates) max_upd + ,max(m.rec_deletes) max_del + ,max(m.rec_backouts) max_bko + ,max(m.rec_purges) max_pur + ,max(m.rec_expunges) max_exp + ,max(m.pg_fetches) max_fetches + ,max(m.pg_marks) max_marks + ,max(m.pg_reads) max_reads + ,max(m.pg_writes) max_writes + ,max(m.rec_locks) max_locks + ,max(m.rec_confl) max_confl + ,left(cast(:v_report_beg as varchar(24)),16) + ,left(cast(:v_report_end as varchar(24)),16) + from mon_log m + where m.dts between :v_report_beg and :v_report_end + group by unit + into + unit + ,iter_counts + ,avg_elap_ms + ,avg_rec_reads_sec + ,avg_rec_dmls_sec + ,avg_bkos_sec + ,avg_purg_sec + ,avg_xpng_sec + ,avg_fetches_sec + ,avg_marks_sec + ,avg_reads_sec + ,avg_writes_sec + ,avg_seq + ,avg_idx + ,avg_rpt + ,avg_bkv + ,avg_frg + ,avg_bkv_per_rec + ,avg_frg_per_rec + ,avg_ins + ,avg_upd + ,avg_del + ,avg_bko + ,avg_pur + ,avg_exp + ,avg_fetches + ,avg_marks + ,avg_reads + ,avg_writes + ,avg_locks + ,avg_confl + ,max_seq + ,max_idx + ,max_rpt + ,max_bkv + ,max_frg + ,max_bkv_per_rec + ,max_frg_per_rec + ,max_ins + ,max_upd + ,max_del + ,max_bko + ,max_pur + ,max_exp + ,max_fetches + ,max_marks + ,max_reads + ,max_writes + ,max_locks + ,max_confl + ,job_beg + ,job_end + do + suspend; +end + +^ -- srv_mon_stat_per_units + +create or alter procedure srv_mon_stat_per_tables ( + a_last_hours smallint default 3, + a_last_mins smallint default 0 ) +returns ( + table_name dm_dbobj + ,unit dm_unit + ,iter_counts bigint + ,avg_seq bigint + ,avg_idx bigint + ,avg_rpt bigint + ,avg_bkv bigint + ,avg_frg bigint + ,avg_bkv_per_rec numeric(12,2) + ,avg_frg_per_rec numeric(12,2) + ,avg_ins bigint + ,avg_upd bigint + ,avg_del bigint + ,avg_bko bigint + ,avg_pur bigint + ,avg_exp bigint + ,avg_locks bigint + ,avg_confl bigint + --,elapsed_minutes int + ,max_seq bigint + ,max_idx bigint + ,max_rpt bigint + ,max_bkv bigint + ,max_frg bigint + ,max_bkv_per_rec numeric(12,2) + ,max_frg_per_rec numeric(12,2) + ,max_ins bigint + ,max_upd bigint + ,max_del bigint + ,max_bko bigint + ,max_pur bigint + ,max_exp bigint + ,max_locks bigint + ,max_confl bigint + ,job_beg varchar(16) + ,job_end varchar(16) +) as + declare v_report_beg timestamp; + declare v_report_end timestamp; +begin + -- SP for detailed performance analysis: count of operations + -- (NOT only business ops; including BOTH successful and failed ones), + -- count of errors (including by their types) + a_last_hours = abs( coalesce(a_last_hours, 3) ); + a_last_mins = coalesce(a_last_mins, 0); + a_last_mins = iif( a_last_mins between 0 and 59, a_last_mins, 0 ); + + select p.last_launch_beg, p.last_launch_end + from srv_get_last_launch_beg_end( :a_last_hours, :a_last_mins ) p + into v_report_beg, v_report_end; + + for + select + t.table_name + ,t.unit + ,count(*) iter_counts + --------------- reads --------------- + ,avg(t.rec_seq_reads) avg_seq + ,avg(t.rec_idx_reads) avg_idx + ,avg(t.rec_rpt_reads) avg_rpt + ,avg(t.bkv_reads) avg_bkv + ,avg(t.frg_reads) avg_frg + ,avg(t.bkv_per_seq_idx_rpt) avg_bkv_per_rec + ,avg(t.frg_per_seq_idx_rpt) avg_frg_per_rec + ---------- modifications ---------- + ,avg(t.rec_inserts) avg_ins + ,avg(t.rec_updates) avg_upd + ,avg(t.rec_deletes) avg_del + ,avg(t.rec_backouts) avg_bko + ,avg(t.rec_purges) avg_pur + ,avg(t.rec_expunges) avg_exp + ----------- locks and conflicts ---------- + ,avg(t.rec_locks) avg_locks + ,avg(t.rec_confl) avg_confl + --,datediff( minute from min(t.dts) to max(t.dts) ) elapsed_minutes + --- 06.02.2015 moved here all MAX values, separate them from AVG ones: --- + ,max(t.rec_seq_reads) max_seq + ,max(t.rec_idx_reads) max_idx + ,max(t.rec_rpt_reads) max_rpt + ,max(t.bkv_reads) max_bkv + ,max(t.frg_reads) max_frg + ,max(t.bkv_per_seq_idx_rpt) max_bkv_per_rec + ,max(t.frg_per_seq_idx_rpt) max_frg_per_rec + ,max(t.rec_inserts) max_ins + ,max(t.rec_updates) max_upd + ,max(t.rec_deletes) max_del + ,max(t.rec_backouts) max_bko + ,max(t.rec_purges) max_pur + ,max(t.rec_expunges) max_exp + ,max(t.rec_locks) max_locks + ,max(t.rec_confl) max_confl + ,left(cast(:v_report_beg as varchar(24)),16) + ,left(cast(:v_report_end as varchar(24)),16) + from mon_log_table_stats t + where + t.dts between :v_report_beg and :v_report_end + and + t.rec_seq_reads + + t.rec_idx_reads + + t.rec_rpt_reads + + t.bkv_reads + + t.frg_reads + + t.rec_inserts + + t.rec_updates + + t.rec_deletes + + t.rec_backouts + + t.rec_purges + + t.rec_expunges + + t.rec_locks + + t.rec_confl + > 0 + group by t.table_name, t.unit + into + table_name + ,unit + ,iter_counts + ,avg_seq + ,avg_idx + ,avg_rpt + ,avg_bkv + ,avg_frg + ,avg_bkv_per_rec + ,avg_frg_per_rec + ,avg_ins + ,avg_upd + ,avg_del + ,avg_bko + ,avg_pur + ,avg_exp + ,avg_locks + ,avg_confl + --,elapsed_minutes + ,max_seq + ,max_idx + ,max_rpt + ,max_bkv + ,max_frg + ,max_bkv_per_rec + ,max_frg_per_rec + ,max_ins + ,max_upd + ,max_del + ,max_bko + ,max_pur + ,max_exp + ,max_locks + ,max_confl + ,job_beg + ,job_end + do + suspend; +end + +^ -- srv_mon_stat_per_tables + +create or alter procedure srv_get_report_name( + a_format varchar(20) default 'regular' -- 'regular' | 'benchmark' + ,a_build varchar(50) default '' -- WI-V3.0.0.32136 or just '32136' + ,a_num_of_sessions int default -1 + ,a_test_time_minutes int default -1 + ,a_prefix varchar(255) default '' + ,a_suffix varchar(255) default '' +) returns ( + report_file varchar(255) -- full name of final report + ,start_at varchar(15) -- '20150223_1527': timestamp of test_time phase start + ,fb_arch varchar(50) -- 'ss30' | 'sc30' | 'cs30' + ,overall_perf varchar(50) -- 'score_07548' + ,fw_setting varchar(20) -- 'fw__on' | 'fw_off' + ,load_time varchar(50) -- '03h00m' + ,load_att varchar(50) -- '150_att' + ,heavy_load_ddl varchar(50) -- only when a_format='benchmark': solid' | 'split' + ,compound_1st_col varchar(50) -- only when a_format='benchmark': 'most__selective_1st' | 'least_selective_1st' + ,compound_idx_num varchar(50) -- only when a_format='benchmark': 'one_index' | 'two_indxs' +) +as + declare v_test_finish_state varchar(50); + declare v_tab_name dm_dbobj; + declare v_idx_name dm_dbobj; + declare v_min_idx_key varchar(255); + declare v_max_idx_key varchar(255); + declare v_test_time int; + declare v_num_of_sessions int; + declare v_dts_beg timestamp; + declare v_dts_end timestamp; + declare k smallint; + declare v_fb_major_vers varchar(10); +begin + + -- Aux. SP for returning FILE NAME of final report which does contain all + -- valuable FB, database and test params + -- Sample: + -- select * from srv_get_report_name('regular', 31236) + -- select * from srv_get_report_name('benchmark', 31236) + + select d1 || d2 + from ( + select d1, left(s, position('.' in s)-1) d2 + from ( + select left(r, position('.' in r)-1) d1, substring(r from 1+position('.' in r)) s + from ( + select rdb$get_context('SYSTEM','ENGINE_VERSION') r from rdb$database + ) + ) + ) into v_fb_major_vers; -- '2.5.0' ==> '25'; '3.0.0' ==> '30'; '19.17.1' ==> '1917' :-) + + select p.fb_arch from sys_get_fb_arch p into fb_arch; + fb_arch = + iif( fb_arch containing 'superserver' or upper(fb_arch) starting with upper('ss'), 'ss' + ,iif( fb_arch containing 'superclassic' or upper(fb_arch) starting with upper('sc'), 'sc' + ,iif( fb_arch containing 'classic' or upper(fb_arch) starting with upper('cs'), 'cs' + ,'fb' + ) + ) + ) + || v_fb_major_vers -- prev: iif( rdb$get_context('SYSTEM','ENGINE_VERSION') starting with '2.5', '25', '30' ) + ; + fw_setting='fw' || iif( (select mon$forced_writes from mon$database)= 1,'__on','_off'); + + select + 'score_'||lpad( cast( coalesce(aux1,0) as int ), iif( coalesce(aux1,0) < 99999, 5, 18 ) , '0' ) + ,datediff(minute from p.dts_beg to p.dts_end) + ,p.dts_beg, p.dts_end + from perf_log p + where p.unit = 'perf_watch_interval' + order by p.dts_beg desc + rows 1 + into overall_perf, v_test_time, v_dts_beg, v_dts_end; + + v_test_finish_state = null; + if ( a_test_time_minutes = -1 ) then -- call AFTER test finish, when making final report + begin + select 'ABEND_GDS_'||p.fb_gdscode + from perf_log p + where p.unit = 'sp_halt_on_error' and p.fb_gdscode >= 0 + order by p.dts_beg desc + rows 1 + into v_test_finish_state; -- will remain NULL if not found ==> test finished NORMAL. + end + else -- a_test_time_minutes > = 0 + begin + -- call from main batch (1run_oltp_emul) just BEFORE all ISQL + -- sessions will be launched: display *estimated* name of report + overall_perf = 'score_' || lpad('',5,'X'); + v_test_time = a_test_time_minutes; + end + + select left(ansi_dts, 13) from sys_timestamp_to_ansi( coalesce(:v_dts_beg, current_timestamp)) + into start_at; + + v_test_time = coalesce(v_test_time,0); + load_time = lpad(cast(v_test_time/60 as int),2,'_')||'h' || lpad(mod(v_test_time,60),2,'0')||'m'; + + if ( a_num_of_sessions = -1 ) then + -- Use *actual* number of ISQL sessions that were participate in this test run. + -- This case is used when final report is created AFTER test finish, from oltp_isql_run_worker.bat (.sh): + select count(distinct e.att_id) + from perf_estimated e + into v_num_of_sessions; + else + -- Use *declared* number of ISQL sessions that *will* be participate in this test run: + -- (this case is used when we diplay name of report BEFORE launching ISQL sessions, in 1run_oltp_emul.bat (.sh) script): + v_num_of_sessions= a_num_of_sessions; + + load_att = lpad( coalesce(v_num_of_sessions, '0'), 3, '_') || '_att'; + + k = position('.' in reverse(a_build)); + a_build = iif( k > 0, reverse(left(reverse(a_build), k - 1)), a_build ); + + if ( a_format = 'regular' ) then + -- 20151102_2219_score_06578_build_32136_ss30__0h30m__10_att_fw_off.txt + report_file = + start_at + || '_' || coalesce( v_test_finish_state, overall_perf ) + || iif( a_build > '', '_build_' || a_build, '' ) + || '_' || fb_arch + || '_' || load_time + || '_' || load_att + || '_' || fw_setting + ; + else if (a_format = 'benchmark') then + begin + for + select + tab_name, + min(idx_key) as min_idx_key, + max(idx_key) as max_idx_key + from z_qd_indices_ddl z + group by tab_name + rows 1 + into + v_tab_name, v_min_idx_key, v_max_idx_key + do begin + + heavy_load_ddl = iif( upper(v_tab_name)=upper('qdistr'), 'solid', 'split' ); + + if ( upper(v_min_idx_key) starting with upper('ware_id') or upper(v_max_idx_key) starting with upper('ware_id') ) then + compound_1st_col = 'most__sel_1st'; + else if ( upper(v_min_idx_key) starting with upper('snd_optype_id') or upper(v_max_idx_key) starting with upper('snd_optype_id') ) then + compound_1st_col = 'least_sel_1st'; + + if ( v_min_idx_key = v_max_idx_key ) then + compound_idx_num = 'one_index'; + else + compound_idx_num = 'two_indxs'; + end + -- ss30_fw__on_solid_most__sel_1st_two_indxs_loadtime_180m_by_100_att_20151102_0958_20151102_1258.txt + report_file = + fb_arch + || '_' || fw_setting + || '_' || heavy_load_ddl -- 'solid' | 'split' + || '_' || compound_1st_col -- 'most__sel_1st' | 'least_sel_1st' + || '_' || compound_idx_num -- 'one_index' | 'two_indxs' + || '_' || coalesce( v_test_finish_state, overall_perf ) + || iif( a_build > '', '_build_' || a_build, '' ) + || '_' || load_time + || '_' || load_att + || '_' || start_at + ; + end + + if ( trim(a_prefix) > '' ) then report_file = trim(a_prefix) || '-' || report_file; + + if ( trim(a_suffix) > '' ) then report_file = report_file || '-' || trim(a_suffix); + + suspend; + +end + +^ -- srv_get_report_name + +create or alter procedure srv_test_work +returns ( + ret_code integer) +as + declare v_bak_ctx1 int; + declare v_bak_ctx2 int; + declare n bigint; + declare v_clo_id bigint; + declare v_ord_id bigint; + declare v_inv_id bigint; + declare v_res_id bigint; +begin + -- "express test" for checking that main app units work OK. + -- NB: all tables must be EMPTY before this SP run. + v_bak_ctx1 = rdb$get_context('USER_SESSION', 'ORDER_FOR_OUR_FIRM_PERCENT'); + v_bak_ctx2 = rdb$get_context('USER_SESSION', 'ENABLE_RESERVES_WHEN_ADD_INVOICE'); + + rdb$set_context('USER_SESSION', 'ORDER_FOR_OUR_FIRM_PERCENT',0); + rdb$set_context('USER_SESSION', 'ENABLE_RESERVES_WHEN_ADD_INVOICE',1); + + select min(p.doc_list_id) from sp_client_order(0,1,1) p into v_clo_id; + select count(*) from srv_make_invnt_saldo into n; + select min(p.doc_list_id) from sp_supplier_order(0,1,1) p into v_ord_id; + select count(*) from srv_make_invnt_saldo into n; + select min(p.doc_list_id) from sp_supplier_invoice(0,1,1) p into v_inv_id; + select count(*) from srv_make_invnt_saldo into n; + select count(*) from sp_add_invoice_to_stock(:v_inv_id) into n; + select count(*) from srv_make_invnt_saldo into n; + + select h.id + from doc_list h + where h.optype_id = fn_oper_retail_reserve() + rows 1 + into :v_res_id; + + select count(*) from sp_reserve_write_off(:v_res_id) into n; + select count(*) from srv_make_invnt_saldo into n; + select count(*) from sp_cancel_client_order(:v_clo_id) into n; + select count(*) from srv_make_invnt_saldo into n; + select count(*) from sp_cancel_supplier_order(:v_ord_id) into n; + select count(*) from srv_make_invnt_saldo into n; + + rdb$set_context('USER_SESSION', 'ORDER_FOR_OUR_FIRM_PERCENT', v_bak_ctx1); + rdb$set_context('USER_SESSION', 'ENABLE_RESERVES_WHEN_ADD_INVOICE', v_bak_ctx2); + + ret_code = iif( exists(select * from v_qdistr_source ) or exists(select * from v_qstorned_source ), 1, 0); + ret_code = iif( exists(select * from invnt_turnover_log), bin_or(ret_code, 2), ret_code ); + ret_code = iif( NOT exists(select * from invnt_saldo), bin_or(ret_code, 4), ret_code ); + + n = null; + select s.id + from invnt_saldo s + where NOT + ( + s.qty_clo=1 and s.qty_clr = 1 + and s.qty_ord = 0 and s.qty_sup = 0 + and s.qty_avl = 0 and s.qty_res = 0 + and s.qty_inc = 0 and s.qty_out = 0 + ) + rows 1 + into n; + + ret_code = iif( n is NOT null, bin_or(ret_code, 8), ret_code ); + + suspend; +end + +^ -- srv_test_work + +set term ;^ + + + +set list on; +set echo off; +select 'oltp30_sp.sql finish at ' || current_timestamp as msg from rdb$database; +set list off; + + +-- ################################################################### +-- End of script oltp30_SP.sql; next to be run: oltp_main_filling.sql +-- (common for both FB 2.5 and 3.0) +-- ################################################################### + +-- ################################### +-- Begin of script oltp_misc_debug.sql // ### O P T I O N A L ### +-- ################################### +-- ::: NB ::: This scipt is COMMON for both FB 2.5 and 3.0 and should be called after oltp_main_filling.sql (if needed) + +-- It creates some OPTIONAL debug views and procedures. +-- Need only when some troubles in algorithms are detected. +-- Call of this script should be AFTER running oltpNN_DDL.sql and oltpNN_sp.sql + +set list on; +select 'oltp_misc_debug.sql start at ' || current_timestamp as msg from rdb$database; +set list off; + + + +------------------------------------------------------- +-- ************ D E B U G T A B L E S ********** +------------------------------------------------------- + -- tables for dump dirty data, 4 debug only +recreate table ztmp_shopping_cart( + id bigint, + snd_id bigint, + qty numeric(12,3), + optype_id bigint, + snd_optype_id bigint, + rcv_optype_id bigint, + qty_bak numeric(12,3), + dup_cnt int, + dump_att bigint, + dump_trn bigint +); + + +recreate table ztmp_dep_docs( + base_doc_id bigint, + dependend_doc_id bigint, + dependend_doc_state bigint, + dependend_doc_dbkey dm_dbkey, + dependend_doc_agent_id bigint, + ware_id bigint, + base_doc_qty numeric(12,3), + dependend_doc_qty numeric(12,3), + dump_att bigint, + dump_trn bigint +); + + +recreate table zdoc_list( + id bigint + ,optype_id bigint + ,agent_id bigint + ,state_id bigint + ,base_doc_id bigint -- id of document that is 'base' for current (stock order => incoming invoice etc) + ,cost_purchase numeric(12,2) default 0 -- total in PURCHASING cost (can be ZERO for stock orders) + ,cost_retail numeric(12,2) default 0 -- total in RETAIL cost, can be zero for incoming docs and stock orders + ,acn_type dm_account_type + ,dts_open timestamp + ,dts_fix timestamp -- when changes of CONTENT of this document became disabled + ,dts_clos timestamp -- when ALL changes of this doc. became disabled + ,att int + ,dump_att bigint + ,dump_trn bigint +); + + +recreate table zdoc_data( + id dm_idb + ,doc_id dm_idb + ,ware_id dm_idb + ,qty dm_qty + ,cost_purchase dm_cost + ,cost_retail dm_cost + ,dts_edit timestamp + ,optype_id dm_idb + ,dump_att bigint + ,dump_trn bigint +); + +-- 27.06.2014 (need to find cases when negative remainders appear) +recreate table zinvnt_turnover_log( + ware_id bigint + ,qty_diff numeric(12,3) + ,cost_diff numeric(12,2) + ,doc_list_id bigint + ,doc_pref dm_mcode + ,doc_data_id bigint + ,optype_id bigint + ,id bigint + ,dts_edit timestamp + ,att_id int + ,trn_id int + ,dump_att bigint + ,dump_trn bigint +); + +recreate table zqdistr( + id dm_idb + ,doc_id dm_idb + ,ware_id dm_idb + ,snd_optype_id dm_idb + ,snd_id dm_idb + ,snd_qty dm_qty + ,rcv_optype_id bigint + ,rcv_id bigint -- nullable! ==> doc_data.id of "receiver" + ,rcv_qty numeric(12,3) + ,snd_purchase dm_cost + ,snd_retail dm_cost + ,rcv_purchase dm_cost + ,rcv_retail dm_cost + ,trn_id bigint + ,dts timestamp + ,dump_att bigint + ,dump_trn bigint +); +create index zqdistr_id on zqdistr(id); -- NON unique! +create index zqdistr_ware_sndop_rcvop on zqdistr(ware_id, snd_optype_id, rcv_optype_id); + + +recreate table zqstorned( + id dm_idb + ,doc_id dm_idb + ,ware_id dm_idb + ,snd_optype_id dm_idb + ,snd_id dm_idb + ,snd_qty dm_qty + ,rcv_optype_id dm_idb + ,rcv_id dm_idb + ,rcv_qty dm_qty + ,snd_purchase dm_cost + ,snd_retail dm_cost + ,rcv_purchase dm_cost + ,rcv_retail dm_cost + ,trn_id bigint + ,dts timestamp + ,dump_att bigint + ,dump_trn bigint +); +create index zqstorned_id on zqstorned(id); -- NON unique! +create index zqstorned_doc_id on zqstorned(doc_id); -- confirmed 16.09.2014, see s`p_lock_dependent_docs +create index zqstorned_snd_id on zqstorned(snd_id); -- confirmed 16.09.2014, see s`p_kill_qty_storno +create index zqstorned_rcv_id on zqstorned(rcv_id); -- confirmed 16.09.2014, see s`p_kill_qty_storno + +recreate table zpdistr( + id dm_idb + ,agent_id dm_idb + ,snd_optype_id dm_idb + ,snd_id dm_idb + ,snd_cost dm_qty + ,rcv_optype_id dm_idb + ,trn_id bigint + ,dump_att bigint + ,dump_trn bigint +); +create index zpdistr_id on zpdistr(id); -- NON unique! + +recreate table zpstorned( + id dm_idb + ,agent_id dm_idb + ,snd_optype_id dm_idb + ,snd_id dm_idb + ,snd_cost dm_cost + ,rcv_optype_id dm_idb + ,rcv_id dm_idb + ,rcv_cost dm_cost + ,trn_id bigint + ,dump_att bigint + ,dump_trn bigint +); +create index zpstorned_id on zpstorned(id); -- NON unique! + + + +set term ^; +create or alter procedure z_remember_view_usage ( + a_view_for_search dm_dbobj, + a_view_for_min_id dm_dbobj default null, + a_view_for_max_id dm_dbobj default null +) as + declare i smallint; + declare v_ctxn dm_ctxnv; + declare v_name dm_dbobj; +begin + + i = 1; + while (i <= 3) do -- a_view_for_search, a_view_for_min_id, a_view_for_max_id + begin + v_name = decode(i, 1, a_view_for_search, 2, a_view_for_min_id , a_view_for_max_id ); + if ( v_name is not null ) then + begin + v_ctxn = right(v_name||'_is_used', 80); + if ( rdb$get_context('USER_SESSION', v_ctxn) is null ) then + begin + if (not exists( select * from z_used_views u where u.name = :v_name )) then + begin + insert into z_used_views(name) values( :v_name ); + rdb$set_context('USER_SESSION', v_ctxn, '1' ); + end + when any do + -- ::: nb ::: do NOT use "wh`en gdscode " followed by "wh`en any": + -- the latter ("w`hen ANY") will handle ALWAYS, even if "w`hen " + -- catched it's kind of exception! + -- 1) tracker.firebirdsql.org/browse/CORE-3275 + -- "W`HEN ANY handles exceptions even if they are handled in another W`HEN section" + -- 2) sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1088890&msg=15879669 + begin + if ( not gdscode in ( 335544665,335544349 ) ) then + + -- ####### + exception; + -- ####### + -- else ==> yes, supress no_dup exception here -- + end + end + end + i = i + 1; + end + +end +^ + + +-------------------------------------------------------------------------------- + +create or alter procedure z_get_dependend_docs( + a_doc_list_id dm_idb, + a_doc_oper_id dm_idb default null -- = (for invoices which are to be 'reopened' - old_oper_id) +) returns ( + dependend_doc_id dm_idb, + dependend_doc_state dm_idb +) +as + declare v_rcv_optype_id dm_idb; +begin + -- former: s`p_get_dependend_docs; now need only for debug + if ( a_doc_oper_id is null ) then + select h.optype_id + from doc_list h + where h.id = :a_doc_list_id + into a_doc_oper_id; + + v_rcv_optype_id = decode( + a_doc_oper_id + ,2100, 3300 -- ,fn_oper_invoice_add(), fn_oper_retail_reserve() + ,1200, 2000 -- ,fn_oper_order_for_supplier(), fn_oper_invoice_get() + ,null + ); + + for + select x.dependend_doc_id, h.state_id + -- 30.12.2014: PLAN JOIN (SORT (X Q INDEX (QSTORNED_DOC_ID)), H INDEX (PK_DOC_LIST)) + -- (added field rcv_doc_id in table qstorned, now can remove join with doc_data!) + from ( + -- Checked plan 13.07.2014: + -- PLAN (Q ORDER QSTORNED_RCV_ID INDEX (QSTORNED_DOC_ID)) + select q.rcv_doc_id dependend_doc_id -- q.rcv_id dependend_doc_data_id + from v_qstorned_source q + where + q.doc_id = :a_doc_list_id -- choosen invoice which is to be re-opened + and q.snd_optype_id = :a_doc_oper_id -- fn_oper_invoice_add() + and q.rcv_optype_id = :v_rcv_optype_id --fn_oper_retail_reserve() -- in ( fn_oper_retail_reserve(), fn_oper_retail_realization() ) + group by 1 + ) x + join doc_list h on x.dependend_doc_id = h.id + into dependend_doc_id, dependend_doc_state + do + suspend; + +end + +^ -- z_get_dependend_docs + +set term ;^ + + +-------------------------------------------------------------------------------- + +create or alter view z_perf_trn as +select * from perf_log p where p.trn_id = current_transaction +; + +------------------------------------------------------------------------------- + +create or alter view z_random_bop as +select b.sort_prior as id, b.unit, b.info +from business_ops b +; + +-------------------------------------------------------------------------------- + +create or alter view v_diag_fk_uk as +-- service view for check data in FK/UNQ indices: search 'orphan' rows in FK +-- or duplicate rows in all PK/UNQ keys (suggestion by DS, 05.05.2014 18:23) +-- ::: NB ::: this view does NOT include in its reultset self-referenced tables! +with recursive +c as ( + select + rc.rdb$relation_name child_tab + ,rc.rdb$constraint_name child_fk + ,rc.rdb$index_name child_idx + ,ru.rdb$const_name_uq parent_uk + ,rp.rdb$relation_name parent_tab + ,rp.rdb$index_name parent_idx + from rdb$relation_constraints rc + join rdb$ref_constraints ru on + rc.rdb$constraint_name = ru.rdb$constraint_name + and rc.rdb$constraint_type = 'FOREIGN KEY' + join rdb$relation_constraints rp + on ru.rdb$const_name_uq = rp.rdb$constraint_name + where rc.rdb$relation_name <> rp.rdb$relation_name -- prevent from select self-ref PK/FK tables! +) +,d as( + select + 0 i + ,child_tab + ,child_fk + ,child_idx + ,parent_uk + ,parent_tab + ,parent_idx + from c c0 + -- filter tables which are NOT parents for any other tables: + where not exists( select * from c cx where cx.parent_tab= c0.child_tab ) + + union all + + select + d.i+1 + ,c.child_tab + ,c.child_fk + ,c.child_idx + ,c.parent_uk + ,c.parent_tab + ,c.parent_idx + from d + join c on d.parent_tab = c.child_tab +) +--select * from d where d.child_tab='DOC_DATA' + +,e as( + select distinct + child_tab + ,child_fk + ,child_idx + ,parent_uk + ,parent_tab + ,parent_idx + ,rsc.rdb$field_name fk_fld + ,rsp.rdb$field_name uk_fld + from d + join rdb$index_segments rsc on d.child_idx = rsc.rdb$index_name + join rdb$index_segments rsp on d.parent_idx = rsp.rdb$index_name and rsc.rdb$field_position=rsp.rdb$field_position +) +,f as( + select + e.child_tab,e.child_fk,e.parent_tab,e.parent_uk + --,e.fk_fld,e.uk_fld + ,list( 'd.'||trim(e.fk_fld)||' = m.'||trim(e.uk_fld), ' and ') jcond + ,list( 'm.'||trim(e.uk_fld)||' is null', ' and ' ) ncond + from e + group by e.child_tab,e.child_fk,e.parent_tab,e.parent_uk +) +--select * from f + +select + f.child_fk checked_constraint + ,'FK' type_of_constraint + ,'select count(*) from ' + ||trim(f.child_tab)||' d left join ' + ||trim(f.parent_tab)||' m on ' + ||f.jcond + ||' where '||f.ncond as checked_qry +from f + +UNION ALL + +select + uk_idx as checked_constraint + ,'UK' type_of_constraint + ,'select count(*) from '||trim(tab_name)||' group by '||trim(uk_lst)||' having count(*)>1' as checked_qry +from( + select tab_name,uk_idx, list( trim(uk_fld) ) uk_lst + from( + select rr.rdb$relation_name tab_name, rc.rdb$index_name uk_idx, rs.rdb$field_name uk_fld + from rdb$relation_constraints rc + join rdb$relations rr on rc.rdb$relation_name = rr.rdb$relation_name + join rdb$index_segments rs on rc.rdb$index_name = rs.rdb$index_name + where + rc.rdb$constraint_type in ('PRIMARY KEY', 'UNIQUE') + and coalesce(rr.rdb$system_flag,0)=0 + ) + group by tab_name,uk_idx +) +-- v_diag_fk_uk +; + +------------------------------------------- + +create or alter view v_diag_idx_entries as +-- source to check match of all possible counts ortder by table indices +-- and count via natural order (suggestion by DS, 05.05.2014 18:23) +select + tab_name + ,idx_name + ,cast('select count(*) from (select * from '||trim(tab_name)||' order by '||trim(idx_expr||desc_expr)||')' as varchar(255)) + as checked_qry +from( + select + tab_name + ,idx_name + ,max(iif(idx_type=1,' desc','')) desc_expr + ,list(trim(coalesce(idx_comp, idx_key))) idx_expr + from + ( + select + ri.rdb$relation_name tab_name + ,ri.rdb$index_name idx_name + ,ri.rdb$expression_source idx_comp + ,ri.rdb$index_type idx_type + ,rs.rdb$field_name idx_key + from rdb$indices ri + join rdb$relations rr on ri.rdb$relation_name = rr.rdb$relation_name + left join rdb$index_segments rs on ri.rdb$index_name=rs.rdb$index_name + where coalesce(rr.rdb$system_flag,0)=0 and rr.rdb$relation_type not in(4,5) + order by ri.rdb$relation_name, rs.rdb$index_name,rs.rdb$field_position + ) + group by + tab_name + ,idx_name +) +-- v_diag_idx_entries +; + + + +------------------------------------------------------------------------ + +create or alter view z_check_inv_vs_sup as +-- for checking: all qty in INVOICES which supplier has sent us must be +-- LESS or EQUEAL than qty which we've ORDERED to supplier before +-- This view should return records with ERRORS in data. +select + doc_id, + doc_data_id, + ware_id, + qty as doc_qty, + qty_sup, + qty_clo, + qty_clr, + qty_ord, + qty_avl, + qty_res +from v_add_invoice_to_stock v +join v_doc_detailed f on v.id=f.doc_id +where qty > qty_sup +; + + + + +-------------------------------------------------------------------------------- + +create or alter view z_clean_data as +with recursive +c as ( + select + rc.rdb$relation_name child_tab + ,rc.rdb$constraint_name child_fk + ,ru.rdb$const_name_uq parent_uk + ,rp.rdb$relation_name parent_tab + from rdb$relation_constraints rc + join rdb$ref_constraints ru on + rc.rdb$constraint_name = ru.rdb$constraint_name + and rc.rdb$constraint_type = 'FOREIGN KEY' + join rdb$relation_constraints rp + on ru.rdb$const_name_uq = rp.rdb$constraint_name + where rc.rdb$relation_name <> rp.rdb$relation_name +) +--select * from c +,d as( + select + 0 i + ,child_tab + ,child_fk + ,parent_uk + ,parent_tab + from c c0 + where not exists( select * from c cx where cx.parent_tab= c0.child_tab ) + + union all + + select + d.i+1 + ,c.child_tab + ,c.child_fk + ,c.parent_uk + ,c.parent_tab + from d + join c on d.parent_tab = c.child_tab +) +,e as( + select + i + ,child_tab + ,child_fk + ,parent_uk + ,parent_tab + --,max(i)over() mi + --,(select max(i) from d) as mi + from d +) +-- select * from e +,f as( + select distinct + 0 i + ,child_tab + from e where i=0 + + UNION DISTINCT + + select + 1 + ,child_tab + from (select child_tab from e where i > 0 order by i) + + UNION DISTINCT + + select k,parent_tab + from ( + select + 2 as k + ,parent_tab + from e + order by i desc rows 1 + ) + --- doesn`t work in 3.0 when "(select max(i) from d) as mi", see CTE `e`, 06.02.2015: + -- select 2 as k,parent_tab from e where i=mi +) +,t as( + select + rt.rdb$trigger_name trg_name -- f.child_tab, rt.rdb$trigger_name, rt.rdb$trigger_type + from f + join rdb$triggers rt on f.child_tab = rt.rdb$relation_name + where rt.rdb$system_flag=0 and rt.rdb$trigger_inactive=0 +) +select 'alter trigger '||trim(trg_name)||' inactive' sql_expr +from t +union all +select 'delete from '||trim(child_tab) +from f +union all +select 'alter trigger '||trim(trg_name)||' active' +from t +; + +---------------------- + +create or alter view z_idx_stat as +select ri.rdb$relation_name tab_name, ri.rdb$index_name idx_name, nullif(ri.rdb$statistics,0) idx_stat +from rdb$indices ri +where ri.rdb$relation_name not starting with 'RDB$' --and ri.rdb$statistics > 0 +order by 3 desc nulls first,1,2 +; + + +-------------------------------------------------------------------------------- + +create or alter view z_rules_for_qdistr as +-- 4debug +select r.mode, r.snd_optype_id, so.mcode snd_mcode, r.rcv_optype_id, ro.mcode rcv_mcode +from rules_for_qdistr r +left join optypes so on r.snd_optype_id = so.id +left join optypes ro on r.rcv_optype_id = ro.id +; + + +-------------------------------------------------------------------------------- + +create or alter view zv_doc_detailed as +-- Debug: analysis of dumped dirty data (filled by SP zdump4dbg in some critical errors) +select + h.id doc_id, + h.optype_id, + o.mcode oper, + h.base_doc_id, + d.id doc_data_id, + d.ware_id, + d.qty, + coalesce(d.cost_purchase, h.cost_purchase) cost_purchase, -- cost in purchase price + coalesce(d.cost_retail, h.cost_retail) cost_retail, -- cost in retail price + h.state_id, + h.agent_id, + d.dts_edit, + h.dts_open, + h.dts_fix, + h.dts_clos, + s.mcode state, + h.att +from zdoc_list h + join optypes o on h.optype_id = o.id + join doc_states s on h.state_id=s.id + left join zdoc_data d on h.id = d.doc_id + -- ::: NB ::: do NOT remove "left" from here otherwise performance will degrade + -- (FB will not push predicate inside view; 22.04.2014) + --LEFT join v_saldo_invnt n on d.ware_id=n.ware_id +; +-------------------------------------------------------------------------------- +create or alter view zv_saldo_invnt as +-- 21.04.2014 +-- ::: NB ::: this view can return NEGATIVE remainders in qty_xxx +-- if parallel attaches call of sp_make_invnt_saldo +-- (because of deleting rows in invnt_turnover_log in this SP) +-- !!! look at table INVNT_SALDO for actual remainders !!! +select + ng.ware_id + ,sum(o.m_qty_clo * ng.qty_diff) qty_clo + ,sum(o.m_qty_clr * ng.qty_diff) qty_clr + ,sum(o.m_qty_ord * ng.qty_diff) qty_ord + ,sum(o.m_qty_sup * ng.qty_diff) qty_sup + ,sum(o.m_qty_avl * ng.qty_diff) qty_avl + ,sum(o.m_qty_res * ng.qty_diff) qty_res + ,sum(o.m_cost_inc * ng.qty_diff) qty_inc + ,sum(o.m_cost_out * ng.qty_diff) qty_out + ,sum(o.m_cost_inc * ng.cost_diff) cost_inc + ,sum(o.m_cost_out * ng.cost_diff) cost_out + -- amount "on hand" as it seen by accounter: + ,sum(o.m_qty_avl * ng.qty_diff) + sum(o.m_qty_res * ng.qty_diff) qty_acn + -- total cost "on hand" in purchasing prices: + ,sum(o.m_cost_inc * ng.cost_diff) - sum(o.m_cost_out * ng.cost_diff) cost_acn +from zinvnt_turnover_log ng +join optypes o on ng.optype_id=o.id +group by 1 +; + +-------------------------------------------------------------------------------- + + +create or alter view z_mism_dd_qd_qs_orphans as +-- 4 debug: search only those rows in doc_data for which absent any rows in +-- qdistr and qstorned ('lite' diagnostics): +select d.doc_id,h.optype_id,d.id,d.ware_id,d.qty +from doc_data d +join doc_list h on d.doc_id = h.id +left join v_qdistr_source q on d.id=q.snd_id +left join v_qstorned_source s on d.id in(s.snd_id, s.rcv_id) +where h.optype_id<>1100 and q.id is null and s.id is null +; + +-------------------------------------------------------------------------------- + +create or alter view z_mism_dd_qd_qs_sums as +-- 4 debug: search for mismatches be`tween doc_data.qty and number of +-- records in qdistr or qstorned +select d.doc_id, d.id,d.optype_id,d.qty,d.qd_sum,coalesce(sum(qs.snd_qty),0) qs_sum +from( + select d.doc_id, d.id, d.optype_id, d.qty,coalesce(sum(qd.snd_qty),0) qd_sum + from ( + select d.doc_id, d.id, d.ware_id, iif(h.optype_id=3400, 3300, h.optype_id) as optype_id, d.qty + from doc_data d + join doc_list h on d.doc_id = h.id + ) d + inner join rules_for_qdistr p on d.optype_id = p.snd_optype_id + 0 and coalesce(p.storno_sub,1)=1 -- hash join! 3.0 only + left join v_qdistr_source qd on + qd.ware_id = d.ware_id + and qd.snd_optype_id = p.snd_optype_id + and qd.rcv_optype_id is not distinct from p.rcv_optype_id + where d.optype_id<>1100 -- client refused from order + group by d.doc_id, d.id, d.optype_id, d.qty +) d +join rules_for_qdistr p on d.optype_id = p.snd_optype_id + 0 and coalesce(p.storno_sub,1)=1 -- hash join! 3.0 only +left join v_qstorned_source qs on + d.id=qs.snd_id + and p.snd_optype_id=qs.snd_optype_id + and p.rcv_optype_id is not distinct from qs.rcv_optype_id +group by d.doc_id, d.id,d.optype_id,d.qty,d.qd_sum +having d.qty <> d.qd_sum + coalesce(sum(qs.snd_qty),0) +; + +-------------------------------------------------------------------------------- + +create or alter view z_mism_zdd_zqdzqs as +-- 4 debug: search for mismatches between doc_data.qty and number of +-- records in qdistr or qstorned +select d.doc_id, d.id,d.optype_id,d.qty,d.qd_sum,coalesce(sum(qs.snd_qty),0) qs_sum +from( + select d.doc_id, d.id, d.optype_id, d.qty,coalesce(sum(qd.snd_qty),0) qd_sum + from ( + select d.doc_id, d.id, d.ware_id, iif(d.optype_id=3400, 3300, d.optype_id) as optype_id, d.qty + from zdoc_data d + ) d + inner join rules_for_qdistr p on d.optype_id=p.snd_optype_id and coalesce(p.storno_sub,1)=1 + left join zqdistr qd on + qd.ware_id = d.ware_id + and qd.snd_optype_id = p.snd_optype_id + and qd.rcv_optype_id is not distinct from p.rcv_optype_id + where d.optype_id<>1100 -- client refused from order + group by d.doc_id, d.id, d.optype_id, d.qty +) d +inner join rules_for_qdistr p on d.optype_id=p.snd_optype_id and coalesce(p.storno_sub,1)=1 +left join zqstorned qs on + d.id=qs.snd_id + and p.snd_optype_id=qs.snd_optype_id + and p.rcv_optype_id is not distinct from qs.rcv_optype_id +group by d.doc_id, d.id,d.optype_id,d.qty,d.qd_sum +having d.qty <> d.qd_sum + coalesce(sum(qs.snd_qty),0) +; + +-------------------------------------------------------------------------------- +create or alter view z_qdqs as +-- Debug: analysis of dumped dirty data (filled by SP zdump4dbg in some critical errors) +select + cast(q.src as varchar(8)) as src, + q.id, + q.ware_id, + q.snd_optype_id, + cast(so.mcode as varchar(3)) snd_op, + q.doc_id as snd_doc_id, + sh.agent_id as snd_agent, + q.snd_id, + q.snd_qty, + q.snd_purchase, + q.snd_retail, + q.rcv_optype_id, + cast(ro.mcode as varchar(3)) rcv_op, + d.doc_id as rcv_doc_id, + rh.agent_id as rcv_agent, + q.rcv_id, + q.rcv_qty, + q.rcv_purchase, + q.rcv_retail, + q.trn_id, + q.dts +from ( + select 'qdistr' src,q.* + from qdistr q + union all + select 'qstorned', s.* + from qstorned s +) q +left join doc_data d on q.rcv_id = d.id +left join optypes so on q.snd_optype_id = so.id +left join doc_list sh on q.doc_id=sh.id +left join optypes ro on q.rcv_optype_id = ro.id +left join doc_list rh on d.doc_id=rh.id +order by q.src, q.doc_id, q.id +; + +------------------------------- + +create or alter view z_zqdzqs as +-- Debug: analysis of dumped dirty data (filled by SP zdump4dbg in some critical errors) +select + q.src, + q.id, + q.ware_id, + q.snd_optype_id, + left(so.mcode,3) snd_op, + q.doc_id as snd_doc_id, + q.snd_id, + q.snd_qty, + q.rcv_optype_id, + left(ro.mcode,3) rcv_op, + d.doc_id as rcv_doc_id, + q.rcv_id, + q.rcv_qty, + q.trn_id, + q.dts, + q.dump_att, + q.dump_trn +from ( + select 'zqdistr' src,q.* + from zqdistr q + union all + select 'zqstorned', s.* + from zqstorned s +) q +left join zdoc_data d on q.rcv_id = d.id +left join optypes so on q.snd_optype_id = so.id +left join optypes ro on q.rcv_optype_id = ro.id +order by q.src, q.doc_id, q.id +; +------------------------------- + +create or alter view z_pdps as +-- Debug: analysis of dumped dirty data (filled by SP zdump4dbg in some critical errors) +select + cast(p.src as varchar(8)) as src, + p.id, + p.agent_id, + p.snd_optype_id, + cast(so.mcode as varchar(3)) snd_op, + p.snd_id, + p.snd_cost, + p.rcv_optype_id, + cast(ro.mcode as varchar(3)) rcv_op, + p.rcv_id, + p.rcv_cost, + p.trn_id +from ( + select 'pdistr' src,p.id,p.agent_id,p.snd_optype_id,p.snd_id,p.snd_cost,p.rcv_optype_id, cast(null as bigint) as rcv_id, cast(null as numeric(12,2)) as rcv_cost, p.trn_id + from pdistr p + union all + select 'pstorned', s.id, s.agent_id, s.snd_optype_id, s.snd_id, s.snd_cost, s.rcv_optype_id, s.rcv_id, s.rcv_cost, s.trn_id + from pstorned s +) p +left join optypes so on p.snd_optype_id = so.id +left join optypes ro on p.rcv_optype_id = ro.id +order by p.src, p.id -- p.agent_id, p.rcv_id, p.id +; +------------------------------ + +create or alter view z_zpdzps as +-- Debug: analysis of dumped dirty data (filled by SP zdump4dbg in some critical errors) +select + p.src, + p.id, + p.agent_id, + p.snd_optype_id, + left(so.mcode,3) snd_op, + p.snd_id, + p.snd_cost, + p.rcv_optype_id, + left(ro.mcode,3) rcv_op, + p.rcv_id, + p.rcv_cost, + p.trn_id, + p.dump_att, + p.dump_trn +from ( + select 'zpdistr' src,p.id,p.agent_id,p.snd_optype_id,p.snd_id,p.snd_cost,p.rcv_optype_id, + cast(null as bigint) as rcv_id, cast(null as numeric(12,2)) as rcv_cost, + p.trn_id, p.dump_att, p.dump_trn + from zpdistr p + union all + select 'zpstorned', s.id, s.agent_id, s.snd_optype_id, s.snd_id, s.snd_cost, s.rcv_optype_id, + s.rcv_id, s.rcv_cost, + s.trn_id, s.dump_att, s.dump_trn + from zpstorned s +) p +left join optypes so on p.snd_optype_id = so.id +left join optypes ro on p.rcv_optype_id = ro.id +order by p.src, p.agent_id, p.rcv_id, p.id +; + +-------------------------------------------------------------------------------- + +create or alter view z_slow_get_random_id as +select + substring(pg.info from 1 for coalesce(nullif(position(';',pg.info)-1,-1),31) ) mode, + pg.elapsed_ms, + min(pg.elapsed_ms) ms_min, + max(pg.elapsed_ms) ms_max, + count(*) cnt +from perf_log pg +where pg.unit='fn_get_random_id' and pg.elapsed_ms>=3000 +group by 1,2 +; + + +-------------------------------------------------------------------------------- + +create or alter view z_get_min_max_id as +-- 08.02.2015: debug view for efficiency estimation of 'boundary' views which +-- is used for obtaining MIN and MAX ids before subsequent random selection. +-- (v_min/max_id_clo_ord, v_min/max_id_ord_sup etc) +-- Registering in perf_log is in fn_get_random_id. +select + g.unit + ,count(iif( coalesce(g.fb_gdscode,0)=0, 1, null ) ) cnt_ok + ,count(*) cnt_all + ,avg(g.elapsed_ms) avg_time + ,min(g.elapsed_ms) min_time + ,max(g.elapsed_ms) max_time +from perf_log g +where +( + g.unit starting with 'v_min_id' + or + g.unit starting with 'v_max_id' +) +group by 1 +order by right(g.unit,6),left(g.unit,4) desc +; + +-------------------------------------------------------------------------------- + +create or alter view z_doc_data_oper_cnt as +-- 19.07.2014, for analyze results of init data population alg +select h.optype_id,o.name op_name,count(*) doc_data_cnt +from doc_list h +join optypes o on h.optype_id=o.id +join doc_data d on h.id=d.doc_id +group by 1,2 +; + + +-------------------------------------------------------------------------------- + +create or alter view z_doc_list_oper_cnt as +-- 19.07.2014, for analyze results of init data population alg +select h.optype_id,o.name op_name, count(*) doc_list_cnt +from doc_list h +join optypes o on h.optype_id=o.id +group by 1,2 +; + +-------------------------------------------------------------------------------- + +create or alter view z_invoices_to_be_adopted as +-- 4 debug (performance of sp_add_invoice_to_stock) +select + invoice_id, total_rows, total_qty + ,min(p.clo_agent_id) agent_min_id + ,max(p.clo_agent_id) agent_max_id + ,count(distinct p.clo_agent_id) agent_diff_cnt +from ( + select h.id invoice_id, count(*) total_rows, sum(qty) total_qty + from doc_list h + join doc_data d on h.id=d.doc_id + where h.optype_id = 2000 -- fn_oper_invoice_get + group by 1 +) x +left join sp_get_clo_for_invoice(x.invoice_id) p on 1=1 +group by invoice_id, total_rows, total_qty +order by total_rows desc, total_qty desc +; + +-------------------------------------------------------------------------------- + +create or alter view z_invoices_to_be_cancelled as +-- 4 debug (performance of s`p_cancel_adding_invoice) +select h.id invoice_id, count(*) total_rows, sum(qty) total_qty +from doc_list h +join doc_data d on h.id=d.doc_id +where h.optype_id = 2100 -- fn_oper_invoice_add +group by 1 +order by 2 desc +; + +-------------------------------------------------------------------------------- + +create or alter view z_ord_inc_res_dependencies as +-- 17.07.2014: get all dependencies (links) b`etween +-- supplier orders (take first 5), invoices and customer reserves +with +s as( + select v.ord_id, count(*) ord_rows, sum(d0.qty) ord_qty_sum + from ( select first 5 v.id as ord_id from v_cancel_supplier_order v ) v + join doc_data d0 on v.ord_id = d0.doc_id + group by v.ord_id +) +,i as( + select + s.ord_id + ,s.ord_rows + ,s.ord_qty_sum + ,p1.dependend_doc_id as inv_id + ,count(*) inv_rows + ,sum(di.qty) inv_qty_sum + from s + left join z_get_dependend_docs( s.ord_id, 1200 ) p1 on 1=1 -- 1200=fn_oper_order_for_supplier() + left join doc_data di on p1.dependend_doc_id = di.doc_id + group by + s.ord_id + ,s.ord_rows + ,s.ord_qty_sum + ,p1.dependend_doc_id +) +select + i.ord_id + ,i.ord_rows + ,i.ord_qty_sum + ,i.inv_id + ,i.inv_rows + ,i.inv_qty_sum + ,p2.dependend_doc_id as res_id + ,count(*) res_rows + ,sum(dr.qty) res_qty_sum +from i +left join z_get_dependend_docs( i.inv_id, 2100 ) p2 on 1=1-- 2100=fn_oper_invoice_add() +left join doc_data dr on p2.dependend_doc_id = dr.doc_id +group by + i.ord_id + ,i.ord_rows + ,i.ord_qty_sum + ,i.inv_id + ,i.inv_rows + ,i.inv_qty_sum + ,p2.dependend_doc_id +; + + + +--------------------------------------- + +set term ^; + +create or alter procedure srv_diag_fk_uk +returns( + checked_constraint type of column rdb$relation_constraints.rdb$constraint_name, + type_of_constraint type of column v_diag_fk_uk.type_of_constraint, + failed_rows int +) +as + declare v_checked_qry varchar(8190); +begin + -- obtain text of queries for checking data in tables which have + -- FK and PK/UNQ constraints; counts rows from these tables where + -- violations of FK or PK/UNQ occur: 'orphan' FK, duplicates in PK/UNQ + for + select v.checked_constraint, v.type_of_constraint, cast(v.checked_qry as varchar(8190)) + from v_diag_fk_uk v + into checked_constraint, type_of_constraint, v_checked_qry + do begin + execute statement(v_checked_qry) into failed_rows; -- this must be always 'select count(*) from ...' + if (failed_rows > 0) then suspend; + end +end + +^ -- srv_diag_fk_uk + +---------------------------------------------------------------------- + +create or alter procedure srv_diag_idx_entries +returns( + tab_name type of column rdb$relations.rdb$relation_name, + idx_name type of column rdb$indices.rdb$index_name, + nat_count bigint, + idx_count bigint, + failed_rows bigint +) +as + declare v_checked_qry varchar(8190); + declare v_nat_stt varchar(255); + declare rn bigint; + declare v_prev_tab type of column v_diag_idx_entries.tab_name = ''; +begin + for + select v.tab_name, v.idx_name, v.checked_qry + from v_diag_idx_entries v + where v.checked_qry not containing 'DOC_NUMB' -- temply, smth wrong with coll num-sort=1 and unique index: FB uses plan natural instead of that index, see: http://www.sql.ru/forum/1093394/select-from-t1-order-by-s-ne-uzaet-uniq-indeks-esli-s-utf8-coll-numeric-sort-1 + into tab_name, idx_name, v_checked_qry + do begin + if ( v_prev_tab is distinct from tab_name ) then begin + v_nat_stt = 'select count(*) from '||tab_name; + execute statement ( v_nat_stt ) into nat_count; + v_prev_tab = tab_name; + end + execute statement(v_checked_qry) into idx_count; -- this must be always 'select count(*) from ...' + if ( nat_count <> idx_count ) then begin + failed_rows = nat_count - idx_count; + suspend; + end + end +end + +^ -- srv_diag_idx_entries + +---------------------------------------------------------------------- + +create or alter procedure srv_diag_qty_distr +returns( + doc_id dm_idb, + optype_id dm_idb, + rcv_optype_id dm_idb, + doc_data_id dm_idb, + qty dm_qty, + qdqs_sum dm_qty, + qdistr_q dm_qty, + qstorned_q dm_qty +) as +begin + -- Looks for mismatches between records count in v_qdistr + v_qstorned and doc_data + -- Must be run ONLY in TIL = SNAPSHOT! + -- ################################### + -- Check that current Tx run in NO wait or with lock_timeout. + -- Otherwise raise error: performance degrades almost to zero. + execute procedure sp_check_nowait_or_timeout; + + for + select + b.doc_id, + b.optype_id, + b.rcv_optype_id, + b.id, + b.qty, + b.qdistr_q + coalesce(sum(qs.snd_qty),0) qdqs_sum, + b.qdistr_q, + coalesce(sum(qs.snd_qty),0) qstorned_q + from ( + select d.doc_id, h.optype_id, r.rcv_optype_id, d.id, d.qty -- + ,coalesce(sum(qd.snd_qty),0) qdistr_q + from doc_data d + join doc_list h on d.doc_id = h.id + join rules_for_qdistr r on h.optype_id = r.snd_optype_id + left join v_qdistr_source qd on + d.ware_id = qd.ware_id + and qd.snd_optype_id = r.snd_optype_id + and qd.rcv_optype_id is not distinct from r.rcv_optype_id + group by d.doc_id, h.optype_id, r.rcv_optype_id, d.id, d.qty + ) b + left join v_qstorned_source qs on b.id = qs.snd_id and b.optype_id=qs.snd_optype_id and b.rcv_optype_id=qs.rcv_optype_id + group by + b.doc_id, + b.optype_id, + b.rcv_optype_id, + b.id, + b.qty, + b.qdistr_q + having b.qty <> b.qdistr_q + coalesce(sum(qs.snd_qty),0) + into + doc_id, + optype_id, + rcv_optype_id, + doc_data_id, + qty, + qdqs_sum, + qdistr_q, + qstorned_q + do suspend; +end + +^ -- srv_diag_qty_distr + +-------------------------------------------------------------------------------- +-- ############# D E B U G: D U M P D I R T Y D A T A ########### +-------------------------------------------------------------------------------- + +create or alter procedure zdump4dbg( + a_doc_list_id bigint default null, + a_doc_data_id bigint default null, + a_ware_id bigint default null +) +as + declare v_catch_bitset bigint; + declare id bigint; + declare trn_id bigint; + declare snd_optype_id bigint; + declare rcv_optype_id bigint; + declare qty numeric(12,3); + declare dup_cnt int; + declare qty_bak numeric(12,3); + declare snd_qty numeric(12,3); + declare rcv_qty numeric(12,3); + + declare snd_id bigint; + declare rcv_id bigint; + declare doc_id bigint; + declare ware_id bigint; + declare optype_id bigint; + declare agent_id bigint; + declare state_id bigint; + declare dts_open timestamp; + declare dts_fix timestamp; + declare dts_clos timestamp; + declare dts_edit timestamp; + declare base_doc_id bigint; + declare acn_type type of dm_account_type; + + declare dependend_doc_id bigint; + declare dependend_doc_state bigint; + declare dependend_doc_dbkey dm_dbkey; + declare dependend_doc_agent_id bigint; + declare base_doc_qty numeric(12,3); + declare dependend_doc_qty numeric(12,3); + + declare cost_purchase numeric(12,2); + declare cost_retail numeric(12,2); + declare snd_purchase numeric(12,2); + declare snd_retail numeric(12,2); + declare rcv_purchase numeric(12,2); + declare rcv_retail numeric(12,2); + declare snd_cost numeric(12,2); + declare rcv_cost numeric(12,2); + + declare v_curr_att int; + declare v_curr_trn int; + declare i int; + declare v_step int = 1000; + declare v_max_id bigint; + declare v_perf_semaphore_id bigint; + declare v_perf_progress_id bigint; + declare v_this dm_dbobj = 'zdump4dbg'; +begin + -- See oltp_main_filling.sql for definition of bitset var `QMISM_VERIFY_BITSET`: + -- bit#0 := 1 ==> perform calls of srv_catch_qd_qs_mism in doc_list_aiud => sp_add_invnt_log + -- in order to register mismatches b`etween doc_data.qty and total number of rows + -- in v_qdistr_source + v_qstorned_source for doc_data.id + -- bit#1 := 1 ==> perform calls of SRV_CATCH_NEG_REMAINDERS from INVNT_TURNOVER_LOG_AI + -- (instead of totalling turnovers to `invnt_saldo` table) + -- bit#2 := 1 ==> allow dump dirty data into z-tables for analysis, see sp zdump4dbg, in case + -- when some 'bad exception' occurs (see ctx var `HALT_TEST_ON_ERRORS`) + v_catch_bitset = cast(rdb$get_context('USER_SESSION','QMISM_VERIFY_BITSET') as bigint); + if ( bin_and( v_catch_bitset, 4 ) = 0 ) -- dump dirty data DISABLED + then + --#### + exit; + --#### + + v_curr_att = current_connection; + v_curr_trn = current_transaction; + v_perf_semaphore_id = null; + + -- record with EMPTY is added by 1run_oltp_emul.bat on every new start of test, + -- it always contains EMPTY string in field `info` at this moment: + select id from perf_log g + where g.unit = 'dump_dirty_data_semaphore' + order by id + rows 1 + into v_perf_semaphore_id; + if ( v_perf_semaphore_id is null ) then + begin + exit; + end + + in autonomous transaction do + update perf_log g set + g.info = 'start, tra_'||:v_curr_trn, + dts_beg = 'now', + dts_end = null + where g.id = :v_perf_semaphore_id + and g.dts_beg is null; + + -- jump to when-section if lock_conflict, see below -- + if ( row_count = 0 ) then -- ==> this job was already done by another attach + begin + exit; + end + + -- record for show progress in case of watching from IBE etc: + in autonomous transaction do + insert into perf_log(unit, dts_beg) values( 'dump_dirty_data_progress', current_timestamp ) + returning id into v_perf_progress_id; + + -- dumps dirty data into tables for further analysis before halt (4debug only) + ---------------------------------------------------------------------------- + for + select c.id,c.snd_optype_id,c.rcv_optype_id,c.qty,c.dup_cnt,c.qty_bak + from tmp$shopping_cart c + --as cursor ct + into id,snd_optype_id,rcv_optype_id,qty,dup_cnt,qty_bak + do + in autonomous transaction do + insert into ztmp_shopping_cart(id, snd_optype_id, rcv_optype_id, qty, dup_cnt, qty_bak) + values( :id, :snd_optype_id, :rcv_optype_id, :qty, :dup_cnt, :qty_bak) + ; + ---------------------------------------------------------------------------- + for + select + base_doc_id,dependend_doc_id,dependend_doc_state,dependend_doc_dbkey + ,dependend_doc_agent_id,ware_id,base_doc_qty,dependend_doc_qty + from tmp$dep_docs + into + base_doc_id,dependend_doc_id,dependend_doc_state,dependend_doc_dbkey + ,dependend_doc_agent_id,ware_id,base_doc_qty,dependend_doc_qty + do + in autonomous transaction do + insert into ztmp_dep_docs( + base_doc_id,dependend_doc_id,dependend_doc_state,dependend_doc_dbkey + ,dependend_doc_agent_id,ware_id,base_doc_qty,dependend_doc_qty + ,dump_att + ,dump_trn + ) + values( + :base_doc_id,:dependend_doc_id,:dependend_doc_state,:dependend_doc_dbkey + ,:dependend_doc_agent_id,:ware_id,:base_doc_qty,:dependend_doc_qty + ,:v_curr_att + ,:v_curr_trn + ) + ; + + ---------------------------------------------------------------------------- + -- dump dirty data from ### d o c _ l i s t ### + select 0, max(id) from doc_list into i,v_max_id; -- for verbosing in perf_log.stack + for + select + id + ,optype_id + ,agent_id + ,state_id + ,dts_open + ,dts_fix + ,dts_clos + ,base_doc_id + ,acn_type + ,cost_purchase + ,cost_retail + from doc_list h + where h.id = :a_doc_list_id or :a_doc_list_id is null + into + :id + ,:optype_id + ,:agent_id + ,:state_id + ,:dts_open + ,:dts_fix + ,:dts_clos + ,:base_doc_id + ,:acn_type + ,:cost_purchase + ,:cost_retail + do + begin + in autonomous transaction do + insert into zdoc_list( + id + ,optype_id + ,agent_id + ,state_id + ,dts_open + ,dts_fix + ,dts_clos + ,base_doc_id + ,acn_type + ,cost_purchase + ,cost_retail + ) + values( + :id + ,:optype_id + ,:agent_id + ,:state_id + ,:dts_open + ,:dts_fix + ,:dts_clos + ,:base_doc_id + ,:acn_type + ,:cost_purchase + ,:cost_retail + ); + if ( mod(i, v_step) = 0 ) then + in autonomous transaction do + update perf_log g set g.stack = 'doc_list: id='||:id||', max='||:v_max_id + where g.id = :v_perf_progress_id; + i = i + 1; + + end + + ---------------------------------------------------------------------------- + -- dump dirty data from ### d o c _ d a t a ### + select 0, max(id) from doc_data into i,v_max_id; -- for verbosing in perf_log.stack + for + select + id + ,doc_id + ,ware_id + ,qty + ,cost_purchase + ,cost_retail + ,dts_edit + from doc_data d + where d.id between coalesce(:a_doc_data_id, -9223372036854775807) and coalesce(:a_doc_data_id, 9223372036854775807) + and + d.ware_id between coalesce(:a_ware_id, -9223372036854775807) and coalesce(:a_ware_id, 9223372036854775807) + --as cursor cd + into + id + ,doc_id + ,ware_id + ,qty + ,cost_purchase + ,cost_retail + ,dts_edit + do + begin + in autonomous transaction do + insert into zdoc_data( + id + ,doc_id + ,ware_id + ,qty + ,cost_purchase + ,cost_retail + ,dts_edit + ,dump_att + ,dump_trn + ) + values( + :id + ,:doc_id + ,:ware_id + ,:qty + ,:cost_purchase + ,:cost_retail + ,:dts_edit + ,:v_curr_att + ,:v_curr_trn + ); + if ( mod(i, v_step) = 0 ) then + in autonomous transaction do + update perf_log g set g.stack = 'doc_data: id='||:id||', max='||:v_max_id + where g.id = :v_perf_progress_id; + i = i + 1; + end + ---------------------------------------------------------------------------- + -- 27.06.2014 dump dirty data from ### q d i s t r ### + select 0, max(id) from v_qdistr_source into i,v_max_id; -- for verbosing in perf_log.stack + for + select + id + ,doc_id + ,ware_id + ,snd_optype_id + ,snd_id + ,snd_qty + ,rcv_optype_id + ,rcv_id + ,rcv_qty + ,snd_purchase + ,snd_retail + ,rcv_purchase + ,rcv_retail + ,trn_id + ,dts + from v_qdistr_source d + where d.ware_id between coalesce(:a_ware_id, -9223372036854775807) and coalesce(:a_ware_id, 9223372036854775807) + --as cursor cq + into + id + ,doc_id + ,ware_id + ,snd_optype_id + ,snd_id + ,snd_qty + ,rcv_optype_id + ,rcv_id + ,rcv_qty + ,snd_purchase + ,snd_retail + ,rcv_purchase + ,rcv_retail + ,trn_id + ,dts_edit + do + begin + in autonomous transaction do + insert into zqdistr ( + id + ,doc_id + ,ware_id + ,snd_optype_id + ,snd_id + ,snd_qty + ,rcv_optype_id + ,rcv_id + ,rcv_qty + ,snd_purchase + ,snd_retail + ,rcv_purchase + ,rcv_retail + ,trn_id + ,dts + ,dump_att + ,dump_trn + ) + values( + :id + ,:doc_id + ,:ware_id + ,:snd_optype_id + ,:snd_id + ,:snd_qty + ,:rcv_optype_id + ,:rcv_id + ,:rcv_qty + ,:snd_purchase + ,:snd_retail + ,:rcv_purchase + ,:rcv_retail + ,:trn_id + ,:dts_edit + ,:v_curr_att + ,:v_curr_trn + ); + if ( mod(i, v_step) = 0 ) then + in autonomous transaction do + update perf_log g set g.stack = 'v_qdistr_source: id='||:id||', max='||:v_max_id + where g.id = :v_perf_progress_id; + i = i + 1; + end + ---------------------------------------------------------------------------- + -- 27.06.2014 dump dirty data from ### q s t o r n e d ### + select 0, max(id) from v_qstorned_source into i,v_max_id; -- for verbosing in perf_log.stack + for + select + id + ,doc_id + ,ware_id + ,snd_optype_id + ,snd_id + ,snd_qty + ,rcv_optype_id + ,rcv_id + ,rcv_qty + ,snd_purchase + ,snd_retail + ,rcv_purchase + ,rcv_retail + ,trn_id + ,dts + from v_qstorned_source d + where d.ware_id between coalesce(:a_ware_id, -9223372036854775807) and coalesce(:a_ware_id, 9223372036854775807) + into + id + ,doc_id + ,ware_id + ,snd_optype_id + ,snd_id + ,snd_qty + ,rcv_optype_id + ,rcv_id + ,rcv_qty + ,snd_purchase + ,snd_retail + ,rcv_purchase + ,rcv_retail + ,trn_id + ,dts_edit + do + begin + in autonomous transaction do + insert into zqstorned( + id + ,doc_id + ,ware_id + ,snd_optype_id + ,snd_id + ,snd_qty + ,rcv_optype_id + ,rcv_id + ,rcv_qty + ,snd_purchase + ,snd_retail + ,rcv_purchase + ,rcv_retail + ,trn_id + ,dts + ,dump_att + ,dump_trn + ) + values( + :id + ,:doc_id + ,:ware_id + ,:snd_optype_id + ,:snd_id + ,:snd_qty + ,:rcv_optype_id + ,:rcv_id + ,:rcv_qty + ,:snd_purchase + ,:snd_retail + ,:rcv_purchase + ,:rcv_retail + ,:trn_id + ,:dts_edit + ,:v_curr_att + ,:v_curr_trn + ); + if ( mod(i, v_step) = 0 ) then + in autonomous transaction do + update perf_log g set g.stack = 'v_qstorned_source: id='||:id||', max='||:v_max_id + where g.id = :v_perf_progress_id; + i = i + 1; + end + --------------------------------------------------------------------------- + -- 04.07.2014 dump dirty data from ### p d i s t r, p s t o r n e d ### + select 0, max(id) from pdistr into i,v_max_id; -- for verbosing in perf_log.stack + for + select + id + ,agent_id + ,snd_optype_id + ,snd_id + ,snd_cost + ,rcv_optype_id + ,trn_id + from pdistr + into + id + ,agent_id + ,snd_optype_id + ,snd_id + ,snd_cost + ,rcv_optype_id + ,trn_id + do + begin + in autonomous transaction do + insert into zpdistr( + id + ,agent_id + ,snd_optype_id + ,snd_id + ,snd_cost + ,rcv_optype_id + ,trn_id + ,dump_att + ,dump_trn + ) + values( + :id + ,:agent_id + ,:snd_optype_id + ,:snd_id + ,:snd_cost + ,:rcv_optype_id + ,:trn_id + ,:v_curr_att + ,:v_curr_trn + ); + if ( mod(i, v_step) = 0 ) then + in autonomous transaction do + update perf_log g set g.stack = 'pdistr: id='||:id||', max='||:v_max_id + where g.id = :v_perf_progress_id; + i = i + 1; + end + + ---------------------------------------------------------------------------- + select 0, max(id) from pstorned into i,v_max_id; -- for verbosing in perf_log.stack + for + select + id + ,agent_id + ,snd_optype_id + ,snd_id + ,snd_cost + ,rcv_optype_id + ,rcv_id + ,rcv_cost + ,trn_id + from pstorned + into + id + ,agent_id + ,snd_optype_id + ,snd_id + ,snd_cost + ,rcv_optype_id + ,rcv_id + ,rcv_cost + ,trn_id + do + begin + in autonomous transaction do + insert into zpstorned( + id + ,agent_id + ,snd_optype_id + ,snd_id + ,snd_cost + ,rcv_optype_id + ,rcv_id + ,rcv_cost + ,trn_id + ,dump_att + ,dump_trn + ) + values( + :id + ,:agent_id + ,:snd_optype_id + ,:snd_id + ,:snd_cost + ,:rcv_optype_id + ,:rcv_id + ,:rcv_cost + ,:trn_id + ,:v_curr_att + ,:v_curr_trn + ); + if ( mod(i, v_step) = 0 ) then + in autonomous transaction do + update perf_log g set g.stack = 'pstorned: id='||:id||', max='||:v_max_id + where g.id = :v_perf_progress_id; + i = i + 1; + end + + in autonomous transaction do + begin + update perf_log g + set g.info = 'finish, tra_'||:v_curr_trn, + g.dts_end = 'now' + --stack = fn_get_stack(1) + where g.id = :v_perf_semaphore_id; + delete from perf_log g where g.id = :v_perf_progress_id; + end + +when any do + begin + -- nop: supress ANY exception! We now dump dirty data due to abnormal case! -- + end +end + +^ -- zdump4dbg + +set term ;^ + + +set list on; +set echo off; +select 'oltp_misc_debug.sql finish at ' || current_timestamp as msg from rdb$database; +set list off; + + +-- ################################# +-- End of script oltp_misc_debug.sql // ### O P T I O N A L ### +-- Next run: oltp_split_heavy_tabs_0 | 1.sql - depending on config parameter 'create_with_split_heavy_tabs' +-- ################################# + +-- ##################################### +-- Begin of script oltp_split_heavy_tabs_1.sql +-- ##################################### +-- ::: NB ::: This script is COMMON for both FB 2.5 and 3.0 and should be called +-- after oltp_main_filling.sql and oltp_misc_debug.sql + +-- run: isql /3333:oltp30 -i oltp_split_heavy_tabs_1.sql | sed "s/[ ]*$//" 1>log.tmp + +set list on; +set echo off; +select 'oltp_split_heavy_tabs_1.sql start at ' || current_timestamp as msg from rdb$database; +set list off; + +set echo off; + +set term ^; + +create or alter procedure tmp_init_autogen_qdistr_tables +as + declare v_ddl_const varchar(1024); + + declare v_idx_expr1 varchar(1024); + declare v_idx_expr2 varchar(1024); + declare v_idx_suff1 varchar(31); + declare v_idx_suff2 varchar(31); + declare v_ddl_qdidx1 varchar(1024); + declare v_ddl_qdidx2 varchar(1024); + + declare v_qd_table varchar(31); + declare v_qd_suffix varchar(31); + declare v_ddl_qdistr varchar(1024); + declare v_id bigint; + declare v_build_with_qd_compound_ordr varchar(31); -- 'most_selective_first' or 'least_selective_first' + declare v_make_separate_qd_idx smallint; +begin + + -- Called from 1build_oltp_emul.bat when config setting create_with_split_heavy_tabs = 1, see: + -- echo execute procedure tmp_init_autogen_qdistr_tables; >> %...% + + v_ddl_const = ' + id dm_idb not null + ,doc_id dm_idb -- denorm for speed, also 4debug + ,ware_id dm_idb + ,snd_optype_id dm_ids -- denorm for speed + ,snd_id dm_idb -- ==> doc_data.id of "sender" + ,snd_qty dm_qty + ,rcv_doc_id bigint -- 30.12.2014, always null, for some debug views + ,rcv_optype_id dm_ids + ,rcv_id bigint -- nullable! ==> doc_data.id of "receiver" + ,rcv_qty numeric(12,3) + ,snd_purchase dm_cost + ,snd_retail dm_cost + ,rcv_purchase dm_cost + ,rcv_retail dm_cost + ,trn_id bigint default current_transaction + ,dts timestamp default ''now'' + '; + + + -- This row is created in 1run_oltp_emul.bat, in sub-routine "make_db_objects": + -- Value is defined by config parameter create_with_split_heavy_tabs = 0 | 1. + select s.svalue + from settings s + where s.working_mode='COMMON' and s.mcode='BUILD_WITH_SEPAR_QDISTR_IDX' + into v_make_separate_qd_idx; + + -- This row is created in 1run_oltp_emul.bat, in sub-routine "make_db_objects": + -- Value is defined by config parameter create_with_compound_columns_order = 'most_selective_first' or 'least_selective_first' + select s.svalue + from settings s + where s.working_mode='COMMON' and s.mcode='BUILD_WITH_QD_COMPOUND_ORDR' + into v_build_with_qd_compound_ordr; + + v_idx_expr1 = ''; + v_idx_expr2 = ''; + -- 24.10.2015: do NOT remove 'snd_optype_id' and 'rcv_optype_id' from index key + -- otherwise excessive index scans will occur in each XQD* table even if it has no + -- such key. See SP srv_find_qd_qs_mism which is called after each document creation + -- (this SP, in turn, is called from doc_list_aiud trigger when QMISM_VERIFY_BITSET = 1, + -- see oltp_main_filling.sql). + -- See also sp_get_clo_for_invoice - there is query that search only for ware_id, w/o snd_id! + if ( v_make_separate_qd_idx = 1 ) then + begin + if ( upper(v_build_with_qd_compound_ordr) = upper('least_selective_first') ) then + begin + v_idx_expr1 = '(snd_optype_id, rcv_optype_id, ware_id)'; -- do NOT remove snd_optype & rcv_optype! + v_idx_expr2 = '(snd_id)'; + v_idx_suff1 = 'sop_rop_ware'; + v_idx_suff2 = 'snd'; + end + else -- 'most_selective_first' + begin + v_idx_expr1 = '(ware_id, snd_optype_id, rcv_optype_id)'; -- do NOT remove snd_optype & rcv_optype! + v_idx_expr2 = '(snd_id)'; + v_idx_suff1 = 'ware_sop_rop'; + v_idx_suff2 = 'snd'; + end + end + else + begin + if ( upper(v_build_with_qd_compound_ordr) = upper('least_selective_first') ) then + begin + v_idx_expr1 = '(snd_optype_id, rcv_optype_id, ware_id, snd_id)'; -- do NOT remove snd_optype & rcv_optype! + v_idx_suff1 = 'sop_rop_ware_snd'; + end + else -- 'most_selective_first' + begin + v_idx_expr1 = '(ware_id, snd_optype_id, rcv_optype_id, snd_id)'; -- do NOT remove snd_optype & rcv_optype! + v_idx_suff1 = 'ware_sop_rop_snd'; + end + end + + for + select '' || q.snd_optype_id || '_' || q.rcv_optype_id + from rules_for_qdistr q + where q.snd_optype_id is not null + into v_qd_suffix --------------------------- '1000_1200'; '1200_2000' etc + do begin + v_qd_table = 'xqd_' || v_qd_suffix; + v_ddl_qdistr = 'recreate table ' || v_qd_table || '(' || v_ddl_const || ')'; + + v_ddl_qdidx1 = 'create index ' || v_qd_table || '_' || v_idx_suff1 || ' on ' || v_qd_table || v_idx_expr1; + v_ddl_qdidx2 = 'create index ' || v_qd_table || '_' || v_idx_suff2 || ' on ' || v_qd_table || v_idx_expr2; + + in autonomous transaction do + begin + execute statement v_ddl_qdistr; + if ( not v_ddl_qdidx1 = '' ) then execute statement v_ddl_qdidx1; + if ( not v_ddl_qdidx2 = '' ) then execute statement v_ddl_qdidx2; + if ( v_qd_suffix = '1000_3300' ) then -- 13.11.2015: make v_min_id_clo_res much faster + execute statement 'create index xqd_1000_3300_doc on xqd_1000_3300(doc_id)'; + + end + end + if ( v_ddl_qdistr is null ) then + -- This script should be called ***AFTER*** oltp_main_filling.sql which does fill table 'optypes'. + -- Probably this table currently is empty! + exception ex_record_not_found; + --'required record not found, datasource: @1, key: @2'; + +end -- tmp_init_autogen_qdistr_tables + +^ +set term ;^ + +set term ^; + +create or alter procedure tmp_init_autogen_qstorn_tables +as + declare v_ddl_const varchar(1024); + declare v_idx_expr1 varchar(1024); + declare v_idx_expr2 varchar(1024); + declare v_idx_expr3 varchar(1024); + declare v_qs_table varchar(31); + declare v_qs_suffix varchar(31); + declare v_ddl_qstorn varchar(1024); + declare v_ddl_qsidx1 varchar(1024); + declare v_ddl_qsidx2 varchar(1024); + declare v_ddl_qsidx3 varchar(1024); + declare v_id bigint; +begin + -- Called from 1build_oltp_emul.bat when config setting create_with_split_heavy_tabs = 1, see: + -- echo execute procedure tmp_init_autogen_qstorn_tables; >> %...% + + v_ddl_const = ' + id dm_idb not null + ,doc_id dm_idb -- denorm for speed + ,ware_id dm_idb + ,snd_optype_id dm_ids -- denorm for speed + ,snd_id dm_idb -- ==> doc_data.id of "sender" + ,snd_qty dm_qty + ,rcv_doc_id dm_idb -- 30.12.2014, for enable to remove PK on doc_data, see S P_LOCK_DEPENDENT_DOCS + ,rcv_optype_id dm_ids + ,rcv_id dm_idb + ,rcv_qty dm_qty + ,snd_purchase dm_cost + ,snd_retail dm_cost + ,rcv_purchase dm_cost + ,rcv_retail dm_cost + ,trn_id bigint default current_transaction + ,dts timestamp default ''now'' + '; + v_idx_expr1='(doc_id)'; + v_idx_expr2='(snd_id)'; + v_idx_expr3='(rcv_id)'; + for +-- select o.id +-- from optypes o +-- where o.acn_type in('1', '2', 'i', 'o') -- all operations that affect on quantity remainders +-- into v_id + select '' || q.snd_optype_id || '_' || q.rcv_optype_id + from rules_for_qdistr q + where q.snd_optype_id is not null + into v_qs_suffix + do begin + v_qs_table = 'xqs_' || v_qs_suffix; + v_ddl_qstorn = 'recreate table ' || v_qs_table || '(' || v_ddl_const || ')'; + v_ddl_qsidx1 = 'create index '||v_qs_table||'_doc_id on ' || v_qs_table || v_idx_expr1; + v_ddl_qsidx2 = 'create index '||v_qs_table||'_snd_id on ' || v_qs_table || v_idx_expr2; + v_ddl_qsidx3 = 'create index '||v_qs_table||'_rcv_id on ' || v_qs_table || v_idx_expr3; + in autonomous transaction do + begin + execute statement v_ddl_qstorn; + execute statement v_ddl_qsidx1; + execute statement v_ddl_qsidx2; + if ( upper(v_qs_table) <> upper('xqs_3300_3400') ) then + -- 25.11.2015, look at index statistics of 'xqs_3300_3400': + -- there are 100% dups in the field 'rcv_id', it has NULL value in all rows. + -- We have to avoid creation of this index, it's absolutely useless! + execute statement v_ddl_qsidx3; + end + end + + if ( v_ddl_qstorn is null ) then + -- This script should be called ***AFTER*** oltp_main_filling.sql which does fill table 'optypes'. + -- Probably this table currently is empty! + exception ex_record_not_found; + +end -- tmp_init_autogen_qstorn_tables + +^ + +create or alter procedure tmp_remove_dyn_in_random_id +returns(src varchar(32765)) as + declare v_name_fin varchar(31); + declare v_name_min varchar(31); + declare v_name_max varchar(31); + declare v_line_type varchar(12); + declare v_add_comment smallint; + declare v_body_repl varchar(32765); + + declare v_body_line varchar(8190) character set utf8; + declare v_line_repl varchar(8190) character set utf8; + declare i int; + declare v_lf char(10); +begin + v_lf = ascii_char(10); + + v_line_type = 'std:start'; + v_add_comment = 0; + delete from tmp$autogen$rand$calls; + delete from tmp$autogen$rand$calls; + + insert into tmp$autogen$rand$calls( + view_name_for_find + ,view_name_for_min_id + ,view_name_for_max_id + ) + select + 'v_all_wares', null, null + from rdb$database union all select + 'v_random_find_clo_ord' + ,'v_min_id_clo_ord' + ,'v_max_id_clo_ord' + from rdb$database union all select + 'v_random_find_ord_sup' + ,'v_min_id_ord_sup' + ,'v_max_id_ord_sup' + from rdb$database union all select + 'v_random_find_clo_res' + ,'v_min_id_clo_res' + ,'v_max_id_clo_res' + from rdb$database union all select + 'v_min_id_avl_res' + ,'v_max_id_avl_res' + ,'v_random_find_avl_res' + from rdb$database union all select + 'v_random_find_non_paid_invoice' + ,'v_min_non_paid_invoice' + ,'v_max_non_paid_invoice' + from rdb$database union all select + 'v_random_find_non_paid_realizn' + ,'v_min_non_paid_realizn' + ,'v_max_non_paid_realizn' + + from rdb$database union all select + 'v_reserve_write_off',null, null + from rdb$database union all select + 'v_cancel_client_order',null, null + from rdb$database union all select + 'v_cancel_customer_reserve',null, null + from rdb$database union all select + 'v_add_invoice_to_stock',null, null + from rdb$database union all select + + 'v_cancel_adding_invoice',null, null + from rdb$database union all select + 'v_cancel_supplier_invoice',null, null + from rdb$database union all select + 'v_cancel_customer_prepayment',null, null + from rdb$database union all select + 'v_cancel_payment_to_supplier',null, null + from rdb$database union all select + 'v_all_customers',null, null + from rdb$database union all select + 'v_all_suppliers',null, null + from rdb$database + ; + + delete from tmp$autogen$source; + for + select p.src from sys_get_func_ddl('fn$get$random$id$subst$names',1,1) p + into v_line_repl + do begin + if ( v_line_repl containing '$name_to_substutite_start_of_loop' ) then v_line_type = 'var:subst'; + insert into tmp$autogen$source(line_no, text, line_type) values(:i, :v_line_repl, :v_line_type); + if ( v_line_repl containing '$name_to_substutite_end_of_loop' ) then v_line_type = 'std:final'; + end + + v_body_repl = ''; + for + select text + from tmp$autogen$source s + where s.line_type = 'std:start' + into v_line_repl + do begin + if ( v_add_comment = 0 and trim(v_line_repl) collate unicode_ci starting with 'declare' ) then + begin + v_line_repl = 'declare "!ACHTUNG_READ_ME_1!" varchar(255) = ''### GENERATED AUTO, BASED ON INITIAL SOURCE OF "FN_GET_RANDOM_ID". DO NOT EDIT ###'';'; + --suspend; + v_add_comment = 1; + end + else + begin + v_line_repl = replace(v_line_repl collate unicode_ci, 'fn$get$random$id$subst$names', 'fn_get_random_id'); + end + + if ( char_length(v_body_repl) + char_length(v_line_repl) + 2 < 32765 ) then + begin + v_body_repl = v_body_repl || v_line_repl || v_lf; + end + else + begin + src = v_body_repl; + suspend; + v_body_repl = v_line_repl || v_lf; + end + + end + src = v_body_repl; + suspend; + + v_body_repl = ''; + + for + select + view_name_for_find + ,coalesce(view_name_for_min_id, view_name_for_find) + ,coalesce(view_name_for_max_id, view_name_for_find) + from tmp$autogen$rand$calls + --rows 2 + into + v_name_fin + ,v_name_min + ,v_name_max + do + begin + v_body_repl = ''; + for + select text + from tmp$autogen$source s + where s.line_type = 'var:subst' + into v_line_repl + do begin + v_line_repl = replace(v_line_repl collate unicode_ci, 'name$to$substutite$min$id$', v_name_min); + v_line_repl = replace(v_line_repl collate unicode_ci, 'name$to$substutite$max$id$', v_name_max); + v_line_repl = replace(v_line_repl collate unicode_ci, 'name$to$substutite$search$', v_name_fin); + + if ( char_length(v_body_repl) + char_length(v_line_repl) + 2 < 32765 ) then + begin + v_body_repl = v_body_repl || v_line_repl || v_lf; + end + else + begin + src = v_body_repl; + suspend; + v_body_repl = v_line_repl || v_lf; + end + end + src = v_body_repl; + suspend; + end + + v_body_repl = ''; + for + select text + from tmp$autogen$source s + where s.line_type = 'std:final' + into v_line_repl + do begin + if ( char_length(v_body_repl) + char_length(v_line_repl) + 2 < 32765 ) then + begin + v_body_repl = v_body_repl || v_line_repl || v_lf; + end + else + begin + src = v_body_repl; + suspend; + v_body_repl = v_line_repl || v_lf; + end + end + src = v_body_repl; + suspend; + +end -- tmp_remove_dyn_in_random_id + +^ + +set term ;^ + +set list on; +set echo off; +select 'oltp_split_heavy_tabs_1.sql finish at ' || current_timestamp as msg from rdb$database; + +--rollback; + +drop exception ex_exclusive_required; +drop exception ex_not_suitable_fb_version; +COMMIT; +select count(*) as cnt_collations from rdb$collations s where s.rdb$system_flag is distinct from 1; +select count(*) as cnt_domains from rdb$fields s where s.rdb$system_flag is distinct from 1 and s.rdb$field_name not starting with 'RDB$'; +select count(*) as cnt_exceptions from rdb$exceptions s where s.rdb$system_flag is distinct from 1; +select count(*) as cnt_functions from rdb$functions s where s.rdb$system_flag is distinct from 1; +select count(*) as cnt_generators from rdb$generators s where s.rdb$system_flag = 0; -- do NOT: is distinct from 1; -- can be '6' for autoincrements! +select count(*) as cnt_indices from rdb$indices s where s.rdb$system_flag is distinct from 1; +select count(*) as cnt_procedures from rdb$procedures s where s.rdb$system_flag is distinct from 1; +select count(*) as cnt_tables_or_views from rdb$relations s where s.rdb$system_flag is distinct from 1; +select count(*) as cnt_triggers from rdb$triggers s where s.rdb$system_flag is distinct from 1; +set list off; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MSG oltp30_DDL.sql start at 2016-04-11 15:50:59.5620 + MSG oltp30_DDL.sql finish at 2016-04-11 15:51:01.0780 + MSG oltp30_sp.sql start at 2016-04-11 15:51:01.0780 + MSG oltp30_sp.sql finish at 2016-04-11 15:51:02.0460 + MSG oltp_misc_debug.sql start at 2016-04-11 15:51:02.0460 + MSG oltp_misc_debug.sql finish at 2016-04-11 15:51:02.4210 + MSG oltp_split_heavy_tabs_1.sql start at 2016-04-11 15:51:02.4210 + MSG oltp_split_heavy_tabs_1.sql finish at 2016-04-11 15:51:02.4370 + + CNT_COLLATIONS 2 + CNT_DOMAINS 21 + CNT_EXCEPTIONS 22 + CNT_FUNCTIONS 28 + CNT_GENERATORS 7 + CNT_INDICES 85 + CNT_PROCEDURES 100 + CNT_TABLES_OR_VIEWS 132 + CNT_TRIGGERS 24 + """ + +@pytest.mark.version('>=3.0') +def test_oltp_emul_30_compiler_check_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_optimizer_index_navigation.py b/tests/functional/tabloid/test_optimizer_index_navigation.py new file mode 100644 index 00000000..3e8d5286 --- /dev/null +++ b/tests/functional/tabloid/test_optimizer_index_navigation.py @@ -0,0 +1,65 @@ +#coding:utf-8 +# +# id: functional.tabloid.optimizer_index_navigation +# title: Check that optimizer takes in account presense of index and does navigation instead of external sort. +# decription: +# Verified commit: https://github.com/FirebirdSQL/firebird/actions/runs/176006556 +# Source message to dimitr: 20.07.2020 20:00. +# +# Checked on 3.0.7.33340 and 4.0.0.2114 (intermediate build with timestamp 20.07.2020 17:45) +# +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table t(x int); + create index t_x_asc on t(x); + create descending index t_x_dec on t(x); + insert into t select rand()*1000 from rdb$types,rdb$types; + commit; + set statistics index t_x_asc; + set statistics index t_x_dec; + commit; + set planonly; + + select * from t as t1 where x>=0.5; -- NO 'plan order' must be here; bitmap is enough! + + select * from t as t2 where x>=0.5 order by x; -- here PLAN ORDER is much efficient than bitmap + PLAN SORT + + select * from t as t3 where x<=0.5; -- NO 'plan order' must be here; bitmap is enough! + + select * from t as t4 where x<=0.5 order by x desc; -- here PLAN ORDER is much efficient than bitmap + PLAN SORT + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PLAN (T1 INDEX (T_X_ASC)) + + PLAN (T2 ORDER T_X_ASC) + + PLAN (T3 INDEX (T_X_ASC)) + + PLAN (T4 ORDER T_X_DEC) + """ + +@pytest.mark.version('>=3.0') +def test_optimizer_index_navigation_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_ora_4475843.py b/tests/functional/tabloid/test_ora_4475843.py new file mode 100644 index 00000000..bbd5a426 --- /dev/null +++ b/tests/functional/tabloid/test_ora_4475843.py @@ -0,0 +1,97 @@ +#coding:utf-8 +# +# id: functional.tabloid.ora_4475843 +# title: Wrong (empty) result of query in Oracle 19 +# decription: +# Original issue: +# https://community.oracle.com/tech/developers/discussion/4475843/wrong-result-on-a-simple-sql-statement +# According to message, Oracle return no rows for the query that follows. +# Could not check because of problems with install Oracle XE. +# +# Checked on 4.0.0.2416, 3.0.8.33445 - results OK (one row). +# Checked also on SQL Server XE and Postgres 13 +# +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table test( + p_c_id int, + v_id int, + r_m_i_id int not null, + r_m_s_id int, + constraint pk_test primary key (p_c_id, v_id) + ); + insert into test(p_c_id, v_id, r_m_i_id, r_m_s_id) values(102, 646, 318, 1089); + insert into test(p_c_id, v_id, r_m_i_id, r_m_s_id) values(102, 647, 317, 1089); + insert into test(p_c_id, v_id, r_m_i_id, r_m_s_id) values(102, 648, 316, 1363); + insert into test(p_c_id, v_id, r_m_i_id, r_m_s_id) values(102, 649, 315, null); + commit; + + set list on; + set count on; + select + ( + select rmis.s_id + from ( + select + 316 as r_m_i_id + ,1089 as s_id + ,'true' as i_d_s + from rdb$database + union all + select + 316 as r_m_i_id + ,1363 as s_id + ,'false' as i_d_s + from rdb$database + ) rmis + where rmis.r_m_i_id = pm.r_m_i_id + and ( + pm.r_m_s_id is null and rmis.i_d_s = 'true' + or + pm.r_m_s_id is not null and rmis.s_id = pm.r_m_s_id + ) + fetch first 1 rows only + ) as supplier + ,pm.r_m_s_id + ,pc.m_c_id + ,pc.id + from test pm + inner join (select 102 as id, 10 as m_c_id from rdb$database ) pc on pc.id = pm.p_c_id + where + pm.p_c_id = 102 + and pm.v_id = 648; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + SUPPLIER 1363 + R_M_S_ID 1363 + M_C_ID 10 + ID 102 + Records affected: 1 + """ + +@pytest.mark.version('>=3.0') +def test_ora_4475843_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_pg_13918.py b/tests/functional/tabloid/test_pg_13918.py new file mode 100644 index 00000000..b183baf1 --- /dev/null +++ b/tests/functional/tabloid/test_pg_13918.py @@ -0,0 +1,57 @@ +#coding:utf-8 +# +# id: functional.tabloid.pg_13918 +# title: Some _TRIVIAL_ queries allow to specify HAVING without group by, and for such case one may to get record from EMPTY source rowset(!) +# decription: +# Original issue: +# http://www.postgresql.org/message-id/flat/CAKFQuwYSa5Dzvw8KdxhiUAY+fjbO4DRQ-sDqQXPVexvVoTkvQA@mail.gmail.com#CAKFQuwYSa5Dzvw8KdxhiUAY+fjbO4DRQ-sDqQXPVexvVoTkvQA@mail.gmail.com +# +# See also http://www.postgresql.org/docs/9.5/interactive/sql-select.html +# === +# The presence of HAVING turns a query into a grouped query even if there is no GROUP BY clause <...> +# Such a query will emit a single row if the HAVING condition is true, zero rows if it is not true. +# === +# +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + set count on; + -- This compiles OK and, moreover, outputs one record: + select 123456789 as "Yeah!" from rdb$database where 1=0 having 1=1; + select 987654321 as "Waw!!" from rdb$database where 1=0 having 1=2; + + -- Following will NOT compile: + -- select i from (select 1 i from rdb$database) where i<0 having 1=0; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Yeah! 123456789 + Records affected: 1 + Records affected: 0 + """ + +@pytest.mark.version('>=2.5') +def test_pg_13918_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_pg_14105.py b/tests/functional/tabloid/test_pg_14105.py new file mode 100644 index 00000000..6c1ce8f1 --- /dev/null +++ b/tests/functional/tabloid/test_pg_14105.py @@ -0,0 +1,88 @@ +#coding:utf-8 +# +# id: functional.tabloid.pg_14105 +# title: Check ability to compile query with combination of full and right join. Taken from PG bug library. +# decription: +# Original issue ( http://www.postgresql.org/message-id/20160420194758.22924.80319@wrigleys.postgresql.org ): +# === +# create table a as (select 1 as id); +# select * +# from (( +# a as a1 +# full join (select 1 as id) as tt +# on (a1.id = tt.id) +# ) +# right join (select 1 as id) as tt2 +# on (coalesce(tt.id) = tt2.id) +# ) +# ; +# ERROR: XX000: failed to build any 2-way joins +# LOCATION: standard_join_search, allpaths.c:1832 +# +# +# It works on PostgreSQL 9.2.13., returning: +# id | id | id +# ----+----+---- +# 1 | 1 | 1 +# (1 row) +# === +# PS. NOTE on strange form of COALESCE: "coalesce(tt.id)" - it has only single argument. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate table a(id int); + commit; + + insert into a values(1); + commit; + + set list on; + + select * + from ( + select a1.id as a1_id, tt.id as tt_id, tt2.id as tt2_id + from + ( + a as a1 + full join ( select 1 as id from rdb$database ) as tt + on ( a1.id = tt.id ) + ) + right join (select 1 as id from rdb$database) as tt2 + -- https://www.drupal.org/node/336712 + -- When used with one argument, it will return NULL if that argument is NULL; + -- therefore, in such cases, using it is perfectly useless. + on ( coalesce(tt.id,tt.id) = tt2.id ) + ) + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + A1_ID 1 + TT_ID 1 + TT2_ID 1 + """ + +@pytest.mark.version('>=2.5') +def test_pg_14105_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_pg_14421.py b/tests/functional/tabloid/test_pg_14421.py new file mode 100644 index 00000000..55629b10 --- /dev/null +++ b/tests/functional/tabloid/test_pg_14421.py @@ -0,0 +1,71 @@ +#coding:utf-8 +# +# id: functional.tabloid.pg_14421 +# title: UPDATE/DETERE RETURNING should issue only one row when applying to table with self-referencing FK +# decription: +# Original issue: +# https://www.postgresql.org/message-id/cakfquwyrb5iyfqs6o9mmtbxp96l40bxpnfgosj8xm88ag%2b5_aa%40mail.gmail.com +# +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + recreate table test( + id int primary key, + pid int references test(id) on delete cascade on update cascade + ); + insert into test values (1, null); + insert into test values (2, 1); + insert into test values (3, 2); + insert into test values (4, 2); + insert into test values (5, 2); + insert into test values (6, 2); + insert into test values (7, 2); + commit; + + delete from test + where id = 2 + returning id as old_id + ; + rollback; + + + update test set id=9 where id=2 + returning old.id as old_id, new.id as new_id + ; + + rollback; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + OLD_ID 2 + + + + OLD_ID 2 + NEW_ID 9 + """ + +@pytest.mark.version('>=3.0') +def test_pg_14421_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_remote_access_to_security_db.py b/tests/functional/tabloid/test_remote_access_to_security_db.py new file mode 100644 index 00000000..e70c69d8 --- /dev/null +++ b/tests/functional/tabloid/test_remote_access_to_security_db.py @@ -0,0 +1,57 @@ +#coding:utf-8 +# +# id: functional.tabloid.remote_access_to_security_db +# title: Verify ability to make REMOTE connect to security.db +# decription: +# This test verifies only ability to make REMOTE connect to security.db +# Line "RemoteAccess = false" in file $FB_HOME/databases.conf should be COMMENTED. +# On the host that run tests this must is done BEFORE launch all testsby calling +# batch file "upd_databases_conf.bat" (see \\FirebirdQA\\qa3x.bat; qa4x.bat). +# Checked 28.06.2016 on 4.0.0.267 +# +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('TCPv4', 'TCP'), ('TCPv6', 'TCP')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.close() +# sql_chk=''' +# connect 'localhost:security.db'; +# set list on; +# select mon$attachment_name,mon$remote_protocol from mon$attachments where mon$attachment_id = current_connection; +# ''' +# runProgram('isql',['-q'],sql_chk) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + MON$ATTACHMENT_NAME security.db + MON$REMOTE_PROTOCOL TCP + """ + +@pytest.mark.version('>=3.0') +@pytest.mark.xfail +def test_remote_access_to_security_db_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/tabloid/test_request_of_expr_index.py b/tests/functional/tabloid/test_request_of_expr_index.py new file mode 100644 index 00000000..2d5cf572 --- /dev/null +++ b/tests/functional/tabloid/test_request_of_expr_index.py @@ -0,0 +1,80 @@ +#coding:utf-8 +# +# id: functional.tabloid.request_of_expr_index +# title: request of expression index could run outside of main request's snapshot. +# decription: +# Test verifies fix that is described here: +# https://github.com/FirebirdSQL/firebird/commit/26ee42e69d0a381c166877e3c2a17893d85317e0 +# Thanks Vlad for example of implementation and suggestions. +# ::: NOTE ::: +# It is crusial that final SELECT must run in TIL = read committed read consistency. +# +# Confirmed bug on 4.0.0.1810. +# Checked on 4.0.0.1812 (SS/CS) - all OK. +# +# tracker_id: +# min_versions: ['4.0.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + recreate global temporary table gtt_snap (id bigint) on commit delete rows; + + set term ^; + create or alter function fn_idx returns int as + declare ret int; + begin + insert into gtt_snap values (rdb$get_context('SYSTEM', 'SNAPSHOT_NUMBER')); + return 1; + end + ^ + set term ;^ + commit; + + recreate table fix_test (id int); + create index t_expr_idx on fix_test computed by ((fn_idx())); + commit; + + set transaction read committed READ CONSISTENCY; -- ::: NB ::: + + insert into fix_test values (rdb$get_context('SYSTEM', 'SNAPSHOT_NUMBER')); + + -- numbers must be equal: + set list on; + select + -- f.id as fix_id, g.id as gtt_id, + iif( f.id = g.id + ,'Expected: values are equal.' + ,'MISMATCH: fixed table ID=' || coalesce( cast(f.id as varchar(20)), '' ) || '; GTT ID=' || coalesce( cast(g.id as varchar(20)), '' ) + ) as result + from fix_test f + cross join gtt_snap g + ; + commit; + + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + RESULT Expected: values are equal. + """ + +@pytest.mark.version('>=4.0') +def test_request_of_expr_index_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/tabloid/test_snd_7795_20120706_1249.py b/tests/functional/tabloid/test_snd_7795_20120706_1249.py new file mode 100644 index 00000000..8d98df18 --- /dev/null +++ b/tests/functional/tabloid/test_snd_7795_20120706_1249.py @@ -0,0 +1,267 @@ +#coding:utf-8 +# +# id: functional.tabloid.snd_7795_20120706_1249 +# title: Common SQL. Check correctness of the results +# decription: +# NB: new datatype in FB 4.0 was introduces: numeric(38,0). +# It leads to additional ident of values when we show them in form "SET LIST ON", +# so we have to ignore all internal spaces - see added 'substitution' section below. +# +# Checked on: +# 4.0.0.1635 SS: 1.824s. +# 3.0.5.33182 SS: 1.387s. +# +# tracker_id: +# min_versions: ['3.0'] +# versions: 3.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(from_backup='tabloid-snd-7795.fbk', init=init_script_1) + +test_script_1 = """ + set list on; + with recursive + n as(select -1 i from rdb$database union all select n.i+1 from n where n.i<1), + c0 as + ( + select + gate + ,dts + ,coalesce(sum(purchase),0) purchase + ,coalesce( sum(retail),0) retail + ,iif( sum(purchase) is not null, iif( sum(retail) is not null, 'u', 'i' ), 'o' ) kind + ,row_number()over(partition by gate order by dts desc) r + from + ( + select cast(i.igate as char(12)) || 'a' gate, i.idate dts, i.icost purchase, null retail + from sndxi i + union all + select cast(ogate as char(12)) || 'a', o.odate dts, null, o.ocost retail + from sndxo o + union all + select cast(igate as char(12)) || 'b', i.idate, i.icost, null + from snd1i i + union all + select cast(o.ogate as char(12)) || 'b', o.odate, null, o.ocost + from snd1o o + )a + group by gate,dts + ) + ,c1 as + ( + select + gate + ,max(case when i=0 then r end) r + ,max(case when i=0 then purchase end) purchase + ,max(case when i=0 then retail end) retail + ,max(case when i=0 then dts end) dts + ,max(case when i=1 then dts end) next_dts + ,max(case when i=-1 then dts end) prev_dts + ,max(case when i=0 then kind end) kind + ,max(case when i=1 then kind end) next_kind + ,max(case when i=-1 then kind end) prev_kind + from c0 + cross join n -- <<< small set of 3 rows, created via recursive + -- this leads to VERY poor performance: + --cross join ( select row_number()over()-2 i from rdb$types rows 3 ) + group by gate,r-i + having max(case when i=0 then r end) is not null + ) + --select * from c1 + + ,c2 as( + select + t1.gate g1 + ,t2.gate g2 + ,t1.r + ,t1.dts + ,t1.purchase purchase_1 + ,t1.retail retail_1 + ,t2.purchase purchase_2 + ,t2.retail retail_2 + ,row_number()over(partition by t1.gate,t2.gate order by t1.r) n + ,min( + min( + case + when + t3.gate is not null + and + ( + t3.prev_dts is null and t1.r>1 + or t1.prev_dts<>t3.prev_dts + or t1.prev_kind<>t3.prev_kind + or t2.prev_dts<>t3.prev_dts + or t2.prev_kind<>t3.prev_kind + ) + then t1.r + when t1.r=1 and t3.r<>1 + then -1 + end) + )over(partition by t1.gate,t2.gate) rmin1 + from + c1 t1 + join c1 t2 on t1.gaten then n end)over(partition by g1,g2) rmin2 + from c2 a + ) + --select * from c3 + + ,c4 as + ( + select + g1 + ,g2 + ,min(dts) dts + ,sum(retail_1) retail_1 + ,sum(retail_2) retail_2 + ,sum(purchase_1) purchase_1 + ,sum(purchase_2) purchase_2 + from c3 + where + (rmin2 is null and cnt>=2 or r2) + and (r2 or rmin1 is null or rmin1=1) + group by g1,g2 + ) + --select * from c4 + + ,c5 as( + select + g1 + ,min(g2) g2 + ,max(g2) g3 + ,min(dts) dts + ,max(purchase_1) purchase_1 + ,max(retail_1) retail_1 + ,sum(purchase_2) purchase_2 + ,sum(retail_2) retail_2 + from c4 + group by g1 + ) + --select * from c5 + + ,t5 as( + select + min(g1) g1,min(g2) g2,g3,min(dts) dts, + max(case when g2<>g3 then purchase_1 else 0 end) purchase_1, + max(case when g2<>g3 then retail_1 else 0 end) retail_1, + max(case when g2<>g3 then purchase_2 else purchase_2+purchase_1 end) purchase_2, + max(case when g2<>g3 then retail_2 else retail_2+retail_1 end) retail_2 + from c5 + group by g3 + ) + ,c6 as ( + select + cast(substring(g1 from 1 for 12) as int) g1 + ,cast(substring(g2 from 1 for 12) as int) g2 + ,cast(case when g3<>g2 then substring(g3 from 1 for 12) end as int) g3 + ,dts + ,retail_1+retail_2 retail_sum + ,purchase_1+purchase_2 purchase_sum + from t5 + ) + --select * from c6 + + ,c7 as + ( + select + case + when g1<=g2 and g2<=g3 then g1||','||g2||','||g3 + when g1<=g3 and g3<=g2 then g1||','||g3||','||g2 + when g2<=g1 and g1<=g3 then g2||','||g1||','||g3 + when g2<=g3 and g3<=g1 then g2||','||g3||','||g1 + when g3<=g1 and g1<=g2 then g3||','||g1||','||g2 + when g3<=g2 and g2<=g1 then g3||','||g2||','||g1 + when g1<=g2 then g1||','||g2 + when g2<=g1 then g2||','||g1 + end gate, + dts, + retail_sum, + purchase_sum + from c6 + ) + select gate,dts,retail_sum,purchase_sum + from c7 + order by 1,2; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + GATE 1,1 + DTS 2001-03-14 + RETAIL_SUM 80778.08 + PURCHASE_SUM 109400.00 + + GATE 100,101,102 + DTS 2007-07-01 + RETAIL_SUM 0.00 + PURCHASE_SUM 10.00 + + GATE 121,122,124 + DTS 2011-05-01 + RETAIL_SUM 0.00 + PURCHASE_SUM 9.00 + + GATE 141,142,144 + DTS 2012-01-02 + RETAIL_SUM 0.00 + PURCHASE_SUM 27.00 + + GATE 161,162,163 + DTS 2013-05-01 + RETAIL_SUM 33022.00 + PURCHASE_SUM 0.00 + + GATE 171,172 + DTS 2013-01-01 + RETAIL_SUM 22222.00 + PURCHASE_SUM 0.00 + + GATE 181,182 + DTS 2013-10-03 + RETAIL_SUM 2200.00 + PURCHASE_SUM 0.00 + + GATE 2,2 + DTS 2001-03-22 + RETAIL_SUM 24096.00 + PURCHASE_SUM 24500.00 + """ + +@pytest.mark.version('>=3.0') +def test_snd_7795_20120706_1249_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/transactions/__init__.py b/tests/functional/transactions/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/transactions/__init__.py @@ -0,0 +1 @@ +# Python module 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 new file mode 100644 index 00000000..36c24f14 --- /dev/null +++ b/tests/functional/transactions/test_read_consist_statement_delete_undone_01.py @@ -0,0 +1,393 @@ +#coding:utf-8 +# +# id: functional.transactions.read_consist_statement_delete_undone_01 +# title: READ CONSISTENCY. Changes produced by DELETE statement must be UNDONE when cursor resultset becomes empty after this statement start. Test-01 +# decription: +# Initial article for reading: +# https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:11504247549852 +# Note on terms which are used there: "BLOCKER", "LONG" and "FIRSTLAST" - their names are slightly changed here +# to: LOCKER-1, WORKER and LOCKER-2 respectively. +# See also: doc\\README.read_consistency.md +# +# ********************************************** +# +# ::: NB ::: +# This test uses script %FBT_REPO% +# iles +# ead-consist-sttm-restart-DDL.sql which contains common DDL for all other such tests. +# Particularly, it contains two TRIGGERS (TLOG_WANT and TLOG_DONE) which are used for logging of planned actions and actual +# results against table TEST. These triggers launched AUTONOMOUS transactions in order to have ability to see results in any +# outcome of test. +# +# ############### +# Following scenario if executed here: +# * five rows are inserted into the table TEST, with IDs: 1...5. +# +# * session 'locker-1' ("BLOCKER" in Tom Kyte's article ): +# update test set id = id where id=1; +# +# * session 'worker' ("LONG" in TK article) has mission: +# delete from test where not exists(select * from test where id >= 10) order by id desc; // using TIL = read committed read consistency +# +# // Execution will have PLAN ORDER . +# // It will delete rows starting with ID = 5 and down to ID = 2, but hang on row with ID = 1 because of locker-1; +# +# * session 'locker-2' ("FIRSTLAST" in TK article): +# (1) insert into test(id) values(6); +# (2) commit; +# (3) update test set id=id where id = 6; +# +# // session-'worker' remains waiting at this point because row with ID = 5 is still occupied by by locker-1 +# // but worker must further see record with (new) id = 6 because its TIL was changed to RC NO RECORD_VERSION. +# +# * session 'locker-1': commit (and allows lead session-worker to delete row with ID = 1). +# (1) commit; +# (2) insert into test(id) values(7); +# (3) commit; +# (4) update test set id=id where id = 7; +# +# // This: '(1) commit' - will release record with ID = 1. Worker sees this record and put write-lock on it. +# // [DOC]: "b) engine put write lock on conflicted record" +# // Because of TIL = RC NRV session-'worker' must see all committed records regardless on its own snapshot. +# // Worker resumes search for any rows which with taking in account required order of its DML (i.e. 'ORDER BY ID DESC'). +# // [DOC]: "c) engine continue to evaluate remaining records of update\\delete cursor and put write locks on it too" +# // Worker starts to search records which must be involved in its DML and *found* first sucn row: it has ID = 7. +# // Then it goes on and stops on ID=6 because id is occupied by locker-2. +# // BECAUSE OF FACT THAT AT LEAST ONE ROW *WAS FOUND* - STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# // [DOC]: "d) when there is *no more* records to fetch, engine start to undo all actions performed since +# // top-level statement execution starts and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# +# +# * session 'locker-2': +# (1) commit; +# (2) insert into test(id) values(8); +# (3) commit; +# (4) update test set id=id where id = 8; +# +# // This: '(1) commit' - will release record with ID = 6. Worker sees this record and put write-lock on it. +# // [DOC]: "b) engine put write lock on conflicted record" +# // Because of TIL = RC NRV session-'worker' must see all committed records regardless on its own snapshot. +# // Worker resumes search for any rows which with taking in account required order of its DML (i.e. 'ORDER BY ID DESC') +# // [DOC]: "c) engine continue to evaluate remaining records of update\\delete cursor and put write locks on it too" +# // Worker starts to search records which must be involved in its DML and *found* first sucn row: it has ID = 8. +# // Then it goes on stops on ID=7 because id is occupied by locker-1. +# // BECAUSE OF FACT THAT AT LEAST ONE ROW *WAS FOUND* - STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# // [DOC]: "d) when there is *no more* records to fetch, engine start to undo all actions performed since +# // top-level statement execution starts and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# +# * session 'locker-1': commit (this allows session-worker to delete row with ID = 7). +# (1) commit; +# (2) insert into test(id) values(9); +# (3) commit; +# (4) update test set id=id where id = 9; +# +# // Comments here are similar to previous one: STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# +# * session 'locker-2': commit (this allows session-worker to delete row with ID = 6). +# (1) commit; +# (2) insert into test(id) values(10); +# (3) commit; +# (4) update test set id=id where id = 10; +# +# // This will made this row visible to session-worker when it will resume its DML. +# // NOTE: this record will cause session-worker immediately UNDO all changes that it was performed before - see "WHERE NOT EXISTS(...)" in its DML expression. +# +# +# Expected result: +# * session-'worker' must be cancelled. No rows must be deleted, PLUS new rows must remain (with ID = 6 ... 10). +# * we must NOT see statement-level restart because no rows actually were affected by session-worker statement. +# Column TLOG_DONE.SNAP_NO must contain only one unique value that relates to start of DELETE statement. +# +# ################ +# +# Additional comments for this case - see letter from Vlad, 05-aug-2020 00:51. +# +# Checked on 4.0.0.2151 SS/CS +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# from subprocess import Popen +# import re +# import difflib +# from fdb import services +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# sql_init_ddl = os.path.join(context['files_location'],'read-consist-sttm-restart-DDL.sql') +# +# f_init_log=open( os.path.join(context['temp_directory'],'read-consist-sttm-restart-DDL.log'), 'w') +# f_init_err=open( ''.join( ( os.path.splitext(f_init_log.name)[0], '.err') ), 'w') +# +# subprocess.call( [context['isql_path'], dsn, '-q', '-i', sql_init_ddl], stdout=f_init_log, stderr=f_init_err ) +# flush_and_close(f_init_log) +# flush_and_close(f_init_err) +# +# # add rows with ID = 1,2,3,4,5: +# sql_addi=''' +# set term ^; +# execute block as +# begin +# rdb$set_context('USER_SESSION', 'WHO', 'INIT_DATA'); +# end +# ^ +# set term ;^ +# insert into test(id, x) +# select row_number()over(),row_number()over() +# from rdb$types rows 5; +# commit; +# ''' +# runProgram('isql', [ dsn, '-q' ], sql_addi) +# +# +# con_lock_1 = fdb.connect( dsn = dsn ) +# con_lock_2 = fdb.connect( dsn = dsn ) +# con_lock_1.execute_immediate( "execute block as begin rdb$set_context('USER_SESSION', 'WHO', 'LOCKER #1'); end" ) +# con_lock_2.execute_immediate( "execute block as begin rdb$set_context('USER_SESSION', 'WHO', 'LOCKER #2'); end" ) +# +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# +# con_lock_1.execute_immediate( 'update test set id=id where id = 1' ) +# +# sql_text=''' +# connect '%(dsn)s'; +# set list on; +# set autoddl off; +# set term ^; +# execute block returns (whoami varchar(30)) as +# begin +# whoami = 'WORKER'; -- , ATT#' || current_connection; +# rdb$set_context('USER_SESSION','WHO', whoami); +# -- suspend; +# end +# ^ +# set term ;^ +# commit; +# SET KEEP_TRAN_PARAMS ON; +# set transaction read committed read consistency; +# --select current_connection, current_transaction from rdb$database; +# set list off; +# set wng off; +# --set plan on; +# set count on; +# +# delete from test where not exists(select * from test where id >= 10) order by id desc; -- THIS MUST BE LOCKED +# +# -- check results: +# -- ############### +# +# select id from test order by id; -- this will produce output only after all lockers do their commit/rollback +# +# select v.old_id, v.op, v.snap_no_rank +# from v_worker_log v +# where v.op = 'del'; +# +# set width who 10; +# -- DO NOT check this! Values can differ here from one run to another! +# --select id, trn, who, old_id, new_id, op, rec_vers, global_cn, snap_no from tlog_done order by id; +# +# rollback; +# +# ''' % dict(globals(), **locals()) +# +# f_worker_sql=open( os.path.join(context['temp_directory'],'tmp_read_consist_statement_undone_delete_01.sql'), 'w') +# f_worker_sql.write(sql_text) +# flush_and_close(f_worker_sql) +# +# +# f_worker_log=open( ''.join( ( os.path.splitext(f_worker_sql.name)[0], '.log') ), 'w') +# f_worker_err=open( ''.join( ( os.path.splitext(f_worker_log.name)[0], '.err') ), 'w') +# +# ############################################################################ +# ### L A U N C H W O R K E R U S I N G I S Q L, A S Y N C. ### +# ############################################################################ +# +# p_worker = Popen( [ context['isql_path'], '-pag', '999999', '-q', '-i', f_worker_sql.name ],stdout=f_worker_log, stderr=f_worker_err) +# time.sleep(1) +# +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# # Add record so that it **will* be included in the set of rows that must be affected by session-worker: +# con_lock_2.execute_immediate( 'insert into test(id, x) values(6, 6);' ) +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'update test set id = id where id = 6;' ) +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# con_lock_1.commit() # releases record with ID=1 (allow it to be deleted by session-worker) +# # Add record so that it **will* be included in the set of rows that must be affected by session-worker: +# con_lock_1.execute_immediate( 'insert into test(id, x) values(7, 7);' ) +# con_lock_1.commit() +# con_lock_1.execute_immediate( 'update test set id = id where id = 7;' ) +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# con_lock_2.commit() # releases record with ID = 6, but session-worker is waiting for record with ID = 7 (that was added by locker-1). +# con_lock_2.execute_immediate( 'insert into test(id, x) values(8, 8);' ) +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'update test set id = id where id = 8;' ) +# +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# con_lock_1.commit() # releases record with ID = 7, but session-worker is waiting for record with ID = 8 (that was added by locker-2). +# con_lock_1.execute_immediate( 'insert into test(id, x) values(9, 9);' ) +# con_lock_1.commit() +# con_lock_1.execute_immediate( 'update test set id = id where id = 9;' ) +# +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# con_lock_2.commit() # releases record with ID = 8, but session-worker is waiting for record with ID = 9 (that was added by locker-1). +# con_lock_2.execute_immediate( 'insert into test(id, x) values(10, 10);' ) +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'update test set id = id where id = 10;' ) +# +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# con_lock_1.commit() # <<< THIS MUST CANCEL ALL PERFORMED DELETIONS OF SESSION-WORKER +# +# con_lock_2.commit() +# +# # Here we wait for ISQL complete its mission: +# p_worker.wait() +# +# flush_and_close(f_worker_log) +# flush_and_close(f_worker_err) +# +# # Close lockers: +# ################ +# for c in (con_lock_1, con_lock_2): +# c.close() +# +# +# # CHECK RESULTS +# ############### +# +# for f in (f_init_err, f_worker_err): +# with open(f.name,'r') as g: +# for line in g: +# if line: +# print( 'UNEXPECTED STDERR IN ' + g.name + ':' + line) +# +# with open(f_worker_log.name,'r') as f: +# for line in f: +# print(line) +# +# +# # Cleanup. +# ########## +# time.sleep(1) +# cleanup( (f_init_log, f_init_err, f_worker_sql, f_worker_log, f_worker_err) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + + ID + ======= + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + + Records affected: 10 + + OLD_ID OP SNAP_NO_RANK + ======= ====== ===================== + 5 DEL 1 + 4 DEL 1 + 3 DEL 1 + 2 DEL 1 + + Records affected: 4 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_read_consist_statement_delete_undone_01_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + 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 new file mode 100644 index 00000000..d463b077 --- /dev/null +++ b/tests/functional/transactions/test_read_consist_statement_delete_undone_02.py @@ -0,0 +1,350 @@ +#coding:utf-8 +# +# id: functional.transactions.read_consist_statement_delete_undone_02 +# title: READ CONSISTENCY. Changes produced by DELETE statement must be UNDONE when cursor resultset becomes empty after this statement start. Test-02 +# decription: +# Initial article for reading: +# https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:11504247549852 +# Note on terms which are used there: "BLOCKER", "LONG" and "FIRSTLAST" - their names are slightly changed here +# to: LOCKER-1, WORKER and LOCKER-2 respectively. +# See also: doc\\README.read_consistency.md +# +# ********************************************** +# +# ::: NB ::: +# This test uses script %FBT_REPO% +# iles +# ead-consist-sttm-restart-DDL.sql which contains common DDL for all other such tests. +# Particularly, it contains two TRIGGERS (TLOG_WANT and TLOG_DONE) which are used for logging of planned actions and actual +# results against table TEST. These triggers launched AUTONOMOUS transactions in order to have ability to see results in any +# outcome of test. +# +# ############### +# Following scenario if executed here: +# * five rows are inserted into the table TEST, with IDs: 1...5. +# +# * session 'locker-1' ("BLOCKER" in Tom Kyte's article ): +# update test set id = id where id = 1; +# +# * session 'worker' ("LONG" in TK article) has mission: +# delete from test where x not in (select x from test where id >= 4) order by id desc; // using TIL = read committed read consistency +# +# // Execution will have PLAN ORDER . +# // It will delete rows starting with ID = 5 and down to ID = 2, but hang on row with ID = 1 because of locker-1; +# +# * session 'locker-2' ("FIRSTLAST" in TK article): +# (1) insert into test(id) values(-1); +# (2) commit; +# (3) update test set id=id where id = -1; +# +# // session-'worker' remains waiting at this point because row with ID = 1 is still occupied by by locker-1 +# // but worker must further see record with (new) id = -1 because its TIL was changed to RC NO RECORD_VERSION. +# +# * session 'locker-1': +# (1) commit; +# (2) insert into test(id) values(-2); +# (3) commit; +# (4) update test set id=id where id = -2; +# +# // This: '(1) commit' - will release record with ID = 1. Worker sees this record and put write-lock on it. +# // [DOC]: "b) engine put write lock on conflicted record" +# // Because of TIL = RC NRV session-'worker' must see all committed records regardless on its own snapshot. +# // Worker resumes search for any rows which with taking in account required order of its DML (i.e. 'ORDER BY ID DESC'). +# // [DOC]: "c) engine continue to evaluate remaining records of update\\delete cursor and put write locks on it too" +# // Worker starts to search records which must be involved in its DML and *found* row that was not yet locked: it has ID = 1. +# // Then it goes on and stops on ID = -1 because id is occupied by locker-2. +# // BECAUSE OF FACT THAT AT LEAST ONE ROW *WAS FOUND* - STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# // [DOC]: "d) when there is *no more* records to fetch, engine start to undo all actions performed since +# // top-level statement execution starts and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# +# * session 'locker-2': +# (1) commit; +# (2) insert into test(id, x) values(10, NULL); -- ::: NB ::: X is NULL here! +# (3) update test set id=id where id = 10; +# +# // This: '(1) commit' - will release record with ID = -1. Worker sees this record and put write-lock on it. +# // [DOC]: "b) engine put write lock on conflicted record" +# // Because of TIL = RC NRV session-'worker' must see all committed records regardless on its own snapshot. +# // Worker resumes search for any rows which with taking in account required order of its DML (i.e. 'ORDER BY ID DESC'). +# // [DOC]: "c) engine continue to evaluate remaining records of update\\delete cursor and put write locks on it too" +# // Worker starts to search records which must be involved in its DML and *found* row that was not yet locked: it has ID = -1. +# // Then it goes on and stops on ID = -2 because id is occupied by locker-1. +# // BECAUSE OF FACT THAT AT LEAST ONE ROW *WAS FOUND* - STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# // [DOC]: "d) when there is *no more* records to fetch, engine start to undo all actions performed since +# // top-level statement execution starts and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# // ::: NB ::: +# // Expression "where x not in (select x from test where id >= 4)" will be evaluated as FALSE since this point +# // because one of its records has NULL in 'X' column. +# +# * session 'locker-1': +# commit; +# +# // this allows session-worker to delete row with ID = -2. +# // session-worker must immediately cancel its DML because now it sees record with ID = 10 and X is NULL which not meets NOT-IN requirements. +# +# Expected result: +# * session-'worker' must be cancelled. No rows must be deleted, PLUS new rows must remain (with ID = -1, -2 and 10). +# * we must NOT see statement-level restart because no rows actually were affected by session-worker statement. +# Column TLOG_DONE.SNAP_NO must contain only one unique value that relates to start of DELETE statement. +# ################ +# +# Checked on 4.0.0.2151 SS/CS +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# from subprocess import Popen +# import re +# import difflib +# from fdb import services +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql_init_ddl = os.path.join(context['files_location'],'read-consist-sttm-restart-DDL.sql') +# +# f_init_log=open( os.path.join(context['temp_directory'],'read-consist-sttm-restart-DDL.log'), 'w') +# f_init_err=open( ''.join( ( os.path.splitext(f_init_log.name)[0], '.err') ), 'w') +# +# subprocess.call( [context['isql_path'], dsn, '-q', '-i', sql_init_ddl], stdout=f_init_log, stderr=f_init_err ) +# flush_and_close(f_init_log) +# flush_and_close(f_init_err) +# +# # add rows with ID = 1,2,3,4,5: +# sql_addi=''' +# set term ^; +# execute block as +# begin +# rdb$set_context('USER_SESSION', 'WHO', 'INIT_DATA'); +# end +# ^ +# set term ;^ +# insert into test(id, x) +# select row_number()over(),row_number()over() +# from rdb$types rows 5; +# commit; +# ''' +# runProgram('isql', [ dsn, '-q' ], sql_addi) +# +# con_lock_1 = fdb.connect( dsn = dsn ) +# con_lock_2 = fdb.connect( dsn = dsn ) +# con_lock_1.execute_immediate( "execute block as begin rdb$set_context('USER_SESSION', 'WHO', 'LOCKER #1'); end" ) +# con_lock_2.execute_immediate( "execute block as begin rdb$set_context('USER_SESSION', 'WHO', 'LOCKER #2'); end" ) +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# +# con_lock_1.execute_immediate( 'update test set id=id where id = 1' ) +# +# sql_text=''' +# connect '%(dsn)s'; +# set list on; +# set autoddl off; +# set term ^; +# execute block returns (whoami varchar(30)) as +# begin +# whoami = 'WORKER'; -- , ATT#' || current_connection; +# rdb$set_context('USER_SESSION','WHO', whoami); +# -- suspend; +# end +# ^ +# set term ;^ +# commit; +# SET KEEP_TRAN_PARAMS ON; +# set transaction read committed read consistency; +# --select current_connection, current_transaction from rdb$database; +# set list off; +# set wng off; +# --set plan on; +# set count on; +# +# delete from test where x not in (select x from test where id >= 4) order by id desc; -- THIS MUST BE LOCKED +# +# -- check results: +# -- ############### +# +# +# select id from test order by id; -- this will produce output only after all lockers do their commit/rollback +# +# select v.old_id, v.op, v.snap_no_rank +# from v_worker_log v +# where v.op = 'del'; +# +# set width who 10; +# -- DO NOT check this! Values can differ here from one run to another! +# --select id, trn, who, old_id, new_id, op, rec_vers, global_cn, snap_no from tlog_done order by id; +# +# rollback; +# +# ''' % dict(globals(), **locals()) +# +# f_worker_sql=open( os.path.join(context['temp_directory'],'tmp_read_consist_statement_undone_delete_02.sql'), 'w') +# f_worker_sql.write(sql_text) +# flush_and_close(f_worker_sql) +# +# +# f_worker_log=open( ''.join( ( os.path.splitext(f_worker_sql.name)[0], '.log') ), 'w') +# f_worker_err=open( ''.join( ( os.path.splitext(f_worker_log.name)[0], '.err') ), 'w') +# +# ############################################################################ +# ### L A U N C H W O R K E R U S I N G I S Q L, A S Y N C. ### +# ############################################################################ +# +# p_worker = Popen( [ context['isql_path'], '-pag', '999999', '-q', '-i', f_worker_sql.name ],stdout=f_worker_log, stderr=f_worker_err) +# time.sleep(1) +# +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# con_lock_2.execute_immediate( 'insert into test(id,x) values( -1, -1 )') +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'update test set id=id where id=-1' ) +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# con_lock_1.commit() # releases record with ID=1 (allow it to be deleted by session-worker) +# con_lock_1.execute_immediate( 'insert into test(id, x) values(-2, -2);' ) +# con_lock_1.commit() +# con_lock_1.execute_immediate( 'update test set id = id where id = -2' ) +# +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'insert into test(id, x) values(10, null)' ) +# con_lock_2.commit() +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# con_lock_1.commit() # <<< THIS MUST CANCEL ALL PERFORMED DELETIONS OF SESSION-WORKER +# +# +# # Here we wait for ISQL complete its mission: +# p_worker.wait() +# +# flush_and_close(f_worker_log) +# flush_and_close(f_worker_err) +# +# # Close lockers: +# ################ +# for c in (con_lock_1, con_lock_2): +# c.close() +# +# +# # CHECK RESULTS +# ############### +# +# for f in (f_init_err, f_worker_err): +# with open(f.name,'r') as g: +# for line in g: +# if line: +# print( 'UNEXPECTED STDERR IN ' + g.name + ':' + line) +# +# with open(f_worker_log.name,'r') as f: +# for line in f: +# print(line) +# +# # Cleanup. +# ########## +# time.sleep(1) +# cleanup( (f_init_log, f_init_err, f_worker_sql, f_worker_log, f_worker_err) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Records affected: 0 + + ID + ======= + -2 + -1 + 1 + 2 + 3 + 4 + 5 + 10 + + Records affected: 8 + + OLD_ID OP SNAP_NO_RANK + ======= ====== ===================== + 3 DEL 1 + 2 DEL 1 + + Records affected: 2 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_read_consist_statement_delete_undone_02_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + 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 new file mode 100644 index 00000000..bf646afc --- /dev/null +++ b/tests/functional/transactions/test_read_consist_sttm_merge_deny_multiple_matches.py @@ -0,0 +1,419 @@ +#coding:utf-8 +# +# id: functional.transactions.read_consist_sttm_merge_deny_multiple_matches +# title: READ CONSISTENCY. MERGE must reject multiple matches, regardless on statement-level restart. +# decription: +# Initial article for reading: +# https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:11504247549852 +# Note on terms which are used there: "BLOCKER", "LONG" and "FIRSTLAST" - their names are slightly changed here +# to: LOCKER-1, WORKER and LOCKER-2 respectively. +# +# See also: doc\\README.read_consistency.md +# Letter from Vlad: 15.09.2020 20:04 // subj "read consistency // addi test(s)" +# +# ::: NB ::: +# This test uses script %FBT_REPO% +# iles +# ead-consist-sttm-restart-DDL.sql which contains common DDL for all other such tests. +# Particularly, it contains two TRIGGERS (TLOG_WANT and TLOG_DONE) which are used for logging of planned actions and actual +# results against table TEST. These triggers use AUTONOMOUS transactions in order to have ability to see results in any +# outcome of test. +# +# Test verifies DENIAL of multiple matches when MERGE encounteres them, but this statement works in read committed read consistency TIL +# and forced to do several statement-level restarts before such condition will occur. +# +# Scenario: +# * add initial data to the table TEST: six rows with ID and X = (0, ..., 5); +# * launch LOCKER-1 and catch record with ID = 0: update, then commit and once again update this record (without commit); +# * launch WORKER which tries to do: +# merge into test t +# using ( +# select s.id, s.x from test as s +# where s.id <= 1 +# order by s.id DESC +# ) s +# on abs(t.id) = abs(s.id) +# when matched then +# update set t.x = t.x * s.x +# ; +# This statement will update record with ID = 1 but then hanging because rows with ID = 0 is locked by LOCKER-1. +# At this point WORKER changes its TIL to RC NO RECORD_VERSION. This allows WORKER to see all records which will be committed later; +# NOTE: records with ID = 2...5 will not be subect for this statement (because they will not returned by data source marked as 's'). +# +# * LOCKER-2 updates row with ID = 5 by reverting sign of this field (i.e. set ID to -5), then issues commit and updates this row again (without commit); +# * LOCKER-1 updates row with ID = 4 and set ID to -4, then issues commit and updates this row again (without commit); +# * LOCKER-2 updates row with ID = 3 and set ID to -3, then issues commit and updates this row again (without commit); +# * LOCKER-1 updates row with ID = 2 and set ID to -2, then issues commit and updates this row again (without commit); +# * LOCKER-2 inserts row (ID,X) = (-1, 1), commit and updates this row again (without commit); +# * LOCKER-1 issues commit; +# * LOCKER-2 issues commit; +# +# Each of updates/inserts which are performed by LOCKERs lead to new record be appeared in the data source 's' of MERGE statement. +# But note that last statement: insert into test(id,x) values(-1,1) -- creates record that will match TWISE when ON-expression of MERGE +# will evaluates "abs(t.id) = abs(s.id)": first match will be found for record with ID = +1 and second - for newly added rows with ID=-1. +# +# At this point MERGE must fail with message +# Statement failed, SQLSTATE = 21000 +# Multiple source records cannot match the same target during MERGE +# +# All changes that was performed by MERGE must be rolled back. +# ISQL which did MERGE must issue "Records affected: 2" because MERGE was actually could process records with ID = 1 and 0 (and failed on row with ID=-1). +# +# Above mentioned actions are performed two times: first for TABLE and second for naturally-updatable VIEW (v_test), see 'target_object_type'. +# +# Checked on 4.0.0.2214 SS/CS. +# +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' '), ('.After\\s+line\\s+\\d+\\s+.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# from subprocess import Popen +# import shutil +# from fdb import services +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # How long LOCKER must wait before raise update-conflict error +# # (useful for debug in case os some error in this test algorithm): +# LOCKER_LOCK_TIMEOUT = 5 +# +# ############################## +# # Temply, for debug obly: +# this_fdb=db_conn.database_name +# this_dbg=os.path.splitext(this_fdb)[0] + '.4debug.fdb' +# ############################## +# +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql_init_ddl = os.path.join(context['files_location'],'read-consist-sttm-restart-DDL.sql') +# +# for target_object_type in('table', 'view'): +# +# +# target_obj = 'test' if target_object_type == 'table' else 'v_test' +# +# f_init_log=open( os.path.join(context['temp_directory'],'read-consist-sttm-merge-deny-multiple-matches-DDL.log'), 'w') +# f_init_err=open( ''.join( ( os.path.splitext(f_init_log.name)[0], '.err') ), 'w') +# +# # RECREATION OF ALL DB OBJECTS: +# # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# subprocess.call( [context['isql_path'], dsn, '-q', '-i', sql_init_ddl], stdout=f_init_log, stderr=f_init_err ) +# +# flush_and_close(f_init_log) +# flush_and_close(f_init_err) +# +# sql_addi=''' +# set term ^; +# execute block as +# begin +# rdb$set_context('USER_SESSION', 'WHO', 'INIT_DATA'); +# end +# ^ +# set term ;^ +# +# -- INITIAL DATA: add rows with ID = 0...6 +# -- ############# +# insert into %(target_obj)s(id, x) +# select row_number()over()-1, row_number()over()-1 +# from rdb$types rows 6; +# +# commit; +# ''' % locals() +# +# runProgram('isql', [ dsn, '-q' ], sql_addi) +# +# locker_tpb = fdb.TPB() +# locker_tpb.lock_timeout = LOCKER_LOCK_TIMEOUT +# locker_tpb.lock_resolution = fdb.isc_tpb_wait +# +# con_lock_1 = fdb.connect( dsn = dsn, isolation_level=locker_tpb ) +# con_lock_2 = fdb.connect( dsn = dsn, isolation_level=locker_tpb ) +# +# con_lock_1.execute_immediate( "execute block as begin rdb$set_context('USER_SESSION', 'WHO', 'LOCKER #1'); end" ) +# con_lock_2.execute_immediate( "execute block as begin rdb$set_context('USER_SESSION', 'WHO', 'LOCKER #2'); end" ) +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# +# con_lock_1.execute_immediate( 'update %(target_obj)s set id=id where id = 0' % locals() ) +# +# sql_text=''' +# connect '%(dsn)s'; +# set list on; +# set autoddl off; +# set term ^; +# execute block as +# begin +# rdb$set_context('USER_SESSION','WHO', 'WORKER'); +# end +# ^ +# set term ;^ +# commit; +# SET KEEP_TRAN_PARAMS ON; +# set transaction read committed read consistency; +# set list off; +# set wng off; +# +# set count on; +# +# merge into %(target_obj)s t +# using ( +# select s.id, s.x from %(target_obj)s as s +# where s.id <= 1 +# order by s.id DESC +# ) s +# on abs(t.id) = abs(s.id) +# when matched then +# update set t.x = t.x * s.x +# ; +# +# -- check results: +# -- ############### +# +# select id,x from %(target_obj)s order by id; +# +# select v.old_id, v.op, v.snap_no_rank +# from v_worker_log v +# where v.op = 'upd'; +# +# +# --set width who 10; +# -- DO NOT check this! Values can differ here from one run to another! +# -- select id, trn, who, old_id, new_id, op, rec_vers, global_cn, snap_no from tlog_done order by id; +# rollback; +# +# ''' % dict(globals(), **locals()) +# +# f_worker_sql=open( os.path.join(context['temp_directory'],'read-consist-sttm-merge-deny-multiple-matches.sql'), 'w') +# f_worker_sql.write(sql_text) +# flush_and_close(f_worker_sql) +# +# +# f_worker_log=open( ''.join( ( os.path.splitext(f_worker_sql.name)[0], '.log') ), 'w') +# f_worker_err=open( ''.join( ( os.path.splitext(f_worker_log.name)[0], '.err') ), 'w') +# +# ############################################################################ +# ### L A U N C H W O R K E R U S I N G I S Q L, A S Y N C. ### +# ############################################################################ +# +# p_worker = Popen( [ context['isql_path'], '-pag', '9999999', '-q', '-i', f_worker_sql.name ],stdout=f_worker_log, stderr=f_worker_err) +# time.sleep(1) +# +# cur_lock_1 = con_lock_1.cursor() +# cur_lock_2 = con_lock_2.cursor() +# +# +# sttm = 'update %(target_obj)s set id = ? where abs( id ) = ?' % locals() +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# cur_lock_2.execute( sttm, ( -5, 5, ) ) +# con_lock_2.commit() +# cur_lock_2.execute( sttm, ( -5, 5, ) ) +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# con_lock_1.commit() +# cur_lock_1.execute( sttm, ( -4, 4, ) ) +# con_lock_1.commit() +# cur_lock_1.execute( sttm, ( -4, 4, ) ) +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# con_lock_2.commit() +# cur_lock_2.execute( sttm, ( -3, 3, ) ) +# con_lock_2.commit() +# cur_lock_2.execute( sttm, ( -3, 3, ) ) +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# con_lock_1.commit() +# cur_lock_1.execute( sttm, ( -2, 2, ) ) +# con_lock_1.commit() +# cur_lock_1.execute( sttm, ( -2, 2, ) ) +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# con_lock_2.commit() +# cur_lock_2.execute( 'insert into %(target_obj)s(id,x) values(?, ?)' % locals(), ( -1, 1, ) ) +# con_lock_2.commit() +# cur_lock_2.execute( 'update %(target_obj)s set id = id where id = ?' % locals(), ( -1, ) ) +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# con_lock_1.commit() +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# con_lock_2.commit() # At this point merge can complete its job but it must FAIL because of multiple matches for abs(t.id) = abs(s.id), i.e. when ID = -1 and 1 +# +# # Close lockers: +# ################ +# for c in (con_lock_1, con_lock_2): +# c.close() +# +# # Here we wait for ISQL complete its mission: +# p_worker.wait() +# +# flush_and_close(f_worker_log) +# flush_and_close(f_worker_err) +# +# # CHECK RESULTS +# ############### +# with open(f_init_err.name,'r') as f: +# for line in f: +# if line: +# print( 'target_object_type: %(target_object_type)s, checked_DML = %(checked_DML)s, UNEXPECTED STDERR for initial SQL: %(line)s' % locals() ) +# +# for f in (f_worker_log, f_worker_err): +# with open(f.name,'r') as g: +# for line in g: +# if line: +# logname = 'STDLOG' if f.name == f_worker_log.name else 'STDERR' +# print( 'target_object_type: %(target_object_type)s, worker %(logname)s: %(line)s' % locals() ) +# +# +# # < for target_object_type in ('table', 'view') +# +# # Cleanup. +# ########## +# time.sleep(1) +# cleanup( (f_init_log, f_init_err, f_worker_sql, f_worker_log, f_worker_err) ) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + target_object_type: table, worker STDLOG: Records affected: 2 + target_object_type: table, worker STDLOG: + target_object_type: table, worker STDLOG: ID X + target_object_type: table, worker STDLOG: ======= ======= + target_object_type: table, worker STDLOG: -5 5 + target_object_type: table, worker STDLOG: -4 4 + target_object_type: table, worker STDLOG: -3 3 + target_object_type: table, worker STDLOG: -2 2 + target_object_type: table, worker STDLOG: -1 1 + target_object_type: table, worker STDLOG: 0 0 + target_object_type: table, worker STDLOG: 1 1 + target_object_type: table, worker STDLOG: + target_object_type: table, worker STDLOG: Records affected: 7 + target_object_type: table, worker STDLOG: + target_object_type: table, worker STDLOG: OLD_ID OP SNAP_NO_RANK + target_object_type: table, worker STDLOG: ======= ====== ===================== + target_object_type: table, worker STDLOG: 0 UPD 1 + target_object_type: table, worker STDLOG: 1 UPD 1 + target_object_type: table, worker STDLOG: 0 UPD 2 + target_object_type: table, worker STDLOG: 1 UPD 2 + target_object_type: table, worker STDLOG: 0 UPD 3 + target_object_type: table, worker STDLOG: 1 UPD 3 + target_object_type: table, worker STDLOG: 0 UPD 4 + target_object_type: table, worker STDLOG: 1 UPD 4 + target_object_type: table, worker STDLOG: 0 UPD 5 + target_object_type: table, worker STDLOG: 1 UPD 5 + target_object_type: table, worker STDLOG: + target_object_type: table, worker STDLOG: Records affected: 10 + target_object_type: table, worker STDERR: Statement failed, SQLSTATE = 21000 + target_object_type: table, worker STDERR: Multiple source records cannot match the same target during MERGE + target_object_type: table, worker STDERR: After line 18 in file C:\\FBTESTING\\qa bt-repo mp mp_sttm_restart_max_limit.sql + target_object_type: view, worker STDLOG: Records affected: 2 + target_object_type: view, worker STDLOG: + target_object_type: view, worker STDLOG: ID X + target_object_type: view, worker STDLOG: ======= ======= + target_object_type: view, worker STDLOG: -5 5 + target_object_type: view, worker STDLOG: -4 4 + target_object_type: view, worker STDLOG: -3 3 + target_object_type: view, worker STDLOG: -2 2 + target_object_type: view, worker STDLOG: -1 1 + target_object_type: view, worker STDLOG: 0 0 + target_object_type: view, worker STDLOG: 1 1 + target_object_type: view, worker STDLOG: + target_object_type: view, worker STDLOG: Records affected: 7 + target_object_type: view, worker STDLOG: + target_object_type: view, worker STDLOG: OLD_ID OP SNAP_NO_RANK + target_object_type: view, worker STDLOG: ======= ====== ===================== + target_object_type: view, worker STDLOG: 0 UPD 1 + target_object_type: view, worker STDLOG: 1 UPD 1 + target_object_type: view, worker STDLOG: 0 UPD 2 + target_object_type: view, worker STDLOG: 1 UPD 2 + target_object_type: view, worker STDLOG: 0 UPD 3 + target_object_type: view, worker STDLOG: 1 UPD 3 + target_object_type: view, worker STDLOG: 0 UPD 4 + target_object_type: view, worker STDLOG: 1 UPD 4 + target_object_type: view, worker STDLOG: 0 UPD 5 + target_object_type: view, worker STDLOG: 1 UPD 5 + target_object_type: view, worker STDLOG: + target_object_type: view, worker STDLOG: Records affected: 10 + target_object_type: view, worker STDERR: Statement failed, SQLSTATE = 21000 + target_object_type: view, worker STDERR: Multiple source records cannot match the same target during MERGE + target_object_type: view, worker STDERR: After line 18 in file C:\\FBTESTING\\qa bt-repo mp mp_sttm_restart_max_limit.sql + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_read_consist_sttm_merge_deny_multiple_matches_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + 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 new file mode 100644 index 00000000..0329f0a9 --- /dev/null +++ b/tests/functional/transactions/test_read_consist_sttm_restart_max_limit.py @@ -0,0 +1,1062 @@ +#coding:utf-8 +# +# id: functional.transactions.read_consist_sttm_restart_max_limit +# title: READ CONSISTENCY. Maximal number of statement-level restarts must be 10. +# decription: +# Initial article for reading: +# https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:11504247549852 +# Note on terms which are used there: "BLOCKER", "LONG" and "FIRSTLAST" - their names are slightly changed here +# to: LOCKER-1, WORKER and LOCKER-2 respectively. +# +# See also: doc\\README.read_consistency.md +# Letter from Vlad: 15.09.2020 20:04 // subj "read consistency // addi test(s)" +# +# ::: NB ::: +# This test uses script %FBT_REPO% +# iles +# ead-consist-sttm-restart-DDL.sql which contains common DDL for all other such tests. +# Particularly, it contains two TRIGGERS (TLOG_WANT and TLOG_DONE) which are used for logging of planned actions and actual +# results against table TEST. These triggers use AUTONOMOUS transactions in order to have ability to see results in any +# outcome of test. +# +# Detailed description can be found in "read-consist-sttm-restart-on-update-04.fbt", this test is based on the same ideas: +# * initial script add records with ID = 1...12 and does commit; +# * start locker-1 which catch record with ID = 1 that is to be involved futher in cursor of worker; +# * start worker DML which must change records in descending order of ID, starting with ID=2; worker must write ID = ID * 100 for each row; +# * start locker-2 which changes record with ID=12 by assigning this ID to -12, makes COMMIT and locks this record again (makes UPDATE w/o commit); +# * locker-1 releases record with ID=1, then changes record with ID=11 by assigning this ID to -11, makes COMMIT and locks this record again; +# * locker-2 releases record with ID=-12, then changes record with ID=10 by assigning this ID to -10, makes COMMIT and locks this record again; +# * ... and so on, until number of such actions iterations less 10 or 11 (see below) ... +# +# Each UPDATE that is performed by lockers (starting from ID=11) produces new ID (-11, -10, -9, ...) that was not present in the scope which worker +# could see before this action. This forces worker to make statement-level restart. +# +# When number of such new IDs is less than 10 then worker must finish its job successfully. +# But if this number if 11 then worker must raise exception (SQLSTATE = 40001 / deadlock / update conflicts) and rollback all changes. +# +# Test verifies both cases, using loop with TWO iterations (see 'main_iter' below): first for 10 and second to 11 records that are to be updated. +# After each iteration we do queries to the table TEST and to the view V_WORKER_LOG which contains data generated by trigger TLOG_DONE for logging. +# +# Test verifies restart number for three modes of WORKER job: UPDATE, MERGE, DELETE and SELECT WITH LOCK (see loop for checked_DML: 'upd', 'mer', 'del', 'lok'). +# NOTE-1. +# For 'SELECT WITH LOCK' we must provide that no rows will be returned to client while worker is waiting for records. +# EXECUTE BLOCK with for-select which does nothing is used for this. +# +# NOTE-2. +# SELECT WITH LOCK does not allow to use VIEW as subject of query (raises "-WITH LOCK can be used only with a single physical table"). +# This error is expected in current FB versions and its text presents in expected_std* section. +# +# Checked on 4.0.0.2195 SS/CS. +# 29.09.2020: added for-loop in order to check different target objects: TABLE ('test') and VIEW ('v_test'), see 'target_object_type'. +# +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' '), ('.*After line \\d+.*', ''), ('.*[\\-]?concurrent transaction number is \\d+', 'concurrent transaction number is'), ('.*At\\s+block\\s+line(:)?\\s+\\d+(,)?\\s+col(:)?\\s+\\d+', ''), ('.After\\s+line\\s+\\d+\\s+.*', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# from subprocess import Popen +# import shutil +# from fdb import services +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # How long LOCKER must wait before raise update-conflict error +# # (useful for debug in case os some error in this test algorithm): +# LOCKER_LOCK_TIMEOUT = 5 +# +# ############################## +# # Temply, for debug obly: +# this_fdb=db_conn.database_name +# this_dbg=os.path.splitext(this_fdb)[0] + '.4debug.fdb' +# ############################## +# +# db_conn.close() +# fb_home = services.connect(host='localhost').get_home_directory() +# +# #-------------------------------------------- +# +# 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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql_init_ddl = os.path.join(context['files_location'],'read-consist-sttm-restart-DDL.sql') +# +# for target_object_type in('table', 'view'): +# +# target_obj = 'test' if target_object_type == 'table' else 'v_test' +# +# for checked_DML in('upd', 'mer', 'del', 'lok'): +# #for checked_DML in('lok',): +# worker_dml = "select 'UNKNOWN MODE' as msg from rdb$database" +# if checked_DML == 'upd': +# worker_dml = 'update %(target_obj)s set id = id * 100 where id <= 2 order by id DESC;' % locals() +# elif checked_DML == 'mer': +# worker_dml = 'merge into %(target_obj)s t using (select x.id from %(target_obj)s x where x.id <= 2 order by id DESC) s on t.id = s.id when matched then update set t.id = s.id * 100;' % locals() +# elif checked_DML == 'del': +# worker_dml = 'delete from %(target_obj)s where id <= 2 order by id DESC;' % locals() +# elif checked_DML == 'lok': +# # ::: NB ::: +# # We must SUPRESS sending record to client for SELECT WITH LOCK, otherwise error +# # deadlock/update conflist will raise immediately! Because of this, we enclose +# # such select into execute block which returns nothing: +# worker_dml = 'set term ^; execute block as declare c int; begin for select id from %(target_obj)s where id<=2 order by id desc with lock into c do begin end end^ set term ;^' % locals() +# +# for main_iter in (0,1): +# #for main_iter in (1,): +# +# ################################################################################### +# ### H O W M A N Y R E S T A R T S W E W A N T T O C H E C K ### +# ################################################################################### +# ROWS_TO_ADD = 10 + 2 * main_iter +# +# +# f_init_log=open( os.path.join(context['temp_directory'],'read-consist-sttm-restart-DDL.log'), 'w') +# f_init_err=open( ''.join( ( os.path.splitext(f_init_log.name)[0], '.err') ), 'w') +# +# # RECREATION OF ALL DB OBJECTS: +# # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# subprocess.call( [context['isql_path'], dsn, '-q', '-i', sql_init_ddl], stdout=f_init_log, stderr=f_init_err ) +# +# flush_and_close(f_init_log) +# flush_and_close(f_init_err) +# +# sql_addi=''' +# set term ^; +# execute block as +# begin +# rdb$set_context('USER_SESSION', 'WHO', 'INIT_DATA'); +# end +# ^ +# set term ;^ +# insert into %(target_obj)s(id, x) select row_number()over(),row_number()over() from rdb$types rows (2 + %(ROWS_TO_ADD)s); -- <<< INITIAL DATA +# commit; +# ''' % locals() +# +# runProgram('isql', [ dsn, '-q' ], sql_addi) +# +# locker_tpb = fdb.TPB() +# locker_tpb.lock_timeout = LOCKER_LOCK_TIMEOUT +# locker_tpb.lock_resolution = fdb.isc_tpb_wait +# +# con_lock_1 = fdb.connect( dsn = dsn, isolation_level=locker_tpb ) +# con_lock_2 = fdb.connect( dsn = dsn, isolation_level=locker_tpb ) +# +# con_lock_1.execute_immediate( "execute block as begin rdb$set_context('USER_SESSION', 'WHO', 'LOCKER #1'); end" ) +# con_lock_2.execute_immediate( "execute block as begin rdb$set_context('USER_SESSION', 'WHO', 'LOCKER #2'); end" ) +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# +# con_lock_1.execute_immediate( 'update %(target_obj)s set id=id where id = 1' % locals() ) +# +# sql_text=''' +# connect '%(dsn)s'; +# set list on; +# set autoddl off; +# set term ^; +# execute block as +# begin +# rdb$set_context('USER_SESSION','WHO', 'WORKER'); +# end +# ^ +# set term ;^ +# commit; +# SET KEEP_TRAN_PARAMS ON; +# set transaction read committed read consistency; +# set list off; +# set wng off; +# +# set count on; +# %(worker_dml)s -- UPDATE or DELETE or SELECT WITH LOCK; all ORDER BY ID DESC; MUST HANG BECAUSE OF LOCKERs +# +# -- check results: +# -- ############### +# +# select id from %(target_obj)s order by id; +# +# select v.old_id, v.op, v.snap_no_rank +# from v_worker_log v +# where v.op = iif( '%(checked_DML)s' = 'mer', 'upd', '%(checked_DML)s'); -- 'UPD' or 'DEL'; for 'SELECT WITH LOCK' no records will be in v_worker_log. +# +# +# --set width who 10; +# -- DO NOT check this! Values can differ here from one run to another! +# -- select id, trn, who, old_id, new_id, op, rec_vers, global_cn, snap_no from tlog_done order by id; +# rollback; +# +# ''' % dict(globals(), **locals()) +# +# f_worker_sql=open( os.path.join(context['temp_directory'],'tmp_sttm_restart_max_limit.sql'), 'w') +# f_worker_sql.write(sql_text) +# flush_and_close(f_worker_sql) +# +# +# f_worker_log=open( ''.join( ( os.path.splitext(f_worker_sql.name)[0], '.log') ), 'w') +# f_worker_err=open( ''.join( ( os.path.splitext(f_worker_log.name)[0], '.err') ), 'w') +# +# ############################################################################ +# ### L A U N C H W O R K E R U S I N G I S Q L, A S Y N C. ### +# ############################################################################ +# +# p_worker = Popen( [ context['isql_path'], '-pag', '9999999', '-q', '-i', f_worker_sql.name ],stdout=f_worker_log, stderr=f_worker_err) +# time.sleep(1) +# +# cur_lock_1 = con_lock_1.cursor() +# cur_lock_2 = con_lock_2.cursor() +# sttm = 'update %(target_obj)s set id = ? where abs( id ) = ?' % locals() +# +# +# for i in range(0,ROWS_TO_ADD): +# v_id = 2 + ROWS_TO_ADD-i +# if i % 2 == 0: +# cur_lock_2.execute( sttm, ( -abs( v_id ), v_id, ) ) +# con_lock_2.commit() +# cur_lock_2.execute( sttm, ( -abs( v_id ), v_id, ) ) +# con_lock_1.commit() +# else: +# cur_lock_1.execute( sttm, ( -abs( v_id ), v_id, ) ) +# con_lock_1.commit() +# cur_lock_1.execute( sttm, ( -abs( v_id ), v_id, ) ) +# con_lock_2.commit() +# +# cur_lock_1.close() +# cur_lock_2.close() +# +# if ROWS_TO_ADD % 2 == 0: +# con_lock_2.commit() +# con_lock_1.commit() +# else: +# con_lock_1.commit() +# con_lock_2.commit() +# +# # Close lockers: +# ################ +# for c in (con_lock_1, con_lock_2): +# c.close() +# +# # Here we wait for ISQL complete its mission: +# p_worker.wait() +# +# flush_and_close(f_worker_log) +# flush_and_close(f_worker_err) +# +# # CHECK RESULTS +# ############### +# +# print( 'target_object_type: %(target_object_type)s, checked_DML = %(checked_DML)s, iter = %(main_iter)s, restarts number to be tested: %(ROWS_TO_ADD)s' % locals() ) +# +# with open(f_init_err.name,'r') as f: +# for line in f: +# if line: +# print( 'target_object_type: %(target_object_type)s, checked_DML = %(checked_DML)s, iter = %(main_iter)s, UNEXPECTED STDERR for initial SQL: %(line)s' % locals() ) +# +# for f in (f_worker_log, f_worker_err): +# with open(f.name,'r') as g: +# for line in g: +# if line: +# logname = 'STDLOG' if f.name == f_worker_log.name else 'STDERR' +# print( 'target_object_type: %(target_object_type)s, checked_DML = %(checked_DML)s, iter = %(main_iter)s, worker %(logname)s: %(line)s' % locals() ) +# +# +# #< for main_iter in (0,1) +# # < for checked_DML in ('upd', 'mer', 'del', 'lok') +# # < for target_object_type in ('table', 'view') +# # Cleanup. +# ########## +# time.sleep(1) +# cleanup( (f_init_log, f_init_err, f_worker_sql, f_worker_log, f_worker_err) ) +# +# ''' +# 'substitutions':[ +# ('=','') +# ,('[ ]+',' ') +# ,('.*After line \\d+.*', '') +# ,('.*[\\-]?concurrent transaction number is \\d+', 'concurrent transaction number is') +# ,('.*At\\s+block\\s+line(:)?\\s+\\d+(,)?\\s+col(:)?\\s+\\d+', '') +# ] +# +# ''' +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + target_object_type: table, checked_DML = upd, iter = 0, restarts number to be tested: 10 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: Records affected: 12 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: ID + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: ======= + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: -1200 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: -1100 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: -1000 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: -900 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: -800 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: -700 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: -600 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: -500 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: -400 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: -300 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: 100 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: 200 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: Records affected: 12 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: OLD_ID OP SNAP_NO_RANK + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: ======= ====== ===================== + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: 2 UPD 1 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: 2 UPD 2 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: 1 UPD 2 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: 2 UPD 3 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: 1 UPD 3 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: 2 UPD 4 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: 1 UPD 4 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: 2 UPD 5 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: 1 UPD 5 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: 2 UPD 6 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: 1 UPD 6 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: 2 UPD 7 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: 1 UPD 7 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: 2 UPD 8 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: 1 UPD 8 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: 2 UPD 9 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: 1 UPD 9 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: 2 UPD 10 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: 1 UPD 10 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: 2 UPD 11 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: 1 UPD 11 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: -3 UPD 11 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: -4 UPD 11 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: -5 UPD 11 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: -6 UPD 11 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: -7 UPD 11 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: -8 UPD 11 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: -9 UPD 11 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: -10 UPD 11 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: -11 UPD 11 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: -12 UPD 11 + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: + target_object_type: table, checked_DML = upd, iter = 0, worker STDLOG: Records affected: 31 + + target_object_type: table, checked_DML = upd, iter = 1, restarts number to be tested: 12 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: Records affected: 2 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: ID + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: ======= + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: -14 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: -13 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: -12 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: -11 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: -10 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: -9 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: -8 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: -7 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: -6 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: -5 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: -4 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: -3 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: 1 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: 2 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: Records affected: 14 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: OLD_ID OP SNAP_NO_RANK + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: ======= ====== ===================== + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: 2 UPD 1 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: 2 UPD 2 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: 1 UPD 2 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: 2 UPD 3 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: 1 UPD 3 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: 2 UPD 4 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: 1 UPD 4 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: 2 UPD 5 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: 1 UPD 5 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: 2 UPD 6 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: 1 UPD 6 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: 2 UPD 7 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: 1 UPD 7 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: 2 UPD 8 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: 1 UPD 8 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: 2 UPD 9 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: 1 UPD 9 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: 2 UPD 10 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: 1 UPD 10 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: 2 UPD 11 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: 1 UPD 11 + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: + target_object_type: table, checked_DML = upd, iter = 1, worker STDLOG: Records affected: 21 + target_object_type: table, checked_DML = upd, iter = 1, worker STDERR: Statement failed, SQLSTATE = 40001 + target_object_type: table, checked_DML = upd, iter = 1, worker STDERR: deadlock + target_object_type: table, checked_DML = upd, iter = 1, worker STDERR: -update conflicts with concurrent update + target_object_type: table, checked_DML = upd, iter = 1, worker STDERR: -concurrent transaction number is 343 + target_object_type: table, checked_DML = upd, iter = 1, worker STDERR: After line 18 in file C:\\FBTESTING\\qa bt-repo mp mp_sttm_restart_max_limit.sql + + target_object_type: table, checked_DML = mer, iter = 0, restarts number to be tested: 10 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: Records affected: 12 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: ID + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: ======= + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: -1200 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: -1100 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: -1000 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: -900 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: -800 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: -700 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: -600 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: -500 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: -400 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: -300 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: 100 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: 200 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: Records affected: 12 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: OLD_ID OP SNAP_NO_RANK + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: ======= ====== ===================== + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: 2 UPD 1 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: 2 UPD 2 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: 1 UPD 2 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: 2 UPD 3 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: 1 UPD 3 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: 2 UPD 4 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: 1 UPD 4 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: 2 UPD 5 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: 1 UPD 5 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: 2 UPD 6 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: 1 UPD 6 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: 2 UPD 7 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: 1 UPD 7 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: 2 UPD 8 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: 1 UPD 8 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: 2 UPD 9 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: 1 UPD 9 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: 2 UPD 10 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: 1 UPD 10 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: 2 UPD 11 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: 1 UPD 11 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: -3 UPD 11 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: -4 UPD 11 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: -5 UPD 11 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: -6 UPD 11 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: -7 UPD 11 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: -8 UPD 11 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: -9 UPD 11 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: -10 UPD 11 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: -11 UPD 11 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: -12 UPD 11 + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: + target_object_type: table, checked_DML = mer, iter = 0, worker STDLOG: Records affected: 31 + + target_object_type: table, checked_DML = mer, iter = 1, restarts number to be tested: 12 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: Records affected: 2 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: ID + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: ======= + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: -14 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: -13 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: -12 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: -11 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: -10 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: -9 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: -8 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: -7 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: -6 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: -5 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: -4 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: -3 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: 1 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: 2 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: Records affected: 14 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: OLD_ID OP SNAP_NO_RANK + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: ======= ====== ===================== + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: 2 UPD 1 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: 2 UPD 2 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: 1 UPD 2 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: 2 UPD 3 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: 1 UPD 3 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: 2 UPD 4 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: 1 UPD 4 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: 2 UPD 5 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: 1 UPD 5 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: 2 UPD 6 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: 1 UPD 6 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: 2 UPD 7 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: 1 UPD 7 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: 2 UPD 8 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: 1 UPD 8 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: 2 UPD 9 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: 1 UPD 9 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: 2 UPD 10 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: 1 UPD 10 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: 2 UPD 11 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: 1 UPD 11 + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: + target_object_type: table, checked_DML = mer, iter = 1, worker STDLOG: Records affected: 21 + target_object_type: table, checked_DML = mer, iter = 1, worker STDERR: Statement failed, SQLSTATE = 40001 + target_object_type: table, checked_DML = mer, iter = 1, worker STDERR: deadlock + target_object_type: table, checked_DML = mer, iter = 1, worker STDERR: -update conflicts with concurrent update + target_object_type: table, checked_DML = mer, iter = 1, worker STDERR: -concurrent transaction number is 696 + target_object_type: table, checked_DML = mer, iter = 1, worker STDERR: After line 18 in file C:\\FBTESTING\\qa bt-repo mp mp_sttm_restart_max_limit.sql + + target_object_type: table, checked_DML = del, iter = 0, restarts number to be tested: 10 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: Records affected: 12 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: Records affected: 0 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: OLD_ID OP SNAP_NO_RANK + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: ======= ====== ===================== + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: 2 DEL 1 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: 2 DEL 2 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: 1 DEL 2 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: 2 DEL 3 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: 1 DEL 3 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: 2 DEL 4 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: 1 DEL 4 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: 2 DEL 5 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: 1 DEL 5 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: 2 DEL 6 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: 1 DEL 6 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: 2 DEL 7 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: 1 DEL 7 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: 2 DEL 8 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: 1 DEL 8 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: 2 DEL 9 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: 1 DEL 9 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: 2 DEL 10 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: 1 DEL 10 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: 2 DEL 11 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: 1 DEL 11 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: -3 DEL 11 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: -4 DEL 11 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: -5 DEL 11 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: -6 DEL 11 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: -7 DEL 11 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: -8 DEL 11 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: -9 DEL 11 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: -10 DEL 11 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: -11 DEL 11 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: -12 DEL 11 + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: + target_object_type: table, checked_DML = del, iter = 0, worker STDLOG: Records affected: 31 + + target_object_type: table, checked_DML = del, iter = 1, restarts number to be tested: 12 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: Records affected: 2 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: ID + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: ======= + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: -14 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: -13 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: -12 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: -11 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: -10 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: -9 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: -8 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: -7 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: -6 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: -5 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: -4 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: -3 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: 1 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: 2 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: Records affected: 14 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: OLD_ID OP SNAP_NO_RANK + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: ======= ====== ===================== + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: 2 DEL 1 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: 2 DEL 2 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: 1 DEL 2 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: 2 DEL 3 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: 1 DEL 3 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: 2 DEL 4 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: 1 DEL 4 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: 2 DEL 5 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: 1 DEL 5 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: 2 DEL 6 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: 1 DEL 6 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: 2 DEL 7 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: 1 DEL 7 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: 2 DEL 8 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: 1 DEL 8 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: 2 DEL 9 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: 1 DEL 9 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: 2 DEL 10 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: 1 DEL 10 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: 2 DEL 11 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: 1 DEL 11 + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: + target_object_type: table, checked_DML = del, iter = 1, worker STDLOG: Records affected: 21 + target_object_type: table, checked_DML = del, iter = 1, worker STDERR: Statement failed, SQLSTATE = 40001 + target_object_type: table, checked_DML = del, iter = 1, worker STDERR: deadlock + target_object_type: table, checked_DML = del, iter = 1, worker STDERR: -update conflicts with concurrent update + target_object_type: table, checked_DML = del, iter = 1, worker STDERR: -concurrent transaction number is 1049 + target_object_type: table, checked_DML = del, iter = 1, worker STDERR: After line 18 in file C:\\FBTESTING\\qa bt-repo mp mp_sttm_restart_max_limit.sql + + target_object_type: table, checked_DML = lok, iter = 0, restarts number to be tested: 10 + target_object_type: table, checked_DML = lok, iter = 0, worker STDLOG: + target_object_type: table, checked_DML = lok, iter = 0, worker STDLOG: ID + target_object_type: table, checked_DML = lok, iter = 0, worker STDLOG: ======= + target_object_type: table, checked_DML = lok, iter = 0, worker STDLOG: -12 + target_object_type: table, checked_DML = lok, iter = 0, worker STDLOG: -11 + target_object_type: table, checked_DML = lok, iter = 0, worker STDLOG: -10 + target_object_type: table, checked_DML = lok, iter = 0, worker STDLOG: -9 + target_object_type: table, checked_DML = lok, iter = 0, worker STDLOG: -8 + target_object_type: table, checked_DML = lok, iter = 0, worker STDLOG: -7 + target_object_type: table, checked_DML = lok, iter = 0, worker STDLOG: -6 + target_object_type: table, checked_DML = lok, iter = 0, worker STDLOG: -5 + target_object_type: table, checked_DML = lok, iter = 0, worker STDLOG: -4 + target_object_type: table, checked_DML = lok, iter = 0, worker STDLOG: -3 + target_object_type: table, checked_DML = lok, iter = 0, worker STDLOG: 1 + target_object_type: table, checked_DML = lok, iter = 0, worker STDLOG: 2 + target_object_type: table, checked_DML = lok, iter = 0, worker STDLOG: + target_object_type: table, checked_DML = lok, iter = 0, worker STDLOG: Records affected: 12 + target_object_type: table, checked_DML = lok, iter = 0, worker STDLOG: Records affected: 0 + + target_object_type: table, checked_DML = lok, iter = 1, restarts number to be tested: 12 + target_object_type: table, checked_DML = lok, iter = 1, worker STDLOG: + target_object_type: table, checked_DML = lok, iter = 1, worker STDLOG: ID + target_object_type: table, checked_DML = lok, iter = 1, worker STDLOG: ======= + target_object_type: table, checked_DML = lok, iter = 1, worker STDLOG: -14 + target_object_type: table, checked_DML = lok, iter = 1, worker STDLOG: -13 + target_object_type: table, checked_DML = lok, iter = 1, worker STDLOG: -12 + target_object_type: table, checked_DML = lok, iter = 1, worker STDLOG: -11 + target_object_type: table, checked_DML = lok, iter = 1, worker STDLOG: -10 + target_object_type: table, checked_DML = lok, iter = 1, worker STDLOG: -9 + target_object_type: table, checked_DML = lok, iter = 1, worker STDLOG: -8 + target_object_type: table, checked_DML = lok, iter = 1, worker STDLOG: -7 + target_object_type: table, checked_DML = lok, iter = 1, worker STDLOG: -6 + target_object_type: table, checked_DML = lok, iter = 1, worker STDLOG: -5 + target_object_type: table, checked_DML = lok, iter = 1, worker STDLOG: -4 + target_object_type: table, checked_DML = lok, iter = 1, worker STDLOG: -3 + target_object_type: table, checked_DML = lok, iter = 1, worker STDLOG: 1 + target_object_type: table, checked_DML = lok, iter = 1, worker STDLOG: 2 + target_object_type: table, checked_DML = lok, iter = 1, worker STDLOG: + target_object_type: table, checked_DML = lok, iter = 1, worker STDLOG: Records affected: 14 + target_object_type: table, checked_DML = lok, iter = 1, worker STDLOG: Records affected: 0 + target_object_type: table, checked_DML = lok, iter = 1, worker STDERR: Statement failed, SQLSTATE = 40001 + target_object_type: table, checked_DML = lok, iter = 1, worker STDERR: deadlock + target_object_type: table, checked_DML = lok, iter = 1, worker STDERR: -update conflicts with concurrent update + target_object_type: table, checked_DML = lok, iter = 1, worker STDERR: -concurrent transaction number is 1282 + target_object_type: table, checked_DML = lok, iter = 1, worker STDERR: -At block line: 1, col: 39 + target_object_type: table, checked_DML = lok, iter = 1, worker STDERR: After line 19 in file C:\\FBTESTING\\qa bt-repo mp mp_sttm_restart_max_limit.sql + + target_object_type: view, checked_DML = upd, iter = 0, restarts number to be tested: 10 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: Records affected: 12 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: ID + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: ======= + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: -1200 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: -1100 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: -1000 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: -900 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: -800 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: -700 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: -600 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: -500 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: -400 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: -300 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: 100 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: 200 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: Records affected: 12 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: OLD_ID OP SNAP_NO_RANK + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: ======= ====== ===================== + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: 2 UPD 1 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: 2 UPD 2 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: 1 UPD 2 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: 2 UPD 3 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: 1 UPD 3 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: 2 UPD 4 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: 1 UPD 4 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: 2 UPD 5 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: 1 UPD 5 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: 2 UPD 6 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: 1 UPD 6 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: 2 UPD 7 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: 1 UPD 7 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: 2 UPD 8 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: 1 UPD 8 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: 2 UPD 9 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: 1 UPD 9 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: 2 UPD 10 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: 1 UPD 10 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: 2 UPD 11 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: 1 UPD 11 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: -3 UPD 11 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: -4 UPD 11 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: -5 UPD 11 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: -6 UPD 11 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: -7 UPD 11 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: -8 UPD 11 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: -9 UPD 11 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: -10 UPD 11 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: -11 UPD 11 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: -12 UPD 11 + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: + target_object_type: view, checked_DML = upd, iter = 0, worker STDLOG: Records affected: 31 + + target_object_type: view, checked_DML = upd, iter = 1, restarts number to be tested: 12 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: Records affected: 2 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: ID + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: ======= + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: -14 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: -13 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: -12 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: -11 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: -10 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: -9 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: -8 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: -7 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: -6 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: -5 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: -4 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: -3 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: 1 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: 2 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: Records affected: 14 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: OLD_ID OP SNAP_NO_RANK + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: ======= ====== ===================== + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: 2 UPD 1 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: 2 UPD 2 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: 1 UPD 2 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: 2 UPD 3 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: 1 UPD 3 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: 2 UPD 4 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: 1 UPD 4 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: 2 UPD 5 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: 1 UPD 5 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: 2 UPD 6 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: 1 UPD 6 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: 2 UPD 7 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: 1 UPD 7 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: 2 UPD 8 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: 1 UPD 8 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: 2 UPD 9 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: 1 UPD 9 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: 2 UPD 10 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: 1 UPD 10 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: 2 UPD 11 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: 1 UPD 11 + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: + target_object_type: view, checked_DML = upd, iter = 1, worker STDLOG: Records affected: 21 + target_object_type: view, checked_DML = upd, iter = 1, worker STDERR: Statement failed, SQLSTATE = 40001 + target_object_type: view, checked_DML = upd, iter = 1, worker STDERR: deadlock + target_object_type: view, checked_DML = upd, iter = 1, worker STDERR: -update conflicts with concurrent update + target_object_type: view, checked_DML = upd, iter = 1, worker STDERR: -concurrent transaction number is 1630 + target_object_type: view, checked_DML = upd, iter = 1, worker STDERR: After line 18 in file C:\\FBTESTING\\qa bt-repo mp mp_sttm_restart_max_limit.sql + + target_object_type: view, checked_DML = mer, iter = 0, restarts number to be tested: 10 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: Records affected: 12 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: ID + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: ======= + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: -1200 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: -1100 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: -1000 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: -900 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: -800 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: -700 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: -600 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: -500 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: -400 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: -300 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: 100 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: 200 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: Records affected: 12 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: OLD_ID OP SNAP_NO_RANK + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: ======= ====== ===================== + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: 2 UPD 1 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: 2 UPD 2 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: 1 UPD 2 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: 2 UPD 3 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: 1 UPD 3 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: 2 UPD 4 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: 1 UPD 4 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: 2 UPD 5 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: 1 UPD 5 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: 2 UPD 6 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: 1 UPD 6 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: 2 UPD 7 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: 1 UPD 7 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: 2 UPD 8 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: 1 UPD 8 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: 2 UPD 9 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: 1 UPD 9 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: 2 UPD 10 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: 1 UPD 10 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: 2 UPD 11 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: 1 UPD 11 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: -3 UPD 11 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: -4 UPD 11 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: -5 UPD 11 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: -6 UPD 11 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: -7 UPD 11 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: -8 UPD 11 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: -9 UPD 11 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: -10 UPD 11 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: -11 UPD 11 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: -12 UPD 11 + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: + target_object_type: view, checked_DML = mer, iter = 0, worker STDLOG: Records affected: 31 + + target_object_type: view, checked_DML = mer, iter = 1, restarts number to be tested: 12 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: Records affected: 2 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: ID + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: ======= + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: -14 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: -13 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: -12 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: -11 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: -10 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: -9 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: -8 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: -7 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: -6 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: -5 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: -4 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: -3 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: 1 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: 2 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: Records affected: 14 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: OLD_ID OP SNAP_NO_RANK + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: ======= ====== ===================== + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: 2 UPD 1 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: 2 UPD 2 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: 1 UPD 2 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: 2 UPD 3 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: 1 UPD 3 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: 2 UPD 4 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: 1 UPD 4 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: 2 UPD 5 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: 1 UPD 5 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: 2 UPD 6 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: 1 UPD 6 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: 2 UPD 7 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: 1 UPD 7 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: 2 UPD 8 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: 1 UPD 8 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: 2 UPD 9 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: 1 UPD 9 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: 2 UPD 10 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: 1 UPD 10 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: 2 UPD 11 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: 1 UPD 11 + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: + target_object_type: view, checked_DML = mer, iter = 1, worker STDLOG: Records affected: 21 + target_object_type: view, checked_DML = mer, iter = 1, worker STDERR: Statement failed, SQLSTATE = 40001 + target_object_type: view, checked_DML = mer, iter = 1, worker STDERR: deadlock + target_object_type: view, checked_DML = mer, iter = 1, worker STDERR: -update conflicts with concurrent update + target_object_type: view, checked_DML = mer, iter = 1, worker STDERR: -concurrent transaction number is 1983 + target_object_type: view, checked_DML = mer, iter = 1, worker STDERR: After line 18 in file C:\\FBTESTING\\qa bt-repo mp mp_sttm_restart_max_limit.sql + + target_object_type: view, checked_DML = del, iter = 0, restarts number to be tested: 10 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: Records affected: 12 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: Records affected: 0 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: OLD_ID OP SNAP_NO_RANK + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: ======= ====== ===================== + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: 2 DEL 1 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: 2 DEL 2 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: 1 DEL 2 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: 2 DEL 3 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: 1 DEL 3 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: 2 DEL 4 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: 1 DEL 4 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: 2 DEL 5 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: 1 DEL 5 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: 2 DEL 6 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: 1 DEL 6 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: 2 DEL 7 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: 1 DEL 7 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: 2 DEL 8 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: 1 DEL 8 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: 2 DEL 9 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: 1 DEL 9 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: 2 DEL 10 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: 1 DEL 10 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: 2 DEL 11 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: 1 DEL 11 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: -3 DEL 11 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: -4 DEL 11 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: -5 DEL 11 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: -6 DEL 11 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: -7 DEL 11 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: -8 DEL 11 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: -9 DEL 11 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: -10 DEL 11 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: -11 DEL 11 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: -12 DEL 11 + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: + target_object_type: view, checked_DML = del, iter = 0, worker STDLOG: Records affected: 31 + + target_object_type: view, checked_DML = del, iter = 1, restarts number to be tested: 12 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: Records affected: 2 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: ID + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: ======= + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: -14 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: -13 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: -12 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: -11 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: -10 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: -9 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: -8 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: -7 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: -6 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: -5 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: -4 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: -3 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: 1 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: 2 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: Records affected: 14 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: OLD_ID OP SNAP_NO_RANK + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: ======= ====== ===================== + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: 2 DEL 1 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: 2 DEL 2 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: 1 DEL 2 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: 2 DEL 3 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: 1 DEL 3 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: 2 DEL 4 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: 1 DEL 4 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: 2 DEL 5 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: 1 DEL 5 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: 2 DEL 6 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: 1 DEL 6 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: 2 DEL 7 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: 1 DEL 7 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: 2 DEL 8 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: 1 DEL 8 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: 2 DEL 9 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: 1 DEL 9 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: 2 DEL 10 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: 1 DEL 10 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: 2 DEL 11 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: 1 DEL 11 + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: + target_object_type: view, checked_DML = del, iter = 1, worker STDLOG: Records affected: 21 + target_object_type: view, checked_DML = del, iter = 1, worker STDERR: Statement failed, SQLSTATE = 40001 + target_object_type: view, checked_DML = del, iter = 1, worker STDERR: deadlock + target_object_type: view, checked_DML = del, iter = 1, worker STDERR: -update conflicts with concurrent update + target_object_type: view, checked_DML = del, iter = 1, worker STDERR: -concurrent transaction number is 2336 + target_object_type: view, checked_DML = del, iter = 1, worker STDERR: After line 18 in file C:\\FBTESTING\\qa bt-repo mp mp_sttm_restart_max_limit.sql + + target_object_type: view, checked_DML = lok, iter = 0, restarts number to be tested: 10 + target_object_type: view, checked_DML = lok, iter = 0, worker STDLOG: + target_object_type: view, checked_DML = lok, iter = 0, worker STDLOG: ID + target_object_type: view, checked_DML = lok, iter = 0, worker STDLOG: ======= + target_object_type: view, checked_DML = lok, iter = 0, worker STDLOG: 1 + target_object_type: view, checked_DML = lok, iter = 0, worker STDLOG: 2 + target_object_type: view, checked_DML = lok, iter = 0, worker STDLOG: 3 + target_object_type: view, checked_DML = lok, iter = 0, worker STDLOG: 4 + target_object_type: view, checked_DML = lok, iter = 0, worker STDLOG: 5 + target_object_type: view, checked_DML = lok, iter = 0, worker STDLOG: 6 + target_object_type: view, checked_DML = lok, iter = 0, worker STDLOG: 7 + target_object_type: view, checked_DML = lok, iter = 0, worker STDLOG: 8 + target_object_type: view, checked_DML = lok, iter = 0, worker STDLOG: 9 + target_object_type: view, checked_DML = lok, iter = 0, worker STDLOG: 10 + target_object_type: view, checked_DML = lok, iter = 0, worker STDLOG: 11 + target_object_type: view, checked_DML = lok, iter = 0, worker STDLOG: 12 + target_object_type: view, checked_DML = lok, iter = 0, worker STDLOG: + target_object_type: view, checked_DML = lok, iter = 0, worker STDLOG: Records affected: 12 + target_object_type: view, checked_DML = lok, iter = 0, worker STDLOG: Records affected: 0 + target_object_type: view, checked_DML = lok, iter = 0, worker STDERR: Statement failed, SQLSTATE = 42000 + target_object_type: view, checked_DML = lok, iter = 0, worker STDERR: Dynamic SQL Error + target_object_type: view, checked_DML = lok, iter = 0, worker STDERR: -SQL error code = -104 + target_object_type: view, checked_DML = lok, iter = 0, worker STDERR: -WITH LOCK can be used only with a single physical table + target_object_type: view, checked_DML = lok, iter = 0, worker STDERR: After line 19 in file C:\\FBTESTING\\qa bt-repo mp mp_sttm_restart_max_limit.sql + + target_object_type: view, checked_DML = lok, iter = 1, restarts number to be tested: 12 + target_object_type: view, checked_DML = lok, iter = 1, worker STDLOG: + target_object_type: view, checked_DML = lok, iter = 1, worker STDLOG: ID + target_object_type: view, checked_DML = lok, iter = 1, worker STDLOG: ======= + target_object_type: view, checked_DML = lok, iter = 1, worker STDLOG: 1 + target_object_type: view, checked_DML = lok, iter = 1, worker STDLOG: 2 + target_object_type: view, checked_DML = lok, iter = 1, worker STDLOG: 3 + target_object_type: view, checked_DML = lok, iter = 1, worker STDLOG: 4 + target_object_type: view, checked_DML = lok, iter = 1, worker STDLOG: 5 + target_object_type: view, checked_DML = lok, iter = 1, worker STDLOG: 6 + target_object_type: view, checked_DML = lok, iter = 1, worker STDLOG: 7 + target_object_type: view, checked_DML = lok, iter = 1, worker STDLOG: 8 + target_object_type: view, checked_DML = lok, iter = 1, worker STDLOG: 9 + target_object_type: view, checked_DML = lok, iter = 1, worker STDLOG: 10 + target_object_type: view, checked_DML = lok, iter = 1, worker STDLOG: 11 + target_object_type: view, checked_DML = lok, iter = 1, worker STDLOG: 12 + target_object_type: view, checked_DML = lok, iter = 1, worker STDLOG: 13 + target_object_type: view, checked_DML = lok, iter = 1, worker STDLOG: 14 + target_object_type: view, checked_DML = lok, iter = 1, worker STDLOG: + target_object_type: view, checked_DML = lok, iter = 1, worker STDLOG: Records affected: 14 + target_object_type: view, checked_DML = lok, iter = 1, worker STDLOG: Records affected: 0 + target_object_type: view, checked_DML = lok, iter = 1, worker STDERR: Statement failed, SQLSTATE = 42000 + target_object_type: view, checked_DML = lok, iter = 1, worker STDERR: Dynamic SQL Error + target_object_type: view, checked_DML = lok, iter = 1, worker STDERR: -SQL error code = -104 + target_object_type: view, checked_DML = lok, iter = 1, worker STDERR: -WITH LOCK can be used only with a single physical table + target_object_type: view, checked_DML = lok, iter = 1, worker STDERR: After line 19 in file C:\\FBTESTING\\qa bt-repo mp mp_sttm_restart_max_limit.sql + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_read_consist_sttm_restart_max_limit_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + 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 new file mode 100644 index 00000000..9b563130 --- /dev/null +++ b/tests/functional/transactions/test_read_consist_sttm_restart_on_delete_01.py @@ -0,0 +1,420 @@ +#coding:utf-8 +# +# id: functional.transactions.read_consist_sttm_restart_on_delete_01 +# title: READ CONSISTENCY. Check creation of new statement-level snapshot and restarting changed caused by DELETE. Test-01. +# decription: +# Initial article for reading: +# https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:11504247549852 +# Note on terms which are used there: "BLOCKER", "LONG" and "FIRSTLAST" - their names are slightly changed here +# to: LOCKER-1, WORKER and LOCKER-2 respectively. +# +# ********************************************** +# +# This test verifies that statement-level snapshot and restart will be performed when "main" session ("worker") +# performs DELETE statement and is involved in update conflicts. +# ("When update conflict is detected <...> then engine <...> creates new statement-level snapshot and restart execution...") +# +# ::: NB ::: +# This test uses script %FBT_REPO% +# iles +# ead-consist-sttm-restart-DDL.sql which contains common DDL for all other such tests. +# Particularly, it contains two TRIGGERS (TLOG_WANT and TLOG_DONE) which are used for logging of planned actions and actual +# results against table TEST. These triggers use AUTONOMOUS transactions in order to have ability to see results in any +# outcome of test. +# +# ############### +# Following scenario if executed here (see also: "doc\\README.read_consistency.md"; hereafer is marked as "DOC"): +# +# * five rows are inserted into the table TEST, with IDs: 1,2,3,4,5 +# * session 'locker-1' ("BLOCKER" in Tom Kyte's article ): +# update test set id = id where id = 5; +# +# * session 'worker' ("LONG" in TK article) has mission: +# delete from test order by id rows ( iif(exists(select 1 from test where id < 0), 3, 8 ) ) // using TIL = read committed read consistency +# +# // Execution will have PLAN ORDER . NOTE: NUMBER OF ROWS TO BE DELETED DEPENDS ON EXISTENSE OF ID < 0! +# // Worker starts with deletion (avaliable for its cursor) rows with ID = 1...4 but can not change row with ID = 5 because of locker-1. +# +# * session 'locker-2' ("FIRSTLAST" in TK article): +# (1) insert into test(id) values(6); +# (2) commit; +# (3) update test set id=id where id = 6; +# // session-'worker' remains waiting at this point because row with ID = 5 is still occupied by by locker-1 +# // but worker must further see record with (new) id = 6 because its TIL was changed to RC NO RECORD_VERSION. +# +# * session 'locker-1': +# (1) commit; +# (2) insert into test(id) values(7); +# (3) commit; +# (4) update test set id=id where id = 7; +# +# // This: '(1) commit' - will release record with ID = 5. Worker sees this record and put write-lock on it. +# // [DOC]: "b) engine put write lock on conflicted record" +# // Because of TIL = RC NRV session-'worker' must see all committed records regardless on its own snapshot. +# // Worker resumes search for any rows which with taking in account required order of its DML (i.e. 'ORDER BY ID') +# // and number of records to be deleted: 'rows ( iif(exists(select 1 from test where id < 0), 3, 8 ) )' +# // [DOC]: "c) engine continue to evaluate remaining records of update\\delete cursor and put write locks on it too" +# // Worker starts to search records which must be involved in its DML and *found* first sucn row: it has ID = 1. +# // Then it goes on through IDs = 2...5 and stops on ID=6 because id is occupied by locker-2. +# // BECAUSE OF FACT THAT AT LEAST ONE ROW *WAS FOUND* - STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# // [DOC]: "d) when there is *no more* records to fetch, engine start to undo all actions performed since +# // top-level statement execution starts and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# +# * session 'locker-2': +# (1) commit; +# (2) insert into test(id) values(8); +# (3) commit; +# (4) update test set id=id where id = 8; +# +# // This: '(1) commit' - will release record with ID = 6. Worker sees this record and put write-lock on it. +# // [DOC]: "b) engine put write lock on conflicted record" +# // Because of TIL = RC NRV session-'worker' must see all committed records regardless on its own snapshot. +# // Worker resumes search for any rows which with taking in account required order of its DML (i.e. 'ORDER BY ID') +# // and number of records to be deleted: 'rows ( iif(exists(select 1 from test where id < 0), 3, 8 ) )' +# // [DOC]: "c) engine continue to evaluate remaining records of update\\delete cursor and put write locks on it too" +# // Worker starts to search records which must be involved in its DML and *found* first sucn row: it has ID = 1. +# // Then it goes on through IDs = 2...6 and stops on ID=7 because id is occupied by locker-1. +# // BECAUSE OF FACT THAT AT LEAST ONE ROW *WAS FOUND* - STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# // [DOC]: "d) when there is *no more* records to fetch, engine start to undo all actions performed since +# // top-level statement execution starts and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# +# +# * session 'locker-1': +# (1) commit; +# (2) insert into test(id) values(-1); +# (3) commit; +# (4) update test set id=id where id = -1; +# +# // This: '(1) commit' - will release record with ID = 8. Worker sees this record and put write-lock on it. +# // [DOC]: "b) engine put write lock on conflicted record" +# // Because of TIL = RC NRV session-'worker' must see all committed records regardless on its own snapshot. +# // Worker resumes search for any rows which with taking in account required order of its DML (i.e. 'ORDER BY ID') +# // and number of records to be deleted: 'rows ( iif(exists(select 1 from test where id < 0), 3, 8 ) )' +# // Here worker starts from row with ID = -1 but can not go on because it is occupied by locker-1 +# +# * session 'locker-2': +# (1) commit; +# // This releases record with ID = 8 but worker can not do somewhat here: it is still waiting for row with ID = -1. +# +# * session 'locker-1': +# (1) commit; +# +# // This releases row with ID = -1. Worker sees this record and put write-lock on it. +# // [DOC]: "b) engine put write lock on conflicted record" +# // Because of TIL = RC NRV session-'worker' must see all committed records regardless on its own snapshot. +# // Worker resumes search for any rows which with taking in account required order of its DML (i.e. 'ORDER BY ID') +# // and number of records to be deleted: 'rows ( iif(exists(select 1 from test where id < 0), 3, 8 ) )' +# // One row *exists* with ID < 0 thus worker must delete only 3 rows (according to 'ROWS ...' clause) rather than 8. +# // At this point there are no more records to be locked (by worker) that meet cursor condition: worker did put +# // write locks on all rows that meet its cursor conditions. +# // BECAUSE OF FACT THAT NO MORE RECORDS FOUND TO BE LOCKED, WORKER DOES UNDO BUT KEEP LOCKS AND THEN +# // MAKES FIRST STATEMENT-LEVEL RESTART. This restart is also the last in this test. +# +# +# Expected result: +# * session-'worker' must *successfully* complete deletion of THREE rows with ID = -1, 1 and 2. Other rows (ID=3...8) must remain. +# +# * Two unique values must be in the column TLOG_DONE.SNAP_NO for session-'worker' when it performed DELETE statement: first of them +# was created by initial statement start and second reflect SINGLE restart (this column has values which are evaluated using +# rdb$get_context('SYSTEM', 'SNAPSHOT_NUMBER') -- see trigger TEST_AIUD). +# It is enough to count these values using COUNT(*) or enumarate them by DENSE_RANK() function. +# +# NOTE: concrete values of fields TRN, GLOBAL_CN and SNAP_NO in the TLOG_DONE can differ from one to another run! +# This is because of concurrent nature of connections that work against database. We must not assume that these values will be constant. +# +# ################ +# +# Checked on 4.0.0.2144 +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# from subprocess import Popen +# from fdb import services +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql_init_ddl = os.path.join(context['files_location'],'read-consist-sttm-restart-DDL.sql') +# +# for checked_mode in('table', 'view'): +# +# target_obj = 'test' if checked_mode == 'table' else 'v_test' +# +# f_init_log=open( os.path.join(context['temp_directory'],'read-consist-sttm-restart-DDL.log'), 'w') +# f_init_err=open( ''.join( ( os.path.splitext(f_init_log.name)[0], '.err') ), 'w') +# +# subprocess.call( [context['isql_path'], dsn, '-q', '-i', sql_init_ddl], stdout=f_init_log, stderr=f_init_err ) +# flush_and_close(f_init_log) +# flush_and_close(f_init_err) +# +# # add rows with ID = 1,2,3,4,5: +# sql_addi=''' +# set term ^; +# execute block as +# begin +# rdb$set_context('USER_SESSION', 'WHO', 'INIT_DATA'); +# end +# ^ +# set term ;^ +# insert into %(target_obj)s(id, x) +# select row_number()over(),row_number()over() +# from rdb$types rows 5; +# commit; +# ''' % locals() +# runProgram('isql', [ dsn, '-q' ], sql_addi) +# +# con_lock_1 = fdb.connect( dsn = dsn ) +# con_lock_2 = fdb.connect( dsn = dsn ) +# con_lock_1.execute_immediate( "execute block as begin rdb$set_context('USER_SESSION', 'WHO', 'LOCKER #1'); end" ) +# con_lock_2.execute_immediate( "execute block as begin rdb$set_context('USER_SESSION', 'WHO', 'LOCKER #2'); end" ) +# +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# +# con_lock_1.execute_immediate( 'update %(target_obj)s set id=id where id = 5' % locals() ) +# +# sql_text=''' +# connect '%(dsn)s'; +# set list on; +# set autoddl off; +# set term ^; +# execute block returns (whoami varchar(30)) as +# begin +# whoami = 'WORKER'; -- , ATT#' || current_connection; +# rdb$set_context('USER_SESSION','WHO', whoami); +# -- suspend; +# end +# ^ +# set term ;^ +# commit; +# --set echo on; +# SET KEEP_TRAN_PARAMS ON; +# set transaction read committed read consistency; +# --select current_connection, current_transaction from rdb$database; +# set list off; +# set wng off; +# --set plan on; +# set count on; +# +# delete from %(target_obj)s order by id rows ( iif(exists(select 1 from %(target_obj)s where id < 0), 3, 8 ) ); -- THIS MUST BE LOCKED +# +# -- check results: +# -- ############### +# +# select id from %(target_obj)s order by id; -- this will produce output only after all lockers do their commit/rollback +# +# select v.old_id, v.op, v.snap_no_rank +# from v_worker_log v +# where v.op = 'del'; +# +# set width who 10; +# -- DO NOT check this! Values can differ here from one run to another! +# --select id, trn, who, old_id, new_id, op, rec_vers, global_cn, snap_no from tlog_done order by id; +# +# rollback; +# +# ''' % dict(globals(), **locals()) +# +# f_worker_sql=open( os.path.join(context['temp_directory'],'tmp_sttm_restart_on_delete_01.sql'), 'w') +# f_worker_sql.write(sql_text) +# flush_and_close(f_worker_sql) +# +# +# f_worker_log=open( ''.join( ( os.path.splitext(f_worker_sql.name)[0], '.log') ), 'w') +# f_worker_err=open( ''.join( ( os.path.splitext(f_worker_log.name)[0], '.err') ), 'w') +# +# ############################################################################ +# ### L A U N C H W O R K E R U S I N G I S Q L, A S Y N C. ### +# ############################################################################ +# +# p_worker = Popen( [ context['isql_path'], '-pag', '999999', '-q', '-i', f_worker_sql.name ],stdout=f_worker_log, stderr=f_worker_err) +# time.sleep(1) +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# con_lock_2.execute_immediate( 'insert into %(target_obj)s(id) values(6)' % locals() ) +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'update %(target_obj)s set id=id where id = 6' % locals() ) +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# con_lock_1.commit() +# con_lock_1.execute_immediate( 'insert into %(target_obj)s(id) values(7)' % locals() ) +# con_lock_1.commit() +# con_lock_1.execute_immediate( 'update %(target_obj)s set id=id where id = 7' % locals() ) +# +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'insert into %(target_obj)s(id) values(8)' % locals() ) +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'update %(target_obj)s set id=id where id = 8' % locals() ) +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# con_lock_1.commit() +# con_lock_1.execute_immediate( 'insert into %(target_obj)s(id) values(-1)' % locals() ) +# con_lock_1.commit() +# +# con_lock_2.commit() +# +# con_lock_1.commit() +# +# # Here we wait for ISQL complete its mission: +# p_worker.wait() +# +# flush_and_close(f_worker_log) +# flush_and_close(f_worker_err) +# +# # Close lockers: +# ################ +# for c in (con_lock_1, con_lock_2): +# c.close() +# +# +# # CHECK RESULTS +# ############### +# with open(f_worker_log.name,'r') as f: +# for line in f: +# if line.strip(): +# print('checked_mode: %(checked_mode)s, STDLOG: %(line)s' % locals()) +# +# for f in (f_init_err, f_worker_err): +# with open(f.name,'r') as g: +# for line in g: +# if line.strip(): +# print( 'checked_mode: ', checked_mode, ' UNEXPECTED STDERR IN ' + g.name + ':', line) +# +# #=4.0') +@pytest.mark.xfail +def test_read_consist_sttm_restart_on_delete_01_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + 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 new file mode 100644 index 00000000..aaddb929 --- /dev/null +++ b/tests/functional/transactions/test_read_consist_sttm_restart_on_delete_02.py @@ -0,0 +1,404 @@ +#coding:utf-8 +# +# id: functional.transactions.read_consist_sttm_restart_on_delete_02 +# title: READ CONSISTENCY. Check creation of new statement-level snapshot and restarting changed caused by DELETE. Test-02. +# decription: +# Initial article for reading: +# https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:11504247549852 +# Note on terms which are used there: "BLOCKER", "LONG" and "FIRSTLAST" - their names are slightly changed here +# to: LOCKER-1, WORKER and LOCKER-2 respectively. +# See also: doc\\README.read_consistency.md +# +# ********************************************** +# +# This test verifies that statement-level snapshot and restart will be performed when "main" session ("worker") +# performs DELETE statement and is involved in update conflicts. +# ("When update conflict is detected <...> then engine <...> creates new statement-level snapshot and restart execution...") +# +# ::: NB ::: +# This test uses script %FBT_REPO% +# iles +# ead-consist-sttm-restart-DDL.sql which contains common DDL for all other such tests. +# Particularly, it contains two TRIGGERS (TLOG_WANT and TLOG_DONE) which are used for logging of planned actions and actual +# results against table TEST. These triggers use AUTONOMOUS transactions in order to have ability to see results in any +# outcome of test. +# +# +# ############### +# Following scenario if executed here (see also: "doc\\README.read_consistency.md"; hereafer is marked as "DOC"): +# +# * five rows are inserted into the table TEST, with IDs: 1...5 +# * session 'locker-1' ("BLOCKER" in Tom Kyte's article ); +# update set id=id where id = 5; +# +# * session 'worker' ("LONG" in TK article) has mission: +# delete from test where id < 0 or id >= 3 order by id; // using TIL = read committed read consistency +# +# // Execution will have PLAN ORDER . +# // It will delete rows with ID = 3 and 4 but hang on row with ID = 5 because of locker-1; +# // Update conflict appears here and, because of this, worker temporary changes its TIL to RC no record_version (RC NRV). +# // [DOC]: "a) transaction isolation mode temporarily switched to the READ COMMITTED *NO RECORD VERSION MODE*" +# // This (new) TIL allows worker further to see all committed versions, regardless of its own snapshot. +# +# * session 'locker-2' ("FIRSTLAST" in TK article): +# (1) insert into test(id) values(-1); // i.e. LESS than min(id)=1 that existed at the start of session-worker statement +# (2) commit; +# (3) update test set id=id where id = -1; +# // Session-worker must still hang because row with ID = 5 is occupied by locker-1. +# // But worker must further see record with (new) id = -1 because its TIL was changed to RC NO RECORD_VERSION. +# +# * session 'locker-1': +# (1) commit; +# (2) insert into test(id) values(-2); // i.e. LESS than min(id)=-1 that existed before this +# (3) commit; +# (4) update test set id=id where id = -2; +# // This: '(1) commit' - will release record with ID = 5. Worker sees this record and put write-lock on it. +# // [DOC]: "b) engine put write lock on conflicted record" +# // Because of TIL = RC NRV session-'worker' must see all committed records regardless on its own snapshot. +# // Worker resumes search for any rows which meet condition: "id < 0 or id >= 3", and it does this with taking in account +# // required order of its DML (i.e. 'ORDER BY ID') +# // [DOC]: "c) engine continue to evaluate remaining records of update\\delete cursor and put write locks on it too" +# // Worker starts to search records which must be involved in its DML and *found* first sucn row: it has ID = -1. +# // NB. This row currently can NOT be deleted by worker because locker-2 has uncommitted update of it. +# // BECAUSE OF FACT THAT AT LEAST ONE ROW *WAS FOUND* - STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# // :::!! NB, AGAIN !! ::: restart NOT occurs here because at least one records found, see: +# // [DOC]: "d) when there is *no more* records to fetch, engine start to undo all actions performed since +# // top-level statement execution starts and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# +# +# * session 'locker-2': +# (1) commit; +# (2) insert into test(id) values(-3); // i.e. LESS than min(id)=-1 that existed before this +# (3) commit; +# (4) update test set id=id where id = -3; +# +# // This: '(1) commit' - will release record with ID = -1. Worker sees this record and put write-lock on it. +# // [DOC]: "b) engine put write lock on conflicted record" +# // Because of TIL = RC NRV session-'worker' must see all committed records regardless on its own snapshot. +# // Worker resumes search for any rows which meet condition: "id < 0 or id >= 3", and it does this with taking in account +# // required order of its DML (i.e. 'ORDER BY ID') +# // [DOC]: "c) engine continue to evaluate remaining records of update\\delete cursor and put write locks on it too" +# // Worker starts to search records which must be involved in its DML and *found* first sucn row: it has ID = -2. +# // NB. This row currently can NOT be deleted by worker because locker-1 has uncommitted update of it. +# // BECAUSE OF FACT THAT AT LEAST ONE ROW *WAS FOUND* - STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# +# * session 'locker-1': +# commit; +# // This: '(1) commit' - will release record with ID = -2. Worker sees this record and put write-lock on it. +# // Because of worker TIL = RC NRV, he must see all committed records regardless on its own snapshot. +# // Worker resumes search for any rows with ID < 0, and it does this with taking in account required order +# // of its DML (i.e. 'ORDER BY ID') +# // Worker starts to search records which must be involved in its DML and *found* first sucn row with ID = -3. +# // NB. This row currently can NOT be deleted by worker because locker-2 has uncommitted update of it. +# // BECAUSE OF FACT THAT AT LEAST ONE ROW *WAS FOUND* - STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# +# * session 'locker-2': +# commit; +# // This will release record with ID=-3. Worker sees this record and put write-lock on it. +# // Because of worker TIL = RC NRV, he must see all committed records regardless on its own snapshot. +# // Worker resumes search for any rows with ID < 0, and it does this with taking in account required order +# // of its DML (i.e. 'ORDER BY ID'). +# // At this point there are no more records to be locked (by worker) that meet cursor condition: worker did put +# // write locks on all rows that meet its cursor conditions (ID < 0 or ID>= 3). +# // BECAUSE OF FACT THAT NO MORE RECORDS FOUND TO BE LOCKED, WORKER DOES UNDO BUT KEEP LOCKS AND THEN +# // MAKES FIRST STATEMENT-LEVEL RESTART. This restart is also the last in this test. +# +# Expected result: +# * session-'worker' must *successfully* complete deletion of all rows with ID < 0 or ID >= 3. Rows with ID = 1 and 2 must remain. +# +# * Two unique values must be in the column TLOG_DONE.SNAP_NO for session-'worker' when it performed DELETE statement: first of them +# was created by initial statement start and second reflect SINGLE restart (this column has values which are evaluated using +# rdb$get_context('SYSTEM', 'SNAPSHOT_NUMBER') -- see trigger TEST_AIUD). +# It is enough to count these values using COUNT(*) or enumarate them by DENSE_RANK() function. +# +# NOTE: concrete values of fields TRN, GLOBAL_CN and SNAP_NO in the TLOG_DONE can differ from one to another run! +# This is because of concurrent nature of connections that work against database. We must not assume that these values will be constant. +# +# ################ +# +# +# Checked on 4.0.0.2144 SS/CS +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# from subprocess import Popen +# from fdb import services +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql_init_ddl = os.path.join(context['files_location'],'read-consist-sttm-restart-DDL.sql') +# +# for checked_mode in('table', 'view'): +# +# target_obj = 'test' if checked_mode == 'table' else 'v_test' +# +# f_init_log=open( os.path.join(context['temp_directory'],'read-consist-sttm-restart-DDL.log'), 'w') +# f_init_err=open( ''.join( ( os.path.splitext(f_init_log.name)[0], '.err') ), 'w') +# +# subprocess.call( [context['isql_path'], dsn, '-q', '-i', sql_init_ddl], stdout=f_init_log, stderr=f_init_err ) +# flush_and_close(f_init_log) +# flush_and_close(f_init_err) +# +# # add rows with ID = 1,2,3,4,5: +# sql_addi=''' +# set term ^; +# execute block as +# begin +# rdb$set_context('USER_SESSION', 'WHO', 'INIT_DATA'); +# end +# ^ +# set term ;^ +# insert into %(target_obj)s(id, x) +# select row_number()over(),row_number()over() +# from rdb$types rows 5; +# commit; +# ''' % locals() +# runProgram('isql', [ dsn, '-q' ], sql_addi) +# +# con_lock_1 = fdb.connect( dsn = dsn ) +# con_lock_2 = fdb.connect( dsn = dsn ) +# con_lock_1.execute_immediate( "execute block as begin rdb$set_context('USER_SESSION', 'WHO', 'LOCKER #1'); end" ) +# con_lock_2.execute_immediate( "execute block as begin rdb$set_context('USER_SESSION', 'WHO', 'LOCKER #2'); end" ) +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# +# con_lock_1.execute_immediate( 'update %(target_obj)s set id=id where id = 5' % locals() ) +# +# sql_text=''' +# connect '%(dsn)s'; +# set list on; +# set autoddl off; +# set term ^; +# execute block returns (whoami varchar(30)) as +# begin +# whoami = 'WORKER'; -- , ATT#' || current_connection; +# rdb$set_context('USER_SESSION','WHO', whoami); +# -- suspend; +# end +# ^ +# set term ;^ +# commit; +# --set echo on; +# SET KEEP_TRAN_PARAMS ON; +# set transaction read committed read consistency; +# --select current_connection, current_transaction from rdb$database; +# set list off; +# set wng off; +# --set plan on; +# set count on; +# +# delete from %(target_obj)s where id < 0 or id >= 3 order by id; -- THIS MUST BE LOCKED +# +# -- check results: +# -- ############### +# +# select id from %(target_obj)s order by id; -- this will produce output only after all lockers do their commit/rollback +# +# select v.old_id, v.op, v.snap_no_rank +# from v_worker_log v +# where v.op = 'del'; +# +# set width who 10; +# -- DO NOT check this! Values can differ here from one run to another! +# -- select id, trn, who, old_id, new_id, op, rec_vers, global_cn, snap_no from tlog_done order by id; +# +# rollback; +# +# ''' % dict(globals(), **locals()) +# +# f_worker_sql=open( os.path.join(context['temp_directory'],'tmp_sttm_restart_on_delete_02.sql'), 'w') +# f_worker_sql.write(sql_text) +# flush_and_close(f_worker_sql) +# +# +# f_worker_log=open( ''.join( ( os.path.splitext(f_worker_sql.name)[0], '.log') ), 'w') +# f_worker_err=open( ''.join( ( os.path.splitext(f_worker_log.name)[0], '.err') ), 'w') +# +# ############################################################################ +# ### L A U N C H W O R K E R U S I N G I S Q L, A S Y N C. ### +# ############################################################################ +# +# p_worker = Popen( [ context['isql_path'], '-pag', '999999', '-q', '-i', f_worker_sql.name ],stdout=f_worker_log, stderr=f_worker_err) +# time.sleep(1) +# +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# # Insert ID value that is less than previous min(id). +# # Session-worker is executing its statement using PLAN ORDER, +# # and it should see this new value and restart its statement: +# con_lock_2.execute_immediate( 'insert into %(target_obj)s(id) values(-1)' % locals() ) +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'update %(target_obj)s set id=id where id = -1' % locals() ) +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# con_lock_1.commit() +# con_lock_1.execute_immediate( 'insert into %(target_obj)s(id) values(-2)' % locals() ) +# con_lock_1.commit() +# con_lock_1.execute_immediate( 'update %(target_obj)s set id=id where id = -2' % locals() ) +# +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# # Insert ID value that is less than previous min(id). +# # Session-worker is executing its statement using PLAN ORDER, +# # and it should see this new value and restart its statement: +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'insert into %(target_obj)s(id) values(-3)' % locals() ) +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'update %(target_obj)s set id=id where id = -3' % locals() ) +# +# con_lock_1.commit() +# con_lock_2.commit() +# +# # Here we wait for ISQL complete its mission: +# p_worker.wait() +# +# flush_and_close(f_worker_log) +# flush_and_close(f_worker_err) +# +# # Close lockers: +# ################ +# for c in (con_lock_1, con_lock_2): +# c.close() +# +# +# # CHECK RESULTS +# ############### +# with open(f_worker_log.name,'r') as f: +# for line in f: +# if line.strip(): +# print('checked_mode: %(checked_mode)s, STDLOG: %(line)s' % locals()) +# +# for f in (f_init_err, f_worker_err): +# with open(f.name,'r') as g: +# for line in g: +# if line.strip(): +# print( 'checked_mode: ', checked_mode, ' UNEXPECTED STDERR IN ' + g.name + ':', line) +# +# +# #=4.0') +@pytest.mark.xfail +def test_read_consist_sttm_restart_on_delete_02_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + 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 new file mode 100644 index 00000000..df923a8e --- /dev/null +++ b/tests/functional/transactions/test_read_consist_sttm_restart_on_delete_03.py @@ -0,0 +1,372 @@ +#coding:utf-8 +# +# id: functional.transactions.read_consist_sttm_restart_on_delete_03 +# title: READ CONSISTENCY. Check creation of new statement-level snapshot and restarting changed caused by DELETE. Test-03. +# decription: +# Initial article for reading: +# https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:11504247549852 +# Note on terms which are used there: "BLOCKER", "LONG" and "FIRSTLAST" - their names are slightly changed here +# to: LOCKER-1, WORKER and LOCKER-2 respectively. +# See also: doc\\README.read_consistency.md +# +# ********************************************** +# +# This test verifies that statement-level snapshot and restart will be performed when "main" session ("worker") +# performs DELETE statement and is involved in update conflicts. +# ("When update conflict is detected <...> then engine <...> creates new statement-level snapshot and restart execution...") +# +# ::: NB ::: +# This test uses script %FBT_REPO% +# iles +# ead-consist-sttm-restart-DDL.sql which contains common DDL for all other such tests. +# Particularly, it contains two TRIGGERS (TLOG_WANT and TLOG_DONE) which are used for logging of planned actions and actual +# results against table TEST. These triggers use AUTONOMOUS transactions in order to have ability to see results in any +# outcome of test. +# +# ############### +# Following scenario if executed here (see also: "doc\\README.read_consistency.md"; hereafer is marked as "DOC"): +# +# * add new table that is child to test: TDETL (with FK that references TEST and 'on delete cascade' clause) +# * three rows are inserted into the table TEST, with IDs: 2, 3 and 5. +# +# * session 'locker-1' ("BLOCKER" in Tom Kyte's article ): +# update set id=id where id = 5; +# +# * session 'worker' ("LONG" in TK article) has mission: +# delete from test where id >= 3 order by id; // using TIL = read committed read consistency +# +# // Execution will have PLAN ORDER . +# // It will delete (first avaliable for cursor) row with ID = 3 but can not change row with ID = 5 because of locker-1. +# // Update conflict appears here and, because of this, worker temporary changes its TIL to RC no record_version (RC NRV). +# // [DOC]: "a) transaction isolation mode temporarily switched to the READ COMMITTED *NO RECORD VERSION MODE*" +# // This (new) TIL allows worker further to see all committed versions, regardless of its own snapshot. +# +# * session 'locker-2' ("FIRSTLAST" in TK article): replaces ID = 2 with new value = 4, then commits +# and locks this record again: +# (1) update test set id = 4 where id = 2; +# (2) commit; +# (3) update test set id=id where id = 4; +# // session-'worker' remains waiting at this point because row with ID = 5 is still occupied by by locker-1 +# // but worker must further see record with (new) id = 4 because its TIL was changed to RC NO RECORD_VERSION. +# +# * session 'locker-1': +# (1) commit; +# (2) insert into test(id) values(6); +# (3) insert into detl(id, pid) values(6001, 6); +# (4) commit; +# (5) update test set id=id where id=6; +# // first of these statements: '(1) commit' - will release record with ID = 5. +# // Worker sees this record (because of TIL = RC NRV) and put write-lock on it. +# // [DOC]: "b) engine put write lock on conflicted record" +# // Also, because worker TIL = RC NRV, it will see two new rows with ID = 4 and 6, and they meet worker cursor condition ("id>=3"). +# // Worker resumes search for any rows with ID >=3, and it does this with taking in account "ORDER BY ID ASC". +# // [DOC]: "c) engine continue to evaluate remaining records of update\\delete cursor and put write locks on it too" +# // Worker starts to search records which must be involved in its DML and *found* sucn rows (with ID = 4 and 6). +# // NB. These rows currently can NOT be deleted by worker because of locker-2 and locker-1 have uncommitted updates. +# // BECAUSE OF FACT THAT AT LEAST ONE ROW *WAS FOUND* - STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# // :::!! NB, AGAIN !! ::: restart NOT occurs here because at least one records found, see: +# // [DOC]: "d) when there is *no more* records to fetch, engine start to undo all actions performed since +# // top-level statement execution starts and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# +# * session 'locker-2': +# commit; +# // This will release record with ID = 4 (but row with ID = 6 is still inaccessible because of locker-1). +# // Worker sees record (because of TIL = RC NRV) with ID = 4 and put write-lock on it. +# // Then worker resumes search for any (new) rows with ID >= 3, and it does this with taking in account required order +# // of its DML (i.e. ORDER BY ID ASC). +# // [DOC]: "c) engine continue to evaluate remaining records of update\\delete cursor and put write locks on it too" +# // But there are no such rows in the tableL earlier worker already encountered all possible rows (with ID=4 and 6) +# // and *did* put write-locks on them. So at this point NO new rows can be found for putting new lock on it. +# // BECAUSE OF FACT THAT NO RECORDS FOUND, WORKER DOES UNDO BUT KEEP LOCKS AND THEN MAKES FIRST STATEMENT-LEVEL RESTART. +# // [DOC]: "d) when there is no more records to fetch, engine start to undo all actions ... and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# +# * session 'locker-1': +# commit; +# // This will release record with ID = 6 - and this is the last row which meet cursor condition of session-worker. +# // Worker sees record (because of TIL = RC NRV) with ID = 6 and put write-lock on it. +# // Then worker resumes search for any (new) rows with ID >= 3, and it does this with taking in account required order +# // of its DML (i.e. ORDER BY ID ASC). NO new rows (with ID >= 3) can be found for putting new lock on it. +# // BECAUSE OF FACT THAT NO RECORDS FOUND, WORKER DOES UNDO BUT KEEP LOCKS AND THEN MAKES SECOND STATEMENT-LEVEL RESTART. +# +# Expected result: +# * session-'worker' must *successfully* complete deletion of all rows which it could see at the starting point (ID=3 and 5) +# PLUS rows with ID = 4 (ex. ID=2) and 6 (this ID is new, it did not exist at the statement start). +# As result, all rows must be deleted. +# +# * three unique values must be in the column TLOG_DONE.SNAP_NO for session-'worker' when it performed DELETE statement: first of them +# was created by initial statement start and all others reflect two restarts (this column has values which are evaluated using +# rdb$get_context('SYSTEM', 'SNAPSHOT_NUMBER') -- see trigger TEST_AIUD). +# It is enough to count these values using COUNT(*) or enumarate them by DENSE_RANK() function. +# +# NOTE: concrete values of fields TRN, GLOBAL_CN and SNAP_NO in the TLOG_DONE can differ from one to another run! +# This is because of concurrent nature of connections that work against database. We must not assume that these values will be constant. +# ################ +# +# +# Checked on 4.0.0.2144 SS/CS +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# from subprocess import Popen +# import re +# import difflib +# from fdb import services +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql_init_ddl = os.path.join(context['files_location'],'read-consist-sttm-restart-DDL.sql') +# +# for checked_mode in('table', 'view'): +# +# target_obj = 'test' if checked_mode == 'table' else 'v_test' +# +# # drop dependencies: +# runProgram('isql', [ dsn, '-q' ], 'recreate table detl(id int);') +# +# f_init_log=open( os.path.join(context['temp_directory'],'read-consist-sttm-restart-DDL.log'), 'w') +# f_init_err=open( ''.join( ( os.path.splitext(f_init_log.name)[0], '.err') ), 'w') +# subprocess.call( [context['isql_path'], dsn, '-q', '-i', sql_init_ddl], stdout=f_init_log, stderr=f_init_err ) +# flush_and_close(f_init_log) +# flush_and_close(f_init_err) +# +# sql_addi=''' +# recreate table detl(id int, PID int references test on delete cascade on update cascade); +# commit; +# +# delete from test; +# insert into test(id, x) values(2,2); +# insert into test(id, x) values(3,3); +# insert into test(id, x) values(5,5); +# insert into detl(id, pid) values(2000, 2); +# insert into detl(id, pid) values(2001, 2); +# insert into detl(id, pid) values(2002, 2); +# insert into detl(id, pid) values(3001, 3); +# insert into detl(id, pid) values(5001, 5); +# insert into detl(id, pid) values(5001, 5); +# commit; +# ''' +# runProgram('isql', [ dsn, '-q' ], sql_addi) +# +# locker_tpb = fdb.TPB() +# locker_tpb.lock_timeout = 3; # LOCKER_LOCK_TIMEOUT +# locker_tpb.lock_resolution = fdb.isc_tpb_wait +# +# con_lock_1 = fdb.connect( dsn = dsn, isolation_level=locker_tpb ) +# con_lock_2 = fdb.connect( dsn = dsn, isolation_level=locker_tpb ) +# +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# +# con_lock_1.execute_immediate( 'update %(target_obj)s set id=id where id=5' % locals() ) +# +# sql_text=''' +# connect '%(dsn)s'; +# set list on; +# set autoddl off; +# set term ^; +# execute block returns (whoami varchar(30)) as +# begin +# whoami = 'WORKER'; -- , ATT#' || current_connection; +# rdb$set_context('USER_SESSION','WHO', whoami); +# -- suspend; +# end +# ^ +# set term ;^ +# commit; +# SET KEEP_TRAN_PARAMS ON; +# set transaction read committed read consistency; +# --select current_connection, current_transaction from rdb$database; +# set list off; +# set wng off; +# --set plan on; +# set count on; +# +# delete from %(target_obj)s where id >= 3 order by id; -- THIS MUST BE LOCKED +# +# -- check results: +# -- ############### +# +# select id from %(target_obj)s order by id; -- this will produce output only after all lockers do their commit/rollback +# +# select v.old_id, v.op, v.snap_no_rank +# from v_worker_log v +# where v.op = 'del'; +# +# rollback; +# +# ''' % dict(globals(), **locals()) +# +# f_worker_sql=open( os.path.join(context['temp_directory'],'tmp_sttm_restart_on_delete_03.sql'), 'w') +# f_worker_sql.write(sql_text) +# flush_and_close(f_worker_sql) +# +# +# f_worker_log=open( ''.join( ( os.path.splitext(f_worker_sql.name)[0], '.log') ), 'w') +# f_worker_err=open( ''.join( ( os.path.splitext(f_worker_log.name)[0], '.err') ), 'w') +# +# ############################################################################ +# ### L A U N C H W O R K E R U S I N G I S Q L, A S Y N C. ### +# ############################################################################ +# +# p_worker = Popen( [ context['isql_path'], '-q', '-i', f_worker_sql.name ],stdout=f_worker_log, stderr=f_worker_err) +# time.sleep(1) +# +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# con_lock_2.execute_immediate( 'update %(target_obj)s set id=4 where id=2;' % locals() ) +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'update %(target_obj)s set id=id where id=4;' % locals() ) +# +# +# con_lock_1.commit() # release record with ID=5 (allow it to be deleted by session-worker) +# +# # Add record which did not exists when session-worker statement started. +# # Add also child record for it, then commit + re-lock just added record: +# con_lock_1.execute_immediate('insert into %(target_obj)s(id,x) values(6,6)' % locals()) +# con_lock_1.execute_immediate('insert into detl(id, pid) values(6001, 6)') +# con_lock_1.commit() +# con_lock_1.execute_immediate('update %(target_obj)s set id=id where id=6' % locals()) +# +# con_lock_2.commit() # release record with ID=4. At this point session-worker will be allowed to delete rows with ID=4 and 5. +# +# con_lock_1.commit() # release record with ID=6. It is the last record which also must be deleted by session-worker. +# +# # Here we wait for ISQL complete its mission: +# p_worker.wait() +# +# flush_and_close(f_worker_log) +# flush_and_close(f_worker_err) +# +# # Close lockers: +# ################ +# for c in (con_lock_1, con_lock_2): +# c.close() +# +# +# # CHECK RESULTS +# ############### +# with open(f_worker_log.name,'r') as f: +# for line in f: +# if line.strip(): +# print('checked_mode: %(checked_mode)s, STDLOG: %(line)s' % locals()) +# +# for f in (f_init_err, f_worker_err): +# with open(f.name,'r') as g: +# for line in g: +# if line.strip(): +# print( 'checked_mode: ', checked_mode, ' UNEXPECTED STDERR IN ' + g.name + ':', line) +# +# #=4.0') +@pytest.mark.xfail +def test_read_consist_sttm_restart_on_delete_03_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + 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 new file mode 100644 index 00000000..724af672 --- /dev/null +++ b/tests/functional/transactions/test_read_consist_sttm_restart_on_delete_04.py @@ -0,0 +1,416 @@ +#coding:utf-8 +# +# id: functional.transactions.read_consist_sttm_restart_on_delete_04 +# title: READ CONSISTENCY. Check creation of new statement-level snapshot and restarting changed caused by DELETE. Test-04. +# decription: +# Initial article for reading: +# https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:11504247549852 +# Note on terms which are used there: "BLOCKER", "LONG" and "FIRSTLAST" - their names are slightly changed here +# to: LOCKER-1, WORKER and LOCKER-2 respectively. +# See also: doc\\README.read_consistency.md +# +# ********************************************** +# +# This test verifies that statement-level snapshot and restart will be performed when "main" session ("worker") +# performs DELETE statement and is involved in update conflicts. +# ("When update conflict is detected <...> then engine <...> creates new statement-level snapshot and restart execution...") +# +# ::: NB ::: +# This test uses script %FBT_REPO% +# iles +# ead-consist-sttm-restart-DDL.sql which contains common DDL for all other such tests. +# Particularly, it contains two TRIGGERS (TLOG_WANT and TLOG_DONE) which are used for logging of planned actions and actual +# results against table TEST. These triggers use AUTONOMOUS transactions in order to have ability to see results in any +# outcome of test. +# +# ############### +# Following scenario if executed here (see also: "doc\\README.read_consistency.md"; hereafer is marked as "DOC"): +# * five rows are inserted into the table TEST, with IDs: 1...5. +# +# * session 'locker-1' ("BLOCKER" in Tom Kyte's article ): +# update test set id = id where id = 1 +# +# * session 'worker' ("LONG" in TK article) has mission: +# delete from test where id<=2 order by id DESC rows 4; // using TIL = read committed read consistency +# +# // Execution will have PLAN ORDER . +# // It will delete rows starting with ID = 2 but can not change row with ID = 1 because of locker-1. +# // Update conflict appears here and, because of this, worker temporary changes its TIL to RC no record_version (RC NRV). +# // [DOC]: "a) transaction isolation mode temporarily switched to the READ COMMITTED *NO RECORD VERSION MODE*" +# // This (new) TIL allows worker further to see all committed versions, regardless of its own snapshot. +# +# * session 'locker-2' ("FIRSTLAST" in TK article): replaces ID = 5 with new value = -5, then commits +# and locks this record again: +# (1) commit; +# (2) update test set id = -5 where abs(id)=5; +# (3) commit; +# (4) update test set id = id where abs(id)=5; +# // session-'worker' remains waiting at this point because row with ID = 1 is still occupied by by locker-1. +# // but worker must further see record with (new) id = -5 because its TIL was changed to RC NO RECORD_VERSION. +# +# +# * session 'locker-1': replaces ID = 4 with new value = -4, then commits and locks this record again: +# (1) commit; +# (2) update test set id = -4 where abs(id)=4; +# (3) commit; +# (4) update test set id = id where abs(id)=4; +# +# // This: '(1) commit' - will release record with ID = 1. Worker sees this record and put write-lock on it. +# // [DOC]: "b) engine put write lock on conflicted record" +# // But it is only 2nd row of total 4 that worker must delete. +# // Because of TIL = RC NRV session-'worker' must see all committed records regardless on its own snapshot. +# // Worker resumes search for any rows with ID < 2, and it does this with taking in account required order +# // of its DML (i.e. 'ORDER BY ID DESC ...') +# // [DOC]: "c) engine continue to evaluate remaining records of update\\delete cursor and put write locks on it too" +# // Worker starts to search records which must be involved in its DML and *found* first sucn row with ID = -5. +# // NB. This row currently can NOT be deleted by worker because locker-2 has uncommitted update of it. +# // BECAUSE OF FACT THAT AT LEAST ONE ROW *WAS FOUND* - STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# // :::!! NB, AGAIN !! ::: restart NOT occurs here because at least one records found, see: +# // [DOC]: "d) when there is *no more* records to fetch, engine start to undo all actions performed since +# // top-level statement execution starts and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# +# * session 'locker-2': replaces ID = 3 with new value = -3, then commits and locks this record again: +# (1) commit; +# (2) update test set id = -3 where abs(id)=3; +# (3) commit; +# (4) update test set id = id where abs(id)=3; +# +# // This: '(1) commit' - will release record with ID = -5. Worker sees this record and put write-lock on it. +# // But this is only 3rd row of total 4 that worker must delete. +# // Because of worker TIL = RC NRV, he must see all committed records regardless on its own snapshot. +# // Worker resumes search for any rows with ID < -5, and it does this with taking in account required order +# // of its DML (i.e. 'ORDER BY ID DESC ...') +# // [DOC]: "c) engine continue to evaluate remaining records of update\\delete cursor and put write locks on it too" +# // There are no such rows in the table. +# // BECAUSE OF FACT THAT NO RECORDS FOUND, WORKER DOES UNDO BUT KEEP LOCKS AND THEN MAKES FIRST STATEMENT-LEVEL RESTART. +# // [DOC]: "d) when there is no more records to fetch, engine start to undo all actions ... and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# +# * session 'locker-1': +# commit; +# // This will release record with ID=-4. Worker sees this record and put write-lock on it. +# // At this point worker has proceeded all required number of rows for DML: 2, 1, -4 and -5. +# // BECAUSE OF FACT THAT ALL ROWS WERE PROCEEDED, WORKER DOES UNDO BUT KEEP LOCKS AND THEN MAKES SECOND STATEMENT-LEVEL RESTART. +# // [DOC]: "d) when there is no more records to fetch, engine start to undo all actions ... and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# // After this restart worker will waiting for row with ID = -3 (it sees this because of TIL = RC NRV). +# +# * session 'locker-2': +# commit. +# // This releases row with ID=-3. Worker sees this record and put write-lock on it. +# // Records with ID = 2, 1, -4 and -5 already have been locked, but worker must delete only FOUR rows (see its DML statement). +# // Thus only rows with ID = 2, 1, -3 and -4 will be deleted. Record with ID = -5 must *remain* in the table. +# // At this point worker has proceeded all required rows that meet condition for DML: 2, 1, -3 and -4. +# // BECAUSE OF FACT THAT ALL ROWS WERE PROCEEDED, WORKER DOES UNDO BUT KEEP LOCKS AND THEN MAKES THIRD STATEMENT-LEVEL RESTART. +# // [DOC]: "d) when there is no more records to fetch, engine start to undo all actions ... and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# +# Expected result: +# * session-'worker' must *successfully* complete deletion of 4 rows (but only two of them did exist at the starting point). +# Record with ID = -5 must remain in the table. +# +# * four unique values must be in the column TLOG_DONE.SNAP_NO for session-'worker' when it performed DELETE statement: first of them +# was created by initial statement start and all others reflect three restarts (this column has values which are evaluated using +# rdb$get_context('SYSTEM', 'SNAPSHOT_NUMBER') -- see trigger TEST_AIUD). +# It is enough to count these values using COUNT(*) or enumarate them by DENSE_RANK() function. +# +# NOTE: concrete values of fields TRN, GLOBAL_CN and SNAP_NO in the TLOG_DONE can differ from one to another run! +# This is because of concurrent nature of connections that work against database. We must not assume that these values will be constant. +# +# ################ +# +# Checked on 4.0.0.2144 SS/CS +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# from subprocess import Popen +# import shutil +# from fdb import services +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # How long can we wait for session-worker completition, seconds +# # (ISQL often can not complete its job for several seconds!): +# MAX_TIME_FOR_WAITING_WORKER_FINISH = 60 +# +# ############################## +# # Temply, for debug obly: +# this_fdb=db_conn.database_name +# this_dbg=os.path.splitext(this_fdb)[0] + '.4debug.fdb' +# ############################## +# +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# +# sql_init_ddl = os.path.join(context['files_location'],'read-consist-sttm-restart-DDL.sql') +# +# for checked_mode in('table', 'view'): +# +# target_obj = 'test' if checked_mode == 'table' else 'v_test' +# +# f_init_log=open( os.path.join(context['temp_directory'],'read-consist-sttm-restart-DDL.log'), 'w') +# f_init_err=open( ''.join( ( os.path.splitext(f_init_log.name)[0], '.err') ), 'w') +# +# subprocess.call( [context['isql_path'], dsn, '-q', '-i', sql_init_ddl], stdout=f_init_log, stderr=f_init_err ) +# flush_and_close(f_init_log) +# flush_and_close(f_init_err) +# +# sql_addi=''' +# set term ^; +# execute block as +# begin +# rdb$set_context('USER_SESSION', 'WHO', 'INIT_DATA'); +# end +# ^ +# set term ;^ +# insert into %(target_obj)s(id, x) +# select row_number()over(),row_number()over() +# from rdb$types rows 5; +# commit; +# ''' % locals() +# runProgram('isql', [ dsn, '-q' ], sql_addi) +# +# locker_tpb = fdb.TPB() +# locker_tpb.lock_timeout = MAX_TIME_FOR_WAITING_WORKER_FINISH +# locker_tpb.lock_resolution = fdb.isc_tpb_wait +# +# con_lock_1 = fdb.connect( dsn = dsn, isolation_level=locker_tpb ) +# con_lock_2 = fdb.connect( dsn = dsn, isolation_level=locker_tpb ) +# +# con_lock_1.execute_immediate( "execute block as begin rdb$set_context('USER_SESSION', 'WHO', 'LOCKER #1'); end" ) +# con_lock_2.execute_immediate( "execute block as begin rdb$set_context('USER_SESSION', 'WHO', 'LOCKER #2'); end" ) +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# +# con_lock_1.execute_immediate( 'update %(target_obj)s set id=id where id=1' % locals() ) +# +# sql_text=''' +# connect '%(dsn)s'; +# set list on; +# set autoddl off; +# set term ^; +# execute block returns (whoami varchar(30)) as +# begin +# whoami = 'WORKER'; -- , ATT#' || current_connection; +# rdb$set_context('USER_SESSION','WHO', whoami); +# -- suspend; +# end +# ^ +# set term ;^ +# commit; +# SET KEEP_TRAN_PARAMS ON; +# set transaction read committed read consistency; +# --select current_connection, current_transaction from rdb$database; +# set list off; +# set wng off; +# +# --set plan on; +# set count on; +# delete from %(target_obj)s where id <= 2 order by id DESC rows 4; -- THIS MUST HANG BECAUSE OF LOCKERs +# +# -- check results: +# -- ############### +# +# select id from %(target_obj)s order by id; -- one record must remain, with ID = -5 +# +# select v.old_id, v.op, v.snap_no_rank -- snap_no_rank must have four unique values: 1,2,3 and 4. +# from v_worker_log v +# where v.op = 'del'; +# +# --set width who 10; +# -- DO NOT check this! Values can differ here from one run to another! +# -- select id, trn, who, old_id, new_id, op, rec_vers, global_cn, snap_no from tlog_done order by id; +# rollback; +# +# ''' % dict(globals(), **locals()) +# +# f_worker_sql=open( os.path.join(context['temp_directory'],'tmp_sttm_restart_on_delete_04.sql'), 'w') +# f_worker_sql.write(sql_text) +# flush_and_close(f_worker_sql) +# +# +# f_worker_log=open( ''.join( ( os.path.splitext(f_worker_sql.name)[0], '.log') ), 'w') +# f_worker_err=open( ''.join( ( os.path.splitext(f_worker_log.name)[0], '.err') ), 'w') +# +# ############################################################################ +# ### L A U N C H W O R K E R U S I N G I S Q L, A S Y N C. ### +# ############################################################################ +# +# p_worker = Popen( [ context['isql_path'], '-pag', '9999999', '-q', '-i', f_worker_sql.name ],stdout=f_worker_log, stderr=f_worker_err) +# time.sleep(1) +# +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# +# # Change ID so that it **will* be included in the set of rows that must be affected by session-worker: +# con_lock_2.execute_immediate( 'update %(target_obj)s set id = -5 where abs(id) = 5;' % locals() ) +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'update %(target_obj)s set id = id where abs(id) = 5;' % locals() ) +# +# +# con_lock_1.commit() # releases record with ID=1 (allow it to be deleted by session-worker) +# +# # Change ID so that it **will* be included in the set of rows that must be affected by session-worker: +# con_lock_1.execute_immediate( 'update %(target_obj)s set id = -4 where abs(id) = 4;' % locals() ) +# con_lock_1.commit() +# con_lock_1.execute_immediate( 'update %(target_obj)s set id = id where abs(id) = 4;' % locals() ) +# +# +# con_lock_2.commit() # releases record with ID = -5, but session-worker is waiting for record with ID = -4 (that was changed by locker-1). +# con_lock_2.execute_immediate( 'update %(target_obj)s set id = -3 where abs(id) = 3;' % locals() ) +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'update %(target_obj)s set id = id where abs(id) = 3;' % locals() ) +# +# con_lock_1.commit() # This releases row with ID=-4 but session-worker is waiting for ID = - 3 (changed by locker-2). +# con_lock_2.commit() # This releases row with ID=-3. No more locked rows so session-worker can finish its mission. +# +# # Here we wait for ISQL complete its mission: +# p_worker.wait() +# +# flush_and_close(f_worker_log) +# flush_and_close(f_worker_err) +# +# # Close lockers: +# ################ +# for c in (con_lock_1, con_lock_2): +# c.close() +# +# +# # CHECK RESULTS +# ############### +# with open(f_worker_log.name,'r') as f: +# for line in f: +# if line.strip(): +# print('checked_mode: %(checked_mode)s, STDLOG: %(line)s' % locals()) +# +# for f in (f_init_err, f_worker_err): +# with open(f.name,'r') as g: +# for line in g: +# if line.strip(): +# print( 'checked_mode: ', checked_mode, ' UNEXPECTED STDERR IN ' + g.name + ':', line) +# +# #=4.0') +@pytest.mark.xfail +def test_read_consist_sttm_restart_on_delete_04_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + 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 new file mode 100644 index 00000000..963f5e3a --- /dev/null +++ b/tests/functional/transactions/test_read_consist_sttm_restart_on_merge_01.py @@ -0,0 +1,395 @@ +#coding:utf-8 +# +# id: functional.transactions.read_consist_sttm_restart_on_merge_01 +# title: READ CONSISTENCY. Check creation of new statement-level snapshot and restarting changed caused by MERGE. Test-01. +# decription: +# Initial article for reading: +# https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:11504247549852 +# Note on terms which are used there: "BLOCKER", "LONG" and "FIRSTLAST" - their names are slightly changed here +# to: LOCKER-1, WORKER and LOCKER-2 respectively. +# +# ********************************************** +# +# This test verifies that statement-level snapshot and restart will be performed when "main" session ("worker") +# performs MERGE statement and is involved in update conflicts. +# ("When update conflict is detected <...> then engine <...> creates new statement-level snapshot and restart execution...") +# +# ::: NB ::: +# This test uses script %FBT_REPO% +# iles +# ead-consist-sttm-restart-DDL.sql which contains common DDL for all other such tests. +# Particularly, it contains two TRIGGERS (TLOG_WANT and TLOG_DONE) which are used for logging of planned actions and actual +# results against table TEST. These triggers use AUTONOMOUS transactions in order to have ability to see results in any +# outcome of test. +# +# ############### +# Following scenario if executed here (see also: "doc\\README.read_consistency.md"; hereafer is marked as "DOC"): +# +# * three rows are inserted into the table TEST, with ID = 1,2,3 (and X=1,2,3) +# * session 'locker-1' ("BLOCKER" in Tom Kyte's article ): +# update test set id = id where id = 3; +# +# * session 'worker' ("LONG" in TK article) has mission: +# merge into test t -- THIS MUST BE LOCKED +# using (select * from test order by id) s on s.id=t.id +# when matched then +# update set t.id = -t.id, t.x = -s.x +# when not matched then +# insert(id,x) values(s.id, -s.x - 500); +# -- and it does this within read committed read consistency. +# +# +# // Execution will have PLAN ORDER . +# // Worker starts with updating rows with ID = 1, 2 but can not change row with ID = 3 because of locker-1. +# // Because of detecting update conflist, worker changes here its TIL to RC NO RECORD_VERSION. +# +# * session 'locker-2' ("FIRSTLAST" in TK article): +# (1) insert into test(id) values(-13); +# (2) commit; +# (3) update test set id=id where id = -13; +# // session-'worker' remains waiting at this point because row with ID = 3 is still occupied by by locker-1. +# // Record with (new) id = -13 will be seen further because worker's TIL was changed to RC NO RECORD_VERSION. +# +# * session 'locker-1': +# (1) commit; +# (2) insert into test(id) values(-12); +# (3) commit; +# (4) update test set id=id where id = -12; +# +# // This: '(1) commit' - will release record with ID = 3. Worker sees this record and put write-lock on it. +# // [DOC]: "b) engine put write lock on conflicted record" +# // Because of TIL = RC NRV session-'worker' must see all committed records regardless on its own snapshot. +# // Worker resumes search for rows that must be updated with taking in account required order of its DML (i.e. 'ORDER BY ID'). +# // [DOC]: "c) engine continue to evaluate remaining records of update\\delete cursor and put write locks on it too" +# // New record which is involved in DML (and did not exist before) *will be found*, its ID = -13. +# // Worker stops on this record (with ID = -13) because id is occupied by locker-2. +# // BECAUSE OF FACT THAT AT LEAST ONE ROW *WAS FOUND* - STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# // [DOC]: "d) when there is *no more* records to fetch, engine start to undo all actions performed since +# // top-level statement execution starts and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# +# * session 'locker-2': +# commit; +# +# // This: 'commit' - will release record with ID = -13. Worker sees this record and put write-lock on it. +# // [DOC]: "b) engine put write lock on conflicted record" +# // Because of TIL = RC NRV session-'worker' must see all committed records regardless on its own snapshot. +# // Worker resumes search for rows that must be updated with taking in account required order of its DML (i.e. 'ORDER BY ID'). +# // [DOC]: "c) engine continue to evaluate remaining records of update\\delete cursor and put write locks on it too" +# // New record which is involved in DML (and did not exist before) *will be found*, its ID = -12. +# // Worker stops on this record (with ID = -12) because id is occupied by locker-1. +# // BECAUSE OF FACT THAT AT LEAST ONE ROW *WAS FOUND* - STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# // [DOC]: "d) when there is *no more* records to fetch, engine start to undo all actions performed since +# // top-level statement execution starts and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# +# +# * session 'locker-1': +# commit; +# // This commit will release record with ID = -12. Worker sees this record and put write-lock on it. +# // At this point there are no more records to be locked (by worker) that meet cursor condition: worker did put +# // write locks on all rows that meet its cursor conditions. +# // BECAUSE OF FACT THAT NO MORE RECORDS FOUND TO BE LOCKED, WORKER DOES UNDO BUT KEEP LOCKS AND THEN +# // MAKES FIRST STATEMENT-LEVEL RESTART. This restart is also the last in this test. +# +# +# Expected result: +# * session-'worker' must update of all rows with reverting signs of their IDs. Records which were inserted must have positive IDs. +# +# * Two unique values must be in the column TLOG_DONE.SNAP_NO for session-'worker' when it performed MERGE statement: first of them +# was created by initial statement start and second reflects SINGLE restart (this column has values which are evaluated using +# rdb$get_context('SYSTEM', 'SNAPSHOT_NUMBER') -- see trigger TEST_AIUD). +# It is enough to count these values using COUNT(*) or enumarate them by DENSE_RANK() function. +# +# NOTE: concrete values of fields TRN, GLOBAL_CN and SNAP_NO in the TLOG_DONE can differ from one to another run! +# This is because of concurrent nature of connections that work against database. We must not assume that these values will be constant. +# +# ################ +# +# Checked on 4.0.0.2204 +# NOTE test contains for-loop in order to check different target objects: TABLE ('test') and VIEW ('v_test'), see 'checked_mode'. +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# from subprocess import Popen +# from fdb import services +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql_init_ddl = os.path.join(context['files_location'],'read-consist-sttm-restart-DDL.sql') +# +# for checked_mode in('table', 'view'): +# +# target_obj = 'test' if checked_mode == 'table' else 'v_test' +# +# f_init_log=open( os.path.join(context['temp_directory'],'read-consist-sttm-restart-DDL.log'), 'w') +# f_init_err=open( ''.join( ( os.path.splitext(f_init_log.name)[0], '.err') ), 'w') +# +# # RECREATION OF ALL DB OBJECTS: +# # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# subprocess.call( [context['isql_path'], dsn, '-q', '-i', sql_init_ddl], stdout=f_init_log, stderr=f_init_err ) +# flush_and_close(f_init_log) +# flush_and_close(f_init_err) +# +# # add rows with ID = 1, 2, 3: +# sql_addi=''' +# set term ^; +# execute block as +# begin +# rdb$set_context('USER_SESSION', 'WHO', 'INIT_DATA'); +# end +# ^ +# set term ;^ +# insert into %(target_obj)s(id, x) +# select row_number()over(),row_number()over() +# from rdb$types rows 3; +# commit; +# ''' % locals() +# runProgram('isql', [ dsn, '-q' ], sql_addi) +# +# con_lock_1 = fdb.connect( dsn = dsn ) +# con_lock_2 = fdb.connect( dsn = dsn ) +# con_lock_1.execute_immediate( "execute block as begin rdb$set_context('USER_SESSION', 'WHO', 'LOCKER #1'); end" ) +# con_lock_2.execute_immediate( "execute block as begin rdb$set_context('USER_SESSION', 'WHO', 'LOCKER #2'); end" ) +# +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# +# con_lock_1.execute_immediate( 'update %(target_obj)s set id=id where id = 3' % locals()) +# +# sql_text=''' +# connect '%(dsn)s'; +# set list on; +# set autoddl off; +# set term ^; +# execute block returns (whoami varchar(30)) as +# begin +# whoami = 'WORKER'; -- , ATT#' || current_connection; +# rdb$set_context('USER_SESSION','WHO', whoami); +# -- suspend; +# end +# ^ +# set term ;^ +# commit; +# --set echo on; +# SET KEEP_TRAN_PARAMS ON; +# set transaction read committed read consistency; +# +# set list off; +# set wng off; +# set count on; +# +# merge into %(target_obj)s t -- THIS MUST BE LOCKED +# using (select * from %(target_obj)s order by id) s on s.id=t.id +# when matched then +# update set t.id = -t.id, t.x = -s.x +# when not matched then +# insert(id,x) values(s.id, -s.x - 500); +# +# -- check results: +# -- ############### +# +# select id,x from %(target_obj)s order by id; -- this will produce output only after all lockers do their commit/rollback +# +# select v.old_id, v.op, v.snap_no_rank +# from v_worker_log v +# where v.op = 'upd'; +# +# set width who 10; +# -- DO NOT check this! Values can differ here from one run to another! +# -- select id, trn, who, old_id, new_id, op, rec_vers, global_cn, snap_no from tlog_done order by id; +# +# rollback; +# +# ''' % dict(globals(), **locals()) +# +# f_worker_sql=open( os.path.join(context['temp_directory'],'tmp_sttm_restart_on_merge_01.sql'), 'w') +# f_worker_sql.write(sql_text) +# flush_and_close(f_worker_sql) +# +# +# f_worker_log=open( ''.join( ( os.path.splitext(f_worker_sql.name)[0], '.log') ), 'w') +# f_worker_err=open( ''.join( ( os.path.splitext(f_worker_log.name)[0], '.err') ), 'w') +# +# ############################################################################ +# ### L A U N C H W O R K E R U S I N G I S Q L, A S Y N C. ### +# ############################################################################ +# +# p_worker = Popen( [ context['isql_path'], '-pag', '999999', '-q', '-i', f_worker_sql.name ],stdout=f_worker_log, stderr=f_worker_err) +# time.sleep(1) +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# con_lock_2.execute_immediate( 'insert into %(target_obj)s(id,x) values(-13,-13)' % locals()) +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'update %(target_obj)s set id=id where id = -13' % locals()) +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# con_lock_1.commit() +# con_lock_1.execute_immediate( 'insert into %(target_obj)s(id,x) values(-12,-12)' % locals() ) +# con_lock_1.commit() +# con_lock_1.execute_immediate( 'update %(target_obj)s set id=id where id = -12' % locals() ) +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# con_lock_2.commit() +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# con_lock_1.commit() # WORKER will complete his job after this +# +# # Here we wait for ISQL complete its mission: +# p_worker.wait() +# +# flush_and_close(f_worker_log) +# flush_and_close(f_worker_err) +# +# # Close lockers: +# ################ +# for c in (con_lock_1, con_lock_2): +# c.close() +# +# +# # CHECK RESULTS +# ############### +# with open(f_worker_log.name,'r') as f: +# for line in f: +# if line.strip(): +# print('checked_mode: %(checked_mode)s, STDLOG: %(line)s' % locals()) +# +# for f in (f_init_err, f_worker_err): +# with open(f.name,'r') as g: +# for line in g: +# if line.strip(): +# print( 'checked_mode: ', checked_mode, ' UNEXPECTED STDERR IN ' + g.name + ':', line) +# +# #=4.0') +@pytest.mark.xfail +def test_read_consist_sttm_restart_on_merge_01_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + 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 new file mode 100644 index 00000000..100868c2 --- /dev/null +++ b/tests/functional/transactions/test_read_consist_sttm_restart_on_merge_02.py @@ -0,0 +1,409 @@ +#coding:utf-8 +# +# id: functional.transactions.read_consist_sttm_restart_on_merge_02 +# title: READ CONSISTENCY. Check creation of new statement-level snapshot and restarting changed caused by MERGE. Test-02. +# decription: +# Initial article for reading: +# https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:11504247549852 +# Note on terms which are used there: "BLOCKER", "LONG" and "FIRSTLAST" - their names are slightly changed here +# to: LOCKER-1, WORKER and LOCKER-2 respectively. +# See also: doc\\README.read_consistency.md +# +# ********************************************** +# +# This test verifies that statement-level snapshot and restart will be performed when "main" session ("worker") +# performs DELETE statement and is involved in update conflicts. +# ("When update conflict is detected <...> then engine <...> creates new statement-level snapshot and restart execution...") +# +# ::: NB ::: +# This test uses script %FBT_REPO% +# iles +# ead-consist-sttm-restart-DDL.sql which contains common DDL for all other such tests. +# Particularly, it contains two TRIGGERS (TLOG_WANT and TLOG_DONE) which are used for logging of planned actions and actual +# results against table TEST. These triggers use AUTONOMOUS transactions in order to have ability to see results in any +# outcome of test. +# +# +# ############### +# Following scenario if executed here (see also: "doc\\README.read_consistency.md"; hereafer is marked as "DOC"): +# +# * five rows are inserted into the table TEST, with IDs: 1...5 +# * session 'locker-1' ("BLOCKER" in Tom Kyte's article ); +# update set id=id where id = 5; +# +# * session 'worker' ("LONG" in TK article) has mission: +# merge into test t using(select * from test where id < 0 or id >= 3 order by id) s on t.id = s.id when matched then delete; +# // using TIL = read committed read consistency +# +# // Execution will have PLAN ORDER . +# // It will delete rows with ID = 3 and 4 but hang on row with ID = 5 because of locker-1; +# // Update conflict appears here and, because of this, worker temporary changes its TIL to RC no record_version (RC NRV). +# // [DOC]: "a) transaction isolation mode temporarily switched to the READ COMMITTED *NO RECORD VERSION MODE*" +# // This (new) TIL allows worker further to see all committed versions, regardless of its own snapshot. +# +# * session 'locker-2' ("FIRSTLAST" in TK article): +# (1) insert into test(id) values(-1); // i.e. LESS than min(id)=1 that existed at the start of session-worker statement +# (2) commit; +# (3) update test set id=id where id = -1; +# // Session-worker must still hang because row with ID = 5 is occupied by locker-1. +# // But worker must further see record with (new) id = -1 because its TIL was changed to RC NO RECORD_VERSION. +# +# * session 'locker-1': +# (1) commit; +# (2) insert into test(id) values(-2); // i.e. LESS than min(id)=-1 that existed before this +# (3) commit; +# (4) update test set id=id where id = -2; +# // This: '(1) commit' - will release record with ID = 5. Worker sees this record and put write-lock on it. +# // [DOC]: "b) engine put write lock on conflicted record" +# // Because of TIL = RC NRV session-'worker' must see all committed records regardless on its own snapshot. +# // Worker resumes search for any rows which meet condition: "id < 0 or id >= 3", and it does this with taking in account +# // required order of its DML (i.e. 'ORDER BY ID') +# // [DOC]: "c) engine continue to evaluate remaining records of update\\delete cursor and put write locks on it too" +# // Worker starts to search records which must be involved in its DML and *found* first sucn row: it has ID = -1. +# // NB. This row currently can NOT be deleted by worker because locker-2 has uncommitted update of it. +# // BECAUSE OF FACT THAT AT LEAST ONE ROW *WAS FOUND* - STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# // :::!! NB, AGAIN !! ::: restart NOT occurs here because at least one records found, see: +# // [DOC]: "d) when there is *no more* records to fetch, engine start to undo all actions performed since +# // top-level statement execution starts and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# +# +# * session 'locker-2': +# (1) commit; +# (2) insert into test(id) values(-3); // i.e. LESS than min(id)=-1 that existed before this +# (3) commit; +# (4) update test set id=id where id = -3; +# +# // This: '(1) commit' - will release record with ID = -1. Worker sees this record and put write-lock on it. +# // [DOC]: "b) engine put write lock on conflicted record" +# // Because of TIL = RC NRV session-'worker' must see all committed records regardless on its own snapshot. +# // Worker resumes search for any rows which meet condition: "id < 0 or id >= 3", and it does this with taking in account +# // required order of its DML (i.e. 'ORDER BY ID') +# // [DOC]: "c) engine continue to evaluate remaining records of update\\delete cursor and put write locks on it too" +# // Worker starts to search records which must be involved in its DML and *found* first sucn row: it has ID = -2. +# // NB. This row currently can NOT be deleted by worker because locker-1 has uncommitted update of it. +# // BECAUSE OF FACT THAT AT LEAST ONE ROW *WAS FOUND* - STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# +# * session 'locker-1': +# commit; +# // This: '(1) commit' - will release record with ID = -2. Worker sees this record and put write-lock on it. +# // Because of worker TIL = RC NRV, he must see all committed records regardless on its own snapshot. +# // Worker resumes search for any rows with ID < 0, and it does this with taking in account required order +# // of its DML (i.e. 'ORDER BY ID') +# // Worker starts to search records which must be involved in its DML and *found* first sucn row with ID = -3. +# // NB. This row currently can NOT be deleted by worker because locker-2 has uncommitted update of it. +# // BECAUSE OF FACT THAT AT LEAST ONE ROW *WAS FOUND* - STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# +# * session 'locker-2': +# commit; +# // This will release record with ID=-3. Worker sees this record and put write-lock on it. +# // Because of worker TIL = RC NRV, he must see all committed records regardless on its own snapshot. +# // Worker resumes search for any rows with ID < 0, and it does this with taking in account required order +# // of its DML (i.e. 'ORDER BY ID'). +# // At this point there are no more records to be locked (by worker) that meet cursor condition: worker did put +# // write locks on all rows that meet its cursor conditions (ID < 0 or ID>= 3). +# // BECAUSE OF FACT THAT NO MORE RECORDS FOUND TO BE LOCKED, WORKER DOES UNDO BUT KEEP LOCKS AND THEN +# // MAKES FIRST STATEMENT-LEVEL RESTART. This restart is also the last in this test. +# +# Expected result: +# * session-'worker' must *successfully* complete deletion of all rows with ID < 0 or ID >= 3. Rows with ID = 1 and 2 must remain. +# +# * Two unique values must be in the column TLOG_DONE.SNAP_NO for session-'worker' when it performed DELETE statement: first of them +# was created by initial statement start and second reflect SINGLE restart (this column has values which are evaluated using +# rdb$get_context('SYSTEM', 'SNAPSHOT_NUMBER') -- see trigger TEST_AIUD). +# It is enough to count these values using COUNT(*) or enumarate them by DENSE_RANK() function. +# +# NOTE: concrete values of fields TRN, GLOBAL_CN and SNAP_NO in the TLOG_DONE can differ from one to another run! +# This is because of concurrent nature of connections that work against database. We must not assume that these values will be constant. +# +# ################ +# +# Checked on 4.0.0.2204 SS/CS +# NOTE: added for-loop in order to check different target objects: TABLE ('test') and VIEW ('v_test'), see 'checked_mode'. +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# from subprocess import Popen +# from fdb import services +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql_init_ddl = os.path.join(context['files_location'],'read-consist-sttm-restart-DDL.sql') +# +# for checked_mode in('table', 'view'): +# +# target_obj = 'test' if checked_mode == 'table' else 'v_test' +# +# f_init_log=open( os.path.join(context['temp_directory'],'read-consist-sttm-restart-DDL.log'), 'w') +# f_init_err=open( ''.join( ( os.path.splitext(f_init_log.name)[0], '.err') ), 'w') +# +# subprocess.call( [context['isql_path'], dsn, '-q', '-i', sql_init_ddl], stdout=f_init_log, stderr=f_init_err ) +# flush_and_close(f_init_log) +# flush_and_close(f_init_err) +# +# # add rows with ID = 1,2,3,4,5: +# sql_addi=''' +# set term ^; +# execute block as +# begin +# rdb$set_context('USER_SESSION', 'WHO', 'INIT_DATA'); +# end +# ^ +# set term ;^ +# insert into %(target_obj)s(id, x) +# select row_number()over(),row_number()over() +# from rdb$types rows 5; +# commit; +# ''' % locals() +# runProgram('isql', [ dsn, '-q' ], sql_addi) +# +# con_lock_1 = fdb.connect( dsn = dsn ) +# con_lock_2 = fdb.connect( dsn = dsn ) +# con_lock_1.execute_immediate( "execute block as begin rdb$set_context('USER_SESSION', 'WHO', 'LOCKER #1'); end" ) +# con_lock_2.execute_immediate( "execute block as begin rdb$set_context('USER_SESSION', 'WHO', 'LOCKER #2'); end" ) +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# +# con_lock_1.execute_immediate( 'update %(target_obj)s set id=id where id = 5' % locals() ) +# +# sql_text=''' +# connect '%(dsn)s'; +# set list on; +# set autoddl off; +# set term ^; +# execute block returns (whoami varchar(30)) as +# begin +# whoami = 'WORKER'; -- , ATT#' || current_connection; +# rdb$set_context('USER_SESSION','WHO', whoami); +# -- suspend; +# end +# ^ +# set term ;^ +# commit; +# --set echo on; +# SET KEEP_TRAN_PARAMS ON; +# set transaction read committed read consistency; +# --select current_connection, current_transaction from rdb$database; +# set list off; +# set wng off; +# --set plan on; +# set count on; +# +# merge into %(target_obj)s t +# using(select * from %(target_obj)s where id < 0 or id >= 3 order by id) s on t.id = s.id +# when matched then +# DELETE +# ; +# +# -- check results: +# -- ############### +# +# select id from %(target_obj)s order by id; -- this will produce output only after all lockers do their commit/rollback +# +# select v.old_id, v.op, v.snap_no_rank +# from v_worker_log v +# where v.op = 'del'; +# +# set width who 10; +# -- DO NOT check this! Values can differ here from one run to another! +# -- select id, trn, who, old_id, new_id, op, rec_vers, global_cn, snap_no from tlog_done order by id; +# +# rollback; +# +# ''' % dict(globals(), **locals()) +# +# f_worker_sql=open( os.path.join(context['temp_directory'],'tmp_sttm_restart_on_delete_02.sql'), 'w') +# f_worker_sql.write(sql_text) +# flush_and_close(f_worker_sql) +# +# +# f_worker_log=open( ''.join( ( os.path.splitext(f_worker_sql.name)[0], '.log') ), 'w') +# f_worker_err=open( ''.join( ( os.path.splitext(f_worker_log.name)[0], '.err') ), 'w') +# +# ############################################################################ +# ### L A U N C H W O R K E R U S I N G I S Q L, A S Y N C. ### +# ############################################################################ +# +# p_worker = Popen( [ context['isql_path'], '-pag', '999999', '-q', '-i', f_worker_sql.name ],stdout=f_worker_log, stderr=f_worker_err) +# time.sleep(1) +# +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# # Insert ID value that is less than previous min(id). +# # Session-worker is executing its statement using PLAN ORDER, +# # and it should see this new value and restart its statement: +# con_lock_2.execute_immediate( 'insert into %(target_obj)s(id) values(-1)' % locals() ) +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'update %(target_obj)s set id=id where id = -1' % locals() ) +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# con_lock_1.commit() +# con_lock_1.execute_immediate( 'insert into %(target_obj)s(id) values(-2)' % locals() ) +# con_lock_1.commit() +# con_lock_1.execute_immediate( 'update %(target_obj)s set id=id where id = -2' % locals() ) +# +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# # Insert ID value that is less than previous min(id). +# # Session-worker is executing its statement using PLAN ORDER, +# # and it should see this new value and restart its statement: +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'insert into %(target_obj)s(id) values(-3)' % locals() ) +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'update %(target_obj)s set id=id where id = -3' % locals() ) +# +# con_lock_1.commit() +# con_lock_2.commit() +# +# # Here we wait for ISQL complete its mission: +# p_worker.wait() +# +# flush_and_close(f_worker_log) +# flush_and_close(f_worker_err) +# +# # Close lockers: +# ################ +# for c in (con_lock_1, con_lock_2): +# c.close() +# +# +# # CHECK RESULTS +# ############### +# with open(f_worker_log.name,'r') as f: +# for line in f: +# if line.strip(): +# print('checked_mode: %(checked_mode)s, STDLOG: %(line)s' % locals()) +# +# for f in (f_init_err, f_worker_err): +# with open(f.name,'r') as g: +# for line in g: +# if line.strip(): +# print( 'checked_mode: ', checked_mode, ' UNEXPECTED STDERR IN ' + g.name + ':', line) +# +# +# #=4.0') +@pytest.mark.xfail +def test_read_consist_sttm_restart_on_merge_02_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + 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 new file mode 100644 index 00000000..105b8edd --- /dev/null +++ b/tests/functional/transactions/test_read_consist_sttm_restart_on_merge_03.py @@ -0,0 +1,377 @@ +#coding:utf-8 +# +# id: functional.transactions.read_consist_sttm_restart_on_merge_03 +# title: READ CONSISTENCY. Check creation of new statement-level snapshot and restarting changed caused by MERGE. Test-03. +# decription: +# Initial article for reading: +# https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:11504247549852 +# Note on terms which are used there: "BLOCKER", "LONG" and "FIRSTLAST" - their names are slightly changed here +# to: LOCKER-1, WORKER and LOCKER-2 respectively. +# See also: doc\\README.read_consistency.md +# +# ********************************************** +# +# This test verifies that statement-level snapshot and restart will be performed when "main" session ("worker") +# performs DELETE statement and is involved in update conflicts. +# ("When update conflict is detected <...> then engine <...> creates new statement-level snapshot and restart execution...") +# +# ::: NB ::: +# This test uses script %FBT_REPO% +# iles +# ead-consist-sttm-restart-DDL.sql which contains common DDL for all other such tests. +# Particularly, it contains two TRIGGERS (TLOG_WANT and TLOG_DONE) which are used for logging of planned actions and actual +# results against table TEST. These triggers use AUTONOMOUS transactions in order to have ability to see results in any +# outcome of test. +# +# ############### +# Following scenario if executed here (see also: "doc\\README.read_consistency.md"; hereafer is marked as "DOC"): +# +# * add new table that is child to test: TDETL (with FK that references TEST and 'on delete cascade' clause) +# * three rows are inserted into the table TEST, with IDs: 2, 3 and 5. +# +# * session 'locker-1' ("BLOCKER" in Tom Kyte's article ): +# update set id=id where id = 5; +# +# * session 'worker' ("LONG" in TK article) has mission: +# merge into test t using(select * from test where id >= 3 order by id) s on t.id = s.id when matched then delete; +# // using TIL = read committed read consistency +# +# // Execution will have PLAN ORDER . +# // It will delete (first avaliable for cursor) row with ID = 3 but can not change row with ID = 5 because of locker-1. +# // Update conflict appears here and, because of this, worker temporary changes its TIL to RC no record_version (RC NRV). +# // [DOC]: "a) transaction isolation mode temporarily switched to the READ COMMITTED *NO RECORD VERSION MODE*" +# // This (new) TIL allows worker further to see all committed versions, regardless of its own snapshot. +# +# * session 'locker-2' ("FIRSTLAST" in TK article): replaces ID = 2 with new value = 4, then commits +# and locks this record again: +# (1) update test set id = 4 where id = 2; +# (2) commit; +# (3) update test set id=id where id = 4; +# // session-'worker' remains waiting at this point because row with ID = 5 is still occupied by by locker-1 +# // but worker must further see record with (new) id = 4 because its TIL was changed to RC NO RECORD_VERSION. +# +# * session 'locker-1': +# (1) commit; +# (2) insert into test(id) values(6); +# (3) insert into detl(id, pid) values(6001, 6); +# (4) commit; +# (5) update test set id=id where id=6; +# // first of these statements: '(1) commit' - will release record with ID = 5. +# // Worker sees this record (because of TIL = RC NRV) and put write-lock on it. +# // [DOC]: "b) engine put write lock on conflicted record" +# // Also, because worker TIL = RC NRV, it will see two new rows with ID = 4 and 6, and they meet worker cursor condition ("id>=3"). +# // Worker resumes search for any rows with ID >=3, and it does this with taking in account "ORDER BY ID ASC". +# // [DOC]: "c) engine continue to evaluate remaining records of update\\delete cursor and put write locks on it too" +# // Worker starts to search records which must be involved in its DML and *found* sucn rows (with ID = 4 and 6). +# // NB. These rows currently can NOT be deleted by worker because of locker-2 and locker-1 have uncommitted updates. +# // BECAUSE OF FACT THAT AT LEAST ONE ROW *WAS FOUND* - STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# // :::!! NB, AGAIN !! ::: restart NOT occurs here because at least one records found, see: +# // [DOC]: "d) when there is *no more* records to fetch, engine start to undo all actions performed since +# // top-level statement execution starts and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# +# * session 'locker-2': +# commit; +# // This will release record with ID = 4 (but row with ID = 6 is still inaccessible because of locker-1). +# // Worker sees record (because of TIL = RC NRV) with ID = 4 and put write-lock on it. +# // Then worker resumes search for any (new) rows with ID >= 3, and it does this with taking in account required order +# // of its DML (i.e. ORDER BY ID ASC). +# // [DOC]: "c) engine continue to evaluate remaining records of update\\delete cursor and put write locks on it too" +# // But there are no such rows in the tableL earlier worker already encountered all possible rows (with ID=4 and 6) +# // and *did* put write-locks on them. So at this point NO new rows can be found for putting new lock on it. +# // BECAUSE OF FACT THAT NO RECORDS FOUND, WORKER DOES UNDO BUT KEEP LOCKS AND THEN MAKES FIRST STATEMENT-LEVEL RESTART. +# // [DOC]: "d) when there is no more records to fetch, engine start to undo all actions ... and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# +# * session 'locker-1': +# commit; +# // This will release record with ID = 6 - and this is the last row which meet cursor condition of session-worker. +# // Worker sees record (because of TIL = RC NRV) with ID = 6 and put write-lock on it. +# // Then worker resumes search for any (new) rows with ID >= 3, and it does this with taking in account required order +# // of its DML (i.e. ORDER BY ID ASC). NO new rows (with ID >= 3) can be found for putting new lock on it. +# // BECAUSE OF FACT THAT NO RECORDS FOUND, WORKER DOES UNDO BUT KEEP LOCKS AND THEN MAKES SECOND STATEMENT-LEVEL RESTART. +# +# Expected result: +# * session-'worker' must *successfully* complete deletion of all rows which it could see at the starting point (ID=3 and 5) +# PLUS rows with ID = 4 (ex. ID=2) and 6 (this ID is new, it did not exist at the statement start). +# As result, all rows must be deleted. +# +# * three unique values must be in the column TLOG_DONE.SNAP_NO for session-'worker' when it performed DELETE statement: first of them +# was created by initial statement start and all others reflect two restarts (this column has values which are evaluated using +# rdb$get_context('SYSTEM', 'SNAPSHOT_NUMBER') -- see trigger TEST_AIUD). +# It is enough to count these values using COUNT(*) or enumarate them by DENSE_RANK() function. +# +# NOTE: concrete values of fields TRN, GLOBAL_CN and SNAP_NO in the TLOG_DONE can differ from one to another run! +# This is because of concurrent nature of connections that work against database. We must not assume that these values will be constant. +# ################ +# +# Checked on 4.0.0.2204 SS/CS +# NOTE: added for-loop in order to check different target objects: TABLE ('test') and VIEW ('v_test'), see 'checked_mode'. +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# from subprocess import Popen +# import re +# import difflib +# from fdb import services +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql_init_ddl = os.path.join(context['files_location'],'read-consist-sttm-restart-DDL.sql') +# +# for checked_mode in('table', 'view'): +# +# target_obj = 'test' if checked_mode == 'table' else 'v_test' +# +# # drop dependencies: +# runProgram('isql', [ dsn, '-q' ], 'recreate table detl(id int);') +# +# f_init_log=open( os.path.join(context['temp_directory'],'read-consist-sttm-restart-DDL.log'), 'w') +# f_init_err=open( ''.join( ( os.path.splitext(f_init_log.name)[0], '.err') ), 'w') +# subprocess.call( [context['isql_path'], dsn, '-q', '-i', sql_init_ddl], stdout=f_init_log, stderr=f_init_err ) +# flush_and_close(f_init_log) +# flush_and_close(f_init_err) +# +# sql_addi=''' +# recreate table detl(id int, PID int references test on delete cascade on update cascade); +# commit; +# +# delete from test; +# insert into test(id, x) values(2,2); +# insert into test(id, x) values(3,3); +# insert into test(id, x) values(5,5); +# insert into detl(id, pid) values(2000, 2); +# insert into detl(id, pid) values(2001, 2); +# insert into detl(id, pid) values(2002, 2); +# insert into detl(id, pid) values(3001, 3); +# insert into detl(id, pid) values(5001, 5); +# insert into detl(id, pid) values(5001, 5); +# commit; +# ''' +# runProgram('isql', [ dsn, '-q' ], sql_addi) +# +# locker_tpb = fdb.TPB() +# locker_tpb.lock_timeout = 3; # LOCKER_LOCK_TIMEOUT +# locker_tpb.lock_resolution = fdb.isc_tpb_wait +# +# con_lock_1 = fdb.connect( dsn = dsn, isolation_level=locker_tpb ) +# con_lock_2 = fdb.connect( dsn = dsn, isolation_level=locker_tpb ) +# +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# +# con_lock_1.execute_immediate( 'update %(target_obj)s set id=id where id=5' % locals() ) +# +# sql_text=''' +# connect '%(dsn)s'; +# set list on; +# set autoddl off; +# set term ^; +# execute block returns (whoami varchar(30)) as +# begin +# whoami = 'WORKER'; -- , ATT#' || current_connection; +# rdb$set_context('USER_SESSION','WHO', whoami); +# -- suspend; +# end +# ^ +# set term ;^ +# commit; +# SET KEEP_TRAN_PARAMS ON; +# set transaction read committed read consistency; +# --select current_connection, current_transaction from rdb$database; +# set list off; +# set wng off; +# --set plan on; +# set count on; +# +# merge into %(target_obj)s t -- THIS MUST BE LOCKED +# using(select * from %(target_obj)s where id >= 3 order by id) s on t.id = s.id +# when matched then +# DELETE +# ; +# +# -- check results: +# -- ############### +# +# select id from %(target_obj)s order by id; -- this will produce output only after all lockers do their commit/rollback +# +# select v.old_id, v.op, v.snap_no_rank +# from v_worker_log v +# where v.op = 'del'; +# +# rollback; +# +# ''' % dict(globals(), **locals()) +# +# f_worker_sql=open( os.path.join(context['temp_directory'],'tmp_sttm_restart_on_merge_03.sql'), 'w') +# f_worker_sql.write(sql_text) +# flush_and_close(f_worker_sql) +# +# +# f_worker_log=open( ''.join( ( os.path.splitext(f_worker_sql.name)[0], '.log') ), 'w') +# f_worker_err=open( ''.join( ( os.path.splitext(f_worker_log.name)[0], '.err') ), 'w') +# +# ############################################################################ +# ### L A U N C H W O R K E R U S I N G I S Q L, A S Y N C. ### +# ############################################################################ +# +# p_worker = Popen( [ context['isql_path'], '-q', '-i', f_worker_sql.name ],stdout=f_worker_log, stderr=f_worker_err) +# time.sleep(1) +# +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# con_lock_2.execute_immediate( 'update %(target_obj)s set id=4 where id=2;' % locals() ) +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'update %(target_obj)s set id=id where id=4;' % locals() ) +# +# +# con_lock_1.commit() # release record with ID=5 (allow it to be deleted by session-worker) +# +# # Add record which did not exists when session-worker statement started. +# # Add also child record for it, then commit + re-lock just added record: +# con_lock_1.execute_immediate('insert into %(target_obj)s(id,x) values(6,6)' % locals()) +# con_lock_1.execute_immediate('insert into detl(id, pid) values(6001, 6)') +# con_lock_1.commit() +# con_lock_1.execute_immediate('update %(target_obj)s set id=id where id=6' % locals()) +# +# con_lock_2.commit() # release record with ID=4. At this point session-worker will be allowed to delete rows with ID=4 and 5. +# +# con_lock_1.commit() # release record with ID=6. It is the last record which also must be deleted by session-worker. +# +# # Here we wait for ISQL complete its mission: +# p_worker.wait() +# +# flush_and_close(f_worker_log) +# flush_and_close(f_worker_err) +# +# # Close lockers: +# ################ +# for c in (con_lock_1, con_lock_2): +# c.close() +# +# +# # CHECK RESULTS +# ############### +# with open(f_worker_log.name,'r') as f: +# for line in f: +# if line.strip(): +# print('checked_mode: %(checked_mode)s, STDLOG: %(line)s' % locals()) +# +# for f in (f_init_err, f_worker_err): +# with open(f.name,'r') as g: +# for line in g: +# if line.strip(): +# print( 'checked_mode: ', checked_mode, ' UNEXPECTED STDERR IN ' + g.name + ':', line) +# +# #=4.0') +@pytest.mark.xfail +def test_read_consist_sttm_restart_on_merge_03_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + 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 new file mode 100644 index 00000000..ce5105b4 --- /dev/null +++ b/tests/functional/transactions/test_read_consist_sttm_restart_on_merge_04.py @@ -0,0 +1,436 @@ +#coding:utf-8 +# +# id: functional.transactions.read_consist_sttm_restart_on_merge_04 +# title: READ CONSISTENCY. Check creation of new statement-level snapshot and restarting changed caused by MERGE. Test-04. +# decription: +# Initial article for reading: +# https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:11504247549852 +# Note on terms which are used there: "BLOCKER", "LONG" and "FIRSTLAST" - their names are slightly changed here +# to: LOCKER-1, WORKER and LOCKER-2 respectively. +# See also: doc\\README.read_consistency.md +# +# ********************************************** +# +# This test verifies that statement-level snapshot and restart will be performed when "main" session ("worker") +# performs MERGE statement and is involved in update conflicts. +# ("When update conflict is detected <...> then engine <...> creates new statement-level snapshot and restart execution...") +# +# ::: NB ::: +# This test uses script %FBT_REPO% +# iles +# ead-consist-sttm-restart-DDL.sql which contains common DDL for all other such tests. +# Particularly, it contains two TRIGGERS (TLOG_WANT and TLOG_DONE) which are used for logging of planned actions and actual +# results against table TEST. These triggers use AUTONOMOUS transactions in order to have ability to see results in any +# outcome of test. +# +# ############### +# Following scenario if executed here (see also: "doc\\README.read_consistency.md"; hereafer is marked as "DOC"): +# * five rows are inserted into the table TEST, with ID = 1...5 and x = 1...5. +# +# * session 'locker-1' ("BLOCKER" in Tom Kyte's article ): +# update test set id = id where id = 1 +# +# * session 'worker' ("LONG" in TK article) has mission: +# update test where set id = -id where id <= 2 order by id DESC rows 4; // using TIL = read committed read consistency +# +# merge into test t +# using (select * from test where id <=2 order by id DESC rows 4) s on s.id=t.id +# when matched then +# update set t.id = -t.id +# when not matched then +# insert(id,x) values(1000 + s.id, 1000+ s.x); +# +# // Execution will have PLAN ORDER . +# // It will update rows starting with ID = 2 but can not change row with ID = 1 because of locker-1. +# // Update conflict appears here and, because of this, worker temporary changes its TIL to RC no record_version (RC NRV). +# // [DOC]: "a) transaction isolation mode temporarily switched to the READ COMMITTED *NO RECORD VERSION MODE*" +# // This (new) TIL allows worker further to see all committed versions, regardless of its own snapshot. +# +# * session 'locker-2' ("FIRSTLAST" in TK article): replaces ID = 5 with new value = -5, then commits +# and locks this record again: +# (1) commit; +# (2) update test set id = -5 where abs(id)=5; +# (3) commit; +# (4) update test set id = id where abs(id)=5; +# // session-'worker' remains waiting at this point because row with ID = 1 is still occupied by by locker-1. +# // but worker must further see record with (new) id = -5 because its TIL was changed to RC NO RECORD_VERSION. +# +# +# * session 'locker-1': replaces ID = 4 with new value = -4, then commits and locks this record again: +# (1) commit; +# (2) update test set id = -4 where abs(id)=4; +# (3) commit; +# (4) update test set id = id where abs(id)=4; +# +# // This: '(1) commit' - will release record with ID = 1. Worker sees this record and put write-lock on it. +# // [DOC]: "b) engine put write lock on conflicted record" +# // But it is only 2nd row of total 4 that worker must delete. +# // Because of TIL = RC NRV session-'worker' must see all committed records regardless on its own snapshot. +# // Worker resumes search for any rows with ID < 2, and it does this with taking in account required order +# // of its DML (i.e. 'ORDER BY ID DESC ...') +# // [DOC]: "c) engine continue to evaluate remaining records of update\\delete cursor and put write locks on it too" +# // Worker starts to search records which must be involved in its DML and *found* first sucn row with ID = -5. +# // NB. This row currently can NOT be deleted by worker because locker-2 has uncommitted update of it. +# // BECAUSE OF FACT THAT AT LEAST ONE ROW *WAS FOUND* - STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# // :::!! NB, AGAIN !! ::: restart NOT occurs here because at least one records found, see: +# // [DOC]: "d) when there is *no more* records to fetch, engine start to undo all actions performed since +# // top-level statement execution starts and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# +# * session 'locker-2': replaces ID = 3 with new value = -3, then commits and locks this record again: +# (1) commit; +# (2) update test set id = -3 where abs(id)=3; +# (3) commit; +# (4) update test set id = id where abs(id)=3; +# +# // This: '(1) commit' - will release record with ID = -5. Worker sees this record and put write-lock on it. +# // But this is only 3rd row of total 4 that worker must update. +# // Because of worker TIL = RC NRV, he must see all committed records regardless on its own snapshot. +# // Worker resumes search for any rows with ID < -5, and it does this with taking in account required order +# // of its DML (i.e. 'ORDER BY ID DESC ...') +# // [DOC]: "c) engine continue to evaluate remaining records of update\\delete cursor and put write locks on it too" +# // There are no such rows in the table. +# // BECAUSE OF FACT THAT NO RECORDS FOUND, WORKER DOES UNDO BUT KEEP LOCKS AND THEN MAKES FIRST STATEMENT-LEVEL RESTART. +# // [DOC]: "d) when there is no more records to fetch, engine start to undo all actions ... and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# +# * session 'locker-1': +# commit; +# // This will release record with ID=-4. Worker sees this record and put write-lock on it. +# // At this point worker has proceeded all required number of rows for DML: 2, 1, -4 and -5. +# // BECAUSE OF FACT THAT ALL ROWS WERE PROCEEDED, WORKER DOES UNDO BUT KEEP LOCKS AND THEN MAKES SECOND STATEMENT-LEVEL RESTART. +# // [DOC]: "d) when there is no more records to fetch, engine start to undo all actions ... and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# // After this restart worker will waiting for row with ID = -3 (it sees this because of TIL = RC NRV). +# +# * session 'locker-2': +# commit. +# // This releases row with ID=-3. Worker sees this record and put write-lock on it. +# // Records with ID = 2, 1, -4 and -5 already have been locked, but worker must update only FOUR rows (see its DML statement). +# // Thus only rows with ID = 2, 1, -3 and -4 will be updated. Record with ID = -5 must *remain* in the table. +# // At this point worker has proceeded all required rows that meet condition for DML: 2, 1, -3 and -4. +# // BECAUSE OF FACT THAT ALL ROWS WERE PROCEEDED, WORKER DOES UNDO BUT KEEP LOCKS AND THEN MAKES THIRD STATEMENT-LEVEL RESTART. +# // [DOC]: "d) when there is no more records to fetch, engine start to undo all actions ... and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# +# Expected result: +# * session-'worker' must *successfully* complete changes of 4 rows (but only two of them did exist at the starting point). +# Record with ID = -5 must remain in the table. +# +# * four unique values must be in the column TLOG_DONE.SNAP_NO for session-'worker' when it performed UPDATE statement: first of them +# was created by initial statement start and all others reflect three restarts (this column has values which are evaluated using +# rdb$get_context('SYSTEM', 'SNAPSHOT_NUMBER') -- see trigger TEST_AIUD). +# It is enough to count these values using COUNT(*) or enumarate them by DENSE_RANK() function. +# +# NOTE: concrete values of fields TRN, GLOBAL_CN and SNAP_NO in the TLOG_DONE can differ from one to another run! +# This is because of concurrent nature of connections that work against database. We must not assume that these values will be constant. +# +# ################ +# +# Checked on 4.0.0.2204 +# NOTE: added for-loop in order to check different target objects: TABLE ('test') and VIEW ('v_test'), see 'checked_mode'. +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# from subprocess import Popen +# import shutil +# from fdb import services +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # How long can we wait for session-worker completition, seconds +# # (ISQL often can not complete its job for several seconds!): +# MAX_TIME_FOR_WAITING_WORKER_FINISH = 60 +# +# ############################## +# # Temply, for debug obly: +# this_fdb=db_conn.database_name +# this_dbg=os.path.splitext(this_fdb)[0] + '.4debug.fdb' +# ############################## +# +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql_init_ddl = os.path.join(context['files_location'],'read-consist-sttm-restart-DDL.sql') +# +# for checked_mode in('table', 'view'): +# +# target_obj = 'test' if checked_mode == 'table' else 'v_test' +# +# f_init_log=open( os.path.join(context['temp_directory'],'read-consist-sttm-restart-DDL.log'), 'w') +# f_init_err=open( ''.join( ( os.path.splitext(f_init_log.name)[0], '.err') ), 'w') +# +# subprocess.call( [context['isql_path'], dsn, '-q', '-i', sql_init_ddl], stdout=f_init_log, stderr=f_init_err ) +# flush_and_close(f_init_log) +# flush_and_close(f_init_err) +# +# sql_addi=''' +# set term ^; +# execute block as +# begin +# rdb$set_context('USER_SESSION', 'WHO', 'INIT_DATA'); +# end +# ^ +# set term ;^ +# insert into %(target_obj)s(id, x) +# select row_number()over(),row_number()over() +# from rdb$types rows 5; +# commit; +# ''' % locals() +# runProgram('isql', [ dsn, '-q' ], sql_addi) +# +# locker_tpb = fdb.TPB() +# locker_tpb.lock_timeout = MAX_TIME_FOR_WAITING_WORKER_FINISH +# locker_tpb.lock_resolution = fdb.isc_tpb_wait +# +# con_lock_1 = fdb.connect( dsn = dsn, isolation_level=locker_tpb ) +# con_lock_2 = fdb.connect( dsn = dsn, isolation_level=locker_tpb ) +# +# con_lock_1.execute_immediate( "execute block as begin rdb$set_context('USER_SESSION', 'WHO', 'LOCKER #1'); end" ) +# con_lock_2.execute_immediate( "execute block as begin rdb$set_context('USER_SESSION', 'WHO', 'LOCKER #2'); end" ) +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# +# con_lock_1.execute_immediate( 'update %(target_obj)s set id=id where id=1' % locals() ) +# +# sql_text=''' +# connect '%(dsn)s'; +# set list on; +# set autoddl off; +# set term ^; +# execute block returns (whoami varchar(30)) as +# begin +# whoami = 'WORKER'; -- , ATT#' || current_connection; +# rdb$set_context('USER_SESSION','WHO', whoami); +# -- suspend; +# end +# ^ +# set term ;^ +# commit; +# SET KEEP_TRAN_PARAMS ON; +# set transaction read committed read consistency; +# --select current_connection, current_transaction from rdb$database; +# set list off; +# set wng off; +# +# --set plan on; +# set count on; +# +# merge into %(target_obj)s t -- THIS MUST HANG BECAUSE OF LOCKERs +# using (select * from %(target_obj)s where id <=2 order by id DESC rows 4) s on s.id=t.id +# when matched then +# update set t.id = -t.id +# when not matched then +# insert(id,x) values(1000 + s.id, 1000 + s.x); +# +# -- check results: +# -- ############### +# +# select id from %(target_obj)s order by id; -- one record must remain, with ID = -5 +# +# select v.old_id, v.op, v.snap_no_rank -- snap_no_rank must have four unique values: 1,2,3 and 4. +# from v_worker_log v +# where v.op = 'upd'; +# +# --set width who 10; +# -- DO NOT check this! Values can differ here from one run to another! +# -- select id, trn, who, old_id, new_id, op, rec_vers, global_cn, snap_no from tlog_done order by id; +# rollback; +# +# ''' % dict(globals(), **locals()) +# +# f_worker_sql=open( os.path.join(context['temp_directory'],'tmp_sttm_restart_on_delete_04.sql'), 'w') +# f_worker_sql.write(sql_text) +# flush_and_close(f_worker_sql) +# +# +# f_worker_log=open( ''.join( ( os.path.splitext(f_worker_sql.name)[0], '.log') ), 'w') +# f_worker_err=open( ''.join( ( os.path.splitext(f_worker_log.name)[0], '.err') ), 'w') +# +# ############################################################################ +# ### L A U N C H W O R K E R U S I N G I S Q L, A S Y N C. ### +# ############################################################################ +# +# p_worker = Popen( [ context['isql_path'], '-pag', '9999999', '-q', '-i', f_worker_sql.name ],stdout=f_worker_log, stderr=f_worker_err) +# time.sleep(1) +# +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# +# # Change ID so that it **will* be included in the set of rows that must be affected by session-worker: +# con_lock_2.execute_immediate( 'update %(target_obj)s set id = -5 where abs(id) = 5;' % locals() ) +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'update %(target_obj)s set id = id where abs(id) = 5;' % locals() ) +# +# +# con_lock_1.commit() # releases record with ID=1 (allow it to be deleted by session-worker) +# +# # Change ID so that it **will* be included in the set of rows that must be affected by session-worker: +# con_lock_1.execute_immediate( 'update %(target_obj)s set id = -4 where abs(id) = 4;' % locals() ) +# con_lock_1.commit() +# con_lock_1.execute_immediate( 'update %(target_obj)s set id = id where abs(id) = 4;' % locals() ) +# +# +# con_lock_2.commit() # releases record with ID = -5, but session-worker is waiting for record with ID = -4 (that was changed by locker-1). +# con_lock_2.execute_immediate( 'update %(target_obj)s set id = -3 where abs(id) = 3;' % locals() ) +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'update %(target_obj)s set id = id where abs(id) = 3;' % locals() ) +# +# con_lock_1.commit() # This releases row with ID=-4 but session-worker is waiting for ID = - 3 (changed by locker-2). +# con_lock_2.commit() # This releases row with ID=-3. No more locked rows so session-worker can finish its mission. +# +# # Here we wait for ISQL complete its mission: +# p_worker.wait() +# +# flush_and_close(f_worker_log) +# flush_and_close(f_worker_err) +# +# # Close lockers: +# ################ +# for c in (con_lock_1, con_lock_2): +# c.close() +# +# +# # CHECK RESULTS +# ############### +# with open(f_worker_log.name,'r') as f: +# for line in f: +# if line.strip(): +# print('checked_mode: %(checked_mode)s, STDLOG: %(line)s' % locals()) +# +# for f in (f_init_err, f_worker_err): +# with open(f.name,'r') as g: +# for line in g: +# if line.strip(): +# print( 'checked_mode: ', checked_mode, ' UNEXPECTED STDERR IN ' + g.name + ':', line) +# +# #=4.0') +@pytest.mark.xfail +def test_read_consist_sttm_restart_on_merge_04_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + 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 new file mode 100644 index 00000000..8a2bb376 --- /dev/null +++ b/tests/functional/transactions/test_read_consist_sttm_restart_on_update_01.py @@ -0,0 +1,422 @@ +#coding:utf-8 +# +# id: functional.transactions.read_consist_sttm_restart_on_update_01 +# title: READ CONSISTENCY. Check creation of new statement-level snapshot and restarting changed caused by UPDATE. Test-01. +# decription: +# Initial article for reading: +# https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:11504247549852 +# Note on terms which are used there: "BLOCKER", "LONG" and "FIRSTLAST" - their names are slightly changed here +# to: LOCKER-1, WORKER and LOCKER-2 respectively. +# +# ********************************************** +# +# This test verifies that statement-level snapshot and restart will be performed when "main" session ("worker") +# performs UPDATE statement and is involved in update conflicts. +# ("When update conflict is detected <...> then engine <...> creates new statement-level snapshot and restart execution...") +# +# ::: NB ::: +# This test uses script %FBT_REPO% +# iles +# ead-consist-sttm-restart-DDL.sql which contains common DDL for all other such tests. +# Particularly, it contains two TRIGGERS (TLOG_WANT and TLOG_DONE) which are used for logging of planned actions and actual +# results against table TEST. These triggers use AUTONOMOUS transactions in order to have ability to see results in any +# outcome of test. +# +# ############### +# Following scenario if executed here (see also: "doc\\README.read_consistency.md"; hereafer is marked as "DOC"): +# +# * five rows are inserted into the table TEST, with IDs: 1,2,3,4,5 +# * session 'locker-1' ("BLOCKER" in Tom Kyte's article ): +# update test set id = id where id = 5; +# +# * session 'worker' ("LONG" in TK article) has mission: +# update test set id = -id order by id // using TIL = read committed read consistency +# +# // Execution will have PLAN ORDER . +# // Worker starts with updating rows with ID = 1...4 but can not change row with ID = 5 because of locker-1. +# // Because of detecting update conflist, worker changes here its TIL to RC NO RECORD_VERSION. +# +# * session 'locker-2' ("FIRSTLAST" in TK article): +# (1) insert into test(id) values(-11); +# (2) commit; +# (3) update test set id=id where id = -11; +# // session-'worker' remains waiting at this point because row with ID = 5 is still occupied by by locker-1. +# // Record with (new) id = -11 will be seen further because worker's TIL was changed to RC NO RECORD_VERSION. +# +# * session 'locker-1': +# (1) commit; +# (2) insert into test(id) values(-12); +# (3) commit; +# (4) update test set id=id where id = -12; +# +# // This: '(1) commit' - will release record with ID = 5. Worker sees this record and put write-lock on it. +# // [DOC]: "b) engine put write lock on conflicted record" +# // Because of TIL = RC NRV session-'worker' must see all committed records regardless on its own snapshot. +# // Worker resumes search for rows that must be updated with taking in account required order of its DML (i.e. 'ORDER BY ID'). +# // [DOC]: "c) engine continue to evaluate remaining records of update\\delete cursor and put write locks on it too" +# // New record which is involved in DML (and did not exist before) *will be found*, its ID = -11. +# // Worker stops on this record (with ID = -11) because id is occupied by locker-2. +# // BECAUSE OF FACT THAT AT LEAST ONE ROW *WAS FOUND* - STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# // [DOC]: "d) when there is *no more* records to fetch, engine start to undo all actions performed since +# // top-level statement execution starts and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# +# * session 'locker-2': +# (1) commit; +# (2) insert into test(id) values(-13); +# (3) commit; +# (4) update test set id=id where id = -13; +# +# // This: '(1) commit' - will release record with ID = -11. Worker sees this record and put write-lock on it. +# // [DOC]: "b) engine put write lock on conflicted record" +# // Because of TIL = RC NRV session-'worker' must see all committed records regardless on its own snapshot. +# // Worker resumes search for rows that must be updated with taking in account required order of its DML (i.e. 'ORDER BY ID'). +# // [DOC]: "c) engine continue to evaluate remaining records of update\\delete cursor and put write locks on it too" +# // New record which is involved in DML (and did not exist before) *will be found*, its ID = -12. +# // Worker stops on this record (with ID = -12) because id is occupied by locker-1. +# // BECAUSE OF FACT THAT AT LEAST ONE ROW *WAS FOUND* - STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# // [DOC]: "d) when there is *no more* records to fetch, engine start to undo all actions performed since +# // top-level statement execution starts and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# +# +# * session 'locker-1': +# commit; +# // This commit will release record with ID = -12. Worker sees this record and put write-lock on it. +# // Worker resumes search for rows that must be updated with taking in account required order of its DML (i.e. 'ORDER BY ID'). +# // New record which is involved in DML (and did not exist before) *will be found*, its ID = -13. +# // Worker stops on this record (with ID = -13) because id is occupied by locker-2. +# // BECAUSE OF FACT THAT AT LEAST ONE ROW *WAS FOUND* - STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# +# * session 'locker-2': +# commit; +# // This releases row with ID = -13. Worker sees this record and put write-lock on it. +# // At this point there are no more records to be locked (by worker) that meet cursor condition: worker did put +# // write locks on all rows that meet its cursor conditions. +# // BECAUSE OF FACT THAT NO MORE RECORDS FOUND TO BE LOCKED, WORKER DOES UNDO BUT KEEP LOCKS AND THEN +# // MAKES FIRST STATEMENT-LEVEL RESTART. This restart is also the last in this test. +# +# +# Expected result: +# * session-'worker' must update of all rows with reverting signs of their IDs. Records which were inserted must have positive IDs. +# +# * Two unique values must be in the column TLOG_DONE.SNAP_NO for session-'worker' when it performed UPDATE statement: first of them +# was created by initial statement start and second reflects SINGLE restart (this column has values which are evaluated using +# rdb$get_context('SYSTEM', 'SNAPSHOT_NUMBER') -- see trigger TEST_AIUD). +# It is enough to count these values using COUNT(*) or enumarate them by DENSE_RANK() function. +# +# NOTE: concrete values of fields TRN, GLOBAL_CN and SNAP_NO in the TLOG_DONE can differ from one to another run! +# This is because of concurrent nature of connections that work against database. We must not assume that these values will be constant. +# +# ################ +# +# Checked on 4.0.0.2195 +# 24.09.2020: added for-loop in order to check different target objects: TABLE ('test') and VIEW ('v_test'), see 'checked_mode'. +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# from subprocess import Popen +# from fdb import services +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql_init_ddl = os.path.join(context['files_location'],'read-consist-sttm-restart-DDL.sql') +# +# for checked_mode in('table', 'view'): +# +# target_obj = 'test' if checked_mode == 'table' else 'v_test' +# +# f_init_log=open( os.path.join(context['temp_directory'],'read-consist-sttm-restart-DDL.log'), 'w') +# f_init_err=open( ''.join( ( os.path.splitext(f_init_log.name)[0], '.err') ), 'w') +# +# # RECREATION OF ALL DB OBJECTS: +# # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# subprocess.call( [context['isql_path'], dsn, '-q', '-i', sql_init_ddl], stdout=f_init_log, stderr=f_init_err ) +# flush_and_close(f_init_log) +# flush_and_close(f_init_err) +# +# # add rows with ID = 1, 2, ..., 5: +# sql_addi=''' +# set term ^; +# execute block as +# begin +# rdb$set_context('USER_SESSION', 'WHO', 'INIT_DATA'); +# end +# ^ +# set term ;^ +# insert into %(target_obj)s(id, x) +# select row_number()over(),row_number()over() +# from rdb$types rows 5; +# commit; +# ''' % locals() +# runProgram('isql', [ dsn, '-q' ], sql_addi) +# +# con_lock_1 = fdb.connect( dsn = dsn ) +# con_lock_2 = fdb.connect( dsn = dsn ) +# con_lock_1.execute_immediate( "execute block as begin rdb$set_context('USER_SESSION', 'WHO', 'LOCKER #1'); end" ) +# con_lock_2.execute_immediate( "execute block as begin rdb$set_context('USER_SESSION', 'WHO', 'LOCKER #2'); end" ) +# +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# +# con_lock_1.execute_immediate( 'update %(target_obj)s set id=id where id = 5' % locals()) +# +# sql_text=''' +# connect '%(dsn)s'; +# set list on; +# set autoddl off; +# set term ^; +# execute block returns (whoami varchar(30)) as +# begin +# whoami = 'WORKER'; -- , ATT#' || current_connection; +# rdb$set_context('USER_SESSION','WHO', whoami); +# -- suspend; +# end +# ^ +# set term ;^ +# commit; +# --set echo on; +# SET KEEP_TRAN_PARAMS ON; +# set transaction read committed read consistency; +# --select current_connection, current_transaction from rdb$database; +# set list off; +# set wng off; +# --set plan on; +# set count on; +# +# update %(target_obj)s set id = -id order by id; -- THIS MUST BE LOCKED +# +# -- check results: +# -- ############### +# +# select id from %(target_obj)s order by id; -- this will produce output only after all lockers do their commit/rollback +# +# select v.old_id, v.op, v.snap_no_rank +# from v_worker_log v +# where v.op = 'upd'; +# +# set width who 10; +# -- DO NOT check this! Values can differ here from one run to another! +# -- select id, trn, who, old_id, new_id, op, rec_vers, global_cn, snap_no from tlog_done order by id; +# +# rollback; +# +# ''' % dict(globals(), **locals()) +# +# f_worker_sql=open( os.path.join(context['temp_directory'],'tmp_sttm_restart_on_update_01.sql'), 'w') +# f_worker_sql.write(sql_text) +# flush_and_close(f_worker_sql) +# +# +# f_worker_log=open( ''.join( ( os.path.splitext(f_worker_sql.name)[0], '.log') ), 'w') +# f_worker_err=open( ''.join( ( os.path.splitext(f_worker_log.name)[0], '.err') ), 'w') +# +# ############################################################################ +# ### L A U N C H W O R K E R U S I N G I S Q L, A S Y N C. ### +# ############################################################################ +# +# p_worker = Popen( [ context['isql_path'], '-pag', '999999', '-q', '-i', f_worker_sql.name ],stdout=f_worker_log, stderr=f_worker_err) +# time.sleep(1) +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# con_lock_2.execute_immediate( 'insert into %(target_obj)s(id) values(-11)' % locals()) +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'update %(target_obj)s set id=id where id = -11' % locals()) +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# con_lock_1.commit() +# con_lock_1.execute_immediate( 'insert into %(target_obj)s(id) values(-12)' % locals() ) +# con_lock_1.commit() +# con_lock_1.execute_immediate( 'update %(target_obj)s set id=id where id = -12' % locals() ) +# +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'insert into %(target_obj)s(id) values(-13)' % locals() ) +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'update %(target_obj)s set id=id where id = -13' % locals() ) +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# con_lock_1.commit() +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# con_lock_2.commit() # WORKER will complete his job after this +# +# +# # Here we wait for ISQL complete its mission: +# p_worker.wait() +# +# flush_and_close(f_worker_log) +# flush_and_close(f_worker_err) +# +# # Close lockers: +# ################ +# for c in (con_lock_1, con_lock_2): +# c.close() +# +# +# # CHECK RESULTS +# ############### +# with open(f_worker_log.name,'r') as f: +# for line in f: +# if line.strip(): +# print('checked_mode: %(checked_mode)s, STDLOG: %(line)s' % locals()) +# +# for f in (f_init_err, f_worker_err): +# with open(f.name,'r') as g: +# for line in g: +# if line.strip(): +# print( 'checked_mode: ', checked_mode, ' UNEXPECTED STDERR IN ' + g.name + ':', line) +# +# #=4.0') +@pytest.mark.xfail +def test_read_consist_sttm_restart_on_update_01_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + 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 new file mode 100644 index 00000000..35ddcd31 --- /dev/null +++ b/tests/functional/transactions/test_read_consist_sttm_restart_on_update_02.py @@ -0,0 +1,406 @@ +#coding:utf-8 +# +# id: functional.transactions.read_consist_sttm_restart_on_update_02 +# title: READ CONSISTENCY. Check creation of new statement-level snapshot and restarting changed caused by UPDATE. Test-02. +# decription: +# Initial article for reading: +# https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:11504247549852 +# Note on terms which are used there: "BLOCKER", "LONG" and "FIRSTLAST" - their names are slightly changed here +# to: LOCKER-1, WORKER and LOCKER-2 respectively. +# +# ********************************************** +# +# This test verifies that statement-level snapshot and restart will be performed when "main" session ("worker") +# performs UPDATE statement and is involved in update conflicts. +# ("When update conflict is detected <...> then engine <...> creates new statement-level snapshot and restart execution...") +# +# ::: NB ::: +# This test uses script %FBT_REPO% +# iles +# ead-consist-sttm-restart-DDL.sql which contains common DDL for all other such tests. +# Particularly, it contains two TRIGGERS (TLOG_WANT and TLOG_DONE) which are used for logging of planned actions and actual +# results against table TEST. These triggers use AUTONOMOUS transactions in order to have ability to see results in any +# outcome of test. +# +# ############### +# Following scenario if executed here (see also: "doc\\README.read_consistency.md"; hereafer is marked as "DOC"): +# +# * five rows are inserted into the table TEST, with IDs: 1,2,3,4,5 +# * session 'locker-1' ("BLOCKER" in Tom Kyte's article ): +# delete from test where id = 5; +# +# * session 'worker' ("LONG" in TK article) has mission: +# update test set id = -id where exists(select * from test where id < 0 or id = 5) order by id; // using TIL = read committed read consistency +# +# // Execution will have PLAN ORDER . +# // Worker starts with updating rows with ID = 1...4 but can not change row with ID = 5 because of locker-1. +# // Because of detecting update conflist, worker changes here its TIL to RC NO RECORD_VERSION. +# +# * session 'locker-2' ("FIRSTLAST" in TK article): +# (1) insert into test(id) values(-11); +# (2) commit; +# (3) delete from test where id = -11; +# +# // session-'worker' remains waiting at this point because row with ID = 5 is still occupied by by locker-1. +# // Record with (new) id = -11 will be seen further because worker's TIL was changed to RC NO RECORD_VERSION. +# +# * session 'locker-1': +# (1) commit; +# (2) insert into test(id) values(-12); +# (3) commit; +# (4) delete from test where id = -12; +# +# // This: '(1) commit' - removes record with id = 5. +# // Because of TIL = RC NRV session-'worker' must see all committed records regardless on its own snapshot. +# // Thus worker sees record with id = -11 (which is locked now by locker-2) and puts write-lock on it. +# // [DOC]: "b) engine put write lock on conflicted record" +# // BECAUSE OF FACT THAT AT LEAST ONE ROW *WAS FOUND* - STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# // [DOC]: "d) when there is *no more* records to fetch, engine start to undo all actions performed since +# // top-level statement execution starts and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# +# * session 'locker-2': +# (1) commit; +# (2) insert into test(id) values(-13); +# (3) commit; +# (4) update test set id=id where id = -13; +# +# // This: '(1) commit' - removes record with id = -11. +# // Because of TIL = RC NRV session-'worker' must see all committed records regardless on its own snapshot. +# // Thus worker sees record with id = -12 (which is locked now by locker-1) and puts write-lock on it. +# // BECAUSE OF FACT THAT AT LEAST ONE ROW *WAS FOUND* - STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# +# * session 'locker-1': +# (1) commit; +# (2) insert into test(id) values(-14); +# (3) commit; +# (4) update test set id=id where id = -14; +# +# // This: '(1) commit' - removes record with id = -12. +# // Because of TIL = RC NRV session-'worker' must see all committed records regardless on its own snapshot. +# // Thus worker sees record with id = -13 (which is locked now by locker-2) and puts write-lock on it. +# // BECAUSE OF FACT THAT AT LEAST ONE ROW *WAS FOUND* - STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# +# * session 'locker-2': +# (1) commit; +# +# // This removes record with id = -13. +# // Worker still waits for record with id = -14 which is occupied by locker-1. +# +# * session 'locker-1': +# (1) commit; +# +# // This removes record with id = -14. +# // At this point there are no more records to be locked (by worker) that meet cursor condition: worker did put +# // write locks on all rows that meet its cursor conditions. +# // BECAUSE OF FACT THAT NO MORE RECORDS FOUND TO BE LOCKED, WORKER DOES UNDO BUT KEEP LOCKS AND THEN +# // MAKES FIRST STATEMENT-LEVEL RESTART. This restart is also the last in this test. +# +# +# Expected result: +# * session-'worker' must update of only rows with ID = 1...4 (reverting sign of IDs value). +# +# * Two unique values must be in the column TLOG_DONE.SNAP_NO for session-'worker' when it performed UPDATE statement: first of them +# was created by initial statement start and second reflects SINGLE restart (this column has values which are evaluated using +# rdb$get_context('SYSTEM', 'SNAPSHOT_NUMBER') -- see trigger TEST_AIUD). +# It is enough to count these values using COUNT(*) or enumarate them by DENSE_RANK() function. +# +# NOTE: concrete values of fields TRN, GLOBAL_CN and SNAP_NO in the TLOG_DONE can differ from one to another run! +# This is because of concurrent nature of connections that work against database. We must not assume that these values will be constant. +# +# ################ +# +# Checked on 4.0.0.2195 +# 26.09.2020: added for-loop in order to check different target objects: TABLE ('test') and VIEW ('v_test'), see 'checked_mode'. +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# from subprocess import Popen +# from fdb import services +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql_init_ddl = os.path.join(context['files_location'],'read-consist-sttm-restart-DDL.sql') +# +# for checked_mode in('table', 'view'): +# +# target_obj = 'test' if checked_mode == 'table' else 'v_test' +# +# f_init_log=open( os.path.join(context['temp_directory'],'read-consist-sttm-restart-DDL.log'), 'w') +# f_init_err=open( ''.join( ( os.path.splitext(f_init_log.name)[0], '.err') ), 'w') +# +# subprocess.call( [context['isql_path'], dsn, '-q', '-i', sql_init_ddl], stdout=f_init_log, stderr=f_init_err ) +# flush_and_close(f_init_log) +# flush_and_close(f_init_err) +# +# # add rows with ID = 1, 2, ..., 5: +# sql_addi=''' +# set term ^; +# execute block as +# begin +# rdb$set_context('USER_SESSION', 'WHO', 'INIT_DATA'); +# end +# ^ +# set term ;^ +# insert into %(target_obj)s(id, x) select row_number()over(),row_number()over() from rdb$types rows 5; +# commit; +# ''' % locals() +# runProgram('isql', [ dsn, '-q' ], sql_addi) +# +# con_lock_1 = fdb.connect( dsn = dsn ) +# con_lock_2 = fdb.connect( dsn = dsn ) +# con_lock_1.execute_immediate( "execute block as begin rdb$set_context('USER_SESSION', 'WHO', 'LOCKER #1'); end" ) +# con_lock_2.execute_immediate( "execute block as begin rdb$set_context('USER_SESSION', 'WHO', 'LOCKER #2'); end" ) +# +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# +# con_lock_1.execute_immediate( 'delete from %(target_obj)s where id = 5' % locals()) +# +# sql_text=''' +# connect '%(dsn)s'; +# set list on; +# set autoddl off; +# set term ^; +# execute block returns (whoami varchar(30)) as +# begin +# whoami = 'WORKER'; -- , ATT#' || current_connection; +# rdb$set_context('USER_SESSION','WHO', whoami); +# -- suspend; +# end +# ^ +# set term ;^ +# commit; +# --set echo on; +# SET KEEP_TRAN_PARAMS ON; +# set transaction read committed read consistency; +# --select current_connection, current_transaction from rdb$database; +# set list off; +# set wng off; +# --set plan on; +# set count on; +# +# update %(target_obj)s set id = -id order by id; -- THIS MUST BE LOCKED +# +# -- check results: +# -- ############### +# +# select id from %(target_obj)s order by id; -- this will produce output only after all lockers do their commit/rollback +# +# select v.old_id, v.op, v.snap_no_rank from v_worker_log v where v.op = 'upd'; +# +# set width who 10; +# -- DO NOT check this! Values can differ here from one run to another! +# -- select id, trn, who, old_id, new_id, op, rec_vers, global_cn, snap_no from tlog_done order by id; +# +# rollback; +# +# ''' % dict(globals(), **locals()) +# +# f_worker_sql=open( os.path.join(context['temp_directory'],'tmp_sttm_restart_on_update_02.sql'), 'w') +# f_worker_sql.write(sql_text) +# flush_and_close(f_worker_sql) +# +# +# f_worker_log=open( ''.join( ( os.path.splitext(f_worker_sql.name)[0], '.log') ), 'w') +# f_worker_err=open( ''.join( ( os.path.splitext(f_worker_log.name)[0], '.err') ), 'w') +# +# ############################################################################ +# ### L A U N C H W O R K E R U S I N G I S Q L, A S Y N C. ### +# ############################################################################ +# +# p_worker = Popen( [ context['isql_path'], '-pag', '999999', '-q', '-i', f_worker_sql.name ],stdout=f_worker_log, stderr=f_worker_err) +# time.sleep(1) +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# con_lock_2.execute_immediate( 'insert into %(target_obj)s(id) values(-11)' % locals()) +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'delete from %(target_obj)s where id = -11' % locals()) +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# con_lock_1.commit() +# con_lock_1.execute_immediate( 'insert into %(target_obj)s(id) values(-12)' % locals()) +# con_lock_1.commit() +# con_lock_1.execute_immediate( 'delete from %(target_obj)s where id = -12' % locals()) +# +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'insert into %(target_obj)s(id) values(-13)' % locals()) +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'delete from %(target_obj)s where id = -13' % locals()) +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# con_lock_1.commit() +# con_lock_1.execute_immediate( 'insert into %(target_obj)s(id) values(-14)' % locals()) +# con_lock_1.commit() +# con_lock_1.execute_immediate( 'delete from %(target_obj)s where id = -14' % locals()) +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# con_lock_1.commit() +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# con_lock_2.commit() # WORKER will complete his job after this +# +# +# # Here we wait for ISQL complete its mission: +# p_worker.wait() +# +# flush_and_close(f_worker_log) +# flush_and_close(f_worker_err) +# +# # Close lockers: +# ################ +# for c in (con_lock_1, con_lock_2): +# c.close() +# +# # CHECK RESULTS +# ############### +# with open(f_worker_log.name,'r') as f: +# for line in f: +# if line.strip(): +# print('checked_mode: %(checked_mode)s, STDLOG: %(line)s' % locals()) +# +# for f in (f_init_err, f_worker_err): +# with open(f.name,'r') as g: +# for line in g: +# if line.strip(): +# print( 'checked_mode: ', checked_mode, ' UNEXPECTED STDERR IN ' + g.name + ':', line) +# +# #=4.0') +@pytest.mark.xfail +def test_read_consist_sttm_restart_on_update_02_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + 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 new file mode 100644 index 00000000..4b19761c --- /dev/null +++ b/tests/functional/transactions/test_read_consist_sttm_restart_on_update_03.py @@ -0,0 +1,440 @@ +#coding:utf-8 +# +# id: functional.transactions.read_consist_sttm_restart_on_update_03 +# title: READ CONSISTENCY. Check creation of new statement-level snapshot and restarting changed caused by UPDATE. Test-03. +# decription: +# Initial article for reading: +# https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:11504247549852 +# Note on terms which are used there: "BLOCKER", "LONG" and "FIRSTLAST" - their names are slightly changed here +# to: LOCKER-1, WORKER and LOCKER-2 respectively. +# +# ********************************************** +# +# This test verifies that statement-level snapshot and restart will be performed when "main" session ("worker") +# performs UPDATE statement and is involved in update conflicts. +# ("When update conflict is detected <...> then engine <...> creates new statement-level snapshot and restart execution...") +# +# ::: NB ::: +# This test uses script %FBT_REPO% +# iles +# ead-consist-sttm-restart-DDL.sql which contains common DDL for all other such tests. +# Particularly, it contains two TRIGGERS (TLOG_WANT and TLOG_DONE) which are used for logging of planned actions and actual +# results against table TEST. These triggers use AUTONOMOUS transactions in order to have ability to see results in any +# outcome of test. +# +# ############### +# Following scenario if executed here (see also: "doc\\README.read_consistency.md"; hereafer is marked as "DOC"): +# +# * two rows are inserted into the table TEST, with IDs: 1,2 +# * session 'locker-1' ("BLOCKER" in Tom Kyte's article ): +# update test set id=id where id = 2; +# +# * session 'worker' ("LONG" in TK article) has mission: +# update test set id = -id order by id; // using TIL = read committed read consistency +# +# // Execution will have PLAN ORDER . +# // Worker starts with updating rows with ID = 1...2 but can not change row with ID = 2 because of locker-1. +# // Because of detecting update conflist, worker changes here its TIL to RC NO RECORD_VERSION. +# +# * session 'locker-2' ("FIRSTLAST" in TK article): +# (1) insert into test(id) values( 110); +# (2) insert into test(id) values(-11); +# (3) commit; +# (4) update test set id=-d where id = 110; +# (5) update test set id=-d where id = -11; +# +# // session-'worker' remains waiting at this point because row with ID = 2 is still occupied by by locker-1. +# // Records with (new) IDs = -11 and 110 will be seen further because worker's TIL was changed to RC NO RECORD_VERSION. +# +# * session 'locker-1': +# (1) commit; +# (2) insert into test(id) values(120); +# (3) insert into test(id) values(-12); +# (4) commit; +# (5) update test set id=-d where id = 120; +# (6) update test set id=-d where id = -12; +# +# // This: '(1) commit' - releases record with id = 2. +# // Because of TIL = RC NRV session-'worker' must see all committed records regardless on its own snapshot. +# // Thus worker sees records with id = -11 and 110 (which is locked now by locker-2) and puts write-lock on them. +# // [DOC]: "b) engine put write lock on conflicted record" +# // BECAUSE OF FACT THAT AT LEAST ONE ROW *WAS FOUND* - STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# // [DOC]: "d) when there is *no more* records to fetch, engine start to undo all actions performed since +# // top-level statement execution starts and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# +# * session 'locker-2': +# (1) commit; +# (2) insert into test(id) values(130); +# (3) insert into test(id) values(-13); +# (4) commit; +# (5) update test set id=-d where id = 130; +# (6) update test set id=-d where id = -13; +# +# // This: '(1) commit' - releases records with IDs = -11 and 110. +# // Because of TIL = RC NRV session-'worker' must see all committed records regardless on its own snapshot. +# // Thus worker sees records with id = -12 and 120 (which is locked now by locker-1) and puts write-lock on them. +# // BECAUSE OF FACT THAT AT LEAST ONE ROW *WAS FOUND* - STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# +# * session 'locker-1': +# (1) commit; +# (2) insert into test(id) values(140); +# (3) insert into test(id) values(-14); +# (4) commit; +# (5) update test set id=-d where id = 140; +# (6) update test set id=-d where id = -14; +# +# // This: '(1) commit' - releases records with IDs = -12 and 120. +# // Because of TIL = RC NRV session-'worker' must see all committed records regardless on its own snapshot. +# // Thus worker sees records with id = -13 and 130 (which is locked now by locker-2) and puts write-lock on them. +# // BECAUSE OF FACT THAT AT LEAST ONE ROW *WAS FOUND* - STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# +# * session 'locker-2': +# (1) commit; +# +# // This releases records with id = -13 and 130. +# // Worker still waits for records with id = -14 and 140 which are occupied by locker-1. +# +# * session 'locker-1': +# (1) commit; +# +# // This releases records with id = -14 and 140. +# // At this point there are no more records to be locked (by worker) that meet cursor condition: worker did put +# // write locks on all rows that meet its cursor conditions. +# // BECAUSE OF FACT THAT NO MORE RECORDS FOUND TO BE LOCKED, WORKER DOES UNDO BUT KEEP LOCKS AND THEN +# // MAKES FIRST STATEMENT-LEVEL RESTART. This restart is also the last in this test. +# +# +# Expected result: +# * session-'worker' must update all rows. +# +# * Two unique values must be in the column TLOG_DONE.SNAP_NO for session-'worker' when it performed UPDATE statement: first of them +# was created by initial statement start and second reflects SINGLE restart (this column has values which are evaluated using +# rdb$get_context('SYSTEM', 'SNAPSHOT_NUMBER') -- see trigger TEST_AIUD). +# It is enough to count these values using COUNT(*) or enumarate them by DENSE_RANK() function. +# +# NOTE: concrete values of fields TRN, GLOBAL_CN and SNAP_NO in the TLOG_DONE can differ from one to another run! +# This is because of concurrent nature of connections that work against database. We must not assume that these values will be constant. +# +# ################ +# +# Checked on 4.0.0.2195 +# 26.09.2020: added for-loop in order to check different target objects: TABLE ('test') and VIEW ('v_test'), see 'checked_mode'. +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# from subprocess import Popen +# from fdb import services +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql_init_ddl = os.path.join(context['files_location'],'read-consist-sttm-restart-DDL.sql') +# +# for checked_mode in('table', 'view'): +# +# target_obj = 'test' if checked_mode == 'table' else 'v_test' +# +# f_init_log=open( os.path.join(context['temp_directory'],'read-consist-sttm-restart-DDL.log'), 'w') +# f_init_err=open( ''.join( ( os.path.splitext(f_init_log.name)[0], '.err') ), 'w') +# +# subprocess.call( [context['isql_path'], dsn, '-q', '-i', sql_init_ddl], stdout=f_init_log, stderr=f_init_err ) +# flush_and_close(f_init_log) +# flush_and_close(f_init_err) +# +# # add rows with ID = 1, 2: +# sql_addi=''' +# set term ^; +# execute block as +# begin +# rdb$set_context('USER_SESSION', 'WHO', 'INIT_DATA'); +# end +# ^ +# set term ;^ +# insert into %(target_obj)s(id, x) select row_number()over(),row_number()over() from rdb$types rows 2; +# commit; +# ''' % locals() +# runProgram('isql', [ dsn, '-q' ], sql_addi) +# +# con_lock_1 = fdb.connect( dsn = dsn ) +# con_lock_2 = fdb.connect( dsn = dsn ) +# con_lock_1.execute_immediate( "execute block as begin rdb$set_context('USER_SESSION', 'WHO', 'LOCKER #1'); end" ) +# con_lock_2.execute_immediate( "execute block as begin rdb$set_context('USER_SESSION', 'WHO', 'LOCKER #2'); end" ) +# +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# +# con_lock_1.execute_immediate( 'update %(target_obj)s set id=id where id = 2' % locals() ) +# +# sql_text=''' +# connect '%(dsn)s'; +# set list on; +# set autoddl off; +# set term ^; +# execute block returns (whoami varchar(30)) as +# begin +# whoami = 'WORKER'; -- , ATT#' || current_connection; +# rdb$set_context('USER_SESSION','WHO', whoami); +# -- suspend; +# end +# ^ +# set term ;^ +# commit; +# --set echo on; +# SET KEEP_TRAN_PARAMS ON; +# set transaction read committed read consistency; +# --select current_connection, current_transaction from rdb$database; +# set list off; +# set wng off; +# --set plan on; +# set count on; +# +# update %(target_obj)s set id = -id order by id; -- THIS MUST BE LOCKED +# +# -- check results: +# -- ############### +# +# select id from %(target_obj)s order by id; -- this will produce output only after all lockers do their commit/rollback +# +# select v.old_id, v.op, v.snap_no_rank from v_worker_log v where v.op = 'upd'; +# +# set width who 10; +# -- DO NOT check this! Values can differ here from one run to another! +# -- select id, trn, who, old_id, new_id, op, rec_vers, global_cn, snap_no from tlog_done order by id; +# +# rollback; +# +# ''' % dict(globals(), **locals()) +# +# f_worker_sql=open( os.path.join(context['temp_directory'],'tmp_sttm_restart_on_update_03.sql'), 'w') +# f_worker_sql.write(sql_text) +# flush_and_close(f_worker_sql) +# +# +# f_worker_log=open( ''.join( ( os.path.splitext(f_worker_sql.name)[0], '.log') ), 'w') +# f_worker_err=open( ''.join( ( os.path.splitext(f_worker_log.name)[0], '.err') ), 'w') +# +# ############################################################################ +# ### L A U N C H W O R K E R U S I N G I S Q L, A S Y N C. ### +# ############################################################################ +# +# p_worker = Popen( [ context['isql_path'], '-pag', '999999', '-q', '-i', f_worker_sql.name ],stdout=f_worker_log, stderr=f_worker_err) +# time.sleep(1) +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# con_lock_2.execute_immediate( 'insert into %(target_obj)s(id) values(110)' % locals() ) +# con_lock_2.execute_immediate( 'insert into %(target_obj)s(id) values(-11)' % locals() ) +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'update %(target_obj)s set id=id where id = 110' % locals() ) +# con_lock_2.execute_immediate( 'update %(target_obj)s set id=id where id = -11' % locals() ) +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# con_lock_1.commit() +# con_lock_1.execute_immediate( 'insert into %(target_obj)s(id) values(120)' % locals() ) +# con_lock_1.execute_immediate( 'insert into %(target_obj)s(id) values(-12)' % locals() ) +# con_lock_1.commit() +# con_lock_1.execute_immediate( 'update %(target_obj)s set id=id where id = 120' % locals() ) +# con_lock_1.execute_immediate( 'update %(target_obj)s set id=id where id = -12' % locals() ) +# +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'insert into %(target_obj)s(id) values(130)' % locals() ) +# con_lock_2.execute_immediate( 'insert into %(target_obj)s(id) values(-13)' % locals() ) +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'update %(target_obj)s set id=id where id = 130' % locals() ) +# con_lock_2.execute_immediate( 'update %(target_obj)s set id=id where id = -13' % locals() ) +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# con_lock_1.commit() +# con_lock_1.execute_immediate( 'insert into %(target_obj)s(id) values(140)' % locals() ) +# con_lock_1.execute_immediate( 'insert into %(target_obj)s(id) values(-14)' % locals() ) +# con_lock_1.commit() +# con_lock_1.execute_immediate( 'update %(target_obj)s set id=id where id = 140' % locals() ) +# con_lock_1.execute_immediate( 'update %(target_obj)s set id=id where id = -14' % locals() ) +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# con_lock_1.commit() +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# con_lock_2.commit() # WORKER will complete his job after this +# +# +# # Here we wait for ISQL complete its mission: +# p_worker.wait() +# +# flush_and_close(f_worker_log) +# flush_and_close(f_worker_err) +# +# # Close lockers: +# ################ +# for c in (con_lock_1, con_lock_2): +# c.close() +# +# # CHECK RESULTS +# ############### +# with open(f_worker_log.name,'r') as f: +# for line in f: +# if line.strip(): +# print('checked_mode: %(checked_mode)s, STDLOG: %(line)s' % locals()) +# +# for f in (f_init_err, f_worker_err): +# with open(f.name,'r') as g: +# for line in g: +# if line.strip(): +# print( 'checked_mode: ', checked_mode, ' UNEXPECTED STDERR IN ' + g.name + ':', line) +# +# #=4.0') +@pytest.mark.xfail +def test_read_consist_sttm_restart_on_update_03_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + 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 new file mode 100644 index 00000000..54929b3f --- /dev/null +++ b/tests/functional/transactions/test_read_consist_sttm_restart_on_update_04.py @@ -0,0 +1,426 @@ +#coding:utf-8 +# +# id: functional.transactions.read_consist_sttm_restart_on_update_04 +# title: READ CONSISTENCY. Check creation of new statement-level snapshot and restarting changed caused by UPDATE. Test-04. +# decription: +# Initial article for reading: +# https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:11504247549852 +# Note on terms which are used there: "BLOCKER", "LONG" and "FIRSTLAST" - their names are slightly changed here +# to: LOCKER-1, WORKER and LOCKER-2 respectively. +# See also: doc\\README.read_consistency.md +# +# ********************************************** +# +# This test verifies that statement-level snapshot and restart will be performed when "main" session ("worker") +# performs UPDATE statement and is involved in update conflicts. +# ("When update conflict is detected <...> then engine <...> creates new statement-level snapshot and restart execution...") +# +# ::: NB ::: +# This test uses script %FBT_REPO% +# iles +# ead-consist-sttm-restart-DDL.sql which contains common DDL for all other such tests. +# Particularly, it contains two TRIGGERS (TLOG_WANT and TLOG_DONE) which are used for logging of planned actions and actual +# results against table TEST. These triggers use AUTONOMOUS transactions in order to have ability to see results in any +# outcome of test. +# +# ############### +# Following scenario if executed here (see also: "doc\\README.read_consistency.md"; hereafer is marked as "DOC"): +# * five rows are inserted into the table TEST, with ID = 1...5 and x = 1...5. +# +# * session 'locker-1' ("BLOCKER" in Tom Kyte's article ): +# update test set id = id where id = 1 +# +# * session 'worker' ("LONG" in TK article) has mission: +# update test where set id = -id where id <= 2 order by id DESC rows 4; // using TIL = read committed read consistency +# +# // Execution will have PLAN ORDER . +# // It will update rows starting with ID = 2 but can not change row with ID = 1 because of locker-1. +# // Update conflict appears here and, because of this, worker temporary changes its TIL to RC no record_version (RC NRV). +# // [DOC]: "a) transaction isolation mode temporarily switched to the READ COMMITTED *NO RECORD VERSION MODE*" +# // This (new) TIL allows worker further to see all committed versions, regardless of its own snapshot. +# +# * session 'locker-2' ("FIRSTLAST" in TK article): replaces ID = 5 with new value = -5, then commits +# and locks this record again: +# (1) commit; +# (2) update test set id = -5 where abs(id)=5; +# (3) commit; +# (4) update test set id = id where abs(id)=5; +# // session-'worker' remains waiting at this point because row with ID = 1 is still occupied by by locker-1. +# // but worker must further see record with (new) id = -5 because its TIL was changed to RC NO RECORD_VERSION. +# +# +# * session 'locker-1': replaces ID = 4 with new value = -4, then commits and locks this record again: +# (1) commit; +# (2) update test set id = -4 where abs(id)=4; +# (3) commit; +# (4) update test set id = id where abs(id)=4; +# +# // This: '(1) commit' - will release record with ID = 1. Worker sees this record and put write-lock on it. +# // [DOC]: "b) engine put write lock on conflicted record" +# // But it is only 2nd row of total 4 that worker must delete. +# // Because of TIL = RC NRV session-'worker' must see all committed records regardless on its own snapshot. +# // Worker resumes search for any rows with ID < 2, and it does this with taking in account required order +# // of its DML (i.e. 'ORDER BY ID DESC ...') +# // [DOC]: "c) engine continue to evaluate remaining records of update\\delete cursor and put write locks on it too" +# // Worker starts to search records which must be involved in its DML and *found* first sucn row with ID = -5. +# // NB. This row currently can NOT be deleted by worker because locker-2 has uncommitted update of it. +# // BECAUSE OF FACT THAT AT LEAST ONE ROW *WAS FOUND* - STATEMENT-LEVEL RESTART *NOT* YET OCCURS HERE. +# // :::!! NB, AGAIN !! ::: restart NOT occurs here because at least one records found, see: +# // [DOC]: "d) when there is *no more* records to fetch, engine start to undo all actions performed since +# // top-level statement execution starts and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# +# * session 'locker-2': replaces ID = 3 with new value = -3, then commits and locks this record again: +# (1) commit; +# (2) update test set id = -3 where abs(id)=3; +# (3) commit; +# (4) update test set id = id where abs(id)=3; +# +# // This: '(1) commit' - will release record with ID = -5. Worker sees this record and put write-lock on it. +# // But this is only 3rd row of total 4 that worker must update. +# // Because of worker TIL = RC NRV, he must see all committed records regardless on its own snapshot. +# // Worker resumes search for any rows with ID < -5, and it does this with taking in account required order +# // of its DML (i.e. 'ORDER BY ID DESC ...') +# // [DOC]: "c) engine continue to evaluate remaining records of update\\delete cursor and put write locks on it too" +# // There are no such rows in the table. +# // BECAUSE OF FACT THAT NO RECORDS FOUND, WORKER DOES UNDO BUT KEEP LOCKS AND THEN MAKES FIRST STATEMENT-LEVEL RESTART. +# // [DOC]: "d) when there is no more records to fetch, engine start to undo all actions ... and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# +# * session 'locker-1': +# commit; +# // This will release record with ID=-4. Worker sees this record and put write-lock on it. +# // At this point worker has proceeded all required number of rows for DML: 2, 1, -4 and -5. +# // BECAUSE OF FACT THAT ALL ROWS WERE PROCEEDED, WORKER DOES UNDO BUT KEEP LOCKS AND THEN MAKES SECOND STATEMENT-LEVEL RESTART. +# // [DOC]: "d) when there is no more records to fetch, engine start to undo all actions ... and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# // After this restart worker will waiting for row with ID = -3 (it sees this because of TIL = RC NRV). +# +# * session 'locker-2': +# commit. +# // This releases row with ID=-3. Worker sees this record and put write-lock on it. +# // Records with ID = 2, 1, -4 and -5 already have been locked, but worker must update only FOUR rows (see its DML statement). +# // Thus only rows with ID = 2, 1, -3 and -4 will be updated. Record with ID = -5 must *remain* in the table. +# // At this point worker has proceeded all required rows that meet condition for DML: 2, 1, -3 and -4. +# // BECAUSE OF FACT THAT ALL ROWS WERE PROCEEDED, WORKER DOES UNDO BUT KEEP LOCKS AND THEN MAKES THIRD STATEMENT-LEVEL RESTART. +# // [DOC]: "d) when there is no more records to fetch, engine start to undo all actions ... and preserve already taken write locks +# // e) then engine restores transaction isolation mode as READ COMMITTED *READ CONSISTENCY*, +# // creates new statement-level snapshot and restart execution of top-level statement." +# +# Expected result: +# * session-'worker' must *successfully* complete deletion of 4 rows (but only two of them did exist at the starting point). +# Record with ID = -5 must remain in the table. +# +# * four unique values must be in the column TLOG_DONE.SNAP_NO for session-'worker' when it performed UPDATE statement: first of them +# was created by initial statement start and all others reflect three restarts (this column has values which are evaluated using +# rdb$get_context('SYSTEM', 'SNAPSHOT_NUMBER') -- see trigger TEST_AIUD). +# It is enough to count these values using COUNT(*) or enumarate them by DENSE_RANK() function. +# +# NOTE: concrete values of fields TRN, GLOBAL_CN and SNAP_NO in the TLOG_DONE can differ from one to another run! +# This is because of concurrent nature of connections that work against database. We must not assume that these values will be constant. +# +# ################ +# +# Checked on 4.0.0.2195 SS/CS +# 26.09.2020: added for-loop in order to check different target objects: TABLE ('test') and VIEW ('v_test'), see 'checked_mode'. +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('=', ''), ('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import sys +# import subprocess +# from subprocess import Popen +# import shutil +# from fdb import services +# import time +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# # How long can we wait for session-worker completition, seconds +# # (ISQL often can not complete its job for several seconds!): +# MAX_TIME_FOR_WAITING_WORKER_FINISH = 60 +# +# ############################## +# # Temply, for debug obly: +# this_fdb=db_conn.database_name +# this_dbg=os.path.splitext(this_fdb)[0] + '.4debug.fdb' +# ############################## +# +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# sql_init_ddl = os.path.join(context['files_location'],'read-consist-sttm-restart-DDL.sql') +# +# for checked_mode in('table', 'view'): +# +# target_obj = 'test' if checked_mode == 'table' else 'v_test' +# +# f_init_log=open( os.path.join(context['temp_directory'],'read-consist-sttm-restart-DDL.log'), 'w') +# f_init_err=open( ''.join( ( os.path.splitext(f_init_log.name)[0], '.err') ), 'w') +# +# subprocess.call( [context['isql_path'], dsn, '-q', '-i', sql_init_ddl], stdout=f_init_log, stderr=f_init_err ) +# flush_and_close(f_init_log) +# flush_and_close(f_init_err) +# +# sql_addi=''' +# set term ^; +# execute block as +# begin +# rdb$set_context('USER_SESSION', 'WHO', 'INIT_DATA'); +# end +# ^ +# set term ;^ +# insert into %(target_obj)s(id, x) +# select row_number()over(),row_number()over() +# from rdb$types rows 5; +# commit; +# ''' % locals() +# runProgram('isql', [ dsn, '-q' ], sql_addi) +# +# locker_tpb = fdb.TPB() +# locker_tpb.lock_timeout = MAX_TIME_FOR_WAITING_WORKER_FINISH +# locker_tpb.lock_resolution = fdb.isc_tpb_wait +# +# con_lock_1 = fdb.connect( dsn = dsn, isolation_level=locker_tpb ) +# con_lock_2 = fdb.connect( dsn = dsn, isolation_level=locker_tpb ) +# +# con_lock_1.execute_immediate( "execute block as begin rdb$set_context('USER_SESSION', 'WHO', 'LOCKER #1'); end" ) +# con_lock_2.execute_immediate( "execute block as begin rdb$set_context('USER_SESSION', 'WHO', 'LOCKER #2'); end" ) +# +# ######################### +# ### L O C K E R - 1 ### +# ######################### +# +# con_lock_1.execute_immediate( 'update %(target_obj)s set id=id where id=1' % locals() ) +# +# sql_text=''' +# connect '%(dsn)s'; +# set list on; +# set autoddl off; +# set term ^; +# execute block returns (whoami varchar(30)) as +# begin +# whoami = 'WORKER'; -- , ATT#' || current_connection; +# rdb$set_context('USER_SESSION','WHO', whoami); +# -- suspend; +# end +# ^ +# set term ;^ +# commit; +# SET KEEP_TRAN_PARAMS ON; +# set transaction read committed read consistency; +# --select current_connection, current_transaction from rdb$database; +# set list off; +# set wng off; +# +# --set plan on; +# set count on; +# update %(target_obj)s set id = -id where id <= 2 order by id DESC rows 4; -- THIS MUST HANG BECAUSE OF LOCKERs +# +# -- check results: +# -- ############### +# +# select id from %(target_obj)s order by id; -- one record must remain, with ID = -5 +# +# select v.old_id, v.op, v.snap_no_rank -- snap_no_rank must have four unique values: 1,2,3 and 4. +# from v_worker_log v +# where v.op = 'upd'; +# +# --set width who 10; +# -- DO NOT check this! Values can differ here from one run to another! +# -- select id, trn, who, old_id, new_id, op, rec_vers, global_cn, snap_no from tlog_done order by id; +# rollback; +# +# ''' % dict(globals(), **locals()) +# +# f_worker_sql=open( os.path.join(context['temp_directory'],'tmp_sttm_restart_on_delete_04.sql'), 'w') +# f_worker_sql.write(sql_text) +# flush_and_close(f_worker_sql) +# +# +# f_worker_log=open( ''.join( ( os.path.splitext(f_worker_sql.name)[0], '.log') ), 'w') +# f_worker_err=open( ''.join( ( os.path.splitext(f_worker_log.name)[0], '.err') ), 'w') +# +# ############################################################################ +# ### L A U N C H W O R K E R U S I N G I S Q L, A S Y N C. ### +# ############################################################################ +# +# p_worker = Popen( [ context['isql_path'], '-pag', '9999999', '-q', '-i', f_worker_sql.name ],stdout=f_worker_log, stderr=f_worker_err) +# time.sleep(1) +# +# +# ######################### +# ### L O C K E R - 2 ### +# ######################### +# +# # Change ID so that it **will* be included in the set of rows that must be affected by session-worker: +# con_lock_2.execute_immediate( 'update %(target_obj)s set id = -5 where abs(id) = 5;' % locals() ) +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'update %(target_obj)s set id = id where abs(id) = 5;' % locals() ) +# +# +# con_lock_1.commit() # releases record with ID=1 (allow it to be deleted by session-worker) +# +# # Change ID so that it **will* be included in the set of rows that must be affected by session-worker: +# con_lock_1.execute_immediate( 'update %(target_obj)s set id = -4 where abs(id) = 4;' % locals() ) +# con_lock_1.commit() +# con_lock_1.execute_immediate( 'update %(target_obj)s set id = id where abs(id) = 4;' % locals() ) +# +# +# con_lock_2.commit() # releases record with ID = -5, but session-worker is waiting for record with ID = -4 (that was changed by locker-1). +# con_lock_2.execute_immediate( 'update %(target_obj)s set id = -3 where abs(id) = 3;' % locals() ) +# con_lock_2.commit() +# con_lock_2.execute_immediate( 'update %(target_obj)s set id = id where abs(id) = 3;' % locals() ) +# +# con_lock_1.commit() # This releases row with ID=-4 but session-worker is waiting for ID = - 3 (changed by locker-2). +# con_lock_2.commit() # This releases row with ID=-3. No more locked rows so session-worker can finish its mission. +# +# # Here we wait for ISQL complete its mission: +# p_worker.wait() +# +# flush_and_close(f_worker_log) +# flush_and_close(f_worker_err) +# +# # Close lockers: +# ################ +# for c in (con_lock_1, con_lock_2): +# c.close() +# +# +# # CHECK RESULTS +# ############### +# with open(f_worker_log.name,'r') as f: +# for line in f: +# if line.strip(): +# print('checked_mode: %(checked_mode)s, STDLOG: %(line)s' % locals()) +# +# for f in (f_init_err, f_worker_err): +# with open(f.name,'r') as g: +# for line in g: +# if line.strip(): +# print( 'checked_mode: ', checked_mode, ' UNEXPECTED STDERR IN ' + g.name + ':', line) +# +# #=4.0') +@pytest.mark.xfail +def test_read_consist_sttm_restart_on_update_04_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/trigger/__init__.py b/tests/functional/trigger/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/trigger/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/trigger/alter/__init__.py b/tests/functional/trigger/alter/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/trigger/alter/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/trigger/alter/test_01.py b/tests/functional/trigger/alter/test_01.py new file mode 100644 index 00000000..eb9860ba --- /dev/null +++ b/tests/functional/trigger/alter/test_01.py @@ -0,0 +1,59 @@ +#coding:utf-8 +# +# id: functional.trigger.alter.01 +# title: ALTER TRIGGER - ACTIVE +# decription: ALTER TRIGGER - ACTIVE +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# CREATE TRIGGER +# SHOW TRIGGER +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.trigger.alter.alter_trigger_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [('\\+.*', ''), ('\\=.*', ''), ('Trigger text.*', '')] + +init_script_1 = """CREATE TABLE test( id INTEGER NOT NULL CONSTRAINT unq UNIQUE, + text VARCHAR(32)); +commit; +SET TERM ^; +CREATE TRIGGER tg FOR test INACTIVE BEFORE INSERT +AS +BEGIN + new.id=1; +END ^ +SET TERM ;^ +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ALTER TRIGGER tg ACTIVE; +SHOW TRIGGER tg; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Triggers on Table TEST: +TG, Sequence: 0, Type: BEFORE INSERT, Active +AS +BEGIN + new.id=1; +END ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +""" + +@pytest.mark.version('>=1.0') +def test_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/trigger/alter/test_02.py b/tests/functional/trigger/alter/test_02.py new file mode 100644 index 00000000..9ad484ae --- /dev/null +++ b/tests/functional/trigger/alter/test_02.py @@ -0,0 +1,58 @@ +#coding:utf-8 +# +# id: functional.trigger.alter.02 +# title: ALTER TRIGGER - INACTIVE +# decription: ALTER TRIGGER - INACTIVE +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# CREATE TRIGGER +# SHOW TRIGGER +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.trigger.alter.alter_trigger_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [('\\+.*', ''), ('\\=.*', ''), ('Trigger text.*', '')] + +init_script_1 = """CREATE TABLE test( id INTEGER NOT NULL CONSTRAINT unq UNIQUE, + text VARCHAR(32)); +commit; +SET TERM ^; +CREATE TRIGGER tg FOR test BEFORE INSERT +AS +BEGIN + new.id=1; +END ^ +SET TERM ;^ +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ALTER TRIGGER tg INACTIVE; +SHOW TRIGGER tg;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Triggers on Table TEST: +TG, Sequence: 0, Type: BEFORE INSERT, Inactive +AS +BEGIN + new.id=1; +END ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +""" + +@pytest.mark.version('>=1.0') +def test_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/trigger/alter/test_03.py b/tests/functional/trigger/alter/test_03.py new file mode 100644 index 00000000..715898fb --- /dev/null +++ b/tests/functional/trigger/alter/test_03.py @@ -0,0 +1,55 @@ +#coding:utf-8 +# +# id: functional.trigger.alter.03 +# title: ALTER TRIGGER - BEFORE DELETE +# decription: ALTER TRIGGER - BEFORE DELETE +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# CREATE TRIGGER +# SHOW TRIGGER +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.trigger.alter.alter_trigger_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [('\\+.*', ''), ('\\=.*', ''), ('Trigger text.*', '')] + +init_script_1 = """CREATE TABLE test( id INTEGER NOT NULL CONSTRAINT unq UNIQUE, + text VARCHAR(32)); +SET TERM ^; +CREATE TRIGGER tg FOR test AFTER UPDATE +AS +BEGIN +END ^ +SET TERM ;^ +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ALTER TRIGGER tg BEFORE DELETE; +SHOW TRIGGER tg;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Triggers on Table TEST: +TG, Sequence: 0, Type: BEFORE DELETE, Active +AS +BEGIN +END ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +""" + +@pytest.mark.version('>=2.0') +def test_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/trigger/alter/test_04.py b/tests/functional/trigger/alter/test_04.py new file mode 100644 index 00000000..5be89cfc --- /dev/null +++ b/tests/functional/trigger/alter/test_04.py @@ -0,0 +1,55 @@ +#coding:utf-8 +# +# id: functional.trigger.alter.04 +# title: ALTER TRIGGER - BEFORE INSERT +# decription: ALTER TRIGGER - BEFORE INSERT +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# CREATE TRIGGER +# SHOW TRIGGER +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.trigger.alter.alter_trigger_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [('\\+.*', ''), ('\\=.*', ''), ('Trigger text.*', '')] + +init_script_1 = """CREATE TABLE test( id INTEGER NOT NULL CONSTRAINT unq UNIQUE, + text VARCHAR(32)); +SET TERM ^; +CREATE TRIGGER tg FOR test AFTER UPDATE +AS +BEGIN +END ^ +SET TERM ;^ +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ALTER TRIGGER tg BEFORE INSERT; +SHOW TRIGGER tg;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Triggers on Table TEST: +TG, Sequence: 0, Type: BEFORE INSERT, Active +AS +BEGIN +END ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +""" + +@pytest.mark.version('>=2.0') +def test_04_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/trigger/alter/test_05.py b/tests/functional/trigger/alter/test_05.py new file mode 100644 index 00000000..bbc40c15 --- /dev/null +++ b/tests/functional/trigger/alter/test_05.py @@ -0,0 +1,55 @@ +#coding:utf-8 +# +# id: functional.trigger.alter.05 +# title: ALTER TRIGGER - BEFORE UPDATE +# decription: ALTER TRIGGER - BEFORE UPDATE +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# CREATE TRIGGER +# SHOW TRIGGER +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.trigger.alter.alter_trigger_05 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [('\\+.*', ''), ('\\=.*', ''), ('Trigger text.*', '')] + +init_script_1 = """CREATE TABLE test( id INTEGER NOT NULL CONSTRAINT unq UNIQUE, + text VARCHAR(32)); +SET TERM ^; +CREATE TRIGGER tg FOR test AFTER INSERT +AS +BEGIN +END ^ +SET TERM ;^ +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ALTER TRIGGER tg BEFORE UPDATE; +SHOW TRIGGER tg;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Triggers on Table TEST: +TG, Sequence: 0, Type: BEFORE UPDATE, Active +AS +BEGIN +END ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +""" + +@pytest.mark.version('>=2.0') +def test_05_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/trigger/alter/test_06.py b/tests/functional/trigger/alter/test_06.py new file mode 100644 index 00000000..045e340b --- /dev/null +++ b/tests/functional/trigger/alter/test_06.py @@ -0,0 +1,59 @@ +#coding:utf-8 +# +# id: functional.trigger.alter.06 +# title: ALTER TRIGGER - AFTER DELETE +# decription: ALTER TRIGGER - AFTER DELETE +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# CREATE TRIGGER +# SHOW TRIGGER +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.trigger.alter.alter_trigger_06 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [('\\+.*', ''), ('\\=.*', ''), ('Trigger text.*', '')] + +init_script_1 = """ + CREATE TABLE test( id INTEGER NOT NULL CONSTRAINT unq UNIQUE, + text VARCHAR(32)); + SET TERM ^; + CREATE TRIGGER tg FOR test BEFORE UPDATE + AS + BEGIN + END ^ + SET TERM ;^ + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + ALTER TRIGGER tg AFTER DELETE; + SHOW TRIGGER tg; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Triggers on Table TEST: + TG, Sequence: 0, Type: AFTER DELETE, Active + AS + BEGIN + END + """ + +@pytest.mark.version('>=2.0') +def test_06_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/trigger/alter/test_07.py b/tests/functional/trigger/alter/test_07.py new file mode 100644 index 00000000..83942df7 --- /dev/null +++ b/tests/functional/trigger/alter/test_07.py @@ -0,0 +1,75 @@ +#coding:utf-8 +# +# id: functional.trigger.alter.07 +# title: ALTER TRIGGER - AFTER INSERT +# decription: +# ALTER TRIGGER - AFTER INSERT +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# CREATE TRIGGER +# SHOW TRIGGER +# +# Checked on: +# 2.5.9.27115: OK, 0.484s. +# 3.0.4.33021: OK, 1.000s. +# 4.0.0.1143: OK, 2.203s. +# NB: phrase 'attempted update of read-only column' contains name of table and column ('TEST.ID') on 4.0.x +# +# tracker_id: +# min_versions: [] +# versions: 4.0.0 +# qmid: functional.trigger.alter.alter_trigger_07 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0.0 +# resources: None + +substitutions_1 = [('\\+.*', ''), ('\\=.*', ''), ('Trigger text.*', '')] + +init_script_1 = """ + CREATE TABLE test( id INTEGER NOT NULL CONSTRAINT unq UNIQUE, text VARCHAR(32)); + SET TERM ^; + CREATE TRIGGER tg FOR test BEFORE UPDATE + AS + BEGIN + new.id=1; + END ^ + SET TERM ;^ + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + ALTER TRIGGER tg AFTER INSERT; + SHOW TRIGGER tg; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Triggers on Table TEST: + TG, Sequence: 0, Type: BEFORE UPDATE, Active + AS + BEGIN + new.id=1; + END + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + """ +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42000 + attempted update of read-only column TEST.ID + """ + +@pytest.mark.version('>=4.0.0') +def test_07_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/trigger/alter/test_08.py b/tests/functional/trigger/alter/test_08.py new file mode 100644 index 00000000..eb851cd7 --- /dev/null +++ b/tests/functional/trigger/alter/test_08.py @@ -0,0 +1,60 @@ +#coding:utf-8 +# +# id: functional.trigger.alter.08 +# title: ALTER TRIGGER - POSITION +# decription: ALTER TRIGGER - POSITION +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# CREATE TRIGGER +# SHOW TRIGGER +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.trigger.alter.alter_trigger_08 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [('\\+.*', ''), ('\\=.*', ''), ('Trigger text.*', '')] + +init_script_1 = """ + CREATE TABLE test( id INTEGER NOT NULL CONSTRAINT unq UNIQUE, text VARCHAR(32)); + SET TERM ^; + CREATE TRIGGER tg FOR test BEFORE UPDATE + AS + BEGIN + new.id=1; + END ^ + SET TERM ;^ + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + ALTER TRIGGER tg POSITION 20; + SHOW TRIGGER tg; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Triggers on Table TEST: + TG, Sequence: 20, Type: BEFORE UPDATE, Active + AS + BEGIN + new.id=1; + END + """ + +@pytest.mark.version('>=1.0') +def test_08_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/trigger/alter/test_09.py b/tests/functional/trigger/alter/test_09.py new file mode 100644 index 00000000..f021324d --- /dev/null +++ b/tests/functional/trigger/alter/test_09.py @@ -0,0 +1,64 @@ +#coding:utf-8 +# +# id: functional.trigger.alter.09 +# title: ALTER TRIGGER - POSITION +# decription: ALTER TRIGGER - POSITION +# Test by checking trigger seqeunce +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# CREATE TRIGGER +# INSERT +# Basic SELECT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.trigger.alter.alter_trigger_09 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE test( id INTEGER NOT NULL CONSTRAINT unq UNIQUE, + text VARCHAR(32)); +SET TERM ^; +CREATE TRIGGER tg1 FOR test BEFORE INSERT POSITION 1 +AS +BEGIN + new.text=new.text||'tg1 '; +END ^ + +CREATE TRIGGER tg2 FOR test BEFORE INSERT POSITION 10 +AS +BEGIN + new.text=new.text||'tg2 '; +END ^ +SET TERM ;^ +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ALTER TRIGGER tg2 POSITION 0; +INSERT INTO test VALUES(0,''); +COMMIT; +SELECT text FROM test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEXT +================================ + +tg2 tg1 +""" + +@pytest.mark.version('>=1.0') +def test_09_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/trigger/alter/test_10.py b/tests/functional/trigger/alter/test_10.py new file mode 100644 index 00000000..7351e26d --- /dev/null +++ b/tests/functional/trigger/alter/test_10.py @@ -0,0 +1,64 @@ +#coding:utf-8 +# +# id: functional.trigger.alter.10 +# title: ALTER TRIGGER - AS +# decription: ALTER TRIGGER - AS +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# CREATE TRIGGER +# SHOW TRIGGER +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.trigger.alter.alter_trigger_10 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [('\\+.*', ''), ('\\=.*', ''), ('Trigger text.*', '')] + +init_script_1 = """CREATE TABLE test( id INTEGER NOT NULL CONSTRAINT unq UNIQUE, + text VARCHAR(32)); +SET TERM ^; +CREATE TRIGGER tg FOR test BEFORE INSERT POSITION 1 +AS +BEGIN + new.text=new.text||'tg1 '; +END ^ +SET TERM ;^ +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET TERM ^; +ALTER TRIGGER tg AS +BEGIN + new.text='altered trigger'; +END ^ + +SET TERM ;^ +SHOW TRIGGER tg; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Triggers on Table TEST: +TG, Sequence: 1, Type: BEFORE INSERT, Active +AS +BEGIN + new.text='altered trigger'; +END ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +""" + +@pytest.mark.version('>=1.0') +def test_10_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/trigger/alter/test_11.py b/tests/functional/trigger/alter/test_11.py new file mode 100644 index 00000000..1188524e --- /dev/null +++ b/tests/functional/trigger/alter/test_11.py @@ -0,0 +1,62 @@ +#coding:utf-8 +# +# id: functional.trigger.alter.11 +# title: ALTER TRIGGER - AS +# decription: ALTER TRIGGER - AS +# Test by insert data +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# CREATE TRIGGER +# SHOW TRIGGER +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.trigger.alter.alter_trigger_11 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE test( id INTEGER NOT NULL CONSTRAINT unq UNIQUE, + text VARCHAR(32)); +SET TERM ^; +CREATE TRIGGER tg FOR test BEFORE INSERT POSITION 1 +AS +BEGIN + new.text=new.text||'tg1 '; +END ^ +SET TERM ;^ +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET TERM ^; +ALTER TRIGGER tg AS +BEGIN + new.text='altered trigger'; +END ^ + +SET TERM ;^ +INSERT INTO test VALUES(0,null); +SELECT text FROM test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """TEXT +================================ + +altered trigger +""" + +@pytest.mark.version('>=1.0') +def test_11_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/trigger/create/__init__.py b/tests/functional/trigger/create/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/trigger/create/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/trigger/create/test_01.py b/tests/functional/trigger/create/test_01.py new file mode 100644 index 00000000..22358383 --- /dev/null +++ b/tests/functional/trigger/create/test_01.py @@ -0,0 +1,53 @@ +#coding:utf-8 +# +# id: functional.trigger.create.01 +# title: CREATE TRIGGER +# decription: CREATE TRIGGER +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.trigger.create.create_trigger_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [('\\+.*', ''), ('\\=.*', ''), ('Trigger text.*', '')] + +init_script_1 = """CREATE TABLE tb(id INT); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET TERM ^; +/* Tested command: */ +CREATE TRIGGER test FOR tb BEFORE INSERT AS +BEGIN + new.id=1; +END^ +SET TERM ;^ +SHOW TRIGGER test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Triggers on Table TB: +TEST, Sequence: 0, Type: BEFORE INSERT, Active +AS +BEGIN + new.id=1; +END ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +""" + +@pytest.mark.version('>=1.0') +def test_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/trigger/create/test_02.py b/tests/functional/trigger/create/test_02.py new file mode 100644 index 00000000..73ef7716 --- /dev/null +++ b/tests/functional/trigger/create/test_02.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: functional.trigger.create.02 +# title: CREATE TRIGGER AFTER INSERT +# decription: CREATE TRIGGER AFTER INSERT +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.trigger.create.create_trigger_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [('\\+.*', ''), ('\\=.*', ''), ('Trigger text.*', '')] + +init_script_1 = """CREATE TABLE tb(id INT); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET TERM ^; +CREATE TRIGGER test FOR tb AFTER INSERT AS +BEGIN +END^ +SET TERM ;^ +SHOW TRIGGER test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Triggers on Table TB: +TEST, Sequence: 0, Type: AFTER INSERT, Active +AS +BEGIN +END ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +""" + +@pytest.mark.version('>=2.0') +def test_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/trigger/create/test_03.py b/tests/functional/trigger/create/test_03.py new file mode 100644 index 00000000..942f86d0 --- /dev/null +++ b/tests/functional/trigger/create/test_03.py @@ -0,0 +1,52 @@ +#coding:utf-8 +# +# id: functional.trigger.create.03 +# title: CREATE TRIGGER BEFORE UPDATE +# decription: CREATE TRIGGER BEFORE UPDATE +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.trigger.create.create_trigger_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [('\\+.*', ''), ('\\=.*', ''), ('Trigger text.*', '')] + +init_script_1 = """CREATE TABLE tb(id INT);""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET TERM ^; +CREATE TRIGGER test FOR tb BEFORE UPDATE AS +BEGIN + new.id=1; +END^ +SET TERM ;^ +SHOW TRIGGER test; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Triggers on Table TB: +TEST, Sequence: 0, Type: BEFORE UPDATE, Active +AS +BEGIN + new.id=1; +END ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +""" + +@pytest.mark.version('>=1.0') +def test_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/trigger/create/test_04.py b/tests/functional/trigger/create/test_04.py new file mode 100644 index 00000000..8b04784d --- /dev/null +++ b/tests/functional/trigger/create/test_04.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: functional.trigger.create.04 +# title: CREATE TRIGGER AFTER UPDATE +# decription: CREATE TRIGGER AFTER UPDATE +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.trigger.create.create_trigger_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [('\\+.*', ''), ('\\=.*', ''), ('Trigger text.*', '')] + +init_script_1 = """CREATE TABLE tb(id INT);""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET TERM ^; +CREATE TRIGGER test FOR tb AFTER UPDATE AS +BEGIN +END^ +SET TERM ;^ +SHOW TRIGGER test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Triggers on Table TB: +TEST, Sequence: 0, Type: AFTER UPDATE, Active +AS +BEGIN +END ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +""" + +@pytest.mark.version('>=2.0') +def test_04_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/trigger/create/test_05.py b/tests/functional/trigger/create/test_05.py new file mode 100644 index 00000000..b08f2efc --- /dev/null +++ b/tests/functional/trigger/create/test_05.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: functional.trigger.create.05 +# title: CREATE TRIGGER BEFORE DELETE +# decription: CREATE TRIGGER BEFORE DELETE +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.trigger.create.create_trigger_05 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [('\\+.*', ''), ('\\=.*', ''), ('Trigger text.*', '')] + +init_script_1 = """CREATE TABLE tb(id INT); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET TERM ^; +CREATE TRIGGER test FOR tb BEFORE DELETE AS +BEGIN +END^ +SET TERM ;^ +SHOW TRIGGER test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Triggers on Table TB: +TEST, Sequence: 0, Type: BEFORE DELETE, Active +AS +BEGIN +END ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +""" + +@pytest.mark.version('>=2.0') +def test_05_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/trigger/create/test_06.py b/tests/functional/trigger/create/test_06.py new file mode 100644 index 00000000..54e5e51d --- /dev/null +++ b/tests/functional/trigger/create/test_06.py @@ -0,0 +1,50 @@ +#coding:utf-8 +# +# id: functional.trigger.create.06 +# title: CREATE TRIGGER AFTER DELETE +# decription: CREATE TRIGGER AFTER DELETE +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.trigger.create.create_trigger_06 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [('\\+.*', ''), ('\\=.*', ''), ('Trigger text.*', '')] + +init_script_1 = """CREATE TABLE tb(id INT);""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET TERM ^; +CREATE TRIGGER test FOR tb AFTER DELETE AS +BEGIN +END^ +SET TERM ;^ +SHOW TRIGGER test; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Triggers on Table TB: +TEST, Sequence: 0, Type: AFTER DELETE, Active +AS +BEGIN +END ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +""" + +@pytest.mark.version('>=2.0') +def test_06_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/trigger/create/test_07.py b/tests/functional/trigger/create/test_07.py new file mode 100644 index 00000000..8090b94c --- /dev/null +++ b/tests/functional/trigger/create/test_07.py @@ -0,0 +1,52 @@ +#coding:utf-8 +# +# id: functional.trigger.create.07 +# title: CREATE TRIGGER INACTIVE AFTER DELETE +# decription: CREATE TRIGGER INACTIVE AFTER DELETE +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.trigger.create.create_trigger_07 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [('\\+.*', ''), ('\\=.*', ''), ('Trigger text.*', '')] + +init_script_1 = """ + CREATE TABLE tb(id INT); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + SET TERM ^; + CREATE TRIGGER test FOR tb INACTIVE AFTER DELETE AS + BEGIN + END^ + SET TERM ;^ + SHOW TRIGGER test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Triggers on Table TB: + TEST, Sequence: 0, Type: AFTER DELETE, Inactive + AS + BEGIN + END + """ + +@pytest.mark.version('>=2.0') +def test_07_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/trigger/create/test_08.py b/tests/functional/trigger/create/test_08.py new file mode 100644 index 00000000..31a3b525 --- /dev/null +++ b/tests/functional/trigger/create/test_08.py @@ -0,0 +1,49 @@ +#coding:utf-8 +# +# id: functional.trigger.create.08 +# title: CREATE TRIGGER AFTER DELETE POSITION 12 +# decription: CREATE TRIGGER AFTER DELETE POSITION 12 +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# tracker_id: +# min_versions: [] +# versions: 2.0 +# qmid: functional.trigger.create.create_trigger_08 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.0 +# resources: None + +substitutions_1 = [('\\+.*', ''), ('\\=.*', ''), ('Trigger text.*', '')] + +init_script_1 = """CREATE TABLE tb(id INT);""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET TERM ^; +CREATE TRIGGER test FOR tb AFTER DELETE POSITION 12 AS +BEGIN +END^ +SET TERM ;^ +SHOW TRIGGER test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Triggers on Table TB: +TEST, Sequence: 12, Type: AFTER DELETE, Active +AS +BEGIN +END ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +""" + +@pytest.mark.version('>=2.0') +def test_08_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/trigger/create/test_09.py b/tests/functional/trigger/create/test_09.py new file mode 100644 index 00000000..0f03f428 --- /dev/null +++ b/tests/functional/trigger/create/test_09.py @@ -0,0 +1,93 @@ +#coding:utf-8 +# +# id: functional.trigger.create.09 +# title: CREATE TRIGGER BEFORE INSERT DECLARE VARIABLE +# decription: CREATE TRIGGER BEFORE INSERT DECLARE VARIABLE +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.trigger.create.create_trigger_09 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [('\\+.*', ''), ('\\=.*', ''), ('Trigger text.*', '')] + +init_script_1 = """CREATE TABLE tb(id INT);""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET TERM ^; +CREATE TRIGGER test FOR tb BEFORE INSERT AS +DECLARE VARIABLE v1 SMALLINT; +DECLARE VARIABLE v2 INTEGER; +DECLARE VARIABLE v3 FLOAT; +DECLARE VARIABLE v4 DOUBLE PRECISION; +DECLARE VARIABLE v5 DECIMAL; +DECLARE VARIABLE v6 DECIMAL(4); +DECLARE VARIABLE v7 DECIMAL(4,2); +DECLARE VARIABLE v8 NUMERIC; +DECLARE VARIABLE v9 NUMERIC(5); +DECLARE VARIABLE v10 NUMERIC(5,3); +DECLARE VARIABLE v11 DATE; +DECLARE VARIABLE v12 TIME; +DECLARE VARIABLE v13 TIMESTAMP; +DECLARE VARIABLE v14 CHAR(1200); +DECLARE VARIABLE v15 CHAR(2000) CHARACTER SET WIN1250; +DECLARE VARIABLE v16 CHARACTER(3400); +DECLARE VARIABLE v17 CHARACTER VARYING(300); +DECLARE VARIABLE v18 NCHAR(1); +DECLARE VARIABLE v19 NATIONAL CHARACTER(30); +DECLARE VARIABLE v20 NATIONAL CHAR(130); +DECLARE VARIABLE v21 NATIONAL CHAR VARYING(30); +BEGIN + new.id=1; +END^ +SET TERM ;^ +SHOW TRIGGER test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Triggers on Table TB: +TEST, Sequence: 0, Type: BEFORE INSERT, Active +AS +DECLARE VARIABLE v1 SMALLINT; +DECLARE VARIABLE v2 INTEGER; +DECLARE VARIABLE v3 FLOAT; +DECLARE VARIABLE v4 DOUBLE PRECISION; +DECLARE VARIABLE v5 DECIMAL; +DECLARE VARIABLE v6 DECIMAL(4); +DECLARE VARIABLE v7 DECIMAL(4,2); +DECLARE VARIABLE v8 NUMERIC; +DECLARE VARIABLE v9 NUMERIC(5); +DECLARE VARIABLE v10 NUMERIC(5,3); +DECLARE VARIABLE v11 DATE; +DECLARE VARIABLE v12 TIME; +DECLARE VARIABLE v13 TIMESTAMP; +DECLARE VARIABLE v14 CHAR(1200); +DECLARE VARIABLE v15 CHAR(2000) CHARACTER SET WIN1250; +DECLARE VARIABLE v16 CHARACTER(3400); +DECLARE VARIABLE v17 CHARACTER VARYING(300); +DECLARE VARIABLE v18 NCHAR(1); +DECLARE VARIABLE v19 NATIONAL CHARACTER(30); +DECLARE VARIABLE v20 NATIONAL CHAR(130); +DECLARE VARIABLE v21 NATIONAL CHAR VARYING(30); +BEGIN + new.id=1; +END ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +""" + +@pytest.mark.version('>=1.0') +def test_09_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/trigger/create/test_10.py b/tests/functional/trigger/create/test_10.py new file mode 100644 index 00000000..77a25320 --- /dev/null +++ b/tests/functional/trigger/create/test_10.py @@ -0,0 +1,144 @@ +#coding:utf-8 +# +# id: functional.trigger.create.10 +# title: CREATE TRIGGER BEFORE INSERT DECLARE VARIABLE, block stataments +# decription: CREATE TRIGGER BEFORE INSERT DECLARE VARIABLE, block stataments +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# CREATE EXCEPTION +# CREATE PROCEDURE +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.trigger.create.create_trigger_10 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [('\\+.*', ''), ('\\=.*', ''), ('Trigger text.*', '')] + +init_script_1 = """ + CREATE TABLE tb(id INT); + CREATE EXCEPTION test 'test exception'; + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + SET TERM ^; + CREATE PROCEDURE test (id INT) RETURNS(d FLOAT)AS + BEGIN + d=id+3.14; + END ^ + + CREATE TRIGGER test FOR tb BEFORE INSERT AS + DECLARE VARIABLE v1 SMALLINT; + DECLARE VARIABLE v2 INTEGER; + DECLARE VARIABLE v3 FLOAT; + DECLARE VARIABLE v4 DOUBLE PRECISION; + DECLARE VARIABLE v5 DECIMAL; + DECLARE VARIABLE v6 DECIMAL(4); + DECLARE VARIABLE v7 DECIMAL(4,2); + DECLARE VARIABLE v8 NUMERIC; + DECLARE VARIABLE v9 NUMERIC(5); + DECLARE VARIABLE v10 NUMERIC(5,3); + DECLARE VARIABLE v11 DATE; + DECLARE VARIABLE v12 TIME; + DECLARE VARIABLE v13 TIMESTAMP; + DECLARE VARIABLE v14 CHAR(1200); + DECLARE VARIABLE v15 CHAR(2000) CHARACTER SET WIN1250; + DECLARE VARIABLE v16 CHARACTER(3400); + DECLARE VARIABLE v17 CHARACTER VARYING(300); + DECLARE VARIABLE v18 NCHAR(1); + DECLARE VARIABLE v19 NATIONAL CHARACTER(30); + DECLARE VARIABLE v20 NATIONAL CHAR(130); + DECLARE VARIABLE v21 NATIONAL CHAR VARYING(30); + BEGIN + BEGIN /* Begin end */ + new.id=1; + END + v1=v2+34/3; /* var assigment */ + /* comment */ + EXCEPTION test; + EXECUTE PROCEDURE test(3) RETURNING_VALUES :v3; + FOR SELECT id FROM tb INTO :v1 DO v2=v2+1; + SELECT id FROM tb INTO :v2; + UPDATE tb SET id=1; + DELETE FROM tb; + INSERT INTO tb(id)VALUES(3); + IF(v10 IS NULL)THEN v1=2; ELSE v1=3; + new.id=v4; + POST_EVENT 'test'; + POST_EVENT v1; + WHILE(v2=1.0') +def test_10_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/trigger/create/test_17.py b/tests/functional/trigger/create/test_17.py new file mode 100644 index 00000000..58bc3e74 --- /dev/null +++ b/tests/functional/trigger/create/test_17.py @@ -0,0 +1,54 @@ +#coding:utf-8 +# +# id: functional.trigger.create.17 +# title: CREATE TRIGGER SQL2003 +# decription: CREATE TRIGGER SQL2003 +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.trigger.create.create_trigger_17 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [('\\+.*', ''), ('\\=.*', ''), ('Trigger text.*', '')] + +init_script_1 = """ + CREATE TABLE tb(id INT); + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + SET TERM ^; + /* Tested command: */ + CREATE TRIGGER test BEFORE INSERT + ON tb AS + BEGIN + new.id=1; + END^ + SET TERM ;^ + SHOW TRIGGER test; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + Triggers on Table TB: + TEST, Sequence: 0, Type: BEFORE INSERT, Active + AS + BEGIN + new.id=1; + END + """ + +@pytest.mark.version('>=2.1') +def test_17_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/trigger/database/__init__.py b/tests/functional/trigger/database/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/trigger/database/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/trigger/database/test_connect_01.py b/tests/functional/trigger/database/test_connect_01.py new file mode 100644 index 00000000..4d19544b --- /dev/null +++ b/tests/functional/trigger/database/test_connect_01.py @@ -0,0 +1,60 @@ +#coding:utf-8 +# +# id: functional.trigger.database.connect_01 +# title: Trigger on database connect. See also CORE-745 +# decription: This tests normal operation of database CONNECT trigger. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.trigger.database.connect_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """ + create table LOG (ID integer, MSG varchar(100)); + create generator LOGID; + set term ^; + create trigger LOG_BI for LOG active before insert position 0 + as + begin + if (new.ID is null) then + new.ID = gen_id(LOGID,1); + end + ^ + + create trigger ONCONNECT on connect position 0 + as + begin + insert into LOG (MSG) values ('Connect'); + end + ^ + set term ;^ + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select * from LOG; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + MSG Connect + """ + +@pytest.mark.version('>=2.1') +def test_connect_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/trigger/database/test_connect_02.py b/tests/functional/trigger/database/test_connect_02.py new file mode 100644 index 00000000..619ee2f0 --- /dev/null +++ b/tests/functional/trigger/database/test_connect_02.py @@ -0,0 +1,72 @@ +#coding:utf-8 +# +# id: functional.trigger.database.connect_02 +# title: Error handling in trigger on database connect +# decription: This test verifies the proper error handling. Uncaught exceptions in trigger roll back the transaction, disconnect the attachment and are returned to the client. +# tracker_id: CORE-745 +# min_versions: [] +# versions: 2.1 +# qmid: functional.trigger.database.connect_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [('line:.*', '')] + +init_script_1 = """create table LOG (ID integer, MSG varchar(100)); +create generator LOGID; +create exception CONNECTERROR 'Exception in ON CONNECT trigger'; +create role TEST; +grant TEST to PUBLIC; +set term ^; +create trigger LOG_BI for LOG active before insert position 0 +as +begin + if (new.ID is null) then + new.ID = gen_id(LOGID,1); +end ^ + +create trigger ONCONNECT on connect position 0 +as +begin + insert into LOG (MSG) values ('Connect as ' || current_role); + if (current_role ='TEST') then + exception CONNECTERROR; +end ^ + +set term ;^ + +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# try: +# con = kdb.connect(dsn=dsn.encode(),user=user_name.encode(),password=user_password.encode(),role='TEST') +# except Exception,e: +# for msg in e: print (msg) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Error while connecting to database: +- SQLCODE: -836 +- exception 1 +- CONNECTERROR +- Exception in ON CONNECT trigger +- At trigger 'ONCONNECT' line: 5, col: 29 +-836 +335544517 +""" + +@pytest.mark.version('>=2.1') +@pytest.mark.xfail +def test_connect_02_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/trigger/database/test_connect_03.py b/tests/functional/trigger/database/test_connect_03.py new file mode 100644 index 00000000..1b0ee0b1 --- /dev/null +++ b/tests/functional/trigger/database/test_connect_03.py @@ -0,0 +1,68 @@ +#coding:utf-8 +# +# id: functional.trigger.database.connect_03 +# title: Multiple triggers on database connect. See also CORE-745 +# decription: This tests normal operation of database CONNECT triggers when there are more of them. +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: functional.trigger.database.connect_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """ + create table LOG (ID integer, MSG varchar(100)); + create generator LOGID; + set term ^; + create trigger LOG_BI for LOG active before insert position 0 + as + begin + if (new.ID is null) then + new.ID = gen_id(LOGID,1); + end ^ + + create trigger ONCONNECT_1 on connect position 0 + as + begin + insert into LOG (MSG) values ('Connect T1'); + end ^ + + create trigger ONCONNECT_2 on connect position 10 + as + begin + insert into LOG (MSG) values ('Connect T2'); + end ^ + + set term ;^ + + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + select * from LOG; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + ID 1 + MSG Connect T1 + ID 2 + MSG Connect T2 + """ + +@pytest.mark.version('>=2.1') +def test_connect_03_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/trigger/database/test_connect_04.py b/tests/functional/trigger/database/test_connect_04.py new file mode 100644 index 00000000..5eacd032 --- /dev/null +++ b/tests/functional/trigger/database/test_connect_04.py @@ -0,0 +1,93 @@ +#coding:utf-8 +# +# id: functional.trigger.database.connect_04 +# title: Error handling in trigger on database connect - multiple triggers. +# decription: This test verifies the proper error handling. Uncaught exceptions in trigger roll back the transaction, disconnect the attachment and are returned to the client. Because this test is implemented in Python, our test support class creates a database connection for our test code (db_conn) that attach to the database without role specification. We verify that this connection was properly logged for convenience. +# tracker_id: CORE-745 +# min_versions: [] +# versions: 2.1 +# qmid: functional.trigger.database.connect_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [('line:.*', '')] + +init_script_1 = """create table LOG (ID integer, MSG varchar(100)); +create generator LOGID; +create exception CONNECTERROR 'Exception in ON CONNECT trigger'; +create role TEST; +grant TEST to PUBLIC; +set term ^; +create trigger LOG_BI for LOG active before insert position 0 +as +begin + if (new.ID is null) then + new.ID = gen_id(LOGID,1); +end ^ + +create trigger ONCONNECT_1 on connect position 0 +as +begin + insert into LOG (MSG) values ('Connect T1 as ' || current_role); +end ^ + +create trigger ONCONNECT_2 on connect position 0 +as +begin + insert into LOG (MSG) values ('Connect T2 as ' || current_role); + if (current_role ='TEST') then + exception CONNECTERROR; +end ^ + +create trigger ONCONNECT_3 on connect position 20 +as +begin + insert into LOG (MSG) values ('Connect T3 as ' || current_role); +end ^ + +set term ;^ + +commit; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# try: +# con = kdb.connect(dsn=dsn.encode(),user=user_name.encode(),password=user_password.encode(),role='TEST') +# except Exception,e: +# for msg in e: print (msg) +# +# c = db_conn.cursor() +# c.execute('select * from LOG') +# printData(c) +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """Error while connecting to database: +- SQLCODE: -836 +- exception 1 +- CONNECTERROR +- Exception in ON CONNECT trigger +- At trigger 'ONCONNECT_2' line: 5, col: 29 +-836 +335544517 +ID MSG +----------- ---------------------------------------------------------------------------------------------------- +1 Connect T1 as NONE +2 Connect T2 as NONE +3 Connect T3 as NONE +""" + +@pytest.mark.version('>=2.1') +@pytest.mark.xfail +def test_connect_04_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/trigger/database/test_disconnect_01.py b/tests/functional/trigger/database/test_disconnect_01.py new file mode 100644 index 00000000..78581c83 --- /dev/null +++ b/tests/functional/trigger/database/test_disconnect_01.py @@ -0,0 +1,153 @@ +#coding:utf-8 +# +# id: functional.trigger.database.disconnect_01 +# title: Trigger on database disconnect: check that exception that raised when trigger fires is written to firebird.log +# decription: +# Discussed with Alex, 16.12.2020 functionality that was not specified in the documentation: +# exception that raises in a trigger on DISCONNECT reflects in the firebird.log. +# +# Test creates trigger on disconnect and put in its body statement which always will fail: 1/0. +# Then we get content of firebird.log before disconnect and after. +# Finally we compare these logs and search in the difference lines about error message. +# +# Checked on 4.0.0.2303 SS/CS. +# +# tracker_id: +# min_versions: [] +# versions: 4.0 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """ + set term ^; + create trigger trg_disconnect on disconnect as + declare n int; + begin + n = 1/0; + end + ^ + set term ;^ + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# +# import os +# import subprocess +# import difflib +# import re +# import time +# +# #-------------------------------------------- +# +# 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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #-------------------------------------------- +# +# def svc_get_fb_log( fb_home, f_fb_log ): +# +# global subprocess +# subprocess.call( [ context['fbsvcmgr_path'], +# "localhost:service_mgr", +# "action_get_fb_log" +# ], +# stdout=f_fb_log, stderr=subprocess.STDOUT +# ) +# return +# +# #-------------------------------------------- +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# f_init_log = open( os.path.join(context['temp_directory'],'tmp_fb_old.log'), 'w') +# subprocess.call( [ context['fbsvcmgr_path'],"localhost:service_mgr", "action_get_fb_log" ], stdout = f_init_log, stderr = subprocess.STDOUT) +# flush_and_close( f_init_log ) +# +# db_conn.close() # this leads to zero divide error in trg_disconnect which must be reflected in the firebird.log +# +# time.sleep(1) +# +# f_curr_log = open( os.path.join(context['temp_directory'],'tmp_fb_new.log'), 'w') +# subprocess.call( [ context['fbsvcmgr_path'],"localhost:service_mgr", "action_get_fb_log" ], stdout = f_curr_log, stderr = subprocess.STDOUT) +# flush_and_close( f_curr_log ) +# +# f_init_log=open(f_init_log.name, 'r') +# f_curr_log=open(f_curr_log.name, 'r') +# difftext = ''.join(difflib.unified_diff( +# f_init_log.readlines(), +# f_curr_log.readlines() +# )) +# flush_and_close( f_init_log ) +# flush_and_close( f_curr_log ) +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_fb_diff.txt'), 'w') +# f_diff_txt.write(difftext) +# flush_and_close( f_diff_txt ) +# +# p = re.compile('\\+\\s?((Error at disconnect)|(arithmetic exception)|(Integer divide by zero)|(At trigger))') +# with open( f_diff_txt.name,'r') as f: +# for line in f: +# if line.startswith('+') and line.strip() != '+++' and p.search(line): +# print( line ) +# # print( 'DIFF in firebird.log: %(line)s' % locals() ) +# +# ############################### +# # Cleanup. +# time.sleep(1) +# cleanup( (f_init_log,f_curr_log,f_diff_txt) ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + + Error at disconnect: + + 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 trigger 'TRG_DISCONNECT' line: 4, col: 9 + """ + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_disconnect_01_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/trigger/database/test_transaction_start_multiple_with_normal_finish.py b/tests/functional/trigger/database/test_transaction_start_multiple_with_normal_finish.py new file mode 100644 index 00000000..a682ee63 --- /dev/null +++ b/tests/functional/trigger/database/test_transaction_start_multiple_with_normal_finish.py @@ -0,0 +1,143 @@ +#coding:utf-8 +# +# id: functional.trigger.database.transaction_start_multiple_with_normal_finish +# title: Multiple triggers on start transaction +# decription: +# This tests normal operation of database TRANSACTION START trigger when: +# 1) more than one such triggers are defined +# 2) NO exception raise within any trigger during its work, i.e. all of them shoudl finish Ok +# +# Triggers must work within the same Tx as "parent" statement (which launched this Tx). +# +# Results (23-05-2017): +# FB25Cs, build 2.5.8.27062: OK, 1.688ss. +# FB25SC, build 2.5.8.27062: OK, 0.469ss. +# fb25sS, build 2.5.8.27062: OK, 1.265ss. +# fb30Cs, build 3.0.3.32726: OK, 2.938ss. +# fb30SC, build 3.0.3.32726: OK, 2.250ss. +# FB30SS, build 3.0.3.32726: OK, 1.937ss. +# FB40CS, build 4.0.0.649: OK, 3.718ss. +# FB40SC, build 4.0.0.649: OK, 1.875ss. +# FB40SS, build 4.0.0.649: OK, 1.984ss. +# +# tracker_id: CORE-745 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set bail on; + set list on; + + recreate table trg_log(id integer, trg_tx int default current_transaction, rows_inserted_before int); + commit; + + set autoddl off; + + set term ^; + + execute block as + declare n int; + declare i int = 1; + declare ddl varchar(255); + begin + + rdb$set_context('USER_SESSION','TRIGGERS_TO_CREATE', 5); -- <<< ---------------- HOW MANY TRIGGERS ARE DEFINED + + n = cast( rdb$get_context('USER_SESSION','TRIGGERS_TO_CREATE') as int); + while ( i <= n ) do + begin + ddl = 'create or alter trigger trg_start_tx_'|| i ||' on transaction start position 0 as ' + || 'begin ' + || ' insert into trg_log(id, rows_inserted_before) values('|| i ||', (select count(*) from trg_log) ); ' + || 'end' + ; + execute statement (ddl); + i = i + 1; + end + end + ^ + set term ;^ + + --select current_timestamp from rdb$database; + commit; + --select current_timestamp from rdb$database; + + -- Following 'select' sttm leads to implicit Tx start ==> all db-level triggers 'on transaction start' will be fired + -- before engine begin to execute this statement. + -- Table trg_log should contain rdb$get_context('USER_SESSION','TRIGGERS_TO_CREATE') records and they all had to be + -- created within current Tx: + + select iif( count(distinct t.id) = max(t.expected_count), + 'EXPECTED.', + 'WRONG: ' || count(distinct id) || ' instead of ' || max(t.expected_count) + ) as triggers_fired_count + from + ( + select t.id, t.trg_tx, cast( rdb$get_context('USER_SESSION','TRIGGERS_TO_CREATE') as int) as expected_count + from trg_log t + ) t + where trg_tx = current_transaction + ; + + select id,rows_inserted_before from trg_log order by id; + + rollback; + + -- Previous rollback should remove from trg_log all rows that were inserted there by triggers: + select count(distinct id) as rows_after_rollback + from trg_log where trg_tx is distinct from current_transaction; + + commit; + + -- Previous commit should save in trg_log two records that were inserted there by triggers: + select iif( count(distinct t.id) = max(expected_count), + 'EXPECTED.', + 'WRONG: ' || count(distinct id) || ' instead of ' || max(t.expected_count) + ) as rows_after_commit + from + ( + select t.id, t.trg_tx, cast( rdb$get_context('USER_SESSION','TRIGGERS_TO_CREATE') as int) as expected_count + from trg_log t + ) t + where trg_tx is distinct from current_transaction; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + TRIGGERS_FIRED_COUNT EXPECTED. + + ID 1 + ROWS_INSERTED_BEFORE 0 + ID 2 + ROWS_INSERTED_BEFORE 1 + ID 3 + ROWS_INSERTED_BEFORE 2 + ID 4 + ROWS_INSERTED_BEFORE 3 + ID 5 + ROWS_INSERTED_BEFORE 4 + + ROWS_AFTER_ROLLBACK 0 + ROWS_AFTER_COMMIT EXPECTED. + """ + +@pytest.mark.version('>=2.5') +def test_transaction_start_multiple_with_normal_finish_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/trigger/database/test_transactioncommit_01.py b/tests/functional/trigger/database/test_transactioncommit_01.py new file mode 100644 index 00000000..ae6195f0 --- /dev/null +++ b/tests/functional/trigger/database/test_transactioncommit_01.py @@ -0,0 +1,76 @@ +#coding:utf-8 +# +# id: functional.trigger.database.transactioncommit_01 +# title: Trigger on commit transaction. See also CORE-645 +# decription: Test trigger on commit transaction +# tracker_id: +# min_versions: [] +# versions: 2.1 +# qmid: + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """ + SET AUTODDL OFF; + CREATE TABLE T1 + ( + T1_ID BIGINT NOT NULL, + T1_VAL CHAR(10) , + CONSTRAINT PK_T1 PRIMARY KEY (T1_ID) + ); + + CREATE SEQUENCE S_TRANSACTION; + + SET TERM ^ ; + RECREATE TRIGGER TRIG_TRANSAC ACTIVE + ON TRANSACTION COMMIT + POSITION 0 + AS + BEGIN + RDB$SET_CONTEXT('USER_SESSION', 'Trn_ID', (NEXT VALUE FOR S_TRANSACTION)); + END^ + + SET TERM ; ^ + + COMMIT; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """SET AUTODDL OFF; + + SET LIST ON; + + INSERT INTO T1 VALUES (1,'val1'); + SELECT RDB$GET_CONTEXT('USER_SESSION', 'Trn_ID') AS CTX_VAR FROM RDB$DATABASE; + COMMIT; + UPDATE T1 SET T1_VAL='val1mod' WHERE T1_ID=1; + SELECT RDB$GET_CONTEXT('USER_SESSION', 'Trn_ID') AS CTX_VAR FROM RDB$DATABASE; + ROLLBACK; + DELETE FROM T1 WHERE T1_ID=1; + SELECT RDB$GET_CONTEXT('USER_SESSION', 'Trn_ID') AS CTX_VAR FROM RDB$DATABASE; + COMMIT; + SELECT RDB$GET_CONTEXT('USER_SESSION', 'Trn_ID') AS CTX_VAR FROM RDB$DATABASE; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CTX_VAR + CTX_VAR 3 + CTX_VAR 3 + CTX_VAR 4 + """ + +@pytest.mark.version('>=2.1') +def test_transactioncommit_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/trigger/database/test_transactionrollback_01.py b/tests/functional/trigger/database/test_transactionrollback_01.py new file mode 100644 index 00000000..aed9d6a1 --- /dev/null +++ b/tests/functional/trigger/database/test_transactionrollback_01.py @@ -0,0 +1,123 @@ +#coding:utf-8 +# +# id: functional.trigger.database.transactionrollback_01 +# title: Trigger on rollback transaction +# decription: +# Test trigger on rollback transaction +# Checked 17.05.2017 on: +# FB25Cs, build 2.5.8.27056: OK, 1.047ss. +# FB25SC, build 2.5.8.27061: OK, 0.516ss. +# fb25sS, build 2.5.7.27038: OK, 0.719ss. +# fb30Cs, build 3.0.3.32721: OK, 2.516ss. +# fb30SC, build 3.0.3.32721: OK, 1.297ss. +# FB30SS, build 3.0.3.32721: OK, 1.578ss. +# FB40CS, build 4.0.0.639: OK, 2.656ss. +# FB40SC, build 4.0.0.639: OK, 1.844ss. +# FB40SS, build 4.0.0.639: OK, 1.735ss. +# +# tracker_id: CORE-645 +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: functional.trigger.database.transactionrollback_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + create sequence g; + commit; + + create view v_check as + select rdb$get_context('USER_SESSION', 'TRG_TX') as ctx + from rdb$database; + commit; + + set term ^; + create or alter trigger trg_tx_rbak inactive on transaction rollback position 0 as + begin + --- nop --- + end + ^ + set term ;^ + commit; + + recreate table test(id int); + commit; + + recreate table log (main_app_tx int, db_trigger_tx int default current_transaction, add_info varchar(80) ); + commit; + + set term ^; + create or alter trigger trg_tx_rbak inactive on transaction rollback position 0 as + begin + rdb$set_context('USER_SESSION', 'TRG_TX', gen_id(g,1)); + end + ^ + set term ;^ + commit; + + set autoddl off; + alter trigger trg_tx_rbak active; + commit; + + select gen_id(g,0) as curr_g, v.* from v_check v; -- 0, + + rollback; -- this should increase value of sequence 'g' by 1 and assign new value to context var. 'TRG_TX' + + set transaction no wait; + select gen_id(g,0) as curr_g, v.* from v_check v; -- 1, 1 (the same! becase Tx START should not be watched by trg_tx_rbak) + + commit; + select gen_id(g,0) as curr_g, v.* from v_check v; -- 1, 1 (the same! because COMMIT should not be watched by trg_tx_rbak) + + set term ^; + create or alter trigger trg_tx_rbak active on transaction rollback position 0 as + begin + rdb$set_context('USER_SESSION', 'TRG_TX', gen_id(g,1234)/0); + end + ^ + set term ;^ + commit; + + -- this should increase value of sequence 'g' by 1234 but context var. 'TRG_TX' + -- will store old value because of zero-divide exception + rollback; + + -- NB: client should NOT get exception (zero divide) from trigger which is defined for __ROLLBACK__ event! + + select gen_id(g,0) as curr_g, v.* from v_check v; -- 1235, 1 + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + CURR_G 0 + CTX + + CURR_G 1 + CTX 1 + + CURR_G 1 + CTX 1 + + CURR_G 1235 + CTX 1 + """ + +@pytest.mark.version('>=2.5') +def test_transactionrollback_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/trigger/database/test_transactionstart_01.py b/tests/functional/trigger/database/test_transactionstart_01.py new file mode 100644 index 00000000..252e906c --- /dev/null +++ b/tests/functional/trigger/database/test_transactionstart_01.py @@ -0,0 +1,125 @@ +#coding:utf-8 +# +# id: functional.trigger.database.transactionstart_01 +# title: Trigger on start tansaction +# decription: +# This tests normal operation of database TRANSACTION START trigger. +# +# Checked 17.05.2017 on: +# FB25Cs, build 2.5.8.27056: OK, 1.375ss. +# FB25SC, build 2.5.8.27061: OK, 0.407ss. +# fb25sS, build 2.5.7.27038: OK, 0.953ss. +# fb30Cs, build 3.0.3.32721: OK, 2.937ss. +# fb30SC, build 3.0.3.32721: OK, 1.906ss. +# FB30SS, build 3.0.3.32721: OK, 1.125ss. +# FB40CS, build 4.0.0.639: OK, 3.422ss. +# FB40SC, build 4.0.0.639: OK, 1.859ss. +# FB40SS, build 4.0.0.639: OK, 1.266ss. +# +# +# tracker_id: CORE-745 +# min_versions: ['2.5.0'] +# versions: 3.0 +# qmid: functional.trigger.database.transactionstart_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('line: \\d+, col: \\d+', '')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set autoddl off; + create table trg_log(id integer, trg_tx int default current_transaction); + + create view v_check as + select count(*) as cnt_chk_tx, count(iif(trg_tx=current_transaction,1,null)) as cnt_chk_trg + from trg_log + where trg_tx = current_transaction; + + set term ^; + create trigger trg_start_tx inactive on transaction start position 0 as + begin + insert into trg_log default values; + --insert into trg_log(trg_tx) values (current_transaction); + end + ^ + set term ;^ + commit; + + alter trigger trg_start_tx active; + commit; + + set list on; + set autoddl off; + + select 'Tx to be rolled back' as phase + --, current_transaction + from rdb$database; + --select a.* from trg_log a; + select * from v_check; + rollback; + + + select 'Tx to be committed' as phase + --, current_transaction + from rdb$database; + --select a.* from trg_log a; + select * from v_check; + commit; + + select 'Final select' as phase + --, current_transaction + from rdb$database; + --select a.* from trg_log a order by id desc rows 1; + select * from v_check; + + set term ^; + alter trigger trg_start_tx inactive position 0 as + begin + insert into trg_log(trg_tx) values (1/0); + end + ^ + set term ;^ + commit; + + alter trigger trg_start_tx active; + commit; + + commit; -- this should raise exception in trg_start_tx and this exception SHOULD PASS to the client. + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + PHASE Tx to be rolled back + CNT_CHK_TX 1 + CNT_CHK_TRG 1 + PHASE Tx to be committed + CNT_CHK_TX 1 + CNT_CHK_TRG 1 + PHASE Final select + CNT_CHK_TX 1 + CNT_CHK_TRG 1 + """ +expected_stderr_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. + -At trigger 'TRG_START_TX' + """ + +@pytest.mark.version('>=3.0') +def test_transactionstart_01_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_expected_stderr == act_1.clean_stderr + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/trigger/table/__init__.py b/tests/functional/trigger/table/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/trigger/table/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/trigger/table/test_alter_12.py b/tests/functional/trigger/table/test_alter_12.py new file mode 100644 index 00000000..316dd2c0 --- /dev/null +++ b/tests/functional/trigger/table/test_alter_12.py @@ -0,0 +1,71 @@ +#coding:utf-8 +# +# id: functional.trigger.table.alter_12 +# title: ALTER TRIGGER - AS +# decription: ALTER TRIGGER - AS +# Try use old prefix in INSERT trigger +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# CREATE TRIGGER +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.trigger.alter.alter_trigger_12 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('At line.*', '')] + +init_script_1 = """ + create table test(id integer not null constraint unq unique, text varchar(32)); + commit; + set term ^; + create trigger tg for test before insert position 1 as + begin + new.text=new.text||'tg1 '; + end + ^ + set term ;^ + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Since WI-T3.0.0.31733 content of STDERR has been changed: source position of + -- problematic statement is displayed now on seperate line, like this: + -- "-At line 4, column 1" + -- Decided to suppress this line. + set term ^; + alter trigger tg as + begin + old.text = 'altered trigger'; + end ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42S22 + unsuccessful metadata update + -ALTER TRIGGER TG failed + -Dynamic SQL Error + -SQL error code = -206 + -Column unknown + -OLD.TEXT + -At line 4, column 1 + """ + +@pytest.mark.version('>=3.0') +def test_alter_12_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/trigger/table/test_alter_13.py b/tests/functional/trigger/table/test_alter_13.py new file mode 100644 index 00000000..e383dc3e --- /dev/null +++ b/tests/functional/trigger/table/test_alter_13.py @@ -0,0 +1,69 @@ +#coding:utf-8 +# +# id: functional.trigger.table.alter_13 +# title: ALTER TRIGGER - AS +# decription: ALTER TRIGGER - AS +# Try use new prefix in DELETE trigger +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# CREATE TRIGGER +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.trigger.alter.alter_trigger_13 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('At line.*', '')] + +init_script_1 = """ + create table test( id integer not null constraint unq unique, text varchar(32)); + commit; + set term ^; + create trigger tg for test before delete position 1 as + begin + end ^ + set term ;^ + commit; + """ + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + -- Since WI-T3.0.0.31733 content of STDERR has been changed: source position of + -- problematic statement is displayed now on seperate line, like this: + -- "-At line 4, column 1" + -- Decided to suppress this line. + set term ^; + alter trigger tg as + begin + new.text='altered trigger'; + end ^ + set term ;^ + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """ + Statement failed, SQLSTATE = 42S22 + unsuccessful metadata update + -ALTER TRIGGER TG failed + -Dynamic SQL Error + -SQL error code = -206 + -Column unknown + -NEW.TEXT + -At line 4, column 5 + """ + +@pytest.mark.version('>=3.0') +def test_alter_13_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/util/__init__.py b/tests/functional/util/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/util/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/util/test_gbak_zip.py b/tests/functional/util/test_gbak_zip.py new file mode 100644 index 00000000..58bed5ff --- /dev/null +++ b/tests/functional/util/test_gbak_zip.py @@ -0,0 +1,648 @@ +#coding:utf-8 +# +# id: functional.util.gbak_zip +# title: gbak utility: check ability to use -ZIP command switch when create backup +# decription: +# We create some metadata, extracte them into .SQL script, make backup with '-ZIP' switch. +# Then we try to restore this DB, validate it and again extract metadata with saving to new .SQL. +# Comparing old and new metadata must show that they are equal. +# All STDERR logs must be empty. Logs of backup, restore and validation must also be empty. +# To make test more complex non-ascii metadata are used. +# +# Checked on: +# 4.0.0.1694 SS: 4.921s. +# 4.0.0.1691 CS: 7.796s. +# +# NOTE. Command key '-zip' does not convert .fbk to .zip format; rather it just produces .fbk +# which content is compressed using LZ-algorothm and sign (flag) that this was done. +# +# Beside of that, database is encrypted before backup using IBSurgeon Demo Encryption package +# ( https://ib-aid.com/download-demo-firebird-encryption-plugin/ ; https://ib-aid.com/download/crypt/CryptTest.zip ) +# License file plugins\\dbcrypt.conf with unlimited expiration was provided by IBSurgeon to Firebird Foundation (FF). +# This file was preliminary stored in FF Test machine. +# Test assumes that this file and all neccessary libraries already were stored into FB_HOME and %FB_HOME%\\plugins. +# +# Anyone who wants to run this test on his own machine must +# 1) download https://ib-aid.com/download/crypt/CryptTest.zip AND +# 2) PURCHASE LICENSE and get from IBSurgeon file plugins\\dbcrypt.conf with apropriate expiration date and other info. +# +# ################################################ ! ! ! N O T E ! ! ! ############################################## +# FF tests storage (aka "fbt-repo") does not (and will not) contain any license file for IBSurgeon Demo Encryption package! +# ######################################################################################################################### +# +# tracker_id: +# min_versions: ['4.0'] +# versions: 4.0 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 4.0 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1) + +# test_script_1 +#--- +# import os +# import time +# import difflib +# import subprocess +# from fdb import services +# +# os.environ["ISC_USER"] = user_name +# os.environ["ISC_PASSWORD"] = user_password +# +# this_db = db_conn.database_name +# tmpfbk='$(DATABASE_LOCATION)'+'tmp_zipped_backup.fbk' +# tmpfdb='$(DATABASE_LOCATION)'+'tmp_zipped_restore.fdb' +# +# # 27.02.2021. +# # Name of encryption plugin depends on OS: +# # * for Windows we (currently) use plugin by IBSurgeon, its name is 'dbcrypt'; +# # later it can be replaced with built-in plugin 'fbSampleDbCrypt' +# # but currently it is included only in FB 4.x builds (not in FB 3.x). +# # Discussed tih Dimitr, Alex, Vlad, letters since: 08-feb-2021 00:22 +# # "Windows-distributive FB 3.x: it is desired to see sub-folder 'examples\\prebuild' with files for encryption, like it is in FB 4.x +# # *** DEFERRED *** +# # * for Linux we use: +# # ** 'DbCrypt_example' for FB 3.x +# # ** 'fbSampleDbCrypt' for FB 4.x+ +# # +# PLUGIN_NAME = 'dbcrypt' if os.name == 'nt' else ( '"DbCrypt_example"' if db_conn.engine_version < 4 else '"fbSampleDbCrypt"' ) +# +# ################################################ +# ### e n c r y p t d a t a b a s e ### +# ################################################ +# runProgram('isql', [ dsn ], 'alter database encrypt with %(PLUGIN_NAME)s key Red;' % locals()) +# time.sleep(1) +# db_conn.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 f in f_names_list: +# if type(f) == file: +# del_name = f.name +# elif type(f) == str: +# del_name = f +# else: +# print('Unrecognized type of element:', f, ' - can not be treated as file.') +# del_name = None +# +# if del_name and os.path.isfile( del_name ): +# os.remove( del_name ) +# +# #------------------------------------------- +# sql_ddl=''' +# set bail on; +# +# -- ###################################################### +# -- ################ C O R E 0 9 8 6 ############# +# -- ###################################################### +# +# create collation "Циферки" for utf8 from unicode case insensitive 'NUMERIC-SORT=1'; +# create collation "Испания" for iso8859_1 from es_es_ci_ai 'SPECIALS-FIRST=1';; +# commit; +# +# create domain "ИД'шники" int; +# create domain "Группы" varchar(30) check( value in ('Электрика', 'Ходовая', 'Арматурка', 'Кузовщина') ); +# create domain "Артикулы" varchar(12) character set utf8 check( value = upper(value) ) +# collate "Циферки" -- enabled since core-5220 was fixed (30.04.2016) +# ; +# create domain "Комрады" varchar(40) character set iso8859_1 +# collate "Испания" -- enabled since core-5220 was fixed (30.04.2016) +# ; +# create domain "Кол-во" numeric(12,3) not null; +# +# create sequence generilka; +# create sequence "Генерилка"; +# +# --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) +# --recreate exception "Невзлет" 'Запись обломалась, ваши не пляшут. Но не стесняйтесь и обязательно заходите еще, мы всегда рады видеть вас. До скорой встречи, товарищ!'; +# commit; +# +# ------------------------------------------------- +# recreate table "склад" ( +# "ИД'шник" "ИД'шники" +# ,"Откудова" "Группы" +# ,"Номенклатура" "Артикулы" +# ,"ИД'родителя" "ИД'шники" +# ,"сколько там" "Кол-во" +# ,constraint "ПК-ИД'шник" primary key ("ИД'шник") using index "склад_ПК" +# ,constraint "ФК-на-родока" foreign key("ИД'родителя") references "склад" ("ИД'шник") using index "склад_ФК" +# ,constraint "остаток >=0" check ("сколько там" >= 0) +# ); +# +# recreate view "Электрика"("ид изделия", "Название", "Запас") as +# select +# "ИД'шник" +# ,"Номенклатура" +# ,"сколько там" +# from "склад" +# where "Откудова" = 'Электрика' +# ; +# +# set term ^; +# create or alter trigger "склад би" for "склад" active before insert as +# begin +# --new."ИД'шник" = coalesce( new."ИД'шник", gen_id(generilka, 1) ); +# -- not avail up to 2.5.6: +# new."ИД'шник" = coalesce( new."ИД'шник", gen_id("Генерилка", 1) ); +# end +# ^ +# +# create or alter procedure "Доб на склад"( +# "Откудова" varchar(30) +# ,"Номенклатура" varchar(30) +# ,"ИД'родителя" int +# ,"сколько там" numeric(12,3) +# ) returns ( +# "код возврата" int +# ) as +# begin +# insert into "склад"( +# "Откудова" +# ,"Номенклатура" +# ,"ИД'родителя" +# ,"сколько там" +# ) values ( +# :"Откудова" +# ,:"Номенклатура" +# ,:"ИД'родителя" +# ,:"сколько там" +# ); +# +# end +# ^ +# create or alter procedure "Удалить" as +# begin +# /* +# Антон Павлович Чехов. Каштанка +# +# 1. Дурное поведение +# +# Молодая рыжая собака - помесь такса с дворняжкой - очень похожая мордой +# на лисицу, бегала взад и вперед по тротуару и беспокойно оглядывалась по +# сторонам. Изредка она останавливалась и, плача, приподнимая то одну озябшую +# лапу, то другую, старалась дать себе отчет: как это могло случиться, что она +# заблудилась? +# */ +# end +# ^ +# set term ;^ +# +# --grant select on "склад" to "манагер"; +# --grant select, insert, update, delete on "склад" to "начсклд"; +# +# comment on sequence "Генерилка" is 'Генератор простых идей'; +# comment on table "склад" is 'Это всё, что мы сейчас имеем в наличии'; +# comment on view "Электрика" is 'Не суй пальцы в розетку, будет бо-бо!'; +# comment on procedure "Доб на склад" is 'Процедурка добавления изделия на склад'; +# comment on parameter "Доб на склад"."Откудова" is 'Группа изделия, которое собираемся добавить'; +# +# comment on parameter "Доб на склад"."ИД'родителя" is ' +# Федор Михайлович Достоевский +# +# Преступление и наказание +# +# Роман в шести частях с эпилогом +# +# +# Часть первая +# +# I +# В начале июля, в чрезвычайно жаркое время, под вечер, один молодой человек вышел из своей каморки, которую нанимал от жильцов в С -- м переулке, на улицу и медленно, как бы в нерешимости, отправился к К -- ну мосту. +# Он благополучно избегнул встречи с своею хозяйкой на лестнице. Каморка его приходилась под самою кровлей высокого пятиэтажного дома и походила более на шкаф, чем на квартиру. Квартирная же хозяйка его, у которой он нанимал эту каморку с обедом и прислугой, помещалась одною лестницей ниже, в отдельной квартире, и каждый раз, при выходе на улицу, ему непременно надо было проходить мимо хозяйкиной кухни, почти всегда настежь отворенной на лестницу. И каждый раз молодой человек, проходя мимо, чувствовал какое-то болезненное и трусливое ощущение, которого стыдился и от которого морщился. Он был должен кругом хозяйке и боялся с нею встретиться. +# Не то чтоб он был так труслив и забит, совсем даже напротив; но с некоторого времени он был в раздражительном и напряженном состоянии, похожем на ипохондрию. Он до того углубился в себя и уединился от всех, что боялся даже всякой встречи, не только встречи с хозяйкой. Он был задавлен бедностью; но даже стесненное положение перестало в последнее время тяготить его. Насущными делами своими он совсем перестал и не хотел заниматься. Никакой хозяйки, в сущности, он не боялся, что бы та ни замышляла против него. Но останавливаться на лестнице, слушать всякий вздор про всю эту обыденную дребедень, до которой ему нет никакого дела, все эти приставания о платеже, угрозы, жалобы, и при этом самому изворачиваться, извиняться, лгать, -- нет уж, лучше проскользнуть как-нибудь кошкой по лестнице и улизнуть, чтобы никто не видал. +# Впрочем, на этот раз страх встречи с своею кредиторшей даже его самого поразил по выходе на улицу. +# "На какое дело хочу покуситься и в то же время каких пустяков боюсь! -- подумал он с странною улыбкой. -- Гм... да... всё в руках человека, и всё-то он мимо носу проносит, единственно от одной трусости... это уж аксиома... Любопытно, чего люди больше всего боятся? Нового шага, нового собственного слова они всего больше боятся... А впрочем, я слишком много болтаю. Оттого и ничего не делаю, что болтаю. Пожалуй, впрочем, и так: оттого болтаю, что ничего не делаю. Это я в этот последний месяц выучился болтать, лежа по целым суткам в углу и думая... о царе Горохе. Ну зачем я теперь иду? Разве я способен на это? Разве это серьезно? Совсем не серьезно. Так, ради фантазии сам себя тешу; игрушки! Да, пожалуй что и игрушки!" +# На улице жара стояла страшная, к тому же духота, толкотня, всюду известка, леса, кирпич, пыль и та особенная летняя вонь, столь известная каждому петербуржцу, не имеющему возможности нанять дачу, -- всё это разом неприятно потрясло и без того уже расстроенные нервы юноши. Нестерпимая же вонь из распивочных, которых в этой части города особенное множество, и пьяные, поминутно попадавшиеся, несмотря на буднее время, довершили отвратительный и грустный колорит картины. Чувство глубочайшего омерзения мелькнуло на миг в тонких чертах молодого человека. Кстати, он был замечательно хорош собою, с прекрасными темными глазами, темно-рус, ростом выше среднего, тонок и строен. Но скоро он впал как бы в глубокую задумчивость, даже, вернее сказать, как бы в какое-то забытье, и пошел, уже не замечая окружающего, да и не желая его замечать. Изредка только бормотал он что-то про себя, от своей привычки к монологам, в которой он сейчас сам себе признался. В эту же минуту он и сам сознавал, что мысли его порою мешаются и что он очень слаб: второй день как уж он почти совсем ничего не ел. +# Он был до того худо одет, что иной, даже и привычный человек, посовестился бы днем выходить в таких лохмотьях на улицу. Впрочем, квартал был таков, что костюмом здесь было трудно кого-нибудь удивить. Близость Сенной, обилие известных заведений и, по преимуществу, цеховое и ремесленное население, скученное в этих серединных петербургских улицах и переулках, пестрили иногда общую панораму такими субъектами, что странно было бы и удивляться при встрече с иною фигурой. Но столько злобного презрения уже накопилось в душе молодого человека, что, несмотря на всю свою, иногда очень молодую, щекотливость, он менее всего совестился своих лохмотьев на улице. Другое дело при встрече с иными знакомыми или с прежними товарищами, с которыми вообще он не любил встречаться... А между тем, когда один пьяный, которого неизвестно почему и куда провозили в это время по улице в огромной телеге, запряженной огромною ломовою лошадью, крикнул ему вдруг, проезжая: "Эй ты, немецкий шляпник!" -- и заорал во всё горло, указывая на него рукой, -- молодой человек вдруг остановился и судорожно схватился за свою шляпу. Шляпа эта была высокая, круглая, циммермановская, но вся уже изношенная, совсем рыжая, вся в дырах и пятнах, без полей и самым безобразнейшим углом заломившаяся на сторону. Но не стыд, а совсем другое чувство, похожее даже на испуг, охватило его. +# "Я так и знал! -- бормотал он в смущении, -- я так и думал! Это уж всего сквернее! Вот эдакая какая-нибудь глупость, какая-нибудь пошлейшая мелочь, весь замысел может испортить! Да, слишком приметная шляпа... Смешная, потому и приметная... К моим лохмотьям непременно нужна фуражка, хотя бы старый блин какой-нибудь, а не этот урод. Никто таких не носит, за версту заметят, запомнят... главное, потом запомнят, ан и улика. Тут нужно быть как можно неприметнее... Мелочи, мелочи главное!.. Вот эти-то мелочи и губят всегда и всё..." +# '; +# +# commit; +# +# +# -- ###################################################### +# -- ################ C O R E 2 2 3 8 ############# +# -- ###################################################### +# create domain dm_long_utf8 as varchar(8191) character set utf8; +# create table test (long_text dm_long_utf8, long_descr blob sub_type text character set utf8 ); +# commit; +# set count on; +# -- Length of this literal is exact 8191 characters: +# insert into test(long_text) +# values( +# 'Kaikki neuvon-antajat ja etevimmät päälliköt ja mollat ja imamit ja kadit ja kaupungin päähenkilöt olivat suuresti hämmästyksissään. Hänen tunnettu hurskautensa vaati kaikkia äänettömyyteen, sillä välin kuin hän itse lausui pitkän rukouksen, pyytäen Allah''ta ja Profeettaa hämmentämään kaikkia häväiseviä Juutalaisia ja uskottomia ja vuodattamaan totuuden sanoja jumalisten ihmisten suuhun. Ja nyt kunnian-arvoisa sheiki kutsui esiin kaikki todistajat David Alroy''ta vastaan. Heti Kisloch, Kurdilainen, joka oli koroitettu Bagdadin kadiksi, astui esiin, veti sametti-kukkarostansa paperikääryn ja luki semmoisen todistuksen, jossa arvoisa Kisloch vakuutti, että hän ensin tutustui vangin, David Alroy''n kanssa joissakin erämaan raunioissa -- muutamain rosvojen pesässä, joita Alroy johdatti; että hän, Kisloch, oli rehellinen kauppias ja että nämät konnat olivat ryöstäneet hänen karavaninsa ja hän itse joutunut vankeuteen; että hänen vankeutensa toisena yönä Alroy oli ilmestynyt hänen eteensä leijonan muodossa ja kolmantena tuimasilmäisenä härkänä; että hänen oli tapa alinomaa muuttaa itsensä; että hän usein nosti henkiä; että viimein eräänä kauheana yönä Eblis itse tuli suurella juhlasaatolla ja antoi Alroy''lle Salomonin, Davidin pojan valtikan; ja että tämä seuraavana päivänä kohotti lippunsa ja kohta sen jälkeen kukisti Hassan Subah''n ja tämän Seldshukit useitten hirmuisten paholaisten silminnähtävällä avulla. Kalidaan, Indialaisen, Guebriläisen ja Neekerin ja muutamien muitten saman hengen lapsien todistukset vetivät täysin määrin vertoja Kisloch Kurdilaisen uhkealle kertomukselle. Hebrealaisen valloittajan vastustamaton menestys oli kieltämättömällä tavalla selitetty, Mahomettilaisten aseitten kunnia ja Moslemin uskon puhtaus olivat asetetut jälleen entiseen loistoonsa ja saastuttamattomaan maineesensa. Todeksi saatiin, että David Alroy oli Ebliin lapsi, noitamies, taikakalujen ja myrkkyjen käyttäjä. Kansa kuunteli kauhulla ja harmilla. He olisivat tunkeneet vartiaväen läpitse ja repineet hänet kappaleiksi, jolleivät olisi pelänneet Karamanialaisten sotatapparoita. Niin he lohduttivat mieltänsä sillä, että he ennen pitkää saisivat nähdä hänen kidutuksensa. Bagdadin kadi kumarsi Karamanian kuningasta ja kuiskasi soveliaan matkan päästä jotakin kuninkaalliseen korvaan. Torvet kaikkuivat, kuuluttajat vaativat äänettömyyttä ja kuninkaan huulet liikkuivat taas. "Kuule, oi kansa, ja ole viisas. Pääkadi aikoo nyt lukea kuninkaallisen prinsessan Schirenen, noiturin etevimmän uhrin todistuksen." Ja todistus luettiin, joka vakuutti, että David Alroy omisti ja kantoi lähinnä sydäntänsä erästä talismania, jonka Eblis oli antanut hänelle ja jonka voima oli niin suuri, että, jos sitä kerta painettiin naisen rintaa vastaan, tämä ei enää voinut hallita tahtoansa. Tämmöinen kova onni oli kohdannut oikeauskoisten hallitsian tytärtä. "Onko siinä niin kirjoitettu?" vanki kysyi. "On", kadi vastasi, "ja sen alla on vielä prinsessan kuninkaallinen allekirjoitus." "Se on väärennetty." Karamanian kuningas kavahti valta-istuimeltansa ja oli vihoissansa astumallaan sen portaita alas. Hänen kasvonsa olivat veripunaiset, hänen partansa kuin tulen liekki. Joku lempiministeri rohkeni vienosti pidättää häntä hänen kuninkaallisesta vaipastansa. "Tapa paikalla pois se koira", Karamanian kuningas mutisi. "Prinsessa on itse täällä", lausui kadi, "todistamassa niitä noitakeinoja, joitten alaisena hän oli, vaan joitten vaikutuksesta hän nyt Allah''n ja Profeetan voiman kautta on pääsnyt." Alroy''ta vävähti! "Astu esiin, kuninkaallinen prinsessa", kadi sanoi, "ja jos se todistus, jonka kuulit, on perustettu, nosta ylös se kuninkaallinen käsi, joka koristi sen allekirjoituksellaan." Lähellä valta-istuinta oleva eunukkien joukko teki tilaa; naishaamu, joka oli verhottu hunnulla jalkoihin saakka, astui esiin. Hän nosti ylös kätensä; koko kerääntynyt kansa tuskin hengitti mielenliikutuksesta; eunukkien rivit ummistuivat jälleen; huuto kuului ja hunnustettu haamu katosi. "Minä odotan kidutuskoneitasi, kuningas", Alroy lausui raskaan surun äänellä. Hänen lujuutensa näytti luopuneen hänestä. Hänen silmänsä olivat luodut maahan. Hän oli nähtävästi vaipunut syvään miettimiseen taikka heittäynyt epätoivoon. "Valmistakaat seipäät", käski Alp Arslan. Koko kansan joukkoa värisytti vasten mieltäkin. Yksi orja lähestyi ja tarjosi paperikääryä Alroy''lle. Hän tunsi Nubialaisen, joka oli Honainin palveluksessa. Hänen entinen ministerinsä ilmoitti hänelle, että hän oli saapuvilla; että ne ehdot, joita hän vankihuoneessa tarjosi, vielä myönnettäisiin; että jos Alroy, jota asiaa hän ei epäillyt ja jota hän rukoili, suostuisi niitä vastaan-ottamaan, hänen tuli pistää paperikäärö poveensa, mutta, jos hän yhä oli taipumaton, jos hänen yhä oli mieletön päätös kuolla hirveä ja häväisevä kuolema, hänen tuli repiä se rikki ja heittää se tanterelle. Silmänräpäyksellä Alroy otti paperikääryn ja repi sen kiivaasti tuhansiin palasiin. Tuulen puuska levitti kappaleet laajalle yliympäri. Alhaiso riiteli näistä David Alroy''n viimeisistä muistoista; ja tämä vähäinen tapaus tuotti paljon hämminkiä. Tällä välin Neekerit varustivat kidutuksen ja kuoleman koneita. "Tuon juutalaisen koiran itsepintaisuus tekee minun hulluksi", lausui Karamanian kuningas hovimiehillensä. "Minua haluttaa puhutella häntä vähän, ennenkuin hän kuolee." Lempiministeri pyysi hallitsiaansa olemaan levollisena; mutta kuninkaallinen parta kävi niin punaiseksi, ja kuninkaalliset silmät iskivät niin kauheata tulta, että lempiministerikin lopulta myöntyi. Torvi kaikkui, kuuluttajat vaativat vaiti-oloa, ja Alp Arslanin ääni eroitettiin jälleen. "Senkin koira, näetkö sinä, mikä on tarjonasi? Tiedätkö sinä, mikä vartoo sinua sinun herrasi Ebliin asunnoissa? Voiko väärä ylpeys viehättää Juutalaistakin? Eikö elämä ole suloista? Eikö olisi parempi olla minun varvaskenkieni kantaja kuin tulla seivästetyksi?" "Jalomielinen Alp Arslan", vastasi Alroy ilmeisen ylenkatseen äänellä; "luuletko, että mikään kidutus rasittaa niin, kuin se muisto, että sinä olet voittanut minun?" "Partani kautta, hän ivaa minua!" Karamanialaisten hallitsia huudahti; "hän tekee kiusaa minulle! Älkäät koskeko vaippaani. Minä tahdon puhua hänen kanssaan. Te ette näe kauemmaksi kuin hunnustettu haukka, te sokean äidin lapset. Se on noita; hänellä on vielä jälellä joku päätaika; hän pelastaa vielä henkensä. Hän lentää ilmaan taikka vaipuu maan sisään. Hän nauraa meidän kidutuksiamme." Karamanian kuningas astui tuota pikaa valta-istuimensa portaita alaspäin; häntä seurasivat hänen lempiministerinsä ja hänen neuvon-antajansa ja hänen etevimmät päällikkönsä ja kadit ja mollat ja imamit ja kaupungin päähenkilöt. "Sinä noita!" Alp Arslan huudahti, "hävytön noita! halvan äidin halpa poika! koirien koira! niskotteletko sinä meitä vastaan? Kuiskaako herrasi Eblis toivoa sinun korviisi? Nauratko meidän rangaistuksiamme? Aiotko lentää ylös ilmaan? vai painua alas maahan? Niinkö, niinkö?" Hengästyneenä ja vihastansa uupuneena hallitsia vaikeni. Hän repi partaansa ja polki maata rajussa vimmassaan. "Sinä olet viisaampi kuin neuvon-antajasi, kuningas Arslan; minä en nöyrry sinun edessäsi. Minun Herrani, vaikka hän ei ole Eblis, ei ole hylännyt minua. Minä nauran sinun rangaistuksiasi. Sinun kidutuksiasi minä ylenkatson. Minä sekä vaivun maan sisään että kohoan ilmaan. Tyydytkö nyt vastaukseeni?" "Partani kautta", huudahti tulistunut Arslan, "minä tyydyn vastaukseesi. Pelastakoon Eblis sinut, jos hän voi;" ja Karamanian kuningas, Aasian mainioin miekan piteliä veti säilänsä, ikäänkuin salaman, tupesta ja silpaisi yhdellä säväyksellä Alroy''lta pään. Se kaatui, vaan, kun se kaatui, riemuitsevan pilkan hymy näytti vivahtelevan sankarin kylmenevillä kasvoilla ja kysyvän hänen vihollisiltansa: "missä kaikki teidän kidutuksenne nyt ovat?" Do Dzieci Gołąbki i Dziewczynka Dziecię i Koza Wróbel i Jaskółka Osieł i Chłopczyk Nieposłuszny Zajączek Kotek Brytan i Pudelek Egzamin Małego "Misia" Wilk i Owce Lis i Gąski Chłopczyk i Źrebię Gęsia Kapela Lew i Piesek Niedźwiedź i Pszczółka Śniadanie Artysta Z Zimowych Rozrywek Leniwy Chłopczyk Przygoda z Indykiem O hämmästyksissään. Leniwy ЙЦУКЕН' +# ); +# insert into test(long_text) +# values( +# 'Kaikki neuvon-antajat ja etevimmät päälliköt ja mollat ja imamit ja kadit ja kaupungin päähenkilöt olivat suuresti hämmästyksissään. Hänen tunnettu hurskautensa vaati kaikkia äänettömyyteen, sillä välin kuin hän itse lausui pitkän rukouksen, pyytäen Allah''ta ja Profeettaa hämmentämään kaikkia häväiseviä Juutalaisia ja uskottomia ja vuodattamaan totuuden sanoja jumalisten ihmisten suuhun. Ja nyt kunnian-arvoisa sheiki kutsui esiin kaikki todistajat David Alroy''ta vastaan. Heti Kisloch, Kurdilainen, joka oli koroitettu Bagdadin kadiksi, astui esiin, veti sametti-kukkarostansa paperikääryn ja luki semmoisen todistuksen, jossa arvoisa Kisloch vakuutti, että hän ensin tutustui vangin, David Alroy''n kanssa joissakin erämaan raunioissa -- muutamain rosvojen pesässä, joita Alroy johdatti; että hän, Kisloch, oli rehellinen kauppias ja että nämät konnat olivat ryöstäneet hänen karavaninsa ja hän itse joutunut vankeuteen; että hänen vankeutensa toisena yönä Alroy oli ilmestynyt hänen eteensä leijonan muodossa ja kolmantena tuimasilmäisenä härkänä; että hänen oli tapa alinomaa muuttaa itsensä; että hän usein nosti henkiä; että viimein eräänä kauheana yönä Eblis itse tuli suurella juhlasaatolla ja antoi Alroy''lle Salomonin, Davidin pojan valtikan; ja että tämä seuraavana päivänä kohotti lippunsa ja kohta sen jälkeen kukisti Hassan Subah''n ja tämän Seldshukit useitten hirmuisten paholaisten silminnähtävällä avulla. Kalidaan, Indialaisen, Guebriläisen ja Neekerin ja muutamien muitten saman hengen lapsien todistukset vetivät täysin määrin vertoja Kisloch Kurdilaisen uhkealle kertomukselle. Hebrealaisen valloittajan vastustamaton menestys oli kieltämättömällä tavalla selitetty, Mahomettilaisten aseitten kunnia ja Moslemin uskon puhtaus olivat asetetut jälleen entiseen loistoonsa ja saastuttamattomaan maineesensa. Todeksi saatiin, että David Alroy oli Ebliin lapsi, noitamies, taikakalujen ja myrkkyjen käyttäjä. Kansa kuunteli kauhulla ja harmilla. He olisivat tunkeneet vartiaväen läpitse ja repineet hänet kappaleiksi, jolleivät olisi pelänneet Karamanialaisten sotatapparoita. Niin he lohduttivat mieltänsä sillä, että he ennen pitkää saisivat nähdä hänen kidutuksensa. Bagdadin kadi kumarsi Karamanian kuningasta ja kuiskasi soveliaan matkan päästä jotakin kuninkaalliseen korvaan. Torvet kaikkuivat, kuuluttajat vaativat äänettömyyttä ja kuninkaan huulet liikkuivat taas. "Kuule, oi kansa, ja ole viisas. Pääkadi aikoo nyt lukea kuninkaallisen prinsessan Schirenen, noiturin etevimmän uhrin todistuksen." Ja todistus luettiin, joka vakuutti, että David Alroy omisti ja kantoi lähinnä sydäntänsä erästä talismania, jonka Eblis oli antanut hänelle ja jonka voima oli niin suuri, että, jos sitä kerta painettiin naisen rintaa vastaan, tämä ei enää voinut hallita tahtoansa. Tämmöinen kova onni oli kohdannut oikeauskoisten hallitsian tytärtä. "Onko siinä niin kirjoitettu?" vanki kysyi. "On", kadi vastasi, "ja sen alla on vielä prinsessan kuninkaallinen allekirjoitus." "Se on väärennetty." Karamanian kuningas kavahti valta-istuimeltansa ja oli vihoissansa astumallaan sen portaita alas. Hänen kasvonsa olivat veripunaiset, hänen partansa kuin tulen liekki. Joku lempiministeri rohkeni vienosti pidättää häntä hänen kuninkaallisesta vaipastansa. "Tapa paikalla pois se koira", Karamanian kuningas mutisi. "Prinsessa on itse täällä", lausui kadi, "todistamassa niitä noitakeinoja, joitten alaisena hän oli, vaan joitten vaikutuksesta hän nyt Allah''n ja Profeetan voiman kautta on pääsnyt." Alroy''ta vävähti! "Astu esiin, kuninkaallinen prinsessa", kadi sanoi, "ja jos se todistus, jonka kuulit, on perustettu, nosta ylös se kuninkaallinen käsi, joka koristi sen allekirjoituksellaan." Lähellä valta-istuinta oleva eunukkien joukko teki tilaa; naishaamu, joka oli verhottu hunnulla jalkoihin saakka, astui esiin. Hän nosti ylös kätensä; koko kerääntynyt kansa tuskin hengitti mielenliikutuksesta; eunukkien rivit ummistuivat jälleen; huuto kuului ja hunnustettu haamu katosi. "Minä odotan kidutuskoneitasi, kuningas", Alroy lausui raskaan surun äänellä. Hänen lujuutensa näytti luopuneen hänestä. Hänen silmänsä olivat luodut maahan. Hän oli nähtävästi vaipunut syvään miettimiseen taikka heittäynyt epätoivoon. "Valmistakaat seipäät", käski Alp Arslan. Koko kansan joukkoa värisytti vasten mieltäkin. Yksi orja lähestyi ja tarjosi paperikääryä Alroy''lle. Hän tunsi Nubialaisen, joka oli Honainin palveluksessa. Hänen entinen ministerinsä ilmoitti hänelle, että hän oli saapuvilla; että ne ehdot, joita hän vankihuoneessa tarjosi, vielä myönnettäisiin; että jos Alroy, jota asiaa hän ei epäillyt ja jota hän rukoili, suostuisi niitä vastaan-ottamaan, hänen tuli pistää paperikäärö poveensa, mutta, jos hän yhä oli taipumaton, jos hänen yhä oli mieletön päätös kuolla hirveä ja häväisevä kuolema, hänen tuli repiä se rikki ja heittää se tanterelle. Silmänräpäyksellä Alroy otti paperikääryn ja repi sen kiivaasti tuhansiin palasiin. Tuulen puuska levitti kappaleet laajalle yliympäri. Alhaiso riiteli näistä David Alroy''n viimeisistä muistoista; ja tämä vähäinen tapaus tuotti paljon hämminkiä. Tällä välin Neekerit varustivat kidutuksen ja kuoleman koneita. "Tuon juutalaisen koiran itsepintaisuus tekee minun hulluksi", lausui Karamanian kuningas hovimiehillensä. "Minua haluttaa puhutella häntä vähän, ennenkuin hän kuolee." Lempiministeri pyysi hallitsiaansa olemaan levollisena; mutta kuninkaallinen parta kävi niin punaiseksi, ja kuninkaalliset silmät iskivät niin kauheata tulta, että lempiministerikin lopulta myöntyi. Torvi kaikkui, kuuluttajat vaativat vaiti-oloa, ja Alp Arslanin ääni eroitettiin jälleen. "Senkin koira, näetkö sinä, mikä on tarjonasi? Tiedätkö sinä, mikä vartoo sinua sinun herrasi Ebliin asunnoissa? Voiko väärä ylpeys viehättää Juutalaistakin? Eikö elämä ole suloista? Eikö olisi parempi olla minun varvaskenkieni kantaja kuin tulla seivästetyksi?" "Jalomielinen Alp Arslan", vastasi Alroy ilmeisen ylenkatseen äänellä; "luuletko, että mikään kidutus rasittaa niin, kuin se muisto, että sinä olet voittanut minun?" "Partani kautta, hän ivaa minua!" Karamanialaisten hallitsia huudahti; "hän tekee kiusaa minulle! Älkäät koskeko vaippaani. Minä tahdon puhua hänen kanssaan. Te ette näe kauemmaksi kuin hunnustettu haukka, te sokean äidin lapset. Se on noita; hänellä on vielä jälellä joku päätaika; hän pelastaa vielä henkensä. Hän lentää ilmaan taikka vaipuu maan sisään. Hän nauraa meidän kidutuksiamme." Karamanian kuningas astui tuota pikaa valta-istuimensa portaita alaspäin; häntä seurasivat hänen lempiministerinsä ja hänen neuvon-antajansa ja hänen etevimmät päällikkönsä ja kadit ja mollat ja imamit ja kaupungin päähenkilöt. "Sinä noita!" Alp Arslan huudahti, "hävytön noita! halvan äidin halpa poika! koirien koira! niskotteletko sinä meitä vastaan? Kuiskaako herrasi Eblis toivoa sinun korviisi? Nauratko meidän rangaistuksiamme? Aiotko lentää ylös ilmaan? vai painua alas maahan? Niinkö, niinkö?" Hengästyneenä ja vihastansa uupuneena hallitsia vaikeni. Hän repi partaansa ja polki maata rajussa vimmassaan. "Sinä olet viisaampi kuin neuvon-antajasi, kuningas Arslan; minä en nöyrry sinun edessäsi. Minun Herrani, vaikka hän ei ole Eblis, ei ole hylännyt minua. Minä nauran sinun rangaistuksiasi. Sinun kidutuksiasi minä ylenkatson. Minä sekä vaivun maan sisään että kohoan ilmaan. Tyydytkö nyt vastaukseeni?" "Partani kautta", huudahti tulistunut Arslan, "minä tyydyn vastaukseesi. Pelastakoon Eblis sinut, jos hän voi;" ja Karamanian kuningas, Aasian mainioin miekan piteliä veti säilänsä, ikäänkuin salaman, tupesta ja silpaisi yhdellä säväyksellä Alroy''lta pään. Se kaatui, vaan, kun se kaatui, riemuitsevan pilkan hymy näytti vivahtelevan sankarin kylmenevillä kasvoilla ja kysyvän hänen vihollisiltansa: "missä kaikki teidän kidutuksenne nyt ovat?" Do Dzieci Gołąbki i Dziewczynka Dziecię i Koza Wróbel i Jaskółka Osieł i Chłopczyk Nieposłuszny Zajączek Kotek Brytan i Pudelek Egzamin Małego "Misia" Wilk i Owce Lis i Gąski Chłopczyk i Źrebię Gęsia Kapela Lew i Piesek Niedźwiedź i Pszczółka Śniadanie Artysta Z Zimowych Rozrywek Leniwy Chłopczyk Przygoda z Indykiem O hämmästyksissään. Leniwy НЕКУЦЙ' +# ); +# +# update test set long_descr = long_text; +# commit; +# +# +# +# -- ################################################### +# -- ############## C O R E 3 4 4 6 ############## +# -- ################################################### +# recreate table test( s varchar(8187) character set utf8 collate unicode_ci_ai, b blob sub_type 1 character set utf8 collate unicode_ci_ai); +# commit; +# +# insert into test (s, b ) +# values( +# 'Sur le boulevard Montmorency, au n° 53, s''élève une maison portant, +# encastré dans son balcon, un profil lauré de Louis XV, en bronze +# doré, qui a tout l''air d''être le médaillon, dont était décorée la +# tribune de musique de la salle à manger de Luciennes, représenté dans +# l''aquarelle de Moreau que l''on voit au Louvre. Cette tête, que quelques +# promeneurs regardent d''un œil farouche, n''est point,--ai-je besoin de +# le dire?--une affiche des opinions politiques du propriétaire, elle est +# tout bonnement l''enseigne d''un des nids les plus pleins de choses du +# XVIIIe siècle qui existent à Paris. +# +# La porte noire, que surmonte un élégant dessus de grille de chapelle +# jésuite en fer forgé, la porte ouverte, du bas de l''escalier, de +# l''entrée du vestibule, du seuil de la maison, le visiteur est accueilli +# par des terres cuites, des bronzes, des dessins, des porcelaines du +# siècle aimable par excellence, mêlés à des objets de l''Extrême-Orient, +# qui se trouvaient faire si bon ménage dans les collections de Madame de +# Pompadour et de tous les _curieux_ et les _curiolets_ du temps. +# +# La vie d''aujourd''hui est une vie de combattivité; elle demande dans +# toutes les carrières une concentration, un effort, un travail, qui, en +# son foyer enferment l''homme, dont l''existence n''est plus extérieure +# comme au XVIIIe siècle, n''est plus papillonnante parmi la société +# depuis ses dix-sept ans jusqu''à sa mort. De notre temps on va bien +# encore dans le monde, mais toute la vie ne s''y dépense plus, et le +# _chez-soi_ a cessé d''être l''hôtel garni où l''on ne faisait que coucher. +# Dans cette vie assise au coin du feu, renfermée, sédentaire, la +# créature humaine, et la première venue, a été poussée à vouloir les +# quatre murs de son _home_ agréables, plaisants, amusants aux yeux; et +# cet entour et ce décor de son intérieur, elle l''a cherché et trouvé +# naturellement dans l''objet d''art pur ou dans l''objet d''art industriel, +# plus accessible au goût de tous. Du même coup, ces habitudes moins +# mondaines amenaient un amoindrissement du rôle de la femme dans la +# pensée masculine; elle n''était plus pour nous l''occupation galante de +# toute notre existence, cette occupation qui était autrefois la carrière +# du plus grand nombre, et, à la suite de cette modification dans les +# mœurs, il arrivait ceci: c''est que l''intérêt de l''homme, s''en allant +# de l''être charmant, se reportait en grande partie sur les jolis objets +# inanimés dont la passion revêt un peu de la nature et du caractère +# de l''amour. Au XVIIIe siècle, il n''y a pas de _bibeloteurs_ jeunes: +# c''est là la différence des deux siècles. Pour notre génération, la +# _bricabracomanie_ n''est qu''un bouche-trou de la femme qui ne possède +# plus l''imagination de l''homme, et j''ai fait à mon égard cette remarque, +# que, lorsque par hasard mon cœur s''est trouvé occupé, l''objet d''art ne +# m''était de rien. +# +# Oui, cette passion devenue générale, ce plaisir solitaire, auquel se +# livre presque toute une nation, doit son développement au vide, à +# l''ennui du cœur, et aussi, il faut le reconnaître, à la tristesse +# des jours actuels, à l''incertitude des lendemains, à l''enfantement, +# les pieds devant, de la société nouvelle, à des soucis et à des +# préoccupations qui poussent, comme à la veille d''un déluge, les désirs +# et les envies à se donner la jouissance immédiate de tout ce qui les +# charme, les séduit, les tente: l''oubli du moment dans l''assouvissement +# artistique. +# +# Ce sont ces causes, et incontestablement l''éducation de l''œil des +# gens du XIXe siècle, et encore un sentiment tout nouveau, la tendresse +# presque humaine pour les _choses_, qui font, à l''heure qu''il est, de +# presque tout le monde, des collectionneurs et de moi en particulier le +# plus passionné de tous les collectionneurs. +# +# Un riant pavé en marbre blanc et en marbre rouge du Languedoc, avec, +# pour revêtement aux murs et au plafond, un cuir moderne peuplé de +# perroquets fantastiques dorés et peints sur un fond vert d''eau. +# +# Sur ce cuir, dans un désordre cherché, dans un pittoresque +# d''antichambre et d''atelier, toutes sortes de choses voyantes et +# claquantes, de brillants cuivres découpés, des poteries dorées, des +# broderies du Japon et encore des objets bizarres, inattendus, étonnant +# par leur originalité, leur exotisme, et vis-à-vis d''un certain nombre +# desquels je me fais un peu l''effet du bon Père Buffier quand il disait: +# «Voilà des choses que je ne sais pas, il faut que je fasse un livre +# dessus.» +# +# Ça, une petite jardinière à suspension, fabriquée d''une coloquinte +# excentrique, dont la tige tournante et recroquevillée est une tige de +# bronze qui a la flexibilité d''une liane; cette grande planchette fruste +# de bois, toute parcourue des tortils d''un feuillage de lierre, exécuté +# en nacre et en écaille: le porte-éventail qui tient dans l''appartement +# l''éventail ouvert contre le mur; cette petite boule de porcelaine +# jaune impérial si délicatement treillagée: la cage au grillon ou à +# la mouche bourdonnante, que le Chinois aime suspendre au chevet de +# son lit; et cette plaque de faïence figurant une branche de pêcher en +# fleur, modelée à jour dans un cadre de bois en forme d''écran, vous +# représente la décoration de l''angle religieux et mystique d''une chambre +# de prostituée de maison de thé, l''espèce de tableau d''autel devant +# lequel elle place une fleur dans un vase. +# +# Des broderies du Japon, ai-je dit plus haut, c''est là, dans leurs +# cadres de bambous, la riche, la splendide, l''_éclairante_ décoration +# des murs du vestibule et un peu de toute la maison. Ces carrés de soie +# brodés appelés _fusha_ ou _foukousa_ font la chatoyante couverture +# sous laquelle on a l''habitude, dans l''Empire du Lever du Soleil, +# d''envoyer tout présent quelconque, et le plus minime, fût-il même de +# deux œufs[1]. Les anciens _foukousas_ fabriqués à Kioto[2] sont des +# produits d''un art tout particulier au Japon, et auxquels l''Europe +# ne peut rien opposer: de la peinture, de vrais tableaux composés +# et exécutés en soie par un brodeur, où sur les fonds aux adorables +# nuances, et telles qu''en donne le satin ou le crêpe, un oiseau, un +# poisson, une fleur se détache dans le haut relief d''une broderie. +# Et rien là dedans du travail d''un art mécanique, du dessin bête de +# vieille fille de nos broderies à nous, mais des silhouettes d''êtres +# pleins de vie, avec leurs pattes d''oiseau d''un si grand style, avec +# leurs nageoires de poisson d''un si puissant contournement. Quelquefois +# des parties peintes, peintes à l''encre de Chine, s''associent de la +# manière la plus heureuse à la broderie. Je connais, chez Mme Auguste +# Sichel, une fusée de fleurs brodée dans un vase en sparterie peint ou +# imprimé, qui est bien la plus harmonieuse chose qu''il soit possible +# de voir. M. de Nittis a fait un écran, d''un admirable et singulier +# carré, où deux grues, brodées en noir sur un fond rose saumoné, ont, +# comme accompagnement et adoucissement de la broderie, des demi-teintes +# doucement lavées d''encre de Chine sur l''étoffe enchanteresse. Et dans +# ce vestibule, il y a, sur un fond lilas, des carpes nageant au milieu +# de branchages de presle brodées en or, et dont le ventre apparaît comme +# argenté par un reflet de bourbe: un effet obtenu par une réserve au +# milieu du fond tout teinté et obscuré d''encre de Chine. Il est même un +# certain nombre de foukousas absolument peints. J''ai coloriée, sur un +# crêpe gris, dans l''orbe d''un soleil rouge comme du feu, l''échancrure +# pittoresque d''un passage de sept grues, exécuté avec la science que les +# Japonais possèdent du vol de l''échassier. J''ai encore, jetées sur un +# fond maïs, sans aucun détail de terrain, deux grandes grues blanches, +# à la petite crête rougie de vermillon, au cou, aux pattes, à la queue, +# teintés d''encre de Chine. Et ne vous étonnez pas de rencontrer si +# souvent sur les broderies la grue, cet oiseau qui apparaît dans le +# haut du ciel aux Japonais comme un messager céleste, et qu''ils saluent +# de l''appellation: _O Tsouri Sama_, Sa Seigneurie la Grue. +# +# [1] Il n''est guère besoin de dire que le carré est toujours +# rapporté à son maître par le porteur du présent. +# +# [2] Les foukousas modernes seraient aujourd''hui fabriqués à +# Togané, d''où on les expédierait à Yedo. +# ' +# , ----------- +# 'Sur le boulevard Montmorency, au n° 53, s''élève une maison portant, +# encastré dans son balcon, un profil lauré de Louis XV, en bronze +# doré, qui a tout l''air d''être le médaillon, dont était décorée la +# tribune de musique de la salle à manger de Luciennes, représenté dans +# l''aquarelle de Moreau que l''on voit au Louvre. Cette tête, que quelques +# promeneurs regardent d''un œil farouche, n''est point,--ai-je besoin de +# le dire?--une affiche des opinions politiques du propriétaire, elle est +# tout bonnement l''enseigne d''un des nids les plus pleins de choses du +# XVIIIe siècle qui existent à Paris. +# +# La porte noire, que surmonte un élégant dessus de grille de chapelle +# jésuite en fer forgé, la porte ouverte, du bas de l''escalier, de +# l''entrée du vestibule, du seuil de la maison, le visiteur est accueilli +# par des terres cuites, des bronzes, des dessins, des porcelaines du +# siècle aimable par excellence, mêlés à des objets de l''Extrême-Orient, +# qui se trouvaient faire si bon ménage dans les collections de Madame de +# Pompadour et de tous les _curieux_ et les _curiolets_ du temps. +# +# La vie d''aujourd''hui est une vie de combattivité; elle demande dans +# toutes les carrières une concentration, un effort, un travail, qui, en +# son foyer enferment l''homme, dont l''existence n''est plus extérieure +# comme au XVIIIe siècle, n''est plus papillonnante parmi la société +# depuis ses dix-sept ans jusqu''à sa mort. De notre temps on va bien +# encore dans le monde, mais toute la vie ne s''y dépense plus, et le +# _chez-soi_ a cessé d''être l''hôtel garni où l''on ne faisait que coucher. +# Dans cette vie assise au coin du feu, renfermée, sédentaire, la +# créature humaine, et la première venue, a été poussée à vouloir les +# quatre murs de son _home_ agréables, plaisants, amusants aux yeux; et +# cet entour et ce décor de son intérieur, elle l''a cherché et trouvé +# naturellement dans l''objet d''art pur ou dans l''objet d''art industriel, +# plus accessible au goût de tous. Du même coup, ces habitudes moins +# mondaines amenaient un amoindrissement du rôle de la femme dans la +# pensée masculine; elle n''était plus pour nous l''occupation galante de +# toute notre existence, cette occupation qui était autrefois la carrière +# du plus grand nombre, et, à la suite de cette modification dans les +# mœurs, il arrivait ceci: c''est que l''intérêt de l''homme, s''en allant +# de l''être charmant, se reportait en grande partie sur les jolis objets +# inanimés dont la passion revêt un peu de la nature et du caractère +# de l''amour. Au XVIIIe siècle, il n''y a pas de _bibeloteurs_ jeunes: +# c''est là la différence des deux siècles. Pour notre génération, la +# _bricabracomanie_ n''est qu''un bouche-trou de la femme qui ne possède +# plus l''imagination de l''homme, et j''ai fait à mon égard cette remarque, +# que, lorsque par hasard mon cœur s''est trouvé occupé, l''objet d''art ne +# m''était de rien. +# +# Oui, cette passion devenue générale, ce plaisir solitaire, auquel se +# livre presque toute une nation, doit son développement au vide, à +# l''ennui du cœur, et aussi, il faut le reconnaître, à la tristesse +# des jours actuels, à l''incertitude des lendemains, à l''enfantement, +# les pieds devant, de la société nouvelle, à des soucis et à des +# préoccupations qui poussent, comme à la veille d''un déluge, les désirs +# et les envies à se donner la jouissance immédiate de tout ce qui les +# charme, les séduit, les tente: l''oubli du moment dans l''assouvissement +# artistique. +# +# Ce sont ces causes, et incontestablement l''éducation de l''œil des +# gens du XIXe siècle, et encore un sentiment tout nouveau, la tendresse +# presque humaine pour les _choses_, qui font, à l''heure qu''il est, de +# presque tout le monde, des collectionneurs et de moi en particulier le +# plus passionné de tous les collectionneurs. +# +# Un riant pavé en marbre blanc et en marbre rouge du Languedoc, avec, +# pour revêtement aux murs et au plafond, un cuir moderne peuplé de +# perroquets fantastiques dorés et peints sur un fond vert d''eau. +# +# Sur ce cuir, dans un désordre cherché, dans un pittoresque +# d''antichambre et d''atelier, toutes sortes de choses voyantes et +# claquantes, de brillants cuivres découpés, des poteries dorées, des +# broderies du Japon et encore des objets bizarres, inattendus, étonnant +# par leur originalité, leur exotisme, et vis-à-vis d''un certain nombre +# desquels je me fais un peu l''effet du bon Père Buffier quand il disait: +# «Voilà des choses que je ne sais pas, il faut que je fasse un livre +# dessus.» +# +# Ça, une petite jardinière à suspension, fabriquée d''une coloquinte +# excentrique, dont la tige tournante et recroquevillée est une tige de +# bronze qui a la flexibilité d''une liane; cette grande planchette fruste +# de bois, toute parcourue des tortils d''un feuillage de lierre, exécuté +# en nacre et en écaille: le porte-éventail qui tient dans l''appartement +# l''éventail ouvert contre le mur; cette petite boule de porcelaine +# jaune impérial si délicatement treillagée: la cage au grillon ou à +# la mouche bourdonnante, que le Chinois aime suspendre au chevet de +# son lit; et cette plaque de faïence figurant une branche de pêcher en +# fleur, modelée à jour dans un cadre de bois en forme d''écran, vous +# représente la décoration de l''angle religieux et mystique d''une chambre +# de prostituée de maison de thé, l''espèce de tableau d''autel devant +# lequel elle place une fleur dans un vase. +# +# Des broderies du Japon, ai-je dit plus haut, c''est là, dans leurs +# cadres de bambous, la riche, la splendide, l''_éclairante_ décoration +# des murs du vestibule et un peu de toute la maison. Ces carrés de soie +# brodés appelés _fusha_ ou _foukousa_ font la chatoyante couverture +# sous laquelle on a l''habitude, dans l''Empire du Lever du Soleil, +# d''envoyer tout présent quelconque, et le plus minime, fût-il même de +# deux œufs[1]. Les anciens _foukousas_ fabriqués à Kioto[2] sont des +# produits d''un art tout particulier au Japon, et auxquels l''Europe +# ne peut rien opposer: de la peinture, de vrais tableaux composés +# et exécutés en soie par un brodeur, où sur les fonds aux adorables +# nuances, et telles qu''en donne le satin ou le crêpe, un oiseau, un +# poisson, une fleur se détache dans le haut relief d''une broderie. +# Et rien là dedans du travail d''un art mécanique, du dessin bête de +# vieille fille de nos broderies à nous, mais des silhouettes d''êtres +# pleins de vie, avec leurs pattes d''oiseau d''un si grand style, avec +# leurs nageoires de poisson d''un si puissant contournement. Quelquefois +# des parties peintes, peintes à l''encre de Chine, s''associent de la +# manière la plus heureuse à la broderie. Je connais, chez Mme Auguste +# Sichel, une fusée de fleurs brodée dans un vase en sparterie peint ou +# imprimé, qui est bien la plus harmonieuse chose qu''il soit possible +# de voir. M. de Nittis a fait un écran, d''un admirable et singulier +# carré, où deux grues, brodées en noir sur un fond rose saumoné, ont, +# comme accompagnement et adoucissement de la broderie, des demi-teintes +# doucement lavées d''encre de Chine sur l''étoffe enchanteresse. Et dans +# ce vestibule, il y a, sur un fond lilas, des carpes nageant au milieu +# de branchages de presle brodées en or, et dont le ventre apparaît comme +# argenté par un reflet de bourbe: un effet obtenu par une réserve au +# milieu du fond tout teinté et obscuré d''encre de Chine. Il est même un +# certain nombre de foukousas absolument peints. J''ai coloriée, sur un +# crêpe gris, dans l''orbe d''un soleil rouge comme du feu, l''échancrure +# pittoresque d''un passage de sept grues, exécuté avec la science que les +# Japonais possèdent du vol de l''échassier. J''ai encore, jetées sur un +# fond maïs, sans aucun détail de terrain, deux grandes grues blanches, +# à la petite crête rougie de vermillon, au cou, aux pattes, à la queue, +# teintés d''encre de Chine. Et ne vous étonnez pas de rencontrer si +# souvent sur les broderies la grue, cet oiseau qui apparaît dans le +# haut du ciel aux Japonais comme un messager céleste, et qu''ils saluent +# de l''appellation: _O Tsouri Sama_, Sa Seigneurie la Grue. +# +# [1] Il n''est guère besoin de dire que le carré est toujours +# rapporté à son maître par le porteur du présent. +# +# [2] Les foukousas modernes seraient aujourd''hui fabriqués à +# Togané, d''où on les expédierait à Yedo. +# ' +# ); +# commit; +# set count off; +# set heading off; +# set list off; +# select 'All OK.' from rdb$database; +# ''' +# #------------------------------------------- +# f_init_ddl=open( os.path.join(context['temp_directory'],'tmp_check_ddl.sql'), 'w') +# f_init_ddl.write(sql_ddl) +# flush_and_close( f_init_ddl ) +# +# f_init_log = open( os.path.join(context['temp_directory'],'tmp_check_ddl.log'), 'w') +# f_init_err = open( os.path.join(context['temp_directory'],'tmp_check_ddl.err'), 'w') +# subprocess.call( [ context['isql_path'], dsn, '-ch', 'utf8', '-i', f_init_ddl.name ], stdout = f_init_log,stderr = f_init_err) +# flush_and_close( f_init_log ) +# flush_and_close( f_init_err ) +# +# f_meta_log1 = open( os.path.join(context['temp_directory'],'tmp_initial_meta.sql'), 'w') +# f_meta_err1 = open( os.path.join(context['temp_directory'],'tmp_initial_meta.err'), 'w') +# subprocess.call( [ context['isql_path'], dsn, '-x', '-ch', 'utf8' ], stdout = f_meta_log1, stderr = f_meta_err1) +# flush_and_close( f_meta_log1 ) +# flush_and_close( f_meta_err1 ) +# +# +# # Backup with '-ZIP' command switch +# ######## +# +# f_backup_log = open( os.path.join(context['temp_directory'],'tmp_backup.log'), 'w') +# f_backup_err = open( os.path.join(context['temp_directory'],'tmp_backup.err'), 'w') +# subprocess.call( [ context['gbak_path'], '-b', '-zip', dsn, tmpfbk ], stdout = f_backup_log, stderr = f_backup_err) +# flush_and_close( f_backup_log ) +# flush_and_close( f_backup_err ) +# +# # Restore: +# ########## +# +# f_restore_log = open( os.path.join(context['temp_directory'],'tmp_restore.log'), 'w') +# f_restore_err = open( os.path.join(context['temp_directory'],'tmp_restore.err'), 'w') +# subprocess.call( [ context['gbak_path'], '-rep', tmpfbk, 'localhost:' + tmpfdb ], stdout = f_restore_log, stderr = f_restore_err) +# flush_and_close( f_restore_log ) +# flush_and_close( f_restore_err ) +# +# # Validate restored database: +# ########## +# +# f_validate_log = open( os.path.join(context['temp_directory'],'tmp_validate.log'), 'w') +# f_validate_err = open( os.path.join(context['temp_directory'],'tmp_validate.err'), 'w') +# subprocess.call( [ context['gfix_path'], '-v', '-full', 'localhost:' + tmpfdb ], stdout = f_validate_log, stderr = f_validate_err) +# flush_and_close( f_validate_log ) +# flush_and_close( f_validate_err ) +# +# f_meta_log2 = open( os.path.join(context['temp_directory'],'tmp_restored_meta.sql'), 'w') +# f_meta_err2 = open( os.path.join(context['temp_directory'],'tmp_restored_meta.err'), 'w') +# subprocess.call( [ context['isql_path'], dsn, '-x', '-ch', 'utf8' ], stdout = f_meta_log2, stderr = f_meta_err2) +# flush_and_close( f_meta_log2 ) +# flush_and_close( f_meta_err2 ) +# +# +# # Compare extracted metadata: +# ######### +# +# f_meta_log1 = open( f_meta_log1.name,'r' ) +# f_meta_log2 = open( f_meta_log2.name,'r') +# +# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_meta_diff.txt'), 'w') +# f_diff_txt.write( ''.join( difflib.unified_diff( f_meta_log1.readlines(), f_meta_log2.readlines() ) ) ) +# flush_and_close( f_diff_txt ) +# +# flush_and_close( f_meta_log1 ) +# flush_and_close( f_meta_log2 ) +# +# # Check: all files from following set must be EMPTY: +# ######## +# +# f_list = set( (f_init_err, f_meta_err1, f_meta_err2, f_backup_err, f_restore_err, f_validate_log, f_validate_err, f_diff_txt) ) +# for x in f_list: +# with open(x.name, 'r') as f: +# for line in f: +# if line.split(): +# print('UNEXPECTED CONTENT in '+ x.name + ': '+line) +# +# +# ###################################################################### +# # Cleanup: +# f_list |= set( ( f_init_ddl, f_init_log, f_meta_log1, f_meta_log2, f_backup_log, f_restore_log, tmpfbk, tmpfdb) ) +# cleanup( f_list ) +# +# +#--- +#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + + +@pytest.mark.version('>=4.0') +@pytest.mark.xfail +def test_gbak_zip_1(db_1): + pytest.fail("Test not IMPLEMENTED") + + diff --git a/tests/functional/view/__init__.py b/tests/functional/view/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/view/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/view/create/__init__.py b/tests/functional/view/create/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/view/create/__init__.py @@ -0,0 +1 @@ +# Python module diff --git a/tests/functional/view/create/test_01.py b/tests/functional/view/create/test_01.py new file mode 100644 index 00000000..1fb17940 --- /dev/null +++ b/tests/functional/view/create/test_01.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: functional.view.create.01 +# title: CREATE VIEW +# decription: CREATE VIEW +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.view.create.create_view_01 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE tb(id INT); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE VIEW test AS SELECT * FROM tb; +SHOW VIEW test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ID INTEGER Nullable +View Source: +==== ====== + SELECT * FROM tb""" + +@pytest.mark.version('>=1.0') +def test_01_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/view/create/test_02.py b/tests/functional/view/create/test_02.py new file mode 100644 index 00000000..22d951cc --- /dev/null +++ b/tests/functional/view/create/test_02.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: functional.view.create.02 +# title: CREATE VIEW +# decription: CREATE VIEW +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# tracker_id: +# min_versions: [] +# versions: 2.5 +# qmid: functional.view.create.create_view_02 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE tb(id INT); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE VIEW test (id,num) AS SELECT id,5 FROM tb; +SHOW VIEW test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ID INTEGER Nullable +NUM INTEGER Expression +View Source: +==== ====== + SELECT id,5 FROM tb +""" + +@pytest.mark.version('>=2.5') +def test_02_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/view/create/test_03.py b/tests/functional/view/create/test_03.py new file mode 100644 index 00000000..2607551c --- /dev/null +++ b/tests/functional/view/create/test_03.py @@ -0,0 +1,47 @@ +#coding:utf-8 +# +# id: functional.view.create_03 +# title: CREATE VIEW - bad number of columns +# decription: CREATE VIEW - bad number of columns +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.view.create.create_view_03 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE tb(id INT); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE VIEW test (id,num,text) AS SELECT id,5 FROM tb; +SHOW VIEW test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 07002 +unsuccessful metadata update +-CREATE VIEW TEST failed +-SQL error code = -607 +-Invalid command +-number of columns does not match select list +There is no view TEST in this database +""" + +@pytest.mark.version('>=3.0') +def test_create_03_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/view/create/test_04.py b/tests/functional/view/create/test_04.py new file mode 100644 index 00000000..6a232ed4 --- /dev/null +++ b/tests/functional/view/create/test_04.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: functional.view.create_04 +# title: CREATE VIEW - bad number of columns +# decription: CREATE VIEW - bad number of columns +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.view.create.create_view_04 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE tb(id INT);""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE VIEW test (id) AS SELECT id,5 FROM tb; +SHOW VIEW test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 07002 +unsuccessful metadata update +-CREATE VIEW TEST failed +-SQL error code = -607 +-Invalid command +-number of columns does not match select list +There is no view TEST in this database +""" + +@pytest.mark.version('>=3.0') +def test_create_04_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/view/create/test_05.py b/tests/functional/view/create/test_05.py new file mode 100644 index 00000000..962da84d --- /dev/null +++ b/tests/functional/view/create/test_05.py @@ -0,0 +1,48 @@ +#coding:utf-8 +# +# id: functional.view.create.05 +# title: CREATE VIEW +# decription: CREATE VIEW +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# INSERT +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.view.create.create_view_05 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE tb(id INT); +INSERT INTO tb VALUES(3); +INSERT INTO tb VALUES(10); +COMMIT;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE VIEW test (id,num) AS SELECT id,5 FROM tb; +SELECT * FROM test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ ID NUM +============ ============ + + 3 5 + 10 5 +""" + +@pytest.mark.version('>=1.0') +def test_05_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/view/create/test_06.py b/tests/functional/view/create/test_06.py new file mode 100644 index 00000000..28e9ef6e --- /dev/null +++ b/tests/functional/view/create/test_06.py @@ -0,0 +1,46 @@ +#coding:utf-8 +# +# id: functional.view.create.06 +# title: CREATE VIEW - updateable +# decription: CREATE VIEW - updateable +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.view.create.create_view_06 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE tb(id INT); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE VIEW test (id) AS SELECT id FROM tb; +INSERT INTO test VALUES(2); +COMMIT; +SELECT * FROM test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ ID +============ + + 2 +""" + +@pytest.mark.version('>=1.0') +def test_06_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/view/create/test_07.py b/tests/functional/view/create/test_07.py new file mode 100644 index 00000000..97679e99 --- /dev/null +++ b/tests/functional/view/create/test_07.py @@ -0,0 +1,45 @@ +#coding:utf-8 +# +# id: functional.view.create.07 +# title: CREATE VIEW - updateable WITH CHECK OPTION +# decription: CREATE VIEW - updateable WITH CHECK OPTION +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# tracker_id: +# min_versions: [] +# versions: 1.0 +# qmid: functional.view.create.create_view_07 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 1.0 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE tb(id INT);""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE VIEW test (id) AS SELECT id FROM tb WHERE id<10 WITH CHECK OPTION; +INSERT INTO test VALUES(2); +COMMIT; +SELECT * FROM test;""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ ID +============ + + 2 +""" + +@pytest.mark.version('>=1.0') +def test_07_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/functional/view/create/test_08.py b/tests/functional/view/create/test_08.py new file mode 100644 index 00000000..e5e8eb24 --- /dev/null +++ b/tests/functional/view/create/test_08.py @@ -0,0 +1,43 @@ +#coding:utf-8 +# +# id: functional.view.create_08 +# title: CREATE VIEW - updateable WITH CHECK OPTION +# decription: CREATE VIEW - updateable WITH CHECK OPTION +# +# Dependencies: +# CREATE DATABASE +# CREATE TABLE +# tracker_id: +# min_versions: [] +# versions: 3.0 +# qmid: functional.view.create.create_view_08 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 3.0 +# resources: None + +substitutions_1 = [('-At trigger.*', '')] + +init_script_1 = """CREATE TABLE tb(id INT); +commit;""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE VIEW test (id) AS SELECT id FROM tb WHERE id<10 WITH CHECK OPTION; +INSERT INTO test VALUES(10);""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stderr_1 = """Statement failed, SQLSTATE = 23000 +Operation violates CHECK constraint on view or table TEST +-At trigger 'CHECK_1' +""" + +@pytest.mark.version('>=3.0') +def test_create_08_1(act_1: Action): + act_1.expected_stderr = expected_stderr_1 + act_1.execute() + assert act_1.clean_expected_stderr == act_1.clean_stderr + diff --git a/tests/functional/view/create/test_10.py b/tests/functional/view/create/test_10.py new file mode 100644 index 00000000..f77da77c --- /dev/null +++ b/tests/functional/view/create/test_10.py @@ -0,0 +1,44 @@ +#coding:utf-8 +# +# id: functional.view.create.10 +# title: CREATE VIEW as SELECT .... +# decription: Create view without field list +# tracker_id: CORE-831 +# min_versions: [] +# versions: 2.1 +# qmid: functional.view.create.create_view_10 + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.1 +# resources: None + +substitutions_1 = [] + +init_script_1 = """CREATE TABLE T1 (ID INTEGER, NAME VARCHAR(10)); +COMMIT; +""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """CREATE VIEW V1 AS SELECT ID AS VID, NAME FROM T1; +COMMIT; +SHOW VIEW V1; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """VID INTEGER Nullable +NAME VARCHAR(10) Nullable +View Source: +==== ====== + SELECT ID AS VID, NAME FROM T1 +""" + +@pytest.mark.version('>=2.1') +def test_10_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout + diff --git a/tests/test_full_join_push_where_predicate.py b/tests/test_full_join_push_where_predicate.py new file mode 100644 index 00000000..29b47bcd --- /dev/null +++ b/tests/test_full_join_push_where_predicate.py @@ -0,0 +1,68 @@ +#coding:utf-8 +# +# id: full_join_push_where_predicate +# title: WHERE-filter must be applied after FULL JOIN result +# decription: +# See (rus): https://www.sql.ru/forum/1326682/dva-cte-ih-full-join-i-uslovie-daut-nekorrektnyy-rezultat +# Confirmed bug on 2.5.9.27151. +# Checked on 3.0.6.33322, 4.0.0.2073 -- all fine. +# +# tracker_id: +# min_versions: ['2.5.0'] +# versions: 2.5 +# qmid: None + +import pytest +from firebird.qa import db_factory, isql_act, Action + +# version: 2.5 +# resources: None + +substitutions_1 = [('[ \t]+', ' ')] + +init_script_1 = """""" + +db_1 = db_factory(sql_dialect=3, init=init_script_1) + +test_script_1 = """ + set list on; + + recreate table t ( + f1 varchar(10), + f2 integer + ); + + insert into t (f1, f2) values ('a', 1); + insert into t (f1, f2) values ('b', 1); + insert into t (f1, f2) values ('c', 1); + insert into t (f1, f2) values ('b', 2); + insert into t (f1, f2) values ('c', 2); + insert into t (f1, f2) values ('d', 2); + commit; + + with + t1 as (select f1 from t where f2 = 1) + ,t2 as (select f1 from t where f2 = 2) + select + t1.f1 t1_f1, + t2.f1 t2_f1 + from + t1 full join t2 on t1.f1 = t2.f1 + where t1.f1 is null + order by 1,2 + ; + """ + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1) + +expected_stdout_1 = """ + T1_F1 + T2_F1 d + """ + +@pytest.mark.version('>=2.5') +def test_full_join_push_where_predicate_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_expected_stdout == act_1.clean_stdout +